diff options
author | Lukas Tönne <lukas.toenne@gmail.com> | 2018-06-15 09:02:23 +0300 |
---|---|---|
committer | Lukas Tönne <lukas.toenne@gmail.com> | 2018-06-15 09:02:23 +0300 |
commit | cd71dd638245ad21e59e3f83229e926a285ccc45 (patch) | |
tree | 1c5fdeef0a37ebec1a1ade80ced18b27dd0482e6 /source | |
parent | dec92e6ba1a1944c642ded967d7f65fc5d8e704a (diff) | |
parent | 27de412ca8de4edad99a46ebdb8aadd7003e42a6 (diff) |
Merge branch 'blender2.8' into hair_guides
Diffstat (limited to 'source')
482 files changed, 7536 insertions, 41707 deletions
diff --git a/source/blender/blenkernel/BKE_animsys.h b/source/blender/blenkernel/BKE_animsys.h index 326c25e8899..7ae9527b2f7 100644 --- a/source/blender/blenkernel/BKE_animsys.h +++ b/source/blender/blenkernel/BKE_animsys.h @@ -76,7 +76,7 @@ struct AnimData *BKE_animdata_copy(struct Main *bmain, struct AnimData *adt, con bool BKE_animdata_copy_id(struct Main *bmain, struct ID *id_to, struct ID *id_from, const bool do_action, const bool do_id_user); /* Copy AnimData Actions */ -void BKE_animdata_copy_id_action(struct ID *id, const bool set_newid); +void BKE_animdata_copy_id_action(struct Main *bmain, struct ID *id, const bool set_newid); /* Merge copies of data from source AnimData block */ typedef enum eAnimData_MergeCopy_Modes { @@ -90,7 +90,9 @@ typedef enum eAnimData_MergeCopy_Modes { ADT_MERGECOPY_SRC_REF = 2 } eAnimData_MergeCopy_Modes; -void BKE_animdata_merge_copy(struct ID *dst_id, struct ID *src_id, eAnimData_MergeCopy_Modes action_mode, bool fix_drivers); +void BKE_animdata_merge_copy( + struct Main *bmain, struct ID *dst_id, struct ID *src_id, + eAnimData_MergeCopy_Modes action_mode, bool fix_drivers); /* ************************************* */ /* KeyingSets API */ @@ -141,7 +143,8 @@ void BKE_animdata_fix_paths_remove(struct ID *id, const char *path); /* -------------------------------------- */ /* Move animation data from src to destination if it's paths are based on basepaths */ -void BKE_animdata_separate_by_basepath(struct ID *srcID, struct ID *dstID, struct ListBase *basepaths); +void BKE_animdata_separate_by_basepath( + struct Main *bmain, struct ID *srcID, struct ID *dstID, struct ListBase *basepaths); /* Move F-Curves from src to destination if it's path is based on basepath */ void action_move_fcurves_by_basepath(struct bAction *srcAct, struct bAction *dstAct, const char basepath[]); diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index a1212322983..c3dbb362206 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -29,9 +29,9 @@ * Use STRINGIFY() rather than defining with quotes */ #define BLENDER_VERSION 280 #define BLENDER_SUBVERSION 17 -/* Several breakages with 270, e.g. constraint deg vs rad */ -#define BLENDER_MINVERSION 270 -#define BLENDER_MINSUBVERSION 6 +/* Several breakages with 280, e.g. collections vs layers */ +#define BLENDER_MINVERSION 280 +#define BLENDER_MINSUBVERSION 0 /* used by packaging tools */ /* can be left blank, otherwise a,b,c... etc with no quotes */ diff --git a/source/blender/blenkernel/BKE_brush.h b/source/blender/blenkernel/BKE_brush.h index f2601f2ca32..9f326d97937 100644 --- a/source/blender/blenkernel/BKE_brush.h +++ b/source/blender/blenkernel/BKE_brush.h @@ -57,12 +57,6 @@ void BKE_brush_sculpt_reset(struct Brush *brush); /* image icon function */ struct ImBuf *get_brush_icon(struct Brush *brush); -/* brush library operations used by different paint panels */ -int BKE_brush_texture_set_nr(struct Brush *brush, int nr); -int BKE_brush_texture_delete(struct Brush *brush); -int BKE_brush_clone_image_set_nr(struct Brush *brush, int nr); -int BKE_brush_clone_image_delete(struct Brush *brush); - /* jitter */ void BKE_brush_jitter_pos( const struct Scene *scene, struct Brush *brush, diff --git a/source/blender/blenkernel/BKE_collection.h b/source/blender/blenkernel/BKE_collection.h index fc5b19ccb4f..7dce3b2c703 100644 --- a/source/blender/blenkernel/BKE_collection.h +++ b/source/blender/blenkernel/BKE_collection.h @@ -90,14 +90,13 @@ void BKE_collections_child_remove_nulls(struct Main *bmain, struct Collection *o bool BKE_collection_is_in_scene(struct Collection *collection); void BKE_collections_after_lib_link(struct Main *bmain); bool BKE_collection_object_cyclic_check(struct Main *bmain, struct Object *object, struct Collection *collection); -bool BKE_collection_is_animated(struct Collection *collection, struct Object *parent); /* Object list cache. */ struct ListBase BKE_collection_object_cache_get(struct Collection *collection); void BKE_collection_object_cache_free(struct Collection *collection); -struct Base *BKE_collection_or_layer_objects(struct Depsgraph *depsgraph, +struct Base *BKE_collection_or_layer_objects(const struct Depsgraph *depsgraph, const struct Scene *scene, const struct ViewLayer *view_layer, struct Collection *collection); @@ -139,13 +138,21 @@ void BKE_scene_objects_callback(struct Scene *scene, BKE_scene_objects_Cb callba /* Iteratorion over objects in collection. */ -#define FOREACH_COLLECTION_BASE_RECURSIVE_BEGIN(_collection, _base) \ - for (Base *_base = (Base*)BKE_collection_object_cache_get(_collection).first; \ - _base; \ - _base = _base->next) \ - { - -#define FOREACH_COLLECTION_BASE_RECURSIVE_END \ +#define FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_BEGIN(_collection, _object, _mode) \ + { \ + int _base_flag = (_mode == DAG_EVAL_VIEWPORT) ? \ + BASE_VISIBLE_VIEWPORT : BASE_VISIBLE_RENDER; \ + int _base_id = 0; \ + for (Base *_base = (Base*)BKE_collection_object_cache_get(_collection).first; \ + _base; \ + _base = _base->next, _base_id++) \ + { \ + if (_base->flag & _base_flag) { \ + Object *_object = _base->object; \ + +#define FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_END \ + } \ + } \ } #define FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(_collection, _object) \ diff --git a/source/blender/blenkernel/BKE_displist.h b/source/blender/blenkernel/BKE_displist.h index 09e9b667369..6dd40b7a651 100644 --- a/source/blender/blenkernel/BKE_displist.h +++ b/source/blender/blenkernel/BKE_displist.h @@ -57,11 +57,12 @@ enum { /* prototypes */ -struct Scene; -struct Object; -struct ListBase; struct Depsgraph; struct DerivedMesh; +struct ListBase; +struct Main; +struct Object; +struct Scene; /* used for curves, nurbs, mball, importing */ typedef struct DispList { diff --git a/source/blender/blenkernel/BKE_dynamicpaint.h b/source/blender/blenkernel/BKE_dynamicpaint.h index a0814fc9183..0a759629930 100644 --- a/source/blender/blenkernel/BKE_dynamicpaint.h +++ b/source/blender/blenkernel/BKE_dynamicpaint.h @@ -28,6 +28,7 @@ */ struct Depsgraph; +struct Main; struct Scene; struct ViewLayer; @@ -86,7 +87,9 @@ struct DynamicPaintSurface *get_activeSurface(struct DynamicPaintCanvasSettings /* image sequence baking */ int dynamicPaint_createUVSurface(struct Scene *scene, struct DynamicPaintSurface *surface, float *progress, short *do_update); -int dynamicPaint_calculateFrame(struct DynamicPaintSurface *surface, struct Depsgraph *depsgraph, struct Scene *scene, struct Object *cObject, int frame); +int dynamicPaint_calculateFrame( + struct DynamicPaintSurface *surface, struct Depsgraph *depsgraph, + struct Scene *scene, struct Object *cObject, int frame); void dynamicPaint_outputSurfaceImage(struct DynamicPaintSurface *surface, char *filename, short output_layer); /* PaintPoint state */ diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h index 09f5ecce050..dbe325b2056 100644 --- a/source/blender/blenkernel/BKE_fcurve.h +++ b/source/blender/blenkernel/BKE_fcurve.h @@ -108,7 +108,8 @@ bool driver_get_variable_property( struct ChannelDriver *driver, struct DriverTarget *dtar, struct PointerRNA *r_ptr, struct PropertyRNA **r_prop, int *r_index); -float evaluate_driver(struct PathResolvedRNA *anim_rna, struct ChannelDriver *driver, const float evaltime); +float evaluate_driver(struct PathResolvedRNA *anim_rna, struct ChannelDriver *driver, + struct ChannelDriver *driver_orig, const float evaltime); /* ************** F-Curve Modifiers *************** */ @@ -282,7 +283,8 @@ void correct_bezpart(float v1[2], float v2[2], float v3[2], float v4[2]); /* evaluate fcurve */ float evaluate_fcurve(struct FCurve *fcu, float evaltime); -float evaluate_fcurve_driver(struct PathResolvedRNA *anim_rna, struct FCurve *fcu, float evaltime); +float evaluate_fcurve_driver(struct PathResolvedRNA *anim_rna, struct FCurve *fcu, + struct ChannelDriver *driver_orig, float evaltime); /* evaluate fcurve and store value */ float calculate_fcurve(struct PathResolvedRNA *anim_rna, struct FCurve *fcu, float evaltime); diff --git a/source/blender/blenkernel/BKE_font.h b/source/blender/blenkernel/BKE_font.h index e5eea4423c9..bb1f97e83e6 100644 --- a/source/blender/blenkernel/BKE_font.h +++ b/source/blender/blenkernel/BKE_font.h @@ -86,13 +86,13 @@ struct VFont *BKE_vfont_load_exists(struct Main *bmain, const char *filepath); void BKE_vfont_make_local(struct Main *bmain, struct VFont *vfont, const bool lib_local); -bool BKE_vfont_to_curve_ex(struct Main *bmain, struct Object *ob, struct Curve *cu, int mode, +bool BKE_vfont_to_curve_ex(struct Object *ob, struct Curve *cu, int mode, struct ListBase *r_nubase, const wchar_t **r_text, int *r_text_len, bool *r_text_free, struct CharTrans **r_chartransdata); -bool BKE_vfont_to_curve_nubase(struct Main *bmain, struct Object *ob, int mode, +bool BKE_vfont_to_curve_nubase(struct Object *ob, int mode, struct ListBase *r_nubase); -bool BKE_vfont_to_curve(struct Main *bmain, struct Object *ob, int mode); +bool BKE_vfont_to_curve(struct Object *ob, int mode); int BKE_vfont_select_get(struct Object *ob, int *r_start, int *r_end); void BKE_vfont_select_clamp(struct Object *ob); diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h index e184fd3796b..c5ad91c81fd 100644 --- a/source/blender/blenkernel/BKE_global.h +++ b/source/blender/blenkernel/BKE_global.h @@ -54,7 +54,7 @@ typedef struct Global { /* strings: lastsaved */ char ima[1024], lib[1024]; /* 1024 = FILE_MAX */ - /* when set: G.main->name contains valid relative base path */ + /* when set: G_MAIN->name contains valid relative base path */ bool relbase_valid; bool file_loaded; bool save_over; @@ -210,6 +210,11 @@ enum { /* Memory is allocated where? blender.c */ extern Global G; +/** + * Stupid macro to hide the few *valid* usages of G.main (from startup/exit code e.g.), helps with cleanup task. + */ +#define G_MAIN (G).main + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_gpencil.h b/source/blender/blenkernel/BKE_gpencil.h index b6de922c245..c7ea73463e3 100644 --- a/source/blender/blenkernel/BKE_gpencil.h +++ b/source/blender/blenkernel/BKE_gpencil.h @@ -56,7 +56,7 @@ void BKE_gpencil_stroke_sync_selection(struct bGPDstroke *gps); struct bGPDframe *BKE_gpencil_frame_addnew(struct bGPDlayer *gpl, int cframe); struct bGPDframe *BKE_gpencil_frame_addcopy(struct bGPDlayer *gpl, int cframe); struct bGPDlayer *BKE_gpencil_layer_addnew(struct bGPdata *gpd, const char *name, bool setactive); -struct bGPdata *BKE_gpencil_data_addnew(const char name[]); +struct bGPdata *BKE_gpencil_data_addnew(struct Main *bmain, const char name[]); struct bGPDframe *BKE_gpencil_frame_duplicate(const struct bGPDframe *gpf_src); struct bGPDlayer *BKE_gpencil_layer_duplicate(const struct bGPDlayer *gpl_src); diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h index 1af123759e6..a7d7806997c 100644 --- a/source/blender/blenkernel/BKE_image.h +++ b/source/blender/blenkernel/BKE_image.h @@ -190,25 +190,25 @@ void BKE_image_alpha_mode_from_extension(struct Image *image); /* returns a new image or NULL if it can't load */ struct Image *BKE_image_load(struct Main *bmain, const char *filepath); /* returns existing Image when filename/type is same (frame optional) */ -struct Image *BKE_image_load_exists_ex(const char *filepath, bool *r_exists); -struct Image *BKE_image_load_exists(const char *filepath); +struct Image *BKE_image_load_exists_ex(struct Main *bmain, const char *filepath, bool *r_exists); +struct Image *BKE_image_load_exists(struct Main *bmain, const char *filepath); /* adds image, adds ibuf, generates color or pattern */ struct Image *BKE_image_add_generated( struct Main *bmain, unsigned int width, unsigned int height, const char *name, int depth, int floatbuf, short gen_type, const float color[4], const bool stereo3d); /* adds image from imbuf, owns imbuf */ -struct Image *BKE_image_add_from_imbuf(struct ImBuf *ibuf, const char *name); +struct Image *BKE_image_add_from_imbuf(struct Main *bmain, struct ImBuf *ibuf, const char *name); /* for reload, refresh, pack */ void BKE_image_init_imageuser(struct Image *ima, struct ImageUser *iuser); -void BKE_image_signal(struct Image *ima, struct ImageUser *iuser, int signal); +void BKE_image_signal(struct Main *bmain, struct Image *ima, struct ImageUser *iuser, int signal); void BKE_image_walk_all_users(const struct Main *mainp, void *customdata, void callback(struct Image *ima, struct ImageUser *iuser, void *customdata)); /* ensures an Image exists for viewing nodes or render */ -struct Image *BKE_image_verify_viewer(int type, const char *name); +struct Image *BKE_image_verify_viewer(struct Main *bmain, int type, const char *name); /* ensures the view node cache is compatible with the scene views */ void BKE_image_verify_viewer_views(const struct RenderData *rd, struct Image *ima, struct ImageUser *iuser); @@ -242,27 +242,27 @@ void BKE_image_backup_render(struct Scene *scene, struct Image *ima, bool free_c bool BKE_image_save_openexr_multiview(struct Image *ima, struct ImBuf *ibuf, const char *filepath, const int flags); /* goes over all textures that use images */ -void BKE_image_free_all_textures(void); +void BKE_image_free_all_textures(struct Main *bmain); /* does one image! */ void BKE_image_free_anim_ibufs(struct Image *ima, int except_frame); /* does all images with type MOVIE or SEQUENCE */ -void BKE_image_all_free_anim_ibufs(int except_frame); +void BKE_image_all_free_anim_ibufs(struct Main *bmain, int except_frame); void BKE_image_memorypack(struct Image *ima); void BKE_image_packfiles(struct ReportList *reports, struct Image *ima, const char *basepath); void BKE_image_packfiles_from_mem(struct ReportList *reports, struct Image *ima, char *data, const size_t data_len); /* prints memory statistics for images */ -void BKE_image_print_memlist(void); +void BKE_image_print_memlist(struct Main *bmain); /* empty image block, of similar type and filename */ void BKE_image_copy_data(struct Main *bmain, struct Image *ima_dst, const struct Image *ima_src, const int flag); struct Image *BKE_image_copy(struct Main *bmain, const struct Image *ima); /* merge source into dest, and free source */ -void BKE_image_merge(struct Image *dest, struct Image *source); +void BKE_image_merge(struct Main *bmain, struct Image *dest, struct Image *source); /* scale the image */ bool BKE_image_scale(struct Image *image, int width, int height); @@ -271,7 +271,7 @@ bool BKE_image_scale(struct Image *image, int width, int height); bool BKE_image_has_alpha(struct Image *image); /* check if texture has gpu texture code */ -bool BKE_image_has_bindcode(struct Image *ima); +bool BKE_image_has_opengl_texture(struct Image *ima); void BKE_image_get_size(struct Image *image, struct ImageUser *iuser, int *width, int *height); void BKE_image_get_size_fl(struct Image *image, struct ImageUser *iuser, float size[2]); @@ -296,6 +296,12 @@ void BKE_image_file_format_set(struct Image *image, int ftype, const struct ImbF bool BKE_image_has_loaded_ibuf(struct Image *image); struct ImBuf *BKE_image_get_ibuf_with_name(struct Image *image, const char *name); struct ImBuf *BKE_image_get_first_ibuf(struct Image *image); + +struct RenderSlot *BKE_image_add_renderslot(struct Image *ima, const char *name); +bool BKE_image_remove_renderslot(struct Image *ima, struct ImageUser *iuser, int slot); +struct RenderSlot *BKE_image_get_renderslot(struct Image *ima, int slot); +bool BKE_image_clear_renderslot(struct Image *ima, struct ImageUser *iuser, int slot); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_key.h b/source/blender/blenkernel/BKE_key.h index 5eef44ef896..2f953e57d71 100644 --- a/source/blender/blenkernel/BKE_key.h +++ b/source/blender/blenkernel/BKE_key.h @@ -50,7 +50,7 @@ extern "C" { void BKE_key_free(struct Key *sc); void BKE_key_free_nolib(struct Key *key); -struct Key *BKE_key_add(struct ID *id); +struct Key *BKE_key_add(struct Main *bmain, struct ID *id); void BKE_key_copy_data(struct Main *bmain, struct Key *key_dst, const struct Key *key_src, const int flag); struct Key *BKE_key_copy(struct Main *bmain, const struct Key *key); struct Key *BKE_key_copy_nolib(struct Key *key); diff --git a/source/blender/blenkernel/BKE_mball_tessellate.h b/source/blender/blenkernel/BKE_mball_tessellate.h index df652df177d..363bfe09c75 100644 --- a/source/blender/blenkernel/BKE_mball_tessellate.h +++ b/source/blender/blenkernel/BKE_mball_tessellate.h @@ -24,6 +24,7 @@ * \ingroup bke */ struct Depsgraph; +struct Main; struct Object; struct Scene; diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index cb58deb9511..85ce4eb6cae 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -145,10 +145,10 @@ int BKE_mesh_nurbs_displist_to_mdata( struct MLoop **r_allloop, struct MPoly **r_allpoly, struct MLoopUV **r_alluv, int *r_totloop, int *r_totpoly); void BKE_mesh_from_nurbs_displist( - struct Object *ob, struct ListBase *dispbase, const bool use_orco_uv, const char *obdata_name, bool temporary); -void BKE_mesh_from_nurbs(struct Object *ob); + struct Main *bmain, struct Object *ob, struct ListBase *dispbase, const bool use_orco_uv, const char *obdata_name, bool temporary); +void BKE_mesh_from_nurbs(struct Main *bmain, struct Object *ob); void BKE_mesh_to_curve_nurblist(const struct Mesh *me, struct ListBase *nurblist, const int edge_users_test); -void BKE_mesh_to_curve(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob); +void BKE_mesh_to_curve(struct Main *bmain, struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob); void BKE_mesh_material_index_remove(struct Mesh *me, short index); void BKE_mesh_material_index_clear(struct Mesh *me); void BKE_mesh_material_remap(struct Mesh *me, const unsigned int *remap, unsigned int remap_len); diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h index b5d3e67b970..b40d32203f6 100644 --- a/source/blender/blenkernel/BKE_modifier.h +++ b/source/blender/blenkernel/BKE_modifier.h @@ -468,7 +468,7 @@ void modifier_mdef_compact_influences(struct ModifierData *md); void modifier_path_init(char *path, int path_maxlen, const char *name); const char *modifier_path_relbase(struct Main *bmain, struct Object *ob); - +const char *modifier_path_relbase_from_global(struct Object *ob); /* wrappers for modifier callbacks that ensure valid normals */ diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h index 4509d374b02..6f0b6d59984 100644 --- a/source/blender/blenkernel/BKE_nla.h +++ b/source/blender/blenkernel/BKE_nla.h @@ -34,6 +34,7 @@ */ struct AnimData; +struct Main; struct NlaStrip; struct NlaTrack; struct bAction; @@ -50,9 +51,9 @@ void BKE_nlastrip_free(ListBase *strips, struct NlaStrip *strip); void BKE_nlatrack_free(ListBase *tracks, struct NlaTrack *nlt); void BKE_nla_tracks_free(ListBase *tracks); -struct NlaStrip *BKE_nlastrip_copy(struct NlaStrip *strip, const bool use_same_action); -struct NlaTrack *BKE_nlatrack_copy(struct NlaTrack *nlt, const bool use_same_actions); -void BKE_nla_tracks_copy(ListBase *dst, ListBase *src); +struct NlaStrip *BKE_nlastrip_copy(struct Main *bmain, struct NlaStrip *strip, const bool use_same_action); +struct NlaTrack *BKE_nlatrack_copy(struct Main *bmain, struct NlaTrack *nlt, const bool use_same_actions); +void BKE_nla_tracks_copy(struct Main *bmain, ListBase *dst, ListBase *src); struct NlaTrack *BKE_nlatrack_add(struct AnimData *adt, struct NlaTrack *prev); struct NlaStrip *BKE_nlastrip_new(struct bAction *act); diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index cb211b65948..d271252ceef 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -293,7 +293,7 @@ typedef struct bNodeTreeType { /* calls allowing threaded composite */ void (*localize)(struct bNodeTree *localtree, struct bNodeTree *ntree); void (*local_sync)(struct bNodeTree *localtree, struct bNodeTree *ntree); - void (*local_merge)(struct bNodeTree *localtree, struct bNodeTree *ntree); + void (*local_merge)(struct Main *bmain, struct bNodeTree *localtree, struct bNodeTree *ntree); /* Tree update. Overrides nodetype->updatetreefunc! */ void (*update)(struct bNodeTree *ntree); @@ -371,7 +371,7 @@ int ntreeOutputExists(struct bNode *node, struct bNodeSocket *testso void ntreeNodeFlagSet(const bNodeTree *ntree, const int flag, const bool enable); struct bNodeTree *ntreeLocalize(struct bNodeTree *ntree); void ntreeLocalSync(struct bNodeTree *localtree, struct bNodeTree *ntree); -void ntreeLocalMerge(struct bNodeTree *localtree, struct bNodeTree *ntree); +void ntreeLocalMerge(struct Main *bmain, struct bNodeTree *localtree, struct bNodeTree *ntree); /** \} */ diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index 6172c9998af..ab8327d354a 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -258,12 +258,10 @@ void BKE_object_eval_flush_base_flags( struct Object *object, int base_index, const bool is_from_set); -void BKE_object_handle_data_update( - struct Depsgraph *depsgraph, +void BKE_object_handle_data_update(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob); -void BKE_object_handle_update( - struct Depsgraph *depsgraph, +void BKE_object_handle_update(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob); void BKE_object_handle_update_ex( struct Depsgraph *depsgraph, @@ -281,7 +279,7 @@ struct Mesh *BKE_object_get_original_mesh(struct Object *object); int BKE_object_insert_ptcache(struct Object *ob); void BKE_object_delete_ptcache(struct Object *ob, int index); -struct KeyBlock *BKE_object_shapekey_insert(struct Object *ob, const char *name, const bool from_mix); +struct KeyBlock *BKE_object_shapekey_insert(struct Main *bmain, struct Object *ob, const char *name, const bool from_mix); bool BKE_object_shapekey_remove(struct Main *bmain, struct Object *ob, struct KeyBlock *kb); bool BKE_object_shapekey_free(struct Main *bmain, struct Object *ob); diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index 412cf45de2b..2ba6446c18f 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -121,7 +121,7 @@ void BKE_paint_curve_copy_data( struct PaintCurve *BKE_paint_curve_copy(struct Main *bmain, const struct PaintCurve *pc); void BKE_paint_curve_make_local(struct Main *bmain, struct PaintCurve *pc, const bool lib_local); -void BKE_paint_init(struct Scene *sce, ePaintMode mode, const char col[3]); +void BKE_paint_init(struct Main *bmain, struct Scene *sce, ePaintMode mode, const char col[3]); void BKE_paint_free(struct Paint *p); void BKE_paint_copy(struct Paint *src, struct Paint *tar, const int flag); diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index 2f192c43504..9a9b8016e27 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -90,6 +90,8 @@ typedef struct ParticleSimulationData { * maximum value per time step is important. Only sph_integrate makes use of * this at the moment. Other solvers could, too. */ float courant_num; + /* Only valid during dynamics_step(). */ + struct RNG *rng; } ParticleSimulationData; typedef struct SPHData { @@ -329,9 +331,10 @@ void psys_particle_on_emitter(struct ParticleSystemModifierData *psmd, int distr float utan[3], float vtan[3], float orco[3]); struct ParticleSystemModifierData *psys_get_modifier(struct Object *ob, struct ParticleSystem *psys); -struct ModifierData *object_add_particle_system(struct Scene *scene, struct Object *ob, const char *name); -void object_remove_particle_system(struct Scene *scene, struct Object *ob); -struct ParticleSettings *BKE_particlesettings_add(struct Main *main, const char *name); +struct ModifierData *object_add_particle_system( + struct Main *bmain, struct Scene *scene, struct Object *ob, const char *name); +void object_remove_particle_system(struct Main *bmain, struct Scene *scene, struct Object *ob); +struct ParticleSettings *BKE_particlesettings_add(struct Main *bmain, const char *name); void BKE_particlesettings_copy_data( struct Main *bmain, struct ParticleSettings *part_dst, const struct ParticleSettings *part_src, const int flag); diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h index 89f1aa5eadd..8daef0348b9 100644 --- a/source/blender/blenkernel/BKE_pointcache.h +++ b/source/blender/blenkernel/BKE_pointcache.h @@ -185,7 +185,7 @@ typedef struct PTCacheID { } PTCacheID; typedef struct PTCacheBaker { - struct Main *main; + struct Main *bmain; struct Scene *scene; struct ViewLayer *view_layer; struct Depsgraph *depsgraph; @@ -278,7 +278,8 @@ void BKE_ptcache_id_from_dynamicpaint(PTCacheID *pid, struct Object *ob, struct void BKE_ptcache_id_from_rigidbody(PTCacheID *pid, struct Object *ob, struct RigidBodyWorld *rbw); PTCacheID BKE_ptcache_id_find(struct Object *ob, struct Scene *scene, struct PointCache *cache); -void BKE_ptcache_ids_from_object(struct ListBase *lb, struct Object *ob, struct Scene *scene, int duplis); +void BKE_ptcache_ids_from_object( + struct ListBase *lb, struct Object *ob, struct Scene *scene, int duplis); /***************** Global funcs ****************************/ void BKE_ptcache_remove(void); diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h index 0b95152ad8e..1b42ce97940 100644 --- a/source/blender/blenkernel/BKE_screen.h +++ b/source/blender/blenkernel/BKE_screen.h @@ -216,6 +216,8 @@ typedef struct PanelType { int (*poll)(const struct bContext *C, struct PanelType *pt); /* draw header (optional) */ void (*draw_header)(const struct bContext *C, struct Panel *pa); + /* draw header preset (optional) */ + void (*draw_header_preset)(const struct bContext *C, struct Panel *pa); /* draw entirely, view changes should be handled here */ void (*draw)(const struct bContext *C, struct Panel *pa); @@ -305,6 +307,7 @@ typedef struct Menu { /* spacetypes */ struct SpaceType *BKE_spacetype_from_id(int spaceid); +struct ARegionType *BKE_regiontype_from_id_or_first(struct SpaceType *st, int regionid); struct ARegionType *BKE_regiontype_from_id(struct SpaceType *st, int regionid); const struct ListBase *BKE_spacetypes_list(void); void BKE_spacetype_register(struct SpaceType *st); diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h index 63c91ef9635..a541120638b 100644 --- a/source/blender/blenkernel/BKE_sequencer.h +++ b/source/blender/blenkernel/BKE_sequencer.h @@ -495,6 +495,6 @@ struct ImBuf *BKE_sequencer_render_mask_input( int cfra, int fra_offset, bool make_float); void BKE_sequencer_color_balance_apply(struct StripColorBalance *cb, struct ImBuf *ibuf, float mul, bool make_float, struct ImBuf *mask_input); -void BKE_sequencer_all_free_anim_ibufs(int cfra); +void BKE_sequencer_all_free_anim_ibufs(struct Main *bmain, int cfra); #endif /* __BKE_SEQUENCER_H__ */ diff --git a/source/blender/blenkernel/BKE_studiolight.h b/source/blender/blenkernel/BKE_studiolight.h index 7883f89f33a..e4c4fd87ecd 100644 --- a/source/blender/blenkernel/BKE_studiolight.h +++ b/source/blender/blenkernel/BKE_studiolight.h @@ -51,8 +51,11 @@ #define STUDIOLIGHT_Y_NEG 3 #define STUDIOLIGHT_Z_POS 4 #define STUDIOLIGHT_Z_NEG 5 -#define STUDIOLIGHT_ICON_ID_TYPE_RADIANCE 0 -#define STUDIOLIGHT_ICON_ID_TYPE_IRRADIANCE 1 + +#define STUDIOLIGHT_ICON_ID_TYPE_RADIANCE 0 +#define STUDIOLIGHT_ICON_ID_TYPE_IRRADIANCE 1 +#define STUDIOLIGHT_ICON_ID_TYPE_MATCAP 2 +#define STUDIOLIGHT_ICON_ID_TYPE_MATCAP_FLIPPED 3 struct GPUTexture; @@ -75,15 +78,18 @@ enum StudioLightFlag { #define STUDIOLIGHT_FLAG_ALL (STUDIOLIGHT_INTERNAL | STUDIOLIGHT_EXTERNAL_FILE) #define STUDIOLIGHT_FLAG_ORIENTATIONS (STUDIOLIGHT_ORIENTATION_CAMERA | STUDIOLIGHT_ORIENTATION_WORLD | STUDIOLIGHT_ORIENTATION_VIEWNORMAL) #define STUDIOLIGHT_ORIENTATIONS_MATERIAL_MODE (STUDIOLIGHT_INTERNAL | STUDIOLIGHT_ORIENTATION_WORLD) -#define STUDIOLIGHT_ORIENTATIONS_SOLID (STUDIOLIGHT_ORIENTATION_CAMERA | STUDIOLIGHT_ORIENTATION_WORLD) +#define STUDIOLIGHT_ORIENTATIONS_SOLID (STUDIOLIGHT_INTERNAL | STUDIOLIGHT_ORIENTATION_CAMERA | STUDIOLIGHT_ORIENTATION_WORLD) typedef struct StudioLight { struct StudioLight *next, *prev; int flag; char name[FILE_MAXFILE]; char path[FILE_MAX]; - int irradiance_icon_id; - int radiance_icon_id; + char *path_irr; + int icon_id_irradiance; + int icon_id_radiance; + int icon_id_matcap; + int icon_id_matcap_flipped; int index; float diffuse_light[6][3]; float light_direction[3]; diff --git a/source/blender/blenkernel/BKE_undo_system.h b/source/blender/blenkernel/BKE_undo_system.h index 05093deec70..a75606a17cb 100644 --- a/source/blender/blenkernel/BKE_undo_system.h +++ b/source/blender/blenkernel/BKE_undo_system.h @@ -135,6 +135,7 @@ extern const UndoType *BKE_UNDOSYS_TYPE_TEXT; UndoStack *BKE_undosys_stack_create(void); void BKE_undosys_stack_destroy(UndoStack *ustack); void BKE_undosys_stack_clear(UndoStack *ustack); +void BKE_undosys_stack_clear_active(UndoStack *ustack); bool BKE_undosys_stack_has_undo(UndoStack *ustack, const char *name); void BKE_undosys_stack_init_from_main(UndoStack *ustack, struct Main *bmain); void BKE_undosys_stack_init_from_context(UndoStack *ustack, struct bContext *C); diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index c081bb0799f..c4904fcaa7c 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -2051,6 +2051,7 @@ static void mesh_calc_modifiers( ModifierApplyFlag app_flags = useRenderParams ? MOD_APPLY_RENDER : 0; ModifierApplyFlag deform_app_flags = app_flags; + BLI_assert((me->id.tag & LIB_TAG_COPIED_ON_WRITE_EVAL_RESULT) == 0); if (useCache) app_flags |= MOD_APPLY_USECACHE; diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index 01f6eab261f..28534fc9783 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -426,7 +426,7 @@ bPoseChannel *BKE_pose_channel_verify(bPose *pose, const char *name) return NULL; /* See if this channel exists */ - chan = BLI_findstring(&pose->chanbase, name, offsetof(bPoseChannel, name)); + chan = BKE_pose_channel_find_name(pose, name); if (chan) { return chan; } @@ -454,7 +454,9 @@ bPoseChannel *BKE_pose_channel_verify(bPose *pose, const char *name) chan->protectflag = OB_LOCK_ROT4D; /* lock by components by default */ BLI_addtail(&pose->chanbase, chan); - BKE_pose_channels_hash_free(pose); + if (pose->chanhash) { + BLI_ghash_insert(pose->chanhash, chan->name, chan); + } return chan; } diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index c7730d8877b..e2cecb32a36 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -275,7 +275,6 @@ typedef struct MPathTarget { * that provide all the coordinates we want to save off) */ Object *ob_eval; /* evaluated object */ - bPoseChannel *pchan_eval; /* evaluated posechannel (if applicable) */ } MPathTarget; /* ........ */ @@ -348,9 +347,6 @@ static void motionpaths_calc_bake_targets(Scene *scene, ListBase *targets) bMotionPath *mpath = mpt->mpath; bMotionPathVert *mpv; - Object *ob_eval = mpt->ob_eval; - bPoseChannel *pchan_eval = mpt->pchan_eval; - /* current frame must be within the range the cache works for * - is inclusive of the first frame, but not the last otherwise we get buffer overruns */ @@ -361,8 +357,17 @@ static void motionpaths_calc_bake_targets(Scene *scene, ListBase *targets) /* get the relevant cache vert to write to */ mpv = mpath->points + (CFRA - mpath->start_frame); + Object *ob_eval = mpt->ob_eval; + + /* Lookup evaluated pose channel, here because the depsgraph + * evaluation can change them so they are not cached in mpt. */ + bPoseChannel *pchan_eval = NULL; + if (mpt->pchan) { + pchan_eval = BKE_pose_channel_find_name(ob_eval->pose, mpt->pchan->name); + } + /* pose-channel or object path baking? */ - if (mpt->pchan_eval) { + if (pchan_eval) { /* heads or tails */ if (mpath->flag & MOTIONPATH_FLAG_BHEAD) { copy_v3_v3(mpv->co, pchan_eval->pose_head); @@ -425,9 +430,6 @@ static void motionpaths_calc_bake_targets(Scene *scene, ListBase *targets) // TODO: Create a copy of background depsgraph that only contain these entities, and only evaluates them.. for (mpt = targets->first; mpt; mpt = mpt->next) { mpt->ob_eval = DEG_get_evaluated_object(depsgraph, mpt->ob); - if (mpt->pchan) { - mpt->pchan_eval = BKE_pose_channel_find_name(mpt->ob_eval->pose, mpt->pchan->name); - } AnimData *adt = BKE_animdata_from_id(&mpt->ob_eval->id); diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index e5a68fa7476..ec979623a98 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -288,7 +288,7 @@ AnimData *BKE_animdata_copy(Main *bmain, AnimData *adt, const bool do_action, co } /* duplicate NLA data */ - BKE_nla_tracks_copy(&dadt->nla_tracks, &adt->nla_tracks); + BKE_nla_tracks_copy(bmain, &dadt->nla_tracks, &adt->nla_tracks); /* duplicate drivers (F-Curves) */ copy_fcurves(&dadt->drivers, &adt->drivers); @@ -319,25 +319,27 @@ bool BKE_animdata_copy_id(Main *bmain, ID *id_to, ID *id_from, const bool do_act return true; } -void BKE_animdata_copy_id_action(ID *id, const bool set_newid) +void BKE_animdata_copy_id_action(Main *bmain, ID *id, const bool set_newid) { AnimData *adt = BKE_animdata_from_id(id); if (adt) { if (adt->action) { id_us_min((ID *)adt->action); - adt->action = set_newid ? ID_NEW_SET(adt->action, BKE_action_copy(G.main, adt->action)) : - BKE_action_copy(G.main, adt->action); + adt->action = set_newid ? ID_NEW_SET(adt->action, BKE_action_copy(bmain, adt->action)) : + BKE_action_copy(bmain, adt->action); } if (adt->tmpact) { id_us_min((ID *)adt->tmpact); - adt->tmpact = set_newid ? ID_NEW_SET(adt->tmpact, BKE_action_copy(G.main, adt->tmpact)) : - BKE_action_copy(G.main, adt->tmpact); + adt->tmpact = set_newid ? ID_NEW_SET(adt->tmpact, BKE_action_copy(bmain, adt->tmpact)) : + BKE_action_copy(bmain, adt->tmpact); } } } /* Merge copies of the data from the src AnimData into the destination AnimData */ -void BKE_animdata_merge_copy(ID *dst_id, ID *src_id, eAnimData_MergeCopy_Modes action_mode, bool fix_drivers) +void BKE_animdata_merge_copy( + Main *bmain, ID *dst_id, ID *src_id, + eAnimData_MergeCopy_Modes action_mode, bool fix_drivers) { AnimData *src = BKE_animdata_from_id(src_id); AnimData *dst = BKE_animdata_from_id(dst_id); @@ -355,8 +357,8 @@ void BKE_animdata_merge_copy(ID *dst_id, ID *src_id, eAnimData_MergeCopy_Modes a /* handle actions... */ if (action_mode == ADT_MERGECOPY_SRC_COPY) { /* make a copy of the actions */ - dst->action = BKE_action_copy(G.main, src->action); - dst->tmpact = BKE_action_copy(G.main, src->tmpact); + dst->action = BKE_action_copy(bmain, src->action); + dst->tmpact = BKE_action_copy(bmain, src->tmpact); } else if (action_mode == ADT_MERGECOPY_SRC_REF) { /* make a reference to it */ @@ -371,7 +373,7 @@ void BKE_animdata_merge_copy(ID *dst_id, ID *src_id, eAnimData_MergeCopy_Modes a if (src->nla_tracks.first) { ListBase tracks = {NULL, NULL}; - BKE_nla_tracks_copy(&tracks, &src->nla_tracks); + BKE_nla_tracks_copy(bmain, &tracks, &src->nla_tracks); BLI_movelisttolist(&dst->nla_tracks, &tracks); } @@ -508,7 +510,8 @@ void action_move_fcurves_by_basepath(bAction *srcAct, bAction *dstAct, const cha * animation data is based off "basepath", creating new AnimData and * associated data as necessary */ -void BKE_animdata_separate_by_basepath(ID *srcID, ID *dstID, ListBase *basepaths) +void BKE_animdata_separate_by_basepath( + Main *bmain, ID *srcID, ID *dstID, ListBase *basepaths) { AnimData *srcAdt = NULL, *dstAdt = NULL; LinkData *ld; @@ -534,7 +537,7 @@ void BKE_animdata_separate_by_basepath(ID *srcID, ID *dstID, ListBase *basepaths if (srcAdt->action) { /* set up an action if necessary, and name it in a similar way so that it can be easily found again */ if (dstAdt->action == NULL) { - dstAdt->action = BKE_action_add(G.main, srcAdt->action->id.name + 2); + dstAdt->action = BKE_action_add(bmain, srcAdt->action->id.name + 2); } else if (dstAdt->action == srcAdt->action) { printf("Argh! Source and Destination share animation! ('%s' and '%s' both use '%s') Making new empty action\n", @@ -542,7 +545,7 @@ void BKE_animdata_separate_by_basepath(ID *srcID, ID *dstID, ListBase *basepaths /* TODO: review this... */ id_us_min(&dstAdt->action->id); - dstAdt->action = BKE_action_add(G.main, dstAdt->action->id.name + 2); + dstAdt->action = BKE_action_add(bmain, dstAdt->action->id.name + 2); } /* loop over base paths, trying to fix for each one... */ @@ -1051,20 +1054,20 @@ static void adt_apply_all_fcurves_cb(ID *id, AnimData *adt, void *wrapper_data) } /* apply the given callback function on all F-Curves attached to data in main database */ -void BKE_fcurves_main_cb(Main *mainptr, ID_FCurve_Edit_Callback func, void *user_data) +void BKE_fcurves_main_cb(Main *bmain, ID_FCurve_Edit_Callback func, void *user_data) { /* Wrap F-Curve operation stuff to pass to the general AnimData-level func */ AllFCurvesCbWrapper wrapper = {func, user_data}; /* Use the AnimData-based function so that we don't have to reimplement all that stuff */ - BKE_animdata_main_cb(mainptr, adt_apply_all_fcurves_cb, &wrapper); + BKE_animdata_main_cb(bmain, adt_apply_all_fcurves_cb, &wrapper); } /* Whole Database Ops -------------------------------------------- */ /* apply the given callback function on all data in main database */ -void BKE_animdata_main_cb(Main *mainptr, ID_AnimData_Edit_Callback func, void *user_data) +void BKE_animdata_main_cb(Main *bmain, ID_AnimData_Edit_Callback func, void *user_data) { ID *id; @@ -1088,67 +1091,67 @@ void BKE_animdata_main_cb(Main *mainptr, ID_AnimData_Edit_Callback func, void *u } (void)0 /* nodes */ - ANIMDATA_IDS_CB(mainptr->nodetree.first); + ANIMDATA_IDS_CB(bmain->nodetree.first); /* textures */ - ANIMDATA_NODETREE_IDS_CB(mainptr->tex.first, Tex); + ANIMDATA_NODETREE_IDS_CB(bmain->tex.first, Tex); /* lamps */ - ANIMDATA_NODETREE_IDS_CB(mainptr->lamp.first, Lamp); + ANIMDATA_NODETREE_IDS_CB(bmain->lamp.first, Lamp); /* materials */ - ANIMDATA_NODETREE_IDS_CB(mainptr->mat.first, Material); + ANIMDATA_NODETREE_IDS_CB(bmain->mat.first, Material); /* cameras */ - ANIMDATA_IDS_CB(mainptr->camera.first); + ANIMDATA_IDS_CB(bmain->camera.first); /* shapekeys */ - ANIMDATA_IDS_CB(mainptr->key.first); + ANIMDATA_IDS_CB(bmain->key.first); /* metaballs */ - ANIMDATA_IDS_CB(mainptr->mball.first); + ANIMDATA_IDS_CB(bmain->mball.first); /* curves */ - ANIMDATA_IDS_CB(mainptr->curve.first); + ANIMDATA_IDS_CB(bmain->curve.first); /* armatures */ - ANIMDATA_IDS_CB(mainptr->armature.first); + ANIMDATA_IDS_CB(bmain->armature.first); /* lattices */ - ANIMDATA_IDS_CB(mainptr->latt.first); + ANIMDATA_IDS_CB(bmain->latt.first); /* meshes */ - ANIMDATA_IDS_CB(mainptr->mesh.first); + ANIMDATA_IDS_CB(bmain->mesh.first); /* particles */ - ANIMDATA_IDS_CB(mainptr->particle.first); + ANIMDATA_IDS_CB(bmain->particle.first); /* speakers */ - ANIMDATA_IDS_CB(mainptr->speaker.first); + ANIMDATA_IDS_CB(bmain->speaker.first); /* movie clips */ - ANIMDATA_IDS_CB(mainptr->movieclip.first); + ANIMDATA_IDS_CB(bmain->movieclip.first); /* objects */ - ANIMDATA_IDS_CB(mainptr->object.first); + ANIMDATA_IDS_CB(bmain->object.first); /* masks */ - ANIMDATA_IDS_CB(mainptr->mask.first); + ANIMDATA_IDS_CB(bmain->mask.first); /* worlds */ - ANIMDATA_NODETREE_IDS_CB(mainptr->world.first, World); + ANIMDATA_NODETREE_IDS_CB(bmain->world.first, World); /* scenes */ - ANIMDATA_NODETREE_IDS_CB(mainptr->scene.first, Scene); + ANIMDATA_NODETREE_IDS_CB(bmain->scene.first, Scene); /* line styles */ - ANIMDATA_IDS_CB(mainptr->linestyle.first); + ANIMDATA_IDS_CB(bmain->linestyle.first); /* grease pencil */ - ANIMDATA_IDS_CB(mainptr->gpencil.first); + ANIMDATA_IDS_CB(bmain->gpencil.first); /* cache files */ - ANIMDATA_IDS_CB(mainptr->cachefiles.first); + ANIMDATA_IDS_CB(bmain->cachefiles.first); } /* Fix all RNA-Paths throughout the database (directly access the Global.main version) @@ -1158,7 +1161,7 @@ void BKE_animdata_main_cb(Main *mainptr, ID_AnimData_Edit_Callback func, void *u /* TODO: use BKE_animdata_main_cb for looping over all data */ void BKE_animdata_fix_paths_rename_all(ID *ref_id, const char *prefix, const char *oldName, const char *newName) { - Main *mainptr = G.main; + Main *bmain = G.main; /* XXX UGLY! */ ID *id; /* macro for less typing @@ -1184,67 +1187,67 @@ void BKE_animdata_fix_paths_rename_all(ID *ref_id, const char *prefix, const cha } (void)0 /* nodes */ - RENAMEFIX_ANIM_IDS(mainptr->nodetree.first); + RENAMEFIX_ANIM_IDS(bmain->nodetree.first); /* textures */ - RENAMEFIX_ANIM_NODETREE_IDS(mainptr->tex.first, Tex); + RENAMEFIX_ANIM_NODETREE_IDS(bmain->tex.first, Tex); /* lamps */ - RENAMEFIX_ANIM_NODETREE_IDS(mainptr->lamp.first, Lamp); + RENAMEFIX_ANIM_NODETREE_IDS(bmain->lamp.first, Lamp); /* materials */ - RENAMEFIX_ANIM_NODETREE_IDS(mainptr->mat.first, Material); + RENAMEFIX_ANIM_NODETREE_IDS(bmain->mat.first, Material); /* cameras */ - RENAMEFIX_ANIM_IDS(mainptr->camera.first); + RENAMEFIX_ANIM_IDS(bmain->camera.first); /* shapekeys */ - RENAMEFIX_ANIM_IDS(mainptr->key.first); + RENAMEFIX_ANIM_IDS(bmain->key.first); /* metaballs */ - RENAMEFIX_ANIM_IDS(mainptr->mball.first); + RENAMEFIX_ANIM_IDS(bmain->mball.first); /* curves */ - RENAMEFIX_ANIM_IDS(mainptr->curve.first); + RENAMEFIX_ANIM_IDS(bmain->curve.first); /* armatures */ - RENAMEFIX_ANIM_IDS(mainptr->armature.first); + RENAMEFIX_ANIM_IDS(bmain->armature.first); /* lattices */ - RENAMEFIX_ANIM_IDS(mainptr->latt.first); + RENAMEFIX_ANIM_IDS(bmain->latt.first); /* meshes */ - RENAMEFIX_ANIM_IDS(mainptr->mesh.first); + RENAMEFIX_ANIM_IDS(bmain->mesh.first); /* particles */ - RENAMEFIX_ANIM_IDS(mainptr->particle.first); + RENAMEFIX_ANIM_IDS(bmain->particle.first); /* speakers */ - RENAMEFIX_ANIM_IDS(mainptr->speaker.first); + RENAMEFIX_ANIM_IDS(bmain->speaker.first); /* movie clips */ - RENAMEFIX_ANIM_IDS(mainptr->movieclip.first); + RENAMEFIX_ANIM_IDS(bmain->movieclip.first); /* objects */ - RENAMEFIX_ANIM_IDS(mainptr->object.first); + RENAMEFIX_ANIM_IDS(bmain->object.first); /* masks */ - RENAMEFIX_ANIM_IDS(mainptr->mask.first); + RENAMEFIX_ANIM_IDS(bmain->mask.first); /* worlds */ - RENAMEFIX_ANIM_NODETREE_IDS(mainptr->world.first, World); + RENAMEFIX_ANIM_NODETREE_IDS(bmain->world.first, World); /* linestyles */ - RENAMEFIX_ANIM_IDS(mainptr->linestyle.first); + RENAMEFIX_ANIM_IDS(bmain->linestyle.first); /* grease pencil */ - RENAMEFIX_ANIM_IDS(mainptr->gpencil.first); + RENAMEFIX_ANIM_IDS(bmain->gpencil.first); /* cache files */ - RENAMEFIX_ANIM_IDS(mainptr->cachefiles.first); + RENAMEFIX_ANIM_IDS(bmain->cachefiles.first); /* scenes */ - RENAMEFIX_ANIM_NODETREE_IDS(mainptr->scene.first, Scene); + RENAMEFIX_ANIM_NODETREE_IDS(bmain->scene.first, Scene); } /* *********************************** */ @@ -3017,7 +3020,7 @@ void BKE_animsys_eval_driver(Depsgraph *depsgraph, PathResolvedRNA anim_rna; if (animsys_store_rna_setting(&id_ptr, NULL, fcu->rna_path, fcu->array_index, &anim_rna)) { const float ctime = DEG_get_ctime(depsgraph); - const float curval = calculate_fcurve(&anim_rna, fcu, ctime); + const float curval = evaluate_fcurve_driver(&anim_rna, fcu, driver_orig, ctime); ok = animsys_write_rna_setting(&anim_rna, curval); if (ok && DEG_is_active(depsgraph)) { animsys_write_orig_anim_rna(&id_ptr, NULL, fcu, curval); diff --git a/source/blender/blenkernel/intern/armature_update.c b/source/blender/blenkernel/intern/armature_update.c index 9613ec4116a..ce99da87c74 100644 --- a/source/blender/blenkernel/intern/armature_update.c +++ b/source/blender/blenkernel/intern/armature_update.c @@ -692,6 +692,8 @@ void BKE_pose_bone_done(struct Depsgraph *depsgraph, bPoseChannel *pchan_orig = pchan->orig_pchan; copy_m4_m4(pchan_orig->pose_mat, pchan->pose_mat); copy_m4_m4(pchan_orig->chan_mat, pchan->chan_mat); + copy_v3_v3(pchan_orig->pose_head, pchan->pose_mat[3]); + BKE_pose_where_is_bone_tail(pchan_orig); } } diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index 3f78b096115..1ec5b347168 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -81,9 +81,9 @@ char versionstr[48] = ""; /* only to be called on exit blender */ void BKE_blender_free(void) { - /* samples are in a global list..., also sets G.main->sound->sample NULL */ - BKE_main_free(G.main); - G.main = NULL; + /* samples are in a global list..., also sets G_MAIN->sound->sample NULL */ + BKE_main_free(G_MAIN); + G_MAIN = NULL; if (G.log.file != NULL) { fclose(G.log.file); @@ -125,7 +125,7 @@ void BKE_blender_globals_init(void) U.savetime = 1; - G.main = BKE_main_new(); + G_MAIN = BKE_main_new(); strcpy(G.ima, "//"); @@ -142,9 +142,9 @@ void BKE_blender_globals_init(void) void BKE_blender_globals_clear(void) { - BKE_main_free(G.main); /* free all lib data */ + BKE_main_free(G_MAIN); /* free all lib data */ - G.main = NULL; + G_MAIN = NULL; } /***/ diff --git a/source/blender/blenkernel/intern/blendfile.c b/source/blender/blenkernel/intern/blendfile.c index 597c69408b5..27b5089b092 100644 --- a/source/blender/blenkernel/intern/blendfile.c +++ b/source/blender/blenkernel/intern/blendfile.c @@ -116,7 +116,7 @@ static void setup_app_data( bContext *C, BlendFileData *bfd, const char *filepath, ReportList *reports) { - Main *bmain = G.main; /* Valid usage */ + Main *bmain = G_MAIN; Scene *curscene = NULL; const bool is_startup = (bfd->filename[0] == '\0'); const bool recover = (G.fileflags & G_FILE_RECOVER) != 0; @@ -207,7 +207,7 @@ static void setup_app_data( win->scene = curscene; } - /* BKE_blender_globals_clear will free G.main, here we can still restore pointers */ + /* BKE_blender_globals_clear will free G_MAIN, here we can still restore pointers */ blo_lib_link_restore(bfd->main, CTX_wm_manager(C), curscene, cur_view_layer); if (win) { curscene = win->scene; @@ -230,14 +230,14 @@ static void setup_app_data( } } - /* free G.main Main database */ + /* free G_MAIN Main database */ // CTX_wm_manager_set(C, NULL); BKE_blender_globals_clear(); /* clear old property update cache, in case some old references are left dangling */ RNA_property_update_cache_free(); - bmain = G.main = bfd->main; + bmain = G_MAIN = bfd->main; CTX_data_main_set(C, bmain); diff --git a/source/blender/blenkernel/intern/bpath.c b/source/blender/blenkernel/intern/bpath.c index 82d9f9f8f69..7c9e57b039e 100644 --- a/source/blender/blenkernel/intern/bpath.c +++ b/source/blender/blenkernel/intern/bpath.c @@ -442,7 +442,7 @@ void BKE_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int /* image may have been painted onto (and not saved, T44543) */ !BKE_image_is_dirty(ima)) { - BKE_image_signal(ima, NULL, IMA_SIGNAL_RELOAD); + BKE_image_signal(bmain, ima, NULL, IMA_SIGNAL_RELOAD); BKE_image_walk_all_users(bmain, ima, bpath_traverse_image_user_cb); } } diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index d82c1ca56fe..7f50e521e63 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -457,68 +457,6 @@ void BKE_brush_curve_preset(Brush *b, eCurveMappingPreset preset) curvemapping_changed(b->curve, false); } -/* XXX Unused function. */ -int BKE_brush_texture_set_nr(Brush *brush, int nr) -{ - ID *idtest, *id = NULL; - - id = (ID *)brush->mtex.tex; - - idtest = (ID *)BLI_findlink(&G.main->tex, nr - 1); - if (idtest == NULL) { /* new tex */ - if (id) idtest = (ID *)BKE_texture_copy(G.main, (Tex *)id); - else idtest = (ID *)BKE_texture_add(G.main, "Tex"); - id_us_min(idtest); - } - if (idtest != id) { - BKE_brush_texture_delete(brush); - - brush->mtex.tex = (Tex *)idtest; - id_us_plus(idtest); - - return 1; - } - - return 0; -} - -int BKE_brush_texture_delete(Brush *brush) -{ - if (brush->mtex.tex) - id_us_min(&brush->mtex.tex->id); - - return 1; -} - -int BKE_brush_clone_image_set_nr(Brush *brush, int nr) -{ - if (brush && nr > 0) { - Image *ima = (Image *)BLI_findlink(&G.main->image, nr - 1); - - if (ima) { - BKE_brush_clone_image_delete(brush); - brush->clone.image = ima; - id_us_plus(&ima->id); - brush->clone.offset[0] = brush->clone.offset[1] = 0.0f; - - return 1; - } - } - - return 0; -} - -int BKE_brush_clone_image_delete(Brush *brush) -{ - if (brush && brush->clone.image) { - id_us_min(&brush->clone.image->id); - brush->clone.image = NULL; - return 1; - } - - return 0; -} - /* Generic texture sampler for 3D painting systems. point has to be either in * region space mouse coordinates, or 3d world coordinates for 3D mapping. * diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c index ab0ec8b0491..3f30082576c 100644 --- a/source/blender/blenkernel/intern/collection.c +++ b/source/blender/blenkernel/intern/collection.c @@ -297,20 +297,6 @@ void BKE_collection_new_name_get(Collection *collection_parent, char *rname) MEM_freeN(name); } -/************************* Dependencies ****************************/ - -bool BKE_collection_is_animated(Collection *collection, Object *UNUSED(parent)) -{ - FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(collection, object) - { - if (object->proxy) { - return true; - } - } - FOREACH_COLLECTION_OBJECT_RECURSIVE_END; - return false; -} - /* **************** Object List Cache *******************/ static void collection_object_cache_fill(ListBase *lb, Collection *collection, int parent_restrict) @@ -325,13 +311,8 @@ static void collection_object_cache_fill(ListBase *lb, Collection *collection, i base->object = cob->ob; if ((child_restrict & COLLECTION_RESTRICT_VIEW) == 0) { - base->flag |= BASE_VISIBLED | BASE_VISIBLE_VIEWPORT; - - if ((child_restrict & COLLECTION_RESTRICT_SELECT) == 0) { - base->flag |= BASE_SELECTABLED; - } + base->flag |= BASE_VISIBLE_VIEWPORT; } - if ((child_restrict & COLLECTION_RESTRICT_RENDER) == 0) { base->flag |= BASE_VISIBLE_RENDER; } @@ -377,7 +358,7 @@ void BKE_collection_object_cache_free(Collection *collection) collection_object_cache_free(collection); } -Base *BKE_collection_or_layer_objects(Depsgraph *depsgraph, +Base *BKE_collection_or_layer_objects(const Depsgraph *depsgraph, const Scene *scene, const ViewLayer *view_layer, Collection *collection) diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index 01da9857864..504999b0b10 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -4962,7 +4962,7 @@ bool BKE_curve_minmax(Curve *cu, bool use_radius, float min[3], float max[3]) */ if (is_font) { nurb_lb = &temp_nurb_lb; - BKE_vfont_to_curve_ex(G.main, NULL, cu, FO_EDIT, nurb_lb, + BKE_vfont_to_curve_ex(NULL, cu, FO_EDIT, nurb_lb, NULL, NULL, NULL, NULL); use_radius = false; } diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index aa67eafaa98..2f33ca3210d 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -3483,7 +3483,7 @@ bool CustomData_verify_versions(struct CustomData *data, int index) static void customdata_external_filename(char filename[FILE_MAX], ID *id, CustomDataExternal *external) { BLI_strncpy(filename, external->filename, FILE_MAX); - BLI_path_abs(filename, ID_BLEND_PATH(G.main, id)); + BLI_path_abs(filename, ID_BLEND_PATH_FROM_GLOBAL(id)); } void CustomData_external_reload(CustomData *data, ID *UNUSED(id), CustomDataMask mask, int totelem) diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index a591ab354f6..ad055a727a9 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -53,6 +53,7 @@ #include "BKE_cdderivedmesh.h" #include "BKE_object.h" #include "BKE_library.h" +#include "BKE_main.h" #include "BKE_mball.h" #include "BKE_mball_tessellate.h" #include "BKE_mesh.h" @@ -1572,7 +1573,7 @@ static void do_makeDispListCurveTypes( } if (ob->type == OB_FONT) { - BKE_vfont_to_curve_nubase(G.main, ob, FO_EDIT, &nubase); + BKE_vfont_to_curve_nubase(ob, FO_EDIT, &nubase); } else { BKE_nurbList_duplicate(&nubase, BKE_curve_nurbs_get(cu)); diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c index 36452e1d2cf..ed2566c9bb5 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.c +++ b/source/blender/blenkernel/intern/dynamicpaint.c @@ -490,9 +490,9 @@ static void scene_setSubframe(Scene *scene, float subframe) scene->r.subframe = subframe; } -static int surface_getBrushFlags(DynamicPaintSurface *surface, const ViewLayer *view_layer) +static int surface_getBrushFlags(DynamicPaintSurface *surface, const Depsgraph *depsgraph) { - Base *base = BKE_collection_or_layer_objects(NULL, NULL, view_layer, surface->brush_group); + Base *base = BKE_collection_or_layer_objects(depsgraph, NULL, NULL, surface->brush_group); Object *brushObj = NULL; ModifierData *md = NULL; @@ -3645,7 +3645,7 @@ static void dynamic_paint_brush_velocity_compute_cb( } static void dynamicPaint_brushMeshCalculateVelocity( - struct Depsgraph *depsgraph, Scene *scene, + Depsgraph *depsgraph, Scene *scene, Object *ob, DynamicPaintBrushSettings *brush, Vec3f **brushVel, float timescale) { float prev_obmat[4][4]; @@ -3710,7 +3710,8 @@ static void dynamicPaint_brushMeshCalculateVelocity( } /* calculate velocity for object center point */ -static void dynamicPaint_brushObjectCalculateVelocity(struct Depsgraph *depsgraph, Scene *scene, Object *ob, Vec3f *brushVel, float timescale) +static void dynamicPaint_brushObjectCalculateVelocity( + Depsgraph *depsgraph, Scene *scene, Object *ob, Vec3f *brushVel, float timescale) { float prev_obmat[4][4]; float cur_loc[3] = {0.0f}, prev_loc[3] = {0.0f}; @@ -4096,7 +4097,7 @@ static void dynamic_paint_paint_mesh_cell_point_cb_ex( } } -static int dynamicPaint_paintMesh(struct Depsgraph *depsgraph, DynamicPaintSurface *surface, +static int dynamicPaint_paintMesh(Depsgraph *depsgraph, DynamicPaintSurface *surface, DynamicPaintBrushSettings *brush, Object *brushOb, Scene *scene, @@ -4584,7 +4585,7 @@ static void dynamic_paint_paint_single_point_cb_ex( } static int dynamicPaint_paintSinglePoint( - struct Depsgraph *depsgraph, DynamicPaintSurface *surface, float *pointCoord, DynamicPaintBrushSettings *brush, + Depsgraph *depsgraph, DynamicPaintSurface *surface, float *pointCoord, DynamicPaintBrushSettings *brush, Object *brushOb, Scene *scene, float timescale) { PaintSurfaceData *sData = surface->data; @@ -5757,7 +5758,7 @@ static void dynamic_paint_generate_bake_data_cb( } } -static int dynamicPaint_generateBakeData(DynamicPaintSurface *surface, const ViewLayer *view_layer, Object *ob) +static int dynamicPaint_generateBakeData(DynamicPaintSurface *surface, const Depsgraph *depsgraph, Object *ob) { PaintSurfaceData *sData = surface->data; PaintBakeData *bData = sData->bData; @@ -5765,7 +5766,7 @@ static int dynamicPaint_generateBakeData(DynamicPaintSurface *surface, const Vie int index; bool new_bdata = false; const bool do_velocity_data = ((surface->effect & MOD_DPAINT_EFFECT_DO_DRIP) || - (surface_getBrushFlags(surface, view_layer) & BRUSH_USES_VELOCITY)); + (surface_getBrushFlags(surface, depsgraph) & BRUSH_USES_VELOCITY)); const bool do_accel_data = (surface->effect & MOD_DPAINT_EFFECT_DO_DRIP) != 0; int canvasNumOfVerts = dm->getNumVerts(dm); @@ -5882,7 +5883,9 @@ static int dynamicPaint_generateBakeData(DynamicPaintSurface *surface, const Vie /* * Do Dynamic Paint step. Paints scene brush objects of current state/frame to the surface. */ -static int dynamicPaint_doStep(struct Depsgraph *depsgraph, Scene *scene, Object *ob, DynamicPaintSurface *surface, float timescale, float subframe) +static int dynamicPaint_doStep( + Depsgraph *depsgraph, Scene *scene, + Object *ob, DynamicPaintSurface *surface, float timescale, float subframe) { PaintSurfaceData *sData = surface->data; PaintBakeData *bData = sData->bData; @@ -5909,8 +5912,7 @@ static int dynamicPaint_doStep(struct Depsgraph *depsgraph, Scene *scene, Object { Object *brushObj = NULL; ModifierData *md = NULL; - ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph); - Base *base = BKE_collection_or_layer_objects(NULL, NULL, view_layer, surface->brush_group); + Base *base = BKE_collection_or_layer_objects(depsgraph, NULL, NULL, surface->brush_group); /* backup current scene frame */ int scene_frame = scene->r.cfra; @@ -6048,8 +6050,7 @@ int dynamicPaint_calculateFrame( dynamicPaint_applySurfaceDisplace(surface, surface->canvas->dm); /* update bake data */ - ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph); - dynamicPaint_generateBakeData(surface, view_layer, cObject); + dynamicPaint_generateBakeData(surface, depsgraph, cObject); /* don't do substeps for first frame */ if (surface->substeps && (frame != surface->start_frame)) { diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index bdf6e84a3b1..3bf58b8886a 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -219,10 +219,6 @@ ListBase *pdInitEffectors( ListBase *effectors = NULL; for (; base; base = base->next) { - if ((base->flag & BASE_VISIBLED) == 0) { - continue; - } - if (base->object->pd && base->object->pd->forcefield) { add_object_to_effectors(&effectors, depsgraph, scene, weights, base->object, ob_src, for_simulation); } diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index 0de04e31be9..0ffc9054ddd 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -1922,13 +1922,14 @@ float driver_get_variable_value(ChannelDriver *driver, DriverVar *dvar) /* Evaluate an Channel-Driver to get a 'time' value to use instead of "evaltime" * - "evaltime" is the frame at which F-Curve is being evaluated * - has to return a float value + * - driver_orig is where we cache Python expressions, in case of COW */ -float evaluate_driver(PathResolvedRNA *anim_rna, ChannelDriver *driver, const float evaltime) +float evaluate_driver(PathResolvedRNA *anim_rna, ChannelDriver *driver, ChannelDriver *driver_orig, const float evaltime) { DriverVar *dvar; /* check if driver can be evaluated */ - if (driver->flag & DRIVER_FLAG_INVALID) + if (driver_orig->flag & DRIVER_FLAG_INVALID) return 0.0f; switch (driver->type) { @@ -1998,8 +1999,8 @@ float evaluate_driver(PathResolvedRNA *anim_rna, ChannelDriver *driver, const fl { #ifdef WITH_PYTHON /* check for empty or invalid expression */ - if ( (driver->expression[0] == '\0') || - (driver->flag & DRIVER_FLAG_INVALID) ) + if ( (driver_orig->expression[0] == '\0') || + (driver_orig->flag & DRIVER_FLAG_INVALID) ) { driver->curval = 0.0f; } @@ -2009,7 +2010,7 @@ float evaluate_driver(PathResolvedRNA *anim_rna, ChannelDriver *driver, const fl */ BLI_mutex_lock(&python_driver_lock); - driver->curval = BPY_driver_exec(anim_rna, driver, evaltime); + driver->curval = BPY_driver_exec(anim_rna, driver, driver_orig, evaltime); BLI_mutex_unlock(&python_driver_lock); } @@ -2705,7 +2706,7 @@ float evaluate_fcurve(FCurve *fcu, float evaltime) return evaluate_fcurve_ex(fcu, evaltime, 0.0); } -float evaluate_fcurve_driver(PathResolvedRNA *anim_rna, FCurve *fcu, float evaltime) +float evaluate_fcurve_driver(PathResolvedRNA *anim_rna, FCurve *fcu, ChannelDriver *driver_orig, float evaltime) { BLI_assert(fcu->driver != NULL); float cvalue = 0.0f; @@ -2715,7 +2716,7 @@ float evaluate_fcurve_driver(PathResolvedRNA *anim_rna, FCurve *fcu, float evalt */ if (fcu->driver) { /* evaltime now serves as input for the curve */ - evaltime = evaluate_driver(anim_rna, fcu->driver, evaltime); + evaltime = evaluate_driver(anim_rna, fcu->driver, driver_orig, evaltime); /* only do a default 1-1 mapping if it's unlikely that anything else will set a value... */ if (fcu->totvert == 0) { @@ -2762,7 +2763,7 @@ float calculate_fcurve(PathResolvedRNA *anim_rna, FCurve *fcu, float evaltime) /* calculate and set curval (evaluates driver too if necessary) */ float curval; if (fcu->driver) { - curval = evaluate_fcurve_driver(anim_rna, fcu, evaltime); + curval = evaluate_fcurve_driver(anim_rna, fcu, fcu->driver, evaltime); } else { curval = evaluate_fcurve(fcu, evaltime); diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c index f7ab5415d1c..29767efa71f 100644 --- a/source/blender/blenkernel/intern/font.c +++ b/source/blender/blenkernel/intern/font.c @@ -153,7 +153,7 @@ static PackedFile *get_builtin_packedfile(void) } } -static VFontData *vfont_get_data(Main *bmain, VFont *vfont) +static VFontData *vfont_get_data(VFont *vfont) { if (vfont == NULL) { return NULL; @@ -188,10 +188,10 @@ static VFontData *vfont_get_data(Main *bmain, VFont *vfont) } } else { - pf = newPackedFile(NULL, vfont->name, ID_BLEND_PATH(bmain, &vfont->id)); + pf = newPackedFile(NULL, vfont->name, ID_BLEND_PATH_FROM_GLOBAL(&vfont->id)); if (vfont->temp_pf == NULL) { - vfont->temp_pf = newPackedFile(NULL, vfont->name, ID_BLEND_PATH(bmain, &vfont->id)); + vfont->temp_pf = newPackedFile(NULL, vfont->name, ID_BLEND_PATH_FROM_GLOBAL(&vfont->id)); } } if (!pf) { @@ -349,13 +349,13 @@ VFont *BKE_vfont_builtin_get(void) { VFont *vfont; - for (vfont = G.main->vfont.first; vfont; vfont = vfont->id.next) { + for (vfont = G_MAIN->vfont.first; vfont; vfont = vfont->id.next) { if (BKE_vfont_is_builtin(vfont)) { return vfont; } } - return BKE_vfont_load(G.main, FO_BUILTIN_NAME); + return BKE_vfont_load(G_MAIN, FO_BUILTIN_NAME); } static VChar *find_vfont_char(VFontData *vfd, unsigned int character) @@ -423,7 +423,7 @@ static void build_underline(Curve *cu, ListBase *nubase, const rctf *rect, mul_v2_fl(bp[3].vec, cu->fsize); } -static void buildchar(Main *bmain, Curve *cu, ListBase *nubase, unsigned int character, CharInfo *info, +static void buildchar(Curve *cu, ListBase *nubase, unsigned int character, CharInfo *info, float ofsx, float ofsy, float rot, int charidx) { BezTriple *bezt1, *bezt2; @@ -433,7 +433,7 @@ static void buildchar(Main *bmain, Curve *cu, ListBase *nubase, unsigned int cha VChar *che = NULL; int i; - vfd = vfont_get_data(bmain, which_vfont(cu, info)); + vfd = vfont_get_data(which_vfont(cu, info)); if (!vfd) return; #if 0 @@ -635,7 +635,7 @@ struct TempLineInfo { int wspace_nr; /* number of whitespaces of line */ }; -bool BKE_vfont_to_curve_ex(Main *bmain, Object *ob, Curve *cu, int mode, ListBase *r_nubase, +bool BKE_vfont_to_curve_ex(Object *ob, Curve *cu, int mode, ListBase *r_nubase, const wchar_t **r_text, int *r_text_len, bool *r_text_free, struct CharTrans **r_chartransdata) { @@ -677,7 +677,7 @@ bool BKE_vfont_to_curve_ex(Main *bmain, Object *ob, Curve *cu, int mode, ListBas if (cu->str == NULL) return ok; if (vfont == NULL) return ok; - vfd = vfont_get_data(bmain, vfont); + vfd = vfont_get_data(vfont); /* The VFont Data can not be found */ if (!vfd) return ok; @@ -770,7 +770,7 @@ makebreak: if (vfont == NULL) break; if (vfont != oldvfont) { - vfd = vfont_get_data(bmain, vfont); + vfd = vfont_get_data(vfont); oldvfont = vfont; } @@ -1274,7 +1274,7 @@ makebreak: } /* We do not want to see any character for \n or \r */ if (cha != '\n') - buildchar(bmain, cu, r_nubase, cha, info, ct->xof, ct->yof, ct->rot, i); + buildchar(cu, r_nubase, cha, info, ct->xof, ct->yof, ct->rot, i); if ((info->flag & CU_CHINFO_UNDERLINE) && (cha != '\n')) { float ulwidth, uloverlap = 0.0f; @@ -1340,19 +1340,19 @@ finally: } -bool BKE_vfont_to_curve_nubase(Main *bmain, Object *ob, int mode, ListBase *r_nubase) +bool BKE_vfont_to_curve_nubase(Object *ob, int mode, ListBase *r_nubase) { BLI_assert(ob->type == OB_FONT); - return BKE_vfont_to_curve_ex(bmain, ob, ob->data, mode, r_nubase, + return BKE_vfont_to_curve_ex(ob, ob->data, mode, r_nubase, NULL, NULL, NULL, NULL); } -bool BKE_vfont_to_curve(Main *bmain, Object *ob, int mode) +bool BKE_vfont_to_curve(Object *ob, int mode) { Curve *cu = ob->data; - return BKE_vfont_to_curve_ex(bmain, ob, ob->data, mode, &cu->nurb, NULL, NULL, NULL, NULL); + return BKE_vfont_to_curve_ex(ob, ob->data, mode, &cu->nurb, NULL, NULL, NULL, NULL); } diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c index ee0d0b41898..9b79415f006 100644 --- a/source/blender/blenkernel/intern/gpencil.c +++ b/source/blender/blenkernel/intern/gpencil.c @@ -622,12 +622,12 @@ bGPDpalettecolor *BKE_gpencil_palettecolor_addnew(bGPDpalette *palette, const ch } /* add a new gp-datablock */ -bGPdata *BKE_gpencil_data_addnew(const char name[]) +bGPdata *BKE_gpencil_data_addnew(Main *bmain, const char name[]) { bGPdata *gpd; /* allocate memory for a new block */ - gpd = BKE_libblock_alloc(G.main, ID_GD, name, 0); + gpd = BKE_libblock_alloc(bmain, ID_GD, name, 0); /* initial settings */ gpd->flag = (GP_DATA_DISPINFO | GP_DATA_EXPAND); diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 9a29a8a898b..3e7a9de6968 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -342,19 +342,18 @@ void BKE_image_free_buffers(Image *ima) /** Free (or release) any data used by this image (does not free the image itself). */ void BKE_image_free(Image *ima) { - int a; - /* Also frees animdata. */ BKE_image_free_buffers(ima); image_free_packedfiles(ima); - for (a = 0; a < IMA_MAX_RENDER_SLOT; a++) { - if (ima->renders[a]) { - RE_FreeRenderResult(ima->renders[a]); - ima->renders[a] = NULL; + LISTBASE_FOREACH(RenderSlot *, slot, &ima->renderslots) { + if (slot->render) { + RE_FreeRenderResult(slot->render); + slot->render = NULL; } } + BLI_freelistN(&ima->renderslots); BKE_image_free_views(ima); MEM_SAFE_FREE(ima->stereo3d_format); @@ -380,6 +379,12 @@ static void image_init(Image *ima, short source, short type) if (source == IMA_SRC_VIEWER) ima->flag |= IMA_VIEW_AS_RENDER; + if (type == IMA_TYPE_R_RESULT) { + for (int i = 0; i < 8; i++) { + BKE_image_add_renderslot(ima, NULL); + } + } + BKE_color_managed_colorspace_settings_init(&ima->colorspace_settings); ima->stereo3d_format = MEM_callocN(sizeof(Stereo3dFormat), "Image Stereo Format"); } @@ -466,14 +471,15 @@ void BKE_image_copy_data(Main *UNUSED(bmain), Image *ima_dst, const Image *ima_s /* Cleanup stuff that cannot be copied. */ ima_dst->cache = NULL; ima_dst->rr = NULL; - for (int i = 0; i < IMA_MAX_RENDER_SLOT; i++) { - ima_dst->renders[i] = NULL; + + BLI_duplicatelist(&ima_dst->renderslots, &ima_src->renderslots); + LISTBASE_FOREACH(RenderSlot *, slot, &ima_dst->renderslots) { + slot->render = NULL; } BLI_listbase_clear(&ima_dst->anims); for (int i = 0; i < TEXTARGET_COUNT; i++) { - ima_dst->bindcode[i] = 0; ima_dst->gputexture[i] = NULL; } @@ -498,7 +504,7 @@ void BKE_image_make_local(Main *bmain, Image *ima, const bool lib_local) BKE_id_make_local_generic(bmain, &ima->id, true, lib_local); } -void BKE_image_merge(Image *dest, Image *source) +void BKE_image_merge(Main *bmain, Image *dest, Image *source) { /* sanity check */ if (dest && source && dest != source) { @@ -516,7 +522,7 @@ void BKE_image_merge(Image *dest, Image *source) } BLI_spin_unlock(&image_spin); - BKE_libblock_free(G.main, source); + BKE_libblock_free(bmain, source); } } @@ -538,16 +544,14 @@ bool BKE_image_scale(Image *image, int width, int height) return (ibuf != NULL); } -bool BKE_image_has_bindcode(Image *ima) +bool BKE_image_has_opengl_texture(Image *ima) { - bool has_bindcode = false; for (int i = 0; i < TEXTARGET_COUNT; i++) { - if (ima->bindcode[i]) { - has_bindcode = true; - break; + if (ima->gputexture[i]) { + return true; } } - return has_bindcode; + return false; } static void image_init_color_management(Image *ima) @@ -615,7 +619,7 @@ Image *BKE_image_load(Main *bmain, const char *filepath) /* otherwise creates new. */ /* does not load ibuf itself */ /* pass on optional frame for #name images */ -Image *BKE_image_load_exists_ex(const char *filepath, bool *r_exists) +Image *BKE_image_load_exists_ex(Main *bmain, const char *filepath, bool *r_exists) { Image *ima; char str[FILE_MAX], strtest[FILE_MAX]; @@ -624,10 +628,10 @@ Image *BKE_image_load_exists_ex(const char *filepath, bool *r_exists) BLI_path_abs(str, BKE_main_blendfile_path_from_global()); /* first search an identical filepath */ - for (ima = G.main->image.first; ima; ima = ima->id.next) { + for (ima = bmain->image.first; ima; ima = ima->id.next) { if (ima->source != IMA_SRC_VIEWER && ima->source != IMA_SRC_GENERATED) { STRNCPY(strtest, ima->name); - BLI_path_abs(strtest, ID_BLEND_PATH(G.main, &ima->id)); + BLI_path_abs(strtest, ID_BLEND_PATH(bmain, &ima->id)); if (BLI_path_cmp(strtest, str) == 0) { if ((BKE_image_has_anim(ima) == false) || @@ -646,12 +650,12 @@ Image *BKE_image_load_exists_ex(const char *filepath, bool *r_exists) if (r_exists) *r_exists = false; - return BKE_image_load(G.main, filepath); + return BKE_image_load(bmain, filepath); } -Image *BKE_image_load_exists(const char *filepath) +Image *BKE_image_load_exists(Main *bmain, const char *filepath) { - return BKE_image_load_exists_ex(filepath, NULL); + return BKE_image_load_exists_ex(bmain, filepath, NULL); } static ImBuf *add_ibuf_size(unsigned int width, unsigned int height, const char *name, int depth, int floatbuf, short gen_type, @@ -753,7 +757,7 @@ Image *BKE_image_add_generated( /* Create an image image from ibuf. The refcount of ibuf is increased, * caller should take care to drop its reference by calling * IMB_freeImBuf if needed. */ -Image *BKE_image_add_from_imbuf(ImBuf *ibuf, const char *name) +Image *BKE_image_add_from_imbuf(Main *bmain, ImBuf *ibuf, const char *name) { /* on save, type is changed to FILE in editsima.c */ Image *ima; @@ -762,7 +766,7 @@ Image *BKE_image_add_from_imbuf(ImBuf *ibuf, const char *name) name = BLI_path_basename(ibuf->name); } - ima = image_alloc(G.main, name, IMA_SRC_FILE, IMA_TYPE_IMAGE); + ima = image_alloc(bmain, name, IMA_SRC_FILE, IMA_TYPE_IMAGE); if (ima) { STRNCPY(ima->name, ibuf->name); @@ -930,21 +934,6 @@ void BKE_image_tag_time(Image *ima) ima->lastused = PIL_check_seconds_timer_i(); } -#if 0 -static void tag_all_images_time() -{ - Image *ima; - int ctime = PIL_check_seconds_timer_i(); - - ima = G.main->image.first; - while (ima) { - if (ima->bindcode || ima->repbind || ima->ibufs.first) { - ima->lastused = ctime; - } - } -} -#endif - static uintptr_t image_mem_size(Image *image) { uintptr_t size = 0; @@ -990,17 +979,17 @@ static uintptr_t image_mem_size(Image *image) return size; } -void BKE_image_print_memlist(void) +void BKE_image_print_memlist(Main *bmain) { Image *ima; uintptr_t size, totsize = 0; - for (ima = G.main->image.first; ima; ima = ima->id.next) + for (ima = bmain->image.first; ima; ima = ima->id.next) totsize += image_mem_size(ima); printf("\ntotal image memory len: %.3f MB\n", (double)totsize / (double)(1024 * 1024)); - for (ima = G.main->image.first; ima; ima = ima->id.next) { + for (ima = bmain->image.first; ima; ima = ima->id.next) { size = image_mem_size(ima); if (size) @@ -1013,7 +1002,7 @@ static bool imagecache_check_dirty(ImBuf *ibuf, void *UNUSED(userkey), void *UNU return (ibuf->userflags & IB_BITMAPDIRTY) == 0; } -void BKE_image_free_all_textures(void) +void BKE_image_free_all_textures(Main *bmain) { #undef CHECK_FREED_SIZE @@ -1023,14 +1012,14 @@ void BKE_image_free_all_textures(void) uintptr_t tot_freed_size = 0; #endif - for (ima = G.main->image.first; ima; ima = ima->id.next) + for (ima = bmain->image.first; ima; ima = ima->id.next) ima->id.tag &= ~LIB_TAG_DOIT; - for (tex = G.main->tex.first; tex; tex = tex->id.next) + for (tex = bmain->tex.first; tex; tex = tex->id.next) if (tex->ima) tex->ima->id.tag |= LIB_TAG_DOIT; - for (ima = G.main->image.first; ima; ima = ima->id.next) { + for (ima = bmain->image.first; ima; ima = ima->id.next) { if (ima->cache && (ima->id.tag & LIB_TAG_DOIT)) { #ifdef CHECK_FREED_SIZE uintptr_t old_size = image_mem_size(ima); @@ -1066,11 +1055,11 @@ void BKE_image_free_anim_ibufs(Image *ima, int except_frame) BLI_spin_unlock(&image_spin); } -void BKE_image_all_free_anim_ibufs(int cfra) +void BKE_image_all_free_anim_ibufs(Main *bmain, int cfra) { Image *ima; - for (ima = G.main->image.first; ima; ima = ima->id.next) + for (ima = bmain->image.first; ima; ima = ima->id.next) if (BKE_image_is_animated(ima)) BKE_image_free_anim_ibufs(ima, cfra); } @@ -2548,17 +2537,17 @@ struct anim *openanim(const char *name, int flags, int streamindex, char colorsp /* forces existence of 1 Image for renderout or nodes, returns Image */ /* name is only for default, when making new one */ -Image *BKE_image_verify_viewer(int type, const char *name) +Image *BKE_image_verify_viewer(Main *bmain, int type, const char *name) { Image *ima; - for (ima = G.main->image.first; ima; ima = ima->id.next) + for (ima = bmain->image.first; ima; ima = ima->id.next) if (ima->source == IMA_SRC_VIEWER) if (ima->type == type) break; if (ima == NULL) - ima = image_alloc(G.main, name, IMA_SRC_VIEWER, type); + ima = image_alloc(bmain, name, IMA_SRC_VIEWER, type); /* happens on reload, imagewindow cannot be image user when hidden*/ if (ima->id.us == 0) @@ -2709,7 +2698,7 @@ void BKE_image_init_imageuser(Image *ima, ImageUser *iuser) image_init_imageuser(ima, iuser); } -void BKE_image_signal(Image *ima, ImageUser *iuser, int signal) +void BKE_image_signal(Main *bmain, Image *ima, ImageUser *iuser, int signal) { if (ima == NULL) return; @@ -2771,7 +2760,7 @@ void BKE_image_signal(Image *ima, ImageUser *iuser, int signal) if (iuser) iuser->ok = 1; - BKE_image_walk_all_users(G.main, ima, image_tag_frame_recalc); + BKE_image_walk_all_users(bmain, ima, image_tag_frame_recalc); break; @@ -2783,13 +2772,13 @@ void BKE_image_signal(Image *ima, ImageUser *iuser, int signal) if (totfiles != BLI_listbase_count_at_most(&ima->packedfiles, totfiles + 1)) { /* in case there are new available files to be loaded */ image_free_packedfiles(ima); - BKE_image_packfiles(NULL, ima, ID_BLEND_PATH(G.main, &ima->id)); + BKE_image_packfiles(NULL, ima, ID_BLEND_PATH(bmain, &ima->id)); } else { ImagePackedFile *imapf; for (imapf = ima->packedfiles.first; imapf; imapf = imapf->next) { PackedFile *pf; - pf = newPackedFile(NULL, imapf->filepath, ID_BLEND_PATH(G.main, &ima->id)); + pf = newPackedFile(NULL, imapf->filepath, ID_BLEND_PATH(bmain, &ima->id)); if (pf) { freePackedFile(imapf->packedfile); imapf->packedfile = pf; @@ -2841,7 +2830,7 @@ void BKE_image_signal(Image *ima, ImageUser *iuser, int signal) * this also makes sure all scenes are accounted for. */ { Scene *scene; - for (scene = G.main->scene.first; scene; scene = scene->id.next) { + for (scene = bmain->scene.first; scene; scene = scene->id.next) { if (scene->nodetree) { nodeUpdateID(scene->nodetree, &ima->id); } @@ -3015,7 +3004,7 @@ RenderResult *BKE_image_acquire_renderresult(Scene *scene, Image *ima) if (ima->render_slot == ima->last_render_slot) rr = RE_AcquireResultRead(RE_GetSceneRender(scene)); else - rr = ima->renders[ima->render_slot]; + rr = BKE_image_get_renderslot(ima, ima->render_slot)->render; /* set proper views */ image_init_multilayer_multiview(ima, rr); @@ -3049,22 +3038,23 @@ bool BKE_image_is_openexr(struct Image *ima) void BKE_image_backup_render(Scene *scene, Image *ima, bool free_current_slot) { - /* called right before rendering, ima->renders contains render + /* called right before rendering, ima->renderslots contains render * result pointers for everything but the current render */ Render *re = RE_GetSceneRender(scene); int slot = ima->render_slot, last = ima->last_render_slot; if (slot != last) { - ima->renders[last] = NULL; - RE_SwapResult(re, &ima->renders[last]); + RenderSlot *last_slot = BKE_image_get_renderslot(ima, last); + last_slot->render = NULL; + RE_SwapResult(re, &last_slot->render); - if (ima->renders[slot]) { + RenderSlot *cur_slot = BKE_image_get_renderslot(ima, slot); + if (cur_slot->render) { if (free_current_slot) { - RE_FreeRenderResult(ima->renders[slot]); - ima->renders[slot] = NULL; + BKE_image_clear_renderslot(ima, NULL, slot); } else { - RE_SwapResult(re, &ima->renders[slot]); + RE_SwapResult(re, &cur_slot->render); } } } @@ -3533,7 +3523,7 @@ static ImBuf *load_image_single( BLI_addtail(&ima->packedfiles, imapf); STRNCPY(imapf->filepath, filepath); - imapf->packedfile = newPackedFile(NULL, filepath, ID_BLEND_PATH(G.main, &ima->id)); + imapf->packedfile = newPackedFile(NULL, filepath, ID_BLEND_PATH_FROM_GLOBAL(&ima->id)); } } } @@ -3687,11 +3677,12 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_loc if (BKE_image_is_stereo(ima) && (iuser->flag & IMA_SHOW_STEREO)) actview = iuser->multiview_eye; + RenderSlot *slot; if (from_render) { RE_AcquireResultImage(re, &rres, actview); } - else if (ima->renders[ima->render_slot]) { - rres = *(ima->renders[ima->render_slot]); + else if ((slot = BKE_image_get_renderslot(ima, ima->render_slot))->render) { + rres = *(slot->render); rres.have_combined = ((RenderView *)rres.views.first)->rectf != NULL; } else @@ -4371,7 +4362,7 @@ void BKE_image_user_file_path(ImageUser *iuser, Image *ima, char *filepath) BLI_stringenc(filepath, head, tail, numlen, frame); } - BLI_path_abs(filepath, ID_BLEND_PATH(G.main, &ima->id)); + BLI_path_abs(filepath, ID_BLEND_PATH_FROM_GLOBAL(&ima->id)); } bool BKE_image_has_alpha(struct Image *image) @@ -4721,3 +4712,94 @@ static void image_update_views_format(Image *ima, ImageUser *iuser) } } } + +RenderSlot *BKE_image_add_renderslot(Image *ima, const char *name) +{ + RenderSlot *slot = MEM_callocN(sizeof(RenderSlot), "Image new Render Slot"); + if (name && name[0]) { + BLI_strncpy(slot->name, name, sizeof(slot->name)); + } + else { + int n = BLI_listbase_count(&ima->renderslots) + 1; + BLI_snprintf(slot->name, sizeof(slot->name), "Slot %d", n); + } + BLI_addtail(&ima->renderslots, slot); + return slot; +} + +bool BKE_image_remove_renderslot(Image *ima, ImageUser *iuser, int index) +{ + int num_slots = BLI_listbase_count(&ima->renderslots); + if (index >= num_slots || num_slots == 1) { + return false; + } + + RenderSlot *remove_slot = BLI_findlink(&ima->renderslots, index); + RenderSlot *current_slot = BLI_findlink(&ima->renderslots, ima->render_slot); + RenderSlot *current_last_slot = BLI_findlink(&ima->renderslots, ima->last_render_slot); + + RenderSlot *next_slot; + if (current_slot == remove_slot) + next_slot = BLI_findlink(&ima->renderslots, (index == num_slots-1)? index-1 : index+1); + else + next_slot = current_slot; + + /* If the slot to be removed is the slot with the last render, make another slot the last render slot. */ + if (remove_slot == current_last_slot) { + /* Choose the currently selected slot unless that one is being removed, in that case take the next one. */ + RenderSlot *next_last_slot; + if (current_slot == remove_slot) + next_last_slot = next_slot; + else + next_last_slot = current_slot; + + if (!iuser) return false; + Render *re = RE_GetSceneRender(iuser->scene); + if (!re) return false; + RE_SwapResult(re, ¤t_last_slot->render); + RE_SwapResult(re, &next_last_slot->render); + current_last_slot = next_last_slot; + } + + current_slot = next_slot; + + BLI_remlink(&ima->renderslots, remove_slot); + + ima->render_slot = BLI_findindex(&ima->renderslots, current_slot); + ima->last_render_slot = BLI_findindex(&ima->renderslots, current_last_slot); + + if (remove_slot->render) { + RE_FreeRenderResult(remove_slot->render); + } + MEM_freeN(remove_slot); + + return true; +} + +bool BKE_image_clear_renderslot(Image *ima, ImageUser *iuser, int index) +{ + if (index == ima->last_render_slot) { + if (!iuser) return false; + if (G.is_rendering) return false; + Render *re = RE_GetSceneRender(iuser->scene); + if (!re) return false; + RE_ClearResult(re); + return true; + } + else { + RenderSlot *slot = BLI_findlink(&ima->renderslots, index); + if (!slot) return false; + if (slot->render) { + RE_FreeRenderResult(slot->render); + slot->render = NULL; + } + return true; + } +} + +RenderSlot *BKE_image_get_renderslot(Image *ima, int index) +{ + RenderSlot *slot = BLI_findlink(&ima->renderslots, index); + BLI_assert(slot); + return slot; +} diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c index 82178096b46..f3f690b92da 100644 --- a/source/blender/blenkernel/intern/ipo.c +++ b/source/blender/blenkernel/intern/ipo.c @@ -1509,7 +1509,7 @@ static void action_to_animato(ID *id, bAction *act, ListBase *groups, ListBase * * This assumes that AnimData has been added already. Separation of drivers * from animation data is accomplished here too... */ -static void ipo_to_animdata(ID *id, Ipo *ipo, char actname[], char constname[], Sequence *seq) +static void ipo_to_animdata(Main *bmain, ID *id, Ipo *ipo, char actname[], char constname[], Sequence *seq) { AnimData *adt = BKE_animdata_from_id(id); ListBase anim = {NULL, NULL}; @@ -1544,7 +1544,7 @@ static void ipo_to_animdata(ID *id, Ipo *ipo, char actname[], char constname[], BLI_snprintf(nameBuf, sizeof(nameBuf), "CDA:%s", ipo->id.name + 2); - adt->action = BKE_action_add(G.main, nameBuf); + adt->action = BKE_action_add(bmain, nameBuf); if (G.debug & G_DEBUG) printf("\t\tadded new action - '%s'\n", nameBuf); } @@ -1680,19 +1680,19 @@ static void nlastrips_to_animdata(ID *id, ListBase *strips) * clear which datablocks have yet to be converted, and also prevent freeing errors when we exit. */ // XXX currently done after all file reading... -void do_versions_ipos_to_animato(Main *main) +void do_versions_ipos_to_animato(Main *bmain) { ListBase drivers = {NULL, NULL}; ID *id; - if (main == NULL) { + if (bmain == NULL) { printf("Argh! Main is NULL in do_versions_ipos_to_animato()\n"); return; } /* only convert if version is right */ - if (main->versionfile >= 250) { - printf("WARNING: Animation data too new to convert (Version %d)\n", main->versionfile); + if (bmain->versionfile >= 250) { + printf("WARNING: Animation data too new to convert (Version %d)\n", bmain->versionfile); return; } else if (G.debug & G_DEBUG) @@ -1701,7 +1701,7 @@ void do_versions_ipos_to_animato(Main *main) /* ----------- Animation Attached to Data -------------- */ /* objects */ - for (id = main->object.first; id; id = id->next) { + for (id = bmain->object.first; id; id = id->next) { Object *ob = (Object *)id; bPoseChannel *pchan; bConstraint *con; @@ -1716,7 +1716,7 @@ void do_versions_ipos_to_animato(Main *main) /* IPO first to take into any non-NLA'd Object Animation */ if (ob->ipo) { - ipo_to_animdata(id, ob->ipo, NULL, NULL, NULL); + ipo_to_animdata(bmain, id, ob->ipo, NULL, NULL, NULL); id_us_min(&ob->ipo->id); ob->ipo = NULL; @@ -1750,7 +1750,7 @@ void do_versions_ipos_to_animato(Main *main) /* IPO second... */ if (ob->ipo) { - ipo_to_animdata(id, ob->ipo, NULL, NULL, NULL); + ipo_to_animdata(bmain, id, ob->ipo, NULL, NULL, NULL); id_us_min(&ob->ipo->id); ob->ipo = NULL; } @@ -1770,7 +1770,7 @@ void do_versions_ipos_to_animato(Main *main) /* although this was the constraint's local IPO, we still need to provide pchan + con * so that drivers can be added properly... */ - ipo_to_animdata(id, con->ipo, pchan->name, con->name, NULL); + ipo_to_animdata(bmain, id, con->ipo, pchan->name, con->name, NULL); id_us_min(&con->ipo->id); con->ipo = NULL; } @@ -1790,7 +1790,7 @@ void do_versions_ipos_to_animato(Main *main) /* although this was the constraint's local IPO, we still need to provide con * so that drivers can be added properly... */ - ipo_to_animdata(id, con->ipo, NULL, con->name, NULL); + ipo_to_animdata(bmain, id, con->ipo, NULL, con->name, NULL); id_us_min(&con->ipo->id); con->ipo = NULL; } @@ -1810,7 +1810,7 @@ void do_versions_ipos_to_animato(Main *main) /* convert Constraint Channel's IPO data */ if (conchan->ipo) { - ipo_to_animdata(id, conchan->ipo, NULL, conchan->name, NULL); + ipo_to_animdata(bmain, id, conchan->ipo, NULL, conchan->name, NULL); id_us_min(&conchan->ipo->id); conchan->ipo = NULL; } @@ -1829,7 +1829,7 @@ void do_versions_ipos_to_animato(Main *main) } /* shapekeys */ - for (id = main->key.first; id; id = id->next) { + for (id = bmain->key.first; id; id = id->next) { Key *key = (Key *)id; if (G.debug & G_DEBUG) printf("\tconverting key %s\n", id->name + 2); @@ -1843,7 +1843,7 @@ void do_versions_ipos_to_animato(Main *main) AnimData *adt = BKE_animdata_add_id(id); /* Convert Shapekey data... */ - ipo_to_animdata(id, key->ipo, NULL, NULL, NULL); + ipo_to_animdata(bmain, id, key->ipo, NULL, NULL, NULL); if (adt->action) adt->action->idroot = key->ipo->blocktype; @@ -1854,7 +1854,7 @@ void do_versions_ipos_to_animato(Main *main) } /* materials */ - for (id = main->mat.first; id; id = id->next) { + for (id = bmain->mat.first; id; id = id->next) { Material *ma = (Material *)id; if (G.debug & G_DEBUG) printf("\tconverting material %s\n", id->name + 2); @@ -1865,7 +1865,7 @@ void do_versions_ipos_to_animato(Main *main) AnimData *adt = BKE_animdata_add_id(id); /* Convert Material data... */ - ipo_to_animdata(id, ma->ipo, NULL, NULL, NULL); + ipo_to_animdata(bmain, id, ma->ipo, NULL, NULL, NULL); if (adt->action) adt->action->idroot = ma->ipo->blocktype; @@ -1876,7 +1876,7 @@ void do_versions_ipos_to_animato(Main *main) } /* worlds */ - for (id = main->world.first; id; id = id->next) { + for (id = bmain->world.first; id; id = id->next) { World *wo = (World *)id; if (G.debug & G_DEBUG) printf("\tconverting world %s\n", id->name + 2); @@ -1887,7 +1887,7 @@ void do_versions_ipos_to_animato(Main *main) AnimData *adt = BKE_animdata_add_id(id); /* Convert World data... */ - ipo_to_animdata(id, wo->ipo, NULL, NULL, NULL); + ipo_to_animdata(bmain, id, wo->ipo, NULL, NULL, NULL); if (adt->action) adt->action->idroot = wo->ipo->blocktype; @@ -1898,7 +1898,7 @@ void do_versions_ipos_to_animato(Main *main) } /* sequence strips */ - for (id = main->scene.first; id; id = id->next) { + for (id = bmain->scene.first; id; id = id->next) { Scene *scene = (Scene *)id; Editing *ed = scene->ed; if (ed && ed->seqbasep) { @@ -1938,7 +1938,7 @@ void do_versions_ipos_to_animato(Main *main) icu->adrcode = adrcode; /* convert IPO */ - ipo_to_animdata((ID *)scene, seq->ipo, NULL, NULL, seq); + ipo_to_animdata(bmain, (ID *)scene, seq->ipo, NULL, NULL, seq); if (adt->action) adt->action->idroot = ID_SCE; /* scene-rooted */ @@ -1952,7 +1952,7 @@ void do_versions_ipos_to_animato(Main *main) /* textures */ - for (id = main->tex.first; id; id = id->next) { + for (id = bmain->tex.first; id; id = id->next) { Tex *te = (Tex *)id; if (G.debug & G_DEBUG) printf("\tconverting texture %s\n", id->name + 2); @@ -1963,7 +1963,7 @@ void do_versions_ipos_to_animato(Main *main) AnimData *adt = BKE_animdata_add_id(id); /* Convert Texture data... */ - ipo_to_animdata(id, te->ipo, NULL, NULL, NULL); + ipo_to_animdata(bmain, id, te->ipo, NULL, NULL, NULL); if (adt->action) adt->action->idroot = te->ipo->blocktype; @@ -1974,7 +1974,7 @@ void do_versions_ipos_to_animato(Main *main) } /* cameras */ - for (id = main->camera.first; id; id = id->next) { + for (id = bmain->camera.first; id; id = id->next) { Camera *ca = (Camera *)id; if (G.debug & G_DEBUG) printf("\tconverting camera %s\n", id->name + 2); @@ -1985,7 +1985,7 @@ void do_versions_ipos_to_animato(Main *main) AnimData *adt = BKE_animdata_add_id(id); /* Convert Camera data... */ - ipo_to_animdata(id, ca->ipo, NULL, NULL, NULL); + ipo_to_animdata(bmain, id, ca->ipo, NULL, NULL, NULL); if (adt->action) adt->action->idroot = ca->ipo->blocktype; @@ -1996,7 +1996,7 @@ void do_versions_ipos_to_animato(Main *main) } /* lamps */ - for (id = main->lamp.first; id; id = id->next) { + for (id = bmain->lamp.first; id; id = id->next) { Lamp *la = (Lamp *)id; if (G.debug & G_DEBUG) printf("\tconverting lamp %s\n", id->name + 2); @@ -2007,7 +2007,7 @@ void do_versions_ipos_to_animato(Main *main) AnimData *adt = BKE_animdata_add_id(id); /* Convert Lamp data... */ - ipo_to_animdata(id, la->ipo, NULL, NULL, NULL); + ipo_to_animdata(bmain, id, la->ipo, NULL, NULL, NULL); if (adt->action) adt->action->idroot = la->ipo->blocktype; @@ -2018,7 +2018,7 @@ void do_versions_ipos_to_animato(Main *main) } /* curves */ - for (id = main->curve.first; id; id = id->next) { + for (id = bmain->curve.first; id; id = id->next) { Curve *cu = (Curve *)id; if (G.debug & G_DEBUG) printf("\tconverting curve %s\n", id->name + 2); @@ -2029,7 +2029,7 @@ void do_versions_ipos_to_animato(Main *main) AnimData *adt = BKE_animdata_add_id(id); /* Convert Curve data... */ - ipo_to_animdata(id, cu->ipo, NULL, NULL, NULL); + ipo_to_animdata(bmain, id, cu->ipo, NULL, NULL, NULL); if (adt->action) adt->action->idroot = cu->ipo->blocktype; @@ -2051,7 +2051,7 @@ void do_versions_ipos_to_animato(Main *main) */ /* actions */ - for (id = main->action.first; id; id = id->next) { + for (id = bmain->action.first; id; id = id->next) { bAction *act = (bAction *)id; if (G.debug & G_DEBUG) printf("\tconverting action %s\n", id->name + 2); @@ -2065,7 +2065,7 @@ void do_versions_ipos_to_animato(Main *main) } /* ipo's */ - for (id = main->ipo.first; id; id = id->next) { + for (id = bmain->ipo.first; id; id = id->next) { Ipo *ipo = (Ipo *)id; if (G.debug & G_DEBUG) printf("\tconverting ipo %s\n", id->name + 2); @@ -2075,7 +2075,7 @@ void do_versions_ipos_to_animato(Main *main) bAction *new_act; /* add a new action for this, and convert all data into that action */ - new_act = BKE_action_add(main, id->name + 2); + new_act = BKE_action_add(bmain, id->name + 2); ipo_to_animato(NULL, ipo, NULL, NULL, NULL, NULL, &new_act->curves, &drivers); new_act->idroot = ipo->blocktype; } diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c index fd42556067e..e63f7d7cefe 100644 --- a/source/blender/blenkernel/intern/key.c +++ b/source/blender/blenkernel/intern/key.c @@ -102,12 +102,12 @@ void BKE_key_free_nolib(Key *key) } } -Key *BKE_key_add(ID *id) /* common function */ +Key *BKE_key_add(Main *bmain, ID *id) /* common function */ { Key *key; char *el; - key = BKE_libblock_alloc(G.main, ID_KE, "Key", 0); + key = BKE_libblock_alloc(bmain, ID_KE, "Key", 0); key->type = KEY_NORMAL; key->from = id; diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index b9244ee1f83..2fb3fcf3ee8 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -772,9 +772,10 @@ bool id_single_user(bContext *C, ID *id, PointerRNA *ptr, PropertyRNA *prop) if (id) { /* if property isn't editable, we're going to have an extra block hanging around until we save */ if (RNA_property_editable(ptr, prop)) { - if (id_copy(CTX_data_main(C), id, &newid, false) && newid) { + Main *bmain = CTX_data_main(C); + if (id_copy(bmain, id, &newid, false) && newid) { /* copy animation actions too */ - BKE_animdata_copy_id_action(id, false); + BKE_animdata_copy_id_action(bmain, id, false); /* us is 1 by convention, but RNA_property_pointer_set * will also increment it, so set it to zero */ newid->us = 0; @@ -1748,13 +1749,13 @@ const char *BKE_main_blendfile_path(const Main *bmain) } /** - * Return filepath of global main (G.main). + * Return filepath of global main (G_MAIN). * - * \warning Usage is not recommended, you should always try to get a velid Main pointer from context... + * \warning Usage is not recommended, you should always try to get a valid Main pointer from context... */ const char *BKE_main_blendfile_path_from_global(void) { - return BKE_main_blendfile_path(G.main); + return BKE_main_blendfile_path(G_MAIN); } /* ***************** ID ************************ */ diff --git a/source/blender/blenkernel/intern/mball_tessellate.c b/source/blender/blenkernel/intern/mball_tessellate.c index 0f13618c76a..7e26a0f7713 100644 --- a/source/blender/blenkernel/intern/mball_tessellate.c +++ b/source/blender/blenkernel/intern/mball_tessellate.c @@ -48,9 +48,10 @@ #include "BKE_global.h" -#include "BKE_scene.h" #include "BKE_displist.h" +#include "BKE_main.h" #include "BKE_mball_tessellate.h" /* own include */ +#include "BKE_scene.h" #include "DEG_depsgraph.h" #include "DEG_depsgraph_query.h" diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index b325d8d02d9..e83f2d92dd9 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -728,8 +728,9 @@ BMesh *BKE_mesh_to_bmesh( Mesh *BKE_bmesh_to_mesh_nomain(BMesh *bm, const struct BMeshToMeshParams *params) { + BLI_assert(params->calc_object_remap == false); Mesh *mesh = BKE_id_new_nomain(ID_ME, NULL); - BM_mesh_bm_to_me(bm, mesh, params); + BM_mesh_bm_to_me(NULL, bm, mesh, params); return mesh; } diff --git a/source/blender/blenkernel/intern/mesh_convert.c b/source/blender/blenkernel/intern/mesh_convert.c index acd0cf32b13..33b38d60183 100644 --- a/source/blender/blenkernel/intern/mesh_convert.c +++ b/source/blender/blenkernel/intern/mesh_convert.c @@ -544,9 +544,9 @@ Mesh *BKE_mesh_new_nomain_from_curve(Object *ob) } /* this may fail replacing ob->data, be sure to check ob->type */ -void BKE_mesh_from_nurbs_displist(Object *ob, ListBase *dispbase, const bool use_orco_uv, const char *obdata_name, bool temporary) +void BKE_mesh_from_nurbs_displist( + Main *bmain, Object *ob, ListBase *dispbase, const bool use_orco_uv, const char *obdata_name, bool temporary) { - Main *bmain = G.main; Object *ob1; DerivedMesh *dm = ob->derivedFinal; Mesh *me; @@ -642,7 +642,7 @@ void BKE_mesh_from_nurbs_displist(Object *ob, ListBase *dispbase, const bool use } } -void BKE_mesh_from_nurbs(Object *ob) +void BKE_mesh_from_nurbs(Main *bmain, Object *ob) { Curve *cu = (Curve *) ob->data; bool use_orco_uv = (cu->flag & CU_UV_ORCO) != 0; @@ -652,7 +652,7 @@ void BKE_mesh_from_nurbs(Object *ob) disp = ob->curve_cache->disp; } - BKE_mesh_from_nurbs_displist(ob, &disp, use_orco_uv, cu->id.name, false); + BKE_mesh_from_nurbs_displist(bmain, ob, &disp, use_orco_uv, cu->id.name, false); } typedef struct EdgeLink { @@ -812,7 +812,7 @@ void BKE_mesh_to_curve_nurblist(const Mesh *me, ListBase *nurblist, const int ed } } -void BKE_mesh_to_curve(Depsgraph *depsgraph, Scene *scene, Object *ob) +void BKE_mesh_to_curve(Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *ob) { /* make new mesh data from the original copy */ Mesh *me_eval = mesh_get_eval_final(depsgraph, scene, ob, CD_MASK_MESH); @@ -823,7 +823,7 @@ void BKE_mesh_to_curve(Depsgraph *depsgraph, Scene *scene, Object *ob) BKE_mesh_to_curve_nurblist(me_eval, &nurblist, 1); if (nurblist.first) { - Curve *cu = BKE_curve_add(G.main, ob->id.name + 2, OB_CURVE); + Curve *cu = BKE_curve_add(bmain, ob->id.name + 2, OB_CURVE); cu->flag |= CU_3D; cu->nurb = nurblist; @@ -929,7 +929,7 @@ Mesh *BKE_mesh_new_from_object( /* convert object type to mesh */ uv_from_orco = (tmpcu->flag & CU_UV_ORCO) != 0; - BKE_mesh_from_nurbs_displist(tmpobj, &dispbase, uv_from_orco, tmpcu->id.name + 2, true); + BKE_mesh_from_nurbs_displist(bmain, tmpobj, &dispbase, uv_from_orco, tmpcu->id.name + 2, true); tmpmesh = tmpobj->data; diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index bd9cd684548..0b904caf375 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -809,6 +809,18 @@ const char *modifier_path_relbase(Main *bmain, Object *ob) } } +const char *modifier_path_relbase_from_global(Object *ob) +{ + if (G.relbase_valid || ID_IS_LINKED(ob)) { + return ID_BLEND_PATH_FROM_GLOBAL(&ob->id); + } + else { + /* last resort, better then using "" which resolves to the current + * working directory */ + return BKE_tempdir_session(); + } +} + /* initializes the path with either */ void modifier_path_init(char *path, int path_maxlen, const char *name) { diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c index fc236cc2ad0..98586a5c2f5 100644 --- a/source/blender/blenkernel/intern/movieclip.c +++ b/source/blender/blenkernel/intern/movieclip.c @@ -171,7 +171,7 @@ static void get_sequence_fname(const MovieClip *clip, BLI_strncpy(name, clip->name, sizeof(clip->name)); } - BLI_path_abs(name, ID_BLEND_PATH(G.main, &clip->id)); + BLI_path_abs(name, ID_BLEND_PATH_FROM_GLOBAL(&clip->id)); } /* supposed to work with sequences only */ @@ -261,7 +261,7 @@ static void movieclip_open_anim_file(MovieClip *clip) if (!clip->anim) { BLI_strncpy(str, clip->name, FILE_MAX); - BLI_path_abs(str, ID_BLEND_PATH(G.main, &clip->id)); + BLI_path_abs(str, ID_BLEND_PATH_FROM_GLOBAL(&clip->id)); /* FIXME: make several stream accessible in image editor, too */ clip->anim = openanim(str, IB_rect, 0, clip->colorspace_settings.name); @@ -1300,7 +1300,7 @@ void BKE_movieclip_reload(Main *bmain, MovieClip *clip) */ { Scene *scene; - for (scene = G.main->scene.first; scene; scene = scene->id.next) { + for (scene = bmain->scene.first; scene; scene = scene->id.next) { if (scene->nodetree) { nodeUpdateID(scene->nodetree, &clip->id); } @@ -1568,7 +1568,7 @@ void BKE_movieclip_filename_for_frame(MovieClip *clip, MovieClipUser *user, char } else { BLI_strncpy(name, clip->name, FILE_MAX); - BLI_path_abs(name, ID_BLEND_PATH(G.main, &clip->id)); + BLI_path_abs(name, ID_BLEND_PATH_FROM_GLOBAL(&clip->id)); } } diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index b91887e6815..56705c834d5 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -54,9 +54,10 @@ #include "BKE_action.h" #include "BKE_fcurve.h" -#include "BKE_nla.h" #include "BKE_global.h" #include "BKE_library.h" +#include "BKE_main.h" +#include "BKE_nla.h" #ifdef WITH_AUDASPACE # include <AUD_Special.h> @@ -162,7 +163,7 @@ void BKE_nla_tracks_free(ListBase *tracks) * * \param use_same_action When true, the existing action is used (instead of being duplicated) */ -NlaStrip *BKE_nlastrip_copy(NlaStrip *strip, const bool use_same_action) +NlaStrip *BKE_nlastrip_copy(Main *bmain, NlaStrip *strip, const bool use_same_action) { NlaStrip *strip_d; NlaStrip *cs, *cs_d; @@ -183,7 +184,7 @@ NlaStrip *BKE_nlastrip_copy(NlaStrip *strip, const bool use_same_action) } else { /* use a copy of the action instead (user count shouldn't have changed yet) */ - strip_d->act = BKE_action_copy(G.main, strip_d->act); + strip_d->act = BKE_action_copy(bmain, strip_d->act); } } @@ -195,7 +196,7 @@ NlaStrip *BKE_nlastrip_copy(NlaStrip *strip, const bool use_same_action) BLI_listbase_clear(&strip_d->strips); for (cs = strip->strips.first; cs; cs = cs->next) { - cs_d = BKE_nlastrip_copy(cs, use_same_action); + cs_d = BKE_nlastrip_copy(bmain, cs, use_same_action); BLI_addtail(&strip_d->strips, cs_d); } @@ -204,7 +205,7 @@ NlaStrip *BKE_nlastrip_copy(NlaStrip *strip, const bool use_same_action) } /* Copy NLA Track */ -NlaTrack *BKE_nlatrack_copy(NlaTrack *nlt, const bool use_same_actions) +NlaTrack *BKE_nlatrack_copy(Main *bmain, NlaTrack *nlt, const bool use_same_actions) { NlaStrip *strip, *strip_d; NlaTrack *nlt_d; @@ -221,7 +222,7 @@ NlaTrack *BKE_nlatrack_copy(NlaTrack *nlt, const bool use_same_actions) BLI_listbase_clear(&nlt_d->strips); for (strip = nlt->strips.first; strip; strip = strip->next) { - strip_d = BKE_nlastrip_copy(strip, use_same_actions); + strip_d = BKE_nlastrip_copy(bmain, strip, use_same_actions); BLI_addtail(&nlt_d->strips, strip_d); } @@ -230,7 +231,7 @@ NlaTrack *BKE_nlatrack_copy(NlaTrack *nlt, const bool use_same_actions) } /* Copy all NLA data */ -void BKE_nla_tracks_copy(ListBase *dst, ListBase *src) +void BKE_nla_tracks_copy(Main *bmain, ListBase *dst, ListBase *src) { NlaTrack *nlt, *nlt_d; @@ -245,7 +246,7 @@ void BKE_nla_tracks_copy(ListBase *dst, ListBase *src) for (nlt = src->first; nlt; nlt = nlt->next) { /* make a copy, and add the copy to the destination list */ // XXX: we need to fix this sometime - nlt_d = BKE_nlatrack_copy(nlt, true); + nlt_d = BKE_nlatrack_copy(bmain, nlt, true); BLI_addtail(dst, nlt_d); } } diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index bf25306028f..72a34d35715 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -2050,11 +2050,11 @@ void ntreeLocalSync(bNodeTree *localtree, bNodeTree *ntree) /* merge local tree results back, and free local tree */ /* we have to assume the editor already changed completely */ -void ntreeLocalMerge(bNodeTree *localtree, bNodeTree *ntree) +void ntreeLocalMerge(Main *bmain, bNodeTree *localtree, bNodeTree *ntree) { if (ntree && localtree) { if (ntree->typeinfo->local_merge) - ntree->typeinfo->local_merge(localtree, ntree); + ntree->typeinfo->local_merge(bmain, localtree, ntree); ntreeFreeTree(localtree); MEM_freeN(localtree); diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index f55925f64f5..2db9e2f6b5e 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -2969,7 +2969,7 @@ void BKE_object_delete_ptcache(Object *ob, int index) /* shape key utility function */ /************************* Mesh ************************/ -static KeyBlock *insert_meshkey(Object *ob, const char *name, const bool from_mix) +static KeyBlock *insert_meshkey(Main *bmain, Object *ob, const char *name, const bool from_mix) { Mesh *me = ob->data; Key *key = me->key; @@ -2977,7 +2977,7 @@ static KeyBlock *insert_meshkey(Object *ob, const char *name, const bool from_mi int newkey = 0; if (key == NULL) { - key = me->key = BKE_key_add((ID *)me); + key = me->key = BKE_key_add(bmain, (ID *)me); key->type = KEY_RELATIVE; newkey = 1; } @@ -3001,7 +3001,7 @@ static KeyBlock *insert_meshkey(Object *ob, const char *name, const bool from_mi return kb; } /************************* Lattice ************************/ -static KeyBlock *insert_lattkey(Object *ob, const char *name, const bool from_mix) +static KeyBlock *insert_lattkey(Main *bmain, Object *ob, const char *name, const bool from_mix) { Lattice *lt = ob->data; Key *key = lt->key; @@ -3009,7 +3009,7 @@ static KeyBlock *insert_lattkey(Object *ob, const char *name, const bool from_mi int newkey = 0; if (key == NULL) { - key = lt->key = BKE_key_add((ID *)lt); + key = lt->key = BKE_key_add(bmain, (ID *)lt); key->type = KEY_RELATIVE; newkey = 1; } @@ -3039,7 +3039,7 @@ static KeyBlock *insert_lattkey(Object *ob, const char *name, const bool from_mi return kb; } /************************* Curve ************************/ -static KeyBlock *insert_curvekey(Object *ob, const char *name, const bool from_mix) +static KeyBlock *insert_curvekey(Main *bmain, Object *ob, const char *name, const bool from_mix) { Curve *cu = ob->data; Key *key = cu->key; @@ -3048,7 +3048,7 @@ static KeyBlock *insert_curvekey(Object *ob, const char *name, const bool from_m int newkey = 0; if (key == NULL) { - key = cu->key = BKE_key_add((ID *)cu); + key = cu->key = BKE_key_add(bmain, (ID *)cu); key->type = KEY_RELATIVE; newkey = 1; } @@ -3079,16 +3079,16 @@ static KeyBlock *insert_curvekey(Object *ob, const char *name, const bool from_m return kb; } -KeyBlock *BKE_object_shapekey_insert(Object *ob, const char *name, const bool from_mix) +KeyBlock *BKE_object_shapekey_insert(Main *bmain, Object *ob, const char *name, const bool from_mix) { switch (ob->type) { case OB_MESH: - return insert_meshkey(ob, name, from_mix); + return insert_meshkey(bmain, ob, name, from_mix); case OB_CURVE: case OB_SURF: - return insert_curvekey(ob, name, from_mix); + return insert_curvekey(bmain, ob, name, from_mix); case OB_LATTICE: - return insert_lattkey(ob, name, from_mix); + return insert_lattkey(bmain, ob, name, from_mix); default: return NULL; } diff --git a/source/blender/blenkernel/intern/object_dupli.c b/source/blender/blenkernel/intern/object_dupli.c index 324ad3a31dc..e48a04c5726 100644 --- a/source/blender/blenkernel/intern/object_dupli.c +++ b/source/blender/blenkernel/intern/object_dupli.c @@ -98,7 +98,9 @@ typedef struct DupliGenerator { static const DupliGenerator *get_dupli_generator(const DupliContext *ctx); /* create initial context for root object */ -static void init_context(DupliContext *r_ctx, Depsgraph *depsgraph, Scene *scene, Object *ob, float space_mat[4][4]) +static void init_context( + DupliContext *r_ctx, Depsgraph *depsgraph, + Scene *scene, Object *ob, float space_mat[4][4]) { r_ctx->depsgraph = depsgraph; r_ctx->scene = scene; @@ -231,13 +233,12 @@ static void make_child_duplis(const DupliContext *ctx, void *userdata, MakeChild Object *parent = ctx->object; if (ctx->collection) { - int collectionid = 0; - FOREACH_COLLECTION_BASE_RECURSIVE_BEGIN(ctx->collection, base) + eEvaluationMode mode = DEG_get_mode(ctx->depsgraph); + FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_BEGIN(ctx->collection, ob, mode) { - Object *ob = base->object; - if ((base->flag & BASE_VISIBLED) && ob != ctx->obedit && is_child(ob, parent)) { + if ((ob != ctx->obedit) && is_child(ob, parent)) { DupliContext pctx; - copy_dupli_context(&pctx, ctx, ctx->object, NULL, collectionid); + copy_dupli_context(&pctx, ctx, ctx->object, NULL, _base_id); /* mballs have a different dupli handling */ if (ob->type != OB_MBALL) { @@ -245,9 +246,8 @@ static void make_child_duplis(const DupliContext *ctx, void *userdata, MakeChild } make_child_duplis_cb(&pctx, userdata, ob); } - collectionid++; } - FOREACH_COLLECTION_BASE_RECURSIVE_END + FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_END; } else { int baseid = 0; @@ -276,9 +276,7 @@ static void make_duplis_collection(const DupliContext *ctx) { Object *ob = ctx->object; Collection *collection; - Base *base; float collection_mat[4][4]; - int id; if (ob->dup_group == NULL) return; collection = ob->dup_group; @@ -289,20 +287,22 @@ static void make_duplis_collection(const DupliContext *ctx) mul_m4_m4m4(collection_mat, ob->obmat, collection_mat); /* don't access 'ob->obmat' from now on. */ - const ListBase dup_collection_objects = BKE_collection_object_cache_get(collection); - for (base = dup_collection_objects.first, id = 0; base; base = base->next, id++) { - if (base->object != ob && (base->flag & BASE_VISIBLED)) { + eEvaluationMode mode = DEG_get_mode(ctx->depsgraph); + FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_BEGIN(collection, cob, mode) + { + if (cob != ob) { float mat[4][4]; /* collection dupli offset, should apply after everything else */ - mul_m4_m4m4(mat, collection_mat, base->object->obmat); + mul_m4_m4m4(mat, collection_mat, cob->obmat); - make_dupli(ctx, base->object, mat, id); + make_dupli(ctx, cob, mat, _base_id); /* recursion */ - make_recursive_duplis(ctx, base->object, collection_mat, id); + make_recursive_duplis(ctx, cob, collection_mat, _base_id); } } + FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_END; } static const DupliGenerator gen_dupli_collection = { @@ -496,7 +496,7 @@ static void make_duplis_verts(const DupliContext *ctx) { Scene *scene = ctx->scene; Object *parent = ctx->object; - bool use_texcoords = ELEM(DEG_get_mode(ctx->depsgraph), DAG_EVAL_RENDER, DAG_EVAL_PREVIEW); + bool use_texcoords = (DEG_get_mode(ctx->depsgraph) == DAG_EVAL_RENDER); VertexDupliData vdd; vdd.ctx = ctx; @@ -538,7 +538,7 @@ static const DupliGenerator gen_dupli_verts = { }; /* OB_DUPLIVERTS - FONT */ -static Object *find_family_object(const char *family, size_t family_len, unsigned int ch, GHash *family_gh) +static Object *find_family_object(Main *bmain, const char *family, size_t family_len, unsigned int ch, GHash *family_gh) { Object **ob_pt; Object *ob; @@ -555,7 +555,7 @@ static Object *find_family_object(const char *family, size_t family_len, unsigne ch_utf8[ch_utf8_len] = '\0'; ch_utf8_len += 1; /* compare with null terminator */ - for (ob = G.main->object.first; ob; ob = ob->id.next) { + for (ob = bmain->object.first; ob; ob = ob->id.next) { if (STREQLEN(ob->id.name + 2 + family_len, ch_utf8, ch_utf8_len)) { if (STREQLEN(ob->id.name + 2, family, family_len)) { break; @@ -591,7 +591,7 @@ static void make_duplis_font(const DupliContext *ctx) /* in par the family name is stored, use this to find the other objects */ - BKE_vfont_to_curve_ex(G.main, par, par->data, FO_DUPLI, NULL, + BKE_vfont_to_curve_ex(par, par->data, FO_DUPLI, NULL, &text, &text_len, &text_free, &chartransdata); if (text == NULL || chartransdata == NULL) { @@ -612,7 +612,9 @@ static void make_duplis_font(const DupliContext *ctx) /* advance matching BLI_strncpy_wchar_from_utf8 */ for (a = 0; a < text_len; a++, ct++) { - ob = find_family_object(cu->family, family_len, (unsigned int)text[a], family_gh); + /* XXX That G.main is *really* ugly, but not sure what to do here... + * Definitively don't think it would be safe to put back Main *bmain pointer in DupliContext as done in 2.7x? */ + ob = find_family_object(G.main, cu->family, family_len, (unsigned int)text[a], family_gh); if (ob) { vec[0] = fsize * (ct->xof - xof); vec[1] = fsize * (ct->yof - yof); @@ -700,7 +702,7 @@ static void make_child_duplis_faces(const DupliContext *ctx, void *userdata, Obj float (*orco)[3] = fdd->orco; MLoopUV *mloopuv = fdd->mloopuv; int a, totface = fdd->totface; - bool use_texcoords = ELEM(DEG_get_mode(ctx->depsgraph), DAG_EVAL_RENDER, DAG_EVAL_PREVIEW); + bool use_texcoords = (DEG_get_mode(ctx->depsgraph) == DAG_EVAL_RENDER); float child_imat[4][4]; DupliObject *dob; @@ -766,7 +768,7 @@ static void make_duplis_faces(const DupliContext *ctx) { Scene *scene = ctx->scene; Object *parent = ctx->object; - bool use_texcoords = ELEM(DEG_get_mode(ctx->depsgraph), DAG_EVAL_RENDER, DAG_EVAL_PREVIEW); + bool use_texcoords = (DEG_get_mode(ctx->depsgraph) == DAG_EVAL_RENDER); FaceDupliData fdd; fdd.use_scale = ((parent->transflag & OB_DUPLIFACES_SCALE) != 0); @@ -818,8 +820,9 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem { Scene *scene = ctx->scene; Object *par = ctx->object; - bool for_render = DEG_get_mode(ctx->depsgraph) == DAG_EVAL_RENDER; - bool use_texcoords = ELEM(DEG_get_mode(ctx->depsgraph), DAG_EVAL_RENDER, DAG_EVAL_PREVIEW); + eEvaluationMode mode = DEG_get_mode(ctx->depsgraph); + bool for_render = mode == DAG_EVAL_RENDER; + bool use_texcoords = for_render; Object *ob = NULL, **oblist = NULL, obcopy, *obcopylist = NULL; DupliObject *dob; @@ -834,6 +837,7 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem float (*obmat)[4]; int a, b, hair = 0; int totpart, totchild, totcollection = 0 /*, pa_num */; + RNG *rng; int no_draw_flag = PARS_UNEXIST; @@ -844,7 +848,7 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem if (part == NULL) return; - if (!psys_check_enabled(par, psys, (DEG_get_mode(ctx->depsgraph) == DAG_EVAL_RENDER))) + if (!psys_check_enabled(par, psys, for_render)) return; if (!for_render) @@ -855,7 +859,7 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem totpart = psys->totpart; totchild = psys->totchild; - BLI_srandom((unsigned int)(31415926 + psys->seed)); + rng = BLI_rng_new_srandom(31415926u + (unsigned int)psys->seed); if ((for_render || part->draw_as == PART_DRAW_REND) && ELEM(part->ren_as, PART_DRAW_OB, PART_DRAW_GR)) { ParticleSimulationData sim = {NULL}; @@ -908,12 +912,12 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem totcollection += dw->count; } else { - FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(part->dup_group, object) + FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_BEGIN(part->dup_group, object, mode) { (void) object; totcollection++; } - FOREACH_COLLECTION_OBJECT_RECURSIVE_END; + FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_END; } /* we also copy the actual objects to restore afterwards, since @@ -933,7 +937,7 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem } else { a = 0; - FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(part->dup_group, object) + FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_BEGIN(part->dup_group, object, mode) { oblist[a] = object; obcopylist[a] = *object; @@ -943,7 +947,7 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem continue; } } - FOREACH_COLLECTION_OBJECT_RECURSIVE_END; + FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_END; } } else { @@ -990,7 +994,7 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem /* for collections, pick the object based on settings */ if (part->draw & PART_DRAW_RAND_GR) - b = BLI_rand() % totcollection; + b = BLI_rng_get_int(rng) % totcollection; else b = a % totcollection; @@ -1033,7 +1037,7 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem if (part->ren_as == PART_DRAW_GR && psys->part->draw & PART_DRAW_WHOLE_GR) { b = 0; - FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(part->dup_group, object) + FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_BEGIN(part->dup_group, object, mode) { copy_m4_m4(tmat, oblist[b]->obmat); @@ -1058,7 +1062,7 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem b++; } - FOREACH_COLLECTION_OBJECT_RECURSIVE_END; + FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_END; } else { /* to give ipos in object correct offset */ @@ -1129,6 +1133,8 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem end_latt_deform(psys->lattice_deform_data); psys->lattice_deform_data = NULL; } + + BLI_rng_free(rng); } static void make_duplis_particles(const DupliContext *ctx) diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c index 3b684ebfd94..c1bda070bd8 100644 --- a/source/blender/blenkernel/intern/object_update.c +++ b/source/blender/blenkernel/intern/object_update.c @@ -39,28 +39,29 @@ #include "BLI_utildefines.h" #include "BLI_math.h" -#include "BKE_global.h" +#include "BKE_animsys.h" #include "BKE_armature.h" #include "BKE_action.h" #include "BKE_constraint.h" #include "BKE_curve.h" #include "BKE_DerivedMesh.h" -#include "BKE_animsys.h" #include "BKE_displist.h" +#include "BKE_editmesh.h" #include "BKE_effect.h" +#include "BKE_global.h" +#include "BKE_image.h" #include "BKE_key.h" #include "BKE_lamp.h" #include "BKE_lattice.h" #include "BKE_library.h" -#include "BKE_editmesh.h" +#include "BKE_main.h" +#include "BKE_material.h" +#include "BKE_mball.h" +#include "BKE_mesh.h" #include "BKE_object.h" #include "BKE_particle.h" #include "BKE_pointcache.h" #include "BKE_scene.h" -#include "BKE_material.h" -#include "BKE_mball.h" -#include "BKE_mesh.h" -#include "BKE_image.h" #include "MEM_guardedalloc.h" @@ -241,7 +242,6 @@ void BKE_object_handle_data_update( if (!(ob->mode & OB_MODE_EDIT) && ob->particlesystem.first) { const bool use_render_params = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER); ParticleSystem *tpsys, *psys; - DerivedMesh *dm; ob->transflag &= ~OB_DUPLIPARTS; psys = ob->particlesystem.first; while (psys) { @@ -266,18 +266,6 @@ void BKE_object_handle_data_update( else psys = psys->next; } - - if (use_render_params && ob->transflag & OB_DUPLIPARTS) { - /* this is to make sure we get render level duplis in groups: - * the derivedmesh must be created before init_render_mesh, - * since object_duplilist does dupliparticles before that */ - CustomDataMask data_mask = CD_MASK_BAREMESH | CD_MASK_MFACE | CD_MASK_MTFACE | CD_MASK_MCOL; - dm = mesh_create_derived_render(depsgraph, scene, ob, data_mask); - dm->release(dm); - - for (psys = ob->particlesystem.first; psys; psys = psys->next) - psys_get_modifier(ob, psys)->flag &= ~eParticleSystemFlag_psys_updated; - } } /* quick cache removed */ diff --git a/source/blender/blenkernel/intern/packedFile.c b/source/blender/blenkernel/intern/packedFile.c index baa88f00985..07cd28da556 100644 --- a/source/blender/blenkernel/intern/packedFile.c +++ b/source/blender/blenkernel/intern/packedFile.c @@ -622,7 +622,7 @@ int unpackImage(Main *bmain, ReportList *reports, Image *ima, int how) } if (ret_value == RET_OK) { - BKE_image_signal(ima, NULL, IMA_SIGNAL_RELOAD); + BKE_image_signal(bmain, ima, NULL, IMA_SIGNAL_RELOAD); } return(ret_value); diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index f03b46c8a07..7403f458c49 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -504,7 +504,7 @@ eObjectMode BKE_paint_object_mode_from_paint_mode(ePaintMode mode) } } -void BKE_paint_init(Scene *sce, ePaintMode mode, const char col[3]) +void BKE_paint_init(Main *bmain, Scene *sce, ePaintMode mode, const char col[3]) { UnifiedPaintSettings *ups = &sce->toolsettings->unified_paint_settings; Brush *brush; @@ -514,10 +514,10 @@ void BKE_paint_init(Scene *sce, ePaintMode mode, const char col[3]) brush = BKE_paint_brush(paint); if (brush == NULL) { eObjectMode ob_mode = BKE_paint_object_mode_from_paint_mode(mode); - brush = BKE_brush_first_search(G.main, ob_mode); + brush = BKE_brush_first_search(bmain, ob_mode); if (!brush) { - brush = BKE_brush_add(G.main, "Brush", ob_mode); + brush = BKE_brush_add(bmain, "Brush", ob_mode); id_us_min(&brush->id); /* fake user only */ } BKE_paint_brush_set(paint, brush); @@ -709,7 +709,7 @@ static void sculptsession_bm_to_me_update_data_only(Object *ob, bool reorder) } if (reorder) BM_log_mesh_elems_reorder(ss->bm, ss->bm_log); - BM_mesh_bm_to_me(ss->bm, ob->data, (&(struct BMeshToMeshParams){0})); + BM_mesh_bm_to_me(NULL, ss->bm, ob->data, (&(struct BMeshToMeshParams){.calc_object_remap = false})); } } } diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index c1fb9130b5d..c46d342f8a1 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -100,19 +100,19 @@ float PSYS_FRAND_BASE[PSYS_FRAND_COUNT]; void psys_init_rng(void) { - int i; - BLI_srandom(5831); /* arbitrary */ - for (i = 0; i < PSYS_FRAND_COUNT; ++i) { - PSYS_FRAND_BASE[i] = BLI_frand(); - PSYS_FRAND_SEED_OFFSET[i] = (unsigned int)BLI_rand(); - PSYS_FRAND_SEED_MULTIPLIER[i] = (unsigned int)BLI_rand(); + RNG *rng = BLI_rng_new_srandom(5831); /* arbitrary */ + for (int i = 0; i < PSYS_FRAND_COUNT; ++i) { + PSYS_FRAND_BASE[i] = BLI_rng_get_float(rng); + PSYS_FRAND_SEED_OFFSET[i] = (unsigned int)BLI_rng_get_int(rng); + PSYS_FRAND_SEED_MULTIPLIER[i] = (unsigned int)BLI_rng_get_int(rng); } + BLI_rng_free(rng); } static void get_child_modifier_parameters(ParticleSettings *part, ParticleThreadContext *ctx, ChildParticle *cpa, short cpa_from, int cpa_num, float *cpa_fuv, float *orco, ParticleTexture *ptex); static void get_cpa_texture(Mesh *mesh, ParticleSystem *psys, ParticleSettings *part, ParticleData *par, - int child_index, int face_index, const float fw[4], float *orco, ParticleTexture *ptex, int event, float cfra); + int child_index, int face_index, const float fw[4], float *orco, ParticleTexture *ptex, int event, float cfra); /* few helpers for countall etc. */ int count_particles(ParticleSystem *psys) @@ -2980,7 +2980,7 @@ void psys_mat_hair_to_global(Object *ob, Mesh *mesh, short from, ParticleData *p /************************************************/ /* ParticleSettings handling */ /************************************************/ -ModifierData *object_add_particle_system(Scene *scene, Object *ob, const char *name) +ModifierData *object_add_particle_system(Main *bmain, Scene *scene, Object *ob, const char *name) { ParticleSystem *psys; ModifierData *md; @@ -2997,7 +2997,7 @@ ModifierData *object_add_particle_system(Scene *scene, Object *ob, const char *n psys->pointcache = BKE_ptcache_add(&psys->ptcaches); BLI_addtail(&ob->particlesystem, psys); - psys->part = BKE_particlesettings_add(NULL, DATA_("ParticleSettings")); + psys->part = BKE_particlesettings_add(bmain, DATA_("ParticleSettings")); if (BLI_listbase_count_at_most(&ob->particlesystem, 2) > 1) BLI_snprintf(psys->name, sizeof(psys->name), DATA_("ParticleSystem %i"), BLI_listbase_count(&ob->particlesystem)); @@ -3020,12 +3020,12 @@ ModifierData *object_add_particle_system(Scene *scene, Object *ob, const char *n psys->flag = PSYS_CURRENT; psys->cfra = BKE_scene_frame_get_from_ctime(scene, CFRA + 1); - DEG_relations_tag_update(G.main); + DEG_relations_tag_update(bmain); DEG_id_tag_update(&ob->id, OB_RECALC_DATA); return md; } -void object_remove_particle_system(Scene *UNUSED(scene), Object *ob) +void object_remove_particle_system(Main *bmain, Scene *UNUSED(scene), Object *ob) { ParticleSystem *psys = psys_get_current(ob); ParticleSystemModifierData *psmd; @@ -3066,7 +3066,7 @@ void object_remove_particle_system(Scene *UNUSED(scene), Object *ob) else ob->mode &= ~OB_MODE_PARTICLE_EDIT; - DEG_relations_tag_update(G.main); + DEG_relations_tag_update(bmain); DEG_id_tag_update(&ob->id, OB_RECALC_DATA); /* Flush object mode. */ @@ -3160,14 +3160,11 @@ static void default_particle_settings(ParticleSettings *part) } -ParticleSettings *BKE_particlesettings_add(Main *main, const char *name) +ParticleSettings *BKE_particlesettings_add(Main *bmain, const char *name) { ParticleSettings *part; - if (main == NULL) - main = G.main; - - part = BKE_libblock_alloc(main, ID_PA, name, 0); + part = BKE_libblock_alloc(bmain, ID_PA, name, 0); default_particle_settings(part); diff --git a/source/blender/blenkernel/intern/particle_distribute.c b/source/blender/blenkernel/intern/particle_distribute.c index 846afd48064..05ce45e3900 100644 --- a/source/blender/blenkernel/intern/particle_distribute.c +++ b/source/blender/blenkernel/intern/particle_distribute.c @@ -85,6 +85,7 @@ static void distribute_simple_children(Scene *scene, Object *ob, Mesh *final_mes int i, p; int child_nbr= psys_get_child_number(scene, psys, use_render_params); int totpart= psys_get_tot_child(scene, psys, use_render_params); + RNG *rng = BLI_rng_new_srandom(31415926 + psys->seed + psys->child_seed); alloc_child_particles(psys, totpart); @@ -96,9 +97,9 @@ static void distribute_simple_children(Scene *scene, Object *ob, Mesh *final_mes /* create even spherical distribution inside unit sphere */ while (length>=1.0f) { - cpa->fuv[0]=2.0f*BLI_frand()-1.0f; - cpa->fuv[1]=2.0f*BLI_frand()-1.0f; - cpa->fuv[2]=2.0f*BLI_frand()-1.0f; + cpa->fuv[0]=2.0f*BLI_rng_get_float(rng)-1.0f; + cpa->fuv[1]=2.0f*BLI_rng_get_float(rng)-1.0f; + cpa->fuv[2]=2.0f*BLI_rng_get_float(rng)-1.0f; length=len_v3(cpa->fuv); } @@ -107,6 +108,8 @@ static void distribute_simple_children(Scene *scene, Object *ob, Mesh *final_mes } /* dmcache must be updated for parent particles if children from faces is used */ psys_calc_dmcache(ob, final_mesh, deform_mesh, psys); + + BLI_rng_free(rng); } static void distribute_grid(Mesh *mesh, ParticleSystem *psys) { @@ -430,7 +433,7 @@ static int distribute_binary_search(float *sum, int n, float value) /* the max number if calls to rng_* funcs within psys_thread_distribute_particle * be sure to keep up to date if this changes */ -#define PSYS_RND_DIST_SKIP 2 +#define PSYS_RND_DIST_SKIP 3 /* note: this function must be thread safe, for from == PART_FROM_CHILD */ #define ONLY_WORKING_WITH_PA_VERTS 0 @@ -484,8 +487,10 @@ static void distribute_from_verts_exec(ParticleTask *thread, ParticleData *pa, i } #endif - if (rng_skip_tot > 0) /* should never be below zero */ + BLI_assert(rng_skip_tot > 0); /* should never be below zero */ + if (rng_skip_tot > 0) { BLI_rng_skip(thread->rng, rng_skip_tot); + } } static void distribute_from_faces_exec(ParticleTask *thread, ParticleData *pa, int p) { @@ -525,9 +530,11 @@ static void distribute_from_faces_exec(ParticleTask *thread, ParticleData *pa, i break; } pa->foffset= 0.0f; - - if (rng_skip_tot > 0) /* should never be below zero */ + + BLI_assert(rng_skip_tot > 0); /* should never be below zero */ + if (rng_skip_tot > 0) { BLI_rng_skip(thread->rng, rng_skip_tot); + } } static void distribute_from_volume_exec(ParticleTask *thread, ParticleData *pa, int p) { @@ -615,13 +622,16 @@ static void distribute_from_volume_exec(ParticleTask *thread, ParticleData *pa, pa->foffset *= ctx->jit[p % (2 * ctx->jitlevel)]; break; case PART_DISTR_RAND: - pa->foffset *= BLI_frand(); + pa->foffset *= BLI_rng_get_float(thread->rng); + rng_skip_tot--; break; } } - if (rng_skip_tot > 0) /* should never be below zero */ + BLI_assert(rng_skip_tot > 0); /* should never be below zero */ + if (rng_skip_tot > 0) { BLI_rng_skip(thread->rng, rng_skip_tot); + } } static void distribute_children_exec(ParticleTask *thread, ChildParticle *cpa, int p) { @@ -818,6 +828,7 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, Parti int jitlevel= 1, distr; float *element_weight=NULL,*jitter_offset=NULL, *vweight=NULL; float cur, maxweight=0.0, tweight, totweight, inv_totweight, co[3], nor[3], orco[3]; + RNG *rng = NULL; if (ELEM(NULL, ob, psys, psys->part)) return 0; @@ -846,7 +857,6 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, Parti if (from == PART_FROM_CHILD) { /* Simple children */ if (part->childtype != PART_CHILD_FACES) { - BLI_srandom(31415926 + psys->seed + psys->child_seed); distribute_simple_children(scene, ob, final_mesh, sim->psmd->mesh_original, psys, use_render_params); return 0; } @@ -854,8 +864,6 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, Parti else { /* Grid distribution */ if (part->distr==PART_DISTR_GRID && from != PART_FROM_VERT) { - BLI_srandom(31415926 + psys->seed); - if (psys->part->use_modifier_stack) { mesh = final_mesh; } @@ -882,8 +890,8 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, Parti /* Create trees and original coordinates if needed */ if (from == PART_FROM_CHILD) { - distr=PART_DISTR_RAND; - BLI_srandom(31415926 + psys->seed + psys->child_seed); + distr = PART_DISTR_RAND; + rng = BLI_rng_new_srandom(31415926 + psys->seed + psys->child_seed); mesh= final_mesh; /* BMESH ONLY */ @@ -906,7 +914,8 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, Parti } else { distr = part->distr; - BLI_srandom(31415926 + psys->seed); + + rng = BLI_rng_new_srandom(31415926 + psys->seed); if (psys->part->use_modifier_stack) mesh = final_mesh; @@ -958,6 +967,7 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, Parti if (mesh != final_mesh) BKE_id_free(NULL, mesh); BLI_kdtree_free(tree); + BLI_rng_free(rng); return 0; } @@ -1098,7 +1108,7 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, Parti for (p = 0; p < totpart; p++) { /* In theory element_sum[totmapped - 1] should be 1.0, * but due to float errors this is not necessarily always true, so scale pos accordingly. */ - const float pos = BLI_frand() * element_sum[totmapped - 1]; + const float pos = BLI_rng_get_float(rng) * element_sum[totmapped - 1]; const int eidx = distribute_binary_search(element_sum, totmapped, pos); particle_element[p] = element_map[eidx]; BLI_assert(pos <= element_sum[eidx]); @@ -1191,6 +1201,8 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, Parti alloc_child_particles(psys, totpart); } + BLI_rng_free(rng); + return 1; } diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 8d6991ff9f4..81666936c6f 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -2061,6 +2061,7 @@ static void basic_force_cb(void *efdata_v, ParticleKey *state, float *force, flo ParticleSettings *part = sim->psys->part; ParticleData *pa = efdata->pa; EffectedPoint epoint; + RNG *rng = sim->rng; /* add effectors */ pd_point_from_particle(efdata->sim, efdata->pa, state, &epoint); @@ -2076,9 +2077,9 @@ static void basic_force_cb(void *efdata_v, ParticleKey *state, float *force, flo /* brownian force */ if (part->brownfac != 0.0f) { - force[0] += (BLI_frand()-0.5f) * part->brownfac; - force[1] += (BLI_frand()-0.5f) * part->brownfac; - force[2] += (BLI_frand()-0.5f) * part->brownfac; + force[0] += (BLI_rng_get_float(rng)-0.5f) * part->brownfac; + force[1] += (BLI_rng_get_float(rng)-0.5f) * part->brownfac; + force[2] += (BLI_rng_get_float(rng)-0.5f) * part->brownfac; } if (part->flag & PART_ROT_DYN && epoint.ave) @@ -2649,16 +2650,17 @@ static int collision_detect(ParticleData *pa, ParticleCollision *col, BVHTreeRay return hit->index >= 0; } -static int collision_response(ParticleData *pa, ParticleCollision *col, BVHTreeRayHit *hit, int kill, int dynamic_rotation) +static int collision_response(ParticleSimulationData *sim, ParticleData *pa, ParticleCollision *col, BVHTreeRayHit *hit, int kill, int dynamic_rotation) { ParticleCollisionElement *pce = &col->pce; PartDeflect *pd = col->hit->pd; + RNG *rng = sim->rng; float co[3]; /* point of collision */ float x = hit->dist/col->original_ray_length; /* location factor of collision between this iteration */ float f = col->f + x * (1.0f - col->f); /* time factor of collision between timestep */ float dt1 = (f - col->f) * col->total_time; /* time since previous collision (in seconds) */ float dt2 = (1.0f - f) * col->total_time; /* time left after collision (in seconds) */ - int through = (BLI_frand() < pd->pdef_perm) ? 1 : 0; /* did particle pass through the collision surface? */ + int through = (BLI_rng_get_float(rng) < pd->pdef_perm) ? 1 : 0; /* did particle pass through the collision surface? */ /* calculate exact collision location */ interp_v3_v3v3(co, col->co1, col->co2, x); @@ -2683,8 +2685,8 @@ static int collision_response(ParticleData *pa, ParticleCollision *col, BVHTreeR float v0_tan[3];/* tangential component of v0 */ float vc_tan[3];/* tangential component of collision surface velocity */ float v0_dot, vc_dot; - float damp = pd->pdef_damp + pd->pdef_rdamp * 2 * (BLI_frand() - 0.5f); - float frict = pd->pdef_frict + pd->pdef_rfrict * 2 * (BLI_frand() - 0.5f); + float damp = pd->pdef_damp + pd->pdef_rdamp * 2 * (BLI_rng_get_float(rng) - 0.5f); + float frict = pd->pdef_frict + pd->pdef_rfrict * 2 * (BLI_rng_get_float(rng) - 0.5f); float distance, nor[3], dot; CLAMP(damp,0.0f, 1.0f); @@ -2894,7 +2896,7 @@ static void collision_check(ParticleSimulationData *sim, int p, float dfra, floa if (collision_count == PARTICLE_COLLISION_MAX_COLLISIONS) collision_fail(pa, &col); - else if (collision_response(pa, &col, &hit, part->flag & PART_DIE_ON_COL, part->flag & PART_ROT_DYN)==0) + else if (collision_response(sim, pa, &col, &hit, part->flag & PART_DIE_ON_COL, part->flag & PART_ROT_DYN)==0) return; } else @@ -3502,7 +3504,6 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra) { ParticleSystem *psys = sim->psys; ParticleSettings *part=psys->part; - RNG *rng; BoidBrainData bbd; ParticleTexture ptex; PARTICLE_P; @@ -3529,9 +3530,8 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra) return; } - BLI_srandom(31415926 + (int)cfra + psys->seed); /* for now do both, boids us 'rng' */ - rng = BLI_rng_new_srandom(31415926 + (int)cfra + psys->seed); + sim->rng = BLI_rng_new_srandom(31415926 + (int)cfra + psys->seed); psys_update_effectors(sim); @@ -3548,7 +3548,7 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra) bbd.cfra = cfra; bbd.dfra = dfra; bbd.timestep = timestep; - bbd.rng = rng; + bbd.rng = sim->rng; psys_update_particle_tree(psys, cfra); @@ -3744,8 +3744,10 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra) } free_collider_cache(&sim->colliders); - BLI_rng_free(rng); + BLI_rng_free(sim->rng); + sim->rng = NULL; } + static void update_children(ParticleSimulationData *sim, const bool use_render_params) { if ((sim->psys->part->type == PART_HAIR) && (sim->psys->flag & PSYS_HAIR_DONE)==0) diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index af13909bf89..10050e5e083 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -1743,16 +1743,15 @@ void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int dup * for baking with linking dupligroups. Once we have better overrides * this can be revisited so users select the local objects directly. */ if (scene && (duplis-- > 0) && (ob->dup_group)) { - Collection *collection = ob->dup_group; - Base *base = BKE_collection_object_cache_get(collection).first; - - for (; base; base = base->next) { - if (base->object != ob) { + FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(ob->dup_group, object) + { + if (object != ob) { ListBase lb_dupli_pid; - BKE_ptcache_ids_from_object(&lb_dupli_pid, base->object, scene, duplis); + BKE_ptcache_ids_from_object(&lb_dupli_pid, object, scene, duplis); BLI_movelisttolist(lb, &lb_dupli_pid); } } + FOREACH_COLLECTION_OBJECT_RECURSIVE_END; } } @@ -3537,7 +3536,7 @@ void BKE_ptcache_quick_cache_all(Main *bmain, Scene *scene, ViewLayer *view_laye PTCacheBaker baker; memset(&baker, 0, sizeof(baker)); - baker.main = bmain; + baker.bmain = bmain; baker.scene = scene; baker.view_layer = view_layer; baker.bake = 0; @@ -3563,7 +3562,7 @@ static void ptcache_dt_to_str(char *str, double dtime) /* if bake is not given run simulations to current frame */ void BKE_ptcache_bake(PTCacheBaker *baker) { - Main *bmain = baker->main; + Main *bmain = baker->bmain; Scene *scene = baker->scene; ViewLayer *view_layer = baker->view_layer; struct Depsgraph *depsgraph = baker->depsgraph; diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c index e79f86c6520..cb5887c07af 100644 --- a/source/blender/blenkernel/intern/rigidbody.c +++ b/source/blender/blenkernel/intern/rigidbody.c @@ -58,6 +58,7 @@ #include "BKE_collection.h" #include "BKE_effect.h" #include "BKE_global.h" +#include "BKE_layer.h" #include "BKE_library.h" #include "BKE_library_query.h" #include "BKE_mesh.h" @@ -1201,17 +1202,20 @@ void BKE_rigidbody_remove_constraint(Scene *scene, Object *ob) /* Update object array and rigid body count so they're in sync with the rigid body group */ static void rigidbody_update_ob_array(RigidBodyWorld *rbw) { - const ListBase objects = BKE_collection_object_cache_get(rbw->group); - int i, n; - - n = BLI_listbase_count(&objects); + int n = 0; + FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(rbw->group, object) + { + (void)object; + n++; + } + FOREACH_COLLECTION_OBJECT_RECURSIVE_END; if (rbw->numbodies != n) { rbw->numbodies = n; rbw->objects = realloc(rbw->objects, sizeof(Object *) * rbw->numbodies); } - i = 0; + int i = 0; FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(rbw->group, object) { rbw->objects[i] = object; @@ -1240,7 +1244,7 @@ static void rigidbody_update_sim_world(Scene *scene, RigidBodyWorld *rbw) rigidbody_update_ob_array(rbw); } -static void rigidbody_update_sim_ob(struct Depsgraph *depsgraph, Scene *scene, RigidBodyWorld *rbw, Object *ob, RigidBodyOb *rbo) +static void rigidbody_update_sim_ob(Depsgraph *depsgraph, Scene *scene, RigidBodyWorld *rbw, Object *ob, RigidBodyOb *rbo) { float loc[3]; float rot[4]; @@ -1329,7 +1333,7 @@ static void rigidbody_update_sim_ob(struct Depsgraph *depsgraph, Scene *scene, R * * \param rebuild Rebuild entire simulation */ -static void rigidbody_update_simulation(struct Depsgraph *depsgraph, Scene *scene, RigidBodyWorld *rbw, bool rebuild) +static void rigidbody_update_simulation(Depsgraph *depsgraph, Scene *scene, RigidBodyWorld *rbw, bool rebuild) { /* update world */ if (rebuild) @@ -1436,14 +1440,16 @@ static void rigidbody_update_simulation(struct Depsgraph *depsgraph, Scene *scen FOREACH_COLLECTION_OBJECT_RECURSIVE_END; } -static void rigidbody_update_simulation_post_step(RigidBodyWorld *rbw) +static void rigidbody_update_simulation_post_step(Depsgraph *depsgraph, RigidBodyWorld *rbw) { - FOREACH_COLLECTION_BASE_RECURSIVE_BEGIN(rbw->group, base) + ViewLayer *view_layer = DEG_get_input_view_layer(depsgraph); + + FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(rbw->group, ob) { - Object *ob = base->object; + Base *base = BKE_view_layer_base_find(view_layer, ob); RigidBodyOb *rbo = ob->rigidbody_object; /* Reset kinematic state for transformed objects. */ - if (rbo && (base->flag & BASE_SELECTED) && (G.moving & G_TRANSFORM_OBJ)) { + if (rbo && base && (base->flag & BASE_SELECTED) && (G.moving & G_TRANSFORM_OBJ)) { RB_body_set_kinematic_state(rbo->physics_object, rbo->flag & RBO_FLAG_KINEMATIC || rbo->flag & RBO_FLAG_DISABLED); RB_body_set_mass(rbo->physics_object, RBO_GET_MASS(rbo)); /* Deactivate passive objects so they don't interfere with deactivation of active objects. */ @@ -1451,7 +1457,7 @@ static void rigidbody_update_simulation_post_step(RigidBodyWorld *rbw) RB_body_deactivate(rbo->physics_object); } } - FOREACH_COLLECTION_BASE_RECURSIVE_END + FOREACH_COLLECTION_OBJECT_RECURSIVE_END; } bool BKE_rigidbody_check_sim_running(RigidBodyWorld *rbw, float ctime) @@ -1566,7 +1572,7 @@ void BKE_rigidbody_cache_reset(RigidBodyWorld *rbw) /* Rebuild rigid body world */ /* NOTE: this needs to be called before frame update to work correctly */ -void BKE_rigidbody_rebuild_world(struct Depsgraph *depsgraph, Scene *scene, float ctime) +void BKE_rigidbody_rebuild_world(Depsgraph *depsgraph, Scene *scene, float ctime) { RigidBodyWorld *rbw = scene->rigidbody_world; PointCache *cache; @@ -1578,8 +1584,15 @@ void BKE_rigidbody_rebuild_world(struct Depsgraph *depsgraph, Scene *scene, floa cache = rbw->pointcache; /* flag cache as outdated if we don't have a world or number of objects in the simulation has changed */ - const ListBase objects = BKE_collection_object_cache_get(rbw->group); - if (rbw->physics_world == NULL || rbw->numbodies != BLI_listbase_count(&objects)) { + int n = 0; + FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(rbw->group, object) + { + (void)object; + n++; + } + FOREACH_COLLECTION_OBJECT_RECURSIVE_END; + + if (rbw->physics_world == NULL || rbw->numbodies != n) { cache->flag |= PTCACHE_OUTDATED; } @@ -1595,7 +1608,7 @@ void BKE_rigidbody_rebuild_world(struct Depsgraph *depsgraph, Scene *scene, floa } /* Run RigidBody simulation for the specified physics world */ -void BKE_rigidbody_do_simulation(struct Depsgraph *depsgraph, Scene *scene, float ctime) +void BKE_rigidbody_do_simulation(Depsgraph *depsgraph, Scene *scene, float ctime) { float timestep; RigidBodyWorld *rbw = scene->rigidbody_world; @@ -1647,7 +1660,7 @@ void BKE_rigidbody_do_simulation(struct Depsgraph *depsgraph, Scene *scene, floa /* step simulation by the requested timestep, steps per second are adjusted to take time scale into account */ RB_dworld_step_simulation(rbw->physics_world, timestep, INT_MAX, 1.0f / (float)rbw->steps_per_second * min_ff(rbw->time_scale, 1.0f)); - rigidbody_update_simulation_post_step(rbw); + rigidbody_update_simulation_post_step(depsgraph, rbw); /* write cache for current frame */ BKE_ptcache_validate(cache, (int)ctime); @@ -1684,8 +1697,8 @@ void BKE_rigidbody_sync_transforms(RigidBodyWorld *rbw, Object *ob, float ctime) void BKE_rigidbody_aftertrans_update(Object *ob, float loc[3], float rot[3], float quat[4], float rotAxis[3], float rotAngle) {} bool BKE_rigidbody_check_sim_running(RigidBodyWorld *rbw, float ctime) { return false; } void BKE_rigidbody_cache_reset(RigidBodyWorld *rbw) {} -void BKE_rigidbody_rebuild_world(struct Depsgraph *depsgraph, Scene *scene, float ctime) {} -void BKE_rigidbody_do_simulation(struct Depsgraph *depsgraph, Scene *scene, float ctime) {} +void BKE_rigidbody_rebuild_world(Depsgraph *depsgraph, Scene *scene, float ctime) {} +void BKE_rigidbody_do_simulation(Depsgraph *depsgraph, Scene *scene, float ctime) {} #if defined(__GNUC__) || defined(__clang__) # pragma GCC diagnostic pop @@ -1696,7 +1709,7 @@ void BKE_rigidbody_do_simulation(struct Depsgraph *depsgraph, Scene *scene, floa /* -------------------- */ /* Depsgraph evaluation */ -void BKE_rigidbody_rebuild_sim(struct Depsgraph *depsgraph, +void BKE_rigidbody_rebuild_sim(Depsgraph *depsgraph, Scene *scene) { float ctime = DEG_get_ctime(depsgraph); @@ -1707,7 +1720,7 @@ void BKE_rigidbody_rebuild_sim(struct Depsgraph *depsgraph, } } -void BKE_rigidbody_eval_simulation(struct Depsgraph *depsgraph, +void BKE_rigidbody_eval_simulation(Depsgraph *depsgraph, Scene *scene) { float ctime = DEG_get_ctime(depsgraph); @@ -1718,7 +1731,7 @@ void BKE_rigidbody_eval_simulation(struct Depsgraph *depsgraph, } } -void BKE_rigidbody_object_sync_transforms(struct Depsgraph *depsgraph, +void BKE_rigidbody_object_sync_transforms(Depsgraph *depsgraph, Scene *scene, Object *ob) { diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 2916e5559c4..7e161a8dd2d 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -110,7 +110,6 @@ #include "bmesh.h" -const char *RE_engine_id_BLENDER_CLAY = "BLENDER_CLAY"; const char *RE_engine_id_BLENDER_EEVEE = "BLENDER_EEVEE"; const char *RE_engine_id_BLENDER_WORKBENCH = "BLENDER_WORKBENCH"; const char *RE_engine_id_CYCLES = "CYCLES"; @@ -450,9 +449,6 @@ void BKE_scene_free_ex(Scene *sce, const bool do_id_user) { BKE_animdata_free((ID *)sce, false); - /* check all sequences */ - BKE_sequencer_clear_scene_in_allseqs(G.main, sce); - BKE_sequencer_editing_free(sce, do_id_user); BKE_keyingsets_free(&sce->keyingsets); @@ -808,15 +804,8 @@ void BKE_scene_init(Scene *sce) copy_v3_v3(sce->display.light_direction, (float[3]){-M_SQRT1_3, -M_SQRT1_3, M_SQRT1_3}); sce->display.shadow_shift = 0.1; - sce->display.matcap_icon = 1; - sce->display.matcap_type = CLAY_MATCAP_NONE; - sce->display.matcap_hue = 0.5f; - sce->display.matcap_saturation = 0.5f; - sce->display.matcap_value = 0.5f; sce->display.matcap_ssao_distance = 0.2f; sce->display.matcap_ssao_attenuation = 1.0f; - sce->display.matcap_ssao_factor_cavity = 1.0f; - sce->display.matcap_ssao_factor_edge = 1.0f; sce->display.matcap_ssao_samples = 16; /* SceneEEVEE */ @@ -954,8 +943,7 @@ Scene *BKE_scene_set_name(Main *bmain, const char *name) } /* Used by metaballs, return *all* objects (including duplis) existing in the scene (including scene's sets) */ -int BKE_scene_base_iter_next( - Depsgraph *depsgraph, SceneBaseIter *iter, +int BKE_scene_base_iter_next(Depsgraph *depsgraph, SceneBaseIter *iter, Scene **scene, int val, Base **base, Object **ob) { bool run_again = true; @@ -1334,7 +1322,7 @@ static void prepare_mesh_for_viewport_render( if (check_rendered_viewport_visible(bmain)) { BMesh *bm = mesh->edit_btmesh->bm; BM_mesh_bm_to_me( - bm, mesh, + bmain, bm, mesh, (&(struct BMeshToMeshParams){ .calc_object_remap = true, })); diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c index 8cff10902ef..2ccb2012a76 100644 --- a/source/blender/blenkernel/intern/screen.c +++ b/source/blender/blenkernel/intern/screen.c @@ -114,7 +114,7 @@ SpaceType *BKE_spacetype_from_id(int spaceid) return NULL; } -ARegionType *BKE_regiontype_from_id(SpaceType *st, int regionid) +ARegionType *BKE_regiontype_from_id_or_first(SpaceType *st, int regionid) { ARegionType *art; @@ -126,6 +126,18 @@ ARegionType *BKE_regiontype_from_id(SpaceType *st, int regionid) return st->regiontypes.first; } +ARegionType *BKE_regiontype_from_id(SpaceType *st, int regionid) +{ + ARegionType *art; + + for (art = st->regiontypes.first; art; art = art->next) { + if (art->regionid == regionid) { + return art; + } + } + return NULL; +} + const ListBase *BKE_spacetypes_list(void) { @@ -221,10 +233,15 @@ ARegion *BKE_area_region_copy(SpaceType *st, ARegion *ar) if (ar->regiondata) { ARegionType *art = BKE_regiontype_from_id(st, ar->regiontype); - if (art && art->duplicate) + if (art && art->duplicate) { newar->regiondata = art->duplicate(ar->regiondata); - else + } + else if (ar->flag & RGN_FLAG_TEMP_REGIONDATA) { + newar->regiondata = NULL; + } + else { newar->regiondata = MEM_dupallocN(ar->regiondata); + } } if (ar->v2d.tab_offset) diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index ecd0335fc4e..7d1bb69c788 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -5724,10 +5724,10 @@ static void sequencer_all_free_anim_ibufs(ListBase *seqbase, int cfra) } } -void BKE_sequencer_all_free_anim_ibufs(int cfra) +void BKE_sequencer_all_free_anim_ibufs(Main *bmain, int cfra) { BKE_sequencer_cache_cleanup(); - for (Scene *scene = G.main->scene.first; + for (Scene *scene = bmain->scene.first; scene != NULL; scene = scene->id.next) { diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c index 922f82a5e2e..738be9ded54 100644 --- a/source/blender/blenkernel/intern/smoke.c +++ b/source/blender/blenkernel/intern/smoke.c @@ -2108,7 +2108,8 @@ BLI_INLINE void apply_inflow_fields(SmokeFlowSettings *sfs, float emission_value } } -static void update_flowsfluids(struct Depsgraph *depsgraph, Scene *scene, Object *ob, SmokeDomainSettings *sds, float dt) +static void update_flowsfluids( + struct Depsgraph *depsgraph, Scene *scene, Object *ob, SmokeDomainSettings *sds, float dt) { Object **flowobjs = NULL; EmissionMap *emaps = NULL; @@ -2562,7 +2563,9 @@ static void update_effectors(struct Depsgraph *depsgraph, Scene *scene, Object * pdEndEffectors(&effectors); } -static void step(struct Depsgraph *depsgraph, Scene *scene, Object *ob, SmokeModifierData *smd, DerivedMesh *domain_dm, float fps) +static void step( + Depsgraph *depsgraph, + Scene *scene, Object *ob, SmokeModifierData *smd, DerivedMesh *domain_dm, float fps) { SmokeDomainSettings *sds = smd->domain; /* stability values copied from wturbulence.cpp */ diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index 9aa6c172a90..fe31222bbba 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -75,6 +75,7 @@ variables on the UI for now #include "BKE_curve.h" #include "BKE_effect.h" #include "BKE_global.h" +#include "BKE_layer.h" #include "BKE_modifier.h" #include "BKE_softbody.h" #include "BKE_pointcache.h" @@ -516,19 +517,17 @@ static void ccd_build_deflector_hash_single(GHash *hash, Object *ob) /** * \note collection overrides scene when not NULL. */ -static void ccd_build_deflector_hash(ViewLayer *view_layer, Collection *collection, Object *vertexowner, GHash *hash) +static void ccd_build_deflector_hash(Depsgraph *depsgraph, Collection *collection, Object *vertexowner, GHash *hash) { - Object *ob; - if (!hash) return; /* Explicit collision collection. */ - Base *base = BKE_collection_or_layer_objects(NULL, NULL, view_layer, collection); + Base *base = BKE_collection_or_layer_objects(depsgraph, NULL, NULL, collection); for (; base; base = base->next) { /* Only proceed for mesh object in same layer. */ if (base->object->type == OB_MESH) { - ob = base->object; + Object *ob = base->object; if (ob == vertexowner) { /* If vertexowner is given we don't want to check collision with owner object. */ continue; @@ -551,19 +550,17 @@ static void ccd_update_deflector_hash_single(GHash *hash, Object *ob) /** * \note collection overrides scene when not NULL. */ -static void ccd_update_deflector_hash(ViewLayer *view_layer, Collection *collection, Object *vertexowner, GHash *hash) +static void ccd_update_deflector_hash(Depsgraph *depsgraph, Collection *collection, Object *vertexowner, GHash *hash) { - Object *ob; - if ((!hash) || (!vertexowner)) return; /* Explicit collision collection. */ - Base *base = BKE_collection_or_layer_objects(NULL, NULL, view_layer, collection); + Base *base = BKE_collection_or_layer_objects(depsgraph, NULL, NULL, collection); for (; base; base = base->next) { /* Only proceed for mesh object in same layer. */ if (base->object->type == OB_MESH) { - ob = base->object; + Object *ob = base->object; if (ob == vertexowner) { /* If vertexowner is given we don't want to check collision with owner object. */ continue; @@ -974,9 +971,9 @@ static bool are_there_deflectors(Base *first_base) return 0; } -static int query_external_colliders(ViewLayer *view_layer, Collection *collection) +static int query_external_colliders(Depsgraph *depsgraph, Collection *collection) { - return(are_there_deflectors(BKE_collection_or_layer_objects(NULL, NULL, view_layer, collection))); + return(are_there_deflectors(BKE_collection_or_layer_objects(depsgraph, NULL, NULL, collection))); } /* --- dependency information functions*/ @@ -2220,7 +2217,7 @@ static void softbody_calc_forcesEx(struct Depsgraph *depsgraph, Scene *scene, Ob /* gravity = sb->grav * sb_grav_force_scale(ob); */ /* UNUSED */ /* check conditions for various options */ - do_deflector= query_external_colliders(DEG_get_evaluated_view_layer(depsgraph), sb->collision_group); + do_deflector= query_external_colliders(depsgraph, sb->collision_group); /* do_selfcollision=((ob->softflag & OB_SB_EDGES) && (sb->bspring)&& (ob->softflag & OB_SB_SELF)); */ /* UNUSED */ do_springcollision=do_deflector && (ob->softflag & OB_SB_EDGES) &&(ob->softflag & OB_SB_EDGECOLL); do_aero=((sb->aeroedge)&& (ob->softflag & OB_SB_EDGES)); @@ -2284,7 +2281,7 @@ static void softbody_calc_forces(struct Depsgraph *depsgraph, Scene *scene, Obje } /* check conditions for various options */ - do_deflector= query_external_colliders(DEG_get_evaluated_view_layer(depsgraph), sb->collision_group); + do_deflector= query_external_colliders(depsgraph, sb->collision_group); do_selfcollision=((ob->softflag & OB_SB_EDGES) && (sb->bspring)&& (ob->softflag & OB_SB_SELF)); do_springcollision=do_deflector && (ob->softflag & OB_SB_EDGES) &&(ob->softflag & OB_SB_EDGECOLL); do_aero=((sb->aeroedge)&& (ob->softflag & OB_SB_EDGES)); @@ -3495,13 +3492,11 @@ static void softbody_step(struct Depsgraph *depsgraph, Scene *scene, Object *ob, */ if (dtime < 0 || dtime > 10.5f) return; - ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph); - - ccd_update_deflector_hash(view_layer, sb->collision_group, ob, sb->scratch->colliderhash); + ccd_update_deflector_hash(depsgraph, sb->collision_group, ob, sb->scratch->colliderhash); if (sb->scratch->needstobuildcollider) { - if (query_external_colliders(view_layer, sb->collision_group)) { - ccd_build_deflector_hash(view_layer, sb->collision_group, ob, sb->scratch->colliderhash); + if (query_external_colliders(depsgraph, sb->collision_group)) { + ccd_build_deflector_hash(depsgraph, sb->collision_group, ob, sb->scratch->colliderhash); } sb->scratch->needstobuildcollider=0; } diff --git a/source/blender/blenkernel/intern/studiolight.c b/source/blender/blenkernel/intern/studiolight.c index e4b49656907..60c25b8976d 100644 --- a/source/blender/blenkernel/intern/studiolight.c +++ b/source/blender/blenkernel/intern/studiolight.c @@ -42,6 +42,7 @@ #include "BLI_path_util.h" #include "BLI_rand.h" #include "BLI_string.h" +#include "BLI_string_utils.h" #include "DNA_listBase.h" @@ -55,8 +56,8 @@ /* Statics */ static ListBase studiolights; -#define STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE 8 -#define STUDIOLIGHT_IRRADIANCE_EQUIRECTANGULAR_HEIGHT 32 +#define STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE 16 +#define STUDIOLIGHT_IRRADIANCE_EQUIRECTANGULAR_HEIGHT 64 #define STUDIOLIGHT_IRRADIANCE_EQUIRECTANGULAR_WIDTH (STUDIOLIGHT_IRRADIANCE_EQUIRECTANGULAR_HEIGHT * 2) static const char *STUDIOLIGHT_CAMERA_FOLDER = "studiolights/camera/"; @@ -71,39 +72,49 @@ static void studiolight_free(struct StudioLight *sl) IMB_freeImBuf(sl->radiance_cubemap_buffers[index]); sl->radiance_cubemap_buffers[index] = NULL; } - - if (sl->equirectangular_radiance_gputexture) { - GPU_texture_free(sl->equirectangular_radiance_gputexture); - sl->equirectangular_radiance_gputexture = NULL; - } - - if (sl->equirectangular_irradiance_gputexture) { - GPU_texture_free(sl->equirectangular_irradiance_gputexture); - sl->equirectangular_irradiance_gputexture = NULL; - } - - if (sl->equirectangular_radiance_buffer) { - IMB_freeImBuf(sl->equirectangular_radiance_buffer); - sl->equirectangular_radiance_buffer = NULL; - } - - if (sl->equirectangular_irradiance_buffer) { - IMB_freeImBuf(sl->equirectangular_irradiance_buffer); - sl->equirectangular_irradiance_buffer = NULL; - } + } + if (sl->equirectangular_radiance_gputexture) { + GPU_texture_free(sl->equirectangular_radiance_gputexture); + sl->equirectangular_radiance_gputexture = NULL; + } + + if (sl->equirectangular_irradiance_gputexture) { + GPU_texture_free(sl->equirectangular_irradiance_gputexture); + sl->equirectangular_irradiance_gputexture = NULL; + } + + if (sl->equirectangular_radiance_buffer) { + IMB_freeImBuf(sl->equirectangular_radiance_buffer); + sl->equirectangular_radiance_buffer = NULL; + } + + if (sl->equirectangular_irradiance_buffer) { + IMB_freeImBuf(sl->equirectangular_irradiance_buffer); + sl->equirectangular_irradiance_buffer = NULL; + } + if (sl->path_irr) { + MEM_freeN(sl->path_irr); + sl->path_irr = NULL; } MEM_freeN(sl); } -static struct StudioLight *studiolight_create(void) +static struct StudioLight *studiolight_create(int flag) { struct StudioLight *sl = MEM_callocN(sizeof(*sl), __func__); sl->path[0] = 0x00; sl->name[0] = 0x00; - sl->flag = 0; + sl->path_irr = NULL; + sl->flag = flag; sl->index = BLI_listbase_count(&studiolights); - sl->radiance_icon_id = BKE_icon_ensure_studio_light(sl, STUDIOLIGHT_ICON_ID_TYPE_RADIANCE); - sl->irradiance_icon_id = BKE_icon_ensure_studio_light(sl, STUDIOLIGHT_ICON_ID_TYPE_IRRADIANCE); + if (flag & STUDIOLIGHT_ORIENTATION_VIEWNORMAL) { + sl->icon_id_matcap = BKE_icon_ensure_studio_light(sl, STUDIOLIGHT_ICON_ID_TYPE_MATCAP); + sl->icon_id_matcap_flipped = BKE_icon_ensure_studio_light(sl, STUDIOLIGHT_ICON_ID_TYPE_MATCAP_FLIPPED); + } + else { + sl->icon_id_radiance = BKE_icon_ensure_studio_light(sl, STUDIOLIGHT_ICON_ID_TYPE_RADIANCE); + sl->icon_id_irradiance = BKE_icon_ensure_studio_light(sl, STUDIOLIGHT_ICON_ID_TYPE_IRRADIANCE); + } for (int index = 0 ; index < 6 ; index ++) { sl->radiance_cubemap_buffers[index] = NULL; @@ -177,7 +188,7 @@ static void studiolight_create_equierectangular_radiance_gputexture(StudioLight char error[256]; BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_EXTERNAL_IMAGE_LOADED); ImBuf *ibuf = sl->equirectangular_radiance_buffer; - sl->equirectangular_radiance_gputexture = GPU_texture_create_2D(ibuf->x, ibuf->y, GPU_RGBA8, ibuf->rect_float, error); + sl->equirectangular_radiance_gputexture = GPU_texture_create_2D(ibuf->x, ibuf->y, GPU_RGBA16F, ibuf->rect_float, error); GPUTexture *tex = sl->equirectangular_radiance_gputexture; GPU_texture_bind(tex, 0); GPU_texture_filter_mode(tex, true); @@ -342,8 +353,30 @@ static void studiolight_calculate_diffuse_light(StudioLight *sl) sl->flag |= STUDIOLIGHT_DIFFUSE_LIGHT_CALCULATED; } +static float area_element(float x, float y ) +{ + return atan2f(x * y, sqrt(x * x + y * y + 1)); +} + +static float texel_coord_solid_angle(float a_U, float a_V, int a_Size) +{ + //scale up to [-1, 1] range (inclusive), offset by 0.5 to point to texel center. + float u = (2.0f * ((float)a_U + 0.5f) / (float)a_Size ) - 1.0f; + float v = (2.0f * ((float)a_V + 0.5f) / (float)a_Size ) - 1.0f; + + float resolution_inv = 1.0f / a_Size; + + // U and V are the -1..1 texture coordinate on the current face. + // Get projected area for this texel + float x0 = u - resolution_inv; + float y0 = v - resolution_inv; + float x1 = u + resolution_inv; + float y1 = v + resolution_inv; + return area_element(x0, y0) - area_element(x0, y1) - area_element(x1, y0) + area_element(x1, y1); +} + BLI_INLINE void studiolight_evaluate_specular_radiance_buffer( - ImBuf *radiance_buffer, const float specular, const float normal[3], float color[3], int *hits, + ImBuf *radiance_buffer, const float normal[3], float color[3], int xoffset, int yoffset, int zoffset, float zvalue) { if (radiance_buffer == NULL) { @@ -355,13 +388,14 @@ BLI_INLINE void studiolight_evaluate_specular_radiance_buffer( for (int y = 0; y < STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE; y ++) { for (int x = 0; x < STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE; x ++) { // calculate light direction; + float u = (x / (float)STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE) - 0.5f; + float v = (y / (float)STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE) - 0.5f; direction[zoffset] = zvalue; - direction[xoffset] = (x / (float)STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE) - 0.5f; - direction[yoffset] = (y / (float)STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE) - 0.5f; + direction[xoffset] = u; + direction[yoffset] = v; normalize_v3(direction); - angle = pow(fmax(0.0f, dot_v3v3(direction, normal)), specular); + angle = fmax(0.0f, dot_v3v3(direction, normal)) * texel_coord_solid_angle(x, y, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE); madd_v3_v3fl(color, radiance_color, angle); - (*hits) ++; radiance_color += 4; } } @@ -370,42 +404,54 @@ BLI_INLINE void studiolight_evaluate_specular_radiance_buffer( static void studiolight_calculate_specular_irradiance(StudioLight *sl, float color[3], const float normal[3]) { - const float specular = 4.0f; - int hits = 0; copy_v3_fl(color, 0.0f); /* back */ studiolight_evaluate_specular_radiance_buffer( - sl->radiance_cubemap_buffers[STUDIOLIGHT_Y_POS], specular, normal, color, &hits, 0, 2, 1, 0.5); + sl->radiance_cubemap_buffers[STUDIOLIGHT_Y_POS], normal, color, 0, 2, 1, 0.5); /* front */ studiolight_evaluate_specular_radiance_buffer( - sl->radiance_cubemap_buffers[STUDIOLIGHT_Y_NEG], specular, normal, color, &hits, 0, 2, 1, -0.5); + sl->radiance_cubemap_buffers[STUDIOLIGHT_Y_NEG], normal, color, 0, 2, 1, -0.5); /* left */ studiolight_evaluate_specular_radiance_buffer( - sl->radiance_cubemap_buffers[STUDIOLIGHT_X_POS], specular, normal, color, &hits, 1, 2, 0, 0.5); + sl->radiance_cubemap_buffers[STUDIOLIGHT_X_POS], normal, color, 1, 2, 0, 0.5); /* right */ studiolight_evaluate_specular_radiance_buffer( - sl->radiance_cubemap_buffers[STUDIOLIGHT_X_NEG], specular, normal, color, &hits, 1, 2, 0, -0.5); + sl->radiance_cubemap_buffers[STUDIOLIGHT_X_NEG], normal, color, 1, 2, 0, -0.5); /* top */ studiolight_evaluate_specular_radiance_buffer( - sl->radiance_cubemap_buffers[STUDIOLIGHT_Z_POS], specular, normal, color, &hits, 0, 1, 2, 0.5); + sl->radiance_cubemap_buffers[STUDIOLIGHT_Z_POS], normal, color, 0, 1, 2, 0.5); /* bottom */ studiolight_evaluate_specular_radiance_buffer( - sl->radiance_cubemap_buffers[STUDIOLIGHT_Z_NEG], specular, normal, color, &hits, 0, 1, 2, -0.5); + sl->radiance_cubemap_buffers[STUDIOLIGHT_Z_NEG], normal, color, 0, 1, 2, -0.5); - if (hits) { - mul_v3_fl(color, specular / hits); - } - else { - copy_v3_fl3(color, 1.0, 0.0, 1.0); + mul_v3_fl(color, 1.0 / M_PI); +} + +static bool studiolight_load_irradiance_equirectangular_image(StudioLight *sl) +{ +#if 1 + if (sl->flag & STUDIOLIGHT_EXTERNAL_FILE) { + ImBuf *ibuf = NULL; + ibuf = IMB_loadiffname(sl->path_irr, 0, NULL); + if (ibuf) { + IMB_float_from_rect(ibuf); + sl->equirectangular_irradiance_buffer = ibuf; + sl->flag |= STUDIOLIGHT_EQUIRECTANGULAR_IRRADIANCE_IMAGE_CALCULATED; + return true; + } } +#endif + return false; } static void studiolight_calculate_irradiance_equirectangular_image(StudioLight *sl) { if (sl->flag & STUDIOLIGHT_EXTERNAL_FILE) { + /* check for cached irr file */ + BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_RADIANCE_BUFFERS_CALCULATED); float *colbuf = MEM_mallocN(STUDIOLIGHT_IRRADIANCE_EQUIRECTANGULAR_WIDTH * STUDIOLIGHT_IRRADIANCE_EQUIRECTANGULAR_HEIGHT * sizeof(float[4]), __func__); @@ -427,10 +473,10 @@ static void studiolight_calculate_irradiance_equirectangular_image(StudioLight * STUDIOLIGHT_IRRADIANCE_EQUIRECTANGULAR_WIDTH, STUDIOLIGHT_IRRADIANCE_EQUIRECTANGULAR_HEIGHT); MEM_freeN(colbuf); -#if 0 - IMB_saveiff(sl->equirectangular_irradiance_buffer, "/tmp/studiolight_specular_irradiance.png", IB_rectfloat); -#endif + if (sl->flag | STUDIOLIGHT_USER_DEFINED) { + IMB_saveiff(sl->equirectangular_irradiance_buffer, sl->path_irr, IB_rectfloat); + } } sl->flag |= STUDIOLIGHT_EQUIRECTANGULAR_IRRADIANCE_IMAGE_CALCULATED; } @@ -482,10 +528,10 @@ static void studiolight_add_files_from_datafolder(const int folder_id, const cha const char *filename = dir[i].relname; const char *path = dir[i].path; if (BLI_testextensie_array(filename, imb_ext_image)) { - sl = studiolight_create(); - sl->flag = STUDIOLIGHT_EXTERNAL_FILE | flag; + sl = studiolight_create(STUDIOLIGHT_EXTERNAL_FILE | flag); BLI_strncpy(sl->name, filename, FILE_MAXFILE); BLI_strncpy(sl->path, path, FILE_MAXFILE); + sl->path_irr = BLI_string_joinN(path, ".irr"); BLI_addtail(&studiolights, sl); } } @@ -579,7 +625,7 @@ static uint *studiolight_radiance_preview(StudioLight *sl, int icon_size) return rect; } -static uint *studiolight_matcap_preview(StudioLight *sl, int icon_size) +static uint *studiolight_matcap_preview(StudioLight *sl, int icon_size, bool flipped) { BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_EXTERNAL_IMAGE_LOADED); @@ -589,14 +635,21 @@ static uint *studiolight_matcap_preview(StudioLight *sl, int icon_size) float fx, fy; int offset = 0; ImBuf *ibuf = sl->equirectangular_radiance_buffer; + for (int y = 0; y < icon_size; y++) { + fy = y * ibuf->y / icon_size; for (int x = 0; x < icon_size; x++) { - fx = x * ibuf->x / icon_size; - fy = y * ibuf->y / icon_size; + if (flipped) { + fx = ibuf->x - (x * ibuf->x / icon_size) - 1; + } + else { + fx = x * ibuf->x / icon_size; + } nearest_interpolation_color(ibuf, NULL, color, fx, fy); - rect[offset++] = rgb_to_cpack(linearrgb_to_srgb(color[0]), - linearrgb_to_srgb(color[1]), - linearrgb_to_srgb(color[2])) | alphamask; + rect[offset++] = rgb_to_cpack( + linearrgb_to_srgb(color[0]), + linearrgb_to_srgb(color[1]), + linearrgb_to_srgb(color[2])) | alphamask; } } return rect; @@ -604,7 +657,10 @@ static uint *studiolight_matcap_preview(StudioLight *sl, int icon_size) static uint *studiolight_irradiance_preview(StudioLight *sl, int icon_size) { - if (/*!(sl->flag & STUDIOLIGHT_EXTERNAL_FILE)*/ 1) { +#if 0 + if (!(sl->flag & STUDIOLIGHT_EXTERNAL_FILE)) +#endif + { BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_DIFFUSE_LIGHT_CALCULATED); @@ -655,6 +711,7 @@ static uint *studiolight_irradiance_preview(StudioLight *sl, int icon_size) } return rect; } +#if 0 else { BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_EQUIRECTANGULAR_IRRADIANCE_IMAGE_CALCULATED); @@ -707,6 +764,7 @@ static uint *studiolight_irradiance_preview(StudioLight *sl, int icon_size) } return rect; } +#endif } /* API */ @@ -717,15 +775,14 @@ void BKE_studiolight_init(void) /* order studio lights by name */ /* Also reserve icon space for it. */ /* Add default studio light */ - sl = studiolight_create(); + sl = studiolight_create(STUDIOLIGHT_INTERNAL | STUDIOLIGHT_DIFFUSE_LIGHT_CALCULATED | STUDIOLIGHT_ORIENTATION_CAMERA); BLI_strncpy(sl->name, "INTERNAL_01", FILE_MAXFILE); - sl->flag = STUDIOLIGHT_INTERNAL | STUDIOLIGHT_DIFFUSE_LIGHT_CALCULATED | STUDIOLIGHT_ORIENTATION_CAMERA; - copy_v3_fl(sl->diffuse_light[STUDIOLIGHT_X_POS], 0.0f); + copy_v3_fl(sl->diffuse_light[STUDIOLIGHT_X_POS], 1.5f); copy_v3_fl(sl->diffuse_light[STUDIOLIGHT_X_NEG], 0.0f); copy_v3_fl(sl->diffuse_light[STUDIOLIGHT_Y_POS], 0.8f); copy_v3_fl(sl->diffuse_light[STUDIOLIGHT_Y_NEG], 0.05f); copy_v3_fl(sl->diffuse_light[STUDIOLIGHT_Z_POS], 0.2f); - copy_v3_fl(sl->diffuse_light[STUDIOLIGHT_Z_NEG], 0.1f); + copy_v3_fl3(sl->diffuse_light[STUDIOLIGHT_Z_NEG], 0.1f, 0.0f, 0.0f); BLI_addtail(&studiolights, sl); studiolight_add_files_from_datafolder(BLENDER_SYSTEM_DATAFILES, STUDIOLIGHT_CAMERA_FOLDER, STUDIOLIGHT_ORIENTATION_CAMERA); @@ -792,16 +849,16 @@ struct ListBase *BKE_studiolight_listbase(void) uint *BKE_studiolight_preview(StudioLight *sl, int icon_size, int icon_id_type) { - if (icon_id_type == STUDIOLIGHT_ICON_ID_TYPE_IRRADIANCE) { - if (sl->flag & STUDIOLIGHT_ORIENTATION_VIEWNORMAL) { - return studiolight_matcap_preview(sl, icon_size); - } - else { + switch (icon_id_type) { + case STUDIOLIGHT_ICON_ID_TYPE_RADIANCE: + default: + return studiolight_radiance_preview(sl, icon_size); + case STUDIOLIGHT_ICON_ID_TYPE_IRRADIANCE: return studiolight_irradiance_preview(sl, icon_size); - } - } - else { - return studiolight_radiance_preview(sl, icon_size); + case STUDIOLIGHT_ICON_ID_TYPE_MATCAP: + return studiolight_matcap_preview(sl, icon_size, false); + case STUDIOLIGHT_ICON_ID_TYPE_MATCAP_FLIPPED: + return studiolight_matcap_preview(sl, icon_size, true); } } @@ -830,7 +887,9 @@ void BKE_studiolight_ensure_flag(StudioLight *sl, int flag) studiolight_create_equierectangular_irradiance_gputexture(sl); } if ((flag & STUDIOLIGHT_EQUIRECTANGULAR_IRRADIANCE_IMAGE_CALCULATED)) { - studiolight_calculate_irradiance_equirectangular_image(sl); + if (!studiolight_load_irradiance_equirectangular_image(sl)) { + studiolight_calculate_irradiance_equirectangular_image(sl); + } } } diff --git a/source/blender/blenkernel/intern/suggestions.c b/source/blender/blenkernel/intern/suggestions.c index eb17e103671..b74143b5c07 100644 --- a/source/blender/blenkernel/intern/suggestions.c +++ b/source/blender/blenkernel/intern/suggestions.c @@ -246,12 +246,12 @@ void texttool_docs_show(const char *docs) /* Ensure documentation ends with a '\n' */ if (docs[len - 1] != '\n') { documentation = MEM_mallocN(len + 2, "Documentation"); - strncpy(documentation, docs, len); + BLI_strncpy(documentation, docs, len); documentation[len++] = '\n'; } else { documentation = MEM_mallocN(len + 1, "Documentation"); - strncpy(documentation, docs, len); + BLI_strncpy(documentation, docs, len); } documentation[len] = '\0'; } diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c index a24020d7764..226ab33e45e 100644 --- a/source/blender/blenkernel/intern/text.c +++ b/source/blender/blenkernel/intern/text.c @@ -1702,7 +1702,7 @@ static void txt_undo_add_blockop(Text *text, TextUndoBuf *utxt, int op, const ch /* 4 bytes */ txt_undo_store_uint32(utxt->buf, &utxt->pos, length); /* 'length' bytes */ - strncpy(utxt->buf + utxt->pos, buf, length); + BLI_strncpy(utxt->buf + utxt->pos, buf, length); utxt->pos += length; /* 4 bytes */ txt_undo_store_uint32(utxt->buf, &utxt->pos, length); diff --git a/source/blender/blenkernel/intern/undo_system.c b/source/blender/blenkernel/intern/undo_system.c index a05e79aae1f..173b459f442 100644 --- a/source/blender/blenkernel/intern/undo_system.c +++ b/source/blender/blenkernel/intern/undo_system.c @@ -235,6 +235,23 @@ void BKE_undosys_stack_clear(UndoStack *ustack) ustack->step_active = NULL; } +void BKE_undosys_stack_clear_active(UndoStack *ustack) +{ + /* Remove active and all following undos. */ + UndoStep *us = ustack->step_active; + + if (us) { + ustack->step_active = us->prev; + bool is_not_empty = ustack->step_active != NULL; + + while (ustack->steps.last != ustack->step_active) { + UndoStep *us_iter = ustack->steps.last; + undosys_step_free_and_unlink(ustack, us_iter); + undosys_stack_validate(ustack, is_not_empty); + } + } +} + static bool undosys_stack_push_main(UndoStack *ustack, const char *name, struct Main *bmain) { UNDO_NESTED_ASSERT(false); diff --git a/source/blender/blenlib/BLI_rand.h b/source/blender/blenlib/BLI_rand.h index 69b23b2473f..811a6ba1768 100644 --- a/source/blender/blenlib/BLI_rand.h +++ b/source/blender/blenlib/BLI_rand.h @@ -64,15 +64,9 @@ void BLI_rng_shuffle_array(struct RNG *rng, void *data, unsigned int elem /** Note that skipping is as slow as generating n numbers! */ void BLI_rng_skip(struct RNG *rng, int n) ATTR_NONNULL(1); -/** Seed for the random number generator, using noise.c hash[] */ -void BLI_srandom(unsigned int seed); - -/** Return a pseudo-random number N where 0<=N<(2^31) */ -int BLI_rand(void) ATTR_WARN_UNUSED_RESULT; - /** Return a pseudo-random number N where 0.0f<=N<1.0f */ +/* !!!!! NOTE: DO NOT USE IT IN NEW CODE !!!!! */ float BLI_frand(void) ATTR_WARN_UNUSED_RESULT; -void BLI_frand_unit_v3(float v[3]); /** Return a pseudo-random (hash) float from an integer value */ float BLI_hash_frand(unsigned int seed) ATTR_WARN_UNUSED_RESULT; diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c index 0533126fe56..a3651de73a2 100644 --- a/source/blender/blenlib/intern/path_util.c +++ b/source/blender/blenlib/intern/path_util.c @@ -83,7 +83,7 @@ static bool BLI_path_is_abs(const char *name); * \param tail Optional area to return copy of part of string following digits, or from dot if no digits. * \param numlen Optional to return number of digits found. */ -int BLI_stringdec(const char *string, char *head, char *tail, unsigned short *numlen) +int BLI_stringdec(const char *string, char *head, char *tail, ushort *r_num_len) { uint nums = 0, nume = 0; int i; @@ -93,8 +93,12 @@ int BLI_stringdec(const char *string, char *head, char *tail, unsigned short *nu const uint lslash_len = lslash != NULL ? (int)(lslash - string) : 0; uint name_end = string_len; - while (name_end > lslash_len && string[--name_end] != '.') {} /* name ends at dot if present */ - if (name_end == lslash_len && string[name_end] != '.') name_end = string_len; + while (name_end > lslash_len && string[--name_end] != '.') { + /* name ends at dot if present */ + } + if (name_end == lslash_len && string[name_end] != '.') { + name_end = string_len; + } for (i = name_end - 1; i >= (int)lslash_len; i--) { if (isdigit(string[i])) { @@ -113,25 +117,35 @@ int BLI_stringdec(const char *string, char *head, char *tail, unsigned short *nu } if (found_digit) { - if (tail) strcpy(tail, &string[nume + 1]); - if (head) { - strcpy(head, string); - head[nums] = 0; + const long long int ret = strtoll(&(string[nums]), NULL, 10); + if (ret >= INT_MIN && ret <= INT_MAX) { + if (tail) { + strcpy(tail, &string[nume + 1]); + } + if (head) { + strcpy(head, string); + head[nums] = 0; + } + if (r_num_len) { + *r_num_len = nume - nums + 1; + } + return (int)ret; } - if (numlen) *numlen = nume - nums + 1; - return ((int)atoi(&(string[nums]))); } - else { - if (tail) strcpy(tail, string + name_end); - if (head) { - /* name_end points to last character of head, - * make it +1 so null-terminator is nicely placed - */ - BLI_strncpy(head, string, name_end + 1); - } - if (numlen) *numlen = 0; - return 0; + + if (tail) { + strcpy(tail, string + name_end); + } + if (head) { + /* name_end points to last character of head, + * make it +1 so null-terminator is nicely placed + */ + BLI_strncpy(head, string, name_end + 1); + } + if (r_num_len) { + *r_num_len = 0; } + return 0; } diff --git a/source/blender/blenlib/intern/rand.c b/source/blender/blenlib/intern/rand.c index 700524965f0..557f0d79270 100644 --- a/source/blender/blenlib/intern/rand.c +++ b/source/blender/blenlib/intern/rand.c @@ -268,26 +268,23 @@ void BLI_rng_skip(RNG *rng, int n) /* initialize with some non-zero seed */ static RNG theBLI_rng = {611330372042337130}; -void BLI_srandom(unsigned int seed) +static void ensure_rng_thread_safe(void) { - BLI_rng_srandom(&theBLI_rng, seed); -} - -int BLI_rand(void) -{ - return BLI_rng_get_int(&theBLI_rng); + /* TODO(sergey): Ideally we will get rid of all rng functions which + * are using global generator. But for until then we need some way to + * catch "bad" calls at runtime. + * + * NOTE: Lots of areas are not ported, so we keep check disabled for now. + */ + // BLI_assert(BLI_thread_is_main()); } float BLI_frand(void) { + ensure_rng_thread_safe(); return BLI_rng_get_float(&theBLI_rng); } -void BLI_frand_unit_v3(float v[3]) -{ - BLI_rng_get_float_unit_v3(&theBLI_rng, v); -} - float BLI_hash_frand(unsigned int seed) { RNG rng; diff --git a/source/blender/blenloader/CMakeLists.txt b/source/blender/blenloader/CMakeLists.txt index f42336a2c7a..c59232e7887 100644 --- a/source/blender/blenloader/CMakeLists.txt +++ b/source/blender/blenloader/CMakeLists.txt @@ -82,10 +82,6 @@ if(WITH_INTERNATIONAL) add_definitions(-DWITH_INTERNATIONAL) endif() -if(WITH_CLAY_ENGINE) - add_definitions(-DWITH_CLAY_ENGINE) -endif() - if(WITH_CODEC_FFMPEG) add_definitions(-DWITH_FFMPEG) endif() diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 87dda371b88..a6ca3b43099 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -1647,9 +1647,9 @@ void blo_make_image_pointer_map(FileData *fd, Main *oldmain) oldnewmap_insert(fd->imamap, ima->gputexture[a], ima->gputexture[a], 0); if (ima->rr) oldnewmap_insert(fd->imamap, ima->rr, ima->rr, 0); - for (a=0; a < IMA_MAX_RENDER_SLOT; a++) - if (ima->renders[a]) - oldnewmap_insert(fd->imamap, ima->renders[a], ima->renders[a], 0); + LISTBASE_FOREACH(RenderSlot *, slot, &ima->renderslots) + if (slot->render) + oldnewmap_insert(fd->imamap, slot->render, slot->render, 0); } for (; sce; sce = sce->id.next) { if (sce->nodetree && sce->nodetree->previews) { @@ -1682,13 +1682,12 @@ void blo_end_image_pointer_map(FileData *fd, Main *oldmain) if (ima->cache == NULL) { ima->tpageflag &= ~IMA_GLBIND_IS_DATA; for (i = 0; i < TEXTARGET_COUNT; i++) { - ima->bindcode[i] = 0; ima->gputexture[i] = NULL; } ima->rr = NULL; } - for (i = 0; i < IMA_MAX_RENDER_SLOT; i++) - ima->renders[i] = newimaadr(fd, ima->renders[i]); + LISTBASE_FOREACH(RenderSlot *, slot, &ima->renderslots) + slot->render = newimaadr(fd, slot->render); for (i = 0; i < TEXTARGET_COUNT; i++) ima->gputexture[i] = newimaadr(fd, ima->gputexture[i]); @@ -3917,21 +3916,22 @@ static void direct_link_image(FileData *fd, Image *ima) if (!ima->cache) { ima->tpageflag &= ~IMA_GLBIND_IS_DATA; for (int i = 0; i < TEXTARGET_COUNT; i++) { - ima->bindcode[i] = 0; ima->gputexture[i] = NULL; } ima->rr = NULL; } /* undo system, try to restore render buffers */ + link_list(fd, &(ima->renderslots)); if (fd->imamap) { int a; - for (a = 0; a < IMA_MAX_RENDER_SLOT; a++) - ima->renders[a] = newimaadr(fd, ima->renders[a]); + LISTBASE_FOREACH(RenderSlot *, slot, &ima->renderslots) + slot->render = newimaadr(fd, slot->render); } else { - memset(ima->renders, 0, sizeof(ima->renders)); + LISTBASE_FOREACH(RenderSlot *, slot, &ima->renderslots) + slot->render = NULL; ima->last_render_slot = ima->render_slot; } @@ -4534,12 +4534,12 @@ static void lib_link_mesh(FileData *fd, Main *main) if (me->totface && !me->totpoly) { /* temporarily switch main so that reading from * external CustomData works */ - Main *gmain = G.main; - G.main = main; + Main *gmain = G_MAIN; + G_MAIN = main; BKE_mesh_do_versions_convert_mfaces_to_mpolys(me); - G.main = gmain; + G_MAIN = gmain; } /* @@ -6463,6 +6463,10 @@ static void direct_link_region(FileData *fd, ARegion *ar, int spacetype) /* unkown space type, don't leak regiondata */ ar->regiondata = NULL; } + else if (ar->flag & RGN_FLAG_TEMP_REGIONDATA) { + /* Runtime data, don't use. */ + ar->regiondata = NULL; + } else { ar->regiondata = newdataadr(fd, ar->regiondata); if (ar->regiondata) { @@ -7245,11 +7249,12 @@ static void lib_link_workspace_layout_restore(struct IDNameLib_Map *id_map, Main /* free render engines for now */ for (ar = sa->regionbase.first; ar; ar = ar->next) { - RegionView3D *rv3d= ar->regiondata; - - if (rv3d && rv3d->render_engine) { - RE_engine_free(rv3d->render_engine); - rv3d->render_engine = NULL; + if (ar->regiontype == RGN_TYPE_WINDOW) { + RegionView3D *rv3d = ar->regiondata; + if (rv3d && rv3d->render_engine) { + RE_engine_free(rv3d->render_engine); + rv3d->render_engine = NULL; + } } } } @@ -8863,6 +8868,7 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath) /* Now that all our data-blocks are loaded, we can re-generate overrides from their references. */ if (fd->memfile == NULL) { /* Do not apply in undo case! */ + lib_verify_nodetree(bfd->main, true); /* Needed to ensure we have typeinfo in nodes... */ BKE_main_override_static_update(bfd->main); BKE_collections_after_lib_link(bfd->main); } @@ -10031,13 +10037,15 @@ static void add_loose_objects_to_scene( if ((ob->id.tag & LIB_TAG_INDIRECT) && (ob->id.tag & LIB_TAG_PRE_EXISTING) == 0) { bool do_it = false; - if (ob->id.us == 0) { - do_it = true; - } - else if (!is_link && (ob->id.lib == lib) && (object_in_any_scene(bmain, ob) == 0)) { - /* When appending, make sure any indirectly loaded objects get a base, else they cant be accessed at all - * (see T27437). */ - do_it = true; + if (!is_link) { + if (ob->id.us == 0) { + do_it = true; + } + else if ((ob->id.lib == lib) && (object_in_any_scene(bmain, ob) == 0)) { + /* When appending, make sure any indirectly loaded objects get a base, else they cant be accessed at all + * (see T27437). */ + do_it = true; + } } if (do_it) { @@ -10365,7 +10373,7 @@ static Main *library_link_begin(Main *mainvar, FileData **fd, const char *filepa /** * Initialize the BlendHandle for linking library data. * - * \param mainvar The current main database, e.g. G.main or CTX_data_main(C). + * \param mainvar The current main database, e.g. G_MAIN or CTX_data_main(C). * \param bh A blender file handle as returned by \a BLO_blendhandle_from_file or \a BLO_blendhandle_from_memory. * \param filepath Used for relative linking, copied to the \a lib->name. * \return the library Main, to be passed to \a BLO_library_append_named_part as \a mainl. diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c index eb165efb4f9..a5d2ced6858 100644 --- a/source/blender/blenloader/intern/versioning_280.c +++ b/source/blender/blenloader/intern/versioning_280.c @@ -60,6 +60,7 @@ #include "BKE_customdata.h" #include "BKE_freestyle.h" #include "BKE_idprop.h" +#include "BKE_image.h" #include "BKE_layer.h" #include "BKE_main.h" #include "BKE_mesh.h" @@ -1444,15 +1445,8 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain) if (!MAIN_VERSION_ATLEAST(bmain, 280, 15)) { for (Scene *scene = bmain->scene.first; scene; scene = scene->id.next) { - scene->display.matcap_icon = 1; - scene->display.matcap_type = CLAY_MATCAP_NONE; - scene->display.matcap_hue = 0.5f; - scene->display.matcap_saturation = 0.5f; - scene->display.matcap_value = 0.5f; scene->display.matcap_ssao_distance = 0.2f; scene->display.matcap_ssao_attenuation = 1.0f; - scene->display.matcap_ssao_factor_cavity = 1.0f; - scene->display.matcap_ssao_factor_edge = 1.0f; scene->display.matcap_ssao_samples = 16; } @@ -1593,5 +1587,16 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain) } } } + if (!DNA_struct_elem_find(fd->filesdna, "Image", "ListBase", "renderslot")) { + for (Image *ima = bmain->image.first; ima; ima = ima->id.next) { + if (ima->type == IMA_TYPE_R_RESULT) { + for (int i = 0; i < 8; i++) { + RenderSlot *slot = MEM_callocN(sizeof(RenderSlot), "Image Render Slot Init"); + BLI_snprintf(slot->name, sizeof(slot->name), "Slot %d", i+1); + BLI_addtail(&ima->renderslots, slot); + } + } + } + } } } diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index ddb0a39dc9a..c2fb51f9bec 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -2712,6 +2712,10 @@ static void write_region(WriteData *wd, ARegion *ar, int spacetype) writestruct(wd, DATA, ARegion, 1, ar); if (ar->regiondata) { + if (ar->flag & RGN_FLAG_TEMP_REGIONDATA) { + return; + } + switch (spacetype) { case SPACE_VIEW3D: if (ar->regiontype == RGN_TYPE_WINDOW) { @@ -4116,7 +4120,7 @@ bool BLO_write_file( if (G.relbase_valid) { /* blend may not have been saved before. Tn this case * we should not have any relative paths, but if there - * is somehow, an invalid or empty G.main->name it will + * is somehow, an invalid or empty G_MAIN->name it will * print an error, don't try make the absolute in this case. */ BKE_bpath_absolute_convert(mainvar, BKE_main_blendfile_path_from_global(), NULL); } @@ -4124,7 +4128,7 @@ bool BLO_write_file( } if (write_flags & G_FILE_RELATIVE_REMAP) { - /* note, making relative to something OTHER then G.main->name */ + /* note, making relative to something OTHER then G_MAIN->name */ BKE_bpath_relative_convert(mainvar, filepath, NULL); } diff --git a/source/blender/bmesh/intern/bmesh_mesh_conv.c b/source/blender/bmesh/intern/bmesh_mesh_conv.c index 5ba3f149689..00bb0110e74 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_conv.c +++ b/source/blender/bmesh/intern/bmesh_mesh_conv.c @@ -548,8 +548,12 @@ BLI_INLINE void bmesh_quick_edgedraw_flag(MEdge *med, BMEdge *e) } } +/** + * + * \param bmain May be NULL in case \a calc_object_remap parameter option is set. + */ void BM_mesh_bm_to_me( - BMesh *bm, Mesh *me, + Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMeshParams *params) { MLoop *mloop; @@ -710,11 +714,12 @@ void BM_mesh_bm_to_me( /* patch hook indices and vertex parents */ if (params->calc_object_remap && (ototvert > 0)) { + BLI_assert(bmain != NULL); Object *ob; ModifierData *md; BMVert **vertMap = NULL; - for (ob = G.main->object.first; ob; ob = ob->id.next) { + for (ob = bmain->object.first; ob; ob = ob->id.next) { if ((ob->parent) && (ob->parent->data == me) && ELEM(ob->partype, PARVERT1, PARVERT3)) { if (vertMap == NULL) { diff --git a/source/blender/bmesh/intern/bmesh_mesh_conv.h b/source/blender/bmesh/intern/bmesh_mesh_conv.h index 6e9d62349ea..008960e7f6e 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_conv.h +++ b/source/blender/bmesh/intern/bmesh_mesh_conv.h @@ -32,6 +32,7 @@ * \ingroup bmesh */ +struct Main; struct Mesh; void BM_mesh_cd_validate(BMesh *bm); @@ -60,8 +61,8 @@ struct BMeshToMeshParams { int64_t cd_mask_extra; }; void BM_mesh_bm_to_me( - BMesh *bm, struct Mesh *me, + struct Main *bmain, BMesh *bm, struct Mesh *me, const struct BMeshToMeshParams *params) -ATTR_NONNULL(1, 2, 3); +ATTR_NONNULL(2, 3, 4); #endif /* __BMESH_MESH_CONV_H__ */ diff --git a/source/blender/bmesh/operators/bmo_mesh_conv.c b/source/blender/bmesh/operators/bmo_mesh_conv.c index 7311ed5ce64..cc1f45baf0c 100644 --- a/source/blender/bmesh/operators/bmo_mesh_conv.c +++ b/source/blender/bmesh/operators/bmo_mesh_conv.c @@ -38,6 +38,7 @@ #include "bmesh.h" #include "intern/bmesh_operators_private.h" +#include "BKE_global.h" void bmo_mesh_to_bmesh_exec(BMesh *bm, BMOperator *op) { @@ -72,7 +73,7 @@ void bmo_bmesh_to_mesh_exec(BMesh *bm, BMOperator *op) /* Object *ob = BMO_slot_ptr_get(op, "object"); */ BM_mesh_bm_to_me( - bm, me, + G.main, bm, me, (&(struct BMeshToMeshParams){ .calc_object_remap = true, })); diff --git a/source/blender/collada/AnimationExporter.cpp b/source/blender/collada/AnimationExporter.cpp index 95298986f5a..ab53e282476 100644 --- a/source/blender/collada/AnimationExporter.cpp +++ b/source/blender/collada/AnimationExporter.cpp @@ -34,9 +34,10 @@ void forEachObjectInExportSet(Scene *sce, Functor &f, LinkNode *export_set) } } -bool AnimationExporter::exportAnimations(Scene *sce) +bool AnimationExporter::exportAnimations(Main *bmain, Scene *sce) { bool has_animations = hasAnimations(sce); + m_bmain = bmain; if (has_animations) { this->scene = sce; @@ -214,7 +215,7 @@ void AnimationExporter::export_sampled_matrix_animation(Object *ob, std::vector< for (std::vector<float>::iterator ctime = ctimes.begin(); ctime != ctimes.end(); ++ctime) { float fmat[4][4]; - bc_update_scene(depsgraph, scene, *ctime); + bc_update_scene(m_bmain, depsgraph, scene, *ctime); BKE_object_matrix_local_get(ob, fmat); if (this->export_settings->limit_precision) bc_sanitize_mat(fmat, 6); @@ -246,7 +247,7 @@ void AnimationExporter::export_sampled_transrotloc_animation(Object *ob, std::ve float fsize[3]; float feul[3]; - bc_update_scene(depsgraph, scene, *ctime); + bc_update_scene(m_bmain, depsgraph, scene, *ctime); BKE_object_matrix_local_get(ob, fmat); mat4_decompose(floc, fquat, fsize, fmat); quat_to_eul(feul, fquat); @@ -1315,7 +1316,7 @@ std::string AnimationExporter::create_4x4_source(std::vector<float> &frames, Obj float frame = *it; float ctime = BKE_scene_frame_get_from_ctime(scene, frame); - bc_update_scene(depsgraph, scene, ctime); + bc_update_scene(m_bmain, depsgraph, scene, ctime); if (is_bone_animation) { if (pchan->flag & POSE_CHAIN) { diff --git a/source/blender/collada/AnimationExporter.h b/source/blender/collada/AnimationExporter.h index a50bcaf0ef4..67468458f81 100644 --- a/source/blender/collada/AnimationExporter.h +++ b/source/blender/collada/AnimationExporter.h @@ -84,6 +84,7 @@ struct Depsgraph; class AnimationExporter: COLLADASW::LibraryAnimations { private: + Main *m_bmain; Scene *scene; Depsgraph *depsgraph; COLLADASW::StreamWriter *sw; @@ -98,7 +99,8 @@ public: this->sw = sw; } - bool exportAnimations(Scene *sce); + bool exportAnimations(Main *bmain, Scene *sce); + // called for each exported object void operator() (Object *ob); diff --git a/source/blender/collada/ArmatureImporter.cpp b/source/blender/collada/ArmatureImporter.cpp index 19f174d4840..2f5c3237bf6 100644 --- a/source/blender/collada/ArmatureImporter.cpp +++ b/source/blender/collada/ArmatureImporter.cpp @@ -55,8 +55,10 @@ static const char *bc_get_joint_name(T *node) } -ArmatureImporter::ArmatureImporter(UnitConverter *conv, MeshImporterBase *mesh, Scene *sce, ViewLayer *view_layer, const ImportSettings *import_settings) : +ArmatureImporter::ArmatureImporter( + UnitConverter *conv, MeshImporterBase *mesh, Main *bmain, Scene *sce, ViewLayer *view_layer, const ImportSettings *import_settings) : TransformReader(conv), + m_bmain(bmain), scene(sce), view_layer(view_layer), unit_converter(conv), @@ -411,7 +413,7 @@ Object *ArmatureImporter::get_empty_for_leaves() { if (empty) return empty; - empty = bc_add_object(scene, view_layer, OB_EMPTY, NULL); + empty = bc_add_object(m_bmain, scene, view_layer, OB_EMPTY, NULL); empty->empty_drawtype = OB_EMPTY_SPHERE; return empty; @@ -586,7 +588,7 @@ Object *ArmatureImporter::create_armature_bones(Main *bmain, SkinInfo& skin) ob_arm = skin.set_armature(shared); } else { - ob_arm = skin.create_armature(scene, view_layer); //once for every armature + ob_arm = skin.create_armature(m_bmain, scene, view_layer); //once for every armature } // enter armature edit mode @@ -856,8 +858,9 @@ bool ArmatureImporter::write_controller(const COLLADAFW::Controller *controller) return true; } -void ArmatureImporter::make_shape_keys() +void ArmatureImporter::make_shape_keys(bContext *C) { + Main *bmain = CTX_data_main(C); std::vector<COLLADAFW::MorphController *>::iterator mc; float weight; @@ -873,7 +876,7 @@ void ArmatureImporter::make_shape_keys() Mesh *source_me = (Mesh *)source_ob->data; //insert key to source mesh - Key *key = source_me->key = BKE_key_add((ID *)source_me); + Key *key = source_me->key = BKE_key_add(bmain, (ID *)source_me); key->type = KEY_RELATIVE; KeyBlock *kb; diff --git a/source/blender/collada/ArmatureImporter.h b/source/blender/collada/ArmatureImporter.h index b13e40bf855..419861554f4 100644 --- a/source/blender/collada/ArmatureImporter.h +++ b/source/blender/collada/ArmatureImporter.h @@ -62,6 +62,7 @@ extern "C" { class ArmatureImporter : private TransformReader { private: + Main *m_bmain; Scene *scene; ViewLayer *view_layer; UnitConverter *unit_converter; @@ -138,7 +139,8 @@ private: TagsMap uid_tags_map; public: - ArmatureImporter(UnitConverter *conv, MeshImporterBase *mesh, Scene *sce, ViewLayer *view_layer, const ImportSettings *import_settings); + ArmatureImporter( + UnitConverter *conv, MeshImporterBase *mesh, Main *bmain, Scene *sce, ViewLayer *view_layer, const ImportSettings *import_settings); ~ArmatureImporter(); void add_root_joint(COLLADAFW::Node *node, Object *parent); @@ -146,7 +148,7 @@ public: // here we add bones to armatures, having armatures previously created in write_controller void make_armatures(bContext *C, std::vector<Object *> &objects_to_scale); - void make_shape_keys(); + void make_shape_keys(bContext *C); #if 0 // link with meshes, create vertex groups, assign weights diff --git a/source/blender/collada/ControllerExporter.cpp b/source/blender/collada/ControllerExporter.cpp index 122094e33a6..6cb1e58db6e 100644 --- a/source/blender/collada/ControllerExporter.cpp +++ b/source/blender/collada/ControllerExporter.cpp @@ -104,9 +104,10 @@ bool ControllerExporter::add_instance_controller(Object *ob) return true; } -void ControllerExporter::export_controllers(struct Depsgraph *depsgraph, Scene *sce) +void ControllerExporter::export_controllers(Main *bmain, Depsgraph *depsgraph, Scene *sce) { this->depsgraph = depsgraph; + m_bmain = bmain; scene = sce; openLibrary(); @@ -198,7 +199,10 @@ void ControllerExporter::export_skin_controller(Object *ob, Object *ob_arm) bool use_instantiation = this->export_settings->use_object_instantiation; Mesh *me; - me = bc_get_mesh_copy(depsgraph, scene, + me = bc_get_mesh_copy( + m_bmain, + depsgraph, + scene, ob, this->export_settings->export_mesh_type, this->export_settings->apply_modifiers, @@ -289,7 +293,7 @@ void ControllerExporter::export_skin_controller(Object *ob, Object *ob_arm) add_joints_element(&ob->defbase, joints_source_id, inv_bind_mat_source_id); add_vertex_weights_element(weights_source_id, joints_source_id, vcounts, joints); - BKE_libblock_free_us(G.main, me); + BKE_libblock_free_us(m_bmain, me); closeSkin(); closeController(); @@ -300,7 +304,10 @@ void ControllerExporter::export_morph_controller(Object *ob, Key *key) bool use_instantiation = this->export_settings->use_object_instantiation; Mesh *me; - me = bc_get_mesh_copy(depsgraph, scene, + me = bc_get_mesh_copy( + m_bmain, + depsgraph, + scene, ob, this->export_settings->export_mesh_type, this->export_settings->apply_modifiers, @@ -325,7 +332,7 @@ void ControllerExporter::export_morph_controller(Object *ob, Key *key) COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, morph_weights_id))); targets.add(); - BKE_libblock_free_us(G.main, me); + BKE_libblock_free_us(m_bmain, me); //support for animations diff --git a/source/blender/collada/ControllerExporter.h b/source/blender/collada/ControllerExporter.h index e13d7c7ebea..2b6853901be 100644 --- a/source/blender/collada/ControllerExporter.h +++ b/source/blender/collada/ControllerExporter.h @@ -66,12 +66,13 @@ public: bool add_instance_controller(Object *ob); - void export_controllers(struct Depsgraph *depsgraph, Scene *sce); + void export_controllers(Main *bmain, Depsgraph *depsgraph, Scene *sce); void operator()(Object *ob); private: - struct Depsgraph *depsgraph; + Depsgraph *depsgraph; + Main *m_bmain; Scene *scene; UnitConverter converter; const ExportSettings *export_settings; diff --git a/source/blender/collada/DocumentExporter.cpp b/source/blender/collada/DocumentExporter.cpp index 9e78c164dad..04d39f4f568 100644 --- a/source/blender/collada/DocumentExporter.cpp +++ b/source/blender/collada/DocumentExporter.cpp @@ -182,6 +182,7 @@ static COLLADABU::NativeString make_temp_filepath(const char *name, const char * int DocumentExporter::exportCurrentScene(bContext *C, Scene *sce) { + Main *bmain = CTX_data_main(C); PointerRNA sceneptr, unit_settings; PropertyRNA *system; /* unused , *scale; */ @@ -286,7 +287,7 @@ int DocumentExporter::exportCurrentScene(bContext *C, Scene *sce) // <library_geometries> if (bc_has_object_type(export_set, OB_MESH)) { GeometryExporter ge(writer, this->export_settings); - ge.exportGeom(depsgraph, sce); + ge.exportGeom(bmain, depsgraph, sce); } // <library_controllers> @@ -294,7 +295,7 @@ int DocumentExporter::exportCurrentScene(bContext *C, Scene *sce) ControllerExporter controller_exporter(writer, this->export_settings); if (bc_has_object_type(export_set, OB_ARMATURE) || this->export_settings->include_shapekeys) { - controller_exporter.export_controllers(depsgraph, sce); + controller_exporter.export_controllers(bmain, depsgraph, sce); } // <library_visual_scenes> @@ -304,7 +305,7 @@ int DocumentExporter::exportCurrentScene(bContext *C, Scene *sce) if (this->export_settings->include_animations) { // <library_animations> AnimationExporter ae(depsgraph, writer, this->export_settings); - ae.exportAnimations(sce); + ae.exportAnimations(bmain, sce); } se.exportScene(C, depsgraph, sce); diff --git a/source/blender/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp index ae573fec0d8..c6ba3b8f4ac 100644 --- a/source/blender/collada/DocumentImporter.cpp +++ b/source/blender/collada/DocumentImporter.cpp @@ -108,8 +108,8 @@ DocumentImporter::DocumentImporter(bContext *C, const ImportSettings *import_set mImportStage(General), mContext(C), view_layer(CTX_data_view_layer(mContext)), - armature_importer(&unit_converter, &mesh_importer, CTX_data_scene(C), view_layer, import_settings), - mesh_importer(&unit_converter, &armature_importer, CTX_data_scene(C), view_layer), + armature_importer(&unit_converter, &mesh_importer, CTX_data_main(C), CTX_data_scene(C), view_layer, import_settings), + mesh_importer(&unit_converter, &armature_importer, CTX_data_main(C), CTX_data_scene(C), view_layer), anim_importer(&unit_converter, &armature_importer, CTX_data_scene(C)) { } @@ -244,7 +244,7 @@ void DocumentImporter::finish() armature_importer.set_tags_map(this->uid_tags_map); armature_importer.make_armatures(mContext, *objects_to_scale); - armature_importer.make_shape_keys(); + armature_importer.make_shape_keys(mContext); DEG_relations_tag_update(bmain); #if 0 @@ -266,7 +266,7 @@ void DocumentImporter::finish() std::vector<Object *>::iterator it; for (it = libnode_ob.begin(); it != libnode_ob.end(); it++) { Object *ob = *it; - BKE_scene_collections_object_remove(G.main, sce, ob, true); + BKE_scene_collections_object_remove(bmain, sce, ob, true); } libnode_ob.clear(); @@ -379,11 +379,12 @@ Object *DocumentImporter::create_camera_object(COLLADAFW::InstanceCamera *camera return NULL; } - Object *ob = bc_add_object(sce, view_layer, OB_CAMERA, NULL); + Main *bmain = CTX_data_main(mContext); + Object *ob = bc_add_object(bmain, sce, view_layer, OB_CAMERA, NULL); Camera *cam = uid_camera_map[cam_uid]; Camera *old_cam = (Camera *)ob->data; ob->data = cam; - BKE_libblock_free_us(G.main, old_cam); + BKE_libblock_free_us(bmain, old_cam); return ob; } @@ -395,11 +396,12 @@ Object *DocumentImporter::create_lamp_object(COLLADAFW::InstanceLight *lamp, Sce return NULL; } - Object *ob = bc_add_object(sce, view_layer, OB_LAMP, NULL); + Main *bmain = CTX_data_main(mContext); + Object *ob = bc_add_object(bmain, sce, view_layer, OB_LAMP, NULL); Lamp *la = uid_lamp_map[lamp_uid]; Lamp *old_lamp = (Lamp *)ob->data; ob->data = la; - BKE_libblock_free_us(G.main, old_lamp); + BKE_libblock_free_us(bmain, old_lamp); return ob; } @@ -407,9 +409,10 @@ Object *DocumentImporter::create_instance_node(Object *source_ob, COLLADAFW::Nod { fprintf(stderr, "create <instance_node> under node id=%s from node id=%s\n", instance_node ? instance_node->getOriginalId().c_str() : NULL, source_node ? source_node->getOriginalId().c_str() : NULL); - Object *obn = BKE_object_copy(G.main, source_ob); + Main *bmain = CTX_data_main(mContext); + Object *obn = BKE_object_copy(bmain, source_ob); DEG_id_tag_update(&obn->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); - BKE_collection_object_add_from(G.main, sce, source_ob, obn); + BKE_collection_object_add_from(bmain, sce, source_ob, obn); if (instance_node) { anim_importer.read_node_transform(instance_node, obn); @@ -490,6 +493,7 @@ void DocumentImporter::report_unknown_reference(const COLLADAFW::Node &node, con std::vector<Object *> *DocumentImporter::write_node(COLLADAFW::Node *node, COLLADAFW::Node *parent_node, Scene *sce, Object *par, bool is_library_node) { + Main *bmain = CTX_data_main(mContext); Object *ob = NULL; bool is_joint = node->getType() == COLLADAFW::Node::JOINT; bool read_transform = true; @@ -511,7 +515,7 @@ std::vector<Object *> *DocumentImporter::write_node(COLLADAFW::Node *node, COLLA if (parent_node == NULL && !is_library_node) { // A Joint on root level is a skeleton without root node. // Here we add the armature "on the fly": - par = bc_add_object(sce, view_layer, OB_ARMATURE, std::string("Armature").c_str()); + par = bc_add_object(bmain, sce, view_layer, OB_ARMATURE, std::string("Armature").c_str()); objects_done->push_back(par); root_objects->push_back(par); object_map.insert(std::pair<COLLADAFW::UniqueId, Object *>(node->getUniqueId(), par)); @@ -624,10 +628,10 @@ std::vector<Object *> *DocumentImporter::write_node(COLLADAFW::Node *node, COLLA if ( (geom_done + camera_done + lamp_done + controller_done + inst_done) < 1) { //Check if Object is armature, by checking if immediate child is a JOINT node. if (is_armature(node)) { - ob = bc_add_object(sce, view_layer, OB_ARMATURE, name.c_str()); + ob = bc_add_object(bmain, sce, view_layer, OB_ARMATURE, name.c_str()); } else { - ob = bc_add_object(sce, view_layer, OB_EMPTY, NULL); + ob = bc_add_object(bmain, sce, view_layer, OB_EMPTY, NULL); } objects_done->push_back(ob); if (parent_node == NULL) { @@ -644,7 +648,7 @@ std::vector<Object *> *DocumentImporter::write_node(COLLADAFW::Node *node, COLLA for (std::vector<Object *>::iterator it = objects_done->begin(); it != objects_done->end(); ++it) { ob = *it; std::string nodename = node->getName().size() ? node->getName() : node->getOriginalId(); - BKE_libblock_rename(G.main, &ob->id, (char *)nodename.c_str()); + BKE_libblock_rename(bmain, &ob->id, (char *)nodename.c_str()); object_map.insert(std::pair<COLLADAFW::UniqueId, Object *>(node->getUniqueId(), ob)); node_map[node->getUniqueId()] = node; @@ -754,8 +758,9 @@ bool DocumentImporter::writeMaterial(const COLLADAFW::Material *cmat) if (mImportStage != General) return true; + Main *bmain = CTX_data_main(mContext); const std::string& str_mat_id = cmat->getName().size() ? cmat->getName() : cmat->getOriginalId(); - Material *ma = BKE_material_add(G.main, (char *)str_mat_id.c_str()); + Material *ma = BKE_material_add(bmain, (char *)str_mat_id.c_str()); this->uid_effect_map[cmat->getInstantiatedEffect()] = ma; this->uid_material_map[cmat->getUniqueId()] = ma; @@ -940,14 +945,15 @@ bool DocumentImporter::writeCamera(const COLLADAFW::Camera *camera) if (mImportStage != General) return true; + Main *bmain = CTX_data_main(mContext); Camera *cam = NULL; std::string cam_id, cam_name; ExtraTags *et=getExtraTags(camera->getUniqueId()); cam_id = camera->getOriginalId(); cam_name = camera->getName(); - if (cam_name.size()) cam = (Camera *)BKE_camera_add(G.main, (char *)cam_name.c_str()); - else cam = (Camera *)BKE_camera_add(G.main, (char *)cam_id.c_str()); + if (cam_name.size()) cam = (Camera *)BKE_camera_add(bmain, (char *)cam_name.c_str()); + else cam = (Camera *)BKE_camera_add(bmain, (char *)cam_id.c_str()); if (!cam) { fprintf(stderr, "Cannot create camera.\n"); @@ -1085,7 +1091,7 @@ bool DocumentImporter::writeImage(const COLLADAFW::Image *image) workpath = imagepath.c_str(); } - Image *ima = BKE_image_load_exists(workpath); + Image *ima = BKE_image_load_exists(CTX_data_main(mContext), workpath); if (!ima) { fprintf(stderr, "Cannot create image: %s\n", workpath); return true; @@ -1102,6 +1108,7 @@ bool DocumentImporter::writeLight(const COLLADAFW::Light *light) if (mImportStage != General) return true; + Main *bmain = CTX_data_main(mContext); Lamp *lamp = NULL; std::string la_id, la_name; @@ -1114,8 +1121,8 @@ bool DocumentImporter::writeLight(const COLLADAFW::Light *light) la_id = light->getOriginalId(); la_name = light->getName(); - if (la_name.size()) lamp = (Lamp *)BKE_lamp_add(G.main, (char *)la_name.c_str()); - else lamp = (Lamp *)BKE_lamp_add(G.main, (char *)la_id.c_str()); + if (la_name.size()) lamp = (Lamp *)BKE_lamp_add(bmain, (char *)la_name.c_str()); + else lamp = (Lamp *)BKE_lamp_add(bmain, (char *)la_id.c_str()); if (!lamp) { fprintf(stderr, "Cannot create lamp.\n"); diff --git a/source/blender/collada/GeometryExporter.cpp b/source/blender/collada/GeometryExporter.cpp index 65e844cbe50..f59be97b545 100644 --- a/source/blender/collada/GeometryExporter.cpp +++ b/source/blender/collada/GeometryExporter.cpp @@ -57,11 +57,12 @@ GeometryExporter::GeometryExporter(COLLADASW::StreamWriter *sw, const ExportSett { } -void GeometryExporter::exportGeom(struct Depsgraph *depsgraph, Scene *sce) +void GeometryExporter::exportGeom(Main *bmain, struct Depsgraph *depsgraph, Scene *sce) { openLibrary(); mDepsgraph = depsgraph; + m_bmain = bmain; mScene = sce; GeometryFunctor gf; gf.forEachMeshObjectInExportSet<GeometryExporter>(sce, *this, this->export_settings->export_set); @@ -77,7 +78,10 @@ void GeometryExporter::operator()(Object *ob) #endif bool use_instantiation = this->export_settings->use_object_instantiation; - Mesh *me = bc_get_mesh_copy(mDepsgraph, mScene, + Mesh *me = bc_get_mesh_copy( + m_bmain, + mDepsgraph, + mScene, ob, this->export_settings->export_mesh_type, this->export_settings->apply_modifiers, @@ -166,7 +170,7 @@ void GeometryExporter::operator()(Object *ob) } } - BKE_libblock_free_us(G.main, me); + BKE_libblock_free_us(m_bmain, me); } diff --git a/source/blender/collada/GeometryExporter.h b/source/blender/collada/GeometryExporter.h index b0cd650adcd..5d74124b07a 100644 --- a/source/blender/collada/GeometryExporter.h +++ b/source/blender/collada/GeometryExporter.h @@ -75,12 +75,13 @@ class GeometryExporter : COLLADASW::LibraryGeometries Normal n; struct Depsgraph *mDepsgraph; + Main *m_bmain; Scene *mScene; public: GeometryExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings); - void exportGeom(struct Depsgraph *depsgraph, Scene *sce); + void exportGeom(Main *bmain, Depsgraph *depsgraph, Scene *sce); void operator()(Object *ob); diff --git a/source/blender/collada/MeshImporter.cpp b/source/blender/collada/MeshImporter.cpp index e95f8ed0888..4a8fca6d3cd 100644 --- a/source/blender/collada/MeshImporter.cpp +++ b/source/blender/collada/MeshImporter.cpp @@ -207,8 +207,9 @@ void VCOLDataWrapper::get_vcol(int v_index, MLoopCol *mloopcol) } -MeshImporter::MeshImporter(UnitConverter *unitconv, ArmatureImporter *arm, Scene *sce, ViewLayer *view_layer): +MeshImporter::MeshImporter(UnitConverter *unitconv, ArmatureImporter *arm, Main *bmain, Scene *sce, ViewLayer *view_layer): unitconverter(unitconv), + m_bmain(bmain), scene(sce), view_layer(view_layer), armature_importer(arm) { @@ -1035,7 +1036,7 @@ void MeshImporter::assign_material_to_geom( // Attention! This temporaly assigns material to object on purpose! // See note above. ob->actcol=0; - assign_material(G.main, ob, ma, mat_index + 1, BKE_MAT_ASSIGN_OBJECT); + assign_material(m_bmain, ob, ma, mat_index + 1, BKE_MAT_ASSIGN_OBJECT); MaterialIdPrimitiveArrayMap& mat_prim_map = geom_uid_mat_mapping_map[*geom_uid]; COLLADAFW::MaterialId mat_id = cmaterial.getMaterialId(); @@ -1090,7 +1091,7 @@ Object *MeshImporter::create_mesh_object(COLLADAFW::Node *node, COLLADAFW::Insta const char *name = (id.length()) ? id.c_str() : NULL; // add object - Object *ob = bc_add_object(scene, view_layer, OB_MESH, name); + Object *ob = bc_add_object(m_bmain, scene, view_layer, OB_MESH, name); bc_set_mark(ob); // used later for material assignement optimization @@ -1102,11 +1103,11 @@ Object *MeshImporter::create_mesh_object(COLLADAFW::Node *node, COLLADAFW::Insta Mesh *old_mesh = (Mesh *)ob->data; Mesh *new_mesh = uid_mesh_map[*geom_uid]; - BKE_mesh_assign_object(G.main, ob, new_mesh); + BKE_mesh_assign_object(m_bmain, ob, new_mesh); BKE_mesh_calc_normals(new_mesh); id_us_plus(&old_mesh->id); /* Because BKE_mesh_assign_object would have already decreased it... */ - BKE_libblock_free_us(G.main, old_mesh); + BKE_libblock_free_us(m_bmain, old_mesh); COLLADAFW::MaterialBindingArray& mat_array = geom->getMaterialBindings(); @@ -1145,7 +1146,7 @@ bool MeshImporter::write_geometry(const COLLADAFW::Geometry *geom) } const std::string& str_geom_id = mesh->getName().size() ? mesh->getName() : mesh->getOriginalId(); - Mesh *me = BKE_mesh_add(G.main, (char *)str_geom_id.c_str()); + Mesh *me = BKE_mesh_add(m_bmain, (char *)str_geom_id.c_str()); id_us_min(&me->id); // is already 1 here, but will be set later in BKE_mesh_assign_object // store the Mesh pointer to link it later with an Object diff --git a/source/blender/collada/MeshImporter.h b/source/blender/collada/MeshImporter.h index c98126916d7..4583242808b 100644 --- a/source/blender/collada/MeshImporter.h +++ b/source/blender/collada/MeshImporter.h @@ -90,6 +90,7 @@ private: UnitConverter *unitconverter; + Main *m_bmain; Scene *scene; ViewLayer *view_layer; @@ -160,7 +161,7 @@ private: public: - MeshImporter(UnitConverter *unitconv, ArmatureImporter *arm, Scene *sce, ViewLayer *view_layer); + MeshImporter(UnitConverter *unitconv, ArmatureImporter *arm, Main *bmain, Scene *sce, ViewLayer *view_layer); virtual Object *get_object_by_geom_uid(const COLLADAFW::UniqueId& geom_uid); diff --git a/source/blender/collada/SkinInfo.cpp b/source/blender/collada/SkinInfo.cpp index 7ec3f04aabf..b07c6518050 100644 --- a/source/blender/collada/SkinInfo.cpp +++ b/source/blender/collada/SkinInfo.cpp @@ -159,9 +159,9 @@ void SkinInfo::set_controller(const COLLADAFW::SkinController *co) } // called from write_controller -Object *SkinInfo::create_armature(Scene *scene, ViewLayer *view_layer) +Object *SkinInfo::create_armature(Main *bmain, Scene *scene, ViewLayer *view_layer) { - ob_arm = bc_add_object(scene, view_layer, OB_ARMATURE, NULL); + ob_arm = bc_add_object(bmain, scene, view_layer, OB_ARMATURE, NULL); return ob_arm; } diff --git a/source/blender/collada/SkinInfo.h b/source/blender/collada/SkinInfo.h index fdfee0a943a..39808c546b1 100644 --- a/source/blender/collada/SkinInfo.h +++ b/source/blender/collada/SkinInfo.h @@ -99,7 +99,7 @@ public: void set_controller(const COLLADAFW::SkinController* co); // called from write_controller - Object *create_armature(Scene *scene, ViewLayer *view_layer); + Object *create_armature(Main *bmain, Scene *scene, ViewLayer *view_layer); Object* set_armature(Object *ob_arm); diff --git a/source/blender/collada/collada_utils.cpp b/source/blender/collada/collada_utils.cpp index 945dda68745..4ded9bd2d86 100644 --- a/source/blender/collada/collada_utils.cpp +++ b/source/blender/collada/collada_utils.cpp @@ -142,29 +142,22 @@ Scene *bc_get_scene(bContext *C) return CTX_data_scene(C); } -Main *bc_get_main() -{ - return G.main; -} - - -void bc_update_scene(Depsgraph *depsgraph, Scene *scene, float ctime) +void bc_update_scene(Main *bmain, Depsgraph *depsgraph, Scene *scene, float ctime) { BKE_scene_frame_set(scene, ctime); - Main *bmain = bc_get_main(); BKE_scene_graph_update_for_newframe(depsgraph, bmain); } -Object *bc_add_object(Scene *scene, ViewLayer *view_layer, int type, const char *name) +Object *bc_add_object(Main *bmain, Scene *scene, ViewLayer *view_layer, int type, const char *name) { - Object *ob = BKE_object_add_only_object(G.main, type, name); + Object *ob = BKE_object_add_only_object(bmain, type, name); - ob->data = BKE_object_obdata_add_from_type(G.main, type, name); + ob->data = BKE_object_obdata_add_from_type(bmain, type, name); ob->lay = scene->lay; DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); LayerCollection *layer_collection = BKE_layer_collection_get_active(view_layer); - BKE_collection_object_add(G.main, layer_collection->collection, ob); + BKE_collection_object_add(bmain, layer_collection->collection, ob); Base *base = BKE_view_layer_base_find(view_layer, ob); BKE_view_layer_base_select(view_layer, base); @@ -172,7 +165,8 @@ Object *bc_add_object(Scene *scene, ViewLayer *view_layer, int type, const char return ob; } -Mesh *bc_get_mesh_copy(struct Depsgraph *depsgraph, Scene *scene, Object *ob, BC_export_mesh_type export_mesh_type, bool apply_modifiers, bool triangulate) +Mesh *bc_get_mesh_copy( + Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *ob, BC_export_mesh_type export_mesh_type, bool apply_modifiers, bool triangulate) { Mesh *tmpmesh; CustomDataMask mask = CD_MASK_MESH; @@ -196,7 +190,7 @@ Mesh *bc_get_mesh_copy(struct Depsgraph *depsgraph, Scene *scene, Object *ob, BC dm = mesh_create_derived((Mesh *)ob->data, NULL); } - tmpmesh = BKE_mesh_add(G.main, "ColladaMesh"); // name is not important here + tmpmesh = BKE_mesh_add(bmain, "ColladaMesh"); // name is not important here DM_to_mesh(dm, tmpmesh, ob, CD_MASK_MESH, true); tmpmesh->flag = mesh->flag; @@ -449,7 +443,8 @@ void bc_triangulate_mesh(Mesh *me) BM_mesh_triangulate(bm, quad_method, use_beauty, tag_only, NULL, NULL, NULL); BMeshToMeshParams bm_to_me_params = {0}; - BM_mesh_bm_to_me(bm, me, &bm_to_me_params); + bm_to_me_params.calc_object_remap = false; + BM_mesh_bm_to_me(NULL, bm, me, &bm_to_me_params); BM_mesh_free(bm); } diff --git a/source/blender/collada/collada_utils.h b/source/blender/collada/collada_utils.h index 20c569834d8..de9167efb07 100644 --- a/source/blender/collada/collada_utils.h +++ b/source/blender/collada/collada_utils.h @@ -65,15 +65,15 @@ struct Depsgraph; typedef std::map<COLLADAFW::TextureMapId, std::vector<MTex *> > TexIndexTextureArrayMap; extern Scene *bc_get_scene(bContext *C); -extern Main *bc_get_main(); extern Depsgraph *bc_get_depsgraph(); -extern void bc_update_scene(Depsgraph *depsgraph, Scene *scene, float ctime); +extern void bc_update_scene(Main *bmain, Depsgraph *depsgraph, Scene *scene, float ctime); extern float bc_get_float_value(const COLLADAFW::FloatOrDoubleArray& array, unsigned int index); extern int bc_test_parent_loop(Object *par, Object *ob); extern int bc_set_parent(Object *ob, Object *par, bContext *C, bool is_parent_space = true); -extern Object *bc_add_object(Scene *scene, ViewLayer *view_layer, int type, const char *name); -extern Mesh *bc_get_mesh_copy(struct Depsgraph *depsgraph, Scene *scene, Object *ob, BC_export_mesh_type export_mesh_type, bool apply_modifiers, bool triangulate); +extern Object *bc_add_object(Main *bmain, Scene *scene, ViewLayer *view_layer, int type, const char *name); +extern Mesh *bc_get_mesh_copy( + Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *ob, BC_export_mesh_type export_mesh_type, bool apply_modifiers, bool triangulate); extern Object *bc_get_assigned_armature(Object *ob); extern Object *bc_get_highest_selected_ancestor_or_self(LinkNode *export_set, Object *ob); diff --git a/source/blender/compositor/operations/COM_CompositorOperation.cpp b/source/blender/compositor/operations/COM_CompositorOperation.cpp index 241ae20ce33..16e33c908d6 100644 --- a/source/blender/compositor/operations/COM_CompositorOperation.cpp +++ b/source/blender/compositor/operations/COM_CompositorOperation.cpp @@ -22,6 +22,7 @@ #include "COM_CompositorOperation.h" #include "BLI_listbase.h" +#include "BKE_global.h" #include "BKE_image.h" extern "C" { @@ -109,7 +110,7 @@ void CompositorOperation::deinitExecution() } BLI_thread_lock(LOCK_DRAW_IMAGE); - BKE_image_signal(BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result"), NULL, IMA_SIGNAL_FREE); + BKE_image_signal(G.main, BKE_image_verify_viewer(G.main, IMA_TYPE_R_RESULT, "Render Result"), NULL, IMA_SIGNAL_FREE); BLI_thread_unlock(LOCK_DRAW_IMAGE); } else { diff --git a/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cpp b/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cpp index 651c336452e..1ebb0f93939 100644 --- a/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cpp +++ b/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cpp @@ -26,6 +26,7 @@ extern "C" { # include "BLI_math.h" # include "BLI_utildefines.h" # include "BLI_rand.h" +# include "PIL_time.h" } ScreenLensDistortionOperation::ScreenLensDistortionOperation() : NodeOperation() @@ -59,6 +60,10 @@ void ScreenLensDistortionOperation::initExecution() { this->m_inputProgram = this->getInputSocketReader(0); this->initMutex(); + + uint rng_seed = (uint)(PIL_check_seconds_timer_i() & UINT_MAX); + rng_seed ^= (uint)GET_INT_FROM_POINTER(m_inputProgram); + this->m_rng = BLI_rng_new(rng_seed); this->m_cx = 0.5f * (float)getWidth(); this->m_cy = 0.5f * (float)getHeight(); @@ -142,7 +147,7 @@ void ScreenLensDistortionOperation::accumulate(MemoryBuffer *buffer, float dk4 = m_dk4[a]; for (float z = 0; z < ds; ++z) { - float tz = (z + (m_jitter ? BLI_frand() : 0.5f)) * sd; + float tz = (z + (m_jitter ? BLI_rng_get_float(m_rng) : 0.5f)) * sd; float t = 1.0f - (k4 + tz * dk4) * r_sq; float xy[2]; @@ -192,6 +197,7 @@ void ScreenLensDistortionOperation::deinitExecution() { this->deinitMutex(); this->m_inputProgram = NULL; + BLI_rng_free(this->m_rng); } void ScreenLensDistortionOperation::determineUV(float result[6], float x, float y) const diff --git a/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.h b/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.h index 648a7a6e551..71df73ebd8c 100644 --- a/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.h +++ b/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.h @@ -31,6 +31,7 @@ private: * Cached reference to the inputProgram */ SocketReader *m_inputProgram; + struct RNG *m_rng; bool m_fit; bool m_jitter; diff --git a/source/blender/depsgraph/DEG_depsgraph.h b/source/blender/depsgraph/DEG_depsgraph.h index 1dd2e1e587a..0174b002292 100644 --- a/source/blender/depsgraph/DEG_depsgraph.h +++ b/source/blender/depsgraph/DEG_depsgraph.h @@ -70,8 +70,7 @@ struct ViewLayer; typedef enum eEvaluationMode { DAG_EVAL_VIEWPORT = 0, /* evaluate for OpenGL viewport */ - DAG_EVAL_PREVIEW = 1, /* evaluate for render with preview settings */ - DAG_EVAL_RENDER = 2, /* evaluate for render purposes */ + DAG_EVAL_RENDER = 1, /* evaluate for render purposes */ } eEvaluationMode; /* DagNode->eval_flags */ diff --git a/source/blender/depsgraph/intern/builder/deg_builder.cc b/source/blender/depsgraph/intern/builder/deg_builder.cc index f1f3da85968..1b2dcd8fcf8 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder.cc @@ -30,9 +30,14 @@ #include "intern/builder/deg_builder.h" +#include "DNA_anim_types.h" #include "DNA_object_types.h" #include "DNA_ID.h" +extern "C" { +#include "BKE_animsys.h" +} + #include "intern/depsgraph.h" #include "intern/depsgraph_types.h" #include "intern/eval/deg_eval_copy_on_write.h" @@ -53,12 +58,17 @@ void deg_graph_build_finalize(Main *bmain, Depsgraph *graph) foreach (IDDepsNode *id_node, graph->id_nodes) { ID *id = id_node->id_orig; id_node->finalize_build(graph); + int flag = DEG_TAG_TRANSFORM | DEG_TAG_GEOMETRY; if ((id->recalc & ID_RECALC_ALL)) { - DEG_id_tag_update_ex(bmain, id_node->id_orig, 0); + AnimData *adt = BKE_animdata_from_id(id); + if (adt != NULL && (adt->recalc & ADT_RECALC_ANIM) != 0) { + flag |= DEG_TAG_TIME; + } } if (!deg_copy_on_write_is_expanded(id_node->id_cow)) { - DEG_id_tag_update_ex(bmain, id_node->id_orig, DEG_TAG_COPY_ON_WRITE); + flag |= DEG_TAG_COPY_ON_WRITE; } + DEG_id_tag_update_ex(bmain, id_node->id_orig, flag); } } diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc index aaf96a47711..ba34d24d9d5 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc @@ -439,8 +439,8 @@ void DepsgraphNodeBuilder::build_id(ID *id) { } void DepsgraphNodeBuilder::build_collection( - eDepsNode_CollectionOwner owner_type, - Collection *collection) + eDepsNode_CollectionOwner owner_type, + Collection *collection) { if (built_map_.checkIsBuiltAndTag(collection)) { return; @@ -552,7 +552,7 @@ void DepsgraphNodeBuilder::build_object_flags( const bool is_from_set = (linked_state == DEG_ID_LINKED_VIA_SET); /* TODO(sergey): Is this really best component to be used? */ add_operation_node(&object->id, - DEG_NODE_TYPE_LAYER_COLLECTIONS, + DEG_NODE_TYPE_OBJECT_FROM_LAYER, function_bind(BKE_object_eval_flush_base_flags, _1, scene_cow, @@ -897,11 +897,9 @@ void DepsgraphNodeBuilder::build_rigidbody(Scene *scene) /* objects - simulation participants */ if (rbw->group) { - const ListBase group_objects = BKE_collection_object_cache_get(rbw->group); - LISTBASE_FOREACH (Base *, base, &group_objects) { - Object *object = base->object; - - if (!object || (object->type != OB_MESH)) + FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(rbw->group, object) + { + if (object->type != OB_MESH) continue; /* 2) create operation for flushing results */ @@ -915,6 +913,7 @@ void DepsgraphNodeBuilder::build_rigidbody(Scene *scene) get_cow_datablock(object)), DEG_OPCODE_RIGIDBODY_TRANSFORM_COPY); } + FOREACH_COLLECTION_OBJECT_RECURSIVE_END; } } diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc index eb1ee0c1535..5312c7adac8 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc @@ -478,16 +478,12 @@ void DepsgraphRelationBuilder::build_collection( } } if (object != NULL) { - const ListBase group_objects = BKE_collection_object_cache_get(collection); - const int base_flag = (graph_->mode == DAG_EVAL_VIEWPORT) ? - BASE_VISIBLE_VIEWPORT : BASE_VISIBLE_RENDER; - LISTBASE_FOREACH (Base *, base, &group_objects) { - if ((base->flag & base_flag) == 0) { - continue; - } - ComponentKey dupli_transform_key(&base->object->id, DEG_NODE_TYPE_TRANSFORM); + FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_BEGIN(collection, ob, graph_->mode) + { + ComponentKey dupli_transform_key(&ob->id, DEG_NODE_TYPE_TRANSFORM); add_relation(dupli_transform_key, object_local_transform_key, "Dupligroup"); } + FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_END; } } @@ -610,7 +606,7 @@ void DepsgraphRelationBuilder::build_object_flags(Base *base, Object *object) DEG_NODE_TYPE_LAYER_COLLECTIONS, DEG_OPCODE_VIEW_LAYER_EVAL); OperationKey object_flags_key(&object->id, - DEG_NODE_TYPE_LAYER_COLLECTIONS, + DEG_NODE_TYPE_OBJECT_FROM_LAYER, DEG_OPCODE_OBJECT_BASE_FLAGS); add_relation(view_layer_done_key, object_flags_key, "Base flags flush"); } @@ -1430,10 +1426,9 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene) /* objects - simulation participants */ if (rbw->group) { - const ListBase group_objects = BKE_collection_object_cache_get(rbw->group); - LISTBASE_FOREACH (Base *, base, &group_objects) { - Object *object = base->object; - if (object == NULL || object->type != OB_MESH) { + FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(rbw->group, object) + { + if (object->type != OB_MESH) { continue; } @@ -1481,14 +1476,14 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene) /* Needed to get correct base values. */ add_relation(trans_op, sim_key, "Base Ob Transform -> Rigidbody Sim Eval"); } + FOREACH_COLLECTION_OBJECT_RECURSIVE_END; } /* constraints */ if (rbw->constraints) { - const ListBase constraint_objects = BKE_collection_object_cache_get(rbw->constraints); - LISTBASE_FOREACH (Base *, base, &constraint_objects) { - Object *object = base->object; - if (object == NULL || !object->rigidbody_constraint) { + FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(rbw->constraints, object) + { + if (!object->rigidbody_constraint) { continue; } @@ -1508,6 +1503,7 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene) /* - ensure that sim depends on this constraint's transform */ add_relation(trans_key, sim_key, "RigidBodyConstraint Transform -> RB Simulation"); } + FOREACH_COLLECTION_OBJECT_RECURSIVE_END; } } diff --git a/source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc b/source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc index d64ab79d918..df6e72f490f 100644 --- a/source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc +++ b/source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc @@ -271,6 +271,26 @@ static void deg_debug_graphviz_relation_style(const DebugContext &ctx, deg_debug_fprintf(ctx, "%s", style); } +static void deg_debug_graphviz_relation_arrowhead(const DebugContext &ctx, + const DepsRelation *rel) +{ + const char *shape_default = "normal"; + const char *shape_no_cow = "box"; + const char *shape = shape_default; + if (rel->from->get_class() == DEG_NODE_CLASS_OPERATION && + rel->to->get_class() == DEG_NODE_CLASS_OPERATION) + { + OperationDepsNode *op_from = (OperationDepsNode *)rel->from; + OperationDepsNode *op_to = (OperationDepsNode *)rel->to; + if (op_from->owner->type == DEG_NODE_TYPE_COPY_ON_WRITE && + !op_to->owner->need_tag_cow_before_update()) + { + shape = shape_no_cow; + } + } + deg_debug_fprintf(ctx, "%s", shape); +} + static void deg_debug_graphviz_node_style(const DebugContext &ctx, const DepsNode *node) { const char *base_style = "filled"; /* default style */ @@ -386,6 +406,7 @@ static void deg_debug_graphviz_node(const DebugContext &ctx, case DEG_NODE_TYPE_LAYER_COLLECTIONS: case DEG_NODE_TYPE_EVAL_PARTICLES: case DEG_NODE_TYPE_COPY_ON_WRITE: + case DEG_NODE_TYPE_OBJECT_FROM_LAYER: case DEG_NODE_TYPE_BATCH_CACHE: { ComponentDepsNode *comp_node = (ComponentDepsNode *)node; @@ -484,6 +505,8 @@ static void deg_debug_graphviz_node_relations(const DebugContext &ctx, deg_debug_graphviz_relation_color(ctx, rel); deg_debug_fprintf(ctx, ",style="); deg_debug_graphviz_relation_style(ctx, rel); + deg_debug_fprintf(ctx, ",arrowhead="); + deg_debug_graphviz_relation_arrowhead(ctx, rel); deg_debug_fprintf(ctx, ",penwidth=\"%f\"", penwidth); /* NOTE: edge from node to own cluster is not possible and gives graphviz * warning, avoid this here by just linking directly to the invisible diff --git a/source/blender/depsgraph/intern/depsgraph_query_iter.cc b/source/blender/depsgraph/intern/depsgraph_query_iter.cc index 97a28038b7b..1dd6f8b6a0b 100644 --- a/source/blender/depsgraph/intern/depsgraph_query_iter.cc +++ b/source/blender/depsgraph/intern/depsgraph_query_iter.cc @@ -60,9 +60,30 @@ extern "C" { # include "intern/eval/deg_eval_copy_on_write.h" #endif +// If defined, all working data will be set to an invalid state, helping +// to catch issues when areas accessing data which is considered to be no +// longer available. +#undef INVALIDATE_WORK_DATA + +#ifndef NDEBUG +# define INVALIDATE_WORK_DATA +#endif + /* ************************ DEG ITERATORS ********************* */ -static void verify_id_proeprties_freed(DEGObjectIterData *data) +namespace { + +void deg_invalidate_iterator_work_data(DEGObjectIterData *data) +{ +#ifdef INVALIDATE_WORK_DATA + BLI_assert(data != NULL); + memset(&data->temp_dupli_object, 0xff, sizeof(data->temp_dupli_object)); +#else + (void) data; +#endif +} + +void verify_id_proeprties_freed(DEGObjectIterData *data) { if (data->dupli_object_current == NULL) { // We didn't enter duplication yet, so we can't have any dangling @@ -86,7 +107,7 @@ static void verify_id_proeprties_freed(DEGObjectIterData *data) temp_dupli_object->id.properties = NULL; } -static bool deg_objects_dupli_iterator_next(BLI_Iterator *iter) +bool deg_objects_dupli_iterator_next(BLI_Iterator *iter) { DEGObjectIterData *data = (DEGObjectIterData *)iter->data; while (data->dupli_object_next != NULL) { @@ -137,7 +158,7 @@ static bool deg_objects_dupli_iterator_next(BLI_Iterator *iter) return false; } -static void DEG_iterator_objects_step(BLI_Iterator *iter, DEG::IDDepsNode *id_node) +void deg_iterator_objects_step(BLI_Iterator *iter, DEG::IDDepsNode *id_node) { /* Set it early in case we need to exit and we are running from within a loop. */ iter->skip = true; @@ -191,6 +212,8 @@ static void DEG_iterator_objects_step(BLI_Iterator *iter, DEG::IDDepsNode *id_no iter->skip = false; } +} // namespace + void DEG_iterator_objects_begin(BLI_Iterator *iter, DEGObjectIterData *data) { Depsgraph *depsgraph = data->graph; @@ -212,13 +235,13 @@ void DEG_iterator_objects_begin(BLI_Iterator *iter, DEGObjectIterData *data) data->id_node_index = 0; data->num_id_nodes = num_id_nodes; eEvaluationMode eval_mode = DEG_get_mode(depsgraph); - /* Viewport rendered mode is DAG_EVAL_PREVIEW but still treated as viewport. */ data->visibility_check = (eval_mode == DAG_EVAL_RENDER) ? OB_VISIBILITY_CHECK_FOR_RENDER : OB_VISIBILITY_CHECK_FOR_VIEWPORT; + deg_invalidate_iterator_work_data(data); DEG::IDDepsNode *id_node = deg_graph->id_nodes[data->id_node_index]; - DEG_iterator_objects_step(iter, id_node); + deg_iterator_objects_step(iter, id_node); if (iter->skip) { DEG_iterator_objects_next(iter); @@ -243,6 +266,7 @@ void DEG_iterator_objects_next(BLI_Iterator *iter) data->dupli_list = NULL; data->dupli_object_next = NULL; data->dupli_object_current = NULL; + deg_invalidate_iterator_work_data(data); } } @@ -253,24 +277,19 @@ void DEG_iterator_objects_next(BLI_Iterator *iter) } DEG::IDDepsNode *id_node = deg_graph->id_nodes[data->id_node_index]; - DEG_iterator_objects_step(iter, id_node); + deg_iterator_objects_step(iter, id_node); } while (iter->skip); } void DEG_iterator_objects_end(BLI_Iterator *iter) { -#ifndef NDEBUG DEGObjectIterData *data = (DEGObjectIterData *)iter->data; - - if (data) { + if (data != NULL) { /* Force crash in case the iterator data is referenced and accessed down * the line. (T51718) */ - memset(&data->temp_dupli_object, 0xff, sizeof(data->temp_dupli_object)); + deg_invalidate_iterator_work_data(data); } -#else - (void) iter; -#endif } /* ************************ DEG ID ITERATOR ********************* */ diff --git a/source/blender/depsgraph/intern/depsgraph_tag.cc b/source/blender/depsgraph/intern/depsgraph_tag.cc index 437999a06a9..9128571155f 100644 --- a/source/blender/depsgraph/intern/depsgraph_tag.cc +++ b/source/blender/depsgraph/intern/depsgraph_tag.cc @@ -142,7 +142,7 @@ void depsgraph_select_tag_to_component_opcode( *operation_code = DEG_OPCODE_VIEW_LAYER_EVAL; } else if (id_type == ID_OB) { - *component_type = DEG_NODE_TYPE_LAYER_COLLECTIONS; + *component_type = DEG_NODE_TYPE_OBJECT_FROM_LAYER; *operation_code = DEG_OPCODE_OBJECT_BASE_FLAGS; } else { @@ -162,7 +162,7 @@ void depsgraph_base_flags_tag_to_component_opcode( *operation_code = DEG_OPCODE_VIEW_LAYER_EVAL; } else if (id_type == ID_OB) { - *component_type = DEG_NODE_TYPE_LAYER_COLLECTIONS; + *component_type = DEG_NODE_TYPE_OBJECT_FROM_LAYER; *operation_code = DEG_OPCODE_OBJECT_BASE_FLAGS; } } @@ -284,7 +284,7 @@ void depsgraph_tag_component(Depsgraph *graph, } } /* If component depends on copy-on-write, tag it as well. */ - if (component_node->depends_on_cow()) { + if (component_node->need_tag_cow_before_update()) { ComponentDepsNode *cow_comp = id_node->find_component(DEG_NODE_TYPE_COPY_ON_WRITE); cow_comp->tag_update(graph); diff --git a/source/blender/depsgraph/intern/depsgraph_type_defines.cc b/source/blender/depsgraph/intern/depsgraph_type_defines.cc index 79d29f72b8d..9b1733bae8e 100644 --- a/source/blender/depsgraph/intern/depsgraph_type_defines.cc +++ b/source/blender/depsgraph/intern/depsgraph_type_defines.cc @@ -92,6 +92,7 @@ const char *nodeTypeAsString(eDepsNode_Type type) STRINGIFY_TYPE(SEQUENCER); STRINGIFY_TYPE(LAYER_COLLECTIONS); STRINGIFY_TYPE(COPY_ON_WRITE); + STRINGIFY_TYPE(OBJECT_FROM_LAYER); /* **** Evaluation-Related Outer Types (with Subdata) **** */ STRINGIFY_TYPE(EVAL_POSE); STRINGIFY_TYPE(BONE); diff --git a/source/blender/depsgraph/intern/depsgraph_types.h b/source/blender/depsgraph/intern/depsgraph_types.h index cec279a04bb..c6eb0d57bac 100644 --- a/source/blender/depsgraph/intern/depsgraph_types.h +++ b/source/blender/depsgraph/intern/depsgraph_types.h @@ -134,6 +134,10 @@ typedef enum eDepsNode_Type { * execution. */ DEG_NODE_TYPE_COPY_ON_WRITE, + /* Used by all operations which are updating object when something is + * changed in view layer. + */ + DEG_NODE_TYPE_OBJECT_FROM_LAYER, /* **** Evaluation-Related Outer Types (with Subdata) **** */ diff --git a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc index 3330c802aa9..e9f11f8e089 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc @@ -34,9 +34,13 @@ // TODO(sergey): Use some sort of wrapper. #include <deque> +#include <cmath> + +#include "BKE_object.h" #include "BLI_utildefines.h" #include "BLI_listbase.h" +#include "BLI_math_vector.h" #include "BLI_task.h" #include "BLI_ghash.h" @@ -55,6 +59,17 @@ extern "C" { #include "intern/eval/deg_eval_copy_on_write.h" #include "util/deg_util_foreach.h" +// Invalidate datablock data when update is flushed on it. +// +// The idea of this is to help catching cases when area is accessing data which +// is not yet evaluated, which could happen due to missing relations. The issue +// is that usually that data will be kept from previous frame, and it looks to +// be plausible. +// +// This ensures that data does not look plausible, making it much easier to +// catch usage of invalid state. +#undef INVALIDATE_ON_FLUSH + namespace DEG { enum { @@ -255,6 +270,72 @@ void flush_editors_id_update(Main *bmain, } } +#ifdef INVALIDATE_ON_FLUSH +void invalidate_tagged_evaluated_transform(ID *id) +{ + const ID_Type id_type = GS(id->name); + switch (id_type) { + case ID_OB: + { + Object *object = (Object *)id; + copy_vn_fl((float *)object->obmat, 16, NAN); + break; + } + default: + break; + } +} + +void invalidate_tagged_evaluated_geometry(ID *id) +{ + const ID_Type id_type = GS(id->name); + switch (id_type) { + case ID_OB: + { + Object *object = (Object *)id; + BKE_object_free_derived_caches(object); + break; + } + default: + break; + } +} +#endif + +void invalidate_tagged_evaluated_data(Depsgraph *graph) +{ +#ifdef INVALIDATE_ON_FLUSH + foreach (IDDepsNode *id_node, graph->id_nodes) { + if (id_node->done != ID_STATE_MODIFIED) { + continue; + } + ID *id_cow = id_node->id_cow; + if (!deg_copy_on_write_is_expanded(id_cow)) { + continue; + } + GHASH_FOREACH_BEGIN(ComponentDepsNode *, comp_node, id_node->components) + { + if (comp_node->done != COMPONENT_STATE_DONE) { + continue; + } + switch (comp_node->type) { + case DEG_TAG_TRANSFORM: + invalidate_tagged_evaluated_transform(id_cow); + break; + case DEG_TAG_GEOMETRY: + invalidate_tagged_evaluated_geometry(id_cow); + break; + default: + break; + } + } + GHASH_FOREACH_END(); + } +#else + (void) graph; +#endif +} + } // namespace /* Flush updates from tagged nodes outwards until all affected nodes @@ -300,6 +381,10 @@ void deg_graph_flush_updates(Main *bmain, Depsgraph *graph) } /* Inform editors about all changes. */ flush_editors_id_update(bmain, graph, &update_ctx); + /* Reset evaluation result tagged which is tagged for update to some state + * which is obvious to catch. + */ + invalidate_tagged_evaluated_data(graph); } static void graph_clear_operation_func( diff --git a/source/blender/depsgraph/intern/nodes/deg_node_component.cc b/source/blender/depsgraph/intern/nodes/deg_node_component.cc index 699ee1a3cad..9600eadb126 100644 --- a/source/blender/depsgraph/intern/nodes/deg_node_component.cc +++ b/source/blender/depsgraph/intern/nodes/deg_node_component.cc @@ -392,6 +392,7 @@ DEG_COMPONENT_NODE_DEFINE(Sequencer, SEQUENCER, ID_RECALC); DEG_COMPONENT_NODE_DEFINE(Shading, SHADING, ID_RECALC_DRAW); DEG_COMPONENT_NODE_DEFINE(ShadingParameters, SHADING_PARAMETERS, ID_RECALC_DRAW); DEG_COMPONENT_NODE_DEFINE(Transform, TRANSFORM, ID_RECALC_TRANSFORM); +DEG_COMPONENT_NODE_DEFINE(ObjectFromLayer, OBJECT_FROM_LAYER, ID_RECALC); /* Node Types Register =================================== */ @@ -412,6 +413,7 @@ void deg_register_component_depsnodes() deg_register_node_typeinfo(&DNTI_SHADING); deg_register_node_typeinfo(&DNTI_SHADING_PARAMETERS); deg_register_node_typeinfo(&DNTI_TRANSFORM); + deg_register_node_typeinfo(&DNTI_OBJECT_FROM_LAYER); } } // namespace DEG diff --git a/source/blender/depsgraph/intern/nodes/deg_node_component.h b/source/blender/depsgraph/intern/nodes/deg_node_component.h index 5b6461f950e..5e79dc1c685 100644 --- a/source/blender/depsgraph/intern/nodes/deg_node_component.h +++ b/source/blender/depsgraph/intern/nodes/deg_node_component.h @@ -144,8 +144,12 @@ struct ComponentDepsNode : public DepsNode { OperationDepsNode *entry_operation; OperationDepsNode *exit_operation; - // XXX: a poll() callback to check if component's first node can be started? virtual bool depends_on_cow() { return true; } + + /* Denotes whether COW component is to be tagged when this component + * is tagged for update. + */ + virtual bool need_tag_cow_before_update() { return true; } }; /* ---------------------------------------- */ @@ -168,8 +172,14 @@ struct ComponentDepsNode : public DepsNode { DEG_COMPONENT_NODE_DECLARE; \ } +#define DEG_COMPONENT_NODE_DECLARE_NO_COW_TAG_ON_UPDATE(name) \ + struct name ## ComponentDepsNode : public ComponentDepsNode { \ + DEG_COMPONENT_NODE_DECLARE; \ + virtual bool need_tag_cow_before_update() { return false; } \ + } + DEG_COMPONENT_NODE_DECLARE_GENERIC(Animation); -DEG_COMPONENT_NODE_DECLARE_GENERIC(BatchCache); +DEG_COMPONENT_NODE_DECLARE_NO_COW_TAG_ON_UPDATE(BatchCache); DEG_COMPONENT_NODE_DECLARE_GENERIC(Cache); DEG_COMPONENT_NODE_DECLARE_GENERIC(CopyOnWrite); DEG_COMPONENT_NODE_DECLARE_GENERIC(Geometry); @@ -182,6 +192,7 @@ DEG_COMPONENT_NODE_DECLARE_GENERIC(Sequencer); DEG_COMPONENT_NODE_DECLARE_GENERIC(Shading); DEG_COMPONENT_NODE_DECLARE_GENERIC(ShadingParameters); DEG_COMPONENT_NODE_DECLARE_GENERIC(Transform); +DEG_COMPONENT_NODE_DECLARE_NO_COW_TAG_ON_UPDATE(ObjectFromLayer); /* Bone Component */ struct BoneComponentDepsNode : public ComponentDepsNode { diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index 6d2d273e497..e785438c566 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -93,7 +93,6 @@ set(SRC modes/pose_mode.c modes/sculpt_mode.c engines/basic/basic_engine.c - engines/clay/clay_engine.c engines/eevee/eevee_bloom.c engines/eevee/eevee_data.c engines/eevee/eevee_depth_of_field.c @@ -136,27 +135,12 @@ set(SRC modes/draw_mode_engines.h modes/edit_mesh_mode_intern.h engines/basic/basic_engine.h - engines/clay/clay_engine.h engines/eevee/eevee_engine.h engines/eevee/eevee_lut.h engines/eevee/eevee_private.h engines/external/external_engine.h ) -if(WITH_CLAY_ENGINE) - add_definitions(-DWITH_CLAY_ENGINE) -endif() - -data_to_c_simple(engines/clay/shaders/clay_frag.glsl SRC) -data_to_c_simple(engines/clay/shaders/clay_fxaa.glsl SRC) -data_to_c_simple(engines/clay/shaders/clay_copy.glsl SRC) -data_to_c_simple(engines/clay/shaders/clay_prepass_frag.glsl SRC) -data_to_c_simple(engines/clay/shaders/clay_vert.glsl SRC) -data_to_c_simple(engines/clay/shaders/clay_particle_vert.glsl SRC) -data_to_c_simple(engines/clay/shaders/clay_particle_strand_frag.glsl SRC) -data_to_c_simple(engines/clay/shaders/ssao_alchemy.glsl SRC) -data_to_c_simple(engines/clay/shaders/ssao_groundtruth.glsl SRC) - data_to_c_simple(engines/eevee/shaders/ambient_occlusion_lib.glsl SRC) data_to_c_simple(engines/eevee/shaders/default_frag.glsl SRC) data_to_c_simple(engines/eevee/shaders/default_world_frag.glsl SRC) @@ -203,7 +187,6 @@ data_to_c_simple(engines/eevee/shaders/shadow_store_frag.glsl SRC) data_to_c_simple(engines/eevee/shaders/shadow_copy_frag.glsl SRC) data_to_c_simple(engines/eevee/shaders/bsdf_lut_frag.glsl SRC) data_to_c_simple(engines/eevee/shaders/btdf_lut_frag.glsl SRC) -data_to_c_simple(engines/eevee/shaders/bsdf_direct_lib.glsl SRC) data_to_c_simple(engines/eevee/shaders/bsdf_common_lib.glsl SRC) data_to_c_simple(engines/eevee/shaders/irradiance_lib.glsl SRC) data_to_c_simple(engines/eevee/shaders/octahedron_lib.glsl SRC) @@ -230,7 +213,6 @@ data_to_c_simple(engines/workbench/shaders/workbench_deferred_composite_frag.gls data_to_c_simple(engines/workbench/shaders/workbench_forward_composite_frag.glsl SRC) data_to_c_simple(engines/workbench/shaders/workbench_forward_depth_frag.glsl SRC) data_to_c_simple(engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl SRC) -data_to_c_simple(engines/workbench/shaders/workbench_forward_transparent_revealage_frag.glsl SRC) data_to_c_simple(engines/workbench/shaders/workbench_object_outline_lib.glsl SRC) data_to_c_simple(engines/workbench/shaders/workbench_prepass_vert.glsl SRC) data_to_c_simple(engines/workbench/shaders/workbench_prepass_frag.glsl SRC) @@ -291,6 +273,8 @@ data_to_c_simple(modes/shaders/object_empty_image_vert.glsl SRC) data_to_c_simple(modes/shaders/object_outline_resolve_frag.glsl SRC) data_to_c_simple(modes/shaders/object_outline_expand_frag.glsl SRC) data_to_c_simple(modes/shaders/object_outline_detect_frag.glsl SRC) +data_to_c_simple(modes/shaders/object_outline_prepass_vert.glsl SRC) +data_to_c_simple(modes/shaders/object_outline_prepass_geom.glsl SRC) data_to_c_simple(modes/shaders/object_outline_prepass_frag.glsl SRC) data_to_c_simple(modes/shaders/object_grid_frag.glsl SRC) data_to_c_simple(modes/shaders/object_grid_vert.glsl SRC) diff --git a/source/blender/draw/engines/clay/clay_engine.c b/source/blender/draw/engines/clay/clay_engine.c deleted file mode 100644 index 5d3717097b1..00000000000 --- a/source/blender/draw/engines/clay/clay_engine.c +++ /dev/null @@ -1,985 +0,0 @@ -/* - * Copyright 2016, Blender Foundation. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * Contributor(s): Blender Institute - * - */ - -#include "BLI_utildefines.h" -#include "BLI_string_utils.h" -#include "BLI_rand.h" - -#include "DNA_particle_types.h" -#include "DNA_view3d_types.h" - -#include "BKE_icons.h" -#include "BKE_idprop.h" -#include "BKE_main.h" -#include "BKE_particle.h" - -#include "GPU_shader.h" - -#include "IMB_imbuf.h" -#include "IMB_imbuf_types.h" - -#include "UI_resources.h" -#include "UI_interface_icons.h" - -#include "DRW_render.h" - -#include "DEG_depsgraph_query.h" - -#include "clay_engine.h" - -#ifdef WITH_CLAY_ENGINE -#include "../eevee/eevee_lut.h" /* TODO find somewhere to share blue noise Table */ - -/* Shaders */ - -#define CLAY_ENGINE "BLENDER_CLAY" - -#define MAX_CLAY_MAT 512 /* 512 = 9 bit material id */ - -#define SHADER_DEFINES_NO_AO \ - "#define MAX_MATERIAL " STRINGIFY(MAX_CLAY_MAT) "\n" \ - "#define USE_ROTATION\n" \ - "#define USE_HSV\n" - -#define SHADER_DEFINES \ - SHADER_DEFINES_NO_AO \ - "#define USE_AO\n" - -extern char datatoc_clay_frag_glsl[]; -extern char datatoc_clay_prepass_frag_glsl[]; -extern char datatoc_clay_copy_glsl[]; -extern char datatoc_clay_vert_glsl[]; -extern char datatoc_clay_fxaa_glsl[]; -extern char datatoc_clay_particle_vert_glsl[]; -extern char datatoc_clay_particle_strand_frag_glsl[]; -extern char datatoc_ssao_alchemy_glsl[]; -extern char datatoc_common_fxaa_lib_glsl[]; - -/* *********** LISTS *********** */ - -/** - * UBOs data needs to be 16 byte aligned (size of vec4) - * - * Reminder: float, int, bool are 4 bytes - * - * \note struct is expected to be initialized with all pad-bits zero'd - * so we can use 'memcmp' to check for duplicates. Possibly hash data later. - */ -typedef struct CLAY_UBO_Material { - float ssao_params_var[4]; - /* - 16 -*/ - float matcap_hsv[3]; - float matcap_id; /* even float encoding have enough precision */ - /* - 16 -*/ - float matcap_rot[2]; - float pad[2]; /* ensure 16 bytes alignement */ -} CLAY_UBO_Material; /* 48 bytes */ -BLI_STATIC_ASSERT_ALIGN(CLAY_UBO_Material, 16) - -typedef struct CLAY_HAIR_UBO_Material { - float hair_randomness; - float matcap_id; - float matcap_rot[2]; - float matcap_hsv[3]; - float pad; -} CLAY_HAIR_UBO_Material; /* 32 bytes */ -BLI_STATIC_ASSERT_ALIGN(CLAY_HAIR_UBO_Material, 16) - -typedef struct CLAY_UBO_Storage { - CLAY_UBO_Material materials[MAX_CLAY_MAT]; -} CLAY_UBO_Storage; - -typedef struct CLAY_HAIR_UBO_Storage { - CLAY_HAIR_UBO_Material materials[MAX_CLAY_MAT]; -} CLAY_HAIR_UBO_Storage; - -/* GPUViewport.storage - * Is freed everytime the viewport engine changes */ -typedef struct CLAY_Storage { - /* Materials Parameter UBO */ - CLAY_UBO_Storage mat_storage; - CLAY_HAIR_UBO_Storage hair_mat_storage; - int ubo_current_id; - int hair_ubo_current_id; - DRWShadingGroup *shgrps[MAX_CLAY_MAT]; - DRWShadingGroup *shgrps_flat[MAX_CLAY_MAT]; - DRWShadingGroup *shgrps_pre[MAX_CLAY_MAT]; - DRWShadingGroup *shgrps_pre_flat[MAX_CLAY_MAT]; - DRWShadingGroup *hair_shgrps[MAX_CLAY_MAT]; -} CLAY_Storage; - -typedef struct CLAY_StorageList { - struct CLAY_Storage *storage; - struct CLAY_PrivateData *g_data; -} CLAY_StorageList; - -typedef struct CLAY_FramebufferList { - struct GPUFrameBuffer *antialias_fb; - struct GPUFrameBuffer *prepass_fb; -} CLAY_FramebufferList; - -typedef struct CLAY_PassList { - struct DRWPass *clay_ps; - struct DRWPass *clay_cull_ps; - struct DRWPass *clay_flat_ps; - struct DRWPass *clay_flat_cull_ps; - struct DRWPass *clay_pre_ps; - struct DRWPass *clay_pre_cull_ps; - struct DRWPass *clay_flat_pre_ps; - struct DRWPass *clay_flat_pre_cull_ps; - struct DRWPass *clay_deferred_ps; - struct DRWPass *fxaa_ps; - struct DRWPass *copy_ps; - struct DRWPass *hair_pass; -} CLAY_PassList; - - -typedef struct CLAY_Data { - void *engine_type; - CLAY_FramebufferList *fbl; - DRWViewportEmptyList *txl; - CLAY_PassList *psl; - CLAY_StorageList *stl; -} CLAY_Data; - -typedef struct CLAY_ViewLayerData { - struct GPUTexture *jitter_tx; - struct GPUUniformBuffer *mat_ubo; - struct GPUUniformBuffer *matcaps_ubo; - struct GPUUniformBuffer *hair_mat_ubo; - struct GPUUniformBuffer *sampling_ubo; - int cached_sample_num; -} CLAY_ViewLayerData; - -/* *********** STATIC *********** */ - -static struct { - /* Shading Pass */ - struct GPUShader *clay_sh; - struct GPUShader *clay_flat_sh; - struct GPUShader *clay_prepass_flat_sh; - struct GPUShader *clay_prepass_sh; - struct GPUShader *clay_deferred_shading_sh; - struct GPUShader *fxaa_sh; - struct GPUShader *copy_sh; - struct GPUShader *hair_sh; - /* Matcap textures */ - struct GPUTexture *matcap_array; - float matcap_colors[24][4]; - /* Just a serie of int from 0 to MAX_CLAY_MAT-1 */ - int ubo_mat_idxs[MAX_CLAY_MAT]; - /* To avoid useless texture and ubo binds. */ - bool first_shgrp; -} e_data = {NULL}; /* Engine data */ - -typedef struct CLAY_PrivateData { - DRWShadingGroup *depth_shgrp; - DRWShadingGroup *depth_shgrp_select; - DRWShadingGroup *depth_shgrp_active; - DRWShadingGroup *depth_shgrp_cull; - DRWShadingGroup *depth_shgrp_cull_select; - DRWShadingGroup *depth_shgrp_cull_active; - /* Deferred shading */ - struct GPUTexture *depth_tx; /* ref only, not alloced */ - struct GPUTexture *normal_tx; /* ref only, not alloced */ - struct GPUTexture *id_tx; /* ref only, not alloced */ - struct GPUTexture *color_copy; /* ref only, not alloced */ - bool enable_deferred_path; - /* Ssao */ - float winmat[4][4]; - float viewvecs[3][4]; - float ssao_params[4]; -} CLAY_PrivateData; /* Transient data */ - -/* Functions */ - -static void clay_view_layer_data_free(void *storage) -{ - CLAY_ViewLayerData *sldata = (CLAY_ViewLayerData *)storage; - - DRW_UBO_FREE_SAFE(sldata->mat_ubo); - DRW_UBO_FREE_SAFE(sldata->matcaps_ubo); - DRW_UBO_FREE_SAFE(sldata->hair_mat_ubo); - DRW_UBO_FREE_SAFE(sldata->sampling_ubo); - DRW_TEXTURE_FREE_SAFE(sldata->jitter_tx); -} - -static CLAY_ViewLayerData *CLAY_view_layer_data_get(void) -{ - CLAY_ViewLayerData **sldata = (CLAY_ViewLayerData **)DRW_view_layer_engine_data_ensure( - &draw_engine_clay_type, &clay_view_layer_data_free); - - if (*sldata == NULL) { - *sldata = MEM_callocN(sizeof(**sldata), "CLAY_ViewLayerData"); - } - - return *sldata; -} - -static void add_icon_to_rect(PreviewImage *prv, float *final_rect, int layer) -{ - int image_size = prv->w[0] * prv->h[0]; - float *new_rect = &final_rect[image_size * 4 * layer]; - - IMB_buffer_float_from_byte(new_rect, (unsigned char *)prv->rect[0], IB_PROFILE_SRGB, IB_PROFILE_SRGB, - false, prv->w[0], prv->h[0], prv->w[0], prv->w[0]); - - /* Find overall color */ - for (int y = 0; y < 4; ++y) { - for (int x = 0; x < 4; ++x) { - e_data.matcap_colors[layer][0] += new_rect[y * 512 * 128 * 4 + x * 128 * 4 + 0]; - e_data.matcap_colors[layer][1] += new_rect[y * 512 * 128 * 4 + x * 128 * 4 + 1]; - e_data.matcap_colors[layer][2] += new_rect[y * 512 * 128 * 4 + x * 128 * 4 + 2]; - } - } - - e_data.matcap_colors[layer][0] /= 16.0f * 2.0f; /* the * 2 is to darken for shadows */ - e_data.matcap_colors[layer][1] /= 16.0f * 2.0f; - e_data.matcap_colors[layer][2] /= 16.0f * 2.0f; -} - -static struct GPUTexture *load_matcaps(PreviewImage *prv[24], int nbr) -{ - struct GPUTexture *tex; - int w = prv[0]->w[0]; - int h = prv[0]->h[0]; - float *final_rect = MEM_callocN(sizeof(float) * 4 * w * h * nbr, "Clay Matcap array rect"); - - for (int i = 0; i < nbr; ++i) { - add_icon_to_rect(prv[i], final_rect, i); - BKE_previewimg_free(&prv[i]); - } - - tex = DRW_texture_create_2D_array(w, h, nbr, GPU_RGBA8, DRW_TEX_FILTER, final_rect); - MEM_freeN(final_rect); - - return tex; -} - -static int matcap_to_index(int matcap) -{ - return matcap - 1; -} - -/* Using Hammersley distribution */ -static float *create_disk_samples(int num_samples) -{ - /* vec4 to ensure memory alignment. */ - float (*texels)[4] = MEM_mallocN(sizeof(float[4]) * num_samples, "concentric_tex"); - const float num_samples_inv = 1.0f / num_samples; - - for (int i = 0; i < num_samples; i++) { - float r = (i + 0.5f) * num_samples_inv; - double dphi; - BLI_hammersley_1D(i, &dphi); - - float phi = (float)dphi * 2.0f * M_PI; - texels[i][0] = cosf(phi); - texels[i][1] = sinf(phi); - /* This deliberatly distribute more samples - * at the center of the disk (and thus the shadow). */ - texels[i][2] = r; - } - - return (float *)texels; -} - -static struct GPUTexture *create_jitter_texture(int num_samples) -{ - float jitter[64 * 64][3]; - const float num_samples_inv = 1.0f / num_samples; - - for (int i = 0; i < 64 * 64; i++) { - float phi = blue_noise[i][0] * 2.0f * M_PI; - /* This rotate the sample per pixels */ - jitter[i][0] = cosf(phi); - jitter[i][1] = sinf(phi); - /* This offset the sample along it's direction axis (reduce banding) */ - float bn = blue_noise[i][1] - 0.5f; - CLAMP(bn, -0.499f, 0.499f); /* fix fireflies */ - jitter[i][2] = bn * num_samples_inv; - } - - UNUSED_VARS(bsdf_split_sum_ggx, btdf_split_sum_ggx, ltc_mag_ggx, ltc_mat_ggx, ltc_disk_integral); - - return DRW_texture_create_2D(64, 64, GPU_RGB16F, DRW_TEX_FILTER | DRW_TEX_WRAP, &jitter[0][0]); -} - -static void clay_engine_init(void *vedata) -{ - CLAY_StorageList *stl = ((CLAY_Data *)vedata)->stl; - CLAY_FramebufferList *fbl = ((CLAY_Data *)vedata)->fbl; - CLAY_ViewLayerData *sldata = CLAY_view_layer_data_get(); - DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); - - /* Create Texture Array */ - if (!e_data.matcap_array) { - PreviewImage *prv[24]; /* For now use all of the 24 internal matcaps */ - const int num_matcap = ARRAY_SIZE(prv); - - /* TODO only load used matcaps */ - for (int i = 0; i < num_matcap; ++i) { - prv[i] = UI_icon_to_preview((int)ICON_MATCAP_01 + i); - } - - e_data.matcap_array = load_matcaps(prv, num_matcap); - } - - /* Shading pass */ - if (!e_data.clay_sh) { - char *matcap_with_ao = BLI_string_joinN( - datatoc_clay_frag_glsl, - datatoc_ssao_alchemy_glsl); - - e_data.clay_sh = DRW_shader_create( - datatoc_clay_vert_glsl, NULL, datatoc_clay_frag_glsl, - SHADER_DEFINES_NO_AO); - e_data.clay_flat_sh = DRW_shader_create( - datatoc_clay_vert_glsl, NULL, datatoc_clay_frag_glsl, - SHADER_DEFINES_NO_AO - "#define USE_FLAT_NORMAL\n"); - - e_data.clay_prepass_sh = DRW_shader_create( - datatoc_clay_vert_glsl, NULL, datatoc_clay_prepass_frag_glsl, - SHADER_DEFINES); - e_data.clay_prepass_flat_sh = DRW_shader_create( - datatoc_clay_vert_glsl, NULL, datatoc_clay_prepass_frag_glsl, - SHADER_DEFINES - "#define USE_FLAT_NORMAL\n"); - - e_data.clay_deferred_shading_sh = DRW_shader_create_fullscreen( - matcap_with_ao, - SHADER_DEFINES - "#define DEFERRED_SHADING\n"); - - MEM_freeN(matcap_with_ao); - - char *fxaa_str = BLI_string_joinN( - datatoc_common_fxaa_lib_glsl, - datatoc_clay_fxaa_glsl); - - e_data.fxaa_sh = DRW_shader_create_fullscreen(fxaa_str, NULL); - - MEM_freeN(fxaa_str); - - e_data.copy_sh = DRW_shader_create_fullscreen(datatoc_clay_copy_glsl, NULL); - } - - if (!stl->storage) { - stl->storage = MEM_callocN(sizeof(CLAY_Storage), "CLAY_Storage"); - } - - if (!stl->g_data) { - stl->g_data = MEM_mallocN(sizeof(*stl->g_data), "CLAY_PrivateStorage"); - } - - CLAY_PrivateData *g_data = stl->g_data; - - if (!sldata->mat_ubo) { - sldata->mat_ubo = DRW_uniformbuffer_create(sizeof(CLAY_UBO_Storage), NULL); - } - - if (!sldata->hair_mat_ubo) { - sldata->hair_mat_ubo = DRW_uniformbuffer_create(sizeof(CLAY_HAIR_UBO_Storage), NULL); - } - - if (!sldata->matcaps_ubo) { - sldata->matcaps_ubo = DRW_uniformbuffer_create(sizeof(e_data.matcap_colors), e_data.matcap_colors); - } - - if (e_data.ubo_mat_idxs[1] == 0) { - /* Just int to have pointers to them */ - for (int i = 0; i < MAX_CLAY_MAT; ++i) { - e_data.ubo_mat_idxs[i] = i; - } - } - - /* FBO setup */ - { - const float *viewport_size = DRW_viewport_size_get(); - const int size[2] = {(int)viewport_size[0], (int)viewport_size[1]}; - - g_data->normal_tx = DRW_texture_pool_query_2D(size[0], size[1], GPU_RG8, &draw_engine_clay_type); - g_data->id_tx = DRW_texture_pool_query_2D(size[0], size[1], GPU_R16UI, &draw_engine_clay_type); - - GPU_framebuffer_ensure_config(&fbl->prepass_fb, { - GPU_ATTACHMENT_TEXTURE(dtxl->depth), - GPU_ATTACHMENT_TEXTURE(g_data->normal_tx), - GPU_ATTACHMENT_TEXTURE(g_data->id_tx) - }); - - /* For FXAA */ - /* TODO(fclem): OPTI: we could merge normal_tx and id_tx into a GPU_RGBA8 - * and reuse it for the fxaa target. */ - g_data->color_copy = DRW_texture_pool_query_2D(size[0], size[1], GPU_RGBA8, &draw_engine_clay_type); - - GPU_framebuffer_ensure_config(&fbl->antialias_fb, { - GPU_ATTACHMENT_NONE, - GPU_ATTACHMENT_TEXTURE(g_data->color_copy) - }); - } - - /* SSAO setup */ - { - const DRWContextState *draw_ctx = DRW_context_state_get(); - Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph); - const int ssao_samples = scene_eval->display.matcap_ssao_samples; - - float invproj[4][4]; - float dfdyfacs[2]; - const bool is_persp = DRW_viewport_is_persp_get(); - /* view vectors for the corners of the view frustum. - * Can be used to recreate the world space position easily */ - float viewvecs[3][4] = { - {-1.0f, -1.0f, -1.0f, 1.0f}, - {1.0f, -1.0f, -1.0f, 1.0f}, - {-1.0f, 1.0f, -1.0f, 1.0f} - }; - int i; - const float *size = DRW_viewport_size_get(); - - DRW_state_dfdy_factors_get(dfdyfacs); - - g_data->ssao_params[0] = ssao_samples; - g_data->ssao_params[1] = size[0] / 64.0; - g_data->ssao_params[2] = size[1] / 64.0; - g_data->ssao_params[3] = dfdyfacs[1]; /* dfdy sign for offscreen */ - - /* invert the view matrix */ - DRW_viewport_matrix_get(g_data->winmat, DRW_MAT_WIN); - invert_m4_m4(invproj, g_data->winmat); - - /* convert the view vectors to view space */ - for (i = 0; i < 3; i++) { - mul_m4_v4(invproj, viewvecs[i]); - /* normalized trick see: - * http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer */ - mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][3]); - if (is_persp) - mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][2]); - viewvecs[i][3] = 1.0; - - copy_v4_v4(g_data->viewvecs[i], viewvecs[i]); - } - - /* we need to store the differences */ - g_data->viewvecs[1][0] -= g_data->viewvecs[0][0]; - g_data->viewvecs[1][1] = g_data->viewvecs[2][1] - g_data->viewvecs[0][1]; - - /* calculate a depth offset as well */ - if (!is_persp) { - float vec_far[] = {-1.0f, -1.0f, 1.0f, 1.0f}; - mul_m4_v4(invproj, vec_far); - mul_v3_fl(vec_far, 1.0f / vec_far[3]); - g_data->viewvecs[1][2] = vec_far[2] - g_data->viewvecs[0][2]; - } - - /* AO Samples Tex */ - if (sldata->sampling_ubo && (sldata->cached_sample_num != ssao_samples)) { - DRW_UBO_FREE_SAFE(sldata->sampling_ubo); - DRW_TEXTURE_FREE_SAFE(sldata->jitter_tx); - } - - if (sldata->sampling_ubo == NULL) { - float *samples = create_disk_samples(ssao_samples); - sldata->jitter_tx = create_jitter_texture(ssao_samples); - sldata->sampling_ubo = DRW_uniformbuffer_create(sizeof(float[4]) * ssao_samples, samples); - sldata->cached_sample_num = ssao_samples; - MEM_freeN(samples); - } - } -} - -static DRWShadingGroup *CLAY_shgroup_create(DRWPass *pass, GPUShader *sh, int id) -{ - CLAY_ViewLayerData *sldata = CLAY_view_layer_data_get(); - DRWShadingGroup *grp = DRW_shgroup_create(sh, pass); - DRW_shgroup_uniform_int(grp, "mat_id", &e_data.ubo_mat_idxs[id], 1); - if (e_data.first_shgrp) { - DRW_shgroup_uniform_texture_persistent(grp, "matcaps", e_data.matcap_array); - DRW_shgroup_uniform_block_persistent(grp, "material_block", sldata->mat_ubo); - DRW_shgroup_uniform_block_persistent(grp, "matcaps_block", sldata->matcaps_ubo); - } - return grp; -} - -static DRWShadingGroup *CLAY_shgroup_deferred_prepass_create(DRWPass *pass, GPUShader *sh, int id) -{ - DRWShadingGroup *grp = DRW_shgroup_create(sh, pass); - DRW_shgroup_uniform_int(grp, "mat_id", &e_data.ubo_mat_idxs[id], 1); - - return grp; -} - -static DRWShadingGroup *CLAY_shgroup_deferred_shading_create(DRWPass *pass, CLAY_PrivateData *g_data) -{ - CLAY_ViewLayerData *sldata = CLAY_view_layer_data_get(); - DRWShadingGroup *grp = DRW_shgroup_create(e_data.clay_deferred_shading_sh, pass); - DRW_shgroup_uniform_texture_ref(grp, "depthtex", &g_data->depth_tx); - DRW_shgroup_uniform_texture_ref(grp, "normaltex", &g_data->normal_tx); - DRW_shgroup_uniform_texture_ref(grp, "idtex", &g_data->id_tx); - DRW_shgroup_uniform_texture(grp, "matcaps", e_data.matcap_array); - DRW_shgroup_uniform_texture(grp, "ssao_jitter", sldata->jitter_tx); - DRW_shgroup_uniform_block(grp, "samples_block", sldata->sampling_ubo); - DRW_shgroup_uniform_block(grp, "material_block", sldata->mat_ubo); - DRW_shgroup_uniform_block(grp, "matcaps_block", sldata->matcaps_ubo); - /* TODO put in ubo */ - DRW_shgroup_uniform_mat4(grp, "WinMatrix", g_data->winmat); - DRW_shgroup_uniform_vec2(grp, "invscreenres", DRW_viewport_invert_size_get(), 1); - DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)g_data->viewvecs, 3); - DRW_shgroup_uniform_vec4(grp, "ssao_params", g_data->ssao_params, 1); - return grp; -} - -static DRWShadingGroup *CLAY_hair_shgroup_create(DRWPass *pass, int id) -{ - CLAY_ViewLayerData *sldata = CLAY_view_layer_data_get(); - - if (!e_data.hair_sh) { - e_data.hair_sh = DRW_shader_create( - datatoc_clay_particle_vert_glsl, NULL, datatoc_clay_particle_strand_frag_glsl, - "#define MAX_MATERIAL " STRINGIFY(MAX_CLAY_MAT) "\n" ); - } - - DRWShadingGroup *grp = DRW_shgroup_create(e_data.hair_sh, pass); - DRW_shgroup_uniform_texture(grp, "matcaps", e_data.matcap_array); - DRW_shgroup_uniform_block(grp, "material_block", sldata->mat_ubo); - DRW_shgroup_uniform_int(grp, "mat_id", &e_data.ubo_mat_idxs[id], 1); - - return grp; -} - -static int search_mat_to_ubo(CLAY_Storage *storage, const CLAY_UBO_Material *mat_ubo_test) -{ - /* For now just use a linear search and test all parameters */ - /* TODO make a hash table */ - for (int i = 0; i < storage->ubo_current_id; ++i) { - CLAY_UBO_Material *ubo = &storage->mat_storage.materials[i]; - if (memcmp(ubo, mat_ubo_test, sizeof(*mat_ubo_test)) == 0) { - return i; - } - } - - return -1; -} - -static int search_hair_mat_to_ubo(CLAY_Storage *storage, const CLAY_HAIR_UBO_Material *hair_mat_ubo_test) -{ - /* For now just use a linear search and test all parameters */ - /* TODO make a hash table */ - for (int i = 0; i < storage->hair_ubo_current_id; ++i) { - CLAY_HAIR_UBO_Material *ubo = &storage->hair_mat_storage.materials[i]; - if (memcmp(ubo, hair_mat_ubo_test, sizeof(*hair_mat_ubo_test)) == 0) { - return i; - } - } - - return -1; -} - -static int push_mat_to_ubo(CLAY_Storage *storage, const CLAY_UBO_Material *mat_ubo_test) -{ - int id = storage->ubo_current_id++; - id = min_ii(MAX_CLAY_MAT, id); - storage->mat_storage.materials[id] = *mat_ubo_test; - return id; -} - -static int push_hair_mat_to_ubo(CLAY_Storage *storage, const CLAY_HAIR_UBO_Material *hair_mat_ubo_test) -{ - int id = storage->hair_ubo_current_id++; - id = min_ii(MAX_CLAY_MAT, id); - storage->hair_mat_storage.materials[id] = *hair_mat_ubo_test; - return id; -} - -static int mat_in_ubo(CLAY_Storage *storage, const CLAY_UBO_Material *mat_ubo_test) -{ - /* Search material in UBO */ - int id = search_mat_to_ubo(storage, mat_ubo_test); - - /* if not found create it */ - if (id == -1) { - id = push_mat_to_ubo(storage, mat_ubo_test); - } - - return id; -} - -static int hair_mat_in_ubo(CLAY_Storage *storage, const CLAY_HAIR_UBO_Material *hair_mat_ubo_test) -{ - /* Search material in UBO */ - int id = search_hair_mat_to_ubo(storage, hair_mat_ubo_test); - - /* if not found create it */ - if (id == -1) { - id = push_hair_mat_to_ubo(storage, hair_mat_ubo_test); - } - - return id; -} - -static void ubo_mat_from_object(CLAY_Storage *storage, Object *UNUSED(ob), bool *r_needs_ao, int *r_id) -{ - const DRWContextState *draw_ctx = DRW_context_state_get(); - const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph); - - const int matcap_icon = scene_eval->display.matcap_icon; - const float matcap_rot = scene_eval->display.matcap_rotation; - const float matcap_hue = scene_eval->display.matcap_hue; - const float matcap_sat = scene_eval->display.matcap_saturation; - const float matcap_val = scene_eval->display.matcap_value; - const float ssao_distance = scene_eval->display.matcap_ssao_distance; - const float ssao_factor_cavity = scene_eval->display.matcap_ssao_factor_cavity; - const float ssao_factor_edge = scene_eval->display.matcap_ssao_factor_edge; - const float ssao_attenuation = scene_eval->display.matcap_ssao_attenuation; - - CLAY_UBO_Material r_ubo = {{0.0f}}; - - if (((ssao_factor_cavity > 0.0) || (ssao_factor_edge > 0.0)) && - (ssao_distance > 0.0)) - { - *r_needs_ao = true; - - r_ubo.ssao_params_var[0] = ssao_distance; - r_ubo.ssao_params_var[1] = ssao_factor_cavity; - r_ubo.ssao_params_var[2] = ssao_factor_edge; - r_ubo.ssao_params_var[3] = ssao_attenuation; - } - else { - *r_needs_ao = false; - } - - r_ubo.matcap_rot[0] = cosf(matcap_rot * 3.14159f * 2.0f); - r_ubo.matcap_rot[1] = sinf(matcap_rot * 3.14159f * 2.0f); - - r_ubo.matcap_hsv[0] = matcap_hue + 0.5f; - r_ubo.matcap_hsv[1] = matcap_sat * 2.0f; - r_ubo.matcap_hsv[2] = matcap_val * 2.0f; - - r_ubo.matcap_id = matcap_to_index(matcap_icon); - - *r_id = mat_in_ubo(storage, &r_ubo); -} - -static void hair_ubo_mat_from_object(Object *UNUSED(ob), CLAY_HAIR_UBO_Material *r_ubo) -{ - const DRWContextState *draw_ctx = DRW_context_state_get(); - const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph); - - const int matcap_icon = scene_eval->display.matcap_icon; - const float matcap_rot = scene_eval->display.matcap_rotation; - const float matcap_hue = scene_eval->display.matcap_hue; - const float matcap_sat = scene_eval->display.matcap_saturation; - const float matcap_val = scene_eval->display.matcap_value; - const float hair_randomness = scene_eval->display.matcap_hair_brightness_randomness; - - memset(r_ubo, 0x0, sizeof(*r_ubo)); - - r_ubo->matcap_rot[0] = cosf(matcap_rot * 3.14159f * 2.0f); - r_ubo->matcap_rot[1] = sinf(matcap_rot * 3.14159f * 2.0f); - r_ubo->matcap_hsv[0] = matcap_hue + 0.5f; - r_ubo->matcap_hsv[1] = matcap_sat * 2.0f; - r_ubo->matcap_hsv[2] = matcap_val * 2.0f; - r_ubo->hair_randomness = hair_randomness; - r_ubo->matcap_id = matcap_to_index(matcap_icon); -} - -static DRWShadingGroup *CLAY_object_shgrp_get(CLAY_Data *vedata, Object *ob, bool use_flat, bool cull) -{ - bool prepass; int id; - CLAY_PassList *psl = vedata->psl; - CLAY_Storage *storage = vedata->stl->storage; - DRWShadingGroup **shgrps; - DRWPass *pass; GPUShader *sh; - - ubo_mat_from_object(storage, ob, &prepass, &id); - - if (prepass) { - if (use_flat) { - shgrps = storage->shgrps_pre_flat; - pass = (cull) ? psl->clay_flat_pre_cull_ps : psl->clay_flat_pre_ps; - sh = e_data.clay_prepass_flat_sh; - } - else { - shgrps = storage->shgrps_pre; - pass = (cull) ? psl->clay_pre_cull_ps : psl->clay_pre_ps; - sh = e_data.clay_prepass_sh; - } - - if (shgrps[id] == NULL) { - shgrps[id] = CLAY_shgroup_deferred_prepass_create(pass, sh, id); - } - - vedata->stl->g_data->enable_deferred_path = true; - } - else { - if (use_flat) { - shgrps = storage->shgrps_flat; - pass = (cull) ? psl->clay_flat_cull_ps : psl->clay_flat_ps; - sh = e_data.clay_flat_sh; - } - else { - shgrps = storage->shgrps; - pass = (cull) ? psl->clay_cull_ps : psl->clay_ps; - sh = e_data.clay_sh; - } - - if (shgrps[id] == NULL) { - shgrps[id] = CLAY_shgroup_create(pass, sh, id); - e_data.first_shgrp = false; - } - } - - return shgrps[id]; -} - -static DRWShadingGroup *CLAY_hair_shgrp_get( - CLAY_Data *UNUSED(vedata), Object *ob, CLAY_StorageList *stl, CLAY_PassList *psl) -{ - DRWShadingGroup **hair_shgrps = stl->storage->hair_shgrps; - - CLAY_HAIR_UBO_Material hair_mat_ubo_test; - hair_ubo_mat_from_object(ob, &hair_mat_ubo_test); - - int hair_id = hair_mat_in_ubo(stl->storage, &hair_mat_ubo_test); - - if (hair_shgrps[hair_id] == NULL) { - hair_shgrps[hair_id] = CLAY_hair_shgroup_create(psl->hair_pass, hair_id); - } - - return hair_shgrps[hair_id]; -} - -static void clay_cache_init(void *vedata) -{ - DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); - CLAY_PassList *psl = ((CLAY_Data *)vedata)->psl; - CLAY_StorageList *stl = ((CLAY_Data *)vedata)->stl; - - /* Disable AO unless a material needs it. */ - stl->g_data->enable_deferred_path = false; - - /* Reset UBO datas, shgrp pointers and material id counters. */ - memset(stl->storage, 0, sizeof(*stl->storage)); - e_data.first_shgrp = true; - - /* Solid Passes */ - { - DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL; - psl->clay_ps = DRW_pass_create("Clay", state); - psl->clay_cull_ps = DRW_pass_create("Clay Culled", state | DRW_STATE_CULL_BACK); - psl->clay_flat_ps = DRW_pass_create("Clay Flat", state); - psl->clay_flat_cull_ps = DRW_pass_create("Clay Flat Culled", state | DRW_STATE_CULL_BACK); - - DRWState prepass_state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL; - DRWState prepass_cull_state = prepass_state | DRW_STATE_CULL_BACK; - psl->clay_pre_ps = DRW_pass_create("Clay Deferred Pre", prepass_state); - psl->clay_pre_cull_ps = DRW_pass_create("Clay Deferred Pre Culled", prepass_cull_state); - psl->clay_flat_pre_ps = DRW_pass_create("Clay Deferred Flat Pre", prepass_state); - psl->clay_flat_pre_cull_ps = DRW_pass_create("Clay Deferred Flat Pre Culled", prepass_cull_state); - - psl->clay_deferred_ps = DRW_pass_create("Clay Deferred Shading", DRW_STATE_WRITE_COLOR); - DRWShadingGroup *grp = CLAY_shgroup_deferred_shading_create(psl->clay_deferred_ps, stl->g_data); - DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); - } - - /* Hair Pass */ - { - psl->hair_pass = DRW_pass_create( - "Hair Pass", - DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_WIRE); - } - - { - psl->fxaa_ps = DRW_pass_create("Fxaa", DRW_STATE_WRITE_COLOR); - DRWShadingGroup *grp = DRW_shgroup_create(e_data.fxaa_sh, psl->fxaa_ps); - DRW_shgroup_uniform_texture_ref(grp, "colortex", &dtxl->color); - DRW_shgroup_uniform_vec2(grp, "invscreenres", DRW_viewport_invert_size_get(), 1); - DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); - - psl->copy_ps = DRW_pass_create("Copy", DRW_STATE_WRITE_COLOR); - grp = DRW_shgroup_create(e_data.copy_sh, psl->copy_ps); - DRW_shgroup_uniform_texture_ref(grp, "colortex", &stl->g_data->color_copy); - DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); - } -} - -static void clay_cache_populate_particles(void *vedata, Object *ob) -{ - CLAY_PassList *psl = ((CLAY_Data *)vedata)->psl; - CLAY_StorageList *stl = ((CLAY_Data *)vedata)->stl; - const DRWContextState *draw_ctx = DRW_context_state_get(); - - if (ob == draw_ctx->object_edit) { - return; - } - - for (ParticleSystem *psys = ob->particlesystem.first; psys; psys = psys->next) { - if (!psys_check_enabled(ob, psys, false)) { - continue; - } - if (!DRW_check_psys_visible_within_active_context(ob, psys)) { - continue; - } - ParticleSettings *part = psys->part; - const int draw_as = (part->draw_as == PART_DRAW_REND) ? part->ren_as : part->draw_as; - if (draw_as == PART_DRAW_PATH) { - struct Gwn_Batch *geom = DRW_cache_particles_get_hair(ob, psys, NULL); - DRWShadingGroup *hair_shgrp = CLAY_hair_shgrp_get(vedata, ob, stl, psl); - DRW_shgroup_call_add(hair_shgrp, geom, NULL); - } - } -} - -static void clay_cache_populate(void *vedata, Object *ob) -{ - DRWShadingGroup *clay_shgrp; - - if (!DRW_object_is_renderable(ob)) - return; - - const DRWContextState *draw_ctx = DRW_context_state_get(); - const bool is_active = (ob == draw_ctx->obact); - if (is_active) { - if (DRW_object_is_mode_shade(ob) == true) { - return; - } - } - - /* Handle particles first in case the emitter itself shouldn't be rendered. */ - if (ob->type == OB_MESH) { - clay_cache_populate_particles(vedata, ob); - } - - if (DRW_check_object_visible_within_active_context(ob) == false) { - return; - } - - struct Gwn_Batch *geom = DRW_cache_object_surface_get(ob); - if (geom) { - const bool do_cull = (draw_ctx->v3d && (draw_ctx->v3d->flag2 & V3D_BACKFACE_CULLING)); - const bool is_sculpt_mode = is_active && (draw_ctx->object_mode & OB_MODE_SCULPT) != 0; - const bool use_flat = is_sculpt_mode && DRW_object_is_flat_normal(ob); - - clay_shgrp = CLAY_object_shgrp_get(vedata, ob, use_flat, do_cull); - - if (is_sculpt_mode) { - DRW_shgroup_call_sculpt_add(clay_shgrp, ob, ob->obmat); - } - else { - DRW_shgroup_call_object_add(clay_shgrp, geom, ob); - } - } -} - -static void clay_cache_finish(void *vedata) -{ - CLAY_ViewLayerData *sldata = CLAY_view_layer_data_get(); - CLAY_StorageList *stl = ((CLAY_Data *)vedata)->stl; - - DRW_uniformbuffer_update(sldata->mat_ubo, &stl->storage->mat_storage); - DRW_uniformbuffer_update(sldata->hair_mat_ubo, &stl->storage->hair_mat_storage); -} - -static void clay_draw_scene(void *vedata) -{ - CLAY_StorageList *stl = ((CLAY_Data *)vedata)->stl; - CLAY_PassList *psl = ((CLAY_Data *)vedata)->psl; - CLAY_FramebufferList *fbl = ((CLAY_Data *)vedata)->fbl; - DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); - DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); - stl->g_data->depth_tx = dtxl->depth; - - /* Passes are ordered to have less _potential_ overdraw */ - DRW_draw_pass(psl->clay_cull_ps); - DRW_draw_pass(psl->clay_flat_cull_ps); - DRW_draw_pass(psl->clay_ps); - DRW_draw_pass(psl->clay_flat_ps); - DRW_draw_pass(psl->hair_pass); - - if (stl->g_data->enable_deferred_path) { - GPU_framebuffer_bind(fbl->prepass_fb); - /* We need to clear the id texture unfortunately. */ - const float clear_col[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - GPU_framebuffer_clear_color(fbl->prepass_fb, clear_col); - - DRW_draw_pass(psl->clay_pre_cull_ps); - DRW_draw_pass(psl->clay_flat_pre_cull_ps); - DRW_draw_pass(psl->clay_pre_ps); - DRW_draw_pass(psl->clay_flat_pre_ps); - - GPU_framebuffer_bind(dfbl->color_only_fb); - DRW_draw_pass(psl->clay_deferred_ps); - } - - if (true) { /* Always on for now. We might want a parameter for this. */ - GPU_framebuffer_bind(fbl->antialias_fb); - DRW_draw_pass(psl->fxaa_ps); - - GPU_framebuffer_bind(dfbl->color_only_fb); - DRW_draw_pass(psl->copy_ps); - } -} - -static void clay_engine_free(void) -{ - DRW_SHADER_FREE_SAFE(e_data.clay_sh); - DRW_SHADER_FREE_SAFE(e_data.clay_flat_sh); - DRW_SHADER_FREE_SAFE(e_data.clay_prepass_flat_sh); - DRW_SHADER_FREE_SAFE(e_data.clay_prepass_sh); - DRW_SHADER_FREE_SAFE(e_data.clay_deferred_shading_sh); - DRW_SHADER_FREE_SAFE(e_data.fxaa_sh); - DRW_SHADER_FREE_SAFE(e_data.copy_sh); - DRW_SHADER_FREE_SAFE(e_data.hair_sh); - DRW_TEXTURE_FREE_SAFE(e_data.matcap_array); -} - -static const DrawEngineDataSize clay_data_size = DRW_VIEWPORT_DATA_SIZE(CLAY_Data); - -DrawEngineType draw_engine_clay_type = { - NULL, NULL, - N_("Clay"), - &clay_data_size, - &clay_engine_init, - &clay_engine_free, - &clay_cache_init, - &clay_cache_populate, - &clay_cache_finish, - NULL, - &clay_draw_scene, - NULL, - NULL, - NULL, -}; - -RenderEngineType DRW_engine_viewport_clay_type = { - NULL, NULL, - CLAY_ENGINE, N_("Clay"), RE_INTERNAL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, - &draw_engine_clay_type, - {NULL, NULL, NULL} -}; - - -#undef CLAY_ENGINE - -#endif /* WITH_CLAY_ENGINE */ diff --git a/source/blender/draw/engines/clay/clay_engine.h b/source/blender/draw/engines/clay/clay_engine.h deleted file mode 100644 index b7c9d00c9ae..00000000000 --- a/source/blender/draw/engines/clay/clay_engine.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2016, Blender Foundation. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * Contributor(s): Blender Institute - * - */ - -/** \file clay_engine.h - * \ingroup draw_engine - */ - -#ifndef __CLAY_ENGINE_H__ -#define __CLAY_ENGINE_H__ - -extern DrawEngineType draw_engine_clay_type; -extern RenderEngineType DRW_engine_viewport_clay_type; - -struct IDProperty; - -struct IDProperty *CLAY_render_settings_create(void); - -#endif /* __CLAY_ENGINE_H__ */ diff --git a/source/blender/draw/engines/clay/shaders/clay_copy.glsl b/source/blender/draw/engines/clay/shaders/clay_copy.glsl deleted file mode 100644 index ec462978e67..00000000000 --- a/source/blender/draw/engines/clay/shaders/clay_copy.glsl +++ /dev/null @@ -1,10 +0,0 @@ - -in vec4 uvcoordsvar; -out vec4 fragColor; - -uniform sampler2D colortex; - -void main() -{ - fragColor = texture(colortex, uvcoordsvar.st); -} diff --git a/source/blender/draw/engines/clay/shaders/clay_frag.glsl b/source/blender/draw/engines/clay/shaders/clay_frag.glsl deleted file mode 100644 index 1939e4b735d..00000000000 --- a/source/blender/draw/engines/clay/shaders/clay_frag.glsl +++ /dev/null @@ -1,252 +0,0 @@ -uniform vec2 invscreenres; -uniform mat4 WinMatrix; - -/* Matcap */ -uniform sampler2DArray matcaps; - -/* Screen Space Occlusion */ -/* store the view space vectors for the corners of the view frustum here. - * It helps to quickly reconstruct view space vectors by using uv coordinates, - * see http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer */ -uniform vec4 viewvecs[3]; -uniform vec4 ssao_params; - -uniform sampler2D ssao_jitter; - -/* Material Parameters packed in an UBO */ -struct Material { - vec4 ssao_params_var; - vec4 matcap_hsv_id; - vec4 matcap_rot; /* vec4 to ensure 16 bytes alignement (don't trust compiler) */ -}; - -layout(std140) uniform samples_block { - vec4 ssao_samples[500]; -}; - -layout(std140) uniform matcaps_block { - vec4 matcaps_color[24]; -}; - -layout(std140) uniform material_block { - Material matcaps_param[MAX_MATERIAL]; -}; - -#ifdef DEFERRED_SHADING -uniform sampler2D depthtex; -uniform sampler2D normaltex; -uniform isampler2D idtex; -int mat_id; /* global */ -#else -uniform int mat_id; -#endif - -/* Aliases */ -#define ssao_samples_num ssao_params.x -#define jitter_tilling ssao_params.yz -#define dfdy_sign ssao_params.w - -#define matcap_hsv matcaps_param[mat_id].matcap_hsv_id.xyz -#define matcap_index matcaps_param[mat_id].matcap_hsv_id.w -#define matcap_rotation matcaps_param[mat_id].matcap_rot.xy - -#ifndef DEFERRED_SHADING -# ifdef USE_FLAT_NORMAL -flat in vec3 normal; -# else -in vec3 normal; -# endif -#endif - -out vec4 fragColor; - -/* TODO Move this to SSAO modules */ -/* simple depth reconstruction, see http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer - * we change the factors from the article to fit the OpennGL model. */ -vec3 get_view_space_from_depth(in vec2 uvcoords, in float depth) -{ - if (WinMatrix[3][3] == 0.0) { - /* Perspective */ - float d = 2.0 * depth - 1.0; - - float zview = -WinMatrix[3][2] / (d + WinMatrix[2][2]); - - return zview * (viewvecs[0].xyz + vec3(uvcoords, 0.0) * viewvecs[1].xyz); - } - else { - /* Orthographic */ - vec3 offset = vec3(uvcoords, depth); - - return viewvecs[0].xyz + offset * viewvecs[1].xyz; - } -} - -#ifdef USE_HSV -void rgb_to_hsv(vec3 rgb, out vec3 outcol) -{ - float cmax, cmin, h, s, v, cdelta; - vec3 c; - - cmax = max(rgb[0], max(rgb[1], rgb[2])); - cmin = min(rgb[0], min(rgb[1], rgb[2])); - cdelta = cmax - cmin; - - v = cmax; - if (cmax != 0.0) - s = cdelta / cmax; - else { - s = 0.0; - h = 0.0; - } - - if (s == 0.0) { - h = 0.0; - } - else { - c = (vec3(cmax, cmax, cmax) - rgb.xyz) / cdelta; - - if (rgb.x == cmax) h = c[2] - c[1]; - else if (rgb.y == cmax) h = 2.0 + c[0] - c[2]; - else h = 4.0 + c[1] - c[0]; - - h /= 6.0; - - if (h < 0.0) - h += 1.0; - } - - outcol = vec3(h, s, v); -} - -void hsv_to_rgb(vec3 hsv, out vec3 outcol) -{ - float i, f, p, q, t, h, s, v; - vec3 rgb; - - h = hsv[0]; - s = hsv[1]; - v = hsv[2]; - - if (s == 0.0) { - rgb = vec3(v, v, v); - } - else { - if (h == 1.0) - h = 0.0; - - h *= 6.0; - i = floor(h); - f = h - i; - rgb = vec3(f, f, f); - p = v * (1.0 - s); - q = v * (1.0 - (s * f)); - t = v * (1.0 - (s * (1.0 - f))); - - if (i == 0.0) rgb = vec3(v, t, p); - else if (i == 1.0) rgb = vec3(q, v, p); - else if (i == 2.0) rgb = vec3(p, v, t); - else if (i == 3.0) rgb = vec3(p, q, v); - else if (i == 4.0) rgb = vec3(t, p, v); - else rgb = vec3(v, p, q); - } - - outcol = rgb; -} - -void hue_sat(float hue, float sat, float value, inout vec3 col) -{ - vec3 hsv; - - rgb_to_hsv(col, hsv); - - hsv.x += hue; - hsv.x -= floor(hsv.x); - hsv.y *= sat; - hsv.y = clamp(hsv.y, 0.0, 1.0); - hsv.z *= value; - hsv.z = clamp(hsv.z, 0.0, 1.0); - - hsv_to_rgb(hsv, col); -} -#endif - -#ifdef USE_AO -/* Prototype */ -void ssao_factors( - in float depth, in vec3 normal, in vec3 position, in vec2 screenco, - out float cavities, out float edges); -#endif - -/* From http://aras-p.info/texts/CompactNormalStorage.html - * Using Method #4: Spheremap Transform */ -vec3 normal_decode(vec2 enc) -{ - vec2 fenc = enc * 4.0 - 2.0; - float f = dot(fenc, fenc); - float g = sqrt(1.0 - f / 4.0); - vec3 n; - n.xy = fenc*g; - n.z = 1 - f / 2; - return n; -} - -vec3 shade(vec3 N, vec3 position, float depth, vec2 screenco) -{ -#ifdef USE_ROTATION - /* Rotate texture coordinates */ - vec2 rotY = vec2(-matcap_rotation.y, matcap_rotation.x); - vec2 texco = abs(vec2(dot(N.xy, matcap_rotation), dot(N.xy, rotY)) * .49 + 0.5); -#else - vec2 texco = abs(N.xy * .49 + 0.5); -#endif - vec3 col = texture(matcaps, vec3(texco, matcap_index)).rgb; - -#ifdef USE_AO - float cavity = 0.0, edges = 0.0; - ssao_factors(depth, N, position, screenco, cavity, edges); - - col *= mix(vec3(1.0), matcaps_color[int(matcap_index)].rgb, cavity); -#endif - -#ifdef USE_HSV - hue_sat(matcap_hsv.x, matcap_hsv.y, matcap_hsv.z, col); -#endif - -#ifdef USE_AO - /* Apply highlights after hue shift */ - col *= edges + 1.0; -#endif - - return col; -} - -void main() -{ - vec2 screenco = vec2(gl_FragCoord.xy) * invscreenres; - -#ifdef DEFERRED_SHADING - ivec2 texel = ivec2(gl_FragCoord.xy); - mat_id = texelFetch(idtex, texel, 0).r; - - /* early out (manual stencil test) */ - if (mat_id == 0) - discard; - - float depth = texelFetch(depthtex, texel, 0).r; - vec3 N = normal_decode(texelFetch(normaltex, texel, 0).rg); - /* see the prepass for explanations. */ - if (mat_id < 0) { - N = -N; - } - mat_id = abs(mat_id) - 1; -#else - float depth = gl_FragCoord.z; - vec3 N = normal; -#endif - - vec3 position = get_view_space_from_depth(screenco, depth); - - vec3 col = shade(N, position, depth, screenco); - - fragColor = vec4(col, 1.0); -} diff --git a/source/blender/draw/engines/clay/shaders/clay_fxaa.glsl b/source/blender/draw/engines/clay/shaders/clay_fxaa.glsl deleted file mode 100644 index 924e51421aa..00000000000 --- a/source/blender/draw/engines/clay/shaders/clay_fxaa.glsl +++ /dev/null @@ -1,18 +0,0 @@ - -in vec4 uvcoordsvar; -out vec4 fragColor; - -uniform vec2 invscreenres; -uniform sampler2D colortex; - -void main() -{ - fragColor = vec4(FxaaPixelShader( - uvcoordsvar.st, - colortex, - invscreenres, - 1.0, - 0.166, - 0.0833 - ).rgb, 1.0); -} diff --git a/source/blender/draw/engines/clay/shaders/clay_particle_strand_frag.glsl b/source/blender/draw/engines/clay/shaders/clay_particle_strand_frag.glsl deleted file mode 100644 index 980a1e4690d..00000000000 --- a/source/blender/draw/engines/clay/shaders/clay_particle_strand_frag.glsl +++ /dev/null @@ -1,144 +0,0 @@ - -/* Material Parameters packed in an UBO */ -struct Material { - vec4 one; - vec4 two; -}; - -layout(std140) uniform material_block { - Material shader_param[MAX_MATERIAL]; -}; - -uniform mat4 ProjectionMatrix; -uniform sampler2DArray matcaps; -uniform int mat_id; - -#define randomness shader_param[mat_id].one.x -#define matcap_index shader_param[mat_id].one.y -#define matcap_rotation shader_param[mat_id].one.zw -#define matcap_hsv shader_param[mat_id].two.xyz - -in vec3 tangent; -in vec3 viewPosition; -flat in float colRand; -out vec4 fragColor; - -vec3 rotate(vec3 norm, vec3 ortho, float ang) -{ - return norm * cos(ang) + ortho * sin(ang); -} - -void rgb_to_hsv(vec3 rgb, out vec3 outcol) -{ - float cmax, cmin, h, s, v, cdelta; - vec3 c; - - cmax = max(rgb[0], max(rgb[1], rgb[2])); - cmin = min(rgb[0], min(rgb[1], rgb[2])); - cdelta = cmax - cmin; - - v = cmax; - if (cmax != 0.0) - s = cdelta / cmax; - else { - s = 0.0; - h = 0.0; - } - - if (s == 0.0) { - h = 0.0; - } - else { - c = (vec3(cmax, cmax, cmax) - rgb.xyz) / cdelta; - - if (rgb.x == cmax) h = c[2] - c[1]; - else if (rgb.y == cmax) h = 2.0 + c[0] - c[2]; - else h = 4.0 + c[1] - c[0]; - - h /= 6.0; - - if (h < 0.0) - h += 1.0; - } - - outcol = vec3(h, s, v); -} - -void hsv_to_rgb(vec3 hsv, out vec3 outcol) -{ - float i, f, p, q, t, h, s, v; - vec3 rgb; - - h = hsv[0]; - s = hsv[1]; - v = hsv[2]; - - if (s == 0.0) { - rgb = vec3(v, v, v); - } - else { - if (h == 1.0) - h = 0.0; - - h *= 6.0; - i = floor(h); - f = h - i; - rgb = vec3(f, f, f); - p = v * (1.0 - s); - q = v * (1.0 - (s * f)); - t = v * (1.0 - (s * (1.0 - f))); - - if (i == 0.0) rgb = vec3(v, t, p); - else if (i == 1.0) rgb = vec3(q, v, p); - else if (i == 2.0) rgb = vec3(p, v, t); - else if (i == 3.0) rgb = vec3(p, q, v); - else if (i == 4.0) rgb = vec3(t, p, v); - else rgb = vec3(v, p, q); - } - - outcol = rgb; -} - -void hue_sat(float hue, float sat, float value, inout vec3 col) -{ - vec3 hsv; - - rgb_to_hsv(col, hsv); - - hsv.x += hue; - hsv.x -= floor(hsv.x); - hsv.y *= sat; - hsv.y = clamp(hsv.y, 0.0, 1.0); - hsv.z *= value; - hsv.z = clamp(hsv.z, 0.0, 1.0); - - hsv_to_rgb(hsv, col); -} - -void main() -{ - vec3 viewvec = (ProjectionMatrix[3][3] == 0.0) ? normalize(viewPosition) : vec3(0.0, 0.0, -1.0); - vec3 ortho = normalize(cross(viewvec, tangent)); - vec3 norm = normalize(cross(ortho, tangent)); - - vec3 col = vec3(0); - - vec2 rotY = vec2(-matcap_rotation.y, matcap_rotation.x); - - for (int i = 0; i < 9; i++) { - vec3 rotNorm = rotate(norm, ortho, -0.5 + (i * 0.125)); - vec3 ray = reflect(viewvec, rotNorm); - vec2 texco = abs(vec2(dot(ray.xy, matcap_rotation), dot(ray.xy, rotY)) * .49 + 0.5); - - col += texture(matcaps, vec3(texco, matcap_index)).rgb / 9.0; - } - - hue_sat(matcap_hsv.x, matcap_hsv.y, matcap_hsv.z, col); - - float maxChan = max(max(col.r, col.g), col.b); - - col += (colRand * maxChan * randomness * 1.5) - (maxChan * randomness * 0.75); - - fragColor.rgb = col; - fragColor.a = 1.0; -} diff --git a/source/blender/draw/engines/clay/shaders/clay_particle_vert.glsl b/source/blender/draw/engines/clay/shaders/clay_particle_vert.glsl deleted file mode 100644 index d4c35d14182..00000000000 --- a/source/blender/draw/engines/clay/shaders/clay_particle_vert.glsl +++ /dev/null @@ -1,34 +0,0 @@ - -uniform mat4 ModelViewProjectionMatrix; -uniform mat3 NormalMatrix; -uniform mat4 ModelViewMatrix; - -in vec3 pos; -in vec3 nor; -in int ind; -out vec3 tangent; -out vec3 viewPosition; -flat out float colRand; - -float rand(int s) -{ - int seed = s * 1023423; - - seed = (seed ^ 61) ^ (seed >> 16); - seed *= 9; - seed = seed ^ (seed >> 4); - seed *= 0x27d4eb2d; - seed = seed ^ (seed >> 15); - - float value = float(seed); - value *= 1.0 / 42596.0; - return fract(value); -} - -void main() -{ - gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); - tangent = normalize(NormalMatrix * nor); - viewPosition = (ModelViewMatrix * vec4(pos, 1.0)).xyz; - colRand = rand(ind); -} diff --git a/source/blender/draw/engines/clay/shaders/clay_prepass_frag.glsl b/source/blender/draw/engines/clay/shaders/clay_prepass_frag.glsl deleted file mode 100644 index f30322bc9fe..00000000000 --- a/source/blender/draw/engines/clay/shaders/clay_prepass_frag.glsl +++ /dev/null @@ -1,44 +0,0 @@ -uniform int mat_id; - -#ifdef USE_FLAT_NORMAL -flat in vec3 normal; -#else -in vec3 normal; -#endif - -layout(location = 0) out vec2 outNormals; -layout(location = 1) out int outIndex; - -/* From http://aras-p.info/texts/CompactNormalStorage.html - * Using Method #4: Spheremap Transform */ -vec2 normal_encode(vec3 n) -{ - float p = sqrt(n.z * 8.0 + 8.0); - return n.xy / p + 0.5; -} - -/* 4x4 bayer matrix prepared for 8bit UNORM precision error. */ -#define P(x) (((x + 0.5) * (1.0 / 16.0) - 0.5) * (1.0 / 255.0)) -const vec4 dither_mat[4] = vec4[4]( - vec4( P(0.0), P(8.0), P(2.0), P(10.0)), - vec4(P(12.0), P(4.0), P(14.0), P(6.0)), - vec4( P(3.0), P(11.0), P(1.0), P(9.0)), - vec4(P(15.0), P(7.0), P(13.0), P(5.0)) -); - -void main() { - outIndex = (mat_id + 1); /* 0 is clear color */ - /** - * To fix the normal buffer precision issue for backfaces, - * we invert normals and use the sign of the index buffer - * to tag them, and re-invert in deferred pass. - **/ - vec3 N = (gl_FrontFacing) ? normal : -normal; - outIndex = (gl_FrontFacing) ? outIndex : -outIndex; - - outNormals = normal_encode(N); - - /* Dither the output to fight low quality. */ - ivec2 tx = ivec2(gl_FragCoord.xy) % 4; - outNormals += dither_mat[tx.x][tx.y]; -} diff --git a/source/blender/draw/engines/clay/shaders/clay_vert.glsl b/source/blender/draw/engines/clay/shaders/clay_vert.glsl deleted file mode 100644 index 8f8866b3839..00000000000 --- a/source/blender/draw/engines/clay/shaders/clay_vert.glsl +++ /dev/null @@ -1,17 +0,0 @@ -uniform mat4 ModelViewProjectionMatrix; -uniform mat3 NormalMatrix; - -in vec3 pos; -in vec3 nor; - -#ifdef USE_FLAT_NORMAL -flat out vec3 normal; -#else -out vec3 normal; -#endif - -void main() -{ - normal = normalize(NormalMatrix * nor); - gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); -} diff --git a/source/blender/draw/engines/clay/shaders/ssao_alchemy.glsl b/source/blender/draw/engines/clay/shaders/ssao_alchemy.glsl deleted file mode 100644 index 94e2d6f3c7b..00000000000 --- a/source/blender/draw/engines/clay/shaders/ssao_alchemy.glsl +++ /dev/null @@ -1,82 +0,0 @@ -#define ssao_distance matcaps_param[mat_id].ssao_params_var.x -#define ssao_factor_cavity matcaps_param[mat_id].ssao_params_var.y -#define ssao_factor_edge matcaps_param[mat_id].ssao_params_var.z -#define ssao_attenuation matcaps_param[mat_id].ssao_params_var.w - -/* from The Alchemy screen-space ambient obscurance algorithm - * http://graphics.cs.williams.edu/papers/AlchemyHPG11/VV11AlchemyAO.pdf */ - -void ssao_factors( - in float depth, in vec3 normal, in vec3 position, in vec2 screenco, - out float cavities, out float edges) -{ - cavities = edges = 0.0; - /* early out if there is no need for SSAO */ - if (ssao_factor_cavity == 0.0 && ssao_factor_edge == 0.0) - return; - - /* take the normalized ray direction here */ - vec3 noise = texture(ssao_jitter, screenco.xy * jitter_tilling).rgb; - - /* find the offset in screen space by multiplying a point - * in camera space at the depth of the point by the projection matrix. */ - vec2 offset; - float homcoord = WinMatrix[2][3] * position.z + WinMatrix[3][3]; - offset.x = WinMatrix[0][0] * ssao_distance / homcoord; - offset.y = WinMatrix[1][1] * ssao_distance / homcoord; - /* convert from -1.0...1.0 range to 0.0..1.0 for easy use with texture coordinates */ - offset *= 0.5; - - int num_samples = int(ssao_samples_num); - - /* Note. Putting noise usage here to put some ALU after texture fetch. */ - vec2 rotX = noise.rg; - vec2 rotY = vec2(-rotX.y, rotX.x); - - for (int x = 0; x < num_samples && x < 500; x++) { - /* ssao_samples[x].xy is sample direction (normalized). - * ssao_samples[x].z is sample distance from disk center. */ - - /* Rotate with random direction to get jittered result. */ - vec2 dir_jittered = vec2(dot(ssao_samples[x].xy, rotX), dot(ssao_samples[x].xy, rotY)); - dir_jittered.xy *= ssao_samples[x].z + noise.b; - - vec2 uvcoords = screenco.xy + dir_jittered * offset; - - if (uvcoords.x > 1.0 || uvcoords.x < 0.0 || uvcoords.y > 1.0 || uvcoords.y < 0.0) - continue; - - float depth_new = texture(depthtex, uvcoords).r; - - /* Handle Background case */ - bool is_background = (depth_new == 1.0); - - /* This trick provide good edge effect even if no neighboor is found. */ - vec3 pos_new = get_view_space_from_depth(uvcoords, (is_background) ? depth : depth_new); - - if (is_background) - pos_new.z -= ssao_distance; - - vec3 dir = pos_new - position; - float len = length(dir); - float f_cavities = dot(dir, normal); - float f_edge = -f_cavities; - float f_bias = 0.05 * len + 0.0001; - - float attenuation = 1.0 / (len * (1.0 + len * len * ssao_attenuation)); - - /* use minor bias here to avoid self shadowing */ - if (f_cavities > -f_bias) - cavities += f_cavities * attenuation; - - if (f_edge > f_bias) - edges += f_edge * attenuation; - } - - cavities /= ssao_samples_num; - edges /= ssao_samples_num; - - /* don't let cavity wash out the surface appearance */ - cavities = clamp(cavities * ssao_factor_cavity, 0.0, 1.0); - edges = edges * ssao_factor_edge; -} diff --git a/source/blender/draw/engines/clay/shaders/ssao_groundtruth.glsl b/source/blender/draw/engines/clay/shaders/ssao_groundtruth.glsl deleted file mode 100644 index 9c203a4246c..00000000000 --- a/source/blender/draw/engines/clay/shaders/ssao_groundtruth.glsl +++ /dev/null @@ -1,122 +0,0 @@ -#define ssao_distance matcaps_param[mat_id].ssao_params_var.x -#define ssao_factor_cavity matcaps_param[mat_id].ssao_params_var.y -#define ssao_factor_edge matcaps_param[mat_id].ssao_params_var.z -#define ssao_attenuation matcaps_param[mat_id].ssao_params_var.w - -/* Based on Practical Realtime Strategies for Accurate Indirect Occlusion - * http://blog.selfshadow.com/publications/s2016-shading-course/activision/s2016_pbs_activision_occlusion.pdf - * http://blog.selfshadow.com/publications/s2016-shading-course/activision/s2016_pbs_activision_occlusion.pptx */ - -#define COSINE_WEIGHTING - -float integrate_arc(in float h1, in float h2, in float gamma, in float n_proj_len) -{ - float a = 0.0; -#ifdef COSINE_WEIGHTING - float cos_gamma = cos(gamma); - float sin_gamma_2 = 2.0 * sin(gamma); - a += -cos(2.0 * h1 - gamma) + cos_gamma + h1 * sin_gamma_2; - a += -cos(2.0 * h2 - gamma) + cos_gamma + h2 * sin_gamma_2; - a *= 0.25; /* 1/4 */ - a *= n_proj_len; -#else - /* Uniform weighting (slide 59) */ - a += 1 - cos(h1); - a += 1 - cos(h2); -#endif - return a; -} - -float get_max_horizon(in vec2 co, in vec3 x, in vec3 omega_o, in float h) -{ - if (co.x > 1.0 || co.x < 0.0 || co.y > 1.0 || co.y < 0.0) - return h; - - float depth = texture(depthtex, co).r; - - /* Background case */ - if (depth == 1.0) - return h; - - vec3 s = get_view_space_from_depth(co, depth); /* s View coordinate */ - vec3 omega_s = s - x; - float len = length(omega_s); - - if (len < ssao_distance) { - omega_s /= len; - h = max(h, dot(omega_s, omega_o)); - } - return h; -} - -void ssao_factors( - in float depth, in vec3 normal, in vec3 position, in vec2 screenco, - out float cavities, out float edges) -{ - /* Renaming */ - vec3 omega_o = -normalize(position); /* viewvec */ - vec2 x_ = screenco; /* x^ Screen coordinate */ - vec3 x = position; /* x view space coordinate */ - -#ifdef SPATIAL_DENOISE - float noise_dir = (1.0 / 16.0) * float(((int(gl_FragCoord.x + gl_FragCoord.y) & 0x3) << 2) + (int(gl_FragCoord.x) & 0x3)); - float noise_offset = (1.0 / 4.0) * float(int(gl_FragCoord.y - gl_FragCoord.x) & 0x3); -#else - float noise_dir = (1.0 / 16.0) * float(((int(gl_FragCoord.x + gl_FragCoord.y) & 0x3) << 2) + (int(gl_FragCoord.x) & 0x3)); - float noise_offset = (0.5 / 16.0) + (1.0 / 16.0) * float(((int(gl_FragCoord.x - gl_FragCoord.y) & 0x3) << 2) + (int(gl_FragCoord.x) & 0x3)); -#endif - - const float phi_step = 16.0; - const float theta_step = 16.0; - const float m_pi = 3.14159265358979323846; - vec2 pixel_ratio = vec2(screenres.y / screenres.x, 1.0); - vec2 pixel_size = vec2(1.0) / screenres.xy; - float min_stride = length(pixel_size); - float homcco = WinMatrix[2][3] * position.z + WinMatrix[3][3]; - float n = max(min_stride * theta_step, ssao_distance / homcco); /* Search distance */ - - /* Integral over PI */ - float A = 0.0; - for (float i = 0.0; i < phi_step; i++) { - float phi = m_pi * ((noise_dir + i) / phi_step); - - vec2 t_phi = vec2(cos(phi), sin(phi)); /* Screen space direction */ - - /* Search maximum horizon angles Theta1 and Theta2 */ - float theta1 = -1.0, theta2 = -1.0; /* init at cos(pi) */ - for (float j = 0.0; j < theta_step; j++) { - vec2 s_ = t_phi * pixel_ratio * n * ((j + noise_offset)/ theta_step); /* s^ Screen coordinate */ - vec2 co; - - co = x_ + s_; - theta1 = get_max_horizon(co, x, omega_o, theta1); - - co = x_ - s_; - theta2 = get_max_horizon(co, x, omega_o, theta2); - } - - /* (Slide 54) */ - theta1 = -acos(theta1); - theta2 = acos(theta2); - - /* Projecting Normal to Plane P defined by t_phi and omega_o */ - vec3 h = normalize(cross(vec3(t_phi, 0.0), omega_o)); /* Normal vector to Integration plane */ - vec3 t = cross(h, omega_o); /* Normal vector to plane */ - vec3 n_proj = normal - h * dot(normal, h); - float n_proj_len = length(n_proj); - vec3 n_proj_norm = normalize(n_proj); - - /* Clamping thetas (slide 58) */ - float gamma = sign(dot(n_proj_norm, t)) * acos(dot(normal, omega_o)); /* Angle between view vec and normal */ - theta1 = gamma + max(theta1 - gamma, -m_pi * 0.5); - theta2 = gamma + min(theta2 - gamma, m_pi * 0.5); - - /* Solving inner integral */ - A += integrate_arc(theta1, theta2, gamma, n_proj_len); - } - - A /= phi_step; - - cavities = 1.0 - A; - edges = 0.0; -} diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c index f159bf21d03..d7c6684f086 100644 --- a/source/blender/draw/engines/eevee/eevee_engine.c +++ b/source/blender/draw/engines/eevee/eevee_engine.c @@ -142,7 +142,7 @@ static void eevee_cache_populate(void *vedata, Object *ob) } if (DRW_check_object_visible_within_active_context(ob)) { - if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT)) { + if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL)) { EEVEE_materials_cache_populate(vedata, sldata, ob, &cast_shadow); } else if (!USE_SCENE_LIGHT(draw_ctx->v3d)) { diff --git a/source/blender/draw/engines/eevee/eevee_lookdev.c b/source/blender/draw/engines/eevee/eevee_lookdev.c index 5c626b42ddd..806fb65b8e8 100644 --- a/source/blender/draw/engines/eevee/eevee_lookdev.c +++ b/source/blender/draw/engines/eevee/eevee_lookdev.c @@ -149,12 +149,12 @@ void EEVEE_lookdev_draw_background(EEVEE_Data *vedata) GPUFrameBuffer *fb = effects->final_fb; GPU_framebuffer_bind(fb); - GPU_framebuffer_viewport_set(fb, rect.xmax - viewport_inset_x, 0, viewport_inset_x, viewport_inset_y); + GPU_framebuffer_viewport_set(fb, rect.xmax - viewport_inset_x, rect.ymin, viewport_inset_x, viewport_inset_y); DRW_draw_pass(psl->lookdev_pass); fb = dfbl->depth_only_fb; GPU_framebuffer_bind(fb); - GPU_framebuffer_viewport_set(fb, rect.xmax - viewport_inset_x, 0, viewport_inset_x, viewport_inset_y); + GPU_framebuffer_viewport_set(fb, rect.xmax - viewport_inset_x, rect.ymin, viewport_inset_x, viewport_inset_y); DRW_draw_pass(psl->lookdev_pass); DRW_viewport_matrix_override_unset_all(); diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c index a356c30aece..b262845511a 100644 --- a/source/blender/draw/engines/eevee/eevee_materials.c +++ b/source/blender/draw/engines/eevee/eevee_materials.c @@ -88,7 +88,6 @@ extern char datatoc_ltc_lib_glsl[]; extern char datatoc_bsdf_lut_frag_glsl[]; extern char datatoc_btdf_lut_frag_glsl[]; extern char datatoc_bsdf_common_lib_glsl[]; -extern char datatoc_bsdf_direct_lib_glsl[]; extern char datatoc_bsdf_sampling_lib_glsl[]; extern char datatoc_common_uniforms_lib_glsl[]; extern char datatoc_common_hair_lib_glsl[]; @@ -561,7 +560,6 @@ void EEVEE_materials_init(EEVEE_ViewLayerData *sldata, EEVEE_StorageList *stl, E datatoc_irradiance_lib_glsl, datatoc_lightprobe_lib_glsl, datatoc_ltc_lib_glsl, - datatoc_bsdf_direct_lib_glsl, datatoc_lamps_lib_glsl, /* Add one for each Closure */ datatoc_lit_surface_frag_glsl, @@ -583,7 +581,6 @@ void EEVEE_materials_init(EEVEE_ViewLayerData *sldata, EEVEE_StorageList *stl, E datatoc_irradiance_lib_glsl, datatoc_lightprobe_lib_glsl, datatoc_ltc_lib_glsl, - datatoc_bsdf_direct_lib_glsl, datatoc_lamps_lib_glsl, datatoc_volumetric_lib_glsl, datatoc_volumetric_frag_glsl); @@ -1639,7 +1636,7 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_ViewLayerData *sld const bool is_default_mode_shader = is_sculpt_mode; /* First get materials for this mesh. */ - if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT)) { + if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL)) { const int materials_len = MAX2(1, (is_sculpt_mode_draw ? 1 : ob->totcol)); struct DRWShadingGroup **shgrp_array = BLI_array_alloca(shgrp_array, materials_len); @@ -1717,6 +1714,9 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_ViewLayerData *sld &auto_layer_count); if (mat_geom) { for (int i = 0; i < materials_len; ++i) { + if (mat_geom[i] == NULL) { + continue; + } EEVEE_ObjectEngineData *oedata = NULL; Material *ma = give_current_material(ob, i + 1); diff --git a/source/blender/draw/engines/eevee/eevee_render.c b/source/blender/draw/engines/eevee/eevee_render.c index 76887145ad2..d24551976f9 100644 --- a/source/blender/draw/engines/eevee/eevee_render.c +++ b/source/blender/draw/engines/eevee/eevee_render.c @@ -150,7 +150,7 @@ void EEVEE_render_cache( } if (DRW_check_object_visible_within_active_context(ob)) { - if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT)) { + if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL)) { EEVEE_materials_cache_populate(vedata, sldata, ob, &cast_shadow); } else if (ob->type == OB_LIGHTPROBE) { @@ -423,6 +423,8 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl DRW_render_instance_buffer_finish(); /* Need to be called after DRW_render_instance_buffer_finish() */ + /* Also we weed to have a correct fbo bound for DRW_hair_update */ + GPU_framebuffer_bind(fbl->main_fb); DRW_hair_update(); if ((view_layer->passflag & (SCE_PASS_SUBSURFACE_COLOR | diff --git a/source/blender/draw/engines/eevee/eevee_volumes.c b/source/blender/draw/engines/eevee/eevee_volumes.c index 2d074eea522..560f898b275 100644 --- a/source/blender/draw/engines/eevee/eevee_volumes.c +++ b/source/blender/draw/engines/eevee/eevee_volumes.c @@ -65,7 +65,6 @@ static struct { } e_data = {NULL}; /* Engine data */ extern char datatoc_bsdf_common_lib_glsl[]; -extern char datatoc_bsdf_direct_lib_glsl[]; extern char datatoc_common_uniforms_lib_glsl[]; extern char datatoc_common_view_lib_glsl[]; extern char datatoc_octahedron_lib_glsl[]; @@ -92,7 +91,6 @@ static void eevee_create_shader_volumes(void) datatoc_common_view_lib_glsl, datatoc_common_uniforms_lib_glsl, datatoc_bsdf_common_lib_glsl, - datatoc_bsdf_direct_lib_glsl, datatoc_octahedron_lib_glsl, datatoc_irradiance_lib_glsl, datatoc_lamps_lib_glsl, diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl index a1890433b0f..8b232bf14a4 100644 --- a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl @@ -666,6 +666,13 @@ Closure closure_add(Closure cl1, Closure cl2) return cl; } +Closure closure_emission(vec3 rgb) +{ + Closure cl = CLOSURE_DEFAULT; + cl.emission = rgb; + return cl; +} + #else /* VOLUMETRICS */ struct Closure { @@ -767,6 +774,13 @@ Closure closure_add(Closure cl1, Closure cl2) return cl; } +Closure closure_emission(vec3 rgb) +{ + Closure cl = CLOSURE_DEFAULT; + cl.radiance = rgb; + return cl; +} + # if defined(MESH_SHADER) && !defined(USE_ALPHA_HASH) && !defined(USE_ALPHA_CLIP) && !defined(SHADOW_SHADER) && !defined(USE_MULTIPLY) layout(location = 0) out vec4 fragColor; layout(location = 1) out vec4 ssrNormals; diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_direct_lib.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_direct_lib.glsl deleted file mode 100644 index aad71b3e48e..00000000000 --- a/source/blender/draw/engines/eevee/shaders/bsdf_direct_lib.glsl +++ /dev/null @@ -1,186 +0,0 @@ -/* Bsdf direct light function */ -/* in other word, how materials react to scene lamps */ - -/* Naming convention - * V View vector (normalized) - * N World Normal (normalized) - * L Outgoing Light Vector (Surface to Light in World Space) (normalized) - * Ldist Distance from surface to the light - * W World Pos - */ - -/* ------------ Diffuse ------------- */ - -float direct_diffuse_point(vec3 N, vec4 l_vector) -{ - float dist = l_vector.w; - vec3 L = l_vector.xyz / dist; - float bsdf = max(0.0, dot(N, L)); - bsdf /= dist * dist; - return bsdf; -} - -/* infinitly far away point source, no decay */ -float direct_diffuse_sun(LightData ld, vec3 N) -{ - float bsdf = max(0.0, dot(N, -ld.l_forward)); - bsdf *= M_1_PI; /* Normalize */ - return bsdf; -} - -#ifdef USE_LTC -float direct_diffuse_sphere(LightData ld, vec3 N, vec4 l_vector) -{ - float NL = dot(N, l_vector.xyz / l_vector.w); - - return ltc_evaluate_disk_simple(ld.l_radius / l_vector.w, NL); -} - -float direct_diffuse_rectangle(LightData ld, vec3 N, vec3 V, vec4 l_vector) -{ - vec3 corners[4]; - corners[0] = normalize(l_vector.xyz + ld.l_right * -ld.l_sizex + ld.l_up * ld.l_sizey); - corners[1] = normalize(l_vector.xyz + ld.l_right * -ld.l_sizex + ld.l_up * -ld.l_sizey); - corners[2] = normalize(l_vector.xyz + ld.l_right * ld.l_sizex + ld.l_up * -ld.l_sizey); - corners[3] = normalize(l_vector.xyz + ld.l_right * ld.l_sizex + ld.l_up * ld.l_sizey); - - return ltc_evaluate_quad(corners, N); -} - -float direct_diffuse_ellipse(LightData ld, vec3 N, vec3 V, vec4 l_vector) -{ - vec3 points[3]; - points[0] = l_vector.xyz + ld.l_right * -ld.l_sizex + ld.l_up * -ld.l_sizey; - points[1] = l_vector.xyz + ld.l_right * ld.l_sizex + ld.l_up * -ld.l_sizey; - points[2] = l_vector.xyz + ld.l_right * ld.l_sizex + ld.l_up * ld.l_sizey; - - return ltc_evaluate_disk(N, V, mat3(1), points); -} - -float direct_diffuse_unit_disc(LightData ld, vec3 N, vec3 V) -{ - float NL = dot(N, -ld.l_forward); - - return ltc_evaluate_disk_simple(ld.l_radius, NL); -} -#endif - -/* ----------- GGx ------------ */ -vec3 direct_ggx_point(vec3 N, vec3 V, vec4 l_vector, float roughness, vec3 f0) -{ - roughness = max(1e-3, roughness); - float dist = l_vector.w; - vec3 L = l_vector.xyz / dist; - float bsdf = bsdf_ggx(N, L, V, roughness); - bsdf /= dist * dist; - - /* Fresnel */ - float VH = max(dot(V, normalize(V + L)), 0.0); - return F_schlick(f0, VH) * bsdf; -} - -vec3 direct_ggx_sun(LightData ld, vec3 N, vec3 V, float roughness, vec3 f0) -{ - roughness = max(1e-3, roughness); - float bsdf = bsdf_ggx(N, -ld.l_forward, V, roughness); - float VH = dot(V, -ld.l_forward) * 0.5 + 0.5; - return F_schlick(f0, VH) * bsdf; -} - -#ifdef USE_LTC -vec3 direct_ggx_sphere(LightData ld, vec3 N, vec3 V, vec4 l_vector, float roughness, vec3 f0) -{ - roughness = clamp(roughness, 0.0008, 0.999); /* Fix low roughness artifacts. */ - - vec2 uv = lut_coords(dot(N, V), sqrt(roughness)); - vec3 brdf_lut = texture(utilTex, vec3(uv, 1.0)).rgb; - vec4 ltc_lut = texture(utilTex, vec3(uv, 0.0)).rgba; - mat3 ltc_mat = ltc_matrix(ltc_lut); - - /* Make orthonormal basis. */ - vec3 L = l_vector.xyz / l_vector.w; - vec3 Px, Py; - make_orthonormal_basis(L, Px, Py); - Px *= ld.l_radius; - Py *= ld.l_radius; - - vec3 points[3]; - points[0] = l_vector.xyz - Px - Py; - points[1] = l_vector.xyz + Px - Py; - points[2] = l_vector.xyz + Px + Py; - - float bsdf = ltc_evaluate_disk(N, V, ltc_mat, points); - bsdf *= brdf_lut.b; /* Bsdf intensity */ - - vec3 spec = F_area(f0, brdf_lut.xy) * bsdf; - - return spec; -} - -vec3 direct_ggx_ellipse(LightData ld, vec3 N, vec3 V, vec4 l_vector, float roughness, vec3 f0) -{ - vec3 points[3]; - points[0] = l_vector.xyz + ld.l_right * -ld.l_sizex + ld.l_up * -ld.l_sizey; - points[1] = l_vector.xyz + ld.l_right * ld.l_sizex + ld.l_up * -ld.l_sizey; - points[2] = l_vector.xyz + ld.l_right * ld.l_sizex + ld.l_up * ld.l_sizey; - - vec2 uv = lut_coords(dot(N, V), sqrt(roughness)); - vec3 brdf_lut = texture(utilTex, vec3(uv, 1.0)).rgb; - vec4 ltc_lut = texture(utilTex, vec3(uv, 0.0)).rgba; - mat3 ltc_mat = ltc_matrix(ltc_lut); - - float bsdf = ltc_evaluate_disk(N, V, ltc_mat, points); - bsdf *= brdf_lut.b; /* Bsdf intensity */ - - vec3 spec = F_area(f0, brdf_lut.xy) * bsdf; - - return spec; -} - -vec3 direct_ggx_rectangle(LightData ld, vec3 N, vec3 V, vec4 l_vector, float roughness, vec3 f0) -{ - vec3 corners[4]; - corners[0] = l_vector.xyz + ld.l_right * -ld.l_sizex + ld.l_up * ld.l_sizey; - corners[1] = l_vector.xyz + ld.l_right * -ld.l_sizex + ld.l_up * -ld.l_sizey; - corners[2] = l_vector.xyz + ld.l_right * ld.l_sizex + ld.l_up * -ld.l_sizey; - corners[3] = l_vector.xyz + ld.l_right * ld.l_sizex + ld.l_up * ld.l_sizey; - - vec2 uv = lut_coords(dot(N, V), sqrt(roughness)); - vec3 brdf_lut = texture(utilTex, vec3(uv, 1.0)).rgb; - vec4 ltc_lut = texture(utilTex, vec3(uv, 0.0)).rgba; - mat3 ltc_mat = ltc_matrix(ltc_lut); - - ltc_transform_quad(N, V, ltc_mat, corners); - float bsdf = ltc_evaluate_quad(corners, vec3(0.0, 0.0, 1.0)); - bsdf *= brdf_lut.b; /* Bsdf intensity */ - - vec3 spec = F_area(f0, brdf_lut.xy) * bsdf; - - return spec; -} - -vec3 direct_ggx_unit_disc(LightData ld, vec3 N, vec3 V, float roughness, vec3 f0) -{ - roughness = clamp(roughness, 0.0004, 0.999); /* Fix low roughness artifacts. */ - - vec2 uv = lut_coords(dot(N, V), sqrt(roughness)); - vec3 brdf_lut = texture(utilTex, vec3(uv, 1.0)).rgb; - vec4 ltc_lut = texture(utilTex, vec3(uv, 0.0)).rgba; - mat3 ltc_mat = ltc_matrix(ltc_lut); - - vec3 Px = ld.l_right * ld.l_radius; - vec3 Py = ld.l_up * ld.l_radius; - - vec3 points[3]; - points[0] = -ld.l_forward - Px - Py; - points[1] = -ld.l_forward + Px - Py; - points[2] = -ld.l_forward + Px + Py; - - float bsdf = ltc_evaluate_disk(N, V, ltc_mat, points); - bsdf *= brdf_lut.b; /* Bsdf intensity */ - - vec3 spec = F_area(f0, brdf_lut.xy) * bsdf; - - return spec; -} -#endif diff --git a/source/blender/draw/engines/eevee/shaders/lamps_lib.glsl b/source/blender/draw/engines/eevee/shaders/lamps_lib.glsl index 0e6f976187a..ec5f6f4472f 100644 --- a/source/blender/draw/engines/eevee/shaders/lamps_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/lamps_lib.glsl @@ -249,55 +249,70 @@ float light_visibility(LightData ld, vec3 W, return vis; } +#ifdef USE_LTC float light_diffuse(LightData ld, vec3 N, vec3 V, vec4 l_vector) { -#ifdef USE_LTC - if (ld.l_type == SUN) { - return direct_diffuse_unit_disc(ld, N, V); - } - else if (ld.l_type == AREA_RECT) { - return direct_diffuse_rectangle(ld, N, V, l_vector); + if (ld.l_type == AREA_RECT) { + vec3 corners[4]; + corners[0] = normalize((l_vector.xyz + ld.l_right * -ld.l_sizex) + ld.l_up * ld.l_sizey); + corners[1] = normalize((l_vector.xyz + ld.l_right * -ld.l_sizex) + ld.l_up * -ld.l_sizey); + corners[2] = normalize((l_vector.xyz + ld.l_right * ld.l_sizex) + ld.l_up * -ld.l_sizey); + corners[3] = normalize((l_vector.xyz + ld.l_right * ld.l_sizex) + ld.l_up * ld.l_sizey); + + return ltc_evaluate_quad(corners, N); } else if (ld.l_type == AREA_ELLIPSE) { - return direct_diffuse_ellipse(ld, N, V, l_vector); - } - else { - return direct_diffuse_sphere(ld, N, l_vector); - } -#else - if (ld.l_type == SUN) { - return direct_diffuse_sun(ld, N); + vec3 points[3]; + points[0] = (l_vector.xyz + ld.l_right * -ld.l_sizex) + ld.l_up * -ld.l_sizey; + points[1] = (l_vector.xyz + ld.l_right * ld.l_sizex) + ld.l_up * -ld.l_sizey; + points[2] = (l_vector.xyz + ld.l_right * ld.l_sizex) + ld.l_up * ld.l_sizey; + + return ltc_evaluate_disk(N, V, mat3(1.0), points); } else { - return direct_diffuse_point(N, l_vector); + float radius = ld.l_radius; + radius /= (ld.l_type == SUN) ? 1.0 : l_vector.w; + vec3 L = (ld.l_type == SUN) ? -ld.l_forward : (l_vector.xyz / l_vector.w); + + return ltc_evaluate_disk_simple(radius, dot(N, L)); } -#endif } -vec3 light_specular(LightData ld, vec3 N, vec3 V, vec4 l_vector, float roughness, vec3 f0) +float light_specular(LightData ld, vec4 ltc_mat, vec3 N, vec3 V, vec4 l_vector) { -#ifdef USE_LTC - if (ld.l_type == SUN) { - return direct_ggx_unit_disc(ld, N, V, roughness, f0); - } - else if (ld.l_type == AREA_RECT) { - return direct_ggx_rectangle(ld, N, V, l_vector, roughness, f0); - } - else if (ld.l_type == AREA_ELLIPSE) { - return direct_ggx_ellipse(ld, N, V, l_vector, roughness, f0); - } - else { - return direct_ggx_sphere(ld, N, V, l_vector, roughness, f0); - } -#else - if (ld.l_type == SUN) { - return direct_ggx_sun(ld, N, V, roughness, f0); + if (ld.l_type == AREA_RECT) { + vec3 corners[4]; + corners[0] = (l_vector.xyz + ld.l_right * -ld.l_sizex) + ld.l_up * ld.l_sizey; + corners[1] = (l_vector.xyz + ld.l_right * -ld.l_sizex) + ld.l_up * -ld.l_sizey; + corners[2] = (l_vector.xyz + ld.l_right * ld.l_sizex) + ld.l_up * -ld.l_sizey; + corners[3] = (l_vector.xyz + ld.l_right * ld.l_sizex) + ld.l_up * ld.l_sizey; + + ltc_transform_quad(N, V, ltc_matrix(ltc_mat), corners); + + return ltc_evaluate_quad(corners, vec3(0.0, 0.0, 1.0)); } else { - return direct_ggx_point(N, V, l_vector, roughness, f0); + bool is_ellipse = (ld.l_type == AREA_ELLIPSE); + float radius_x = is_ellipse ? ld.l_sizex : ld.l_radius; + float radius_y = is_ellipse ? ld.l_sizey : ld.l_radius; + + vec3 L = (ld.l_type == SUN) ? -ld.l_forward : l_vector.xyz; + vec3 Px = ld.l_right; + vec3 Py = ld.l_up; + + if (ld.l_type == SPOT || ld.l_type == POINT) { + make_orthonormal_basis(l_vector.xyz / l_vector.w, Px, Py); + } + + vec3 points[3]; + points[0] = (L + Px * -radius_x) + Py * -radius_y; + points[1] = (L + Px * radius_x) + Py * -radius_y; + points[2] = (L + Px * radius_x) + Py * radius_y; + + return ltc_evaluate_disk(N, V, ltc_matrix(ltc_mat), points); } -#endif } +#endif #define MAX_SSS_SAMPLES 65 #define SSS_LUT_SIZE 64.0 diff --git a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl index 4e65834e528..ac1dd071a29 100644 --- a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl @@ -182,6 +182,17 @@ void CLOSURE_NAME( /* -------------------- SCENE LAMPS LIGHTING ---------------------- */ /* ---------------------------------------------------------------- */ +#ifdef CLOSURE_GLOSSY + vec2 lut_uv = lut_coords(dot(N, V), roughness); + vec4 ltc_mat = texture(utilTex, vec3(lut_uv, 0.0)).rgba; +#endif + +#ifdef CLOSURE_CLEARCOAT + vec2 lut_uv_clear = lut_coords(dot(C_N, V), C_roughness); + vec4 ltc_mat_clear = texture(utilTex, vec3(lut_uv_clear, 0.0)).rgba; + vec3 out_spec_clear = vec3(0.0); +#endif + for (int i = 0; i < MAX_LIGHT && i < laNumLight; ++i) { LightData ld = lights_data[i]; @@ -200,14 +211,24 @@ void CLOSURE_NAME( #endif #ifdef CLOSURE_GLOSSY - out_spec += l_color_vis * light_specular(ld, N, V, l_vector, roughnessSquared, f0) * ld.l_spec; + out_spec += l_color_vis * light_specular(ld, ltc_mat, N, V, l_vector) * ld.l_spec; #endif #ifdef CLOSURE_CLEARCOAT - out_spec += l_color_vis * light_specular(ld, C_N, V, l_vector, C_roughnessSquared, f0) * C_intensity * ld.l_spec; + out_spec_clear += l_color_vis * light_specular(ld, ltc_mat_clear, C_N, V, l_vector) * C_intensity * ld.l_spec; #endif } +#ifdef CLOSURE_GLOSSY + vec3 brdf_lut_lamps = texture(utilTex, vec3(lut_uv, 1.0)).rgb; + out_spec *= F_area(f0, brdf_lut_lamps.xy) * brdf_lut_lamps.z; +#endif + +#ifdef CLOSURE_CLEARCOAT + vec3 brdf_lut_lamps_clear = texture(utilTex, vec3(lut_uv_clear, 1.0)).rgb; + out_spec_clear *= F_area(f0, brdf_lut_lamps_clear.xy) * brdf_lut_lamps_clear.z; + out_spec += out_spec_clear; +#endif /* ---------------------------------------------------------------- */ /* ---------------- SPECULAR ENVIRONMENT LIGHTING ----------------- */ diff --git a/source/blender/draw/engines/workbench/shaders/workbench_checkerboard_depth_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_checkerboard_depth_frag.glsl index 4e44f6e1914..7027543f5a9 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_checkerboard_depth_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_checkerboard_depth_frag.glsl @@ -1,8 +1,35 @@ + +/* 4x4 bayer matrix. */ +#define P(x) ((x + 0.5) * (1.0 / 16.0)) +const vec4 dither_mat[4] = vec4[4]( + vec4( P(0.0), P(8.0), P(2.0), P(10.0)), + vec4(P(12.0), P(4.0), P(14.0), P(6.0)), + vec4( P(3.0), P(11.0), P(1.0), P(9.0)), + vec4(P(15.0), P(7.0), P(13.0), P(5.0)) +); + +uniform float threshold = 0.5; + +/* Noise dithering pattern + * 0 - Bayer matrix + * 1 - Interlieved gradient noise + */ +#define NOISE 1 + void main() { - vec2 p= vec2(floor(gl_FragCoord.x), floor(gl_FragCoord.y)); - vec2 test = mod(p, 2.0); - if (mod(test.x + test.y, 2.0)==0.0) { +#if NOISE == 0 + ivec2 tx = ivec2(gl_FragCoord.xy) % 4; + float noise = dither_mat[tx.x][tx.y]; +#elif NOISE == 1 + /* Interlieved gradient noise by Jorge Jimenez + * http://www.iryoku.com/next-generation-post-processing-in-call-of-duty-advanced-warfare */ + float noise = fract(52.9829189 * fract(0.06711056 * gl_FragCoord.x + 0.00583715 * gl_FragCoord.y)); +#else +#error +#endif + + if (noise > threshold) { discard; } else { gl_FragDepth = 1.0; diff --git a/source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl b/source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl index 39c6863e71c..c56e02e72d6 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl @@ -65,9 +65,57 @@ void fresnel(vec3 I, vec3 N, float ior, out float kr) // kt = 1 - kr; } -vec4 calculate_transparent_accum(vec4 premultiplied) { - float a = min(1.0, premultiplied.a) * 8.0 + 0.01; +float calculate_transparent_weight(float z, float alpha) +{ +#if 0 + /* Eq 10 : Good for surfaces with varying opacity (like particles) */ + float a = min(1.0, alpha * 10.0) + 0.01; float b = -gl_FragCoord.z * 0.95 + 1.0; - float w = clamp(a * a * a * 1e8 * b * b * b, 1e-2, 3e2); - return premultiplied * w; + float w = a * a * a * 3e2 * b * b * b; +#else + /* Eq 7 put more emphasis on surfaces closer to the view. */ + // float w = 10.0 / (1e-5 + pow(abs(z) / 5.0, 2.0) + pow(abs(z) / 200.0, 6.0)); /* Eq 7 */ + // float w = 10.0 / (1e-5 + pow(abs(z) / 10.0, 3.0) + pow(abs(z) / 200.0, 6.0)); /* Eq 8 */ + // float w = 10.0 / (1e-5 + pow(abs(z) / 200.0, 4.0)); /* Eq 9 */ + /* Same as eq 7, but optimized. */ + float a = abs(z) / 5.0; + float b = abs(z) / 200.0; + b *= b; + float w = 10.0 / ((1e-5 + a * a) + b * (b * b)); /* Eq 7 */ +#endif + return alpha * clamp(w, 1e-2, 3e2); +} + +/* Special function only to be used with calculate_transparent_weight(). */ +float linear_zdepth(float depth, vec4 viewvecs[3], mat4 proj_mat) +{ + if (proj_mat[3][3] == 0.0) { + float d = 2.0 * depth - 1.0; + return -proj_mat[3][2] / (d + proj_mat[2][2]); + } + else { + /* Return depth from near plane. */ + return depth * viewvecs[1].z; + } +} + +vec3 view_vector_from_screen_uv(vec2 uv, vec4 viewvecs[3], mat4 proj_mat) +{ + return (proj_mat[3][3] == 0.0) + ? normalize(viewvecs[0].xyz + vec3(uv, 0.0) * viewvecs[1].xyz) + : vec3(0.0, 0.0, 1.0); +} + +vec2 matcap_uv_compute(vec3 I, vec3 N, bool flipped) +{ + /* Quick creation of an orthonormal basis */ + float a = 1.0 / (1.0 + I.z); + float b = -I.x * I.y * a; + vec3 b1 = vec3(1.0 - I.x * I.x * a, b, -I.x); + vec3 b2 = vec3(b, 1.0 - I.y * I.y * a, -I.y); + vec2 matcap_uv = vec2(dot(b1, N), dot(b2, N)); + if (flipped) { + matcap_uv.x = -matcap_uv.x; + } + return matcap_uv * 0.496 + 0.5; } diff --git a/source/blender/draw/engines/workbench/shaders/workbench_deferred_composite_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_deferred_composite_frag.glsl index e5ee272e7fd..461fb2fb130 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_deferred_composite_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_deferred_composite_frag.glsl @@ -1,5 +1,7 @@ out vec4 fragColor; +uniform mat4 ProjectionMatrix; + uniform usampler2D objectId; uniform sampler2D colorBuffer; uniform sampler2D specularBuffer; @@ -8,6 +10,7 @@ uniform sampler2D normalBuffer; uniform sampler2D cavityBuffer; uniform vec2 invertedViewportSize; +uniform vec4 viewvecs[3]; uniform float shadowMultiplier; uniform float lightMultiplier; uniform float shadowShift = 0.1; @@ -61,17 +64,15 @@ void main() # endif /* WORKBENCH_ENCODE_NORMALS */ #endif + vec3 I_vs = view_vector_from_screen_uv(uv_viewport, viewvecs, ProjectionMatrix); + #ifdef STUDIOLIGHT_ORIENTATION_VIEWNORMAL - vec2 matcap_uv = normal_viewport.xy / 2.0 + 0.5; - if (world_data.matcap_orientation != 0) { - matcap_uv.x = 1.0 - matcap_uv.x; - } - diffuse_color = texture(matcapImage, matcap_uv); + bool flipped = world_data.matcap_orientation != 0; + vec2 matcap_uv = matcap_uv_compute(I_vs, normal_viewport, flipped); + diffuse_color = textureLod(matcapImage, matcap_uv, 0.0); #endif #ifdef V3D_SHADING_SPECULAR_HIGHLIGHT - /* XXX Should calculate the correct VS Incoming direction */ - vec3 I_vs = vec3(0.0, 0.0, 1.0); vec4 specular_data = texelFetch(specularBuffer, texel, 0); vec3 specular_color = get_world_specular_lights(world_data, specular_data, normal_viewport, I_vs); #else diff --git a/source/blender/draw/engines/workbench/shaders/workbench_forward_composite_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_forward_composite_frag.glsl index f335e1a15bd..1d9f37274bd 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_forward_composite_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_forward_composite_frag.glsl @@ -2,9 +2,7 @@ out vec4 fragColor; uniform usampler2D objectId; uniform sampler2D transparentAccum; -#ifdef WORKBENCH_REVEALAGE_ENABLED uniform sampler2D transparentRevealage; -#endif uniform vec2 invertedViewportSize; layout(std140) uniform world_block { @@ -16,29 +14,24 @@ void main() ivec2 texel = ivec2(gl_FragCoord.xy); vec2 uv_viewport = gl_FragCoord.xy * invertedViewportSize; uint object_id = texelFetch(objectId, texel, 0).r; - vec4 transparent_accum = texelFetch(transparentAccum, texel, 0); -#ifdef WORKBENCH_REVEALAGE_ENABLED - float transparent_revealage = texelFetch(transparentRevealage, texel, 0).r; -#endif - vec4 color; - vec4 bg_color; + + /* Listing 4 */ + vec4 trans_accum = texelFetch(transparentAccum, texel, 0); + float trans_revealage = trans_accum.a; + trans_accum.a = texelFetch(transparentRevealage, texel, 0).r; #ifdef V3D_SHADING_OBJECT_OUTLINE float outline = calculate_object_outline(objectId, texel, object_id); #else /* V3D_SHADING_OBJECT_OUTLINE */ float outline = 1.0; #endif /* V3D_SHADING_OBJECT_OUTLINE */ - bg_color = vec4(background_color(world_data, uv_viewport.y), 0.0); - if (object_id == NO_OBJECT_ID) { - color = bg_color; - } else { -#ifdef WORKBENCH_REVEALAGE_ENABLED - color = vec4((transparent_accum.xyz / max(transparent_accum.a, EPSILON)) * (1.0 - transparent_revealage), 1.0); - color = mix(bg_color, color, clamp(1.0 - transparent_revealage, 0.0, 1.0)); -#else - color = vec4(transparent_accum.xyz / max(transparent_accum.a, EPSILON), 1.0); -#endif - } - - fragColor = vec4(mix(world_data.object_outline_color.rgb, color.xyz, outline), 1.0); + vec3 bg_color = background_color(world_data, uv_viewport.y); + + /* TODO: Bypass the whole shader if there is no xray pass and no outline pass. */ + vec3 trans_color = trans_accum.rgb / clamp(trans_accum.a, 1e-4, 5e4); + vec3 color = mix(trans_color, bg_color, trans_revealage); + + color = mix(world_data.object_outline_color.rgb, color, outline); + + fragColor = vec4(color, 1.0); } diff --git a/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl index e04bffdeea5..4a7d195a56a 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl @@ -1,8 +1,11 @@ #ifdef OB_TEXTURE uniform sampler2D image; #endif +uniform mat4 ProjectionMatrix; uniform mat3 normalWorldMatrix; uniform float alpha = 0.5; +uniform vec2 invertedViewportSize; +uniform vec4 viewvecs[3]; #ifdef NORMAL_VIEWPORT_PASS_ENABLED in vec3 normal_viewport; @@ -23,7 +26,7 @@ layout(std140) uniform material_block { }; layout(location=0) out vec4 transparentAccum; - +layout(location=1) out float revealageAccum; /* revealage actually stored in transparentAccum.a */ void main() { @@ -36,29 +39,45 @@ void main() diffuse_color = texture(image, uv_interp); #endif /* OB_TEXTURE */ + vec2 uv_viewport = gl_FragCoord.xy * invertedViewportSize; + vec3 I_vs = view_vector_from_screen_uv(uv_viewport, viewvecs, ProjectionMatrix); + +#ifdef NORMAL_VIEWPORT_PASS_ENABLED + vec3 nor = normalize(normal_viewport); +#endif + #ifdef V3D_LIGHTING_MATCAP - diffuse_light = texture(matcapImage, normal_viewport.xy / 2.0 + 0.5).rgb; + bool flipped = world_data.matcap_orientation != 0; + vec2 matcap_uv = matcap_uv_compute(I_vs, nor, flipped); + diffuse_light = texture(matcapImage, matcap_uv).rgb; #endif #ifdef V3D_SHADING_SPECULAR_HIGHLIGHT - vec3 specular_color = get_world_specular_lights(world_data, vec4(material_data.specular_color.rgb, material_data.roughness), normal_viewport, vec3(0.0, 0.0, 1.0)); + vec3 specular_color = get_world_specular_lights(world_data, vec4(material_data.specular_color.rgb, material_data.roughness), nor, I_vs); #else vec3 specular_color = vec3(0.0); #endif #ifdef V3D_LIGHTING_STUDIO # ifdef STUDIOLIGHT_ORIENTATION_CAMERA - diffuse_light = get_camera_diffuse_light(world_data, normal_viewport); + diffuse_light = get_camera_diffuse_light(world_data, nor); # endif # ifdef STUDIOLIGHT_ORIENTATION_WORLD - vec3 normal_world = normalWorldMatrix * normal_viewport; + vec3 normal_world = normalWorldMatrix * nor; diffuse_light = get_world_diffuse_light(world_data, normal_world); # endif #endif vec3 shaded_color = diffuse_light * diffuse_color.rgb + specular_color; - vec4 premultiplied = vec4(shaded_color.rgb * alpha, alpha); - transparentAccum = calculate_transparent_accum(premultiplied); + /* Based on : + * McGuire and Bavoil, Weighted Blended Order-Independent Transparency, Journal of + * Computer Graphics Techniques (JCGT), vol. 2, no. 2, 122–141, 2013 + */ + /* Listing 4 */ + float z = linear_zdepth(gl_FragCoord.z, viewvecs, ProjectionMatrix); + float weight = calculate_transparent_weight(z, alpha); + transparentAccum = vec4(shaded_color * weight, alpha); + revealageAccum = weight; } diff --git a/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_revealage_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_revealage_frag.glsl deleted file mode 100644 index c591425b950..00000000000 --- a/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_revealage_frag.glsl +++ /dev/null @@ -1,7 +0,0 @@ -layout(location=0) out float transparentRevealage; -uniform float alpha = 0.5; -void main() -{ - transparentRevealage = alpha; -} - diff --git a/source/blender/draw/engines/workbench/shaders/workbench_world_light_lib.glsl b/source/blender/draw/engines/workbench/shaders/workbench_world_light_lib.glsl index 6f4237ebd0a..9d256e5350a 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_world_light_lib.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_world_light_lib.glsl @@ -60,4 +60,3 @@ vec3 get_world_specular_lights(WorldData world_data, vec4 specular_data, vec3 N, } return specular_light; } - diff --git a/source/blender/draw/engines/workbench/workbench_deferred.c b/source/blender/draw/engines/workbench/workbench_deferred.c index 1a1f626d563..f32060bd64f 100644 --- a/source/blender/draw/engines/workbench/workbench_deferred.c +++ b/source/blender/draw/engines/workbench/workbench_deferred.c @@ -114,7 +114,7 @@ static char *workbench_build_composite_frag(WORKBENCH_PrivateData *wpd) BLI_dynstr_append(ds, datatoc_workbench_common_lib_glsl); BLI_dynstr_append(ds, datatoc_workbench_background_lib_glsl); - if ((wpd->shading.light & V3D_LIGHTING_STUDIO) || (wpd->shading.flag & V3D_SHADING_SPECULAR_HIGHLIGHT)) { + if ((wpd->shading.light & V3D_LIGHTING_MATCAP) || (wpd->shading.light & V3D_LIGHTING_STUDIO) || (wpd->shading.flag & V3D_SHADING_SPECULAR_HIGHLIGHT)) { BLI_dynstr_append(ds, datatoc_workbench_world_light_lib_glsl); } if (wpd->shading.flag & V3D_SHADING_OBJECT_OUTLINE) { @@ -447,32 +447,14 @@ static void workbench_composite_uniforms(WORKBENCH_PrivateData *wpd, DRWShadingG } if (SPECULAR_HIGHLIGHT_ENABLED(wpd) || MATCAP_ENABLED(wpd)) { DRW_shgroup_uniform_texture_ref(grp, "specularBuffer", &e_data.specular_buffer_tx); - -#if 0 - float invwinmat[4][4]; - DRW_viewport_matrix_get(invwinmat, DRW_MAT_WININV); - - copy_v4_fl4(e_data.screenvecs[0], 1.0f, -1.0f, 0.0f, 1.0f); - copy_v4_fl4(e_data.screenvecs[1], -1.0f, 1.0f, 0.0f, 1.0f); - copy_v4_fl4(e_data.screenvecs[2], -1.0f, -1.0f, 0.0f, 1.0f); - for (int i = 0; i < 3; i++) { - mul_m4_v4(invwinmat, e_data.screenvecs[i]); - e_data.screenvecs[i][0] /= e_data.screenvecs[i][3]; /* perspective divide */ - e_data.screenvecs[i][1] /= e_data.screenvecs[i][3]; /* perspective divide */ - e_data.screenvecs[i][2] /= e_data.screenvecs[i][3]; /* perspective divide */ - e_data.screenvecs[i][3] = 1.0f; - } - sub_v3_v3(e_data.screenvecs[0], e_data.screenvecs[2]); - sub_v3_v3(e_data.screenvecs[1], e_data.screenvecs[2]); - DRW_shgroup_uniform_vec4(grp, "screenvecs[0]", e_data.screenvecs[0], 3); -#endif + DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)wpd->viewvecs, 3); } DRW_shgroup_uniform_block(grp, "world_block", wpd->world_ubo); DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1); if (STUDIOLIGHT_ORIENTATION_VIEWNORMAL_ENABLED(wpd)) { BKE_studiolight_ensure_flag(wpd->studio_light, STUDIOLIGHT_EQUIRECTANGULAR_RADIANCE_GPUTEXTURE); - DRW_shgroup_uniform_texture(grp, "matcapImage", wpd->studio_light->equirectangular_radiance_gputexture); DRW_shgroup_uniform_texture(grp, "matcapImage", wpd->studio_light->equirectangular_radiance_gputexture); + DRW_shgroup_uniform_texture(grp, "matcapImage", wpd->studio_light->equirectangular_radiance_gputexture); } workbench_material_set_normal_world_matrix(grp, wpd, e_data.normal_world_matrix); @@ -594,7 +576,7 @@ static WORKBENCH_MaterialData *get_or_create_material_data( case OB_TEXTURE: { - GPUTexture *tex = GPU_texture_from_blender(ima, NULL, GL_TEXTURE_2D, false, false, false); + GPUTexture *tex = GPU_texture_from_blender(ima, NULL, GL_TEXTURE_2D, false, 0.0); DRW_shgroup_uniform_texture(material->shgrp, "image", tex); break; } @@ -657,7 +639,7 @@ static void workbench_cache_populate_particles(WORKBENCH_Data *vedata, Object *o DRW_shgroup_uniform_int(shgrp, "object_id", &material->object_id, 1); DRW_shgroup_uniform_block(shgrp, "material_block", material->material_ubo); if (image) { - GPUTexture *tex = GPU_texture_from_blender(image, NULL, GL_TEXTURE_2D, false, false, false); + GPUTexture *tex = GPU_texture_from_blender(image, NULL, GL_TEXTURE_2D, false, 0.0f); DRW_shgroup_uniform_texture(shgrp, "image", tex); } } @@ -681,12 +663,12 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob) } WORKBENCH_MaterialData *material; - if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT)) { + if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL)) { const DRWContextState *draw_ctx = DRW_context_state_get(); const bool is_active = (ob == draw_ctx->obact); const bool is_sculpt_mode = is_active && (draw_ctx->object_mode & OB_MODE_SCULPT) != 0; bool is_drawn = false; - if (!is_sculpt_mode && wpd->drawtype == OB_TEXTURE && ob->type == OB_MESH) { + if (!is_sculpt_mode && wpd->drawtype == OB_TEXTURE && ELEM(ob->type, OB_MESH)) { const Mesh *me = ob->data; if (me->mloopuv) { const int materials_len = MAX2(1, (is_sculpt_mode ? 1 : ob->totcol)); @@ -694,6 +676,10 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob) struct Gwn_Batch **geom_array = me->totcol ? DRW_cache_mesh_surface_texpaint_get(ob) : NULL; if (materials_len > 0 && geom_array) { for (int i = 0; i < materials_len; i++) { + if (geom_array[i] == NULL) { + continue; + } + Material *mat = give_current_material(ob, i + 1); Image *image; ED_object_get_active_image(ob, i + 1, &image, NULL, NULL, NULL); @@ -712,7 +698,7 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob) /* Fallback from not drawn OB_TEXTURE mode or just OB_SOLID mode */ if (!is_drawn) { - if ((wpd->shading.color_type != V3D_SHADING_MATERIAL_COLOR) || is_sculpt_mode) { + if ((wpd->shading.color_type != V3D_SHADING_MATERIAL_COLOR)) { /* No material split needed */ struct Gwn_Batch *geom = DRW_cache_object_surface_get(ob); if (geom) { @@ -736,9 +722,18 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob) ob, gpumat_array, materials_len, NULL, NULL, NULL); if (mat_geom) { for (int i = 0; i < materials_len; ++i) { + if (mat_geom[i] == NULL) { + continue; + } + Material *mat = give_current_material(ob, i + 1); material = get_or_create_material_data(vedata, ob, mat, NULL, OB_SOLID); - DRW_shgroup_call_object_add(material->shgrp, mat_geom[i], ob); + if (is_sculpt_mode) { + DRW_shgroup_call_sculpt_add(material->shgrp, ob, ob->obmat); + } + else { + DRW_shgroup_call_object_add(material->shgrp, mat_geom[i], ob); + } } } } diff --git a/source/blender/draw/engines/workbench/workbench_forward.c b/source/blender/draw/engines/workbench/workbench_forward.c index a31a45ffdc0..9a362440877 100644 --- a/source/blender/draw/engines/workbench/workbench_forward.c +++ b/source/blender/draw/engines/workbench/workbench_forward.c @@ -50,9 +50,6 @@ static struct { struct GPUShader *composite_sh_cache[MAX_SHADERS]; struct GPUShader *transparent_accum_sh_cache[MAX_SHADERS]; - struct GPUShader *transparent_revealage_sh; - struct GPUShader *transparent_revealage_hair_sh; - struct GPUShader *transparent_revealage_hair_fibers_sh; struct GPUShader *object_outline_sh; struct GPUShader *object_outline_hair_sh; struct GPUShader *object_outline_hair_fibers_sh; @@ -60,9 +57,7 @@ static struct { struct GPUTexture *object_id_tx; /* ref only, not alloced */ struct GPUTexture *transparent_accum_tx; /* ref only, not alloced */ -#ifdef WORKBENCH_REVEALAGE_ENABLED struct GPUTexture *transparent_revealage_tx; /* ref only, not alloced */ -#endif struct GPUTexture *composite_buffer_tx; /* ref only, not alloced */ int next_object_id; float normal_world_matrix[3][3]; @@ -74,9 +69,6 @@ extern char datatoc_common_hair_guides_lib_glsl[]; extern char datatoc_workbench_forward_composite_frag_glsl[]; extern char datatoc_workbench_forward_depth_frag_glsl[]; extern char datatoc_workbench_forward_transparent_accum_frag_glsl[]; -#ifdef WORKBENCH_REVEALAGE_ENABLED -extern char datatoc_workbench_forward_transparent_revealage_frag_glsl[]; -#endif extern char datatoc_workbench_data_lib_glsl[]; extern char datatoc_workbench_background_lib_glsl[]; extern char datatoc_workbench_checkerboard_depth_frag_glsl[]; @@ -131,22 +123,6 @@ static char *workbench_build_forward_transparent_accum_frag(void) return str; } -#ifdef WORKBENCH_REVEALAGE_ENABLED -static char *workbench_build_forward_transparent_revealage_frag(void) -{ - char *str = NULL; - - DynStr *ds = BLI_dynstr_new(); - - BLI_dynstr_append(ds, datatoc_workbench_common_lib_glsl); - BLI_dynstr_append(ds, datatoc_workbench_forward_transparent_revealage_frag_glsl); - - str = BLI_dynstr_get_cstring(ds); - BLI_dynstr_free(ds); - return str; -} -#endif - static char *workbench_build_forward_composite_frag(void) { char *str = NULL; @@ -199,6 +175,7 @@ static WORKBENCH_MaterialData *get_or_create_material_data( psl->transparent_accum_pass); DRW_shgroup_uniform_block(grp, "world_block", wpd->world_ubo); DRW_shgroup_uniform_float(grp, "alpha", &wpd->shading.xray_alpha, 1); + DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)wpd->viewvecs, 3); workbench_material_set_normal_world_matrix(grp, wpd, e_data.normal_world_matrix); material->object_id = engine_object_data->object_id; copy_v4_v4(material->material_data.diffuse_color, material_template.material_data.diffuse_color); @@ -211,12 +188,15 @@ static WORKBENCH_MaterialData *get_or_create_material_data( BKE_studiolight_ensure_flag(wpd->studio_light, STUDIOLIGHT_EQUIRECTANGULAR_RADIANCE_GPUTEXTURE); DRW_shgroup_uniform_texture(grp, "matcapImage", wpd->studio_light->equirectangular_radiance_gputexture); } + if (SPECULAR_HIGHLIGHT_ENABLED(wpd) || MATCAP_ENABLED(wpd)) { + DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1); + } break; } case OB_TEXTURE: { - GPUTexture *tex = GPU_texture_from_blender(ima, NULL, GL_TEXTURE_2D, false, false, false); + GPUTexture *tex = GPU_texture_from_blender(ima, NULL, GL_TEXTURE_2D, false, 0.0f); DRW_shgroup_uniform_texture(grp, "image", tex); break; } @@ -320,20 +300,6 @@ void workbench_forward_engine_init(WORKBENCH_Data *vedata) forward_vert, NULL, forward_depth_frag, defines_hair_fibers); -#ifdef WORKBENCH_REVEALAGE_ENABLED - char *forward_transparent_revealage_frag = workbench_build_forward_transparent_revealage_frag(); - e_data.transparent_revealage_sh = DRW_shader_create( - forward_vert, NULL, - forward_transparent_revealage_frag, defines); - e_data.transparent_revealage_hair_sh = DRW_shader_create( - forward_vert, NULL, - forward_transparent_revealage_frag, defines_hair); - e_data.transparent_revealage_hair_fibers_sh = DRW_shader_create( - forward_vert, NULL, - forward_transparent_revealage_frag, defines_hair_fibers); - MEM_freeN(forward_transparent_revealage_frag); -#endif - e_data.checker_depth_sh = DRW_shader_create_fullscreen( datatoc_workbench_checkerboard_depth_frag_glsl, NULL); MEM_freeN(forward_vert); @@ -350,63 +316,32 @@ void workbench_forward_engine_init(WORKBENCH_Data *vedata) size[0], size[1], GPU_R32UI, &draw_engine_workbench_transparent); e_data.transparent_accum_tx = DRW_texture_pool_query_2D( size[0], size[1], GPU_RGBA16F, &draw_engine_workbench_transparent); -#ifdef WORKBENCH_REVEALAGE_ENABLED e_data.transparent_revealage_tx = DRW_texture_pool_query_2D( size[0], size[1], GPU_R16F, &draw_engine_workbench_transparent); -#endif e_data.composite_buffer_tx = DRW_texture_pool_query_2D( size[0], size[1], GPU_RGBA16F, &draw_engine_workbench_transparent); + GPU_framebuffer_ensure_config(&fbl->object_outline_fb, { GPU_ATTACHMENT_TEXTURE(dtxl->depth), GPU_ATTACHMENT_TEXTURE(e_data.object_id_tx), }); + GPU_framebuffer_ensure_config(&fbl->transparent_accum_fb, { GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(e_data.transparent_accum_tx), - }); - -#ifdef WORKBENCH_REVEALAGE_ENABLED - GPU_framebuffer_ensure_config(&fbl->transparent_revealage_fb, { - GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(e_data.transparent_revealage_tx), }); -#endif GPU_framebuffer_ensure_config(&fbl->composite_fb, { GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(e_data.composite_buffer_tx), }); - const float clear_color[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - DRW_stats_group_start("Clear Buffers"); - GPU_framebuffer_bind(fbl->transparent_accum_fb); - GPU_framebuffer_clear_color(fbl->transparent_accum_fb, clear_color); - -#ifdef WORKBENCH_REVEALAGE_ENABLED - const float clear_color1[4] = {1.0f, 1.0f, 1.0f, 1.0f}; - GPU_framebuffer_bind(fbl->transparent_revealage_fb); - GPU_framebuffer_clear_color(fbl->transparent_revealage_fb, clear_color1); -#endif - GPU_framebuffer_bind(fbl->object_outline_fb); - GPU_framebuffer_clear_color_depth(fbl->object_outline_fb, clear_color, 1.0f); - DRW_stats_group_end(); /* Transparency Accum */ { - int state = DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE_FULL; + int state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_OIT; psl->transparent_accum_pass = DRW_pass_create("Transparent Accum", state); } - -#ifdef WORKBENCH_REVEALAGE_ENABLED - /* Transparency Revealage */ - { - int state = DRW_STATE_WRITE_COLOR | DRW_STATE_TRANSPARENT_REVEALAGE; - psl->transparent_revealage_pass = DRW_pass_create("Transparent Revealage", state); - grp = DRW_shgroup_create(e_data.transparent_revealage_sh, psl->transparent_revealage_pass); - DRW_shgroup_uniform_float(grp, "alpha", &wpd->shading.xray_alpha, 1); - wpd->transparent_revealage_shgrp = grp; - } -#endif - /* Depth */ { int state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS; @@ -420,9 +355,7 @@ void workbench_forward_engine_init(WORKBENCH_Data *vedata) grp = DRW_shgroup_create(wpd->composite_sh, psl->composite_pass); DRW_shgroup_uniform_texture_ref(grp, "objectId", &e_data.object_id_tx); DRW_shgroup_uniform_texture_ref(grp, "transparentAccum", &e_data.transparent_accum_tx); -#ifdef WORKBENCH_REVEALAGE_ENABLED DRW_shgroup_uniform_texture_ref(grp, "transparentRevealage", &e_data.transparent_revealage_tx); -#endif DRW_shgroup_uniform_block(grp, "world_block", wpd->world_ubo); DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1); DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); @@ -433,6 +366,7 @@ void workbench_forward_engine_init(WORKBENCH_Data *vedata) psl->checker_depth_pass = DRW_pass_create("Checker Depth", state); grp = DRW_shgroup_create(e_data.checker_depth_sh, psl->checker_depth_pass); DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); + DRW_shgroup_uniform_float_copy(grp, "threshold", 0.75f - wpd->shading.xray_alpha * 0.5f); } } @@ -442,11 +376,6 @@ void workbench_forward_engine_free() DRW_SHADER_FREE_SAFE(e_data.composite_sh_cache[index]); DRW_SHADER_FREE_SAFE(e_data.transparent_accum_sh_cache[index]); } -#ifdef WORKBENCH_REVEALAGE_ENABLED - DRW_SHADER_FREE_SAFE(e_data.transparent_revealage_sh); - DRW_SHADER_FREE_SAFE(e_data.transparent_revealage_hair_sh); - DRW_SHADER_FREE_SAFE(e_data.transparent_revealage_hair_fibers_sh); -#endif DRW_SHADER_FREE_SAFE(e_data.object_outline_sh); DRW_SHADER_FREE_SAFE(e_data.object_outline_hair_sh); DRW_SHADER_FREE_SAFE(e_data.object_outline_hair_fibers_sh); @@ -506,17 +435,22 @@ static void workbench_forward_cache_populate_particles(WORKBENCH_Data *vedata, O workbench_material_set_normal_world_matrix(shgrp, wpd, e_data.normal_world_matrix); DRW_shgroup_uniform_block(shgrp, "world_block", wpd->world_ubo); DRW_shgroup_uniform_block(shgrp, "material_block", material->material_ubo); - DRW_shgroup_uniform_float(shgrp, "alpha", &wpd->shading.xray_alpha, 1); + DRW_shgroup_uniform_vec4(shgrp, "viewvecs[0]", (float *)wpd->viewvecs, 3); + /* Hairs have lots of layer and can rapidly become the most prominent surface. + * So lower their alpha artificially. */ + float hair_alpha = wpd->shading.xray_alpha * 0.33f; + DRW_shgroup_uniform_float_copy(shgrp, "alpha", hair_alpha); if (image) { - GPUTexture *tex = GPU_texture_from_blender(image, NULL, GL_TEXTURE_2D, false, false, false); + GPUTexture *tex = GPU_texture_from_blender(image, NULL, GL_TEXTURE_2D, false, 0.0f); DRW_shgroup_uniform_texture(shgrp, "image", tex); } -#ifdef WORKBENCH_REVEALAGE_ENABLED - shgrp = DRW_shgroup_hair_create(ob, psys, md, - psl->transparent_revealage_pass, - e_data.transparent_revealage_hair_sh); - DRW_shgroup_uniform_float(shgrp, "alpha", &wpd->shading.xray_alpha, 1); -#endif + if (STUDIOLIGHT_ORIENTATION_VIEWNORMAL_ENABLED(wpd)) { + BKE_studiolight_ensure_flag(wpd->studio_light, STUDIOLIGHT_EQUIRECTANGULAR_RADIANCE_GPUTEXTURE); + DRW_shgroup_uniform_texture(shgrp, "matcapImage", wpd->studio_light->equirectangular_radiance_gputexture); + } + if (SPECULAR_HIGHLIGHT_ENABLED(wpd) || MATCAP_ENABLED(wpd)) { + DRW_shgroup_uniform_vec2(shgrp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1); + } shgrp = DRW_shgroup_hair_create(ob, psys, md, vedata->psl->object_outline_pass, e_data.object_outline_hair_sh); @@ -541,14 +475,14 @@ void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob) return; } - if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT)) { + if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL)) { const DRWContextState *draw_ctx = DRW_context_state_get(); const bool is_active = (ob == draw_ctx->obact); const bool is_sculpt_mode = is_active && (draw_ctx->object_mode & OB_MODE_SCULPT) != 0; bool is_drawn = false; WORKBENCH_MaterialData *material = get_or_create_material_data(vedata, ob, NULL, NULL, OB_SOLID); - if (!is_sculpt_mode && wpd->drawtype == OB_TEXTURE && ob->type == OB_MESH) { + if (!is_sculpt_mode && wpd->drawtype == OB_TEXTURE && ELEM(ob->type, OB_MESH)) { const Mesh *me = ob->data; if (me->mloopuv) { const int materials_len = MAX2(1, (is_sculpt_mode ? 1 : ob->totcol)); @@ -556,6 +490,10 @@ void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob) struct Gwn_Batch **geom_array = me->totcol ? DRW_cache_mesh_surface_texpaint_get(ob) : NULL; if (materials_len > 0 && geom_array) { for (int i = 0; i < materials_len; i++) { + if (geom_array[i] == NULL) { + continue; + } + Material *mat = give_current_material(ob, i + 1); Image *image; ED_object_get_active_image(ob, i + 1, &image, NULL, NULL, NULL); @@ -565,9 +503,6 @@ void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob) mat_drawtype = OB_TEXTURE; } material = get_or_create_material_data(vedata, ob, mat, image, mat_drawtype); -#ifdef WORKBENCH_REVEALAGE_ENABLED - DRW_shgroup_call_object_add(wpd->transparent_revealage_shgrp, geom_array[i], ob); -#endif DRW_shgroup_call_object_add(material->shgrp_object_outline, geom_array[i], ob); DRW_shgroup_call_object_add(material->shgrp, geom_array[i], ob); } @@ -578,21 +513,15 @@ void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob) /* Fallback from not drawn OB_TEXTURE mode or just OB_SOLID mode */ if (!is_drawn) { - if ((wpd->shading.color_type != V3D_SHADING_MATERIAL_COLOR) || is_sculpt_mode) { + if ((wpd->shading.color_type != V3D_SHADING_MATERIAL_COLOR)) { /* No material split needed */ struct Gwn_Batch *geom = DRW_cache_object_surface_get(ob); if (geom) { if (is_sculpt_mode) { -#ifdef WORKBENCH_REVEALAGE_ENABLED - DRW_shgroup_call_sculpt_add(wpd->transparent_revealage_shgrp, ob, ob->obmat); -#endif DRW_shgroup_call_sculpt_add(material->shgrp_object_outline, ob, ob->obmat); DRW_shgroup_call_sculpt_add(material->shgrp, ob, ob->obmat); } else { -#ifdef WORKBENCH_REVEALAGE_ENABLED - DRW_shgroup_call_object_add(wpd->transparent_revealage_shgrp, geom, ob); -#endif DRW_shgroup_call_object_add(material->shgrp_object_outline, geom, ob); DRW_shgroup_call_object_add(material->shgrp, geom, ob); } @@ -609,13 +538,20 @@ void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob) ob, gpumat_array, materials_len, NULL, NULL, NULL); if (mat_geom) { for (int i = 0; i < materials_len; ++i) { + if (mat_geom[i] == NULL) { + continue; + } + Material *mat = give_current_material(ob, i + 1); material = get_or_create_material_data(vedata, ob, mat, NULL, OB_SOLID); -#ifdef WORKBENCH_REVEALAGE_ENABLED - DRW_shgroup_call_object_add(wpd->transparent_revealage_shgrp, mat_geom[i], ob); -#endif - DRW_shgroup_call_object_add(material->shgrp_object_outline, mat_geom[i], ob); - DRW_shgroup_call_object_add(material->shgrp, mat_geom[i], ob); + if (is_sculpt_mode) { + DRW_shgroup_call_sculpt_add(material->shgrp_object_outline, ob, ob->obmat); + DRW_shgroup_call_sculpt_add(material->shgrp, ob, ob->obmat); + } + else { + DRW_shgroup_call_object_add(material->shgrp_object_outline, mat_geom[i], ob); + DRW_shgroup_call_object_add(material->shgrp, mat_geom[i], ob); + } } } } @@ -631,7 +567,7 @@ void workbench_forward_draw_background(WORKBENCH_Data *UNUSED(vedata)) { const float clear_depth = 1.0f; DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); - DRW_stats_group_start("Clear Background"); + DRW_stats_group_start("Clear depth"); GPU_framebuffer_bind(dfbl->default_fb); GPU_framebuffer_clear_depth(dfbl->default_fb, clear_depth); DRW_stats_group_end(); @@ -646,17 +582,23 @@ void workbench_forward_draw_scene(WORKBENCH_Data *vedata) DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); /* Write Depth + Object ID */ + const float clear_outline[4] = {0.0f}; GPU_framebuffer_bind(fbl->object_outline_fb); + GPU_framebuffer_clear_color(fbl->object_outline_fb, clear_outline); DRW_draw_pass(psl->object_outline_pass); if (wpd->shading.xray_alpha > 0.0) { - /* Shade */ + const float clear_color[4] = {0.0f, 0.0f, 0.0f, 1.0f}; GPU_framebuffer_bind(fbl->transparent_accum_fb); + GPU_framebuffer_clear_color(fbl->transparent_accum_fb, clear_color); DRW_draw_pass(psl->transparent_accum_pass); -#ifdef WORKBENCH_REVEALAGE_ENABLED - GPU_framebuffer_bind(fbl->transparent_revealage_fb); - DRW_draw_pass(psl->transparent_revealage_pass); -#endif + } + else { + /* TODO(fclem): this is unecessary and takes up perf. + * Better change the composite frag shader to not use the tx. */ + const float clear_color[4] = {0.0f, 0.0f, 0.0f, 1.0f}; + GPU_framebuffer_bind(fbl->transparent_accum_fb); + GPU_framebuffer_clear_color(fbl->transparent_accum_fb, clear_color); } /* Composite */ diff --git a/source/blender/draw/engines/workbench/workbench_materials.c b/source/blender/draw/engines/workbench/workbench_materials.c index da1a9182306..31188fd2edf 100644 --- a/source/blender/draw/engines/workbench/workbench_materials.c +++ b/source/blender/draw/engines/workbench/workbench_materials.c @@ -103,10 +103,6 @@ char *workbench_material_build_defines(WORKBENCH_PrivateData *wpd, int drawtype, break; } -#ifdef WORKBENCH_REVEALAGE_ENABLED - BLI_dynstr_appendf(ds, "#define WORKBENCH_REVEALAGE_ENABLED\n"); -#endif - str = BLI_dynstr_get_cstring(ds); BLI_dynstr_free(ds); return str; diff --git a/source/blender/draw/engines/workbench/workbench_private.h b/source/blender/draw/engines/workbench/workbench_private.h index db3c219a597..c7173ee8f27 100644 --- a/source/blender/draw/engines/workbench/workbench_private.h +++ b/source/blender/draw/engines/workbench/workbench_private.h @@ -55,8 +55,6 @@ #define NORMAL_VIEWPORT_COMP_PASS_ENABLED(wpd) (MATCAP_ENABLED(wpd) || STUDIOLIGHT_ENABLED(wpd) || SHADOW_ENABLED(wpd) || SPECULAR_HIGHLIGHT_ENABLED(wpd)) #define NORMAL_VIEWPORT_PASS_ENABLED(wpd) (NORMAL_VIEWPORT_COMP_PASS_ENABLED(wpd) || CAVITY_ENABLED(wpd)) #define NORMAL_ENCODING_ENABLED() (true) -#define WORKBENCH_REVEALAGE_ENABLED - typedef struct WORKBENCH_FramebufferList { /* Deferred render buffers */ @@ -67,10 +65,7 @@ typedef struct WORKBENCH_FramebufferList { /* Forward render buffers */ struct GPUFrameBuffer *object_outline_fb; struct GPUFrameBuffer *transparent_accum_fb; - -#ifdef WORKBENCH_REVEALAGE_ENABLED struct GPUFrameBuffer *transparent_revealage_fb; -#endif } WORKBENCH_FramebufferList; typedef struct WORKBENCH_StorageList { @@ -93,9 +88,6 @@ typedef struct WORKBENCH_PassList { /* forward rendering */ struct DRWPass *transparent_accum_pass; -#ifdef WORKBENCH_REVEALAGE_ENABLED - struct DRWPass *transparent_revealage_pass; -#endif struct DRWPass *object_outline_pass; struct DRWPass *depth_pass; struct DRWPass *checker_depth_pass; @@ -162,9 +154,6 @@ typedef struct WORKBENCH_PrivateData { struct GPUUniformBuffer *world_ubo; struct DRWShadingGroup *shadow_shgrp; struct DRWShadingGroup *depth_shgrp; -#ifdef WORKBENCH_REVEALAGE_ENABLED - struct DRWShadingGroup *transparent_revealage_shgrp; -#endif WORKBENCH_UBO_World world_data; float shadow_multiplier; float cached_shadow_direction[3]; diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h index b74e6ba9204..f79a2405c3f 100644 --- a/source/blender/draw/intern/DRW_render.h +++ b/source/blender/draw/intern/DRW_render.h @@ -282,7 +282,7 @@ typedef enum { DRW_STATE_BLEND_PREMUL = (1 << 21), /* Use that if color is already premult by alpha. */ DRW_STATE_WIRE_SMOOTH = (1 << 22), DRW_STATE_TRANS_FEEDBACK = (1 << 23), - DRW_STATE_TRANSPARENT_REVEALAGE = (1 << 24), + DRW_STATE_BLEND_OIT = (1 << 24), DRW_STATE_WRITE_STENCIL = (1 << 27), DRW_STATE_WRITE_STENCIL_SHADOW_PASS = (1 << 28), diff --git a/source/blender/draw/intern/draw_armature.c b/source/blender/draw/intern/draw_armature.c index a736f0a31fb..82662d77020 100644 --- a/source/blender/draw/intern/draw_armature.c +++ b/source/blender/draw/intern/draw_armature.c @@ -1462,6 +1462,10 @@ static void pchan_draw_ik_lines(bPoseChannel *pchan, const bool only_temp, const bSplineIKConstraint *data = (bSplineIKConstraint *)con->data; int segcount = 0; + /* don't draw if only_temp, as Spline IK chains cannot be temporary */ + if (only_temp) + continue; + parchan = pchan; line_start = parchan->pose_tail; @@ -1489,17 +1493,24 @@ static void draw_bone_relations( { if (g_data.passes.relationship_lines) { if (ebone && ebone->parent) { - if ((boneflag & BONE_CONNECTED) == 0) { - drw_shgroup_bone_relationship_lines(ebone->head, ebone->parent->tail); + if (do_relations) { + /* Always draw for unconnected bones, regardless of selection, + * since riggers will want to know about the links between bones + */ + if ((boneflag & BONE_CONNECTED) == 0) { + drw_shgroup_bone_relationship_lines(ebone->head, ebone->parent->tail); + } } } else if (pchan && pchan->parent) { - /* Only draw if bone or its parent is selected - reduces viewport complexity with complex rigs */ - if ((boneflag & BONE_SELECTED) || - (pchan->parent->bone && (pchan->parent->bone->flag & BONE_SELECTED))) - { - if ((boneflag & BONE_CONNECTED) == 0) { - drw_shgroup_bone_relationship_lines(pchan->pose_head, pchan->parent->pose_tail); + if (do_relations) { + /* Only draw if bone or its parent is selected - reduces viewport complexity with complex rigs */ + if ((boneflag & BONE_SELECTED) || + (pchan->parent->bone && (pchan->parent->bone->flag & BONE_SELECTED))) + { + if ((boneflag & BONE_CONNECTED) == 0) { + drw_shgroup_bone_relationship_lines(pchan->pose_head, pchan->parent->pose_tail); + } } } @@ -1523,6 +1534,7 @@ static void draw_bone_relations( static void draw_armature_edit(Object *ob) { + const DRWContextState *draw_ctx = DRW_context_state_get(); EditBone *eBone; bArmature *arm = ob->data; int index; @@ -1531,7 +1543,7 @@ static void draw_armature_edit(Object *ob) update_color(ob, NULL); const bool show_text = DRW_state_show_text(); - const bool show_relations = true; /* TODO get value from overlays settings. */ + const bool show_relations = ((draw_ctx->v3d->flag & V3D_HIDE_HELPLINES) == 0); for (eBone = arm->edbo->first, index = ob->select_color; eBone; eBone = eBone->next, index += 0x10000) { if (eBone->layer & arm->layer) { @@ -1601,6 +1613,7 @@ static void draw_armature_edit(Object *ob) /* if const_color is NULL do pose mode coloring */ static void draw_armature_pose(Object *ob, const float const_color[4]) { + const DRWContextState *draw_ctx = DRW_context_state_get(); bArmature *arm = ob->data; bPoseChannel *pchan; int index = -1; @@ -1615,8 +1628,6 @@ static void draw_armature_pose(Object *ob, const float const_color[4]) // if (!(base->flag & OB_FROMDUPLI)) // TODO { - const DRWContextState *draw_ctx = DRW_context_state_get(); - if ((draw_ctx->object_mode & OB_MODE_POSE) || (ob == draw_ctx->object_pose)) { arm->flag |= ARM_POSEMODE; } @@ -1628,7 +1639,7 @@ static void draw_armature_pose(Object *ob, const float const_color[4]) const bool is_pose_select = (arm->flag & ARM_POSEMODE) && DRW_state_is_select(); const bool show_text = DRW_state_show_text(); - const bool show_relations = true; /* TODO get value from overlays settings. */ + const bool show_relations = ((draw_ctx->v3d->flag & V3D_HIDE_HELPLINES) == 0); /* being set below */ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c index 35b8392507d..45814946e8a 100644 --- a/source/blender/draw/intern/draw_cache.c +++ b/source/blender/draw/intern/draw_cache.c @@ -26,6 +26,7 @@ #include "DNA_scene_types.h" #include "DNA_mesh_types.h" +#include "DNA_meta_types.h" #include "DNA_curve_types.h" #include "DNA_object_types.h" #include "DNA_particle_types.h" @@ -111,6 +112,17 @@ void DRW_shape_cache_free(void) } } +void DRW_shape_cache_reset(void) +{ + uint i = sizeof(SHC) / sizeof(Gwn_Batch *); + Gwn_Batch **batch = (Gwn_Batch **)&SHC; + while (i--) { + if (*batch) { + gwn_batch_vao_cache_clear(*batch); + } + batch++; + } +} /* -------------------------------------------------------------------- */ @@ -576,6 +588,8 @@ Gwn_Batch **DRW_cache_object_surface_material_get( return DRW_cache_surf_surface_shaded_get(ob, gpumat_array, gpumat_array_len); case OB_FONT: return DRW_cache_text_surface_shaded_get(ob, gpumat_array, gpumat_array_len); + case OB_MBALL: + return DRW_cache_mball_surface_shaded_get(ob, gpumat_array, gpumat_array_len); default: return NULL; } @@ -2804,6 +2818,14 @@ Gwn_Batch *DRW_cache_mball_surface_get(Object *ob) return DRW_metaball_batch_cache_get_triangles_with_normals(ob); } +Gwn_Batch **DRW_cache_mball_surface_shaded_get( + Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len) +{ + BLI_assert(ob->type == OB_MBALL); + MetaBall *mb = ob->data; + return DRW_metaball_batch_cache_get_surface_shaded(ob, mb, gpumat_array, gpumat_array_len); +} + /** \} */ /* -------------------------------------------------------------------- */ diff --git a/source/blender/draw/intern/draw_cache.h b/source/blender/draw/intern/draw_cache.h index 4b353d8f461..ea08b8e0fe0 100644 --- a/source/blender/draw/intern/draw_cache.h +++ b/source/blender/draw/intern/draw_cache.h @@ -36,6 +36,7 @@ struct HairExportCache; struct DRWHairFiberTextureBuffer; void DRW_shape_cache_free(void); +void DRW_shape_cache_reset(void); /* 3D cursor */ struct Gwn_Batch *DRW_cache_cursor_get(bool crosshair_lines); @@ -196,5 +197,6 @@ struct Gwn_Batch *DRW_cache_hair_get_guide_curve_edges(struct HairSystem *hsys, /* Metaball */ struct Gwn_Batch *DRW_cache_mball_surface_get(struct Object *ob); +struct Gwn_Batch **DRW_cache_mball_surface_shaded_get(struct Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len); #endif /* __DRAW_CACHE_H__ */ diff --git a/source/blender/draw/intern/draw_cache_impl.h b/source/blender/draw/intern/draw_cache_impl.h index c15ab49d0ce..5652657526f 100644 --- a/source/blender/draw/intern/draw_cache_impl.h +++ b/source/blender/draw/intern/draw_cache_impl.h @@ -79,6 +79,7 @@ struct Gwn_Batch **DRW_curve_batch_cache_get_surface_shaded( /* Metaball */ struct Gwn_Batch *DRW_metaball_batch_cache_get_triangles_with_normals(struct Object *ob); +struct Gwn_Batch **DRW_metaball_batch_cache_get_surface_shaded(struct Object *ob, struct MetaBall *mb, struct GPUMaterial **gpumat_array, uint gpumat_array_len); /* Curve (Font) */ struct Gwn_Batch *DRW_curve_batch_cache_get_overlay_cursor(struct Curve *cu); diff --git a/source/blender/draw/intern/draw_cache_impl_metaball.c b/source/blender/draw/intern/draw_cache_impl_metaball.c index f01e7b929f8..24930921bee 100644 --- a/source/blender/draw/intern/draw_cache_impl_metaball.c +++ b/source/blender/draw/intern/draw_cache_impl_metaball.c @@ -49,7 +49,9 @@ static void metaball_batch_cache_clear(MetaBall *mb); typedef struct MetaBallBatchCache { Gwn_Batch *batch; + Gwn_Batch **shaded_triangles; + int mat_len; /* settings to determine if cache is invalid */ bool is_dirty; } MetaBallBatchCache; @@ -75,6 +77,8 @@ static void metaball_batch_cache_init(MetaBall *mb) cache = mb->batch_cache = MEM_mallocN(sizeof(*cache), __func__); } cache->batch = NULL; + cache->mat_len = 0; + cache->shaded_triangles = NULL; cache->is_dirty = false; } @@ -110,6 +114,9 @@ static void metaball_batch_cache_clear(MetaBall *mb) } GWN_BATCH_DISCARD_SAFE(cache->batch); + /* Note: shaded_triangles[0] is already freed by cache->batch */ + MEM_SAFE_FREE(cache->shaded_triangles); + cache->mat_len = 0; } void DRW_mball_batch_cache_free(MetaBall *mb) @@ -125,8 +132,9 @@ void DRW_mball_batch_cache_free(MetaBall *mb) Gwn_Batch *DRW_metaball_batch_cache_get_triangles_with_normals(Object *ob) { - if (!BKE_mball_is_basis(ob)) + if (!BKE_mball_is_basis(ob)) { return NULL; + } MetaBall *mb = ob->data; MetaBallBatchCache *cache = metaball_batch_cache_get(mb); @@ -142,3 +150,22 @@ Gwn_Batch *DRW_metaball_batch_cache_get_triangles_with_normals(Object *ob) return cache->batch; } + +Gwn_Batch **DRW_metaball_batch_cache_get_surface_shaded(Object *ob, MetaBall *mb, struct GPUMaterial **UNUSED(gpumat_array), uint gpumat_array_len) +{ + if (!BKE_mball_is_basis(ob)) { + return NULL; + } + + MetaBallBatchCache *cache = metaball_batch_cache_get(mb); + if (cache->shaded_triangles == NULL) { + cache->mat_len = gpumat_array_len; + cache->shaded_triangles = MEM_callocN(sizeof(*cache->shaded_triangles) * cache->mat_len, __func__); + cache->shaded_triangles[0] = DRW_metaball_batch_cache_get_triangles_with_normals(ob); + for (int i = 1; i < cache->mat_len; ++i) { + cache->shaded_triangles[i] = NULL; + } + } + return cache->shaded_triangles; + +} diff --git a/source/blender/draw/intern/draw_common.c b/source/blender/draw/intern/draw_common.c index fb8833f40c3..f32dc5fadaa 100644 --- a/source/blender/draw/intern/draw_common.c +++ b/source/blender/draw/intern/draw_common.c @@ -50,6 +50,7 @@ struct GPUTexture *globals_ramp = NULL; void DRW_globals_update(void) { UI_GetThemeColor4fv(TH_WIRE, ts.colorWire); + UI_GetThemeColor4fv(TH_WIRE_INACTIVE, ts.colorWireInactive); UI_GetThemeColor4fv(TH_WIRE_EDIT, ts.colorWireEdit); UI_GetThemeColor4fv(TH_ACTIVE, ts.colorActive); UI_GetThemeColor4fv(TH_SELECT, ts.colorSelect); @@ -64,6 +65,7 @@ void DRW_globals_update(void) UI_GetThemeColor4fv(TH_VERTEX_SELECT, ts.colorVertexSelect); UI_GetThemeColor4fv(TH_EDITMESH_ACTIVE, ts.colorEditMeshActive); UI_GetThemeColor4fv(TH_EDGE_SELECT, ts.colorEdgeSelect); + UI_GetThemeColor4fv(TH_EDGE_SEAM, ts.colorEdgeSeam); UI_GetThemeColor4fv(TH_EDGE_SHARP, ts.colorEdgeSharp); UI_GetThemeColor4fv(TH_EDGE_CREASE, ts.colorEdgeCrease); diff --git a/source/blender/draw/intern/draw_common.h b/source/blender/draw/intern/draw_common.h index d2e9c4d1537..422d478c8a8 100644 --- a/source/blender/draw/intern/draw_common.h +++ b/source/blender/draw/intern/draw_common.h @@ -47,6 +47,7 @@ struct PTCacheEdit; typedef struct GlobalsUboStorage { /* UBOs data needs to be 16 byte aligned (size of vec4) */ float colorWire[4]; + float colorWireInactive[4]; float colorWireEdit[4]; float colorActive[4]; float colorSelect[4]; diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index a70f5f8a487..d3cda45f79d 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -76,7 +76,6 @@ #include "draw_cache_impl.h" #include "draw_mode_engines.h" -#include "engines/clay/clay_engine.h" #include "engines/eevee/eevee_engine.h" #include "engines/basic/basic_engine.h" #include "engines/workbench/workbench_engine.h" @@ -100,7 +99,7 @@ extern struct GPUUniformBuffer *view_ubo; /* draw_manager_exec.c */ static void drw_state_prepare_clean_for_draw(DRWManager *dst) { - memset(dst, 0x0, offsetof(DRWManager, ogl_context)); + memset(dst, 0x0, offsetof(DRWManager, gl_context)); } /* This function is used to reset draw manager to a state @@ -110,7 +109,7 @@ static void drw_state_prepare_clean_for_draw(DRWManager *dst) #ifdef DEBUG static void drw_state_ensure_not_reused(DRWManager *dst) { - memset(dst, 0xff, offsetof(DRWManager, ogl_context)); + memset(dst, 0xff, offsetof(DRWManager, gl_context)); } #endif @@ -1180,7 +1179,7 @@ void DRW_notify_view_update(const DRWUpdateContext *update_ctx) /* XXX Really nasty locking. But else this could * be executed by the material previews thread * while rendering a viewport. */ - BLI_mutex_lock(&DST.ogl_context_mutex); + BLI_mutex_lock(&DST.gl_context_mutex); /* Reset before using it. */ drw_state_prepare_clean_for_draw(&DST); @@ -1208,7 +1207,7 @@ void DRW_notify_view_update(const DRWUpdateContext *update_ctx) drw_engines_disable(); - BLI_mutex_unlock(&DST.ogl_context_mutex); + BLI_mutex_unlock(&DST.gl_context_mutex); } } @@ -1312,13 +1311,14 @@ void DRW_draw_render_loop_ex( } DRW_stats_begin(); - DRW_hair_update(); GPU_framebuffer_bind(DST.default_framebuffer); /* Start Drawing */ DRW_state_reset(); + DRW_hair_update(); + drw_engines_draw_background(); /* WIP, single image drawn over the camera view (replace) */ @@ -1460,12 +1460,28 @@ void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph) RenderData *r = &scene->r; Render *render = engine->re; - if (G.background && DST.ogl_context == NULL) { + if (G.background && DST.gl_context == NULL) { WM_init_opengl(); } + void *re_gl_context = RE_gl_context_get(render); + void *re_gwn_context = NULL; + /* Changing Context */ - DRW_opengl_context_enable(); + if (re_gl_context != NULL) { + /* TODO get rid of the blocking. Only here because of the static global DST. */ + BLI_mutex_lock(&DST.gl_context_mutex); + WM_opengl_context_activate(re_gl_context); + re_gwn_context = RE_gwn_context_get(render); + if (GWN_context_active_get() == NULL) { + GWN_context_active_set(re_gwn_context); + } + DRW_shape_cache_reset(); /* XXX fix that too. */ + } + else { + DRW_opengl_context_enable(); + } + /* IMPORTANT: We dont support immediate mode in render mode! * This shall remain in effect until immediate mode supports * multiple threads. */ @@ -1532,13 +1548,23 @@ void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph) GPU_viewport_free(DST.viewport); GPU_framebuffer_restore(); - /* Changing Context */ - DRW_opengl_context_disable(); - #ifdef DEBUG /* Avoid accidental reuse. */ drw_state_ensure_not_reused(&DST); #endif + + /* Changing Context */ + if (re_gl_context != NULL) { + DRW_shape_cache_reset(); /* XXX fix that too. */ + glFlush(); + GWN_context_active_set(NULL); + WM_opengl_context_release(re_gl_context); + /* TODO get rid of the blocking. */ + BLI_mutex_unlock(&DST.gl_context_mutex); + } + else { + DRW_opengl_context_disable(); + } } void DRW_render_object_iter( @@ -1712,8 +1738,6 @@ void DRW_draw_select_loop( DRW_render_instance_buffer_finish(); } - DRW_hair_update(); - /* Setup framebuffer */ draw_select_framebuffer_setup(rect); GPU_framebuffer_bind(g_select_buffer.framebuffer); @@ -1723,6 +1747,8 @@ void DRW_draw_select_loop( DRW_state_reset(); DRW_draw_callbacks_pre_scene(); + DRW_hair_update(); + DRW_state_lock( DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS | @@ -1872,10 +1898,11 @@ void DRW_draw_depth_loop( DRW_render_instance_buffer_finish(); } - DRW_hair_update(); - /* Start Drawing */ DRW_state_reset(); + + DRW_hair_update(); + DRW_draw_callbacks_pre_scene(); drw_engines_draw_scene(); DRW_draw_callbacks_post_scene(); @@ -2042,9 +2069,6 @@ void DRW_engine_register(DrawEngineType *draw_engine_type) void DRW_engines_register(void) { -#ifdef WITH_CLAY_ENGINE - RE_engines_register(&DRW_engine_viewport_clay_type); -#endif RE_engines_register(&DRW_engine_viewport_eevee_type); RE_engines_register(&DRW_engine_viewport_workbench_type); @@ -2145,10 +2169,6 @@ void DRW_engines_free(void) MEM_SAFE_FREE(DST.RST.bound_ubo_slots); DRW_opengl_context_disable(); - -#ifdef WITH_CLAY_ENGINE - BLI_remlink(&R_engines, &DRW_engine_viewport_clay_type); -#endif } /** \} */ @@ -2158,14 +2178,16 @@ void DRW_engines_free(void) void DRW_opengl_context_create(void) { - BLI_assert(DST.ogl_context == NULL); /* Ensure it's called once */ + BLI_assert(DST.gl_context == NULL); /* Ensure it's called once */ - BLI_mutex_init(&DST.ogl_context_mutex); + BLI_mutex_init(&DST.gl_context_mutex); if (!G.background) { immDeactivate(); } /* This changes the active context. */ - DST.ogl_context = WM_opengl_context_create(); + DST.gl_context = WM_opengl_context_create(); + /* Make the context active for this thread (main thread) */ + WM_opengl_context_activate(DST.gl_context); /* Be sure to create gawain.context too. */ DST.gwn_context = GWN_context_create(); if (!G.background) { @@ -2180,28 +2202,28 @@ void DRW_opengl_context_create(void) void DRW_opengl_context_destroy(void) { BLI_assert(BLI_thread_is_main()); - if (DST.ogl_context != NULL) { - WM_opengl_context_activate(DST.ogl_context); + if (DST.gl_context != NULL) { + WM_opengl_context_activate(DST.gl_context); GWN_context_active_set(DST.gwn_context); GWN_context_discard(DST.gwn_context); - WM_opengl_context_dispose(DST.ogl_context); - BLI_mutex_end(&DST.ogl_context_mutex); + WM_opengl_context_dispose(DST.gl_context); + BLI_mutex_end(&DST.gl_context_mutex); } } void DRW_opengl_context_enable(void) { - if (DST.ogl_context != NULL) { + if (DST.gl_context != NULL) { /* IMPORTANT: We dont support immediate mode in render mode! * This shall remain in effect until immediate mode supports * multiple threads. */ - BLI_mutex_lock(&DST.ogl_context_mutex); + BLI_mutex_lock(&DST.gl_context_mutex); if (BLI_thread_is_main()) { if (!G.background) { immDeactivate(); } } - WM_opengl_context_activate(DST.ogl_context); + WM_opengl_context_activate(DST.gl_context); GWN_context_active_set(DST.gwn_context); if (BLI_thread_is_main()) { if (!G.background) { @@ -2214,7 +2236,7 @@ void DRW_opengl_context_enable(void) void DRW_opengl_context_disable(void) { - if (DST.ogl_context != NULL) { + if (DST.gl_context != NULL) { #ifdef __APPLE__ /* Need to flush before disabling draw context, otherwise it does not * always finish drawing and viewport can be empty or partially drawn */ @@ -2225,11 +2247,11 @@ void DRW_opengl_context_disable(void) wm_window_reset_drawable(); } else { - WM_opengl_context_release(DST.ogl_context); + WM_opengl_context_release(DST.gl_context); GWN_context_active_set(NULL); } - BLI_mutex_unlock(&DST.ogl_context_mutex); + BLI_mutex_unlock(&DST.gl_context_mutex); } } diff --git a/source/blender/draw/intern/draw_manager.h b/source/blender/draw/intern/draw_manager.h index 7cb6aef818b..e811e9ea8a9 100644 --- a/source/blender/draw/intern/draw_manager.h +++ b/source/blender/draw/intern/draw_manager.h @@ -369,11 +369,11 @@ typedef struct DRWManager { /* ---------- Nothing after this point is cleared after use ----------- */ - /* ogl_context serves as the offset for clearing only + /* gl_context serves as the offset for clearing only * the top portion of the struct so DO NOT MOVE IT! */ - void *ogl_context; /* Unique ghost context used by the draw manager. */ + void *gl_context; /* Unique ghost context used by the draw manager. */ Gwn_Context *gwn_context; - ThreadMutex ogl_context_mutex; /* Mutex to lock the drw manager and avoid concurent context usage. */ + ThreadMutex gl_context_mutex; /* Mutex to lock the drw manager and avoid concurent context usage. */ /** GPU Resource State: Memory storage between drawing. */ struct { diff --git a/source/blender/draw/intern/draw_manager_data.c b/source/blender/draw/intern/draw_manager_data.c index b49af47223f..db4e16d362a 100644 --- a/source/blender/draw/intern/draw_manager_data.c +++ b/source/blender/draw/intern/draw_manager_data.c @@ -768,7 +768,7 @@ static DRWShadingGroup *drw_shgroup_material_inputs(DRWShadingGroup *grp, struct if (input->ima) { double time = 0.0; /* TODO make time variable */ GPUTexture *tex = GPU_texture_from_blender( - input->ima, input->iuser, input->textarget, input->image_isdata, time, 1); + input->ima, input->iuser, input->textarget, input->image_isdata, time); if (input->bindtex) { DRW_shgroup_uniform_texture(grp, input->shadername, tex); diff --git a/source/blender/draw/intern/draw_manager_exec.c b/source/blender/draw/intern/draw_manager_exec.c index f6b6438395d..3b7d19ac361 100644 --- a/source/blender/draw/intern/draw_manager_exec.c +++ b/source/blender/draw/intern/draw_manager_exec.c @@ -222,7 +222,7 @@ void drw_state_set(DRWState state) if (CHANGED_ANY_STORE_VAR( DRW_STATE_BLEND | DRW_STATE_BLEND_PREMUL | DRW_STATE_ADDITIVE | DRW_STATE_MULTIPLY | DRW_STATE_TRANSMISSION | DRW_STATE_ADDITIVE_FULL | - DRW_STATE_TRANSPARENT_REVEALAGE, + DRW_STATE_BLEND_OIT, test)) { if (test) { @@ -241,8 +241,9 @@ void drw_state_set(DRWState state) else if ((state & DRW_STATE_TRANSMISSION) != 0) { glBlendFunc(GL_ONE, GL_SRC_ALPHA); } - else if ((state & DRW_STATE_TRANSPARENT_REVEALAGE) != 0) { - glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR); + else if ((state & DRW_STATE_BLEND_OIT) != 0) { + glBlendFuncSeparate(GL_ONE, GL_ONE, /* RGB */ + GL_ZERO, GL_ONE_MINUS_SRC_ALPHA); /* Alpha */ } else if ((state & DRW_STATE_ADDITIVE) != 0) { /* Do not let alpha accumulate but premult the source RGB by it. */ diff --git a/source/blender/draw/intern/draw_manager_shader.c b/source/blender/draw/intern/draw_manager_shader.c index 0b6974b7b36..edc65afd465 100644 --- a/source/blender/draw/intern/draw_manager_shader.c +++ b/source/blender/draw/intern/draw_manager_shader.c @@ -71,7 +71,7 @@ typedef struct DRWShaderCompiler { DRWDeferredShader *mat_compiling; ThreadMutex compilation_lock; - void *ogl_context; + void *gl_context; int shaders_done; /* To compute progress. */ } DRWShaderCompiler; @@ -93,9 +93,9 @@ static void drw_deferred_shader_queue_free(ListBase *queue) static void drw_deferred_shader_compilation_exec(void *custom_data, short *stop, short *do_update, float *progress) { DRWShaderCompiler *comp = (DRWShaderCompiler *)custom_data; - void *ogl_context = comp->ogl_context; + void *gl_context = comp->gl_context; - WM_opengl_context_activate(ogl_context); + WM_opengl_context_activate(gl_context); while (true) { BLI_spin_lock(&comp->list_lock); @@ -134,7 +134,7 @@ static void drw_deferred_shader_compilation_exec(void *custom_data, short *stop, drw_deferred_shader_free(comp->mat_compiling); } - WM_opengl_context_release(ogl_context); + WM_opengl_context_release(gl_context); } static void drw_deferred_shader_compilation_free(void *custom_data) @@ -146,9 +146,9 @@ static void drw_deferred_shader_compilation_free(void *custom_data) BLI_spin_end(&comp->list_lock); BLI_mutex_end(&comp->compilation_lock); - if (comp->ogl_context) { + if (comp->gl_context) { /* Only destroy if the job owns the context. */ - WM_opengl_context_dispose(comp->ogl_context); + WM_opengl_context_dispose(comp->gl_context); } MEM_freeN(comp); @@ -189,16 +189,16 @@ static void drw_deferred_shader_add(GPUMaterial *mat) BLI_movelisttolist(&comp->queue, &old_comp->queue); BLI_spin_unlock(&old_comp->list_lock); /* Do not recreate context, just pass ownership. */ - comp->ogl_context = old_comp->ogl_context; - old_comp->ogl_context = NULL; + comp->gl_context = old_comp->gl_context; + old_comp->gl_context = NULL; } BLI_addtail(&comp->queue, dsh); /* Create only one context. */ - if (comp->ogl_context == NULL) { - comp->ogl_context = WM_opengl_context_create(); - WM_opengl_context_activate(DST.ogl_context); + if (comp->gl_context == NULL) { + comp->gl_context = WM_opengl_context_create(); + WM_opengl_context_activate(DST.gl_context); } WM_jobs_customdata_set(wm_job, comp, drw_deferred_shader_compilation_free); diff --git a/source/blender/draw/modes/edit_mesh_mode.c b/source/blender/draw/modes/edit_mesh_mode.c index b50fb554a51..94eeb58dcb2 100644 --- a/source/blender/draw/modes/edit_mesh_mode.c +++ b/source/blender/draw/modes/edit_mesh_mode.c @@ -39,6 +39,9 @@ #include "BKE_object.h" +#include "BLI_dynstr.h" + + extern struct GPUUniformBuffer *globals_ubo; /* draw_common.c */ extern struct GlobalsUboStorage ts; /* draw_common.c */ @@ -87,16 +90,16 @@ typedef struct EDIT_MESH_Data { } EDIT_MESH_Data; /* *********** STATIC *********** */ +#define MAX_SHADERS 16 static struct { /* weight/vert-color */ GPUShader *vcolor_face_shader; - GPUShader *overlay_tri_sh; - GPUShader *overlay_tri_fast_sh; - GPUShader *overlay_tri_vcol_sh; - GPUShader *overlay_tri_vcol_fast_sh; - GPUShader *overlay_edge_sh; - GPUShader *overlay_edge_vcol_sh; + + /* Geometry */ + GPUShader *overlay_tri_sh_cache[MAX_SHADERS]; + GPUShader *overlay_loose_edge_sh_cache[MAX_SHADERS]; + GPUShader *overlay_vert_sh; GPUShader *overlay_facedot_sh; GPUShader *overlay_mix_sh; @@ -133,6 +136,79 @@ typedef struct EDIT_MESH_PrivateData { } EDIT_MESH_PrivateData; /* Transient data */ /* *********** FUNCTIONS *********** */ +static int EDIT_MESH_sh_index(ToolSettings *tsettings, RegionView3D *rv3d, bool supports_fast_mode) +{ + int result = tsettings->selectmode << 1; + if (supports_fast_mode) { + SET_FLAG_FROM_TEST(result, (rv3d->rflag & RV3D_NAVIGATING), 1 << 0); + } + return result; +} + +static char *EDIT_MESH_sh_defines(ToolSettings *tsettings, RegionView3D *rv3d, bool anti_alias) +{ + const int selectmode = tsettings->selectmode; + const int fast_mode = rv3d->rflag & RV3D_NAVIGATING; + + char *str = NULL; + DynStr *ds = BLI_dynstr_new(); + + if (selectmode & SCE_SELECT_VERTEX) { + BLI_dynstr_append(ds, "#define VERTEX_SELECTION\n"); + } + + if (selectmode & SCE_SELECT_EDGE) { + BLI_dynstr_append(ds, "#define EDGE_SELECTION\n"); + } + + if (selectmode & SCE_SELECT_FACE) { + BLI_dynstr_append(ds, "#define FACE_SELECTION\n"); + } + + if (!fast_mode) { + BLI_dynstr_append(ds, "#define EDGE_FIX\n"); + } + + if (anti_alias) { + BLI_dynstr_append(ds, "#define ANTI_ALIASING\n"); + } + BLI_dynstr_append(ds, "#define VERTEX_FACING\n"); + + str = BLI_dynstr_get_cstring(ds); + BLI_dynstr_free(ds); + return str; +} + +static GPUShader *EDIT_MESH_ensure_shader(ToolSettings *tsettings, RegionView3D *rv3d, bool fast_mode, bool looseedge) +{ + const int index = EDIT_MESH_sh_index(tsettings, rv3d, fast_mode); + if (looseedge) { + if (!e_data.overlay_loose_edge_sh_cache[index]) { + char *defines = EDIT_MESH_sh_defines(tsettings, rv3d, true); + e_data.overlay_loose_edge_sh_cache[index] = DRW_shader_create_with_lib( + datatoc_edit_mesh_overlay_vert_glsl, + datatoc_edit_mesh_overlay_geom_edge_glsl, + datatoc_edit_mesh_overlay_frag_glsl, + datatoc_common_globals_lib_glsl, + defines); + MEM_freeN(defines); + } + return e_data.overlay_loose_edge_sh_cache[index]; + } + else { + if (!e_data.overlay_tri_sh_cache[index]) { + char *defines = EDIT_MESH_sh_defines(tsettings, rv3d, true); + e_data.overlay_tri_sh_cache[index] = DRW_shader_create_with_lib( + datatoc_edit_mesh_overlay_vert_glsl, + datatoc_edit_mesh_overlay_geom_tri_glsl, + datatoc_edit_mesh_overlay_frag_glsl, + datatoc_common_globals_lib_glsl, + defines); + MEM_freeN(defines); + } + return e_data.overlay_tri_sh_cache[index]; + } +} static void EDIT_MESH_engine_init(void *vedata) { @@ -155,64 +231,6 @@ static void EDIT_MESH_engine_init(void *vedata) e_data.vcolor_face_shader = GPU_shader_get_builtin_shader(GPU_SHADER_SIMPLE_LIGHTING_SMOOTH_COLOR_ALPHA); } - if (!e_data.overlay_tri_sh) { - e_data.overlay_tri_sh = DRW_shader_create_with_lib( - datatoc_edit_mesh_overlay_vert_glsl, - datatoc_edit_mesh_overlay_geom_tri_glsl, - datatoc_edit_mesh_overlay_frag_glsl, - datatoc_common_globals_lib_glsl, - "#define EDGE_FIX\n" - "#define ANTI_ALIASING\n" - "#define VERTEX_FACING"); - } - if (!e_data.overlay_tri_fast_sh) { - e_data.overlay_tri_fast_sh = DRW_shader_create_with_lib( - datatoc_edit_mesh_overlay_vert_glsl, - datatoc_edit_mesh_overlay_geom_tri_glsl, - datatoc_edit_mesh_overlay_frag_glsl, - datatoc_common_globals_lib_glsl, - "#define ANTI_ALIASING\n" - "#define VERTEX_FACING\n"); - } - if (!e_data.overlay_tri_vcol_sh) { - e_data.overlay_tri_vcol_sh = DRW_shader_create_with_lib( - datatoc_edit_mesh_overlay_vert_glsl, - datatoc_edit_mesh_overlay_geom_tri_glsl, - datatoc_edit_mesh_overlay_frag_glsl, - datatoc_common_globals_lib_glsl, - "#define EDGE_FIX\n" - "#define VERTEX_SELECTION\n" - "#define ANTI_ALIASING\n" - "#define VERTEX_FACING\n"); - } - if (!e_data.overlay_tri_vcol_fast_sh) { - e_data.overlay_tri_vcol_fast_sh = DRW_shader_create_with_lib( - datatoc_edit_mesh_overlay_vert_glsl, - datatoc_edit_mesh_overlay_geom_tri_glsl, - datatoc_edit_mesh_overlay_frag_glsl, - datatoc_common_globals_lib_glsl, - "#define VERTEX_SELECTION\n" - "#define ANTI_ALIASING\n" - "#define VERTEX_FACING\n"); - } - if (!e_data.overlay_edge_sh) { - e_data.overlay_edge_sh = DRW_shader_create_with_lib( - datatoc_edit_mesh_overlay_vert_glsl, - datatoc_edit_mesh_overlay_geom_edge_glsl, - datatoc_edit_mesh_overlay_frag_glsl, - datatoc_common_globals_lib_glsl, - "#define ANTI_ALIASING\n" - "#define VERTEX_FACING\n"); - } - if (!e_data.overlay_edge_vcol_sh) { - e_data.overlay_edge_vcol_sh = DRW_shader_create_with_lib( - datatoc_edit_mesh_overlay_vert_glsl, - datatoc_edit_mesh_overlay_geom_edge_glsl, - datatoc_edit_mesh_overlay_frag_glsl, - datatoc_common_globals_lib_glsl, - "#define VERTEX_SELECTION\n" - "#define VERTEX_FACING\n"); - } if (!e_data.overlay_vert_sh) { e_data.overlay_vert_sh = DRW_shader_create_with_lib( datatoc_edit_mesh_overlay_loosevert_vert_glsl, NULL, @@ -272,22 +290,8 @@ static DRWPass *edit_mesh_create_overlay_pass( Scene *scene = draw_ctx->scene; ToolSettings *tsettings = scene->toolsettings; - if ((tsettings->selectmode & SCE_SELECT_VERTEX) != 0) { - ledge_sh = e_data.overlay_edge_vcol_sh; - - if ((rv3d->rflag & RV3D_NAVIGATING) != 0) - tri_sh = e_data.overlay_tri_vcol_fast_sh; - else - tri_sh = e_data.overlay_tri_vcol_sh; - } - else { - ledge_sh = e_data.overlay_edge_sh; - - if ((rv3d->rflag & RV3D_NAVIGATING) != 0) - tri_sh = e_data.overlay_tri_fast_sh; - else - tri_sh = e_data.overlay_tri_sh; - } + ledge_sh = EDIT_MESH_ensure_shader(tsettings, rv3d, false, true); + tri_sh = EDIT_MESH_ensure_shader(tsettings, rv3d, true, false); DRWPass *pass = DRW_pass_create( "Edit Mesh Face Overlay Pass", @@ -435,7 +439,7 @@ static void edit_mesh_add_ob_to_pass( DRW_shgroup_call_add(lverts_shgrp, geo_ovl_lverts, ob->obmat); } - if ((tsettings->selectmode & SCE_SELECT_FACE) != 0) { + if (facedot_shgrp && (tsettings->selectmode & SCE_SELECT_FACE) != 0 ) { geo_ovl_fcenter = DRW_cache_face_centers_get(ob); DRW_shgroup_call_add(facedot_shgrp, geo_ovl_fcenter, ob->obmat); } @@ -505,7 +509,7 @@ static void EDIT_MESH_cache_populate(void *vedata, Object *ob) else { edit_mesh_add_ob_to_pass( scene, ob, stl->g_data->face_overlay_shgrp, stl->g_data->ledges_overlay_shgrp, - stl->g_data->lverts_overlay_shgrp, stl->g_data->facedot_overlay_shgrp, NULL); + stl->g_data->lverts_overlay_shgrp, NULL, NULL); } /* 3D text overlay */ @@ -557,12 +561,6 @@ static void EDIT_MESH_draw_scene(void *vedata) static void EDIT_MESH_engine_free(void) { - DRW_SHADER_FREE_SAFE(e_data.overlay_tri_sh); - DRW_SHADER_FREE_SAFE(e_data.overlay_tri_fast_sh); - DRW_SHADER_FREE_SAFE(e_data.overlay_tri_vcol_sh); - DRW_SHADER_FREE_SAFE(e_data.overlay_tri_vcol_fast_sh); - DRW_SHADER_FREE_SAFE(e_data.overlay_edge_sh); - DRW_SHADER_FREE_SAFE(e_data.overlay_edge_vcol_sh); DRW_SHADER_FREE_SAFE(e_data.overlay_vert_sh); DRW_SHADER_FREE_SAFE(e_data.overlay_facedot_sh); DRW_SHADER_FREE_SAFE(e_data.overlay_mix_sh); @@ -570,6 +568,11 @@ static void EDIT_MESH_engine_free(void) DRW_SHADER_FREE_SAFE(e_data.normals_loop_sh); DRW_SHADER_FREE_SAFE(e_data.normals_face_sh); DRW_SHADER_FREE_SAFE(e_data.normals_sh); + + for (int i = 0; i < MAX_SHADERS; i++) { + DRW_SHADER_FREE_SAFE(e_data.overlay_tri_sh_cache[i]); + DRW_SHADER_FREE_SAFE(e_data.overlay_loose_edge_sh_cache[i]); + } } static const DrawEngineDataSize EDIT_MESH_data_size = DRW_VIEWPORT_DATA_SIZE(EDIT_MESH_Data); diff --git a/source/blender/draw/modes/object_mode.c b/source/blender/draw/modes/object_mode.c index 09ed4b96756..a5875eff813 100644 --- a/source/blender/draw/modes/object_mode.c +++ b/source/blender/draw/modes/object_mode.c @@ -74,6 +74,8 @@ extern struct GPUUniformBuffer *globals_ubo; /* draw_common.c */ extern struct GPUTexture *globals_ramp; /* draw_common.c */ extern GlobalsUboStorage ts; +extern char datatoc_object_outline_prepass_vert_glsl[]; +extern char datatoc_object_outline_prepass_geom_glsl[]; extern char datatoc_object_outline_prepass_frag_glsl[]; extern char datatoc_object_outline_resolve_frag_glsl[]; extern char datatoc_object_outline_detect_frag_glsl[]; @@ -257,9 +259,11 @@ static struct { /* fullscreen shaders */ GPUShader *outline_prepass_sh; + GPUShader *outline_prepass_wire_sh; GPUShader *outline_resolve_sh; GPUShader *outline_resolve_aa_sh; GPUShader *outline_detect_sh; + GPUShader *outline_detect_wire_sh; GPUShader *outline_fade_sh; /* regular shaders */ @@ -348,6 +352,11 @@ static void OBJECT_engine_init(void *vedata) /* Outline */ e_data.outline_prepass_sh = DRW_shader_create_3D(datatoc_object_outline_prepass_frag_glsl, NULL); + e_data.outline_prepass_wire_sh = DRW_shader_create( + datatoc_object_outline_prepass_vert_glsl, + datatoc_object_outline_prepass_geom_glsl, + datatoc_object_outline_prepass_frag_glsl, NULL); + e_data.outline_resolve_sh = DRW_shader_create_fullscreen(datatoc_object_outline_resolve_frag_glsl, NULL); e_data.outline_resolve_aa_sh = DRW_shader_create_with_lib( @@ -363,6 +372,14 @@ static void OBJECT_engine_init(void *vedata) datatoc_common_globals_lib_glsl, "#extension GL_ARB_texture_gather : enable\n"); + e_data.outline_detect_wire_sh = DRW_shader_create_with_lib( + datatoc_common_fullscreen_vert_glsl, NULL, + datatoc_object_outline_detect_frag_glsl, + datatoc_common_globals_lib_glsl, + "#define WIRE\n" + "#extension GL_ARB_texture_gather : enable\n"); + + e_data.outline_fade_sh = DRW_shader_create_fullscreen(datatoc_object_outline_expand_frag_glsl, NULL); /* Empty images */ @@ -587,9 +604,11 @@ static void OBJECT_engine_free(void) MEM_SAFE_FREE(e_data.empty_image_format); MEM_SAFE_FREE(e_data.empty_image_wire_format); DRW_SHADER_FREE_SAFE(e_data.outline_prepass_sh); + DRW_SHADER_FREE_SAFE(e_data.outline_prepass_wire_sh); DRW_SHADER_FREE_SAFE(e_data.outline_resolve_sh); DRW_SHADER_FREE_SAFE(e_data.outline_resolve_aa_sh); DRW_SHADER_FREE_SAFE(e_data.outline_detect_sh); + DRW_SHADER_FREE_SAFE(e_data.outline_detect_wire_sh); DRW_SHADER_FREE_SAFE(e_data.outline_fade_sh); DRW_SHADER_FREE_SAFE(e_data.object_empty_image_sh); DRW_SHADER_FREE_SAFE(e_data.object_empty_image_wire_sh); @@ -787,7 +806,7 @@ static void DRW_shgroup_empty_image( struct EmptyImageShadingGroupData *empty_image_data; GPUTexture *tex = ob->data ? - GPU_texture_from_blender(ob->data, ob->iuser, GL_TEXTURE_2D, false, false, false) : NULL; + GPU_texture_from_blender(ob->data, ob->iuser, GL_TEXTURE_2D, false, 0.0f) : NULL; void **val_p; /* Create on demand, 'tex' may be NULL. */ @@ -861,6 +880,8 @@ static void OBJECT_cache_init(void *vedata) OBJECT_StorageList *stl = ((OBJECT_Data *)vedata)->stl; DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); OBJECT_PrivateData *g_data; + const DRWContextState *draw_ctx = DRW_context_state_get(); + const bool xray_enabled = ((draw_ctx->v3d->shading.flag & V3D_SHADING_XRAY) != 0); /* TODO : use dpi setting for enabling the second pass */ const bool do_outline_expand = false; @@ -877,13 +898,12 @@ static void OBJECT_cache_init(void *vedata) GPUShader *sh = e_data.outline_prepass_sh; - /* Select */ - g_data->outlines_select = shgroup_outline(psl->outlines, &g_data->id_ofs_select, sh); + if (xray_enabled) { + sh = e_data.outline_prepass_wire_sh; + } - /* Transform */ + g_data->outlines_select = shgroup_outline(psl->outlines, &g_data->id_ofs_select, sh); g_data->outlines_transform = shgroup_outline(psl->outlines, &g_data->id_ofs_transform, sh); - - /* Active */ g_data->outlines_active = shgroup_outline(psl->outlines, &g_data->id_ofs_active, sh); g_data->id_ofs_select = 0; @@ -915,19 +935,21 @@ static void OBJECT_cache_init(void *vedata) { DRWState state = DRW_STATE_WRITE_COLOR; struct Gwn_Batch *quad = DRW_cache_fullscreen_quad_get(); - static float alphaOcclu = 0.35f; + /* Don't occlude the "outline" detection pass if in xray mode (too much flickering). */ + float alphaOcclu = (xray_enabled) ? 1.0f : 0.35f; /* Reminder : bool uniforms need to be 4 bytes. */ static const int bTrue = true; static const int bFalse = false; psl->outlines_search = DRW_pass_create("Outlines Detect Pass", state); - DRWShadingGroup *grp = DRW_shgroup_create(e_data.outline_detect_sh, psl->outlines_search); + GPUShader *sh = (xray_enabled) ? e_data.outline_detect_wire_sh : e_data.outline_detect_sh; + DRWShadingGroup *grp = DRW_shgroup_create(sh, psl->outlines_search); DRW_shgroup_uniform_texture_ref(grp, "outlineId", &e_data.outlines_id_tx); DRW_shgroup_uniform_texture_ref(grp, "outlineDepth", &e_data.outlines_depth_tx); DRW_shgroup_uniform_texture_ref(grp, "sceneDepth", &dtxl->depth); DRW_shgroup_uniform_block(grp, "globalsBlock", globals_ubo); - DRW_shgroup_uniform_float(grp, "alphaOcclu", &alphaOcclu, 1); + DRW_shgroup_uniform_float_copy(grp, "alphaOcclu", alphaOcclu); DRW_shgroup_uniform_int(grp, "idOffsets", &stl->g_data->id_ofs_active, 3); DRW_shgroup_call_add(grp, quad, NULL); @@ -1920,8 +1942,13 @@ static void DRW_shgroup_lightprobe(OBJECT_StorageList *stl, OBJECT_PassList *psl static void DRW_shgroup_relationship_lines(OBJECT_StorageList *stl, Object *ob) { if (ob->parent && DRW_check_object_visible_within_active_context(ob->parent)) { - DRW_shgroup_call_dynamic_add(stl->g_data->relationship_lines, ob->parent->obmat[3]); - DRW_shgroup_call_dynamic_add(stl->g_data->relationship_lines, ob->obmat[3]); + /* Only draw relationship lines when object or its parent are selected + * as a way of reducing visual clutter. + */ + if ((ob->base_flag & BASE_SELECTED) || (ob->parent->base_flag & BASE_SELECTED)) { + DRW_shgroup_call_dynamic_add(stl->g_data->relationship_lines, ob->parent->obmat[3]); + DRW_shgroup_call_dynamic_add(stl->g_data->relationship_lines, ob->obmat[3]); + } } } @@ -2103,10 +2130,17 @@ static void OBJECT_cache_populate(void *vedata, Object *ob) } bool do_outlines = ((ob->base_flag & BASE_SELECTED) != 0); + bool show_relations = ((draw_ctx->v3d->flag & V3D_HIDE_HELPLINES) == 0); if (do_outlines) { if ((ob != draw_ctx->object_edit) && !((ob == draw_ctx->obact) && (draw_ctx->object_mode & OB_MODE_ALL_PAINT))) { - struct Gwn_Batch *geom = DRW_cache_object_surface_get(ob); + struct Gwn_Batch *geom; + if (v3d->shading.flag & V3D_SHADING_XRAY) { + geom = DRW_cache_object_edge_detection_get(ob, NULL); + } + else { + geom = DRW_cache_object_surface_get(ob); + } if (geom) { theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL); DRWShadingGroup *shgroup = shgroup_theme_id_to_outline_or(stl, theme_id, NULL); @@ -2249,7 +2283,9 @@ static void OBJECT_cache_populate(void *vedata, Object *ob) DRW_shgroup_object_center(stl, ob, view_layer, v3d); - DRW_shgroup_relationship_lines(stl, ob); + if (show_relations) { + DRW_shgroup_relationship_lines(stl, ob); + } if ((ob->dtx != 0) && theme_id == TH_UNDEFINED) { theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL); diff --git a/source/blender/draw/modes/paint_texture_mode.c b/source/blender/draw/modes/paint_texture_mode.c index 1d7f686a51c..bd8a1c71a6a 100644 --- a/source/blender/draw/modes/paint_texture_mode.c +++ b/source/blender/draw/modes/paint_texture_mode.c @@ -222,7 +222,7 @@ static void PAINT_TEXTURE_cache_init(void *vedata) Material *ma = give_current_material(ob, i + 1); Image *ima = (ma && ma->texpaintslot) ? ma->texpaintslot[ma->paint_active_slot].ima : NULL; GPUTexture *tex = ima ? - GPU_texture_from_blender(ima, NULL, GL_TEXTURE_2D, false, false, false) : NULL; + GPU_texture_from_blender(ima, NULL, GL_TEXTURE_2D, false, 0.0f) : NULL; if (tex) { DRWShadingGroup *grp = DRW_shgroup_create(e_data.image_sh, psl->image_faces); @@ -237,7 +237,7 @@ static void PAINT_TEXTURE_cache_init(void *vedata) else { Image *ima = scene->toolsettings->imapaint.canvas; GPUTexture *tex = ima ? - GPU_texture_from_blender(ima, NULL, GL_TEXTURE_2D, false, false, false) : NULL; + GPU_texture_from_blender(ima, NULL, GL_TEXTURE_2D, false, 0.0f) : NULL; if (tex) { DRWShadingGroup *grp = DRW_shgroup_create(e_data.image_sh, psl->image_faces); diff --git a/source/blender/draw/modes/shaders/common_globals_lib.glsl b/source/blender/draw/modes/shaders/common_globals_lib.glsl index c55457bb6d2..f8a8f3b9203 100644 --- a/source/blender/draw/modes/shaders/common_globals_lib.glsl +++ b/source/blender/draw/modes/shaders/common_globals_lib.glsl @@ -2,6 +2,7 @@ /* keep in sync with GlobalsUboStorage */ layout(std140) uniform globalsBlock { vec4 colorWire; + vec4 colorWireInactive; vec4 colorWireEdit; vec4 colorActive; vec4 colorSelect; diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_facedot_frag.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_facedot_frag.glsl index 07b36079884..71cc1ccde8d 100644 --- a/source/blender/draw/modes/shaders/edit_mesh_overlay_facedot_frag.glsl +++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_facedot_frag.glsl @@ -11,7 +11,7 @@ void main() if (isSelected != 0) FragColor = colorFaceDot; else - FragColor = colorWireEdit; + FragColor = colorVertex; #ifdef VERTEX_FACING FragColor.a *= 1.0 - abs(facing) * 0.4; diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_facefill_frag.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_facefill_frag.glsl index 23b794d9b8b..2e729009a38 100644 --- a/source/blender/draw/modes/shaders/edit_mesh_overlay_facefill_frag.glsl +++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_facefill_frag.glsl @@ -1,29 +1,7 @@ - -/* Solid Wirefram implementation - * Mike Erwin, Clément Foucault */ - -/* This shader follows the principles of - * http://developer.download.nvidia.com/SDK/10/direct3d/Source/SolidWireframe/Doc/SolidWireframe.pdf */ - flat in vec4 faceColor; -flat in int faceActive; - out vec4 FragColor; -const vec4 stipple_matrix[4] = vec4[4]( - vec4(1.0, 0.0, 0.0, 0.0), - vec4(0.0, 0.0, 0.0, 0.0), - vec4(0.0, 0.0, 1.0, 0.0), - vec4(0.0, 0.0, 0.0, 0.0) -); - void main() { FragColor = faceColor; - - if (faceActive == 1) { - int x = int(gl_FragCoord.x) & 0x3; /* mod 4 */ - int y = int(gl_FragCoord.y) & 0x3; /* mod 4 */ - FragColor *= stipple_matrix[x][y]; - } } 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 3b9aa77306f..c9de6d29524 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 @@ -5,25 +5,11 @@ in vec3 pos; in ivec4 data; flat out vec4 faceColor; -flat out int faceActive; -#define FACE_ACTIVE (1 << 2) #define FACE_SELECTED (1 << 3) void main() { gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); - - if ((data.x & FACE_ACTIVE) != 0) { - faceColor = colorEditMeshActive; - faceActive = 1; - } - else if ((data.x & FACE_SELECTED) != 0) { - faceColor = colorFaceSelect; - faceActive = 0; - } - else { - faceColor = colorFace; - faceActive = 0; - } + faceColor = ((data.x & FACE_SELECTED) != 0)? colorFaceSelect: colorFace; } diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_frag.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_frag.glsl index cf1051b70b3..eadb774c57e 100644 --- a/source/blender/draw/modes/shaders/edit_mesh_overlay_frag.glsl +++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_frag.glsl @@ -10,7 +10,6 @@ * TODO Refine the range to only affect GPUs. */ uniform float faceAlphaMod; - flat in vec3 edgesCrease; flat in vec3 edgesBweight; flat in vec4 faceColor; @@ -55,6 +54,10 @@ out vec4 FragColor; #define VERTEX_SELECTED (1 << (1 + 8)) #define FACE_ACTIVE (1 << (2 + 8)) +#define LARGE_EDGE_SIZE 3.0 +#define LARGE_EDGE_SIZE_ACTIVE_FACE 5.0 + + /* Style Parameters in pixel */ /* Array to retrieve vert/edge indices */ @@ -76,13 +79,6 @@ const ivec3 clipPointIdx[6] = ivec3[6]( ivec3(2, 1, 0) ); -const vec4 stipple_matrix[4] = vec4[4]( - vec4(1.0, 0.0, 0.0, 0.0), - vec4(0.0, 0.0, 0.0, 0.0), - vec4(0.0, 0.0, 1.0, 0.0), - vec4(0.0, 0.0, 0.0, 0.0) -); - void colorDist(vec4 color, float dist) { FragColor = (dist < 0) ? color : FragColor; @@ -98,7 +94,10 @@ float distToEdge(vec2 o, vec2 dir) #ifdef ANTI_ALIASING void colorDistEdge(vec4 color, float dist) { + /* May not work if color.a is not 1.0. */ + FragColor.rgb *= FragColor.a; FragColor = mix(color, FragColor, clamp(dist, 0.0, 1.0)); + FragColor.rgb /= FragColor.a; } #else #define colorDistEdge colorDist @@ -146,21 +145,13 @@ void main() /* First */ FragColor = faceColor; - - if ((flag[0] & FACE_ACTIVE) != 0) { - int x = int(gl_FragCoord.x) & 0x3; /* mod 4 */ - int y = int(gl_FragCoord.y) & 0x3; /* mod 4 */ - FragColor *= stipple_matrix[x][y]; - } - else { - FragColor.a *= faceAlphaMod; - } + FragColor.a *= faceAlphaMod; /* Edges */ for (int v = 0; v < 3; ++v) { if ((flag[v] & EDGE_EXISTS) != 0) { /* Outer large edge */ - float largeEdge = e[v] - sizeEdge * 3.0; + float largeEdge = e[v] - sizeEdge * LARGE_EDGE_SIZE; vec4 large_edge_color = vec4(0.0); large_edge_color = ((flag[v] & EDGE_SHARP) != 0) ? colorEdgeSharp : large_edge_color; @@ -168,6 +159,12 @@ void main() large_edge_color = (edgesBweight[v] > 0.0) ? vec4(colorEdgeBWeight.rgb, edgesBweight[v]) : large_edge_color; large_edge_color = ((flag[v] & EDGE_SEAM) != 0) ? colorEdgeSeam : large_edge_color; + if ((flag[0] & FACE_ACTIVE) != 0) + { + large_edge_color = colorEditMeshActive; + largeEdge = e[v] - sizeEdge * LARGE_EDGE_SIZE_ACTIVE_FACE; + } + if (large_edge_color.a != 0.0) { colorDistEdge(large_edge_color, largeEdge); } @@ -181,10 +178,14 @@ void main() #ifdef VERTEX_SELECTION colorDistEdge(vec4(vertexColor, 1.0), innerEdge); #else +# ifdef EDGE_SELECTION vec4 inner_edge_color = colorWireEdit; inner_edge_color = ((flag[v] & EDGE_SELECTED) != 0) ? colorEdgeSelect : inner_edge_color; - inner_edge_color = ((flag[v] & EDGE_ACTIVE) != 0) ? vec4(colorEditMeshActive.xyz, 1.0) : inner_edge_color; + inner_edge_color = ((flag[v] & EDGE_ACTIVE) != 0) ? vec4(colorEditMeshActive.rgb, 1.0) : inner_edge_color; +# else + vec4 inner_edge_color = colorWireInactive; +# endif colorDistEdge(inner_edge_color, innerEdge); #endif } diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_geom_edge.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_geom_edge.glsl index 77bc8a25695..6702722e61f 100644 --- a/source/blender/draw/modes/shaders/edit_mesh_overlay_geom_edge.glsl +++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_geom_edge.glsl @@ -76,7 +76,11 @@ vec3 getVertexColor(int v) if ((vData[v].x & (VERTEX_ACTIVE | VERTEX_SELECTED)) != 0) return colorEdgeSelect.rgb; else +#ifdef EDGE_SELECTION return colorWireEdit.rgb; +#else + return colorWireInactive.rgb; +#endif } void doVertex(int v, vec4 pos) diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_geom_tri.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_geom_tri.glsl index d9c902697b6..7e778c325a6 100644 --- a/source/blender/draw/modes/shaders/edit_mesh_overlay_geom_tri.glsl +++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_geom_tri.glsl @@ -95,7 +95,11 @@ vec3 getVertexColor(int v) if ((vData[v].x & (VERTEX_ACTIVE | VERTEX_SELECTED)) != 0) return colorEdgeSelect.rgb; else +#ifdef EDGE_SELECTION return colorWireEdit.rgb; +#else + return colorWireInactive.rgb; +#endif } vec4 getClipData(vec2 pos[3], ivec2 vidx) @@ -163,7 +167,7 @@ void main() /* Face */ if ((vData[0].x & FACE_ACTIVE) != 0) - faceColor = colorEditMeshActive; + faceColor = colorFaceSelect; else if ((vData[0].x & FACE_SELECTED) != 0) faceColor = colorFaceSelect; else diff --git a/source/blender/draw/modes/shaders/object_outline_detect_frag.glsl b/source/blender/draw/modes/shaders/object_outline_detect_frag.glsl index 45bbdb18340..9a7856ecb13 100644 --- a/source/blender/draw/modes/shaders/object_outline_detect_frag.glsl +++ b/source/blender/draw/modes/shaders/object_outline_detect_frag.glsl @@ -51,6 +51,12 @@ void main() id.w = texelFetchOffset(outlineId, texel, 0, ivec2( 1, 0)).r; #endif +#ifdef WIRE + /* We want only 2px outlines. */ + /* TODO optimize, don't sample if we don't need to. */ + id.xy = uvec2(ref_id); +#endif + bool outline = any(notEqual(id, uvec4(ref_id))); ivec2 depth_texel = texel; diff --git a/source/blender/draw/modes/shaders/object_outline_prepass_geom.glsl b/source/blender/draw/modes/shaders/object_outline_prepass_geom.glsl new file mode 100644 index 00000000000..c90195e11fd --- /dev/null +++ b/source/blender/draw/modes/shaders/object_outline_prepass_geom.glsl @@ -0,0 +1,40 @@ + +layout(lines_adjacency) in; +layout(line_strip, max_vertices = 2) out; + +uniform mat4 ProjectionMatrix; + +in vec4 pPos[]; +in vec3 vPos[]; + +void main() +{ + bool is_persp = (ProjectionMatrix[3][3] == 0.0); + + vec3 view_vec = (is_persp) ? normalize(vPos[1]) : vec3(0.0, 0.0, -1.0); + + vec3 v10 = vPos[0] - vPos[1]; + vec3 v12 = vPos[2] - vPos[1]; + vec3 v13 = vPos[3] - vPos[1]; + + vec3 n0 = cross(v12, v10); + vec3 n3 = cross(v13, v12); + + float fac0 = dot(view_vec, n0); + float fac3 = dot(view_vec, n3); + + /* If both adjacent verts are facing the camera the same way, + * then it isn't an outline edge. */ + if (sign(fac0) == sign(fac3)) + return; + + /* Don't outline if concave edge. */ + /* That would hide a lot of non usefull edge but it flickers badly. + * TODO revisit later... */ + // if (dot(n0, v13) > 0.01) + // return; + + gl_Position = pPos[1]; EmitVertex(); + gl_Position = pPos[2]; EmitVertex(); + EndPrimitive(); +} diff --git a/source/blender/draw/modes/shaders/object_outline_prepass_vert.glsl b/source/blender/draw/modes/shaders/object_outline_prepass_vert.glsl new file mode 100644 index 00000000000..ba824a7c007 --- /dev/null +++ b/source/blender/draw/modes/shaders/object_outline_prepass_vert.glsl @@ -0,0 +1,16 @@ + +uniform mat4 ModelViewMatrix; +uniform mat4 ModelViewProjectionMatrix; + +in vec3 pos; + +out vec4 pPos; +out vec3 vPos; + +void main() +{ + vPos = (ModelViewMatrix * vec4(pos, 1.0)).xyz; + pPos = ModelViewProjectionMatrix * vec4(pos, 1.0); + /* Small bias to always be on top of the geom. */ + pPos.z -= 1e-3; +} diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c index 624c6e9f5de..e957e84857a 100644 --- a/source/blender/editors/animation/anim_markers.c +++ b/source/blender/editors/animation/anim_markers.c @@ -76,6 +76,8 @@ #include "ED_transform.h" #include "ED_types.h" +#include "DEG_depsgraph.h" + /* ************* Marker API **************** */ /* helper function for getting the list of markers to work on */ @@ -1196,6 +1198,7 @@ static int ed_marker_select(bContext *C, const wmEvent *event, bool extend, bool } } + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); } #else diff --git a/source/blender/editors/animation/anim_ops.c b/source/blender/editors/animation/anim_ops.c index 23563e7f15f..4402ca78976 100644 --- a/source/blender/editors/animation/anim_ops.c +++ b/source/blender/editors/animation/anim_ops.c @@ -268,7 +268,7 @@ static void ANIM_OT_change_frame(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR | OPTYPE_UNDO_GROUPED; - ot->undo_group = "FRAME_CHANGE"; + ot->undo_group = "Frame Change"; /* rna */ ot->prop = RNA_def_float(ot->srna, "frame", 0, MINAFRAME, MAXFRAME, "Frame", "", MINAFRAME, MAXFRAME); @@ -332,7 +332,7 @@ static void ANIM_OT_start_frame_set(wmOperatorType *ot) /* identifiers */ ot->name = "Set Start Frame"; ot->idname = "ANIM_OT_start_frame_set"; - ot->description = "Set the start frame"; + ot->description = "Set the current frame as the preview or scene start frame"; /* api callbacks */ ot->exec = anim_set_sfra_exec; @@ -376,7 +376,7 @@ static void ANIM_OT_end_frame_set(wmOperatorType *ot) /* identifiers */ ot->name = "Set End Frame"; ot->idname = "ANIM_OT_end_frame_set"; - ot->description = "Set the end frame"; + ot->description = "Set the current frame as the preview or scene end frame"; /* api callbacks */ ot->exec = anim_set_efra_exec; diff --git a/source/blender/editors/animation/drivers.c b/source/blender/editors/animation/drivers.c index 03639b0ad77..294cff43c56 100644 --- a/source/blender/editors/animation/drivers.c +++ b/source/blender/editors/animation/drivers.c @@ -414,13 +414,20 @@ int ANIM_add_driver(ReportList *reports, ID *id, const char rna_path[], int arra /* set the type of the driver */ driver->type = type; - /* creating drivers for buttons will create the driver(s) with type + /* Creating drivers for buttons will create the driver(s) with type * "scripted expression" so that their values won't be lost immediately, * so here we copy those values over to the driver's expression + * + * If the "default dvar" option (for easier UI setup of drivers) is provided, + * include "var" in the expressions too, so that the user doesn't have to edit + * it to get something to happen. It should be fine to just add it to the default + * value, so that we get both in the expression, even if it's a bit more confusing + * that way... */ if (type == DRIVER_TYPE_PYTHON) { PropertyType proptype = RNA_property_type(prop); int array = RNA_property_array_length(&ptr, prop); + const char *dvar_prefix = (flag & CREATEDRIVER_WITH_DEFAULT_DVAR) ? "var + " : ""; char *expression = driver->expression; int val, maxlen = sizeof(driver->expression); float fval; @@ -429,19 +436,22 @@ int ANIM_add_driver(ReportList *reports, ID *id, const char rna_path[], int arra if (!array) val = RNA_property_boolean_get(&ptr, prop); else val = RNA_property_boolean_get_index(&ptr, prop, array_index); - BLI_strncpy(expression, (val) ? "True" : "False", maxlen); + BLI_snprintf(expression, maxlen, "%s%s", dvar_prefix, (val) ? "True" : "False"); } else if (proptype == PROP_INT) { if (!array) val = RNA_property_int_get(&ptr, prop); else val = RNA_property_int_get_index(&ptr, prop, array_index); - BLI_snprintf(expression, maxlen, "%d", val); + BLI_snprintf(expression, maxlen, "%s%d", dvar_prefix, val); } else if (proptype == PROP_FLOAT) { if (!array) fval = RNA_property_float_get(&ptr, prop); else fval = RNA_property_float_get_index(&ptr, prop, array_index); - BLI_snprintf(expression, maxlen, "%.3f", fval); + BLI_snprintf(expression, maxlen, "%s%.3f", dvar_prefix, fval); + } + else if (flag & CREATEDRIVER_WITH_DEFAULT_DVAR) { + BLI_strncpy(expression, "var", maxlen); } } @@ -806,7 +816,7 @@ static const EnumPropertyItem *driver_mapping_type_itemsf(bContext *C, PointerRN } -/* Add Driver Button Operator ------------------------ */ +/* Add Driver (With Menu) Button Operator ------------------------ */ static int add_driver_button_poll(bContext *C) { @@ -855,7 +865,7 @@ static int add_driver_button_none(bContext *C, wmOperator *op, short mapping_typ } } -static int add_driver_button_exec(bContext *C, wmOperator *op) +static int add_driver_button_menu_exec(bContext *C, wmOperator *op) { short mapping_type = RNA_enum_get(op->ptr, "mapping_type"); if (ELEM(mapping_type, CREATEDRIVER_MAPPING_NONE, CREATEDRIVER_MAPPING_NONE_ALL)) { @@ -874,13 +884,13 @@ static int add_driver_button_exec(bContext *C, wmOperator *op) } /* Show menu or create drivers */ -static int add_driver_button_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +static int add_driver_button_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { PropertyRNA *prop; if ((prop = RNA_struct_find_property(op->ptr, "mapping_type")) && RNA_property_is_set(op->ptr, prop)) { /* Mapping Type is Set - Directly go into creating drivers */ - return add_driver_button_exec(C, op); + return add_driver_button_menu_exec(C, op); } else { /* Show menu */ @@ -890,19 +900,16 @@ static int add_driver_button_invoke(bContext *C, wmOperator *op, const wmEvent * } } -void ANIM_OT_driver_button_add(wmOperatorType *ot) +static void UNUSED_FUNCTION(ANIM_OT_driver_button_add_menu)(wmOperatorType *ot) { /* identifiers */ - ot->name = "Add Driver"; - ot->idname = "ANIM_OT_driver_button_add"; + ot->name = "Add Driver Menu"; + ot->idname = "ANIM_OT_driver_button_add_menu"; ot->description = "Add driver(s) for the property(s) represented by the highlighted button"; /* callbacks */ - /* NOTE: No exec, as we need all these to use the current context info - * (especially the eyedropper, which is interactive) - */ - ot->invoke = add_driver_button_invoke; - ot->exec = add_driver_button_exec; + ot->invoke = add_driver_button_menu_invoke; + ot->exec = add_driver_button_menu_exec; ot->poll = add_driver_button_poll; /* flags */ @@ -914,6 +921,59 @@ void ANIM_OT_driver_button_add(wmOperatorType *ot) RNA_def_enum_funcs(ot->prop, driver_mapping_type_itemsf); } +/* Add Driver Button Operator ------------------------ */ + +static int add_driver_button_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +{ + PointerRNA ptr = {{NULL}}; + PropertyRNA *prop = NULL; + int index; + + /* try to find driver using property retrieved from UI */ + UI_context_active_but_prop_get(C, &ptr, &prop, &index); + + if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) { + /* 1) Create a new "empty" driver for this property */ + char *path = BKE_animdata_driver_path_hack(C, &ptr, prop, NULL); + short flags = CREATEDRIVER_WITH_DEFAULT_DVAR; + short success = 0; + + if (path) { + success += ANIM_add_driver(op->reports, ptr.id.data, path, index, flags, DRIVER_TYPE_PYTHON); + MEM_freeN(path); + } + + if (success) { + /* send updates */ + UI_context_update_anim_flag(C); + DEG_relations_tag_update(CTX_data_main(C)); + WM_event_add_notifier(C, NC_ANIMATION | ND_FCURVES_ORDER, NULL); + } + + /* 2) Show editing panel for setting up this driver */ + /* TODO: Use a different one from the editing popever, so we can have the single/all toggle? */ + UI_popover_panel_invoke(C, SPACE_IPO, RGN_TYPE_UI, "GRAPH_PT_drivers_popover", true, op->reports); + } + + return OPERATOR_INTERFACE; +} + +void ANIM_OT_driver_button_add(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Add Driver"; + ot->idname = "ANIM_OT_driver_button_add"; + ot->description = "Add driver for the property under the cursor"; + + /* callbacks */ + /* NOTE: No exec, as we need all these to use the current context info */ + ot->invoke = add_driver_button_invoke; + ot->poll = add_driver_button_poll; + + /* flags */ + ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL; +} + /* Remove Driver Button Operator ------------------------ */ static int remove_driver_button_exec(bContext *C, wmOperator *op) @@ -975,14 +1035,10 @@ static int edit_driver_button_exec(bContext *C, wmOperator *op) PointerRNA ptr = {{NULL}}; PropertyRNA *prop = NULL; int index; - const bool all = 0; // RNA_boolean_get(op->ptr, "all"); /* try to find driver using property retrieved from UI */ UI_context_active_but_prop_get(C, &ptr, &prop, &index); - if (all) - index = -1; - if (ptr.id.data && ptr.data && prop) { UI_popover_panel_invoke(C, SPACE_IPO, RGN_TYPE_UI, "GRAPH_PT_drivers_popover", true, op->reports); } @@ -1003,9 +1059,6 @@ void ANIM_OT_driver_button_edit(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL; - - /* properties */ - //RNA_def_boolean(ot->srna, "all", 1, "All", "Edit drivers for all elements of the array"); } /* Copy Driver Button Operator ------------------------ */ diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c index 1913eb944d9..fe5714aba2e 100644 --- a/source/blender/editors/animation/keyframing.c +++ b/source/blender/editors/animation/keyframing.c @@ -954,7 +954,7 @@ bool insert_keyframe_direct(Depsgraph *depsgraph, ReportList *reports, PointerRN if (RNA_path_resolved_create(&ptr, prop, fcu->array_index, &anim_rna)) { /* for making it easier to add corrective drivers... */ - cfra = evaluate_driver(&anim_rna, fcu->driver, cfra); + cfra = evaluate_driver(&anim_rna, fcu->driver, fcu->driver, cfra); } else { cfra = 0.0f; diff --git a/source/blender/editors/armature/armature_relations.c b/source/blender/editors/armature/armature_relations.c index 9282148e857..cc149d3e42f 100644 --- a/source/blender/editors/armature/armature_relations.c +++ b/source/blender/editors/armature/armature_relations.c @@ -377,7 +377,7 @@ int join_armature_exec(bContext *C, wmOperator *op) } else { /* merge in data - we'll fix the drivers manually */ - BKE_animdata_merge_copy(&ob->id, &base->object->id, ADT_MERGECOPY_KEEP_DST, false); + BKE_animdata_merge_copy(bmain, &ob->id, &base->object->id, ADT_MERGECOPY_KEEP_DST, false); } } @@ -388,7 +388,7 @@ int join_armature_exec(bContext *C, wmOperator *op) } else { /* merge in data - we'll fix the drivers manually */ - BKE_animdata_merge_copy(&arm->id, &curarm->id, ADT_MERGECOPY_KEEP_DST, false); + BKE_animdata_merge_copy(bmain, &arm->id, &curarm->id, ADT_MERGECOPY_KEEP_DST, false); } } @@ -403,6 +403,7 @@ int join_armature_exec(bContext *C, wmOperator *op) ED_armature_from_edit(bmain, arm); ED_armature_edit_free(arm); + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); return OPERATOR_FINISHED; diff --git a/source/blender/editors/armature/armature_select.c b/source/blender/editors/armature/armature_select.c index 95acc8ab6ba..cd5a4ced26f 100644 --- a/source/blender/editors/armature/armature_select.c +++ b/source/blender/editors/armature/armature_select.c @@ -717,6 +717,7 @@ bool ED_armature_edit_select_pick(bContext *C, const int mval[2], bool extend, b if (vc.view_layer->basact != basact) { vc.view_layer->basact = basact; + DEG_id_tag_update(&vc.scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, vc.scene); } } diff --git a/source/blender/editors/armature/pose_utils.c b/source/blender/editors/armature/pose_utils.c index b64c8528010..e280284a9ce 100644 --- a/source/blender/editors/armature/pose_utils.c +++ b/source/blender/editors/armature/pose_utils.c @@ -40,6 +40,7 @@ #include "BKE_action.h" #include "BKE_armature.h" #include "BKE_idprop.h" +#include "BKE_main.h" #include "BKE_context.h" diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index 616017dac0a..aa50916f5e0 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -2896,7 +2896,7 @@ static int hide_exec(bContext *C, wmOperator *op) } } - DEG_id_tag_update(obedit->data, 0); + DEG_id_tag_update(obedit->data, DEG_TAG_COPY_ON_WRITE | DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); BKE_curve_nurb_vert_active_validate(obedit->data); @@ -2959,7 +2959,7 @@ static int reveal_exec(bContext *C, wmOperator *op) } } - DEG_id_tag_update(obedit->data, 0); + DEG_id_tag_update(obedit->data, DEG_TAG_COPY_ON_WRITE | DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); return OPERATOR_FINISHED; @@ -4413,6 +4413,7 @@ bool ED_curve_editnurb_select_pick(bContext *C, const int mval[2], bool extend, BKE_curve_nurb_active_set(cu, nu); } + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); return true; @@ -5300,6 +5301,7 @@ static int duplicate_exec(bContext *C, wmOperator *op) if (BLI_listbase_is_empty(&newnurb) == false) { BLI_movelisttolist(object_editcurve_get(obedit), &newnurb); + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } else { @@ -5803,7 +5805,7 @@ void CURVE_OT_delete(wmOperatorType *ot) /* properties */ prop = RNA_def_enum(ot->srna, "type", curve_delete_type_items, 0, "Type", "Which elements to delete"); RNA_def_enum_funcs(prop, rna_curve_delete_type_itemf); - + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); ot->prop = prop; } @@ -6148,6 +6150,7 @@ int join_curve_exec(bContext *C, wmOperator *op) DEG_relations_tag_update(bmain); // because we removed object(s), call before editmode! DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA); + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); diff --git a/source/blender/editors/curve/editcurve_select.c b/source/blender/editors/curve/editcurve_select.c index 58fb6d50575..0fae39776a9 100644 --- a/source/blender/editors/curve/editcurve_select.c +++ b/source/blender/editors/curve/editcurve_select.c @@ -55,10 +55,10 @@ #include "curve_intern.h" - #include "RNA_access.h" #include "RNA_define.h" +#include "DEG_depsgraph.h" /* returns 1 in case (de)selection was successful */ bool select_beztriple(BezTriple *bezt, bool selstatus, short flag, eVisible_Types hidden) @@ -404,6 +404,7 @@ static int de_select_first_exec(bContext *C, wmOperator *UNUSED(op)) Object *obedit = CTX_data_edit_object(C); selectend_nurb(obedit, FIRST, true, DESELECT); + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); BKE_curve_nurb_vert_active_validate(obedit->data); @@ -430,6 +431,7 @@ static int de_select_last_exec(bContext *C, wmOperator *UNUSED(op)) Object *obedit = CTX_data_edit_object(C); selectend_nurb(obedit, LAST, true, DESELECT); + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); BKE_curve_nurb_vert_active_validate(obedit->data); @@ -488,6 +490,7 @@ static int de_select_all_exec(bContext *C, wmOperator *op) break; } + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); BKE_curve_nurb_vert_active_validate(cu); } @@ -540,6 +543,7 @@ static int select_linked_exec(bContext *C, wmOperator *UNUSED(op)) } if (changed) { + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } } @@ -608,6 +612,7 @@ static int select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent } } + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); if (!select) { BKE_curve_nurb_vert_active_validate(obedit->data); @@ -670,6 +675,7 @@ static int select_row_exec(bContext *C, wmOperator *UNUSED(op)) } } + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); return OPERATOR_FINISHED; @@ -698,6 +704,7 @@ static int select_next_exec(bContext *C, wmOperator *UNUSED(op)) ListBase *editnurb = object_editcurve_get(obedit); select_adjacent_cp(editnurb, 1, 0, SELECT); + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); return OPERATOR_FINISHED; @@ -726,6 +733,7 @@ static int select_previous_exec(bContext *C, wmOperator *UNUSED(op)) ListBase *editnurb = object_editcurve_get(obedit); select_adjacent_cp(editnurb, -1, 0, SELECT); + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); return OPERATOR_FINISHED; @@ -814,6 +822,7 @@ static int select_more_exec(bContext *C, wmOperator *UNUSED(op)) select_adjacent_cp(editnurb, -1, 0, SELECT); } + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); return OPERATOR_FINISHED; @@ -1001,6 +1010,7 @@ static int select_less_exec(bContext *C, wmOperator *UNUSED(op)) } } + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); BKE_curve_nurb_vert_active_validate(obedit->data); @@ -1087,6 +1097,7 @@ static int curve_select_random_exec(bContext *C, wmOperator *op) curve_select_random(editnurb, randfac, seed_iter, select); BKE_curve_nurb_vert_active_validate(obedit->data); + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } @@ -1197,6 +1208,7 @@ static int select_nth_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); return OPERATOR_FINISHED; @@ -1503,6 +1515,7 @@ static int curve_select_similar_exec(bContext *C, wmOperator *op) } if (changed) { + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); return OPERATOR_FINISHED; } @@ -1744,6 +1757,7 @@ static int edcu_shortest_path_pick_invoke(bContext *C, wmOperator *op, const wmE BKE_curve_nurb_vert_active_set(cu, nu_dst, vert_dst_p); + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c index 7cdfafdad43..75efdec3dd2 100644 --- a/source/blender/editors/curve/editfont.c +++ b/source/blender/editors/curve/editfont.c @@ -246,7 +246,6 @@ static int insert_into_textbuf(Object *obedit, uintptr_t c) static void text_update_edited(bContext *C, Object *obedit, int mode) { - struct Main *bmain = CTX_data_main(C); Curve *cu = obedit->data; EditFont *ef = cu->editfont; @@ -259,7 +258,7 @@ static void text_update_edited(bContext *C, Object *obedit, int mode) } else { /* depsgraph runs above, but since we're not tagging for update, call direct */ - BKE_vfont_to_curve(bmain, obedit, mode); + BKE_vfont_to_curve(obedit, mode); } cu->curinfo = ef->textbufinfo[ef->pos ? ef->pos - 1 : 0]; @@ -982,16 +981,14 @@ static int move_cursor(bContext *C, int type, const bool select) /* apply virtical cursor motion to position immediately * otherwise the selection will lag behind */ if (FO_CURS_IS_MOTION(cursmove)) { - struct Main *bmain = CTX_data_main(C); - BKE_vfont_to_curve(bmain, obedit, cursmove); + BKE_vfont_to_curve(obedit, cursmove); cursmove = FO_CURS; } if (select == 0) { if (ef->selstart) { - struct Main *bmain = CTX_data_main(C); ef->selstart = ef->selend = 0; - BKE_vfont_to_curve(bmain, obedit, FO_SELCHANGE); + BKE_vfont_to_curve(obedit, FO_SELCHANGE); } } diff --git a/source/blender/editors/datafiles/CMakeLists.txt b/source/blender/editors/datafiles/CMakeLists.txt index 23b328aa8e0..98b57fcbd71 100644 --- a/source/blender/editors/datafiles/CMakeLists.txt +++ b/source/blender/editors/datafiles/CMakeLists.txt @@ -681,32 +681,6 @@ if(WITH_BLENDER) data_to_c_simple(../../../../release/datafiles/brushicons/twist.png SRC) data_to_c_simple(../../../../release/datafiles/brushicons/vertexdraw.png SRC) - # matcap - data_to_c_simple(../../../../release/datafiles/matcaps/mc01.jpg SRC) - data_to_c_simple(../../../../release/datafiles/matcaps/mc02.jpg SRC) - data_to_c_simple(../../../../release/datafiles/matcaps/mc03.jpg SRC) - data_to_c_simple(../../../../release/datafiles/matcaps/mc04.jpg SRC) - data_to_c_simple(../../../../release/datafiles/matcaps/mc05.jpg SRC) - data_to_c_simple(../../../../release/datafiles/matcaps/mc06.jpg SRC) - data_to_c_simple(../../../../release/datafiles/matcaps/mc07.jpg SRC) - data_to_c_simple(../../../../release/datafiles/matcaps/mc08.jpg SRC) - data_to_c_simple(../../../../release/datafiles/matcaps/mc09.jpg SRC) - data_to_c_simple(../../../../release/datafiles/matcaps/mc10.jpg SRC) - data_to_c_simple(../../../../release/datafiles/matcaps/mc11.jpg SRC) - data_to_c_simple(../../../../release/datafiles/matcaps/mc12.jpg SRC) - data_to_c_simple(../../../../release/datafiles/matcaps/mc13.jpg SRC) - data_to_c_simple(../../../../release/datafiles/matcaps/mc14.jpg SRC) - data_to_c_simple(../../../../release/datafiles/matcaps/mc15.jpg SRC) - data_to_c_simple(../../../../release/datafiles/matcaps/mc16.jpg SRC) - data_to_c_simple(../../../../release/datafiles/matcaps/mc17.jpg SRC) - data_to_c_simple(../../../../release/datafiles/matcaps/mc18.jpg SRC) - data_to_c_simple(../../../../release/datafiles/matcaps/mc19.jpg SRC) - data_to_c_simple(../../../../release/datafiles/matcaps/mc20.jpg SRC) - data_to_c_simple(../../../../release/datafiles/matcaps/mc21.jpg SRC) - data_to_c_simple(../../../../release/datafiles/matcaps/mc22.jpg SRC) - data_to_c_simple(../../../../release/datafiles/matcaps/mc23.jpg SRC) - data_to_c_simple(../../../../release/datafiles/matcaps/mc24.jpg SRC) - endif() data_to_c_simple(../../../../release/datafiles/startup.blend SRC) diff --git a/source/blender/editors/gpencil/gpencil_convert.c b/source/blender/editors/gpencil/gpencil_convert.c index dfaa1420d68..d2301337c0e 100644 --- a/source/blender/editors/gpencil/gpencil_convert.c +++ b/source/blender/editors/gpencil/gpencil_convert.c @@ -1374,6 +1374,7 @@ static int gp_convert_layer_exec(bContext *C, wmOperator *op) } /* notifiers */ + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_OBJECT | NA_ADDED, NULL); WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c index 2e8e48b2f15..9f437f28f0f 100644 --- a/source/blender/editors/gpencil/gpencil_data.c +++ b/source/blender/editors/gpencil/gpencil_data.c @@ -52,14 +52,15 @@ #include "DNA_view3d_types.h" #include "DNA_gpencil_types.h" +#include "BKE_colortools.h" #include "BKE_context.h" #include "BKE_gpencil.h" #include "BKE_library.h" +#include "BKE_main.h" #include "BKE_object.h" #include "BKE_report.h" #include "BKE_scene.h" #include "BKE_screen.h" -#include "BKE_colortools.h" #include "UI_interface.h" #include "UI_resources.h" @@ -83,6 +84,7 @@ /* add new datablock - wrapper around API */ static int gp_data_add_exec(bContext *C, wmOperator *op) { + Main *bmain = CTX_data_main(C); bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL); ToolSettings *ts = CTX_data_tool_settings(C); @@ -95,7 +97,7 @@ static int gp_data_add_exec(bContext *C, wmOperator *op) bGPdata *gpd = (*gpd_ptr); id_us_min(&gpd->id); - *gpd_ptr = BKE_gpencil_data_addnew(DATA_("GPencil")); + *gpd_ptr = BKE_gpencil_data_addnew(bmain, DATA_("GPencil")); /* if not exist brushes, create a new set */ if (ts) { @@ -183,6 +185,7 @@ void GPENCIL_OT_data_unlink(wmOperatorType *ot) /* add new layer - wrapper around API */ static int gp_layer_add_exec(bContext *C, wmOperator *op) { + Main *bmain = CTX_data_main(C); bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL); ToolSettings *ts = CTX_data_tool_settings(C); @@ -192,7 +195,7 @@ static int gp_layer_add_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } if (*gpd_ptr == NULL) - *gpd_ptr = BKE_gpencil_data_addnew(DATA_("GPencil")); + *gpd_ptr = BKE_gpencil_data_addnew(bmain, DATA_("GPencil")); /* if not exist brushes, create a new set */ if (ts) { @@ -1376,6 +1379,7 @@ void GPENCIL_OT_brush_select(wmOperatorType *ot) /* add new palette - wrapper around API */ static int gp_palette_add_exec(bContext *C, wmOperator *op) { + Main *bmain = CTX_data_main(C); bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL); /* if there's no existing Grease-Pencil data there, add some */ @@ -1384,7 +1388,7 @@ static int gp_palette_add_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } if (*gpd_ptr == NULL) - *gpd_ptr = BKE_gpencil_data_addnew(DATA_("GPencil")); + *gpd_ptr = BKE_gpencil_data_addnew(bmain, DATA_("GPencil")); /* add new palette now */ BKE_gpencil_palette_addnew(*gpd_ptr, DATA_("GP_Palette"), true); @@ -1588,6 +1592,7 @@ void GPENCIL_OT_palette_lock_layer(wmOperatorType *ot) /* add new palette - wrapper around API */ static int gp_palettecolor_add_exec(bContext *C, wmOperator *op) { + Main *bmain = CTX_data_main(C); bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL); /* if there's no existing Grease-Pencil data there, add some */ @@ -1596,7 +1601,7 @@ static int gp_palettecolor_add_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } if (*gpd_ptr == NULL) - *gpd_ptr = BKE_gpencil_data_addnew(DATA_("GPencil")); + *gpd_ptr = BKE_gpencil_data_addnew(bmain, DATA_("GPencil")); /* verify palette */ bGPDpalette *palette = BKE_gpencil_palette_getactive(*gpd_ptr); diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index 437d5cef6f8..6afa6f41828 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -1387,6 +1387,7 @@ static void gp_init_palette(tGPsdata *p) /* (re)init new painting data */ static bool gp_session_initdata(bContext *C, tGPsdata *p) { + Main *bmain = CTX_data_main(C); bGPdata **gpd_ptr = NULL; ScrArea *curarea = CTX_wm_area(C); ARegion *ar = CTX_wm_region(C); @@ -1537,7 +1538,7 @@ static bool gp_session_initdata(bContext *C, tGPsdata *p) else { /* if no existing GPencil block exists, add one */ if (*gpd_ptr == NULL) - *gpd_ptr = BKE_gpencil_data_addnew("GPencil"); + *gpd_ptr = BKE_gpencil_data_addnew(bmain, "GPencil"); p->gpd = *gpd_ptr; } diff --git a/source/blender/editors/include/ED_image.h b/source/blender/editors/include/ED_image.h index ce12c2fcd7a..73926b8a687 100644 --- a/source/blender/editors/include/ED_image.h +++ b/source/blender/editors/include/ED_image.h @@ -43,7 +43,7 @@ struct ViewLayer; /* image_edit.c, exported for transform */ struct Image *ED_space_image(struct SpaceImage *sima); -void ED_space_image_set(struct SpaceImage *sima, struct Scene *scene, struct Object *obedit, struct Image *ima); +void ED_space_image_set(struct Main *bmain, struct SpaceImage *sima, struct Scene *scene, struct Object *obedit, struct Image *ima); struct Mask *ED_space_image_get_mask(struct SpaceImage *sima); void ED_space_image_set_mask(struct bContext *C, struct SpaceImage *sima, struct Mask *mask); @@ -60,8 +60,8 @@ void ED_space_image_get_uv_aspect(struct SpaceImage *sima, float *aspx, float *a void ED_space_image_scopes_update(const struct bContext *C, struct SpaceImage *sima, struct ImBuf *ibuf, bool use_view_settings); -void ED_space_image_paint_update(struct wmWindowManager *wm, struct Scene *scene); -void ED_space_image_uv_sculpt_update(struct wmWindowManager *wm, struct Scene *scene); +void ED_space_image_paint_update(struct Main *bmain, struct wmWindowManager *wm, struct Scene *scene); +void ED_space_image_uv_sculpt_update(struct Main *bmain, struct wmWindowManager *wm, struct Scene *scene); void ED_image_get_uv_aspect(struct Image *ima, struct ImageUser *iuser, float *aspx, float *aspy); void ED_image_mouse_pos(struct SpaceImage *sima, struct ARegion *ar, const int mval[2], float co[2]); diff --git a/source/blender/editors/include/ED_manipulator_library.h b/source/blender/editors/include/ED_manipulator_library.h index b67af4274a6..fca0f5c8806 100644 --- a/source/blender/editors/include/ED_manipulator_library.h +++ b/source/blender/editors/include/ED_manipulator_library.h @@ -73,11 +73,18 @@ enum { ED_MANIPULATOR_ARROW_STYLE_CONE = 3, }; +/* transform */ enum { /* inverted offset during interaction - if set it also sets constrained below */ - ED_MANIPULATOR_ARROW_STYLE_INVERTED = (1 << 3), + ED_MANIPULATOR_ARROW_XFORM_FLAG_INVERTED = (1 << 3), /* clamp arrow interaction to property width */ - ED_MANIPULATOR_ARROW_STYLE_CONSTRAINED = (1 << 4), + ED_MANIPULATOR_ARROW_XFORM_FLAG_CONSTRAINED = (1 << 4), +}; + +/* draw_options */ +enum { + /* Show arrow stem. */ + ED_MANIPULATOR_ARROW_DRAW_FLAG_STEM = (1 << 0), }; void ED_manipulator_arrow3d_set_ui_range(struct wmManipulator *mpr, const float min, const float max); diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index 0d323258a19..a9c9e8c0fbd 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -83,7 +83,7 @@ void EDBM_mesh_clear(struct BMEditMesh *em); void EDBM_selectmode_to_scene(struct bContext *C); void EDBM_mesh_make(struct Object *ob, const int select_mode, const bool add_key_index); void EDBM_mesh_free(struct BMEditMesh *em); -void EDBM_mesh_load(struct Object *ob); +void EDBM_mesh_load(struct Main *bmain, struct Object *ob); struct DerivedMesh *EDBM_mesh_deform_dm_get(struct BMEditMesh *em); /* flushes based on the current select mode. if in vertex select mode, diff --git a/source/blender/editors/include/ED_node.h b/source/blender/editors/include/ED_node.h index 6828cedbd80..0b3ce144097 100644 --- a/source/blender/editors/include/ED_node.h +++ b/source/blender/editors/include/ED_node.h @@ -86,7 +86,7 @@ float ED_node_grid_size(void); /* node_relationships.c */ void ED_node_link_intersect_test(struct ScrArea *sa, int test); -void ED_node_link_insert(struct ScrArea *sa); +void ED_node_link_insert(struct Main *bmain, struct ScrArea *sa); /* node_edit.c */ void ED_node_set_tree_type(struct SpaceNode *snode, struct bNodeTreeType *typeinfo); @@ -107,7 +107,7 @@ void ED_node_composite_job(const struct bContext *C, struct bNodeTree *nodetree, void ED_operatormacros_node(void); /* node_view.c */ -bool ED_space_node_color_sample(struct SpaceNode *snode, struct ARegion *ar, int mval[2], float r_col[3]); +bool ED_space_node_color_sample(struct Main *bmain, struct SpaceNode *snode, struct ARegion *ar, int mval[2], float r_col[3]); #endif /* __ED_NODE_H__ */ diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h index 71b713da0d0..a5155b5b945 100644 --- a/source/blender/editors/include/ED_object.h +++ b/source/blender/editors/include/ED_object.h @@ -137,11 +137,11 @@ bool ED_object_editmode_calc_active_center(struct Object *obedit, const bool sel void ED_object_vpaintmode_enter_ex( - struct Depsgraph *depsgraph, struct wmWindowManager *wm, + struct Main *bmain, struct Depsgraph *depsgraph, struct wmWindowManager *wm, struct Scene *scene, struct Object *ob); void ED_object_vpaintmode_enter(struct bContext *C); void ED_object_wpaintmode_enter_ex( - struct Depsgraph *depsgraph, struct wmWindowManager *wm, + struct Main *bmain, struct Depsgraph *depsgraph, struct wmWindowManager *wm, struct Scene *scene, struct Object *ob); void ED_object_wpaintmode_enter(struct bContext *C); @@ -245,7 +245,7 @@ int ED_object_modifier_convert( struct ReportList *reports, struct Main *bmain, struct Scene *scene, struct ViewLayer *view_layer, struct Object *ob, struct ModifierData *md); int ED_object_modifier_apply( - struct ReportList *reports, struct Depsgraph *depsgraph, struct Scene *scene, + struct Main *bmain, struct ReportList *reports, struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, struct ModifierData *md, int mode); int ED_object_modifier_copy(struct ReportList *reports, struct Object *ob, struct ModifierData *md); diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index cd1fb1f91d8..9fcefc1e4b1 100644 --- a/source/blender/editors/include/ED_screen.h +++ b/source/blender/editors/include/ED_screen.h @@ -69,22 +69,33 @@ void ED_region_do_layout(struct bContext *C, struct ARegion *ar); void ED_region_do_draw(struct bContext *C, struct ARegion *ar); void ED_region_exit(struct bContext *C, struct ARegion *ar); void ED_region_pixelspace(struct ARegion *ar); -void ED_region_update_rect(struct bContext *C, struct ARegion *ar); -void ED_region_init(struct bContext *C, struct ARegion *ar); +void ED_region_update_rect(struct ARegion *ar); +void ED_region_init(struct ARegion *ar); void ED_region_tag_redraw(struct ARegion *ar); void ED_region_tag_redraw_partial(struct ARegion *ar, const struct rcti *rct); void ED_region_tag_redraw_overlay(struct ARegion *ar); void ED_region_tag_redraw_no_rebuild(struct ARegion *ar); void ED_region_tag_refresh_ui(struct ARegion *ar); -void ED_region_panels_init(struct wmWindowManager *wm, struct ARegion *ar); -void ED_region_panels( - const struct bContext *C, struct ARegion *ar, - const char *contexts[], int contextnr, - const bool vertical); -void ED_region_header_init(struct ARegion *ar); -void ED_region_header(const struct bContext *C, struct ARegion *ar); -void ED_region_header_layout(const struct bContext *C, struct ARegion *ar); -void ED_region_header_draw(const struct bContext *C, struct ARegion *ar); + +void ED_region_panels_init(struct wmWindowManager *wm, struct ARegion *ar); +void ED_region_panels_ex( + const struct bContext *C, struct ARegion *ar, + const char *contexts[], int contextnr, const bool vertical); +void ED_region_panels( + const struct bContext *C, struct ARegion *ar); +void ED_region_panels_layout_ex( + const struct bContext *C, struct ARegion *ar, + const char *contexts[], int contextnr, const bool vertical); +void ED_region_panels_layout( + const struct bContext *C, struct ARegion *ar); +void ED_region_panels_draw( + const struct bContext *C, struct ARegion *ar); + +void ED_region_header_init(struct ARegion *ar); +void ED_region_header(const struct bContext *C, struct ARegion *ar); +void ED_region_header_layout(const struct bContext *C, struct ARegion *ar); +void ED_region_header_draw(const struct bContext *C, struct ARegion *ar); + void ED_region_cursor_set(struct wmWindow *win, struct ScrArea *sa, struct ARegion *ar); void ED_region_toggle_hidden(struct bContext *C, struct ARegion *ar); void ED_region_visibility_change_update(struct bContext *C, struct ARegion *ar); @@ -307,6 +318,11 @@ void ED_region_cache_draw_background(const struct ARegion *ar); void ED_region_cache_draw_curfra_label(const int framenr, const float x, const float y); void ED_region_cache_draw_cached_segments(const struct ARegion *ar, const int num_segments, const int *points, const int sfra, const int efra); +/* interface_region_hud.c */ +struct ARegionType *ED_area_type_hud(int space_type); +void ED_area_type_hud_clear(struct wmWindowManager *wm, ScrArea *sa_keep); +void ED_area_type_hud_ensure(struct bContext *C, struct ScrArea *sa); + /* default keymaps, bitflags */ #define ED_KEYMAP_UI 1 #define ED_KEYMAP_VIEW2D 2 diff --git a/source/blender/editors/include/ED_undo.h b/source/blender/editors/include/ED_undo.h index 5103ac97361..37744e7eb0f 100644 --- a/source/blender/editors/include/ED_undo.h +++ b/source/blender/editors/include/ED_undo.h @@ -52,14 +52,6 @@ int ED_undo_operator_repeat(struct bContext *C, struct wmOperator *op); void ED_undo_operator_repeat_cb(struct bContext *C, void *arg_op, void *arg_unused); void ED_undo_operator_repeat_cb_evt(struct bContext *C, void *arg_op, int arg_unused); -/* Context sanity helpers for operator repeat. */ -typedef struct OperatorRepeatContextHandle OperatorRepeatContextHandle; - -const OperatorRepeatContextHandle *ED_operator_repeat_prepare_context( - struct bContext *C, struct wmOperator *op) ATTR_WARN_UNUSED_RESULT; -void ED_operator_repeat_reset_context( - struct bContext *C, const OperatorRepeatContextHandle *context_info); - bool ED_undo_is_valid(const struct bContext *C, const char *undoname); struct UndoStack *ED_undo_stack_get(void); diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h index 3bc1255d23f..659f6c97696 100644 --- a/source/blender/editors/include/UI_icons.h +++ b/source/blender/editors/include/UI_icons.h @@ -113,9 +113,7 @@ DEF_ICON(FILE_TICK) DEF_ICON(QUIT) DEF_ICON(URL) DEF_ICON(RECOVER_LAST) -#ifndef DEF_ICON_BLANK_SKIP - DEF_ICON(BLANK038) -#endif +DEF_ICON(PRESET) DEF_ICON(FULLSCREEN_ENTER) DEF_ICON(FULLSCREEN_EXIT) DEF_ICON(BLANK1) // Not actually blank - this is used all over the place diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index a283068853c..876a382bb7c 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -305,7 +305,8 @@ typedef enum { UI_BTYPE_NODE_SOCKET = (53 << 9), UI_BTYPE_SEPR = (54 << 9), UI_BTYPE_SEPR_LINE = (55 << 9), - UI_BTYPE_GRIP = (56 << 9), /* resize handle (resize uilist) */ + UI_BTYPE_SEPR_SPACER = (56 << 9), /* Dynamically fill available space. */ + UI_BTYPE_GRIP = (57 << 9), /* resize handle (resize uilist) */ } eButType; #define BUTTYPE (63 << 9) @@ -829,6 +830,7 @@ struct Panel *UI_panel_begin(struct ScrArea *sa, struct ARegion *ar, struct List void UI_panel_end(uiBlock *block, int width, int height); void UI_panels_scale(struct ARegion *ar, float new_width); void UI_panel_label_offset(struct uiBlock *block, int *x, int *y); +int UI_panel_size_y(const struct Panel *pa); bool UI_panel_category_is_visible(struct ARegion *ar); void UI_panel_category_add(struct ARegion *ar, const char *name); @@ -904,6 +906,7 @@ void UI_exit(void); #define UI_ITEM_O_DEPRESS (1 << 9) #define UI_ITEM_R_COMPACT (1 << 10) +#define UI_HEADER_OFFSET ((void)0, 0.2f * UI_UNIT_X) /* uiLayoutOperatorButs flags */ enum { @@ -943,7 +946,6 @@ uiBlock *uiLayoutGetBlock(uiLayout *layout); void uiLayoutSetFunc(uiLayout *layout, uiMenuHandleFunc handlefunc, void *argv); void uiLayoutSetContextPointer(uiLayout *layout, const char *name, struct PointerRNA *ptr); void uiLayoutContextCopy(uiLayout *layout, struct bContextStore *context); -const char *uiLayoutIntrospect(uiLayout *layout); // XXX - testing struct MenuType *UI_but_menutype_get(uiBut *but); struct PanelType *UI_but_paneltype_get(uiBut *but); void UI_menutype_draw(struct bContext *C, struct MenuType *mt, struct uiLayout *layout); @@ -979,6 +981,8 @@ bool uiLayoutGetPropSep(uiLayout *layout); uiLayout *uiLayoutRow(uiLayout *layout, int align); uiLayout *uiLayoutColumn(uiLayout *layout, int align); uiLayout *uiLayoutColumnFlow(uiLayout *layout, int number, int align); +uiLayout *uiLayoutGridFlow( + uiLayout *layout, int row_major, int num_columns, int even_columns, int even_rows, int align); uiLayout *uiLayoutBox(uiLayout *layout); uiLayout *uiLayoutListBox(uiLayout *layout, struct uiList *ui_list, struct PointerRNA *ptr, struct PropertyRNA *prop, struct PointerRNA *actptr, struct PropertyRNA *actprop); @@ -1027,6 +1031,7 @@ uiLayout *uiTemplateConstraint(uiLayout *layout, struct PointerRNA *ptr); void uiTemplatePreview(uiLayout *layout, struct bContext *C, struct ID *id, int show_buttons, struct ID *parent, struct MTex *slot, const char *preview_id); void uiTemplateColorRamp(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int expand); +void uiTemplateIcon(uiLayout *layout, int icon_value, float icon_scale); void uiTemplateIconView(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int show_labels, float icon_scale); void uiTemplateHistogram(uiLayout *layout, struct PointerRNA *ptr, const char *propname); void uiTemplateWaveform(uiLayout *layout, struct PointerRNA *ptr, const char *propname); @@ -1125,6 +1130,7 @@ void uiItemLDrag(uiLayout *layout, struct PointerRNA *ptr, const char *name, int void uiItemM(uiLayout *layout, struct bContext *C, const char *menuname, const char *name, int icon); /* menu */ void uiItemV(uiLayout *layout, const char *name, int icon, int argval); /* value */ void uiItemS(uiLayout *layout); /* separator */ +void uiItemSpacer(uiLayout *layout); /* Special separator. */ void uiItemPopoverPanel_ptr( uiLayout *layout, struct bContext *C, diff --git a/source/blender/editors/include/UI_interface_icons.h b/source/blender/editors/include/UI_interface_icons.h index ee43b987a49..651081c46bb 100644 --- a/source/blender/editors/include/UI_interface_icons.h +++ b/source/blender/editors/include/UI_interface_icons.h @@ -49,7 +49,7 @@ typedef struct IconFile { #define ICON_DEFAULT_HEIGHT 16 #define ICON_DEFAULT_WIDTH 16 -#define ICON_DEFAULT_HEIGHT_TOOLBAR 38 +#define ICON_DEFAULT_HEIGHT_TOOLBAR 32 #define ICON_DEFAULT_HEIGHT_SCALE ((int)(UI_UNIT_Y * 0.8f)) #define ICON_DEFAULT_WIDTH_SCALE ((int)(UI_UNIT_X * 0.8f)) diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h index cab0fa8645d..48afea6bbf0 100644 --- a/source/blender/editors/include/UI_resources.h +++ b/source/blender/editors/include/UI_resources.h @@ -90,6 +90,7 @@ typedef enum ThemeColorID { TH_WIRE, TH_WIRE_INNER, TH_WIRE_EDIT, + TH_WIRE_INACTIVE, TH_SELECT, TH_ACTIVE, TH_GROUP, diff --git a/source/blender/editors/interface/CMakeLists.txt b/source/blender/editors/interface/CMakeLists.txt index 49fe6bfb2dc..07ba3b90e11 100644 --- a/source/blender/editors/interface/CMakeLists.txt +++ b/source/blender/editors/interface/CMakeLists.txt @@ -58,6 +58,7 @@ set(SRC interface_panel.c interface_regions.c interface_region_color_picker.c + interface_region_hud.c interface_region_menu_pie.c interface_region_menu_popup.c interface_region_popover.c diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 28f4c40469a..cc3f450a99d 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -86,6 +86,9 @@ #include "interface_intern.h" +/* prototypes. */ +static void ui_but_to_pixelrect(struct rcti *rect, const struct ARegion *ar, struct uiBlock *block, struct uiBut *but); + /* avoid unneeded calls to ui_but_value_get */ #define UI_BUT_VALUE_UNSET DBL_MAX #define UI_GET_BUT_VALUE_INIT(_but, _value) if (_value == DBL_MAX) { (_value) = ui_but_value_get(_but); } (void)0 @@ -225,6 +228,64 @@ void ui_region_to_window(const ARegion *ar, int *x, int *y) *y += ar->winrct.ymin; } +static void ui_update_flexible_spacing(const ARegion *region, uiBlock *block) +{ + int sepr_flex_len = 0; + for (uiBut *but = block->buttons.first; but; but = but->next) { + if (but->type == UI_BTYPE_SEPR_SPACER) { + sepr_flex_len++; + } + } + + if (sepr_flex_len == 0) { + return; + } + + rcti rect; + ui_but_to_pixelrect(&rect, region, block, block->buttons.last); + const float buttons_width = (float)rect.xmax + UI_HEADER_OFFSET; + const float region_width = (float)region->sizex * U.dpi_fac; + + if (region_width <= buttons_width) { + return; + } + + /* We could get rid of this loop if we agree on a max number of spacer */ + int *spacers_pos = alloca(sizeof(*spacers_pos) * (size_t)sepr_flex_len); + int i = 0; + for (uiBut *but = block->buttons.first; but; but = but->next) { + if (but->type == UI_BTYPE_SEPR_SPACER) { + ui_but_to_pixelrect(&rect, region, block, but); + spacers_pos[i] = rect.xmax + UI_HEADER_OFFSET; + i++; + } + } + + const float segment_width = region_width / (float)sepr_flex_len; + float offset = 0, remaining_space = region_width - buttons_width; + i = 0; + for (uiBut *but = block->buttons.first; but; but = but->next) { + BLI_rctf_translate(&but->rect, offset, 0); + if (but->type == UI_BTYPE_SEPR_SPACER) { + /* How much the next block overlap with the current segment */ + int overlap = ( + (i == sepr_flex_len - 1) ? + buttons_width - spacers_pos[i] : + (spacers_pos[i + 1] - spacers_pos[i]) / 2); + int segment_end = segment_width * (i + 1); + int spacer_end = segment_end - overlap; + int spacer_sta = spacers_pos[i] + offset; + if (spacer_end > spacer_sta) { + float step = min_ff(remaining_space, spacer_end - spacer_sta); + remaining_space -= step; + offset += step; + } + i++; + } + } + ui_block_bounds_calc(block); +} + static void ui_update_window_matrix(const wmWindow *window, const ARegion *region, uiBlock *block) { /* window matrix and aspect */ @@ -283,7 +344,7 @@ static void ui_block_bounds_calc_text(uiBlock *block, float offset) UI_fontstyle_set(&style->widget); for (init_col_bt = bt = block->buttons.first; bt; bt = bt->next) { - if (!ELEM(bt->type, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE)) { + if (!ELEM(bt->type, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE, UI_BTYPE_SEPR_SPACER)) { j = BLF_width(style->widget.uifont_id, bt->drawstr, sizeof(bt->drawstr)); if (j > i) @@ -1182,6 +1243,7 @@ void UI_block_end_ex(const bContext *C, uiBlock *block, const int xy[2], int r_x { wmWindow *window = CTX_wm_window(C); Scene *scene = CTX_data_scene(C); + ARegion *region = CTX_wm_region(C); uiBut *but; BLI_assert(block->active); @@ -1258,6 +1320,8 @@ void UI_block_end_ex(const bContext *C, uiBlock *block, const int xy[2], int r_x UI_block_align_end(block); } + ui_update_flexible_spacing(region, block); + block->endblock = 1; } @@ -3225,7 +3289,8 @@ static uiBut *ui_def_but( UI_BTYPE_BLOCK, UI_BTYPE_BUT, UI_BTYPE_LABEL, UI_BTYPE_PULLDOWN, UI_BTYPE_ROUNDBOX, UI_BTYPE_LISTBOX, UI_BTYPE_BUT_MENU, UI_BTYPE_SCROLL, UI_BTYPE_GRIP, - UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE) || + UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE, + UI_BTYPE_SEPR_SPACER) || (but->type >= UI_BTYPE_SEARCH_MENU)) { /* pass */ diff --git a/source/blender/editors/interface/interface_align.c b/source/blender/editors/interface/interface_align.c index 619dce1b9d9..c945746c2df 100644 --- a/source/blender/editors/interface/interface_align.c +++ b/source/blender/editors/interface/interface_align.c @@ -111,7 +111,7 @@ enum { bool ui_but_can_align(const uiBut *but) { const bool btype_can_align = !ELEM(but->type, UI_BTYPE_LABEL, UI_BTYPE_CHECKBOX, UI_BTYPE_CHECKBOX_N, - UI_BTYPE_TAB, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE); + UI_BTYPE_TAB, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE, UI_BTYPE_SEPR_SPACER); return (btype_can_align && (BLI_rctf_size_x(&but->rect) > 0.0f) && (BLI_rctf_size_y(&but->rect) > 0.0f)); } @@ -499,7 +499,8 @@ void ui_block_align_calc(uiBlock *block, const ARegion *region) bool ui_but_can_align(uiBut *but) { - return !ELEM(but->type, UI_BTYPE_LABEL, UI_BTYPE_CHECKBOX, UI_BTYPE_CHECKBOX_N, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE); + return !ELEM(but->type, UI_BTYPE_LABEL, UI_BTYPE_CHECKBOX, UI_BTYPE_CHECKBOX_N, + UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE, UI_BTYPE_SEPR_SPACER); } static bool buts_are_horiz(uiBut *but1, uiBut *but2) diff --git a/source/blender/editors/interface/interface_eyedropper_color.c b/source/blender/editors/interface/interface_eyedropper_color.c index f3301d55284..a60b6f3f60b 100644 --- a/source/blender/editors/interface/interface_eyedropper_color.c +++ b/source/blender/editors/interface/interface_eyedropper_color.c @@ -38,6 +38,7 @@ #include "BLI_math_vector.h" #include "BKE_context.h" +#include "BKE_main.h" #include "BKE_screen.h" #include "RNA_access.h" @@ -131,6 +132,7 @@ static void eyedropper_exit(bContext *C, wmOperator *op) void eyedropper_color_sample_fl(bContext *C, int mx, int my, float r_col[3]) { /* we could use some clever */ + Main *bmain = CTX_data_main(C); bScreen *screen = CTX_wm_screen(C); ScrArea *sa = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, mx, my); const char *display_device = CTX_data_scene(C)->display_settings.display_device; @@ -156,7 +158,7 @@ void eyedropper_color_sample_fl(bContext *C, int mx, int my, float r_col[3]) int mval[2] = {mx - ar->winrct.xmin, my - ar->winrct.ymin}; - if (ED_space_node_color_sample(snode, ar, mval, r_col)) { + if (ED_space_node_color_sample(bmain, snode, ar, mval, r_col)) { return; } } diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index b05dbe9c3b0..74ecc20ebe0 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -6792,16 +6792,8 @@ static bool ui_but_menu(bContext *C, uiBut *but) else if (is_anim) { uiItemS(layout); - if (is_array_component) { - uiItemMenuEnumO(layout, C, "ANIM_OT_driver_button_add", "mapping_type", - CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add Drivers"), - ICON_DRIVER); - } - else { - uiItemMenuEnumO(layout, C, "ANIM_OT_driver_button_add", "mapping_type", - CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add Driver"), - ICON_DRIVER); - } + uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add Driver"), + ICON_DRIVER, "ANIM_OT_driver_button_add"); if (ANIM_driver_can_paste()) { uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Paste Driver"), @@ -7185,6 +7177,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent * /* quiet warnings for unhandled types */ case UI_BTYPE_SEPR: case UI_BTYPE_SEPR_LINE: + case UI_BTYPE_SEPR_SPACER: case UI_BTYPE_EXTRA: break; } @@ -9143,7 +9136,7 @@ static int ui_handle_menu_event( add_v2_v2v2_int(menu->popup_create_vars.event_xy, menu->popup_create_vars.event_xy, mdiff); - ui_popup_translate(C, ar, mdiff); + ui_popup_translate(ar, mdiff); } return retval; diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index c2ada1e3733..6e0c71c2224 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -451,49 +451,6 @@ static void icon_verify_datatoc(IconImage *iimg) } } -static void init_matcap_icons(void) -{ - /* dynamic allocation now, tucking datatoc pointers in DrawInfo */ -#define INIT_MATCAP_ICON(icon_id, name) \ - { \ - unsigned char *rect = (unsigned char *)datatoc_ ##name## _jpg; \ - int size = datatoc_ ##name## _jpg_size; \ - DrawInfo *di; \ - \ - di = def_internal_icon(NULL, icon_id, 0, 0, 96, ICON_TYPE_BUFFER); \ - di->data.buffer.image->datatoc_rect = rect; \ - di->data.buffer.image->datatoc_size = size; \ - } (void)0 - - INIT_MATCAP_ICON(ICON_MATCAP_01, mc01); - INIT_MATCAP_ICON(ICON_MATCAP_02, mc02); - INIT_MATCAP_ICON(ICON_MATCAP_03, mc03); - INIT_MATCAP_ICON(ICON_MATCAP_04, mc04); - INIT_MATCAP_ICON(ICON_MATCAP_05, mc05); - INIT_MATCAP_ICON(ICON_MATCAP_06, mc06); - INIT_MATCAP_ICON(ICON_MATCAP_07, mc07); - INIT_MATCAP_ICON(ICON_MATCAP_08, mc08); - INIT_MATCAP_ICON(ICON_MATCAP_09, mc09); - INIT_MATCAP_ICON(ICON_MATCAP_10, mc10); - INIT_MATCAP_ICON(ICON_MATCAP_11, mc11); - INIT_MATCAP_ICON(ICON_MATCAP_12, mc12); - INIT_MATCAP_ICON(ICON_MATCAP_13, mc13); - INIT_MATCAP_ICON(ICON_MATCAP_14, mc14); - INIT_MATCAP_ICON(ICON_MATCAP_15, mc15); - INIT_MATCAP_ICON(ICON_MATCAP_16, mc16); - INIT_MATCAP_ICON(ICON_MATCAP_17, mc17); - INIT_MATCAP_ICON(ICON_MATCAP_18, mc18); - INIT_MATCAP_ICON(ICON_MATCAP_19, mc19); - INIT_MATCAP_ICON(ICON_MATCAP_20, mc20); - INIT_MATCAP_ICON(ICON_MATCAP_21, mc21); - INIT_MATCAP_ICON(ICON_MATCAP_22, mc22); - INIT_MATCAP_ICON(ICON_MATCAP_23, mc23); - INIT_MATCAP_ICON(ICON_MATCAP_24, mc24); - -#undef INIT_MATCAP_ICON - -} - static void init_internal_icons(void) { // bTheme *btheme = UI_GetTheme(); @@ -850,7 +807,6 @@ void UI_icons_init(int first_dyn_id) init_iconfile_list(&iconfilelist); init_internal_icons(); init_brush_icons(); - init_matcap_icons(); #endif } @@ -1488,6 +1444,19 @@ int UI_rnaptr_icon_get(bContext *C, PointerRNA *ptr, int rnaicon, const bool big else if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) return ICON_FILE_IMAGE; } + else if (RNA_struct_is_a(ptr->type, &RNA_StudioLight)) { + StudioLight *sl = (StudioLight *)ptr->data; + switch (sl->flag & STUDIOLIGHT_FLAG_ORIENTATIONS) + { + case STUDIOLIGHT_ORIENTATION_CAMERA: + return sl->icon_id_irradiance; + case STUDIOLIGHT_ORIENTATION_WORLD: + default: + return sl->icon_id_radiance; + case STUDIOLIGHT_ORIENTATION_VIEWNORMAL: + return sl->icon_id_matcap; + } + } /* get icon from ID */ if (id) { diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index b5bf9be737b..1013f39faba 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -652,7 +652,7 @@ void ui_pie_menu_level_create( const EnumPropertyItem *items, int totitem, int context, int flag); /* interface_region_popup.c */ -void ui_popup_translate(struct bContext *C, struct ARegion *ar, const int mdiff[2]); +void ui_popup_translate(struct ARegion *ar, const int mdiff[2]); void ui_popup_block_free(struct bContext *C, uiPopupBlockHandle *handle); void ui_popup_block_scrolltest(struct uiBlock *block); @@ -757,8 +757,13 @@ void ui_draw_menu_back(struct uiStyle *style, uiBlock *block, rcti *rect); void ui_draw_popover_back(ARegion *ar, struct uiStyle *style, uiBlock *block, rcti *rect); void ui_draw_pie_center(uiBlock *block); uiWidgetColors *ui_tooltip_get_theme(void); + +void ui_draw_widget_back_color( + uiWidgetTypeEnum type, bool use_shadow, const rcti *rect, + const float color[4]); +void ui_draw_widget_back( + uiWidgetTypeEnum type, bool use_shadow, const rcti *rect); void ui_draw_tooltip_background(uiStyle *UNUSED(style), uiBlock *block, rcti *rect); -void ui_draw_search_back(struct uiStyle *style, uiBlock *block, rcti *rect); extern void ui_draw_but(const struct bContext *C, ARegion *ar, struct uiStyle *style, uiBut *but, rcti *rect); /* theme color init */ diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index b3bd98c7b94..a67a7740908 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -37,6 +37,7 @@ #include "DNA_armature_types.h" #include "DNA_userdef_types.h" +#include "BLI_alloca.h" #include "BLI_listbase.h" #include "BLI_string.h" #include "BLI_rect.h" @@ -101,6 +102,7 @@ typedef enum uiItemType { ITEM_LAYOUT_COLUMN, ITEM_LAYOUT_COLUMN_FLOW, ITEM_LAYOUT_ROW_FLOW, + ITEM_LAYOUT_GRID_FLOW, ITEM_LAYOUT_BOX, ITEM_LAYOUT_ABSOLUTE, ITEM_LAYOUT_SPLIT, @@ -152,6 +154,7 @@ struct uiLayout { bool enabled; bool redalert; bool keepaspect; + bool variable_size; /* For layouts inside gridflow, they and their items shall never have a fixed maximal size. */ char alignment; char emboss; }; @@ -162,6 +165,22 @@ typedef struct uiLayoutItemFlow { int totcol; } uiLayoutItemFlow; +typedef struct uiLayoutItemGridFlow { + uiLayout litem; + + /* Extra parameters */ + bool row_major; /* Fill first row first, instead of filling first column first. */ + bool even_columns; /* Same width for all columns. */ + bool even_rows; /* Same height for all rows. */ + /* If positive, absolute fixed number of columns. + * If 0, fully automatic (based on available width). + * If negative, automatic but only generates number of columns/rows multiple of given (absolute) value. */ + int num_columns; + + /* Pure internal runtime storage. */ + int tot_items, tot_columns, tot_rows; +} uiLayoutItemGridFlow; + typedef struct uiLayoutItemBx { uiLayout litem; uiBut *roundbox; @@ -237,6 +256,13 @@ static int ui_layout_vary_direction(uiLayout *layout) UI_ITEM_VARY_X : UI_ITEM_VARY_Y); } +static bool ui_layout_variable_size(uiLayout *layout) +{ + /* Note that this code is probably a bit flacky, we'd probably want to know whether it's variable in X and/or Y, + * etc. But for now it mimics previous one, with addition of variable flag set for children of gridflow layouts. */ + return ui_layout_vary_direction(layout) == UI_ITEM_VARY_X || layout->variable_size; +} + /* estimated size of text + icon */ static int ui_text_icon_width(uiLayout *layout, const char *name, int icon, bool compact) { @@ -246,7 +272,7 @@ static int ui_text_icon_width(uiLayout *layout, const char *name, int icon, bool if (icon && !name[0]) return unit_x; /* icon only */ - variable = (ui_layout_vary_direction(layout) == UI_ITEM_VARY_X); + variable = ui_layout_variable_size(layout); if (variable) { if (layout->alignment != UI_LAYOUT_ALIGN_EXPAND) { @@ -347,6 +373,7 @@ static int ui_layout_local_dir(uiLayout *layout) return UI_LAYOUT_HORIZONTAL; case ITEM_LAYOUT_COLUMN: case ITEM_LAYOUT_COLUMN_FLOW: + case ITEM_LAYOUT_GRID_FLOW: case ITEM_LAYOUT_SPLIT: case ITEM_LAYOUT_ABSOLUTE: case ITEM_LAYOUT_BOX: @@ -713,7 +740,7 @@ static uiBut *ui_item_with_label( w_label = (int)((w_hint * 2) * UI_ITEM_PROP_SEP_DIVIDE); } else { - if (ui_layout_vary_direction(layout) == UI_ITEM_VARY_X) { + if (ui_layout_variable_size(layout)) { /* w_hint is width for label in this case. Use a default width for property button(s) */ prop_but_width = UI_UNIT_X * 5; w_label = w_hint; @@ -1426,7 +1453,7 @@ static void ui_item_rna_size( else h += len * UI_UNIT_Y; } - else if (ui_layout_vary_direction(layout) == UI_ITEM_VARY_X) { + else if (ui_layout_variable_size(layout)) { if (type == PROP_BOOLEAN && name[0]) w += UI_UNIT_X / 5; else if (type == PROP_ENUM && !icon_only) @@ -1958,12 +1985,15 @@ static uiBut *ui_item_menu( h = UI_UNIT_Y; if (layout->root->type == UI_LAYOUT_HEADER) { /* ugly .. */ - if (force_menu) { - w += UI_UNIT_Y; + if (icon == ICON_NONE && force_menu) { + /* pass */ + } + else if (force_menu) { + w += UI_UNIT_X; } else { if (name[0]) { - w -= UI_UNIT_Y / 2; + w -= UI_UNIT_X / 2; } } } @@ -2017,12 +2047,23 @@ void uiItemPopoverPanel_ptr(uiLayout *layout, bContext *C, PanelType *pt, const name = CTX_IFACE_(pt->translation_context, pt->label); } - if (layout->root->type == UI_LAYOUT_MENU && !icon) + if (layout->root->type == UI_LAYOUT_MENU && !icon) { icon = ICON_BLANK1; + } + const bool ok = (pt->poll == NULL) || pt->poll(C, pt); + if (ok && (pt->draw_header != NULL)) { + layout = uiLayoutRow(layout, true); + Panel panel = { + .type = pt, + .layout = layout, + .flag = PNL_POPOVER, + }; + pt->draw_header(C, &panel); + } uiBut *but = ui_item_menu(layout, name, icon, ui_item_paneltype_func, pt, NULL, NULL, true); but->type = UI_BTYPE_POPOVER; - if (pt->poll && (pt->poll(C, pt) == false)) { + if (!ok) { but->flag |= UI_BUT_DISABLED; } } @@ -2075,10 +2116,12 @@ void uiItemPopoverPanelFromGroup( for (PanelType *pt = art->paneltypes.first; pt; pt = pt->next) { /* Causes too many panels, check context. */ - if (/* (*context == '\0') || */ STREQ(pt->context, context)) { - if ((*category == '\0') || STREQ(pt->category, category)) { - if (pt->poll == NULL || pt->poll(C, pt)) { - uiItemPopoverPanel_ptr(layout, C, pt, NULL, ICON_NONE); + if (pt->parent_id[0] == '\0') { + if (/* (*context == '\0') || */ STREQ(pt->context, context)) { + if ((*category == '\0') || STREQ(pt->category, category)) { + if (pt->poll == NULL || pt->poll(C, pt)) { + uiItemPopoverPanel_ptr(layout, C, pt, NULL, ICON_NONE); + } } } } @@ -2176,6 +2219,26 @@ void uiItemS(uiLayout *layout) uiDefBut(block, (is_menu) ? UI_BTYPE_SEPR_LINE : UI_BTYPE_SEPR, 0, "", 0, 0, space, space, NULL, 0.0, 0.0, 0, 0, ""); } +/* Flexible spacing. */ +void uiItemSpacer(uiLayout *layout) +{ + uiBlock *block = layout->root->block; + bool is_menu = ui_block_is_menu(block); + + if (is_menu) { + printf("Error: separator_spacer() not supported in menus.\n"); + return; + } + + if (block->direction & UI_DIR_RIGHT) { + printf("Error: separator_spacer() only supported in horizontal blocks.\n"); + return; + } + + UI_block_layout_set_current(block, layout); + uiDefBut(block, UI_BTYPE_SEPR_SPACER, 0, "", 0, 0, 0.3f * UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, ""); +} + /* level items */ void uiItemMenuF(uiLayout *layout, const char *name, int icon, uiMenuCreateFunc func, void *arg) { @@ -2559,7 +2622,7 @@ static bool ui_item_is_radial_displayable(uiItem *item) static bool ui_item_is_radial_drawable(uiButtonItem *bitem) { - if (ELEM(bitem->but->type, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE)) + if (ELEM(bitem->but->type, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE, UI_BTYPE_SEPR_SPACER)) return false; return true; @@ -2832,6 +2895,364 @@ static void ui_litem_layout_column_flow(uiLayout *litem) litem->y = miny; } +/* multi-column and multi-row layout. */ +typedef struct UILayoutGridFlowInput { + /* General layout controll settings. */ + const bool row_major : 1; /* Fill rows before columns */ + const bool even_columns : 1; /* All columns will have same width. */ + const bool even_rows : 1; /* All rows will have same height. */ + const int space_x; /* Space between columns. */ + const int space_y; /* Space between rows. */ + /* Real data about current position and size of this layout item (either estimated, or final values). */ + const int litem_w; /* Layout item width. */ + const int litem_x; /* Layout item X position. */ + const int litem_y; /* Layout item Y position. */ + /* Actual number of columns and rows to generate (computed from first pass usually). */ + const int tot_columns; /* Number of columns. */ + const int tot_rows; /* Number of rows. */ +} UILayoutGridFlowInput; + +typedef struct UILayoutGridFlowOutput { + int *tot_items; /* Total number of items in this grid layout. */ + /* Width / X pos data. */ + float *global_avg_w; /* Computed average width of the columns. */ + int *cos_x_array; /* Computed X coordinate of each column. */ + int *widths_array; /* Computed width of each column. */ + int *tot_w; /* Computed total width. */ + /* Height / Y pos data. */ + int *global_max_h; /* Computed height of the tallest item in the grid. */ + int *cos_y_array; /* Computed Y coordinate of each column. */ + int *heights_array; /* Computed height of each column. */ + int *tot_h; /* Computed total height. */ +} UILayoutGridFlowOutput; + +static void ui_litem_grid_flow_compute( + ListBase *items, UILayoutGridFlowInput *parameters, UILayoutGridFlowOutput *results) +{ + uiItem *item; + int i; + + float tot_w = 0.0f, tot_h = 0.0f; + float global_avg_w = 0.0f, global_totweight_w = 0.0f; + int global_max_h = 0; + + float *avg_w = NULL, *totweight_w = NULL; + int *max_h = NULL; + + BLI_assert(parameters->tot_columns != 0 || (results->cos_x_array == NULL && results->widths_array == NULL && results->tot_w == NULL)); + BLI_assert(parameters->tot_rows != 0 || (results->cos_y_array == NULL && results->heights_array == NULL && results->tot_h == NULL)); + + if (results->tot_items) { + *results->tot_items = 0; + } + + if (items->first == NULL) { + if (results->global_avg_w) { + *results->global_avg_w = 0.0f; + } + if (results->global_max_h) { + *results->global_max_h = 0; + } + return; + } + + if (parameters->tot_columns != 0) { + avg_w = BLI_array_alloca(avg_w, parameters->tot_columns); + totweight_w = BLI_array_alloca(totweight_w, parameters->tot_columns); + memset(avg_w, 0, sizeof(*avg_w) * parameters->tot_columns); + memset(totweight_w, 0, sizeof(*totweight_w) * parameters->tot_columns); + } + if (parameters->tot_rows != 0) { + max_h = BLI_array_alloca(max_h, parameters->tot_rows); + memset(max_h, 0, sizeof(*max_h) * parameters->tot_rows); + } + + for (i = 0, item = items->first; item; item = item->next, i++) { + int item_w, item_h; + ui_item_size(item, &item_w, &item_h); + + global_avg_w += (float)(item_w * item_w); + global_totweight_w += (float)item_w; + global_max_h = max_ii(global_max_h, item_h); + + if (parameters->tot_rows != 0 && parameters->tot_columns != 0) { + const int index_col = parameters->row_major ? i % parameters->tot_columns : i / parameters->tot_rows; + const int index_row = parameters->row_major ? i / parameters->tot_columns : i % parameters->tot_rows; + + avg_w[index_col] += (float)(item_w * item_w); + totweight_w[index_col] += (float)item_w; + + max_h[index_row] = max_ii(max_h[index_row], item_h); + } + + if (results->tot_items) { + (*results->tot_items)++; + } + } + + /* Finalize computing of column average sizes */ + global_avg_w /= global_totweight_w; + if (parameters->tot_columns != 0) { + for (i = 0; i < parameters->tot_columns; i++) { + avg_w[i] /= totweight_w[i]; + tot_w += avg_w[i]; + } + if (parameters->even_columns) { + tot_w = ceilf(global_avg_w) * parameters->tot_columns; + } + } + /* Finalize computing of rows max sizes */ + if (parameters->tot_rows != 0) { + for (i = 0; i < parameters->tot_rows; i++) { + tot_h += max_h[i]; + } + if (parameters->even_rows) { + tot_h = global_max_h * parameters->tot_columns; + } + } + + /* Compute positions and sizes of all cells. */ + if (results->cos_x_array != NULL && results->widths_array != NULL) { + /* We enlarge/narrow columns evenly to match available width. */ + const float wfac = (float)(parameters->litem_w - (parameters->tot_columns - 1) * parameters->space_x) / tot_w; + + for (int col = 0; col < parameters->tot_columns; col++) { + results->cos_x_array[col] = ( + col ? + results->cos_x_array[col - 1] + results->widths_array[col - 1] + parameters->space_x : + parameters->litem_x + ); + if (parameters->even_columns) { + /* (< remaining width > - < space between remaining columns >) / < remaining columns > */ + results->widths_array[col] = ( + ((parameters->litem_w - (results->cos_x_array[col] - parameters->litem_x)) - + (parameters->tot_columns - col - 1) * parameters->space_x) / (parameters->tot_columns - col)); + } + else if (col == parameters->tot_columns - 1) { + /* Last column copes width rounding errors... */ + results->widths_array[col] = parameters->litem_w - (results->cos_x_array[col] - parameters->litem_x); + } + else { + results->widths_array[col] = (int)(avg_w[col] * wfac); + } + } + } + if (results->cos_y_array != NULL && results->heights_array != NULL) { + for (int row = 0; row < parameters->tot_rows; row++) { + if (parameters->even_rows) { + results->heights_array[row] = global_max_h; + } + else { + results->heights_array[row] = max_h[row]; + } + results->cos_y_array[row] = ( + row ? + results->cos_y_array[row - 1] - parameters->space_y - results->heights_array[row] : + parameters->litem_y - results->heights_array[row]); + } + } + + if (results->global_avg_w) { + *results->global_avg_w = global_avg_w; + } + if (results->global_max_h) { + *results->global_max_h = global_max_h; + } + if (results->tot_w) { + *results->tot_w = (int)tot_w + parameters->space_x * (parameters->tot_columns - 1); + } + if (results->tot_h) { + *results->tot_h = tot_h + parameters->space_y * (parameters->tot_rows - 1); + } +} + +static void ui_litem_estimate_grid_flow(uiLayout *litem) +{ + uiStyle *style = litem->root->style; + uiLayoutItemGridFlow *gflow = (uiLayoutItemGridFlow *)litem; + + const int space_x = style->columnspace; + const int space_y = style->buttonspacey; + + /* Estimate average needed width and height per item. */ + { + float avg_w; + int max_h; + + ui_litem_grid_flow_compute( + &litem->items, + &((UILayoutGridFlowInput) { + .row_major = gflow->row_major, + .even_columns = gflow->even_columns, + .even_rows = gflow->even_rows, + .litem_w = litem->w, + .litem_x = litem->x, + .litem_y = litem->y, + .space_x = space_x, + .space_y = space_y, + }), + &((UILayoutGridFlowOutput) { + .tot_items = &gflow->tot_items, + .global_avg_w = &avg_w, + .global_max_h = &max_h, + })); + + if (gflow->tot_items == 0) { + litem->w = litem->h = 0; + gflow->tot_columns = gflow->tot_rows = 0; + return; + } + + /* Even in varying column width case, we fix our columns number from weighted average width of items, + * a proper solving of required width would be too costly, and this should give reasonably good results + * in all resonable cases... */ + if (gflow->num_columns > 0) { + gflow->tot_columns = gflow->num_columns; + } + else { + if (avg_w == 0.0f) { + gflow->tot_columns = 1; + } + else { + gflow->tot_columns = min_ii(max_ii((int)(litem->w / avg_w), 1), gflow->tot_items); + } + } + gflow->tot_rows = (int)ceilf((float)gflow->tot_items / gflow->tot_columns); + + /* Try to tweak number of columns and rows to get better filling of last column or row, + * and apply 'modulo' value to number of columns or rows. + * Note that modulo does not prevent ending with fewer columns/rows than modulo, if mandatory + * to avoid empty column/row. */ + { + const int modulo = (gflow->num_columns < -1) ? -gflow->num_columns : 0; + const int step = modulo ? modulo : 1; + + if (gflow->row_major) { + /* Adjust number of columns to be mutiple of given modulo. */ + if (modulo && gflow->tot_columns % modulo != 0 && gflow->tot_columns > modulo) { + gflow->tot_columns = gflow->tot_columns - (gflow->tot_columns % modulo); + } + /* Find smallest number of columns conserving computed optimal number of rows. */ + for (gflow->tot_rows = (int)ceilf((float)gflow->tot_items / gflow->tot_columns); + (gflow->tot_columns - step) > 0 && + (int)ceilf((float)gflow->tot_items / (gflow->tot_columns - step)) <= gflow->tot_rows; + gflow->tot_columns -= step); + } + else { + /* Adjust number of rows to be mutiple of given modulo. */ + if (modulo && gflow->tot_rows % modulo != 0) { + gflow->tot_rows = min_ii(gflow->tot_rows + modulo - (gflow->tot_rows % modulo), gflow->tot_items); + } + /* Find smallest number of rows conserving computed optimal number of columns. */ + for (gflow->tot_columns = (int)ceilf((float)gflow->tot_items / gflow->tot_rows); + (gflow->tot_rows - step) > 0 && + (int)ceilf((float)gflow->tot_items / (gflow->tot_rows - step)) <= gflow->tot_columns; + gflow->tot_rows -= step); + } + } + + /* Set evenly-spaced axes size (quick optimization in case we have even columns and rows). */ + if (gflow->even_columns && gflow->even_rows) { + litem->w = (int)(gflow->tot_columns * avg_w) + space_x * (gflow->tot_columns - 1); + litem->h = (int)(gflow->tot_rows * max_h) + space_y * (gflow->tot_rows - 1); + return; + } + } + + /* Now that we have our final number of columns and rows, + * we can compute actual needed space for non-evenly sized axes. */ + { + int tot_w, tot_h; + + ui_litem_grid_flow_compute( + &litem->items, + &((UILayoutGridFlowInput) { + .row_major = gflow->row_major, + .even_columns = gflow->even_columns, + .even_rows = gflow->even_rows, + .litem_w = litem->w, + .litem_x = litem->x, + .litem_y = litem->y, + .space_x = space_x, + .space_y = space_y, + .tot_columns = gflow->tot_columns, + .tot_rows = gflow->tot_rows, + }), + &((UILayoutGridFlowOutput) { + .tot_w = &tot_w, + .tot_h = &tot_h, + })); + + litem->w = tot_w; + litem->h = tot_h; + } +} + +static void ui_litem_layout_grid_flow(uiLayout *litem) +{ + int i; + uiStyle *style = litem->root->style; + uiLayoutItemGridFlow *gflow = (uiLayoutItemGridFlow *)litem; + uiItem *item; + + if (gflow->tot_items == 0) { + litem->w = litem->h = 0; + return; + } + + BLI_assert(gflow->tot_columns > 0); + BLI_assert(gflow->tot_rows > 0); + + const int space_x = style->columnspace; + const int space_y = style->buttonspacey; + + int *widths = BLI_array_alloca(widths, gflow->tot_columns); + int *heights = BLI_array_alloca(heights, gflow->tot_rows); + int *cos_x = BLI_array_alloca(cos_x, gflow->tot_columns); + int *cos_y = BLI_array_alloca(cos_y, gflow->tot_rows); + + /* This time we directly compute coordinates and sizes of all cells. */ + ui_litem_grid_flow_compute( + &litem->items, + &((UILayoutGridFlowInput) { + .row_major = gflow->row_major, + .even_columns = gflow->even_columns, + .even_rows = gflow->even_rows, + .litem_w = litem->w, + .litem_x = litem->x, + .litem_y = litem->y, + .space_x = space_x, + .space_y = space_y, + .tot_columns = gflow->tot_columns, + .tot_rows = gflow->tot_rows, + }), + &((UILayoutGridFlowOutput) { + .cos_x_array = cos_x, + .cos_y_array = cos_y, + .widths_array = widths, + .heights_array = heights, + })); + + for (item = litem->items.first, i = 0; item; item = item->next, i++) { + const int col = gflow->row_major ? i % gflow->tot_columns : i / gflow->tot_rows; + const int row = gflow->row_major ? i / gflow->tot_columns : i % gflow->tot_rows; + int item_w, item_h; + ui_item_size(item, &item_w, &item_h); + + const int w = widths[col]; + const int h = heights[row]; + + item_w = (litem->alignment == UI_LAYOUT_ALIGN_EXPAND) ? w : min_ii(w, item_w); + item_h = (litem->alignment == UI_LAYOUT_ALIGN_EXPAND) ? h : min_ii(h, item_h); + + ui_item_position(item, cos_x[col], cos_y[row], item_w, item_h); + } + + litem->h = litem->y - cos_y[gflow->tot_rows - 1]; + litem->x = (cos_x[gflow->tot_columns - 1] - litem->x) + widths[gflow->tot_columns - 1]; + litem->y = litem->y - litem->h; +} + /* free layout */ static void ui_litem_estimate_absolute(uiLayout *litem) { @@ -3005,6 +3426,8 @@ static void ui_litem_init_from_parent(uiLayout *litem, uiLayout *layout, int ali { litem->root = layout->root; litem->align = align; + /* Children of gridflow layout shall never have "ideal big size" returned as estimated size. */ + litem->variable_size = layout->variable_size || layout->item.type == ITEM_LAYOUT_GRID_FLOW; litem->active = true; litem->enabled = true; litem->context = layout->context; @@ -3062,6 +3485,26 @@ uiLayout *uiLayoutColumnFlow(uiLayout *layout, int number, int align) return &flow->litem; } +uiLayout *uiLayoutGridFlow( + uiLayout *layout, int row_major, int num_columns, int even_columns, int even_rows, int align) +{ + uiLayoutItemGridFlow *flow; + + flow = MEM_callocN(sizeof(uiLayoutItemGridFlow), __func__); + flow->litem.item.type = ITEM_LAYOUT_GRID_FLOW; + ui_litem_init_from_parent(&flow->litem, layout, align); + + flow->litem.space = (flow->litem.align) ? 0 : layout->root->style->columnspace; + flow->row_major = row_major; + flow->num_columns = num_columns; + flow->even_columns = even_columns; + flow->even_rows = even_rows; + + UI_block_layout_set_current(layout->root->block, &flow->litem); + + return &flow->litem; +} + static uiLayoutItemBx *ui_layout_box(uiLayout *layout, int type) { uiLayoutItemBx *box; @@ -3357,6 +3800,9 @@ static void ui_item_estimate(uiItem *item) case ITEM_LAYOUT_COLUMN_FLOW: ui_litem_estimate_column_flow(litem); break; + case ITEM_LAYOUT_GRID_FLOW: + ui_litem_estimate_grid_flow(litem); + break; case ITEM_LAYOUT_ROW: ui_litem_estimate_row(litem); break; @@ -3456,6 +3902,9 @@ static void ui_item_layout(uiItem *item) case ITEM_LAYOUT_COLUMN_FLOW: ui_litem_layout_column_flow(litem); break; + case ITEM_LAYOUT_GRID_FLOW: + ui_litem_layout_grid_flow(litem); + break; case ITEM_LAYOUT_ROW: ui_litem_layout_row(litem); break; @@ -3696,93 +4145,6 @@ void uiLayoutSetContextFromBut(uiLayout *layout, uiBut *but) } } -/* introspect funcs */ -#include "BLI_dynstr.h" - -static void ui_intro_button(DynStr *ds, uiButtonItem *bitem) -{ - uiBut *but = bitem->but; - BLI_dynstr_appendf(ds, "'type':%d, ", (int)but->type); - BLI_dynstr_appendf(ds, "'draw_string':'''%s''', ", but->drawstr); - BLI_dynstr_appendf(ds, "'tip':'''%s''', ", but->tip ? but->tip : ""); /* not exactly needed, rna has this */ - - if (but->optype) { - char *opstr = WM_operator_pystring_ex(but->block->evil_C, NULL, false, true, but->optype, but->opptr); - BLI_dynstr_appendf(ds, "'operator':'''%s''', ", opstr ? opstr : ""); - MEM_freeN(opstr); - } - - if (but->rnaprop) { - BLI_dynstr_appendf(ds, "'rna':'%s.%s[%d]', ", RNA_struct_identifier(but->rnapoin.type), RNA_property_identifier(but->rnaprop), but->rnaindex); - } - -} - -static void ui_intro_items(DynStr *ds, ListBase *lb) -{ - uiItem *item; - - BLI_dynstr_append(ds, "["); - - for (item = lb->first; item; item = item->next) { - - BLI_dynstr_append(ds, "{"); - - /* could also use the INT but this is nicer*/ - switch (item->type) { - case ITEM_BUTTON: BLI_dynstr_append(ds, "'type':'BUTTON', "); break; - case ITEM_LAYOUT_ROW: BLI_dynstr_append(ds, "'type':'UI_BTYPE_ROW', "); break; - case ITEM_LAYOUT_COLUMN: BLI_dynstr_append(ds, "'type':'COLUMN', "); break; - case ITEM_LAYOUT_COLUMN_FLOW: BLI_dynstr_append(ds, "'type':'COLUMN_FLOW', "); break; - case ITEM_LAYOUT_ROW_FLOW: BLI_dynstr_append(ds, "'type':'ROW_FLOW', "); break; - case ITEM_LAYOUT_BOX: BLI_dynstr_append(ds, "'type':'BOX', "); break; - case ITEM_LAYOUT_ABSOLUTE: BLI_dynstr_append(ds, "'type':'ABSOLUTE', "); break; - case ITEM_LAYOUT_SPLIT: BLI_dynstr_append(ds, "'type':'SPLIT', "); break; - case ITEM_LAYOUT_OVERLAP: BLI_dynstr_append(ds, "'type':'OVERLAP', "); break; - case ITEM_LAYOUT_ROOT: BLI_dynstr_append(ds, "'type':'ROOT', "); break; - default: BLI_dynstr_append(ds, "'type':'UNKNOWN', "); break; - } - - switch (item->type) { - case ITEM_BUTTON: - ui_intro_button(ds, (uiButtonItem *)item); - break; - default: - BLI_dynstr_append(ds, "'items':"); - ui_intro_items(ds, &((uiLayout *)item)->items); - break; - } - - BLI_dynstr_append(ds, "}"); - - if (item != lb->last) - BLI_dynstr_append(ds, ", "); - } - BLI_dynstr_append(ds, "], "); -} - -static void ui_intro_uiLayout(DynStr *ds, uiLayout *layout) -{ - ui_intro_items(ds, &layout->items); -} - -static char *str = NULL; /* XXX, constant re-freeing, far from ideal. */ -const char *uiLayoutIntrospect(uiLayout *layout) -{ - DynStr *ds = BLI_dynstr_new(); - - if (str) { - MEM_freeN(str); - } - - ui_intro_uiLayout(ds, layout); - - str = BLI_dynstr_get_cstring(ds); - BLI_dynstr_free(ds); - - return str; -} - /* this is a bit of a hack but best keep it in one place at least */ MenuType *UI_but_menutype_get(uiBut *but) { @@ -3828,31 +4190,58 @@ void UI_menutype_draw(bContext *C, MenuType *mt, struct uiLayout *layout) } } + +static void ui_paneltype_draw_impl( + bContext *C, PanelType *pt, uiLayout *layout, bool show_header) +{ + Panel *panel = MEM_callocN(sizeof(Panel), "popover panel"); + panel->type = pt; + panel->flag = PNL_POPOVER; + + if (show_header) { + uiLayout *row = uiLayoutRow(layout, false); + if (pt->draw_header) { + panel->layout = row; + pt->draw_header(C, panel); + panel->layout = NULL; + } + uiItemL(row, pt->label, ICON_NONE); + } + + panel->layout = layout; + pt->draw(C, panel); + panel->layout = NULL; + + MEM_freeN(panel); + + PanelType *pt_iter = pt; + while (pt_iter->prev) { + pt_iter = pt_iter->prev; + } + do { + if (pt_iter != pt && STREQ(pt_iter->parent_id, pt->idname)) { + if (pt_iter->poll == NULL || pt_iter->poll(C, pt_iter)) { + uiItemS(layout); + uiLayout *col = uiLayoutColumn(layout, false); + ui_paneltype_draw_impl(C, pt_iter, col, true); + } + } + } while ((pt_iter = pt_iter->next)); +} + /** * Used for popup panels only. */ void UI_paneltype_draw(bContext *C, PanelType *pt, uiLayout *layout) { - Panel *panel = MEM_callocN(sizeof(Panel), "popover panel"); - panel->type = pt; - if (layout->context) { CTX_store_set(C, layout->context); } - if (pt->draw_header) { - panel->layout = uiLayoutRow(layout, false); - pt->draw_header(C, panel); - panel->layout = NULL; - } - - panel->layout = layout; - pt->draw(C, panel); - panel->layout = NULL; + ui_paneltype_draw_impl(C, pt, layout, false); if (layout->context) { CTX_store_set(C, NULL); } - MEM_freeN(panel); } diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c index dbdf2a0863c..e383ae42f8c 100644 --- a/source/blender/editors/interface/interface_panel.c +++ b/source/blender/editors/interface/interface_panel.c @@ -110,7 +110,7 @@ typedef struct uiHandlePanelData { int startsizex, startsizey; } uiHandlePanelData; -static int get_panel_real_size_y(Panel *pa); +static int get_panel_real_size_y(const Panel *pa); static void panel_activate_state(const bContext *C, Panel *pa, uiHandlePanelState state); /*********************** space specific code ************************/ @@ -855,7 +855,7 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con /************************** panel alignment *************************/ -static int get_panel_header(Panel *pa) +static int get_panel_header(const Panel *pa) { if (pa->type && (pa->type->flag & PNL_NO_HEADER)) return 0; @@ -863,7 +863,7 @@ static int get_panel_header(Panel *pa) return PNL_HEADER; } -static int get_panel_size_y(Panel *pa) +static int get_panel_size_y(const Panel *pa) { if (pa->type && (pa->type->flag & PNL_NO_HEADER)) return pa->sizey; @@ -871,7 +871,7 @@ static int get_panel_size_y(Panel *pa) return PNL_HEADER + pa->sizey; } -static int get_panel_real_size_y(Panel *pa) +static int get_panel_real_size_y(const Panel *pa) { int sizey = (pa->flag & PNL_CLOSED) ? 0 : pa->sizey; @@ -881,6 +881,11 @@ static int get_panel_real_size_y(Panel *pa) return PNL_HEADER + sizey; } +int UI_panel_size_y(const Panel *pa) +{ + return get_panel_real_size_y(pa); +} + /* this function is needed because uiBlock and Panel itself don't * change sizey or location when closed */ static int get_panel_real_ofsy(Panel *pa) @@ -1596,6 +1601,10 @@ static void ui_handle_panel_header(const bContext *C, uiBlock *block, int mx, in ED_region_tag_redraw(ar); } else if (show_drag && BLI_rctf_isect_x(&rect_drag, mx)) { + /* XXX, for now don't allow dragging in floating windows yet. */ + if (ar->alignment == RGN_ALIGN_FLOAT) { + return; + } panel_activate_state(C, block->panel, PANEL_STATE_DRAG); } else if (show_pin && BLI_rctf_isect_x(&rect_pin, mx)) { diff --git a/source/blender/editors/interface/interface_region_hud.c b/source/blender/editors/interface/interface_region_hud.c new file mode 100644 index 00000000000..569f50a9c75 --- /dev/null +++ b/source/blender/editors/interface/interface_region_hud.c @@ -0,0 +1,335 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2008 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/interface/interface_region_hud.c + * \ingroup edinterface + * + * Floating Persistent Region + */ + +#include <string.h> + +#include "MEM_guardedalloc.h" + +#include "DNA_userdef_types.h" + +#include "BLI_string.h" +#include "BLI_rect.h" +#include "BLI_listbase.h" +#include "BLI_utildefines.h" + +#include "BKE_context.h" +#include "BKE_screen.h" +#include "BKE_main.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "RNA_access.h" + +#include "BIF_gl.h" + +#include "UI_interface.h" +#include "UI_view2d.h" + +#include "BLT_translation.h" + +#include "ED_screen.h" +#include "ED_undo.h" + +#include "interface_intern.h" + + +/* -------------------------------------------------------------------- */ +/** \name Utilities + * \{ */ + +static bool last_redo_poll(const bContext *C) +{ + wmOperator *op = WM_operator_last_redo(C); + if (op == NULL) { + return false; + } + bool success = false; + if (WM_operator_repeat_check(C, op) && + WM_operator_check_ui_empty(op->type) == false) + { + success = WM_operator_poll((bContext *)C, op->type); + } + return success; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Redo Panel + * \{ */ + +static int hud_panel_operator_redo_poll(const bContext *C, PanelType *UNUSED(pt)) +{ + return last_redo_poll(C); +} + +static void hud_panel_operator_redo_draw_header(const bContext *C, Panel *pa) +{ + wmOperator *op = WM_operator_last_redo(C); + BLI_strncpy(pa->drawname, RNA_struct_ui_name(op->type->srna), sizeof(pa->drawname)); +} + +static void hud_panel_operator_redo_draw(const bContext *C, Panel *pa) +{ + wmOperator *op = WM_operator_last_redo(C); + if (op == NULL) { + return; + } + if (!WM_operator_check_ui_enabled(C, op->type->name)) { + uiLayoutSetEnabled(pa->layout, false); + } + uiLayout *col = uiLayoutColumn(pa->layout, false); + uiTemplateOperatorRedoProperties(col, C); +} + +static void hud_panels_register(ARegionType *art, int space_type, int region_type) +{ + PanelType *pt; + + pt = MEM_callocN(sizeof(PanelType), __func__); + strcpy(pt->idname, "OPERATOR_PT_redo"); + strcpy(pt->label, N_("Redo")); + strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); + pt->draw_header = hud_panel_operator_redo_draw_header; + pt->draw = hud_panel_operator_redo_draw; + pt->poll = hud_panel_operator_redo_poll; + pt->space_type = space_type; + pt->region_type = region_type; + BLI_addtail(&art->paneltypes, pt); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Callbacks for Floating Region + * \{ */ + +struct HudRegionData { + short regionid; +}; + +static void hud_region_init(wmWindowManager *wm, ARegion *ar) +{ + ED_region_panels_init(wm, ar); + UI_region_handlers_add(&ar->handlers); + ar->flag |= RGN_FLAG_TEMP_REGIONDATA; +} + +static void hud_region_free(ARegion *ar) +{ + MEM_SAFE_FREE(ar->regiondata); +} + +static void hud_region_layout(const bContext *C, ARegion *ar) +{ + bool ok = false; + + { + struct HudRegionData *hrd = ar->regiondata; + if (hrd != NULL) { + ScrArea *sa = CTX_wm_area(C); + ARegion *ar_op = (hrd->regionid != -1) ? BKE_area_find_region_type(sa, hrd->regionid) : NULL; + ARegion *ar_prev = CTX_wm_region(C); + CTX_wm_region_set((bContext *)C, ar_op); + ok = last_redo_poll(C); + CTX_wm_region_set((bContext *)C, ar_prev); + } + } + + if (!ok) { + ED_region_tag_redraw(ar); + ar->flag |= RGN_FLAG_HIDDEN; + return; + } + + int size_y = ar->sizey; + + ED_region_panels_layout(C, ar); + + if (ar->panels.first && (ar->sizey != size_y)) { + View2D *v2d = &ar->v2d; + ar->winx = ar->sizex; + ar->winy = ar->sizey; + + ar->winrct.xmax = (ar->winrct.xmin + ar->winx) - 1; + ar->winrct.ymax = (ar->winrct.ymin + ar->winy) - 1; + + UI_view2d_region_reinit(v2d, V2D_COMMONVIEW_PANELS_UI, ar->winx, ar->winy); + } + + /* restore view matrix */ + UI_view2d_view_restore(C); +} + +static void hud_region_draw(const bContext *C, ARegion *ar) +{ + UI_view2d_view_ortho(&ar->v2d); + wmOrtho2_region_pixelspace(ar); + glClearColor(0, 0, 0, 0.0f); + glClear(GL_COLOR_BUFFER_BIT); + + if ((ar->flag & RGN_FLAG_HIDDEN) == 0) { + float color[4]; + UI_GetThemeColor4fv(TH_BUTBACK, color); + if ((U.uiflag2 & USER_REGION_OVERLAP) == 0) { + color[3] = 1.0f; + } + ui_draw_widget_back_color(UI_WTYPE_BOX, false, &(rcti){.xmax = ar->winx, .ymax = ar->winy}, color); + ED_region_panels_draw(C, ar); + } +} + +ARegionType *ED_area_type_hud(int space_type) +{ + ARegionType *art = MEM_callocN(sizeof(ARegionType), __func__); + art->regionid = RGN_TYPE_HUD; + art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D; + art->layout = hud_region_layout; + art->draw = hud_region_draw; + art->init = hud_region_init; + art->free = hud_region_free; + + hud_panels_register(art, space_type, art->regionid); + + art->lock = 1; /* can become flag, see BKE_spacedata_draw_locks */ + return art; +} + +static ARegion *hud_region_add(ScrArea *sa) +{ + ARegion *ar = MEM_callocN(sizeof(ARegion), "area region"); + ARegion *ar_win = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW); + if (ar_win) { + BLI_insertlinkbefore(&sa->regionbase, ar_win, ar); + } + else { + BLI_addtail(&sa->regionbase, ar); + } + ar->regiontype = RGN_TYPE_HUD; + ar->alignment = RGN_ALIGN_FLOAT; + ar->overlap = true; + ar->flag |= RGN_FLAG_DYNAMIC_SIZE; + + return ar; +} + +void ED_area_type_hud_clear(wmWindowManager *wm, ScrArea *sa_keep) +{ + for (wmWindow *win = wm->windows.first; win; win = win->next) { + bScreen *screen = WM_window_get_active_screen(win); + for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) { + if (sa != sa_keep) { + for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) { + if (ar->regiontype == RGN_TYPE_HUD) { + if ((ar->flag & RGN_FLAG_HIDDEN) == 0) { + ar->flag |= RGN_FLAG_HIDDEN; + ED_region_tag_redraw(ar); + ED_area_tag_redraw(sa); + } + } + } + } + } + } +} + +void ED_area_type_hud_ensure(bContext *C, ScrArea *sa) +{ + wmWindowManager *wm = CTX_wm_manager(C); + ED_area_type_hud_clear(wm, sa); + + ARegionType *art = BKE_regiontype_from_id(sa->type, RGN_TYPE_HUD); + if (art == NULL) { + return; + } + + bool init = false; + ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_HUD); + if (!last_redo_poll(C)) { + if (ar) { + ED_region_tag_redraw(ar); + ar->flag |= RGN_FLAG_HIDDEN; + } + return; + } + + if (ar == NULL) { + init = true; + ar = hud_region_add(sa); + ar->type = art; + } + + ED_region_init(ar); + ED_region_tag_redraw(ar); + + /* Reset zoom level (not well supported). */ + ar->v2d.cur = ar->v2d.tot = (rctf){.xmax = ar->winx, .ymax = ar->winy}; + ar->v2d.minzoom = 1.0f; + ar->v2d.maxzoom = 1.0f; + + /* Let 'ED_area_update_region_sizes' do the work of placing the region. + * Otherwise we could set the 'ar->winrct' & 'ar->winx/winy' here. */ + if (init) { + sa->flag |= AREA_FLAG_REGION_SIZE_UPDATE; + } + else { + if (ar->flag & RGN_FLAG_HIDDEN) { + sa->flag |= AREA_FLAG_REGION_SIZE_UPDATE; + } + ar->flag &= ~RGN_FLAG_HIDDEN; + } + + { + ARegion *ar_op = CTX_wm_region(C); + BLI_assert((ar_op == NULL) || (ar_op->regiontype != RGN_TYPE_HUD)); + struct HudRegionData *hrd = ar->regiondata; + if (hrd == NULL) { + hrd = MEM_callocN(sizeof(*hrd), __func__); + ar->regiondata = hrd; + } + if (ar_op) { + hrd->regionid = ar_op->regiontype; + } + else { + hrd->regionid = -1; + } + } + + /* XXX, should be handled in more general way. */ + ar->visible = !((ar->flag & RGN_FLAG_HIDDEN) || (ar->flag & RGN_FLAG_TOO_SMALL)); + + /* We shouldn't need to do this every time :S */ + /* XXX, this is evil! - it also makes the menu show on first draw. :( */ + hud_region_layout(C, ar); +} + +/** \} */ diff --git a/source/blender/editors/interface/interface_region_popover.c b/source/blender/editors/interface/interface_region_popover.c index c681cfe776f..fb14ca745c6 100644 --- a/source/blender/editors/interface/interface_region_popover.c +++ b/source/blender/editors/interface/interface_region_popover.c @@ -135,7 +135,7 @@ static uiBlock *ui_block_func_POPOVER(bContext *C, uiPopupBlockHandle *handle, v UI_block_region_set(block, handle->region); UI_block_layout_resolve(block, &width, &height); - UI_block_flag_enable(block, UI_BLOCK_MOVEMOUSE_QUIT | UI_BLOCK_KEEP_OPEN | UI_BLOCK_POPOVER); + UI_block_flag_enable(block, UI_BLOCK_KEEP_OPEN | UI_BLOCK_POPOVER); #ifdef USE_UI_POPOVER_ONCE if (pup->is_once) { UI_block_flag_enable(block, UI_BLOCK_POPOVER_ONCE); @@ -168,11 +168,17 @@ static uiBlock *ui_block_func_POPOVER(bContext *C, uiPopupBlockHandle *handle, v block->my = handle->prev_my; } - /* Prefer popover from header to be positioned into the editor. */ if (!slideout) { ScrArea *sa = CTX_wm_area(C); - if (sa && ED_area_header_alignment(sa) == RGN_ALIGN_BOTTOM) { - ARegion *ar = CTX_wm_region(C); + ARegion *ar = CTX_wm_region(C); + + if (ar && ar->panels.first) { + /* For regions with panels, prefer to open to top so we can + * see the values of the buttons below changing. */ + UI_block_direction_set(block, UI_DIR_UP | UI_DIR_CENTER_X); + } + else if (sa && ED_area_header_alignment(sa) == RGN_ALIGN_BOTTOM) { + /* Prefer popover from header to be positioned into the editor. */ if (ar && ar->regiontype == RGN_TYPE_HEADER) { UI_block_direction_set(block, UI_DIR_UP | UI_DIR_CENTER_X); } diff --git a/source/blender/editors/interface/interface_region_popup.c b/source/blender/editors/interface/interface_region_popup.c index 654dc5e4d30..0ac4d4d28ec 100644 --- a/source/blender/editors/interface/interface_region_popup.c +++ b/source/blender/editors/interface/interface_region_popup.c @@ -63,13 +63,13 @@ /** * Translate any popup regions (so we can drag them). */ -void ui_popup_translate(bContext *C, ARegion *ar, const int mdiff[2]) +void ui_popup_translate(ARegion *ar, const int mdiff[2]) { uiBlock *block; BLI_rcti_translate(&ar->winrct, UNPACK2(mdiff)); - ED_region_update_rect(C, ar); + ED_region_update_rect(ar); ED_region_tag_redraw(ar); @@ -625,7 +625,7 @@ uiBlock *ui_popup_block_refresh( ui_popup_block_scrolltest(block); /* adds subwindow */ - ED_region_init(C, ar); + ED_region_init(ar); /* get winmat now that we actually have the subwindow */ wmGetProjectionMatrix(block->winmat, &ar->winrct); @@ -633,7 +633,7 @@ uiBlock *ui_popup_block_refresh( /* notify change and redraw */ ED_region_tag_redraw(ar); - ED_region_update_rect(C, ar); + ED_region_update_rect(ar); #ifdef DEBUG window->eventstate = event_back; diff --git a/source/blender/editors/interface/interface_region_search.c b/source/blender/editors/interface/interface_region_search.c index f14f9af8785..e0dc149be17 100644 --- a/source/blender/editors/interface/interface_region_search.c +++ b/source/blender/editors/interface/interface_region_search.c @@ -404,8 +404,9 @@ static void ui_searchbox_region_draw_cb(const bContext *C, ARegion *ar) /* pixel space */ wmOrtho2_region_pixelspace(ar); - if (data->noback == false) - ui_draw_search_back(NULL, NULL, &data->bbox); /* style not used yet */ + if (data->noback == false) { + ui_draw_widget_back(UI_WTYPE_BOX, true, &data->bbox); + } /* draw text */ if (data->items.totitem) { @@ -625,7 +626,7 @@ ARegion *ui_searchbox_create_generic(bContext *C, ARegion *butregion, uiBut *but } /* adds subwindow */ - ED_region_init(C, ar); + ED_region_init(ar); /* notify change and redraw */ ED_region_tag_redraw(ar); @@ -681,8 +682,9 @@ static void ui_searchbox_region_draw_cb__operator(const bContext *UNUSED(C), ARe /* pixel space */ wmOrtho2_region_pixelspace(ar); - if (data->noback == false) - ui_draw_search_back(NULL, NULL, &data->bbox); /* style not used yet */ + if (data->noback == false) { + ui_draw_widget_back(UI_WTYPE_BOX, true, &data->bbox); + } /* draw text */ if (data->items.totitem) { diff --git a/source/blender/editors/interface/interface_region_tooltip.c b/source/blender/editors/interface/interface_region_tooltip.c index aa8fe173638..ed83a715c7e 100644 --- a/source/blender/editors/interface/interface_region_tooltip.c +++ b/source/blender/editors/interface/interface_region_tooltip.c @@ -867,7 +867,7 @@ static ARegion *ui_tooltip_create_with_data( } /* adds subwindow */ - ED_region_init(C, ar); + ED_region_init(ar); /* notify change and redraw */ ED_region_tag_redraw(ar); diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 9978726fa74..22487f29977 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -500,6 +500,7 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event) Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); ED_object_single_user(bmain, scene, (struct Object *)id); + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); DEG_relations_tag_update(bmain); } @@ -1578,12 +1579,16 @@ void uiTemplateOperatorRedoProperties(uiLayout *layout, const bContext *C) #endif if (WM_operator_repeat_check(C, op)) { + int layout_flags = 0; + if (block->panel == NULL) { + layout_flags = UI_TEMPLATE_OP_PROPS_SHOW_TITLE; + } #if 0 bool has_advanced = false; #endif UI_block_func_set(block, ED_undo_operator_repeat_cb, op, NULL); - template_operator_redo_property_buts_draw(C, op, layout, UI_TEMPLATE_OP_PROPS_COMPACT, NULL /* &has_advanced */ ); + template_operator_redo_property_buts_draw(C, op, layout, layout_flags, NULL /* &has_advanced */ ); UI_block_func_set(block, NULL, NULL, NULL); /* may want to reset to old state instead of NULLing all */ #if 0 @@ -2180,6 +2185,19 @@ void uiTemplateColorRamp(uiLayout *layout, PointerRNA *ptr, const char *propname MEM_freeN(cb); } +/********************* Icon Template ************************/ +/** + * \param icon_scale: Scale of the icon, 1x == button height. + */ +void uiTemplateIcon(uiLayout *layout, int icon_value, float icon_scale) +{ + uiBlock *block; + uiBut *but; + + block = uiLayoutAbsoluteBlock(layout); + but = uiDefIconBut(block, UI_BTYPE_LABEL, 0, ICON_X, 0, 0, UI_UNIT_X * icon_scale, UI_UNIT_Y * icon_scale, NULL, 0.0, 0.0, 0.0, 0.0, ""); + ui_def_but_icon(but, icon_value, UI_HAS_ICON | UI_BUT_ICON_PREVIEW); +} /********************* Icon viewer Template ************************/ typedef struct IconViewMenuArgs { @@ -2266,13 +2284,20 @@ void uiTemplateIconView(uiLayout *layout, PointerRNA *ptr, const char *propname, value = RNA_property_enum_get(ptr, prop); RNA_enum_icon_from_value(items, value, &icon); - cb_args = MEM_callocN(sizeof(IconViewMenuArgs), __func__); - cb_args->ptr = *ptr; - cb_args->prop = prop; - cb_args->show_labels = show_labels; - cb_args->icon_scale = icon_scale; - but = uiDefBlockButN(block, ui_icon_view_menu_cb, cb_args, "", 0, 0, UI_UNIT_X * 6, UI_UNIT_Y * 6, ""); + if (RNA_property_editable(ptr, prop)) { + cb_args = MEM_callocN(sizeof(IconViewMenuArgs), __func__); + cb_args->ptr = *ptr; + cb_args->prop = prop; + cb_args->show_labels = show_labels; + cb_args->icon_scale = icon_scale; + + but = uiDefBlockButN(block, ui_icon_view_menu_cb, cb_args, "", 0, 0, UI_UNIT_X * 6, UI_UNIT_Y * 6, ""); + } + else { + but = uiDefIconBut(block, UI_BTYPE_LABEL, 0, ICON_X, 0, 0, UI_UNIT_X * 6, UI_UNIT_Y * 6, NULL, 0.0, 0.0, 0.0, 0.0, ""); + } + ui_def_but_icon(but, icon, UI_HAS_ICON | UI_BUT_ICON_PREVIEW); @@ -3945,6 +3970,8 @@ eAutoPropButsReturn uiTemplateOperatorPropertyButs( RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr); + uiLayoutSetPropSep(layout, true); + /* main draw call */ return_info = uiDefAutoButsRNA(layout, &ptr, check_prop, label_align, (flag & UI_TEMPLATE_OP_PROPS_COMPACT)); diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index 3188bc847a7..c39e2f8a771 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -4423,6 +4423,7 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct case UI_BTYPE_SEPR: case UI_BTYPE_SEPR_LINE: + case UI_BTYPE_SEPR_SPACER: break; case UI_BTYPE_BUT: @@ -4915,30 +4916,41 @@ uiWidgetColors *ui_tooltip_get_theme(void) return wt->wcol_theme; } -void ui_draw_tooltip_background(uiStyle *UNUSED(style), uiBlock *UNUSED(block), rcti *rect) +/** + * Generic drawing for background. + */ +void ui_draw_widget_back_color( + uiWidgetTypeEnum type, bool use_shadow, const rcti *rect, + const float color[4]) { - uiWidgetType *wt = widget_type(UI_WTYPE_TOOLTIP); + uiWidgetType *wt = widget_type(type); + + if (use_shadow) { + glEnable(GL_BLEND); + widget_softshadow(rect, UI_CNR_ALL, 0.25f * U.widget_unit); + glDisable(GL_BLEND); + } + + rcti rect_copy = *rect; wt->state(wt, 0); - /* wt->draw ends up using same function to draw the tooltip as menu_back */ - wt->draw(&wt->wcol, rect, 0, 0); + if (color) { + rgba_float_to_uchar((unsigned char *)wt->wcol.inner, color); + } + wt->draw(&wt->wcol, &rect_copy, 0, UI_CNR_ALL); } - -void ui_draw_search_back(uiStyle *UNUSED(style), uiBlock *block, rcti *rect) +void ui_draw_widget_back(uiWidgetTypeEnum type, bool use_shadow, const rcti *rect) { - uiWidgetType *wt = widget_type(UI_WTYPE_BOX); - - glEnable(GL_BLEND); - widget_softshadow(rect, UI_CNR_ALL, 0.25f * U.widget_unit); - glDisable(GL_BLEND); + ui_draw_widget_back_color(type, use_shadow, rect, NULL); +} +void ui_draw_tooltip_background(uiStyle *UNUSED(style), uiBlock *UNUSED(block), rcti *rect) +{ + uiWidgetType *wt = widget_type(UI_WTYPE_TOOLTIP); wt->state(wt, 0); - if (block) - wt->draw(&wt->wcol, rect, block->flag, UI_CNR_ALL); - else - wt->draw(&wt->wcol, rect, 0, UI_CNR_ALL); + /* wt->draw ends up using same function to draw the tooltip as menu_back */ + wt->draw(&wt->wcol, rect, 0, 0); } - /* helper call to draw a menu item without button */ /* state: UI_ACTIVE or 0 */ void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, const char *name, int iconid, int state, bool use_sep) diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index 2a61be21589..fcbdcfbd02b 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -298,6 +298,8 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo cp = ts->syntaxr; break; case TH_WIRE_EDIT: cp = ts->wire_edit; break; + case TH_WIRE_INACTIVE: + cp = ts->wire_inactive; break; case TH_LAMP: cp = ts->lamp; break; case TH_SPEAKER: @@ -934,6 +936,7 @@ void ui_theme_init_default(void) rgba_char_args_set(btheme->tv3d.view_overlay, 0, 0, 0, 255); rgba_char_args_set(btheme->tv3d.wire, 0x0, 0x0, 0x0, 255); rgba_char_args_set(btheme->tv3d.wire_edit, 0x0, 0x0, 0x0, 255); + rgba_char_args_set(btheme->tv3d.wire_inactive, 32, 32, 32, 255); rgba_char_args_set(btheme->tv3d.lamp, 0, 0, 0, 40); rgba_char_args_set(btheme->tv3d.speaker, 0, 0, 0, 255); rgba_char_args_set(btheme->tv3d.camera, 0, 0, 0, 255); @@ -3046,6 +3049,17 @@ void init_userdef_do_versions(Main *bmain) } } + for (bTheme *btheme = U.themes.first; btheme; btheme = btheme->next) { + ThemeSpace *ts; + + for (ts = UI_THEMESPACE_START(btheme); ts != UI_THEMESPACE_END(btheme); ts++) { + if (btheme->tv3d.wire_inactive[3] == 0) { + rgba_char_args_set(btheme->tv3d.wire_inactive, 32, 32, 32, 255); + } + } + } + + if (U.pixelsize == 0.0f) U.pixelsize = 1.0f; diff --git a/source/blender/editors/lattice/editlattice_select.c b/source/blender/editors/lattice/editlattice_select.c index 2ba1dde243b..6f1c864130d 100644 --- a/source/blender/editors/lattice/editlattice_select.c +++ b/source/blender/editors/lattice/editlattice_select.c @@ -59,6 +59,8 @@ #include "WM_api.h" #include "WM_types.h" +#include "DEG_depsgraph.h" + #include "lattice_intern.h" /* -------------------------------------------------------------------- */ @@ -118,6 +120,7 @@ static int lattice_select_random_exec(bContext *C, wmOperator *op) BLI_rng_free(rng); + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } @@ -209,6 +212,7 @@ static int lattice_select_mirror_exec(bContext *C, wmOperator *op) } /* TODO, only notify changes */ + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } MEM_freeN(objects); @@ -295,6 +299,7 @@ static int lattice_select_more_less(bContext *C, const bool select) MEM_freeN(selpoints); + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); return OPERATOR_FINISHED; } @@ -411,6 +416,7 @@ static int lattice_select_all_exec(bContext *C, wmOperator *op) } break; } + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } MEM_freeN(objects); @@ -470,6 +476,7 @@ static int lattice_select_ungrouped_exec(bContext *C, wmOperator *op) } } + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); return OPERATOR_FINISHED; @@ -568,6 +575,7 @@ bool ED_lattice_select_pick(bContext *C, const int mval[2], bool extend, bool de lt->actbp = LT_ACTBP_NONE; } + DEG_id_tag_update(vc.obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data); return true; diff --git a/source/blender/editors/manipulator_library/manipulator_types/arrow3d_manipulator.c b/source/blender/editors/manipulator_library/manipulator_types/arrow3d_manipulator.c index 409a2c3ca83..8516b9d8244 100644 --- a/source/blender/editors/manipulator_library/manipulator_types/arrow3d_manipulator.c +++ b/source/blender/editors/manipulator_library/manipulator_types/arrow3d_manipulator.c @@ -92,6 +92,7 @@ static void arrow_draw_geom(const ArrowManipulator3D *arrow, const bool select, uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); bool unbind_shader = true; const int draw_style = RNA_enum_get(arrow->manipulator.ptr, "draw_style"); + const int draw_options = RNA_enum_get(arrow->manipulator.ptr, "draw_options"); immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); @@ -131,9 +132,13 @@ static void arrow_draw_geom(const ArrowManipulator3D *arrow, const bool select, {0.0f, 0.0f, arrow_length}, }; - glLineWidth(arrow->manipulator.line_width); - wm_manipulator_vec_draw(color, vec, ARRAY_SIZE(vec), pos, GWN_PRIM_LINE_STRIP); - + if (draw_options & ED_MANIPULATOR_ARROW_DRAW_FLAG_STEM) { + glLineWidth(arrow->manipulator.line_width); + wm_manipulator_vec_draw(color, vec, ARRAY_SIZE(vec), pos, GWN_PRIM_LINE_STRIP); + } + else { + immUniformColor4fv(color); + } /* *** draw arrow head *** */ @@ -303,9 +308,9 @@ static int manipulator_arrow_modal( /* set the property for the operator and call its modal function */ if (WM_manipulator_target_property_is_valid(mpr_prop)) { - const int draw_options = RNA_enum_get(arrow->manipulator.ptr, "draw_options"); - const bool constrained = (draw_options & ED_MANIPULATOR_ARROW_STYLE_CONSTRAINED) != 0; - const bool inverted = (draw_options & ED_MANIPULATOR_ARROW_STYLE_INVERTED) != 0; + const int transform_flag = RNA_enum_get(arrow->manipulator.ptr, "transform"); + const bool constrained = (transform_flag & ED_MANIPULATOR_ARROW_XFORM_FLAG_CONSTRAINED) != 0; + const bool inverted = (transform_flag & ED_MANIPULATOR_ARROW_XFORM_FLAG_INVERTED) != 0; const bool use_precision = (tweak_flag & WM_MANIPULATOR_TWEAK_PRECISE) != 0; float value = manipulator_value_from_offset(data, inter, ofs_new, constrained, inverted, use_precision); @@ -363,9 +368,9 @@ static int manipulator_arrow_invoke( static void manipulator_arrow_property_update(wmManipulator *mpr, wmManipulatorProperty *mpr_prop) { ArrowManipulator3D *arrow = (ArrowManipulator3D *)mpr; - const int draw_options = RNA_enum_get(arrow->manipulator.ptr, "draw_options"); - const bool constrained = (draw_options & ED_MANIPULATOR_ARROW_STYLE_CONSTRAINED) != 0; - const bool inverted = (draw_options & ED_MANIPULATOR_ARROW_STYLE_INVERTED) != 0; + const int transform_flag = RNA_enum_get(arrow->manipulator.ptr, "transform"); + const bool constrained = (transform_flag & ED_MANIPULATOR_ARROW_XFORM_FLAG_CONSTRAINED) != 0; + const bool inverted = (transform_flag & ED_MANIPULATOR_ARROW_XFORM_FLAG_INVERTED) != 0; manipulator_property_data_update(mpr, &arrow->data, mpr_prop, constrained, inverted); } @@ -448,21 +453,35 @@ static void MANIPULATOR_WT_arrow_3d(wmManipulatorType *wt) wt->struct_size = sizeof(ArrowManipulator3D); /* rna */ - static EnumPropertyItem rna_enum_draw_style[] = { + static EnumPropertyItem rna_enum_draw_style_items[] = { {ED_MANIPULATOR_ARROW_STYLE_NORMAL, "NORMAL", 0, "Normal", ""}, {ED_MANIPULATOR_ARROW_STYLE_CROSS, "CROSS", 0, "Cross", ""}, {ED_MANIPULATOR_ARROW_STYLE_BOX, "BOX", 0, "Box", ""}, {ED_MANIPULATOR_ARROW_STYLE_CONE, "CONE", 0, "Cone", ""}, {0, NULL, 0, NULL, NULL} }; - static EnumPropertyItem rna_enum_draw_options[] = { - {ED_MANIPULATOR_ARROW_STYLE_INVERTED, "INVERT", 0, "Inverted", ""}, - {ED_MANIPULATOR_ARROW_STYLE_CONSTRAINED, "CONSTRAIN", 0, "Constrained", ""}, + static EnumPropertyItem rna_enum_draw_options_items[] = { + {ED_MANIPULATOR_ARROW_DRAW_FLAG_STEM, "STEM", 0, "Stem", ""}, + {0, NULL, 0, NULL, NULL} + }; + static EnumPropertyItem rna_enum_transform_items[] = { + {ED_MANIPULATOR_ARROW_XFORM_FLAG_INVERTED, "INVERT", 0, "Inverted", ""}, + {ED_MANIPULATOR_ARROW_XFORM_FLAG_CONSTRAINED, "CONSTRAIN", 0, "Constrained", ""}, {0, NULL, 0, NULL, NULL} }; - RNA_def_enum(wt->srna, "draw_style", rna_enum_draw_style, ED_MANIPULATOR_ARROW_STYLE_NORMAL, "Draw Style", ""); - RNA_def_enum_flag(wt->srna, "draw_options", rna_enum_draw_options, 0, "Draw Options", ""); + RNA_def_enum( + wt->srna, "draw_style", rna_enum_draw_style_items, + ED_MANIPULATOR_ARROW_STYLE_NORMAL, + "Draw Style", ""); + RNA_def_enum_flag( + wt->srna, "draw_options", rna_enum_draw_options_items, + ED_MANIPULATOR_ARROW_DRAW_FLAG_STEM, + "Draw Options", ""); + RNA_def_enum_flag( + wt->srna, "transform", rna_enum_transform_items, + 0, + "Transform", ""); RNA_def_float(wt->srna, "length", 1.0f, 0.0f, FLT_MAX, "Arrow Line Length", "", 0.0f, FLT_MAX); RNA_def_float_vector(wt->srna, "aspect", 2, NULL, 0, FLT_MAX, "Aspect", "Cone/box style only", 0.0f, FLT_MAX); diff --git a/source/blender/editors/manipulator_library/manipulator_types/dial3d_manipulator.c b/source/blender/editors/manipulator_library/manipulator_types/dial3d_manipulator.c index a3034597f56..643a379cbb0 100644 --- a/source/blender/editors/manipulator_library/manipulator_types/dial3d_manipulator.c +++ b/source/blender/editors/manipulator_library/manipulator_types/dial3d_manipulator.c @@ -94,6 +94,9 @@ typedef struct DialInteraction { #define DIAL_WIDTH 1.0f #define DIAL_RESOLUTION 48 +/* Could make option, negative to clip more (don't show when view aligned). */ +#define DIAL_CLIP_BIAS 0.02 + /** * We can't use this for the #wmManipulatorType.matrix_basis_get callback, it conflicts with depth picking. */ @@ -347,6 +350,7 @@ static void manipulator_dial_draw_select(const bContext *C, wmManipulator *mpr, copy_v3_v3(clip_plane, rv3d->viewinv[2]); clip_plane[3] = -dot_v3v3(rv3d->viewinv[2], mpr->matrix_basis[3]); + clip_plane[3] += DIAL_CLIP_BIAS * mpr->scale_final; glEnable(GL_CLIP_DISTANCE0); } @@ -373,7 +377,7 @@ static void manipulator_dial_draw(const bContext *C, wmManipulator *mpr) copy_v3_v3(clip_plane, rv3d->viewinv[2]); clip_plane[3] = -dot_v3v3(rv3d->viewinv[2], mpr->matrix_basis[3]); - clip_plane[3] -= 0.02f * mpr->scale_final; + clip_plane[3] += DIAL_CLIP_BIAS * mpr->scale_final; glEnable(GL_CLIP_DISTANCE0); } diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c index 7e31b6a3774..cf4d8ebf05d 100644 --- a/source/blender/editors/mesh/editface.c +++ b/source/blender/editors/mesh/editface.c @@ -52,6 +52,8 @@ #include "GPU_draw.h" +#include "DEG_depsgraph.h" + /* own include */ /* copy the face flags, most importantly selection from the mesh to the final derived mesh, @@ -382,6 +384,7 @@ bool paintface_mouse_select(struct bContext *C, Object *ob, const int mval[2], b /* image window redraw */ paintface_flush_flags(ob, SELECT); + DEG_id_tag_update(ob->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data); ED_region_tag_redraw(CTX_wm_region(C)); // XXX - should redraw all 3D views return true; diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c index 3e787b2055a..b7d87949ddb 100644 --- a/source/blender/editors/mesh/editmesh_loopcut.c +++ b/source/blender/editors/mesh/editmesh_loopcut.c @@ -400,6 +400,7 @@ static void edgering_select(RingSelOpData *lcd) Object *ob_iter = lcd->objects[ob_index]; BMEditMesh *em = BKE_editmesh_from_object(ob_iter); EDBM_flag_disable_all(em, BM_ELEM_SELECT); + DEG_id_tag_update(ob_iter->data, DEG_TAG_SELECT_UPDATE); WM_main_add_notifier(NC_GEOM | ND_SELECT, ob_iter->data); } } @@ -496,6 +497,7 @@ static void ringsel_finish(bContext *C, wmOperator *op) BM_select_history_store(em->bm, lcd->eed); EDBM_selectmode_flush(lcd->em); + DEG_id_tag_update(lcd->ob->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, lcd->ob->data); } } diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index 634c65485e9..99a95c27b7b 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -1414,6 +1414,7 @@ static int edbm_select_similar_region_exec(bContext *C, wmOperator *op) MEM_freeN(group_index); if (changed) { + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } else { @@ -1621,6 +1622,7 @@ static int edbm_loop_multiselect_exec(bContext *C, wmOperator *op) MEM_freeN(edarray); // if (EM_texFaceCheck()) + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } MEM_freeN(objects); @@ -1824,6 +1826,7 @@ static bool mouse_mesh_loop(bContext *C, const int mval[2], bool extend, bool de } } + DEG_id_tag_update(vc.obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data); return true; @@ -1930,6 +1933,7 @@ static int edbm_select_all_exec(bContext *C, wmOperator *op) EDBM_selectmode_flush(em); break; } + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } @@ -1975,6 +1979,7 @@ static int edbm_faces_select_interior_exec(bContext *C, wmOperator *UNUSED(op)) continue; } + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } MEM_freeN(objects); @@ -2032,6 +2037,7 @@ bool EDBM_select_pick(bContext *C, const int mval[2], bool extend, bool deselect Object *ob_iter = objects[ob_index]; EDBM_flag_disable_all(BKE_editmesh_from_object(ob_iter), BM_ELEM_SELECT); if (basact->object != ob_iter) { + DEG_id_tag_update(ob_iter->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob_iter->data); } } @@ -2150,8 +2156,10 @@ bool EDBM_select_pick(bContext *C, const int mval[2], bool extend, bool deselect * switch UV layers, vgroups for eg. */ if (vc.view_layer->basact != basact) { vc.view_layer->basact = basact; + DEG_id_tag_update(&vc.scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, vc.scene); } + DEG_id_tag_update(vc.obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data); return true; @@ -2482,7 +2490,7 @@ bool EDBM_selectmode_toggle( Object *ob_iter = objects[ob_index]; BMEditMesh *em_iter = BKE_editmesh_from_object(ob_iter); EDBM_selectmode_set(em_iter); - DEG_id_tag_update(ob_iter->data, DEG_TAG_COPY_ON_WRITE); + DEG_id_tag_update(ob_iter->data, DEG_TAG_COPY_ON_WRITE | DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob_iter->data); } WM_main_add_notifier(NC_SCENE | ND_TOOLSETTINGS, NULL); @@ -2932,6 +2940,7 @@ static int edbm_select_linked_exec(bContext *C, wmOperator *op) select_linked_delimit_end(em); } + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } @@ -3143,6 +3152,7 @@ static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmE * index selections isn't very common. */ RNA_int_set(op->ptr, "index", index); + DEG_id_tag_update(basact->object->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, basact->object->data); return OPERATOR_FINISHED; @@ -3172,6 +3182,7 @@ static int edbm_select_linked_pick_exec(bContext *C, wmOperator *op) edbm_select_linked_pick_ex(em, ele, sel, delimit); + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); return OPERATOR_FINISHED; @@ -3260,6 +3271,7 @@ static int edbm_select_face_by_sides_exec(bContext *C, wmOperator *op) EDBM_selectmode_flush(em); + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } @@ -3357,6 +3369,7 @@ static int edbm_select_loose_exec(bContext *C, wmOperator *op) EDBM_selectmode_flush(em); + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } @@ -3420,6 +3433,8 @@ static int edbm_select_mirror_exec(bContext *C, wmOperator *op) if (tot_mirr_iter) { EDBM_selectmode_flush(em); + + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } @@ -3480,6 +3495,7 @@ static int edbm_select_more_exec(bContext *C, wmOperator *op) } EDBM_select_more(em, use_face_step); + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } @@ -3530,6 +3546,7 @@ static int edbm_select_less_exec(bContext *C, wmOperator *op) } EDBM_select_less(em, use_face_step); + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } @@ -3855,6 +3872,7 @@ static int edbm_select_sharp_edges_exec(bContext *C, wmOperator *op) else { EDBM_selectmode_flush(em); } + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } MEM_freeN(objects); @@ -3953,6 +3971,7 @@ static int edbm_select_linked_flat_faces_exec(bContext *C, wmOperator *op) BLI_LINKSTACK_FREE(stack); + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } MEM_freeN(objects); @@ -4049,6 +4068,7 @@ static int edbm_select_non_manifold_exec(bContext *C, wmOperator *op) } } + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); EDBM_selectmode_flush(em); @@ -4152,6 +4172,7 @@ static int edbm_select_random_exec(bContext *C, wmOperator *op) EDBM_deselect_flush(em); } + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } @@ -4246,6 +4267,7 @@ static int edbm_select_ungrouped_exec(bContext *C, wmOperator *op) if (changed) { EDBM_selectmode_flush(em); + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } } @@ -4418,6 +4440,7 @@ static int edbm_region_to_loop_exec(bContext *C, wmOperator *UNUSED(op)) EDBM_selectmode_to_scene(C); } + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } MEM_freeN(objects); @@ -4625,6 +4648,7 @@ static int edbm_loop_to_region_exec(bContext *C, wmOperator *op) EDBM_selectmode_flush(em); + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } MEM_freeN(objects); diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 17f643636cf..3fdca4562d1 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -98,13 +98,13 @@ static int edbm_subdivide_exec(bContext *C, wmOperator *op) const float fractal = RNA_float_get(op->ptr, "fractal") / 2.5f; const float along_normal = RNA_float_get(op->ptr, "fractal_along_normal"); - if (RNA_boolean_get(op->ptr, "quadtri") && + if (RNA_boolean_get(op->ptr, "ngon") && RNA_enum_get(op->ptr, "quadcorner") == SUBD_CORNER_STRAIGHT_CUT) { RNA_enum_set(op->ptr, "quadcorner", SUBD_CORNER_INNERVERT); } const int quad_corner_type = RNA_enum_get(op->ptr, "quadcorner"); - const bool use_quad_tri = RNA_boolean_get(op->ptr, "quadtri"); + const bool use_quad_tri = !RNA_boolean_get(op->ptr, "ngon"); const int seed = RNA_int_get(op->ptr, "seed"); ViewLayer *view_layer = CTX_data_view_layer(C); @@ -170,7 +170,7 @@ void MESH_OT_subdivide(wmOperatorType *ot) WM_operatortype_props_advanced_begin(ot); - RNA_def_boolean(ot->srna, "quadtri", 0, "Quad/Tri Mode", "Tries to prevent ngons"); + RNA_def_boolean(ot->srna, "ngon", true, "Create N-Gons", "When disabled, newly created faces are limited to 3-4 sided faces"); RNA_def_enum(ot->srna, "quadcorner", prop_mesh_cornervert_types, SUBD_CORNER_STRAIGHT_CUT, "Quad Corner Type", "How to subdivide quad corners (anything other than Straight Cut will prevent ngons)"); @@ -512,6 +512,7 @@ void MESH_OT_delete(wmOperatorType *ot) /* props */ ot->prop = RNA_def_enum(ot->srna, "type", prop_mesh_delete_types, MESH_DELETE_VERT, "Type", "Method used for deleting mesh data"); + RNA_def_property_flag(ot->prop, PROP_HIDDEN | PROP_SKIP_SAVE); } /** \} */ @@ -1030,7 +1031,7 @@ void MESH_OT_mark_seam(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; prop = RNA_def_boolean(ot->srna, "clear", 0, "Clear", ""); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); WM_operatortype_props_advanced_begin(ot); } @@ -1103,7 +1104,7 @@ void MESH_OT_mark_sharp(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; prop = RNA_def_boolean(ot->srna, "clear", false, "Clear", ""); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); prop = RNA_def_boolean(ot->srna, "use_verts", false, "Vertices", "Consider vertices instead of edges to select which edges to (un)tag as sharp"); RNA_def_property_flag(prop, PROP_SKIP_SAVE); @@ -3641,7 +3642,7 @@ static Base *mesh_separate_tagged(Main *bmain, Scene *scene, ViewLayer *view_lay BM_mesh_normals_update(bm_new); - BM_mesh_bm_to_me(bm_new, base_new->object->data, (&(struct BMeshToMeshParams){0})); + BM_mesh_bm_to_me(bmain, bm_new, base_new->object->data, (&(struct BMeshToMeshParams){0})); BM_mesh_free(bm_new); ((Mesh *)base_new->object->data)->edit_btmesh = NULL; @@ -3954,7 +3955,7 @@ static int edbm_separate_exec(bContext *C, wmOperator *op) if (retval_iter) { BM_mesh_bm_to_me( - bm_old, me, + bmain, bm_old, me, (&(struct BMeshToMeshParams){ .calc_object_remap = true, })); @@ -6829,7 +6830,7 @@ void MESH_OT_mark_freestyle_edge(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; prop = RNA_def_boolean(ot->srna, "clear", false, "Clear", ""); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } /** \} */ @@ -6912,7 +6913,7 @@ void MESH_OT_mark_freestyle_face(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; prop = RNA_def_boolean(ot->srna, "clear", false, "Clear", ""); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } /** \} */ diff --git a/source/blender/editors/mesh/editmesh_undo.c b/source/blender/editors/mesh/editmesh_undo.c index 4d4b7a098b0..97445ebc9e0 100644 --- a/source/blender/editors/mesh/editmesh_undo.c +++ b/source/blender/editors/mesh/editmesh_undo.c @@ -511,8 +511,8 @@ static void *undomesh_from_editmesh(UndoMesh *um, BMEditMesh *em, Key *key) /* BM_mesh_validate(em->bm); */ /* for troubleshooting */ BM_mesh_bm_to_me( - em->bm, &um->me, (&(struct BMeshToMeshParams){ - /* Undo code should not be manipulating 'G.main->object' hooks/vertex-parent. */ + NULL, em->bm, &um->me, (&(struct BMeshToMeshParams){ + /* Undo code should not be manipulating 'G_MAIN->object' hooks/vertex-parent. */ .calc_object_remap = false, .cd_mask_extra = CD_MASK_SHAPE_KEYINDEX, })); diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c index ab44e017fc6..e18758a5a58 100644 --- a/source/blender/editors/mesh/editmesh_utils.c +++ b/source/blender/editors/mesh/editmesh_utils.c @@ -43,6 +43,7 @@ #include "BKE_DerivedMesh.h" #include "BKE_context.h" +#include "BKE_main.h" #include "BKE_mesh.h" #include "BKE_mesh_mapping.h" #include "BKE_report.h" @@ -172,6 +173,10 @@ bool EDBM_op_finish(BMEditMesh *em, BMOperator *bmop, wmOperator *op, const bool BKE_editmesh_tessface_calc(em); } + if (em->ob) { + DEG_id_tag_update(&((Mesh *)em->ob->data)->id, DEG_TAG_COPY_ON_WRITE); + } + return false; } else { @@ -326,7 +331,7 @@ void EDBM_mesh_make(Object *ob, const int select_mode, const bool add_key_index) * \warning This can invalidate the #DerivedMesh cache of other objects (for linked duplicates). * Most callers should run #DEG_id_tag_update on \a ob->data, see: T46738, T46913 */ -void EDBM_mesh_load(Object *ob) +void EDBM_mesh_load(Main *bmain, Object *ob) { Mesh *me = ob->data; BMesh *bm = me->edit_btmesh->bm; @@ -338,7 +343,7 @@ void EDBM_mesh_load(Object *ob) } BM_mesh_bm_to_me( - bm, me, (&(struct BMeshToMeshParams){ + bmain, bm, me, (&(struct BMeshToMeshParams){ .calc_object_remap = true, })); diff --git a/source/blender/editors/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.c index d2410c7d97b..46b84f328cc 100644 --- a/source/blender/editors/mesh/mesh_data.c +++ b/source/blender/editors/mesh/mesh_data.c @@ -538,6 +538,7 @@ void MESH_OT_uv_texture_add(wmOperatorType *ot) static int drop_named_image_invoke(bContext *C, wmOperator *op, const wmEvent *event) { + Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); View3D *v3d = CTX_wm_view3d(C); Base *base; @@ -578,7 +579,7 @@ static int drop_named_image_invoke(bContext *C, wmOperator *op, const wmEvent *e return OPERATOR_CANCELLED; if (exitmode) { - EDBM_mesh_load(obedit); + EDBM_mesh_load(bmain, obedit); EDBM_mesh_free(me->edit_btmesh); MEM_freeN(me->edit_btmesh); me->edit_btmesh = NULL; diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c index 41e1ca13b79..6c8de1a481e 100644 --- a/source/blender/editors/mesh/meshtools.c +++ b/source/blender/editors/mesh/meshtools.c @@ -373,7 +373,7 @@ int join_mesh_exec(bContext *C, wmOperator *op) } else if (haskey) { /* add a new key-block and add to the mesh */ - key = me->key = BKE_key_add((ID *)me); + key = me->key = BKE_key_add(bmain, (ID *)me); key->type = KEY_RELATIVE; } @@ -593,6 +593,7 @@ int join_mesh_exec(bContext *C, wmOperator *op) DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA); + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); return OPERATOR_FINISHED; @@ -605,6 +606,7 @@ int join_mesh_exec(bContext *C, wmOperator *op) int join_mesh_shapes_exec(bContext *C, wmOperator *op) { + Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); Object *ob = CTX_data_active_object(C); Depsgraph *depsgraph = CTX_data_depsgraph(C); @@ -639,7 +641,7 @@ int join_mesh_shapes_exec(bContext *C, wmOperator *op) } if (key == NULL) { - key = me->key = BKE_key_add((ID *)me); + key = me->key = BKE_key_add(bmain, (ID *)me); key->type = KEY_RELATIVE; /* first key added, so it was the basis. initialize it with the existing mesh */ @@ -670,6 +672,7 @@ int join_mesh_shapes_exec(bContext *C, wmOperator *op) } CTX_DATA_END; + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); return OPERATOR_FINISHED; diff --git a/source/blender/editors/metaball/mball_edit.c b/source/blender/editors/metaball/mball_edit.c index 65bf258f334..aea125ce4b9 100644 --- a/source/blender/editors/metaball/mball_edit.c +++ b/source/blender/editors/metaball/mball_edit.c @@ -154,6 +154,7 @@ static int mball_select_all_exec(bContext *C, wmOperator *op) break; } + DEG_id_tag_update(&mb->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, mb); return OPERATOR_FINISHED; @@ -335,6 +336,7 @@ static int mball_select_similar_exec(bContext *C, wmOperator *op) } if (changed) { + DEG_id_tag_update(&mb->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, mb); } @@ -403,6 +405,7 @@ static int select_random_metaelems_exec(bContext *C, wmOperator *op) BLI_rng_free(rng); + DEG_id_tag_update(&mb->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, mb); } MEM_freeN(objects); @@ -670,6 +673,7 @@ bool ED_mball_select_pick(bContext *C, const int mval[2], bool extend, bool dese mb->lastelem = ml_act; + DEG_id_tag_update(&mb->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, mb); return true; diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index 37589177037..dd358b95722 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -931,6 +931,7 @@ static int empty_drop_named_image_invoke(bContext *C, wmOperator *op, const wmEv /* if empty under cursor, then set object */ if (base && base->object->type == OB_EMPTY) { ob = base->object; + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); } else { @@ -1098,6 +1099,7 @@ static int collection_instance_add_exec(bContext *C, wmOperator *op) DEG_relations_tag_update(bmain); DEG_id_tag_update(&collection->id, 0); + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); return OPERATOR_FINISHED; @@ -1294,6 +1296,7 @@ static int object_delete_exec(bContext *C, wmOperator *op) DEG_relations_tag_update(bmain); + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene); } @@ -1635,10 +1638,10 @@ static void convert_ensure_curve_cache(Depsgraph *depsgraph, Scene *scene, Objec } } -static void curvetomesh(Depsgraph *depsgraph, Scene *scene, Object *ob) +static void curvetomesh(Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *ob) { convert_ensure_curve_cache(depsgraph, scene, ob); - BKE_mesh_from_nurbs(ob); /* also does users */ + BKE_mesh_from_nurbs(bmain, ob); /* also does users */ if (ob->type == OB_MESH) { BKE_object_free_modifiers(ob, 0); @@ -1785,7 +1788,7 @@ static int convert_exec(bContext *C, wmOperator *op) newob = ob; } - BKE_mesh_to_curve(depsgraph, scene, newob); + BKE_mesh_to_curve(bmain, depsgraph, scene, newob); if (newob->type == OB_CURVE) { BKE_object_free_modifiers(newob, 0); /* after derivedmesh calls! */ @@ -1846,7 +1849,7 @@ static int convert_exec(bContext *C, wmOperator *op) * datablock, but for until we've got granular update * lets take care by selves. */ - BKE_vfont_to_curve(bmain, newob, FO_EDIT); + BKE_vfont_to_curve(newob, FO_EDIT); newob->type = OB_CURVE; cu->type = OB_CURVE; @@ -1887,7 +1890,7 @@ static int convert_exec(bContext *C, wmOperator *op) BKE_curve_curve_dimension_update(cu); if (target == OB_MESH) { - curvetomesh(depsgraph, scene, newob); + curvetomesh(bmain, depsgraph, scene, newob); /* meshes doesn't use displist */ BKE_object_free_curve_cache(newob); @@ -1911,7 +1914,7 @@ static int convert_exec(bContext *C, wmOperator *op) newob = ob; } - curvetomesh(depsgraph, scene, newob); + curvetomesh(bmain, depsgraph, scene, newob); /* meshes doesn't use displist */ BKE_object_free_curve_cache(newob); @@ -2018,6 +2021,7 @@ static int convert_exec(bContext *C, wmOperator *op) } DEG_relations_tag_update(bmain); + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, scene); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); @@ -2098,7 +2102,7 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, ViewLayer /* duplicates using userflags */ if (dupflag & USER_DUP_ACT) { - BKE_animdata_copy_id_action(&obn->id, true); + BKE_animdata_copy_id_action(bmain, &obn->id, true); } if (dupflag & USER_DUP_MAT) { @@ -2112,7 +2116,7 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, ViewLayer id_us_min(id); if (dupflag & USER_DUP_ACT) { - BKE_animdata_copy_id_action(&obn->mat[a]->id, true); + BKE_animdata_copy_id_action(bmain, &obn->mat[a]->id, true); } } } @@ -2128,7 +2132,7 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, ViewLayer } if (dupflag & USER_DUP_ACT) { - BKE_animdata_copy_id_action(&psys->part->id, true); + BKE_animdata_copy_id_action(bmain, &psys->part->id, true); } id_us_min(id); @@ -2256,9 +2260,9 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, ViewLayer } if (dupflag & USER_DUP_ACT) { - BKE_animdata_copy_id_action((ID *)obn->data, true); + BKE_animdata_copy_id_action(bmain, (ID *)obn->data, true); if (key) { - BKE_animdata_copy_id_action((ID *)key, true); + BKE_animdata_copy_id_action(bmain, (ID *)key, true); } } @@ -2353,8 +2357,7 @@ static int duplicate_exec(bContext *C, wmOperator *op) BKE_main_id_clear_newpoins(bmain); DEG_relations_tag_update(bmain); - /* TODO(sergey): Use proper flag for tagging here. */ - DEG_id_tag_update(&scene->id, 0); + DEG_id_tag_update(&scene->id, DEG_TAG_COPY_ON_WRITE | DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); @@ -2436,6 +2439,7 @@ static int add_named_exec(bContext *C, wmOperator *op) /* TODO(sergey): Only update relations for the current scene. */ DEG_relations_tag_update(bmain); + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index d47a2576a8a..45ad4bfd196 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -191,7 +191,7 @@ static bool ED_object_editmode_load_ex(Main *bmain, Object *obedit, const bool f return false; } - EDBM_mesh_load(obedit); + EDBM_mesh_load(bmain, obedit); if (freedata) { EDBM_mesh_free(me->edit_btmesh); @@ -473,7 +473,7 @@ static int editmode_toggle_exec(bContext *C, wmOperator *op) } } - ED_space_image_uv_sculpt_update(CTX_wm_manager(C), scene); + ED_space_image_uv_sculpt_update(bmain, CTX_wm_manager(C), scene); WM_msg_publish_rna_prop(mbus, &obact->id, obact, Object, mode); @@ -1631,7 +1631,7 @@ static int move_to_collection_exec(bContext *C, wmOperator *op) collection->id.name + 2); DEG_relations_tag_update(CTX_data_main(C)); - DEG_id_tag_update(&scene->id, 0); + DEG_id_tag_update(&scene->id, DEG_TAG_COPY_ON_WRITE | DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene); WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); diff --git a/source/blender/editors/object/object_hook.c b/source/blender/editors/object/object_hook.c index 31e8685e323..6a3cb9aa097 100644 --- a/source/blender/editors/object/object_hook.c +++ b/source/blender/editors/object/object_hook.c @@ -318,7 +318,7 @@ static bool object_hook_index_array(Main *bmain, Scene *scene, Object *obedit, BMEditMesh *em; - EDBM_mesh_load(obedit); + EDBM_mesh_load(bmain, obedit); EDBM_mesh_make(obedit, scene->toolsettings->selectmode, true); DEG_id_tag_update(obedit->data, 0); @@ -619,6 +619,7 @@ static int object_add_hook_newob_exec(bContext *C, wmOperator *op) Object *obedit = CTX_data_edit_object(C); if (add_hook_object(C, bmain, scene, view_layer, obedit, NULL, OBJECT_ADDHOOK_NEWOB, op->reports)) { + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, obedit); return OPERATOR_FINISHED; @@ -889,6 +890,7 @@ static int object_hook_select_exec(bContext *C, wmOperator *op) /* select functionality */ object_hook_select(ob, hmd); + DEG_id_tag_update(ob->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data); return OPERATOR_FINISHED; diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index 71c9cb3eb69..dae9d3e254b 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -121,7 +121,7 @@ ModifierData *ED_object_modifier_add(ReportList *reports, Main *bmain, Scene *sc /* don't need to worry about the new modifier's name, since that is set to the number * of particle systems which shouldn't have too many duplicates */ - new_md = object_add_particle_system(scene, ob, name); + new_md = object_add_particle_system(bmain, scene, ob, name); } else { /* get new modifier data to add */ @@ -526,7 +526,8 @@ int ED_object_modifier_convert(ReportList *UNUSED(reports), Main *bmain, Scene * return 1; } -static int modifier_apply_shape(ReportList *reports, Depsgraph *depsgraph, Scene *scene, Object *ob, ModifierData *md) +static int modifier_apply_shape( + Main *bmain, ReportList *reports, Depsgraph *depsgraph, Scene *scene, Object *ob, ModifierData *md) { const ModifierTypeInfo *mti = modifierType_getInfo(md->type); @@ -566,7 +567,7 @@ static int modifier_apply_shape(ReportList *reports, Depsgraph *depsgraph, Scene } if (key == NULL) { - key = me->key = BKE_key_add((ID *)me); + key = me->key = BKE_key_add(bmain, (ID *)me); key->type = KEY_RELATIVE; /* if that was the first key block added, then it was the basis. * Initialize it with the mesh, and add another for the modifier */ @@ -675,7 +676,7 @@ static int modifier_apply_obdata(ReportList *reports, Depsgraph *depsgraph, Scen } int ED_object_modifier_apply( - ReportList *reports, Depsgraph *depsgraph, + Main *bmain, ReportList *reports, Depsgraph *depsgraph, Scene *scene, Object *ob, ModifierData *md, int mode) { int prev_mode; @@ -704,7 +705,7 @@ int ED_object_modifier_apply( md->mode |= eModifierMode_Realtime; if (mode == MODIFIER_APPLY_SHAPE) { - if (!modifier_apply_shape(reports, depsgraph, scene, ob, md)) { + if (!modifier_apply_shape(bmain, reports, depsgraph, scene, ob, md)) { md->mode = prev_mode; return 0; } @@ -1019,13 +1020,14 @@ void OBJECT_OT_modifier_move_down(wmOperatorType *ot) static int modifier_apply_exec(bContext *C, wmOperator *op) { + Main *bmain = CTX_data_main(C); Depsgraph *depsgraph = CTX_data_depsgraph(C); Scene *scene = CTX_data_scene(C); Object *ob = ED_object_active_context(C); ModifierData *md = edit_modifier_property_get(op, ob, 0); int apply_as = RNA_enum_get(op->ptr, "apply_as"); - if (!md || !ED_object_modifier_apply(op->reports, depsgraph, scene, ob, md, apply_as)) { + if (!md || !ED_object_modifier_apply(bmain, op->reports, depsgraph, scene, ob, md, apply_as)) { return OPERATOR_CANCELLED; } diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index 4f441826bfd..a114b2cc6d5 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -145,7 +145,7 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op) Mesh *me = obedit->data; BMEditMesh *em; - EDBM_mesh_load(obedit); + EDBM_mesh_load(bmain, obedit); EDBM_mesh_make(obedit, scene->toolsettings->selectmode, true); DEG_id_tag_update(obedit->data, 0); @@ -1786,7 +1786,7 @@ static void single_obdata_users(Main *bmain, Scene *scene, ViewLayer *view_layer /* Needed to remap texcomesh below. */ me = ob->data = ID_NEW_SET(ob->data, BKE_mesh_copy(bmain, ob->data)); if (me->key) /* We do not need to set me->key->id.newid here... */ - BKE_animdata_copy_id_action((ID *)me->key, false); + BKE_animdata_copy_id_action(bmain, (ID *)me->key, false); break; case OB_MBALL: ob->data = ID_NEW_SET(ob->data, BKE_mball_copy(bmain, ob->data)); @@ -1798,12 +1798,12 @@ static void single_obdata_users(Main *bmain, Scene *scene, ViewLayer *view_layer ID_NEW_REMAP(cu->bevobj); ID_NEW_REMAP(cu->taperobj); if (cu->key) /* We do not need to set cu->key->id.newid here... */ - BKE_animdata_copy_id_action((ID *)cu->key, false); + BKE_animdata_copy_id_action(bmain, (ID *)cu->key, false); break; case OB_LATTICE: ob->data = lat = ID_NEW_SET(ob->data, BKE_lattice_copy(bmain, ob->data)); if (lat->key) /* We do not need to set lat->key->id.newid here... */ - BKE_animdata_copy_id_action((ID *)lat->key, false); + BKE_animdata_copy_id_action(bmain, (ID *)lat->key, false); break; case OB_ARMATURE: DEG_id_tag_update(&ob->id, OB_RECALC_DATA); @@ -1830,7 +1830,7 @@ static void single_obdata_users(Main *bmain, Scene *scene, ViewLayer *view_layer * AnimData structure, which is not what we want. * (sergey) */ - BKE_animdata_copy_id_action((ID *)ob->data, false); + BKE_animdata_copy_id_action(bmain, (ID *)ob->data, false); id_us_min(id); } @@ -1845,13 +1845,13 @@ static void single_obdata_users(Main *bmain, Scene *scene, ViewLayer *view_layer } } -static void single_object_action_users(Scene *scene, ViewLayer *view_layer, const int flag) +static void single_object_action_users(Main *bmain, Scene *scene, ViewLayer *view_layer, const int flag) { FOREACH_OBJECT_FLAG_BEGIN(scene, view_layer, flag, ob) { if (!ID_IS_LINKED(ob)) { DEG_id_tag_update(&ob->id, OB_RECALC_DATA); - BKE_animdata_copy_id_action(&ob->id, false); + BKE_animdata_copy_id_action(bmain, &ob->id, false); } } FOREACH_OBJECT_FLAG_END; @@ -1872,7 +1872,7 @@ static void single_mat_users(Main *bmain, Scene *scene, ViewLayer *view_layer, c if (ma->id.us > 1) { man = BKE_material_copy(bmain, ma); - BKE_animdata_copy_id_action(&man->id, false); + BKE_animdata_copy_id_action(bmain, &man->id, false); man->id.us = 0; assign_material(bmain, ob, man, a, BKE_MAT_ASSIGN_USERPREF); @@ -1916,7 +1916,7 @@ void ED_object_single_users(Main *bmain, Scene *scene, const bool full, const bo if (full) { single_obdata_users(bmain, scene, NULL, 0); - single_object_action_users(scene, NULL, 0); + single_object_action_users(bmain, scene, NULL, 0); single_mat_users_expand(bmain); } @@ -2457,7 +2457,7 @@ static int make_single_user_exec(bContext *C, wmOperator *op) } if (RNA_boolean_get(op->ptr, "animation")) { - single_object_action_users(scene, view_layer, flag); + single_object_action_users(bmain, scene, view_layer, flag); } BKE_main_id_clear_newpoins(bmain); diff --git a/source/blender/editors/object/object_select.c b/source/blender/editors/object/object_select.c index bac1ba0e37d..ce29125ac79 100644 --- a/source/blender/editors/object/object_select.c +++ b/source/blender/editors/object/object_select.c @@ -129,6 +129,7 @@ void ED_object_base_activate(bContext *C, Base *base) else { WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, NULL); } + DEG_id_tag_update(&CTX_data_scene(C)->id, DEG_TAG_SELECT_UPDATE); } /********************** Selection Operators **********************/ @@ -172,7 +173,9 @@ static int object_select_by_type_exec(bContext *C, wmOperator *op) } CTX_DATA_END; - WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C)); + Scene *scene = CTX_data_scene(C); + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); return OPERATOR_FINISHED; } @@ -365,7 +368,9 @@ void ED_object_select_linked_by_id(bContext *C, ID *id) } if (changed) { - WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C)); + Scene *scene = CTX_data_scene(C); + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); } } @@ -439,6 +444,7 @@ static int object_select_linked_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; if (changed) { + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); return OPERATOR_FINISHED; } @@ -809,6 +815,7 @@ static int object_select_grouped_exec(bContext *C, wmOperator *op) } if (changed) { + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); return OPERATOR_FINISHED; } @@ -878,7 +885,9 @@ static int object_select_all_exec(bContext *C, wmOperator *op) } CTX_DATA_END; - WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C)); + Scene *scene = CTX_data_scene(C); + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); return OPERATOR_FINISHED; } @@ -930,7 +939,9 @@ static int object_select_same_collection_exec(bContext *C, wmOperator *op) } CTX_DATA_END; - WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C)); + Scene *scene = CTX_data_scene(C); + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); return OPERATOR_FINISHED; } @@ -986,6 +997,7 @@ static int object_select_mirror_exec(bContext *C, wmOperator *op) CTX_DATA_END; /* undo? */ + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); return OPERATOR_FINISHED; @@ -1073,7 +1085,9 @@ static int object_select_more_exec(bContext *C, wmOperator *UNUSED(op)) bool changed = object_select_more_less(C, true); if (changed) { - WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C)); + Scene *scene = CTX_data_scene(C); + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); return OPERATOR_FINISHED; } else { @@ -1101,7 +1115,9 @@ static int object_select_less_exec(bContext *C, wmOperator *UNUSED(op)) bool changed = object_select_more_less(C, false); if (changed) { - WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C)); + Scene *scene = CTX_data_scene(C); + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); return OPERATOR_FINISHED; } else { @@ -1147,7 +1163,9 @@ static int object_select_random_exec(bContext *C, wmOperator *op) BLI_rng_free(rng); - WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C)); + Scene *scene = CTX_data_scene(C); + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/object/object_shapekey.c b/source/blender/editors/object/object_shapekey.c index 03fe6e9de65..4f985293ec3 100644 --- a/source/blender/editors/object/object_shapekey.c +++ b/source/blender/editors/object/object_shapekey.c @@ -78,8 +78,9 @@ static void ED_object_shape_key_add(bContext *C, Object *ob, const bool from_mix) { + Main *bmain = CTX_data_main(C); KeyBlock *kb; - if ((kb = BKE_object_shapekey_insert(ob, NULL, from_mix))) { + if ((kb = BKE_object_shapekey_insert(bmain, ob, NULL, from_mix))) { Key *key = BKE_key_from_object(ob); /* for absolute shape keys, new keys may not be added last */ ob->shapenr = BLI_findindex(&key->block, kb) + 1; diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c index 84786024160..a6f688c49fb 100644 --- a/source/blender/editors/object/object_vgroup.c +++ b/source/blender/editors/object/object_vgroup.c @@ -2820,6 +2820,7 @@ static int vertex_group_select_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_CANCELLED; vgroup_select_verts(ob, 1); + DEG_id_tag_update(ob->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data); return OPERATOR_FINISHED; @@ -2845,6 +2846,7 @@ static int vertex_group_deselect_exec(bContext *C, wmOperator *UNUSED(op)) Object *ob = ED_object_context(C); vgroup_select_verts(ob, 0); + DEG_id_tag_update(ob->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data); return OPERATOR_FINISHED; diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c index 359e9365ea7..eeb14951d43 100644 --- a/source/blender/editors/physics/particle_edit.c +++ b/source/blender/editors/physics/particle_edit.c @@ -56,6 +56,7 @@ #include "BKE_global.h" #include "BKE_object.h" #include "BKE_library.h" +#include "BKE_main.h" #include "BKE_mesh.h" #include "BKE_mesh_runtime.h" #include "BKE_modifier.h" @@ -117,7 +118,7 @@ int PE_hair_poll(bContext *C) if (!scene || !ob || !(ob->mode & OB_MODE_PARTICLE_EDIT)) { return 0; } - edit= PE_get_current(scene, ob); + edit = PE_get_current(scene, ob); return (edit && edit->psys); } @@ -364,6 +365,7 @@ typedef struct PEData { ViewContext vc; const bContext *context; + Main *bmain; Scene *scene; ViewLayer *view_layer; Object *ob; @@ -400,6 +402,7 @@ static void PE_set_data(bContext *C, PEData *data) { memset(data, 0, sizeof(*data)); + data->bmain = CTX_data_main(C); data->scene = CTX_data_scene(C); data->view_layer = CTX_data_view_layer(C); data->ob = CTX_data_active_object(C); @@ -1638,8 +1641,6 @@ static int select_random_exec(bContext *C, wmOperator *op) { PEData data; int type; - Scene *scene; - Object *ob; /* used by LOOP_VISIBLE_POINTS, LOOP_VISIBLE_KEYS and LOOP_KEYS */ PTCacheEdit *edit; @@ -1657,9 +1658,7 @@ static int select_random_exec(bContext *C, wmOperator *op) PE_set_data(C, &data); data.select_action = SEL_SELECT; - scene = CTX_data_scene(C); - ob = CTX_data_active_object(C); - edit = PE_get_current(scene, ob); + edit = PE_get_current(data.scene, data.ob); rng = BLI_rng_new_srandom(seed); @@ -4079,8 +4078,11 @@ static int brush_edit_modal(bContext *C, wmOperator *op, const wmEvent *event) case LEFTMOUSE: case MIDDLEMOUSE: case RIGHTMOUSE: // XXX hardcoded - brush_edit_exit(op); - return OPERATOR_FINISHED; + if (event->val == KM_RELEASE) { + brush_edit_exit(op); + return OPERATOR_FINISHED; + } + break; case MOUSEMOVE: brush_edit_apply_event(C, op, event); break; @@ -4678,7 +4680,6 @@ static int unify_length_exec(bContext *C, wmOperator *UNUSED(op)) } scale_points_to_length(edit, average_length); - PE_update_object(depsgraph, scene, ob, 1); if (edit->psys) { WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob); diff --git a/source/blender/editors/physics/particle_edit_undo.c b/source/blender/editors/physics/particle_edit_undo.c index 6576d692f70..fdf765e4557 100644 --- a/source/blender/editors/physics/particle_edit_undo.c +++ b/source/blender/editors/physics/particle_edit_undo.c @@ -44,9 +44,9 @@ #include "BLI_string.h" #include "BLI_utildefines.h" +#include "BKE_context.h" #include "BKE_particle.h" #include "BKE_pointcache.h" -#include "BKE_context.h" #include "BKE_undo_system.h" #include "DEG_depsgraph.h" diff --git a/source/blender/editors/physics/particle_object.c b/source/blender/editors/physics/particle_object.c index fbccdcfcdba..8a9eb369e66 100644 --- a/source/blender/editors/physics/particle_object.c +++ b/source/blender/editors/physics/particle_object.c @@ -82,13 +82,14 @@ static float I[4][4] = {{1.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f, 0.0f}, {0.0 static int particle_system_add_exec(bContext *C, wmOperator *UNUSED(op)) { + Main *bmain = CTX_data_main(C); Object *ob= ED_object_context(C); Scene *scene = CTX_data_scene(C); if (!scene || !ob) return OPERATOR_CANCELLED; - object_add_particle_system(scene, ob, NULL); + object_add_particle_system(bmain, scene, ob, NULL); WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob); WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, ob); @@ -113,6 +114,7 @@ void OBJECT_OT_particle_system_add(wmOperatorType *ot) static int particle_system_remove_exec(bContext *C, wmOperator *UNUSED(op)) { + Main *bmain = CTX_data_main(C); Object *ob = ED_object_context(C); Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); @@ -122,7 +124,7 @@ static int particle_system_remove_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_CANCELLED; mode_orig = ob->mode; - object_remove_particle_system(scene, ob); + object_remove_particle_system(bmain, scene, ob); /* possible this isn't the active object * object_remove_particle_system() clears the mode on the last psys diff --git a/source/blender/editors/physics/physics_pointcache.c b/source/blender/editors/physics/physics_pointcache.c index 45172774d55..a66dbfc789d 100644 --- a/source/blender/editors/physics/physics_pointcache.c +++ b/source/blender/editors/physics/physics_pointcache.c @@ -164,7 +164,7 @@ static PTCacheBaker *ptcache_baker_create(bContext *C, wmOperator *op, bool all) { PTCacheBaker *baker = MEM_callocN(sizeof(PTCacheBaker), "PTCacheBaker"); - baker->main = CTX_data_main(C); + baker->bmain = CTX_data_main(C); baker->scene = CTX_data_scene(C); baker->view_layer = CTX_data_view_layer(C); baker->depsgraph = CTX_data_depsgraph(C); diff --git a/source/blender/editors/physics/rigidbody_object.c b/source/blender/editors/physics/rigidbody_object.c index 99976898ac1..c2bcb55c3bb 100644 --- a/source/blender/editors/physics/rigidbody_object.c +++ b/source/blender/editors/physics/rigidbody_object.c @@ -110,6 +110,7 @@ bool ED_rigidbody_object_add(Main *bmain, Scene *scene, Object *ob, int type, Re } if (rbw->group == NULL) { rbw->group = BKE_collection_add(bmain, NULL, "RigidBodyWorld"); + id_fake_user_set(&rbw->group->id); } /* make rigidbody object settings */ diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index 2d65b361f99..d990f0b34d0 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -332,8 +332,8 @@ static int screen_render_exec(bContext *C, wmOperator *op) G.is_break = false; RE_test_break_cb(re, NULL, render_break); - ima = BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result"); - BKE_image_signal(ima, NULL, IMA_SIGNAL_FREE); + ima = BKE_image_verify_viewer(mainp, IMA_TYPE_R_RESULT, "Render Result"); + BKE_image_signal(mainp, ima, NULL, IMA_SIGNAL_FREE); BKE_image_backup_render(scene, ima, true); /* cleanup sequencer caches before starting user triggered render. @@ -570,7 +570,7 @@ static void image_rect_update(void *rjv, RenderResult *rr, volatile rcti *renrec else if (rj->image_outdated) { /* update entire render */ rj->image_outdated = false; - BKE_image_signal(ima, NULL, IMA_SIGNAL_COLORMANAGE); + BKE_image_signal(rj->main, ima, NULL, IMA_SIGNAL_COLORMANAGE); *(rj->do_update) = true; return; } @@ -1002,8 +1002,8 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even WM_jobs_callbacks(wm_job, render_startjob, NULL, NULL, render_endjob); /* get a render result image, and make sure it is empty */ - ima = BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result"); - BKE_image_signal(ima, NULL, IMA_SIGNAL_FREE); + ima = BKE_image_verify_viewer(bmain, IMA_TYPE_R_RESULT, "Render Result"); + BKE_image_signal(rj->main, ima, NULL, IMA_SIGNAL_FREE); BKE_image_backup_render(rj->scene, ima, true); rj->image = ima; @@ -1015,6 +1015,7 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even RE_current_scene_update_cb(re, rj, current_scene_update); RE_stats_draw_cb(re, rj, image_renderinfo_cb); RE_progress_cb(re, rj, render_progress_update); + RE_gl_context_create(re); rj->re = re; G.is_break = false; diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c index 7e33549c5ac..fb007accaeb 100644 --- a/source/blender/editors/render/render_opengl.c +++ b/source/blender/editors/render/render_opengl.c @@ -705,8 +705,8 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op) oglrender->re = RE_NewSceneRender(scene); /* create image and image user */ - oglrender->ima = BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result"); - BKE_image_signal(oglrender->ima, NULL, IMA_SIGNAL_FREE); + oglrender->ima = BKE_image_verify_viewer(oglrender->bmain, IMA_TYPE_R_RESULT, "Render Result"); + BKE_image_signal(oglrender->bmain, oglrender->ima, NULL, IMA_SIGNAL_FREE); BKE_image_backup_render(oglrender->scene, oglrender->ima, true); oglrender->iuser.scene = scene; diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c index 4a3c7a3fd4b..cdd79f43a72 100644 --- a/source/blender/editors/render/render_preview.c +++ b/source/blender/editors/render/render_preview.c @@ -176,6 +176,9 @@ typedef struct ShaderPreview { Main *bmain; Main *pr_main; + + void *gl_context; + bool gl_context_owner; } ShaderPreview; typedef struct IconPreviewSize { @@ -191,6 +194,8 @@ typedef struct IconPreview { void *owner; ID *id; ListBase sizes; + + void *gl_context; } IconPreview; /* *************************** Preview for buttons *********************** */ @@ -741,6 +746,10 @@ static void shader_preview_render(ShaderPreview *sp, ID *id, int split, int firs /* set this for all previews, default is react to G.is_break still */ RE_test_break_cb(re, sp, shader_preview_break); + if (sp->gl_context) { + RE_gl_context_set(re, sp->gl_context); + } + /* lens adjust */ oldlens = ((Camera *)sce->camera->data)->lens; if (sizex > sp->sizey) @@ -860,6 +869,10 @@ static void shader_preview_free(void *customdata) } MEM_freeN(sp->lampcopy); } + if (sp->gl_context_owner && sp->gl_context) { + WM_opengl_context_dispose(sp->gl_context); + sp->gl_context = NULL; + } MEM_freeN(sp); } @@ -1075,6 +1088,8 @@ static void icon_preview_startjob_all_sizes(void *customdata, short *stop, short sp->pr_rect = cur_size->rect; sp->id = ip->id; sp->bmain = ip->bmain; + sp->gl_context = ip->gl_context; + sp->gl_context_owner = false; if (is_render) { BLI_assert(ip->id); @@ -1091,6 +1106,11 @@ static void icon_preview_startjob_all_sizes(void *customdata, short *stop, short common_preview_startjob(sp, stop, do_update, progress); shader_preview_free(sp); } + + if (ip->gl_context) { + WM_opengl_context_dispose(ip->gl_context); + ip->gl_context = NULL; + } } static void icon_preview_endjob(void *customdata) @@ -1174,8 +1194,17 @@ void ED_preview_icon_job(const bContext *C, void *owner, ID *id, unsigned int *r /* render all resolutions from suspended job too */ old_ip = WM_jobs_customdata_get(wm_job); - if (old_ip) + if (old_ip) { BLI_movelisttolist(&ip->sizes, &old_ip->sizes); + /* NOTE: This assumes that it will be the same thread + * that will be used when resuming the job. */ + ip->gl_context = old_ip->gl_context; + } + + if (ip->gl_context == NULL) { + /* Create context in the main thread. */ + ip->gl_context = WM_opengl_context_create(); + } /* customdata for preview thread */ ip->bmain = CTX_data_main(C); @@ -1206,7 +1235,7 @@ void ED_preview_shader_job(const bContext *C, void *owner, ID *id, ID *parent, M { Object *ob = CTX_data_active_object(C); wmJob *wm_job; - ShaderPreview *sp; + ShaderPreview *sp, *old_sp; Scene *scene = CTX_data_scene(C); short id_type = GS(id->name); @@ -1223,6 +1252,21 @@ void ED_preview_shader_job(const bContext *C, void *owner, ID *id, ID *parent, M WM_JOB_EXCL_RENDER, WM_JOB_TYPE_RENDER_PREVIEW); sp = MEM_callocN(sizeof(ShaderPreview), "shader preview"); + /* Reuse previous gl context. */ + old_sp = WM_jobs_customdata_get(wm_job); + if (old_sp) { + /* NOTE: This assumes that it will be the same thread + * that will be used when resuming the job. */ + old_sp->gl_context_owner = false; /* Don't free it */ + sp->gl_context = old_sp->gl_context; + } + + if (sp->gl_context == NULL) { + /* Create context in the main thread. */ + sp->gl_context = WM_opengl_context_create(); + } + sp->gl_context_owner = true; + /* customdata for preview thread */ sp->scene = scene; sp->depsgraph = CTX_data_depsgraph(C); diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c index 3f32242cd1b..a822dabf7b4 100644 --- a/source/blender/editors/render/render_shading.c +++ b/source/blender/editors/render/render_shading.c @@ -303,6 +303,7 @@ static int material_slot_de_select(bContext *C, bool select) } } + DEG_id_tag_update(ob->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data); return OPERATOR_FINISHED; diff --git a/source/blender/editors/render/render_view.c b/source/blender/editors/render/render_view.c index a522817825a..351ceda90e3 100644 --- a/source/blender/editors/render/render_view.c +++ b/source/blender/editors/render/render_view.c @@ -37,6 +37,7 @@ #include "BKE_context.h" #include "BKE_image.h" #include "BKE_global.h" +#include "BKE_main.h" #include "BKE_screen.h" #include "BKE_report.h" @@ -131,6 +132,7 @@ static ScrArea *find_area_image_empty(bContext *C) /* new window uses x,y to set position */ ScrArea *render_view_open(bContext *C, int mx, int my, ReportList *reports) { + Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); wmWindow *win = NULL; ScrArea *sa = NULL; @@ -213,7 +215,7 @@ ScrArea *render_view_open(bContext *C, int mx, int my, ReportList *reports) sima = sa->spacedata.first; /* get the correct image, and scale it */ - sima->image = BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result"); + sima->image = BKE_image_verify_viewer(bmain, IMA_TYPE_R_RESULT, "Render Result"); /* if we're rendering to full screen, set appropriate hints on image editor diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index 034ccdf2e7b..8d8d046c741 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -953,6 +953,9 @@ static void region_overlap_fix(ScrArea *sa, ARegion *ar) } if (ar1->overlap && ((ar1->alignment & RGN_SPLIT_PREV) == 0)) { + if (ELEM(ar1->alignment, RGN_ALIGN_FLOAT)) { + continue; + } align1 = ar1->alignment; if (BLI_rcti_isect(&ar1->winrct, &ar->winrct, NULL)) { if (align1 != align) { @@ -994,6 +997,9 @@ static void region_overlap_fix(ScrArea *sa, ARegion *ar) if (ar1->flag & (RGN_FLAG_HIDDEN)) { continue; } + if (ELEM(ar1->alignment, RGN_ALIGN_FLOAT)) { + continue; + } if (ar1->overlap && (ar1->alignment & RGN_SPLIT_PREV) == 0) { if ((ar1->alignment != align) && BLI_rcti_isect(&ar1->winrct, &ar->winrct, NULL)) { @@ -1008,6 +1014,9 @@ static void region_overlap_fix(ScrArea *sa, ARegion *ar) /* overlapping regions only in the following restricted cases */ bool ED_region_is_overlap(int spacetype, int regiontype) { + if (regiontype == RGN_TYPE_HUD) { + return 1; + } if (U.uiflag2 & USER_REGION_OVERLAP) { if (ELEM(spacetype, SPACE_VIEW3D, SPACE_SEQ, SPACE_IMAGE)) { if (ELEM(regiontype, RGN_TYPE_TOOLS, RGN_TYPE_UI, RGN_TYPE_TOOL_PROPS)) @@ -1052,8 +1061,9 @@ static void region_rect_recursive(wmWindow *win, ScrArea *sa, ARegion *ar, rcti /* clear state flags first */ ar->flag &= ~RGN_FLAG_TOO_SMALL; /* user errors */ - if (ar->next == NULL && alignment != RGN_ALIGN_QSPLIT) + if ((ar->next == NULL) && !ELEM(alignment, RGN_ALIGN_QSPLIT, RGN_ALIGN_FLOAT)) { alignment = RGN_ALIGN_NONE; + } /* prefsize, taking into account DPI */ prefsizex = UI_DPI_FAC * ((ar->sizex > 1) ? ar->sizex + 0.5f : ar->type->prefsizex); @@ -1076,7 +1086,28 @@ static void region_rect_recursive(wmWindow *win, ScrArea *sa, ARegion *ar, rcti /* hidden is user flag */ } else if (alignment == RGN_ALIGN_FLOAT) { - /* XXX floating area region, not handled yet here */ + /** + * \note Currently this window type is only used for #RGN_TYPE_HUD, + * We expect the panel to resize it's self to be larger. + * + * This aligns to the lower left of the area. + */ + rcti overlap_remainder_margin = *overlap_remainder; + BLI_rcti_resize( + &overlap_remainder_margin, + max_ii(0, BLI_rcti_size_x(overlap_remainder) - UI_UNIT_X / 2), + max_ii(0, BLI_rcti_size_y(overlap_remainder) - UI_UNIT_Y / 2)); + ar->winrct.xmin = overlap_remainder_margin.xmin; + ar->winrct.ymin = overlap_remainder_margin.ymin; + ar->winrct.xmax = ar->winrct.xmin + ar->sizex - 1; + ar->winrct.ymax = ar->winrct.ymin + ar->sizey - 1; + + BLI_rcti_isect(&ar->winrct, &overlap_remainder_margin, &ar->winrct); + if (BLI_rcti_size_x(&ar->winrct) < UI_UNIT_X || + BLI_rcti_size_y(&ar->winrct) < UI_UNIT_Y) + { + ar->flag |= RGN_FLAG_TOO_SMALL; + } } else if (rct_fits(remainder, 'v', 1) < 0 || rct_fits(remainder, 'h', 1) < 0) { /* remainder is too small for any usage */ @@ -1215,7 +1246,7 @@ static void region_rect_recursive(wmWindow *win, ScrArea *sa, ARegion *ar, rcti if (ar->winy > 1) ar->sizey = (ar->winy + 0.5f) / UI_DPI_FAC; /* exception for multiple overlapping regions on same spot */ - if (ar->overlap) { + if (ar->overlap & (alignment != RGN_ALIGN_FLOAT)) { region_overlap_fix(sa, ar); } @@ -1424,7 +1455,7 @@ void ED_area_initialize(wmWindowManager *wm, wmWindow *win, ScrArea *sa) } for (ar = sa->regionbase.first; ar; ar = ar->next) - ar->type = BKE_regiontype_from_id(sa->type, ar->regiontype); + ar->type = BKE_regiontype_from_id_or_first(sa->type, ar->regiontype); /* area sizes */ area_calc_totrct(sa, &window_rect); @@ -1480,13 +1511,13 @@ static void region_update_rect(ARegion *ar) /** * Call to move a popup window (keep OpenGL context free!) */ -void ED_region_update_rect(bContext *UNUSED(C), ARegion *ar) +void ED_region_update_rect(ARegion *ar) { region_update_rect(ar); } /* externally called for floating regions like menus */ -void ED_region_init(bContext *UNUSED(C), ARegion *ar) +void ED_region_init(ARegion *ar) { /* refresh can be called before window opened */ region_subwindow(ar); @@ -1781,7 +1812,10 @@ static ThemeColorID region_background_color_id(const bContext *C, const ARegion static void region_clear_color(const bContext *C, const ARegion *ar, ThemeColorID colorid) { - if (ar->overlap) { + if (ar->alignment == RGN_ALIGN_FLOAT) { + /* handle our own drawing. */ + } + else if (ar->overlap) { /* view should be in pixelspace */ UI_view2d_view_restore(C); @@ -1806,15 +1840,16 @@ BLI_INLINE bool streq_array_any(const char *s, const char *arr[]) return false; } -static void ed_panel_draw(const bContext *C, - ScrArea *sa, - ARegion *ar, - ListBase *lb, - PanelType *pt, - Panel *panel, - int w, - int em, - bool vertical) +static void ed_panel_draw( + const bContext *C, + ScrArea *sa, + ARegion *ar, + ListBase *lb, + PanelType *pt, + Panel *panel, + int w, + int em, + bool vertical) { uiStyle *style = UI_style_get_dpi(); @@ -1827,6 +1862,21 @@ static void ed_panel_draw(const bContext *C, /* bad fixed values */ int xco, yco, h = 0; + if (pt->draw_header_preset && !(pt->flag & PNL_NO_HEADER) && (open || vertical)) { + /* for preset menu */ + panel->layout = UI_block_layout( + block, UI_LAYOUT_HORIZONTAL, UI_LAYOUT_HEADER, + 0, (UI_UNIT_Y * 1.1f) + style->panelspace, UI_UNIT_Y, 1, 0, style); + + pt->draw_header_preset(C, panel); + + int headerend = w - UI_UNIT_X; + + UI_block_layout_resolve(block, &xco, &yco); + UI_block_translate(block, headerend - xco, 0); + panel->layout = NULL; + } + if (pt->draw_header && !(pt->flag & PNL_NO_HEADER) && (open || vertical)) { int labelx, labely; UI_panel_label_offset(block, &labelx, &labely); @@ -1891,23 +1941,27 @@ static void ed_panel_draw(const bContext *C, * Matching against any of these strings will draw the panel. * Can be NULL to skip context checks. */ -void ED_region_panels(const bContext *C, ARegion *ar, const char *contexts[], int contextnr, const bool vertical) +void ED_region_panels_layout_ex( + const bContext *C, ARegion *ar, + const char *contexts[], int contextnr, const bool vertical) { + ar->runtime.category = NULL; + const WorkSpace *workspace = CTX_wm_workspace(C); ScrArea *sa = CTX_wm_area(C); PanelType *pt; View2D *v2d = &ar->v2d; - View2DScrollers *scrollers; int x, y, w, em; bool is_context_new = 0; int scroll; /* XXX, should use some better check? */ - bool use_category_tabs = (ELEM(ar->regiontype, RGN_TYPE_TOOLS, RGN_TYPE_UI, RGN_TYPE_WINDOW)); + bool use_category_tabs = (ELEM(ar->regiontype, RGN_TYPE_TOOLS, RGN_TYPE_UI)); /* offset panels for small vertical tab area */ const char *category = NULL; const int category_tabs_width = UI_PANEL_CATEGORY_MARGIN_WIDTH; int margin_x = 0; + const bool region_layout_based = ar->flag & RGN_FLAG_DYNAMIC_SIZE; BLI_SMALLSTACK_DECLARE(pt_stack, PanelType *); @@ -2018,7 +2072,27 @@ void ED_region_panels(const bContext *C, ARegion *ar, const char *contexts[], in UI_panels_end(C, ar, &x, &y); /* before setting the view */ - if (vertical) { + if (region_layout_based) { + /* XXX, only single panel support atm. + * Can't use x/y values calculated above because they're not using the real height of panels, + * instead they calculate offsets for the next panel to start drawing. */ + Panel *panel = ar->panels.last; + if (panel != NULL) { + int size_dyn[2] = { + UI_UNIT_X * ((panel->flag & PNL_CLOSED) ? 8 : 14), + UI_panel_size_y(panel), + }; + /* region size is layout based and needs to be updated */ + if ((ar->sizex != size_dyn[0]) || + (ar->sizey != size_dyn[1])) + { + ar->sizex = size_dyn[0]; + ar->sizey = size_dyn[1]; + sa->flag |= AREA_FLAG_REGION_SIZE_UPDATE; + } + } + } + else if (vertical) { /* we always keep the scroll offset - so the total view gets increased with the scrolled away part */ if (v2d->cur.ymax < -FLT_EPSILON) { /* Clamp to lower view boundary */ @@ -2059,7 +2133,22 @@ void ED_region_panels(const bContext *C, ARegion *ar, const char *contexts[], in #endif } - region_clear_color(C, ar, (ar->type->regionid == RGN_TYPE_PREVIEW) ? TH_PREVIEW_BACK : TH_BACK); + if (use_category_tabs) { + ar->runtime.category = category; + } +} +void ED_region_panels_layout(const bContext *C, ARegion *ar) +{ + ED_region_panels_layout_ex(C, ar, NULL, -1, true); +} + +void ED_region_panels_draw(const bContext *C, ARegion *ar) +{ + View2D *v2d = &ar->v2d; + + if (ar->alignment != RGN_ALIGN_FLOAT) { + region_clear_color(C, ar, (ar->type->regionid == RGN_TYPE_PREVIEW) ? TH_PREVIEW_BACK : TH_BACK); + } /* reset line width for drawing tabs */ glLineWidth(1.0f); @@ -2073,16 +2162,34 @@ void ED_region_panels(const bContext *C, ARegion *ar, const char *contexts[], in /* restore view matrix */ UI_view2d_view_restore(C); - if (use_category_tabs) { - UI_panel_category_draw_all(ar, category); + /* Set in layout. */ + if (ar->runtime.category) { + UI_panel_category_draw_all(ar, ar->runtime.category); } /* scrollers */ - scrollers = UI_view2d_scrollers_calc(C, v2d, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY); + View2DScrollers *scrollers = UI_view2d_scrollers_calc( + C, v2d, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY); UI_view2d_scrollers_draw(C, v2d, scrollers); UI_view2d_scrollers_free(scrollers); } +void ED_region_panels_ex( + const bContext *C, ARegion *ar, + const char *contexts[], int contextnr, const bool vertical) +{ + /* TODO: remove? */ + ED_region_panels_layout_ex(C, ar, contexts, contextnr, vertical); + ED_region_panels_draw(C, ar); +} + +void ED_region_panels(const bContext *C, ARegion *ar) +{ + /* TODO: remove? */ + ED_region_panels_layout(C, ar); + ED_region_panels_draw(C, ar); +} + void ED_region_panels_init(wmWindowManager *wm, ARegion *ar) { wmKeyMap *keymap; @@ -2102,13 +2209,12 @@ void ED_region_header_layout(const bContext *C, ARegion *ar) Header header = {NULL}; int maxco, xco, yco; int headery = ED_area_headersize(); - const int start_ofs = 0.4f * UI_UNIT_X; bool region_layout_based = ar->flag & RGN_FLAG_DYNAMIC_SIZE; /* set view2d view matrix for scrolling (without scrollers) */ UI_view2d_view_ortho(&ar->v2d); - xco = maxco = start_ofs; + xco = maxco = UI_HEADER_OFFSET; yco = headery + (ar->winy - headery) / 2 - floor(0.2f * UI_UNIT_Y); /* XXX workaround for 1 px alignment issue. Not sure what causes it... Would prefer a proper fix - Julian */ @@ -2139,7 +2245,7 @@ void ED_region_header_layout(const bContext *C, ARegion *ar) if (xco > maxco) maxco = xco; - int new_sizex = (maxco + start_ofs) / UI_DPI_FAC; + int new_sizex = (maxco + UI_HEADER_OFFSET) / UI_DPI_FAC; if (region_layout_based && (ar->sizex != new_sizex)) { /* region size is layout based and needs to be updated */ @@ -2152,8 +2258,12 @@ void ED_region_header_layout(const bContext *C, ARegion *ar) UI_block_end(C, block); } + if (!region_layout_based) { + maxco += UI_HEADER_OFFSET; + } + /* always as last */ - UI_view2d_totRect_set(&ar->v2d, maxco + (region_layout_based ? 0 : UI_UNIT_X + 80), headery); + UI_view2d_totRect_set(&ar->v2d, maxco, headery); /* restore view matrix */ UI_view2d_view_restore(C); @@ -2161,11 +2271,11 @@ void ED_region_header_layout(const bContext *C, ARegion *ar) void ED_region_header_draw(const bContext *C, ARegion *ar) { - UI_view2d_view_ortho(&ar->v2d); - /* clear */ region_clear_color(C, ar, region_background_color_id(C, ar)); + UI_view2d_view_ortho(&ar->v2d); + /* View2D matrix might have changed due to dynamic sized regions. */ UI_blocklist_update_window_matrix(C, &ar->uiblocks); @@ -2687,6 +2797,9 @@ void ED_region_visible_rect(ARegion *ar, rcti *rect) rect->ymax = arn->winrct.ymin; } } + else if (arn->alignment == RGN_ALIGN_FLOAT) { + /* Skip floating. */ + } else { BLI_assert(!"Region overlap with unknown alignment"); } diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index f6bd238170d..c2dab7e22dd 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -2252,7 +2252,7 @@ static int region_scale_modal(bContext *C, wmOperator *op, const wmEvent *event) case MOUSEMOVE: { const float aspect = BLI_rctf_size_x(&rmd->ar->v2d.cur) / (BLI_rcti_size_x(&rmd->ar->v2d.mask) + 1); - const int snap_size_threshold = (U.widget_unit * 3) / aspect; + const int snap_size_threshold = (U.widget_unit * 2) / aspect; if (rmd->edge == AE_LEFT_TO_TOPRIGHT || rmd->edge == AE_RIGHT_TO_TOPLEFT) { delta = event->x - rmd->origx; if (rmd->edge == AE_LEFT_TO_TOPRIGHT) delta = -delta; @@ -2444,7 +2444,7 @@ static void SCREEN_OT_frame_offset(wmOperatorType *ot) ot->poll = ED_operator_screenactive_norender; ot->flag = OPTYPE_UNDO_GROUPED; - ot->undo_group = "FRAME_CHANGE"; + ot->undo_group = "Frame Change"; /* rna */ RNA_def_int(ot->srna, "delta", 0, INT_MIN, INT_MAX, "Delta", "", INT_MIN, INT_MAX); @@ -2503,7 +2503,7 @@ static void SCREEN_OT_frame_jump(wmOperatorType *ot) ot->poll = ED_operator_screenactive_norender; ot->flag = OPTYPE_UNDO_GROUPED; - ot->undo_group = "FRAME_CHANGE"; + ot->undo_group = "Frame Change"; /* rna */ RNA_def_boolean(ot->srna, "end", 0, "Last Frame", "Jump to the last frame of the frame range"); @@ -2616,7 +2616,7 @@ static void SCREEN_OT_keyframe_jump(wmOperatorType *ot) ot->poll = ED_operator_screenactive_norender; ot->flag = OPTYPE_UNDO_GROUPED; - ot->undo_group = "FRAME_CHANGE"; + ot->undo_group = "Frame Change"; /* properties */ RNA_def_boolean(ot->srna, "next", true, "Next Keyframe", ""); @@ -2683,7 +2683,7 @@ static void SCREEN_OT_marker_jump(wmOperatorType *ot) ot->poll = ED_operator_screenactive_norender; ot->flag = OPTYPE_UNDO_GROUPED; - ot->undo_group = "FRAME_CHANGE"; + ot->undo_group = "Frame Change"; /* properties */ RNA_def_boolean(ot->srna, "next", true, "Next Marker", ""); diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index 2921faf8a5a..93fa3aac0d7 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -739,7 +739,7 @@ static void toggle_paint_cursor(bContext *C, int enable) * purpose is to make sure the paint cursor is shown if paint * mode is enabled in the image editor. the paint poll will * ensure that the cursor is hidden when not in paint mode */ -void ED_space_image_paint_update(wmWindowManager *wm, Scene *scene) +void ED_space_image_paint_update(Main *bmain, wmWindowManager *wm, Scene *scene) { ToolSettings *settings = scene->toolsettings; ImagePaintSettings *imapaint = &settings->imapaint; @@ -758,7 +758,7 @@ void ED_space_image_paint_update(wmWindowManager *wm, Scene *scene) } if (enabled) { - BKE_paint_init(scene, ePaintTexture2D, PAINT_CURSOR_TEXTURE_PAINT); + BKE_paint_init(bmain, scene, ePaintTexture2D, PAINT_CURSOR_TEXTURE_PAINT); paint_cursor_start_explicit(&imapaint->paint, wm, image_paint_poll); } @@ -1109,7 +1109,7 @@ static int texture_paint_toggle_exec(bContext *C, wmOperator *op) if (!sima->pin) { Object *obedit = CTX_data_edit_object(C); - ED_space_image_set(sima, scene, obedit, ima); + ED_space_image_set(bmain, sima, scene, obedit, ima); } } } @@ -1119,7 +1119,7 @@ static int texture_paint_toggle_exec(bContext *C, wmOperator *op) ob->mode |= mode_flag; - BKE_paint_init(scene, ePaintTextureProjective, PAINT_CURSOR_TEXTURE_PAINT); + BKE_paint_init(bmain, scene, ePaintTextureProjective, PAINT_CURSOR_TEXTURE_PAINT); if (U.glreslimit != 0) GPU_free_images(); diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index 32355d41ada..6175b6c6209 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -86,6 +86,7 @@ #include "UI_interface.h" +#include "ED_object.h" #include "ED_mesh.h" #include "ED_node.h" #include "ED_paint.h" @@ -5436,6 +5437,7 @@ static int texture_paint_image_from_view_exec(bContext *C, wmOperator *op) ImBuf *ibuf; char filename[FILE_MAX]; + Main *bmain = CTX_data_main(C); Depsgraph *depsgraph = CTX_data_depsgraph(C); Scene *scene = CTX_data_scene(C); ToolSettings *settings = scene->toolsettings; @@ -5465,7 +5467,7 @@ static int texture_paint_image_from_view_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - image = BKE_image_add_from_imbuf(ibuf, "image_view"); + image = BKE_image_add_from_imbuf(bmain, ibuf, "image_view"); /* Drop reference to ibuf so that the image owns it */ IMB_freeImBuf(ibuf); @@ -5661,7 +5663,7 @@ static Image *proj_paint_image_create(wmOperator *op, Main *bmain) static bool proj_paint_add_slot(bContext *C, wmOperator *op) { - Object *ob = CTX_data_active_object(C); + Object *ob = ED_object_active_context(C); Scene *scene = CTX_data_scene(C); Material *ma; Image *ima = NULL; @@ -5697,7 +5699,7 @@ static bool proj_paint_add_slot(bContext *C, wmOperator *op) if (ima) { BKE_texpaint_slot_refresh_cache(scene, ma); - BKE_image_signal(ima, NULL, IMA_SIGNAL_USER_NEW_IMAGE); + BKE_image_signal(bmain, ima, NULL, IMA_SIGNAL_USER_NEW_IMAGE); WM_event_add_notifier(C, NC_IMAGE | NA_ADDED, ima); DEG_id_tag_update(&ma->id, 0); ED_area_tag_redraw(CTX_wm_area(C)); @@ -5726,7 +5728,7 @@ static int texture_paint_add_texture_paint_slot_invoke(bContext *C, wmOperator * { char imagename[MAX_ID_NAME - 2]; Main *bmain = CTX_data_main(C); - Object *ob = CTX_data_active_object(C); + Object *ob = ED_object_active_context(C); Material *ma = give_current_material(ob, ob->actcol); int type = RNA_enum_get(op->ptr, "type"); @@ -5789,6 +5791,7 @@ void PAINT_OT_add_texture_paint_slot(wmOperatorType *ot) static int add_simple_uvs_exec(bContext *C, wmOperator *UNUSED(op)) { /* no checks here, poll function does them for us */ + Main *bmain = CTX_data_main(C); Object *ob = CTX_data_active_object(C); Scene *scene = CTX_data_scene(C); Mesh *me = ob->data; @@ -5813,7 +5816,7 @@ static int add_simple_uvs_exec(bContext *C, wmOperator *UNUSED(op)) /* set the margin really quickly before the packing operation*/ scene->toolsettings->uvcalc_margin = 0.001f; ED_uvedit_pack_islands(scene, ob, bm, false, false, true); - BM_mesh_bm_to_me(bm, me, (&(struct BMeshToMeshParams){0})); + BM_mesh_bm_to_me(bmain, bm, me, (&(struct BMeshToMeshParams){0})); BM_mesh_free(bm); if (synch_selection) diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c index b63f9461401..a7aa19807dd 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.c +++ b/source/blender/editors/sculpt_paint/paint_stroke.c @@ -38,6 +38,8 @@ #include "BLI_rand.h" #include "BLI_listbase.h" +#include "PIL_time.h" + #include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DNA_brush_types.h" @@ -86,6 +88,7 @@ typedef struct PaintStroke { void *mode_data; void *stroke_cursor; wmTimer *timer; + struct RNG *rng; /* Cached values */ ViewContext vc; @@ -403,17 +406,24 @@ static bool paint_brush_update(bContext *C, } } + if ((do_random || do_random_mask) && stroke->rng == NULL) { + /* Lazy initialization. */ + uint rng_seed = (uint)(PIL_check_seconds_timer_i() & UINT_MAX); + rng_seed ^= (uint)GET_INT_FROM_POINTER(brush); + stroke->rng = BLI_rng_new(rng_seed); + } + if (do_random) { if (brush->mtex.brush_angle_mode & MTEX_ANGLE_RANDOM) { ups->brush_rotation += -brush->mtex.random_angle / 2.0f + - brush->mtex.random_angle * BLI_frand(); + brush->mtex.random_angle * BLI_rng_get_float(stroke->rng); } } if (do_random_mask) { if (brush->mask_mtex.brush_angle_mode & MTEX_ANGLE_RANDOM) { ups->brush_rotation_sec += -brush->mask_mtex.random_angle / 2.0f + - brush->mask_mtex.random_angle * BLI_frand(); + brush->mask_mtex.random_angle * BLI_rng_get_float(stroke->rng); } } @@ -785,6 +795,10 @@ static void stroke_done(struct bContext *C, struct wmOperator *op) stroke->timer); } + if (stroke->rng) { + BLI_rng_free(stroke->rng); + } + if (stroke->stroke_cursor) WM_paint_cursor_end(CTX_wm_manager(C), stroke->stroke_cursor); diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c index 02dae51c594..ac6bfe019a1 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.c +++ b/source/blender/editors/sculpt_paint/paint_vertex.c @@ -55,7 +55,6 @@ #include "BKE_brush.h" #include "BKE_context.h" #include "BKE_deform.h" -#include "BKE_global.h" #include "BKE_main.h" #include "BKE_mesh.h" #include "BKE_mesh_mapping.h" @@ -1062,7 +1061,8 @@ static void vertex_paint_init_session_data(const ToolSettings *ts, Object *ob) * \{ */ static void ed_vwpaintmode_enter_generic( - Depsgraph *depsgraph, wmWindowManager *wm, Scene *scene, + Main *bmain, Depsgraph *depsgraph, + wmWindowManager *wm, Scene *scene, Object *ob, const eObjectMode mode_flag) { ob->mode |= mode_flag; @@ -1083,7 +1083,7 @@ static void ed_vwpaintmode_enter_generic( Paint *paint = BKE_paint_get_active_from_paintmode(scene, paint_mode); paint_cursor_start_explicit(paint, wm, vertex_paint_poll); - BKE_paint_init(scene, paint_mode, PAINT_CURSOR_VERTEX_PAINT); + BKE_paint_init(bmain, scene, paint_mode, PAINT_CURSOR_VERTEX_PAINT); } else if (mode_flag == OB_MODE_WEIGHT_PAINT) { const ePaintMode paint_mode = ePaintWeight; @@ -1094,7 +1094,7 @@ static void ed_vwpaintmode_enter_generic( Paint *paint = BKE_paint_get_active_from_paintmode(scene, paint_mode); paint_cursor_start_explicit(paint, wm, weight_paint_poll); - BKE_paint_init(scene, paint_mode, PAINT_CURSOR_WEIGHT_PAINT); + BKE_paint_init(bmain, scene, paint_mode, PAINT_CURSOR_WEIGHT_PAINT); /* weight paint specific */ ED_mesh_mirror_spatial_table(ob, NULL, NULL, NULL, 's'); @@ -1120,35 +1120,37 @@ static void ed_vwpaintmode_enter_generic( } void ED_object_vpaintmode_enter_ex( - Depsgraph *depsgraph, wmWindowManager *wm, + Main *bmain, Depsgraph *depsgraph, wmWindowManager *wm, Scene *scene, Object *ob) { ed_vwpaintmode_enter_generic( - depsgraph, wm, scene, ob, OB_MODE_VERTEX_PAINT); + bmain, depsgraph, wm, scene, ob, OB_MODE_VERTEX_PAINT); } void ED_object_vpaintmode_enter(struct bContext *C) { + Main *bmain = CTX_data_main(C); Depsgraph *depsgraph = CTX_data_depsgraph(C); wmWindowManager *wm = CTX_wm_manager(C); Scene *scene = CTX_data_scene(C); Object *ob = CTX_data_active_object(C); - ED_object_vpaintmode_enter_ex(depsgraph, wm, scene, ob); + ED_object_vpaintmode_enter_ex(bmain, depsgraph, wm, scene, ob); } void ED_object_wpaintmode_enter_ex( - Depsgraph *depsgraph, wmWindowManager *wm, + Main *bmain, Depsgraph *depsgraph, wmWindowManager *wm, Scene *scene, Object *ob) { ed_vwpaintmode_enter_generic( - depsgraph, wm, scene, ob, OB_MODE_WEIGHT_PAINT); + bmain, depsgraph, wm, scene, ob, OB_MODE_WEIGHT_PAINT); } void ED_object_wpaintmode_enter(struct bContext *C) { + Main *bmain = CTX_data_main(C); Depsgraph *depsgraph = CTX_data_depsgraph(C); wmWindowManager *wm = CTX_wm_manager(C); Scene *scene = CTX_data_scene(C); Object *ob = CTX_data_active_object(C); - ED_object_wpaintmode_enter_ex(depsgraph, wm, scene, ob); + ED_object_wpaintmode_enter_ex(bmain, depsgraph, wm, scene, ob); } /** \} */ @@ -1234,6 +1236,7 @@ void ED_object_wpaintmode_exit(struct bContext *C) */ static int wpaint_mode_toggle_exec(bContext *C, wmOperator *op) { + Main *bmain = CTX_data_main(C); struct wmMsgBus *mbus = CTX_wm_message_bus(C); Object *ob = CTX_data_active_object(C); const int mode_flag = OB_MODE_WEIGHT_PAINT; @@ -1254,7 +1257,7 @@ static int wpaint_mode_toggle_exec(bContext *C, wmOperator *op) else { Depsgraph *depsgraph = CTX_data_depsgraph_on_load(C); wmWindowManager *wm = CTX_wm_manager(C); - ED_object_wpaintmode_enter_ex(depsgraph, wm, scene, ob); + ED_object_wpaintmode_enter_ex(bmain, depsgraph, wm, scene, ob); } /* Weightpaint works by overriding colors in mesh, @@ -2371,6 +2374,7 @@ void PAINT_OT_weight_paint(wmOperatorType *ot) */ static int vpaint_mode_toggle_exec(bContext *C, wmOperator *op) { + Main *bmain = CTX_data_main(C); struct wmMsgBus *mbus = CTX_wm_message_bus(C); Object *ob = CTX_data_active_object(C); const int mode_flag = OB_MODE_VERTEX_PAINT; @@ -2392,7 +2396,7 @@ static int vpaint_mode_toggle_exec(bContext *C, wmOperator *op) else { Depsgraph *depsgraph = CTX_data_depsgraph_on_load(C); wmWindowManager *wm = CTX_wm_manager(C); - ED_object_vpaintmode_enter_ex(depsgraph, wm, scene, ob); + ED_object_vpaintmode_enter_ex(bmain, depsgraph, wm, scene, ob); } BKE_mesh_batch_cache_dirty(ob->data, BKE_MESH_BATCH_DIRTY_ALL); diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 3475aadd171..f3fe04f7714 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -5666,7 +5666,7 @@ void ED_object_sculptmode_enter_ex( /* Make sure derived final from original object does not reference possibly * freed memory. */ - BKE_object_free_derived_mesh_caches(ob); + BKE_object_free_derived_caches(ob); sculpt_init_session(depsgraph, scene, ob); @@ -5687,7 +5687,7 @@ void ED_object_sculptmode_enter_ex( } Paint *paint = BKE_paint_get_active_from_paintmode(scene, ePaintSculpt); - BKE_paint_init(scene, ePaintSculpt, PAINT_CURSOR_SCULPT); + BKE_paint_init(bmain, scene, ePaintSculpt, PAINT_CURSOR_SCULPT); paint_cursor_start_explicit(paint, bmain->wm.first, sculpt_poll_view3d); @@ -5796,7 +5796,7 @@ void ED_object_sculptmode_exit_ex( paint_cursor_delete_textures(); /* Never leave derived meshes behind. */ - BKE_object_free_derived_mesh_caches(ob); + BKE_object_free_derived_caches(ob); /* Flush object mode. */ DEG_id_tag_update(&ob->id, DEG_TAG_COPY_ON_WRITE); diff --git a/source/blender/editors/sculpt_paint/sculpt_uv.c b/source/blender/editors/sculpt_paint/sculpt_uv.c index 46d704e8f74..cf9feae62b5 100644 --- a/source/blender/editors/sculpt_paint/sculpt_uv.c +++ b/source/blender/editors/sculpt_paint/sculpt_uv.c @@ -43,12 +43,13 @@ #include "DNA_meshdata_types.h" #include "BKE_brush.h" -#include "BKE_paint.h" #include "BKE_colortools.h" #include "BKE_context.h" -#include "BKE_mesh_mapping.h" #include "BKE_customdata.h" #include "BKE_editmesh.h" +#include "BKE_main.h" +#include "BKE_mesh_mapping.h" +#include "BKE_paint.h" #include "DEG_depsgraph.h" @@ -230,7 +231,7 @@ static void brush_drawcursor_uvsculpt(bContext *C, int x, int y, void *UNUSED(cu } -void ED_space_image_uv_sculpt_update(wmWindowManager *wm, Scene *scene) +void ED_space_image_uv_sculpt_update(Main *bmain, wmWindowManager *wm, Scene *scene) { ToolSettings *settings = scene->toolsettings; if (settings->use_uv_sculpt) { @@ -243,7 +244,7 @@ void ED_space_image_uv_sculpt_update(wmWindowManager *wm, Scene *scene) settings->uvsculpt->paint.flags |= PAINT_SHOW_BRUSH; } - BKE_paint_init(scene, ePaintSculptUV, PAINT_CURSOR_SCULPT); + BKE_paint_init(bmain, scene, ePaintSculptUV, PAINT_CURSOR_SCULPT); settings->uvsculpt->paint.paint_cursor = WM_paint_cursor_activate(wm, uv_sculpt_brush_poll, brush_drawcursor_uvsculpt, NULL); diff --git a/source/blender/editors/space_action/action_buttons.c b/source/blender/editors/space_action/action_buttons.c index a5cc66add87..55ad773f4df 100644 --- a/source/blender/editors/space_action/action_buttons.c +++ b/source/blender/editors/space_action/action_buttons.c @@ -117,7 +117,7 @@ static int action_properties_toggle_exec(bContext *C, wmOperator *UNUSED(op)) void ACTION_OT_properties(wmOperatorType *ot) { - ot->name = "Properties"; + ot->name = "Toggle Sidebar"; ot->idname = "ACTION_OT_properties"; ot->description = "Toggle the properties region visibility"; diff --git a/source/blender/editors/space_action/space_action.c b/source/blender/editors/space_action/space_action.c index e130ea9369c..527e382ec1e 100644 --- a/source/blender/editors/space_action/space_action.c +++ b/source/blender/editors/space_action/space_action.c @@ -116,7 +116,7 @@ static SpaceLink *action_new(const ScrArea *sa, const Scene *scene) BLI_addtail(&saction->regionbase, ar); ar->regiontype = RGN_TYPE_HEADER; - ar->alignment = RGN_ALIGN_BOTTOM; + ar->alignment = RGN_ALIGN_TOP; /* channel list region */ ar = MEM_callocN(sizeof(ARegion), "channel region for action"); @@ -752,7 +752,7 @@ static void action_buttons_area_init(wmWindowManager *wm, ARegion *ar) static void action_buttons_area_draw(const bContext *C, ARegion *ar) { - ED_region_panels(C, ar, NULL, -1, true); + ED_region_panels(C, ar); } static void action_region_listener( diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c index be687d365f3..4fe3423e730 100644 --- a/source/blender/editors/space_buttons/space_buttons.c +++ b/source/blender/editors/space_buttons/space_buttons.c @@ -144,7 +144,7 @@ static void buttons_main_region_init(wmWindowManager *wm, ARegion *ar) WM_event_add_keymap_handler(&ar->handlers, keymap); } -static void buttons_main_region_draw_properties(const bContext *C, SpaceButs *sbuts, ARegion *ar) +static void buttons_main_region_layout_properties(const bContext *C, SpaceButs *sbuts, ARegion *ar) { const bool vertical = (sbuts->align == BUT_VERTICAL); @@ -203,12 +203,10 @@ static void buttons_main_region_draw_properties(const bContext *C, SpaceButs *sb break; } - if (contexts[0]) { - ED_region_panels(C, ar, contexts, sbuts->mainb, vertical); - } + ED_region_panels_layout_ex(C, ar, contexts, sbuts->mainb, vertical); } -static void buttons_main_region_draw_tool(const bContext *C, SpaceButs *sbuts, ARegion *ar) +static void buttons_main_region_layout_tool(const bContext *C, SpaceButs *sbuts, ARegion *ar) { const bool vertical = (sbuts->align == BUT_VERTICAL); const char *contexts[3] = {NULL}; @@ -260,30 +258,24 @@ static void buttons_main_region_draw_tool(const bContext *C, SpaceButs *sbuts, A ARRAY_SET_ITEMS(contexts, ".todo"); break; } - if (contexts[0]) { - ED_region_panels(C, ar, contexts, -1, vertical); - } } else if (workspace->tools_space_type == SPACE_IMAGE) { /* TODO */ } - if (contexts[0] == NULL) { - UI_ThemeClearColor(TH_BACK); - glClear(GL_COLOR_BUFFER_BIT); - } + ED_region_panels_layout_ex(C, ar, contexts, -1, vertical); } -static void buttons_main_region_draw(const bContext *C, ARegion *ar) +static void buttons_main_region_layout(const bContext *C, ARegion *ar) { /* draw entirely, view changes should be handled here */ SpaceButs *sbuts = CTX_wm_space_buts(C); if (sbuts->mainb == BCONTEXT_TOOL) { - buttons_main_region_draw_tool(C, sbuts, ar); + buttons_main_region_layout_tool(C, sbuts, ar); } else { - buttons_main_region_draw_properties(C, sbuts, ar); + buttons_main_region_layout_properties(C, sbuts, ar); } sbuts->re_align = 0; @@ -619,7 +611,8 @@ void ED_spacetype_buttons(void) art = MEM_callocN(sizeof(ARegionType), "spacetype buttons region"); art->regionid = RGN_TYPE_WINDOW; art->init = buttons_main_region_init; - art->draw = buttons_main_region_draw; + art->layout = buttons_main_region_layout; + art->draw = ED_region_panels_draw; art->listener = buttons_main_region_listener; art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES; BLI_addhead(&st->regiontypes, art); diff --git a/source/blender/editors/space_clip/clip_intern.h b/source/blender/editors/space_clip/clip_intern.h index ab8a7add009..e5c4f567d5c 100644 --- a/source/blender/editors/space_clip/clip_intern.h +++ b/source/blender/editors/space_clip/clip_intern.h @@ -145,6 +145,8 @@ void clip_view_center_to_point(SpaceClip *sc, float x, float y); void clip_draw_sfra_efra(struct View2D *v2d, struct Scene *scene); +void clip_on_marker_selection_changed(struct bContext *C); + /* tracking_ops.c */ struct MovieTrackingTrack *tracking_marker_check_slide(struct bContext *C, const struct wmEvent *event, int *area_r, int *action_r, int *corner_r); diff --git a/source/blender/editors/space_clip/clip_toolbar.c b/source/blender/editors/space_clip/clip_toolbar.c index 61bd8df3dbf..3e4d0cd5bb4 100644 --- a/source/blender/editors/space_clip/clip_toolbar.c +++ b/source/blender/editors/space_clip/clip_toolbar.c @@ -106,7 +106,7 @@ static int properties_exec(bContext *C, wmOperator *UNUSED(op)) void CLIP_OT_properties(wmOperatorType *ot) { /* identifiers */ - ot->name = "Properties"; + ot->name = "Toggle Sidebar"; ot->description = "Toggle the properties region visibility"; ot->idname = "CLIP_OT_properties"; @@ -170,7 +170,7 @@ static int tools_exec(bContext *C, wmOperator *UNUSED(op)) void CLIP_OT_tools(wmOperatorType *ot) { /* identifiers */ - ot->name = "Tools"; + ot->name = "Toggle Toolbar"; ot->description = "Toggle clip tools panel"; ot->idname = "CLIP_OT_tools"; diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index f022bb7e6f8..b050e991140 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -1435,7 +1435,7 @@ static void clip_tools_region_init(wmWindowManager *wm, ARegion *ar) static void clip_tools_region_draw(const bContext *C, ARegion *ar) { - ED_region_panels(C, ar, NULL, -1, true); + ED_region_panels(C, ar); } /****************** tool properties region ******************/ @@ -1484,7 +1484,7 @@ static void clip_properties_region_draw(const bContext *C, ARegion *ar) BKE_movieclip_update_scopes(sc->clip, &sc->user, &sc->scopes); - ED_region_panels(C, ar, NULL, -1, true); + ED_region_panels(C, ar); } static void clip_properties_region_listener( diff --git a/source/blender/editors/space_console/console_ops.c b/source/blender/editors/space_console/console_ops.c index 4867d42030c..32cf5ea2055 100644 --- a/source/blender/editors/space_console/console_ops.c +++ b/source/blender/editors/space_console/console_ops.c @@ -1140,8 +1140,11 @@ static int console_modal_select(bContext *C, wmOperator *op, const wmEvent *even case LEFTMOUSE: case MIDDLEMOUSE: case RIGHTMOUSE: - console_cursor_set_exit(C, op); - return OPERATOR_FINISHED; + if (event->val == KM_RELEASE) { + console_cursor_set_exit(C, op); + return OPERATOR_FINISHED; + } + break; case MOUSEMOVE: console_modal_select_apply(C, op, event); break; diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c index 62e7c7923e8..7b045a42595 100644 --- a/source/blender/editors/space_file/space_file.c +++ b/source/blender/editors/space_file/space_file.c @@ -636,7 +636,7 @@ static void file_tools_region_init(wmWindowManager *wm, ARegion *ar) static void file_tools_region_draw(const bContext *C, ARegion *ar) { - ED_region_panels(C, ar, NULL, -1, true); + ED_region_panels(C, ar); } static void file_tools_region_listener( diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c index 706beb9784a..263b68a2124 100644 --- a/source/blender/editors/space_graph/graph_buttons.c +++ b/source/blender/editors/space_graph/graph_buttons.c @@ -747,7 +747,7 @@ static void graph_draw_driven_property_panel(uiLayout *layout, ID *id, FCurve *f } /* UI properties panel layout for driver settings - shared for Drivers Editor and for */ -static void graph_draw_driver_settings_panel(uiLayout *layout, ID *id, FCurve *fcu) +static void graph_draw_driver_settings_panel(uiLayout *layout, ID *id, FCurve *fcu, const bool is_popover) { ChannelDriver *driver = fcu->driver; DriverVar *dvar; @@ -778,6 +778,9 @@ static void graph_draw_driver_settings_panel(uiLayout *layout, ID *id, FCurve *f uiItemL(row, valBuf, ICON_NONE); } + uiItemS(layout); + uiItemS(layout); + /* show expression box if doing scripted drivers, and/or error messages when invalid drivers exist */ if (driver->type == DRIVER_TYPE_PYTHON) { bool bpy_data_expr_error = (strstr(driver->expression, "bpy.data.") != NULL); @@ -841,15 +844,31 @@ static void graph_draw_driver_settings_panel(uiLayout *layout, ID *id, FCurve *f } } + uiItemS(layout); + /* add/copy/paste driver variables */ - { + if (is_popover) { + /* add driver variable - add blank */ + row = uiLayoutRow(layout, true); + block = uiLayoutGetBlock(row); + but = uiDefIconTextBut(block, UI_BTYPE_BUT, B_IPO_DEPCHANGE, ICON_ZOOMIN, IFACE_("Add Input Variable"), + 0, 0, 10 * UI_UNIT_X, UI_UNIT_Y, + NULL, 0.0, 0.0, 0, 0, + TIP_("Add a Driver Variable to keep track an input used by the driver")); + UI_but_func_set(but, driver_add_var_cb, driver, NULL); + + /* add driver variable - add using eyedropper */ + /* XXX: will this operator work like this? */ + uiItemO(row, "", ICON_EYEDROPPER, "UI_OT_eyedropper_driver"); + } + else { /* add driver variable */ row = uiLayoutRow(layout, false); block = uiLayoutGetBlock(row); but = uiDefIconTextBut(block, UI_BTYPE_BUT, B_IPO_DEPCHANGE, ICON_ZOOMIN, IFACE_("Add Input Variable"), - 0, 0, 10 * UI_UNIT_X, UI_UNIT_Y, - NULL, 0.0, 0.0, 0, 0, - TIP_("Driver variables ensure that all dependencies will be accounted for, eusuring that drivers will update correctly")); + 0, 0, 10 * UI_UNIT_X, UI_UNIT_Y, + NULL, 0.0, 0.0, 0, 0, + TIP_("Driver variables ensure that all dependencies will be accounted for, eusuring that drivers will update correctly")); UI_but_func_set(but, driver_add_var_cb, driver, NULL); /* copy/paste (as sub-row) */ @@ -948,6 +967,9 @@ static void graph_draw_driver_settings_panel(uiLayout *layout, ID *id, FCurve *f } } + uiItemS(layout); + uiItemS(layout); + /* XXX: This should become redundant. But sometimes the flushing fails, so keep this around for a while longer as a "last resort" */ row = uiLayoutRow(layout, true); block = uiLayoutGetBlock(row); @@ -985,7 +1007,7 @@ static void graph_panel_drivers(const bContext *C, Panel *pa) if (!graph_panel_context(C, &ale, &fcu)) return; - graph_draw_driver_settings_panel(pa->layout, ale->id, fcu); + graph_draw_driver_settings_panel(pa->layout, ale->id, fcu, false); /* cleanup */ MEM_freeN(ale); @@ -1019,6 +1041,12 @@ static void graph_panel_drivers_popover(const bContext *C, Panel *pa) &ptr, prop, index, NULL, NULL, &driven, &special); + /* Hack: Force all buttons in this panel to be able to know the driver button + * this panel is getting spawned from, so that things like the "Open Drivers Editor" + * button will work. + */ + uiLayoutSetContextFromBut(layout, but); + /* Populate Panel - With a combination of the contents of the Driven and Driver panels */ if (fcu) { ID *id = ptr.id.data; @@ -1033,7 +1061,7 @@ static void graph_panel_drivers_popover(const bContext *C, Panel *pa) /* Drivers Settings */ uiItemL(layout, IFACE_("Driver Settings:"), ICON_NONE); - graph_draw_driver_settings_panel(pa->layout, id, fcu); + graph_draw_driver_settings_panel(pa->layout, id, fcu, true); } } @@ -1179,7 +1207,7 @@ static int graph_properties_toggle_exec(bContext *C, wmOperator *UNUSED(op)) void GRAPH_OT_properties(wmOperatorType *ot) { - ot->name = "Properties"; + ot->name = "Toggle Sidebar"; ot->idname = "GRAPH_OT_properties"; ot->description = "Toggle the properties region visibility"; diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c index 56236ea8f47..59d7d7500ae 100644 --- a/source/blender/editors/space_graph/space_graph.c +++ b/source/blender/editors/space_graph/space_graph.c @@ -422,7 +422,7 @@ static void graph_buttons_region_init(wmWindowManager *wm, ARegion *ar) static void graph_buttons_region_draw(const bContext *C, ARegion *ar) { - ED_region_panels(C, ar, NULL, -1, true); + ED_region_panels(C, ar); } static void graph_region_listener( diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c index 8b8aabb2ce0..7236a99ad80 100644 --- a/source/blender/editors/space_image/image_buttons.c +++ b/source/blender/editors/space_image/image_buttons.c @@ -291,23 +291,24 @@ static void ui_imageuser_slot_menu(bContext *UNUSED(C), uiLayout *layout, void * { uiBlock *block = uiLayoutGetBlock(layout); Image *image = image_p; - int slot; + int slot_id; uiDefBut(block, UI_BTYPE_LABEL, 0, IFACE_("Slot"), 0, 0, UI_UNIT_X * 5, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, ""); uiItemS(layout); - slot = IMA_MAX_RENDER_SLOT; - while (slot--) { + slot_id = BLI_listbase_count(&image->renderslots) - 1; + for (RenderSlot *slot = image->renderslots.last; slot; slot = slot->prev) { char str[64]; - if (image->render_slots[slot].name[0] != '\0') { - BLI_strncpy(str, image->render_slots[slot].name, sizeof(str)); + if (slot->name[0] != '\0') { + BLI_strncpy(str, slot->name, sizeof(str)); } else { - BLI_snprintf(str, sizeof(str), IFACE_("Slot %d"), slot + 1); + BLI_snprintf(str, sizeof(str), IFACE_("Slot %d"), slot_id + 1); } uiDefButS(block, UI_BTYPE_BUT_MENU, B_NOP, str, 0, 0, - UI_UNIT_X * 5, UI_UNIT_X, &image->render_slot, (float) slot, 0.0, 0, -1, ""); + UI_UNIT_X * 5, UI_UNIT_X, &image->render_slot, (float) slot_id, 0.0, 0, -1, ""); + slot_id--; } } @@ -708,8 +709,9 @@ static void uiblock_layer_pass_buttons( /* menu buts */ if (render_slot) { char str[64]; - if (image->render_slots[*render_slot].name[0] != '\0') { - BLI_strncpy(str, image->render_slots[*render_slot].name, sizeof(str)); + RenderSlot *slot = BKE_image_get_renderslot(image, *render_slot); + if (slot->name[0] != '\0') { + BLI_strncpy(str, slot->name, sizeof(str)); } else { BLI_snprintf(str, sizeof(str), IFACE_("Slot %d"), *render_slot + 1); @@ -1313,7 +1315,7 @@ static int image_properties_toggle_exec(bContext *C, wmOperator *UNUSED(op)) void IMAGE_OT_properties(wmOperatorType *ot) { - ot->name = "Properties"; + ot->name = "Toggle Sidebar"; ot->idname = "IMAGE_OT_properties"; ot->description = "Toggle the properties region visibility"; @@ -1337,7 +1339,7 @@ static int image_scopes_toggle_exec(bContext *C, wmOperator *UNUSED(op)) void IMAGE_OT_toolshelf(wmOperatorType *ot) { - ot->name = "Tool Shelf"; + ot->name = "Toggle Toolbar"; ot->idname = "IMAGE_OT_toolshelf"; ot->description = "Toggles tool shelf display"; diff --git a/source/blender/editors/space_image/image_edit.c b/source/blender/editors/space_image/image_edit.c index 0911bea3be4..72d0051d260 100644 --- a/source/blender/editors/space_image/image_edit.c +++ b/source/blender/editors/space_image/image_edit.c @@ -34,6 +34,7 @@ #include "DNA_scene_types.h" #include "BLI_rect.h" +#include "BLI_listbase.h" #include "BKE_colortools.h" #include "BKE_context.h" @@ -64,7 +65,7 @@ Image *ED_space_image(SpaceImage *sima) } /* called to assign images to UV faces */ -void ED_space_image_set(SpaceImage *sima, Scene *UNUSED(scene), Object *obedit, Image *ima) +void ED_space_image_set(Main *bmain, SpaceImage *sima, Scene *UNUSED(scene), Object *obedit, Image *ima) { /* change the space ima after because uvedit_face_visible_test uses the space ima * to check if the face is displayed in UV-localview */ @@ -77,7 +78,7 @@ void ED_space_image_set(SpaceImage *sima, Scene *UNUSED(scene), Object *obedit, } if (sima->image) - BKE_image_signal(sima->image, &sima->iuser, IMA_SIGNAL_USER_NEW_IMAGE); + BKE_image_signal(bmain, sima->image, &sima->iuser, IMA_SIGNAL_USER_NEW_IMAGE); id_us_ensure_real((ID *)sima->image); @@ -302,17 +303,18 @@ bool ED_image_slot_cycle(struct Image *image, int direction) BLI_assert(ELEM(direction, -1, 1)); - for (i = 1; i < IMA_MAX_RENDER_SLOT; i++) { - slot = (cur + ((direction == -1) ? -i : i)) % IMA_MAX_RENDER_SLOT; - if (slot < 0) slot += IMA_MAX_RENDER_SLOT; + int num_slots = BLI_listbase_count(&image->renderslots); + for (i = 1; i < num_slots; i++) { + slot = (cur + ((direction == -1) ? -i : i)) % num_slots; + if (slot < 0) slot += num_slots; - if (image->renders[slot] || slot == image->last_render_slot) { + if (BKE_image_get_renderslot(image, slot)->render || slot == image->last_render_slot) { image->render_slot = slot; break; } } - if (i == IMA_MAX_RENDER_SLOT) { + if (i == num_slots) { image->render_slot = ((cur == 1) ? 0 : 1); } diff --git a/source/blender/editors/space_image/image_intern.h b/source/blender/editors/space_image/image_intern.h index 9167a193f2d..49c2690daaf 100644 --- a/source/blender/editors/space_image/image_intern.h +++ b/source/blender/editors/space_image/image_intern.h @@ -83,6 +83,9 @@ void IMAGE_OT_unpack(struct wmOperatorType *ot); void IMAGE_OT_invert(struct wmOperatorType *ot); void IMAGE_OT_cycle_render_slot(struct wmOperatorType *ot); +void IMAGE_OT_clear_render_slot(struct wmOperatorType *ot); +void IMAGE_OT_add_render_slot(struct wmOperatorType *ot); +void IMAGE_OT_remove_render_slot(struct wmOperatorType *ot); void IMAGE_OT_sample(struct wmOperatorType *ot); void IMAGE_OT_sample_line(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index d17eb357ff6..44ff1086e27 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -1179,14 +1179,14 @@ static int image_sequence_get_len(ListBase *frames, int *ofs) } static Image *image_open_single( - wmOperator *op, const char *filepath, const char *relbase, + Main *bmain, wmOperator *op, const char *filepath, const char *relbase, bool is_relative_path, bool use_multiview, int frame_seq_len) { bool exists = false; Image *ima = NULL; errno = 0; - ima = BKE_image_load_exists_ex(filepath, &exists); + ima = BKE_image_load_exists_ex(bmain, filepath, &exists); if (!ima) { if (op->customdata) MEM_freeN(op->customdata); @@ -1267,7 +1267,7 @@ static int image_open_exec(bContext *C, wmOperator *op) } Image *ima_range = image_open_single( - op, filepath_range, BKE_main_blendfile_path(bmain), + bmain, op, filepath_range, BKE_main_blendfile_path(bmain), is_relative_path, use_multiview, frame_range_seq_len); /* take the first image */ @@ -1282,7 +1282,7 @@ static int image_open_exec(bContext *C, wmOperator *op) else { /* for drag & drop etc. */ ima = image_open_single( - op, filepath, BKE_main_blendfile_path(bmain), + bmain, op, filepath, BKE_main_blendfile_path(bmain), is_relative_path, use_multiview, 1); } @@ -1308,7 +1308,7 @@ static int image_open_exec(bContext *C, wmOperator *op) } else if (sa && sa->spacetype == SPACE_IMAGE) { SpaceImage *sima = sa->spacedata.first; - ED_space_image_set(sima, scene, obedit, ima); + ED_space_image_set(bmain, sima, scene, obedit, ima); iuser = &sima->iuser; } else { @@ -1349,7 +1349,7 @@ static int image_open_exec(bContext *C, wmOperator *op) /* XXX unpackImage frees image buffers */ ED_preview_kill_jobs(CTX_wm_manager(C), bmain); - BKE_image_signal(ima, iuser, IMA_SIGNAL_RELOAD); + BKE_image_signal(bmain, ima, iuser, IMA_SIGNAL_RELOAD); WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima); MEM_freeN(op->customdata); @@ -1521,6 +1521,7 @@ void IMAGE_OT_match_movie_length(wmOperatorType *ot) static int image_replace_exec(bContext *C, wmOperator *op) { + Main *bmain = CTX_data_main(C); SpaceImage *sima = CTX_wm_space_image(C); char str[FILE_MAX]; @@ -1534,7 +1535,7 @@ static int image_replace_exec(bContext *C, wmOperator *op) if (sima->image->source == IMA_SRC_GENERATED) { sima->image->source = IMA_SRC_FILE; - BKE_image_signal(sima->image, &sima->iuser, IMA_SIGNAL_SRC_CHANGE); + BKE_image_signal(bmain, sima->image, &sima->iuser, IMA_SIGNAL_SRC_CHANGE); } if (BLI_testextensie_array(str, imb_ext_movie)) @@ -1546,7 +1547,7 @@ static int image_replace_exec(bContext *C, wmOperator *op) ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C)); BKE_icon_changed(BKE_icon_id_ensure(&sima->image->id)); - BKE_image_signal(sima->image, &sima->iuser, IMA_SIGNAL_RELOAD); + BKE_image_signal(bmain, sima->image, &sima->iuser, IMA_SIGNAL_RELOAD); WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, sima->image); return OPERATOR_FINISHED; @@ -1737,7 +1738,7 @@ static void save_image_options_to_op(SaveImageOptions *simopts, wmOperator *op) } static void save_image_post( - wmOperator *op, ImBuf *ibuf, Image *ima, int ok, int save_copy, + Main *bmain, wmOperator *op, ImBuf *ibuf, Image *ima, int ok, int save_copy, const char *relbase, int relative, int do_newpath, const char *filepath) { if (ok) { @@ -1783,7 +1784,7 @@ static void save_image_post( if (!BKE_color_managed_colorspace_settings_equals(&old_colorspace_settings, &ima->colorspace_settings)) { - BKE_image_signal(ima, NULL, IMA_SIGNAL_COLORMANAGE); + BKE_image_signal(bmain, ima, NULL, IMA_SIGNAL_COLORMANAGE); } } } @@ -1814,6 +1815,7 @@ static void save_imbuf_post(ImBuf *ibuf, ImBuf *colormanaged_ibuf) */ static bool save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveImageOptions *simopts, bool do_newpath) { + Main *bmain = CTX_data_main(C); Image *ima = ED_space_image(sima); void *lock; ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &lock); @@ -1891,7 +1893,7 @@ static bool save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI if (imf->views_format == R_IMF_VIEWS_MULTIVIEW && is_exr_rr) { /* save render result */ ok = RE_WriteRenderResult(op->reports, rr, simopts->filepath, imf, NULL, sima->iuser.layer); - save_image_post(op, ibuf, ima, ok, true, relbase, relative, do_newpath, simopts->filepath); + save_image_post(bmain, op, ibuf, ima, ok, true, relbase, relative, do_newpath, simopts->filepath); ED_space_image_release_buffer(sima, ibuf, lock); } /* regular mono pipeline */ @@ -1904,7 +1906,7 @@ static bool save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI ok = BKE_imbuf_write_as(colormanaged_ibuf, simopts->filepath, imf, save_copy); save_imbuf_post(ibuf, colormanaged_ibuf); } - save_image_post(op, ibuf, ima, ok, (is_exr_rr ? true : save_copy), relbase, relative, do_newpath, simopts->filepath); + save_image_post(bmain, op, ibuf, ima, ok, (is_exr_rr ? true : save_copy), relbase, relative, do_newpath, simopts->filepath); ED_space_image_release_buffer(sima, ibuf, lock); } /* individual multiview images */ @@ -1926,7 +1928,7 @@ static bool save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI if (is_exr_rr) { BKE_scene_multiview_view_filepath_get(&scene->r, simopts->filepath, view, filepath); ok_view = RE_WriteRenderResult(op->reports, rr, filepath, imf, view, -1); - save_image_post(op, ibuf, ima, ok_view, true, relbase, relative, do_newpath, filepath); + save_image_post(bmain, op, ibuf, ima, ok_view, true, relbase, relative, do_newpath, filepath); } else { /* copy iuser to get the correct ibuf for this view */ @@ -1947,7 +1949,7 @@ static bool save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI colormanaged_ibuf = IMB_colormanagement_imbuf_for_write(ibuf, save_as_render, true, &imf->view_settings, &imf->display_settings, imf); ok_view = BKE_imbuf_write_as(colormanaged_ibuf, filepath, &simopts->im_format, save_copy); save_imbuf_post(ibuf, colormanaged_ibuf); - save_image_post(op, ibuf, ima, ok_view, true, relbase, relative, do_newpath, filepath); + save_image_post(bmain, op, ibuf, ima, ok_view, true, relbase, relative, do_newpath, filepath); BKE_image_release_ibuf(sima->image, ibuf, lock); } ok &= ok_view; @@ -1961,7 +1963,7 @@ static bool save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI else if (simopts->im_format.views_format == R_IMF_VIEWS_STEREO_3D) { if (imf->imtype == R_IMF_IMTYPE_MULTILAYER) { ok = RE_WriteRenderResult(op->reports, rr, simopts->filepath, imf, NULL, -1); - save_image_post(op, ibuf, ima, ok, true, relbase, relative, do_newpath, simopts->filepath); + save_image_post(bmain, op, ibuf, ima, ok, true, relbase, relative, do_newpath, simopts->filepath); ED_space_image_release_buffer(sima, ibuf, lock); } else { @@ -2339,6 +2341,7 @@ void IMAGE_OT_save_sequence(wmOperatorType *ot) static int image_reload_exec(bContext *C, wmOperator *UNUSED(op)) { + Main *bmain = CTX_data_main(C); Image *ima = CTX_data_edit_image(C); SpaceImage *sima = CTX_wm_space_image(C); @@ -2349,7 +2352,7 @@ static int image_reload_exec(bContext *C, wmOperator *UNUSED(op)) ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C)); // XXX other users? - BKE_image_signal(ima, (sima) ? &sima->iuser : NULL, IMA_SIGNAL_RELOAD); + BKE_image_signal(bmain, ima, (sima) ? &sima->iuser : NULL, IMA_SIGNAL_RELOAD); DEG_id_tag_update(&ima->id, 0); WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima); @@ -2441,7 +2444,7 @@ static int image_new_exec(bContext *C, wmOperator *op) RNA_property_update(C, &ptr, prop); } else if (sima) { - ED_space_image_set(sima, scene, obedit, ima); + ED_space_image_set(bmain, sima, scene, obedit, ima); } else if (gen_context == GEN_CONTEXT_PAINT_CANVAS) { bScreen *sc; @@ -2460,7 +2463,7 @@ static int image_new_exec(bContext *C, wmOperator *op) SpaceImage *sima_other = (SpaceImage *)sl; if (!sima_other->pin) { - ED_space_image_set(sima_other, scene, obedit, ima); + ED_space_image_set(bmain, sima_other, scene, obedit, ima); } } } @@ -2487,7 +2490,7 @@ static int image_new_exec(bContext *C, wmOperator *op) } } - BKE_image_signal(ima, (sima) ? &sima->iuser : NULL, IMA_SIGNAL_USER_NEW_IMAGE); + BKE_image_signal(bmain, ima, (sima) ? &sima->iuser : NULL, IMA_SIGNAL_USER_NEW_IMAGE); WM_event_add_notifier(C, NC_IMAGE | NA_ADDED, ima); @@ -3461,7 +3464,7 @@ static int image_cycle_render_slot_exec(bContext *C, wmOperator *op) WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL); /* no undo push for browsing existing */ - if (ima->renders[ima->render_slot] || ima->render_slot == ima->last_render_slot) + if (BKE_image_get_renderslot(ima, ima->render_slot)->render || ima->render_slot == ima->last_render_slot) return OPERATOR_CANCELLED; return OPERATOR_FINISHED; @@ -3484,6 +3487,97 @@ void IMAGE_OT_cycle_render_slot(wmOperatorType *ot) RNA_def_boolean(ot->srna, "reverse", 0, "Cycle in Reverse", ""); } +/********************* clear render slot operator *********************/ + +static int image_clear_render_slot_exec(bContext *C, wmOperator *UNUSED(op)) +{ + SpaceImage *sima = CTX_wm_space_image(C); + Image *ima = CTX_data_edit_image(C); + + if (!BKE_image_clear_renderslot(ima, &sima->iuser, ima->render_slot)) { + return OPERATOR_CANCELLED; + } + + WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL); + + return OPERATOR_FINISHED; +} + +void IMAGE_OT_clear_render_slot(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Clear Render Slot"; + ot->idname = "IMAGE_OT_clear_render_slot"; + ot->description = "Clear the currently selected render slot"; + + /* api callbacks */ + ot->exec = image_clear_render_slot_exec; + ot->poll = image_cycle_render_slot_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER; +} + +/********************* add render slot operator *********************/ + +static int image_add_render_slot_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Image *ima = CTX_data_edit_image(C); + + RenderSlot *slot = BKE_image_add_renderslot(ima, NULL); + ima->render_slot = BLI_findindex(&ima->renderslots, slot); + + WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL); + + return OPERATOR_FINISHED; +} + +void IMAGE_OT_add_render_slot(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Add Render Slot"; + ot->idname = "IMAGE_OT_add_render_slot"; + ot->description = "Add a new render slot"; + + /* api callbacks */ + ot->exec = image_add_render_slot_exec; + ot->poll = image_cycle_render_slot_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER; +} + +/********************* remove render slot operator *********************/ + +static int image_remove_render_slot_exec(bContext *C, wmOperator *UNUSED(op)) +{ + SpaceImage *sima = CTX_wm_space_image(C); + Image *ima = CTX_data_edit_image(C); + + if (!BKE_image_remove_renderslot(ima, &sima->iuser, ima->render_slot)) { + return OPERATOR_CANCELLED; + } + + WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL); + + return OPERATOR_FINISHED; +} + +void IMAGE_OT_remove_render_slot(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Remove Render Slot"; + ot->idname = "IMAGE_OT_remove_render_slot"; + ot->description = "Remove the current render slot"; + + /* api callbacks */ + ot->exec = image_remove_render_slot_exec; + ot->poll = image_cycle_render_slot_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER; +} + /********************** change frame operator *********************/ static int change_frame_poll(bContext *C) @@ -3604,13 +3698,14 @@ void IMAGE_OT_change_frame(wmOperatorType *ot) /* goes over all scenes, reads render layers */ static int image_read_viewlayers_exec(bContext *C, wmOperator *UNUSED(op)) { + Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); SpaceImage *sima = CTX_wm_space_image(C); Image *ima; - ima = BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result"); + ima = BKE_image_verify_viewer(bmain, IMA_TYPE_R_RESULT, "Render Result"); if (sima->image == NULL) { - ED_space_image_set(sima, scene, NULL, ima); + ED_space_image_set(bmain, sima, scene, NULL, ima); } RE_ReadRenderResult(scene, scene); diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index c143ebbcd67..e84b596530e 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -272,6 +272,9 @@ static void image_operatortypes(void) WM_operatortype_append(IMAGE_OT_invert); WM_operatortype_append(IMAGE_OT_cycle_render_slot); + WM_operatortype_append(IMAGE_OT_clear_render_slot); + WM_operatortype_append(IMAGE_OT_add_render_slot); + WM_operatortype_append(IMAGE_OT_remove_render_slot); WM_operatortype_append(IMAGE_OT_sample); WM_operatortype_append(IMAGE_OT_sample_line); @@ -358,7 +361,7 @@ static void image_keymap(struct wmKeyConfig *keyconf) RNA_boolean_set(kmi->ptr, "toggle", true); /* fast switch to render slots */ - for (i = 0; i < MIN2(IMA_MAX_RENDER_SLOT, 9); i++) { + for (i = 0; i < 9; i++) { kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_int", ONEKEY + i, KM_PRESS, 0, 0); RNA_string_set(kmi->ptr, "data_path", "space_data.image.render_slots.active_index"); RNA_int_set(kmi->ptr, "value", i); @@ -869,7 +872,7 @@ static void image_buttons_region_init(wmWindowManager *wm, ARegion *ar) static void image_buttons_region_draw(const bContext *C, ARegion *ar) { - ED_region_panels(C, ar, NULL, -1, true); + ED_region_panels(C, ar); } static void image_buttons_region_listener( @@ -944,7 +947,7 @@ static void image_tools_region_draw(const bContext *C, ARegion *ar) } ED_space_image_release_buffer(sima, ibuf, lock); - ED_region_panels(C, ar, NULL, -1, true); + ED_region_panels(C, ar); } static void image_tools_region_listener( @@ -1096,7 +1099,6 @@ void ED_spacetype_image(void) art->init = image_main_region_init; art->draw = image_main_region_draw; art->listener = image_main_region_listener; - BLI_addhead(&st->regiontypes, art); /* regions: listview/buttons */ @@ -1134,5 +1136,9 @@ void ED_spacetype_image(void) BLI_addhead(&st->regiontypes, art); + /* regions: hud */ + art = ED_area_type_hud(st->spaceid); + BLI_addhead(&st->regiontypes, art); + BKE_spacetype_register(st); } diff --git a/source/blender/editors/space_nla/nla_buttons.c b/source/blender/editors/space_nla/nla_buttons.c index a26e6b0280e..cafb40626ee 100644 --- a/source/blender/editors/space_nla/nla_buttons.c +++ b/source/blender/editors/space_nla/nla_buttons.c @@ -574,7 +574,7 @@ static int nla_properties_toggle_exec(bContext *C, wmOperator *UNUSED(op)) void NLA_OT_properties(wmOperatorType *ot) { - ot->name = "Properties"; + ot->name = "Toggle Sidebar"; ot->idname = "NLA_OT_properties"; ot->description = "Toggle the properties region visibility"; diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c index 26ac06446c4..23cd504978c 100644 --- a/source/blender/editors/space_nla/nla_edit.c +++ b/source/blender/editors/space_nla/nla_edit.c @@ -1057,7 +1057,7 @@ static int nlaedit_duplicate_exec(bContext *C, wmOperator *op) /* if selected, split the strip at its midpoint */ if (strip->flag & NLASTRIP_FLAG_SELECT) { /* make a copy (assume that this is possible) */ - nstrip = BKE_nlastrip_copy(strip, linked); + nstrip = BKE_nlastrip_copy(ac.bmain, strip, linked); /* in case there's no space in the track above, or we haven't got a reference to it yet, try adding */ if (BKE_nlatrack_add_strip(nlt->next, nstrip) == 0) { @@ -1207,7 +1207,7 @@ void NLA_OT_delete(wmOperatorType *ot) // - variable-length splits? /* split a given Action-Clip strip */ -static void nlaedit_split_strip_actclip(AnimData *adt, NlaTrack *nlt, NlaStrip *strip, float cfra) +static void nlaedit_split_strip_actclip(Main *bmain, AnimData *adt, NlaTrack *nlt, NlaStrip *strip, float cfra) { NlaStrip *nstrip; float splitframe, splitaframe; @@ -1242,7 +1242,7 @@ static void nlaedit_split_strip_actclip(AnimData *adt, NlaTrack *nlt, NlaStrip * /* make a copy (assume that this is possible) and append * it immediately after the current strip */ - nstrip = BKE_nlastrip_copy(strip, true); + nstrip = BKE_nlastrip_copy(bmain, strip, true); BLI_insertlinkafter(&nlt->strips, strip, nstrip); /* set the endpoint of the first strip and the start of the new strip @@ -1303,7 +1303,7 @@ static int nlaedit_split_exec(bContext *C, wmOperator *UNUSED(op)) /* splitting method depends on the type of strip */ switch (strip->type) { case NLASTRIP_TYPE_CLIP: /* action-clip */ - nlaedit_split_strip_actclip(adt, nlt, strip, (float)ac.scene->r.cfra); + nlaedit_split_strip_actclip(ac.bmain, adt, nlt, strip, (float)ac.scene->r.cfra); break; case NLASTRIP_TYPE_META: /* meta-strips need special handling */ diff --git a/source/blender/editors/space_nla/space_nla.c b/source/blender/editors/space_nla/space_nla.c index 318d8bf777b..639195c16ac 100644 --- a/source/blender/editors/space_nla/space_nla.c +++ b/source/blender/editors/space_nla/space_nla.c @@ -360,7 +360,7 @@ static void nla_buttons_region_init(wmWindowManager *wm, ARegion *ar) static void nla_buttons_region_draw(const bContext *C, ARegion *ar) { - ED_region_panels(C, ar, NULL, -1, true); + ED_region_panels(C, ar); } static void nla_region_listener( diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index a9120430128..db718da12ef 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -3151,6 +3151,7 @@ void ED_init_node_socket_type_virtual(bNodeSocketType *stype) void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeInstanceKey parent_key) { + Main *bmain = CTX_data_main(C); bNodeInstanceKey active_viewer_key = (snode->nodetree ? snode->nodetree->active_viewer_key : NODE_INSTANCE_KEY_NONE); float shuffle[4] = {0.0f, 0.0f, 0.0f, 0.0f}; Image *ima; @@ -3163,7 +3164,7 @@ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode, b if (parent_key.value != active_viewer_key.value) return; - ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node"); + ima = BKE_image_verify_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node"); ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock); if (ibuf) { float x, y; diff --git a/source/blender/editors/space_node/node_add.c b/source/blender/editors/space_node/node_add.c index 0a8cc838ce5..72b1a35973a 100644 --- a/source/blender/editors/space_node/node_add.c +++ b/source/blender/editors/space_node/node_add.c @@ -304,6 +304,7 @@ void NODE_OT_add_reroute(wmOperatorType *ot) static int node_add_file_exec(bContext *C, wmOperator *op) { + Main *bmain = CTX_data_main(C); SpaceNode *snode = CTX_wm_space_node(C); bNode *node; Image *ima; @@ -343,7 +344,7 @@ static int node_add_file_exec(bContext *C, wmOperator *op) * to get proper image source. */ if (RNA_struct_property_is_set(op->ptr, "filepath")) { - BKE_image_signal(ima, NULL, IMA_SIGNAL_RELOAD); + BKE_image_signal(bmain, ima, NULL, IMA_SIGNAL_RELOAD); WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima); } diff --git a/source/blender/editors/space_node/node_buttons.c b/source/blender/editors/space_node/node_buttons.c index 0a656ee1deb..38183637750 100644 --- a/source/blender/editors/space_node/node_buttons.c +++ b/source/blender/editors/space_node/node_buttons.c @@ -224,7 +224,7 @@ static int node_properties_poll(bContext *C) void NODE_OT_properties(wmOperatorType *ot) { - ot->name = "Properties"; + ot->name = "Toggle Sidebar"; ot->description = "Toggle the properties region visibility"; ot->idname = "NODE_OT_properties"; diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c index 92c055ed12a..8089f47bce4 100644 --- a/source/blender/editors/space_node/node_draw.c +++ b/source/blender/editors/space_node/node_draw.c @@ -165,7 +165,7 @@ void ED_node_tag_update_nodetree(Main *bmain, bNodeTree *ntree, bNode *node) bool do_tag_update = true; if (node != NULL) { - if (!node_connected_to_output(ntree, node)) { + if (!node_connected_to_output(bmain, ntree, node)) { do_tag_update = false; } } diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index 2d1af3f4578..ff87dcf409a 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -88,6 +88,7 @@ enum { }; typedef struct CompoJob { + Main *bmain; Scene *scene; bNodeTree *ntree; bNodeTree *localtree; @@ -183,7 +184,7 @@ static void compo_freejob(void *cjv) CompoJob *cj = cjv; if (cj->localtree) { - ntreeLocalMerge(cj->localtree, cj->ntree); + ntreeLocalMerge(cj->bmain, cj->localtree, cj->ntree); } MEM_freeN(cj); } @@ -267,6 +268,7 @@ void ED_node_composite_job(const bContext *C, struct bNodeTree *nodetree, Scene { wmJob *wm_job; CompoJob *cj; + Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); /* to fix bug: [#32272] */ @@ -278,13 +280,14 @@ void ED_node_composite_job(const bContext *C, struct bNodeTree *nodetree, Scene G.is_break = false; #endif - BKE_image_backup_render(scene, BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result"), false); + BKE_image_backup_render(scene, BKE_image_verify_viewer(bmain, IMA_TYPE_R_RESULT, "Render Result"), false); wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene_owner, "Compositing", WM_JOB_EXCL_RENDER | WM_JOB_PROGRESS, WM_JOB_TYPE_COMPOSITE); cj = MEM_callocN(sizeof(CompoJob), "compo job"); /* customdata for preview thread */ + cj->bmain = bmain; cj->scene = scene; cj->ntree = nodetree; cj->recalc_flags = compo_get_recalc_flags(C); @@ -653,6 +656,7 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node) if (wo->nodetree && wo->use_nodes && ntreeHasTree(wo->nodetree, ntree)) GPU_material_free(&wo->gpumaterial); + ED_node_tag_update_nodetree(bmain, ntree, node); WM_main_add_notifier(NC_IMAGE, NULL); } @@ -673,7 +677,7 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node) ED_node_tag_update_nodetree(bmain, ntree, node); /* addnode() doesnt link this yet... */ - node->id = (ID *)BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node"); + node->id = (ID *)BKE_image_verify_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node"); } else if (node->type == CMP_NODE_COMPOSITE) { if (was_output == 0) { @@ -926,11 +930,13 @@ static int node_resize_modal(bContext *C, wmOperator *op, const wmEvent *event) case LEFTMOUSE: case MIDDLEMOUSE: case RIGHTMOUSE: + if (event->val == KM_RELEASE) { + node_resize_exit(C, op, false); + ED_node_post_apply_transform(C, snode->edittree); - node_resize_exit(C, op, false); - ED_node_post_apply_transform(C, snode->edittree); - - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; + } + break; } return OPERATOR_RUNNING_MODAL; @@ -1102,6 +1108,7 @@ static void node_duplicate_reparent_recursive(bNode *node) static int node_duplicate_exec(bContext *C, wmOperator *op) { + Main *bmain = CTX_data_main(C); SpaceNode *snode = CTX_wm_space_node(C); bNodeTree *ntree = snode->edittree; bNode *node, *newnode, *lastnode; @@ -1109,7 +1116,7 @@ static int node_duplicate_exec(bContext *C, wmOperator *op) const bool keep_inputs = RNA_boolean_get(op->ptr, "keep_inputs"); bool do_tag_update = false; - ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C)); + ED_preview_kill_jobs(CTX_wm_manager(C), bmain); lastnode = ntree->nodes.last; for (node = ntree->nodes.first; node; node = node->next) { @@ -1186,7 +1193,7 @@ static int node_duplicate_exec(bContext *C, wmOperator *op) node->flag &= ~NODE_ACTIVE; nodeSetSelected(newnode, true); - do_tag_update |= (do_tag_update || node_connected_to_output(ntree, newnode)); + do_tag_update |= (do_tag_update || node_connected_to_output(bmain, ntree, newnode)); } /* make sure we don't copy new nodes again! */ @@ -1522,18 +1529,19 @@ void NODE_OT_hide_socket_toggle(wmOperatorType *ot) static int node_mute_exec(bContext *C, wmOperator *UNUSED(op)) { + Main *bmain = CTX_data_main(C); SpaceNode *snode = CTX_wm_space_node(C); bNode *node; bool do_tag_update = false; - ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C)); + ED_preview_kill_jobs(CTX_wm_manager(C), bmain); for (node = snode->edittree->nodes.first; node; node = node->next) { /* Only allow muting of nodes having a mute func! */ if ((node->flag & SELECT) && node->typeinfo->update_internal_links) { node->flag ^= NODE_MUTED; snode_update(snode, node); - do_tag_update |= (do_tag_update || node_connected_to_output(snode->edittree, node)); + do_tag_update |= (do_tag_update || node_connected_to_output(bmain, snode->edittree, node)); } } @@ -1564,17 +1572,18 @@ void NODE_OT_mute_toggle(wmOperatorType *ot) static int node_delete_exec(bContext *C, wmOperator *UNUSED(op)) { + Main *bmain = CTX_data_main(C); SpaceNode *snode = CTX_wm_space_node(C); bNode *node, *next; bool do_tag_update = false; - ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C)); + ED_preview_kill_jobs(CTX_wm_manager(C), bmain); for (node = snode->edittree->nodes.first; node; node = next) { next = node->next; if (node->flag & SELECT) { /* check id user here, nodeFreeNode is called for free dbase too */ - do_tag_update |= (do_tag_update || node_connected_to_output(snode->edittree, node)); + do_tag_update |= (do_tag_update || node_connected_to_output(bmain, snode->edittree, node)); if (node->id) id_us_min(node->id); nodeFreeNode(snode->edittree, node); @@ -2434,13 +2443,14 @@ static void viewer_border_corner_to_backdrop(SpaceNode *snode, ARegion *ar, int static int viewer_border_exec(bContext *C, wmOperator *op) { + Main *bmain = CTX_data_main(C); Image *ima; void *lock; ImBuf *ibuf; - ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C)); + ED_preview_kill_jobs(CTX_wm_manager(C), bmain); - ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node"); + ima = BKE_image_verify_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node"); ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock); if (ibuf) { diff --git a/source/blender/editors/space_node/node_group.c b/source/blender/editors/space_node/node_group.c index 7da3d0bf93d..926fff7a3b6 100644 --- a/source/blender/editors/space_node/node_group.c +++ b/source/blender/editors/space_node/node_group.c @@ -181,7 +181,7 @@ void NODE_OT_group_edit(wmOperatorType *ot) /* ******************** Ungroup operator ********************** */ /* returns 1 if its OK */ -static int node_group_ungroup(bNodeTree *ntree, bNode *gnode) +static int node_group_ungroup(Main *bmain, bNodeTree *ntree, bNode *gnode) { bNodeLink *link, *linkn, *tlink; bNode *node, *nextnode; @@ -200,7 +200,7 @@ static int node_group_ungroup(bNodeTree *ntree, bNode *gnode) * - ngroup (i.e. the source NodeTree) is left unscathed * - temp copy. don't change ID usercount */ - wgroup = ntreeCopyTree_ex(ngroup, G.main, false); + wgroup = ntreeCopyTree_ex(ngroup, bmain, false); /* Add the nodes into the ntree */ for (node = wgroup->nodes.first; node; node = nextnode) { @@ -257,10 +257,10 @@ static int node_group_ungroup(bNodeTree *ntree, bNode *gnode) bAction *waction; /* firstly, wgroup needs to temporary dummy action that can be destroyed, as it shares copies */ - waction = wgroup->adt->action = BKE_action_copy(G.main, wgroup->adt->action); + waction = wgroup->adt->action = BKE_action_copy(bmain, wgroup->adt->action); /* now perform the moving */ - BKE_animdata_separate_by_basepath(&wgroup->id, &ntree->id, &anim_basepaths); + BKE_animdata_separate_by_basepath(bmain, &wgroup->id, &ntree->id, &anim_basepaths); /* paths + their wrappers need to be freed */ for (ld = anim_basepaths.first; ld; ld = ldn) { @@ -272,13 +272,13 @@ static int node_group_ungroup(bNodeTree *ntree, bNode *gnode) /* free temp action too */ if (waction) { - BKE_libblock_free(G.main, waction); + BKE_libblock_free(bmain, waction); wgroup->adt->action = NULL; } } /* free the group tree (takes care of user count) */ - BKE_libblock_free(G.main, wgroup); + BKE_libblock_free(bmain, wgroup); /* restore external links to and from the gnode */ /* note: the nodes have been copied to intermediate wgroup first (so need to use new_node), @@ -354,18 +354,19 @@ static int node_group_ungroup(bNodeTree *ntree, bNode *gnode) static int node_group_ungroup_exec(bContext *C, wmOperator *op) { + Main *bmain = CTX_data_main(C); SpaceNode *snode = CTX_wm_space_node(C); const char *node_idname = group_node_idname(C); bNode *gnode; - ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C)); + ED_preview_kill_jobs(CTX_wm_manager(C), bmain); gnode = node_group_get_active(C, node_idname); if (!gnode) return OPERATOR_CANCELLED; - if (gnode->id && node_group_ungroup(snode->edittree, gnode)) { - ntreeUpdateTree(CTX_data_main(C), snode->nodetree); + if (gnode->id && node_group_ungroup(bmain, snode->edittree, gnode)) { + ntreeUpdateTree(bmain, snode->nodetree); } else { BKE_report(op->reports, RPT_WARNING, "Cannot ungroup"); @@ -396,7 +397,8 @@ void NODE_OT_group_ungroup(wmOperatorType *ot) /* ******************** Separate operator ********************** */ /* returns 1 if its OK */ -static int node_group_separate_selected(bNodeTree *ntree, bNodeTree *ngroup, float offx, float offy, int make_copy) +static int node_group_separate_selected( + Main *bmain, bNodeTree *ntree, bNodeTree *ngroup, float offx, float offy, int make_copy) { bNodeLink *link, *link_next; bNode *node, *node_next, *newnode; @@ -491,7 +493,7 @@ static int node_group_separate_selected(bNodeTree *ntree, bNodeTree *ngroup, flo LinkData *ld, *ldn = NULL; /* now perform the moving */ - BKE_animdata_separate_by_basepath(&ngroup->id, &ntree->id, &anim_basepaths); + BKE_animdata_separate_by_basepath(bmain, &ngroup->id, &ntree->id, &anim_basepaths); /* paths + their wrappers need to be freed */ for (ld = anim_basepaths.first; ld; ld = ldn) { @@ -523,12 +525,13 @@ static const EnumPropertyItem node_group_separate_types[] = { static int node_group_separate_exec(bContext *C, wmOperator *op) { + Main *bmain = CTX_data_main(C); SpaceNode *snode = CTX_wm_space_node(C); bNodeTree *ngroup, *nparent; int type = RNA_enum_get(op->ptr, "type"); float offx, offy; - ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C)); + ED_preview_kill_jobs(CTX_wm_manager(C), bmain); /* are we inside of a group? */ ngroup = snode->edittree; @@ -542,13 +545,13 @@ static int node_group_separate_exec(bContext *C, wmOperator *op) switch (type) { case NODE_GS_COPY: - if (!node_group_separate_selected(nparent, ngroup, offx, offy, 1)) { + if (!node_group_separate_selected(bmain, nparent, ngroup, offx, offy, 1)) { BKE_report(op->reports, RPT_WARNING, "Cannot separate nodes"); return OPERATOR_CANCELLED; } break; case NODE_GS_MOVE: - if (!node_group_separate_selected(nparent, ngroup, offx, offy, 0)) { + if (!node_group_separate_selected(bmain, nparent, ngroup, offx, offy, 0)) { BKE_report(op->reports, RPT_WARNING, "Cannot separate nodes"); return OPERATOR_CANCELLED; } @@ -680,6 +683,7 @@ static int node_get_selected_minmax(bNodeTree *ntree, bNode *gnode, float *min, static void node_group_make_insert_selected(const bContext *C, bNodeTree *ntree, bNode *gnode) { + Main *bmain = CTX_data_main(C); bNodeTree *ngroup = (bNodeTree *)gnode->id; bNodeLink *link, *linkn; bNode *node, *nextn; @@ -741,7 +745,7 @@ static void node_group_make_insert_selected(const bContext *C, bNodeTree *ntree, if (ntree->adt) { LinkData *ld, *ldn = NULL; - BKE_animdata_separate_by_basepath(&ntree->id, &ngroup->id, &anim_basepaths); + BKE_animdata_separate_by_basepath(bmain, &ntree->id, &ngroup->id, &anim_basepaths); /* paths + their wrappers need to be freed */ for (ld = anim_basepaths.first; ld; ld = ldn) { diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h index 4440b2c6ecd..2cc37a4e0fe 100644 --- a/source/blender/editors/space_node/node_intern.h +++ b/source/blender/editors/space_node/node_intern.h @@ -41,6 +41,7 @@ struct ARegion; struct ARegionType; struct View2D; struct bContext; +struct Main; struct wmWindow; struct bNode; struct bNodeSocket; @@ -157,7 +158,7 @@ void NODE_OT_group_edit(struct wmOperatorType *ot); /* node_relationships.c */ -bool node_connected_to_output(struct bNodeTree *ntree, struct bNode *node); +bool node_connected_to_output(struct Main *bmain, struct bNodeTree *ntree, struct bNode *node); void NODE_OT_link(struct wmOperatorType *ot); void NODE_OT_link_make(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_node/node_manipulators.c b/source/blender/editors/space_node/node_manipulators.c index 73b0f44b043..851e3973288 100644 --- a/source/blender/editors/space_node/node_manipulators.c +++ b/source/blender/editors/space_node/node_manipulators.c @@ -31,6 +31,7 @@ #include "BKE_context.h" #include "BKE_image.h" +#include "BKE_main.h" #include "ED_screen.h" #include "ED_manipulator_library.h" @@ -140,13 +141,14 @@ static void WIDGETGROUP_node_transform_setup(const bContext *UNUSED(C), wmManipu static void WIDGETGROUP_node_transform_refresh(const bContext *C, wmManipulatorGroup *mgroup) { + Main *bmain = CTX_data_main(C); wmManipulator *cage = ((wmManipulatorWrapper *)mgroup->customdata)->manipulator; const ARegion *ar = CTX_wm_region(C); /* center is always at the origin */ const float origin[3] = {ar->winx / 2, ar->winy / 2}; void *lock; - Image *ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node"); + Image *ima = BKE_image_verify_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node"); ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock); if (ibuf) { @@ -340,11 +342,12 @@ static void WIDGETGROUP_node_crop_draw_prepare(const bContext *C, wmManipulatorG static void WIDGETGROUP_node_crop_refresh(const bContext *C, wmManipulatorGroup *mgroup) { + Main *bmain = CTX_data_main(C); struct NodeCropWidgetGroup *crop_group = mgroup->customdata; wmManipulator *mpr = crop_group->border; void *lock; - Image *ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node"); + Image *ima = BKE_image_verify_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node"); ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock); if (ibuf) { @@ -451,11 +454,12 @@ static void WIDGETGROUP_node_sbeam_draw_prepare(const bContext *C, wmManipulator static void WIDGETGROUP_node_sbeam_refresh(const bContext *C, wmManipulatorGroup *mgroup) { + Main *bmain = CTX_data_main(C); struct NodeSunBeamsWidgetGroup *sbeam_group = mgroup->customdata; wmManipulator *mpr = sbeam_group->manipulator; void *lock; - Image *ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node"); + Image *ima = BKE_image_verify_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node"); ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock); if (ibuf) { @@ -563,10 +567,11 @@ static void WIDGETGROUP_node_corner_pin_draw_prepare(const bContext *C, wmManipu static void WIDGETGROUP_node_corner_pin_refresh(const bContext *C, wmManipulatorGroup *mgroup) { + Main *bmain = CTX_data_main(C); struct NodeCornerPinWidgetGroup *cpin_group = mgroup->customdata; void *lock; - Image *ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node"); + Image *ima = BKE_image_verify_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node"); ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock); if (ibuf) { diff --git a/source/blender/editors/space_node/node_relationships.c b/source/blender/editors/space_node/node_relationships.c index 682174ebbed..e4c59bc9508 100644 --- a/source/blender/editors/space_node/node_relationships.c +++ b/source/blender/editors/space_node/node_relationships.c @@ -131,9 +131,8 @@ static bool node_group_has_output_dfs(bNode *node) return false; } -static bool node_group_has_output(bNode *node) +static bool node_group_has_output(Main *bmain, bNode *node) { - Main *bmain = G.main; BLI_assert(node->type == NODE_GROUP); bNodeTree *ntree = (bNodeTree *)node->id; if (ntree == NULL) { @@ -143,7 +142,7 @@ static bool node_group_has_output(bNode *node) return node_group_has_output_dfs(node); } -bool node_connected_to_output(bNodeTree *ntree, bNode *node) +bool node_connected_to_output(Main *bmain, bNodeTree *ntree, bNode *node) { /* Special case for drivers: if node tree has any drivers we assume it is * always to be tagged for update when node changes. Otherwise we will be @@ -170,7 +169,7 @@ bool node_connected_to_output(bNodeTree *ntree, bNode *node) return true; } if (ntree_check_nodes_connected(ntree, node, current_node) && - node_group_has_output(current_node)) + node_group_has_output(bmain, current_node)) { return true; } @@ -313,7 +312,7 @@ static bool snode_autoconnect_input(SpaceNode *snode, bNode *node_fr, bNodeSocke return true; } -static void snode_autoconnect(SpaceNode *snode, const bool allow_multiple, const bool replace) +static void snode_autoconnect(Main *bmain, SpaceNode *snode, const bool allow_multiple, const bool replace) { bNodeTree *ntree = snode->edittree; ListBase *nodelist = MEM_callocN(sizeof(ListBase), "items_list"); @@ -390,7 +389,7 @@ static void snode_autoconnect(SpaceNode *snode, const bool allow_multiple, const } if (numlinks > 0) { - ntreeUpdateTree(G.main, ntree); + ntreeUpdateTree(bmain, ntree); } BLI_freelistN(nodelist); @@ -582,6 +581,7 @@ static void node_remove_extra_links(SpaceNode *snode, bNodeLink *link) static void node_link_exit(bContext *C, wmOperator *op, bool apply_links) { + Main *bmain = CTX_data_main(C); SpaceNode *snode = CTX_wm_space_node(C); bNodeTree *ntree = snode->edittree; bNodeLinkDrag *nldrag = op->customdata; @@ -620,7 +620,7 @@ static void node_link_exit(bContext *C, wmOperator *op, bool apply_links) node_remove_extra_links(snode, link); if (link->tonode) { - do_tag_update |= (do_tag_update || node_connected_to_output(ntree, link->tonode)); + do_tag_update |= (do_tag_update || node_connected_to_output(bmain, ntree, link->tonode)); } } else { @@ -629,7 +629,7 @@ static void node_link_exit(bContext *C, wmOperator *op, bool apply_links) } ntree->is_updating = false; - ntreeUpdateTree(CTX_data_main(C), ntree); + ntreeUpdateTree(bmain, ntree); snode_notify(C, snode); if (do_tag_update) { snode_dag_update(C, snode); @@ -741,7 +741,7 @@ static int node_link_modal(bContext *C, wmOperator *op, const wmEvent *event) } /* return 1 when socket clicked */ -static bNodeLinkDrag *node_link_init(SpaceNode *snode, float cursor[2], bool detach) +static bNodeLinkDrag *node_link_init(Main *bmain, SpaceNode *snode, float cursor[2], bool detach) { bNode *node; bNodeSocket *sock; @@ -775,7 +775,7 @@ static bNodeLinkDrag *node_link_init(SpaceNode *snode, float cursor[2], bool det * using TEST flag. */ oplink->flag &= ~NODE_LINK_TEST; - if (node_connected_to_output(snode->edittree, link->tonode)) { + if (node_connected_to_output(bmain, snode->edittree, link->tonode)) { oplink->flag |= NODE_LINK_TEST; } @@ -794,7 +794,7 @@ static bNodeLinkDrag *node_link_init(SpaceNode *snode, float cursor[2], bool det oplink->fromsock = sock; oplink->flag |= NODE_LINK_VALID; oplink->flag &= ~NODE_LINK_TEST; - if (node_connected_to_output(snode->edittree, node)) { + if (node_connected_to_output(bmain, snode->edittree, node)) { oplink->flag |= NODE_LINK_TEST; } @@ -819,7 +819,7 @@ static bNodeLinkDrag *node_link_init(SpaceNode *snode, float cursor[2], bool det oplink->next = oplink->prev = NULL; oplink->flag |= NODE_LINK_VALID; oplink->flag &= ~NODE_LINK_TEST; - if (node_connected_to_output(snode->edittree, link->tonode)) { + if (node_connected_to_output(bmain, snode->edittree, link->tonode)) { oplink->flag |= NODE_LINK_TEST; } @@ -842,7 +842,7 @@ static bNodeLinkDrag *node_link_init(SpaceNode *snode, float cursor[2], bool det oplink->tosock = sock; oplink->flag |= NODE_LINK_VALID; oplink->flag &= ~NODE_LINK_TEST; - if (node_connected_to_output(snode->edittree, node)) { + if (node_connected_to_output(bmain, snode->edittree, node)) { oplink->flag |= NODE_LINK_TEST; } @@ -855,6 +855,7 @@ static bNodeLinkDrag *node_link_init(SpaceNode *snode, float cursor[2], bool det static int node_link_invoke(bContext *C, wmOperator *op, const wmEvent *event) { + Main *bmain = CTX_data_main(C); SpaceNode *snode = CTX_wm_space_node(C); ARegion *ar = CTX_wm_region(C); bNodeLinkDrag *nldrag; @@ -865,9 +866,9 @@ static int node_link_invoke(bContext *C, wmOperator *op, const wmEvent *event) UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &cursor[0], &cursor[1]); - ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C)); + ED_preview_kill_jobs(CTX_wm_manager(C), bmain); - nldrag = node_link_init(snode, cursor, detach); + nldrag = node_link_init(bmain, snode, cursor, detach); if (nldrag) { op->customdata = nldrag; @@ -918,12 +919,13 @@ void NODE_OT_link(wmOperatorType *ot) /* makes a link between selected output and input sockets */ static int node_make_link_exec(bContext *C, wmOperator *op) { + Main *bmain = CTX_data_main(C); SpaceNode *snode = CTX_wm_space_node(C); const bool replace = RNA_boolean_get(op->ptr, "replace"); - ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C)); + ED_preview_kill_jobs(CTX_wm_manager(C), bmain); - snode_autoconnect(snode, 1, replace); + snode_autoconnect(bmain, snode, 1, replace); /* deselect sockets after linking */ node_deselect_all_input_sockets(snode, 0); @@ -971,6 +973,7 @@ static bool cut_links_intersect(bNodeLink *link, float mcoords[][2], int tot) static int cut_links_exec(bContext *C, wmOperator *op) { + Main *bmain = CTX_data_main(C); SpaceNode *snode = CTX_wm_space_node(C); ARegion *ar = CTX_wm_region(C); float mcoords[256][2]; @@ -993,7 +996,7 @@ static int cut_links_exec(bContext *C, wmOperator *op) bool found = false; bNodeLink *link, *next; - ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C)); + ED_preview_kill_jobs(CTX_wm_manager(C), bmain); for (link = snode->edittree->links.first; link; link = next) { next = link->next; @@ -1004,11 +1007,11 @@ static int cut_links_exec(bContext *C, wmOperator *op) if (found == false) { /* TODO(sergey): Why did we kill jobs twice? */ - ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C)); + ED_preview_kill_jobs(CTX_wm_manager(C), bmain); found = true; } - do_tag_update |= (do_tag_update || node_connected_to_output(snode->edittree, link->tonode)); + do_tag_update |= (do_tag_update || node_connected_to_output(bmain, snode->edittree, link->tonode)); snode_update(snode, link->tonode); nodeRemLink(snode->edittree, link); @@ -1833,7 +1836,7 @@ void NODE_OT_insert_offset(wmOperatorType *ot) } /* assumes link with NODE_LINKFLAG_HILITE set */ -void ED_node_link_insert(ScrArea *sa) +void ED_node_link_insert(Main *bmain, ScrArea *sa) { bNode *node, *select; SpaceNode *snode; @@ -1873,7 +1876,7 @@ void ED_node_link_insert(ScrArea *sa) snode->iofsd = iofsd; } - ntreeUpdateTree(G.main, snode->edittree); /* needed for pointers */ + ntreeUpdateTree(bmain, snode->edittree); /* needed for pointers */ snode_update(snode, select); ED_node_tag_update_id(snode->id); } diff --git a/source/blender/editors/space_node/node_templates.c b/source/blender/editors/space_node/node_templates.c index 5a2feacf20c..23fd793cdd3 100644 --- a/source/blender/editors/space_node/node_templates.c +++ b/source/blender/editors/space_node/node_templates.c @@ -82,11 +82,11 @@ static bool node_link_item_compare(bNode *node, NodeLinkItem *item) return true; } -static void node_link_item_apply(bNode *node, NodeLinkItem *item) +static void node_link_item_apply(Main *bmain, bNode *node, NodeLinkItem *item) { if (node->type == NODE_GROUP) { node->id = (ID *)item->ngroup; - ntreeUpdateTree(G.main, item->ngroup); + ntreeUpdateTree(bmain, item->ngroup); } else { /* nothing to do for now */ @@ -191,6 +191,7 @@ static void node_socket_remove(Main *bmain, bNodeTree *ntree, bNode *node_to, bN static void node_socket_add_replace(const bContext *C, bNodeTree *ntree, bNode *node_to, bNodeSocket *sock_to, int type, NodeLinkItem *item) { + Main *bmain = CTX_data_main(C); bNode *node_from; bNodeSocket *sock_from_tmp; bNode *node_prev = NULL; @@ -233,7 +234,7 @@ static void node_socket_add_replace(const bContext *C, bNodeTree *ntree, bNode * node_from->locy = node_to->locy - (node_from->typeinfo->height * index); } - node_link_item_apply(node_from, item); + node_link_item_apply(bmain, node_from, item); } nodeSetActive(ntree, node_from); diff --git a/source/blender/editors/space_node/node_view.c b/source/blender/editors/space_node/node_view.c index d52a6a89413..00eab0c69c1 100644 --- a/source/blender/editors/space_node/node_view.c +++ b/source/blender/editors/space_node/node_view.c @@ -36,8 +36,9 @@ #include "BKE_context.h" #include "BKE_image.h" -#include "BKE_screen.h" +#include "BKE_main.h" #include "BKE_node.h" +#include "BKE_screen.h" #include "ED_node.h" /* own include */ #include "ED_screen.h" @@ -238,6 +239,7 @@ static int snode_bg_viewmove_modal(bContext *C, wmOperator *op, const wmEvent *e static int snode_bg_viewmove_invoke(bContext *C, wmOperator *op, const wmEvent *event) { + Main *bmain = CTX_data_main(C); SpaceNode *snode = CTX_wm_space_node(C); ARegion *ar = CTX_wm_region(C); NodeViewMove *nvm; @@ -247,7 +249,7 @@ static int snode_bg_viewmove_invoke(bContext *C, wmOperator *op, const wmEvent * void *lock; - ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node"); + ima = BKE_image_verify_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node"); ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock); if (ibuf == NULL) { @@ -331,6 +333,7 @@ void NODE_OT_backimage_zoom(wmOperatorType *ot) static int backimage_fit_exec(bContext *C, wmOperator *UNUSED(op)) { + Main *bmain = CTX_data_main(C); SpaceNode *snode = CTX_wm_space_node(C); ARegion *ar = CTX_wm_region(C); @@ -343,7 +346,7 @@ static int backimage_fit_exec(bContext *C, wmOperator *UNUSED(op)) float facx, facy; - ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node"); + ima = BKE_image_verify_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node"); ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock); if ((ibuf == NULL) || (ibuf->x == 0) || (ibuf->y == 0)) { @@ -421,7 +424,7 @@ static void sample_draw(const bContext *C, ARegion *ar, void *arg_info) /* Returns color in linear space, matching ED_space_image_color_sample(). * And here we've got recursion in the comments tips... */ -bool ED_space_node_color_sample(SpaceNode *snode, ARegion *ar, int mval[2], float r_col[3]) +bool ED_space_node_color_sample(Main *bmain, SpaceNode *snode, ARegion *ar, int mval[2], float r_col[3]) { void *lock; Image *ima; @@ -436,7 +439,7 @@ bool ED_space_node_color_sample(SpaceNode *snode, ARegion *ar, int mval[2], floa return false; } - ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node"); + ima = BKE_image_verify_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node"); ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock); if (!ibuf) { return false; @@ -477,6 +480,7 @@ bool ED_space_node_color_sample(SpaceNode *snode, ARegion *ar, int mval[2], floa static void sample_apply(bContext *C, wmOperator *op, const wmEvent *event) { + Main *bmain = CTX_data_main(C); SpaceNode *snode = CTX_wm_space_node(C); ARegion *ar = CTX_wm_region(C); ImageSampleInfo *info = op->customdata; @@ -485,7 +489,7 @@ static void sample_apply(bContext *C, wmOperator *op, const wmEvent *event) ImBuf *ibuf; float fx, fy, bufx, bufy; - ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node"); + ima = BKE_image_verify_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node"); ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock); if (!ibuf) { info->draw = 0; diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c index 36886d0ab32..441ab03cb28 100644 --- a/source/blender/editors/space_node/space_node.c +++ b/source/blender/editors/space_node/space_node.c @@ -603,7 +603,7 @@ static void node_buttons_region_init(wmWindowManager *wm, ARegion *ar) static void node_buttons_region_draw(const bContext *C, ARegion *ar) { - ED_region_panels(C, ar, NULL, -1, true); + ED_region_panels(C, ar); } /* add handlers, stuff you only do once or on area/region changes */ @@ -619,7 +619,7 @@ static void node_toolbar_region_init(wmWindowManager *wm, ARegion *ar) static void node_toolbar_region_draw(const bContext *C, ARegion *ar) { - ED_region_panels(C, ar, NULL, -1, true); + ED_region_panels(C, ar); } static void node_cursor(wmWindow *win, ScrArea *sa, ARegion *ar) diff --git a/source/blender/editors/space_outliner/outliner_collections.c b/source/blender/editors/space_outliner/outliner_collections.c index 909938ad606..a700f8e20e0 100644 --- a/source/blender/editors/space_outliner/outliner_collections.c +++ b/source/blender/editors/space_outliner/outliner_collections.c @@ -320,7 +320,10 @@ static int collection_objects_select_exec(bContext *C, wmOperator *op) } BKE_layer_collection_objects_select(view_layer, layer_collection, deselect); - WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, CTX_data_scene(C)); + + Scene *scene = CTX_data_scene(C); + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); + WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, scene); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c index 2a694e2e2e3..c6288dc05ef 100644 --- a/source/blender/editors/space_outliner/outliner_edit.c +++ b/source/blender/editors/space_outliner/outliner_edit.c @@ -63,6 +63,7 @@ #include "BKE_scene.h" #include "BKE_material.h" +#include "DEG_depsgraph.h" #include "DEG_depsgraph_build.h" #include "../blenloader/BLO_readfile.h" @@ -901,6 +902,7 @@ static int outliner_toggle_selected_exec(bContext *C, wmOperator *UNUSED(op)) else outliner_set_flag(&soops->tree, TSE_SELECTED, 1); + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); ED_region_tag_redraw_no_rebuild(ar); @@ -2169,6 +2171,7 @@ static int scene_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event) DEG_relations_tag_update(bmain); + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, scene); return OPERATOR_FINISHED; diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c index af1b11b28d2..f2ba00190e0 100644 --- a/source/blender/editors/space_outliner/outliner_select.c +++ b/source/blender/editors/space_outliner/outliner_select.c @@ -81,6 +81,7 @@ static void do_outliner_activate_obdata(bContext *C, Scene *scene, ViewLayer *vi if (obact == NULL) { ED_object_base_activate(C, base); + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); obact = base->object; use_all = true; @@ -104,6 +105,7 @@ static void do_outliner_activate_obdata(bContext *C, Scene *scene, ViewLayer *vi } if (ok) { ED_object_base_select(base, (ob->mode & OB_MODE_EDIT) ? BA_SELECT : BA_DESELECT); + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); } } @@ -118,6 +120,7 @@ static void do_outliner_activate_pose(bContext *C, ViewLayer *view_layer, Base * if (obact == NULL) { ED_object_base_activate(C, base); Scene *scene = CTX_data_scene(C); + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); obact = base->object; use_all = true; @@ -144,6 +147,7 @@ static void do_outliner_activate_pose(bContext *C, ViewLayer *view_layer, Base * ED_object_base_select(base, (ob->mode & OB_MODE_POSE) ? BA_SELECT : BA_DESELECT); Scene *scene = CTX_data_scene(C); + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_OBJECT, NULL); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); } @@ -297,6 +301,7 @@ static eOLDrawState tree_element_set_active_object( if (set != OL_SETSEL_NONE) { ED_object_base_activate(C, base); /* adds notifier */ + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); } @@ -941,18 +946,22 @@ static void do_outliner_item_activate_tree_element( if (extend) { int sel = BA_SELECT; - FOREACH_COLLECTION_BASE_RECURSIVE_BEGIN(gr, base) + FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(gr, object) { - if (base->flag & BASE_SELECTED) { + Base *base = BKE_view_layer_base_find(view_layer, object); + if (base && (base->flag & BASE_SELECTED)) { sel = BA_DESELECT; break; } } - FOREACH_COLLECTION_BASE_RECURSIVE_END + FOREACH_COLLECTION_OBJECT_RECURSIVE_END; FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(gr, object) { - ED_object_base_select(BKE_view_layer_base_find(view_layer, object), sel); + Base *base = BKE_view_layer_base_find(view_layer, object); + if (base) { + ED_object_base_select(base, sel); + } } FOREACH_COLLECTION_OBJECT_RECURSIVE_END; } @@ -972,6 +981,7 @@ static void do_outliner_item_activate_tree_element( FOREACH_COLLECTION_OBJECT_RECURSIVE_END; } + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); } else if (OB_DATA_SUPPORT_EDITMODE(te->idcode)) { @@ -1172,6 +1182,7 @@ static int outliner_border_select_exec(bContext *C, wmOperator *op) outliner_item_border_select(scene, &rectf, te, select); } + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); ED_region_tag_redraw(ar); diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c index 8a01e5a7f2f..f8d9877be6e 100644 --- a/source/blender/editors/space_outliner/outliner_tools.c +++ b/source/blender/editors/space_outliner/outliner_tools.c @@ -893,6 +893,7 @@ static void object_delete_hierarchy_cb( #endif } + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); } @@ -947,6 +948,7 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op) } str = "Select Objects"; + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); } else if (event == OL_OP_SELECT_HIERARCHY) { @@ -956,11 +958,13 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op) WM_window_change_active_scene(bmain, C, win, sce); } str = "Select Object Hierarchy"; + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); } else if (event == OL_OP_DESELECT) { outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, object_deselect_cb); str = "Deselect Objects"; + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); } else if (event == OL_OP_DELETE) { @@ -975,6 +979,7 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op) DEG_relations_tag_update(bmain); str = "Delete Objects"; + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); } else if (event == OL_OP_DELETE_HIERARCHY) { @@ -985,6 +990,7 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op) DEG_relations_tag_update(bmain); str = "Delete Object Hierarchy"; + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); } else if (event == OL_OP_REMAP) { diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c index 75734963a0e..fc47934bc1e 100644 --- a/source/blender/editors/space_sequencer/space_sequencer.c +++ b/source/blender/editors/space_sequencer/space_sequencer.c @@ -708,7 +708,7 @@ static void sequencer_buttons_region_init(wmWindowManager *wm, ARegion *ar) static void sequencer_buttons_region_draw(const bContext *C, ARegion *ar) { - ED_region_panels(C, ar, NULL, -1, true); + ED_region_panels(C, ar); } static void sequencer_buttons_region_listener( diff --git a/source/blender/editors/space_text/space_text.c b/source/blender/editors/space_text/space_text.c index 5885312e255..e827f4f0149 100644 --- a/source/blender/editors/space_text/space_text.c +++ b/source/blender/editors/space_text/space_text.c @@ -551,7 +551,7 @@ static void text_properties_region_draw(const bContext *C, ARegion *ar) { SpaceText *st = CTX_wm_space_text(C); - ED_region_panels(C, ar, NULL, -1, true); + ED_region_panels(C, ar); /* this flag trick is make sure buttons have been added already */ if (st->flags & ST_FIND_ACTIVATE) { diff --git a/source/blender/editors/space_text/text_header.c b/source/blender/editors/space_text/text_header.c index 50a8739c5b4..3d964d07908 100644 --- a/source/blender/editors/space_text/text_header.c +++ b/source/blender/editors/space_text/text_header.c @@ -91,7 +91,7 @@ static int text_properties_exec(bContext *C, wmOperator *UNUSED(op)) void TEXT_OT_properties(wmOperatorType *ot) { /* identifiers */ - ot->name = "Properties"; + ot->name = "Toggle Sidebar"; ot->description = "Toggle the properties region visibility"; ot->idname = "TEXT_OT_properties"; diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c index b3815d73c5c..eb014af2d59 100644 --- a/source/blender/editors/space_text/text_ops.c +++ b/source/blender/editors/space_text/text_ops.c @@ -2071,7 +2071,9 @@ void TEXT_OT_delete(wmOperatorType *ot) ot->flag = OPTYPE_UNDO; /* properties */ - RNA_def_enum(ot->srna, "type", delete_type_items, DEL_NEXT_CHAR, "Type", "Which part of the text to delete"); + PropertyRNA *prop; + prop = RNA_def_enum(ot->srna, "type", delete_type_items, DEL_NEXT_CHAR, "Type", "Which part of the text to delete"); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } /******************* toggle overwrite operator **********************/ diff --git a/source/blender/editors/space_topbar/space_topbar.c b/source/blender/editors/space_topbar/space_topbar.c index 4342fa87f89..c7ef6591c0d 100644 --- a/source/blender/editors/space_topbar/space_topbar.c +++ b/source/blender/editors/space_topbar/space_topbar.c @@ -57,9 +57,6 @@ #include "WM_types.h" #include "WM_message.h" - -void topbar_panels_register(ARegionType *art); - /* ******************** default callbacks for topbar space ***************** */ static SpaceLink *topbar_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scene)) @@ -277,64 +274,9 @@ void ED_spacetype_topbar(void) art->layout = ED_region_header_layout; art->draw = ED_region_header_draw; - /* For popovers. */ - topbar_panels_register(art); - BLI_addhead(&st->regiontypes, art); recent_files_menu_register(); BKE_spacetype_register(st); } - - -/* -------------------------------------------------------------------- */ -/** \name Redo Panel - * \{ */ - -static int topbar_panel_operator_redo_poll(const bContext *C, PanelType *UNUSED(pt)) -{ - wmOperator *op = WM_operator_last_redo(C); - if (op == NULL) { - return false; - } - - bool success = false; - if (!WM_operator_check_ui_empty(op->type)) { - const OperatorRepeatContextHandle *context_info; - context_info = ED_operator_repeat_prepare_context((bContext *)C, op); - success = WM_operator_poll((bContext *)C, op->type); - ED_operator_repeat_reset_context((bContext *)C, context_info); - } - return success; -} - -static void topbar_panel_operator_redo(const bContext *C, Panel *pa) -{ - wmOperator *op = WM_operator_last_redo(C); - if (op == NULL) { - return; - } - if (!WM_operator_check_ui_enabled(C, op->type->name)) { - uiLayoutSetEnabled(pa->layout, false); - } - uiLayout *col = uiLayoutColumn(pa->layout, false); - uiTemplateOperatorRedoProperties(col, C); -} - -void topbar_panels_register(ARegionType *art) -{ - PanelType *pt; - - pt = MEM_callocN(sizeof(PanelType), __func__); - strcpy(pt->idname, "TOPBAR_PT_redo"); - strcpy(pt->label, N_("Redo")); - strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); - pt->draw = topbar_panel_operator_redo; - pt->poll = topbar_panel_operator_redo_poll; - pt->space_type = SPACE_TOPBAR; - pt->region_type = RGN_TYPE_HEADER; - BLI_addtail(&art->paneltypes, pt); -} - -/** \} */ diff --git a/source/blender/editors/space_userpref/space_userpref.c b/source/blender/editors/space_userpref/space_userpref.c index b3f45de518b..1d3c24c518a 100644 --- a/source/blender/editors/space_userpref/space_userpref.c +++ b/source/blender/editors/space_userpref/space_userpref.c @@ -64,7 +64,7 @@ static SpaceLink *userpref_new(const ScrArea *UNUSED(area), const Scene *UNUSED( BLI_addtail(&spref->regionbase, ar); ar->regiontype = RGN_TYPE_HEADER; - ar->alignment = RGN_ALIGN_TOP; + ar->alignment = RGN_ALIGN_BOTTOM; /* main region */ ar = MEM_callocN(sizeof(ARegion), "main region for userpref"); @@ -113,7 +113,7 @@ static void userpref_main_region_init(wmWindowManager *wm, ARegion *ar) static void userpref_main_region_draw(const bContext *C, ARegion *ar) { - ED_region_panels(C, ar, NULL, -1, true); + ED_region_panels(C, ar); } static void userpref_operatortypes(void) diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index 7b395153417..3c98bc6d863 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -820,7 +820,6 @@ static void view3d_main_region_listener( break; case ND_OB_ACTIVE: case ND_OB_SELECT: - DEG_id_tag_update((ID *)&scene->id, DEG_TAG_SELECT_UPDATE); ATTR_FALLTHROUGH; case ND_FRAME: case ND_TRANSFORM: @@ -875,18 +874,6 @@ static void view3d_main_region_listener( case ND_SELECT: { WM_manipulatormap_tag_refresh(mmap); - - ID *ob_data = wmn->reference; - if (ob_data == NULL) { - BLI_assert(wmn->window); // Use `WM_event_add_notifier` instead of `WM_main_add_notifier` - ViewLayer *view_layer = WM_window_get_active_view_layer(wmn->window); - ob_data = OBEDIT_FROM_VIEW_LAYER(view_layer)->data; - } - if (ob_data) { - BLI_assert(OB_DATA_SUPPORT_ID(GS(ob_data->name))); - /* TODO(sergey): Notifiers shouldn't really be doing DEG tags. */ - DEG_id_tag_update(ob_data, DEG_TAG_SELECT_UPDATE); - } ATTR_FALLTHROUGH; } case ND_DATA: @@ -1232,7 +1219,7 @@ static void view3d_buttons_region_init(wmWindowManager *wm, ARegion *ar) static void view3d_buttons_region_draw(const bContext *C, ARegion *ar) { - ED_region_panels(C, ar, NULL, -1, true); + ED_region_panels(C, ar); } static void view3d_buttons_region_listener( @@ -1331,7 +1318,7 @@ static int view3d_tools_region_snap_size(const ARegion *ar, int size, int axis) { if (axis == 0) { /* Note, this depends on the icon size: see #ICON_DEFAULT_HEIGHT_TOOLBAR. */ - const float snap_units[] = {3 + 0.25f, 5 + 0.25}; + const float snap_units[] = {2 + 0.8f, 4 + 0.8f}; const float aspect = BLI_rctf_size_x(&ar->v2d.cur) / (BLI_rcti_size_x(&ar->v2d.mask) + 1); int best_diff = INT_MAX; int best_size = size; @@ -1361,7 +1348,7 @@ static void view3d_tools_region_init(wmWindowManager *wm, ARegion *ar) static void view3d_tools_region_draw(const bContext *C, ARegion *ar) { - ED_region_panels(C, ar, (const char * []){CTX_data_mode_string(C), NULL}, -1, true); + ED_region_panels_ex(C, ar, (const char * []){CTX_data_mode_string(C), NULL}, -1, true); } /* area (not region) level listener */ @@ -1565,5 +1552,9 @@ void ED_spacetype_view3d(void) art->message_subscribe = view3d_header_region_message_subscribe; BLI_addhead(&st->regiontypes, art); + /* regions: hud */ + art = ED_area_type_hud(st->spaceid); + BLI_addhead(&st->regiontypes, art); + BKE_spacetype_register(st); } diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c index 69e8aa07d3f..300b6fafd7a 100644 --- a/source/blender/editors/space_view3d/view3d_buttons.c +++ b/source/blender/editors/space_view3d/view3d_buttons.c @@ -1197,7 +1197,7 @@ static int view3d_properties_toggle_exec(bContext *C, wmOperator *UNUSED(op)) void VIEW3D_OT_properties(wmOperatorType *ot) { - ot->name = "Properties"; + ot->name = "Toggle Sidebar"; ot->description = "Toggle the properties region visibility"; ot->idname = "VIEW3D_OT_properties"; diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index e199e84029e..fd2f604651b 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -777,8 +777,13 @@ static void draw_view_axis(RegionView3D *rv3d, const rcti *rect) const float k = U.rvisize * U.pixelsize; /* axis size */ const int bright = - 20 * (10 - U.rvibright); /* axis alpha offset (rvibright has range 0-10) */ - const float startx = rect->xmin + k + 1.0f; /* axis center in screen coordinates, x=y */ - const float starty = rect->ymin + k + 1.0f; + /* Axis center in screen coordinates. + * + * - Unit size offset so small text doesn't draw outside the screen + * - Extra X offset because of the panel expander. + */ + const float startx = rect->xmax - (k + UI_UNIT_X * 1.5); + const float starty = rect->ymax - (k + UI_UNIT_Y); float axis_pos[3][2]; unsigned char axis_col[3][4]; @@ -1079,7 +1084,6 @@ static void draw_selected_name(Scene *scene, Object *ob, rcti *rect) char info[300]; char *s = info; - short offset = 1.5f * UI_UNIT_X + rect->xmin; s += sprintf(s, "(%d)", cfra); @@ -1170,10 +1174,7 @@ static void draw_selected_name(Scene *scene, Object *ob, rcti *rect) s += sprintf(s, " <%s>", markern); } - if (U.uiflag & USER_SHOW_ROTVIEWICON) - offset = U.widget_unit + (U.rvisize * 2) + rect->xmin; - - BLF_draw_default(offset, rect->ymin + 0.5f * U.widget_unit, 0.0f, info, sizeof(info)); + BLF_draw_default(rect->xmin + UI_UNIT_X, rect->ymax - (2 * U.widget_unit), 0.0f, info, sizeof(info)); } /* ******************** view loop ***************** */ @@ -1204,7 +1205,9 @@ void view3d_draw_region_info(const bContext *C, ARegion *ar, const int offset) BLF_batch_draw_begin(); if (((U.uiflag & USER_SHOW_ROTVIEWICON) != 0) && - (v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) + ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) && + /* No need to display manipulator and this info. */ + ((U.manipulator_flag & USER_MANIPULATOR_DRAW_NAVIGATE) == 0)) { draw_view_axis(rv3d, &rect); } diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index cdf2106d8bf..a7fb6071f4e 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -1112,7 +1112,6 @@ static void view3d_ndof_pan_zoom( static void view3d_ndof_orbit( const struct wmNDOFMotionData *ndof, ScrArea *sa, ARegion *ar, - /* optional, can be NULL*/ ViewOpsData *vod, const bool apply_dyn_ofs) { View3D *v3d = sa->spacedata.first; @@ -1445,7 +1444,7 @@ static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *ev ED_view3d_distance_set(rv3d, 0.0f); if (has_rotation) { - view3d_ndof_orbit(ndof, vod->sa, vod->ar, NULL, false); + view3d_ndof_orbit(ndof, vod->sa, vod->ar, vod, false); } ED_view3d_distance_set(rv3d, dist_backup); diff --git a/source/blender/editors/space_view3d/view3d_manipulator_camera.c b/source/blender/editors/space_view3d/view3d_manipulator_camera.c index 49fa83e82fc..023e16c070e 100644 --- a/source/blender/editors/space_view3d/view3d_manipulator_camera.c +++ b/source/blender/editors/space_view3d/view3d_manipulator_camera.c @@ -109,7 +109,7 @@ static void WIDGETGROUP_camera_setup(const bContext *C, wmManipulatorGroup *mgro mpr = camgroup->focal_len = WM_manipulator_new_ptr(wt_arrow, mgroup, NULL); mpr->flag |= WM_MANIPULATOR_DRAW_NO_SCALE; RNA_enum_set(mpr->ptr, "draw_style", ED_MANIPULATOR_ARROW_STYLE_CONE); - RNA_enum_set(mpr->ptr, "draw_options", ED_MANIPULATOR_ARROW_STYLE_CONSTRAINED); + RNA_enum_set(mpr->ptr, "transform", ED_MANIPULATOR_ARROW_XFORM_FLAG_CONSTRAINED); UI_GetThemeColor3fv(TH_MANIPULATOR_PRIMARY, mpr->color); UI_GetThemeColor3fv(TH_MANIPULATOR_HI, mpr->color_hi); @@ -117,7 +117,7 @@ static void WIDGETGROUP_camera_setup(const bContext *C, wmManipulatorGroup *mgro mpr = camgroup->ortho_scale = WM_manipulator_new_ptr(wt_arrow, mgroup, NULL); mpr->flag |= WM_MANIPULATOR_DRAW_NO_SCALE; RNA_enum_set(mpr->ptr, "draw_style", ED_MANIPULATOR_ARROW_STYLE_CONE); - RNA_enum_set(mpr->ptr, "draw_options", ED_MANIPULATOR_ARROW_STYLE_CONSTRAINED); + RNA_enum_set(mpr->ptr, "transform", ED_MANIPULATOR_ARROW_XFORM_FLAG_CONSTRAINED); UI_GetThemeColor3fv(TH_MANIPULATOR_PRIMARY, mpr->color); UI_GetThemeColor3fv(TH_MANIPULATOR_HI, mpr->color_hi); diff --git a/source/blender/editors/space_view3d/view3d_manipulator_forcefield.c b/source/blender/editors/space_view3d/view3d_manipulator_forcefield.c index 2a1fdee8e8a..305085be370 100644 --- a/source/blender/editors/space_view3d/view3d_manipulator_forcefield.c +++ b/source/blender/editors/space_view3d/view3d_manipulator_forcefield.c @@ -72,7 +72,7 @@ static void WIDGETGROUP_forcefield_setup(const bContext *UNUSED(C), wmManipulato wwrapper->manipulator = WM_manipulator_new("MANIPULATOR_WT_arrow_3d", mgroup, NULL); wmManipulator *mpr = wwrapper->manipulator; - RNA_enum_set(mpr->ptr, "draw_options", ED_MANIPULATOR_ARROW_STYLE_CONSTRAINED); + RNA_enum_set(mpr->ptr, "transform", ED_MANIPULATOR_ARROW_XFORM_FLAG_CONSTRAINED); ED_manipulator_arrow3d_set_ui_range(mpr, -200.0f, 200.0f); ED_manipulator_arrow3d_set_range_fac(mpr, 6.0f); diff --git a/source/blender/editors/space_view3d/view3d_manipulator_lamp.c b/source/blender/editors/space_view3d/view3d_manipulator_lamp.c index 01c38cfd899..f98a2f336bc 100644 --- a/source/blender/editors/space_view3d/view3d_manipulator_lamp.c +++ b/source/blender/editors/space_view3d/view3d_manipulator_lamp.c @@ -74,7 +74,7 @@ static void WIDGETGROUP_lamp_spot_setup(const bContext *UNUSED(C), wmManipulator wwrapper->manipulator = WM_manipulator_new("MANIPULATOR_WT_arrow_3d", mgroup, NULL); wmManipulator *mpr = wwrapper->manipulator; - RNA_enum_set(mpr->ptr, "draw_options", ED_MANIPULATOR_ARROW_STYLE_INVERTED); + RNA_enum_set(mpr->ptr, "transform", ED_MANIPULATOR_ARROW_XFORM_FLAG_INVERTED); mgroup->customdata = wwrapper; diff --git a/source/blender/editors/space_view3d/view3d_manipulator_navigate.c b/source/blender/editors/space_view3d/view3d_manipulator_navigate.c index c869e23d552..22b7af48de6 100644 --- a/source/blender/editors/space_view3d/view3d_manipulator_navigate.c +++ b/source/blender/editors/space_view3d/view3d_manipulator_navigate.c @@ -51,13 +51,13 @@ * \{ */ /* Offset from screen edge. */ -#define MANIPULATOR_OFFSET_FAC 2.5 +#define MANIPULATOR_OFFSET_FAC 1.5f /* Size of main icon. */ #define MANIPULATOR_SIZE 64 /* Factor for size of smaller button. */ -#define MANIPULATOR_MINI_FAC 0.5 +#define MANIPULATOR_MINI_FAC 0.35f /* How much mini buttons offset from the primary. */ -#define MANIPULATOR_MINI_OFFSET_FAC 0.6666f +#define MANIPULATOR_MINI_OFFSET_FAC 0.42f enum { @@ -297,10 +297,21 @@ static void WIDGETGROUP_navigate_draw_prepare(const bContext *C, wmManipulatorGr navgroup->state.rv3d.is_camera = (rv3d->persp == RV3D_CAMOB); navgroup->state.rv3d.viewlock = rv3d->viewlock; + const bool show_rotate = ( + ((rv3d->viewlock & RV3D_LOCKED) == 0) && + (navgroup->state.rv3d.is_camera == false)); + const bool show_fixed_offset = navgroup->state.rv3d.is_camera; const float icon_size = MANIPULATOR_SIZE; - const float icon_offset = (icon_size / 2.0) * MANIPULATOR_OFFSET_FAC * UI_DPI_FAC; + const float icon_offset = (icon_size * 0.52f) * MANIPULATOR_OFFSET_FAC * UI_DPI_FAC; const float icon_offset_mini = icon_size * MANIPULATOR_MINI_OFFSET_FAC * UI_DPI_FAC; - const float co[2] = {rect_visible.xmax - icon_offset, rect_visible.ymax - icon_offset}; + const float co_rotate[2] = { + rect_visible.xmax - icon_offset, + rect_visible.ymax - icon_offset, + }; + const float co[2] = { + rect_visible.xmax - ((show_rotate || show_fixed_offset) ? (icon_offset * 2.0f) : (icon_offset_mini * 0.75f)), + rect_visible.ymax - icon_offset_mini * 0.75f, + }; wmManipulator *mpr; @@ -309,48 +320,36 @@ static void WIDGETGROUP_navigate_draw_prepare(const bContext *C, wmManipulatorGr WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, true); } - if (((rv3d->viewlock & RV3D_LOCKED) == 0) && (navgroup->state.rv3d.is_camera == false)) { + /* RV3D_LOCKED or Camera: only show supported buttons. */ + if (show_rotate) { mpr = navgroup->mpr_array[MPR_ROTATE]; - mpr->matrix_basis[3][0] = co[0]; - mpr->matrix_basis[3][1] = co[1]; + mpr->matrix_basis[3][0] = co_rotate[0]; + mpr->matrix_basis[3][1] = co_rotate[1]; WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false); + } - mpr = navgroup->mpr_array[MPR_MOVE]; - mpr->matrix_basis[3][0] = co[0] + icon_offset_mini; - mpr->matrix_basis[3][1] = co[1] - icon_offset_mini; - WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false); + int icon_mini_slot = 0; - mpr = navgroup->mpr_array[MPR_ZOOM]; - mpr->matrix_basis[3][0] = co[0] - icon_offset_mini; - mpr->matrix_basis[3][1] = co[1] - icon_offset_mini; - WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false); + mpr = navgroup->mpr_array[MPR_ZOOM]; + mpr->matrix_basis[3][0] = co[0] - (icon_offset_mini * icon_mini_slot++); + mpr->matrix_basis[3][1] = co[1]; + WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false); - mpr = navgroup->mpr_array[rv3d->is_persp ? MPR_ORTHO : MPR_PERSP]; - mpr->matrix_basis[3][0] = co[0] + icon_offset_mini; - mpr->matrix_basis[3][1] = co[1] + icon_offset_mini; - WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false); + mpr = navgroup->mpr_array[MPR_MOVE]; + mpr->matrix_basis[3][0] = co[0] - (icon_offset_mini * icon_mini_slot++); + mpr->matrix_basis[3][1] = co[1]; + WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false); + if ((rv3d->viewlock & RV3D_LOCKED) == 0) { mpr = navgroup->mpr_array[MPR_CAMERA]; - mpr->matrix_basis[3][0] = co[0] - icon_offset_mini; - mpr->matrix_basis[3][1] = co[1] + icon_offset_mini; - WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false); - } - else { - /* RV3D_LOCKED or Camera: only show supported buttons. */ - mpr = navgroup->mpr_array[MPR_MOVE]; - mpr->matrix_basis[3][0] = co[0] + icon_offset_mini; - mpr->matrix_basis[3][1] = co[1] + icon_offset_mini; - WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false); - - mpr = navgroup->mpr_array[MPR_ZOOM]; - mpr->matrix_basis[3][0] = co[0]; - mpr->matrix_basis[3][1] = co[1] + icon_offset_mini; + mpr->matrix_basis[3][0] = co[0] - (icon_offset_mini * icon_mini_slot++); + mpr->matrix_basis[3][1] = co[1]; WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false); - if (navgroup->state.rv3d.is_camera) { - mpr = navgroup->mpr_array[MPR_CAMERA]; - mpr->matrix_basis[3][0] = co[0] - icon_offset_mini; - mpr->matrix_basis[3][1] = co[1] + icon_offset_mini; + if (navgroup->state.rv3d.is_camera == false) { + mpr = navgroup->mpr_array[rv3d->is_persp ? MPR_PERSP : MPR_ORTHO]; + mpr->matrix_basis[3][0] = co[0] - (icon_offset_mini * icon_mini_slot++); + mpr->matrix_basis[3][1] = co[1]; WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false); } } diff --git a/source/blender/editors/space_view3d/view3d_manipulator_ruler.c b/source/blender/editors/space_view3d/view3d_manipulator_ruler.c index cd918695f60..8178c2f5be9 100644 --- a/source/blender/editors/space_view3d/view3d_manipulator_ruler.c +++ b/source/blender/editors/space_view3d/view3d_manipulator_ruler.c @@ -382,6 +382,7 @@ static bool view3d_ruler_item_mousemove( static bool view3d_ruler_to_gpencil(bContext *C, wmManipulatorGroup *mgroup) { // RulerInfo *ruler_info = mgroup->customdata; + Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); bGPDlayer *gpl; bGPDframe *gpf; @@ -393,7 +394,7 @@ static bool view3d_ruler_to_gpencil(bContext *C, wmManipulatorGroup *mgroup) bool changed = false; if (scene->gpd == NULL) { - scene->gpd = BKE_gpencil_data_addnew("GPencil"); + scene->gpd = BKE_gpencil_data_addnew(bmain, "GPencil"); } gpl = BLI_findstring(&scene->gpd->layers, ruler_name, offsetof(bGPDlayer, info)); diff --git a/source/blender/editors/space_view3d/view3d_ruler.c b/source/blender/editors/space_view3d/view3d_ruler.c index c30b72bfb95..e001ed9112b 100644 --- a/source/blender/editors/space_view3d/view3d_ruler.c +++ b/source/blender/editors/space_view3d/view3d_ruler.c @@ -297,6 +297,7 @@ static void ruler_state_set(bContext *C, RulerInfo *ruler_info, int state) #define RULER_ID "RulerData3D" static bool view3d_ruler_to_gpencil(bContext *C, RulerInfo *ruler_info) { + Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); bGPDlayer *gpl; bGPDframe *gpf; @@ -308,7 +309,7 @@ static bool view3d_ruler_to_gpencil(bContext *C, RulerInfo *ruler_info) bool changed = false; if (scene->gpd == NULL) { - scene->gpd = BKE_gpencil_data_addnew("GPencil"); + scene->gpd = BKE_gpencil_data_addnew(bmain, "GPencil"); } gpl = BLI_findstring(&scene->gpd->layers, ruler_name, offsetof(bGPDlayer, info)); diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index f4e39c7a563..08c6a6c328f 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -855,6 +855,7 @@ static void view3d_lasso_select( } else { do_lasso_select_objects(vc, mcords, moves, extend, select); + DEG_id_tag_update(&vc->scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, vc->scene); } } @@ -885,6 +886,7 @@ static void view3d_lasso_select( break; } + DEG_id_tag_update(vc->obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc->obedit->data); } FOREACH_OBJECT_IN_MODE_END; @@ -1009,7 +1011,9 @@ static int object_select_menu_exec(bContext *C, wmOperator *op) /* undo? */ if (changed) { - WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C)); + Scene *scene = CTX_data_scene(C); + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); return OPERATOR_FINISHED; } else { @@ -1562,6 +1566,7 @@ static bool ed_object_select_pick( retval = true; + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_MOVIECLIP | ND_SELECT, track); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); @@ -1658,6 +1663,7 @@ static bool ed_object_select_pick( } } + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); } @@ -2241,6 +2247,7 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, b MEM_freeN(bases); + DEG_id_tag_update(&vc->scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, vc->scene); } MEM_freeN(vbuffer); @@ -2276,6 +2283,7 @@ static int view3d_borderselect_exec(bContext *C, wmOperator *op) vc.em = BKE_editmesh_from_object(vc.obedit); ret |= do_mesh_box_select(&vc, &rect, select, extend); if (ret & OPERATOR_FINISHED) { + DEG_id_tag_update(vc.obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data); } break; @@ -2283,24 +2291,28 @@ static int view3d_borderselect_exec(bContext *C, wmOperator *op) case OB_SURF: ret |= do_nurbs_box_select(&vc, &rect, select, extend); if (ret & OPERATOR_FINISHED) { + DEG_id_tag_update(vc.obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data); } break; case OB_MBALL: ret |= do_meta_box_select(&vc, &rect, select, extend); if (ret & OPERATOR_FINISHED) { + DEG_id_tag_update(vc.obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data); } break; case OB_ARMATURE: ret |= do_armature_box_select(&vc, &rect, select, extend); if (ret & OPERATOR_FINISHED) { + DEG_id_tag_update(&vc.obedit->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, vc.obedit); } break; case OB_LATTICE: ret |= do_lattice_box_select(&vc, &rect, select, extend); if (ret & OPERATOR_FINISHED) { + DEG_id_tag_update(vc.obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data); } break; @@ -2403,6 +2415,7 @@ static bool ed_wpaint_vertex_select_pick( } paintvert_flush_flags(obact); + DEG_id_tag_update(obact->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obact->data); return true; } @@ -3004,14 +3017,17 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op) if (CTX_data_edit_object(C)) { obedit_circle_select(&vc, select, mval, (float)radius); + DEG_id_tag_update(obact->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obact->data); } else if (BKE_paint_select_face_test(obact)) { paint_facesel_circle_select(&vc, select, mval, (float)radius); + DEG_id_tag_update(obact->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obact->data); } else if (BKE_paint_select_vert_test(obact)) { paint_vertsel_circle_select(&vc, select, mval, (float)radius); + DEG_id_tag_update(obact->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obact->data); } else if (obact->mode & OB_MODE_POSE) { @@ -3028,6 +3044,7 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op) } else { if (object_circle_select(&vc, select, mval, (float)radius)) { + DEG_id_tag_update(&vc.scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, vc.scene); } } diff --git a/source/blender/editors/space_view3d/view3d_toolbar.c b/source/blender/editors/space_view3d/view3d_toolbar.c index 8ea33927c4d..acceb40beaa 100644 --- a/source/blender/editors/space_view3d/view3d_toolbar.c +++ b/source/blender/editors/space_view3d/view3d_toolbar.c @@ -190,7 +190,7 @@ static int view3d_toolshelf_toggle_exec(bContext *C, wmOperator *UNUSED(op)) void VIEW3D_OT_toolshelf(wmOperatorType *ot) { - ot->name = "Tool Shelf"; + ot->name = "Toggle Toolbar"; ot->description = "Toggles tool shelf display"; ot->idname = "VIEW3D_OT_toolshelf"; diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index 419f400df53..df2fa1da43d 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -65,6 +65,7 @@ struct wmEvent; struct wmTimer; struct ARegion; struct ReportList; +struct RNG; struct EditBone; struct RenderEngineType; struct SnapObjectContext; @@ -536,6 +537,9 @@ typedef struct TransInfo { void *draw_handle_pixel; void *draw_handle_cursor; + /** Currently only used for random curve of proportional editing. */ + struct RNG *rng; + /** Typically for mode settings. */ TransCustomDataContainer custom; } TransInfo; diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 45941ba6f39..8462004c549 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -1255,7 +1255,7 @@ static void createTransArmatureVerts(TransInfo *t) bool mirror = ((arm->flag & ARM_MIRROR_EDIT) != 0); int total_mirrored = 0, i; int oldtot; - BoneInitData *bid; + BoneInitData *bid = NULL; tc->data_len = 0; for (ebo = edbo->first; ebo; ebo = ebo->next) { @@ -2120,7 +2120,6 @@ static void createTransParticleVerts(bContext *C, TransInfo *t) void flushTransParticles(TransInfo *t) { FOREACH_TRANS_DATA_CONTAINER (t, tc) { - Scene *scene = t->scene; ViewLayer *view_layer = t->view_layer; Object *ob = OBACT(view_layer); @@ -6429,7 +6428,7 @@ void special_aftertrans_update(bContext *C, TransInfo *t) if (canceled == 0) { ED_node_post_apply_transform(C, snode->edittree); - ED_node_link_insert(t->sa); + ED_node_link_insert(bmain, t->sa); } /* clear link line */ @@ -8633,6 +8632,10 @@ void createTransData(bContext *C, TransInfo *t) createTransPaintCurveVerts(C, t); countAndCleanTransDataContainer(t); } + /* Mark as initialized if above checks fail. */ + if (t->data_len_all == -1) { + t->data_len_all = 0; + } } else { createTransObject(C, t); diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index d3fcd5e5911..053647cbfea 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -58,6 +58,8 @@ #include "BLI_rand.h" #include "BLI_utildefines.h" +#include "PIL_time.h" + #include "BLT_translation.h" #include "RNA_access.h" @@ -74,6 +76,7 @@ #include "BKE_fcurve.h" #include "BKE_lattice.h" #include "BKE_library.h" +#include "BKE_main.h" #include "BKE_nla.h" #include "BKE_context.h" #include "BKE_paint.h" @@ -1695,6 +1698,10 @@ void postTrans(bContext *C, TransInfo *t) MEM_freeN(t->mouse.data); } + if (t->rng != NULL) { + BLI_rng_free(t->rng); + } + freeSnapping(t); } @@ -1956,7 +1963,7 @@ bool calculateCenterActive(TransInfo *t, bool select_only, float r_center[3]) bPoseChannel *pchan = BKE_pose_channel_active(ob); if (pchan && (!select_only || (pchan->bone->flag & BONE_SELECTED))) { copy_v3_v3(r_center, pchan->pose_head); - mul_m4_v3(tc->obedit->obmat, r_center); + mul_m4_v3(ob->obmat, r_center); ok = true; } } @@ -2163,7 +2170,12 @@ void calculatePropRatio(TransInfo *t) td->factor = sqrtf(2 * dist - dist * dist); break; case PROP_RANDOM: - td->factor = BLI_frand() * dist; + if (t->rng == NULL) { + /* Lazy initialization. */ + uint rng_seed = (uint)(PIL_check_seconds_timer_i() & UINT_MAX); + t->rng = BLI_rng_new(rng_seed); + } + td->factor = BLI_rng_get_float(t->rng) * dist; break; case PROP_INVSQUARE: td->factor = dist * (2.0f - dist); diff --git a/source/blender/editors/transform/transform_manipulator_3d.c b/source/blender/editors/transform/transform_manipulator_3d.c index b6782470f96..75da0fc2d23 100644 --- a/source/blender/editors/transform/transform_manipulator_3d.c +++ b/source/blender/editors/transform/transform_manipulator_3d.c @@ -107,8 +107,15 @@ #define MAN_SCALE_C (MAN_SCALE_X | MAN_SCALE_Y | MAN_SCALE_Z) /* threshold for testing view aligned manipulator axis */ -#define TW_AXIS_DOT_MIN 0.02f -#define TW_AXIS_DOT_MAX 0.1f +struct { + float min, max; +} g_tw_axis_range[2] = { + /* Regular range */ + {0.02f, 0.1f}, + /* Use a different range because we flip the dot product, + * also the view aligned planes are harder to see so hiding early is preferred. */ + {0.175f, 0.25f}, +}; /* axes as index */ enum { @@ -247,16 +254,18 @@ static bool manipulator_is_axis_visible( const RegionView3D *rv3d, const int twtype, const float idot[3], const int axis_type, const int axis_idx) { - bool is_plane = false; - const uint aidx_norm = manipulator_orientation_axis(axis_idx, &is_plane); - /* don't draw axis perpendicular to the view */ - if (aidx_norm < 3) { - float idot_axis = idot[aidx_norm]; - if (is_plane) { - idot_axis = 1.0f - idot_axis; - } - if (idot_axis < TW_AXIS_DOT_MIN) { - return false; + if ((axis_idx >= MAN_AXIS_RANGE_ROT_START && axis_idx < MAN_AXIS_RANGE_ROT_END) == 0) { + bool is_plane = false; + const uint aidx_norm = manipulator_orientation_axis(axis_idx, &is_plane); + /* don't draw axis perpendicular to the view */ + if (aidx_norm < 3) { + float idot_axis = idot[aidx_norm]; + if (is_plane) { + idot_axis = 1.0f - idot_axis; + } + if (idot_axis < g_tw_axis_range[is_plane].min) { + return false; + } } } @@ -333,22 +342,31 @@ static void manipulator_get_axis_color( const float alpha_hi = 1.0f; float alpha_fac; - bool is_plane = false; - const int axis_idx_norm = manipulator_orientation_axis(axis_idx, &is_plane); - /* get alpha fac based on axis angle, to fade axis out when hiding it because it points towards view */ - if (axis_idx_norm < 3) { - float idot_axis = idot[axis_idx_norm]; - if (is_plane) { - idot_axis = 1.0f - idot_axis; - } - alpha_fac = (idot_axis > TW_AXIS_DOT_MAX) ? - 1.0f : (idot_axis < TW_AXIS_DOT_MIN) ? - 0.0f : ((idot_axis - TW_AXIS_DOT_MIN) / (TW_AXIS_DOT_MAX - TW_AXIS_DOT_MIN)); - } - else { + if (axis_idx >= MAN_AXIS_RANGE_ROT_START && axis_idx < MAN_AXIS_RANGE_ROT_END) { + /* Never fade rotation rings. */ /* trackball rotation axis is a special case, we only draw a slight overlay */ alpha_fac = (axis_idx == MAN_AXIS_ROT_T) ? 0.1f : 1.0f; } + else { + bool is_plane = false; + const int axis_idx_norm = manipulator_orientation_axis(axis_idx, &is_plane); + /* get alpha fac based on axis angle, to fade axis out when hiding it because it points towards view */ + if (axis_idx_norm < 3) { + const float idot_min = g_tw_axis_range[is_plane].min; + const float idot_max = g_tw_axis_range[is_plane].max; + float idot_axis = idot[axis_idx_norm]; + if (is_plane) { + idot_axis = 1.0f - idot_axis; + } + alpha_fac = ( + (idot_axis > idot_max) ? + 1.0f : (idot_axis < idot_min) ? + 0.0f : ((idot_axis - idot_min) / (idot_max - idot_min))); + } + else { + alpha_fac = 1.0f; + } + } switch (axis_idx) { case MAN_AXIS_TRANS_X: @@ -1238,9 +1256,14 @@ static ManipulatorGroup *manipulatorgroup_init(wmManipulatorGroup *mgroup) * Custom handler for manipulator widgets */ static int manipulator_modal( - bContext *C, wmManipulator *widget, const wmEvent *UNUSED(event), + bContext *C, wmManipulator *widget, const wmEvent *event, eWM_ManipulatorTweak UNUSED(tweak_flag)) { + /* Avoid unnecessary updates, partially address: T55458. */ + if (ELEM(event->type, TIMER, INBETWEEN_MOUSEMOVE)) { + return OPERATOR_RUNNING_MODAL; + } + const ScrArea *sa = CTX_wm_area(C); ARegion *ar = CTX_wm_region(C); View3D *v3d = sa->spacedata.first; @@ -1315,6 +1338,14 @@ static void WIDGETGROUP_manipulator_setup(const bContext *C, wmManipulatorGroup case MAN_AXIS_SCALE_X: case MAN_AXIS_SCALE_Y: case MAN_AXIS_SCALE_Z: + if (axis_idx >= MAN_AXIS_RANGE_TRANS_START && axis_idx < MAN_AXIS_RANGE_TRANS_END) { + int draw_options = 0; + if ((man->twtype & (V3D_MANIP_ROTATE | V3D_MANIP_SCALE)) == 0) { + draw_options |= ED_MANIPULATOR_ARROW_DRAW_FLAG_STEM; + } + RNA_enum_set(axis->ptr, "draw_options", draw_options); + } + WM_manipulator_set_line_width(axis, MANIPULATOR_AXIS_LINE_WIDTH); break; case MAN_AXIS_ROT_X: @@ -1348,6 +1379,7 @@ static void WIDGETGROUP_manipulator_setup(const bContext *C, wmManipulatorGroup } else if (axis_idx == MAN_AXIS_ROT_C) { WM_manipulator_set_flag(axis, WM_MANIPULATOR_DRAW_VALUE, true); + WM_manipulator_set_scale(axis, 1.2f); } else { WM_manipulator_set_scale(axis, 0.2f); @@ -1447,6 +1479,13 @@ static void WIDGETGROUP_manipulator_refresh(const bContext *C, wmManipulatorGrou WM_manipulator_set_matrix_rotation_from_z_axis(axis, rv3d->twmat[aidx_norm]); RNA_float_set(axis->ptr, "length", len); + + if (axis_idx >= MAN_AXIS_RANGE_TRANS_START && axis_idx < MAN_AXIS_RANGE_TRANS_END) { + if (man->twtype & V3D_MANIP_ROTATE) { + /* Avoid rotate and translate arrows overlap. */ + start_co[2] += 0.215f; + } + } WM_manipulator_set_matrix_offset_location(axis, start_co); WM_manipulator_set_flag(axis, WM_MANIPULATOR_DRAW_OFFSET_SCALE, true); break; diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index 1e49d1545af..c42887412fa 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -534,7 +534,7 @@ void Transform_Properties(struct wmOperatorType *ot, int flags) if (flags & P_PROPORTIONAL) { RNA_def_enum(ot->srna, "proportional", rna_enum_proportional_editing_items, 0, "Proportional Editing", ""); prop = RNA_def_enum(ot->srna, "proportional_edit_falloff", rna_enum_proportional_falloff_items, 0, - "Proportional Editing Falloff", "Falloff type for proportional editing mode"); + "Proportional Falloff", "Falloff type for proportional editing mode"); RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_CURVE); /* Abusing id_curve :/ */ RNA_def_float(ot->srna, "proportional_size", 1, T_PROP_SIZE_MIN, T_PROP_SIZE_MAX, "Proportional Size", "", 0.001f, 100.0f); @@ -560,17 +560,20 @@ void Transform_Properties(struct wmOperatorType *ot, int flags) } if (flags & P_GPENCIL_EDIT) { - RNA_def_boolean(ot->srna, "gpencil_strokes", 0, "Edit Grease Pencil", "Edit selected Grease Pencil strokes"); + prop = RNA_def_boolean(ot->srna, "gpencil_strokes", 0, "Edit Grease Pencil", "Edit selected Grease Pencil strokes"); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } if (flags & P_CURSOR_EDIT) { - RNA_def_boolean(ot->srna, "cursor_transform", 0, "Transform Cursor", ""); + prop = RNA_def_boolean(ot->srna, "cursor_transform", 0, "Transform Cursor", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } if ((flags & P_OPTIONS) && !(flags & P_NO_TEXSPACE)) { - RNA_def_boolean(ot->srna, "texture_space", 0, "Edit Texture Space", "Edit Object data texture space"); + prop = RNA_def_boolean(ot->srna, "texture_space", 0, "Edit Texture Space", "Edit Object data texture space"); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); prop = RNA_def_boolean(ot->srna, "remove_on_cancel", 0, "Remove on Cancel", "Remove elements on cancel"); - RNA_def_property_flag(prop, PROP_HIDDEN); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } if (flags & P_CORRECT_UV) { diff --git a/source/blender/editors/undo/ed_undo.c b/source/blender/editors/undo/ed_undo.c index d2ac346df10..102065f5295 100644 --- a/source/blender/editors/undo/ed_undo.c +++ b/source/blender/editors/undo/ed_undo.c @@ -148,15 +148,10 @@ static int ed_undo_step(bContext *C, int step, const char *undoname) void ED_undo_grouped_push(bContext *C, const char *str) { /* do nothing if previous undo task is the same as this one (or from the same undo group) */ - { - wmWindowManager *wm = CTX_wm_manager(C); - if (wm->undo_stack->steps.last) { - const UndoStep *us = wm->undo_stack->steps.last; - if (STREQ(str, us->name)) { - return; - } - } - + wmWindowManager *wm = CTX_wm_manager(C); + const UndoStep *us = wm->undo_stack->step_active; + if (us && STREQ(str, us->name)) { + BKE_undosys_stack_clear_active(wm->undo_stack); } /* push as usual */ @@ -307,36 +302,6 @@ void ED_OT_undo_redo(wmOperatorType *ot) /** \} */ -struct OperatorRepeatContextHandle { - ScrArea *restore_area; - ARegion *restore_region; -}; - -/** - * Resets the context to the state \a op was executed in (or at least, was in when registering). - * #ED_operator_repeat_reset_context should be called when done repeating! - */ -const OperatorRepeatContextHandle *ED_operator_repeat_prepare_context(bContext *C, wmOperator *op) -{ - static OperatorRepeatContextHandle context_info; - - context_info.restore_area = CTX_wm_area(C); - context_info.restore_region = CTX_wm_region(C); - - CTX_wm_area_set(C, op->execution_area); - CTX_wm_region_set(C, op->execution_region); - - return &context_info; -} -/** - * Resets context to the old state from before #ED_operator_repeat_prepare_context was called. - */ -void ED_operator_repeat_reset_context(bContext *C, const OperatorRepeatContextHandle *context_info) -{ - CTX_wm_area_set(C, context_info->restore_area); - CTX_wm_region_set(C, context_info->restore_region); -} - /* -------------------------------------------------------------------- */ /** \name Operator Repeat * \{ */ @@ -351,8 +316,13 @@ int ED_undo_operator_repeat(bContext *C, wmOperator *op) wmWindowManager *wm = CTX_wm_manager(C); struct Scene *scene = CTX_data_scene(C); - const OperatorRepeatContextHandle *context_info; - context_info = ED_operator_repeat_prepare_context(C, op); + /* keep in sync with logic in view3d_panel_operator_redo() */ + ARegion *ar_orig = CTX_wm_region(C); + ARegion *ar_win = BKE_area_find_region_active_win(CTX_wm_area(C)); + + if (ar_win) { + CTX_wm_region_set(C, ar_win); + } if ((WM_operator_repeat_check(C, op)) && (WM_operator_poll(C, op->type)) && @@ -398,7 +368,8 @@ int ED_undo_operator_repeat(bContext *C, wmOperator *op) } } - ED_operator_repeat_reset_context(C, context_info); + /* set region back */ + CTX_wm_region_set(C, ar_orig); } else { CLOG_WARN(&LOG, "called with NULL 'op'"); diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c index 447cff065b7..a829f8c1144 100644 --- a/source/blender/editors/util/ed_util.c +++ b/source/blender/editors/util/ed_util.c @@ -129,7 +129,7 @@ void ED_editors_init(bContext *C) { Scene *sce = CTX_data_scene(C); if (sce) { - ED_space_image_paint_update(wm, sce); + ED_space_image_paint_update(bmain, wm, sce); } } diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index 45a6ccfe28b..e3d2537c040 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -1362,7 +1362,7 @@ static int uv_select_more_less(bContext *C, const bool select) else { EDBM_select_less(em, true); } - + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); return OPERATOR_FINISHED; } @@ -1434,6 +1434,7 @@ static int uv_select_more_less(bContext *C, const bool select) uv_select_flush_from_tag_loop(sima, scene, obedit, select); } + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); return OPERATOR_FINISHED; @@ -2058,6 +2059,7 @@ static int uv_select_all_exec(bContext *C, wmOperator *op) for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } @@ -2371,7 +2373,7 @@ static int uv_mouse_select_multi( #endif } - DEG_id_tag_update(obedit->data, 0); + DEG_id_tag_update(obedit->data, DEG_TAG_COPY_ON_WRITE | DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); return OPERATOR_PASS_THROUGH | OPERATOR_FINISHED; @@ -2547,7 +2549,7 @@ static int uv_select_linked_internal(bContext *C, wmOperator *op, const wmEvent for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; - DEG_id_tag_update(obedit->data, 0); + DEG_id_tag_update(obedit->data, DEG_TAG_COPY_ON_WRITE | DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } @@ -3052,6 +3054,7 @@ static int uv_border_select_exec(bContext *C, wmOperator *op) uv_select_sync_flush(ts, em, select); if (ts->uv_flag & UV_SYNC_SELECTION) { + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } } @@ -3181,6 +3184,7 @@ static int uv_circle_select_exec(bContext *C, wmOperator *op) if (changed) { uv_select_sync_flush(ts, em, select); + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } @@ -3314,6 +3318,7 @@ static bool do_lasso_select_mesh_uv(bContext *C, const int mcords[][2], short mo uv_select_sync_flush(scene->toolsettings, em, select); if (ts->uv_flag & UV_SYNC_SELECTION) { + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } } @@ -3746,6 +3751,7 @@ static int uv_select_pinned_exec(bContext *C, wmOperator *UNUSED(op)) } } + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); return OPERATOR_FINISHED; @@ -3812,6 +3818,8 @@ static int uv_hide_exec(bContext *C, wmOperator *op) if (ts->uv_flag & UV_SYNC_SELECTION) { EDBM_mesh_hide(em, swap); + + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); return OPERATOR_FINISHED; @@ -3880,6 +3888,8 @@ static int uv_hide_exec(bContext *C, wmOperator *op) EDBM_selectmode_flush_ex(em, SCE_SELECT_VERTEX | SCE_SELECT_EDGE); BM_select_history_validate(em->bm); + + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); return OPERATOR_FINISHED; @@ -3933,6 +3943,7 @@ static int uv_reveal_exec(bContext *C, wmOperator *op) /* call the mesh function if we are in mesh sync sel */ if (ts->uv_flag & UV_SYNC_SELECTION) { EDBM_mesh_reveal(em, select); + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); return OPERATOR_FINISHED; @@ -4022,6 +4033,7 @@ static int uv_reveal_exec(bContext *C, wmOperator *op) /* re-select tagged faces */ BM_mesh_elem_hflag_enable_test(em->bm, BM_FACE, BM_ELEM_SELECT, true, false, BM_ELEM_TAG); + DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); return OPERATOR_FINISHED; diff --git a/source/blender/gpu/GPU_draw.h b/source/blender/gpu/GPU_draw.h index e26d973142b..613a07dc869 100644 --- a/source/blender/gpu/GPU_draw.h +++ b/source/blender/gpu/GPU_draw.h @@ -86,9 +86,6 @@ void GPU_set_gpu_mipmapping(int gpu_mipmap); * - these deal with images bound as opengl textures */ void GPU_paint_update_image(struct Image *ima, struct ImageUser *iuser, int x, int y, int w, int h); -int GPU_verify_image( - struct Image *ima, struct ImageUser *iuser, - int textarget, bool compare, bool mipmap, bool is_data); void GPU_create_gl_tex( unsigned int *bind, unsigned int *rect, float *frect, int rectw, int recth, int textarget, bool mipmap, bool use_hight_bit_depth, struct Image *ima); diff --git a/source/blender/gpu/GPU_texture.h b/source/blender/gpu/GPU_texture.h index 3b4cdc21b9d..b974b8ec621 100644 --- a/source/blender/gpu/GPU_texture.h +++ b/source/blender/gpu/GPU_texture.h @@ -161,8 +161,9 @@ GPUTexture *GPU_texture_create_from_vertbuf( GPUTexture *GPU_texture_create_buffer( GPUTextureFormat data_type, const uint buffer); +GPUTexture *GPU_texture_from_bindcode(int textarget, int bindcode); GPUTexture *GPU_texture_from_blender( - struct Image *ima, struct ImageUser *iuser, int textarget, bool is_data, double time, int mipmap); + struct Image *ima, struct ImageUser *iuser, int textarget, bool is_data, double time); GPUTexture *GPU_texture_from_preview(struct PreviewImage *prv, int mipmap); void GPU_texture_update(GPUTexture *tex, const float *pixels); diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c index 0dd9d1f0908..436f43d9c1e 100644 --- a/source/blender/gpu/intern/gpu_codegen.c +++ b/source/blender/gpu/intern/gpu_codegen.c @@ -416,15 +416,26 @@ static void codegen_convert_datatype(DynStr *ds, int from, int to, const char *t else if (from == GPU_FLOAT) BLI_dynstr_appendf(ds, "vec3(%s, %s, %s)", name, name, name); } - else { + else if (to == GPU_VEC4) { if (from == GPU_VEC3) BLI_dynstr_appendf(ds, "vec4(%s, 1.0)", name); else if (from == GPU_VEC2) BLI_dynstr_appendf(ds, "vec4(%s.r, %s.r, %s.r, %s.g)", name, name, name, name); else if (from == GPU_FLOAT) BLI_dynstr_appendf(ds, "vec4(%s, %s, %s, 1.0)", name, name, name); - else /* can happen with closure */ - BLI_dynstr_append(ds, name); + } + else if (to == GPU_CLOSURE) { + if (from == GPU_VEC4) + BLI_dynstr_appendf(ds, "closure_emission(%s.rgb)", name); + else if (from == GPU_VEC3) + BLI_dynstr_appendf(ds, "closure_emission(%s.rgb)", name); + else if (from == GPU_VEC2) + BLI_dynstr_appendf(ds, "closure_emission(%s.rrr)", name); + else if (from == GPU_FLOAT) + BLI_dynstr_appendf(ds, "closure_emission(vec3(%s, %s, %s))", name, name, name); + } + else { + BLI_dynstr_append(ds, name); } } @@ -1183,77 +1194,6 @@ void GPU_nodes_extract_dynamic_inputs(GPUShader *shader, ListBase *inputs, ListB GPU_shader_unbind(); } -void GPU_pass_bind(GPUPass *pass, ListBase *inputs, double time, int mipmap) -{ - GPUInput *input; - GPUShader *shader = pass->shader; - - if (!shader) - return; - - GPU_shader_bind(shader); - - /* create the textures */ - for (input = inputs->first; input; input = input->next) { - if (input->ima) - input->tex = GPU_texture_from_blender(input->ima, input->iuser, input->textarget, input->image_isdata, time, mipmap); - else if (input->prv) - input->tex = GPU_texture_from_preview(input->prv, mipmap); - } - - /* bind the textures, in second loop so texture binding during - * create doesn't overwrite already bound textures */ - for (input = inputs->first; input; input = input->next) { - if (input->tex && input->bindtex) { - GPU_texture_bind(input->tex, input->texid); - GPU_shader_uniform_texture(shader, input->shaderloc, input->tex); - } - } -} - -void GPU_pass_update_uniforms(GPUPass *pass, ListBase *inputs) -{ - GPUInput *input; - GPUShader *shader = pass->shader; - - if (!shader) - return; - - /* pass dynamic inputs to opengl, others were removed */ - for (input = inputs->first; input; input = input->next) { - if (!(input->ima || input->tex || input->prv)) { - if (input->dynamictype == GPU_DYNAMIC_MAT_HARD) { - // The hardness is actually a short pointer, so we convert it here - float val = (float)(*(short *)input->dynamicvec); - GPU_shader_uniform_vector(shader, input->shaderloc, 1, 1, &val); - } - else { - GPU_shader_uniform_vector(shader, input->shaderloc, input->type, 1, - input->dynamicvec); - } - } - } -} - -void GPU_pass_unbind(GPUPass *pass, ListBase *inputs) -{ - GPUInput *input; - GPUShader *shader = pass->shader; - - if (!shader) - return; - - for (input = inputs->first; input; input = input->next) { - if (input->tex && input->bindtex) - GPU_texture_unbind(input->tex); - - if (input->ima || input->prv) - input->tex = NULL; - } - - GPU_shader_unbind(); -} - /* Node Link Functions */ static GPUNodeLink *GPU_node_link_create(void) diff --git a/source/blender/gpu/intern/gpu_codegen.h b/source/blender/gpu/intern/gpu_codegen.h index 04bee545a7e..a0f425e39d6 100644 --- a/source/blender/gpu/intern/gpu_codegen.h +++ b/source/blender/gpu/intern/gpu_codegen.h @@ -184,10 +184,6 @@ void GPU_nodes_extract_dynamic_inputs(struct GPUShader *shader, ListBase *inputs void GPU_nodes_get_vertex_attributes(ListBase *nodes, struct GPUVertexAttribs *attribs); void GPU_nodes_prune(ListBase *nodes, struct GPUNodeLink *outlink); -void GPU_pass_bind(GPUPass *pass, ListBase *inputs, double time, int mipmap); -void GPU_pass_update_uniforms(GPUPass *pass, ListBase *inputs); -void GPU_pass_unbind(GPUPass *pass, ListBase *inputs); - void GPU_pass_compile(GPUPass *pass); void GPU_pass_release(GPUPass *pass); void GPU_pass_free_nodes(ListBase *nodes); diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index 7bfebb702a1..83fd689e3b7 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -127,8 +127,6 @@ static int smaller_power_of_2_limit(int num) /* Current OpenGL state caching for GPU_set_tpage */ static struct GPUTextureState { - Image *ima, *curima; - /* also controls min/mag filtering */ bool domipmap; /* only use when 'domipmap' is set */ @@ -136,10 +134,9 @@ static struct GPUTextureState { /* store this so that new images created while texture painting won't be set to mipmapped */ bool texpaint; - int alphablend; float anisotropic; int gpu_mipmap; -} GTS = {NULL, NULL, 1, 0, 0, -1, 1.0f, 0}; +} GTS = {1, 0, 0, 1.0f, 0}; /* Mipmap settings */ @@ -227,16 +224,14 @@ float GPU_get_anisotropic(void) /* Set OpenGL state for an MTFace */ -static unsigned int *gpu_get_image_bindcode(Image *ima, GLenum textarget) +static GPUTexture **gpu_get_image_gputexture(Image *ima, GLenum textarget) { - unsigned int *bind = 0; - if (textarget == GL_TEXTURE_2D) - bind = &ima->bindcode[TEXTARGET_TEXTURE_2D]; + return &ima->gputexture[TEXTARGET_TEXTURE_2D]; else if (textarget == GL_TEXTURE_CUBE_MAP) - bind = &ima->bindcode[TEXTARGET_TEXTURE_CUBE_MAP]; + return &ima->gputexture[TEXTARGET_TEXTURE_CUBE_MAP]; - return bind; + return NULL; } typedef struct VerifyThreadData { @@ -289,33 +284,45 @@ static void gpu_verify_high_bit_srgb_buffer(float *srgb_frect, } } -int GPU_verify_image( - Image *ima, ImageUser *iuser, - int textarget, bool compare, bool mipmap, bool is_data) +GPUTexture *GPU_texture_from_blender(Image *ima, + ImageUser *iuser, + int textarget, + bool is_data, + double UNUSED(time)) { - unsigned int *bind = NULL; - int tpx = 0, tpy = 0; - unsigned int *rect = NULL; - float *frect = NULL; - float *srgb_frect = NULL; - /* flag to determine whether deep format is used */ - bool use_high_bit_depth = false, do_color_management = false; + if (ima == NULL) { + return NULL; + } - GTS.ima = ima; + /* Test if we already have a texture. */ + GPUTexture **tex = gpu_get_image_gputexture(ima, textarget); + if (*tex) { + return *tex; + } - if (compare && ima == GTS.curima) { - return (ima != NULL); + /* Check if we have a valid image. If not, we return a dummy + * texture with zero bindcode so we don't keep trying. */ + unsigned int bindcode = 0; + if (ima->ok == 0) { + *tex = GPU_texture_from_bindcode(textarget, bindcode); + return *tex; } - /* check if we have a valid image */ - if (ima == NULL || ima->ok == 0) - return 0; + /* currently, tpage refresh is used by ima sequences */ + if (ima->tpageflag & IMA_TPAGE_REFRESH) { + GPU_free_image(ima); + ima->tpageflag &= ~IMA_TPAGE_REFRESH; + } /* check if we have a valid image buffer */ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL); + if (ibuf == NULL) { + *tex = GPU_texture_from_bindcode(textarget, bindcode); + return *tex; + } - if (ibuf == NULL) - return 0; + /* flag to determine whether deep format is used */ + bool use_high_bit_depth = false, do_color_management = false; if (ibuf->rect_float) { if (U.use_16bit_textures) { @@ -337,50 +344,33 @@ int GPU_verify_image( } } - /* currently, tpage refresh is used by ima sequences */ - if (ima->tpageflag & IMA_TPAGE_REFRESH) { - GPU_free_image(ima); - ima->tpageflag &= ~IMA_TPAGE_REFRESH; - } + const int rectw = ibuf->x; + const int recth = ibuf->y; + unsigned int *rect = ibuf->rect; + float *frect = NULL; + float *srgb_frect = NULL; - { - /* regular image mode */ - bind = gpu_get_image_bindcode(ima, textarget); - - if (*bind == 0) { - tpx = ibuf->x; - tpy = ibuf->y; - rect = ibuf->rect; - if (use_high_bit_depth) { - if (do_color_management) { - frect = srgb_frect = MEM_mallocN(ibuf->x * ibuf->y * sizeof(*srgb_frect) * 4, "floar_buf_col_cor"); - gpu_verify_high_bit_srgb_buffer(srgb_frect, ibuf); - } - else - frect = ibuf->rect_float; - } + if (use_high_bit_depth) { + if (do_color_management) { + frect = srgb_frect = MEM_mallocN(ibuf->x * ibuf->y * sizeof(*srgb_frect) * 4, "floar_buf_col_cor"); + gpu_verify_high_bit_srgb_buffer(srgb_frect, ibuf); + } + else { + frect = ibuf->rect_float; } } - if (*bind != 0) { - /* enable opengl drawing with textures */ - glBindTexture(textarget, *bind); - BKE_image_release_ibuf(ima, ibuf, NULL); - return *bind; - } - - const int rectw = tpx; - const int recth = tpy; + const bool mipmap = GPU_get_mipmap(); #ifdef WITH_DDS if (ibuf->ftype == IMB_FTYPE_DDS) - GPU_create_gl_tex_compressed(bind, rect, rectw, recth, textarget, mipmap, ima, ibuf); + GPU_create_gl_tex_compressed(&bindcode, rect, rectw, recth, textarget, mipmap, ima, ibuf); else #endif - GPU_create_gl_tex(bind, rect, frect, rectw, recth, textarget, mipmap, use_high_bit_depth, ima); + GPU_create_gl_tex(&bindcode, rect, frect, rectw, recth, textarget, mipmap, use_high_bit_depth, ima); /* mark as non-color data texture */ - if (*bind) { + if (bindcode) { if (is_data) ima->tpageflag |= IMA_GLBIND_IS_DATA; else @@ -393,7 +383,8 @@ int GPU_verify_image( BKE_image_release_ibuf(ima, ibuf, NULL); - return *bind; + *tex = GPU_texture_from_bindcode(textarget, bindcode); + return *tex; } static void **gpu_gen_cube_map(unsigned int *rect, float *frect, int rectw, int recth, bool use_high_bit_depth) @@ -594,6 +585,8 @@ void GPU_create_gl_tex( if (GLEW_EXT_texture_filter_anisotropic) glTexParameterf(textarget, GL_TEXTURE_MAX_ANISOTROPY_EXT, GPU_get_anisotropic()); + glBindTexture(textarget, 0); + if (ibuf) IMB_freeImBuf(ibuf); } @@ -680,6 +673,8 @@ void GPU_create_gl_tex_compressed( glDeleteTextures(1, (GLuint *)bind); GPU_create_gl_tex(bind, pix, NULL, x, y, textarget, mipmap, 0, ima); } + + glBindTexture(textarget, 0); #endif } @@ -696,17 +691,13 @@ void GPU_paint_set_mipmap(bool mipmap) if (mipmap) { for (Image *ima = G.main->image.first; ima; ima = ima->id.next) { - if (BKE_image_has_bindcode(ima)) { + if (BKE_image_has_opengl_texture(ima)) { if (ima->tpageflag & IMA_MIPMAP_COMPLETE) { - if (ima->bindcode[TEXTARGET_TEXTURE_2D]) { - glBindTexture(GL_TEXTURE_2D, ima->bindcode[TEXTARGET_TEXTURE_2D]); + if (ima->gputexture[TEXTARGET_TEXTURE_2D]) { + GPU_texture_bind(ima->gputexture[TEXTARGET_TEXTURE_2D], 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter(0)); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1)); - } - if (ima->bindcode[TEXTARGET_TEXTURE_CUBE_MAP]) { - glBindTexture(GL_TEXTURE_CUBE_MAP, ima->bindcode[TEXTARGET_TEXTURE_CUBE_MAP]); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter(0)); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1)); + GPU_texture_unbind(ima->gputexture[TEXTARGET_TEXTURE_2D]); } } else @@ -719,16 +710,12 @@ void GPU_paint_set_mipmap(bool mipmap) } else { for (Image *ima = G.main->image.first; ima; ima = ima->id.next) { - if (BKE_image_has_bindcode(ima)) { - if (ima->bindcode[TEXTARGET_TEXTURE_2D]) { - glBindTexture(GL_TEXTURE_2D, ima->bindcode[TEXTARGET_TEXTURE_2D]); + if (BKE_image_has_opengl_texture(ima)) { + if (ima->gputexture[TEXTARGET_TEXTURE_2D]) { + GPU_texture_bind(ima->gputexture[TEXTARGET_TEXTURE_2D], 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1)); - } - if (ima->bindcode[TEXTARGET_TEXTURE_CUBE_MAP]) { - glBindTexture(GL_TEXTURE_CUBE_MAP, ima->bindcode[TEXTARGET_TEXTURE_CUBE_MAP]); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1)); + GPU_texture_unbind(ima->gputexture[TEXTARGET_TEXTURE_2D]); } } else @@ -761,12 +748,13 @@ static bool gpu_check_scaled_image(ImBuf *ibuf, Image *ima, float *frect, int x, if (rectw + x > x_limit) rectw--; if (recth + y > y_limit) recth--; + GPU_texture_bind(ima->gputexture[TEXTARGET_TEXTURE_2D], 0); + /* float rectangles are already continuous in memory so we can use IMB_scaleImBuf */ if (frect) { ImBuf *ibuf_scale = IMB_allocFromBuffer(NULL, frect, w, h); IMB_scaleImBuf(ibuf_scale, rectw, recth); - glBindTexture(GL_TEXTURE_2D, ima->bindcode[TEXTARGET_TEXTURE_2D]); glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, rectw, recth, GL_RGBA, GL_FLOAT, ibuf_scale->rect_float); @@ -786,7 +774,7 @@ static bool gpu_check_scaled_image(ImBuf *ibuf, Image *ima, float *frect, int x, bilinear_interpolation_color_wrap(ibuf, (unsigned char *)(p + i + j * (rectw)), NULL, u, v); } } - glBindTexture(GL_TEXTURE_2D, ima->bindcode[TEXTARGET_TEXTURE_2D]); + glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, rectw, recth, GL_RGBA, GL_UNSIGNED_BYTE, scalerect); @@ -800,6 +788,8 @@ static bool gpu_check_scaled_image(ImBuf *ibuf, Image *ima, float *frect, int x, ima->tpageflag &= ~IMA_MIPMAP_COMPLETE; } + GPU_texture_unbind(ima->gputexture[TEXTARGET_TEXTURE_2D]); + return true; } @@ -811,7 +801,7 @@ void GPU_paint_update_image(Image *ima, ImageUser *iuser, int x, int y, int w, i ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL); if ((!GTS.gpu_mipmap && GPU_get_mipmap()) || - (ima->bindcode[TEXTARGET_TEXTURE_2D] == 0) || + (ima->gputexture[TEXTARGET_TEXTURE_2D] == NULL) || (ibuf == NULL) || (w == 0) || (h == 0)) { @@ -835,7 +825,7 @@ void GPU_paint_update_image(Image *ima, ImageUser *iuser, int x, int y, int w, i return; } - glBindTexture(GL_TEXTURE_2D, ima->bindcode[TEXTARGET_TEXTURE_2D]); + GPU_texture_bind(ima->gputexture[TEXTARGET_TEXTURE_2D], 0); glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA, GL_FLOAT, buffer); MEM_freeN(buffer); @@ -849,6 +839,8 @@ void GPU_paint_update_image(Image *ima, ImageUser *iuser, int x, int y, int w, i ima->tpageflag &= ~IMA_MIPMAP_COMPLETE; } + GPU_texture_unbind(ima->gputexture[TEXTARGET_TEXTURE_2D]); + BKE_image_release_ibuf(ima, ibuf, NULL); return; } @@ -858,7 +850,7 @@ void GPU_paint_update_image(Image *ima, ImageUser *iuser, int x, int y, int w, i return; } - glBindTexture(GL_TEXTURE_2D, ima->bindcode[TEXTARGET_TEXTURE_2D]); + GPU_texture_bind(ima->gputexture[TEXTARGET_TEXTURE_2D], 0); glGetIntegerv(GL_UNPACK_ROW_LENGTH, &row_length); glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &skip_pixels); @@ -882,6 +874,8 @@ void GPU_paint_update_image(Image *ima, ImageUser *iuser, int x, int y, int w, i else { ima->tpageflag &= ~IMA_MIPMAP_COMPLETE; } + + GPU_texture_unbind(ima->gputexture[TEXTARGET_TEXTURE_2D]); } BKE_image_release_ibuf(ima, ibuf, NULL); @@ -1016,11 +1010,6 @@ void GPU_free_image(Image *ima) } for (int i = 0; i < TEXTARGET_COUNT; i++) { - /* free regular image binding */ - if (ima->bindcode[i]) { - glDeleteTextures(1, (GLuint *)&ima->bindcode[i]); - ima->bindcode[i] = 0; - } /* free glsl image binding */ if (ima->gputexture[i]) { GPU_texture_free(ima->gputexture[i]); @@ -1071,7 +1060,7 @@ void GPU_free_images_old(void) if ((ima->flag & IMA_NOCOLLECT) == 0 && ctime - ima->lastused > U.textimeout) { /* If it's in GL memory, deallocate and set time tag to current time * This gives textures a "second chance" to be used before dying. */ - if (BKE_image_has_bindcode(ima)) { + if (BKE_image_has_opengl_texture(ima)) { GPU_free_image(ima); ima->lastused = ctime; } diff --git a/source/blender/gpu/intern/gpu_framebuffer.c b/source/blender/gpu/intern/gpu_framebuffer.c index f86da2eb064..18f8c33c3ca 100644 --- a/source/blender/gpu/intern/gpu_framebuffer.c +++ b/source/blender/gpu/intern/gpu_framebuffer.c @@ -42,7 +42,9 @@ #include "GPU_shader.h" #include "GPU_texture.h" -static ThreadLocal(GLuint) g_currentfb; +#include "intern/gpu_private.h" + +static ThreadLocal(void *) g_currentfb; typedef enum { GPU_FB_DEPTH_ATTACHMENT = 0, @@ -163,6 +165,26 @@ static void gpu_print_framebuffer_error(GLenum status, char err_out[256]) } } +void gpu_framebuffer_module_init(void) +{ + BLI_thread_local_create(g_currentfb); +} + +void gpu_framebuffer_module_exit(void) +{ + BLI_thread_local_delete(g_currentfb); +} + +static uint gpu_framebuffer_current_get(void) +{ + return GET_UINT_FROM_POINTER(BLI_thread_local_get(g_currentfb)); +} + +static void gpu_framebuffer_current_set(uint object) +{ + BLI_thread_local_set(g_currentfb, SET_UINT_IN_POINTER(object)); +} + /* GPUFrameBuffer */ GPUFrameBuffer *GPU_framebuffer_create(void) @@ -188,8 +210,8 @@ void GPU_framebuffer_free(GPUFrameBuffer *fb) /* This restores the framebuffer if it was bound */ glDeleteFramebuffers(1, &fb->object); - if (g_currentfb == fb->object) { - g_currentfb = 0; + if (gpu_framebuffer_current_get() == fb->object) { + gpu_framebuffer_current_set(0); } MEM_freeN(fb); @@ -341,7 +363,7 @@ static void gpu_framebuffer_update_attachments(GPUFrameBuffer *fb) GLenum gl_attachments[GPU_FB_MAX_COLOR_ATTACHMENT]; int numslots = 0; - BLI_assert(g_currentfb == fb->object); + BLI_assert(gpu_framebuffer_current_get() == fb->object); /* Update attachments */ for (GPUAttachmentType type = 0; type < GPU_FB_MAX_ATTACHEMENT; ++type) { @@ -385,10 +407,10 @@ void GPU_framebuffer_bind(GPUFrameBuffer *fb) if (fb->object == 0) gpu_framebuffer_init(fb); - if (g_currentfb != fb->object) + if (gpu_framebuffer_current_get() != fb->object) glBindFramebuffer(GL_FRAMEBUFFER, fb->object); - g_currentfb = fb->object; + gpu_framebuffer_current_set(fb->object); if (fb->dirty_flag != 0) gpu_framebuffer_update_attachments(fb); @@ -409,20 +431,20 @@ void GPU_framebuffer_bind(GPUFrameBuffer *fb) void GPU_framebuffer_restore(void) { - if (g_currentfb != 0) { + if (gpu_framebuffer_current_get() != 0) { glBindFramebuffer(GL_FRAMEBUFFER, 0); - g_currentfb = 0; + gpu_framebuffer_current_set(0); } } bool GPU_framebuffer_bound(GPUFrameBuffer *fb) { - return (fb->object == g_currentfb) && (fb->object != 0); + return (fb->object == gpu_framebuffer_current_get()) && (fb->object != 0); } unsigned int GPU_framebuffer_current_get(void) { - return g_currentfb; + return gpu_framebuffer_current_get(); } bool GPU_framebuffer_check_valid(GPUFrameBuffer *fb, char err_out[256]) @@ -513,7 +535,7 @@ void GPU_framebuffer_blit( { BLI_assert(blit_buffers != 0); - GLuint prev_fb = g_currentfb; + GLuint prev_fb = gpu_framebuffer_current_get(); /* Framebuffers must be up to date. This simplify this function. */ if (fb_read->dirty_flag != 0 || fb_read->object == 0) { @@ -573,7 +595,7 @@ void GPU_framebuffer_blit( } else { glBindFramebuffer(GL_FRAMEBUFFER, prev_fb); - g_currentfb = prev_fb; + gpu_framebuffer_current_set(prev_fb); } } @@ -586,13 +608,13 @@ void GPU_framebuffer_recursive_downsample( void (*callback)(void *userData, int level), void *userData) { /* Framebuffer must be up to date and bound. This simplify this function. */ - if (g_currentfb != fb->object || fb->dirty_flag != 0 || fb->object == 0) { + if (gpu_framebuffer_current_get() != fb->object || fb->dirty_flag != 0 || fb->object == 0) { GPU_framebuffer_bind(fb); } /* HACK: We make the framebuffer appear not bound in order to * not trigger any error in GPU_texture_bind(). */ - GLuint prev_fb = g_currentfb; - g_currentfb = 0; + GLuint prev_fb = gpu_framebuffer_current_get(); + gpu_framebuffer_current_set(0); int i; int current_dim[2] = {fb->width, fb->height}; @@ -640,7 +662,7 @@ void GPU_framebuffer_recursive_downsample( } } - g_currentfb = prev_fb; + gpu_framebuffer_current_set(prev_fb); } /* GPUOffScreen */ diff --git a/source/blender/gpu/intern/gpu_init_exit.c b/source/blender/gpu/intern/gpu_init_exit.c index 92ad9d81b6c..78d4f491b66 100644 --- a/source/blender/gpu/intern/gpu_init_exit.c +++ b/source/blender/gpu/intern/gpu_init_exit.c @@ -60,6 +60,7 @@ void GPU_init(void) GPU_texture_orphans_init(); GPU_material_orphans_init(); gpu_codegen_init(); + gpu_framebuffer_module_init(); if (G.debug & G_DEBUG_GPU) gpu_debug_init(); @@ -89,6 +90,7 @@ void GPU_exit(void) if (G.debug & G_DEBUG_GPU) gpu_debug_exit(); + gpu_framebuffer_module_exit(); gpu_codegen_exit(); gpu_extensions_exit(); /* must come last */ diff --git a/source/blender/gpu/intern/gpu_private.h b/source/blender/gpu/intern/gpu_private.h index 72627e3563e..996ba9c63a1 100644 --- a/source/blender/gpu/intern/gpu_private.h +++ b/source/blender/gpu/intern/gpu_private.h @@ -33,4 +33,8 @@ void gpu_extensions_exit(void); void gpu_debug_init(void); void gpu_debug_exit(void); +/* gpu_framebuffer.c */ +void gpu_framebuffer_module_init(void); +void gpu_framebuffer_module_exit(void); + #endif /* __GPU_PRIVATE_H__ */ diff --git a/source/blender/gpu/intern/gpu_texture.c b/source/blender/gpu/intern/gpu_texture.c index aac75014b3e..ee00a1381f4 100644 --- a/source/blender/gpu/intern/gpu_texture.c +++ b/source/blender/gpu/intern/gpu_texture.c @@ -79,7 +79,6 @@ struct GPUTexture { GLenum target_base; /* same as target, (but no multisample) * use it for unbinding */ GLuint bindcode; /* opengl identifier for texture */ - int fromblender; /* we got the texture from Blender */ GPUTextureFormat format; GPUTextureFormatFlag format_flag; @@ -673,40 +672,22 @@ GPUTexture *GPU_texture_create_buffer(GPUTextureFormat data_type, const GLuint b return tex; } -GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, int textarget, bool is_data, double UNUSED(time), int mipmap) +GPUTexture *GPU_texture_from_bindcode(int textarget, int bindcode) { - int gputt; - /* this binds a texture, so that's why to restore it to 0 */ - GLint bindcode = GPU_verify_image(ima, iuser, textarget, 0, mipmap, is_data); - /* see GPUInput::textarget: it can take two values - GL_TEXTURE_2D and GL_TEXTURE_CUBE_MAP * these values are correct for glDisable, so textarget can be safely used in * GPU_texture_bind/GPU_texture_unbind through tex->target_base */ /* (is any of this obsolete now that we don't glEnable/Disable textures?) */ - if (textarget == GL_TEXTURE_2D) - gputt = TEXTARGET_TEXTURE_2D; - else - gputt = TEXTARGET_TEXTURE_CUBE_MAP; - - if (ima->gputexture[gputt]) { - ima->gputexture[gputt]->bindcode = bindcode; - glBindTexture(textarget, 0); - return ima->gputexture[gputt]; - } - GPUTexture *tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture"); tex->bindcode = bindcode; tex->number = -1; tex->refcount = 1; tex->target = textarget; tex->target_base = textarget; - tex->fromblender = 1; tex->format = -1; tex->components = -1; tex->samples = 0; - ima->gputexture[gputt] = tex; - if (!glIsTexture(tex->bindcode)) { GPU_print_error_debug("Blender Texture Not Loaded"); } @@ -725,10 +706,9 @@ GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, int textarget glGetTexLevelParameteriv(gettarget, 0, GL_TEXTURE_HEIGHT, &h); tex->w = w; tex->h = h; + glBindTexture(textarget, 0); } - glBindTexture(textarget, 0); - return tex; } @@ -1090,7 +1070,7 @@ void GPU_texture_wrap_mode(GPUTexture *tex, bool use_repeat) static void gpu_texture_delete(GPUTexture *tex) { - if (tex->bindcode && !tex->fromblender) + if (tex->bindcode) glDeleteTextures(1, &tex->bindcode); gpu_texture_memory_footprint_remove(tex); diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl index 4c77dd038af..1a07b26ff4d 100644 --- a/source/blender/gpu/shaders/gpu_shader_material.glsl +++ b/source/blender/gpu/shaders/gpu_shader_material.glsl @@ -8,38 +8,6 @@ uniform mat3 NormalMatrix; uniform mat4 ModelMatrixInverse; #endif -/* Old glsl mode compat. */ - -#ifndef CLOSURE_DEFAULT - -struct Closure { - vec3 radiance; - float opacity; -}; - -#define CLOSURE_DEFAULT Closure(vec3(0.0), 1.0) - -Closure closure_mix(Closure cl1, Closure cl2, float fac) -{ - Closure cl; - cl.radiance = mix(cl1.radiance, cl2.radiance, fac); - cl.opacity = mix(cl1.opacity, cl2.opacity, fac); - return cl; -} - -Closure closure_add(Closure cl1, Closure cl2) -{ - Closure cl; - cl.radiance = cl1.radiance + cl2.radiance; - cl.opacity = cl1.opacity + cl2.opacity; - return cl; -} - -Closure nodetree_exec(void); /* Prototype */ - -#endif /* CLOSURE_DEFAULT */ - - /* Converters */ float convert_rgba_to_float(vec4 color) diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h index f79d3259244..8043e01a147 100644 --- a/source/blender/makesdna/DNA_ID.h +++ b/source/blender/makesdna/DNA_ID.h @@ -382,6 +382,7 @@ typedef enum ID_Type { #define ID_CHECK_UNDO(id) ((GS((id)->name) != ID_SCR) && (GS((id)->name) != ID_WM) && (GS((id)->name) != ID_WS)) #define ID_BLEND_PATH(_bmain, _id) ((_id)->lib ? (_id)->lib->filepath : BKE_main_blendfile_path((_bmain))) +#define ID_BLEND_PATH_FROM_GLOBAL(_id) ((_id)->lib ? (_id)->lib->filepath : BKE_main_blendfile_path_from_global()) #define ID_MISSING(_id) (((_id)->tag & LIB_TAG_MISSING) != 0) diff --git a/source/blender/makesdna/DNA_image_types.h b/source/blender/makesdna/DNA_image_types.h index 3d29c5b3833..40fa9d40072 100644 --- a/source/blender/makesdna/DNA_image_types.h +++ b/source/blender/makesdna/DNA_image_types.h @@ -80,7 +80,9 @@ typedef struct ImagePackedFile { } ImagePackedFile; typedef struct RenderSlot { + struct RenderSlot *next, *prev; char name[64]; /* 64 = MAX_NAME */ + struct RenderResult *render; } RenderSlot; /* iuser->flag */ @@ -108,7 +110,7 @@ typedef struct Image { ListBase anims; struct RenderResult *rr; - struct RenderResult *renders[8]; /* IMA_MAX_RENDER_SLOT */ + ListBase renderslots; short render_slot, last_render_slot; int flag; @@ -118,7 +120,6 @@ typedef struct Image { /* texture page */ short tpageflag; short pad2; - unsigned int bindcode[2]; /* only for current image... 2 = TEXTARGET_COUNT */ unsigned int pad3; struct PackedFile *packedfile DNA_DEPRECATED; /* deprecated */ @@ -149,8 +150,6 @@ typedef struct Image { char views_format; ListBase views; /* ImageView */ struct Stereo3dFormat *stereo3d_format; - - RenderSlot render_slots[8]; /* 8 = IMA_MAX_RENDER_SLOT */ } Image; @@ -192,7 +191,6 @@ enum { /* render */ #define IMA_MAX_RENDER_TEXT 512 -#define IMA_MAX_RENDER_SLOT 8 /* gen_flag */ #define IMA_GEN_FLOAT 1 diff --git a/source/blender/makesdna/DNA_material_types.h b/source/blender/makesdna/DNA_material_types.h index 64c40cc3efa..5ebc41a184f 100644 --- a/source/blender/makesdna/DNA_material_types.h +++ b/source/blender/makesdna/DNA_material_types.h @@ -54,16 +54,6 @@ typedef struct TexPaintSlot { int pad; } TexPaintSlot; -/* Clay engine */ - -/* MaterialRuntimeClay.flag */ -#define CLAY_OUTDATED 1 - -/* MaterialEngineSettingsClay.type */ -#define CLAY_MATCAP_NONE 0 -#define CLAY_MATCAP_SIMPLE 1 -#define CLAY_MATCAP_COMPLETE 2 - typedef struct Material { ID id; struct AnimData *adt; /* animation data (must be immediately after id for utilities to use it) */ diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 0938d685edb..3cd0ed81ac5 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -1568,6 +1568,7 @@ enum { enum { MOD_NORMALEDIT_INVERT_VGROUP = (1 << 0), MOD_NORMALEDIT_USE_DIRECTION_PARALLEL = (1 << 1), + MOD_NORMALEDIT_NO_POLYNORS_FIX = (1 << 2), }; /* NormalEditModifierData.mix_mode */ diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index ea6a34df3f5..fd45eb52a60 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -1372,19 +1372,11 @@ typedef struct SceneDisplay { float light_direction[3]; /* light direction for shadows/highlight */ float shadow_shift; - int matcap_icon; - int matcap_type; - float matcap_rotation; - float matcap_hue; - float matcap_saturation; - float matcap_value; + /* Settings for Cavity Shader */ float matcap_ssao_distance; float matcap_ssao_attenuation; - float matcap_ssao_factor_cavity; - float matcap_ssao_factor_edge; - float matcap_hair_brightness_randomness; int matcap_ssao_samples; - + int pad; } SceneDisplay; typedef struct SceneEEVEE { @@ -1623,7 +1615,7 @@ enum { /* #define R_DEPRECATED 0x10000 */ /* #define R_RECURS_PROTECTION 0x20000 */ #define R_TEXNODE_PREVIEW 0x40000 -#define R_VIEWPORT_PREVIEW 0x80000 +/* #define R_VIEWPORT_PREVIEW 0x80000 */ #define R_EXR_CACHE_FILE 0x100000 #define R_MULTIVIEW 0x200000 @@ -1704,7 +1696,6 @@ enum { /* sequencer seq_prev_type seq_rend_type */ /* RenderData.engine (scene.c) */ -extern const char *RE_engine_id_BLENDER_CLAY; extern const char *RE_engine_id_BLENDER_EEVEE; extern const char *RE_engine_id_BLENDER_WORKBENCH; extern const char *RE_engine_id_CYCLES; diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h index 9213893ae66..7fd0dbeb156 100644 --- a/source/blender/makesdna/DNA_screen_types.h +++ b/source/blender/makesdna/DNA_screen_types.h @@ -309,6 +309,12 @@ typedef struct ScrArea { ScrArea_Runtime runtime; } ScrArea; + +typedef struct ARegion_Runtime { + /* Panel category to use between 'layout' and 'draw'. */ + const char *category; +} ARegion_Runtime; + typedef struct ARegion { struct ARegion *next, *prev; @@ -347,6 +353,8 @@ typedef struct ARegion { char *headerstr; /* use this string to draw info */ void *regiondata; /* XXX 2.50, need spacedata equivalent? */ + + ARegion_Runtime runtime; } ARegion; /* area->flag */ @@ -390,6 +398,7 @@ enum { /*PNL_TABBED = (1 << 3), */ /*UNUSED*/ PNL_OVERLAP = (1 << 4), PNL_PIN = (1 << 5), + PNL_POPOVER = (1 << 6), }; /* Panel->snap - for snapping to screen edges */ @@ -454,7 +463,8 @@ enum { RGN_TYPE_UI = 4, RGN_TYPE_TOOLS = 5, RGN_TYPE_TOOL_PROPS = 6, - RGN_TYPE_PREVIEW = 7 + RGN_TYPE_PREVIEW = 7, + RGN_TYPE_HUD = 8, }; /* use for function args */ #define RGN_TYPE_ANY -1 @@ -479,7 +489,9 @@ enum { /* Force delayed reinit of region size data, so that region size is calculated * just big enough to show all its content (if enough space is available). * Note that only ED_region_header supports this right now. */ - RGN_FLAG_DYNAMIC_SIZE = (1 << 2), + RGN_FLAG_DYNAMIC_SIZE = (1 << 2), + /* Region data is NULL'd on read, never written. */ + RGN_FLAG_TEMP_REGIONDATA = (1 << 3), }; /* region do_draw */ diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index 17f520fdfa9..7315c84070c 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -253,7 +253,7 @@ typedef struct ThemeSpace { char view_overlay[4]; - char wire[4], wire_edit[4], select[4]; + char wire[4], wire_edit[4], wire_inactive[4], select[4]; char lamp[4], speaker[4], empty[4], camera[4]; char active[4], group[4], group_active[4], transform[4]; char vertex[4], vertex_select[4], vertex_bevel[4], vertex_unreferenced[4]; @@ -361,6 +361,7 @@ typedef struct ThemeSpace { char metadatabg[4]; char metadatatext[4]; + int pad; } ThemeSpace; diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h index 9794a1efbf5..9686981d674 100644 --- a/source/blender/makesdna/DNA_view3d_types.h +++ b/source/blender/makesdna/DNA_view3d_types.h @@ -371,6 +371,7 @@ enum { V3D_OVERLAY_WIREFRAMES = (1 << 4), V3D_OVERLAY_HIDE_TEXT = (1 << 5), V3D_OVERLAY_HIDE_MOTION_PATHS = (1 << 6), + V3D_OVERLAY_ONION_SKINS = (1 << 7), }; /* View3DOverlay->edit_flag */ diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h index 6d5d2c380e2..a0c764d3771 100644 --- a/source/blender/makesdna/DNA_windowmanager_types.h +++ b/source/blender/makesdna/DNA_windowmanager_types.h @@ -377,11 +377,6 @@ typedef struct wmOperator { struct wmOperator *opm; /* current running macro, not saved */ struct uiLayout *layout; /* runtime for drawing */ short flag, pad[3]; - - /* Screen context the operator was finished in. It gets temporarily - * restored during operator repeat. Only set for registered operators. */ - struct ScrArea *execution_area; - struct ARegion *execution_region; } wmOperator; /* operator type return flags: exec(), invoke() modal(), return values */ diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index 125264ca03c..c08675961c7 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -597,6 +597,7 @@ extern StructRNA RNA_StretchToConstraint; extern StructRNA RNA_StringProperty; extern StructRNA RNA_Struct; extern StructRNA RNA_StucciTexture; +extern StructRNA RNA_StudioLight; extern StructRNA RNA_SubsurfModifier; extern StructRNA RNA_SunLamp; extern StructRNA RNA_SurfaceCurve; diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt index 64ddc67c052..f2ad76674c0 100644 --- a/source/blender/makesrna/intern/CMakeLists.txt +++ b/source/blender/makesrna/intern/CMakeLists.txt @@ -189,10 +189,6 @@ if(WITH_PYTHON) ) endif() -if(WITH_CLAY_ENGINE) - add_definitions(-DWITH_CLAY_ENGINE) -endif() - if(WITH_IMAGE_OPENEXR) add_definitions(-DWITH_OPENEXR) endif() diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c index 8a50da27144..0c2650ede2a 100644 --- a/source/blender/makesrna/intern/makesrna.c +++ b/source/blender/makesrna/intern/makesrna.c @@ -290,7 +290,7 @@ static void rna_sortlist(ListBase *listbase, int (*cmp)(const void *, const void Link *link; void **array; int a, size; - + if (listbase->first == listbase->last) return; @@ -497,7 +497,7 @@ static int rna_enum_bitmask(PropertyRNA *prop) if (eprop->item[a].identifier[0]) mask |= eprop->item[a].value; } - + return mask; } @@ -1416,7 +1416,7 @@ static void rna_set_raw_property(PropertyDefRNA *dp, PropertyRNA *prop) return; if (!dp->dnatype || !dp->dnaname || !dp->dnastructname) return; - + if (STREQ(dp->dnatype, "char")) { prop->rawtype = PROP_RAW_CHAR; prop->flag_internal |= PROP_INTERN_RAW_ACCESS; @@ -1677,7 +1677,7 @@ static void rna_def_property_funcs_header(FILE *f, StructRNA *srna, PropertyDefR if (sprop->maxlength) { fprintf(f, "#define %s_%s_MAX %d\n\n", srna->identifier, prop->identifier, sprop->maxlength); } - + fprintf(f, "void %sget(PointerRNA *ptr, char *value);\n", func); fprintf(f, "int %slength(PointerRNA *ptr);\n", func); fprintf(f, "void %sset(PointerRNA *ptr, const char *value);\n", func); @@ -1733,7 +1733,7 @@ static void rna_def_property_funcs_header_cpp(FILE *f, StructRNA *srna, Property if (prop->flag & PROP_IDPROPERTY || prop->flag_internal & PROP_INTERN_BUILTIN) { return; } - + /* disabled for now to avoid msvc compiler error due to large file size */ #if 0 if (prop->name && prop->description && prop->description[0] != '\0') @@ -2259,7 +2259,7 @@ static void rna_def_function_funcs(FILE *f, StructDefRNA *dsrna, FunctionDefRNA fprintf(f, "\n{\n"); /* variable definitions */ - + if (func->flag & FUNC_USE_SELF_ID) { fprintf(f, "\tstruct ID *_selfid;\n"); } @@ -2301,7 +2301,7 @@ static void rna_def_function_funcs(FILE *f, StructDefRNA *dsrna, FunctionDefRNA /* for dynamic parameters we pass an additional int for the length of the parameter */ if (flag & PROP_DYNAMIC) fprintf(f, "\tint %s%s_len;\n", pout ? "*" : "", dparm->prop->identifier); - + fprintf(f, "\t%s%s %s%s;\n", rna_type_struct(dparm->prop), rna_parameter_type_name(dparm->prop), ptrstr, dparm->prop->identifier); } @@ -2317,7 +2317,7 @@ static void rna_def_function_funcs(FILE *f, StructDefRNA *dsrna, FunctionDefRNA if (func->flag & FUNC_USE_SELF_ID) { fprintf(f, "\t_selfid = (struct ID *)_ptr->id.data;\n"); } - + if ((func->flag & FUNC_NO_SELF) == 0) { if (dsrna->dnafromprop) fprintf(f, "\t_self = (struct %s *)_ptr->data;\n", dsrna->dnafromname); else if (dsrna->dnaname) fprintf(f, "\t_self = (struct %s *)_ptr->data;\n", dsrna->dnaname); @@ -2886,7 +2886,7 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr { char *strnest = (char *)"", *errnest = (char *)""; int len, freenest = 0; - + if (nest != NULL) { len = strlen(nest); @@ -3443,7 +3443,7 @@ static void rna_generate(BlenderRNA *brna, FILE *f, const char *filename, const StructDefRNA *ds; PropertyDefRNA *dp; FunctionDefRNA *dfunc; - + fprintf(f, "\n" "/* Automatically generated struct definitions for the Data API.\n" @@ -3942,7 +3942,7 @@ static void rna_generate_header_cpp(BlenderRNA *UNUSED(brna), FILE *f) fprintf(f, "/* Automatically generated classes for the Data API.\n" " * Do not edit manually, changes will be overwritten. */\n\n"); - + fprintf(f, "#include \"RNA_blender.h\"\n"); fprintf(f, "#include \"RNA_types.h\"\n"); fprintf(f, "#include \"RNA_access.h\"\n"); diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c index 603f4dbc44f..11e45bc688d 100644 --- a/source/blender/makesrna/intern/rna_ID.c +++ b/source/blender/makesrna/intern/rna_ID.c @@ -156,13 +156,13 @@ void rna_ID_name_set(PointerRNA *ptr, const char *value) static int rna_ID_name_editable(PointerRNA *ptr, const char **UNUSED(r_info)) { ID *id = (ID *)ptr->data; - + if (GS(id->name) == ID_VF) { VFont *vfont = (VFont *)id; if (BKE_vfont_is_builtin(vfont)) return false; } - + return PROP_EDITABLE; } @@ -333,7 +333,7 @@ static ID *rna_ID_copy(ID *id, Main *bmain) if (newid) id_us_min(newid); return newid; } - + return NULL; } @@ -817,7 +817,7 @@ static void rna_def_ID_properties(BlenderRNA *brna) srna = RNA_def_struct(brna, "PropertyGroupItem", NULL); RNA_def_struct_sdna(srna, "IDProperty"); RNA_def_struct_ui_text(srna, "ID Property", "Property that stores arbitrary, user defined properties"); - + /* IDP_STRING */ prop = RNA_def_property(srna, "string", PROP_STRING, PROP_NONE); RNA_def_property_flag(prop, PROP_EXPORT | PROP_IDPROPERTY); @@ -903,7 +903,7 @@ static void rna_def_ID_materials(BlenderRNA *brna) StructRNA *srna; FunctionRNA *func; PropertyRNA *parm; - + /* for mesh/mball/curve materials */ srna = RNA_def_struct(brna, "IDMaterials", NULL); RNA_def_struct_sdna(srna, "ID"); @@ -1244,7 +1244,7 @@ static void rna_def_library(BlenderRNA *brna) RNA_def_property_string_sdna(prop, NULL, "name"); RNA_def_property_ui_text(prop, "File Path", "Path to the library .blend file"); RNA_def_property_string_funcs(prop, NULL, NULL, "rna_Library_filepath_set"); - + prop = RNA_def_property(srna, "parent", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "Library"); RNA_def_property_ui_text(prop, "Parent", ""); diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index df09e5c68b5..0532aac1bc3 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -107,9 +107,9 @@ void RNA_init(void) void RNA_exit(void) { StructRNA *srna; - + RNA_property_update_cache_free(); - + for (srna = BLENDER_RNA.structs.first; srna; srna = srna->cont.next) { if (srna->cont.prophash) { BLI_ghash_free(srna->cont.prophash, NULL, NULL); @@ -137,7 +137,7 @@ void RNA_id_pointer_create(ID *id, PointerRNA *r_ptr) PointerRNA tmp = {{NULL}}; tmp.data = id; idtype = rna_ID_refine(&tmp); - + while (idtype->refine) { type = idtype->refine(&tmp); @@ -147,7 +147,7 @@ void RNA_id_pointer_create(ID *id, PointerRNA *r_ptr) idtype = type; } } - + r_ptr->id.data = id; r_ptr->type = idtype; r_ptr->data = id; @@ -289,7 +289,7 @@ IDProperty *RNA_struct_idprops(PointerRNA *ptr, bool create) if (type && type->idproperties) { return type->idproperties(ptr, create); } - + return NULL; } @@ -380,7 +380,7 @@ static bool rna_idproperty_verify_valid(PointerRNA *ptr, PropertyRNA *prop, IDPr * description and otherwise removes it. this is to ensure that * rna property access is type safe, e.g. if you defined the rna * to have a certain array length you can count on that staying so */ - + switch (idprop->type) { case IDP_IDPARRAY: if (prop->type != PROP_COLLECTION) @@ -693,7 +693,7 @@ bool RNA_struct_is_a(const StructRNA *type, const StructRNA *srna) for (base = type; base; base = base->base) if (base == srna) return true; - + return false; } @@ -718,7 +718,7 @@ PropertyRNA *RNA_struct_find_property(PointerRNA *ptr, const char *identifier) if (RNA_property_collection_lookup_string(ptr, iterprop, identifier, &propptr)) return propptr.data; } - + return NULL; } @@ -1180,7 +1180,7 @@ void RNA_property_int_ui_range(PointerRNA *ptr, PropertyRNA *prop, int *softmin, { IntPropertyRNA *iprop = (IntPropertyRNA *)rna_ensure_property(prop); int hardmin, hardmax; - + if (prop->magic != RNA_MAGIC) { /* attempt to get the local ID values */ IDProperty *idp_ui = rna_idproperty_ui(prop); @@ -1693,7 +1693,7 @@ bool RNA_property_enum_identifier(bContext *C, PointerRNA *ptr, PropertyRNA *pro { const EnumPropertyItem *item = NULL; bool free; - + RNA_property_enum_items(C, ptr, prop, &item, NULL, &free); if (item) { bool result; @@ -1710,7 +1710,7 @@ bool RNA_property_enum_name(bContext *C, PointerRNA *ptr, PropertyRNA *prop, con { const EnumPropertyItem *item = NULL; bool free; - + RNA_property_enum_items(C, ptr, prop, &item, NULL, &free); if (item) { bool result; @@ -1718,7 +1718,7 @@ bool RNA_property_enum_name(bContext *C, PointerRNA *ptr, PropertyRNA *prop, con if (free) { MEM_freeN((void *)item); } - + return result; } return false; @@ -1932,7 +1932,7 @@ bool RNA_property_animateable(PointerRNA *ptr, PropertyRNA *prop) /* check that base ID-block can support animation data */ if (!id_can_have_animdata(ptr->id.data)) return false; - + prop = rna_ensure_property(prop); if (!(prop->flag & PROP_ANIMATABLE)) @@ -2147,7 +2147,7 @@ void RNA_property_update_main(Main *bmain, Scene *scene, PointerRNA *ptr, Proper /* cache element */ typedef struct tRnaUpdateCacheElem { struct tRnaUpdateCacheElem *next, *prev; - + PointerRNA ptr; /* L1 key - id as primary, data secondary/ignored? */ ListBase L2Funcs; /* L2 functions (LinkData<RnaUpdateFuncRef>) */ } tRnaUpdateCacheElem; @@ -2163,18 +2163,18 @@ void RNA_property_update_cache_add(PointerRNA *ptr, PropertyRNA *prop) tRnaUpdateCacheElem *uce = NULL; UpdateFunc fn = NULL; LinkData *ld; - + /* sanity check */ if (NULL == ptr) return; - + prop = rna_ensure_property(prop); - + /* we can only handle update calls with no context args for now (makes animsys updates easier) */ if ((is_rna == false) || (prop->update == NULL) || (prop->flag & PROP_CONTEXT_UPDATE)) return; fn = prop->update; - + /* find cache element for which key matches... */ for (uce = rna_updates_cache.first; uce; uce = uce->next) { /* just match by id only for now, since most update calls that we'll encounter only really care about this */ @@ -2187,11 +2187,11 @@ void RNA_property_update_cache_add(PointerRNA *ptr, PropertyRNA *prop) /* create new instance */ uce = MEM_callocN(sizeof(tRnaUpdateCacheElem), "tRnaUpdateCacheElem"); BLI_addtail(&rna_updates_cache, uce); - + /* copy pointer */ RNA_pointer_create(ptr->id.data, ptr->type, ptr->data, &uce->ptr); } - + /* check on the update func */ for (ld = uce->L2Funcs.first; ld; ld = ld->next) { /* stop on match - function already cached */ @@ -2205,13 +2205,13 @@ void RNA_property_update_cache_add(PointerRNA *ptr, PropertyRNA *prop) void RNA_property_update_cache_flush(Main *bmain, Scene *scene) { tRnaUpdateCacheElem *uce; - + /* TODO: should we check that bmain and scene are valid? The above stuff doesn't! */ - + /* execute the cached updates */ for (uce = rna_updates_cache.first; uce; uce = uce->next) { LinkData *ld; - + for (ld = uce->L2Funcs.first; ld; ld = ld->next) { UpdateFunc fn = (UpdateFunc)ld->data; fn(bmain, scene, &uce->ptr); @@ -2222,13 +2222,13 @@ void RNA_property_update_cache_flush(Main *bmain, Scene *scene) void RNA_property_update_cache_free(void) { tRnaUpdateCacheElem *uce, *ucn; - + for (uce = rna_updates_cache.first; uce; uce = ucn) { ucn = uce->next; - + /* free L2 cache */ BLI_freelistN(&uce->L2Funcs); - + /* remove self */ BLI_freelinkN(&rna_updates_cache, uce); } @@ -2429,7 +2429,7 @@ int RNA_property_boolean_get_default(PointerRNA *UNUSED(ptr), PropertyRNA *prop) void RNA_property_boolean_get_default_array(PointerRNA *UNUSED(ptr), PropertyRNA *prop, int *values) { BoolPropertyRNA *bprop = (BoolPropertyRNA *)rna_ensure_property(prop); - + BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN); BLI_assert(RNA_property_array_check(prop) != false); @@ -2684,7 +2684,7 @@ int RNA_property_int_get_default(PointerRNA *UNUSED(ptr), PropertyRNA *prop) void RNA_property_int_get_default_array(PointerRNA *UNUSED(ptr), PropertyRNA *prop, int *values) { IntPropertyRNA *iprop = (IntPropertyRNA *)rna_ensure_property(prop); - + BLI_assert(RNA_property_type(prop) == PROP_INT); BLI_assert(RNA_property_array_check(prop) != false); @@ -2971,7 +2971,7 @@ float RNA_property_float_get_default(PointerRNA *UNUSED(ptr), PropertyRNA *prop) void RNA_property_float_get_default_array(PointerRNA *UNUSED(ptr), PropertyRNA *prop, float *values) { FloatPropertyRNA *fprop = (FloatPropertyRNA *)rna_ensure_property(prop); - + BLI_assert(RNA_property_type(prop) == PROP_FLOAT); BLI_assert(RNA_property_array_check(prop) != false); @@ -3407,7 +3407,7 @@ void RNA_property_pointer_remove(PointerRNA *ptr, PropertyRNA *prop) if ((idprop = rna_idproperty_check(&prop, ptr))) { group = RNA_struct_idprops(ptr, 0); - + if (group) { IDP_FreeFromGroup(group, idprop); } @@ -3688,7 +3688,7 @@ int RNA_property_collection_lookup_index(PointerRNA *ptr, PropertyRNA *prop, Poi { CollectionPropertyIterator iter; int index = 0; - + BLI_assert(RNA_property_type(prop) == PROP_COLLECTION); RNA_property_collection_begin(ptr, prop, &iter); @@ -3697,7 +3697,7 @@ int RNA_property_collection_lookup_index(PointerRNA *ptr, PropertyRNA *prop, Poi break; } RNA_property_collection_end(&iter); - + /* did we find it? */ if (iter.valid) return index; @@ -3890,7 +3890,7 @@ static int rna_property_array_length_all_dimensions(PointerRNA *ptr, PropertyRNA for (size = 1, i = 0; i < dim; i++) size *= len[i]; - + return size; } @@ -3943,7 +3943,7 @@ static int rna_raw_access(ReportList *reports, PointerRNA *ptr, PropertyRNA *pro out.len * arraylen, in.len); return 0; } - + /* matching raw types */ if (out.type == in.type) { void *inp = in.array; @@ -4301,7 +4301,7 @@ void rna_iterator_array_begin(CollectionPropertyIterator *iter, void *ptr, int i internal->itemsize = itemsize; internal->skip = skip; internal->length = length; - + iter->valid = (internal->ptr != internal->endptr); if (skip && iter->valid && skip(iter, internal->ptr)) @@ -4342,7 +4342,7 @@ void *rna_iterator_array_dereference_get(CollectionPropertyIterator *iter) void rna_iterator_array_end(CollectionPropertyIterator *iter) { ArrayIterator *internal = &iter->internal.array; - + if (internal->free_ptr) { MEM_freeN(internal->free_ptr); internal->free_ptr = NULL; @@ -4397,7 +4397,7 @@ static char *rna_path_token(const char **path, char *fixedbuf, int fixedlen, int len++; p++; } - + /* skip the last quoted char to get the ']' */ len++; p++; @@ -4414,11 +4414,11 @@ static char *rna_path_token(const char **path, char *fixedbuf, int fixedlen, int p++; } } - + /* empty, return */ if (len == 0) return NULL; - + /* try to use fixed buffer if possible */ if (len + 1 < fixedlen) buf = fixedbuf; @@ -4464,22 +4464,22 @@ static bool rna_path_parse_collection_key(const char **path, PointerRNA *ptr, Pr { char fixedbuf[256]; int intkey; - + *r_nextptr = *ptr; /* end of path, ok */ if (!(**path)) return true; - + if (**path == '[') { char *token; /* resolve the lookup with [] brackets */ token = rna_path_token(path, fixedbuf, sizeof(fixedbuf), 1); - + if (!token) return false; - + /* check for "" to see if it is a string */ if (rna_token_strip_quotes(token)) { if (RNA_property_collection_lookup_string(ptr, prop, token + 1, r_nextptr)) { @@ -4502,7 +4502,7 @@ static bool rna_path_parse_collection_key(const char **path, PointerRNA *ptr, Pr r_nextptr->data = NULL; } } - + if (token != fixedbuf) { MEM_freeN(token); } @@ -4516,7 +4516,7 @@ static bool rna_path_parse_collection_key(const char **path, PointerRNA *ptr, Pr r_nextptr->data = NULL; } } - + return true; } @@ -4527,21 +4527,21 @@ static bool rna_path_parse_array_index(const char **path, PointerRNA *ptr, Prope int len[RNA_MAX_ARRAY_DIMENSION]; const int dim = RNA_property_array_dimension(ptr, prop, len); int i; - + *r_index = -1; - + /* end of path, ok */ if (!(**path)) return true; - + for (i = 0; i < dim; i++) { int temp_index = -1; char *token; - + /* multi index resolve */ if (**path == '[') { token = rna_path_token(path, fixedbuf, sizeof(fixedbuf), 1); - + if (token == NULL) { /* invalid syntax blah[] */ return false; @@ -4553,12 +4553,12 @@ static bool rna_path_parse_array_index(const char **path, PointerRNA *ptr, Prope else { /* otherwise do int lookup */ temp_index = atoi(token); - + if (temp_index == 0 && (token[0] != '0' || token[1] != '\0')) { if (token != fixedbuf) { MEM_freeN(token); } - + return false; } } @@ -4576,33 +4576,33 @@ static bool rna_path_parse_array_index(const char **path, PointerRNA *ptr, Prope /* just to avoid uninitialized pointer use */ token = fixedbuf; } - + if (token != fixedbuf) { MEM_freeN(token); } - + /* out of range */ if (temp_index < 0 || temp_index >= len[i]) return false; - + index_arr[i] = temp_index; /* end multi index resolve */ } - + /* arrays always contain numbers so further values are not valid */ if (**path) return false; - + /* flatten index over all dimensions */ { int totdim = 1; int flat_index = 0; - + for (i = dim - 1; i >= 0; i--) { flat_index += index_arr[i] * totdim; totdim *= len[i]; } - + *r_index = flat_index; } return true; @@ -4678,7 +4678,7 @@ static bool rna_path_parse(PointerRNA *ptr, const char *path, */ if (eval_pointer || *path) { PointerRNA nextptr = RNA_property_pointer_get(&curptr, prop); - + curptr = nextptr; prop = NULL; /* now we have a PointerRNA, the prop is our parent so forget it */ index = -1; @@ -4695,7 +4695,7 @@ static bool rna_path_parse(PointerRNA *ptr, const char *path, PointerRNA nextptr; if (!rna_path_parse_collection_key(&path, &curptr, prop, &nextptr)) return false; - + curptr = nextptr; prop = NULL; /* now we have a PointerRNA, the prop is our parent so forget it */ index = -1; @@ -4812,7 +4812,7 @@ char *RNA_path_append(const char *path, PointerRNA *UNUSED(ptr), PropertyRNA *pr DynStr *dynstr; const char *s; char appendstr[128], *result; - + dynstr = BLI_dynstr_new(); /* add .identifier */ @@ -4887,7 +4887,7 @@ char *RNA_path_back(const char *path) token = rna_path_token(¤t, fixedbuf, sizeof(fixedbuf), 1); if (token && token != fixedbuf) MEM_freeN(token); - + if (!*current) break; @@ -5058,7 +5058,7 @@ char *RNA_path_from_ID_to_struct(PointerRNA *ptr) if (!ptr->id.data || !ptr->data) return NULL; - + if (!RNA_struct_is_ID(ptr->type)) { if (ptr->type->path) { /* if type has a path to some ID, use it */ @@ -5067,13 +5067,13 @@ char *RNA_path_from_ID_to_struct(PointerRNA *ptr) else if (ptr->type->nested && RNA_struct_is_ID(ptr->type->nested)) { PointerRNA parentptr; PropertyRNA *userprop; - + /* find the property in the struct we're nested in that references this struct, and * use its identifier as the first part of the path used... */ RNA_id_pointer_create(ptr->id.data, &parentptr); userprop = RNA_struct_find_nested(&parentptr, ptr->type); - + if (userprop) ptrpath = BLI_strdup(RNA_property_identifier(userprop)); else @@ -5086,7 +5086,7 @@ char *RNA_path_from_ID_to_struct(PointerRNA *ptr) else return NULL; } - + return ptrpath; } @@ -5138,7 +5138,7 @@ char *RNA_path_from_ID_to_property_index(PointerRNA *ptr, PropertyRNA *prop, int if (!ptr->id.data || !ptr->data) return NULL; - + /* path from ID to the struct holding this property */ ptrpath = RNA_path_from_ID_to_struct(ptr); @@ -5868,23 +5868,23 @@ char *RNA_pointer_as_string_id(bContext *C, PointerRNA *ptr) { DynStr *dynstr = BLI_dynstr_new(); char *cstring; - + const char *propname; int first_time = 1; - + BLI_dynstr_append(dynstr, "{"); - + RNA_STRUCT_BEGIN (ptr, prop) { propname = RNA_property_identifier(prop); - + if (STREQ(propname, "rna_type")) continue; - + if (first_time == 0) BLI_dynstr_append(dynstr, ", "); first_time = 0; - + cstring = RNA_property_as_string(C, ptr, prop, -1, INT_MAX); BLI_dynstr_appendf(dynstr, "\"%s\":%s", propname, cstring); MEM_freeN(cstring); @@ -5892,8 +5892,8 @@ char *RNA_pointer_as_string_id(bContext *C, PointerRNA *ptr) RNA_STRUCT_END; BLI_dynstr_append(dynstr, "}"); - - + + cstring = BLI_dynstr_get_cstring(dynstr); BLI_dynstr_free(dynstr); return cstring; @@ -6046,7 +6046,7 @@ char *RNA_property_as_string(bContext *C, PointerRNA *ptr, PropertyRNA *prop, in DynStr *dynstr = BLI_dynstr_new(); char *cstring; - + /* see if we can coerce into a python type - PropertyType */ switch (type) { @@ -6217,7 +6217,7 @@ char *RNA_property_as_string(bContext *C, PointerRNA *ptr, PropertyRNA *prop, in BLI_dynstr_append(dynstr, cstring); MEM_freeN(cstring); } - + RNA_property_collection_end(&collect_iter); BLI_dynstr_append(dynstr, "]"); break; @@ -6323,7 +6323,7 @@ ParameterList *RNA_parameter_list_create(ParameterList *parms, PointerRNA *UNUSE data_alloc->array_tot = 0; data_alloc->array = NULL; } - + if (!(parm->flag_parameter & PARM_REQUIRED) && !(parm->flag & PROP_DYNAMIC)) { switch (parm->type) { case PROP_BOOLEAN: @@ -6752,7 +6752,7 @@ static int rna_function_parameter_parse(PointerRNA *ptr, PropertyRNA *prop, Prop *((PointerRNA *)dest) = *((PointerRNA *)src); break; } - + if (ptype != srna && !RNA_struct_is_a(srna, ptype)) { fprintf(stderr, "%s.%s: wrong type for parameter %s, " "an object of type %s was expected, passed an object of type %s\n", @@ -6779,7 +6779,7 @@ static int rna_function_parameter_parse(PointerRNA *ptr, PropertyRNA *prop, Prop lb = (ListBase *)src; clb = (ListBase *)dest; ptype = RNA_property_pointer_type(ptr, prop); - + if (ptype != srna && !RNA_struct_is_a(srna, ptype)) { fprintf(stderr, "%s.%s: wrong type for parameter %s, " "a collection of objects of type %s was expected, " @@ -7025,17 +7025,17 @@ bool RNA_property_reset(PointerRNA *ptr, PropertyRNA *prop, int index) /* get the length of the array to work with */ len = RNA_property_array_length(ptr, prop); - + /* get and set the default values as appropriate for the various types */ switch (RNA_property_type(prop)) { case PROP_BOOLEAN: if (len) { if (index == -1) { int *tmparray = MEM_callocN(sizeof(int) * len, "reset_defaults - boolean"); - + RNA_property_boolean_get_default_array(ptr, prop, tmparray); RNA_property_boolean_set_array(ptr, prop, tmparray); - + MEM_freeN(tmparray); } else { @@ -7052,10 +7052,10 @@ bool RNA_property_reset(PointerRNA *ptr, PropertyRNA *prop, int index) if (len) { if (index == -1) { int *tmparray = MEM_callocN(sizeof(int) * len, "reset_defaults - int"); - + RNA_property_int_get_default_array(ptr, prop, tmparray); RNA_property_int_set_array(ptr, prop, tmparray); - + MEM_freeN(tmparray); } else { @@ -7072,10 +7072,10 @@ bool RNA_property_reset(PointerRNA *ptr, PropertyRNA *prop, int index) if (len) { if (index == -1) { float *tmparray = MEM_callocN(sizeof(float) * len, "reset_defaults - float"); - + RNA_property_float_get_default_array(ptr, prop, tmparray); RNA_property_float_set_array(ptr, prop, tmparray); - + MEM_freeN(tmparray); } else { @@ -7094,7 +7094,7 @@ bool RNA_property_reset(PointerRNA *ptr, PropertyRNA *prop, int index) RNA_property_enum_set(ptr, prop, value); return true; } - + case PROP_STRING: { char *value = RNA_property_string_get_default_alloc(ptr, prop, NULL, 0); @@ -7102,14 +7102,14 @@ bool RNA_property_reset(PointerRNA *ptr, PropertyRNA *prop, int index) MEM_freeN(value); return true; } - + case PROP_POINTER: { PointerRNA value = RNA_property_pointer_get_default(ptr, prop); RNA_property_pointer_set(ptr, prop, value); return true; } - + default: /* FIXME: are there still any cases that haven't been handled? comment out "default" block to check :) */ return false; diff --git a/source/blender/makesrna/intern/rna_action.c b/source/blender/makesrna/intern/rna_action.c index b06038a50e4..5b225b18a78 100644 --- a/source/blender/makesrna/intern/rna_action.c +++ b/source/blender/makesrna/intern/rna_action.c @@ -61,13 +61,13 @@ static void rna_ActionGroup_channels_next(CollectionPropertyIterator *iter) ListBaseIterator *internal = &iter->internal.listbase; FCurve *fcu = (FCurve *)internal->link; bActionGroup *grp = fcu->grp; - + /* only continue if the next F-Curve (if existent) belongs in the same group */ if ((fcu->next) && (fcu->next->grp == grp)) internal->link = (Link *)fcu->next; else internal->link = NULL; - + iter->valid = (internal->link != NULL); } @@ -80,7 +80,7 @@ static void rna_Action_groups_remove(bAction *act, ReportList *reports, PointerR { bActionGroup *agrp = agrp_ptr->data; FCurve *fcu, *fcn; - + /* try to remove the F-Curve from the action */ if (BLI_remlink_safe(&act->groups, agrp) == false) { BKE_reportf(reports, RPT_ERROR, "Action group '%s' not found in action '%s'", agrp->name, act->id.name + 2); @@ -141,7 +141,7 @@ static void rna_Action_fcurve_remove(bAction *act, ReportList *reports, PointerR fcu->grp->name, act->id.name + 2); return; } - + action_groups_remove_channel(act, fcu); free_fcurve(fcu); RNA_POINTER_INVALIDATE(fcu_ptr); @@ -151,7 +151,7 @@ static void rna_Action_fcurve_remove(bAction *act, ReportList *reports, PointerR BKE_reportf(reports, RPT_ERROR, "F-Curve not found in action '%s'", act->id.name + 2); return; } - + BLI_remlink(&act->curves, fcu); free_fcurve(fcu); RNA_POINTER_INVALIDATE(fcu_ptr); @@ -227,7 +227,7 @@ int rna_Action_id_poll(PointerRNA *ptr, PointerRNA value) { ID *srcId = (ID *)ptr->id.data; bAction *act = (bAction *)value.id.data; - + if (act) { /* there can still be actions that will have undefined id-root * (i.e. floating "action-library" members) which we will not @@ -238,7 +238,7 @@ int rna_Action_id_poll(PointerRNA *ptr, PointerRNA value) else if (srcId) return GS(srcId->name) == act->idroot; } - + return 0; } @@ -247,7 +247,7 @@ int rna_Action_actedit_assign_poll(PointerRNA *ptr, PointerRNA value) { SpaceAction *saction = (SpaceAction *)ptr->data; bAction *act = (bAction *)value.id.data; - + if (act) { /* there can still be actions that will have undefined id-root * (i.e. floating "action-library" members) which we will not @@ -255,7 +255,7 @@ int rna_Action_actedit_assign_poll(PointerRNA *ptr, PointerRNA value) */ if (act->idroot == 0) return 1; - + if (saction) { if (saction->mode == SACTCONT_ACTION) { /* this is only Object-level for now... */ @@ -267,7 +267,7 @@ int rna_Action_actedit_assign_poll(PointerRNA *ptr, PointerRNA value) } } } - + return 0; } @@ -281,14 +281,14 @@ static void rna_def_dopesheet(BlenderRNA *brna) srna = RNA_def_struct(brna, "DopeSheet", NULL); RNA_def_struct_sdna(srna, "bDopeSheet"); RNA_def_struct_ui_text(srna, "Dope Sheet", "Settings for filtering the channels shown in animation editors"); - + /* Source of DopeSheet data */ /* XXX: make this obsolete? */ prop = RNA_def_property(srna, "source", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "ID"); RNA_def_property_ui_text(prop, "Source", "ID-Block representing source data, usually ID_SCE (i.e. Scene)"); - + /* Show data-block filters */ prop = RNA_def_property(srna, "show_datablock_filters", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", ADS_FLAG_SHOW_DBFILTERS); @@ -296,20 +296,20 @@ static void rna_def_dopesheet(BlenderRNA *brna) "Show options for whether channels related to certain types of data are included"); RNA_def_property_ui_icon(prop, ICON_DISCLOSURE_TRI_RIGHT, 1); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN, NULL); - + /* General Filtering Settings */ prop = RNA_def_property(srna, "show_only_selected", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "filterflag", ADS_FILTER_ONLYSEL); RNA_def_property_ui_text(prop, "Only Selected", "Only include channels relating to selected objects and data"); RNA_def_property_ui_icon(prop, ICON_RESTRICT_SELECT_OFF, 0); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); - + prop = RNA_def_property(srna, "show_hidden", PROP_BOOLEAN, PROP_NONE); 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_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); - + prop = RNA_def_property(srna, "use_datablock_sort", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", ADS_FLAG_NO_DB_SORT); RNA_def_property_ui_text(prop, "Sort Data-Blocks", @@ -317,14 +317,14 @@ static void rna_def_dopesheet(BlenderRNA *brna) "(disable to increase viewport speed)"); RNA_def_property_ui_icon(prop, ICON_SORTALPHA, 0); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); - + /* Debug Filtering Settings */ prop = RNA_def_property(srna, "show_only_errors", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "filterflag", ADS_FILTER_ONLY_ERRORS); RNA_def_property_ui_text(prop, "Show Errors", "Only include F-Curves and drivers that are disabled or have errors"); RNA_def_property_ui_icon(prop, ICON_HELP, 0); /* XXX: this doesn't quite fit */ RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); - + /* Object Collection Filtering Settings */ prop = RNA_def_property(srna, "show_only_collection_objects", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "filterflag", ADS_FILTER_ONLYOBGROUP); @@ -332,13 +332,13 @@ static void rna_def_dopesheet(BlenderRNA *brna) "Only include channels from objects in the specified collection"); RNA_def_property_ui_icon(prop, ICON_GROUP, 0); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); - + prop = RNA_def_property(srna, "filter_collection", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "filter_grp"); RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Filtering Collection", "Collection that included object should be a member of"); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); - + /* FCurve Display Name Search Settings */ prop = RNA_def_property(srna, "show_only_matching_fcurves", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "filterflag", ADS_FILTER_BY_FCU_NAME); @@ -346,13 +346,13 @@ static void rna_def_dopesheet(BlenderRNA *brna) "Only include F-Curves with names containing search text"); RNA_def_property_ui_icon(prop, ICON_VIEWZOOM, 0); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); - + prop = RNA_def_property(srna, "filter_fcurve_name", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "searchstr"); RNA_def_property_ui_text(prop, "F-Curve Name Filter", "F-Curve live filtering string"); RNA_def_property_flag(prop, PROP_TEXTEDIT_UPDATE); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); - + /* NLA Name Search Settings (Shared with FCurve setting, but with different labels) */ prop = RNA_def_property(srna, "use_filter_text", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "filterflag", ADS_FILTER_BY_FCU_NAME); @@ -360,13 +360,13 @@ static void rna_def_dopesheet(BlenderRNA *brna) "Only include channels with names containing search text"); RNA_def_property_ui_icon(prop, ICON_VIEWZOOM, 0); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); - + prop = RNA_def_property(srna, "filter_text", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "searchstr"); RNA_def_property_ui_text(prop, "Name Filter", "Live filtering string"); RNA_def_property_flag(prop, PROP_TEXTEDIT_UPDATE); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); - + /* Multi-word fuzzy search option for name/text filters */ prop = RNA_def_property(srna, "use_multi_word_filter", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", ADS_FLAG_FUZZY_NAMES); @@ -374,7 +374,7 @@ static void rna_def_dopesheet(BlenderRNA *brna) "Perform fuzzy/multi-word matching (WARNING: May be slow)"); RNA_def_property_ui_icon(prop, ICON_SORTALPHA, 0); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); - + /* NLA Specific Settings */ prop = RNA_def_property(srna, "show_missing_nla", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "filterflag", ADS_FILTER_NLA_NOACT); @@ -382,21 +382,21 @@ static void rna_def_dopesheet(BlenderRNA *brna) "Include animation data-blocks with no NLA data (NLA editor only)"); RNA_def_property_ui_icon(prop, ICON_ACTION, 0); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); - + /* Summary Settings (DopeSheet editors only) */ prop = RNA_def_property(srna, "show_summary", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "filterflag", ADS_FILTER_SUMMARY); RNA_def_property_ui_text(prop, "Display Summary", "Display an additional 'summary' line (Dope Sheet editors only)"); RNA_def_property_ui_icon(prop, ICON_BORDERMOVE, 0); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); - + prop = RNA_def_property(srna, "show_expanded_summary", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", ADS_FLAG_SUMMARY_COLLAPSED); RNA_def_property_ui_text(prop, "Collapse Summary", "Collapse summary when shown, so all other channels get hidden (Dope Sheet editors only)"); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); - - + + /* General DataType Filtering Settings */ prop = RNA_def_property(srna, "show_transforms", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "filterflag", ADS_FILTER_NOOBJ); @@ -404,98 +404,98 @@ static void rna_def_dopesheet(BlenderRNA *brna) "Include visualization of object-level animation data (mostly transforms)"); RNA_def_property_ui_icon(prop, ICON_MANIPUL, 0); /* XXX? */ RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); - + prop = RNA_def_property(srna, "show_shapekeys", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "filterflag", ADS_FILTER_NOSHAPEKEYS); RNA_def_property_ui_text(prop, "Display Shapekeys", "Include visualization of shape key related animation data"); RNA_def_property_ui_icon(prop, ICON_SHAPEKEY_DATA, 0); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); - + prop = RNA_def_property(srna, "show_modifiers", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "filterflag", ADS_FILTER_NOMODIFIERS); RNA_def_property_ui_text(prop, "Display Modifier Data", "Include visualization of animation data related to data-blocks linked to modifiers"); RNA_def_property_ui_icon(prop, ICON_MODIFIER, 0); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); - + prop = RNA_def_property(srna, "show_meshes", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "filterflag", ADS_FILTER_NOMESH); RNA_def_property_ui_text(prop, "Display Meshes", "Include visualization of mesh related animation data"); RNA_def_property_ui_icon(prop, ICON_MESH_DATA, 0); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); - + prop = RNA_def_property(srna, "show_lattices", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "filterflag", ADS_FILTER_NOLAT); RNA_def_property_ui_text(prop, "Display Lattices", "Include visualization of lattice related animation data"); RNA_def_property_ui_icon(prop, ICON_LATTICE_DATA, 0); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); - + prop = RNA_def_property(srna, "show_cameras", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "filterflag", ADS_FILTER_NOCAM); RNA_def_property_ui_text(prop, "Display Camera", "Include visualization of camera related animation data"); RNA_def_property_ui_icon(prop, ICON_CAMERA_DATA, 0); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); - + prop = RNA_def_property(srna, "show_materials", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "filterflag", ADS_FILTER_NOMAT); RNA_def_property_ui_text(prop, "Display Material", "Include visualization of material related animation data"); RNA_def_property_ui_icon(prop, ICON_MATERIAL_DATA, 0); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); - + prop = RNA_def_property(srna, "show_lamps", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "filterflag", ADS_FILTER_NOLAM); RNA_def_property_ui_text(prop, "Display Lamp", "Include visualization of lamp related animation data"); RNA_def_property_ui_icon(prop, ICON_LAMP_DATA, 0); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); - + prop = RNA_def_property(srna, "show_linestyles", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "filterflag", ADS_FILTER_NOLINESTYLE); RNA_def_property_ui_text(prop, "Display Line Style", "Include visualization of Line Style related Animation data"); RNA_def_property_ui_icon(prop, ICON_LINE_DATA, 0); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); - + prop = RNA_def_property(srna, "show_textures", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "filterflag", ADS_FILTER_NOTEX); RNA_def_property_ui_text(prop, "Display Texture", "Include visualization of texture related animation data"); RNA_def_property_ui_icon(prop, ICON_TEXTURE_DATA, 0); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); - + prop = RNA_def_property(srna, "show_curves", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "filterflag", ADS_FILTER_NOCUR); RNA_def_property_ui_text(prop, "Display Curve", "Include visualization of curve related animation data"); RNA_def_property_ui_icon(prop, ICON_CURVE_DATA, 0); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); - + prop = RNA_def_property(srna, "show_worlds", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "filterflag", ADS_FILTER_NOWOR); RNA_def_property_ui_text(prop, "Display World", "Include visualization of world related animation data"); RNA_def_property_ui_icon(prop, ICON_WORLD_DATA, 0); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); - + prop = RNA_def_property(srna, "show_scenes", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "filterflag", ADS_FILTER_NOSCE); RNA_def_property_ui_text(prop, "Display Scene", "Include visualization of scene related animation data"); RNA_def_property_ui_icon(prop, ICON_SCENE_DATA, 0); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); - + prop = RNA_def_property(srna, "show_particles", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "filterflag", ADS_FILTER_NOPART); RNA_def_property_ui_text(prop, "Display Particle", "Include visualization of particle related animation data"); RNA_def_property_ui_icon(prop, ICON_PARTICLE_DATA, 0); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); - + prop = RNA_def_property(srna, "show_metaballs", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "filterflag", ADS_FILTER_NOMBA); RNA_def_property_ui_text(prop, "Display Metaball", "Include visualization of metaball related animation data"); RNA_def_property_ui_icon(prop, ICON_META_DATA, 0); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); - + prop = RNA_def_property(srna, "show_armatures", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "filterflag", ADS_FILTER_NOARM); RNA_def_property_ui_text(prop, "Display Armature", "Include visualization of armature related animation data"); RNA_def_property_ui_icon(prop, ICON_ARMATURE_DATA, 0); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); - + prop = RNA_def_property(srna, "show_nodes", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "filterflag", ADS_FILTER_NONTREE); RNA_def_property_ui_text(prop, "Display Node", "Include visualization of node related animation data"); @@ -507,17 +507,17 @@ static void rna_def_dopesheet(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Display Speaker", "Include visualization of speaker related animation data"); RNA_def_property_ui_icon(prop, ICON_SPEAKER, 0); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); - + prop = RNA_def_property(srna, "show_gpencil", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "filterflag", ADS_FILTER_NOGPENCIL); RNA_def_property_ui_text(prop, "Display Grease Pencil", "Include visualization of Grease Pencil related animation data and frames"); RNA_def_property_ui_icon(prop, ICON_GREASEPENCIL, 0); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); - + /* GPencil Mode Settings */ prop = RNA_def_property(srna, "show_gpencil_3d_only", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "filterflag", ADS_FILTER_GP_3DONLY); - RNA_def_property_ui_text(prop, "Active Scene Only", + RNA_def_property_ui_text(prop, "Active Scene Only", "Only show Grease Pencil data-blocks used as part of the active scene"); RNA_def_property_ui_icon(prop, ICON_SCENE_DATA, 0); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); @@ -527,16 +527,16 @@ static void rna_def_action_group(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + srna = RNA_def_struct(brna, "ActionGroup", NULL); RNA_def_struct_sdna(srna, "bActionGroup"); RNA_def_struct_ui_text(srna, "Action Group", "Groups of F-Curves"); - + prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); RNA_def_property_ui_text(prop, "Name", ""); RNA_def_struct_name_property(srna, prop); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); - + /* WARNING: be very careful when working with this list, since the endpoint is not * defined like a standard ListBase. Adding/removing channels from this list needs * extreme care, otherwise the F-Curve list running through adjacent groups does @@ -552,22 +552,22 @@ static void rna_def_action_group(BlenderRNA *brna) RNA_def_property_struct_type(prop, "FCurve"); RNA_def_property_collection_funcs(prop, NULL, "rna_ActionGroup_channels_next", NULL, NULL, NULL, NULL, NULL, NULL); RNA_def_property_ui_text(prop, "Channels", "F-Curves in this group"); - + prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", AGRP_SELECTED); RNA_def_property_ui_text(prop, "Select", "Action group is selected"); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_SELECTED, NULL); - + prop = RNA_def_property(srna, "lock", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", AGRP_PROTECTED); RNA_def_property_ui_text(prop, "Lock", "Action group is locked"); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); - + prop = RNA_def_property(srna, "show_expanded", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", AGRP_EXPANDED); RNA_def_property_ui_text(prop, "Expanded", "Action group is expanded"); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); - + /* color set */ rna_def_actionbone_group_common(srna, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); } @@ -672,14 +672,14 @@ static void rna_def_action_pose_markers(BlenderRNA *brna, PropertyRNA *cprop) parm = RNA_def_pointer(func, "marker", "TimelineMarker", "", "Timeline marker to remove"); RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR); RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0); - + prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "TimelineMarker"); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_LIB_EXCEPTION); RNA_def_property_pointer_funcs(prop, "rna_Action_active_pose_marker_get", "rna_Action_active_pose_marker_set", NULL, NULL); RNA_def_property_ui_text(prop, "Active Pose Marker", "Active pose marker for this action"); - + prop = RNA_def_property(srna, "active_index", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "active_marker"); RNA_def_property_flag(prop, PROP_LIB_EXCEPTION); @@ -692,25 +692,25 @@ static void rna_def_action(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + srna = RNA_def_struct(brna, "Action", "ID"); RNA_def_struct_sdna(srna, "bAction"); RNA_def_struct_ui_text(srna, "Action", "A collection of F-Curves for animation"); RNA_def_struct_ui_icon(srna, ICON_ACTION); - + /* collections */ prop = RNA_def_property(srna, "fcurves", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "curves", NULL); RNA_def_property_struct_type(prop, "FCurve"); RNA_def_property_ui_text(prop, "F-Curves", "The individual F-Curves that make up the action"); rna_def_action_fcurves(brna, prop); - + prop = RNA_def_property(srna, "groups", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "groups", NULL); RNA_def_property_struct_type(prop, "ActionGroup"); RNA_def_property_ui_text(prop, "Groups", "Convenient groupings of F-Curves"); rna_def_action_groups(brna, prop); - + prop = RNA_def_property(srna, "pose_markers", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "markers", NULL); RNA_def_property_struct_type(prop, "TimelineMarker"); @@ -718,13 +718,13 @@ static void rna_def_action(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_LIB_EXCEPTION); RNA_def_property_ui_text(prop, "Pose Markers", "Markers specific to this action, for labeling poses"); rna_def_action_pose_markers(brna, prop); - + /* properties */ prop = RNA_def_float_vector(srna, "frame_range", 2, NULL, 0, 0, "Frame Range", "The final frame range of all F-Curves within this action", 0, 0); RNA_def_property_float_funcs(prop, "rna_Action_frame_range_get", NULL, NULL); RNA_def_property_clear_flag(prop, PROP_EDITABLE); - + /* special "type" limiter - should not really be edited in general, * but is still available/editable in 'emergencies' */ prop = RNA_def_property(srna, "id_root", PROP_ENUM, PROP_NONE); @@ -734,7 +734,7 @@ static void rna_def_action(BlenderRNA *brna) "Type of ID block that action can be used on - " "DO NOT CHANGE UNLESS YOU KNOW WHAT YOU ARE DOING"); RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_ID); - + /* API calls */ RNA_api_action(srna); } diff --git a/source/blender/makesrna/intern/rna_action_api.c b/source/blender/makesrna/intern/rna_action_api.c index fe429d8698b..3d5252b8cdc 100644 --- a/source/blender/makesrna/intern/rna_action_api.c +++ b/source/blender/makesrna/intern/rna_action_api.c @@ -53,7 +53,7 @@ void RNA_api_action(StructRNA *UNUSED(srna)) { - + } #endif diff --git a/source/blender/makesrna/intern/rna_animation.c b/source/blender/makesrna/intern/rna_animation.c index d2c719ac5d1..d89e3e68492 100644 --- a/source/blender/makesrna/intern/rna_animation.c +++ b/source/blender/makesrna/intern/rna_animation.c @@ -85,9 +85,9 @@ const EnumPropertyItem rna_enum_keying_flag_items[] = { static void rna_AnimData_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { ID *id = ptr->id.data; - - /* tag for refresh so that scheduled updates (e.g. action changed) will - * get computed and reflected in the scene [#34869] + + /* tag for refresh so that scheduled updates (e.g. action changed) will + * get computed and reflected in the scene [#34869] */ DEG_id_tag_update(id, OB_RECALC_OB | OB_RECALC_DATA); } @@ -95,7 +95,7 @@ static void rna_AnimData_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Point static int rna_AnimData_action_editable(PointerRNA *ptr, const char **UNUSED(r_info)) { AnimData *adt = (AnimData *)ptr->data; - + /* active action is only editable when it is not a tweaking strip */ if ((adt->flag & ADT_NLA_EDIT_ON) || (adt->actstrip) || (adt->tmpact)) return 0; @@ -107,10 +107,10 @@ static void rna_AnimData_action_set(PointerRNA *ptr, PointerRNA value) { ID *ownerId = (ID *)ptr->id.data; AnimData *adt; - + /* set action */ BKE_animdata_set_action(NULL, ownerId, value.data); - + /* force action to get evaluated [#34869] */ adt = BKE_animdata_from_id(ownerId); if (adt) { @@ -157,16 +157,16 @@ static int RKS_POLL_rna_internal(KeyingSetInfo *ksi, bContext *C) /* hook up arguments */ RNA_parameter_set_lookup(&list, "ksi", &ksi); RNA_parameter_set_lookup(&list, "context", &C); - + /* execute the function */ ksi->ext.call(C, &ptr, func, &list); - + /* read the result */ RNA_parameter_get_lookup(&list, "ok", &ret); ok = *(int *)ret; } RNA_parameter_list_free(&list); - + return ok; } @@ -188,7 +188,7 @@ static void RKS_ITER_rna_internal(KeyingSetInfo *ksi, bContext *C, KeyingSet *ks RNA_parameter_set_lookup(&list, "ksi", &ksi); RNA_parameter_set_lookup(&list, "context", &C); RNA_parameter_set_lookup(&list, "ks", &ks); - + /* execute the function */ ksi->ext.call(C, &ptr, func, &list); } @@ -214,7 +214,7 @@ static void RKS_GEN_rna_internal(KeyingSetInfo *ksi, bContext *C, KeyingSet *ks, RNA_parameter_set_lookup(&list, "context", &C); RNA_parameter_set_lookup(&list, "ks", &ks); RNA_parameter_set_lookup(&list, "data", data); - + /* execute the function */ ksi->ext.call(C, &ptr, func, &list); } @@ -236,11 +236,11 @@ static void rna_KeyingSetInfo_unregister(Main *bmain, StructRNA *type) if (ksi == NULL) return; - + /* free RNA data referencing this */ RNA_struct_free_extension(type, &ksi->ext); RNA_struct_free(&BLENDER_RNA, type); - + WM_main_add_notifier(NC_WINDOW, NULL); /* unlink Blender-side data */ @@ -259,17 +259,17 @@ static StructRNA *rna_KeyingSetInfo_register( /* setup dummy type info to store static properties in */ /* TODO: perhaps we want to get users to register as if they're using 'KeyingSet' directly instead? */ RNA_pointer_create(NULL, &RNA_KeyingSetInfo, &dummyksi, &dummyptr); - + /* validate the python class */ if (validate(&dummyptr, data, have_function) != 0) return NULL; - + if (strlen(identifier) >= sizeof(dummyksi.idname)) { BKE_reportf(reports, RPT_ERROR, "Registering keying set info class: '%s' is too long, maximum length is %d", identifier, (int)sizeof(dummyksi.idname)); return NULL; } - + /* check if we have registered this info before, and remove it */ ksi = ANIM_keyingset_info_find_name(dummyksi.idname); if (ksi && ksi->ext.srna) { @@ -279,23 +279,23 @@ static StructRNA *rna_KeyingSetInfo_register( /* create a new KeyingSetInfo type */ ksi = MEM_callocN(sizeof(KeyingSetInfo), "python keying set info"); memcpy(ksi, &dummyksi, sizeof(KeyingSetInfo)); - + /* set RNA-extensions info */ ksi->ext.srna = RNA_def_struct_ptr(&BLENDER_RNA, ksi->idname, &RNA_KeyingSetInfo); ksi->ext.data = data; ksi->ext.call = call; ksi->ext.free = free; RNA_struct_blender_type_set(ksi->ext.srna, ksi); - + /* set callbacks */ /* NOTE: we really should have all of these... */ ksi->poll = (have_function[0]) ? RKS_POLL_rna_internal : NULL; ksi->iter = (have_function[1]) ? RKS_ITER_rna_internal : NULL; ksi->generate = (have_function[2]) ? RKS_GEN_rna_internal : NULL; - + /* add and register with other info as needed */ ANIM_keyingset_info_register(ksi); - + WM_main_add_notifier(NC_WINDOW, NULL); /* return the struct-rna added */ @@ -319,7 +319,7 @@ static int rna_ksPath_id_editable(PointerRNA *ptr, const char **UNUSED(r_info)) static void rna_ksPath_id_type_set(PointerRNA *ptr, int value) { KS_Path *data = (KS_Path *)(ptr->data); - + /* set the driver type, then clear the id-block if the type is invalid */ data->idtype = value; if ((data->id) && (GS(data->id->name) != data->idtype)) @@ -339,7 +339,7 @@ static void rna_ksPath_RnaPath_get(PointerRNA *ptr, char *value) static int rna_ksPath_RnaPath_length(PointerRNA *ptr) { KS_Path *ksp = (KS_Path *)ptr->data; - + if (ksp->rna_path) return strlen(ksp->rna_path); else @@ -352,7 +352,7 @@ static void rna_ksPath_RnaPath_set(PointerRNA *ptr, const char *value) if (ksp->rna_path) MEM_freeN(ksp->rna_path); - + if (value[0]) ksp->rna_path = BLI_strdup(value); else @@ -364,20 +364,20 @@ static void rna_ksPath_RnaPath_set(PointerRNA *ptr, const char *value) static void rna_KeyingSet_name_set(PointerRNA *ptr, const char *value) { KeyingSet *ks = (KeyingSet *)ptr->data; - + /* update names of corresponding groups if name changes */ if (!STREQ(ks->name, value)) { KS_Path *ksp; - + for (ksp = ks->paths.first; ksp; ksp = ksp->next) { if ((ksp->groupmode == KSP_GROUP_KSNAME) && (ksp->id)) { AnimData *adt = BKE_animdata_from_id(ksp->id); - + /* TODO: NLA strips? */ if (adt && adt->action) { bActionGroup *agrp; - - /* lazy check - should really find the F-Curve for the affected path and check its group + + /* lazy check - should really find the F-Curve for the affected path and check its group * but this way should be faster and work well for most cases, as long as there are no * conflicts */ @@ -392,7 +392,7 @@ static void rna_KeyingSet_name_set(PointerRNA *ptr, const char *value) } } } - + /* finally, update name to new value */ BLI_strncpy(ks->name, value, sizeof(ks->name)); } @@ -401,7 +401,7 @@ static void rna_KeyingSet_name_set(PointerRNA *ptr, const char *value) static int rna_KeyingSet_active_ksPath_editable(PointerRNA *ptr, const char **UNUSED(r_info)) { KeyingSet *ks = (KeyingSet *)ptr->data; - + /* only editable if there are some paths to change to */ return (BLI_listbase_is_empty(&ks->paths) == false) ? PROP_EDITABLE : 0; } @@ -444,7 +444,7 @@ static PointerRNA rna_KeyingSet_typeinfo_get(PointerRNA *ptr) { KeyingSet *ks = (KeyingSet *)ptr->data; KeyingSetInfo *ksi = NULL; - + /* keying set info is only for builtin Keying Sets */ if ((ks->flag & KEYINGSET_ABSOLUTE) == 0) ksi = ANIM_keyingset_info_find_name(ks->typeinfo); @@ -458,13 +458,13 @@ static KS_Path *rna_KeyingSet_paths_add(KeyingSet *keyingset, ReportList *report { KS_Path *ksp = NULL; short flag = 0; - + /* special case when index = -1, we key the whole array (as with other places where index is used) */ if (index == -1) { flag |= KSP_FLAG_WHOLE_ARRAY; index = 0; } - + /* if data is valid, call the API function for this */ if (keyingset) { ksp = BKE_keyingset_add_path(keyingset, id, group_name, rna_path, index, flag, group_method); @@ -473,7 +473,7 @@ static KS_Path *rna_KeyingSet_paths_add(KeyingSet *keyingset, ReportList *report else { BKE_report(reports, RPT_ERROR, "Keying set path could not be added"); } - + /* return added path */ return ksp; } @@ -502,13 +502,13 @@ static void rna_KeyingSet_paths_clear(KeyingSet *keyingset, ReportList *reports) /* if data is valid, call the API function for this */ if (keyingset) { KS_Path *ksp, *kspn; - + /* free each path as we go to avoid looping twice */ for (ksp = keyingset->paths.first; ksp; ksp = kspn) { kspn = ksp->next; BKE_keyingset_free_path(keyingset, ksp); } - + /* reset the active path, since there aren't any left */ keyingset->active_path = 0; } @@ -567,7 +567,7 @@ static FCurve *rna_Driver_from_existing(AnimData *adt, bContext *C, FCurve *src_ else { /* just make a copy of the existing one and add to self */ FCurve *new_fcu = copy_fcurve(src_driver); - + /* XXX: if we impose any ordering on these someday, this will be problematic */ BLI_addtail(&adt->drivers, new_fcu); return new_fcu; @@ -619,39 +619,39 @@ bool rna_AnimaData_override_apply( static void rna_def_common_keying_flags(StructRNA *srna, short reg) { PropertyRNA *prop; - + /* override scene/userpref defaults? */ prop = RNA_def_property(srna, "use_insertkey_override_needed", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "keyingoverride", INSERTKEY_NEEDED); - RNA_def_property_ui_text(prop, "Override Insert Keyframes Default- Only Needed", + RNA_def_property_ui_text(prop, "Override Insert Keyframes Default- Only Needed", "Override default setting to only insert keyframes where they're needed in the relevant F-Curves"); if (reg) RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL); - + prop = RNA_def_property(srna, "use_insertkey_override_visual", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "keyingoverride", INSERTKEY_MATRIX); - RNA_def_property_ui_text(prop, "Override Insert Keyframes Default - Visual", + RNA_def_property_ui_text(prop, "Override Insert Keyframes Default - Visual", "Override default setting to insert keyframes based on 'visual transforms'"); if (reg) RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL); - + prop = RNA_def_property(srna, "use_insertkey_override_xyz_to_rgb", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "keyingoverride", INSERTKEY_XYZ2RGB); RNA_def_property_ui_text(prop, "Override F-Curve Colors - XYZ to RGB", "Override default setting to set color for newly added transformation F-Curves " "(Location, Rotation, Scale) to be based on the transform axis"); if (reg) RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL); - - + + /* value to override defaults with */ prop = RNA_def_property(srna, "use_insertkey_needed", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "keyingflag", INSERTKEY_NEEDED); RNA_def_property_ui_text(prop, "Insert Keyframes - Only Needed", "Only insert keyframes where they're needed in the relevant F-Curves"); if (reg) RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL); - + prop = RNA_def_property(srna, "use_insertkey_visual", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "keyingflag", INSERTKEY_MATRIX); RNA_def_property_ui_text(prop, "Insert Keyframes - Visual", "Insert keyframes based on 'visual transforms'"); if (reg) RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL); - + prop = RNA_def_property(srna, "use_insertkey_xyz_to_rgb", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "keyingflag", INSERTKEY_XYZ2RGB); RNA_def_property_ui_text(prop, "F-Curve Colors - XYZ to RGB", "Color for newly added transformation F-Curves (Location, Rotation, Scale) is based on the transform axis"); @@ -674,36 +674,36 @@ static void rna_def_keyingset_info(BlenderRNA *brna) PropertyRNA *prop; FunctionRNA *func; PropertyRNA *parm; - + srna = RNA_def_struct(brna, "KeyingSetInfo", NULL); RNA_def_struct_sdna(srna, "KeyingSetInfo"); RNA_def_struct_ui_text(srna, "Keying Set Info", "Callback function defines for builtin Keying Sets"); RNA_def_struct_refine_func(srna, "rna_KeyingSetInfo_refine"); RNA_def_struct_register_funcs(srna, "rna_KeyingSetInfo_register", "rna_KeyingSetInfo_unregister", NULL); - + /* Properties --------------------- */ - + RNA_define_verify_sdna(0); /* not in sdna */ - + prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "idname"); RNA_def_property_flag(prop, PROP_REGISTER); RNA_def_property_ui_text(prop, "ID Name", KEYINGSET_IDNAME_DOC); - + prop = RNA_def_property(srna, "bl_label", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "name"); RNA_def_property_ui_text(prop, "UI Name", ""); RNA_def_struct_name_property(srna, prop); RNA_def_property_flag(prop, PROP_REGISTER); - + prop = RNA_def_property(srna, "bl_description", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "description"); RNA_def_property_string_maxlength(prop, RNA_DYN_DESCR_MAX); /* else it uses the pointer size! */ RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL); RNA_def_property_ui_text(prop, "Description", "A short description of the keying set"); - + /* Regarding why we don't use rna_def_common_keying_flags() here: - * - Using it would keep this case in sync with the other places + * - Using it would keep this case in sync with the other places * where these options are exposed (which are optimized for being * used in the UI). * - Unlike all the other places, this case is used for defining @@ -716,9 +716,9 @@ static void rna_def_keyingset_info(BlenderRNA *brna) RNA_def_property_enum_items(prop, rna_enum_keying_flag_items); RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL | PROP_ENUM_FLAG); RNA_def_property_ui_text(prop, "Options", "Keying Set options to use when inserting keyframes"); - + RNA_define_verify_sdna(1); - + /* Function Callbacks ------------- */ /* poll */ func = RNA_def_function(srna, "poll", NULL); @@ -727,7 +727,7 @@ static void rna_def_keyingset_info(BlenderRNA *brna) RNA_def_function_return(func, RNA_def_boolean(func, "ok", 1, "", "")); parm = RNA_def_pointer(func, "context", "Context", "", ""); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); - + /* iterator */ func = RNA_def_function(srna, "iterator", NULL); RNA_def_function_ui_description(func, "Call generate() on the structs which have properties to be keyframed"); @@ -736,7 +736,7 @@ static void rna_def_keyingset_info(BlenderRNA *brna) RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); parm = RNA_def_pointer(func, "ks", "KeyingSet", "", ""); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); - + /* generate */ func = RNA_def_function(srna, "generate", NULL); RNA_def_function_ui_description(func, "Add Paths to the Keying Set to keyframe the properties of the given data"); @@ -753,11 +753,11 @@ static void rna_def_keyingset_path(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + srna = RNA_def_struct(brna, "KeyingSetPath", NULL); RNA_def_struct_sdna(srna, "KS_Path"); RNA_def_struct_ui_text(srna, "Keying Set Path", "Path to a setting for use in a Keying Set"); - + /* ID */ prop = RNA_def_property(srna, "id", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "ID"); @@ -768,7 +768,7 @@ static void rna_def_keyingset_path(BlenderRNA *brna) "ID-Block that keyframes for Keying Set should be added to " "(for Absolute Keying Sets only)"); RNA_def_property_update(prop, NC_SCENE | ND_KEYINGSET | NA_EDITED, NULL); /* XXX: maybe a bit too noisy */ - + prop = RNA_def_property(srna, "id_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "idtype"); RNA_def_property_enum_items(prop, rna_enum_id_type_items); @@ -777,19 +777,19 @@ static void rna_def_keyingset_path(BlenderRNA *brna) RNA_def_property_ui_text(prop, "ID Type", "Type of ID-block that can be used"); RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_ID); RNA_def_property_update(prop, NC_SCENE | ND_KEYINGSET | NA_EDITED, NULL); /* XXX: maybe a bit too noisy */ - + /* Group */ prop = RNA_def_property(srna, "group", PROP_STRING, PROP_NONE); RNA_def_property_ui_text(prop, "Group Name", "Name of Action Group to assign setting(s) for this path to"); RNA_def_property_update(prop, NC_SCENE | ND_KEYINGSET | NA_EDITED, NULL); /* XXX: maybe a bit too noisy */ - + /* Grouping */ prop = RNA_def_property(srna, "group_method", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "groupmode"); RNA_def_property_enum_items(prop, rna_enum_keyingset_path_grouping_items); RNA_def_property_ui_text(prop, "Grouping Method", "Method used to define which Group-name to use"); RNA_def_property_update(prop, NC_SCENE | ND_KEYINGSET | NA_EDITED, NULL); /* XXX: maybe a bit too noisy */ - + /* Path + Array Index */ prop = RNA_def_property(srna, "data_path", PROP_STRING, PROP_NONE); RNA_def_property_string_funcs(prop, "rna_ksPath_RnaPath_get", "rna_ksPath_RnaPath_length", @@ -802,7 +802,7 @@ static void rna_def_keyingset_path(BlenderRNA *brna) prop = RNA_def_property(srna, "array_index", PROP_INT, PROP_NONE); RNA_def_property_ui_text(prop, "RNA Array Index", "Index to the specific setting if applicable"); RNA_def_property_update(prop, NC_SCENE | ND_KEYINGSET | NA_EDITED, NULL); /* XXX: maybe a bit too noisy */ - + /* Flags */ prop = RNA_def_property(srna, "use_entire_array", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", KSP_FLAG_WHOLE_ARRAY); @@ -810,7 +810,7 @@ static void rna_def_keyingset_path(BlenderRNA *brna) "When an 'array/vector' type is chosen (Location, Rotation, Color, etc.), " "entire array is to be used"); RNA_def_property_update(prop, NC_SCENE | ND_KEYINGSET | NA_EDITED, NULL); /* XXX: maybe a bit too noisy */ - + /* Keyframing Settings */ rna_def_common_keying_flags(srna, 0); } @@ -823,7 +823,7 @@ static void rna_def_keyingset_paths(BlenderRNA *brna, PropertyRNA *cprop) FunctionRNA *func; PropertyRNA *parm; - + PropertyRNA *prop; RNA_def_property_srna(cprop, "KeyingSetPaths"); @@ -831,7 +831,7 @@ static void rna_def_keyingset_paths(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_struct_sdna(srna, "KeyingSet"); RNA_def_struct_ui_text(srna, "Keying set paths", "Collection of keying set paths"); - + /* Add Path */ func = RNA_def_function(srna, "add", "rna_KeyingSet_paths_add"); RNA_def_function_ui_description(func, "Add a new path for the Keying Set"); @@ -871,7 +871,7 @@ static void rna_def_keyingset_paths(BlenderRNA *brna, PropertyRNA *cprop) func = RNA_def_function(srna, "clear", "rna_KeyingSet_paths_clear"); RNA_def_function_ui_description(func, "Remove all the paths from the Keying Set"); RNA_def_function_flag(func, FUNC_USE_REPORTS); - + prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "KeyingSetPath"); RNA_def_property_flag(prop, PROP_EDITABLE); @@ -891,17 +891,17 @@ static void rna_def_keyingset(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + srna = RNA_def_struct(brna, "KeyingSet", NULL); RNA_def_struct_ui_text(srna, "Keying Set", "Settings that should be keyframed together"); - + /* Id/Label */ prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "idname"); RNA_def_property_flag(prop, PROP_REGISTER); RNA_def_property_ui_text(prop, "ID Name", KEYINGSET_IDNAME_DOC); /* RNA_def_property_update(prop, NC_SCENE | ND_KEYINGSET | NA_RENAME, NULL); */ /* NOTE: disabled, as ID name shouldn't be editable */ - + prop = RNA_def_property(srna, "bl_label", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "name"); RNA_def_property_string_funcs(prop, NULL, NULL, "rna_KeyingSet_name_set"); @@ -909,19 +909,19 @@ static void rna_def_keyingset(BlenderRNA *brna) RNA_def_struct_ui_icon(srna, ICON_KEYINGSET); RNA_def_struct_name_property(srna, prop); RNA_def_property_update(prop, NC_SCENE | ND_KEYINGSET | NA_RENAME, NULL); - + prop = RNA_def_property(srna, "bl_description", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "description"); RNA_def_property_string_maxlength(prop, RNA_DYN_DESCR_MAX); /* else it uses the pointer size! */ RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL); RNA_def_property_ui_text(prop, "Description", "A short description of the keying set"); - + /* KeyingSetInfo (Type Info) for Builtin Sets only */ prop = RNA_def_property(srna, "type_info", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "KeyingSetInfo"); RNA_def_property_pointer_funcs(prop, "rna_KeyingSet_typeinfo_get", NULL, NULL, NULL); RNA_def_property_ui_text(prop, "Type Info", "Callback function defines for built-in Keying Sets"); - + /* Paths */ prop = RNA_def_property(srna, "paths", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "paths", NULL); @@ -936,11 +936,11 @@ static void rna_def_keyingset(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Absolute", "Keying Set defines specific paths/settings to be keyframed " "(i.e. is not reliant on context info)"); - + /* Keyframing Flags */ rna_def_common_keying_flags(srna, 0); - - + + /* Keying Set API */ RNA_api_keyingset(srna); } @@ -955,12 +955,12 @@ static void rna_api_animdata_nla_tracks(BlenderRNA *brna, PropertyRNA *cprop) FunctionRNA *func; PropertyRNA *prop; - + RNA_def_property_srna(cprop, "NlaTracks"); srna = RNA_def_struct(brna, "NlaTracks", NULL); RNA_def_struct_sdna(srna, "AnimData"); RNA_def_struct_ui_text(srna, "NLA Tracks", "Collection of NLA Tracks"); - + func = RNA_def_function(srna, "new", "rna_NlaTrack_new"); RNA_def_function_flag(func, FUNC_USE_CONTEXT); RNA_def_function_ui_description(func, "Add a new NLA Track"); @@ -968,7 +968,7 @@ static void rna_api_animdata_nla_tracks(BlenderRNA *brna, PropertyRNA *cprop) /* return type */ parm = RNA_def_pointer(func, "track", "NlaTrack", "", "New NLA Track"); RNA_def_function_return(func, parm); - + func = RNA_def_function(srna, "remove", "rna_NlaTrack_remove"); RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_CONTEXT); RNA_def_function_ui_description(func, "Remove a NLA Track"); @@ -992,12 +992,12 @@ static void rna_api_animdata_drivers(BlenderRNA *brna, PropertyRNA *cprop) FunctionRNA *func; /* PropertyRNA *prop; */ - + RNA_def_property_srna(cprop, "AnimDataDrivers"); srna = RNA_def_struct(brna, "AnimDataDrivers", NULL); RNA_def_struct_sdna(srna, "AnimData"); RNA_def_struct_ui_text(srna, "Drivers", "Collection of Driver F-Curves"); - + /* AnimData.drivers.from_existing(...) */ func = RNA_def_function(srna, "from_existing", "rna_Driver_from_existing"); RNA_def_function_flag(func, FUNC_USE_CONTEXT); @@ -1006,7 +1006,7 @@ static void rna_api_animdata_drivers(BlenderRNA *brna, PropertyRNA *cprop) /* return type */ parm = RNA_def_pointer(func, "driver", "FCurve", "", "New Driver F-Curve"); RNA_def_function_return(func, parm); - + /* AnimData.drivers.find(...) */ func = RNA_def_function(srna, "find", "rna_Driver_find"); RNA_def_function_ui_description(func, "Find a driver F-Curve. Note that this function performs a linear scan " @@ -1023,7 +1023,7 @@ static void rna_api_animdata_drivers(BlenderRNA *brna, PropertyRNA *cprop) void rna_def_animdata_common(StructRNA *srna) { PropertyRNA *prop; - + prop = RNA_def_property(srna, "animation_data", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "adt"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); @@ -1036,11 +1036,11 @@ static void rna_def_animdata(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + srna = RNA_def_struct(brna, "AnimData", NULL); RNA_def_struct_ui_text(srna, "Animation Data", "Animation data for data-block"); RNA_def_struct_ui_icon(srna, ICON_ANIM_DATA); - + /* NLA */ prop = RNA_def_property(srna, "nla_tracks", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "nla_tracks", NULL); @@ -1048,7 +1048,7 @@ static void rna_def_animdata(BlenderRNA *brna) RNA_def_property_ui_text(prop, "NLA Tracks", "NLA Tracks (i.e. Animation Layers)"); rna_api_animdata_nla_tracks(brna, prop); - + /* Active Action */ prop = RNA_def_property(srna, "action", PROP_POINTER, PROP_NONE); /* this flag as well as the dynamic test must be defined for this to be editable... */ @@ -1066,31 +1066,31 @@ static void rna_def_animdata(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Action Extrapolation", "Action to take for gaps past the Active Action's range (when evaluating with NLA)"); RNA_def_property_update(prop, NC_ANIMATION | ND_NLA, NULL); - + prop = RNA_def_property(srna, "action_blend_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "act_blendmode"); RNA_def_property_enum_items(prop, rna_enum_nla_mode_blend_items); RNA_def_property_ui_text(prop, "Action Blending", "Method used for combining Active Action's result with result of NLA stack"); RNA_def_property_update(prop, NC_ANIMATION | ND_NLA, NULL); /* this will do? */ - - prop = RNA_def_property(srna, "action_influence", PROP_FLOAT, PROP_FACTOR); + + prop = RNA_def_property(srna, "action_influence", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "act_influence"); RNA_def_property_float_default(prop, 1.0f); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Action Influence", "Amount the Active Action contributes to the result of the NLA stack"); RNA_def_property_update(prop, NC_ANIMATION | ND_NLA, NULL); /* this will do? */ - + /* Drivers */ prop = RNA_def_property(srna, "drivers", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "drivers", NULL); RNA_def_property_struct_type(prop, "FCurve"); RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC); RNA_def_property_ui_text(prop, "Drivers", "The Drivers/Expressions for this data-block"); - + rna_api_animdata_drivers(brna, prop); - + /* General Settings */ prop = RNA_def_property(srna, "use_nla", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", ADT_NLA_EVAL_OFF); @@ -1109,7 +1109,7 @@ static void rna_def_animdata(BlenderRNA *brna) void RNA_def_animation(BlenderRNA *brna) { rna_def_animdata(brna); - + rna_def_keyingset(brna); rna_def_keyingset_path(brna); rna_def_keyingset_info(brna); diff --git a/source/blender/makesrna/intern/rna_animation_api.c b/source/blender/makesrna/intern/rna_animation_api.c index 492659fdc2e..0b8f1acbd74 100644 --- a/source/blender/makesrna/intern/rna_animation_api.c +++ b/source/blender/makesrna/intern/rna_animation_api.c @@ -52,13 +52,13 @@ static void rna_KeyingSet_context_refresh(KeyingSet *ks, bContext *C, ReportList { /* TODO: enable access to providing a list of overrides (dsources)? */ int success = ANIM_validate_keyingset(C, NULL, ks); - + if (success != 0) { switch (success) { case MODIFYKEY_INVALID_CONTEXT: BKE_report(reports, RPT_ERROR, "Invalid context for keying set"); break; - + case MODIFYKEY_MISSING_TYPEINFO: BKE_report(reports, RPT_ERROR, "Incomplete built-in keying set, appears to be missing type info"); break; @@ -72,7 +72,7 @@ void RNA_api_keyingset(StructRNA *srna) { FunctionRNA *func; /*PropertyRNA *parm; */ - + /* validate relative Keying Set (used to ensure paths are ok for context) */ func = RNA_def_function(srna, "refresh", "rna_KeyingSet_context_refresh"); RNA_def_function_ui_description(func, diff --git a/source/blender/makesrna/intern/rna_animviz.c b/source/blender/makesrna/intern/rna_animviz.c index 2ba067629a9..94b4d60ca25 100644 --- a/source/blender/makesrna/intern/rna_animviz.c +++ b/source/blender/makesrna/intern/rna_animviz.c @@ -65,7 +65,7 @@ static PointerRNA rna_AnimViz_motion_paths_get(PointerRNA *ptr) static void rna_AnimViz_ghost_start_frame_set(PointerRNA *ptr, int value) { bAnimVizSettings *data = (bAnimVizSettings *)ptr->data; - + data->ghost_sf = value; CLAMP(data->ghost_ef, data->ghost_sf, MAXFRAME / 2); } @@ -73,7 +73,7 @@ static void rna_AnimViz_ghost_start_frame_set(PointerRNA *ptr, int value) static void rna_AnimViz_ghost_end_frame_set(PointerRNA *ptr, int value) { bAnimVizSettings *data = (bAnimVizSettings *)ptr->data; - + data->ghost_ef = value; CLAMP(data->ghost_sf, 1, data->ghost_ef); } @@ -81,7 +81,7 @@ static void rna_AnimViz_ghost_end_frame_set(PointerRNA *ptr, int value) static void rna_AnimViz_path_start_frame_set(PointerRNA *ptr, int value) { bAnimVizSettings *data = (bAnimVizSettings *)ptr->data; - + /* XXX: watchit! Path Start > MAXFRAME/2 could be a problem... */ data->path_sf = value; CLAMP(data->path_ef, data->path_sf + 1, MAXFRAME / 2); @@ -90,7 +90,7 @@ static void rna_AnimViz_path_start_frame_set(PointerRNA *ptr, int value) static void rna_AnimViz_path_end_frame_set(PointerRNA *ptr, int value) { bAnimVizSettings *data = (bAnimVizSettings *)ptr->data; - + data->path_ef = value; CLAMP(data->path_sf, 1, data->path_ef - 1); } @@ -100,7 +100,7 @@ static void rna_AnimViz_path_end_frame_set(PointerRNA *ptr, int value) void rna_def_motionpath_common(StructRNA *srna) { PropertyRNA *prop; - + prop = RNA_def_property(srna, "motion_path", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "mpath"); RNA_def_property_ui_text(prop, "Motion Path", "Motion Path for this element"); @@ -110,15 +110,15 @@ static void rna_def_animviz_motionpath_vert(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + srna = RNA_def_struct(brna, "MotionPathVert", NULL); RNA_def_struct_sdna(srna, "bMotionPathVert"); RNA_def_struct_ui_text(srna, "Motion Path Cache Point", "Cached location on path"); - + prop = RNA_def_property(srna, "co", PROP_FLOAT, PROP_XYZ); RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Coordinates", ""); - + prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", MOTIONPATH_VERT_SEL); RNA_def_property_ui_text(prop, "Select", "Path point is selected for editing"); @@ -128,28 +128,28 @@ static void rna_def_animviz_motion_path(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + srna = RNA_def_struct(brna, "MotionPath", NULL); RNA_def_struct_sdna(srna, "bMotionPath"); RNA_def_struct_ui_text(srna, "Motion Path", "Cache of the worldspace positions of an element over a frame range"); - + /* Collections */ prop = RNA_def_property(srna, "points", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "points", "length"); RNA_def_property_struct_type(prop, "MotionPathVert"); RNA_def_property_ui_text(prop, "Motion Path Points", "Cached positions per frame"); - + /* Playback Ranges */ prop = RNA_def_property(srna, "frame_start", PROP_INT, PROP_TIME); RNA_def_property_int_sdna(prop, NULL, "start_frame"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Start Frame", "Starting frame of the stored range"); - + prop = RNA_def_property(srna, "frame_end", PROP_INT, PROP_TIME); RNA_def_property_int_sdna(prop, NULL, "end_frame"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "End Frame", "End frame of the stored range"); - + prop = RNA_def_property(srna, "length", PROP_INT, PROP_TIME); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Length", "Number of frames cached"); @@ -173,7 +173,7 @@ static void rna_def_animviz_motion_path(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* xxx */ RNA_def_property_ui_text(prop, "Use Bone Heads", "For PoseBone paths, use the bone head location when calculating this path"); - + /* FIXME: Motion Paths are not currently editable... */ prop = RNA_def_property(srna, "is_modified", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", MOTIONPATH_FLAG_EDIT); @@ -199,7 +199,7 @@ static void rna_def_animviz_ghosts(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + static const EnumPropertyItem prop_type_items[] = { {GHOST_TYPE_NONE, "NONE", 0, "No Ghosts", "Do not show any ghosts"}, {GHOST_TYPE_ACFRA, "CURRENT_FRAME", 0, "Around Current Frame", "Show ghosts from around the current frame"}, @@ -207,8 +207,8 @@ static void rna_def_animviz_ghosts(BlenderRNA *brna) {GHOST_TYPE_KEYS, "KEYS", 0, "On Keyframes", "Show ghosts on keyframes"}, {0, NULL, 0, NULL, NULL} }; - - + + srna = RNA_def_struct(brna, "AnimVizOnionSkinning", NULL); RNA_def_struct_sdna(srna, "bAnimVizSettings"); RNA_def_struct_nested(brna, srna, "AnimViz"); @@ -220,21 +220,21 @@ static void rna_def_animviz_ghosts(BlenderRNA *brna) RNA_def_property_enum_items(prop, prop_type_items); RNA_def_property_ui_text(prop, "Type", "Method used for determining what ghosts get drawn"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); /* XXX since this is only for 3d-view drawing */ - + /* Settings */ prop = RNA_def_property(srna, "show_only_selected", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "ghost_flag", GHOST_FLAG_ONLYSEL); RNA_def_property_ui_text(prop, "On Selected Bones Only", "For Pose-Mode drawing, only draw ghosts for selected bones"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); /* XXX since this is only for 3d-view drawing */ - + prop = RNA_def_property(srna, "frame_step", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "ghost_step"); RNA_def_property_range(prop, 1, 20); RNA_def_property_ui_text(prop, "Frame Step", "Number of frames between ghosts shown (not for 'On Keyframes' Onion-skinning method)"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); /* XXX since this is only for 3d-view drawing */ - + /* Playback Ranges */ prop = RNA_def_property(srna, "frame_start", PROP_INT, PROP_TIME); RNA_def_property_int_sdna(prop, NULL, "ghost_sf"); @@ -243,7 +243,7 @@ static void rna_def_animviz_ghosts(BlenderRNA *brna) "Starting frame of range of Ghosts to display " "(not for 'Around Current Frame' Onion-skinning method)"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); /* XXX since this is only for 3d-view drawing */ - + prop = RNA_def_property(srna, "frame_end", PROP_INT, PROP_TIME); RNA_def_property_int_sdna(prop, NULL, "ghost_ef"); RNA_def_property_int_funcs(prop, NULL, "rna_AnimViz_ghost_end_frame_set", NULL); @@ -251,7 +251,7 @@ static void rna_def_animviz_ghosts(BlenderRNA *brna) "End frame of range of Ghosts to display " "(not for 'Around Current Frame' Onion-skinning method)"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); /* XXX since this is only for 3d-view drawing */ - + /* Around Current Ranges */ prop = RNA_def_property(srna, "frame_before", PROP_INT, PROP_TIME); RNA_def_property_int_sdna(prop, NULL, "ghost_bc"); @@ -260,7 +260,7 @@ static void rna_def_animviz_ghosts(BlenderRNA *brna) "Number of frames to show before the current frame " "(only for 'Around Current Frame' Onion-skinning method)"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); /* XXX since this is only for 3d-view drawing */ - + prop = RNA_def_property(srna, "frame_after", PROP_INT, PROP_TIME); RNA_def_property_int_sdna(prop, NULL, "ghost_ac"); RNA_def_property_range(prop, 0, 30); @@ -274,63 +274,63 @@ static void rna_def_animviz_paths(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + static const EnumPropertyItem prop_type_items[] = { {MOTIONPATH_TYPE_ACFRA, "CURRENT_FRAME", 0, "Around Frame", "Display Paths of poses within a fixed number of frames around the current frame"}, {MOTIONPATH_TYPE_RANGE, "RANGE", 0, "In Range", "Display Paths of poses within specified range"}, {0, NULL, 0, NULL, NULL} }; - + srna = RNA_def_struct(brna, "AnimVizMotionPaths", NULL); RNA_def_struct_sdna(srna, "bAnimVizSettings"); RNA_def_struct_nested(brna, srna, "AnimViz"); RNA_def_struct_ui_text(srna, "Motion Path Settings", "Motion Path settings for animation visualization"); - + /* Enums */ prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "path_type"); RNA_def_property_enum_items(prop, prop_type_items); RNA_def_property_ui_text(prop, "Paths Type", "Type of range to show for Motion Paths"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); /* XXX since this is only for 3d-view drawing */ - + prop = RNA_def_property(srna, "bake_location", PROP_ENUM, PROP_NONE); RNA_def_property_enum_bitflag_sdna(prop, NULL, "path_bakeflag"); RNA_def_property_enum_items(prop, rna_enum_motionpath_bake_location_items); RNA_def_property_ui_text(prop, "Bake Location", "When calculating Bone Paths, use Head or Tips"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); /* XXX since this is only for 3d-view drawing */ - + /* Settings */ prop = RNA_def_property(srna, "show_frame_numbers", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "path_viewflag", MOTIONPATH_VIEW_FNUMS); RNA_def_property_ui_text(prop, "Show Frame Numbers", "Show frame numbers on Motion Paths"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); /* XXX since this is only for 3d-view drawing */ - + prop = RNA_def_property(srna, "show_keyframe_highlight", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "path_viewflag", MOTIONPATH_VIEW_KFRAS); RNA_def_property_ui_text(prop, "Highlight Keyframes", "Emphasize position of keyframes on Motion Paths"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); /* XXX since this is only for 3d-view drawing */ - + prop = RNA_def_property(srna, "show_keyframe_numbers", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "path_viewflag", MOTIONPATH_VIEW_KFNOS); RNA_def_property_ui_text(prop, "Show Keyframe Numbers", "Show frame numbers of Keyframes on Motion Paths"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); /* XXX since this is only for 3d-view drawing */ - + prop = RNA_def_property(srna, "show_keyframe_action_all", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "path_viewflag", MOTIONPATH_VIEW_KFACT); RNA_def_property_ui_text(prop, "All Action Keyframes", "For bone motion paths, search whole Action for keyframes instead of in group" " with matching name only (is slower)"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); /* XXX since this is only for 3d-view drawing */ - + prop = RNA_def_property(srna, "frame_step", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "path_step"); RNA_def_property_range(prop, 1, 100); RNA_def_property_ui_text(prop, "Frame Step", "Number of frames between paths shown (not for 'On Keyframes' Onion-skinning method)"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); /* XXX since this is only for 3d-view drawing */ - - + + /* Playback Ranges */ prop = RNA_def_property(srna, "frame_start", PROP_INT, PROP_TIME); RNA_def_property_int_sdna(prop, NULL, "path_sf"); @@ -339,7 +339,7 @@ static void rna_def_animviz_paths(BlenderRNA *brna) "Starting frame of range of paths to display/calculate " "(not for 'Around Current Frame' Onion-skinning method)"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); /* XXX since this is only for 3d-view drawing */ - + prop = RNA_def_property(srna, "frame_end", PROP_INT, PROP_TIME); RNA_def_property_int_sdna(prop, NULL, "path_ef"); RNA_def_property_int_funcs(prop, NULL, "rna_AnimViz_path_end_frame_set", NULL); @@ -347,7 +347,7 @@ static void rna_def_animviz_paths(BlenderRNA *brna) "End frame of range of paths to display/calculate " "(not for 'Around Current Frame' Onion-skinning method)"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); /* XXX since this is only for 3d-view drawing */ - + /* Around Current Ranges */ prop = RNA_def_property(srna, "frame_before", PROP_INT, PROP_TIME); RNA_def_property_int_sdna(prop, NULL, "path_bc"); @@ -356,7 +356,7 @@ static void rna_def_animviz_paths(BlenderRNA *brna) "Number of frames to show before the current frame " "(only for 'Around Current Frame' Onion-skinning method)"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); /* XXX since this is only for 3d-view drawing */ - + prop = RNA_def_property(srna, "frame_after", PROP_INT, PROP_TIME); RNA_def_property_int_sdna(prop, NULL, "path_ac"); RNA_def_property_range(prop, 1, MAXFRAMEF / 2); @@ -365,7 +365,7 @@ static void rna_def_animviz_paths(BlenderRNA *brna) "(only for 'Around Current Frame' Onion-skinning method)"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); /* XXX since this is only for 3d-view drawing */ - + /* Readonly Property - Do any motion paths exist/need updating? (Mainly for bone paths) */ prop = RNA_def_property(srna, "has_motion_paths", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "path_bakeflag", MOTIONPATH_BAKE_HAS_PATHS); @@ -378,7 +378,7 @@ static void rna_def_animviz_paths(BlenderRNA *brna) void rna_def_animviz_common(StructRNA *srna) { PropertyRNA *prop; - + prop = RNA_def_property(srna, "animation_visualization", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "avs"); @@ -389,18 +389,18 @@ static void rna_def_animviz(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + srna = RNA_def_struct(brna, "AnimViz", NULL); RNA_def_struct_sdna(srna, "bAnimVizSettings"); RNA_def_struct_ui_text(srna, "Animation Visualization", "Settings for the visualization of motion"); - + /* onion-skinning settings (nested struct) */ prop = RNA_def_property(srna, "onion_skin_frames", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_struct_type(prop, "AnimVizOnionSkinning"); RNA_def_property_pointer_funcs(prop, "rna_AnimViz_onion_skinning_get", NULL, NULL, NULL); RNA_def_property_ui_text(prop, "Onion Skinning", "Onion Skinning (ghosting) settings for visualization"); - + /* motion path settings (nested struct) */ prop = RNA_def_property(srna, "motion_path", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); @@ -416,7 +416,7 @@ void RNA_def_animviz(BlenderRNA *brna) rna_def_animviz(brna); rna_def_animviz_ghosts(brna); rna_def_animviz_paths(brna); - + rna_def_animviz_motion_path(brna); rna_def_animviz_motionpath_vert(brna); } diff --git a/source/blender/makesrna/intern/rna_armature.c b/source/blender/makesrna/intern/rna_armature.c index 69a5cc2d6b1..44a21e797f1 100644 --- a/source/blender/makesrna/intern/rna_armature.c +++ b/source/blender/makesrna/intern/rna_armature.c @@ -73,13 +73,13 @@ static void rna_Armature_act_bone_set(PointerRNA *ptr, PointerRNA value) else { if (value.id.data != arm) { Object *ob = (Object *)value.id.data; - + if (GS(ob->id.name) != ID_OB || (ob->data != arm)) { printf("ERROR: armature set active bone - new active doesn't come from this armature\n"); return; } } - + arm->act_bone = value.data; arm->act_bone->flag |= BONE_SELECTED; } @@ -148,7 +148,7 @@ static void rna_Armature_update_layers(Main *bmain, Scene *UNUSED(scene), Pointe static void rna_Armature_redraw_data(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { ID *id = ptr->id.data; - + DEG_id_tag_update(id, DEG_TAG_COPY_ON_WRITE); WM_main_add_notifier(NC_GEOM | ND_DATA, id); } @@ -157,10 +157,10 @@ static void rna_Armature_redraw_data(Main *UNUSED(bmain), Scene *UNUSED(scene), static void rna_Bone_update_renamed(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { ID *id = ptr->id.data; - + /* redraw view */ WM_main_add_notifier(NC_GEOM | ND_DATA, id); - + /* update animation channels */ WM_main_add_notifier(NC_ANIMATION | ND_ANIMCHAN, id); } @@ -168,7 +168,7 @@ static void rna_Bone_update_renamed(Main *UNUSED(bmain), Scene *UNUSED(scene), P static void rna_Bone_select_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { ID *id = ptr->id.data; - + /* 1) special updates for cases where rigs try to hook into armature drawing stuff * e.g. Mask Modifier - 'Armature' option * 2) tag armature for copy-on-write, so that selection status (set by addons) @@ -177,25 +177,25 @@ static void rna_Bone_select_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Po if (id) { if (GS(id->name) == ID_AR) { bArmature *arm = (bArmature *)id; - + if (arm->flag & ARM_HAS_VIZ_DEPS) { DEG_id_tag_update(id, OB_RECALC_DATA); } - + DEG_id_tag_update(id, DEG_TAG_COPY_ON_WRITE); } else if (GS(id->name) == ID_OB) { Object *ob = (Object *)id; bArmature *arm = (bArmature *)ob->data; - + if (arm->flag & ARM_HAS_VIZ_DEPS) { DEG_id_tag_update(id, OB_RECALC_DATA); } - + DEG_id_tag_update(&arm->id, DEG_TAG_COPY_ON_WRITE); } } - + WM_main_add_notifier(NC_GEOM | ND_DATA, id); /* spaces that show animation data of the selected bone need updating */ @@ -207,7 +207,7 @@ static char *rna_Bone_path(PointerRNA *ptr) ID *id = ptr->id.data; Bone *bone = (Bone *)ptr->data; char name_esc[sizeof(bone->name) * 2]; - + BLI_strescape(name_esc, bone->name, sizeof(name_esc)); /* special exception for trying to get the path where ID-block is Object @@ -218,7 +218,7 @@ static char *rna_Bone_path(PointerRNA *ptr) return BLI_sprintfN("pose.bones[\"%s\"].bone", name_esc); } } - + /* from armature... */ return BLI_sprintfN("bones[\"%s\"]", name_esc); } @@ -267,7 +267,7 @@ static void rna_bone_layer_set(int *layer, const int *values) for (i = 0; i < 32; i++) if (values[i]) tot++; - + if (tot == 0) return; @@ -281,9 +281,9 @@ static void rna_Bone_layer_set(PointerRNA *ptr, const int *values) { bArmature *arm = (bArmature *)ptr->id.data; Bone *bone = (Bone *)ptr->data; - + rna_bone_layer_set(&bone->layer, values); - + arm->layer_used = 0; rna_Armature_layer_used_refresh(arm, &arm->bonebase); } @@ -297,7 +297,7 @@ static void rna_Armature_layer_set(PointerRNA *ptr, const int *values) for (i = 0; i < 32; i++) if (values[i]) tot++; - + if (tot == 0) return; @@ -336,11 +336,11 @@ static void rna_EditBone_name_set(PointerRNA *ptr, const char *value) bArmature *arm = (bArmature *)ptr->id.data; EditBone *ebone = (EditBone *)ptr->data; char oldname[sizeof(ebone->name)], newname[sizeof(ebone->name)]; - + /* need to be on the stack */ BLI_strncpy_utf8(newname, value, sizeof(ebone->name)); BLI_strncpy(oldname, ebone->name, sizeof(ebone->name)); - + ED_armature_bone_rename(G.main, arm, oldname, newname); } @@ -349,7 +349,7 @@ static void rna_Bone_name_set(PointerRNA *ptr, const char *value) bArmature *arm = (bArmature *)ptr->id.data; Bone *bone = (Bone *)ptr->data; char oldname[sizeof(bone->name)], newname[sizeof(bone->name)]; - + /* need to be on the stack */ BLI_strncpy_utf8(newname, value, sizeof(bone->name)); BLI_strncpy(oldname, bone->name, sizeof(bone->name)); @@ -415,7 +415,7 @@ static void rna_EditBone_parent_set(PointerRNA *ptr, PointerRNA value) /* make sure this is a valid child */ if (parbone == ebone) return; - + for (pbone = parbone->parent; pbone; pbone = pbone->parent) if (pbone == ebone) return; @@ -442,7 +442,7 @@ static void rna_Armature_editbone_transform_update(Main *bmain, Scene *scene, Po bArmature *arm = (bArmature *)ptr->id.data; EditBone *ebone = (EditBone *)ptr->data; EditBone *child, *eboflip; - + /* update our parent */ if (ebone->parent && ebone->flag & BONE_CONNECTED) copy_v3_v3(ebone->parent->tail, ebone->head); @@ -460,11 +460,11 @@ static void rna_Armature_editbone_transform_update(Main *bmain, Scene *scene, Po eboflip->head[0] = -ebone->head[0]; eboflip->tail[0] = -ebone->tail[0]; - + /* update our parent */ if (eboflip->parent && eboflip->flag & BONE_CONNECTED) copy_v3_v3(eboflip->parent->tail, eboflip->head); - + /* update our children if necessary */ for (child = arm->edbo->first; child; child = child->next) if (child->parent == eboflip && (child->flag & BONE_CONNECTED)) @@ -522,48 +522,48 @@ void rna_def_bone_curved_common(StructRNA *srna, bool is_posebone) else \ RNA_def_property_update(prop, 0, "rna_Armature_update_data"); \ } (void)0; - + PropertyRNA *prop; - + /* Roll In/Out */ prop = RNA_def_property(srna, "bbone_rollin", PROP_FLOAT, PROP_ANGLE); RNA_def_property_float_sdna(prop, NULL, "roll1"); RNA_def_property_range(prop, -M_PI * 2.0, M_PI * 2.0); RNA_def_property_ui_text(prop, "Roll In", "Roll offset for the start of the B-Bone, adjusts twist"); RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone); - + prop = RNA_def_property(srna, "bbone_rollout", PROP_FLOAT, PROP_ANGLE); RNA_def_property_float_sdna(prop, NULL, "roll2"); RNA_def_property_range(prop, -M_PI * 2.0, M_PI * 2.0); RNA_def_property_ui_text(prop, "Roll Out", "Roll offset for the end of the B-Bone, adjusts twist"); RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone); - + if (is_posebone == false) { prop = RNA_def_property(srna, "use_endroll_as_inroll", PROP_BOOLEAN, PROP_NONE); RNA_def_property_ui_text(prop, "Inherit End Roll", "Use Roll Out of parent bone as Roll In of its children"); RNA_def_property_boolean_sdna(prop, NULL, "flag", BONE_ADD_PARENT_END_ROLL); RNA_def_property_update(prop, 0, "rna_Armature_update_data"); } - + /* Curve X/Y Offsets */ prop = RNA_def_property(srna, "bbone_curveinx", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "curveInX"); RNA_def_property_range(prop, -5.0f, 5.0f); RNA_def_property_ui_text(prop, "In X", "X-axis handle offset for start of the B-Bone's curve, adjusts curvature"); RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone); - + prop = RNA_def_property(srna, "bbone_curveiny", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "curveInY"); RNA_def_property_range(prop, -5.0f, 5.0f); RNA_def_property_ui_text(prop, "In Y", "Y-axis handle offset for start of the B-Bone's curve, adjusts curvature"); RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone); - + prop = RNA_def_property(srna, "bbone_curveoutx", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "curveOutX"); RNA_def_property_range(prop, -5.0f, 5.0f); RNA_def_property_ui_text(prop, "Out X", "X-axis handle offset for end of the B-Bone's curve, adjusts curvature"); RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone); - + prop = RNA_def_property(srna, "bbone_curveouty", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "curveOutY"); RNA_def_property_range(prop, -5.0f, 5.0f); @@ -577,7 +577,7 @@ void rna_def_bone_curved_common(StructRNA *srna, bool is_posebone) RNA_def_property_float_default(prop, 1.0f); RNA_def_property_ui_text(prop, "Ease In", "Length of first Bezier Handle (for B-Bones only)"); RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone); - + prop = RNA_def_property(srna, "bbone_easeout", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "ease2"); RNA_def_property_range(prop, -5.0f, 5.0f); @@ -592,14 +592,14 @@ void rna_def_bone_curved_common(StructRNA *srna, bool is_posebone) RNA_def_property_float_default(prop, 1.0f); RNA_def_property_ui_text(prop, "Scale In", "Scale factor for start of the B-Bone, adjusts thickness (for tapering effects)"); RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone); - + prop = RNA_def_property(srna, "bbone_scaleout", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "scaleOut"); RNA_def_property_range(prop, 0.0f, 5.0f); RNA_def_property_float_default(prop, 1.0f); RNA_def_property_ui_text(prop, "Scale Out", "Scale factor for end of the B-Bone, adjusts thickness (for tapering effects)"); RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone); - + #undef RNA_DEF_CURVEBONE_UPDATE } @@ -631,23 +631,23 @@ static void rna_def_bone_common(StructRNA *srna, int editbone) else RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Connected", "When bone has a parent, bone's head is stuck to the parent's tail"); RNA_def_property_update(prop, 0, "rna_Armature_update_data"); - + prop = RNA_def_property(srna, "use_inherit_rotation", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", BONE_HINGE); RNA_def_property_ui_text(prop, "Inherit Rotation", "Bone inherits rotation or scale from parent bone"); RNA_def_property_update(prop, 0, "rna_Armature_update_data"); - + prop = RNA_def_property(srna, "use_envelope_multiply", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", BONE_MULT_VG_ENV); RNA_def_property_ui_text(prop, "Multiply Vertex Group with Envelope", "When deforming bone, multiply effects of Vertex Group weights with Envelope influence"); RNA_def_property_update(prop, 0, "rna_Armature_update_data"); - + prop = RNA_def_property(srna, "use_deform", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", BONE_NO_DEFORM); RNA_def_property_ui_text(prop, "Deform", "Enable Bone to deform geometry"); RNA_def_property_update(prop, 0, "rna_Armature_update_data"); - + prop = RNA_def_property(srna, "use_inherit_scale", PROP_BOOLEAN, PROP_NONE); RNA_def_property_ui_text(prop, "Inherit Scale", "Bone inherits scaling from parent bone"); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", BONE_NO_SCALE); @@ -657,19 +657,19 @@ static void rna_def_bone_common(StructRNA *srna, int editbone) RNA_def_property_ui_text(prop, "Local Location", "Bone location is set in local space"); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", BONE_NO_LOCAL_LOCATION); RNA_def_property_update(prop, 0, "rna_Armature_update_data"); - + prop = RNA_def_property(srna, "use_relative_parent", PROP_BOOLEAN, PROP_NONE); RNA_def_property_ui_text(prop, "Relative Parenting", "Object children will use relative transform, like deform"); RNA_def_property_boolean_sdna(prop, NULL, "flag", BONE_RELATIVE_PARENTING); RNA_def_property_update(prop, 0, "rna_Armature_update_data"); - + prop = RNA_def_property(srna, "show_wire", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", BONE_DRAWWIRE); RNA_def_property_ui_text(prop, "Draw Wire", "Bone is always drawn as Wireframe regardless of viewport draw mode " "(useful for non-obstructive custom bone shapes)"); RNA_def_property_update(prop, 0, "rna_Armature_redraw_data"); - + /* XXX: use_cyclic_offset is deprecated in 2.5. May/may not return */ prop = RNA_def_property(srna, "use_cyclic_offset", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", BONE_NO_CYCLICOFFSET); @@ -677,7 +677,7 @@ static void rna_def_bone_common(StructRNA *srna, int editbone) "When bone doesn't have a parent, it receives cyclic offset effects (Deprecated)"); // "When bone doesn't have a parent, it receives cyclic offset effects"); RNA_def_property_update(prop, 0, "rna_Armature_update_data"); - + prop = RNA_def_property(srna, "hide_select", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", BONE_UNSELECTABLE); RNA_def_property_ui_text(prop, "Selectable", "Bone is able to be selected"); @@ -690,13 +690,13 @@ static void rna_def_bone_common(StructRNA *srna, int editbone) RNA_def_property_range(prop, 0.0f, 1000.0f); RNA_def_property_ui_text(prop, "Envelope Deform Distance", "Bone deformation distance (for Envelope deform only)"); RNA_def_property_update(prop, 0, "rna_Armature_update_data"); - + prop = RNA_def_property(srna, "envelope_weight", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "weight"); RNA_def_property_range(prop, 0.0f, 1000.0f); RNA_def_property_ui_text(prop, "Envelope Deform Weight", "Bone deformation weight (for Envelope deform only)"); RNA_def_property_update(prop, 0, "rna_Armature_update_data"); - + prop = RNA_def_property(srna, "head_radius", PROP_FLOAT, PROP_UNSIGNED); if (editbone) RNA_def_property_update(prop, 0, "rna_Armature_editbone_transform_update"); else RNA_def_property_update(prop, 0, "rna_Armature_update_data"); @@ -705,7 +705,7 @@ static void rna_def_bone_common(StructRNA *srna, int editbone) /*RNA_def_property_range(prop, 0, 1000); */ RNA_def_property_ui_range(prop, 0.01, 100, 0.1, 3); RNA_def_property_ui_text(prop, "Envelope Head Radius", "Radius of head of bone (for Envelope deform only)"); - + prop = RNA_def_property(srna, "tail_radius", PROP_FLOAT, PROP_UNSIGNED); if (editbone) RNA_def_property_update(prop, 0, "rna_Armature_editbone_transform_update"); else RNA_def_property_update(prop, 0, "rna_Armature_update_data"); @@ -714,20 +714,20 @@ static void rna_def_bone_common(StructRNA *srna, int editbone) /*RNA_def_property_range(prop, 0, 1000); */ RNA_def_property_ui_range(prop, 0.01, 100, 0.1, 3); RNA_def_property_ui_text(prop, "Envelope Tail Radius", "Radius of tail of bone (for Envelope deform only)"); - + /* b-bones deform settings */ prop = RNA_def_property(srna, "bbone_segments", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "segments"); RNA_def_property_range(prop, 1, 32); RNA_def_property_ui_text(prop, "B-Bone Segments", "Number of subdivisions of bone (for B-Bones only)"); RNA_def_property_update(prop, 0, "rna_Armature_update_data"); - + prop = RNA_def_property(srna, "bbone_x", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "xwidth"); RNA_def_property_range(prop, 0.0f, 1000.0f); RNA_def_property_ui_text(prop, "B-Bone Display X Width", "B-Bone X size"); RNA_def_property_update(prop, 0, "rna_Armature_update_data"); - + prop = RNA_def_property(srna, "bbone_z", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "zwidth"); RNA_def_property_range(prop, 0.0f, 1000.0f); @@ -740,13 +740,13 @@ static void rna_def_bone(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + srna = RNA_def_struct(brna, "Bone", NULL); RNA_def_struct_ui_text(srna, "Bone", "Bone in an Armature data-block"); RNA_def_struct_ui_icon(srna, ICON_BONE_DATA); RNA_def_struct_path_func(srna, "rna_Bone_path"); RNA_def_struct_idprops_func(srna, "rna_Bone_idprops"); - + /* pointers/collections */ /* parent (pointer) */ prop = RNA_def_property(srna, "parent", PROP_POINTER, PROP_NONE); @@ -755,7 +755,7 @@ static void rna_def_bone(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_PTR_NO_OWNERSHIP); RNA_def_property_ui_text(prop, "Parent", "Parent bone (in same Armature)"); RNA_def_property_update(prop, 0, "rna_Armature_redraw_data"); - + /* children (collection) */ prop = RNA_def_property(srna, "children", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "childbase", NULL); @@ -779,13 +779,13 @@ static void rna_def_bone(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Select", ""); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); /* XXX: review whether this could be used for interesting effects... */ RNA_def_property_update(prop, 0, "rna_Bone_select_update"); - + prop = RNA_def_property(srna, "select_head", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", BONE_ROOTSEL); RNA_def_property_ui_text(prop, "Select Head", ""); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_update(prop, 0, "rna_Armature_redraw_data"); - + prop = RNA_def_property(srna, "select_tail", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", BONE_TIPSEL); RNA_def_property_ui_text(prop, "Select Tail", ""); @@ -840,13 +840,13 @@ static void rna_def_edit_bone(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + srna = RNA_def_struct(brna, "EditBone", NULL); RNA_def_struct_sdna(srna, "EditBone"); RNA_def_struct_idprops_func(srna, "rna_EditBone_idprops"); RNA_def_struct_ui_text(srna, "Edit Bone", "Editmode bone in an Armature data-block"); RNA_def_struct_ui_icon(srna, ICON_BONE_DATA); - + RNA_define_verify_sdna(0); /* not in sdna */ prop = RNA_def_property(srna, "parent", PROP_POINTER, PROP_NONE); @@ -855,7 +855,7 @@ static void rna_def_edit_bone(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Parent", "Parent edit bone (in same Armature)"); RNA_def_property_update(prop, 0, "rna_Armature_redraw_data"); - + prop = RNA_def_property(srna, "roll", PROP_FLOAT, PROP_ANGLE); RNA_def_property_float_sdna(prop, NULL, "roll"); RNA_def_property_ui_range(prop, -M_PI * 2, M_PI * 2, 10, 2); @@ -903,7 +903,7 @@ static void rna_def_edit_bone(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Head Select", ""); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_update(prop, 0, "rna_Armature_redraw_data"); - + prop = RNA_def_property(srna, "select_tail", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", BONE_TIPSEL); RNA_def_property_ui_text(prop, "Tail Select", ""); @@ -1027,7 +1027,7 @@ static void rna_def_armature(BlenderRNA *brna) {ARM_RESTPOS, "REST", 0, "Rest Position", "Show Armature in binding pose state (no posing possible)"}, {0, NULL, 0, NULL, NULL} }; - + srna = RNA_def_struct(brna, "Armature", "ID"); RNA_def_struct_ui_text(srna, "Armature", "Armature data-block containing a hierarchy of bones, usually used for rigging characters"); @@ -1042,7 +1042,7 @@ static void rna_def_armature(BlenderRNA *brna) /* Animation Data */ rna_def_animdata_common(srna); - + /* Collections */ prop = RNA_def_property(srna, "bones", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "bonebase", NULL); @@ -1064,7 +1064,7 @@ static void rna_def_armature(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Pose Position", "Show armature in binding pose or final posed state"); RNA_def_property_update(prop, 0, "rna_Armature_update_data"); RNA_def_property_flag(prop, PROP_LIB_EXCEPTION); - + prop = RNA_def_property(srna, "draw_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "drawtype"); RNA_def_property_enum_items(prop, prop_drawtype_items); @@ -1090,7 +1090,7 @@ static void rna_def_armature(BlenderRNA *brna) RNA_def_property_boolean_funcs(prop, NULL, "rna_Armature_layer_set"); RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Armature_update_layers"); RNA_def_property_flag(prop, PROP_LIB_EXCEPTION); - + /* layer protection */ prop = RNA_def_property(srna, "layers_protected", PROP_BOOLEAN, PROP_LAYER); RNA_def_property_boolean_sdna(prop, NULL, "layer_protected", 1); @@ -1099,47 +1099,47 @@ static void rna_def_armature(BlenderRNA *brna) "Protected layers in Proxy Instances are restored to Proxy settings " "on file reload and undo"); RNA_def_property_update(prop, 0, "rna_Armature_redraw_data"); - + /* flag */ prop = RNA_def_property(srna, "show_axes", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", ARM_DRAWAXES); RNA_def_property_ui_text(prop, "Draw Axes", "Draw bone axes"); RNA_def_property_update(prop, 0, "rna_Armature_redraw_data"); RNA_def_property_flag(prop, PROP_LIB_EXCEPTION); - + prop = RNA_def_property(srna, "show_names", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", ARM_DRAWNAMES); RNA_def_property_ui_text(prop, "Draw Names", "Draw bone names"); RNA_def_property_update(prop, 0, "rna_Armature_redraw_data"); RNA_def_property_flag(prop, PROP_LIB_EXCEPTION); - + prop = RNA_def_property(srna, "use_deform_delay", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", ARM_DELAYDEFORM); RNA_def_property_ui_text(prop, "Delay Deform", "Don't deform children when manipulating bones in Pose Mode"); RNA_def_property_update(prop, 0, "rna_Armature_update_data"); - + prop = RNA_def_property(srna, "use_mirror_x", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", ARM_MIRROR_EDIT); RNA_def_property_ui_text(prop, "X-Axis Mirror", "Apply changes to matching bone on opposite side of X-Axis"); RNA_def_property_update(prop, 0, "rna_Armature_redraw_data"); RNA_def_property_flag(prop, PROP_LIB_EXCEPTION); - + prop = RNA_def_property(srna, "use_auto_ik", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", ARM_AUTO_IK); RNA_def_property_ui_text(prop, "Auto IK", "Add temporary IK constraints while grabbing bones in Pose Mode"); RNA_def_property_update(prop, 0, "rna_Armature_redraw_data"); RNA_def_property_flag(prop, PROP_LIB_EXCEPTION); - + prop = RNA_def_property(srna, "show_bone_custom_shapes", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", ARM_NO_CUSTOM); RNA_def_property_ui_text(prop, "Draw Custom Bone Shapes", "Draw bones with their custom shapes"); RNA_def_property_update(prop, 0, "rna_Armature_redraw_data"); - + prop = RNA_def_property(srna, "show_group_colors", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", ARM_COL_CUSTOM); RNA_def_property_ui_text(prop, "Draw Bone Group Colors", "Draw bone group colors"); RNA_def_property_update(prop, 0, "rna_Armature_redraw_data"); - + /* XXX deprecated ....... old animviz for armatures only */ prop = RNA_def_property(srna, "show_only_ghost_selected", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", ARM_GHOST_ONLYSEL); @@ -1159,7 +1159,7 @@ static void rna_def_armature(BlenderRNA *brna) "(only for 'Around Current Frame' Onion-skinning method)"); RNA_def_property_update(prop, 0, "rna_Armature_redraw_data"); RNA_def_property_flag(prop, PROP_LIB_EXCEPTION); - + prop = RNA_def_property(srna, "ghost_size", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "ghostsize"); RNA_def_property_range(prop, 1, 20); @@ -1167,7 +1167,7 @@ static void rna_def_armature(BlenderRNA *brna) "Frame step for Ghosts (not for 'On Keyframes' Onion-skinning method)"); RNA_def_property_update(prop, 0, "rna_Armature_redraw_data"); RNA_def_property_flag(prop, PROP_LIB_EXCEPTION); - + prop = RNA_def_property(srna, "ghost_frame_start", PROP_INT, PROP_TIME); RNA_def_property_int_sdna(prop, NULL, "ghostsf"); RNA_def_property_int_funcs(prop, NULL, "rna_Armature_ghost_start_frame_set", NULL); @@ -1176,7 +1176,7 @@ static void rna_def_armature(BlenderRNA *brna) "'Around Current Frame' Onion-skinning method)"); RNA_def_property_update(prop, 0, "rna_Armature_redraw_data"); RNA_def_property_flag(prop, PROP_LIB_EXCEPTION); - + prop = RNA_def_property(srna, "ghost_frame_end", PROP_INT, PROP_TIME); RNA_def_property_int_sdna(prop, NULL, "ghostef"); RNA_def_property_int_funcs(prop, NULL, "rna_Armature_ghost_end_frame_set", NULL); diff --git a/source/blender/makesrna/intern/rna_boid.c b/source/blender/makesrna/intern/rna_boid.c index 98ca58e0edd..413cb10422a 100644 --- a/source/blender/makesrna/intern/rna_boid.c +++ b/source/blender/makesrna/intern/rna_boid.c @@ -96,7 +96,7 @@ static void rna_Boids_reset(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRN { if (ptr->type == &RNA_ParticleSystem) { ParticleSystem *psys = (ParticleSystem *)ptr->data; - + psys->recalc = PSYS_RECALC_RESET; DEG_id_tag_update(ptr->id.data, OB_RECALC_DATA); @@ -110,7 +110,7 @@ static void rna_Boids_reset_deps(Main *bmain, Scene *UNUSED(scene), PointerRNA * { if (ptr->type == &RNA_ParticleSystem) { ParticleSystem *psys = (ParticleSystem *)ptr->data; - + psys->recalc = PSYS_RECALC_RESET; DEG_id_tag_update(ptr->id.data, OB_RECALC_DATA); @@ -211,10 +211,10 @@ static int particle_id_check(PointerRNA *ptr) static char *rna_BoidSettings_path(PointerRNA *ptr) { BoidSettings *boids = (BoidSettings *)ptr->data; - + if (particle_id_check(ptr)) { ParticleSettings *part = (ParticleSettings *)ptr->id.data; - + if (part->boids == boids) return BLI_sprintfN("boids"); } @@ -418,36 +418,36 @@ static void rna_def_boidrule(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + /* data */ srna = RNA_def_struct(brna, "BoidRule", NULL); RNA_def_struct_ui_text(srna, "Boid Rule", ""); RNA_def_struct_refine_func(srna, "rna_BoidRule_refine"); RNA_def_struct_path_func(srna, "rna_BoidRule_path"); - + /* strings */ prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); RNA_def_property_ui_text(prop, "Name", "Boid rule name"); RNA_def_struct_name_property(srna, prop); - + /* enums */ prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_enum_sdna(prop, NULL, "type"); RNA_def_property_enum_items(prop, rna_enum_boidrule_type_items); RNA_def_property_ui_text(prop, "Type", ""); - + /* flags */ prop = RNA_def_property(srna, "use_in_air", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", BOIDRULE_IN_AIR); RNA_def_property_ui_text(prop, "In Air", "Use rule when boid is flying"); RNA_def_property_update(prop, 0, "rna_Boids_reset"); - + prop = RNA_def_property(srna, "use_on_land", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", BOIDRULE_ON_LAND); RNA_def_property_ui_text(prop, "On Land", "Use rule when boid is on land"); RNA_def_property_update(prop, 0, "rna_Boids_reset"); - + /*prop = RNA_def_property(srna, "show_expanded", PROP_BOOLEAN, PROP_NONE); */ /*RNA_def_property_boolean_sdna(prop, NULL, "mode", eModifierMode_Expanded); */ /*RNA_def_property_ui_text(prop, "Expanded", "Set modifier expanded in the user interface"); */ diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c index d227d7a3dbe..75d05115006 100644 --- a/source/blender/makesrna/intern/rna_brush.c +++ b/source/blender/makesrna/intern/rna_brush.c @@ -111,7 +111,7 @@ const EnumPropertyItem rna_enum_brush_vertex_tool_items[] = { {0, NULL, 0, NULL, NULL} }; - + const EnumPropertyItem rna_enum_brush_image_tool_items[] = { {PAINT_TOOL_DRAW, "DRAW", ICON_BRUSH_TEXDRAW, "Draw", ""}, {PAINT_TOOL_SOFTEN, "SOFTEN", ICON_BRUSH_SOFTEN, "Soften", ""}, @@ -403,14 +403,14 @@ static void rna_Brush_sculpt_tool_update(Main *bmain, Scene *scene, PointerRNA * rna_Brush_reset_icon(br, "sculpt"); rna_Brush_update(bmain, scene, ptr); } - + static void rna_Brush_vertex_tool_update(Main *bmain, Scene *scene, PointerRNA *ptr) { Brush *br = (Brush *)ptr->data; rna_Brush_reset_icon(br, "vertex_paint"); rna_Brush_update(bmain, scene, ptr); } - + static void rna_Brush_imagepaint_tool_update(Main *bmain, Scene *scene, PointerRNA *ptr) { Brush *br = (Brush *)ptr->data; @@ -656,8 +656,8 @@ static void rna_def_brush_texture_slot(BlenderRNA *brna) RNA_def_property_boolean_funcs(prop, "rna_TextureCapabilities_" \ #prop_name_ "_get", NULL); \ RNA_def_property_ui_text(prop, ui_name_, NULL) - - + + srna = RNA_def_struct(brna, "BrushTextureSlot", "TextureSlot"); RNA_def_struct_sdna(srna, "MTex"); RNA_def_struct_ui_text(srna, "Brush Texture Slot", "Texture slot for textures in a Brush data-block"); @@ -707,10 +707,10 @@ static void rna_def_brush_texture_slot(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Random Angle", "Brush texture random angle"); RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); RNA_def_property_update(prop, 0, "rna_TextureSlot_update"); - + TEXTURE_CAPABILITY(has_texture_angle_source, "Has Texture Angle Source"); TEXTURE_CAPABILITY(has_random_texture_angle, "Has Random Texture Angle"); - TEXTURE_CAPABILITY(has_texture_angle, "Has Texture Angle Source"); + TEXTURE_CAPABILITY(has_texture_angle, "Has Texture Angle Source"); } static void rna_def_sculpt_capabilities(BlenderRNA *brna) @@ -813,7 +813,7 @@ static void rna_def_brush(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + static const EnumPropertyItem prop_blend_items[] = { {IMB_BLEND_MIX, "MIX", 0, "Mix", "Use mix blending mode while painting"}, {IMB_BLEND_ADD, "ADD", 0, "Add", "Use add blending mode while painting"}, @@ -841,7 +841,7 @@ static void rna_def_brush(BlenderRNA *brna) {IMB_BLEND_COLOR, "COLOR", 0, "Color", "Use color blending mode while painting"}, {0, NULL, 0, NULL, NULL} }; - + static const EnumPropertyItem brush_sculpt_plane_items[] = { {SCULPT_DISP_DIR_AREA, "AREA", 0, "Area Plane", ""}, {SCULPT_DISP_DIR_VIEW, "VIEW", 0, "View Plane", ""}, @@ -903,7 +903,7 @@ static void rna_def_brush(BlenderRNA *brna) RNA_def_property_enum_items(prop, rna_enum_brush_vertex_tool_items); RNA_def_property_ui_text(prop, "Blending mode", "Brush blending mode"); RNA_def_property_update(prop, 0, "rna_Brush_vertex_tool_update"); - + prop = RNA_def_property(srna, "image_tool", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "imagepaint_tool"); RNA_def_property_enum_items(prop, rna_enum_brush_image_tool_items); @@ -933,7 +933,7 @@ static void rna_def_brush(BlenderRNA *brna) RNA_def_property_enum_items(prop, brush_mask_tool_items); RNA_def_property_ui_text(prop, "Mask Tool", ""); RNA_def_property_update(prop, 0, "rna_Brush_update"); - + /* number values */ prop = RNA_def_property(srna, "size", PROP_INT, PROP_PIXEL); RNA_def_property_int_funcs(prop, NULL, "rna_Brush_set_size", NULL); @@ -941,7 +941,7 @@ static void rna_def_brush(BlenderRNA *brna) RNA_def_property_ui_range(prop, 1, MAX_BRUSH_PIXEL_RADIUS, 1, -1); RNA_def_property_ui_text(prop, "Radius", "Radius of the brush in pixels"); RNA_def_property_update(prop, 0, "rna_Brush_size_update"); - + prop = RNA_def_property(srna, "unprojected_radius", PROP_FLOAT, PROP_DISTANCE); RNA_def_property_float_funcs(prop, NULL, "rna_Brush_set_unprojected_radius", NULL); RNA_def_property_range(prop, 0.001, FLT_MAX); @@ -985,14 +985,14 @@ static void rna_def_brush(BlenderRNA *brna) RNA_def_property_range(prop, 0.5, 0.99); RNA_def_property_ui_text(prop, "Smooth Stroke Factor", "Higher values give a smoother stroke"); RNA_def_property_update(prop, 0, "rna_Brush_update"); - + prop = RNA_def_property(srna, "rate", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "rate"); RNA_def_property_range(prop, 0.0001f, 10000.0f); RNA_def_property_ui_range(prop, 0.01f, 1.0f, 1, 3); RNA_def_property_ui_text(prop, "Rate", "Interval between paints for Airbrush"); RNA_def_property_update(prop, 0, "rna_Brush_update"); - + prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_range(prop, 0.0, 1.0); RNA_def_property_float_sdna(prop, NULL, "rgb"); @@ -1149,20 +1149,20 @@ static void rna_def_brush(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_AIRBRUSH); RNA_def_property_ui_text(prop, "Airbrush", "Keep applying paint effect while holding mouse (spray)"); RNA_def_property_update(prop, 0, "rna_Brush_update"); - + prop = RNA_def_property(srna, "use_original_normal", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_ORIGINAL_NORMAL); RNA_def_property_ui_icon(prop, ICON_UNLOCKED, true); RNA_def_property_ui_text(prop, "Original Normal", "When locked keep using normal of surface where stroke was initiated"); RNA_def_property_update(prop, 0, "rna_Brush_update"); - + prop = RNA_def_property(srna, "use_pressure_strength", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_ALPHA_PRESSURE); RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0); RNA_def_property_ui_text(prop, "Strength Pressure", "Enable tablet pressure sensitivity for strength"); RNA_def_property_update(prop, 0, "rna_Brush_update"); - + prop = RNA_def_property(srna, "use_offset_pressure", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_OFFSET_PRESSURE); RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0); @@ -1204,7 +1204,7 @@ static void rna_def_brush(BlenderRNA *brna) RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0); RNA_def_property_ui_text(prop, "Inverse Smooth Pressure", "Lighter pressure causes more smoothing to be applied"); RNA_def_property_update(prop, 0, "rna_Brush_update"); - + prop = RNA_def_property(srna, "use_relative_jitter", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", BRUSH_ABSOLUTE_JITTER); RNA_def_property_ui_icon(prop, ICON_UNLOCKED, true); @@ -1260,7 +1260,7 @@ static void rna_def_brush(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_ACCUMULATE); RNA_def_property_ui_text(prop, "Accumulate", "Accumulate stroke daubs on top of each other"); RNA_def_property_update(prop, 0, "rna_Brush_update"); - + prop = RNA_def_property(srna, "use_space_attenuation", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_SPACE_ATTEN); RNA_def_property_ui_icon(prop, ICON_UNLOCKED, true); @@ -1379,7 +1379,7 @@ static void rna_def_brush(BlenderRNA *brna) RNA_def_property_pointer_sdna(prop, NULL, "mtex"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Texture Slot", ""); - + prop = RNA_def_property(srna, "texture", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "mtex.tex"); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_CONTEXT_UPDATE); @@ -1444,7 +1444,7 @@ static void rna_def_brush(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Clone Image", "Image for clone tool"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, "rna_Brush_update"); - + prop = RNA_def_property(srna, "clone_alpha", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "clone.alpha"); RNA_def_property_range(prop, 0.0f, 1.0f); @@ -1524,7 +1524,7 @@ static void rna_def_operator_stroke_element(BlenderRNA *brna) prop = RNA_def_property(srna, "time", PROP_FLOAT, PROP_UNSIGNED); RNA_def_property_flag(prop, PROP_IDPROPERTY); RNA_def_property_ui_text(prop, "Time", ""); - + /* used for Grease Pencil sketching sessions */ prop = RNA_def_property(srna, "is_start", PROP_BOOLEAN, PROP_NONE); RNA_def_property_flag(prop, PROP_IDPROPERTY); diff --git a/source/blender/makesrna/intern/rna_cloth.c b/source/blender/makesrna/intern/rna_cloth.c index 3d1a1458102..0958011a7f0 100644 --- a/source/blender/makesrna/intern/rna_cloth.c +++ b/source/blender/makesrna/intern/rna_cloth.c @@ -89,11 +89,11 @@ static void rna_ClothSettings_bending_set(struct PointerRNA *ptr, float value) static void rna_ClothSettings_max_bend_set(struct PointerRNA *ptr, float value) { ClothSimSettings *settings = (ClothSimSettings *)ptr->data; - + /* check for clipping */ if (value < settings->bending) value = settings->bending; - + settings->max_bend = value; } @@ -111,11 +111,11 @@ static void rna_ClothSettings_structural_set(struct PointerRNA *ptr, float value static void rna_ClothSettings_max_struct_set(struct PointerRNA *ptr, float value) { ClothSimSettings *settings = (ClothSimSettings *)ptr->data; - + /* check for clipping */ if (value < settings->structural) value = settings->structural; - + settings->max_struct = value; } @@ -291,7 +291,7 @@ static void rna_def_cloth_solver_result(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + static const EnumPropertyItem status_items[] = { {BPH_SOLVER_SUCCESS, "SUCCESS", 0, "Success", "Computation was successful"}, {BPH_SOLVER_NUMERICAL_ISSUE, "NUMERICAL_ISSUE", 0, "Numerical Issue", "The provided data did not satisfy the prerequisites"}, @@ -299,49 +299,49 @@ static void rna_def_cloth_solver_result(BlenderRNA *brna) {BPH_SOLVER_INVALID_INPUT, "INVALID_INPUT", 0, "Invalid Input", "The inputs are invalid, or the algorithm has been improperly called"}, {0, NULL, 0, NULL, NULL} }; - + srna = RNA_def_struct(brna, "ClothSolverResult", NULL); RNA_def_struct_ui_text(srna, "Solver Result", "Result of cloth solver iteration"); - + RNA_define_verify_sdna(0); - + prop = RNA_def_property(srna, "status", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, status_items); RNA_def_property_enum_sdna(prop, NULL, "status"); RNA_def_property_flag(prop, PROP_ENUM_FLAG); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Status", "Status of the solver iteration"); - + prop = RNA_def_property(srna, "max_error", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "max_error"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Maximum Error", "Maximum error during substeps"); - + prop = RNA_def_property(srna, "min_error", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "min_error"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Minimum Error", "Minimum error during substeps"); - + prop = RNA_def_property(srna, "avg_error", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "avg_error"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Average Error", "Average error during substeps"); - + prop = RNA_def_property(srna, "max_iterations", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "max_iterations"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Maximum Iterations", "Maximum iterations during substeps"); - + prop = RNA_def_property(srna, "min_iterations", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "min_iterations"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Minimum Iterations", "Minimum iterations during substeps"); - + prop = RNA_def_property(srna, "avg_iterations", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "avg_iterations"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Average Iterations", "Average iterations during substeps"); - + RNA_define_verify_sdna(1); } @@ -349,14 +349,14 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + srna = RNA_def_struct(brna, "ClothSettings", NULL); RNA_def_struct_ui_text(srna, "Cloth Settings", "Cloth simulation settings for an object"); RNA_def_struct_sdna(srna, "ClothSimSettings"); RNA_def_struct_path_func(srna, "rna_ClothSettings_path"); - + /* goal */ - + prop = RNA_def_property(srna, "goal_min", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "mingoal"); RNA_def_property_range(prop, 0.0f, 1.0f); @@ -377,13 +377,13 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Goal Default", "Default Goal (vertex target position) value, when no Vertex Group used"); RNA_def_property_update(prop, 0, "rna_cloth_update"); - + prop = RNA_def_property(srna, "goal_spring", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "goalspring"); RNA_def_property_range(prop, 0.0f, 0.999f); RNA_def_property_ui_text(prop, "Goal Stiffness", "Goal (vertex target position) spring stiffness"); RNA_def_property_update(prop, 0, "rna_cloth_update"); - + prop = RNA_def_property(srna, "goal_friction", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "goalfrict"); RNA_def_property_range(prop, 0.0f, 50.0f); @@ -426,7 +426,7 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna) "rna_ClothSettings_mass_vgroup_set"); RNA_def_property_ui_text(prop, "Mass Vertex Group", "Vertex Group for pinning of vertices"); RNA_def_property_update(prop, 0, "rna_cloth_pinning_changed"); - + prop = RNA_def_property(srna, "gravity", PROP_FLOAT, PROP_ACCELERATION); RNA_def_property_array(prop, 3); RNA_def_property_range(prop, -100.0, 100.0); @@ -510,14 +510,14 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna) "If enabled, stiffness can be scaled along a weight painted vertex group"); RNA_def_property_update(prop, 0, "rna_cloth_update"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - + prop = RNA_def_property(srna, "spring_damping", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "Cdis"); RNA_def_property_range(prop, 0.0f, 50.0f); RNA_def_property_ui_text(prop, "Spring Damping", "Damping of cloth velocity (higher = more smooth, less jiggling)"); RNA_def_property_update(prop, 0, "rna_cloth_update"); - + prop = RNA_def_property(srna, "structural_stiffness", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "structural"); RNA_def_property_range(prop, 0.0f, 10000.0f); @@ -650,7 +650,7 @@ static void rna_def_cloth_collision_settings(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + srna = RNA_def_struct(brna, "ClothCollisionSettings", NULL); RNA_def_struct_ui_text(srna, "Cloth Collision Settings", "Cloth simulation settings for self collision and collision with other objects"); @@ -678,7 +678,7 @@ static void rna_def_cloth_collision_settings(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Repulsion Distance", "Maximum distance to apply repulsion force, must be greater than minimum distance"); RNA_def_property_update(prop, 0, "rna_cloth_update"); - + prop = RNA_def_property(srna, "distance_min", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "epsilon"); RNA_def_property_range(prop, 0.001f, 1.0f); @@ -712,13 +712,13 @@ static void rna_def_cloth_collision_settings(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flags", CLOTH_COLLSETTINGS_FLAG_SELF); RNA_def_property_ui_text(prop, "Enable Self Collision", "Enable self collisions"); RNA_def_property_update(prop, 0, "rna_cloth_update"); - + prop = RNA_def_property(srna, "self_distance_min", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "selfepsilon"); RNA_def_property_range(prop, 0.5f, 1.0f); RNA_def_property_ui_text(prop, "Self Minimum Distance", "0.5 means no distance at all, 1.0 is maximum distance"); RNA_def_property_update(prop, 0, "rna_cloth_update"); - + prop = RNA_def_property(srna, "self_friction", PROP_FLOAT, PROP_NONE); RNA_def_property_range(prop, 0.0f, 80.0f); RNA_def_property_ui_text(prop, "Self Friction", "Friction/damping with self contact"); diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c index 8e090937605..99fa532452f 100644 --- a/source/blender/makesrna/intern/rna_color.c +++ b/source/blender/makesrna/intern/rna_color.c @@ -75,7 +75,7 @@ static int rna_CurveMapping_curves_length(PointerRNA *ptr) for (len = 0; len < CM_TOT; len++) if (!cumap->cm[len].curve) break; - + return len; } @@ -154,11 +154,11 @@ static void rna_CurveMapping_clipmaxy_range(PointerRNA *ptr, float *min, float * static char *rna_ColorRamp_path(PointerRNA *ptr) { char *path = NULL; - + /* handle the cases where a single data-block may have 2 ramp types */ if (ptr->id.data) { ID *id = ptr->id.data; - + switch (GS(id->name)) { case ID_NT: { @@ -166,7 +166,7 @@ static char *rna_ColorRamp_path(PointerRNA *ptr) bNode *node; PointerRNA node_ptr; char *node_path; - + for (node = ntree->nodes.first; node; node = node->next) { if (ELEM(node->type, SH_NODE_VALTORGB, CMP_NODE_VALTORGB, TEX_NODE_VALTORGB)) { if (node->storage == ptr->data) { @@ -182,14 +182,14 @@ static char *rna_ColorRamp_path(PointerRNA *ptr) } break; } - + case ID_LS: { /* may be NULL */ path = BKE_linestyle_path_to_color_ramp((FreestyleLineStyle *)id, (ColorBand *)ptr->data); break; } - + default: /* everything else just uses 'color_ramp' */ path = BLI_strdup("color_ramp"); @@ -200,7 +200,7 @@ static char *rna_ColorRamp_path(PointerRNA *ptr) /* everything else just uses 'color_ramp' */ path = BLI_strdup("color_ramp"); } - + return path; } @@ -210,7 +210,7 @@ static char *rna_ColorRampElement_path(PointerRNA *ptr) PropertyRNA *prop; char *path = NULL; int index; - + /* helper macro for use here to try and get the path * - this calls the standard code for getting a path to a texture... */ @@ -232,13 +232,13 @@ static char *rna_ColorRampElement_path(PointerRNA *ptr) /* FIXME: this is a very slow way to do it, but it will have to suffice... */ if (ptr->id.data) { ID *id = ptr->id.data; - + switch (GS(id->name)) { case ID_NT: { bNodeTree *ntree = (bNodeTree *)id; bNode *node; - + for (node = ntree->nodes.first; node; node = node->next) { if (ELEM(node->type, SH_NODE_VALTORGB, CMP_NODE_VALTORGB, TEX_NODE_VALTORGB)) { RNA_pointer_create(id, &RNA_ColorRamp, node->storage, &ramp_ptr); @@ -272,10 +272,10 @@ static char *rna_ColorRampElement_path(PointerRNA *ptr) } } } - + /* cleanup the macro we defined */ #undef COLRAMP_GETPATH - + return path; } @@ -283,12 +283,12 @@ static void rna_ColorRamp_update(Main *bmain, Scene *UNUSED(scene), PointerRNA * { if (ptr->id.data) { ID *id = ptr->id.data; - + switch (GS(id->name)) { case ID_MA: { Material *ma = ptr->id.data; - + DEG_id_tag_update(&ma->id, 0); WM_main_add_notifier(NC_MATERIAL | ND_SHADING_DRAW, ma); break; @@ -323,7 +323,7 @@ static void rna_ColorRamp_update(Main *bmain, Scene *UNUSED(scene), PointerRNA * case ID_PA: { ParticleSettings *part = ptr->id.data; - + DEG_id_tag_update(&part->id, OB_RECALC_DATA | PSYS_RECALC_REDO); WM_main_add_notifier(NC_OBJECT | ND_PARTICLE | NA_EDITED, part); } @@ -557,7 +557,7 @@ static void rna_ColorManagedColorspaceSettings_reload_update(Main *bmain, Scene DEG_id_tag_update(&ima->id, 0); - BKE_image_signal(ima, NULL, IMA_SIGNAL_COLORMANAGE); + BKE_image_signal(bmain, ima, NULL, IMA_SIGNAL_COLORMANAGE); WM_main_add_notifier(NC_IMAGE | ND_DISPLAY, &ima->id); WM_main_add_notifier(NC_IMAGE | NA_EDITED, &ima->id); @@ -761,7 +761,7 @@ static void rna_def_curvemapping(BlenderRNA *brna) RNA_def_struct_ui_text(srna, "CurveMapping", "Curve mapping to map color, vector and scalar values to other values using " "a user defined curve"); - + prop = RNA_def_property(srna, "use_clip", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", CUMA_DO_CLIP); RNA_def_property_ui_text(prop, "Clip", "Force the curve view to fit a defined boundary"); @@ -828,7 +828,7 @@ static void rna_def_color_ramp_element(BlenderRNA *brna) RNA_def_struct_sdna(srna, "CBData"); RNA_def_struct_path_func(srna, "rna_ColorRampElement_path"); RNA_def_struct_ui_text(srna, "Color Ramp Element", "Element defining a color at a position in the color ramp"); - + prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR); RNA_def_property_float_sdna(prop, NULL, "r"); RNA_def_property_array(prop, 4); @@ -893,7 +893,7 @@ static void rna_def_color_ramp(BlenderRNA *brna) {COLBAND_INTERP_CONSTANT, "CONSTANT", 0, "Constant", ""}, {0, NULL, 0, NULL, NULL} }; - + static const EnumPropertyItem prop_mode_items[] = { {COLBAND_BLEND_RGB, "RGB", 0, "RGB", ""}, {COLBAND_BLEND_HSV, "HSV", 0, "HSV", ""}, @@ -913,7 +913,7 @@ static void rna_def_color_ramp(BlenderRNA *brna) RNA_def_struct_sdna(srna, "ColorBand"); RNA_def_struct_path_func(srna, "rna_ColorRamp_path"); RNA_def_struct_ui_text(srna, "Color Ramp", "Color ramp mapping a scalar value to a color"); - + prop = RNA_def_property(srna, "elements", PROP_COLLECTION, PROP_COLOR); RNA_def_property_collection_sdna(prop, NULL, "data", "tot"); RNA_def_property_struct_type(prop, "ColorRampElement"); @@ -948,7 +948,7 @@ static void rna_def_color_ramp(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Total", "Total number of elements"); RNA_def_property_update(prop, 0, "rna_ColorRamp_update"); #endif - + func = RNA_def_function(srna, "evaluate", "rna_ColorRamp_eval"); RNA_def_function_ui_description(func, "Evaluate ColorRamp"); parm = RNA_def_float(func, "position", 1.0f, 0.0f, 1.0f, "Position", "Evaluate ColorRamp at position", 0.0f, 1.0f); @@ -964,7 +964,7 @@ static void rna_def_histogram(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + static const EnumPropertyItem prop_mode_items[] = { {HISTO_MODE_LUMA, "LUMA", 0, "Luma", "Luma"}, {HISTO_MODE_RGB, "RGB", 0, "RGB", "Red Green Blue"}, @@ -977,7 +977,7 @@ static void rna_def_histogram(BlenderRNA *brna) srna = RNA_def_struct(brna, "Histogram", NULL); RNA_def_struct_ui_text(srna, "Histogram", "Statistical view of the levels of color in an image"); - + prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "mode"); RNA_def_property_enum_items(prop, prop_mode_items); @@ -1006,12 +1006,12 @@ static void rna_def_scopes(BlenderRNA *brna) srna = RNA_def_struct(brna, "Scopes", NULL); RNA_def_struct_ui_text(srna, "Scopes", "Scopes for statistical view of an image"); - + prop = RNA_def_property(srna, "use_full_resolution", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, "Scopes", "sample_full", 1); RNA_def_property_ui_text(prop, "Full Sample", "Sample every pixel of the image"); RNA_def_property_update(prop, 0, "rna_Scopes_update"); - + prop = RNA_def_property(srna, "accuracy", PROP_FLOAT, PROP_PERCENTAGE); RNA_def_property_float_sdna(prop, "Scopes", "accuracy"); RNA_def_property_range(prop, 0.0, 100.0); diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c index e01ca97dfac..a01f2afa26e 100644 --- a/source/blender/makesrna/intern/rna_constraint.c +++ b/source/blender/makesrna/intern/rna_constraint.c @@ -52,59 +52,59 @@ const EnumPropertyItem rna_enum_constraint_type_items[] = { {CONSTRAINT_TYPE_FOLLOWTRACK, "FOLLOW_TRACK", ICON_CONSTRAINT_DATA, "Follow Track", ""}, {CONSTRAINT_TYPE_OBJECTSOLVER, "OBJECT_SOLVER", ICON_CONSTRAINT_DATA, "Object Solver", ""}, {0, "", 0, N_("Transform"), ""}, - {CONSTRAINT_TYPE_LOCLIKE, "COPY_LOCATION", ICON_CONSTRAINT_DATA, "Copy Location", + {CONSTRAINT_TYPE_LOCLIKE, "COPY_LOCATION", ICON_CONSTRAINT_DATA, "Copy Location", "Copy the location of a target (with an optional offset), so that they move together"}, - {CONSTRAINT_TYPE_ROTLIKE, "COPY_ROTATION", ICON_CONSTRAINT_DATA, "Copy Rotation", + {CONSTRAINT_TYPE_ROTLIKE, "COPY_ROTATION", ICON_CONSTRAINT_DATA, "Copy Rotation", "Copy the rotation of a target (with an optional offset), so that they rotate together"}, - {CONSTRAINT_TYPE_SIZELIKE, "COPY_SCALE", ICON_CONSTRAINT_DATA, "Copy Scale", + {CONSTRAINT_TYPE_SIZELIKE, "COPY_SCALE", ICON_CONSTRAINT_DATA, "Copy Scale", "Copy the scale factors of a target (with an optional offset), so that they are scaled by the same amount"}, - {CONSTRAINT_TYPE_TRANSLIKE, "COPY_TRANSFORMS", ICON_CONSTRAINT_DATA, "Copy Transforms", + {CONSTRAINT_TYPE_TRANSLIKE, "COPY_TRANSFORMS", ICON_CONSTRAINT_DATA, "Copy Transforms", "Copy all the transformations of a target, so that they move together"}, - {CONSTRAINT_TYPE_DISTLIMIT, "LIMIT_DISTANCE", ICON_CONSTRAINT_DATA, "Limit Distance", + {CONSTRAINT_TYPE_DISTLIMIT, "LIMIT_DISTANCE", ICON_CONSTRAINT_DATA, "Limit Distance", "Restrict movements to within a certain distance of a target (at the time of constraint evaluation only)"}, - {CONSTRAINT_TYPE_LOCLIMIT, "LIMIT_LOCATION", ICON_CONSTRAINT_DATA, "Limit Location", + {CONSTRAINT_TYPE_LOCLIMIT, "LIMIT_LOCATION", ICON_CONSTRAINT_DATA, "Limit Location", "Restrict movement along each axis within given ranges"}, - {CONSTRAINT_TYPE_ROTLIMIT, "LIMIT_ROTATION", ICON_CONSTRAINT_DATA, "Limit Rotation", + {CONSTRAINT_TYPE_ROTLIMIT, "LIMIT_ROTATION", ICON_CONSTRAINT_DATA, "Limit Rotation", "Restrict rotation along each axis within given ranges"}, - {CONSTRAINT_TYPE_SIZELIMIT, "LIMIT_SCALE", ICON_CONSTRAINT_DATA, "Limit Scale", + {CONSTRAINT_TYPE_SIZELIMIT, "LIMIT_SCALE", ICON_CONSTRAINT_DATA, "Limit Scale", "Restrict scaling along each axis with given ranges"}, - {CONSTRAINT_TYPE_SAMEVOL, "MAINTAIN_VOLUME", ICON_CONSTRAINT_DATA, "Maintain Volume", + {CONSTRAINT_TYPE_SAMEVOL, "MAINTAIN_VOLUME", ICON_CONSTRAINT_DATA, "Maintain Volume", "Compensate for scaling one axis by applying suitable scaling to the other two axes"}, - {CONSTRAINT_TYPE_TRANSFORM, "TRANSFORM", ICON_CONSTRAINT_DATA, "Transformation", + {CONSTRAINT_TYPE_TRANSFORM, "TRANSFORM", ICON_CONSTRAINT_DATA, "Transformation", "Use one transform property from target to control another (or same) property on owner"}, {CONSTRAINT_TYPE_TRANSFORM_CACHE, "TRANSFORM_CACHE", ICON_CONSTRAINT_DATA, "Transform Cache", "Look up the transformation matrix from an external file"}, {0, "", 0, N_("Tracking"), ""}, - {CONSTRAINT_TYPE_CLAMPTO, "CLAMP_TO", ICON_CONSTRAINT_DATA, "Clamp To", + {CONSTRAINT_TYPE_CLAMPTO, "CLAMP_TO", ICON_CONSTRAINT_DATA, "Clamp To", "Restrict movements to lie along a curve by remapping location along curve's longest axis"}, {CONSTRAINT_TYPE_DAMPTRACK, "DAMPED_TRACK", ICON_CONSTRAINT_DATA, "Damped Track", "Point towards a target by performing the smallest rotation necessary"}, - {CONSTRAINT_TYPE_KINEMATIC, "IK", ICON_CONSTRAINT_DATA, "Inverse Kinematics", + {CONSTRAINT_TYPE_KINEMATIC, "IK", ICON_CONSTRAINT_DATA, "Inverse Kinematics", "Control a chain of bones by specifying the endpoint target (Bones only)"}, {CONSTRAINT_TYPE_LOCKTRACK, "LOCKED_TRACK", ICON_CONSTRAINT_DATA, "Locked Track", "Rotate around the specified ('locked') axis to point towards a target"}, - {CONSTRAINT_TYPE_SPLINEIK, "SPLINE_IK", ICON_CONSTRAINT_DATA, "Spline IK", + {CONSTRAINT_TYPE_SPLINEIK, "SPLINE_IK", ICON_CONSTRAINT_DATA, "Spline IK", "Align chain of bones along a curve (Bones only)"}, - {CONSTRAINT_TYPE_STRETCHTO, "STRETCH_TO", ICON_CONSTRAINT_DATA, "Stretch To", + {CONSTRAINT_TYPE_STRETCHTO, "STRETCH_TO", ICON_CONSTRAINT_DATA, "Stretch To", "Stretch along Y-Axis to point towards a target"}, {CONSTRAINT_TYPE_TRACKTO, "TRACK_TO", ICON_CONSTRAINT_DATA, "Track To", "Legacy tracking constraint prone to twisting artifacts"}, {0, "", 0, N_("Relationship"), ""}, - {CONSTRAINT_TYPE_ACTION, "ACTION", ICON_CONSTRAINT_DATA, "Action", + {CONSTRAINT_TYPE_ACTION, "ACTION", ICON_CONSTRAINT_DATA, "Action", "Use transform property of target to look up pose for owner from an Action"}, - {CONSTRAINT_TYPE_CHILDOF, "CHILD_OF", ICON_CONSTRAINT_DATA, "Child Of", + {CONSTRAINT_TYPE_CHILDOF, "CHILD_OF", ICON_CONSTRAINT_DATA, "Child Of", "Make target the 'detachable' parent of owner"}, - {CONSTRAINT_TYPE_MINMAX, "FLOOR", ICON_CONSTRAINT_DATA, "Floor", + {CONSTRAINT_TYPE_MINMAX, "FLOOR", ICON_CONSTRAINT_DATA, "Floor", "Use position (and optionally rotation) of target to define a 'wall' or 'floor' that the owner can not cross"}, - {CONSTRAINT_TYPE_FOLLOWPATH, "FOLLOW_PATH", ICON_CONSTRAINT_DATA, "Follow Path", + {CONSTRAINT_TYPE_FOLLOWPATH, "FOLLOW_PATH", ICON_CONSTRAINT_DATA, "Follow Path", "Use to animate an object/bone following a path"}, - {CONSTRAINT_TYPE_PIVOT, "PIVOT", ICON_CONSTRAINT_DATA, "Pivot", + {CONSTRAINT_TYPE_PIVOT, "PIVOT", ICON_CONSTRAINT_DATA, "Pivot", "Change pivot point for transforms (buggy)"}, /* {CONSTRAINT_TYPE_RIGIDBODYJOINT, "RIGID_BODY_JOINT", ICON_CONSTRAINT_DATA, "Rigid Body Joint", "Use to define a Rigid Body Constraint (for Game Engine use only)"}, */ - /* {CONSTRAINT_TYPE_PYTHON, "SCRIPT", ICON_CONSTRAINT_DATA, "Script", + /* {CONSTRAINT_TYPE_PYTHON, "SCRIPT", ICON_CONSTRAINT_DATA, "Script", "Custom constraint(s) written in Python (Not yet implemented)"}, */ - {CONSTRAINT_TYPE_SHRINKWRAP, "SHRINKWRAP", ICON_CONSTRAINT_DATA, "Shrinkwrap", + {CONSTRAINT_TYPE_SHRINKWRAP, "SHRINKWRAP", ICON_CONSTRAINT_DATA, "Shrinkwrap", "Restrict movements to surface of target mesh"}, {0, NULL, 0, NULL, NULL} }; @@ -229,23 +229,23 @@ static void rna_Constraint_name_set(PointerRNA *ptr, const char *value) { bConstraint *con = ptr->data; char oldname[sizeof(con->name)]; - + /* make a copy of the old name first */ BLI_strncpy(oldname, con->name, sizeof(con->name)); - + /* copy the new name into the name slot */ BLI_strncpy_utf8(con->name, value, sizeof(con->name)); - + /* make sure name is unique */ if (ptr->id.data) { Object *ob = ptr->id.data; ListBase *list = get_constraint_lb(ob, con, NULL); - + /* if we have the list, check for unique name, otherwise give up */ if (list) BKE_constraint_unique_name(con, list); } - + /* fix all the animation data which may link to this */ BKE_animdata_fix_paths_rename_all(NULL, "constraints", oldname, con->name); } @@ -291,7 +291,7 @@ static void rna_Constraint_influence_update(Main *bmain, Scene *scene, PointerRN if (ob->pose) ob->pose->flag |= (POSE_LOCKED | POSE_DO_UNLOCK); - + rna_Constraint_update(bmain, scene, ptr); } @@ -318,7 +318,7 @@ static const EnumPropertyItem *rna_Constraint_owner_space_itemf(bContext *UNUSED { Object *ob = (Object *)ptr->id.data; bConstraint *con = (bConstraint *)ptr->data; - + if (BLI_findindex(&ob->constraints, con) == -1) return owner_space_pchan_items; else /* object */ @@ -332,14 +332,14 @@ static const EnumPropertyItem *rna_Constraint_target_space_itemf(bContext *UNUSE const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); ListBase targets = {NULL, NULL}; bConstraintTarget *ct; - + if (cti && cti->get_constraint_targets) { cti->get_constraint_targets(con, &targets); - + for (ct = targets.first; ct; ct = ct->next) if (ct->tar && ct->tar->type == OB_ARMATURE) break; - + if (cti->flush_constraint_targets) cti->flush_constraint_targets(con, &targets, 1); @@ -384,7 +384,7 @@ static void rna_SplineIKConstraint_joint_bindings_get(PointerRNA *ptr, float *va { bConstraint *con = (bConstraint *)ptr->data; bSplineIKConstraint *ikData = (bSplineIKConstraint *)con->data; - + memcpy(values, ikData->points, ikData->numpoints * sizeof(float)); } @@ -392,7 +392,7 @@ static void rna_SplineIKConstraint_joint_bindings_set(PointerRNA *ptr, const flo { bConstraint *con = (bConstraint *)ptr->data; bSplineIKConstraint *ikData = (bSplineIKConstraint *)con->data; - + memcpy(ikData->points, values, ikData->numpoints * sizeof(float)); } @@ -508,12 +508,12 @@ static const EnumPropertyItem constraint_distance_items[] = { static void rna_def_constraint_headtail_common(StructRNA *srna) { PropertyRNA *prop; - + prop = RNA_def_property(srna, "head_tail", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, "bConstraint", "headtail"); RNA_def_property_ui_text(prop, "Head/Tail", "Target along length of bone: Head=0, Tail=1"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); - + prop = RNA_def_property(srna, "use_bbone_shape", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, "bConstraint", "flag", CONSTRAINT_BBONE_SHAPE); RNA_def_property_ui_text(prop, "Follow B-Bone", "Follow shape of B-Bone segments when calculating Head/Tail position"); @@ -604,13 +604,13 @@ static void rna_def_constraint_childof(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", CHILDOF_SIZEZ); RNA_def_property_ui_text(prop, "Scale Z", "Use Z Scale of Parent"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); - + prop = RNA_def_property(srna, "inverse_matrix", PROP_FLOAT, PROP_MATRIX); RNA_def_property_float_sdna(prop, NULL, "invmat"); RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x4); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_ui_text(prop, "Inverse Matrix", "Transformation matrix to apply before"); - + } static void rna_def_constraint_python(BlenderRNA *brna) @@ -1001,7 +1001,7 @@ static void rna_def_constraint_transform_like(BlenderRNA *brna) srna = RNA_def_struct(brna, "CopyTransformsConstraint", "Constraint"); RNA_def_struct_ui_text(srna, "Copy Transforms Constraint", "Copy all the transforms of the target"); - + rna_def_constraint_headtail_common(srna); RNA_def_struct_sdna_from(srna, "bTransLikeConstraint", "data"); @@ -1149,9 +1149,9 @@ static void rna_def_constraint_locked_track(BlenderRNA *brna) srna = RNA_def_struct(brna, "LockedTrackConstraint", "Constraint"); RNA_def_struct_ui_text(srna, "Locked Track Constraint", "Point toward the target along the track axis, while locking the other axis"); - + rna_def_constraint_headtail_common(srna); - + RNA_def_struct_sdna_from(srna, "bLockTrackConstraint", "data"); rna_def_constraint_target_common(srna); @@ -1206,7 +1206,7 @@ static void rna_def_constraint_follow_path(BlenderRNA *brna) RNA_def_property_range(prop, MINAFRAME, MAXFRAME); RNA_def_property_ui_text(prop, "Offset", "Offset from the position corresponding to the time frame"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); - + prop = RNA_def_property(srna, "offset_factor", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "offset_fac"); RNA_def_property_range(prop, 0.0f, 1.0f); @@ -1229,7 +1229,7 @@ static void rna_def_constraint_follow_path(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "followflag", FOLLOWPATH_FOLLOW); RNA_def_property_ui_text(prop, "Follow Curve", "Object will follow the heading and banking of the curve"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); - + prop = RNA_def_property(srna, "use_fixed_location", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "followflag", FOLLOWPATH_STATIC); RNA_def_property_ui_text(prop, "Fixed Position", @@ -1866,9 +1866,9 @@ static void rna_def_constraint_distance_limit(BlenderRNA *brna) srna = RNA_def_struct(brna, "LimitDistanceConstraint", "Constraint"); RNA_def_struct_ui_text(srna, "Limit Distance Constraint", "Limit the distance from target object"); - + rna_def_constraint_headtail_common(srna); - + RNA_def_struct_sdna_from(srna, "bDistLimitConstraint", "data"); rna_def_constraint_target_common(srna); @@ -1884,7 +1884,7 @@ static void rna_def_constraint_distance_limit(BlenderRNA *brna) RNA_def_property_enum_items(prop, constraint_distance_items); RNA_def_property_ui_text(prop, "Limit Mode", "Distances in relation to sphere of influence to allow"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); - + prop = RNA_def_property(srna, "use_transform_limit", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", LIMITDIST_TRANSFORM); RNA_def_property_ui_text(prop, "For Transform", "Transforms are affected by this constraint as well"); @@ -1895,7 +1895,7 @@ static void rna_def_constraint_shrinkwrap(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + static const EnumPropertyItem type_items[] = { {MOD_SHRINKWRAP_NEAREST_SURFACE, "NEAREST_SURFACE", 0, "Nearest Surface Point", "Shrink the location to the nearest target surface"}, @@ -1905,24 +1905,24 @@ static void rna_def_constraint_shrinkwrap(BlenderRNA *brna) "Shrink the location to the nearest target vertex"}, {0, NULL, 0, NULL, NULL} }; - + srna = RNA_def_struct(brna, "ShrinkwrapConstraint", "Constraint"); RNA_def_struct_ui_text(srna, "Shrinkwrap Constraint", "Create constraint-based shrinkwrap relationship"); RNA_def_struct_sdna_from(srna, "bShrinkwrapConstraint", "data"); - + prop = RNA_def_property(srna, "target", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "target"); /* TODO, mesh type */ RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_Mesh_object_poll"); RNA_def_property_ui_text(prop, "Target", "Target Mesh object"); RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_dependency_update"); - + prop = RNA_def_property(srna, "shrinkwrap_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "shrinkType"); RNA_def_property_enum_items(prop, type_items); RNA_def_property_ui_text(prop, "Shrinkwrap Type", "Select type of shrinkwrap algorithm for target position"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); - + prop = RNA_def_property(srna, "distance", PROP_FLOAT, PROP_DISTANCE); RNA_def_property_float_sdna(prop, NULL, "dist"); RNA_def_property_range(prop, 0.0f, FLT_MAX); @@ -1968,9 +1968,9 @@ static void rna_def_constraint_damped_track(BlenderRNA *brna) srna = RNA_def_struct(brna, "DampedTrackConstraint", "Constraint"); RNA_def_struct_ui_text(srna, "Damped Track Constraint", "Point toward target by taking the shortest rotation path"); - + rna_def_constraint_headtail_common(srna); - + RNA_def_struct_sdna_from(srna, "bDampTrackConstraint", "data"); rna_def_constraint_target_common(srna); @@ -1986,7 +1986,7 @@ static void rna_def_constraint_spline_ik(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + static const EnumPropertyItem splineik_xz_scale_mode[] = { {CONSTRAINT_SPLINEIK_XZS_NONE, "NONE", 0, "None", "Don't scale the X and Z axes (Default)"}, {CONSTRAINT_SPLINEIK_XZS_ORIGINAL, "BONE_ORIGINAL", 0, "Bone Original", @@ -2001,7 +2001,7 @@ static void rna_def_constraint_spline_ik(BlenderRNA *brna) srna = RNA_def_struct(brna, "SplineIKConstraint", "Constraint"); RNA_def_struct_ui_text(srna, "Spline IK Constraint", "Align 'n' bones along a curve"); RNA_def_struct_sdna_from(srna, "bSplineIKConstraint", "data"); - + /* target chain */ prop = RNA_def_property(srna, "target", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "tar"); @@ -2009,7 +2009,7 @@ static void rna_def_constraint_spline_ik(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Target", "Curve that controls this relationship"); RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_dependency_update"); - + prop = RNA_def_property(srna, "chain_count", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "chainlen"); /* TODO: this should really check the max length of the chain the constraint is attached to */ @@ -2017,7 +2017,7 @@ static void rna_def_constraint_spline_ik(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Chain Length", "How many bones are included in the chain"); /* XXX: this update goes wrong... needs extra flush? */ RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_dependency_update"); - + /* direct access to bindings */ /* NOTE: only to be used by experienced users */ prop = RNA_def_property(srna, "joint_bindings", PROP_FLOAT, PROP_FACTOR); @@ -2030,31 +2030,31 @@ static void rna_def_constraint_spline_ik(BlenderRNA *brna) "(EXPERIENCED USERS ONLY) The relative positions of the joints along the chain, " "as percentages"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); - + /* settings */ prop = RNA_def_property(srna, "use_chain_offset", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", CONSTRAINT_SPLINEIK_NO_ROOT); RNA_def_property_ui_text(prop, "Chain Offset", "Offset the entire chain relative to the root joint"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); - + prop = RNA_def_property(srna, "use_even_divisions", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", CONSTRAINT_SPLINEIK_EVENSPLITS); RNA_def_property_ui_text(prop, "Even Divisions", "Ignore the relative lengths of the bones when fitting to the curve"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); - + prop = RNA_def_property(srna, "use_y_stretch", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", CONSTRAINT_SPLINEIK_SCALE_LIMITED); RNA_def_property_ui_text(prop, "Y Stretch", "Stretch the Y axis of the bones to fit the curve"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); - + prop = RNA_def_property(srna, "use_curve_radius", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", CONSTRAINT_SPLINEIK_NO_CURVERAD); RNA_def_property_ui_text(prop, "Use Curve Radius", "Average radius of the endpoints is used to tweak the X and Z Scaling of the bones, " "on top of XZ Scale mode"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); - + /* xz scaling mode */ prop = RNA_def_property(srna, "xz_scale_mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "xzScaleMode"); @@ -2062,33 +2062,33 @@ static void rna_def_constraint_spline_ik(BlenderRNA *brna) RNA_def_property_ui_text(prop, "XZ Scale Mode", "Method used for determining the scaling of the X and Z axes of the bones"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); - + /* volume presevation for "volumetric" scale mode */ prop = RNA_def_property(srna, "bulge", PROP_FLOAT, PROP_NONE); RNA_def_property_range(prop, 0.0, 100.f); RNA_def_property_ui_text(prop, "Volume Variation", "Factor between volume variation and stretching"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); - + prop = RNA_def_property(srna, "use_bulge_min", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", CONSTRAINT_SPLINEIK_USE_BULGE_MIN); RNA_def_property_ui_text(prop, "Use Volume Variation Minimum", "Use lower limit for volume variation"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); - + prop = RNA_def_property(srna, "use_bulge_max", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", CONSTRAINT_SPLINEIK_USE_BULGE_MAX); RNA_def_property_ui_text(prop, "Use Volume Variation Maximum", "Use upper limit for volume variation"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); - + prop = RNA_def_property(srna, "bulge_min", PROP_FLOAT, PROP_NONE); RNA_def_property_range(prop, 0.0, 1.0f); RNA_def_property_ui_text(prop, "Volume Variation Minimum", "Minimum volume stretching factor"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); - + prop = RNA_def_property(srna, "bulge_max", PROP_FLOAT, PROP_NONE); RNA_def_property_range(prop, 1.0, 100.0f); RNA_def_property_ui_text(prop, "Volume Variation Maximum", "Maximum volume stretching factor"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); - + prop = RNA_def_property(srna, "bulge_smooth", PROP_FLOAT, PROP_FACTOR); RNA_def_property_range(prop, 0.0, 1.0f); RNA_def_property_ui_text(prop, "Volume Variation Smoothness", "Strength of volume stretching clamping"); @@ -2116,37 +2116,37 @@ static void rna_def_constraint_pivot(BlenderRNA *brna) srna = RNA_def_struct(brna, "PivotConstraint", "Constraint"); RNA_def_struct_ui_text(srna, "Pivot Constraint", "Rotate around a different point"); - + rna_def_constraint_headtail_common(srna); - + RNA_def_struct_sdna_from(srna, "bPivotConstraint", "data"); - + /* target-defined pivot */ prop = RNA_def_property(srna, "target", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "tar"); RNA_def_property_ui_text(prop, "Target", "Target Object, defining the position of the pivot when defined"); RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_dependency_update"); - + prop = RNA_def_property(srna, "subtarget", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "subtarget"); RNA_def_property_ui_text(prop, "Sub-Target", ""); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_dependency_update"); - + /* pivot offset */ prop = RNA_def_property(srna, "use_relative_location", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", PIVOTCON_FLAG_OFFSET_ABS); RNA_def_property_ui_text(prop, "Use Relative Offset", "Offset will be an absolute point in space instead of relative to the target"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); - + prop = RNA_def_property(srna, "offset", PROP_FLOAT, PROP_XYZ); RNA_def_property_float_sdna(prop, NULL, "offset"); RNA_def_property_ui_text(prop, "Offset", "Offset of pivot from target (when set), or from owner's location " "(when Fixed Position is off), or the absolute pivot point"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); - + /* rotation-based activation */ prop = RNA_def_property(srna, "rotation_range", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "rotAxis"); @@ -2324,21 +2324,21 @@ void RNA_def_constraint(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + /* data */ srna = RNA_def_struct(brna, "Constraint", NULL); RNA_def_struct_ui_text(srna, "Constraint", "Constraint modifying the transformation of objects and bones"); RNA_def_struct_refine_func(srna, "rna_ConstraintType_refine"); RNA_def_struct_path_func(srna, "rna_Constraint_path"); RNA_def_struct_sdna(srna, "bConstraint"); - + /* strings */ prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); RNA_def_property_string_funcs(prop, NULL, NULL, "rna_Constraint_name_set"); RNA_def_property_ui_text(prop, "Name", "Constraint name"); RNA_def_struct_name_property(srna, prop); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT | NA_RENAME, NULL); - + /* enums */ prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_EDITABLE); @@ -2363,7 +2363,7 @@ void RNA_def_constraint(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", CONSTRAINT_OFF); RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC); RNA_def_property_ui_text(prop, "Disable", "Enable/Disable Constraint"); - + prop = RNA_def_property(srna, "show_expanded", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", CONSTRAINT_EXPAND); RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC); @@ -2375,17 +2375,17 @@ void RNA_def_constraint(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", CONSTRAINT_DISABLE); RNA_def_property_ui_text(prop, "Valid", "Constraint has valid settings and can be evaluated"); - + /* TODO: setting this to true must ensure that all others in stack are turned off too... */ prop = RNA_def_property(srna, "active", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", CONSTRAINT_ACTIVE); RNA_def_property_ui_text(prop, "Active", "Constraint is the one being edited "); - + prop = RNA_def_property(srna, "is_proxy_local", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", CONSTRAINT_PROXY_LOCAL); RNA_def_property_ui_text(prop, "Proxy Local", "Constraint was added in this proxy instance (i.e. did not belong to source Armature)"); - + /* values */ prop = RNA_def_property(srna, "influence", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "enforce"); diff --git a/source/blender/makesrna/intern/rna_curve.c b/source/blender/makesrna/intern/rna_curve.c index 894af338c12..0681a449aa2 100644 --- a/source/blender/makesrna/intern/rna_curve.c +++ b/source/blender/makesrna/intern/rna_curve.c @@ -55,7 +55,7 @@ static const EnumPropertyItem beztriple_handle_type_items[] = { {0, NULL, 0, NULL, NULL} }; #endif - + const EnumPropertyItem rna_enum_keyframe_handle_type_items[] = { {HD_FREE, "FREE", 0, "Free", ""}, {HD_VECT, "VECTOR", 0, "Vector", ""}, @@ -71,7 +71,7 @@ const EnumPropertyItem rna_enum_beztriple_interpolation_mode_items[] = { {BEZT_IPO_CONST, "CONSTANT", ICON_IPO_CONSTANT, "Constant", "No interpolation, value of A gets held until B is encountered"}, {BEZT_IPO_LIN, "LINEAR", ICON_IPO_LINEAR, "Linear", "Straight-line interpolation between A and B (i.e. no ease in/out)"}, {BEZT_IPO_BEZ, "BEZIER", ICON_IPO_BEZIER, "Bezier", "Smooth interpolation between A and B, with some control over curve shape"}, - + /* easing */ {0, "", 0, N_("Easing (by strength)"), "Predefined inertial transitions, useful for motion graphics (from least to most ''dramatic'')"}, {BEZT_IPO_SINE, "SINE", ICON_IPO_SINE, "Sinusoidal", "Sinusoidal easing (weakest, almost linear but with a slight curvature)"}, @@ -81,12 +81,12 @@ const EnumPropertyItem rna_enum_beztriple_interpolation_mode_items[] = { {BEZT_IPO_QUINT, "QUINT", ICON_IPO_QUINT, "Quintic", "Quintic easing"}, {BEZT_IPO_EXPO, "EXPO", ICON_IPO_EXPO, "Exponential", "Exponential easing (dramatic)"}, {BEZT_IPO_CIRC, "CIRC", ICON_IPO_CIRC, "Circular", "Circular easing (strongest and most dynamic)"}, - + {0, "", 0, N_("Dynamic Effects"), "Simple physics-inspired easing effects"}, {BEZT_IPO_BACK, "BACK", ICON_IPO_BACK, "Back", "Cubic easing with overshoot and settle"}, {BEZT_IPO_BOUNCE, "BOUNCE", ICON_IPO_BOUNCE, "Bounce", "Exponentially decaying parabolic bounce, like when objects collide"}, {BEZT_IPO_ELASTIC, "ELASTIC", ICON_IPO_ELASTIC, "Elastic", "Exponentially decaying sine wave, like an elastic band"}, - + {0, NULL, 0, NULL, NULL} }; @@ -159,7 +159,7 @@ static Nurb *curve_nurb_from_point(Curve *cu, const void *point, int *nu_index, if (nu_index) { *nu_index = i; } - + if (pt_index) { if (nu->type == CU_BEZIER) *pt_index = (int)((BezTriple *)point - nu->bezt); else *pt_index = (int)((BPoint *)point - nu->bp); @@ -173,7 +173,7 @@ static StructRNA *rna_Curve_refine(PointerRNA *ptr) { Curve *cu = (Curve *)ptr->data; short obtype = BKE_curve_type_get(cu); - + if (obtype == OB_FONT) return &RNA_TextCurve; else if (obtype == OB_SURF) return &RNA_SurfaceCurve; else return &RNA_Curve; @@ -218,7 +218,7 @@ static void rna_BezTriple_ctrlpoint_set(PointerRNA *ptr, const float *values) static void rna_Curve_texspace_set(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { Curve *cu = (Curve *)ptr->data; - + if (cu->texflag & CU_AUTOSPACE) BKE_curve_texspace_calc(cu); } @@ -232,34 +232,34 @@ static int rna_Curve_texspace_editable(PointerRNA *ptr, const char **UNUSED(r_in static void rna_Curve_texspace_loc_get(PointerRNA *ptr, float *values) { Curve *cu = (Curve *)ptr->data; - + if (!cu->bb) BKE_curve_texspace_calc(cu); - + copy_v3_v3(values, cu->loc); } static void rna_Curve_texspace_loc_set(PointerRNA *ptr, const float *values) { Curve *cu = (Curve *)ptr->data; - + copy_v3_v3(cu->loc, values); } static void rna_Curve_texspace_size_get(PointerRNA *ptr, float *values) { Curve *cu = (Curve *)ptr->data; - + if (!cu->bb) BKE_curve_texspace_calc(cu); - + copy_v3_v3(values, cu->size); } static void rna_Curve_texspace_size_set(PointerRNA *ptr, const float *values) { Curve *cu = (Curve *)ptr->data; - + copy_v3_v3(cu->size, values); } @@ -448,7 +448,7 @@ static void rna_Curve_resolution_u_update_data(Main *bmain, Scene *scene, Pointe nu->resolu = cu->resolu; nu = nu->next; } - + rna_Curve_update_data(bmain, scene, ptr); } @@ -900,7 +900,7 @@ static void rna_def_beztriple(BlenderRNA *brna) static void rna_def_path(BlenderRNA *UNUSED(brna), StructRNA *srna) { PropertyRNA *prop; - + /* number values */ prop = RNA_def_property(srna, "path_duration", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "pathlen"); @@ -909,18 +909,18 @@ static void rna_def_path(BlenderRNA *UNUSED(brna), StructRNA *srna) "The number of frames that are needed to traverse the path, " "defining the maximum value for the 'Evaluation Time' setting"); RNA_def_property_update(prop, 0, "rna_Curve_update_data"); - + /* flags */ prop = RNA_def_property(srna, "use_path", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", CU_PATH); RNA_def_property_ui_text(prop, "Path", "Enable the curve to become a translation path"); RNA_def_property_update(prop, 0, "rna_Curve_update_data"); - + prop = RNA_def_property(srna, "use_path_follow", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", CU_FOLLOW); RNA_def_property_ui_text(prop, "Follow", "Make curve path children to rotate along the path"); RNA_def_property_update(prop, 0, "rna_Curve_update_data"); - + prop = RNA_def_property(srna, "use_stretch", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", CU_STRETCH); RNA_def_property_ui_text(prop, "Stretch", "Option for curve-deform: " @@ -943,7 +943,7 @@ static void rna_def_path(BlenderRNA *UNUSED(brna), StructRNA *srna) static void rna_def_nurbs(BlenderRNA *UNUSED(brna), StructRNA *srna) { PropertyRNA *prop; - + /* flags */ prop = RNA_def_property(srna, "use_uv_as_generated", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", CU_UV_ORCO); @@ -992,7 +992,7 @@ static void rna_def_font(BlenderRNA *UNUSED(brna), StructRNA *srna) RNA_def_property_ui_range(prop, 0.01, 10, 1, 3); RNA_def_property_ui_text(prop, "Font size", ""); RNA_def_property_update(prop, 0, "rna_Curve_update_data"); - + prop = RNA_def_property(srna, "small_caps_scale", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "smallcaps_scale"); RNA_def_property_ui_range(prop, 0, 1.0, 1, 2); @@ -1004,51 +1004,51 @@ static void rna_def_font(BlenderRNA *UNUSED(brna), StructRNA *srna) RNA_def_property_range(prop, 0.0f, 10.0f); RNA_def_property_ui_text(prop, "Distance between lines of text", ""); RNA_def_property_update(prop, 0, "rna_Curve_update_data"); - + prop = RNA_def_property(srna, "space_word", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "wordspace"); RNA_def_property_range(prop, 0.0f, 10.0f); RNA_def_property_ui_text(prop, "Spacing between words", ""); RNA_def_property_update(prop, 0, "rna_Curve_update_data"); - + prop = RNA_def_property(srna, "space_character", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "spacing"); RNA_def_property_range(prop, 0.0f, 10.0f); RNA_def_property_ui_text(prop, "Global spacing between characters", ""); RNA_def_property_update(prop, 0, "rna_Curve_update_data"); - + prop = RNA_def_property(srna, "shear", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "shear"); RNA_def_property_range(prop, -1.0f, 1.0f); RNA_def_property_ui_text(prop, "Shear", "Italic angle of the characters"); RNA_def_property_update(prop, 0, "rna_Curve_update_data"); - + prop = RNA_def_property(srna, "offset_x", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "xof"); RNA_def_property_range(prop, -FLT_MAX, FLT_MAX); RNA_def_property_ui_range(prop, -50.0f, 50.0f, 10, 3); RNA_def_property_ui_text(prop, "X Offset", "Horizontal offset from the object origin"); RNA_def_property_update(prop, 0, "rna_Curve_update_data"); - + prop = RNA_def_property(srna, "offset_y", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "yof"); RNA_def_property_range(prop, -FLT_MAX, FLT_MAX); RNA_def_property_ui_range(prop, -50.0f, 50.0f, 10, 3); RNA_def_property_ui_text(prop, "Y Offset", "Vertical offset from the object origin"); RNA_def_property_update(prop, 0, "rna_Curve_update_data"); - + prop = RNA_def_property(srna, "underline_position", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "ulpos"); RNA_def_property_range(prop, -0.2f, 0.8f); RNA_def_property_ui_text(prop, "Underline Position", "Vertical position of underline"); RNA_def_property_update(prop, 0, "rna_Curve_update_data"); - + prop = RNA_def_property(srna, "underline_height", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "ulheight"); RNA_def_property_range(prop, 0.0f, 0.8f); RNA_def_property_ui_text(prop, "Underline Thickness", ""); RNA_def_property_update(prop, 0, "rna_Curve_update_data"); - + prop = RNA_def_property(srna, "text_boxes", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "tb", "totbox"); RNA_def_property_struct_type(prop, "TextBox"); @@ -1058,7 +1058,7 @@ static void rna_def_font(BlenderRNA *UNUSED(brna), StructRNA *srna) RNA_def_property_int_sdna(prop, NULL, "actbox"); RNA_def_property_ui_text(prop, "The active text box", ""); RNA_def_property_int_funcs(prop, NULL, NULL, "rna_Curve_active_textbox_index_range"); - + /* strings */ prop = RNA_def_property(srna, "family", PROP_STRING, PROP_NONE); RNA_def_property_string_maxlength(prop, MAX_ID_NAME - 2); @@ -1067,7 +1067,7 @@ static void rna_def_font(BlenderRNA *UNUSED(brna), StructRNA *srna) "followed by the character they represent, eg. 'family-a', 'family-b', etc, " "set this setting to 'family-', and turn on Vertex Duplication)"); RNA_def_property_update(prop, 0, "rna_Curve_update_data"); - + prop = RNA_def_property(srna, "body", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "str"); RNA_def_property_ui_text(prop, "Body Text", "Content of this text object"); @@ -1079,7 +1079,7 @@ static void rna_def_font(BlenderRNA *UNUSED(brna), StructRNA *srna) RNA_def_property_collection_sdna(prop, NULL, "strinfo", "len_wchar"); RNA_def_property_struct_type(prop, "TextCharacterFormat"); RNA_def_property_ui_text(prop, "Character Info", "Stores the style of each character"); - + /* pointers */ prop = RNA_def_property(srna, "follow_curve", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "textoncurve"); @@ -1087,7 +1087,7 @@ static void rna_def_font(BlenderRNA *UNUSED(brna), StructRNA *srna) RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Text on Curve", "Curve deforming text object"); RNA_def_property_update(prop, 0, "rna_Curve_update_deps"); - + prop = RNA_def_property(srna, "font", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "vfont"); RNA_def_property_ui_text(prop, "Font", ""); @@ -1128,10 +1128,10 @@ static void rna_def_textbox(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + srna = RNA_def_struct(brna, "TextBox", NULL); RNA_def_struct_ui_text(srna, "Text Box", "Text bounding box for layout"); - + /* number values */ prop = RNA_def_property(srna, "x", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "x"); @@ -1139,7 +1139,7 @@ static void rna_def_textbox(BlenderRNA *brna) RNA_def_property_ui_range(prop, -50.0f, 50.0f, 10, 3); RNA_def_property_ui_text(prop, "Textbox X Offset", ""); RNA_def_property_update(prop, 0, "rna_Curve_update_data"); - + prop = RNA_def_property(srna, "y", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "y"); RNA_def_property_range(prop, -FLT_MAX, FLT_MAX); @@ -1160,7 +1160,7 @@ static void rna_def_textbox(BlenderRNA *brna) RNA_def_property_ui_range(prop, 0.0f, 50.0f, 10, 3); RNA_def_property_ui_text(prop, "Textbox Height", ""); RNA_def_property_update(prop, 0, "rna_Curve_update_data"); - + RNA_def_struct_path_func(srna, "rna_TextBox_path"); } @@ -1168,27 +1168,27 @@ static void rna_def_charinfo(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + srna = RNA_def_struct(brna, "TextCharacterFormat", NULL); RNA_def_struct_sdna(srna, "CharInfo"); RNA_def_struct_ui_text(srna, "Text Character Format", "Text character formatting settings"); - + /* flags */ prop = RNA_def_property(srna, "use_bold", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", CU_CHINFO_BOLD); RNA_def_property_ui_text(prop, "Bold", ""); RNA_def_property_update(prop, 0, "rna_Curve_update_data"); - + prop = RNA_def_property(srna, "use_italic", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", CU_CHINFO_ITALIC); RNA_def_property_ui_text(prop, "Italic", ""); RNA_def_property_update(prop, 0, "rna_Curve_update_data"); - + prop = RNA_def_property(srna, "use_underline", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", CU_CHINFO_UNDERLINE); RNA_def_property_ui_text(prop, "Underline", ""); RNA_def_property_update(prop, 0, "rna_Curve_update_data"); - + /* probably there is no reason to expose this */ #if 0 prop = RNA_def_property(srna, "wrap", PROP_BOOLEAN, PROP_NONE); @@ -1212,7 +1212,7 @@ static void rna_def_charinfo(BlenderRNA *brna) static void rna_def_surface(BlenderRNA *brna) { StructRNA *srna; - + srna = RNA_def_struct(brna, "SurfaceCurve", "Curve"); RNA_def_struct_sdna(srna, "Curve"); RNA_def_struct_ui_text(srna, "Surface Curve", "Curve data-block used for storing surfaces"); @@ -1224,7 +1224,7 @@ static void rna_def_surface(BlenderRNA *brna) static void rna_def_text(BlenderRNA *brna) { StructRNA *srna; - + srna = RNA_def_struct(brna, "TextCurve", "Curve"); RNA_def_struct_sdna(srna, "Curve"); RNA_def_struct_ui_text(srna, "Text Curve", "Curve data-block used for storing text"); @@ -1335,7 +1335,7 @@ static void rna_def_curve(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + static const EnumPropertyItem curve_twist_mode_items[] = { {CU_TWIST_Z_UP, "Z_UP", 0, "Z-Up", "Use Z-Up axis to calculate the curve twist at each point"}, {CU_TWIST_MINIMUM, "MINIMUM", 0, "Minimum", "Use the least twist over the entire curve"}, @@ -1392,7 +1392,7 @@ static void rna_def_curve(BlenderRNA *brna) RNA_def_property_update(prop, NC_GEOM | ND_DATA, NULL); rna_def_path(brna, srna); - + /* Number values */ prop = RNA_def_property(srna, "bevel_resolution", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "bevresol"); @@ -1401,63 +1401,63 @@ static void rna_def_curve(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Bevel Resolution", "Bevel resolution when depth is non-zero and no specific bevel object has been defined"); RNA_def_property_update(prop, 0, "rna_Curve_update_data"); - + prop = RNA_def_property(srna, "offset", PROP_FLOAT, PROP_NONE | PROP_UNIT_LENGTH); RNA_def_property_float_sdna(prop, NULL, "width"); RNA_def_property_ui_range(prop, -1.0, 1.0, 0.1, 3); RNA_def_property_float_funcs(prop, "rna_Curve_offset_get", "rna_Curve_offset_set", NULL); RNA_def_property_ui_text(prop, "Offset", "Offset the curve to adjust the width of a text"); RNA_def_property_update(prop, 0, "rna_Curve_update_data"); - + prop = RNA_def_property(srna, "extrude", PROP_FLOAT, PROP_NONE | PROP_UNIT_LENGTH); RNA_def_property_float_sdna(prop, NULL, "ext1"); RNA_def_property_ui_range(prop, 0, 100.0, 0.1, 3); RNA_def_property_range(prop, 0.0, FLT_MAX); RNA_def_property_ui_text(prop, "Extrude", "Amount of curve extrusion when not using a bevel object"); RNA_def_property_update(prop, 0, "rna_Curve_update_data"); - + prop = RNA_def_property(srna, "bevel_depth", PROP_FLOAT, PROP_NONE | PROP_UNIT_LENGTH); RNA_def_property_float_sdna(prop, NULL, "ext2"); RNA_def_property_ui_range(prop, 0, 100.0, 0.1, 3); RNA_def_property_ui_text(prop, "Bevel Depth", "Bevel depth when not using a bevel object"); RNA_def_property_update(prop, 0, "rna_Curve_update_data"); - + prop = RNA_def_property(srna, "resolution_u", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "resolu"); RNA_def_property_range(prop, 1, 1024); RNA_def_property_ui_range(prop, 1, 64, 1, -1); RNA_def_property_ui_text(prop, "Resolution U", "Surface resolution in U direction"); RNA_def_property_update(prop, 0, "rna_Curve_resolution_u_update_data"); - + prop = RNA_def_property(srna, "resolution_v", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "resolv"); RNA_def_property_ui_range(prop, 1, 64, 1, -1); RNA_def_property_range(prop, 1, 1024); RNA_def_property_ui_text(prop, "Resolution V", "Surface resolution in V direction"); RNA_def_property_update(prop, 0, "rna_Curve_resolution_v_update_data"); - + prop = RNA_def_property(srna, "render_resolution_u", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "resolu_ren"); RNA_def_property_range(prop, 0, 1024); RNA_def_property_ui_range(prop, 0, 64, 1, -1); RNA_def_property_ui_text(prop, "Render Resolution U", "Surface resolution in U direction used while rendering (zero uses preview resolution)"); - + prop = RNA_def_property(srna, "render_resolution_v", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "resolv_ren"); RNA_def_property_ui_range(prop, 0, 64, 1, -1); RNA_def_property_range(prop, 0, 1024); RNA_def_property_ui_text(prop, "Render Resolution V", "Surface resolution in V direction used while rendering (zero uses preview resolution)"); - - + + prop = RNA_def_property(srna, "eval_time", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "ctime"); RNA_def_property_ui_text(prop, "Evaluation Time", "Parametric position along the length of the curve that Objects 'following' it should be " "at (position is evaluated by dividing by the 'Path Length' value)"); RNA_def_property_update(prop, 0, "rna_Curve_update_data"); - + /* pointers */ prop = RNA_def_property(srna, "bevel_object", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "Object"); @@ -1485,7 +1485,7 @@ static void rna_def_curve(BlenderRNA *brna) RNA_def_property_enum_funcs(prop, NULL, "rna_Curve_dimension_set", NULL); RNA_def_property_ui_text(prop, "Dimensions", "Select 2D or 3D curve type"); RNA_def_property_update(prop, 0, "rna_Curve_update_data"); - + prop = RNA_def_property(srna, "fill_mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag"); RNA_def_property_enum_items(prop, curve3d_fill_mode_items); @@ -1547,7 +1547,7 @@ static void rna_def_curve(BlenderRNA *brna) RNA_def_property_editable_func(prop, "rna_Curve_texspace_editable"); RNA_def_property_float_funcs(prop, "rna_Curve_texspace_loc_get", "rna_Curve_texspace_loc_set", NULL); RNA_def_property_update(prop, 0, "rna_Curve_update_data"); - + prop = RNA_def_property(srna, "texspace_size", PROP_FLOAT, PROP_XYZ); RNA_def_property_array(prop, 3); RNA_def_property_flag(prop, PROP_PROPORTIONAL); @@ -1555,7 +1555,7 @@ static void rna_def_curve(BlenderRNA *brna) RNA_def_property_editable_func(prop, "rna_Curve_texspace_editable"); RNA_def_property_float_funcs(prop, "rna_Curve_texspace_size_get", "rna_Curve_texspace_size_set", NULL); RNA_def_property_update(prop, 0, "rna_Curve_update_data"); - + /* not supported yet */ #if 0 prop = RNA_def_property(srna, "texspace_rot", PROP_FLOAT, PROP_EULER); @@ -1564,12 +1564,12 @@ static void rna_def_curve(BlenderRNA *brna) RNA_def_property_editable_func(prop, texspace_editable); RNA_def_property_update(prop, 0, "rna_Curve_update_data"); #endif - + prop = RNA_def_property(srna, "use_uv_as_generated", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", CU_UV_ORCO); RNA_def_property_ui_text(prop, "Use UV for mapping", "Uses the UV values as Generated textured coordinates"); RNA_def_property_update(prop, 0, "rna_Curve_update_data"); - + /* materials */ prop = RNA_def_property(srna, "materials", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "mat", "totcol"); @@ -1633,7 +1633,7 @@ static void rna_def_curve_nurb(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Bezier Points", "Collection of points for Bezier curves only"); rna_def_curve_spline_bezpoints(brna, prop); - + prop = RNA_def_property(srna, "tilt_interpolation", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "tilt_interp"); RNA_def_property_enum_items(prop, spline_interpolation_items); @@ -1752,7 +1752,7 @@ static void rna_def_curve_nurb(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Material Index", ""); RNA_def_property_int_funcs(prop, NULL, NULL, "rna_Curve_material_index_range"); RNA_def_property_update(prop, 0, "rna_Curve_update_data"); - + prop = RNA_def_property(srna, "character_index", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "charidx"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* editing this needs knot recalc*/ diff --git a/source/blender/makesrna/intern/rna_define.c b/source/blender/makesrna/intern/rna_define.c index b8387263932..5b91a3e43d2 100644 --- a/source/blender/makesrna/intern/rna_define.c +++ b/source/blender/makesrna/intern/rna_define.c @@ -128,12 +128,12 @@ void rna_freelinkN(ListBase *listbase, void *vlink) void rna_freelistN(ListBase *listbase) { Link *link, *next; - + for (link = listbase->first; link; link = next) { next = link->next; MEM_freeN(link); } - + listbase->first = listbase->last = NULL; } @@ -335,13 +335,13 @@ typedef struct DNAStructMember { static int rna_member_cmp(const char *name, const char *oname) { int a = 0; - + /* compare without pointer or array part */ while (name[0] == '*') name++; while (oname[0] == '*') oname++; - + while (1) { if (name[a] == '[' && oname[a] == 0) return 1; if (name[a] == '[' && oname[a] == '[') return 1; @@ -419,7 +419,7 @@ static int rna_find_sdna_member(SDNA *sdna, const char *structname, const char * static int rna_validate_identifier(const char *identifier, char *error, bool property) { int a = 0; - + /* list is from... * ", ".join(['"%s"' % kw for kw in __import__("keyword").kwlist if kw not in {"False", "None", "True"}]) */ @@ -431,13 +431,13 @@ static int rna_validate_identifier(const char *identifier, char *error, bool pro "is", "lambda", "nonlocal", "not", "or", "pass", "raise", "return", "try", "while", "with", "yield", NULL }; - - + + if (!isalpha(identifier[0])) { strcpy(error, "first character failed isalpha() check"); return 0; } - + for (a = 0; identifier[a]; a++) { if (DefRNA.preprocess && property) { if (isalpha(identifier[a]) && isupper(identifier[a])) { @@ -445,7 +445,7 @@ static int rna_validate_identifier(const char *identifier, char *error, bool pro return 0; } } - + if (identifier[a] == '_') { continue; } @@ -460,7 +460,7 @@ static int rna_validate_identifier(const char *identifier, char *error, bool pro return 0; } } - + for (a = 0; kwlist[a]; a++) { if (STREQ(identifier, kwlist[a])) { strcpy(error, "this keyword is reserved by python"); @@ -482,14 +482,14 @@ static int rna_validate_identifier(const char *identifier, char *error, bool pro } } } - + return 1; } void RNA_identifier_sanitize(char *identifier, int property) { int a = 0; - + /* list from http://docs.python.org/py3k/reference/lexical_analysis.html#keywords */ static const char *kwlist[] = { /* "False", "None", "True", */ @@ -499,13 +499,13 @@ void RNA_identifier_sanitize(char *identifier, int property) "is", "lambda", "nonlocal", "not", "or", "pass", "raise", "return", "try", "while", "with", "yield", NULL }; - - + + if (!isalpha(identifier[0])) { /* first character failed isalpha() check */ identifier[0] = '_'; } - + for (a = 0; identifier[a]; a++) { if (DefRNA.preprocess && property) { if (isalpha(identifier[a]) && isupper(identifier[a])) { @@ -513,7 +513,7 @@ void RNA_identifier_sanitize(char *identifier, int property) identifier[a] = tolower(identifier[a]); } } - + if (identifier[a] == '_') { continue; } @@ -528,7 +528,7 @@ void RNA_identifier_sanitize(char *identifier, int property) identifier[a] = '_'; } } - + for (a = 0; kwlist[a]; a++) { if (STREQ(identifier, kwlist[a])) { /* this keyword is reserved by python. @@ -703,7 +703,7 @@ void RNA_free(BlenderRNA *brna) } rna_freelistN(&brna->structs); - + MEM_freeN(brna); } else { @@ -1078,13 +1078,13 @@ PropertyRNA *RNA_def_property(StructOrFunctionRNA *cont_, const char *identifier if (DefRNA.preprocess) { char error[512]; - + if (rna_validate_identifier(identifier, error, true) == 0) { fprintf(stderr, "%s: property identifier \"%s.%s\" - %s\n", __func__, CONTAINER_RNA_ID(cont), identifier, error); DefRNA.error = 1; } - + dcont = rna_find_container_def(cont); /* XXX - toto, detect supertype collisions */ @@ -1198,7 +1198,7 @@ PropertyRNA *RNA_def_property(StructOrFunctionRNA *cont_, const char *identifier if (type != PROP_COLLECTION && type != PROP_POINTER) { prop->flag = PROP_EDITABLE; - + if (type != PROP_STRING) { #ifdef RNA_RUNTIME prop->flag |= PROP_ANIMATABLE; @@ -1382,7 +1382,7 @@ void RNA_def_property_multi_array(PropertyRNA *prop, int dimension, const int le { StructRNA *srna = DefRNA.laststruct; int i; - + if (dimension < 1 || dimension > RNA_MAX_ARRAY_DIMENSION) { fprintf(stderr, "%s: \"%s.%s\", array dimension must be between 1 and %d.\n", __func__, srna->identifier, prop->identifier, RNA_MAX_ARRAY_DIMENSION); @@ -1894,7 +1894,7 @@ static PropertyDefRNA *rna_def_property_sdna(PropertyRNA *prop, const char *stru prop->arraydimension = 0; prop->totarraylength = 0; } - + dp->dnastructname = structname; dp->dnastructfromname = ds->dnafromname; dp->dnastructfromprop = ds->dnafromprop; @@ -1910,7 +1910,7 @@ void RNA_def_property_boolean_sdna(PropertyRNA *prop, const char *structname, co { PropertyDefRNA *dp; StructRNA *srna = DefRNA.laststruct; - + if (!DefRNA.preprocess) { fprintf(stderr, "%s: only during preprocessing.\n", __func__); return; @@ -1956,7 +1956,7 @@ void RNA_def_property_int_sdna(PropertyRNA *prop, const char *structname, const PropertyDefRNA *dp; IntPropertyRNA *iprop = (IntPropertyRNA *)prop; StructRNA *srna = DefRNA.laststruct; - + if (!DefRNA.preprocess) { fprintf(stderr, "%s: only during preprocessing.\n", __func__); return; @@ -2046,7 +2046,7 @@ void RNA_def_property_enum_sdna(PropertyRNA *prop, const char *structname, const { /* PropertyDefRNA *dp; */ StructRNA *srna = DefRNA.laststruct; - + if (!DefRNA.preprocess) { fprintf(stderr, "%s: only during preprocessing.\n", __func__); return; @@ -2114,7 +2114,7 @@ void RNA_def_property_pointer_sdna(PropertyRNA *prop, const char *structname, co { /* PropertyDefRNA *dp; */ StructRNA *srna = DefRNA.laststruct; - + if (!DefRNA.preprocess) { fprintf(stderr, "%s: only during preprocessing.\n", __func__); return; @@ -2670,7 +2670,7 @@ PropertyRNA *RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, { ContainerRNA *cont = cont_; PropertyRNA *prop; - + prop = RNA_def_property(cont, identifier, PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_default(prop, default_value); RNA_def_property_ui_text(prop, ui_name, ui_description); @@ -2683,7 +2683,7 @@ PropertyRNA *RNA_def_boolean_array(StructOrFunctionRNA *cont_, const char *ident { ContainerRNA *cont = cont_; PropertyRNA *prop; - + prop = RNA_def_property(cont, identifier, PROP_BOOLEAN, PROP_NONE); if (len != 0) RNA_def_property_array(prop, len); if (default_value) RNA_def_property_boolean_array_default(prop, default_value); @@ -2697,7 +2697,7 @@ PropertyRNA *RNA_def_boolean_layer(StructOrFunctionRNA *cont_, const char *ident { ContainerRNA *cont = cont_; PropertyRNA *prop; - + prop = RNA_def_property(cont, identifier, PROP_BOOLEAN, PROP_LAYER); if (len != 0) RNA_def_property_array(prop, len); if (default_value) RNA_def_property_boolean_array_default(prop, default_value); @@ -2711,7 +2711,7 @@ PropertyRNA *RNA_def_boolean_layer_member(StructOrFunctionRNA *cont_, const char { ContainerRNA *cont = cont_; PropertyRNA *prop; - + prop = RNA_def_property(cont, identifier, PROP_BOOLEAN, PROP_LAYER_MEMBER); if (len != 0) RNA_def_property_array(prop, len); if (default_value) RNA_def_property_boolean_array_default(prop, default_value); @@ -2725,7 +2725,7 @@ PropertyRNA *RNA_def_boolean_vector(StructOrFunctionRNA *cont_, const char *iden { ContainerRNA *cont = cont_; PropertyRNA *prop; - + prop = RNA_def_property(cont, identifier, PROP_BOOLEAN, PROP_XYZ); /* XXX */ if (len != 0) RNA_def_property_array(prop, len); if (default_value) RNA_def_property_boolean_array_default(prop, default_value); @@ -2740,7 +2740,7 @@ PropertyRNA *RNA_def_int(StructOrFunctionRNA *cont_, const char *identifier, int { ContainerRNA *cont = cont_; PropertyRNA *prop; - + ASSERT_SOFT_HARD_LIMITS; prop = RNA_def_property(cont, identifier, PROP_INT, PROP_NONE); @@ -2758,7 +2758,7 @@ PropertyRNA *RNA_def_int_vector(StructOrFunctionRNA *cont_, const char *identifi { ContainerRNA *cont = cont_; PropertyRNA *prop; - + ASSERT_SOFT_HARD_LIMITS; prop = RNA_def_property(cont, identifier, PROP_INT, PROP_XYZ); /* XXX */ @@ -2777,7 +2777,7 @@ PropertyRNA *RNA_def_int_array(StructOrFunctionRNA *cont_, const char *identifie { ContainerRNA *cont = cont_; PropertyRNA *prop; - + ASSERT_SOFT_HARD_LIMITS; prop = RNA_def_property(cont, identifier, PROP_INT, PROP_NONE); @@ -2864,7 +2864,7 @@ PropertyRNA *RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, co printf("%s: items not allowed to be NULL.\n", __func__); return NULL; } - + prop = RNA_def_property(cont, identifier, PROP_ENUM, PROP_NONE); if (items) RNA_def_property_enum_items(prop, items); RNA_def_property_enum_default(prop, default_value); @@ -2906,7 +2906,7 @@ PropertyRNA *RNA_def_float(StructOrFunctionRNA *cont_, const char *identifier, f { ContainerRNA *cont = cont_; PropertyRNA *prop; - + ASSERT_SOFT_HARD_LIMITS; prop = RNA_def_property(cont, identifier, PROP_FLOAT, PROP_NONE); @@ -2924,7 +2924,7 @@ PropertyRNA *RNA_def_float_vector(StructOrFunctionRNA *cont_, const char *identi { ContainerRNA *cont = cont_; PropertyRNA *prop; - + ASSERT_SOFT_HARD_LIMITS; prop = RNA_def_property(cont, identifier, PROP_FLOAT, PROP_XYZ); @@ -2942,7 +2942,7 @@ PropertyRNA *RNA_def_float_vector_xyz(StructOrFunctionRNA *cont_, const char *id const char *ui_description, float softmin, float softmax) { PropertyRNA *prop; - + prop = RNA_def_float_vector(cont_, identifier, len, default_value, hardmin, hardmax, ui_name, ui_description, softmin, softmax); prop->subtype = PROP_XYZ_LENGTH; @@ -2956,7 +2956,7 @@ PropertyRNA *RNA_def_float_color(StructOrFunctionRNA *cont_, const char *identif { ContainerRNA *cont = cont_; PropertyRNA *prop; - + ASSERT_SOFT_HARD_LIMITS; prop = RNA_def_property(cont, identifier, PROP_FLOAT, PROP_COLOR); @@ -3033,7 +3033,7 @@ PropertyRNA *RNA_def_float_array(StructOrFunctionRNA *cont_, const char *identif { ContainerRNA *cont = cont_; PropertyRNA *prop; - + ASSERT_SOFT_HARD_LIMITS; prop = RNA_def_property(cont, identifier, PROP_FLOAT, PROP_NONE); @@ -3052,7 +3052,7 @@ PropertyRNA *RNA_def_float_percentage(StructOrFunctionRNA *cont_, const char *id { ContainerRNA *cont = cont_; PropertyRNA *prop; - + ASSERT_SOFT_HARD_LIMITS; prop = RNA_def_property(cont, identifier, PROP_FLOAT, PROP_PERCENTAGE); @@ -3070,7 +3070,7 @@ PropertyRNA *RNA_def_float_factor(StructOrFunctionRNA *cont_, const char *identi { ContainerRNA *cont = cont_; PropertyRNA *prop; - + ASSERT_SOFT_HARD_LIMITS; prop = RNA_def_property(cont, identifier, PROP_FLOAT, PROP_FACTOR); @@ -3087,7 +3087,7 @@ PropertyRNA *RNA_def_pointer(StructOrFunctionRNA *cont_, const char *identifier, { ContainerRNA *cont = cont_; PropertyRNA *prop; - + prop = RNA_def_property(cont, identifier, PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, type); RNA_def_property_ui_text(prop, ui_name, ui_description); @@ -3100,7 +3100,7 @@ PropertyRNA *RNA_def_pointer_runtime(StructOrFunctionRNA *cont_, const char *ide { ContainerRNA *cont = cont_; PropertyRNA *prop; - + prop = RNA_def_property(cont, identifier, PROP_POINTER, PROP_NONE); RNA_def_property_struct_runtime(prop, type); if ((type->flag & STRUCT_ID) != 0) { @@ -3116,7 +3116,7 @@ PropertyRNA *RNA_def_collection(StructOrFunctionRNA *cont_, const char *identifi { ContainerRNA *cont = cont_; PropertyRNA *prop; - + prop = RNA_def_property(cont, identifier, PROP_COLLECTION, PROP_NONE); RNA_def_property_struct_type(prop, type); RNA_def_property_ui_text(prop, ui_name, ui_description); @@ -3129,7 +3129,7 @@ PropertyRNA *RNA_def_collection_runtime(StructOrFunctionRNA *cont_, const char * { ContainerRNA *cont = cont_; PropertyRNA *prop; - + prop = RNA_def_property(cont, identifier, PROP_COLLECTION, PROP_NONE); RNA_def_property_struct_runtime(prop, type); RNA_def_property_ui_text(prop, ui_name, ui_description); @@ -3586,7 +3586,7 @@ void RNA_def_property_free_pointers(PropertyRNA *prop) static void rna_def_property_free(StructOrFunctionRNA *cont_, PropertyRNA *prop) { ContainerRNA *cont = cont_; - + if (prop->flag_internal & PROP_INTERN_RUNTIME) { if (cont->prophash) BLI_ghash_remove(cont->prophash, prop->identifier, NULL, NULL); @@ -3604,7 +3604,7 @@ int RNA_def_property_free_identifier(StructOrFunctionRNA *cont_, const char *ide { ContainerRNA *cont = cont_; PropertyRNA *prop; - + for (prop = cont->properties.first; prop; prop = prop->next) { if (STREQ(prop->identifier, identifier)) { if (prop->flag_internal & PROP_INTERN_RUNTIME) { diff --git a/source/blender/makesrna/intern/rna_depsgraph.c b/source/blender/makesrna/intern/rna_depsgraph.c index f904d4c06b1..3e85e225d27 100644 --- a/source/blender/makesrna/intern/rna_depsgraph.c +++ b/source/blender/makesrna/intern/rna_depsgraph.c @@ -474,7 +474,6 @@ static void rna_def_depsgraph(BlenderRNA *brna) static EnumPropertyItem enum_depsgraph_mode_items[] = { {DAG_EVAL_VIEWPORT, "VIEWPORT", 0, "Viewport", "Viewport non-rendered mode"}, - {DAG_EVAL_PREVIEW, "PREVIEW", 0, "Preview", "Viewport rendered draw mode"}, {DAG_EVAL_RENDER, "RENDER", 0, "Render", "Render"}, {0, NULL, 0, NULL, NULL} }; diff --git a/source/blender/makesrna/intern/rna_dynamicpaint.c b/source/blender/makesrna/intern/rna_dynamicpaint.c index 0358efff266..509265c04df 100644 --- a/source/blender/makesrna/intern/rna_dynamicpaint.c +++ b/source/blender/makesrna/intern/rna_dynamicpaint.c @@ -438,7 +438,7 @@ static void rna_def_canvas_surface(BlenderRNA *brna) prop = RNA_def_property(srna, "use_dissolve", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_DPAINT_DISSOLVE); RNA_def_property_ui_text(prop, "Dissolve", "Enable to make surface changes disappear over time"); - + prop = RNA_def_property(srna, "dissolve_speed", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "diss_speed"); RNA_def_property_range(prop, 1.0, 10000.0); @@ -448,12 +448,12 @@ static void rna_def_canvas_surface(BlenderRNA *brna) prop = RNA_def_property(srna, "use_drying", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_DPAINT_USE_DRYING); RNA_def_property_ui_text(prop, "Dry", "Enable to make surface wetness dry over time"); - + prop = RNA_def_property(srna, "dry_speed", PROP_INT, PROP_NONE); RNA_def_property_range(prop, 1.0, 10000.0); RNA_def_property_ui_range(prop, 1.0, 10000.0, 5, -1); RNA_def_property_ui_text(prop, "Dry Speed", "Approximately in how many frames should drying happen"); - + /* * Simulation settings */ @@ -462,12 +462,12 @@ static void rna_def_canvas_surface(BlenderRNA *brna) RNA_def_property_range(prop, 16.0, 4096.0); RNA_def_property_ui_range(prop, 16.0, 4096.0, 1, -1); RNA_def_property_ui_text(prop, "Resolution", "Output image resolution"); - + prop = RNA_def_property(srna, "uv_layer", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "uvlayer_name"); RNA_def_property_ui_text(prop, "UV Map", "UV map name"); RNA_def_property_string_funcs(prop, NULL, NULL, "rna_DynamicPaint_uvlayer_set"); - + prop = RNA_def_property(srna, "frame_start", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "start_frame"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); @@ -475,7 +475,7 @@ static void rna_def_canvas_surface(BlenderRNA *brna) RNA_def_property_ui_range(prop, 1.0, 9999, 1, -1); RNA_def_property_ui_text(prop, "Start Frame", "Simulation start frame"); RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_DynamicPaintSurfaces_updateFrames"); - + prop = RNA_def_property(srna, "frame_end", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "end_frame"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); @@ -483,13 +483,13 @@ static void rna_def_canvas_surface(BlenderRNA *brna) RNA_def_property_ui_range(prop, 1.0, 9999.0, 1, -1); RNA_def_property_ui_text(prop, "End Frame", "Simulation end frame"); RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_DynamicPaintSurfaces_updateFrames"); - + prop = RNA_def_property(srna, "frame_substeps", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "substeps"); RNA_def_property_range(prop, 0.0, 20.0); RNA_def_property_ui_range(prop, 0.0, 10, 1, -1); RNA_def_property_ui_text(prop, "Sub-Steps", "Do extra frames between scene frames to ensure smooth motion"); - + prop = RNA_def_property(srna, "use_antialiasing", PROP_BOOLEAN, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_DPAINT_ANTIALIAS); @@ -542,7 +542,7 @@ static void rna_def_canvas_surface(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_enum_items(prop, prop_dynamicpaint_effecttype); RNA_def_property_ui_text(prop, "Effect Type", ""); - + prop = RNA_def_property(srna, "use_dry_log", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_DPAINT_DRY_LOG); RNA_def_property_ui_text(prop, "Slow", "Use logarithmic drying (makes high values to dry faster than low values)"); @@ -551,13 +551,13 @@ static void rna_def_canvas_surface(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_DPAINT_DISSOLVE_LOG); RNA_def_property_ui_text(prop, "Slow", "Use logarithmic dissolve (makes high values to fade faster than low values)"); - + prop = RNA_def_property(srna, "use_spread", PROP_BOOLEAN, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_boolean_sdna(prop, NULL, "effect", MOD_DPAINT_EFFECT_DO_SPREAD); RNA_def_property_ui_text(prop, "Use Spread", "Process spread effect (spread wet paint around surface)"); RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_DynamicPaintSurface_reset"); - + prop = RNA_def_property(srna, "spread_speed", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "spread_speed"); RNA_def_property_range(prop, 0.001, 10.0); @@ -575,19 +575,19 @@ static void rna_def_canvas_surface(BlenderRNA *brna) RNA_def_property_range(prop, 0.0, 2.0); RNA_def_property_ui_range(prop, 0.0, 2.0, 1, 2); RNA_def_property_ui_text(prop, "Color Spread", "How fast colors get mixed within wet paint"); - + prop = RNA_def_property(srna, "use_drip", PROP_BOOLEAN, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_boolean_sdna(prop, NULL, "effect", MOD_DPAINT_EFFECT_DO_DRIP); RNA_def_property_ui_text(prop, "Use Drip", "Process drip effect (drip wet paint to gravity direction)"); RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_DynamicPaintSurface_reset"); - + prop = RNA_def_property(srna, "use_shrink", PROP_BOOLEAN, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_boolean_sdna(prop, NULL, "effect", MOD_DPAINT_EFFECT_DO_SHRINK); RNA_def_property_ui_text(prop, "Use Shrink", "Process shrink effect (shrink paint areas)"); RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_DynamicPaintSurface_reset"); - + prop = RNA_def_property(srna, "shrink_speed", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "shrink_speed"); RNA_def_property_range(prop, 0.001, 10.0); @@ -618,7 +618,7 @@ static void rna_def_canvas_surface(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_DPAINT_MULALPHA); RNA_def_property_ui_text(prop, "Premultiply alpha", "Multiply color by alpha (recommended for Blender input)"); - + prop = RNA_def_property(srna, "image_output_path", PROP_STRING, PROP_DIRPATH); RNA_def_property_string_sdna(prop, NULL, "image_output_path"); RNA_def_property_ui_text(prop, "Output Path", "Directory to save the textures"); @@ -658,7 +658,7 @@ static void rna_def_canvas_surface(BlenderRNA *brna) /* return type */ parm = RNA_def_boolean(func, "exists", 0, "", ""); RNA_def_function_return(func, parm); - + prop = RNA_def_property(srna, "depth_clamp", PROP_FLOAT, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_range(prop, 0.00, 50.0); @@ -674,12 +674,12 @@ static void rna_def_canvas_surface(BlenderRNA *brna) RNA_def_property_ui_range(prop, -5.0, 5.0, 1, 2); RNA_def_property_ui_text(prop, "Displace Factor", "Strength of displace when applied to the mesh"); RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_DynamicPaint_redoModifier"); - + prop = RNA_def_property(srna, "image_fileformat", PROP_ENUM, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_enum_items(prop, prop_dynamicpaint_image_fileformat); RNA_def_property_ui_text(prop, "File Format", ""); - + prop = RNA_def_property(srna, "displace_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "disp_type"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); @@ -824,12 +824,12 @@ static void rna_def_dynamic_paint_brush_settings(BlenderRNA *brna) RNA_def_property_ui_range(prop, 0.0, 1.0, 5, 2); RNA_def_property_ui_text(prop, "Paint Alpha", "Paint alpha"); RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_DynamicPaint_redoModifier"); - + prop = RNA_def_property(srna, "use_absolute_alpha", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_DPAINT_ABS_ALPHA); RNA_def_property_ui_text(prop, "Absolute Alpha", "Only increase alpha value if paint alpha is higher than existing"); - + prop = RNA_def_property(srna, "paint_wetness", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "wetness"); RNA_def_property_range(prop, 0.0, 1.0); @@ -837,7 +837,7 @@ static void rna_def_dynamic_paint_brush_settings(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Paint Wetness", "Paint wetness, visible in wetmap (some effects only affect wet paint)"); RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_DynamicPaint_redoModifier"); - + prop = RNA_def_property(srna, "use_paint_erase", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_DPAINT_ERASE); RNA_def_property_ui_text(prop, "Erase Paint", "Erase / remove paint instead of adding it"); @@ -890,7 +890,7 @@ static void rna_def_dynamic_paint_brush_settings(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_DPAINT_VELOCITY_COLOR); RNA_def_property_ui_text(prop, "Replace Color", "Replace brush color by velocity color ramp"); RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_DynamicPaint_redoModifier"); - + /* * Paint Area / Collision */ @@ -900,7 +900,7 @@ static void rna_def_dynamic_paint_brush_settings(BlenderRNA *brna) RNA_def_property_enum_items(prop, prop_dynamicpaint_collisiontype); RNA_def_property_ui_text(prop, "Paint Source", ""); RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_DynamicPaint_redoModifier"); - + prop = RNA_def_property(srna, "paint_distance", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "paint_distance"); RNA_def_property_range(prop, 0.0, 500.0); @@ -908,19 +908,19 @@ static void rna_def_dynamic_paint_brush_settings(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Proximity Distance", "Maximum distance from brush to mesh surface to affect paint"); RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_DynamicPaint_redoModifier"); - + prop = RNA_def_property(srna, "use_proximity_ramp_alpha", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_DPAINT_RAMP_ALPHA); RNA_def_property_ui_text(prop, "Only Use Alpha", "Only read color ramp alpha"); RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_DynamicPaint_redoModifier"); - + prop = RNA_def_property(srna, "proximity_falloff", PROP_ENUM, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_enum_sdna(prop, NULL, "proximity_falloff"); RNA_def_property_enum_items(prop, prop_dynamicpaint_prox_falloff); RNA_def_property_ui_text(prop, "Falloff", "Proximity falloff type"); RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_DynamicPaint_redoModifier"); - + prop = RNA_def_property(srna, "use_proximity_project", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_DPAINT_PROX_PROJECT); RNA_def_property_ui_text(prop, "Project", @@ -944,7 +944,7 @@ static void rna_def_dynamic_paint_brush_settings(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_DPAINT_NEGATE_VOLUME); RNA_def_property_ui_text(prop, "Negate Volume", "Negate influence inside the volume"); RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_DynamicPaint_redoModifier"); - + /* * Particle @@ -956,12 +956,12 @@ static void rna_def_dynamic_paint_brush_settings(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Particle Systems", "The particle system to paint with"); RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_DynamicPaint_reset_dependency"); - + prop = RNA_def_property(srna, "use_particle_radius", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_DPAINT_PART_RAD); RNA_def_property_ui_text(prop, "Use Particle Radius", "Use radius from particle settings"); RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_DynamicPaint_redoModifier"); - + prop = RNA_def_property(srna, "solid_radius", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "particle_radius"); RNA_def_property_range(prop, 0.01, 10.0); @@ -975,7 +975,7 @@ static void rna_def_dynamic_paint_brush_settings(BlenderRNA *brna) RNA_def_property_ui_range(prop, 0.0, 1.0, 5, -1); RNA_def_property_ui_text(prop, "Smooth Radius", "Smooth falloff added after solid radius"); RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_DynamicPaint_redoModifier"); - + /* * Color ramps diff --git a/source/blender/makesrna/intern/rna_fcurve.c b/source/blender/makesrna/intern/rna_fcurve.c index 0e382248542..64d6960d0ff 100644 --- a/source/blender/makesrna/intern/rna_fcurve.c +++ b/source/blender/makesrna/intern/rna_fcurve.c @@ -85,7 +85,7 @@ const EnumPropertyItem rna_enum_beztriple_interpolation_easing_items[] = { {BEZT_IPO_EASE_AUTO, "AUTO", ICON_IPO_EASE_IN_OUT, "Automatic Easing", "Easing type is chosen automatically based on what the type of interpolation used " "(e.g. 'Ease In' for transitional types, and 'Ease Out' for dynamic effects)"}, - + {BEZT_IPO_EASE_IN, "EASE_IN", ICON_IPO_EASE_IN, "Ease In", "Only on the end closest to the next keyframe"}, {BEZT_IPO_EASE_OUT, "EASE_OUT", ICON_IPO_EASE_OUT, "Ease Out", "Only on the end closest to the first keyframe"}, {BEZT_IPO_EASE_IN_OUT, "EASE_IN_OUT", ICON_IPO_EASE_IN_OUT, "Ease In and Out", "Segment between both keyframes"}, @@ -138,21 +138,21 @@ static void rna_ChannelDriver_update_data(Main *bmain, Scene *scene, PointerRNA ChannelDriver *driver = ptr->data; driver->flag &= ~DRIVER_FLAG_INVALID; - + /* TODO: this really needs an update guard... */ DEG_relations_tag_update(bmain); DEG_id_tag_update(id, OB_RECALC_OB | OB_RECALC_DATA); - + WM_main_add_notifier(NC_SCENE | ND_FRAME, scene); } static void rna_ChannelDriver_update_expr(Main *bmain, Scene *scene, PointerRNA *ptr) { ChannelDriver *driver = ptr->data; - + /* tag driver as needing to be recompiled */ driver->flag |= DRIVER_FLAG_RECOMPILE; - + /* update_data() clears invalid flag and schedules for updates */ rna_ChannelDriver_update_data(bmain, scene, ptr); } @@ -168,7 +168,7 @@ static void rna_DriverTarget_update_data(Main *bmain, Scene *scene, PointerRNA * for (fcu = adt->drivers.first; fcu; fcu = fcu->next) { driver = fcu->driver; fcu->flag &= ~FCURVE_DISABLED; - + if (driver) { /* FIXME: need to be able to search targets for required one... */ /*BLI_findindex(&driver->targets, ptr->data) != -1) */ @@ -212,7 +212,7 @@ static int rna_DriverTarget_id_editable(PointerRNA *ptr, const char **UNUSED(r_i static int rna_DriverTarget_id_type_editable(PointerRNA *ptr, const char **UNUSED(r_info)) { DriverTarget *dtar = (DriverTarget *)ptr->data; - + /* when the id-type can only be object, don't allow editing * otherwise, there may be strange crashes */ @@ -222,7 +222,7 @@ static int rna_DriverTarget_id_type_editable(PointerRNA *ptr, const char **UNUSE static void rna_DriverTarget_id_type_set(PointerRNA *ptr, int value) { DriverTarget *data = (DriverTarget *)(ptr->data); - + /* check if ID-type is settable */ if ((data->flag & DTAR_FLAG_ID_OB_ONLY) == 0) { /* change ID-type to the new type */ @@ -232,7 +232,7 @@ static void rna_DriverTarget_id_type_set(PointerRNA *ptr, int value) /* make sure ID-type is Object */ data->idtype = ID_OB; } - + /* clear the id-block if the type is invalid */ if ((data->id) && (GS(data->id->name) != data->idtype)) data->id = NULL; @@ -251,7 +251,7 @@ static void rna_DriverTarget_RnaPath_get(PointerRNA *ptr, char *value) static int rna_DriverTarget_RnaPath_length(PointerRNA *ptr) { DriverTarget *dtar = (DriverTarget *)ptr->data; - + if (dtar->rna_path) return strlen(dtar->rna_path); else @@ -261,11 +261,11 @@ static int rna_DriverTarget_RnaPath_length(PointerRNA *ptr) static void rna_DriverTarget_RnaPath_set(PointerRNA *ptr, const char *value) { DriverTarget *dtar = (DriverTarget *)ptr->data; - + /* XXX in this case we need to be very careful, as this will require some new dependencies to be added! */ if (dtar->rna_path) MEM_freeN(dtar->rna_path); - + if (value[0]) dtar->rna_path = BLI_strdup(value); else @@ -275,7 +275,7 @@ static void rna_DriverTarget_RnaPath_set(PointerRNA *ptr, const char *value) static void rna_DriverVariable_type_set(PointerRNA *ptr, int value) { DriverVar *dvar = (DriverVar *)ptr->data; - + /* call the API function for this */ driver_change_variable_type(dvar, value); } @@ -283,7 +283,7 @@ static void rna_DriverVariable_type_set(PointerRNA *ptr, int value) void rna_DriverVariable_name_set(PointerRNA *ptr, const char *value) { DriverVar *data = (DriverVar *)(ptr->data); - + BLI_strncpy_utf8(data->name, value, 64); driver_variable_name_validate(data); } @@ -314,7 +314,7 @@ static void rna_Driver_remove_variable(ChannelDriver *driver, ReportList *report static void rna_FKeyframe_handle1_get(PointerRNA *ptr, float *values) { BezTriple *bezt = (BezTriple *)ptr->data; - + values[0] = bezt->vec[0][0]; values[1] = bezt->vec[0][1]; } @@ -322,7 +322,7 @@ static void rna_FKeyframe_handle1_get(PointerRNA *ptr, float *values) static void rna_FKeyframe_handle1_set(PointerRNA *ptr, const float *values) { BezTriple *bezt = (BezTriple *)ptr->data; - + bezt->vec[0][0] = values[0]; bezt->vec[0][1] = values[1]; } @@ -330,7 +330,7 @@ static void rna_FKeyframe_handle1_set(PointerRNA *ptr, const float *values) static void rna_FKeyframe_handle2_get(PointerRNA *ptr, float *values) { BezTriple *bezt = (BezTriple *)ptr->data; - + values[0] = bezt->vec[2][0]; values[1] = bezt->vec[2][1]; } @@ -338,7 +338,7 @@ static void rna_FKeyframe_handle2_get(PointerRNA *ptr, float *values) static void rna_FKeyframe_handle2_set(PointerRNA *ptr, const float *values) { BezTriple *bezt = (BezTriple *)ptr->data; - + bezt->vec[2][0] = values[0]; bezt->vec[2][1] = values[1]; } @@ -346,7 +346,7 @@ static void rna_FKeyframe_handle2_set(PointerRNA *ptr, const float *values) static void rna_FKeyframe_ctrlpoint_get(PointerRNA *ptr, float *values) { BezTriple *bezt = (BezTriple *)ptr->data; - + values[0] = bezt->vec[1][0]; values[1] = bezt->vec[1][1]; } @@ -354,7 +354,7 @@ static void rna_FKeyframe_ctrlpoint_get(PointerRNA *ptr, float *values) static void rna_FKeyframe_ctrlpoint_set(PointerRNA *ptr, const float *values) { BezTriple *bezt = (BezTriple *)ptr->data; - + bezt->vec[1][0] = values[0]; bezt->vec[1][1] = values[1]; } @@ -374,7 +374,7 @@ static void rna_FCurve_RnaPath_get(PointerRNA *ptr, char *value) static int rna_FCurve_RnaPath_length(PointerRNA *ptr) { FCurve *fcu = (FCurve *)ptr->data; - + if (fcu->rna_path) return strlen(fcu->rna_path); else @@ -387,7 +387,7 @@ static void rna_FCurve_RnaPath_set(PointerRNA *ptr, const char *value) if (fcu->rna_path) MEM_freeN(fcu->rna_path); - + if (value[0]) { fcu->rna_path = BLI_strdup(value); fcu->flag &= ~FCURVE_DISABLED; @@ -402,7 +402,7 @@ static void rna_FCurve_group_set(PointerRNA *ptr, PointerRNA value) ID *vid = (ID *)value.id.data; FCurve *fcu = ptr->data; bAction *act = NULL; - + /* get action */ if (ELEM(NULL, pid, vid)) { printf("ERROR: one of the ID's for the groups to assign to is invalid (ptr=%p, val=%p)\n", pid, vid); @@ -413,7 +413,7 @@ static void rna_FCurve_group_set(PointerRNA *ptr, PointerRNA value) printf("ERROR: ID's differ - ptr=%p vs value=%p\n", pid, vid); return; } - + if (GS(pid->name) == ID_AC && GS(vid->name) == ID_AC) { /* the ID given is the action already - usually when F-Curve is obtained from an action's pointer */ act = (bAction *)pid; @@ -423,14 +423,14 @@ static void rna_FCurve_group_set(PointerRNA *ptr, PointerRNA value) AnimData *adt = BKE_animdata_from_id(ptr->id.data); act = (adt) ? adt->action : NULL; } - + /* already belongs to group? */ if (fcu->grp == value.data) { /* nothing to do */ printf("ERROR: F-Curve already belongs to this group\n"); return; } - + /* can only change group if we have info about the action the F-Curve is in * (i.e. for drivers or random F-Curves, this cannot be done) */ @@ -444,10 +444,10 @@ static void rna_FCurve_group_set(PointerRNA *ptr, PointerRNA value) printf("ERROR: F-Curve (%p) doesn't exist in action '%s'\n", fcu, act->id.name); return; } - + /* try to remove F-Curve from action (including from any existing groups) */ action_groups_remove_channel(act, fcu); - + /* add the F-Curve back to the action now in the right place */ /* TODO: make the api function handle the case where there isn't any group to assign to */ if (value.data) { @@ -535,10 +535,10 @@ static void rna_FModifier_active_set(PointerRNA *ptr, int UNUSED(value)) static void rna_FModifier_start_frame_set(PointerRNA *ptr, float value) { FModifier *fcm = (FModifier *)ptr->data; - + CLAMP(value, MINAFRAMEF, MAXFRAMEF); fcm->sfra = value; - + /* XXX: maintain old offset? */ if (fcm->sfra >= fcm->efra) { fcm->efra = fcm->sfra; @@ -548,10 +548,10 @@ static void rna_FModifier_start_frame_set(PointerRNA *ptr, float value) static void rna_FModifer_end_frame_set(PointerRNA *ptr, float value) { FModifier *fcm = (FModifier *)ptr->data; - + CLAMP(value, MINAFRAMEF, MAXFRAMEF); fcm->efra = value; - + /* XXX: maintain old offset? */ if (fcm->efra <= fcm->sfra) { fcm->sfra = fcm->efra; @@ -562,11 +562,11 @@ static void rna_FModifier_start_frame_range(PointerRNA *UNUSED(ptr), float *min, float *UNUSED(softmin), float *UNUSED(softmax)) { // FModifier *fcm = (FModifier *)ptr->data; - - /* Technically, "sfra <= efra" must hold; however, we can't strictly enforce that, - * or else it becomes tricky to adjust the range... [#36844] - * - * NOTE: we do not set soft-limits on lower bounds, as it's too confusing when you + + /* Technically, "sfra <= efra" must hold; however, we can't strictly enforce that, + * or else it becomes tricky to adjust the range... [#36844] + * + * NOTE: we do not set soft-limits on lower bounds, as it's too confusing when you * can't easily use the slider to set things here */ *min = MINAFRAMEF; @@ -577,13 +577,13 @@ static void rna_FModifier_end_frame_range(PointerRNA *ptr, float *min, float *ma float *softmin, float *softmax) { FModifier *fcm = (FModifier *)ptr->data; - - /* Technically, "sfra <= efra" must hold; however, we can't strictly enforce that, - * or else it becomes tricky to adjust the range... [#36844] + + /* Technically, "sfra <= efra" must hold; however, we can't strictly enforce that, + * or else it becomes tricky to adjust the range... [#36844] */ *min = MINAFRAMEF; *softmin = (fcm->flag & FMODIFIER_FLAG_RANGERESTRICT) ? fcm->sfra : MINAFRAMEF; - + *softmax = MAXFRAMEF; *max = MAXFRAMEF; } @@ -602,22 +602,22 @@ static void rna_FModifier_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Poin ID *id = ptr->id.data; FModifier *fcm = (FModifier *)ptr->data; AnimData *adt = BKE_animdata_from_id(id); - + DEG_id_tag_update(id, (GS(id->name) == ID_OB) ? OB_RECALC_OB : OB_RECALC_DATA); - + /* tag datablock for time update so that animation is recalculated, * as FModifiers affect how animation plays... */ DEG_id_tag_update(id, DEG_TAG_TIME); if (adt != NULL) { adt->recalc |= ADT_RECALC_ANIM; - + if (adt->action != NULL) { /* action is separate datablock, needs separate tag */ DEG_id_tag_update(&adt->action->id, DEG_TAG_COPY_ON_WRITE); } } - + if (fcm->curve && fcm->type == FMODIFIER_TYPE_CYCLES) { calchandles_fcurve(fcm->curve); } @@ -682,9 +682,9 @@ static void rna_FModifierLimits_minx_set(PointerRNA *ptr, float value) { FModifier *fcm = (FModifier *)ptr->data; FMod_Limits *data = fcm->data; - + data->rect.xmin = value; - + if (data->rect.xmin >= data->rect.xmax) { data->rect.xmax = data->rect.xmin; } @@ -694,9 +694,9 @@ static void rna_FModifierLimits_maxx_set(PointerRNA *ptr, float value) { FModifier *fcm = (FModifier *)ptr->data; FMod_Limits *data = fcm->data; - + data->rect.xmax = value; - + if (data->rect.xmax <= data->rect.xmin) { data->rect.xmin = data->rect.xmax; } @@ -706,9 +706,9 @@ static void rna_FModifierLimits_miny_set(PointerRNA *ptr, float value) { FModifier *fcm = (FModifier *)ptr->data; FMod_Limits *data = fcm->data; - + data->rect.ymin = value; - + if (data->rect.ymin >= data->rect.ymax) { data->rect.ymax = data->rect.ymin; } @@ -718,9 +718,9 @@ static void rna_FModifierLimits_maxy_set(PointerRNA *ptr, float value) { FModifier *fcm = (FModifier *)ptr->data; FMod_Limits *data = fcm->data; - + data->rect.ymax = value; - + if (data->rect.ymax <= data->rect.ymin) { data->rect.ymin = data->rect.ymax; } @@ -731,7 +731,7 @@ static void rna_FModifierLimits_minx_range(PointerRNA *UNUSED(ptr), float *min, { // FModifier *fcm = (FModifier *)ptr->data; // FMod_Limits *data = fcm->data; - + /* no soft-limits on lower bound - it's too confusing when you can't easily use the slider to set things here */ *min = MINAFRAMEF; *max = MAXFRAMEF; @@ -742,10 +742,10 @@ static void rna_FModifierLimits_maxx_range(PointerRNA *ptr, float *min, float *m { FModifier *fcm = (FModifier *)ptr->data; FMod_Limits *data = fcm->data; - + *min = MINAFRAMEF; *softmin = (data->flag & FCM_LIMIT_XMIN) ? data->rect.xmin : MINAFRAMEF; - + *softmax = MAXFRAMEF; *max = MAXFRAMEF; } @@ -755,7 +755,7 @@ static void rna_FModifierLimits_miny_range(PointerRNA *UNUSED(ptr), float *min, { // FModifier *fcm = (FModifier *)ptr->data; // FMod_Limits *data = fcm->data; - + /* no soft-limits on lower bound - it's too confusing when you can't easily use the slider to set things here */ *min = -FLT_MAX; *max = FLT_MAX; @@ -766,12 +766,12 @@ static void rna_FModifierLimits_maxy_range(PointerRNA *ptr, float *min, float *m { FModifier *fcm = (FModifier *)ptr->data; FMod_Limits *data = fcm->data; - + *min = -FLT_MAX; *softmin = (data->flag & FCM_LIMIT_YMIN) ? data->rect.ymin : -FLT_MAX; - + *softmax = FLT_MAX; - *max = FLT_MAX; + *max = FLT_MAX; } @@ -780,7 +780,7 @@ static void rna_FModifierStepped_start_frame_range(PointerRNA *ptr, float *min, { FModifier *fcm = (FModifier *)ptr->data; FMod_Stepped *data = fcm->data; - + *min = MINAFRAMEF; *max = (data->flag & FCM_STEPPED_NO_AFTER) ? data->end_frame : MAXFRAMEF; } @@ -799,12 +799,12 @@ static void rna_FModifierStepped_frame_start_set(PointerRNA *ptr, float value) { FModifier *fcm = (FModifier *)ptr->data; FMod_Stepped *data = fcm->data; - + float prop_clamp_min = -FLT_MAX, prop_clamp_max = FLT_MAX, prop_soft_min, prop_soft_max; rna_FModifierStepped_start_frame_range(ptr, &prop_clamp_min, &prop_clamp_max, &prop_soft_min, &prop_soft_max); value = CLAMPIS(value, prop_clamp_min, prop_clamp_max); - - /* Need to set both step-data's start/end and the start/end on the base-data, + + /* Need to set both step-data's start/end and the start/end on the base-data, * or else Restrict-Range doesn't work due to RNA-property shadowing (T52009) */ data->start_frame = value; @@ -815,12 +815,12 @@ static void rna_FModifierStepped_frame_end_set(PointerRNA *ptr, float value) { FModifier *fcm = (FModifier *)ptr->data; FMod_Stepped *data = fcm->data; - + float prop_clamp_min = -FLT_MAX, prop_clamp_max = FLT_MAX, prop_soft_min, prop_soft_max; rna_FModifierStepped_end_frame_range(ptr, &prop_clamp_min, &prop_clamp_max, &prop_soft_min, &prop_soft_max); value = CLAMPIS(value, prop_clamp_min, prop_clamp_max); - - /* Need to set both step-data's start/end and the start/end on the base-data, + + /* Need to set both step-data's start/end and the start/end on the base-data, * or else Restrict-Range doesn't work due to RNA-property shadowing (T52009) */ data->end_frame = value; @@ -839,10 +839,10 @@ static void rna_FKeyframe_points_add(FCurve *fcu, int tot) BezTriple *bezt; fcu->bezt = MEM_recallocN(fcu->bezt, sizeof(BezTriple) * (fcu->totvert + tot)); - + bezt = fcu->bezt + fcu->totvert; fcu->totvert += tot; - + while (tot--) { /* defaults, no userprefs gives predictable results for API */ bezt->f1 = bezt->f2 = bezt->f3 = SELECT; @@ -946,17 +946,17 @@ static void rna_def_fmodifier_generator(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + static const EnumPropertyItem generator_mode_items[] = { {FCM_GENERATOR_POLYNOMIAL, "POLYNOMIAL", 0, "Expanded Polynomial", ""}, {FCM_GENERATOR_POLYNOMIAL_FACTORISED, "POLYNOMIAL_FACTORISED", 0, "Factorized Polynomial", ""}, {0, NULL, 0, NULL, NULL} }; - + srna = RNA_def_struct(brna, "FModifierGenerator", "FModifier"); RNA_def_struct_ui_text(srna, "Generator F-Modifier", "Deterministically generate values for the modified F-Curve"); RNA_def_struct_sdna_from(srna, "FMod_Generator", "data"); - + /* define common props */ prop = RNA_def_property(srna, "use_additive", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", FCM_GENERATOR_ADDITIVE); @@ -964,19 +964,19 @@ static void rna_def_fmodifier_generator(BlenderRNA *brna) "Values generated by this modifier are applied on top of " "the existing values instead of overwriting them"); RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, "rna_FModifier_update"); - + prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, generator_mode_items); RNA_def_property_ui_text(prop, "Mode", "Type of generator to use"); RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, "rna_FModifier_verify_data_update"); - + /* order of the polynomial */ prop = RNA_def_property(srna, "poly_order", PROP_INT, PROP_NONE); RNA_def_property_ui_text(prop, "Polynomial Order", "The highest power of 'x' for this polynomial (number of coefficients - 1)"); RNA_def_property_range(prop, 1, 100); RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, "rna_FModifier_verify_data_update"); - + /* coefficients array */ prop = RNA_def_property(srna, "coefficients", PROP_FLOAT, PROP_NONE); RNA_def_property_array(prop, 32); @@ -993,7 +993,7 @@ static void rna_def_fmodifier_function_generator(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + static const EnumPropertyItem prop_type_items[] = { {0, "SIN", 0, "Sine", ""}, {1, "COS", 0, "Cosine", ""}, @@ -1003,28 +1003,28 @@ static void rna_def_fmodifier_function_generator(BlenderRNA *brna) {5, "SINC", 0, "Normalized Sine", "sin(x) / x"}, {0, NULL, 0, NULL, NULL} }; - + srna = RNA_def_struct(brna, "FModifierFunctionGenerator", "FModifier"); RNA_def_struct_ui_text(srna, "Built-In Function F-Modifier", "Generate values using a Built-In Function"); RNA_def_struct_sdna_from(srna, "FMod_FunctionGenerator", "data"); - + /* coefficients */ prop = RNA_def_property(srna, "amplitude", PROP_FLOAT, PROP_NONE); RNA_def_property_ui_text(prop, "Amplitude", "Scale factor determining the maximum/minimum values"); RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, "rna_FModifier_update"); - + prop = RNA_def_property(srna, "phase_multiplier", PROP_FLOAT, PROP_NONE); RNA_def_property_ui_text(prop, "Phase Multiplier", "Scale factor determining the 'speed' of the function"); RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, "rna_FModifier_update"); - + prop = RNA_def_property(srna, "phase_offset", PROP_FLOAT, PROP_NONE); RNA_def_property_ui_text(prop, "Phase Offset", "Constant factor to offset time by for function"); RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, "rna_FModifier_update"); - + prop = RNA_def_property(srna, "value_offset", PROP_FLOAT, PROP_NONE); RNA_def_property_ui_text(prop, "Value Offset", "Constant factor to offset values by"); RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, "rna_FModifier_update"); - + /* flags */ prop = RNA_def_property(srna, "use_additive", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", FCM_GENERATOR_ADDITIVE); @@ -1032,7 +1032,7 @@ static void rna_def_fmodifier_function_generator(BlenderRNA *brna) "Values generated by this modifier are applied on top of " "the existing values instead of overwriting them"); RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, "rna_FModifier_update"); - + prop = RNA_def_property(srna, "function_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "type"); RNA_def_property_enum_items(prop, prop_type_items); @@ -1046,11 +1046,11 @@ static void rna_def_fmodifier_envelope_ctrl(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + srna = RNA_def_struct(brna, "FModifierEnvelopeControlPoint", NULL); RNA_def_struct_ui_text(srna, "Envelope Control Point", "Control point for envelope F-Modifier"); RNA_def_struct_sdna(srna, "FCM_EnvelopeData"); - + /* min/max extents * - for now, these are allowed to go past each other, so that we can have inverted action * - technically, the range is limited by the settings in the envelope-modifier data, not here... @@ -1059,18 +1059,18 @@ static void rna_def_fmodifier_envelope_ctrl(BlenderRNA *brna) RNA_def_property_float_sdna(prop, NULL, "min"); RNA_def_property_ui_text(prop, "Minimum Value", "Lower bound of envelope at this control-point"); RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, "rna_FModifier_update"); - + prop = RNA_def_property(srna, "max", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "max"); RNA_def_property_ui_text(prop, "Maximum Value", "Upper bound of envelope at this control-point"); RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, "rna_FModifier_update"); - + /* Frame */ prop = RNA_def_property(srna, "frame", PROP_FLOAT, PROP_TIME); RNA_def_property_float_sdna(prop, NULL, "time"); RNA_def_property_ui_text(prop, "Frame", "Frame this control-point occurs on"); RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, "rna_FModifier_update"); - + /* TODO: */ /* - selection flags (not implemented in UI yet though) */ } @@ -1109,29 +1109,29 @@ static void rna_def_fmodifier_envelope(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + srna = RNA_def_struct(brna, "FModifierEnvelope", "FModifier"); RNA_def_struct_ui_text(srna, "Envelope F-Modifier", "Scale the values of the modified F-Curve"); RNA_def_struct_sdna_from(srna, "FMod_Envelope", "data"); - + /* Collections */ prop = RNA_def_property(srna, "control_points", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "data", "totvert"); RNA_def_property_struct_type(prop, "FModifierEnvelopeControlPoint"); RNA_def_property_ui_text(prop, "Control Points", "Control points defining the shape of the envelope"); rna_def_fmodifier_envelope_control_points(brna, prop); - + /* Range Settings */ prop = RNA_def_property(srna, "reference_value", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "midval"); RNA_def_property_ui_text(prop, "Reference Value", "Value that envelope's influence is centered around / based on"); RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, "rna_FModifier_update"); - + prop = RNA_def_property(srna, "default_min", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "min"); RNA_def_property_ui_text(prop, "Default Minimum", "Lower distance from Reference Value for 1:1 default influence"); RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, "rna_FModifier_update"); - + prop = RNA_def_property(srna, "default_max", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "max"); RNA_def_property_ui_text(prop, "Default Maximum", "Upper distance from Reference Value for 1:1 default influence"); @@ -1144,7 +1144,7 @@ static void rna_def_fmodifier_cycles(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + static const EnumPropertyItem prop_type_items[] = { {FCM_EXTRAPOLATE_NONE, "NONE", 0, "No Cycles", "Don't do anything"}, {FCM_EXTRAPOLATE_CYCLIC, "REPEAT", 0, "Repeat Motion", "Repeat keyframe range as-is"}, @@ -1155,31 +1155,31 @@ static void rna_def_fmodifier_cycles(BlenderRNA *brna) "Alternate between forward and reverse playback of keyframe range"}, {0, NULL, 0, NULL, NULL} }; - + srna = RNA_def_struct(brna, "FModifierCycles", "FModifier"); RNA_def_struct_ui_text(srna, "Cycles F-Modifier", "Repeat the values of the modified F-Curve"); RNA_def_struct_sdna_from(srna, "FMod_Cycles", "data"); - + /* before */ prop = RNA_def_property(srna, "mode_before", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "before_mode"); RNA_def_property_enum_items(prop, prop_type_items); RNA_def_property_ui_text(prop, "Before Mode", "Cycling mode to use before first keyframe"); RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, "rna_FModifier_update"); - + prop = RNA_def_property(srna, "cycles_before", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "before_cycles"); RNA_def_property_ui_text(prop, "Before Cycles", "Maximum number of cycles to allow before first keyframe (0 = infinite)"); RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, "rna_FModifier_update"); - + /* after */ prop = RNA_def_property(srna, "mode_after", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "after_mode"); RNA_def_property_enum_items(prop, prop_type_items); RNA_def_property_ui_text(prop, "After Mode", "Cycling mode to use after last keyframe"); RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, "rna_FModifier_update"); - + prop = RNA_def_property(srna, "cycles_after", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "after_cycles"); RNA_def_property_ui_text(prop, "After Cycles", @@ -1193,7 +1193,7 @@ static void rna_def_fmodifier_python(BlenderRNA *brna) { StructRNA *srna; /*PropertyRNA *prop; */ - + srna = RNA_def_struct(brna, "FModifierPython", "FModifier"); RNA_def_struct_ui_text(srna, "Python F-Modifier", "Perform user-defined operation on the modified F-Curve"); RNA_def_struct_sdna_from(srna, "FMod_Python", "data"); @@ -1205,49 +1205,49 @@ static void rna_def_fmodifier_limits(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + srna = RNA_def_struct(brna, "FModifierLimits", "FModifier"); RNA_def_struct_ui_text(srna, "Limit F-Modifier", "Limit the time/value ranges of the modified F-Curve"); RNA_def_struct_sdna_from(srna, "FMod_Limits", "data"); - + prop = RNA_def_property(srna, "use_min_x", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", FCM_LIMIT_XMIN); RNA_def_property_ui_text(prop, "Minimum X", "Use the minimum X value"); RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, "rna_FModifier_update"); - + prop = RNA_def_property(srna, "use_min_y", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", FCM_LIMIT_YMIN); RNA_def_property_ui_text(prop, "Minimum Y", "Use the minimum Y value"); RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, "rna_FModifier_update"); - + prop = RNA_def_property(srna, "use_max_x", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", FCM_LIMIT_XMAX); RNA_def_property_ui_text(prop, "Maximum X", "Use the maximum X value"); RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, "rna_FModifier_update"); - + prop = RNA_def_property(srna, "use_max_y", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", FCM_LIMIT_YMAX); RNA_def_property_ui_text(prop, "Maximum Y", "Use the maximum Y value"); RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, "rna_FModifier_update"); - + prop = RNA_def_property(srna, "min_x", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "rect.xmin"); RNA_def_property_float_funcs(prop, NULL, "rna_FModifierLimits_minx_set", "rna_FModifierLimits_minx_range"); RNA_def_property_ui_text(prop, "Minimum X", "Lowest X value to allow"); RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, "rna_FModifier_update"); - + prop = RNA_def_property(srna, "min_y", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "rect.ymin"); RNA_def_property_float_funcs(prop, NULL, "rna_FModifierLimits_miny_set", "rna_FModifierLimits_miny_range"); RNA_def_property_ui_text(prop, "Minimum Y", "Lowest Y value to allow"); RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, "rna_FModifier_update"); - + prop = RNA_def_property(srna, "max_x", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "rect.xmax"); RNA_def_property_float_funcs(prop, NULL, "rna_FModifierLimits_maxx_set", "rna_FModifierLimits_maxx_range"); RNA_def_property_ui_text(prop, "Maximum X", "Highest X value to allow"); RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, "rna_FModifier_update"); - + prop = RNA_def_property(srna, "max_y", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "rect.ymax"); RNA_def_property_float_funcs(prop, NULL, "rna_FModifierLimits_maxy_set", "rna_FModifierLimits_maxy_range"); @@ -1261,7 +1261,7 @@ static void rna_def_fmodifier_noise(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + static const EnumPropertyItem prop_modification_items[] = { {FCM_NOISE_MODIF_REPLACE, "REPLACE", 0, "Replace", ""}, {FCM_NOISE_MODIF_ADD, "ADD", 0, "Add", ""}, @@ -1269,28 +1269,28 @@ static void rna_def_fmodifier_noise(BlenderRNA *brna) {FCM_NOISE_MODIF_MULTIPLY, "MULTIPLY", 0, "Multiply", ""}, {0, NULL, 0, NULL, NULL} }; - + srna = RNA_def_struct(brna, "FModifierNoise", "FModifier"); RNA_def_struct_ui_text(srna, "Noise F-Modifier", "Give randomness to the modified F-Curve"); RNA_def_struct_sdna_from(srna, "FMod_Noise", "data"); - + prop = RNA_def_property(srna, "blend_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "modification"); RNA_def_property_enum_items(prop, prop_modification_items); RNA_def_property_ui_text(prop, "Blend Type", "Method of modifying the existing F-Curve"); RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, "rna_FModifier_update"); - + prop = RNA_def_property(srna, "scale", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "size"); RNA_def_property_ui_text(prop, "Scale", "Scaling (in time) of the noise"); RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, "rna_FModifier_update"); - + prop = RNA_def_property(srna, "strength", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "strength"); RNA_def_property_ui_text(prop, "Strength", "Amplitude of the noise - the amount that it modifies the underlying curve"); RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, "rna_FModifier_update"); - + prop = RNA_def_property(srna, "phase", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "phase"); RNA_def_property_ui_text(prop, "Phase", "A random seed for the noise effect"); @@ -1300,7 +1300,7 @@ static void rna_def_fmodifier_noise(BlenderRNA *brna) RNA_def_property_float_sdna(prop, NULL, "offset"); RNA_def_property_ui_text(prop, "Offset", "Time offset for the noise effect"); RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, "rna_FModifier_update"); - + prop = RNA_def_property(srna, "depth", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "depth"); RNA_def_property_ui_text(prop, "Depth", "Amount of fine level detail present in the noise"); @@ -1314,42 +1314,42 @@ static void rna_def_fmodifier_stepped(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + srna = RNA_def_struct(brna, "FModifierStepped", "FModifier"); RNA_def_struct_ui_text(srna, "Stepped Interpolation F-Modifier", "Hold each interpolated value from the F-Curve for several frames without " "changing the timing"); RNA_def_struct_sdna_from(srna, "FMod_Stepped", "data"); - + /* properties */ prop = RNA_def_property(srna, "frame_step", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "step_size"); RNA_def_property_ui_text(prop, "Step Size", "Number of frames to hold each value"); RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, "rna_FModifier_update"); - + prop = RNA_def_property(srna, "frame_offset", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "offset"); RNA_def_property_ui_text(prop, "Offset", "Reference number of frames before frames get held " "(use to get hold for '1-3' vs '5-7' holding patterns)"); RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, "rna_FModifier_update"); - + prop = RNA_def_property(srna, "use_frame_start", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", FCM_STEPPED_NO_BEFORE); RNA_def_property_ui_text(prop, "Use Start Frame", "Restrict modifier to only act after its 'start' frame"); RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, "rna_FModifier_update"); - + prop = RNA_def_property(srna, "use_frame_end", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", FCM_STEPPED_NO_AFTER); RNA_def_property_ui_text(prop, "Use End Frame", "Restrict modifier to only act before its 'end' frame"); RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, "rna_FModifier_update"); - + prop = RNA_def_property(srna, "frame_start", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "start_frame"); RNA_def_property_float_funcs(prop, NULL, "rna_FModifierStepped_frame_start_set", "rna_FModifierStepped_start_frame_range"); RNA_def_property_ui_text(prop, "Start Frame", "Frame that modifier's influence starts (if applicable)"); RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, "rna_FModifier_update"); - + prop = RNA_def_property(srna, "frame_end", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "end_frame"); RNA_def_property_float_funcs(prop, NULL, "rna_FModifierStepped_frame_end_set", "rna_FModifierStepped_end_frame_range"); @@ -1364,43 +1364,43 @@ static void rna_def_fmodifier(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + /* base struct definition */ srna = RNA_def_struct(brna, "FModifier", NULL); RNA_def_struct_refine_func(srna, "rna_FModifierType_refine"); RNA_def_struct_ui_text(srna, "F-Modifier", "Modifier for values of F-Curve"); - + #if 0 /* XXX not used yet */ /* name */ prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); RNA_def_struct_name_property(srna, prop); RNA_def_property_ui_text(prop, "Name", "Short description of F-Curve Modifier"); #endif /* XXX not used yet */ - + /* type */ prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_enum_items(prop, rna_enum_fmodifier_type_items); RNA_def_property_ui_text(prop, "Type", "F-Curve Modifier Type"); - + /* settings */ prop = RNA_def_property(srna, "show_expanded", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", FMODIFIER_FLAG_EXPANDED); RNA_def_property_ui_text(prop, "Expanded", "F-Curve Modifier's panel is expanded in UI"); RNA_def_property_ui_icon(prop, ICON_TRIA_RIGHT, 1); - + prop = RNA_def_property(srna, "mute", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", FMODIFIER_FLAG_MUTED); RNA_def_property_ui_text(prop, "Muted", "F-Curve Modifier will not be evaluated"); RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME_PROP, "rna_FModifier_update"); RNA_def_property_ui_icon(prop, ICON_MUTE_IPO_OFF, 1); - + prop = RNA_def_property(srna, "is_valid", PROP_BOOLEAN, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", FMODIFIER_FLAG_DISABLED); RNA_def_property_ui_text(prop, "Disabled", "F-Curve Modifier has invalid settings and will not be evaluated"); RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME_PROP, "rna_FModifier_update"); - + /* TODO: setting this to true must ensure that all others in stack are turned off too... */ prop = RNA_def_property(srna, "active", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", FMODIFIER_FLAG_ACTIVE); @@ -1408,7 +1408,7 @@ static void rna_def_fmodifier(BlenderRNA *brna) RNA_def_property_boolean_funcs(prop, NULL, "rna_FModifier_active_set"); RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME_PROP, "rna_FModifier_active_update"); RNA_def_property_ui_icon(prop, ICON_RADIOBUT_OFF, 1); - + /* restricted range */ prop = RNA_def_property(srna, "use_restricted_range", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", FMODIFIER_FLAG_RANGERESTRICT); @@ -1417,40 +1417,40 @@ static void rna_def_fmodifier(BlenderRNA *brna) "mask off effects in order to chain them"); RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME_PROP, "rna_FModifier_update"); RNA_def_property_ui_icon(prop, ICON_TRIA_RIGHT, 1); /* XXX: depends on UI implementation */ - + prop = RNA_def_property(srna, "frame_start", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "sfra"); RNA_def_property_float_funcs(prop, NULL, "rna_FModifier_start_frame_set", "rna_FModifier_start_frame_range"); RNA_def_property_ui_text(prop, "Start Frame", "Frame that modifier's influence starts (if Restrict Frame Range is in use)"); RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME_PROP, "rna_FModifier_update"); - + prop = RNA_def_property(srna, "frame_end", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "efra"); RNA_def_property_float_funcs(prop, NULL, "rna_FModifer_end_frame_set", "rna_FModifier_end_frame_range"); RNA_def_property_ui_text(prop, "End Frame", "Frame that modifier's influence ends (if Restrict Frame Range is in use)"); RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME_PROP, "rna_FModifier_update"); - + prop = RNA_def_property(srna, "blend_in", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "blendin"); RNA_def_property_float_funcs(prop, NULL, NULL, "rna_FModifier_blending_range"); RNA_def_property_ui_text(prop, "Blend In", "Number of frames from start frame for influence to take effect"); RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME_PROP, "rna_FModifier_update"); - + prop = RNA_def_property(srna, "blend_out", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "blendout"); RNA_def_property_float_funcs(prop, NULL, NULL, "rna_FModifier_blending_range"); RNA_def_property_ui_text(prop, "Blend Out", "Number of frames from end frame for influence to fade out"); RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME_PROP, "rna_FModifier_update"); - + /* influence */ prop = RNA_def_property(srna, "use_influence", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", FMODIFIER_FLAG_USEINFLUENCE); RNA_def_property_ui_text(prop, "Use Influence", "F-Curve Modifier's effects will be tempered by a default factor"); RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME_PROP, "rna_FModifier_update"); RNA_def_property_ui_icon(prop, ICON_TRIA_RIGHT, 1); /* XXX: depends on UI implementation */ - + prop = RNA_def_property(srna, "influence", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "influence"); RNA_def_property_range(prop, 0.0f, 1.0f); @@ -1466,7 +1466,7 @@ static void rna_def_drivertarget(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + static const EnumPropertyItem prop_trans_chan_items[] = { {DTAR_TRANSCHAN_LOCX, "LOC_X", 0, "X Location", ""}, {DTAR_TRANSCHAN_LOCY, "LOC_Y", 0, "Y Location", ""}, @@ -1479,7 +1479,7 @@ static void rna_def_drivertarget(BlenderRNA *brna) {DTAR_TRANSCHAN_SCALEZ, "SCALE_Z", 0, "Z Scale", ""}, {0, NULL, 0, NULL, NULL} }; - + static const EnumPropertyItem prop_local_space_items[] = { {0, "WORLD_SPACE", 0, "World Space", "Transforms include effects of parenting/restpose and constraints"}, {DTAR_FLAG_LOCALSPACE, "TRANSFORM_SPACE", 0, "Transform Space", @@ -1489,10 +1489,10 @@ static void rna_def_drivertarget(BlenderRNA *brna) "parenting/restpose"}, {0, NULL, 0, NULL, NULL} }; - + srna = RNA_def_struct(brna, "DriverTarget", NULL); RNA_def_struct_ui_text(srna, "Driver Target", "Source of input values for driver variables"); - + /* Target Properties - ID-block to Drive */ prop = RNA_def_property(srna, "id", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "ID"); @@ -1505,7 +1505,7 @@ static void rna_def_drivertarget(BlenderRNA *brna) "ID-block that the specific property used can be found from " "(id_type property must be set first)"); RNA_def_property_update(prop, 0, "rna_DriverTarget_update_data"); - + prop = RNA_def_property(srna, "id_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "idtype"); RNA_def_property_enum_items(prop, rna_enum_id_type_items); @@ -1515,25 +1515,25 @@ static void rna_def_drivertarget(BlenderRNA *brna) RNA_def_property_ui_text(prop, "ID Type", "Type of ID-block that can be used"); RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_ID); RNA_def_property_update(prop, 0, "rna_DriverTarget_update_data"); - + /* Target Properties - Property to Drive */ prop = RNA_def_property(srna, "data_path", PROP_STRING, PROP_NONE); RNA_def_property_string_funcs(prop, "rna_DriverTarget_RnaPath_get", "rna_DriverTarget_RnaPath_length", "rna_DriverTarget_RnaPath_set"); RNA_def_property_ui_text(prop, "Data Path", "RNA Path (from ID-block) to property used"); RNA_def_property_update(prop, 0, "rna_DriverTarget_update_data"); - + prop = RNA_def_property(srna, "bone_target", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "pchan_name"); RNA_def_property_ui_text(prop, "Bone Name", "Name of PoseBone to use as target"); RNA_def_property_update(prop, 0, "rna_DriverTarget_update_data"); - + prop = RNA_def_property(srna, "transform_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "transChan"); RNA_def_property_enum_items(prop, prop_trans_chan_items); RNA_def_property_ui_text(prop, "Type", "Driver variable type"); RNA_def_property_update(prop, 0, "rna_DriverTarget_update_data"); - + prop = RNA_def_property(srna, "transform_space", PROP_ENUM, PROP_NONE); RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag"); RNA_def_property_enum_items(prop, prop_local_space_items); @@ -1545,7 +1545,7 @@ static void rna_def_drivervar(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + static const EnumPropertyItem prop_type_items[] = { {DVAR_TYPE_SINGLE_PROP, "SINGLE_PROP", ICON_RNA, "Single Property", "Use the value from some RNA property (Default)"}, {DVAR_TYPE_TRANSFORM_CHAN, "TRANSFORMS", ICON_MANIPUL, "Transform Channel", @@ -1554,12 +1554,12 @@ static void rna_def_drivervar(BlenderRNA *brna) {DVAR_TYPE_LOC_DIFF, "LOC_DIFF", ICON_FULLSCREEN_ENTER, "Distance", "Distance between two bones or objects"}, /* XXX: Icon... */ {0, NULL, 0, NULL, NULL} }; - - + + srna = RNA_def_struct(brna, "DriverVariable", NULL); RNA_def_struct_sdna(srna, "DriverVar"); RNA_def_struct_ui_text(srna, "Driver Variable", "Variable from some source/target for driver relationship"); - + /* Variable Name */ prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); RNA_def_struct_name_property(srna, prop); @@ -1568,14 +1568,14 @@ static void rna_def_drivervar(BlenderRNA *brna) "Name to use in scripted expressions/functions (no spaces or dots are allowed, " "and must start with a letter)"); RNA_def_property_update(prop, 0, "rna_DriverTarget_update_name"); /* XXX */ - + /* Enums */ prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, prop_type_items); RNA_def_property_enum_funcs(prop, NULL, "rna_DriverVariable_type_set", NULL); RNA_def_property_ui_text(prop, "Type", "Driver variable type"); RNA_def_property_update(prop, 0, "rna_ChannelDriver_update_data"); /* XXX */ - + /* Targets */ /* TODO: for nicer api, only expose the relevant props via subclassing, * instead of exposing the collection of targets */ @@ -1584,12 +1584,12 @@ static void rna_def_drivervar(BlenderRNA *brna) RNA_def_property_struct_type(prop, "DriverTarget"); RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC); RNA_def_property_ui_text(prop, "Targets", "Sources of input data for evaluating this variable"); - + /* Name Validity Flags */ prop = RNA_def_property(srna, "is_name_valid", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", DVAR_FLAG_INVALID_NAME); RNA_def_property_clear_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "Is Name Valid", "Is this a valid name for a driver variable"); + RNA_def_property_ui_text(prop, "Is Name Valid", "Is this a valid name for a driver variable"); } @@ -1598,16 +1598,16 @@ static void rna_def_channeldriver_variables(BlenderRNA *brna, PropertyRNA *cprop { StructRNA *srna; /* PropertyRNA *prop; */ - + FunctionRNA *func; PropertyRNA *parm; - + RNA_def_property_srna(cprop, "ChannelDriverVariables"); srna = RNA_def_struct(brna, "ChannelDriverVariables", NULL); RNA_def_struct_sdna(srna, "ChannelDriver"); RNA_def_struct_ui_text(srna, "ChannelDriver Variables", "Collection of channel driver Variables"); - - + + /* add variable */ func = RNA_def_function(srna, "new", "rna_Driver_new_variable"); RNA_def_function_ui_description(func, "Add a new variable for the driver"); @@ -1629,7 +1629,7 @@ static void rna_def_channeldriver(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + static const EnumPropertyItem prop_type_items[] = { {DRIVER_TYPE_AVERAGE, "AVERAGE", 0, "Averaged Value", ""}, {DRIVER_TYPE_SUM, "SUM", 0, "Sum Values", ""}, @@ -1662,7 +1662,7 @@ static void rna_def_channeldriver(BlenderRNA *brna) RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC); RNA_def_property_ui_text(prop, "Variables", "Properties acting as inputs for this driver"); rna_def_channeldriver_variables(brna, prop); - + /* Settings */ prop = RNA_def_property(srna, "use_self", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", DRIVER_FLAG_USE_SELF); @@ -1674,8 +1674,8 @@ static void rna_def_channeldriver(BlenderRNA *brna) prop = RNA_def_property(srna, "is_valid", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", DRIVER_FLAG_INVALID); RNA_def_property_ui_text(prop, "Invalid", "Driver could not be evaluated in past, so should be skipped"); - - + + /* Functions */ RNA_api_drivers(srna); } @@ -1686,17 +1686,17 @@ static void rna_def_fpoint(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + srna = RNA_def_struct(brna, "FCurveSample", NULL); RNA_def_struct_sdna(srna, "FPoint"); RNA_def_struct_ui_text(srna, "F-Curve Sample", "Sample point for F-Curve"); - + /* Boolean values */ prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", 1); RNA_def_property_ui_text(prop, "Select", "Selection status"); RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL); - + /* Vector value */ prop = RNA_def_property(srna, "co", PROP_FLOAT, PROP_COORDS); /* keyframes are dimensionless */ RNA_def_property_float_sdna(prop, NULL, "vec"); @@ -1713,40 +1713,40 @@ static void rna_def_fkeyframe(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + srna = RNA_def_struct(brna, "Keyframe", NULL); RNA_def_struct_sdna(srna, "BezTriple"); RNA_def_struct_ui_text(srna, "Keyframe", "Bezier curve point with two handles defining a Keyframe on an F-Curve"); - + /* Boolean values */ prop = RNA_def_property(srna, "select_left_handle", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "f1", 0); RNA_def_property_ui_text(prop, "Handle 1 selected", "Left handle selection status"); RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL); - + prop = RNA_def_property(srna, "select_right_handle", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "f3", 0); RNA_def_property_ui_text(prop, "Handle 2 selected", "Right handle selection status"); RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL); - + prop = RNA_def_property(srna, "select_control_point", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "f2", 0); RNA_def_property_ui_text(prop, "Select", "Control point selection status"); RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL); - + /* Enums */ prop = RNA_def_property(srna, "handle_left_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "h1"); RNA_def_property_enum_items(prop, rna_enum_keyframe_handle_type_items); RNA_def_property_ui_text(prop, "Left Handle Type", "Handle types"); RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME_PROP, NULL); - + prop = RNA_def_property(srna, "handle_right_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "h2"); RNA_def_property_enum_items(prop, rna_enum_keyframe_handle_type_items); RNA_def_property_ui_text(prop, "Right Handle Type", "Handle types"); RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME_PROP, NULL); - + prop = RNA_def_property(srna, "interpolation", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "ipo"); RNA_def_property_enum_items(prop, rna_enum_beztriple_interpolation_mode_items); @@ -1754,18 +1754,18 @@ static void rna_def_fkeyframe(BlenderRNA *brna) "Interpolation method to use for segment of the F-Curve from " "this Keyframe until the next Keyframe"); RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME_PROP, NULL); - + prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "hide"); RNA_def_property_enum_items(prop, rna_enum_beztriple_keyframe_type_items); RNA_def_property_ui_text(prop, "Type", "Type of keyframe (for visual purposes only)"); RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME_PROP, NULL); - - + + prop = RNA_def_property(srna, "easing", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "easing"); RNA_def_property_enum_items(prop, rna_enum_beztriple_interpolation_easing_items); - RNA_def_property_ui_text(prop, "Easing", + RNA_def_property_ui_text(prop, "Easing", "Which ends of the segment between this and the next keyframe easing " "interpolation is applied to"); RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME_PROP, NULL); @@ -1785,20 +1785,20 @@ static void rna_def_fkeyframe(BlenderRNA *brna) RNA_def_property_float_sdna(prop, NULL, "period"); RNA_def_property_ui_text(prop, "Period", "Time between bounces for elastic easing"); RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME_PROP, NULL); - + /* Vector values */ prop = RNA_def_property(srna, "handle_left", PROP_FLOAT, PROP_COORDS); /* keyframes are dimensionless */ RNA_def_property_array(prop, 2); RNA_def_property_float_funcs(prop, "rna_FKeyframe_handle1_get", "rna_FKeyframe_handle1_set", NULL); RNA_def_property_ui_text(prop, "Left Handle", "Coordinates of the left handle (before the control point)"); RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); - + prop = RNA_def_property(srna, "co", PROP_FLOAT, PROP_COORDS); /* keyframes are dimensionless */ RNA_def_property_array(prop, 2); RNA_def_property_float_funcs(prop, "rna_FKeyframe_ctrlpoint_get", "rna_FKeyframe_ctrlpoint_set", NULL); RNA_def_property_ui_text(prop, "Control Point", "Coordinates of the control point"); RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); - + prop = RNA_def_property(srna, "handle_right", PROP_FLOAT, PROP_COORDS); /* keyframes are dimensionless */ RNA_def_property_array(prop, 2); RNA_def_property_float_funcs(prop, "rna_FKeyframe_handle2_get", "rna_FKeyframe_handle2_set", NULL); @@ -1933,7 +1933,7 @@ static void rna_def_fcurve(BlenderRNA *brna) prop = RNA_def_property(srna, "extrapolation", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "extend"); RNA_def_property_enum_items(prop, prop_mode_extend_items); - RNA_def_property_ui_text(prop, "Extrapolation", + RNA_def_property_ui_text(prop, "Extrapolation", "Method used for evaluating value of F-Curve outside first and last keyframes"); RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, "rna_FCurve_update_data"); @@ -1942,7 +1942,7 @@ static void rna_def_fcurve(BlenderRNA *brna) RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Driver", "Channel Driver (only set for Driver F-Curves)"); - + prop = RNA_def_property(srna, "group", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "grp"); RNA_def_property_flag(prop, PROP_EDITABLE); @@ -1964,35 +1964,35 @@ static void rna_def_fcurve(BlenderRNA *brna) "Index to the specific property affected by F-Curve if applicable"); /* XXX need an update callback for this so that animation gets evaluated */ RNA_def_property_update(prop, NC_ANIMATION, NULL); - + /* Color */ prop = RNA_def_property(srna, "color_mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, prop_mode_color_items); RNA_def_property_ui_text(prop, "Color Mode", "Method used to determine color of F-Curve in Graph Editor"); RNA_def_property_update(prop, NC_ANIMATION, NULL); - + prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR); RNA_def_property_array(prop, 3); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Color", "Color of the F-Curve in the Graph Editor"); RNA_def_property_update(prop, NC_ANIMATION, NULL); - + /* Flags */ prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", FCURVE_SELECTED); RNA_def_property_ui_text(prop, "Select", "F-Curve is selected for editing"); RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL); - + prop = RNA_def_property(srna, "lock", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", FCURVE_PROTECTED); RNA_def_property_ui_text(prop, "Lock", "F-Curve's settings cannot be edited"); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); - + prop = RNA_def_property(srna, "mute", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", FCURVE_MUTED); RNA_def_property_ui_text(prop, "Muted", "F-Curve is not evaluated"); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, "rna_FCurve_update_eval"); - + prop = RNA_def_property(srna, "hide", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", FCURVE_VISIBLE); RNA_def_property_ui_text(prop, "Hide", "F-Curve and its keyframes are hidden in the Graph Editor graphs"); @@ -2010,7 +2010,7 @@ static void rna_def_fcurve(BlenderRNA *brna) "False when F-Curve could not be evaluated in past, so should be skipped " "when evaluating"); RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME_PROP, NULL); - + /* Collections */ prop = RNA_def_property(srna, "sampled_points", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "fpt", "totvert"); @@ -2022,7 +2022,7 @@ static void rna_def_fcurve(BlenderRNA *brna) RNA_def_property_struct_type(prop, "Keyframe"); RNA_def_property_ui_text(prop, "Keyframes", "User-editable keyframes"); rna_def_fcurve_keyframe_points(brna, prop); - + prop = RNA_def_property(srna, "modifiers", PROP_COLLECTION, PROP_NONE); RNA_def_property_struct_type(prop, "FModifier"); RNA_def_property_ui_text(prop, "Modifiers", "Modifiers affecting the shape of the F-Curve"); @@ -2038,11 +2038,11 @@ static void rna_def_fcurve(BlenderRNA *brna) /* return value */ parm = RNA_def_float(func, "value", 0, -FLT_MAX, FLT_MAX, "Value", "Value of F-Curve specific frame", -FLT_MAX, FLT_MAX); RNA_def_function_return(func, parm); - + /* -- update / recalculate -- */ func = RNA_def_function(srna, "update", "rna_FCurve_update_data_ex"); RNA_def_function_ui_description(func, "Ensure keyframes are sorted in chronological order and handles are set correctly"); - + /* -- time extents/range -- */ func = RNA_def_function(srna, "range", "rna_FCurve_range"); RNA_def_function_ui_description(func, "Get the time extents for F-Curve"); @@ -2051,7 +2051,7 @@ static void rna_def_fcurve(BlenderRNA *brna) "Min/Max values", -FLT_MAX, FLT_MAX); RNA_def_parameter_flags(parm, PROP_THICK_WRAP, 0); RNA_def_function_output(func, parm); - + /* -- auto-flag validity (ensures valid handling for data type) -- */ func = RNA_def_function(srna, "update_autoflags", "update_autoflags_fcurve"); /* calls the C/API direct */ RNA_def_function_ui_description(func, "Update FCurve flags set automatically from affected property " @@ -2073,13 +2073,13 @@ void RNA_def_fcurve(BlenderRNA *brna) rna_def_fcurve(brna); rna_def_fkeyframe(brna); rna_def_fpoint(brna); - + rna_def_drivertarget(brna); rna_def_drivervar(brna); rna_def_channeldriver(brna); - + rna_def_fmodifier(brna); - + rna_def_fmodifier_generator(brna); rna_def_fmodifier_function_generator(brna); diff --git a/source/blender/makesrna/intern/rna_fluidsim.c b/source/blender/makesrna/intern/rna_fluidsim.c index 16b672ada49..23d9155fccd 100644 --- a/source/blender/makesrna/intern/rna_fluidsim.c +++ b/source/blender/makesrna/intern/rna_fluidsim.c @@ -125,7 +125,7 @@ static void rna_FluidSettings_update_type(Main *bmain, Scene *scene, PointerRNA ParticleSystemModifierData *psmd; ParticleSystem *psys, *next_psys; ParticleSettings *part; - + fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim); fluidmd->fss->flag &= ~OB_FLUIDSIM_REVERSE; /* clear flag */ @@ -243,7 +243,7 @@ static void rna_def_fluid_mesh_vertices(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + srna = RNA_def_struct(brna, "FluidVertexVelocity", NULL); RNA_def_struct_ui_text(srna, "Fluid Mesh Velocity", "Velocity of a simulated fluid mesh"); RNA_def_struct_ui_icon(srna, ICON_VERTEXSEL); @@ -279,7 +279,7 @@ static void rna_def_fluidsim_domain(BlenderRNA *brna) RNA_def_property_int_sdna(prop, NULL, "threads"); RNA_def_property_range(prop, 0, BLENDER_MAX_THREADS); RNA_def_property_ui_text(prop, "Simulation Threads", "Override number of threads for the simulation, 0 is automatic"); - + prop = RNA_def_property(srna, "resolution", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "resolutionxyz"); RNA_def_property_range(prop, 1, 1024); @@ -327,32 +327,32 @@ static void rna_def_fluidsim_domain(BlenderRNA *brna) RNA_def_property_array(prop, 3); RNA_def_property_range(prop, -1000.1, 1000.1); RNA_def_property_ui_text(prop, "Gravity", "Gravity in X, Y and Z direction"); - + prop = RNA_def_property(srna, "use_time_override", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", OB_FLUIDSIM_OVERRIDE_TIME); RNA_def_property_ui_text(prop, "Override Time", "Use a custom start and end time (in seconds) instead of the scene's timeline"); - + prop = RNA_def_property(srna, "start_time", PROP_FLOAT, PROP_TIME); RNA_def_property_float_sdna(prop, NULL, "animStart"); RNA_def_property_range(prop, 0, FLT_MAX); RNA_def_property_ui_text(prop, "Start Time", "Simulation time of the first blender frame (in seconds)"); - + prop = RNA_def_property(srna, "end_time", PROP_FLOAT, PROP_TIME); RNA_def_property_float_sdna(prop, NULL, "animEnd"); RNA_def_property_range(prop, 0, FLT_MAX); RNA_def_property_ui_text(prop, "End Time", "Simulation time of the last blender frame (in seconds)"); - + prop = RNA_def_property(srna, "frame_offset", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "frameOffset"); RNA_def_property_ui_text(prop, "Cache Offset", "Offset when reading baked cache"); RNA_def_property_update(prop, NC_OBJECT, "rna_fluid_update"); - + prop = RNA_def_property(srna, "simulation_scale", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "realsize"); RNA_def_property_range(prop, 0.001, 10); RNA_def_property_ui_text(prop, "Real World Size", "Size of the simulation domain in meters"); - + prop = RNA_def_property(srna, "simulation_rate", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "animRate"); RNA_def_property_range(prop, 0.0, 100.0); @@ -431,7 +431,7 @@ static void rna_def_fluidsim_domain(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_range(prop, 0.0, 10.0); RNA_def_property_ui_text(prop, "Generate Particles", "Amount of particles to generate (0=off, 1=normal, >1=more)"); - + /* simulated fluid mesh data */ prop = RNA_def_property(srna, "fluid_mesh_vertices", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "meshVelocities", "totvert"); @@ -471,7 +471,7 @@ static void rna_def_fluidsim_volume(StructRNA *srna) static void rna_def_fluidsim_active(StructRNA *srna) { PropertyRNA *prop; - + prop = RNA_def_property(srna, "use", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", OB_FLUIDSIM_ACTIVE); RNA_def_property_ui_text(prop, "Enabled", "Object contributes to the fluid simulation"); @@ -489,7 +489,7 @@ static void rna_def_fluidsim_fluid(BlenderRNA *brna) rna_def_fluidsim_active(srna); rna_def_fluidsim_volume(srna); - + prop = RNA_def_property(srna, "initial_velocity", PROP_FLOAT, PROP_VELOCITY); RNA_def_property_float_sdna(prop, NULL, "iniVelx"); RNA_def_property_array(prop, 3); @@ -615,12 +615,12 @@ static void rna_def_fluidsim_control(BlenderRNA *brna) "Fluid simulation settings for objects controlling the motion of fluid in the simulation"); rna_def_fluidsim_active(srna); - + prop = RNA_def_property(srna, "start_time", PROP_FLOAT, PROP_TIME); RNA_def_property_float_sdna(prop, NULL, "cpsTimeStart"); RNA_def_property_range(prop, 0.0, FLT_MAX); RNA_def_property_ui_text(prop, "Start Time", "Time when the control particles are activated"); - + prop = RNA_def_property(srna, "end_time", PROP_FLOAT, PROP_TIME); RNA_def_property_float_sdna(prop, NULL, "cpsTimeEnd"); RNA_def_property_range(prop, 0.0, FLT_MAX); @@ -636,7 +636,7 @@ static void rna_def_fluidsim_control(BlenderRNA *brna) RNA_def_property_float_sdna(prop, NULL, "attractforceRadius"); RNA_def_property_range(prop, 0.0, 10.0); RNA_def_property_ui_text(prop, "Attraction Radius", "Force field radius around the control object"); - + prop = RNA_def_property(srna, "velocity_strength", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "velocityforceStrength"); RNA_def_property_range(prop, 0.0, 10.0); diff --git a/source/blender/makesrna/intern/rna_gpencil.c b/source/blender/makesrna/intern/rna_gpencil.c index b15f6dbccfa..51aed1ff296 100644 --- a/source/blender/makesrna/intern/rna_gpencil.c +++ b/source/blender/makesrna/intern/rna_gpencil.c @@ -82,7 +82,7 @@ static void rna_GPencil_onion_skinning_update(Main *bmain, Scene *scene, Pointer bGPdata *gpd = (bGPdata *)ptr->id.data; bGPDlayer *gpl; bool enabled = false; - + /* Ensure that the datablock's onionskinning toggle flag * stays in sync with the status of the actual layers */ @@ -91,13 +91,13 @@ static void rna_GPencil_onion_skinning_update(Main *bmain, Scene *scene, Pointer enabled = true; } } - + if (enabled) gpd->flag |= GP_DATA_SHOW_ONIONSKINS; else gpd->flag &= ~GP_DATA_SHOW_ONIONSKINS; - - + + /* Now do standard updates... */ rna_GPencil_update(bmain, scene, ptr); } @@ -116,9 +116,9 @@ static char *rna_GPencilLayer_path(PointerRNA *ptr) { bGPDlayer *gpl = (bGPDlayer *)ptr->data; char name_esc[sizeof(gpl->info) * 2]; - + BLI_strescape(name_esc, gpl->info, sizeof(name_esc)); - + return BLI_sprintfN("layers[\"%s\"]", name_esc); } @@ -137,7 +137,7 @@ static void rna_GPencilLayer_line_width_range(PointerRNA *ptr, int *min, int *ma int *softmin, int *softmax) { bGPDlayer *gpl = ptr->data; - + /* The restrictions on max width here are due to OpenGL on Windows not supporting * any widths greater than 10 (for driver-drawn) strokes/points. * @@ -150,14 +150,14 @@ static void rna_GPencilLayer_line_width_range(PointerRNA *ptr, int *min, int *ma if (gpl->flag & GP_LAYER_VOLUMETRIC) { *min = -300; *max = 300; - + *softmin = -100; *softmax = 100; } else { *min = -10; *max = 10; - + *softmin = -10; *softmax = 10; } @@ -196,7 +196,7 @@ static void set_parent(bGPDlayer *gpl, Object *par, const int type, const char * static void rna_GPencilLayer_parent_set(PointerRNA *ptr, PointerRNA value) { bGPDlayer *gpl = (bGPDlayer *)ptr->data; - Object *par = (Object *)value.data; + Object *par = (Object *)value.data; if (par != NULL) { set_parent(gpl, par, gpl->partype, gpl->parsubstr); @@ -317,7 +317,7 @@ static void rna_GPencil_active_layer_set(PointerRNA *ptr, PointerRNA value) gl->flag &= ~GP_LAYER_ACTIVE; } } - + WM_main_add_notifier(NC_GPENCIL | NA_EDITED, NULL); } } @@ -326,7 +326,7 @@ static int rna_GPencil_active_layer_index_get(PointerRNA *ptr) { bGPdata *gpd = (bGPdata *)ptr->id.data; bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd); - + return BLI_findindex(&gpd->layers, gpl); } @@ -370,7 +370,7 @@ static void rna_GPencil_use_onion_skinning_set(PointerRNA *ptr, const int value) { bGPdata *gpd = ptr->id.data; bGPDlayer *gpl; - + /* set new value */ if (value) { /* enable on active layer (it's the one that's most likely to be of interest right now) */ @@ -378,7 +378,7 @@ static void rna_GPencil_use_onion_skinning_set(PointerRNA *ptr, const int value) if (gpl) { gpl->flag |= GP_LAYER_ONIONSKIN; } - + gpd->flag |= GP_DATA_SHOW_ONIONSKINS; } else { @@ -386,7 +386,7 @@ static void rna_GPencil_use_onion_skinning_set(PointerRNA *ptr, const int value) for (gpl = gpd->layers.first; gpl; gpl = gpl->next) { gpl->flag &= ~GP_LAYER_ONIONSKIN; } - + gpd->flag &= ~GP_DATA_SHOW_ONIONSKINS; } } @@ -395,15 +395,15 @@ static bGPDstroke *rna_GPencil_stroke_point_find_stroke(const bGPdata *gpd, cons { bGPDlayer *gpl; bGPDstroke *gps; - + /* sanity checks */ if (ELEM(NULL, gpd, pt)) { return NULL; } - + if (r_gpl) *r_gpl = NULL; if (r_gpf) *r_gpf = NULL; - + /* there's no faster alternative than just looping over everything... */ for (gpl = gpd->layers.first; gpl; gpl = gpl->next) { if (gpl->actframe) { @@ -412,13 +412,13 @@ static bGPDstroke *rna_GPencil_stroke_point_find_stroke(const bGPdata *gpd, cons /* found it */ if (r_gpl) *r_gpl = gpl; if (r_gpf) *r_gpf = gpl->actframe; - + return gps; } } } } - + /* didn't find it */ return NULL; } @@ -428,8 +428,8 @@ static void rna_GPencil_stroke_point_select_set(PointerRNA *ptr, const int value bGPdata *gpd = ptr->id.data; bGPDspoint *pt = ptr->data; bGPDstroke *gps = NULL; - - /* Ensure that corresponding stroke is set + + /* Ensure that corresponding stroke is set * - Since we don't have direct access, we're going to have to search * - We don't apply selection value unless we can find the corresponding * stroke, so that they don't get out of sync @@ -441,7 +441,7 @@ static void rna_GPencil_stroke_point_select_set(PointerRNA *ptr, const int value pt->flag |= GP_SPOINT_SELECT; else pt->flag &= ~GP_SPOINT_SELECT; - + /* Check if the stroke should be selected or not... */ BKE_gpencil_stroke_sync_selection(gps); } @@ -454,7 +454,7 @@ static void rna_GPencil_stroke_point_add(bGPDstroke *stroke, int count, float pr stroke->points = MEM_recallocN_id(stroke->points, sizeof(bGPDspoint) * (stroke->totpoints + count), "gp_stroke_points"); - + /* init the pressure and strength values so that old scripts won't need to * be modified to give these initial values... */ @@ -463,7 +463,7 @@ static void rna_GPencil_stroke_point_add(bGPDstroke *stroke, int count, float pr pt->pressure = pressure; pt->strength = strength; } - + stroke->totpoints += count; } } @@ -530,13 +530,13 @@ static void rna_GPencil_stroke_select_set(PointerRNA *ptr, const int value) bGPDstroke *gps = ptr->data; bGPDspoint *pt; int i; - + /* set new value */ if (value) gps->flag |= GP_STROKE_SELECT; else gps->flag &= ~GP_STROKE_SELECT; - + /* ensure that the stroke's points are selected in the same way */ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { if (value) @@ -800,9 +800,9 @@ static char *rna_GPencilPalette_path(PointerRNA *ptr) { bGPDpalette *palette = ptr->data; char name_esc[sizeof(palette->info) * 2]; - + BLI_strescape(name_esc, palette->info, sizeof(name_esc)); - + return BLI_sprintfN("palettes[\"%s\"]", name_esc); } @@ -826,7 +826,7 @@ static void rna_GPencilPaletteColor_info_set(PointerRNA *ptr, const char *value) bGPdata *gpd = ptr->id.data; bGPDpalette *palette = BKE_gpencil_palette_getactive(gpd); bGPDpalettecolor *palcolor = ptr->data; - + char oldname[64] = ""; BLI_strncpy(oldname, palcolor->info, sizeof(oldname)); @@ -834,7 +834,7 @@ static void rna_GPencilPaletteColor_info_set(PointerRNA *ptr, const char *value) BLI_strncpy_utf8(palcolor->info, value, sizeof(palcolor->info)); BLI_uniquename(&palette->colors, palcolor, DATA_("Color"), '.', offsetof(bGPDpalettecolor, info), sizeof(palcolor->info)); - + /* rename all strokes */ BKE_gpencil_palettecolor_changename(gpd, oldname, palcolor->info); @@ -895,23 +895,23 @@ static void rna_def_gpencil_stroke_point(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + srna = RNA_def_struct(brna, "GPencilStrokePoint", NULL); RNA_def_struct_sdna(srna, "bGPDspoint"); RNA_def_struct_ui_text(srna, "Grease Pencil Stroke Point", "Data point for freehand stroke curve"); - + prop = RNA_def_property(srna, "co", PROP_FLOAT, PROP_XYZ); RNA_def_property_float_sdna(prop, NULL, "x"); RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Coordinates", ""); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); - + prop = RNA_def_property(srna, "pressure", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "pressure"); RNA_def_property_range(prop, 0.0f, 1.0f); 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"); - + prop = RNA_def_property(srna, "strength", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "strength"); RNA_def_property_range(prop, 0.0f, 1.0f); @@ -988,18 +988,18 @@ static void rna_def_gpencil_stroke(BlenderRNA *brna) {GP_STROKE_2DIMAGE, "2DIMAGE", 0, "2D Image", "Stroke is in 2D-space (but with special 'image' scaling)"}, {0, NULL, 0, NULL, NULL} }; - + srna = RNA_def_struct(brna, "GPencilStroke", NULL); RNA_def_struct_sdna(srna, "bGPDstroke"); RNA_def_struct_ui_text(srna, "Grease Pencil Stroke", "Freehand curve defining part of a sketch"); - + /* Points */ prop = RNA_def_property(srna, "points", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "points", "totpoints"); RNA_def_property_struct_type(prop, "GPencilStrokePoint"); RNA_def_property_ui_text(prop, "Stroke Points", "Stroke data points"); rna_def_gpencil_stroke_points_api(brna, prop); - + /* Triangles */ prop = RNA_def_property(srna, "triangles", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "triangles", "tot_triangles"); @@ -1019,7 +1019,7 @@ static void rna_def_gpencil_stroke(BlenderRNA *brna) RNA_def_property_enum_items(prop, stroke_draw_mode_items); RNA_def_property_ui_text(prop, "Draw Mode", ""); RNA_def_property_update(prop, 0, "rna_GPencil_update"); - + prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_STROKE_SELECT); RNA_def_property_boolean_funcs(prop, NULL, "rna_GPencil_stroke_select_set"); @@ -1080,11 +1080,11 @@ static void rna_def_gpencil_frame(BlenderRNA *brna) PropertyRNA *prop; FunctionRNA *func; - + srna = RNA_def_struct(brna, "GPencilFrame", NULL); RNA_def_struct_sdna(srna, "bGPDframe"); RNA_def_struct_ui_text(srna, "Grease Pencil Frame", "Collection of related sketches on a particular frame"); - + /* Strokes */ prop = RNA_def_property(srna, "strokes", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "strokes", NULL); @@ -1098,17 +1098,17 @@ static void rna_def_gpencil_frame(BlenderRNA *brna) /* XXX note: this cannot occur on the same frame as another sketch */ RNA_def_property_range(prop, -MAXFRAME, MAXFRAME); RNA_def_property_ui_text(prop, "Frame Number", "The frame on which this sketch appears"); - + /* Flags */ prop = RNA_def_property(srna, "is_edited", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_FRAME_PAINT); /* XXX should it be editable? */ RNA_def_property_ui_text(prop, "Paint Lock", "Frame is being edited (painted on)"); - + prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_FRAME_SELECT); RNA_def_property_ui_text(prop, "Select", "Frame is selected for editing in the Dope Sheet"); - - + + /* API */ func = RNA_def_function(srna, "clear", "rna_GPencil_frame_clear"); RNA_def_function_ui_description(func, "Remove all the grease pencil frame data"); @@ -1156,12 +1156,12 @@ static void rna_def_gpencil_layer(BlenderRNA *brna) PropertyRNA *prop; FunctionRNA *func; - + srna = RNA_def_struct(brna, "GPencilLayer", NULL); RNA_def_struct_sdna(srna, "bGPDlayer"); RNA_def_struct_ui_text(srna, "Grease Pencil Layer", "Collection of related sketches"); RNA_def_struct_path_func(srna, "rna_GPencilLayer_path"); - + /* Name */ prop = RNA_def_property(srna, "info", PROP_STRING, PROP_NONE); RNA_def_property_ui_text(prop, "Info", "Layer name"); @@ -1190,13 +1190,13 @@ static void rna_def_gpencil_layer(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Volumetric Strokes", "Draw strokes as a series of circular blobs, resulting in a volumetric effect"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); - + prop = RNA_def_property(srna, "opacity", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "opacity"); RNA_def_property_range(prop, 0.0, 1.0f); RNA_def_property_ui_text(prop, "Opacity", "Layer Opacity"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); - + /* Tint Color */ prop = RNA_def_property(srna, "tint_color", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "tintcolor"); @@ -1204,14 +1204,14 @@ static void rna_def_gpencil_layer(BlenderRNA *brna) RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Tint Color", "Color for tinting stroke colors"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); - + /* Tint factor */ prop = RNA_def_property(srna, "tint_factor", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "tintcolor[3]"); RNA_def_property_range(prop, 0.0, 1.0f); RNA_def_property_ui_text(prop, "Tint Factor", "Factor of tinting color"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); - + /* Line Thickness change */ prop = RNA_def_property(srna, "line_change", PROP_INT, PROP_PIXEL); RNA_def_property_int_sdna(prop, NULL, "thickness"); @@ -1219,13 +1219,13 @@ static void rna_def_gpencil_layer(BlenderRNA *brna) RNA_def_property_int_funcs(prop, NULL, NULL, "rna_GPencilLayer_line_width_range"); RNA_def_property_ui_text(prop, "Thickness", "Thickness change to apply to current strokes (in pixels)"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); - + /* Onion-Skinning */ prop = RNA_def_property(srna, "use_onion_skinning", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_ONIONSKIN); RNA_def_property_ui_text(prop, "Onion Skinning", "Ghost frames on either side of frame"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_onion_skinning_update"); - + prop = RNA_def_property(srna, "ghost_before_range", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "gstep"); RNA_def_property_range(prop, -1, 120); @@ -1233,7 +1233,7 @@ static void rna_def_gpencil_layer(BlenderRNA *brna) "Maximum number of frames to show before current frame " "(0 = show only the previous sketch, -1 = don't show any frames before current)"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); - + prop = RNA_def_property(srna, "ghost_after_range", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "gstep_next"); RNA_def_property_range(prop, -1, 120); @@ -1241,46 +1241,46 @@ static void rna_def_gpencil_layer(BlenderRNA *brna) "Maximum number of frames to show after current frame " "(0 = show only the next sketch, -1 = don't show any frames after current)"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); - + prop = RNA_def_property(srna, "use_ghost_custom_colors", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_GHOST_PREVCOL | GP_LAYER_GHOST_NEXTCOL); RNA_def_property_ui_text(prop, "Use Custom Ghost Colors", "Use custom colors for ghost frames"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); - + prop = RNA_def_property(srna, "before_color", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "gcolor_prev"); RNA_def_property_array(prop, 3); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Before Color", "Base color for ghosts before the active frame"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); - + prop = RNA_def_property(srna, "after_color", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "gcolor_next"); RNA_def_property_array(prop, 3); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "After Color", "Base color for ghosts after the active frame"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); - + prop = RNA_def_property(srna, "use_ghosts_always", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_GHOST_ALWAYS); RNA_def_property_ui_text(prop, "Always Show Ghosts", "Ghosts are shown in renders and animation playback. Useful for special effects (e.g. motion blur)"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); - - + + /* Flags */ prop = RNA_def_property(srna, "hide", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_HIDE); RNA_def_property_ui_icon(prop, ICON_RESTRICT_VIEW_OFF, 1); RNA_def_property_ui_text(prop, "Hide", "Set layer Visibility"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); - + prop = RNA_def_property(srna, "lock", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_LOCKED); RNA_def_property_ui_icon(prop, ICON_UNLOCKED, 1); RNA_def_property_ui_text(prop, "Locked", "Protect layer from further editing and/or frame changes"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); - + prop = RNA_def_property(srna, "lock_frame", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_FRAMELOCK); RNA_def_property_ui_icon(prop, ICON_UNLOCKED, 1); @@ -1309,23 +1309,23 @@ static void rna_def_gpencil_layer(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_SELECT); RNA_def_property_ui_text(prop, "Select", "Layer is selected for editing in the Dope Sheet"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA | NA_SELECTED, "rna_GPencil_update"); - + /* XXX keep this option? */ prop = RNA_def_property(srna, "show_points", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_DRAWDEBUG); RNA_def_property_ui_text(prop, "Show Points", "Draw the points which make up the strokes (for debugging purposes)"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); - + /* X-Ray */ prop = RNA_def_property(srna, "show_x_ray", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", GP_LAYER_NO_XRAY); RNA_def_property_ui_text(prop, "X Ray", "Make the layer draw in front of objects"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); - + /* Parent object */ prop = RNA_def_property(srna, "parent", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_funcs(prop, NULL, "rna_GPencilLayer_parent_set", NULL, NULL); - RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); RNA_def_property_ui_text(prop, "Parent", "Parent Object"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); @@ -1397,11 +1397,11 @@ static void rna_def_gpencil_layers_api(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Active Layer", "Active grease pencil layer"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA | NA_SELECTED, NULL); - + prop = RNA_def_property(srna, "active_index", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_funcs(prop, - "rna_GPencil_active_layer_index_get", - "rna_GPencil_active_layer_index_set", + "rna_GPencil_active_layer_index_get", + "rna_GPencil_active_layer_index_set", "rna_GPencil_active_layer_index_range"); RNA_def_property_ui_text(prop, "Active Layer Index", "Index of active grease pencil layer"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA | NA_SELECTED, NULL); @@ -1620,14 +1620,14 @@ static void rna_def_gpencil_data(BlenderRNA *brna) RNA_def_struct_sdna(srna, "bGPdata"); RNA_def_struct_ui_text(srna, "Grease Pencil", "Freehand annotation sketchbook"); RNA_def_struct_ui_icon(srna, ICON_GREASEPENCIL); - + /* Layers */ prop = RNA_def_property(srna, "layers", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "layers", NULL); RNA_def_property_struct_type(prop, "GPencilLayer"); RNA_def_property_ui_text(prop, "Layers", ""); rna_def_gpencil_layers_api(brna, prop); - + /* Palettes */ prop = RNA_def_property(srna, "palettes", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "palettes", NULL); @@ -1637,20 +1637,20 @@ static void rna_def_gpencil_data(BlenderRNA *brna) /* Animation Data */ rna_def_animdata_common(srna); - + /* Flags */ prop = RNA_def_property(srna, "use_stroke_edit_mode", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_DATA_STROKE_EDITMODE); RNA_def_property_ui_text(prop, "Stroke Edit Mode", "Edit Grease Pencil strokes instead of viewport data"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA | ND_GPENCIL_EDITMODE, "rna_GPencil_editmode_update"); - + prop = RNA_def_property(srna, "use_onion_skinning", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_DATA_SHOW_ONIONSKINS); RNA_def_property_boolean_funcs(prop, NULL, "rna_GPencil_use_onion_skinning_set"); - RNA_def_property_ui_text(prop, "Onion Skins", + RNA_def_property_ui_text(prop, "Onion Skins", "Show ghosts of the frames before and after the current frame, toggle to enable on active layer or disable all"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); - + prop = RNA_def_property(srna, "show_stroke_direction", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_DATA_SHOW_DIRECTION); RNA_def_property_ui_text(prop, "Show Direction", "Show stroke drawing direction with a bigger green dot (start) " diff --git a/source/blender/makesrna/intern/rna_group.c b/source/blender/makesrna/intern/rna_group.c index f064e3eb630..de6c6883977 100644 --- a/source/blender/makesrna/intern/rna_group.c +++ b/source/blender/makesrna/intern/rna_group.c @@ -158,7 +158,7 @@ static void rna_def_collection_objects(BlenderRNA *brna, PropertyRNA *cprop) StructRNA *srna; FunctionRNA *func; PropertyRNA *parm; - + RNA_def_property_srna(cprop, "CollectionObjects"); srna = RNA_def_struct(brna, "CollectionObjects", NULL); RNA_def_struct_sdna(srna, "Collection"); diff --git a/source/blender/makesrna/intern/rna_image.c b/source/blender/makesrna/intern/rna_image.c index cd0824733b9..d2b9ee47765 100644 --- a/source/blender/makesrna/intern/rna_image.c +++ b/source/blender/makesrna/intern/rna_image.c @@ -67,6 +67,7 @@ static const EnumPropertyItem image_source_items[] = { #include "BKE_global.h" #include "GPU_draw.h" +#include "GPU_texture.h" #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" @@ -92,12 +93,12 @@ static void rna_Image_source_set(PointerRNA *ptr, int value) if (value != ima->source) { ima->source = value; - BKE_image_signal(ima, NULL, IMA_SIGNAL_SRC_CHANGE); + BKE_image_signal(G.main, ima, NULL, IMA_SIGNAL_SRC_CHANGE); DEG_id_tag_update(&ima->id, 0); } } -static void rna_Image_fields_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) +static void rna_Image_fields_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { Image *ima = ptr->id.data; ImBuf *ibuf; @@ -112,36 +113,36 @@ static void rna_Image_fields_update(Main *UNUSED(bmain), Scene *UNUSED(scene), P if ((ima->flag & IMA_FIELDS) && !(ibuf->flags & IB_fields)) nr = 1; if (nr) - BKE_image_signal(ima, NULL, IMA_SIGNAL_FREE); + BKE_image_signal(bmain, ima, NULL, IMA_SIGNAL_FREE); } BKE_image_release_ibuf(ima, ibuf, lock); } -static void rna_Image_reload_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) +static void rna_Image_reload_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { Image *ima = ptr->id.data; - BKE_image_signal(ima, NULL, IMA_SIGNAL_RELOAD); + BKE_image_signal(bmain, ima, NULL, IMA_SIGNAL_RELOAD); WM_main_add_notifier(NC_IMAGE | NA_EDITED, &ima->id); DEG_id_tag_update(&ima->id, 0); } -static void rna_Image_generated_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) +static void rna_Image_generated_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { Image *ima = ptr->id.data; - BKE_image_signal(ima, NULL, IMA_SIGNAL_FREE); + BKE_image_signal(bmain, ima, NULL, IMA_SIGNAL_FREE); } -static void rna_Image_colormanage_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) +static void rna_Image_colormanage_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { Image *ima = ptr->id.data; - BKE_image_signal(ima, NULL, IMA_SIGNAL_COLORMANAGE); + BKE_image_signal(bmain, ima, NULL, IMA_SIGNAL_COLORMANAGE); DEG_id_tag_update(&ima->id, 0); WM_main_add_notifier(NC_IMAGE | ND_DISPLAY, &ima->id); WM_main_add_notifier(NC_IMAGE | NA_EDITED, &ima->id); } -static void rna_Image_views_format_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr) +static void rna_Image_views_format_update(Main *bmain, Scene *scene, PointerRNA *ptr) { Image *ima = ptr->id.data; ImBuf *ibuf; @@ -152,7 +153,7 @@ static void rna_Image_views_format_update(Main *UNUSED(bmain), Scene *scene, Poi if (ibuf) { ImageUser iuser = {NULL}; iuser.scene = scene; - BKE_image_signal(ima, &iuser, IMA_SIGNAL_FREE); + BKE_image_signal(bmain, ima, &iuser, IMA_SIGNAL_FREE); } BKE_image_release_ibuf(ima, ibuf, lock); @@ -175,7 +176,7 @@ static char *rna_ImageUser_path(PointerRNA *ptr) { if (ptr->id.data) { /* ImageUser *iuser = ptr->data; */ - + switch (GS(((ID *)ptr->id.data)->name)) { case ID_OB: case ID_TE: @@ -190,7 +191,7 @@ static char *rna_ImageUser_path(PointerRNA *ptr) break; } } - + return BLI_strdup(""); } @@ -200,7 +201,7 @@ static const EnumPropertyItem *rna_Image_source_itemf(bContext *UNUSED(C), Point Image *ima = (Image *)ptr->data; EnumPropertyItem *item = NULL; int totitem = 0; - + if (ima->source == IMA_SRC_VIEWER) { RNA_enum_items_add_value(&item, &totitem, image_source_items, IMA_SRC_VIEWER); } @@ -298,13 +299,20 @@ static void rna_Image_resolution_set(PointerRNA *ptr, const float *values) BKE_image_release_ibuf(im, ibuf, lock); } +static int rna_Image_bindcode_get(PointerRNA *ptr) +{ + Image *ima = (Image *)ptr->data; + GPUTexture *tex = ima->gputexture[TEXTARGET_TEXTURE_2D]; + return (tex) ? GPU_texture_opengl_bindcode(tex) : 0; +} + static int rna_Image_depth_get(PointerRNA *ptr) { Image *im = (Image *)ptr->data; ImBuf *ibuf; void *lock; int planes; - + ibuf = BKE_image_acquire_ibuf(im, NULL, &lock); if (!ibuf) @@ -454,16 +462,19 @@ static PointerRNA rna_Image_packed_file_get(PointerRNA *ptr) } } -static void rna_Image_render_slots_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) +static void rna_RenderSlot_clear(ID *id, RenderSlot *slot, ImageUser *iuser) { - Image *image = (Image *)ptr->id.data; - rna_iterator_array_begin(iter, (void *)image->render_slots, sizeof(RenderSlot), IMA_MAX_RENDER_SLOT, 0, NULL); + Image *image = (Image *) id; + int index = BLI_findindex(&image->renderslots, slot); + BKE_image_clear_renderslot(image, iuser, index); + + WM_main_add_notifier(NC_IMAGE | ND_DISPLAY, image); } static PointerRNA rna_render_slots_active_get(PointerRNA *ptr) { Image *image = (Image *)ptr->id.data; - RenderSlot *render_slot = &image->render_slots[image->render_slot]; + RenderSlot *render_slot = BKE_image_get_renderslot(image, image->render_slot); return rna_pointer_inherit_refine(ptr, &RNA_RenderSlot, render_slot); } @@ -472,9 +483,9 @@ static void rna_render_slots_active_set(PointerRNA *ptr, PointerRNA value) { Image *image = (Image *)ptr->id.data; if (value.id.data == image) { - RenderSlot *render_slot = (RenderSlot *)value.data; - int index = render_slot - image->render_slots; - image->render_slot = CLAMPIS(index, 0, IMA_MAX_RENDER_SLOT - 1); + RenderSlot *slot = (RenderSlot *)value.data; + int index = BLI_findindex(&image->renderslots, slot); + if (index != -1) image->render_slot = index; } } @@ -487,8 +498,17 @@ static int rna_render_slots_active_index_get(PointerRNA *ptr) static void rna_render_slots_active_index_set(PointerRNA *ptr, int value) { Image *image = (Image *)ptr->id.data; + int num_slots = BLI_listbase_count(&image->renderslots); image->render_slot = value; - CLAMP(image->render_slot, 0, IMA_MAX_RENDER_SLOT - 1); + CLAMP(image->render_slot, 0, num_slots - 1); +} + +static void rna_render_slots_active_index_range(PointerRNA *ptr, int *min, int *max, + int *UNUSED(softmin), int *UNUSED(softmax)) +{ + Image *image = (Image *)ptr->id.data; + *min = 0; + *max = max_ii(0, BLI_listbase_count(&image->renderslots) - 1); } #else @@ -588,7 +608,9 @@ static void rna_def_image_packed_files(BlenderRNA *brna) static void rna_def_render_slot(BlenderRNA *brna) { StructRNA *srna; - PropertyRNA *prop; + PropertyRNA *prop, *parm; + FunctionRNA *func; + srna = RNA_def_struct(brna, "RenderSlot", NULL); RNA_def_struct_ui_text(srna, "Render Slot", "Parameters defining the render slot"); @@ -596,32 +618,45 @@ static void rna_def_render_slot(BlenderRNA *brna) RNA_def_property_string_sdna(prop, NULL, "name"); RNA_def_property_ui_text(prop, "Name", "Render slot name"); RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, NULL); + + func = RNA_def_function(srna, "clear", "rna_RenderSlot_clear"); + RNA_def_function_flag(func, FUNC_USE_SELF_ID); + RNA_def_function_ui_description(func, "Clear the render slot"); + parm = RNA_def_pointer(func, "iuser", "ImageUser", "ImageUser", ""); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); } -static void rna_def_render_slots(BlenderRNA *brna) +static void rna_def_render_slots(BlenderRNA *brna, PropertyRNA *cprop) { StructRNA *srna; - PropertyRNA *prop; + FunctionRNA *func; + PropertyRNA *prop, *parm; + RNA_def_property_srna(cprop, "RenderSlots"); srna = RNA_def_struct(brna, "RenderSlots", NULL); - RNA_def_struct_sdna(srna, "RenderSlot"); - RNA_def_struct_ui_text(srna, "Render Slots", "Collection of the render slots"); + RNA_def_struct_sdna(srna, "Image"); + RNA_def_struct_ui_text(srna, "Render Layers", "Collection of render layers"); + + prop = RNA_def_property(srna, "active_index", PROP_INT, PROP_UNSIGNED); + RNA_def_property_int_sdna(prop, NULL, "render_slot"); + RNA_def_property_int_funcs(prop, "rna_render_slots_active_index_get", + "rna_render_slots_active_index_set", + "rna_render_slots_active_index_range"); + RNA_def_property_ui_text(prop, "Active", "Active render slot of the image"); + RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, NULL); prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "RenderSlot"); RNA_def_property_pointer_funcs(prop, "rna_render_slots_active_get", "rna_render_slots_active_set", NULL, NULL); - RNA_def_property_flag(prop, PROP_EDITABLE | PROP_NEVER_UNLINK); + RNA_def_property_flag(prop, PROP_EDITABLE | PROP_NEVER_NULL); RNA_def_property_ui_text(prop, "Active", "Active render slot of the image"); RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, NULL); - prop = RNA_def_property(srna, "active_index", PROP_INT, PROP_NONE); - RNA_def_property_int_funcs(prop, "rna_render_slots_active_index_get", - "rna_render_slots_active_index_set", - NULL); - RNA_def_property_range(prop, 0, IMA_MAX_RENDER_SLOT); - RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_ui_text(prop, "Active Index", "Index of an active render slot of the image"); - RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, NULL); + func = RNA_def_function(srna, "new", "BKE_image_add_renderslot"); + RNA_def_function_ui_description(func, "Add a render slot to the image"); + parm = RNA_def_string(func, "name", NULL, 0, "Name", "New name for the render slot"); + parm = RNA_def_pointer(func, "result", "RenderSlot", "", "Newly created render layer"); + RNA_def_function_return(func, parm); } static void rna_def_image(BlenderRNA *brna) @@ -705,7 +740,7 @@ static void rna_def_image(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Fields", "Use fields of the image"); RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_fields_update"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - + prop = RNA_def_property(srna, "use_view_as_render", PROP_BOOLEAN, PROP_NONE); RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC); @@ -756,7 +791,7 @@ static void rna_def_image(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Generated Type", "Generated image type"); RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_generated_update"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - + prop = RNA_def_property(srna, "generated_width", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "gen_x"); RNA_def_property_flag(prop, PROP_PROPORTIONAL); @@ -764,7 +799,7 @@ static void rna_def_image(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Generated Width", "Generated image width"); RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_generated_update"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - + prop = RNA_def_property(srna, "generated_height", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "gen_y"); RNA_def_property_flag(prop, PROP_PROPORTIONAL); @@ -772,7 +807,7 @@ static void rna_def_image(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Generated Height", "Generated image height"); RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_generated_update"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - + prop = RNA_def_property(srna, "use_generated_float", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "gen_flag", IMA_GEN_FLOAT); RNA_def_property_ui_text(prop, "Float Buffer", "Generate floating point buffer"); @@ -796,17 +831,16 @@ static void rna_def_image(BlenderRNA *brna) RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, NULL); prop = RNA_def_property(srna, "bindcode", PROP_INT, PROP_UNSIGNED); - RNA_def_property_int_sdna(prop, NULL, "bindcode"); + RNA_def_property_int_funcs(prop, "rna_Image_bindcode_get", NULL, NULL); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Bindcode", "OpenGL bindcode"); RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, NULL); prop = RNA_def_property(srna, "render_slots", PROP_COLLECTION, PROP_NONE); RNA_def_property_struct_type(prop, "RenderSlot"); + RNA_def_property_collection_sdna(prop, NULL, "renderslots", NULL); RNA_def_property_ui_text(prop, "Render Slots", "Render slots of the image"); - RNA_def_property_collection_funcs(prop, "rna_Image_render_slots_begin", "rna_iterator_array_next", - "rna_iterator_array_end", "rna_iterator_array_get", NULL, NULL, NULL, NULL); - RNA_def_property_srna(prop, "RenderSlots"); + rna_def_render_slots(brna, prop); /* * Image.has_data and Image.depth are temporary, @@ -889,7 +923,6 @@ static void rna_def_image(BlenderRNA *brna) void RNA_def_image(BlenderRNA *brna) { rna_def_render_slot(brna); - rna_def_render_slots(brna); rna_def_image(brna); rna_def_imageuser(brna); rna_def_image_packed_files(brna); diff --git a/source/blender/makesrna/intern/rna_image_api.c b/source/blender/makesrna/intern/rna_image_api.c index 2070ea0a559..d839995d15e 100644 --- a/source/blender/makesrna/intern/rna_image_api.c +++ b/source/blender/makesrna/intern/rna_image_api.c @@ -189,9 +189,9 @@ static void rna_Image_unpack(Image *image, Main *bmain, ReportList *reports, int } } -static void rna_Image_reload(Image *image) +static void rna_Image_reload(Image *image, Main *bmain) { - BKE_image_signal(image, NULL, IMA_SIGNAL_RELOAD); + BKE_image_signal(bmain, image, NULL, IMA_SIGNAL_RELOAD); } static void rna_Image_update(Image *image, ReportList *reports) @@ -220,29 +220,30 @@ static void rna_Image_scale(Image *image, ReportList *reports, int width, int he static int rna_Image_gl_load(Image *image, ReportList *reports, int frame, int filter, int mag) { - ImBuf *ibuf; - unsigned int *bind = &image->bindcode[TEXTARGET_TEXTURE_2D]; + GPUTexture *tex = image->gputexture[TEXTARGET_TEXTURE_2D]; int error = GL_NO_ERROR; - ImageUser iuser = {NULL}; - void *lock; - if (*bind) + if (tex) return error; + + ImageUser iuser = {NULL}; iuser.framenr = frame; iuser.ok = true; - ibuf = BKE_image_acquire_ibuf(image, &iuser, &lock); + void *lock; + ImBuf *ibuf = BKE_image_acquire_ibuf(image, &iuser, &lock); /* clean glError buffer */ while (glGetError() != GL_NO_ERROR) {} if (ibuf == NULL || ibuf->rect == NULL) { BKE_reportf(reports, RPT_ERROR, "Image '%s' does not have any image data", image->id.name + 2); - BKE_image_release_ibuf(image, ibuf, NULL); + BKE_image_release_ibuf(image, ibuf, lock); return (int)GL_INVALID_OPERATION; } - GPU_create_gl_tex(bind, ibuf->rect, ibuf->rect_float, ibuf->x, ibuf->y, GL_TEXTURE_2D, + unsigned int bindcode = 0; + GPU_create_gl_tex(&bindcode, ibuf->rect, ibuf->rect_float, ibuf->x, ibuf->y, GL_TEXTURE_2D, (filter != GL_NEAREST && filter != GL_LINEAR), false, image); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (GLint)filter); @@ -253,23 +254,24 @@ static int rna_Image_gl_load(Image *image, ReportList *reports, int frame, int f error = glGetError(); if (error) { - glDeleteTextures(1, (GLuint *)bind); - image->bindcode[TEXTARGET_TEXTURE_2D] = 0; + glDeleteTextures(1, (GLuint *)&bindcode); + } + else { + image->gputexture[TEXTARGET_TEXTURE_2D] = GPU_texture_from_bindcode(GL_TEXTURE_2D, bindcode); } - BKE_image_release_ibuf(image, ibuf, NULL); + BKE_image_release_ibuf(image, ibuf, lock); return error; } static int rna_Image_gl_touch(Image *image, ReportList *reports, int frame, int filter, int mag) { - unsigned int *bind = &image->bindcode[TEXTARGET_TEXTURE_2D]; int error = GL_NO_ERROR; BKE_image_tag_time(image); - if (*bind == 0) + if (image->gputexture[TEXTARGET_TEXTURE_2D] == NULL) error = rna_Image_gl_load(image, reports, frame, filter, mag); return error; @@ -335,6 +337,7 @@ void RNA_api_image(StructRNA *srna) RNA_def_enum(func, "method", rna_enum_unpack_method_items, PF_USE_LOCAL, "method", "How to unpack"); func = RNA_def_function(srna, "reload", "rna_Image_reload"); + RNA_def_function_flag(func, FUNC_USE_MAIN); RNA_def_function_ui_description(func, "Reload the image from its source path"); func = RNA_def_function(srna, "update", "rna_Image_update"); diff --git a/source/blender/makesrna/intern/rna_key.c b/source/blender/makesrna/intern/rna_key.c index 472298a3053..11fb5f7f94b 100644 --- a/source/blender/makesrna/intern/rna_key.c +++ b/source/blender/makesrna/intern/rna_key.c @@ -75,20 +75,20 @@ static void rna_ShapeKey_name_set(PointerRNA *ptr, const char *value) { KeyBlock *kb = ptr->data; char oldname[sizeof(kb->name)]; - + /* make a copy of the old name first */ BLI_strncpy(oldname, kb->name, sizeof(kb->name)); - + /* copy the new name into the name slot */ BLI_strncpy_utf8(kb->name, value, sizeof(kb->name)); - + /* make sure the name is truly unique */ if (ptr->id.data) { Key *key = rna_ShapeKey_find_key(ptr->id.data); BLI_uniquename(&key->block, kb, CTX_DATA_(BLT_I18NCONTEXT_ID_SHAPEKEY, "Key"), '.', offsetof(KeyBlock, name), sizeof(kb->name)); } - + /* fix all the animation data which may link to this */ BKE_animdata_fix_paths_rename_all(NULL, "key_blocks", oldname, kb->name); } @@ -131,7 +131,7 @@ static void rna_ShapeKey_slider_min_set(PointerRNA *ptr, float value) { KeyBlock *data = (KeyBlock *)ptr->data; float min, max, softmin, softmax; - + rna_ShapeKey_slider_min_range(ptr, &min, &max, &softmin, &softmax); CLAMP(value, min, max); data->slidermin = value; @@ -150,7 +150,7 @@ static void rna_ShapeKey_slider_max_set(PointerRNA *ptr, float value) { KeyBlock *data = (KeyBlock *)ptr->data; float min, max, softmin, softmax; - + rna_ShapeKey_slider_max_range(ptr, &min, &max, &softmin, &softmax); CLAMP(value, min, max); data->slidermax = value; @@ -274,7 +274,7 @@ PointerRNA rna_object_shapekey_index_get(ID *id, int value) if (key && value < key->totkey) kb = BLI_findlink(&key->block, value); - + RNA_pointer_create(id, &RNA_ShapeKey, kb, &ptr); return ptr; @@ -288,7 +288,7 @@ int rna_object_shapekey_index_set(ID *id, PointerRNA value, int current) int a = BLI_findindex(&key->block, value.data); if (a != -1) return a; } - + return current; } @@ -411,17 +411,17 @@ static void rna_ShapeKey_data_begin(CollectionPropertyIterator *iter, PointerRNA Curve *cu; Nurb *nu; int tot = kb->totelem, size = key->elemsize; - + if (GS(key->from->name) == ID_CU) { cu = (Curve *)key->from; nu = cu->nurb.first; - + if (nu->bezt) { tot /= 3; size *= 3; } } - + rna_iterator_array_begin(iter, (void *)kb->data, size, tot, 0, NULL); } @@ -432,15 +432,15 @@ static int rna_ShapeKey_data_length(PointerRNA *ptr) Curve *cu; Nurb *nu; int tot = kb->totelem; - + if (GS(key->from->name) == ID_CU) { cu = (Curve *)key->from; nu = cu->nurb.first; - + if (nu->bezt) tot /= 3; } - + return tot; } @@ -450,11 +450,11 @@ static PointerRNA rna_ShapeKey_data_get(CollectionPropertyIterator *iter) StructRNA *type; Curve *cu; Nurb *nu; - + if (GS(key->from->name) == ID_CU) { cu = (Curve *)key->from; nu = cu->nurb.first; - + if (nu->bezt) type = &RNA_ShapeKeyBezierPoint; else @@ -462,7 +462,7 @@ static PointerRNA rna_ShapeKey_data_get(CollectionPropertyIterator *iter) } else type = &RNA_ShapeKeyPoint; - + return rna_pointer_inherit_refine(&iter->parent, type, rna_iterator_array_get(iter)); } @@ -496,11 +496,11 @@ static void rna_Key_update_data(Main *bmain, Scene *UNUSED(scene), PointerRNA *p static KeyBlock *rna_ShapeKeyData_find_keyblock(Key *key, float *point) { KeyBlock *kb; - + /* sanity checks */ if (ELEM(NULL, key, point)) return NULL; - + /* we'll need to manually search through the keyblocks and check * if the point is somewhere in the middle of each block's data */ @@ -508,7 +508,7 @@ static KeyBlock *rna_ShapeKeyData_find_keyblock(Key *key, float *point) if (kb->data) { float *start = (float *)kb->data; float *end; - + /* easy cases first */ if ((start == NULL) || (start > point)) { /* there's no chance point is in array */ @@ -518,12 +518,12 @@ static KeyBlock *rna_ShapeKeyData_find_keyblock(Key *key, float *point) /* exact match - point is first in array */ return kb; } - + /* determine where end of array is * - elemsize is in bytes, so use (char *) cast to get array in terms of bytes */ end = (float *)((char *)start + (key->elemsize * kb->totelem)); - + /* if point's address is less than the end, then it is somewhere between start and end, so in array */ if (end > point) { /* we've found the owner of the point data */ @@ -531,7 +531,7 @@ static KeyBlock *rna_ShapeKeyData_find_keyblock(Key *key, float *point) } } } - + return NULL; } @@ -543,18 +543,18 @@ static int rna_ShapeKeyPoint_get_index(Key *key, KeyBlock *kb, float *point) */ char *start = (char *)kb->data; char *pt = (char *)point; - + return (int)(pt - start) / key->elemsize; } static int rna_ShapeKeyBezierPoint_get_index(KeyBlock *kb, float *point) { float *start = (float *)kb->data; - + /* Unlike with rna_ShapeKeyPoint_get_index(), we cannot use key->elemsize here * since the default value for curves (16) is actually designed for BPoints * (i.e. NURBS Surfaces). The magic number "12" here was found by empirical - * testing on a 64-bit system, and is similar to what's used for meshes and + * testing on a 64-bit system, and is similar to what's used for meshes and * lattices. For more details, see T38013 */ return (int)(point - start) / 12; @@ -566,21 +566,21 @@ static char *rna_ShapeKeyPoint_path(PointerRNA *ptr) Key *key = rna_ShapeKey_find_key(ptr->id.data); KeyBlock *kb; float *point = (float *)ptr->data; - + /* if we can get a key block, we can construct a path */ kb = rna_ShapeKeyData_find_keyblock(key, point); - + if (kb) { char name_esc_kb[sizeof(kb->name) * 2]; int index; - + if (ptr->type == &RNA_ShapeKeyBezierPoint) index = rna_ShapeKeyBezierPoint_get_index(kb, point); else index = rna_ShapeKeyPoint_get_index(key, kb, point); BLI_strescape(name_esc_kb, kb->name, sizeof(name_esc_kb)); - + if (GS(id->name) == ID_KE) return BLI_sprintfN("key_blocks[\"%s\"].data[%d]", name_esc_kb, index); else @@ -690,7 +690,7 @@ static void rna_def_keyblock(BlenderRNA *brna) RNA_def_property_float_funcs(prop, "rna_ShapeKey_frame_get", NULL, NULL); RNA_def_property_ui_text(prop, "Frame", "Frame for absolute keys"); RNA_def_property_update(prop, 0, "rna_Key_update_data"); - + /* for now, this is editable directly, as users can set this even if they're not animating them * (to test results) */ prop = RNA_def_property(srna, "value", PROP_FLOAT, PROP_FACTOR); diff --git a/source/blender/makesrna/intern/rna_lamp.c b/source/blender/makesrna/intern/rna_lamp.c index fb27c91959e..dff27e1c625 100644 --- a/source/blender/makesrna/intern/rna_lamp.c +++ b/source/blender/makesrna/intern/rna_lamp.c @@ -105,7 +105,7 @@ static void rna_Lamp_use_nodes_update(bContext *C, PointerRNA *ptr) if (la->use_nodes && la->nodetree == NULL) ED_node_shader_default(C, &la->id); - + rna_Lamp_update(CTX_data_main(C), CTX_data_scene(C), ptr); } @@ -173,7 +173,7 @@ static void rna_def_lamp(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); RNA_def_property_ui_text(prop, "Use Nodes", "Use shader nodes to render the lamp"); RNA_def_property_update(prop, 0, "rna_Lamp_use_nodes_update"); - + /* common */ rna_def_animdata_common(srna); } @@ -196,7 +196,7 @@ static void rna_def_lamp_falloff(StructRNA *srna) RNA_def_property_enum_items(prop, prop_fallofftype_items); RNA_def_property_ui_text(prop, "Falloff Type", "Intensity Decay with distance"); RNA_def_property_update(prop, 0, "rna_Lamp_update"); - + prop = RNA_def_property(srna, "falloff_curve", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "curfalloff"); RNA_def_property_ui_text(prop, "Falloff Curve", "Custom Lamp Falloff Curve"); diff --git a/source/blender/makesrna/intern/rna_lattice.c b/source/blender/makesrna/intern/rna_lattice.c index 904a6289fc1..ace7ac30408 100644 --- a/source/blender/makesrna/intern/rna_lattice.c +++ b/source/blender/makesrna/intern/rna_lattice.c @@ -216,19 +216,19 @@ static char *rna_LatticePoint_path(PointerRNA *ptr) Lattice *lt = (Lattice *)ptr->id.data; void *point = ptr->data; BPoint *points = NULL; - + if (lt->editlatt && lt->editlatt->latt->def) points = lt->editlatt->latt->def; else points = lt->def; - + if (points && point) { int tot = lt->pntsu * lt->pntsv * lt->pntsw; - + /* only return index if in range */ if ((point >= (void *)points) && (point < (void *)(points + tot))) { int pt_index = (int)((BPoint *)point - points); - + return BLI_sprintfN("points[%d]", pt_index); } } @@ -345,7 +345,7 @@ static void rna_def_lattice(BlenderRNA *brna) RNA_def_property_boolean_funcs(prop, NULL, "rna_Lattice_use_outside_set"); RNA_def_property_ui_text(prop, "Outside", "Only draw, and take into account, the outer vertices"); RNA_def_property_update(prop, 0, "rna_Lattice_update_data_editlatt"); - + prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "vgroup"); RNA_def_property_ui_text(prop, "Vertex Group", "Vertex group to apply the influence of the lattice"); diff --git a/source/blender/makesrna/intern/rna_main.c b/source/blender/makesrna/intern/rna_main.c index d727b896223..7b9184eb5df 100644 --- a/source/blender/makesrna/intern/rna_main.c +++ b/source/blender/makesrna/intern/rna_main.c @@ -386,7 +386,7 @@ void RNA_def_main(BlenderRNA *brna) }; int i; - + srna = RNA_def_struct(brna, "BlendData", NULL); RNA_def_struct_ui_text(srna, "Blendfile Data", "Main data structure representing a .blend file and all its data-blocks"); @@ -397,7 +397,7 @@ void RNA_def_main(BlenderRNA *brna) RNA_def_property_string_funcs(prop, "rna_Main_filepath_get", "rna_Main_filepath_length", "rna_Main_filepath_set"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Filename", "Path to the .blend file"); - + prop = RNA_def_property(srna, "is_dirty", PROP_BOOLEAN, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_boolean_funcs(prop, "rna_Main_is_dirty_get", NULL); diff --git a/source/blender/makesrna/intern/rna_main_api.c b/source/blender/makesrna/intern/rna_main_api.c index 9b4d6ead53c..6ff3849e295 100644 --- a/source/blender/makesrna/intern/rna_main_api.c +++ b/source/blender/makesrna/intern/rna_main_api.c @@ -346,7 +346,7 @@ static Image *rna_Main_images_load(Main *bmain, ReportList *reports, const char errno = 0; if (check_existing) { - ima = BKE_image_load_exists(filepath); + ima = BKE_image_load_exists(bmain, filepath); } else { ima = BKE_image_load(bmain, filepath); @@ -1642,7 +1642,7 @@ void RNA_def_main_gpencil(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); func = RNA_def_function(srna, "new", "BKE_gpencil_data_addnew"); - RNA_def_function_flag(func, FUNC_NO_SELF); + RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_USE_MAIN); parm = RNA_def_string(func, "name", "GreasePencil", 0, "", "New name for the data-block"); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); /* return type */ diff --git a/source/blender/makesrna/intern/rna_material.c b/source/blender/makesrna/intern/rna_material.c index 9f5b72ff13e..858dd0ec972 100644 --- a/source/blender/makesrna/intern/rna_material.c +++ b/source/blender/makesrna/intern/rna_material.c @@ -97,10 +97,10 @@ static void rna_Material_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Point static void rna_Material_update_previews(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { Material *ma = ptr->id.data; - + if (ma->nodetree) BKE_node_preview_clear_tree(ma->nodetree); - + WM_main_add_notifier(NC_MATERIAL | ND_SHADING_PREVIEW, ma); } @@ -160,7 +160,7 @@ static void rna_Material_active_paint_texture_index_update(Main *bmain, Scene *s if (sl->spacetype == SPACE_IMAGE) { SpaceImage *sima = (SpaceImage *)sl; if (!sima->pin) { - ED_space_image_set(sima, scene, obedit, image); + ED_space_image_set(bmain, sima, scene, obedit, image); } } } @@ -226,7 +226,7 @@ void rna_mtex_texture_slots_clear(ID *self_id, struct bContext *C, ReportList *r BKE_report(reports, RPT_ERROR, "Mtex not found for this type"); return; } - + if (index < 0 || index >= MAX_MTEX) { BKE_reportf(reports, RPT_ERROR, "Index %d is invalid", index); return; @@ -254,7 +254,7 @@ static void rna_def_material_display(StructRNA *srna) RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Diffuse Color", "Diffuse color of the material"); RNA_def_property_update(prop, 0, "rna_Material_draw_update"); - + prop = RNA_def_property(srna, "specular_color", PROP_FLOAT, PROP_COLOR); RNA_def_property_float_sdna(prop, NULL, "specr"); RNA_def_property_array(prop, 3); @@ -267,7 +267,7 @@ static void rna_def_material_display(StructRNA *srna) RNA_def_property_range(prop, 0, 1); RNA_def_property_ui_text(prop, "Roughness", "Roughness of the material"); RNA_def_property_update(prop, 0, "rna_Material_draw_update"); - + prop = RNA_def_property(srna, "specular_intensity", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "spec"); RNA_def_property_float_default(prop, 0.5f); @@ -334,7 +334,7 @@ void RNA_def_material(BlenderRNA *brna) RNA_def_struct_ui_text(srna, "Material", "Material data-block to define the appearance of geometric objects for rendering"); RNA_def_struct_ui_icon(srna, ICON_MATERIAL_DATA); - + /* Blending (only Eevee for now) */ prop = RNA_def_property(srna, "blend_method", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, prop_eevee_blend_items); @@ -386,7 +386,7 @@ void RNA_def_material(BlenderRNA *brna) RNA_def_property_enum_items(prop, preview_type_items); RNA_def_property_ui_text(prop, "Preview render type", "Type of preview render"); RNA_def_property_update(prop, 0, "rna_Material_update_previews"); - + prop = RNA_def_property(srna, "pass_index", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "index"); RNA_def_property_ui_text(prop, "Pass Index", "Index number for the \"Material Index\" render pass"); @@ -432,14 +432,14 @@ static void rna_def_texture_slots(BlenderRNA *brna, PropertyRNA *cprop, const ch RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_NO_SELF | FUNC_USE_CONTEXT | FUNC_USE_REPORTS); parm = RNA_def_pointer(func, "mtex", structname, "", "The newly initialized mtex"); RNA_def_function_return(func, parm); - + func = RNA_def_function(srna, "create", "rna_mtex_texture_slots_create"); RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_NO_SELF | FUNC_USE_CONTEXT | FUNC_USE_REPORTS); parm = RNA_def_int(func, "index", 0, 0, INT_MAX, "Index", "Slot index to initialize", 0, INT_MAX); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); parm = RNA_def_pointer(func, "mtex", structname, "", "The newly initialized mtex"); RNA_def_function_return(func, parm); - + func = RNA_def_function(srna, "clear", "rna_mtex_texture_slots_clear"); RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_NO_SELF | FUNC_USE_CONTEXT | FUNC_USE_REPORTS); parm = RNA_def_int(func, "index", 0, 0, INT_MAX, "Index", "Slot index to clear", 0, INT_MAX); @@ -490,7 +490,7 @@ static void rna_def_tex_slot(BlenderRNA *brna) RNA_def_property_string_sdna(prop, NULL, "uvname"); RNA_def_property_ui_text(prop, "UV Map", "Name of UV map"); RNA_def_property_update(prop, NC_GEOM | ND_DATA, "rna_Material_update"); - + prop = RNA_def_property(srna, "is_valid", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "valid", 1); RNA_def_property_clear_flag(prop, PROP_EDITABLE); diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c index 9ec196034f3..d664415b8ad 100644 --- a/source/blender/makesrna/intern/rna_mesh.c +++ b/source/blender/makesrna/intern/rna_mesh.c @@ -3142,7 +3142,7 @@ static void rna_def_skin_vertices(BlenderRNA *brna, PropertyRNA *UNUSED(cprop)) RNA_def_property_boolean_sdna(prop, NULL, "flag", MVERT_SKIN_ROOT); RNA_def_property_ui_text(prop, "Root", "Vertex is a root for rotation calculations and armature generation"); RNA_def_property_update(prop, 0, "rna_Mesh_update_data"); - + prop = RNA_def_property(srna, "use_loose", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", MVERT_SKIN_LOOSE); RNA_def_property_ui_text(prop, "Loose", "If vertex has multiple adjacent edges, it is hulled to them directly"); diff --git a/source/blender/makesrna/intern/rna_mesh_api.c b/source/blender/makesrna/intern/rna_mesh_api.c index f1f7c9a3b99..ed19877ec0f 100644 --- a/source/blender/makesrna/intern/rna_mesh_api.c +++ b/source/blender/makesrna/intern/rna_mesh_api.c @@ -55,10 +55,10 @@ static const char *rna_Mesh_unit_test_compare(struct Mesh *mesh, struct Mesh *mesh2) { const char *ret = BKE_mesh_cmp(mesh, mesh2, FLT_EPSILON * 60); - + if (!ret) ret = "Same"; - + return ret; } diff --git a/source/blender/makesrna/intern/rna_mesh_utils.h b/source/blender/makesrna/intern/rna_mesh_utils.h index a85e2095121..b16a7254a86 100644 --- a/source/blender/makesrna/intern/rna_mesh_utils.h +++ b/source/blender/makesrna/intern/rna_mesh_utils.h @@ -23,7 +23,7 @@ /** \file blender/makesrna/intern/rna_mesh_utils.h * \ingroup RNA */ - + #ifndef __RNA_MESH_UTILS_H__ #define __RNA_MESH_UTILS_H__ diff --git a/source/blender/makesrna/intern/rna_meta.c b/source/blender/makesrna/intern/rna_meta.c index 124f3a2fbe2..cdecba0760c 100644 --- a/source/blender/makesrna/intern/rna_meta.c +++ b/source/blender/makesrna/intern/rna_meta.c @@ -64,32 +64,32 @@ static int rna_Meta_texspace_editable(PointerRNA *ptr, const char **UNUSED(r_inf static void rna_Meta_texspace_loc_get(PointerRNA *ptr, float *values) { MetaBall *mb = (MetaBall *)ptr->data; - + /* tex_space_mball() needs object.. ugh */ - + copy_v3_v3(values, mb->loc); } static void rna_Meta_texspace_loc_set(PointerRNA *ptr, const float *values) { MetaBall *mb = (MetaBall *)ptr->data; - + copy_v3_v3(mb->loc, values); } static void rna_Meta_texspace_size_get(PointerRNA *ptr, float *values) { MetaBall *mb = (MetaBall *)ptr->data; - + /* tex_space_mball() needs object.. ugh */ - + copy_v3_v3(values, mb->size); } static void rna_Meta_texspace_size_set(PointerRNA *ptr, const float *values) { MetaBall *mb = (MetaBall *)ptr->data; - + copy_v3_v3(mb->size, values); } @@ -104,7 +104,7 @@ static void rna_MetaBall_update_data(Main *bmain, Scene *scene, PointerRNA *ptr) for (ob = bmain->object.first; ob; ob = ob->id.next) if (ob->data == mb) BKE_mball_properties_copy(scene, ob); - + DEG_id_tag_update(&mb->id, 0); WM_main_add_notifier(NC_GEOM | ND_DATA, mb); } @@ -200,7 +200,7 @@ static void rna_def_metaelement(BlenderRNA *brna) RNA_def_property_enum_items(prop, rna_enum_metaelem_type_items); RNA_def_property_ui_text(prop, "Type", "Metaball types"); RNA_def_property_update(prop, 0, "rna_MetaBall_update_data"); - + /* number values */ prop = RNA_def_property(srna, "co", PROP_FLOAT, PROP_TRANSLATION); RNA_def_property_float_sdna(prop, NULL, "x"); @@ -239,19 +239,19 @@ static void rna_def_metaelement(BlenderRNA *brna) RNA_def_property_range(prop, 0.0f, 20.0f); RNA_def_property_ui_text(prop, "Size Z", "Size of element, use of components depends on element type"); RNA_def_property_update(prop, 0, "rna_MetaBall_update_data"); - + prop = RNA_def_property(srna, "stiffness", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "s"); RNA_def_property_range(prop, 0.0f, 10.0f); RNA_def_property_ui_text(prop, "Stiffness", "Stiffness defines how much of the element to fill"); RNA_def_property_update(prop, 0, "rna_MetaBall_update_data"); - + /* flags */ prop = RNA_def_property(srna, "use_negative", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", MB_NEGATIVE); RNA_def_property_ui_text(prop, "Negative", "Set metaball as negative one"); RNA_def_property_update(prop, 0, "rna_MetaBall_update_data"); - + prop = RNA_def_property(srna, "hide", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", MB_HIDE); RNA_def_property_ui_text(prop, "Hide", "Hide element"); @@ -304,7 +304,7 @@ static void rna_def_metaball(BlenderRNA *brna) {MB_UPDATE_NEVER, "NEVER", 0, "Never", "While editing, don't update metaball at all"}, {0, NULL, 0, NULL, NULL} }; - + srna = RNA_def_struct(brna, "MetaBall", "ID"); RNA_def_struct_ui_text(srna, "MetaBall", "Metaball data-block to defined blobby surfaces"); RNA_def_struct_ui_icon(srna, ICON_META_DATA); @@ -321,7 +321,7 @@ static void rna_def_metaball(BlenderRNA *brna) RNA_def_property_enum_items(prop, prop_update_items); RNA_def_property_ui_text(prop, "Update", "Metaball edit update behavior"); RNA_def_property_update(prop, 0, "rna_MetaBall_update_data"); - + /* number values */ prop = RNA_def_property(srna, "resolution", PROP_FLOAT, PROP_DISTANCE); RNA_def_property_float_sdna(prop, NULL, "wiresize"); @@ -329,14 +329,14 @@ static void rna_def_metaball(BlenderRNA *brna) RNA_def_property_ui_range(prop, 0.05f, 1000.0f, 2.5f, 3); RNA_def_property_ui_text(prop, "Wire Size", "Polygonization resolution in the 3D viewport"); RNA_def_property_update(prop, 0, "rna_MetaBall_update_data"); - + prop = RNA_def_property(srna, "render_resolution", PROP_FLOAT, PROP_DISTANCE); RNA_def_property_float_sdna(prop, NULL, "rendersize"); RNA_def_property_range(prop, 0.005f, 10000.0f); RNA_def_property_ui_range(prop, 0.025f, 1000.0f, 2.5f, 3); RNA_def_property_ui_text(prop, "Render Size", "Polygonization resolution in rendering"); RNA_def_property_update(prop, 0, "rna_MetaBall_update_data"); - + prop = RNA_def_property(srna, "threshold", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "thresh"); RNA_def_property_range(prop, 0.0f, 5.0f); @@ -348,14 +348,14 @@ static void rna_def_metaball(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "texflag", MB_AUTOSPACE); RNA_def_property_ui_text(prop, "Auto Texture Space", "Adjust active object's texture space automatically when transforming object"); - + prop = RNA_def_property(srna, "texspace_location", PROP_FLOAT, PROP_TRANSLATION); RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Texture Space Location", "Texture space location"); RNA_def_property_editable_func(prop, "rna_Meta_texspace_editable"); RNA_def_property_float_funcs(prop, "rna_Meta_texspace_loc_get", "rna_Meta_texspace_loc_set", NULL); RNA_def_property_update(prop, 0, "rna_MetaBall_update_data"); - + prop = RNA_def_property(srna, "texspace_size", PROP_FLOAT, PROP_XYZ); RNA_def_property_array(prop, 3); RNA_def_property_flag(prop, PROP_PROPORTIONAL); @@ -363,7 +363,7 @@ static void rna_def_metaball(BlenderRNA *brna) RNA_def_property_editable_func(prop, "rna_Meta_texspace_editable"); RNA_def_property_float_funcs(prop, "rna_Meta_texspace_size_get", "rna_Meta_texspace_size_set", NULL); RNA_def_property_update(prop, 0, "rna_MetaBall_update_data"); - + /* not supported yet */ #if 0 prop = RNA_def_property(srna, "texspace_rot", PROP_FLOAT, PROP_EULER); @@ -372,7 +372,7 @@ static void rna_def_metaball(BlenderRNA *brna) RNA_def_property_editable_func(prop, "rna_Meta_texspace_editable"); RNA_def_property_update(prop, 0, "rna_MetaBall_update_data"); #endif - + /* materials */ prop = RNA_def_property(srna, "materials", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "mat", "totcol"); @@ -380,7 +380,7 @@ static void rna_def_metaball(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Materials", ""); RNA_def_property_srna(prop, "IDMaterials"); /* see rna_ID.c */ RNA_def_property_collection_funcs(prop, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "rna_IDMaterials_assign_int"); - + prop = RNA_def_property(srna, "is_editmode", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_funcs(prop, "rna_Meta_is_editmode_get", NULL); RNA_def_property_clear_flag(prop, PROP_EDITABLE); diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index e38fa1fa452..59816fbdc9b 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -436,19 +436,19 @@ static void rna_Modifier_name_set(PointerRNA *ptr, const char *value) { ModifierData *md = ptr->data; char oldname[sizeof(md->name)]; - + /* make a copy of the old name first */ BLI_strncpy(oldname, md->name, sizeof(md->name)); - + /* copy the new name into the name slot */ BLI_strncpy_utf8(md->name, value, sizeof(md->name)); - + /* make sure the name is truly unique */ if (ptr->id.data) { Object *ob = ptr->id.data; modifier_unique_name(&ob->modifiers, md); } - + /* fix all the animation data which may link to this */ BKE_animdata_fix_paths_rename_all(NULL, "modifiers", oldname, md->name); } @@ -706,7 +706,7 @@ static int rna_ShrinkwrapModifier_face_cull_get(PointerRNA *ptr) static void rna_ShrinkwrapModifier_face_cull_set(struct PointerRNA *ptr, int value) { ShrinkwrapModifierData *swm = (ShrinkwrapModifierData *)ptr->data; - + swm->shrinkOpts = (swm->shrinkOpts & ~(MOD_SHRINKWRAP_CULL_TARGET_FRONTFACE | MOD_SHRINKWRAP_CULL_TARGET_BACKFACE)) | value; } @@ -747,27 +747,27 @@ static void rna_UVProjectModifier_num_projectors_set(PointerRNA *ptr, int value) static void rna_OceanModifier_init_update(Main *bmain, Scene *scene, PointerRNA *ptr) { OceanModifierData *omd = (OceanModifierData *)ptr->data; - + omd->refresh |= (MOD_OCEAN_REFRESH_RESET | MOD_OCEAN_REFRESH_SIM | MOD_OCEAN_REFRESH_CLEAR_CACHE); - + rna_Modifier_update(bmain, scene, ptr); } static void rna_OceanModifier_sim_update(Main *bmain, Scene *scene, PointerRNA *ptr) { OceanModifierData *omd = (OceanModifierData *)ptr->data; - + omd->refresh |= MOD_OCEAN_REFRESH_SIM; - + rna_Modifier_update(bmain, scene, ptr); } static void rna_OceanModifier_topology_update(Main *bmain, Scene *scene, PointerRNA *ptr) { OceanModifierData *omd = (OceanModifierData *)ptr->data; - + omd->refresh |= MOD_OCEAN_REFRESH_TOPOLOGY; - + rna_Modifier_update(bmain, scene, ptr); } @@ -775,9 +775,9 @@ static void rna_OceanModifier_ocean_chop_set(PointerRNA *ptr, float value) { OceanModifierData *omd = (OceanModifierData *)ptr->data; float old_value = omd->chop_amount; - + omd->chop_amount = value; - + if ((old_value == 0.0f && value > 0.0f) || (old_value > 0.0f && value == 0.0f)) { @@ -1307,7 +1307,7 @@ static void rna_def_modifier_subsurf(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flags", eSubsurfModifierFlag_ControlEdges); RNA_def_property_ui_text(prop, "Optimal Display", "Skip drawing/rendering of interior subdivided edges"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); - + prop = RNA_def_property(srna, "use_subsurf_uv", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flags", eSubsurfModifierFlag_SubsurfUv); RNA_def_property_ui_text(prop, "Subdivide UVs", "Use subsurf to subdivide UVs"); @@ -1493,7 +1493,7 @@ static void rna_def_modifier_lattice(BlenderRNA *brna) "Name of Vertex Group which determines influence of modifier per point"); RNA_def_property_string_funcs(prop, NULL, NULL, "rna_LatticeModifier_name_set"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); - + prop = RNA_def_property(srna, "strength", PROP_FLOAT, PROP_NONE); RNA_def_property_range(prop, -FLT_MAX, FLT_MAX); RNA_def_property_ui_range(prop, 0, 1, 10, 2); @@ -1567,7 +1567,7 @@ static void rna_def_modifier_build(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_BUILD_FLAG_REVERSE); RNA_def_property_ui_text(prop, "Reversed", "Deconstruct the mesh instead of building it"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); - + prop = RNA_def_property(srna, "use_random_order", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_BUILD_FLAG_RANDOMIZE); RNA_def_property_ui_text(prop, "Randomize", "Randomize the faces or edges during build"); @@ -1613,7 +1613,7 @@ static void rna_def_modifier_mirror(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_MIR_VGROUP); RNA_def_property_ui_text(prop, "Mirror Vertex Groups", "Mirror vertex groups (e.g. .R->.L)"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); - + prop = RNA_def_property(srna, "use_mirror_merge", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", MOD_MIR_NO_MERGE); RNA_def_property_ui_text(prop, "Merge Vertices", "Merge vertices within the merge threshold"); @@ -1931,7 +1931,7 @@ static void rna_def_modifier_armature(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "deformflag", ARM_DEF_VGROUP); RNA_def_property_ui_text(prop, "Use Vertex Groups", "Bind vertex groups to armature modifier"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); - + prop = RNA_def_property(srna, "use_deform_preserve_volume", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "deformflag", ARM_DEF_QUATERNION); RNA_def_property_ui_text(prop, "Preserve Volume", "Deform rotation interpolation with quaternions"); @@ -1942,7 +1942,7 @@ static void rna_def_modifier_armature(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Multi Modifier", "Use same input as previous modifier, and mix results using overall vgroup"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); - + prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "defgrp_name"); RNA_def_property_ui_text(prop, "Vertex Group", @@ -2006,7 +2006,7 @@ static void rna_def_modifier_hook(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); RNA_def_property_pointer_funcs(prop, NULL, "rna_HookModifier_object_set", NULL, NULL); RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update"); - + prop = RNA_def_property(srna, "subtarget", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "subtarget"); RNA_def_property_ui_text(prop, "Sub-Target", @@ -2152,7 +2152,7 @@ static void rna_def_modifier_array(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "offset_type", MOD_ARR_OFF_CONST); RNA_def_property_ui_text(prop, "Constant Offset", "Add a constant offset"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); - + prop = RNA_def_property(srna, "constant_offset_displace", PROP_FLOAT, PROP_TRANSLATION); RNA_def_property_float_sdna(prop, NULL, "offset"); RNA_def_property_ui_text(prop, "Constant Offset Displacement", "Value for the distance between arrayed items"); @@ -2202,7 +2202,7 @@ static void rna_def_modifier_array(BlenderRNA *brna) "rotational change between arrayed items"); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update"); - + /* Caps */ prop = RNA_def_property(srna, "start_cap", PROP_POINTER, PROP_NONE); RNA_def_property_ui_text(prop, "Start Cap", "Mesh object to use as a start cap"); @@ -2215,7 +2215,7 @@ static void rna_def_modifier_array(BlenderRNA *brna) RNA_def_property_pointer_funcs(prop, NULL, "rna_ArrayModifier_end_cap_set", NULL, "rna_Mesh_object_poll"); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update"); - + prop = RNA_def_property(srna, "offset_u", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "uv_offset[0]"); RNA_def_property_range(prop, -1, 1); @@ -2364,7 +2364,7 @@ static void rna_def_modifier_uvproject(BlenderRNA *brna) RNA_def_property_ui_range(prop, 1, 1000, 1, 3); RNA_def_property_ui_text(prop, "Vertical Aspect Ratio", ""); RNA_def_property_update(prop, 0, "rna_Modifier_update"); - + prop = RNA_def_property(srna, "scale_x", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "scalex"); RNA_def_property_flag(prop, PROP_PROPORTIONAL); @@ -2429,7 +2429,7 @@ static void rna_def_modifier_smooth(BlenderRNA *brna) RNA_def_property_ui_range(prop, 0, 30, 1, -1); RNA_def_property_ui_text(prop, "Repeat", ""); RNA_def_property_update(prop, 0, "rna_Modifier_update"); - + prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "defgrp_name"); RNA_def_property_ui_text(prop, "Vertex Group", @@ -2551,7 +2551,7 @@ static void rna_def_modifier_laplaciansmooth(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_LAPLACIANSMOOTH_PRESERVE_VOLUME); RNA_def_property_ui_text(prop, "Preserve Volume", "Apply volume preservation after smooth"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); - + prop = RNA_def_property(srna, "use_normalized", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_LAPLACIANSMOOTH_NORMALIZED); RNA_def_property_ui_text(prop, "Normalized", "Improve and stabilize the enhanced shape"); @@ -2576,7 +2576,7 @@ static void rna_def_modifier_laplaciansmooth(BlenderRNA *brna) RNA_def_property_ui_range(prop, 0, 200, 1, -1); RNA_def_property_ui_text(prop, "Repeat", ""); RNA_def_property_update(prop, 0, "rna_Modifier_update"); - + prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "defgrp_name"); RNA_def_property_ui_text(prop, "Vertex Group", @@ -2607,7 +2607,7 @@ static void rna_def_modifier_cast(BlenderRNA *brna) RNA_def_property_enum_items(prop, prop_cast_type_items); RNA_def_property_ui_text(prop, "Cast Type", "Target object shape"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); - + prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE); RNA_def_property_ui_text(prop, "Object", "Control object: if available, its location determines the center of the effect"); @@ -2629,17 +2629,17 @@ static void rna_def_modifier_cast(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_CAST_Z); RNA_def_property_ui_text(prop, "Z", ""); RNA_def_property_update(prop, 0, "rna_Modifier_update"); - + prop = RNA_def_property(srna, "use_radius_as_size", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_CAST_SIZE_FROM_RADIUS); RNA_def_property_ui_text(prop, "From Radius", "Use radius as size of projection shape (0 = auto)"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); - + prop = RNA_def_property(srna, "use_transform", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_CAST_USE_OB_TRANSFORM); RNA_def_property_ui_text(prop, "Use transform", "Use object transform to control projection shape"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); - + prop = RNA_def_property(srna, "factor", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "fac"); RNA_def_property_range(prop, -FLT_MAX, FLT_MAX); @@ -2690,12 +2690,12 @@ static void rna_def_modifier_meshdeform(BlenderRNA *brna) RNA_def_property_pointer_funcs(prop, NULL, "rna_MeshDeformModifier_object_set", NULL, "rna_Mesh_object_poll"); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update"); - + prop = RNA_def_property(srna, "is_bound", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_funcs(prop, "rna_MeshDeformModifier_is_bound_get", NULL); RNA_def_property_ui_text(prop, "Bound", "Whether geometry has been bound to control cage"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); - + prop = RNA_def_property(srna, "invert_vertex_group", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_MDEF_INVERT_VGROUP); RNA_def_property_ui_text(prop, "Invert", "Invert vertex group influence"); @@ -2737,7 +2737,7 @@ static void rna_def_modifier_particlesystem(BlenderRNA *brna) RNA_def_struct_ui_text(srna, "ParticleSystem Modifier", "Particle system simulation modifier"); RNA_def_struct_sdna(srna, "ParticleSystemModifierData"); RNA_def_struct_ui_icon(srna, ICON_MOD_PARTICLES); - + prop = RNA_def_property(srna, "particle_system", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "psys"); @@ -2941,22 +2941,22 @@ static void rna_def_modifier_cloth(BlenderRNA *brna) RNA_def_struct_ui_text(srna, "Cloth Modifier", "Cloth simulation modifier"); RNA_def_struct_sdna(srna, "ClothModifierData"); RNA_def_struct_ui_icon(srna, ICON_MOD_CLOTH); - + prop = RNA_def_property(srna, "settings", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "sim_parms"); RNA_def_property_ui_text(prop, "Cloth Settings", ""); - + prop = RNA_def_property(srna, "collision_settings", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "coll_parms"); RNA_def_property_ui_text(prop, "Cloth Collision Settings", ""); - + prop = RNA_def_property(srna, "solver_result", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "ClothSolverResult"); RNA_def_property_pointer_sdna(prop, NULL, "solver_result"); RNA_def_property_ui_text(prop, "Solver Result", ""); - + prop = RNA_def_property(srna, "point_cache", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_ui_text(prop, "Point Cache", ""); @@ -2981,7 +2981,7 @@ static void rna_def_modifier_smoke(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + static const EnumPropertyItem prop_smoke_type_items[] = { {0, "NONE", 0, "None", ""}, {MOD_SMOKE_TYPE_DOMAIN, "DOMAIN", 0, "Domain", ""}, @@ -2989,24 +2989,24 @@ static void rna_def_modifier_smoke(BlenderRNA *brna) {MOD_SMOKE_TYPE_COLL, "COLLISION", 0, "Collision", ""}, {0, NULL, 0, NULL, NULL} }; - + srna = RNA_def_struct(brna, "SmokeModifier", "Modifier"); RNA_def_struct_ui_text(srna, "Smoke Modifier", "Smoke simulation modifier"); RNA_def_struct_sdna(srna, "SmokeModifierData"); RNA_def_struct_ui_icon(srna, ICON_MOD_SMOKE); - + prop = RNA_def_property(srna, "domain_settings", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "domain"); RNA_def_property_ui_text(prop, "Domain Settings", ""); - + prop = RNA_def_property(srna, "flow_settings", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "flow"); RNA_def_property_ui_text(prop, "Flow Settings", ""); - + prop = RNA_def_property(srna, "coll_settings", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "coll"); RNA_def_property_ui_text(prop, "Collision Settings", ""); - + prop = RNA_def_property(srna, "smoke_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "type"); RNA_def_property_enum_items(prop, prop_smoke_type_items); @@ -3019,16 +3019,16 @@ static void rna_def_modifier_dynamic_paint(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + srna = RNA_def_struct(brna, "DynamicPaintModifier", "Modifier"); RNA_def_struct_ui_text(srna, "Dynamic Paint Modifier", "Dynamic Paint modifier"); RNA_def_struct_sdna(srna, "DynamicPaintModifierData"); RNA_def_struct_ui_icon(srna, ICON_MOD_DYNAMICPAINT); - + prop = RNA_def_property(srna, "canvas_settings", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "canvas"); RNA_def_property_ui_text(prop, "Canvas Settings", ""); - + prop = RNA_def_property(srna, "brush_settings", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "brush"); RNA_def_property_ui_text(prop, "Brush Settings", ""); @@ -3181,7 +3181,7 @@ static void rna_def_modifier_shrinkwrap(BlenderRNA *brna) "Shrink the mesh to the nearest target vertex"}, {0, NULL, 0, NULL, NULL} }; - + static const EnumPropertyItem shrink_face_cull_items[] = { {0, "OFF", 0, "Off", "No culling"}, {MOD_SHRINKWRAP_CULL_TARGET_FRONTFACE, "FRONT", 0, "Front", "No projection when in front of the face"}, @@ -3257,7 +3257,7 @@ static void rna_def_modifier_shrinkwrap(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "projAxis", MOD_SHRINKWRAP_PROJECT_OVER_Z_AXIS); RNA_def_property_ui_text(prop, "Z", ""); RNA_def_property_update(prop, 0, "rna_Modifier_update"); - + prop = RNA_def_property(srna, "subsurf_levels", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "subsurfLevels"); RNA_def_property_range(prop, 0, 6); @@ -4100,7 +4100,7 @@ static void rna_def_modifier_ocean(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + static const EnumPropertyItem geometry_items[] = { {MOD_OCEAN_GEOM_GENERATE, "GENERATE", 0, "Generate", "Generate ocean surface geometry at the specified resolution"}, @@ -4111,24 +4111,24 @@ static void rna_def_modifier_ocean(BlenderRNA *brna) #endif {0, NULL, 0, NULL, NULL} }; - + srna = RNA_def_struct(brna, "OceanModifier", "Modifier"); RNA_def_struct_ui_text(srna, "Ocean Modifier", "Simulate an ocean surface"); RNA_def_struct_sdna(srna, "OceanModifierData"); RNA_def_struct_ui_icon(srna, ICON_MOD_OCEAN); - + prop = RNA_def_property(srna, "geometry_mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "geometry_mode"); RNA_def_property_enum_items(prop, geometry_items); RNA_def_property_ui_text(prop, "Geometry", "Method of modifying geometry"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); - + prop = RNA_def_property(srna, "size", PROP_FLOAT, PROP_UNSIGNED); RNA_def_property_float_sdna(prop, NULL, "size"); RNA_def_property_ui_text(prop, "Size", "Surface scale factor (does not affect the height of the waves)"); RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, -1); RNA_def_property_update(prop, 0, "rna_OceanModifier_topology_update"); - + prop = RNA_def_property(srna, "repeat_x", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "repeat_x"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); @@ -4136,7 +4136,7 @@ static void rna_def_modifier_ocean(BlenderRNA *brna) RNA_def_property_ui_range(prop, 1, 100, 1, -1); RNA_def_property_ui_text(prop, "Repeat X", "Repetitions of the generated surface in X"); RNA_def_property_update(prop, 0, "rna_OceanModifier_topology_update"); - + prop = RNA_def_property(srna, "repeat_y", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "repeat_y"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); @@ -4151,13 +4151,13 @@ static void rna_def_modifier_ocean(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Generate Normals", "Output normals for bump mapping - disabling can speed up performance if its not needed"); RNA_def_property_update(prop, 0, "rna_OceanModifier_init_update"); - + prop = RNA_def_property(srna, "use_foam", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_OCEAN_GENERATE_FOAM); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_ui_text(prop, "Generate Foam", "Generate foam mask as a vertex color channel"); RNA_def_property_update(prop, 0, "rna_OceanModifier_init_update"); - + prop = RNA_def_property(srna, "resolution", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "resolution"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); @@ -4165,7 +4165,7 @@ static void rna_def_modifier_ocean(BlenderRNA *brna) RNA_def_property_ui_range(prop, 1, 32, 1, -1); RNA_def_property_ui_text(prop, "Resolution", "Resolution of the generated surface"); RNA_def_property_update(prop, 0, "rna_OceanModifier_init_update"); - + prop = RNA_def_property(srna, "spatial_size", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "spatial_size"); RNA_def_property_ui_range(prop, 1, 512, 2, -1); @@ -4173,66 +4173,66 @@ static void rna_def_modifier_ocean(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Spatial Size", "Size of the simulation domain (in meters), and of the generated geometry (in BU)"); RNA_def_property_update(prop, 0, "rna_OceanModifier_init_update"); - + prop = RNA_def_property(srna, "wind_velocity", PROP_FLOAT, PROP_VELOCITY); RNA_def_property_float_sdna(prop, NULL, "wind_velocity"); RNA_def_property_ui_text(prop, "Wind Velocity", "Wind speed"); RNA_def_property_update(prop, 0, "rna_OceanModifier_init_update"); - + prop = RNA_def_property(srna, "damping", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "damp"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_ui_text(prop, "Damping", "Damp reflected waves going in opposite direction to the wind"); RNA_def_property_update(prop, 0, "rna_OceanModifier_init_update"); - + prop = RNA_def_property(srna, "wave_scale_min", PROP_FLOAT, PROP_DISTANCE); RNA_def_property_float_sdna(prop, NULL, "smallest_wave"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_range(prop, 0.0, FLT_MAX); RNA_def_property_ui_text(prop, "Smallest Wave", "Shortest allowed wavelength"); RNA_def_property_update(prop, 0, "rna_OceanModifier_init_update"); - + prop = RNA_def_property(srna, "wave_alignment", PROP_FLOAT, PROP_UNSIGNED); RNA_def_property_float_sdna(prop, NULL, "wave_alignment"); RNA_def_property_range(prop, 0.0, 10.0); RNA_def_property_ui_text(prop, "Wave Alignment", "How much the waves are aligned to each other"); RNA_def_property_update(prop, 0, "rna_OceanModifier_init_update"); - + prop = RNA_def_property(srna, "wave_direction", PROP_FLOAT, PROP_ANGLE); RNA_def_property_float_sdna(prop, NULL, "wave_direction"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_ui_text(prop, "Wave Direction", "Main direction of the waves when they are (partially) aligned"); RNA_def_property_update(prop, 0, "rna_OceanModifier_init_update"); - + prop = RNA_def_property(srna, "wave_scale", PROP_FLOAT, PROP_UNSIGNED); RNA_def_property_float_sdna(prop, NULL, "wave_scale"); RNA_def_property_ui_text(prop, "Wave Scale", "Scale of the displacement effect"); RNA_def_property_update(prop, 0, "rna_OceanModifier_sim_update"); - + prop = RNA_def_property(srna, "depth", PROP_FLOAT, PROP_DISTANCE); RNA_def_property_float_sdna(prop, NULL, "depth"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_ui_text(prop, "Depth", "Depth of the solid ground below the water surface"); RNA_def_property_ui_range(prop, 0, 250, 1, -1); RNA_def_property_update(prop, 0, "rna_OceanModifier_init_update"); - + prop = RNA_def_property(srna, "foam_coverage", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "foam_coverage"); RNA_def_property_ui_text(prop, "Foam Coverage", "Amount of generated foam"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); - + prop = RNA_def_property(srna, "bake_foam_fade", PROP_FLOAT, PROP_UNSIGNED); RNA_def_property_float_sdna(prop, NULL, "foam_fade"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_ui_text(prop, "Foam Fade", "How much foam accumulates over time (baked ocean only)"); RNA_def_property_ui_range(prop, 0.0, 10.0, 1, -1); RNA_def_property_update(prop, 0, NULL); - + prop = RNA_def_property(srna, "foam_layer_name", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "foamlayername"); RNA_def_property_ui_text(prop, "Foam Layer Name", "Name of the vertex color layer used for foam"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); - + prop = RNA_def_property(srna, "choppiness", PROP_FLOAT, PROP_UNSIGNED); RNA_def_property_float_sdna(prop, NULL, "chop_amount"); RNA_def_property_ui_text(prop, "Choppiness", @@ -4240,31 +4240,31 @@ static void rna_def_modifier_ocean(BlenderRNA *brna) RNA_def_property_ui_range(prop, 0.0, 4.0, 3, -1); RNA_def_property_float_funcs(prop, NULL, "rna_OceanModifier_ocean_chop_set", NULL); RNA_def_property_update(prop, 0, "rna_OceanModifier_sim_update"); - + prop = RNA_def_property(srna, "time", PROP_FLOAT, PROP_UNSIGNED); RNA_def_property_float_sdna(prop, NULL, "time"); RNA_def_property_ui_text(prop, "Time", "Current time of the simulation"); RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, -1); RNA_def_property_update(prop, 0, "rna_OceanModifier_sim_update"); - + prop = RNA_def_property(srna, "random_seed", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "seed"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_ui_text(prop, "Random Seed", "Seed of the random generator"); RNA_def_property_update(prop, 0, "rna_OceanModifier_init_update"); - + prop = RNA_def_property(srna, "frame_start", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "bakestart"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_ui_text(prop, "Bake Start", "Start frame of the ocean baking"); RNA_def_property_update(prop, 0, "rna_OceanModifier_init_update"); - + prop = RNA_def_property(srna, "frame_end", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "bakeend"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_ui_text(prop, "Bake End", "End frame of the ocean baking"); RNA_def_property_update(prop, 0, "rna_OceanModifier_init_update"); - + prop = RNA_def_property(srna, "is_cached", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "cached", 1); RNA_def_property_clear_flag(prop, PROP_EDITABLE); @@ -4904,6 +4904,14 @@ static void rna_def_modifier_normaledit(BlenderRNA *brna) RNA_def_property_subtype(prop, PROP_ANGLE); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + prop = RNA_def_property(srna, "no_polynors_fix", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_NORMALEDIT_NO_POLYNORS_FIX); + RNA_def_property_boolean_default(prop, false); + RNA_def_property_ui_text(prop, "Lock Polygon Normals", + "Do not flip polygons when their normals are not consistent " + "with their newly computed custom vertex normals"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "defgrp_name"); RNA_def_property_ui_text(prop, "Vertex Group", "Vertex group name for selecting/weighting the affected areas"); @@ -5044,28 +5052,28 @@ void RNA_def_modifier(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + /* data */ srna = RNA_def_struct(brna, "Modifier", NULL); RNA_def_struct_ui_text(srna, "Modifier", "Modifier affecting the geometry data of an object"); RNA_def_struct_refine_func(srna, "rna_Modifier_refine"); RNA_def_struct_path_func(srna, "rna_Modifier_path"); RNA_def_struct_sdna(srna, "ModifierData"); - + /* strings */ prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); RNA_def_property_string_funcs(prop, NULL, NULL, "rna_Modifier_name_set"); RNA_def_property_ui_text(prop, "Name", "Modifier name"); RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER | NA_RENAME, NULL); RNA_def_struct_name_property(srna, prop); - + /* enums */ prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_enum_sdna(prop, NULL, "type"); RNA_def_property_enum_items(prop, rna_enum_object_modifier_type_items); RNA_def_property_ui_text(prop, "Type", ""); - + /* flags */ prop = RNA_def_property(srna, "show_viewport", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "mode", eModifierMode_Realtime); @@ -5074,26 +5082,26 @@ void RNA_def_modifier(BlenderRNA *brna) RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC); RNA_def_property_update(prop, 0, "rna_Modifier_update"); RNA_def_property_ui_icon(prop, ICON_RESTRICT_VIEW_OFF, 0); - + prop = RNA_def_property(srna, "show_render", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "mode", eModifierMode_Render); RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC); RNA_def_property_ui_text(prop, "Render", "Use modifier during render"); RNA_def_property_ui_icon(prop, ICON_SCENE, 0); RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, NULL); - + prop = RNA_def_property(srna, "show_in_editmode", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "mode", eModifierMode_Editmode); RNA_def_property_ui_text(prop, "Edit Mode", "Display modifier in Edit mode"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); RNA_def_property_ui_icon(prop, ICON_EDITMODE_HLT, 0); - + prop = RNA_def_property(srna, "show_on_cage", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "mode", eModifierMode_OnCage); RNA_def_property_ui_text(prop, "On Cage", "Adjust edit cage to modifier result"); RNA_def_property_ui_icon(prop, ICON_MESH_DATA, 0); RNA_def_property_update(prop, 0, "rna_Modifier_update"); - + prop = RNA_def_property(srna, "show_expanded", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "mode", eModifierMode_Expanded); RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC); diff --git a/source/blender/makesrna/intern/rna_nla.c b/source/blender/makesrna/intern/rna_nla.c index 38086a47c51..404d9089cd9 100644 --- a/source/blender/makesrna/intern/rna_nla.c +++ b/source/blender/makesrna/intern/rna_nla.c @@ -63,10 +63,10 @@ static void rna_NlaStrip_name_set(PointerRNA *ptr, const char *value) { NlaStrip *data = (NlaStrip *)ptr->data; - + /* copy the name first */ BLI_strncpy_utf8(data->name, value, sizeof(data->name)); - + /* validate if there's enough info to do so */ if (ptr->id.data) { AnimData *adt = BKE_animdata_from_id(ptr->id.data); @@ -78,12 +78,12 @@ static char *rna_NlaStrip_path(PointerRNA *ptr) { NlaStrip *strip = (NlaStrip *)ptr->data; AnimData *adt = BKE_animdata_from_id(ptr->id.data); - + /* if we're attached to AnimData, try to resolve path back to AnimData */ if (adt) { NlaTrack *nlt; NlaStrip *nls; - + for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) { for (nls = nlt->strips.first; nls; nls = nls->next) { if (nls == strip) { @@ -99,7 +99,7 @@ static char *rna_NlaStrip_path(PointerRNA *ptr) } } } - + /* no path */ return BLI_strdup(""); } @@ -133,7 +133,7 @@ static void rna_NlaStrip_transform_update(Main *bmain, Scene *scene, PointerRNA static void rna_NlaStrip_start_frame_set(PointerRNA *ptr, float value) { NlaStrip *data = (NlaStrip *)ptr->data; - + /* clamp value to lie within valid limits * - cannot start past the end of the strip + some flexibility threshold * - cannot start before the previous strip (if present) ends @@ -144,7 +144,7 @@ static void rna_NlaStrip_start_frame_set(PointerRNA *ptr, float value) if (data->prev) { if (data->prev->type == NLASTRIP_TYPE_TRANSITION) { CLAMP(value, data->prev->start + NLASTRIP_MIN_LEN_THRESH, data->end - NLASTRIP_MIN_LEN_THRESH); - + /* re-adjust the transition to stick to the endpoints of the action-clips */ data->prev->end = value; } @@ -161,7 +161,7 @@ static void rna_NlaStrip_start_frame_set(PointerRNA *ptr, float value) static void rna_NlaStrip_end_frame_set(PointerRNA *ptr, float value) { NlaStrip *data = (NlaStrip *)ptr->data; - + /* clamp value to lie within valid limits * - must not have zero or negative length strip, so cannot start before the first frame * + some minimum-strip-length threshold @@ -172,7 +172,7 @@ static void rna_NlaStrip_end_frame_set(PointerRNA *ptr, float value) if (data->next) { if (data->next->type == NLASTRIP_TYPE_TRANSITION) { CLAMP(value, data->start + NLASTRIP_MIN_LEN_THRESH, data->next->end - NLASTRIP_MIN_LEN_THRESH); - + /* readjust the transition to stick to the endpoints of the action-clips */ data->next->start = value; } @@ -184,16 +184,16 @@ static void rna_NlaStrip_end_frame_set(PointerRNA *ptr, float value) CLAMP(value, data->start + NLASTRIP_MIN_LEN_THRESH, MAXFRAME); } data->end = value; - - + + /* calculate the lengths the strip and its action (if applicable) */ if (data->type == NLASTRIP_TYPE_CLIP) { float len, actlen; - + len = data->end - data->start; actlen = data->actend - data->actstart; if (IS_EQF(actlen, 0.0f)) actlen = 1.0f; - + /* now, adjust the 'scale' setting to reflect this (so that this change can be valid) */ data->scale = len / ((actlen) * data->repeat); } @@ -202,12 +202,12 @@ static void rna_NlaStrip_end_frame_set(PointerRNA *ptr, float value) static void rna_NlaStrip_scale_set(PointerRNA *ptr, float value) { NlaStrip *data = (NlaStrip *)ptr->data; - + /* set scale value */ /* NOTE: these need to be synced with the values in the property definition in rna_def_nlastrip() */ CLAMP(value, 0.0001f, 1000.0f); data->scale = value; - + /* adjust the strip extents in response to this */ BKE_nlastrip_recalculate_bounds(data); } @@ -215,12 +215,12 @@ static void rna_NlaStrip_scale_set(PointerRNA *ptr, float value) static void rna_NlaStrip_repeat_set(PointerRNA *ptr, float value) { NlaStrip *data = (NlaStrip *)ptr->data; - + /* set repeat value */ /* NOTE: these need to be synced with the values in the property definition in rna_def_nlastrip() */ CLAMP(value, 0.01f, 1000.0f); data->repeat = value; - + /* adjust the strip extents in response to this */ BKE_nlastrip_recalculate_bounds(data); } @@ -229,11 +229,11 @@ static void rna_NlaStrip_blend_in_set(PointerRNA *ptr, float value) { NlaStrip *data = (NlaStrip *)ptr->data; float len; - + /* blend-in is limited to the length of the strip, and also cannot overlap with blendout */ len = (data->end - data->start) - data->blendout; CLAMP(value, 0, len); - + data->blendin = value; } @@ -241,30 +241,30 @@ static void rna_NlaStrip_blend_out_set(PointerRNA *ptr, float value) { NlaStrip *data = (NlaStrip *)ptr->data; float len; - + /* blend-out is limited to the length of the strip */ len = (data->end - data->start); CLAMP(value, 0, len); - + /* it also cannot overlap with blendin */ if ((len - value) < data->blendin) value = len - data->blendin; - + data->blendout = value; } static void rna_NlaStrip_use_auto_blend_set(PointerRNA *ptr, int value) { NlaStrip *data = (NlaStrip *)ptr->data; - + if (value) { /* set the flag */ data->flag |= NLASTRIP_FLAG_AUTO_BLENDS; - + /* validate state to ensure that auto-blend gets applied immediately */ if (ptr->id.data) { IdAdtTemplate *iat = (IdAdtTemplate *)ptr->id.data; - + if (iat->adt) { BKE_nla_validate_state(iat->adt); } @@ -273,7 +273,7 @@ static void rna_NlaStrip_use_auto_blend_set(PointerRNA *ptr, int value) else { /* clear the flag */ data->flag &= ~NLASTRIP_FLAG_AUTO_BLENDS; - + /* clear the values too, so that it's clear that there has been an effect */ /* TODO: it's somewhat debatable whether it's better to leave these in instead... */ data->blendin = 0.0f; @@ -284,22 +284,22 @@ static void rna_NlaStrip_use_auto_blend_set(PointerRNA *ptr, int value) static int rna_NlaStrip_action_editable(PointerRNA *ptr, const char **UNUSED(r_info)) { NlaStrip *strip = (NlaStrip *)ptr->data; - + /* strip actions shouldn't be editable if NLA tweakmode is on */ if (ptr->id.data) { AnimData *adt = BKE_animdata_from_id(ptr->id.data); - + if (adt) { /* active action is only editable when it is not a tweaking strip */ if ((adt->flag & ADT_NLA_EDIT_ON) || (adt->actstrip) || (adt->tmpact)) return 0; } } - + /* check for clues that strip probably shouldn't be used... */ if (strip->flag & NLASTRIP_FLAG_TWEAKUSER) return 0; - + /* should be ok, though we may still miss some cases */ return PROP_EDITABLE; } @@ -307,11 +307,11 @@ static int rna_NlaStrip_action_editable(PointerRNA *ptr, const char **UNUSED(r_i static void rna_NlaStrip_action_start_frame_set(PointerRNA *ptr, float value) { NlaStrip *data = (NlaStrip *)ptr->data; - + /* prevent start frame from occurring after end of action */ CLAMP(value, MINAFRAME, data->actend); data->actstart = value; - + /* adjust the strip extents in response to this */ /* TODO: should the strip be moved backwards instead as a special case? */ BKE_nlastrip_recalculate_bounds(data); @@ -320,11 +320,11 @@ static void rna_NlaStrip_action_start_frame_set(PointerRNA *ptr, float value) static void rna_NlaStrip_action_end_frame_set(PointerRNA *ptr, float value) { NlaStrip *data = (NlaStrip *)ptr->data; - + /* prevent end frame from starting before start of action */ CLAMP(value, data->actstart, MAXFRAME); data->actend = value; - + /* adjust the strip extents in response to this */ BKE_nlastrip_recalculate_bounds(data); } @@ -332,7 +332,7 @@ static void rna_NlaStrip_action_end_frame_set(PointerRNA *ptr, float value) static void rna_NlaStrip_animated_influence_set(PointerRNA *ptr, int value) { NlaStrip *data = (NlaStrip *)ptr->data; - + if (value) { /* set the flag, then make sure a curve for this exists */ data->flag |= NLASTRIP_FLAG_USR_INFLUENCE; @@ -345,7 +345,7 @@ static void rna_NlaStrip_animated_influence_set(PointerRNA *ptr, int value) static void rna_NlaStrip_animated_time_set(PointerRNA *ptr, int value) { NlaStrip *data = (NlaStrip *)ptr->data; - + if (value) { /* set the flag, then make sure a curve for this exists */ data->flag |= NLASTRIP_FLAG_USR_TIME; @@ -371,22 +371,22 @@ static NlaStrip *rna_NlaStrip_new(NlaTrack *track, bContext *C, ReportList *repo int start, bAction *action) { NlaStrip *strip = BKE_nlastrip_new(action); - + if (strip == NULL) { BKE_report(reports, RPT_ERROR, "Unable to create new strip"); return NULL; } - + strip->end += (start - strip->start); strip->start = start; - + if (BKE_nlastrips_add_strip(&track->strips, strip) == 0) { BKE_report(reports, RPT_ERROR, "Unable to add strip (the track does not have any space to accommodate this new strip)"); BKE_nlastrip_free(NULL, strip); return NULL; } - + /* create dummy AnimData block so that BKE_nlastrip_validate_name() * can be used to ensure a valid name, as we don't have one here... * - only the nla_tracks list is needed there, which we aim to reverse engineer here... @@ -394,25 +394,25 @@ static NlaStrip *rna_NlaStrip_new(NlaTrack *track, bContext *C, ReportList *repo { AnimData adt = {NULL}; NlaTrack *nlt, *nlt_p; - + /* 'first' NLA track is found by going back up chain of given track's parents until we fall off */ nlt_p = track; nlt = track; while ((nlt = nlt->prev) != NULL) nlt_p = nlt; adt.nla_tracks.first = nlt_p; - + /* do the same thing to find the last track */ nlt_p = track; nlt = track; while ((nlt = nlt->next) != NULL) nlt_p = nlt; adt.nla_tracks.last = nlt_p; - + /* now we can just auto-name as usual */ BKE_nlastrip_validate_name(&adt, strip); } - + WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_ADDED, NULL); - + return strip; } @@ -442,7 +442,7 @@ static void rna_NlaTrack_solo_set(PointerRNA *ptr, int value) if (data == NULL) { return; } - + /* firstly, make sure 'solo' flag for all tracks is disabled */ for (nt = data; nt; nt = nt->next) { nt->flag &= ~NLATRACK_SOLO; @@ -450,12 +450,12 @@ static void rna_NlaTrack_solo_set(PointerRNA *ptr, int value) for (nt = data; nt; nt = nt->prev) { nt->flag &= ~NLATRACK_SOLO; } - + /* now, enable 'solo' for the given track if appropriate */ if (value) { /* set solo status */ data->flag |= NLATRACK_SOLO; - + /* set solo-status on AnimData */ adt->flag |= ADT_NLA_SOLO_TRACK; } @@ -518,7 +518,7 @@ static void rna_def_nlastrip(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + /* enum defs */ static const EnumPropertyItem prop_type_items[] = { {NLASTRIP_TYPE_CLIP, "CLIP", 0, "Action Clip", "NLA Strip references some Action"}, @@ -527,20 +527,20 @@ static void rna_def_nlastrip(BlenderRNA *brna) {NLASTRIP_TYPE_SOUND, "SOUND", 0, "Sound Clip", "NLA Strip representing a sound event for speakers"}, {0, NULL, 0, NULL, NULL} }; - + /* struct definition */ srna = RNA_def_struct(brna, "NlaStrip", NULL); RNA_def_struct_ui_text(srna, "NLA Strip", "A container referencing an existing Action"); RNA_def_struct_path_func(srna, "rna_NlaStrip_path"); RNA_def_struct_ui_icon(srna, ICON_NLA); /* XXX */ - + /* name property */ prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); RNA_def_property_ui_text(prop, "Name", ""); RNA_def_property_string_funcs(prop, NULL, NULL, "rna_NlaStrip_name_set"); RNA_def_struct_name_property(srna, prop); RNA_def_property_update(prop, NC_ANIMATION | ND_NLA, NULL); /* this will do? */ - + /* Enums */ prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "type"); @@ -548,19 +548,19 @@ static void rna_def_nlastrip(BlenderRNA *brna) RNA_def_property_enum_items(prop, prop_type_items); RNA_def_property_ui_text(prop, "Type", "Type of NLA Strip"); RNA_def_property_update(prop, NC_ANIMATION | ND_NLA | NA_EDITED, "rna_NlaStrip_update"); - + prop = RNA_def_property(srna, "extrapolation", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "extendmode"); RNA_def_property_enum_items(prop, rna_enum_nla_mode_extend_items); RNA_def_property_ui_text(prop, "Extrapolation", "Action to take for gaps past the strip extents"); RNA_def_property_update(prop, NC_ANIMATION | ND_NLA | NA_EDITED, "rna_NlaStrip_update"); - + prop = RNA_def_property(srna, "blend_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "blendmode"); RNA_def_property_enum_items(prop, rna_enum_nla_mode_blend_items); RNA_def_property_ui_text(prop, "Blending", "Method used for combining strip's result with accumulated result"); RNA_def_property_update(prop, NC_ANIMATION | ND_NLA | NA_EDITED, "rna_NlaStrip_update"); - + /* Strip extents */ prop = RNA_def_property(srna, "frame_start", PROP_FLOAT, PROP_TIME); RNA_def_property_float_sdna(prop, NULL, "start"); @@ -573,20 +573,20 @@ static void rna_def_nlastrip(BlenderRNA *brna) RNA_def_property_float_funcs(prop, NULL, "rna_NlaStrip_end_frame_set", NULL); RNA_def_property_ui_text(prop, "End Frame", ""); RNA_def_property_update(prop, NC_ANIMATION | ND_NLA | NA_EDITED, "rna_NlaStrip_transform_update"); - + /* Blending */ prop = RNA_def_property(srna, "blend_in", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "blendin"); RNA_def_property_float_funcs(prop, NULL, "rna_NlaStrip_blend_in_set", NULL); RNA_def_property_ui_text(prop, "Blend In", "Number of frames at start of strip to fade in influence"); RNA_def_property_update(prop, NC_ANIMATION | ND_NLA | NA_EDITED, "rna_NlaStrip_update"); - + prop = RNA_def_property(srna, "blend_out", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "blendout"); RNA_def_property_float_funcs(prop, NULL, "rna_NlaStrip_blend_out_set", NULL); RNA_def_property_ui_text(prop, "Blend Out", ""); RNA_def_property_update(prop, NC_ANIMATION | ND_NLA | NA_EDITED, "rna_NlaStrip_update"); - + prop = RNA_def_property(srna, "use_auto_blend", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", NLASTRIP_FLAG_AUTO_BLENDS); RNA_def_property_boolean_funcs(prop, NULL, "rna_NlaStrip_use_auto_blend_set"); @@ -594,7 +594,7 @@ static void rna_def_nlastrip(BlenderRNA *brna) "Number of frames for Blending In/Out is automatically determined from " "overlapping strips"); RNA_def_property_update(prop, NC_ANIMATION | ND_NLA | NA_EDITED, "rna_NlaStrip_update"); - + /* Action */ prop = RNA_def_property(srna, "action", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "act"); @@ -603,20 +603,20 @@ static void rna_def_nlastrip(BlenderRNA *brna) RNA_def_property_editable_func(prop, "rna_NlaStrip_action_editable"); RNA_def_property_ui_text(prop, "Action", "Action referenced by this strip"); RNA_def_property_update(prop, NC_ANIMATION | ND_NLA | NA_EDITED, "rna_NlaStrip_update"); - + /* Action extents */ prop = RNA_def_property(srna, "action_frame_start", PROP_FLOAT, PROP_TIME); RNA_def_property_float_sdna(prop, NULL, "actstart"); RNA_def_property_float_funcs(prop, NULL, "rna_NlaStrip_action_start_frame_set", NULL); RNA_def_property_ui_text(prop, "Action Start Frame", "First frame from action to use"); RNA_def_property_update(prop, NC_ANIMATION | ND_NLA | NA_EDITED, "rna_NlaStrip_transform_update"); - + prop = RNA_def_property(srna, "action_frame_end", PROP_FLOAT, PROP_TIME); RNA_def_property_float_sdna(prop, NULL, "actend"); RNA_def_property_float_funcs(prop, NULL, "rna_NlaStrip_action_end_frame_set", NULL); RNA_def_property_ui_text(prop, "Action End Frame", "Last frame from action to use"); RNA_def_property_update(prop, NC_ANIMATION | ND_NLA | NA_EDITED, "rna_NlaStrip_transform_update"); - + /* Action Reuse */ prop = RNA_def_property(srna, "repeat", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "repeat"); @@ -626,7 +626,7 @@ static void rna_def_nlastrip(BlenderRNA *brna) RNA_def_property_range(prop, 0.1f, 1000.0f); RNA_def_property_ui_text(prop, "Repeat", "Number of times to repeat the action range"); RNA_def_property_update(prop, NC_ANIMATION | ND_NLA | NA_EDITED, "rna_NlaStrip_transform_update"); - + prop = RNA_def_property(srna, "scale", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "scale"); RNA_def_property_float_funcs(prop, NULL, "rna_NlaStrip_scale_set", NULL); @@ -635,7 +635,7 @@ static void rna_def_nlastrip(BlenderRNA *brna) RNA_def_property_range(prop, 0.0001f, 1000.0f); RNA_def_property_ui_text(prop, "Scale", "Scaling factor for action"); RNA_def_property_update(prop, NC_ANIMATION | ND_NLA | NA_EDITED, "rna_NlaStrip_transform_update"); - + /* Strip's F-Curves */ prop = RNA_def_property(srna, "fcurves", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "fcurves", NULL); @@ -647,13 +647,13 @@ static void rna_def_nlastrip(BlenderRNA *brna) prop = RNA_def_property(srna, "modifiers", PROP_COLLECTION, PROP_NONE); RNA_def_property_struct_type(prop, "FModifier"); RNA_def_property_ui_text(prop, "Modifiers", "Modifiers affecting all the F-Curves in the referenced Action"); - + /* Strip's Sub-Strips (for Meta-Strips) */ prop = RNA_def_property(srna, "strips", PROP_COLLECTION, PROP_NONE); RNA_def_property_struct_type(prop, "NlaStrip"); RNA_def_property_ui_text(prop, "NLA Strips", "NLA Strips that this strip acts as a container for (if it is of type Meta)"); - + /* Settings - Values necessary for evaluation */ prop = RNA_def_property(srna, "influence", PROP_FLOAT, PROP_FACTOR); RNA_def_property_range(prop, 0.0f, 1.0f); @@ -662,14 +662,14 @@ static void rna_def_nlastrip(BlenderRNA *brna) * Even autokey only applies after the curves have been re-evaluated, causing the unkeyed values to be lost */ RNA_def_property_update(prop, NC_ANIMATION | ND_NLA | NA_EDITED, /*"rna_NlaStrip_update"*/ NULL); - + prop = RNA_def_property(srna, "strip_time", PROP_FLOAT, PROP_TIME); RNA_def_property_ui_text(prop, "Strip Time", "Frame of referenced Action to evaluate"); /* XXX: Update temporarily disabled so that the property can be edited at all! * Even autokey only applies after the curves have been re-evaluated, causing the unkeyed values to be lost */ RNA_def_property_update(prop, NC_ANIMATION | ND_NLA | NA_EDITED, /*"rna_NlaStrip_update"*/ NULL); - + /* TODO: should the animated_influence/time settings be animatable themselves? */ prop = RNA_def_property(srna, "use_animated_influence", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", NLASTRIP_FLAG_USR_INFLUENCE); @@ -677,19 +677,19 @@ static void rna_def_nlastrip(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Animated Influence", "Influence setting is controlled by an F-Curve rather than automatically determined"); RNA_def_property_update(prop, NC_ANIMATION | ND_NLA | NA_EDITED, "rna_NlaStrip_update"); - + prop = RNA_def_property(srna, "use_animated_time", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", NLASTRIP_FLAG_USR_TIME); RNA_def_property_boolean_funcs(prop, NULL, "rna_NlaStrip_animated_time_set"); RNA_def_property_ui_text(prop, "Animated Strip Time", "Strip time is controlled by an F-Curve rather than automatically determined"); RNA_def_property_update(prop, NC_ANIMATION | ND_NLA | NA_EDITED, "rna_NlaStrip_update"); - + prop = RNA_def_property(srna, "use_animated_time_cyclic", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", NLASTRIP_FLAG_USR_TIME_CYCLIC); RNA_def_property_ui_text(prop, "Cyclic Strip Time", "Cycle the animated time within the action start & end"); RNA_def_property_update(prop, NC_ANIMATION | ND_NLA | NA_EDITED, "rna_NlaStrip_transform_update"); - + /* settings */ prop = RNA_def_property(srna, "active", PROP_BOOLEAN, PROP_NONE); /* can be made editable by hooking it up to the necessary NLA API methods */ @@ -697,24 +697,24 @@ static void rna_def_nlastrip(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", NLASTRIP_FLAG_ACTIVE); RNA_def_property_ui_text(prop, "Active", "NLA Strip is active"); RNA_def_property_update(prop, NC_ANIMATION | ND_NLA, NULL); /* this will do? */ - + prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", NLASTRIP_FLAG_SELECT); RNA_def_property_ui_text(prop, "Select", "NLA Strip is selected"); RNA_def_property_update(prop, NC_ANIMATION | ND_NLA, NULL); /* this will do? */ - + prop = RNA_def_property(srna, "mute", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", NLASTRIP_FLAG_MUTED); RNA_def_property_ui_text(prop, "Muted", "NLA Strip is not evaluated"); RNA_def_property_update(prop, NC_ANIMATION | ND_NLA | NA_EDITED, "rna_NlaStrip_update"); - + prop = RNA_def_property(srna, "use_reverse", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", NLASTRIP_FLAG_REVERSE); RNA_def_property_ui_text(prop, "Reversed", "NLA Strip is played back in reverse order (only when timing is " "automatically determined)"); RNA_def_property_update(prop, NC_ANIMATION | ND_NLA | NA_EDITED, "rna_NlaStrip_update"); - + prop = RNA_def_property(srna, "use_sync_length", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", NLASTRIP_FLAG_SYNC_LENGTH); RNA_def_property_ui_text(prop, "Sync Action Length", @@ -760,11 +760,11 @@ static void rna_def_nlatrack(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + srna = RNA_def_struct(brna, "NlaTrack", NULL); RNA_def_struct_ui_text(srna, "NLA Track", "A animation layer containing Actions referenced as NLA strips"); RNA_def_struct_ui_icon(srna, ICON_NLA); - + /* strips collection */ prop = RNA_def_property(srna, "strips", PROP_COLLECTION, PROP_NONE); RNA_def_property_struct_type(prop, "NlaStrip"); @@ -777,7 +777,7 @@ static void rna_def_nlatrack(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Name", ""); RNA_def_struct_name_property(srna, prop); RNA_def_property_update(prop, NC_ANIMATION | ND_NLA, NULL); /* this will do? */ - + /* settings */ prop = RNA_def_property(srna, "active", PROP_BOOLEAN, PROP_NONE); /* can be made editable by hooking it up to the necessary NLA API methods */ @@ -785,7 +785,7 @@ static void rna_def_nlatrack(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", NLATRACK_ACTIVE); RNA_def_property_ui_text(prop, "Active", "NLA Track is active"); RNA_def_property_update(prop, NC_ANIMATION | ND_NLA, NULL); /* this will do? */ - + prop = RNA_def_property(srna, "is_solo", PROP_BOOLEAN, PROP_NONE); /* can be made editable by hooking it up to the necessary NLA API methods */ RNA_def_property_boolean_sdna(prop, NULL, "flag", NLATRACK_SOLO); @@ -799,7 +799,7 @@ static void rna_def_nlatrack(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", NLATRACK_SELECTED); RNA_def_property_ui_text(prop, "Select", "NLA Track is selected"); RNA_def_property_update(prop, NC_ANIMATION | ND_NLA, NULL); /* this will do? */ - + prop = RNA_def_property(srna, "mute", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", NLATRACK_MUTED); RNA_def_property_ui_text(prop, "Muted", "NLA Track is not evaluated"); diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 4f928a9a831..3790dffec3b 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -261,15 +261,15 @@ const EnumPropertyItem *rna_node_tree_type_itemf(void *data, int (*poll)(void *d ++i; continue; } - + tmp.value = i; tmp.identifier = nt->idname; tmp.icon = nt->ui_icon; tmp.name = nt->ui_name; tmp.description = nt->ui_description; - + RNA_enum_item_add(&item, &totitem, &tmp); - + ++i; } NODE_TREE_TYPES_END; @@ -336,15 +336,15 @@ const EnumPropertyItem *rna_node_type_itemf(void *data, int (*poll)(void *data, ++i; continue; } - + tmp.value = i; tmp.identifier = ntype->idname; tmp.icon = ntype->ui_icon; tmp.name = ntype->ui_name; tmp.description = ntype->ui_description; - + RNA_enum_item_add(&item, &totitem, &tmp); - + ++i; NODE_TYPES_END @@ -412,16 +412,16 @@ const EnumPropertyItem *rna_node_socket_type_itemf( ++i; continue; } - + srna = stype->ext_socket.srna; tmp.value = i; tmp.identifier = stype->idname; tmp.icon = RNA_struct_ui_icon(srna); tmp.name = RNA_struct_ui_name(srna); tmp.description = RNA_struct_ui_description(srna); - + RNA_enum_item_add(&item, &totitem, &tmp); - + ++i; NODE_SOCKET_TYPES_END @@ -525,7 +525,7 @@ static const EnumPropertyItem *rna_node_static_type_itemf(bContext *UNUSED(C), P static StructRNA *rna_NodeTree_refine(struct PointerRNA *ptr) { bNodeTree *ntree = (bNodeTree *)ptr->data; - + if (ntree->typeinfo->ext.srna) return ntree->typeinfo->ext.srna; else @@ -590,7 +590,7 @@ static void rna_NodeTree_get_from_context(const bContext *C, bNodeTreeType *ntre RNA_parameter_list_create(&list, &ptr, func); RNA_parameter_set_lookup(&list, "context", &C); ntreetype->ext.call((bContext *)C, &ptr, func, &list); - + RNA_parameter_get_lookup(&list, "result_1", &ret1); RNA_parameter_get_lookup(&list, "result_2", &ret2); RNA_parameter_get_lookup(&list, "result_3", &ret3); @@ -654,7 +654,7 @@ static StructRNA *rna_NodeTree_register( nt->type = NTREE_CUSTOM; - nt->ext.srna = RNA_def_struct_ptr(&BLENDER_RNA, nt->idname, &RNA_NodeTree); + nt->ext.srna = RNA_def_struct_ptr(&BLENDER_RNA, nt->idname, &RNA_NodeTree); nt->ext.data = data; nt->ext.call = call; nt->ext.free = free; @@ -671,7 +671,7 @@ static StructRNA *rna_NodeTree_register( /* update while blender is running */ WM_main_add_notifier(NC_NODE | NA_EDITED, NULL); - + return nt->ext.srna; } @@ -680,7 +680,7 @@ static bool rna_NodeTree_check(bNodeTree *ntree, ReportList *reports) if (!ntreeIsRegistered(ntree)) { if (reports) BKE_reportf(reports, RPT_ERROR, "Node tree '%s' has undefined type %s", ntree->id.name + 2, ntree->idname); - + return false; } else @@ -702,28 +702,28 @@ static bNode *rna_NodeTree_node_new(bNodeTree *ntree, bContext *C, ReportList *r { bNodeType *ntype; bNode *node; - + if (!rna_NodeTree_check(ntree, reports)) return NULL; - + ntype = nodeTypeFind(type); if (!ntype) { BKE_reportf(reports, RPT_ERROR, "Node type %s undefined", type); return NULL; } - + if (ntype->poll && !ntype->poll(ntype, ntree)) { BKE_reportf(reports, RPT_ERROR, "Cannot add node of type %s to node tree '%s'", type, ntree->id.name + 2); return NULL; } - + node = nodeAddNode(C, ntree, type); BLI_assert(node && node->typeinfo); - + if (ntree->type == NTREE_TEXTURE) { ntreeTexCheckCyclics(ntree); } - + ntreeUpdateTree(CTX_data_main(C), ntree); nodeUpdate(ntree, node); WM_main_add_notifier(NC_NODE | NA_EDITED, ntree); @@ -734,10 +734,10 @@ static bNode *rna_NodeTree_node_new(bNodeTree *ntree, bContext *C, ReportList *r static void rna_NodeTree_node_remove(bNodeTree *ntree, Main *bmain, ReportList *reports, PointerRNA *node_ptr) { bNode *node = node_ptr->data; - + if (!rna_NodeTree_check(ntree, reports)) return; - + if (BLI_findindex(&ntree->nodes, node) == -1) { BKE_reportf(reports, RPT_ERROR, "Unable to locate node '%s' in node tree", node->name); return; @@ -785,7 +785,7 @@ static void rna_NodeTree_active_node_set(PointerRNA *ptr, const PointerRNA value { bNodeTree *ntree = (bNodeTree *)ptr->data; bNode *node = (bNode *)value.data; - + if (node && BLI_findindex(&ntree->nodes, node) != -1) nodeSetActive(ntree, node); else @@ -809,7 +809,7 @@ static bNodeLink *rna_NodeTree_link_new(bNodeTree *ntree, Main *bmain, ReportLis */ if (!fromnode || !tonode) return NULL; - + if (&fromsock->in_out == &tosock->in_out) { BKE_report(reports, RPT_ERROR, "Same input/output direction of sockets"); return NULL; @@ -824,7 +824,7 @@ static bNodeLink *rna_NodeTree_link_new(bNodeTree *ntree, Main *bmain, ReportLis } ret = nodeAddLink(ntree, fromnode, fromsock, tonode, tosock); - + if (ret) { /* not an issue from the UI, clear hidden from API to keep valid state. */ @@ -897,7 +897,7 @@ static void rna_NodeTree_active_input_set(PointerRNA *ptr, int value) bNodeTree *ntree = (bNodeTree *)ptr->data; bNodeSocket *gsock; int index; - + for (gsock = ntree->inputs.first, index = 0; gsock; gsock = gsock->next, ++index) { if (index == value) gsock->flag |= SELECT; @@ -926,7 +926,7 @@ static void rna_NodeTree_active_output_set(PointerRNA *ptr, int value) bNodeTree *ntree = (bNodeTree *)ptr->data; bNodeSocket *gsock; int index; - + for (gsock = ntree->inputs.first; gsock; gsock = gsock->next) { gsock->flag &= ~SELECT; } @@ -941,30 +941,30 @@ static void rna_NodeTree_active_output_set(PointerRNA *ptr, int value) static bNodeSocket *rna_NodeTree_inputs_new(bNodeTree *ntree, Main *bmain, ReportList *reports, const char *type, const char *name) { bNodeSocket *sock; - + if (!rna_NodeTree_check(ntree, reports)) return NULL; - + sock = ntreeAddSocketInterface(ntree, SOCK_IN, type, name); - + ntreeUpdateTree(bmain, ntree); WM_main_add_notifier(NC_NODE | NA_EDITED, ntree); - + return sock; } static bNodeSocket *rna_NodeTree_outputs_new(bNodeTree *ntree, Main *bmain, ReportList *reports, const char *type, const char *name) { bNodeSocket *sock; - + if (!rna_NodeTree_check(ntree, reports)) return NULL; - + sock = ntreeAddSocketInterface(ntree, SOCK_OUT, type, name); - + ntreeUpdateTree(bmain, ntree); WM_main_add_notifier(NC_NODE | NA_EDITED, ntree); - + return sock; } @@ -972,13 +972,13 @@ static void rna_NodeTree_socket_remove(bNodeTree *ntree, Main *bmain, ReportList { if (!rna_NodeTree_check(ntree, reports)) return; - + if (BLI_findindex(&ntree->inputs, sock) == -1 && BLI_findindex(&ntree->outputs, sock) == -1) { BKE_reportf(reports, RPT_ERROR, "Unable to locate socket '%s' in node", sock->identifier); } else { ntreeRemoveSocketInterface(ntree, sock); - + ntreeUpdateTree(bmain, ntree); WM_main_add_notifier(NC_NODE | NA_EDITED, ntree); } @@ -987,10 +987,10 @@ static void rna_NodeTree_socket_remove(bNodeTree *ntree, Main *bmain, ReportList static void rna_NodeTree_inputs_clear(bNodeTree *ntree, Main *bmain, ReportList *reports) { bNodeSocket *sock, *nextsock; - + if (!rna_NodeTree_check(ntree, reports)) return; - + for (sock = ntree->inputs.first; sock; sock = nextsock) { nextsock = sock->next; ntreeRemoveSocketInterface(ntree, sock); @@ -1003,10 +1003,10 @@ static void rna_NodeTree_inputs_clear(bNodeTree *ntree, Main *bmain, ReportList static void rna_NodeTree_outputs_clear(bNodeTree *ntree, Main *bmain, ReportList *reports) { bNodeSocket *sock, *nextsock; - + if (!rna_NodeTree_check(ntree, reports)) return; - + for (sock = ntree->outputs.first; sock; sock = nextsock) { nextsock = sock->next; ntreeRemoveSocketInterface(ntree, sock); @@ -1019,12 +1019,12 @@ static void rna_NodeTree_outputs_clear(bNodeTree *ntree, Main *bmain, ReportList static void rna_NodeTree_inputs_move(bNodeTree *ntree, Main *bmain, int from_index, int to_index) { bNodeSocket *sock; - + if (from_index == to_index) return; if (from_index < 0 || to_index < 0) return; - + sock = BLI_findlink(&ntree->inputs, from_index); if (to_index < from_index) { bNodeSocket *nextsock = BLI_findlink(&ntree->inputs, to_index); @@ -1040,9 +1040,9 @@ static void rna_NodeTree_inputs_move(bNodeTree *ntree, Main *bmain, int from_ind BLI_insertlinkafter(&ntree->inputs, prevsock, sock); } } - + ntree->update |= NTREE_UPDATE_GROUP_IN; - + ntreeUpdateTree(bmain, ntree); WM_main_add_notifier(NC_NODE | NA_EDITED, ntree); } @@ -1050,12 +1050,12 @@ static void rna_NodeTree_inputs_move(bNodeTree *ntree, Main *bmain, int from_ind static void rna_NodeTree_outputs_move(bNodeTree *ntree, Main *bmain, int from_index, int to_index) { bNodeSocket *sock; - + if (from_index == to_index) return; if (from_index < 0 || to_index < 0) return; - + sock = BLI_findlink(&ntree->outputs, from_index); if (to_index < from_index) { bNodeSocket *nextsock = BLI_findlink(&ntree->outputs, to_index); @@ -1071,9 +1071,9 @@ static void rna_NodeTree_outputs_move(bNodeTree *ntree, Main *bmain, int from_in BLI_insertlinkafter(&ntree->outputs, prevsock, sock); } } - + ntree->update |= NTREE_UPDATE_GROUP_OUT; - + ntreeUpdateTree(bmain, ntree); WM_main_add_notifier(NC_NODE | NA_EDITED, ntree); } @@ -1084,7 +1084,7 @@ static void rna_NodeTree_interface_update(bNodeTree *ntree, bContext *C) ntree->update |= NTREE_UPDATE_GROUP; ntreeUpdateTree(bmain, ntree); - + ED_node_tag_update_nodetree(bmain, ntree, NULL); } @@ -1103,7 +1103,7 @@ static int rna_NodeLink_is_hidden_get(PointerRNA *ptr) static StructRNA *rna_Node_refine(struct PointerRNA *ptr) { bNode *node = (bNode *)ptr->data; - + if (node->typeinfo->ext.srna) return node->typeinfo->ext.srna; else @@ -1412,7 +1412,7 @@ static bNodeType *rna_Node_register_base(Main *bmain, ReportList *reports, Struc if (nt) { rna_Node_unregister(bmain, nt->ext.srna); } - + /* create a new node type */ nt = MEM_callocN(sizeof(bNodeType), "node type"); memcpy(nt, &dummynt, sizeof(dummynt)); @@ -1447,7 +1447,7 @@ static bNodeType *rna_Node_register_base(Main *bmain, ReportList *reports, Struc nt->draw_buttons = (have_function[7]) ? rna_Node_draw_buttons : NULL; nt->draw_buttons_ex = (have_function[8]) ? rna_Node_draw_buttons_ext : NULL; nt->labelfunc = (have_function[9]) ? rna_Node_draw_label : NULL; - + /* sanitize size values in case not all have been registered */ if (nt->maxwidth < nt->minwidth) nt->maxwidth = nt->minwidth; @@ -1455,7 +1455,7 @@ static bNodeType *rna_Node_register_base(Main *bmain, ReportList *reports, Struc nt->maxheight = nt->minheight; CLAMP(nt->width, nt->minwidth, nt->maxwidth); CLAMP(nt->height, nt->minheight, nt->maxheight); - + return nt; } @@ -1467,12 +1467,12 @@ static StructRNA *rna_Node_register( bNodeType *nt = rna_Node_register_base(bmain, reports, &RNA_Node, data, identifier, validate, call, free); if (!nt) return NULL; - + nodeRegisterType(nt); - + /* update while blender is running */ WM_main_add_notifier(NC_NODE | NA_EDITED, NULL); - + return nt->ext.srna; } @@ -1484,12 +1484,12 @@ static StructRNA *rna_ShaderNode_register( bNodeType *nt = rna_Node_register_base(bmain, reports, &RNA_ShaderNode, data, identifier, validate, call, free); if (!nt) return NULL; - + nodeRegisterType(nt); - + /* update while blender is running */ WM_main_add_notifier(NC_NODE | NA_EDITED, NULL); - + return nt->ext.srna; } @@ -1501,12 +1501,12 @@ static StructRNA *rna_CompositorNode_register( bNodeType *nt = rna_Node_register_base(bmain, reports, &RNA_CompositorNode, data, identifier, validate, call, free); if (!nt) return NULL; - + nodeRegisterType(nt); - + /* update while blender is running */ WM_main_add_notifier(NC_NODE | NA_EDITED, NULL); - + return nt->ext.srna; } @@ -1518,24 +1518,24 @@ static StructRNA *rna_TextureNode_register( bNodeType *nt = rna_Node_register_base(bmain, reports, &RNA_TextureNode, data, identifier, validate, call, free); if (!nt) return NULL; - + nodeRegisterType(nt); - + /* update while blender is running */ WM_main_add_notifier(NC_NODE | NA_EDITED, NULL); - + return nt->ext.srna; } static IDProperty *rna_Node_idprops(PointerRNA *ptr, bool create) { bNode *node = ptr->data; - + if (create && !node->prop) { IDPropertyTemplate val = {0}; node->prop = IDP_New(IDP_GROUP, &val, "RNA_Node ID properties"); } - + return node->prop; } @@ -1543,19 +1543,19 @@ static void rna_Node_parent_set(PointerRNA *ptr, PointerRNA value) { bNode *node = ptr->data; bNode *parent = value.data; - + if (parent) { /* XXX only Frame node allowed for now, * in the future should have a poll function or so to test possible attachment. */ if (parent->type != NODE_FRAME) return; - + /* make sure parent is not attached to the node */ if (nodeAttachNodeCheck(parent, node)) return; } - + nodeDetachNode(node); if (parent) { nodeAttachNode(node, parent); @@ -1566,17 +1566,17 @@ static int rna_Node_parent_poll(PointerRNA *ptr, PointerRNA value) { bNode *node = ptr->data; bNode *parent = value.data; - + /* XXX only Frame node allowed for now, * in the future should have a poll function or so to test possible attachment. */ if (parent->type != NODE_FRAME) return false; - + /* make sure parent is not attached to the node */ if (nodeAttachNodeCheck(parent, node)) return false; - + return true; } @@ -1603,14 +1603,14 @@ static void rna_Node_name_set(PointerRNA *ptr, const char *value) bNodeTree *ntree = (bNodeTree *)ptr->id.data; bNode *node = (bNode *)ptr->data; char oldname[sizeof(node->name)]; - + /* make a copy of the old name first */ BLI_strncpy(oldname, node->name, sizeof(node->name)); /* set new name */ BLI_strncpy_utf8(node->name, value, sizeof(node->name)); - + nodeUniqueName(ntree, node); - + /* fix all the animation data which may link to this */ BKE_animdata_fix_paths_rename_all(NULL, "nodes", oldname, node->name); } @@ -1619,9 +1619,9 @@ static bNodeSocket *rna_Node_inputs_new(ID *id, bNode *node, Main *bmain, Report { bNodeTree *ntree = (bNodeTree *)id; bNodeSocket *sock; - + sock = nodeAddSocket(ntree, node, SOCK_IN, type, identifier, name); - + if (sock == NULL) { BKE_report(reports, RPT_ERROR, "Unable to create socket"); } @@ -1629,7 +1629,7 @@ static bNodeSocket *rna_Node_inputs_new(ID *id, bNode *node, Main *bmain, Report ntreeUpdateTree(bmain, ntree); WM_main_add_notifier(NC_NODE | NA_EDITED, ntree); } - + return sock; } @@ -1637,9 +1637,9 @@ static bNodeSocket *rna_Node_outputs_new(ID *id, bNode *node, Main *bmain, Repor { bNodeTree *ntree = (bNodeTree *)id; bNodeSocket *sock; - + sock = nodeAddSocket(ntree, node, SOCK_OUT, type, identifier, name); - + if (sock == NULL) { BKE_report(reports, RPT_ERROR, "Unable to create socket"); } @@ -1647,20 +1647,20 @@ static bNodeSocket *rna_Node_outputs_new(ID *id, bNode *node, Main *bmain, Repor ntreeUpdateTree(bmain, ntree); WM_main_add_notifier(NC_NODE | NA_EDITED, ntree); } - + return sock; } static void rna_Node_socket_remove(ID *id, bNode *node, Main *bmain, ReportList *reports, bNodeSocket *sock) { bNodeTree *ntree = (bNodeTree *)id; - + if (BLI_findindex(&node->inputs, sock) == -1 && BLI_findindex(&node->outputs, sock) == -1) { BKE_reportf(reports, RPT_ERROR, "Unable to locate socket '%s' in node", sock->identifier); } else { nodeRemoveSocket(ntree, node, sock); - + ntreeUpdateTree(bmain, ntree); WM_main_add_notifier(NC_NODE | NA_EDITED, ntree); } @@ -1670,7 +1670,7 @@ static void rna_Node_inputs_clear(ID *id, bNode *node, Main *bmain) { bNodeTree *ntree = (bNodeTree *)id; bNodeSocket *sock, *nextsock; - + for (sock = node->inputs.first; sock; sock = nextsock) { nextsock = sock->next; nodeRemoveSocket(ntree, node, sock); @@ -1684,7 +1684,7 @@ static void rna_Node_outputs_clear(ID *id, bNode *node, Main *bmain) { bNodeTree *ntree = (bNodeTree *)id; bNodeSocket *sock, *nextsock; - + for (sock = node->outputs.first; sock; sock = nextsock) { nextsock = sock->next; nodeRemoveSocket(ntree, node, sock); @@ -1698,12 +1698,12 @@ static void rna_Node_inputs_move(ID *id, bNode *node, Main *bmain, int from_inde { bNodeTree *ntree = (bNodeTree *)id; bNodeSocket *sock; - + if (from_index == to_index) return; if (from_index < 0 || to_index < 0) return; - + sock = BLI_findlink(&node->inputs, from_index); if (to_index < from_index) { bNodeSocket *nextsock = BLI_findlink(&node->inputs, to_index); @@ -1719,7 +1719,7 @@ static void rna_Node_inputs_move(ID *id, bNode *node, Main *bmain, int from_inde BLI_insertlinkafter(&node->inputs, prevsock, sock); } } - + ntreeUpdateTree(bmain, ntree); WM_main_add_notifier(NC_NODE | NA_EDITED, ntree); } @@ -1728,12 +1728,12 @@ static void rna_Node_outputs_move(ID *id, bNode *node, Main *bmain, int from_ind { bNodeTree *ntree = (bNodeTree *)id; bNodeSocket *sock; - + if (from_index == to_index) return; if (from_index < 0 || to_index < 0) return; - + sock = BLI_findlink(&node->outputs, from_index); if (to_index < from_index) { bNodeSocket *nextsock = BLI_findlink(&node->outputs, to_index); @@ -1749,7 +1749,7 @@ static void rna_Node_outputs_move(ID *id, bNode *node, Main *bmain, int from_ind BLI_insertlinkafter(&node->outputs, prevsock, sock); } } - + ntreeUpdateTree(bmain, ntree); WM_main_add_notifier(NC_NODE | NA_EDITED, ntree); } @@ -1825,7 +1825,7 @@ static void rna_NodeSocket_unregister(Main *UNUSED(bmain), StructRNA *type) bNodeSocketType *st = RNA_struct_blender_type_get(type); if (!st) return; - + RNA_struct_free_extension(type, &st->ext_socket); RNA_struct_free(&BLENDER_RNA, type); @@ -1847,7 +1847,7 @@ static StructRNA *rna_NodeSocket_register( /* setup dummy socket & socket type to store static properties in */ memset(&dummyst, 0, sizeof(bNodeSocketType)); - + memset(&dummysock, 0, sizeof(bNodeSocket)); dummysock.typeinfo = &dummyst; RNA_pointer_create(NULL, &RNA_NodeSocket, &dummysock, &dummyptr); @@ -1855,7 +1855,7 @@ static StructRNA *rna_NodeSocket_register( /* validate the python class */ if (validate(&dummyptr, data, have_function) != 0) return NULL; - + if (strlen(identifier) >= sizeof(dummyst.idname)) { BKE_reportf(reports, RPT_ERROR, "Registering node socket class: '%s' is too long, maximum length is %d", identifier, (int)sizeof(dummyst.idname)); @@ -1868,22 +1868,22 @@ static StructRNA *rna_NodeSocket_register( /* create a new node socket type */ st = MEM_callocN(sizeof(bNodeSocketType), "node socket type"); memcpy(st, &dummyst, sizeof(dummyst)); - + nodeRegisterSocketType(st); } - + /* if RNA type is already registered, unregister first */ if (st->ext_socket.srna) { StructRNA *srna = st->ext_socket.srna; RNA_struct_free_extension(srna, &st->ext_socket); RNA_struct_free(&BLENDER_RNA, srna); } - st->ext_socket.srna = RNA_def_struct_ptr(&BLENDER_RNA, st->idname, &RNA_NodeSocket); + st->ext_socket.srna = RNA_def_struct_ptr(&BLENDER_RNA, st->idname, &RNA_NodeSocket); st->ext_socket.data = data; st->ext_socket.call = call; st->ext_socket.free = free; RNA_struct_blender_type_set(st->ext_socket.srna, st); - + /* XXX bad level call! needed to initialize the basic draw functions ... */ ED_init_custom_node_socket_type(st); @@ -1892,14 +1892,14 @@ static StructRNA *rna_NodeSocket_register( /* update while blender is running */ WM_main_add_notifier(NC_NODE | NA_EDITED, NULL); - + return st->ext_socket.srna; } static StructRNA *rna_NodeSocket_refine(PointerRNA *ptr) { bNodeSocket *sock = (bNodeSocket *)ptr->data; - + if (sock->typeinfo->ext_socket.srna) return sock->typeinfo->ext_socket.srna; else @@ -1913,10 +1913,10 @@ static char *rna_NodeSocket_path(PointerRNA *ptr) bNode *node; int socketindex; char name_esc[sizeof(node->name) * 2]; - + if (!nodeFindNode(ntree, sock, &node, &socketindex)) return NULL; - + BLI_strescape(name_esc, node->name, sizeof(name_esc)); if (sock->in_out == SOCK_IN) { @@ -1930,12 +1930,12 @@ static char *rna_NodeSocket_path(PointerRNA *ptr) static IDProperty *rna_NodeSocket_idprops(PointerRNA *ptr, bool create) { bNodeSocket *sock = ptr->data; - + if (create && !sock->prop) { IDPropertyTemplate val = {0}; sock->prop = IDP_New(IDP_GROUP, &val, "RNA_NodeSocket ID properties"); } - + return sock->prop; } @@ -1945,9 +1945,9 @@ static PointerRNA rna_NodeSocket_node_get(PointerRNA *ptr) bNodeSocket *sock = (bNodeSocket *)ptr->data; bNode *node; PointerRNA r_ptr; - + nodeFindNode(ntree, sock, &node, NULL); - + RNA_pointer_create((ID *)ntree, &RNA_Node, node, &r_ptr); return r_ptr; } @@ -1977,11 +1977,11 @@ static void rna_NodeSocket_link_limit_set(PointerRNA *ptr, int value) static void rna_NodeSocket_hide_set(PointerRNA *ptr, int value) { bNodeSocket *sock = (bNodeSocket *)ptr->data; - + /* don't hide linked sockets */ if (sock->flag & SOCK_IN_USE) return; - + if (value) sock->flag |= SOCK_HIDDEN; else @@ -2109,11 +2109,11 @@ static void rna_NodeSocketInterface_unregister(Main *UNUSED(bmain), StructRNA *t bNodeSocketType *st = RNA_struct_blender_type_get(type); if (!st) return; - + RNA_struct_free_extension(type, &st->ext_interface); - + RNA_struct_free(&BLENDER_RNA, type); - + /* update while blender is running */ WM_main_add_notifier(NC_NODE | NA_EDITED, NULL); } @@ -2129,7 +2129,7 @@ static StructRNA *rna_NodeSocketInterface_register( /* setup dummy socket & socket type to store static properties in */ memset(&dummyst, 0, sizeof(bNodeSocketType)); - + memset(&dummysock, 0, sizeof(bNodeSocket)); dummysock.typeinfo = &dummyst; RNA_pointer_create(NULL, &RNA_NodeSocketInterface, &dummysock, &dummyptr); @@ -2147,38 +2147,38 @@ static StructRNA *rna_NodeSocketInterface_register( /* create a new node socket type */ st = MEM_callocN(sizeof(bNodeSocketType), "node socket type"); memcpy(st, &dummyst, sizeof(dummyst)); - + nodeRegisterSocketType(st); } - + /* if RNA type is already registered, unregister first */ if (st->ext_interface.srna) { StructRNA *srna = st->ext_interface.srna; RNA_struct_free_extension(srna, &st->ext_interface); RNA_struct_free(&BLENDER_RNA, srna); } - st->ext_interface.srna = RNA_def_struct_ptr(&BLENDER_RNA, identifier, &RNA_NodeSocketInterface); + st->ext_interface.srna = RNA_def_struct_ptr(&BLENDER_RNA, identifier, &RNA_NodeSocketInterface); st->ext_interface.data = data; st->ext_interface.call = call; st->ext_interface.free = free; RNA_struct_blender_type_set(st->ext_interface.srna, st); - + st->interface_draw = (have_function[0]) ? rna_NodeSocketInterface_draw : NULL; st->interface_draw_color = (have_function[1]) ? rna_NodeSocketInterface_draw_color : NULL; st->interface_register_properties = (have_function[2]) ? rna_NodeSocketInterface_register_properties : NULL; st->interface_init_socket = (have_function[3]) ? rna_NodeSocketInterface_init_socket : NULL; st->interface_from_socket = (have_function[4]) ? rna_NodeSocketInterface_from_socket : NULL; - + /* update while blender is running */ WM_main_add_notifier(NC_NODE | NA_EDITED, NULL); - + return st->ext_interface.srna; } static StructRNA *rna_NodeSocketInterface_refine(PointerRNA *ptr) { bNodeSocket *sock = (bNodeSocket *)ptr->data; - + if (sock->typeinfo && sock->typeinfo->ext_interface.srna) return sock->typeinfo->ext_interface.srna; else @@ -2190,27 +2190,27 @@ static char *rna_NodeSocketInterface_path(PointerRNA *ptr) bNodeTree *ntree = (bNodeTree *)ptr->id.data; bNodeSocket *sock = (bNodeSocket *)ptr->data; int socketindex; - + socketindex = BLI_findindex(&ntree->inputs, sock); if (socketindex != -1) return BLI_sprintfN("inputs[%d]", socketindex); - + socketindex = BLI_findindex(&ntree->outputs, sock); if (socketindex != -1) return BLI_sprintfN("outputs[%d]", socketindex); - + return NULL; } static IDProperty *rna_NodeSocketInterface_idprops(PointerRNA *ptr, bool create) { bNodeSocket *sock = ptr->data; - + if (create && !sock->prop) { IDPropertyTemplate val = {0}; sock->prop = IDP_New(IDP_GROUP, &val, "RNA_NodeSocketInterface ID properties"); } - + return sock->prop; } @@ -2218,13 +2218,13 @@ static void rna_NodeSocketInterface_update(Main *bmain, Scene *UNUSED(scene), Po { bNodeTree *ntree = ptr->id.data; bNodeSocket *stemp = ptr->data; - + if (!stemp->typeinfo) return; - + ntree->update |= NTREE_UPDATE_GROUP; ntreeUpdateTree(bmain, ntree); - + ED_node_tag_update_nodetree(bmain, ntree, NULL); } @@ -2265,11 +2265,11 @@ static void rna_NodeSocketStandard_float_range(PointerRNA *ptr, float *min, floa bNodeSocket *sock = ptr->data; bNodeSocketValueFloat *dval = sock->default_value; int subtype = sock->typeinfo->subtype; - + if (dval->max < dval->min) { dval->max = dval->min; } - + *min = (subtype == PROP_UNSIGNED ? 0.0f : -FLT_MAX); *max = FLT_MAX; *softmin = dval->min; @@ -2281,11 +2281,11 @@ static void rna_NodeSocketStandard_int_range(PointerRNA *ptr, int *min, int *max bNodeSocket *sock = ptr->data; bNodeSocketValueInt *dval = sock->default_value; int subtype = sock->typeinfo->subtype; - + if (dval->max < dval->min) { dval->max = dval->min; } - + *min = (subtype == PROP_UNSIGNED ? 0 : INT_MIN); *max = INT_MAX; *softmin = dval->min; @@ -2296,11 +2296,11 @@ static void rna_NodeSocketStandard_vector_range(PointerRNA *ptr, float *min, flo { bNodeSocket *sock = ptr->data; bNodeSocketValueVector *dval = sock->default_value; - + if (dval->max < dval->min) { dval->max = dval->min; } - + *min = -FLT_MAX; *max = FLT_MAX; *softmin = dval->min; @@ -2311,16 +2311,16 @@ static void rna_NodeSocketStandard_vector_range(PointerRNA *ptr, float *min, flo static void rna_NodeSocketStandard_value_update(struct bContext *C, PointerRNA *ptr) { bNode *node; - + /* default update */ rna_NodeSocket_update(CTX_data_main(C), CTX_data_scene(C), ptr); - + /* try to use node from context, faster */ node = CTX_data_pointer_get(C, "node").data; if (!node) { bNodeTree *ntree = ptr->id.data; bNodeSocket *sock = ptr->data; - + /* fall back to searching node in the tree */ nodeFindNode(ntree, sock, &node, NULL); } @@ -2453,15 +2453,15 @@ static StructRNA *rna_NodeCustomGroup_register( bNodeType *nt = rna_Node_register_base(bmain, reports, &RNA_NodeCustomGroup, data, identifier, validate, call, free); if (!nt) return NULL; - + /* this updates the group node instance from the tree's interface */ nt->verifyfunc = node_group_verify; - + nodeRegisterType(nt); - + /* update while blender is running */ WM_main_add_notifier(NC_NODE | NA_EDITED, NULL); - + return nt->ext.srna; } @@ -2483,10 +2483,10 @@ static void rna_NodeGroup_update(Main *bmain, Scene *UNUSED(scene), PointerRNA * { bNodeTree *ntree = (bNodeTree *)ptr->id.data; bNode *node = (bNode *)ptr->data; - + if (node->id) ntreeUpdateTree(bmain, (bNodeTree *)node->id); - + ED_node_tag_update_nodetree(bmain, ntree, node); } @@ -2495,13 +2495,13 @@ static void rna_NodeGroup_node_tree_set(PointerRNA *ptr, const PointerRNA value) bNodeTree *ntree = ptr->id.data; bNode *node = ptr->data; bNodeTree *ngroup = value.data; - + if (nodeGroupPoll(ntree, ngroup)) { if (node->id) id_us_min(node->id); if (ngroup) id_us_plus(&ngroup->id); - + node->id = &ngroup->id; } } @@ -2510,11 +2510,11 @@ static int rna_NodeGroup_node_tree_poll(PointerRNA *ptr, const PointerRNA value) { bNodeTree *ntree = ptr->id.data; bNodeTree *ngroup = value.data; - + /* only allow node trees of the same type as the group node's tree */ if (ngroup->type != ntree->type) return false; - + return nodeGroupPoll(ntree, ngroup); } @@ -2535,7 +2535,7 @@ static StructRNA *rna_NodeGroup_interface_typef(PointerRNA *ptr) static StructRNA *rna_NodeGroupInputOutput_interface_typef(PointerRNA *ptr) { bNodeTree *ntree = ptr->id.data; - + if (ntree) { StructRNA *srna = ntreeInterfaceTypeGet(ntree, true); if (srna) @@ -2581,10 +2581,10 @@ static void rna_Matte_t1_set(PointerRNA *ptr, float value) { bNode *node = (bNode *)ptr->data; NodeChroma *chroma = node->storage; - + chroma->t1 = value; - - if (value < chroma->t2) + + if (value < chroma->t2) chroma->t2 = value; } @@ -2592,10 +2592,10 @@ static void rna_Matte_t2_set(PointerRNA *ptr, float value) { bNode *node = (bNode *)ptr->data; NodeChroma *chroma = node->storage; - - if (value > chroma->t1) + + if (value > chroma->t1) value = chroma->t1; - + chroma->t2 = value; } @@ -2618,10 +2618,10 @@ static void rna_Node_image_layer_update(Main *bmain, Scene *scene, PointerRNA *p bNode *node = (bNode *)ptr->data; Image *ima = (Image *)node->id; ImageUser *iuser = node->storage; - + BKE_image_multilayer_index(ima->rr, iuser); - BKE_image_signal(ima, iuser, IMA_SIGNAL_SRC_CHANGE); - + BKE_image_signal(bmain, ima, iuser, IMA_SIGNAL_SRC_CHANGE); + rna_Node_update(bmain, scene, ptr); if (scene->nodetree != NULL) { @@ -2776,7 +2776,7 @@ static const EnumPropertyItem *rna_Node_channel_itemf(bContext *UNUSED(C), Point EnumPropertyItem *item = NULL; EnumPropertyItem tmp = {0}; int totitem = 0; - + switch (node->custom1) { case CMP_NODE_CHANNEL_MATTE_CS_RGB: tmp.identifier = "R"; tmp.name = "R"; tmp.value = 1; @@ -2816,7 +2816,7 @@ static const EnumPropertyItem *rna_Node_channel_itemf(bContext *UNUSED(C), Point RNA_enum_item_end(&item, &totitem); *r_free = true; - + return item; } @@ -2876,7 +2876,7 @@ static int rna_NodeOutputFileSocket_find_node(bNodeTree *ntree, NodeImageMultiFi { bNode *node; bNodeSocket *sock; - + for (node = ntree->nodes.first; node; node = node->next) { for (sock = node->inputs.first; sock; sock = sock->next) { NodeImageMultiFileSocket *sockdata = sock->storage; @@ -2887,7 +2887,7 @@ static int rna_NodeOutputFileSocket_find_node(bNodeTree *ntree, NodeImageMultiFi } } } - + *nodep = NULL; *sockp = NULL; return 0; @@ -2899,7 +2899,7 @@ static void rna_NodeOutputFileSlotFile_path_set(PointerRNA *ptr, const char *val NodeImageMultiFileSocket *sockdata = ptr->data; bNode *node; bNodeSocket *sock; - + if (rna_NodeOutputFileSocket_find_node(ntree, sockdata, &node, &sock)) { ntreeCompositOutputFileSetPath(node, sock, value); } @@ -2911,7 +2911,7 @@ static void rna_NodeOutputFileSlotLayer_name_set(PointerRNA *ptr, const char *va NodeImageMultiFileSocket *sockdata = ptr->data; bNode *node; bNodeSocket *sock; - + if (rna_NodeOutputFileSocket_find_node(ntree, sockdata, &node, &sock)) { ntreeCompositOutputFileSetLayer(node, sock, value); } @@ -2925,12 +2925,12 @@ static bNodeSocket *rna_NodeOutputFile_slots_new(ID *id, bNode *node, bContext * bNodeSocket *sock; if (scene) im_format = &scene->r.im_format; - + sock = ntreeCompositOutputFileAddSocket(ntree, node, name, im_format); - + ntreeUpdateTree(CTX_data_main(C), ntree); WM_main_add_notifier(NC_NODE | NA_EDITED, ntree); - + return sock; } @@ -3324,7 +3324,7 @@ static const EnumPropertyItem node_subsurface_method_items[] = { static void def_group_input(StructRNA *srna) { PropertyRNA *prop; - + prop = RNA_def_property(srna, "interface", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_funcs(prop, NULL, NULL, "rna_NodeGroupInputOutput_interface_typef", NULL); RNA_def_property_struct_type(prop, "PropertyGroup"); @@ -3335,13 +3335,13 @@ static void def_group_input(StructRNA *srna) static void def_group_output(StructRNA *srna) { PropertyRNA *prop; - + prop = RNA_def_property(srna, "interface", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_funcs(prop, NULL, NULL, "rna_NodeGroupInputOutput_interface_typef", NULL); RNA_def_property_struct_type(prop, "PropertyGroup"); RNA_def_property_flag(prop, PROP_IDPROPERTY); RNA_def_property_ui_text(prop, "Interface", "Interface socket data"); - + prop = RNA_def_property(srna, "is_active_output", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", NODE_DO_OUTPUT); RNA_def_property_ui_text(prop, "Active Output", "True if this node is used as the active group output"); @@ -3351,7 +3351,7 @@ static void def_group_output(StructRNA *srna) static void def_group(StructRNA *srna) { PropertyRNA *prop; - + prop = RNA_def_property(srna, "node_tree", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "id"); RNA_def_property_struct_type(prop, "NodeTree"); @@ -3370,7 +3370,7 @@ static void def_group(StructRNA *srna) static void def_custom_group(BlenderRNA *brna) { StructRNA *srna; - + srna = RNA_def_struct(brna, "NodeCustomGroup", "Node"); RNA_def_struct_ui_text(srna, "Custom Group", "Base node type for custom registered node group types"); RNA_def_struct_sdna(srna, "bNode"); @@ -3382,8 +3382,8 @@ static void def_custom_group(BlenderRNA *brna) static void def_frame(StructRNA *srna) { - PropertyRNA *prop; - + PropertyRNA *prop; + prop = RNA_def_property(srna, "text", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "id"); RNA_def_property_struct_type(prop, "Text"); @@ -3393,7 +3393,7 @@ static void def_frame(StructRNA *srna) RNA_def_struct_sdna_from(srna, "NodeFrame", "storage"); RNA_def_struct_translation_context(srna, BLT_I18NCONTEXT_ID_NODETREE); - + prop = RNA_def_property(srna, "shrink", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", NODE_FRAME_SHRINK); RNA_def_property_ui_text(prop, "Shrink", "Shrink the frame to minimal bounding box"); @@ -3409,7 +3409,7 @@ static void def_frame(StructRNA *srna) static void def_math(StructRNA *srna) { PropertyRNA *prop; - + prop = RNA_def_property(srna, "operation", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "custom1"); RNA_def_property_enum_items(prop, rna_enum_node_math_items); @@ -3425,7 +3425,7 @@ static void def_math(StructRNA *srna) static void def_vector_math(StructRNA *srna) { PropertyRNA *prop; - + prop = RNA_def_property(srna, "operation", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "custom1"); RNA_def_property_enum_items(prop, rna_enum_node_vec_math_items); @@ -3436,7 +3436,7 @@ static void def_vector_math(StructRNA *srna) static void def_rgb_curve(StructRNA *srna) { PropertyRNA *prop; - + prop = RNA_def_property(srna, "mapping", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "storage"); RNA_def_property_struct_type(prop, "CurveMapping"); @@ -3447,7 +3447,7 @@ static void def_rgb_curve(StructRNA *srna) static void def_vector_curve(StructRNA *srna) { PropertyRNA *prop; - + prop = RNA_def_property(srna, "mapping", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "storage"); RNA_def_property_struct_type(prop, "CurveMapping"); @@ -3458,18 +3458,18 @@ static void def_vector_curve(StructRNA *srna) static void def_time(StructRNA *srna) { PropertyRNA *prop; - + prop = RNA_def_property(srna, "curve", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "storage"); RNA_def_property_struct_type(prop, "CurveMapping"); RNA_def_property_ui_text(prop, "Curve", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "frame_start", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "custom1"); RNA_def_property_ui_text(prop, "Start Frame", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "frame_end", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "custom2"); RNA_def_property_ui_text(prop, "End Frame", ""); @@ -3479,7 +3479,7 @@ static void def_time(StructRNA *srna) static void def_colorramp(StructRNA *srna) { PropertyRNA *prop; - + prop = RNA_def_property(srna, "color_ramp", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "storage"); RNA_def_property_struct_type(prop, "ColorRamp"); @@ -3490,13 +3490,13 @@ static void def_colorramp(StructRNA *srna) static void def_mix_rgb(StructRNA *srna) { PropertyRNA *prop; - + prop = RNA_def_property(srna, "blend_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "custom1"); RNA_def_property_enum_items(prop, rna_enum_ramp_blend_items); RNA_def_property_ui_text(prop, "Blend Type", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "use_alpha", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "custom2", SHD_MIXRGB_USE_ALPHA); RNA_def_property_ui_text(prop, "Alpha", "Include alpha of second input in this operation"); @@ -3511,14 +3511,14 @@ static void def_mix_rgb(StructRNA *srna) static void def_texture(StructRNA *srna) { PropertyRNA *prop; - + prop = RNA_def_property(srna, "texture", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "id"); RNA_def_property_struct_type(prop, "Texture"); RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Texture", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "node_output", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "custom1"); RNA_def_property_ui_text(prop, "Node Output", "For node-based textures, which output node to use"); @@ -3531,7 +3531,7 @@ static void def_texture(StructRNA *srna) static void def_sh_output(StructRNA *srna) { PropertyRNA *prop; - + prop = RNA_def_property(srna, "is_active_output", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", NODE_DO_OUTPUT); RNA_def_property_ui_text(prop, "Active Output", "True if this node is used as the active output"); @@ -3557,7 +3557,7 @@ static void def_sh_mapping(StructRNA *srna) static float default_1[3] = {1.f, 1.f, 1.f}; PropertyRNA *prop; - + RNA_def_struct_sdna_from(srna, "TexMapping", "storage"); prop = RNA_def_property(srna, "vector_type", PROP_ENUM, PROP_NONE); @@ -3570,36 +3570,36 @@ static void def_sh_mapping(StructRNA *srna) RNA_def_property_float_sdna(prop, NULL, "loc"); RNA_def_property_ui_text(prop, "Location", ""); RNA_def_property_update(prop, 0, "rna_Mapping_Node_update"); - + /* Not PROP_XYZ, this is now in radians, no more degrees */ prop = RNA_def_property(srna, "rotation", PROP_FLOAT, PROP_EULER); RNA_def_property_float_sdna(prop, NULL, "rot"); RNA_def_property_ui_text(prop, "Rotation", ""); RNA_def_property_update(prop, 0, "rna_Mapping_Node_update"); - + prop = RNA_def_property(srna, "scale", PROP_FLOAT, PROP_XYZ); RNA_def_property_float_sdna(prop, NULL, "size"); RNA_def_property_float_array_default(prop, default_1); RNA_def_property_flag(prop, PROP_PROPORTIONAL); RNA_def_property_ui_text(prop, "Scale", ""); RNA_def_property_update(prop, 0, "rna_Mapping_Node_update"); - + prop = RNA_def_property(srna, "min", PROP_FLOAT, PROP_XYZ); RNA_def_property_float_sdna(prop, NULL, "min"); RNA_def_property_ui_text(prop, "Minimum", "Minimum value for clipping"); RNA_def_property_update(prop, 0, "rna_Mapping_Node_update"); - + prop = RNA_def_property(srna, "max", PROP_FLOAT, PROP_XYZ); RNA_def_property_float_sdna(prop, NULL, "max"); RNA_def_property_float_array_default(prop, default_1); RNA_def_property_ui_text(prop, "Maximum", "Maximum value for clipping"); RNA_def_property_update(prop, 0, "rna_Mapping_Node_update"); - + prop = RNA_def_property(srna, "use_min", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", TEXMAP_CLIP_MIN); RNA_def_property_ui_text(prop, "Has Minimum", "Whether to use minimum clipping value"); RNA_def_property_update(prop, 0, "rna_Mapping_Node_update"); - + prop = RNA_def_property(srna, "use_max", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", TEXMAP_CLIP_MAX); RNA_def_property_ui_text(prop, "Has Maximum", "Whether to use maximum clipping value"); @@ -3609,9 +3609,9 @@ static void def_sh_mapping(StructRNA *srna) static void def_sh_attribute(StructRNA *srna) { PropertyRNA *prop; - + RNA_def_struct_sdna_from(srna, "NodeShaderAttribute", "storage"); - + prop = RNA_def_property(srna, "attribute_name", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "name"); RNA_def_property_ui_text(prop, "Attribute Name", ""); @@ -3641,9 +3641,9 @@ static void def_sh_tex_sky(StructRNA *srna) {0, NULL, 0, NULL, NULL} }; static float default_dir[3] = {0.0f, 0.0f, 1.0f}; - + PropertyRNA *prop; - + RNA_def_struct_sdna_from(srna, "NodeTexSky", "storage"); def_sh_tex(srna); @@ -3652,19 +3652,19 @@ static void def_sh_tex_sky(StructRNA *srna) RNA_def_property_enum_items(prop, prop_sky_type); RNA_def_property_ui_text(prop, "Sky Type", ""); RNA_def_property_update(prop, 0, "rna_Node_update"); - + prop = RNA_def_property(srna, "sun_direction", PROP_FLOAT, PROP_DIRECTION); RNA_def_property_ui_text(prop, "Sun Direction", "Direction from where the sun is shining"); RNA_def_property_array(prop, 3); RNA_def_property_float_array_default(prop, default_dir); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "turbidity", PROP_FLOAT, PROP_NONE); RNA_def_property_range(prop, 1.0f, 10.0f); RNA_def_property_ui_range(prop, 1.0f, 10.0f, 10, 3); RNA_def_property_ui_text(prop, "Turbidity", "Atmospheric turbidity"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "ground_albedo", PROP_FLOAT, PROP_FACTOR); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Ground Albedo", "Ground color that is subtly reflected in the sky"); @@ -3819,7 +3819,7 @@ static void def_sh_tex_gradient(StructRNA *srna) }; PropertyRNA *prop; - + RNA_def_struct_sdna_from(srna, "NodeTexGradient", "storage"); def_sh_tex(srna); @@ -3844,44 +3844,44 @@ static void def_sh_tex_checker(StructRNA *srna) static void def_sh_tex_brick(StructRNA *srna) { PropertyRNA *prop; - + RNA_def_struct_sdna_from(srna, "NodeTexBrick", "storage"); def_sh_tex(srna); - + prop = RNA_def_property(srna, "offset_frequency", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "offset_freq"); RNA_def_property_int_default(prop, 2); RNA_def_property_range(prop, 1, 99); RNA_def_property_ui_text(prop, "Offset Frequency", ""); RNA_def_property_update(prop, 0, "rna_Node_update"); - + prop = RNA_def_property(srna, "squash_frequency", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "squash_freq"); RNA_def_property_int_default(prop, 2); RNA_def_property_range(prop, 1, 99); RNA_def_property_ui_text(prop, "Squash Frequency", ""); RNA_def_property_update(prop, 0, "rna_Node_update"); - + prop = RNA_def_property(srna, "offset", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "offset"); RNA_def_property_float_default(prop, 0.5f); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Offset Amount", ""); RNA_def_property_update(prop, 0, "rna_Node_update"); - + prop = RNA_def_property(srna, "squash", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "squash"); RNA_def_property_float_default(prop, 1.0f); RNA_def_property_range(prop, 0.0f, 99.0f); RNA_def_property_ui_text(prop, "Squash Amount", ""); RNA_def_property_update(prop, 0, "rna_Node_update"); - + } static void def_sh_tex_magic(StructRNA *srna) { PropertyRNA *prop; - + RNA_def_struct_sdna_from(srna, "NodeTexMagic", "storage"); def_sh_tex(srna); @@ -3904,7 +3904,7 @@ static void def_sh_tex_musgrave(StructRNA *srna) }; PropertyRNA *prop; - + RNA_def_struct_sdna_from(srna, "NodeTexMusgrave", "storage"); def_sh_tex(srna); @@ -3924,7 +3924,7 @@ static void def_sh_tex_voronoi(StructRNA *srna) }; PropertyRNA *prop; - + RNA_def_struct_sdna_from(srna, "NodeTexVoronoi", "storage"); def_sh_tex(srna); @@ -3950,7 +3950,7 @@ static void def_sh_tex_wave(StructRNA *srna) }; PropertyRNA *prop; - + RNA_def_struct_sdna_from(srna, "NodeTexWave", "storage"); def_sh_tex(srna); @@ -4001,20 +4001,20 @@ static void def_sh_vect_transform(StructRNA *srna) }; PropertyRNA *prop; - + RNA_def_struct_sdna_from(srna, "NodeShaderVectTransform", "storage"); - + prop = RNA_def_property(srna, "vector_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "type"); RNA_def_property_enum_items(prop, prop_vect_type_items); RNA_def_property_ui_text(prop, "Type", ""); RNA_def_property_update(prop, 0, "rna_Node_update"); - + prop = RNA_def_property(srna, "convert_from", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, prop_vect_space_items); RNA_def_property_ui_text(prop, "Convert From", "Space to convert from"); RNA_def_property_update(prop, 0, "rna_Node_update"); - + prop = RNA_def_property(srna, "convert_to", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, prop_vect_space_items); RNA_def_property_ui_text(prop, "Convert To", "Space to convert to"); @@ -4024,7 +4024,7 @@ static void def_sh_vect_transform(StructRNA *srna) static void def_sh_tex_wireframe(StructRNA *srna) { PropertyRNA *prop; - + prop = RNA_def_property(srna, "use_pixel_size", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "custom1", 1); RNA_def_property_ui_text(prop, "Pixel Size", "Use screen pixel size instead of world units"); @@ -4167,7 +4167,7 @@ static void def_sh_tex_pointdensity(StructRNA *srna) static void def_glossy(StructRNA *srna) { PropertyRNA *prop; - + prop = RNA_def_property(srna, "distribution", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "custom1"); RNA_def_property_enum_items(prop, node_glossy_items); @@ -4178,7 +4178,7 @@ static void def_glossy(StructRNA *srna) static void def_glass(StructRNA *srna) { PropertyRNA *prop; - + prop = RNA_def_property(srna, "distribution", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "custom1"); RNA_def_property_enum_items(prop, node_glass_items); @@ -4206,7 +4206,7 @@ static void def_principled(StructRNA *srna) static void def_refraction(StructRNA *srna) { PropertyRNA *prop; - + prop = RNA_def_property(srna, "distribution", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "custom1"); RNA_def_property_enum_items(prop, node_refraction_items); @@ -4217,7 +4217,7 @@ static void def_refraction(StructRNA *srna) static void def_anisotropic(StructRNA *srna) { PropertyRNA *prop; - + prop = RNA_def_property(srna, "distribution", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "custom1"); RNA_def_property_enum_items(prop, node_anisotropic_items); @@ -4228,7 +4228,7 @@ static void def_anisotropic(StructRNA *srna) static void def_toon(StructRNA *srna) { PropertyRNA *prop; - + prop = RNA_def_property(srna, "component", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "custom1"); RNA_def_property_enum_items(prop, node_toon_items); @@ -4239,7 +4239,7 @@ static void def_toon(StructRNA *srna) static void def_sh_bump(StructRNA *srna) { PropertyRNA *prop; - + prop = RNA_def_property(srna, "invert", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "custom1", 1); RNA_def_property_ui_text(prop, "Invert", "Invert the bump mapping direction to push into the surface instead of out"); @@ -4249,7 +4249,7 @@ static void def_sh_bump(StructRNA *srna) static void def_hair(StructRNA *srna) { PropertyRNA *prop; - + prop = RNA_def_property(srna, "component", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "custom1"); RNA_def_property_enum_items(prop, node_hair_items); @@ -4409,7 +4409,7 @@ static void def_sh_subsurface(StructRNA *srna) }; PropertyRNA *prop; - + prop = RNA_def_property(srna, "falloff", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "custom1"); RNA_def_property_enum_items(prop, prop_subsurface_falloff_items); @@ -4453,9 +4453,9 @@ static void def_sh_script(StructRNA *srna) RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT); RNA_def_property_ui_text(prop, "Script", "Internal shader script to define the shader"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNodeScript_update"); - + RNA_def_struct_sdna_from(srna, "NodeShaderScript", "storage"); - + prop = RNA_def_property(srna, "filepath", PROP_STRING, PROP_FILEPATH); RNA_def_property_ui_text(prop, "File Path", "Shader script path"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNodeScript_update"); @@ -4470,7 +4470,7 @@ static void def_sh_script(StructRNA *srna) RNA_def_property_boolean_sdna(prop, NULL, "flag", NODE_SCRIPT_AUTO_UPDATE); RNA_def_property_ui_text(prop, "Auto Update", "Automatically update the shader when the .osl file changes (external scripts only)"); - + prop = RNA_def_property(srna, "bytecode", PROP_STRING, PROP_NONE); RNA_def_property_string_funcs(prop, "rna_ShaderNodeScript_bytecode_get", "rna_ShaderNodeScript_bytecode_length", "rna_ShaderNodeScript_bytecode_set"); @@ -4483,7 +4483,7 @@ static void def_sh_script(StructRNA *srna) /* needs to be reset to avoid bad pointer type in API functions below */ RNA_def_struct_sdna_from(srna, "bNode", NULL); - + /* API functions */ #if 0 /* XXX TODO use general node api for this */ @@ -4494,7 +4494,7 @@ static void def_sh_script(StructRNA *srna) /*parm =*/ RNA_def_boolean(func, "is_output", false, "Output", "Whether the socket is an output"); parm = RNA_def_pointer(func, "result", "NodeSocket", "", ""); RNA_def_function_return(func, parm); - + func = RNA_def_function(srna, "add_socket", "rna_ShaderNodeScript_add_socket"); RNA_def_function_ui_description(func, "Add a socket socket"); RNA_def_function_flag(func, FUNC_USE_SELF_ID); @@ -4505,7 +4505,7 @@ static void def_sh_script(StructRNA *srna) /*parm =*/ RNA_def_boolean(func, "is_output", false, "Output", "Whether the socket is an output"); parm = RNA_def_pointer(func, "result", "NodeSocket", "", ""); RNA_def_function_return(func, parm); - + func = RNA_def_function(srna, "remove_socket", "rna_ShaderNodeScript_remove_socket"); RNA_def_function_ui_description(func, "Remove a socket socket"); RNA_def_function_flag(func, FUNC_USE_SELF_ID); @@ -4519,15 +4519,15 @@ static void def_sh_script(StructRNA *srna) static void def_cmp_alpha_over(StructRNA *srna) { PropertyRNA *prop; - + /* XXX: Tooltip */ prop = RNA_def_property(srna, "use_premultiply", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "custom1", 1); RNA_def_property_ui_text(prop, "Convert Premul", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + RNA_def_struct_sdna_from(srna, "NodeTwoFloats", "storage"); - + prop = RNA_def_property(srna, "premul", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "x"); RNA_def_property_range(prop, 0.0f, 1.0f); @@ -4538,7 +4538,7 @@ static void def_cmp_alpha_over(StructRNA *srna) static void def_cmp_blur(StructRNA *srna) { PropertyRNA *prop; - + static const EnumPropertyItem filter_type_items[] = { {R_FILTER_BOX, "FLAT", 0, "Flat", ""}, {R_FILTER_TENT, "TENT", 0, "Tent", ""}, @@ -4570,13 +4570,13 @@ static void def_cmp_blur(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); RNA_def_struct_sdna_from(srna, "NodeBlurData", "storage"); - + prop = RNA_def_property(srna, "size_x", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "sizex"); RNA_def_property_range(prop, 0, 2048); RNA_def_property_ui_text(prop, "Size X", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "size_y", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "sizey"); RNA_def_property_range(prop, 0, 2048); @@ -4587,7 +4587,7 @@ static void def_cmp_blur(StructRNA *srna) RNA_def_property_boolean_sdna(prop, NULL, "relative", 1); RNA_def_property_ui_text(prop, "Relative", "Use relative (percent) values to define blur radius"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "aspect_correction", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "aspect"); RNA_def_property_enum_items(prop, aspect_correction_type_items); @@ -4599,30 +4599,30 @@ static void def_cmp_blur(StructRNA *srna) RNA_def_property_range(prop, 0.0f, 2.0f); RNA_def_property_ui_text(prop, "Factor", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "factor_x", PROP_FLOAT, PROP_PERCENTAGE); RNA_def_property_float_sdna(prop, NULL, "percentx"); RNA_def_property_range(prop, 0.0f, 100.0f); RNA_def_property_ui_text(prop, "Relative Size X", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "factor_y", PROP_FLOAT, PROP_PERCENTAGE); RNA_def_property_float_sdna(prop, NULL, "percenty"); RNA_def_property_range(prop, 0.0f, 100.0f); RNA_def_property_ui_text(prop, "Relative Size Y", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "filter_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "filtertype"); RNA_def_property_enum_items(prop, filter_type_items); RNA_def_property_ui_text(prop, "Filter Type", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "use_bokeh", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "bokeh", 1); RNA_def_property_ui_text(prop, "Bokeh", "Use circular filter (slower)"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "use_gamma_correction", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "gamma", 1); RNA_def_property_ui_text(prop, "Gamma", "Apply filter on gamma corrected values"); @@ -4643,40 +4643,40 @@ static void def_cmp_filter(StructRNA *srna) static void def_cmp_map_value(StructRNA *srna) { PropertyRNA *prop; - + RNA_def_struct_sdna_from(srna, "TexMapping", "storage"); - + prop = RNA_def_property(srna, "offset", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "loc"); RNA_def_property_array(prop, 1); RNA_def_property_range(prop, -1000.0f, 1000.0f); RNA_def_property_ui_text(prop, "Offset", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "size", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "size"); RNA_def_property_array(prop, 1); RNA_def_property_range(prop, -1000.0f, 1000.0f); RNA_def_property_ui_text(prop, "Size", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "use_min", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", TEXMAP_CLIP_MIN); RNA_def_property_ui_text(prop, "Use Minimum", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "use_max", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", TEXMAP_CLIP_MAX); RNA_def_property_ui_text(prop, "Use Maximum", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "min", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "min"); RNA_def_property_array(prop, 1); RNA_def_property_range(prop, -1000.0f, 1000.0f); RNA_def_property_ui_text(prop, "Minimum", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "max", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "max"); RNA_def_property_array(prop, 1); @@ -4688,7 +4688,7 @@ static void def_cmp_map_value(StructRNA *srna) static void def_cmp_map_range(StructRNA *srna) { PropertyRNA *prop; - + prop = RNA_def_property(srna, "use_clamp", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "custom1", 1); RNA_def_property_ui_text(prop, "Clamp", "Clamp result of the node to 0..1 range"); @@ -4698,28 +4698,28 @@ static void def_cmp_map_range(StructRNA *srna) static void def_cmp_vector_blur(StructRNA *srna) { PropertyRNA *prop; - + RNA_def_struct_sdna_from(srna, "NodeBlurData", "storage"); - + prop = RNA_def_property(srna, "samples", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "samples"); RNA_def_property_range(prop, 1, 256); RNA_def_property_ui_text(prop, "Samples", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "speed_min", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "minspeed"); RNA_def_property_range(prop, 0, 1024); RNA_def_property_ui_text(prop, "Min Speed", "Minimum speed for a pixel to be blurred (used to separate background from foreground)"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "speed_max", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "maxspeed"); RNA_def_property_range(prop, 0, 1024); RNA_def_property_ui_text(prop, "Max Speed", "Maximum speed, or zero for none"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "factor", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "fac"); RNA_def_property_range(prop, 0.0, 20.0); @@ -4727,7 +4727,7 @@ static void def_cmp_vector_blur(StructRNA *srna) RNA_def_property_ui_text(prop, "Blur Factor", "Scaling factor for motion vectors (actually, 'shutter speed', in frames)"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "use_curved", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "curved", 1); RNA_def_property_ui_text(prop, "Curved", "Interpolate between frames in a Bezier curve, rather than linearly"); @@ -4737,7 +4737,7 @@ static void def_cmp_vector_blur(StructRNA *srna) static void def_cmp_levels(StructRNA *srna) { PropertyRNA *prop; - + static const EnumPropertyItem channel_items[] = { {1, "COMBINED_RGB", 0, "C", "Combined RGB"}, {2, "RED", 0, "R", "Red Channel"}, @@ -4746,7 +4746,7 @@ static void def_cmp_levels(StructRNA *srna) {5, "LUMINANCE", 0, "L", "Luminance Channel"}, {0, NULL, 0, NULL, NULL} }; - + prop = RNA_def_property(srna, "channel", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "custom1"); RNA_def_property_enum_items(prop, channel_items); @@ -4763,7 +4763,7 @@ static void def_node_image_user(StructRNA *srna) RNA_def_property_range(prop, 0, MAXFRAMEF); RNA_def_property_ui_text(prop, "Frames", "Number of images of a movie to use"); /* copied from the rna_image.c */ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "frame_start", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "sfra"); RNA_def_property_range(prop, MINAFRAMEF, MAXFRAMEF); @@ -4771,19 +4771,19 @@ static void def_node_image_user(StructRNA *srna) RNA_def_property_ui_text(prop, "Start Frame", "Global starting frame of the movie/sequence, assuming first picture has a #1"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "frame_offset", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "offset"); RNA_def_property_range(prop, MINAFRAMEF, MAXFRAMEF); /* copied from the rna_image.c */ RNA_def_property_ui_text(prop, "Offset", "Offset the number of the frame to use in the animation"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "use_cyclic", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "cycl", 1); RNA_def_property_ui_text(prop, "Cyclic", "Cycle the images in the movie"); /* copied from the rna_image.c */ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "use_auto_refresh", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", IMA_ANIM_ALWAYS); /* copied from the rna_image.c */ @@ -4820,7 +4820,7 @@ static void def_node_image_user(StructRNA *srna) static void def_cmp_image(StructRNA *srna) { PropertyRNA *prop; - + #if 0 static const EnumPropertyItem type_items[] = { {IMA_SRC_FILE, "IMAGE", 0, "Image", ""}, @@ -4830,7 +4830,7 @@ static void def_cmp_image(StructRNA *srna) {0, NULL, 0, NULL, NULL} }; #endif - + prop = RNA_def_property(srna, "image", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "id"); RNA_def_property_struct_type(prop, "Image"); @@ -4854,7 +4854,7 @@ static void def_cmp_image(StructRNA *srna) static void def_cmp_render_layers(StructRNA *srna) { PropertyRNA *prop; - + prop = RNA_def_property(srna, "scene", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "id"); RNA_def_property_pointer_funcs(prop, NULL, "rna_Node_scene_set", NULL, NULL); @@ -4862,7 +4862,7 @@ static void def_cmp_render_layers(StructRNA *srna) RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT); RNA_def_property_ui_text(prop, "Scene", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_view_layer_update"); - + prop = RNA_def_property(srna, "layer", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "custom1"); RNA_def_property_enum_items(prop, prop_view_layer_items); @@ -4876,19 +4876,19 @@ static void rna_def_cmp_output_file_slot_file(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + srna = RNA_def_struct(brna, "NodeOutputFileSlotFile", NULL); RNA_def_struct_sdna(srna, "NodeImageMultiFileSocket"); RNA_def_struct_ui_text(srna, "Output File Slot", "Single layer file slot of the file output node"); - + prop = RNA_def_property(srna, "use_node_format", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "use_node_format", 1); RNA_def_property_ui_text(prop, "Use Node Format", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, NULL); - + prop = RNA_def_property(srna, "format", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "ImageFormatSettings"); - + prop = RNA_def_property(srna, "path", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "path"); RNA_def_property_string_funcs(prop, NULL, NULL, "rna_NodeOutputFileSlotFile_path_set"); @@ -4900,11 +4900,11 @@ static void rna_def_cmp_output_file_slot_layer(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + srna = RNA_def_struct(brna, "NodeOutputFileSlotLayer", NULL); RNA_def_struct_sdna(srna, "NodeImageMultiFileSocket"); RNA_def_struct_ui_text(srna, "Output File Layer Slot", "Multilayer slot of the file output node"); - + prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "layer"); RNA_def_property_string_funcs(prop, NULL, NULL, "rna_NodeOutputFileSlotLayer_name_set"); @@ -4957,33 +4957,33 @@ static void rna_def_cmp_output_file_slots_api(BlenderRNA *brna, PropertyRNA *cpr static void def_cmp_output_file(BlenderRNA *brna, StructRNA *srna) { PropertyRNA *prop; - + RNA_def_struct_sdna_from(srna, "NodeImageMultiFile", "storage"); - + prop = RNA_def_property(srna, "base_path", PROP_STRING, PROP_FILEPATH); RNA_def_property_string_sdna(prop, NULL, "base_path"); RNA_def_property_ui_text(prop, "Base Path", "Base output path for the image"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "active_input_index", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "active_input"); RNA_def_property_ui_text(prop, "Active Input Index", "Active input index in details view list"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "format", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "ImageFormatSettings"); - + /* XXX using two different collections here for the same basic DNA list! * Details of the output slots depend on whether the node is in Multilayer EXR mode. */ - + prop = RNA_def_property(srna, "file_slots", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_funcs(prop, "rna_NodeOutputFile_slots_begin", "rna_iterator_listbase_next", "rna_iterator_listbase_end", "rna_NodeOutputFile_slot_file_get", NULL, NULL, NULL, NULL); RNA_def_property_struct_type(prop, "NodeOutputFileSlotFile"); RNA_def_property_ui_text(prop, "File Slots", ""); rna_def_cmp_output_file_slots_api(brna, prop, "CompositorNodeOutputFileFileSlots"); - + prop = RNA_def_property(srna, "layer_slots", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_funcs(prop, "rna_NodeOutputFile_slots_begin", "rna_iterator_listbase_next", "rna_iterator_listbase_end", "rna_NodeOutputFile_slot_layer_get", NULL, NULL, NULL, NULL); @@ -5003,13 +5003,13 @@ static void def_cmp_dilate_erode(StructRNA *srna) {CMP_NODE_DILATEERODE_DISTANCE_FEATHER, "FEATHER", 0, "Feather", ""}, {0, NULL, 0, NULL, NULL} }; - + prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "custom1"); RNA_def_property_enum_items(prop, mode_items); RNA_def_property_ui_text(prop, "Mode", "Growing/shrinking mode"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "distance", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "custom2"); RNA_def_property_range(prop, -5000, 5000); @@ -5047,7 +5047,7 @@ static void def_cmp_inpaint(StructRNA *srna) RNA_def_property_ui_text(prop, "Type", "Type of inpaint algorithm"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); #endif - + prop = RNA_def_property(srna, "distance", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "custom2"); RNA_def_property_range(prop, 1, 10000); @@ -5083,7 +5083,7 @@ static void def_cmp_scale(StructRNA *srna) {CMP_SCALE_RENDERPERCENT, "RENDER_SIZE", 0, "Render Size", ""}, {0, NULL, 0, NULL, NULL} }; - + /* matching bgpic_camera_frame_items[] */ static const EnumPropertyItem space_frame_items[] = { {0, "STRETCH", 0, "Stretch", ""}, @@ -5119,7 +5119,7 @@ static void def_cmp_scale(StructRNA *srna) static void def_cmp_rotate(StructRNA *srna) { PropertyRNA *prop; - + prop = RNA_def_property(srna, "filter_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "custom1"); RNA_def_property_enum_items(prop, node_sampler_type_items); @@ -5132,14 +5132,14 @@ static void def_cmp_diff_matte(StructRNA *srna) PropertyRNA *prop; RNA_def_struct_sdna_from(srna, "NodeChroma", "storage"); - + prop = RNA_def_property(srna, "tolerance", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "t1"); RNA_def_property_float_funcs(prop, NULL, "rna_difference_matte_t1_set", NULL); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Tolerance", "Color distances below this threshold are keyed"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "falloff", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "t2"); RNA_def_property_float_funcs(prop, NULL, "rna_difference_matte_t2_set", NULL); @@ -5151,7 +5151,7 @@ static void def_cmp_diff_matte(StructRNA *srna) static void def_cmp_color_matte(StructRNA *srna) { PropertyRNA *prop; - + RNA_def_struct_sdna_from(srna, "NodeChroma", "storage"); prop = RNA_def_property(srna, "color_hue", PROP_FLOAT, PROP_NONE); @@ -5159,13 +5159,13 @@ static void def_cmp_color_matte(StructRNA *srna) RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "H", "Hue tolerance for colors to be considered a keying color"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "color_saturation", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "t2"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "S", "Saturation Tolerance for the color"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "color_value", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "t3"); RNA_def_property_range(prop, 0.0f, 1.0f); @@ -5176,7 +5176,7 @@ static void def_cmp_color_matte(StructRNA *srna) static void def_cmp_distance_matte(StructRNA *srna) { PropertyRNA *prop; - + static const EnumPropertyItem color_space_items[] = { {1, "RGB", 0, "RGB", "RGB color space"}, {2, "YCC", 0, "YCC", "YCbCr Suppression"}, @@ -5191,14 +5191,14 @@ static void def_cmp_distance_matte(StructRNA *srna) RNA_def_property_ui_text(prop, "Channel", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "tolerance", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "t1"); RNA_def_property_float_funcs(prop, NULL, "rna_distance_matte_t1_set", NULL); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Tolerance", "Color distances below this threshold are keyed"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "falloff", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "t2"); RNA_def_property_float_funcs(prop, NULL, "rna_distance_matte_t2_set", NULL); @@ -5230,13 +5230,13 @@ static void def_cmp_color_spill(StructRNA *srna) {1, "AVERAGE", 0, "Average", "Average Limit Algorithm"}, {0, NULL, 0, NULL, NULL} }; - + prop = RNA_def_property(srna, "channel", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "custom1"); RNA_def_property_enum_items(prop, channel_items); RNA_def_property_ui_text(prop, "Channel", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "limit_method", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "custom2"); RNA_def_property_enum_items(prop, algorithm_items); @@ -5284,16 +5284,16 @@ static void def_cmp_color_spill(StructRNA *srna) static void def_cmp_luma_matte(StructRNA *srna) { PropertyRNA *prop; - + RNA_def_struct_sdna_from(srna, "NodeChroma", "storage"); - + prop = RNA_def_property(srna, "limit_max", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "t1"); RNA_def_property_float_funcs(prop, NULL, "rna_Matte_t1_set", NULL); RNA_def_property_ui_range(prop, 0, 1, 0.1f, 3); RNA_def_property_ui_text(prop, "High", "Values higher than this setting are 100% opaque"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "limit_min", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "t2"); RNA_def_property_float_funcs(prop, NULL, "rna_Matte_t2_set", NULL); @@ -5315,16 +5315,16 @@ static void def_cmp_brightcontrast(StructRNA *srna) static void def_cmp_chroma_matte(StructRNA *srna) { PropertyRNA *prop; - + RNA_def_struct_sdna_from(srna, "NodeChroma", "storage"); - + prop = RNA_def_property(srna, "tolerance", PROP_FLOAT, PROP_ANGLE); RNA_def_property_float_sdna(prop, NULL, "t1"); RNA_def_property_float_funcs(prop, NULL, "rna_Matte_t1_set", NULL); RNA_def_property_range(prop, DEG2RADF(1.0f), DEG2RADF(80.0f)); RNA_def_property_ui_text(prop, "Acceptance", "Tolerance for a color to be considered a keying color"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "threshold", PROP_FLOAT, PROP_ANGLE); RNA_def_property_float_sdna(prop, NULL, "t2"); RNA_def_property_float_funcs(prop, NULL, "rna_Matte_t2_set", NULL); @@ -5337,13 +5337,13 @@ static void def_cmp_chroma_matte(StructRNA *srna) RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Lift", "Alpha lift"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "gain", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "fstrength"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Falloff", "Alpha falloff"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "shadow_adjust", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "t3"); RNA_def_property_range(prop, 0.0f, 1.0f); @@ -5354,7 +5354,7 @@ static void def_cmp_chroma_matte(StructRNA *srna) static void def_cmp_channel_matte(StructRNA *srna) { PropertyRNA *prop; - + static const EnumPropertyItem color_space_items[] = { {CMP_NODE_CHANNEL_MATTE_CS_RGB, "RGB", 0, "RGB", "RGB Color Space"}, {CMP_NODE_CHANNEL_MATTE_CS_HSV, "HSV", 0, "HSV", "HSV Color Space"}, @@ -5368,13 +5368,13 @@ static void def_cmp_channel_matte(StructRNA *srna) {1, "MAX", 0, "Max", "Limit by max of other channels "}, {0, NULL, 0, NULL, NULL} }; - + prop = RNA_def_property(srna, "color_space", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "custom1"); RNA_def_property_enum_items(prop, color_space_items); RNA_def_property_ui_text(prop, "Color Space", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "matte_channel", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "custom2"); RNA_def_property_enum_items(prop, prop_tri_channel_items); @@ -5396,14 +5396,14 @@ static void def_cmp_channel_matte(StructRNA *srna) RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_Node_channel_itemf"); RNA_def_property_ui_text(prop, "Limit Channel", "Limit by this channel's value"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "limit_max", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "t1"); RNA_def_property_float_funcs(prop, NULL, "rna_Matte_t1_set", NULL); RNA_def_property_ui_range(prop, 0, 1, 0.1f, 3); RNA_def_property_ui_text(prop, "High", "Values higher than this setting are 100% opaque"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "limit_min", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "t2"); RNA_def_property_float_funcs(prop, NULL, "rna_Matte_t2_set", NULL); @@ -5415,7 +5415,7 @@ static void def_cmp_channel_matte(StructRNA *srna) static void def_cmp_flip(StructRNA *srna) { PropertyRNA *prop; - + prop = RNA_def_property(srna, "axis", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "custom1"); RNA_def_property_enum_items(prop, node_flip_items); @@ -5426,7 +5426,7 @@ static void def_cmp_flip(StructRNA *srna) static void def_cmp_splitviewer(StructRNA *srna) { PropertyRNA *prop; - + prop = RNA_def_property(srna, "axis", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "custom2"); RNA_def_property_enum_items(prop, rna_enum_axis_xy_items); @@ -5443,7 +5443,7 @@ static void def_cmp_splitviewer(StructRNA *srna) static void def_cmp_id_mask(StructRNA *srna) { PropertyRNA *prop; - + prop = RNA_def_property(srna, "index", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "custom1"); RNA_def_property_range(prop, 0, 32767); @@ -5533,7 +5533,7 @@ static void def_cmp_defocus(StructRNA *srna) RNA_def_property_range(prop, 0.0f, DEG2RADF(90.0f)); RNA_def_property_ui_text(prop, "Angle", "Bokeh shape rotation offset"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "use_gamma_correction", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "gamco", 1); RNA_def_property_ui_text(prop, "Gamma Correction", "Enable gamma correction before and after main process"); @@ -5547,20 +5547,20 @@ static void def_cmp_defocus(StructRNA *srna) "Amount of focal blur, 128=infinity=perfect focus, half the value doubles " "the blur radius"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "blur_max", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "maxblur"); RNA_def_property_range(prop, 0.0f, 10000.0f); RNA_def_property_ui_text(prop, "Max Blur", "Blur limit, maximum CoC radius"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "threshold", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "bthresh"); RNA_def_property_range(prop, 0.0f, 100.0f); RNA_def_property_ui_text(prop, "Threshold", "CoC radius threshold, prevents background bleed on in-focus midground, 0=off"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "use_preview", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "preview", 1); RNA_def_property_ui_text(prop, "Preview", "Enable low quality mode, useful for preview"); @@ -5572,7 +5572,7 @@ static void def_cmp_defocus(StructRNA *srna) "Disable when using an image as input instead of actual z-buffer " "(auto enabled if node not image based, eg. time node)"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "z_scale", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "scale"); RNA_def_property_range(prop, 0.0f, 1000.0f); @@ -5585,12 +5585,12 @@ static void def_cmp_defocus(StructRNA *srna) static void def_cmp_invert(StructRNA *srna) { PropertyRNA *prop; - + prop = RNA_def_property(srna, "invert_rgb", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "custom1", CMP_CHAN_RGB); RNA_def_property_ui_text(prop, "RGB", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "invert_alpha", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "custom1", CMP_CHAN_A); RNA_def_property_ui_text(prop, "Alpha", ""); @@ -5600,7 +5600,7 @@ static void def_cmp_invert(StructRNA *srna) static void def_cmp_crop(StructRNA *srna) { PropertyRNA *prop; - + prop = RNA_def_property(srna, "use_crop_size", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "custom1", 1); RNA_def_property_ui_text(prop, "Crop Image Size", "Whether to crop the size of the input image"); @@ -5618,19 +5618,19 @@ static void def_cmp_crop(StructRNA *srna) RNA_def_property_range(prop, 0, 10000); RNA_def_property_ui_text(prop, "X1", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "max_x", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "x2"); RNA_def_property_range(prop, 0, 10000); RNA_def_property_ui_text(prop, "X2", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "min_y", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "y1"); RNA_def_property_range(prop, 0, 10000); RNA_def_property_ui_text(prop, "Y1", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "max_y", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "y2"); RNA_def_property_range(prop, 0, 10000); @@ -5665,50 +5665,50 @@ static void def_cmp_crop(StructRNA *srna) static void def_cmp_dblur(StructRNA *srna) { PropertyRNA *prop; - + RNA_def_struct_sdna_from(srna, "NodeDBlurData", "storage"); - + prop = RNA_def_property(srna, "iterations", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "iter"); RNA_def_property_range(prop, 1, 32); RNA_def_property_ui_text(prop, "Iterations", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "use_wrap", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "wrap", 1); RNA_def_property_ui_text(prop, "Wrap", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "center_x", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "center_x"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Center X", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "center_y", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "center_y"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Center Y", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "distance", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "distance"); RNA_def_property_range(prop, -1.0f, 1.0f); RNA_def_property_ui_text(prop, "Distance", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "angle", PROP_FLOAT, PROP_ANGLE); RNA_def_property_float_sdna(prop, NULL, "angle"); RNA_def_property_range(prop, 0.0f, DEG2RADF(360.0f)); RNA_def_property_ui_text(prop, "Angle", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "spin", PROP_FLOAT, PROP_ANGLE); RNA_def_property_float_sdna(prop, NULL, "spin"); RNA_def_property_range(prop, DEG2RADF(-360.0f), DEG2RADF(360.0f)); RNA_def_property_ui_text(prop, "Spin", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "zoom", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "zoom"); RNA_def_property_range(prop, 0.0f, 100.0f); @@ -5719,21 +5719,21 @@ static void def_cmp_dblur(StructRNA *srna) static void def_cmp_bilateral_blur(StructRNA *srna) { PropertyRNA *prop; - + RNA_def_struct_sdna_from(srna, "NodeBilateralBlurData", "storage"); - + prop = RNA_def_property(srna, "iterations", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "iter"); RNA_def_property_range(prop, 1, 128); RNA_def_property_ui_text(prop, "Iterations", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "sigma_color", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "sigma_color"); RNA_def_property_range(prop, 0.01f, 3.0f); RNA_def_property_ui_text(prop, "Color Sigma", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "sigma_space", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "sigma_space"); RNA_def_property_range(prop, 0.01f, 30.0f); @@ -5744,25 +5744,25 @@ static void def_cmp_bilateral_blur(StructRNA *srna) static void def_cmp_premul_key(StructRNA *srna) { PropertyRNA *prop; - + static const EnumPropertyItem type_items[] = { {0, "STRAIGHT_TO_PREMUL", 0, "Straight to Premul", ""}, {1, "PREMUL_TO_STRAIGHT", 0, "Premul to Straight", ""}, {0, NULL, 0, NULL, NULL} }; - + prop = RNA_def_property(srna, "mapping", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "custom1"); RNA_def_property_enum_items(prop, type_items); RNA_def_property_ui_text(prop, "Mapping", "Conversion between premultiplied alpha and key alpha"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + } static void def_cmp_glare(StructRNA *srna) { PropertyRNA *prop; - + static const EnumPropertyItem type_items[] = { {3, "GHOSTS", 0, "Ghosts", ""}, {2, "STREAKS", 0, "Streaks", ""}, @@ -5770,22 +5770,22 @@ static void def_cmp_glare(StructRNA *srna) {0, "SIMPLE_STAR", 0, "Simple Star", ""}, {0, NULL, 0, NULL, NULL} }; - + static const EnumPropertyItem quality_items[] = { {0, "HIGH", 0, "High", ""}, {1, "MEDIUM", 0, "Medium", ""}, {2, "LOW", 0, "Low", ""}, {0, NULL, 0, NULL, NULL} }; - + RNA_def_struct_sdna_from(srna, "NodeGlare", "storage"); - + prop = RNA_def_property(srna, "glare_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "type"); RNA_def_property_enum_items(prop, type_items); RNA_def_property_ui_text(prop, "Glare Type", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "quality", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "quality"); RNA_def_property_enum_items(prop, quality_items); @@ -5793,13 +5793,13 @@ static void def_cmp_glare(StructRNA *srna) "If not set to high quality, the effect will be applied to a low-res copy " "of the source image"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "iterations", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "iter"); RNA_def_property_range(prop, 2, 5); RNA_def_property_ui_text(prop, "Iterations", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "color_modulation", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "colmod"); RNA_def_property_range(prop, 0.0f, 1.0f); @@ -5807,109 +5807,109 @@ static void def_cmp_glare(StructRNA *srna) "Amount of Color Modulation, modulates colors of streaks and ghosts for " "a spectral dispersion effect"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "mix", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "mix"); RNA_def_property_range(prop, -1.0f, 1.0f); RNA_def_property_ui_text(prop, "Mix", "-1 is original image only, 0 is exact 50/50 mix, 1 is processed image only"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "threshold", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "threshold"); RNA_def_property_range(prop, 0.0f, 1000.0f); RNA_def_property_ui_text(prop, "Threshold", "The glare filter will only be applied to pixels brighter than this value"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "streaks", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "streaks"); RNA_def_property_range(prop, 1, 16); RNA_def_property_ui_text(prop, "Streaks", "Total number of streaks"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "angle_offset", PROP_FLOAT, PROP_ANGLE); RNA_def_property_float_sdna(prop, NULL, "angle_ofs"); RNA_def_property_range(prop, 0.0f, DEG2RADF(180.0f)); RNA_def_property_ui_text(prop, "Angle Offset", "Streak angle offset"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "fade", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "fade"); RNA_def_property_range(prop, 0.75f, 1.0f); RNA_def_property_ui_text(prop, "Fade", "Streak fade-out factor"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "use_rotate_45", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "star_45", 0); RNA_def_property_ui_text(prop, "Rotate 45", "Simple star filter: add 45 degree rotation offset"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "size", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "size"); RNA_def_property_range(prop, 6, 9); RNA_def_property_ui_text(prop, "Size", "Glow/glare size (not actual size; relative to initial size of bright area of pixels)"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + /* TODO */ } static void def_cmp_tonemap(StructRNA *srna) { PropertyRNA *prop; - + static const EnumPropertyItem type_items[] = { {1, "RD_PHOTORECEPTOR", 0, "R/D Photoreceptor", ""}, {0, "RH_SIMPLE", 0, "Rh Simple", ""}, {0, NULL, 0, NULL, NULL} }; - + RNA_def_struct_sdna_from(srna, "NodeTonemap", "storage"); - + prop = RNA_def_property(srna, "tonemap_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "type"); RNA_def_property_enum_items(prop, type_items); RNA_def_property_ui_text(prop, "Tonemap Type", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "key", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "key"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Key", "The value the average luminance is mapped to"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "offset", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "offset"); RNA_def_property_range(prop, 0.001f, 10.0f); RNA_def_property_ui_text(prop, "Offset", "Normally always 1, but can be used as an extra control to alter the brightness curve"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "gamma", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "gamma"); RNA_def_property_range(prop, 0.001f, 3.0f); RNA_def_property_ui_text(prop, "Gamma", "If not used, set to 1"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "intensity", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "f"); RNA_def_property_range(prop, -8.0f, 8.0f); RNA_def_property_ui_text(prop, "Intensity", "If less than zero, darkens image; otherwise, makes it brighter"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "contrast", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "m"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Contrast", "Set to 0 to use estimate from input image"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "adaptation", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "a"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Adaptation", "If 0, global; if 1, based on pixel intensity"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "correction", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "c"); RNA_def_property_range(prop, 0.0f, 1.0f); @@ -5920,20 +5920,20 @@ static void def_cmp_tonemap(StructRNA *srna) static void def_cmp_lensdist(StructRNA *srna) { PropertyRNA *prop; - + RNA_def_struct_sdna_from(srna, "NodeLensDist", "storage"); - + prop = RNA_def_property(srna, "use_projector", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "proj", 1); RNA_def_property_ui_text(prop, "Projector", "Enable/disable projector mode (the effect is applied in horizontal direction only)"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "use_jitter", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "jit", 1); RNA_def_property_ui_text(prop, "Jitter", "Enable/disable jittering (faster, but also noisier)"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "use_fit", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "fit", 1); RNA_def_property_ui_text(prop, "Fit", @@ -5945,21 +5945,21 @@ static void def_cmp_colorbalance(StructRNA *srna) { PropertyRNA *prop; static float default_1[3] = {1.f, 1.f, 1.f}; - + static const EnumPropertyItem type_items[] = { {0, "LIFT_GAMMA_GAIN", 0, "Lift/Gamma/Gain", ""}, {1, "OFFSET_POWER_SLOPE", 0, "Offset/Power/Slope (ASC-CDL)", "ASC-CDL standard color correction"}, {0, NULL, 0, NULL, NULL} }; - + prop = RNA_def_property(srna, "correction_method", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "custom1"); RNA_def_property_enum_items(prop, type_items); RNA_def_property_ui_text(prop, "Correction Formula", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + RNA_def_struct_sdna_from(srna, "NodeColorBalance", "storage"); - + prop = RNA_def_property(srna, "lift", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "lift"); RNA_def_property_array(prop, 3); @@ -5967,7 +5967,7 @@ static void def_cmp_colorbalance(StructRNA *srna) RNA_def_property_ui_range(prop, 0, 2, 0.1, 3); RNA_def_property_ui_text(prop, "Lift", "Correction for Shadows"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeColorBalance_update_lgg"); - + prop = RNA_def_property(srna, "gamma", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "gamma"); RNA_def_property_array(prop, 3); @@ -5975,7 +5975,7 @@ static void def_cmp_colorbalance(StructRNA *srna) RNA_def_property_ui_range(prop, 0, 2, 0.1, 3); RNA_def_property_ui_text(prop, "Gamma", "Correction for Midtones"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeColorBalance_update_lgg"); - + prop = RNA_def_property(srna, "gain", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "gain"); RNA_def_property_array(prop, 3); @@ -5983,15 +5983,15 @@ static void def_cmp_colorbalance(StructRNA *srna) RNA_def_property_ui_range(prop, 0, 2, 0.1, 3); RNA_def_property_ui_text(prop, "Gain", "Correction for Highlights"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeColorBalance_update_lgg"); - - + + prop = RNA_def_property(srna, "offset", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "offset"); RNA_def_property_array(prop, 3); RNA_def_property_ui_range(prop, 0, 1, 0.1, 3); RNA_def_property_ui_text(prop, "Offset", "Correction for Shadows"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeColorBalance_update_cdl"); - + prop = RNA_def_property(srna, "power", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "power"); RNA_def_property_array(prop, 3); @@ -6000,7 +6000,7 @@ static void def_cmp_colorbalance(StructRNA *srna) RNA_def_property_ui_range(prop, 0, 2, 0.1, 3); RNA_def_property_ui_text(prop, "Power", "Correction for Midtones"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeColorBalance_update_cdl"); - + prop = RNA_def_property(srna, "slope", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "slope"); RNA_def_property_array(prop, 3); @@ -6020,7 +6020,7 @@ static void def_cmp_colorbalance(StructRNA *srna) static void def_cmp_huecorrect(StructRNA *srna) { PropertyRNA *prop; - + prop = RNA_def_property(srna, "mapping", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "storage"); RNA_def_property_struct_type(prop, "CurveMapping"); @@ -6031,7 +6031,7 @@ static void def_cmp_huecorrect(StructRNA *srna) static void def_cmp_zcombine(StructRNA *srna) { PropertyRNA *prop; - + prop = RNA_def_property(srna, "use_alpha", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "custom1", 0); RNA_def_property_ui_text(prop, "Use Alpha", "Take Alpha channel into account when doing the Z operation"); @@ -6046,7 +6046,7 @@ static void def_cmp_zcombine(StructRNA *srna) static void def_cmp_ycc(StructRNA *srna) { PropertyRNA *prop; - + prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "custom1"); RNA_def_property_enum_items(prop, node_ycc_items); @@ -6201,7 +6201,7 @@ static const EnumPropertyItem node_masktype_items[] = { {0, NULL, 0, NULL, NULL} }; -static void def_cmp_boxmask(StructRNA *srna) +static void def_cmp_boxmask(StructRNA *srna) { PropertyRNA *prop; @@ -6327,7 +6327,7 @@ static void def_cmp_bokehblur(StructRNA *srna) RNA_def_property_range(prop, 0.0f, 10000.0f); RNA_def_property_ui_text(prop, "Max Blur", "Blur limit, maximum CoC radius"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + } static void def_cmp_bokehimage(StructRNA *srna) @@ -6395,21 +6395,21 @@ static void def_cmp_colorcorrection(StructRNA *srna) RNA_def_property_boolean_default(prop, true); RNA_def_property_ui_text(prop, "Red", "Red channel active"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "green", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "custom1", 2); RNA_def_property_boolean_default(prop, true); RNA_def_property_ui_text(prop, "Green", "Green channel active"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "blue", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "custom1", 4); RNA_def_property_boolean_default(prop, true); RNA_def_property_ui_text(prop, "Blue", "Blue channel active"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + RNA_def_struct_sdna_from(srna, "NodeColorCorrection", "storage"); - + prop = RNA_def_property(srna, "midtones_start", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "startmidtones"); RNA_def_property_float_default(prop, 0.2f); @@ -6423,35 +6423,35 @@ static void def_cmp_colorcorrection(StructRNA *srna) RNA_def_property_range(prop, 0, 1); RNA_def_property_ui_text(prop, "Midtones End", "End of midtones"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "master_saturation", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "master.saturation"); RNA_def_property_float_default(prop, 1.0f); RNA_def_property_range(prop, 0, 4); RNA_def_property_ui_text(prop, "Master Saturation", "Master saturation"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "master_contrast", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "master.contrast"); RNA_def_property_float_default(prop, 1.0f); RNA_def_property_range(prop, 0, 4); RNA_def_property_ui_text(prop, "Master Contrast", "Master contrast"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "master_gamma", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "master.gamma"); RNA_def_property_float_default(prop, 1.0f); RNA_def_property_range(prop, 0, 4); RNA_def_property_ui_text(prop, "Master Gamma", "Master gamma"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "master_gain", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "master.gain"); RNA_def_property_float_default(prop, 1.0f); RNA_def_property_range(prop, 0, 4); RNA_def_property_ui_text(prop, "Master Gain", "Master gain"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "master_lift", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "master.lift"); RNA_def_property_float_default(prop, 0.0f); @@ -6466,28 +6466,28 @@ static void def_cmp_colorcorrection(StructRNA *srna) RNA_def_property_range(prop, 0, 4); RNA_def_property_ui_text(prop, "Shadows Saturation", "Shadows saturation"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "shadows_contrast", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "shadows.contrast"); RNA_def_property_float_default(prop, 1.0f); RNA_def_property_range(prop, 0, 4); RNA_def_property_ui_text(prop, "Shadows Contrast", "Shadows contrast"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "shadows_gamma", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "shadows.gamma"); RNA_def_property_float_default(prop, 1.0f); RNA_def_property_range(prop, 0, 4); RNA_def_property_ui_text(prop, "Shadows Gamma", "Shadows gamma"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "shadows_gain", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "shadows.gain"); RNA_def_property_float_default(prop, 1.0f); RNA_def_property_range(prop, 0, 4); RNA_def_property_ui_text(prop, "Shadows Gain", "Shadows gain"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "shadows_lift", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "shadows.lift"); RNA_def_property_float_default(prop, 0.0f); @@ -6501,28 +6501,28 @@ static void def_cmp_colorcorrection(StructRNA *srna) RNA_def_property_range(prop, 0, 4); RNA_def_property_ui_text(prop, "Midtones Saturation", "Midtones saturation"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "midtones_contrast", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "midtones.contrast"); RNA_def_property_float_default(prop, 1.0f); RNA_def_property_range(prop, 0, 4); RNA_def_property_ui_text(prop, "Midtones Contrast", "Midtones contrast"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "midtones_gamma", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "midtones.gamma"); RNA_def_property_float_default(prop, 1.0f); RNA_def_property_range(prop, 0, 4); RNA_def_property_ui_text(prop, "Midtones Gamma", "Midtones gamma"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "midtones_gain", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "midtones.gain"); RNA_def_property_float_default(prop, 1.0f); RNA_def_property_range(prop, 0, 4); RNA_def_property_ui_text(prop, "Midtones Gain", "Midtones gain"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "midtones_lift", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "midtones.lift"); RNA_def_property_float_default(prop, 0.0f); @@ -6536,28 +6536,28 @@ static void def_cmp_colorcorrection(StructRNA *srna) RNA_def_property_range(prop, 0, 4); RNA_def_property_ui_text(prop, "Highlights Saturation", "Highlights saturation"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "highlights_contrast", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "highlights.contrast"); RNA_def_property_float_default(prop, 1.0f); RNA_def_property_range(prop, 0, 4); RNA_def_property_ui_text(prop, "Highlights Contrast", "Highlights contrast"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "highlights_gamma", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "highlights.gamma"); RNA_def_property_float_default(prop, 1.0f); RNA_def_property_range(prop, 0, 4); RNA_def_property_ui_text(prop, "Highlights Gamma", "Highlights gamma"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "highlights_gain", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "highlights.gain"); RNA_def_property_float_default(prop, 1.0f); RNA_def_property_range(prop, 0, 4); RNA_def_property_ui_text(prop, "Highlights Gain", "Highlights gain"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "highlights_lift", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "highlights.lift"); RNA_def_property_float_default(prop, 0.0f); @@ -6589,7 +6589,7 @@ static void def_cmp_viewer(StructRNA *srna) RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "X", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "center_y", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "custom4"); RNA_def_property_float_default(prop, 0.5f); @@ -6853,7 +6853,7 @@ static void def_tex_output(StructRNA *srna) PropertyRNA *prop; RNA_def_struct_sdna_from(srna, "TexNodeOutput", "storage"); - + prop = RNA_def_property(srna, "filepath", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "name"); RNA_def_property_ui_text(prop, "Output Name", ""); @@ -6888,19 +6888,19 @@ static void def_tex_bricks(StructRNA *srna) RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Offset Amount", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "offset_frequency", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "custom1"); RNA_def_property_range(prop, 2, 99); RNA_def_property_ui_text(prop, "Offset Frequency", "Offset every N rows"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "squash", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "custom4"); RNA_def_property_range(prop, 0.0f, 99.0f); RNA_def_property_ui_text(prop, "Squash Amount", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "squash_frequency", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "custom2"); RNA_def_property_range(prop, 2, 99); @@ -6913,7 +6913,7 @@ static void def_tex_bricks(StructRNA *srna) static void rna_def_shader_node(BlenderRNA *brna) { StructRNA *srna; - + srna = RNA_def_struct(brna, "ShaderNode", "NodeInternal"); RNA_def_struct_ui_text(srna, "Shader Node", "Material shader node"); RNA_def_struct_sdna(srna, "bNode"); @@ -6924,12 +6924,12 @@ static void rna_def_compositor_node(BlenderRNA *brna) { StructRNA *srna; FunctionRNA *func; - + srna = RNA_def_struct(brna, "CompositorNode", "NodeInternal"); RNA_def_struct_ui_text(srna, "Compositor Node", ""); RNA_def_struct_sdna(srna, "bNode"); RNA_def_struct_register_funcs(srna, "rna_CompositorNode_register", "rna_Node_unregister", NULL); - + /* compositor node need_exec flag */ func = RNA_def_function(srna, "tag_need_exec", "rna_CompositorNode_tag_need_exec"); RNA_def_function_ui_description(func, "Tag the node for compositor update"); @@ -6938,7 +6938,7 @@ static void rna_def_compositor_node(BlenderRNA *brna) static void rna_def_texture_node(BlenderRNA *brna) { StructRNA *srna; - + srna = RNA_def_struct(brna, "TextureNode", "NodeInternal"); RNA_def_struct_ui_text(srna, "Texture Node", ""); RNA_def_struct_sdna(srna, "bNode"); @@ -6953,9 +6953,9 @@ static void rna_def_node_socket(BlenderRNA *brna) PropertyRNA *prop; PropertyRNA *parm; FunctionRNA *func; - + static float default_draw_color[] = { 0.0f, 0.0f, 0.0f, 1.0f }; - + srna = RNA_def_struct(brna, "NodeSocket", NULL); RNA_def_struct_ui_text(srna, "Node Socket", "Input or output socket of a node"); RNA_def_struct_sdna(srna, "bNodeSocket"); @@ -7082,9 +7082,9 @@ static void rna_def_node_socket_interface(BlenderRNA *brna) PropertyRNA *prop; PropertyRNA *parm; FunctionRNA *func; - + static float default_draw_color[] = { 0.0f, 0.0f, 0.0f, 1.0f }; - + srna = RNA_def_struct(brna, "NodeSocketInterface", NULL); RNA_def_struct_ui_text(srna, "Node Socket Template", "Parameters to define node sockets"); /* XXX Using bNodeSocket DNA for templates is a compatibility hack. @@ -7166,7 +7166,7 @@ static void rna_def_node_socket_float(BlenderRNA *brna, const char *idname, cons StructRNA *srna; PropertyRNA *prop; float value_default; - + /* choose sensible common default based on subtype */ switch (subtype) { case PROP_FACTOR: @@ -7179,46 +7179,46 @@ static void rna_def_node_socket_float(BlenderRNA *brna, const char *idname, cons value_default = 0.0f; break; } - + srna = RNA_def_struct(brna, idname, "NodeSocketStandard"); RNA_def_struct_ui_text(srna, "Float Node Socket", "Floating point number socket of a node"); RNA_def_struct_sdna(srna, "bNodeSocket"); - + RNA_def_struct_sdna_from(srna, "bNodeSocketValueFloat", "default_value"); - + prop = RNA_def_property(srna, "default_value", PROP_FLOAT, subtype); RNA_def_property_float_sdna(prop, NULL, "value"); RNA_def_property_float_funcs(prop, NULL, NULL, "rna_NodeSocketStandard_float_range"); RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketStandard_value_update"); RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); - + RNA_def_struct_sdna_from(srna, "bNodeSocket", NULL); - + /* socket interface */ srna = RNA_def_struct(brna, interface_idname, "NodeSocketInterfaceStandard"); RNA_def_struct_ui_text(srna, "Float Node Socket Interface", "Floating point number socket of a node"); RNA_def_struct_sdna(srna, "bNodeSocket"); - + RNA_def_struct_sdna_from(srna, "bNodeSocketValueFloat", "default_value"); - + prop = RNA_def_property(srna, "default_value", PROP_FLOAT, subtype); RNA_def_property_float_sdna(prop, NULL, "value"); RNA_def_property_float_default(prop, value_default); RNA_def_property_float_funcs(prop, NULL, NULL, "rna_NodeSocketStandard_float_range"); RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketInterface_update"); - + prop = RNA_def_property(srna, "min_value", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "min"); RNA_def_property_ui_text(prop, "Minimum Value", "Minimum value"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketInterface_update"); - + prop = RNA_def_property(srna, "max_value", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "max"); RNA_def_property_ui_text(prop, "Maximum Value", "Maximum value"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketInterface_update"); - + RNA_def_struct_sdna_from(srna, "bNodeSocket", NULL); } @@ -7227,7 +7227,7 @@ static void rna_def_node_socket_int(BlenderRNA *brna, const char *identifier, co StructRNA *srna; PropertyRNA *prop; int value_default; - + /* choose sensible common default based on subtype */ switch (subtype) { case PROP_FACTOR: @@ -7240,13 +7240,13 @@ static void rna_def_node_socket_int(BlenderRNA *brna, const char *identifier, co value_default = 0; break; } - + srna = RNA_def_struct(brna, identifier, "NodeSocketStandard"); RNA_def_struct_ui_text(srna, "Integer Node Socket", "Integer number socket of a node"); RNA_def_struct_sdna(srna, "bNodeSocket"); - + RNA_def_struct_sdna_from(srna, "bNodeSocketValueInt", "default_value"); - + prop = RNA_def_property(srna, "default_value", PROP_INT, subtype); RNA_def_property_int_sdna(prop, NULL, "value"); RNA_def_property_int_default(prop, value_default); @@ -7254,32 +7254,32 @@ static void rna_def_node_socket_int(BlenderRNA *brna, const char *identifier, co RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketStandard_value_update"); RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); - + RNA_def_struct_sdna_from(srna, "bNodeSocket", NULL); - + /* socket interface */ srna = RNA_def_struct(brna, interface_idname, "NodeSocketInterfaceStandard"); RNA_def_struct_ui_text(srna, "Integer Node Socket Interface", "Integer number socket of a node"); RNA_def_struct_sdna(srna, "bNodeSocket"); RNA_def_struct_sdna_from(srna, "bNodeSocketValueInt", "default_value"); - + prop = RNA_def_property(srna, "default_value", PROP_INT, subtype); RNA_def_property_int_sdna(prop, NULL, "value"); RNA_def_property_int_funcs(prop, NULL, NULL, "rna_NodeSocketStandard_int_range"); RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketInterface_update"); - + prop = RNA_def_property(srna, "min_value", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "min"); RNA_def_property_ui_text(prop, "Minimum Value", "Minimum value"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketInterface_update"); - + prop = RNA_def_property(srna, "max_value", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "max"); RNA_def_property_ui_text(prop, "Maximum Value", "Maximum value"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketInterface_update"); - + RNA_def_struct_sdna_from(srna, "bNodeSocket", NULL); } @@ -7287,33 +7287,33 @@ static void rna_def_node_socket_bool(BlenderRNA *brna, const char *identifier, c { StructRNA *srna; PropertyRNA *prop; - + srna = RNA_def_struct(brna, identifier, "NodeSocketStandard"); RNA_def_struct_ui_text(srna, "Boolean Node Socket", "Boolean value socket of a node"); RNA_def_struct_sdna(srna, "bNodeSocket"); - + RNA_def_struct_sdna_from(srna, "bNodeSocketValueBoolean", "default_value"); - + prop = RNA_def_property(srna, "default_value", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "value", 1); RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketStandard_value_update"); RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); - + RNA_def_struct_sdna_from(srna, "bNodeSocket", NULL); - + /* socket interface */ srna = RNA_def_struct(brna, interface_idname, "NodeSocketInterfaceStandard"); RNA_def_struct_ui_text(srna, "Boolean Node Socket Interface", "Boolean value socket of a node"); RNA_def_struct_sdna(srna, "bNodeSocket"); - + RNA_def_struct_sdna_from(srna, "bNodeSocketValueBoolean", "default_value"); - + prop = RNA_def_property(srna, "default_value", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "value", 1); RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketInterface_update"); - + RNA_def_struct_sdna_from(srna, "bNodeSocket", NULL); } @@ -7322,7 +7322,7 @@ static void rna_def_node_socket_vector(BlenderRNA *brna, const char *identifier, StructRNA *srna; PropertyRNA *prop; const float *value_default; - + /* choose sensible common default based on subtype */ switch (subtype) { case PROP_DIRECTION: { @@ -7336,13 +7336,13 @@ static void rna_def_node_socket_vector(BlenderRNA *brna, const char *identifier, break; } } - + srna = RNA_def_struct(brna, identifier, "NodeSocketStandard"); RNA_def_struct_ui_text(srna, "Vector Node Socket", "3D vector socket of a node"); RNA_def_struct_sdna(srna, "bNodeSocket"); - + RNA_def_struct_sdna_from(srna, "bNodeSocketValueVector", "default_value"); - + prop = RNA_def_property(srna, "default_value", PROP_FLOAT, subtype); RNA_def_property_float_sdna(prop, NULL, "value"); RNA_def_property_float_array_default(prop, value_default); @@ -7350,32 +7350,32 @@ static void rna_def_node_socket_vector(BlenderRNA *brna, const char *identifier, RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketStandard_value_update"); RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); - + RNA_def_struct_sdna_from(srna, "bNodeSocket", NULL); - + /* socket interface */ srna = RNA_def_struct(brna, interface_idname, "NodeSocketInterfaceStandard"); RNA_def_struct_ui_text(srna, "Vector Node Socket Interface", "3D vector socket of a node"); RNA_def_struct_sdna(srna, "bNodeSocket"); - + RNA_def_struct_sdna_from(srna, "bNodeSocketValueVector", "default_value"); - + prop = RNA_def_property(srna, "default_value", PROP_FLOAT, subtype); RNA_def_property_float_sdna(prop, NULL, "value"); RNA_def_property_float_funcs(prop, NULL, NULL, "rna_NodeSocketStandard_vector_range"); RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketInterface_update"); - + prop = RNA_def_property(srna, "min_value", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "min"); RNA_def_property_ui_text(prop, "Minimum Value", "Minimum value"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketInterface_update"); - + prop = RNA_def_property(srna, "max_value", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "max"); RNA_def_property_ui_text(prop, "Maximum Value", "Maximum value"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketInterface_update"); - + RNA_def_struct_sdna_from(srna, "bNodeSocket", NULL); } @@ -7383,33 +7383,33 @@ static void rna_def_node_socket_color(BlenderRNA *brna, const char *identifier, { StructRNA *srna; PropertyRNA *prop; - + srna = RNA_def_struct(brna, identifier, "NodeSocketStandard"); RNA_def_struct_ui_text(srna, "Color Node Socket", "RGBA color socket of a node"); RNA_def_struct_sdna(srna, "bNodeSocket"); - + RNA_def_struct_sdna_from(srna, "bNodeSocketValueRGBA", "default_value"); - + prop = RNA_def_property(srna, "default_value", PROP_FLOAT, PROP_COLOR); RNA_def_property_float_sdna(prop, NULL, "value"); RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketStandard_value_update"); RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); - + RNA_def_struct_sdna_from(srna, "bNodeSocket", NULL); - + /* socket interface */ srna = RNA_def_struct(brna, interface_idname, "NodeSocketInterfaceStandard"); RNA_def_struct_ui_text(srna, "Color Node Socket Interface", "RGBA color socket of a node"); RNA_def_struct_sdna(srna, "bNodeSocket"); - + RNA_def_struct_sdna_from(srna, "bNodeSocketValueRGBA", "default_value"); - + prop = RNA_def_property(srna, "default_value", PROP_FLOAT, PROP_COLOR); RNA_def_property_float_sdna(prop, NULL, "value"); RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketInterface_update"); - + RNA_def_struct_sdna_from(srna, "bNodeSocket", NULL); } @@ -7417,44 +7417,44 @@ static void rna_def_node_socket_string(BlenderRNA *brna, const char *identifier, { StructRNA *srna; PropertyRNA *prop; - + srna = RNA_def_struct(brna, identifier, "NodeSocketStandard"); RNA_def_struct_ui_text(srna, "String Node Socket", "String socket of a node"); RNA_def_struct_sdna(srna, "bNodeSocket"); - + RNA_def_struct_sdna_from(srna, "bNodeSocketValueString", "default_value"); - + prop = RNA_def_property(srna, "default_value", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "value"); RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketStandard_value_update"); RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); - + RNA_def_struct_sdna_from(srna, "bNodeSocket", NULL); - + /* socket interface */ srna = RNA_def_struct(brna, interface_idname, "NodeSocketInterfaceStandard"); RNA_def_struct_ui_text(srna, "String Node Socket Interface", "String socket of a node"); RNA_def_struct_sdna(srna, "bNodeSocket"); - + RNA_def_struct_sdna_from(srna, "bNodeSocketValueString", "default_value"); - + prop = RNA_def_property(srna, "default_value", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "value"); RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketInterface_update"); - + RNA_def_struct_sdna_from(srna, "bNodeSocket", NULL); } static void rna_def_node_socket_shader(BlenderRNA *brna, const char *identifier, const char *interface_idname) { StructRNA *srna; - + srna = RNA_def_struct(brna, identifier, "NodeSocketStandard"); RNA_def_struct_ui_text(srna, "Shader Node Socket", "Shader socket of a node"); RNA_def_struct_sdna(srna, "bNodeSocket"); - + /* socket interface */ srna = RNA_def_struct(brna, interface_idname, "NodeSocketInterfaceStandard"); RNA_def_struct_ui_text(srna, "Shader Node Socket Interface", "Shader socket of a node"); @@ -7464,7 +7464,7 @@ static void rna_def_node_socket_shader(BlenderRNA *brna, const char *identifier, static void rna_def_node_socket_virtual(BlenderRNA *brna, const char *identifier) { StructRNA *srna; - + srna = RNA_def_struct(brna, identifier, "NodeSocketStandard"); RNA_def_struct_ui_text(srna, "Virtual Node Socket", "Virtual socket of a node"); RNA_def_struct_sdna(srna, "bNodeSocket"); @@ -7478,16 +7478,16 @@ static void rna_def_node_socket_standard_types(BlenderRNA *brna) * so in order to call them in py scripts we need to overload and replace them with plain C callbacks. * These types provide a usable basis for socket types defined in C. */ - + StructRNA *srna; PropertyRNA *parm, *prop; FunctionRNA *func; - + static float default_draw_color[] = { 0.0f, 0.0f, 0.0f, 1.0f }; - + srna = RNA_def_struct(brna, "NodeSocketStandard", "NodeSocket"); RNA_def_struct_sdna(srna, "bNodeSocket"); - + /* draw socket */ func = RNA_def_function(srna, "draw", "rna_NodeSocketStandard_draw"); RNA_def_function_flag(func, FUNC_USE_SELF_ID); @@ -7518,11 +7518,11 @@ static void rna_def_node_socket_standard_types(BlenderRNA *brna) RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR); parm = RNA_def_float_array(func, "color", 4, default_draw_color, 0.0f, 1.0f, "Color", "", 0.0f, 1.0f); RNA_def_function_output(func, parm); - - + + srna = RNA_def_struct(brna, "NodeSocketInterfaceStandard", "NodeSocketInterface"); RNA_def_struct_sdna(srna, "bNodeSocket"); - + /* for easier type comparison in python */ prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "typeinfo->type"); @@ -7530,7 +7530,7 @@ static void rna_def_node_socket_standard_types(BlenderRNA *brna) RNA_def_property_enum_default(prop, SOCK_FLOAT); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Type", "Data type"); - + func = RNA_def_function(srna, "draw", "rna_NodeSocketInterfaceStandard_draw"); RNA_def_function_flag(func, FUNC_USE_SELF_ID); RNA_def_function_ui_description(func, "Draw template settings"); @@ -7554,7 +7554,7 @@ static void rna_def_node_socket_standard_types(BlenderRNA *brna) * Then use the nodeStaticSocketType and nodeStaticSocketInterfaceType functions * to get the idname strings from int type and subtype (see node_socket.c, register_standard_node_socket_types). */ - + rna_def_node_socket_float(brna, "NodeSocketFloat", "NodeSocketInterfaceFloat", PROP_NONE); rna_def_node_socket_float(brna, "NodeSocketFloatUnsigned", "NodeSocketInterfaceFloatUnsigned", PROP_UNSIGNED); rna_def_node_socket_float(brna, "NodeSocketFloatPercentage", "NodeSocketInterfaceFloatPercentage", PROP_PERCENTAGE); @@ -7591,36 +7591,36 @@ static void rna_def_internal_node(BlenderRNA *brna) StructRNA *srna; PropertyRNA *prop, *parm; FunctionRNA *func; - + srna = RNA_def_struct(brna, "NodeInternalSocketTemplate", NULL); RNA_def_struct_ui_text(srna, "Socket Template", "Type and default value of a node socket"); - + prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); RNA_def_property_string_funcs(prop, "rna_NodeInternalSocketTemplate_name_get", "rna_NodeInternalSocketTemplate_name_length", NULL); RNA_def_property_ui_text(prop, "Name", "Name of the socket"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); - + prop = RNA_def_property(srna, "identifier", PROP_STRING, PROP_NONE); RNA_def_property_string_funcs(prop, "rna_NodeInternalSocketTemplate_identifier_get", "rna_NodeInternalSocketTemplate_identifier_length", NULL); RNA_def_property_ui_text(prop, "Identifier", "Identifier of the socket"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); - + prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_funcs(prop, "rna_NodeInternalSocketTemplate_type_get", NULL, NULL); RNA_def_property_enum_items(prop, node_socket_type_items); RNA_def_property_ui_text(prop, "Type", "Data type of the socket"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); - + /* XXX Workaround: Registered functions are not exposed in python by bpy, * it expects them to be registered from python and use the native implementation. * However, the standard node types are not registering these functions from python, * so in order to call them in py scripts we need to overload and replace them with plain C callbacks. * This type provides a usable basis for node types defined in C. */ - + srna = RNA_def_struct(brna, "NodeInternal", "Node"); RNA_def_struct_sdna(srna, "bNode"); - + /* poll */ func = RNA_def_function(srna, "poll", "rna_NodeInternal_poll"); RNA_def_function_ui_description(func, "If non-null output is returned, the node type can be added to the tree"); @@ -7628,18 +7628,18 @@ static void rna_def_internal_node(BlenderRNA *brna) RNA_def_function_return(func, RNA_def_boolean(func, "visible", false, "", "")); parm = RNA_def_pointer(func, "node_tree", "NodeTree", "Node Tree", ""); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); - + func = RNA_def_function(srna, "poll_instance", "rna_NodeInternal_poll_instance"); RNA_def_function_ui_description(func, "If non-null output is returned, the node can be added to the tree"); RNA_def_function_return(func, RNA_def_boolean(func, "visible", false, "", "")); parm = RNA_def_pointer(func, "node_tree", "NodeTree", "Node Tree", ""); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); - + /* update */ func = RNA_def_function(srna, "update", "rna_NodeInternal_update"); RNA_def_function_ui_description(func, "Update on editor changes"); RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_ALLOW_WRITE); - + /* draw buttons */ func = RNA_def_function(srna, "draw_buttons", "rna_NodeInternal_draw_buttons"); RNA_def_function_ui_description(func, "Draw node buttons"); @@ -7716,7 +7716,7 @@ static void rna_def_node(BlenderRNA *brna) PropertyRNA *prop; FunctionRNA *func; PropertyRNA *parm; - + static const EnumPropertyItem dummy_static_type_items[] = { {NODE_CUSTOM, "CUSTOM", 0, "Custom", "Custom Node"}, {0, NULL, 0, NULL, NULL}}; @@ -7735,7 +7735,7 @@ static void rna_def_node(BlenderRNA *brna) RNA_def_struct_path_func(srna, "rna_Node_path"); RNA_def_struct_register_funcs(srna, "rna_Node_register", "rna_Node_unregister", NULL); RNA_def_struct_idprops_func(srna, "rna_Node_idprops"); - + prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "type"); RNA_def_property_enum_items(prop, dummy_static_type_items); @@ -7743,55 +7743,55 @@ static void rna_def_node(BlenderRNA *brna) RNA_def_property_enum_default(prop, NODE_CUSTOM); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Type", "Node type (deprecated, use bl_static_type or bl_idname for the actual identifier string)"); - + prop = RNA_def_property(srna, "location", PROP_FLOAT, PROP_XYZ); RNA_def_property_float_sdna(prop, NULL, "locx"); RNA_def_property_array(prop, 2); RNA_def_property_range(prop, -100000.0f, 100000.0f); RNA_def_property_ui_text(prop, "Location", ""); RNA_def_property_update(prop, NC_NODE, "rna_Node_update"); - + prop = RNA_def_property(srna, "width", PROP_FLOAT, PROP_XYZ); RNA_def_property_float_sdna(prop, NULL, "width"); RNA_def_property_float_funcs(prop, NULL, NULL, "rna_Node_width_range"); RNA_def_property_ui_text(prop, "Width", "Width of the node"); RNA_def_property_update(prop, NC_NODE | ND_DISPLAY, NULL); - + prop = RNA_def_property(srna, "width_hidden", PROP_FLOAT, PROP_XYZ); RNA_def_property_float_sdna(prop, NULL, "miniwidth"); RNA_def_property_float_funcs(prop, NULL, NULL, "rna_Node_width_range"); RNA_def_property_ui_text(prop, "Width Hidden", "Width of the node in hidden state"); RNA_def_property_update(prop, NC_NODE | ND_DISPLAY, NULL); - + prop = RNA_def_property(srna, "height", PROP_FLOAT, PROP_XYZ); RNA_def_property_float_sdna(prop, NULL, "height"); RNA_def_property_float_funcs(prop, NULL, NULL, "rna_Node_height_range"); RNA_def_property_ui_text(prop, "Height", "Height of the node"); RNA_def_property_update(prop, NC_NODE | ND_DISPLAY, NULL); - + prop = RNA_def_property(srna, "dimensions", PROP_FLOAT, PROP_XYZ_LENGTH); RNA_def_property_array(prop, 2); RNA_def_property_float_funcs(prop, "rna_Node_dimensions_get", NULL, NULL); RNA_def_property_ui_text(prop, "Dimensions", "Absolute bounding box dimensions of the node"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); - + prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); RNA_def_property_ui_text(prop, "Name", "Unique node identifier"); RNA_def_struct_name_property(srna, prop); RNA_def_property_string_funcs(prop, NULL, NULL, "rna_Node_name_set"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + prop = RNA_def_property(srna, "label", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "label"); RNA_def_property_ui_text(prop, "Label", "Optional custom node label"); RNA_def_property_update(prop, NC_NODE | ND_DISPLAY, NULL); - + prop = RNA_def_property(srna, "inputs", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "inputs", NULL); RNA_def_property_struct_type(prop, "NodeSocket"); RNA_def_property_ui_text(prop, "Inputs", ""); rna_def_node_sockets_api(brna, prop, SOCK_IN); - + prop = RNA_def_property(srna, "outputs", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "outputs", NULL); RNA_def_property_struct_type(prop, "NodeSocket"); @@ -7809,7 +7809,7 @@ static void rna_def_node(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_struct_type(prop, "Node"); RNA_def_property_ui_text(prop, "Parent", "Parent this node is attached to"); - + prop = RNA_def_property(srna, "use_custom_color", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", NODE_CUSTOM_COLOR); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); @@ -7886,7 +7886,7 @@ static void rna_def_node(BlenderRNA *brna) prop = RNA_def_property(srna, "bl_description", PROP_STRING, PROP_TRANSLATION); RNA_def_property_string_sdna(prop, NULL, "typeinfo->ui_description"); RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL); - + prop = RNA_def_property(srna, "bl_icon", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "typeinfo->ui_icon"); RNA_def_property_enum_items(prop, rna_enum_node_icon_items); @@ -7934,26 +7934,26 @@ static void rna_def_node(BlenderRNA *brna) RNA_def_function_return(func, RNA_def_boolean(func, "visible", false, "", "")); parm = RNA_def_pointer(func, "node_tree", "NodeTree", "Node Tree", ""); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); - + func = RNA_def_function(srna, "poll_instance", NULL); RNA_def_function_ui_description(func, "If non-null output is returned, the node can be added to the tree"); RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL); RNA_def_function_return(func, RNA_def_boolean(func, "visible", false, "", "")); parm = RNA_def_pointer(func, "node_tree", "NodeTree", "Node Tree", ""); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); - + /* update */ func = RNA_def_function(srna, "update", NULL); RNA_def_function_ui_description(func, "Update on editor changes"); RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE); - + /* insert_link */ func = RNA_def_function(srna, "insert_link", NULL); RNA_def_function_ui_description(func, "Handle creation of a link to or from the node"); RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE); parm = RNA_def_pointer(func, "link", "NodeLink", "Link", "Node link that will be inserted"); RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); - + /* init */ func = RNA_def_function(srna, "init", NULL); RNA_def_function_ui_description(func, "Initialize a new instance of this node"); @@ -8198,7 +8198,7 @@ static void rna_def_nodetree(BlenderRNA *brna) RNA_def_property_array(prop, 2); RNA_def_property_float_sdna(prop, NULL, "view_center"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); - + /* AnimData */ rna_def_animdata_common(srna); @@ -8223,7 +8223,7 @@ static void rna_def_nodetree(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT); RNA_def_property_ui_text(prop, "Grease Pencil Data", "Grease Pencil data-block"); RNA_def_property_update(prop, NC_NODE, NULL); - + prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_enum_items(prop, static_type_items); @@ -8273,7 +8273,7 @@ static void rna_def_nodetree(BlenderRNA *brna) prop = RNA_def_property(srna, "bl_description", PROP_STRING, PROP_TRANSLATION); RNA_def_property_string_sdna(prop, NULL, "typeinfo->ui_description"); RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL); - + prop = RNA_def_property(srna, "bl_icon", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "typeinfo->ui_icon"); RNA_def_property_enum_items(prop, rna_enum_node_icon_items); @@ -8380,11 +8380,11 @@ static StructRNA *define_specific_node(BlenderRNA *brna, const char *struct_name StructRNA *srna; FunctionRNA *func; PropertyRNA *parm; - + /* XXX hack, want to avoid "NodeInternal" prefix, so use "Node" in NOD_static_types.h and replace here */ if (STREQ(base_name, "Node")) base_name = "NodeInternal"; - + srna = RNA_def_struct(brna, struct_name, base_name); RNA_def_struct_ui_text(srna, ui_name, ui_desc); RNA_def_struct_sdna(srna, "bNode"); @@ -8442,26 +8442,26 @@ static void rna_def_node_instance_hash(BlenderRNA *brna) void RNA_def_nodetree(BlenderRNA *brna) { StructRNA *srna; - + rna_def_node_socket(brna); rna_def_node_socket_interface(brna); - + rna_def_node(brna); rna_def_node_link(brna); - + rna_def_internal_node(brna); rna_def_shader_node(brna); rna_def_compositor_node(brna); rna_def_texture_node(brna); - + rna_def_nodetree(brna); - + rna_def_node_socket_standard_types(brna); - + rna_def_composite_nodetree(brna); rna_def_shader_nodetree(brna); rna_def_texture_nodetree(brna); - + #define DefNode(Category, ID, DefFunc, EnumName, StructName, UIName, UIDesc) \ { \ srna = define_specific_node(brna, #Category #StructName, #Category, UIName, UIDesc, DefFunc); \ @@ -8470,12 +8470,12 @@ void RNA_def_nodetree(BlenderRNA *brna) def_cmp_output_file(brna, srna); \ } \ } - + /* hack, don't want to add include path to RNA just for this, since in the future RNA types * for nodes should be defined locally at runtime anyway ... */ #include "../../nodes/NOD_static_types.h" - + /* Node group types need to be defined for shader, compositor, texture nodes individually. * Cannot use the static types header for this, since they share the same int id. */ @@ -8483,11 +8483,11 @@ void RNA_def_nodetree(BlenderRNA *brna) define_specific_node(brna, "CompositorNodeGroup", "CompositorNode", "Group", "", def_group); define_specific_node(brna, "TextureNodeGroup", "TextureNode", "Group", "", def_group); def_custom_group(brna); - + /* special socket types */ rna_def_cmp_output_file_slot_file(brna); rna_def_cmp_output_file_slot_layer(brna); - + rna_def_node_instance_hash(brna); } diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index 9214f8530b8..a9b87ea0703 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -65,10 +65,10 @@ const EnumPropertyItem rna_enum_object_mode_items[] = { {OB_MODE_OBJECT, "OBJECT", ICON_OBJECT_DATAMODE, "Object Mode", ""}, {OB_MODE_EDIT, "EDIT", ICON_EDITMODE_HLT, "Edit Mode", ""}, {OB_MODE_POSE, "POSE", ICON_POSE_HLT, "Pose Mode", ""}, - {OB_MODE_WEIGHT_PAINT, "WEIGHT_PAINT", ICON_WPAINT_HLT, "Weight Paint", ""}, + {OB_MODE_SCULPT, "SCULPT", ICON_SCULPTMODE_HLT, "Sculpt Mode", ""}, {OB_MODE_VERTEX_PAINT, "VERTEX_PAINT", ICON_VPAINT_HLT, "Vertex Paint", ""}, + {OB_MODE_WEIGHT_PAINT, "WEIGHT_PAINT", ICON_WPAINT_HLT, "Weight Paint", ""}, {OB_MODE_TEXTURE_PAINT, "TEXTURE_PAINT", ICON_TPAINT_HLT, "Texture Paint", ""}, - {OB_MODE_SCULPT, "SCULPT", ICON_SCULPTMODE_HLT, "Sculpt Mode", ""}, {OB_MODE_PARTICLE_EDIT, "PARTICLE_EDIT", ICON_PARTICLEMODE, "Particle Edit", ""}, {OB_MODE_GPENCIL, "GPENCIL_EDIT", ICON_GREASEPENCIL, "Edit Strokes", "Edit Grease Pencil Strokes"}, {0, NULL, 0, NULL, NULL} @@ -224,18 +224,6 @@ static void rna_Object_hide_update(Main *bmain, Scene *UNUSED(scene), PointerRNA DEG_id_type_tag(bmain, ID_OB); } -static int rna_Object_is_visible_get(PointerRNA *ptr) -{ - Object *ob = ptr->id.data; - /* The duplicators final visibility is not evaluated by depsgraph, so it's - * in ob->base_flag & VISIBLED. Instead we need to take into account whether - * we are rendering or not, and the ob->duplicator_visibility_flag. - * However for this assessor we don't know if we are rendering, so we just - * ignore the duplicator visibility - */ - return BKE_object_is_visible(ob, OB_VISIBILITY_CHECK_UNKNOWN_RENDER_MODE); -} - static void rna_Object_matrix_local_get(PointerRNA *ptr, float values[16]) { Object *ob = ptr->id.data; @@ -290,7 +278,7 @@ static void rna_Object_active_shape_update(bContext *C, PointerRNA *ptr) /* exit/enter editmode to get new shape */ switch (ob->type) { case OB_MESH: - EDBM_mesh_load(ob); + EDBM_mesh_load(bmain, ob); EDBM_mesh_make(ob, scene->toolsettings->selectmode, true); DEG_id_tag_update(ob->data, 0); @@ -417,7 +405,7 @@ static const EnumPropertyItem *rna_Object_parent_type_itemf(bContext *UNUSED(C), if (ob->parent) { Object *par = ob->parent; - + if (par->type == OB_LATTICE) { /* special hack: prevents this overriding others */ RNA_enum_items_add_value(&item, &totitem, &parent_type_items[2], PARSKEL); @@ -475,7 +463,7 @@ static void rna_Object_dup_group_set(PointerRNA *ptr, PointerRNA value) { Object *ob = (Object *)ptr->data; Collection *grp = (Collection *)value.data; - + /* must not let this be set if the object belongs in this group already, * thus causing a cycle/infinite-recursion leading to crashes on load [#25298] */ @@ -735,7 +723,7 @@ static PointerRNA rna_Object_active_material_get(PointerRNA *ptr) { Object *ob = (Object *)ptr->id.data; Material *ma; - + ma = (ob->totcol) ? give_current_material(ob, ob->actcol) : NULL; return rna_pointer_inherit_refine(ptr, &RNA_Material, ma); } @@ -800,7 +788,7 @@ static void rna_Object_particle_update(Main *UNUSED(bmain), Scene *scene, Pointe static void rna_Object_rotation_axis_angle_get(PointerRNA *ptr, float *value) { Object *ob = ptr->data; - + /* for now, assume that rotation mode is axis-angle */ value[0] = ob->rotAngle; copy_v3_v3(&value[1], ob->rotAxis); @@ -810,21 +798,21 @@ static void rna_Object_rotation_axis_angle_get(PointerRNA *ptr, float *value) static void rna_Object_rotation_axis_angle_set(PointerRNA *ptr, const float *value) { Object *ob = ptr->data; - + /* for now, assume that rotation mode is axis-angle */ ob->rotAngle = value[0]; copy_v3_v3(ob->rotAxis, &value[1]); - + /* TODO: validate axis? */ } static void rna_Object_rotation_mode_set(PointerRNA *ptr, int value) { Object *ob = ptr->data; - + /* use API Method for conversions... */ BKE_rotMode_change_values(ob->quat, ob->rot, ob->rotAxis, &ob->rotAngle, ob->rotmode, (short)value); - + /* finally, set the new rotation type */ ob->rotmode = value; } @@ -844,7 +832,7 @@ static void rna_Object_dimensions_set(PointerRNA *ptr, const float *value) static int rna_Object_location_editable(PointerRNA *ptr, int index) { Object *ob = (Object *)ptr->data; - + /* only if the axis in question is locked, not editable... */ if ((index == 0) && (ob->protectflag & OB_LOCK_LOCX)) return 0; @@ -859,7 +847,7 @@ static int rna_Object_location_editable(PointerRNA *ptr, int index) static int rna_Object_scale_editable(PointerRNA *ptr, int index) { Object *ob = (Object *)ptr->data; - + /* only if the axis in question is locked, not editable... */ if ((index == 0) && (ob->protectflag & OB_LOCK_SCALEX)) return 0; @@ -874,7 +862,7 @@ static int rna_Object_scale_editable(PointerRNA *ptr, int index) static int rna_Object_rotation_euler_editable(PointerRNA *ptr, int index) { Object *ob = (Object *)ptr->data; - + /* only if the axis in question is locked, not editable... */ if ((index == 0) && (ob->protectflag & OB_LOCK_ROTX)) return 0; @@ -889,7 +877,7 @@ static int rna_Object_rotation_euler_editable(PointerRNA *ptr, int index) static int rna_Object_rotation_4d_editable(PointerRNA *ptr, int index) { Object *ob = (Object *)ptr->data; - + /* only consider locks if locking components individually... */ if (ob->protectflag & OB_LOCK_ROT4D) { /* only if the axis in question is locked, not editable... */ @@ -902,16 +890,31 @@ static int rna_Object_rotation_4d_editable(PointerRNA *ptr, int index) else if ((index == 3) && (ob->protectflag & OB_LOCK_ROTZ)) return 0; } - + return PROP_EDITABLE; } +static int rna_MaterialSlot_material_editable(PointerRNA *ptr, const char **UNUSED(r_info)) +{ + Object *ob = (Object *)ptr->id.data; + const int index = (Material **)ptr->data - ob->mat; + bool is_editable; + + if ((ob->matbits == NULL) || ob->matbits[index]) { + is_editable = !ID_IS_LINKED(ob); + } + else { + is_editable = ob->data ? !ID_IS_LINKED(ob->data) : false; + } + + return is_editable ? PROP_EDITABLE : 0; +} static PointerRNA rna_MaterialSlot_material_get(PointerRNA *ptr) { Object *ob = (Object *)ptr->id.data; Material *ma; - int index = (Material **)ptr->data - ob->mat; + const int index = (Material **)ptr->data - ob->mat; ma = give_current_material(ob, index + 1); return rna_pointer_inherit_refine(ptr, &RNA_Material, ma); @@ -937,7 +940,7 @@ static void rna_MaterialSlot_link_set(PointerRNA *ptr, int value) { Object *ob = (Object *)ptr->id.data; int index = (Material **)ptr->data - ob->mat; - + if (value) { ob->matbits[index] = 1; /* ob->colbits |= (1 << index); */ /* DEPRECATED */ @@ -958,7 +961,7 @@ static int rna_MaterialSlot_name_length(PointerRNA *ptr) if (ma) return strlen(ma->id.name + 2); - + return 0; } @@ -1051,7 +1054,7 @@ static PointerRNA rna_Object_active_shape_key_get(PointerRNA *ptr) if (key == NULL) return PointerRNA_NULL; - + kb = BLI_findlink(&key->block, ob->shapenr - 1); RNA_pointer_create((ID *)key, &RNA_ShapeKey, kb, &keyptr); return keyptr; @@ -1064,7 +1067,7 @@ static PointerRNA rna_Object_field_get(PointerRNA *ptr) /* weak */ if (!ob->pd) ob->pd = object_add_collision_fields(0); - + return rna_pointer_inherit_refine(ptr, &RNA_FieldSettings, ob->pd); } @@ -1078,7 +1081,7 @@ static PointerRNA rna_Object_collision_get(PointerRNA *ptr) /* weak */ if (!ob->pd) ob->pd = object_add_collision_fields(0); - + return rna_pointer_inherit_refine(ptr, &RNA_CollisionSettings, ob->pd); } @@ -1465,7 +1468,7 @@ static void rna_def_vertex_group(BlenderRNA *brna) RNA_def_property_string_funcs(prop, NULL, NULL, "rna_VertexGroup_name_set"); /* update data because modifiers may use [#24761] */ RNA_def_property_update(prop, NC_GEOM | ND_DATA | NA_RENAME, "rna_Object_internal_update_data"); - + prop = RNA_def_property(srna, "lock_weight", PROP_BOOLEAN, PROP_NONE); RNA_def_property_ui_text(prop, "", "Maintain the relative weights for the group"); RNA_def_property_boolean_sdna(prop, NULL, "flag", 0); @@ -1521,7 +1524,7 @@ static void rna_def_face_map(BlenderRNA *brna) RNA_def_property_string_funcs(prop, NULL, NULL, "rna_FaceMap_name_set"); /* update data because modifiers may use [#24761] */ RNA_def_property_update(prop, NC_GEOM | ND_DATA | NA_RENAME, "rna_Object_internal_update_data"); - + prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SELECT); RNA_def_property_ui_text(prop, "Select", "Face-map selection state (for tools to use)"); @@ -1557,7 +1560,7 @@ static void rna_def_material_slot(BlenderRNA *brna) {0, "DATA", 0, "Data", ""}, {0, NULL, 0, NULL, NULL} }; - + /* NOTE: there is no MaterialSlot equivalent in DNA, so the internal * pointer data points to ob->mat + index, and we manually implement * get/set for the properties. */ @@ -1578,6 +1581,7 @@ static void rna_def_material_slot(BlenderRNA *brna) prop = RNA_def_property(srna, "material", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "Material"); RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_editable_func(prop, "rna_MaterialSlot_material_editable"); RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC); RNA_def_property_pointer_funcs(prop, "rna_MaterialSlot_material_get", "rna_MaterialSlot_material_set", NULL, NULL); RNA_def_property_ui_text(prop, "Material", "Material data-block used by this material slot"); @@ -1697,7 +1701,7 @@ static void rna_def_object_modifiers(BlenderRNA *brna, PropertyRNA *cprop) static void rna_def_object_particle_systems(BlenderRNA *brna, PropertyRNA *cprop) { StructRNA *srna; - + PropertyRNA *prop; /* FunctionRNA *func; */ @@ -1713,7 +1717,7 @@ static void rna_def_object_particle_systems(BlenderRNA *brna, PropertyRNA *cprop RNA_def_property_pointer_funcs(prop, "rna_Object_active_particle_system_get", NULL, NULL, NULL); RNA_def_property_ui_text(prop, "Active Particle System", "Active particle system being displayed"); RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); - + prop = RNA_def_property(srna, "active_index", PROP_INT, PROP_UNSIGNED); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_int_funcs(prop, "rna_Object_active_particle_system_index_get", @@ -1728,7 +1732,7 @@ static void rna_def_object_particle_systems(BlenderRNA *brna, PropertyRNA *cprop static void rna_def_object_vertex_groups(BlenderRNA *brna, PropertyRNA *cprop) { StructRNA *srna; - + PropertyRNA *prop; FunctionRNA *func; @@ -1754,7 +1758,7 @@ static void rna_def_object_vertex_groups(BlenderRNA *brna, PropertyRNA *cprop) "rna_Object_active_vertex_group_index_range"); RNA_def_property_ui_text(prop, "Active Vertex Group Index", "Active index in vertex group array"); RNA_def_property_update(prop, NC_GEOM | ND_DATA, "rna_Object_internal_update_data"); - + /* vertex groups */ /* add_vertex_group */ func = RNA_def_function(srna, "new", "rna_Object_vgroup_new"); RNA_def_function_ui_description(func, "Add vertex group to object"); @@ -1777,7 +1781,7 @@ static void rna_def_object_vertex_groups(BlenderRNA *brna, PropertyRNA *cprop) static void rna_def_object_face_maps(BlenderRNA *brna, PropertyRNA *cprop) { StructRNA *srna; - + PropertyRNA *prop; FunctionRNA *func; @@ -1803,7 +1807,7 @@ static void rna_def_object_face_maps(BlenderRNA *brna, PropertyRNA *cprop) "rna_Object_active_face_map_index_range"); RNA_def_property_ui_text(prop, "Active Face Map Index", "Active index in face map array"); RNA_def_property_update(prop, NC_GEOM | ND_DATA, "rna_Object_internal_update_data"); - + /* face maps */ /* add_face_map */ func = RNA_def_function(srna, "new", "rna_Object_fmap_new"); RNA_def_function_ui_description(func, "Add face map to object"); @@ -1869,7 +1873,7 @@ static void rna_def_object(BlenderRNA *brna) {0, NULL, 0, NULL, NULL} }; - + /* XXX: this RNA enum define is currently duplicated for objects, * since there is some text here which is not applicable */ static const EnumPropertyItem prop_rotmode_items[] = { @@ -1884,7 +1888,7 @@ static void rna_def_object(BlenderRNA *brna) "Axis Angle (W+XYZ), defines a rotation around some axis defined by 3D-Vector"}, {0, NULL, 0, NULL, NULL} }; - + static float default_quat[4] = {1, 0, 0, 0}; /* default quaternion values */ static float default_axisAngle[4] = {0, 0, 1, 0}; /* default axis-angle rotation values */ static float default_scale[3] = {1, 1, 1}; /* default scale values */ @@ -1937,7 +1941,7 @@ static void rna_def_object(BlenderRNA *brna) RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC); RNA_def_property_ui_text(prop, "Parent", "Parent Object"); RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_dependency_update"); - + prop = RNA_def_property(srna, "parent_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_bitflag_sdna(prop, NULL, "partype"); RNA_def_property_enum_items(prop, parent_type_items); @@ -1956,7 +1960,7 @@ static void rna_def_object(BlenderRNA *brna) RNA_def_property_string_funcs(prop, NULL, NULL, "rna_Object_parent_bone_set"); RNA_def_property_ui_text(prop, "Parent Bone", "Name of parent bone in case of a bone parenting relation"); RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_dependency_update"); - + /* Track and Up flags */ /* XXX: these have been saved here for a bit longer (after old track was removed), * since some other tools still refer to this */ @@ -1975,7 +1979,7 @@ static void rna_def_object(BlenderRNA *brna) "Axis that points in the upward direction (applies to DupliFrame when " "parent 'Follow' is enabled)"); RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_internal_update"); - + /* proxy */ prop = RNA_def_property(srna, "proxy", PROP_POINTER, PROP_NONE); RNA_def_property_ui_text(prop, "Proxy", "Library object this proxy object controls"); @@ -1997,6 +2001,7 @@ static void rna_def_object(BlenderRNA *brna) RNA_def_property_pointer_funcs(prop, "rna_Object_active_material_get", "rna_Object_active_material_set", NULL, NULL); RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC); RNA_def_property_editable_func(prop, "rna_Object_active_material_editable"); RNA_def_property_ui_text(prop, "Active Material", "Active material being displayed"); RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_MaterialSlot_update"); @@ -2009,7 +2014,7 @@ static void rna_def_object(BlenderRNA *brna) "rna_Object_active_material_index_range"); RNA_def_property_ui_text(prop, "Active Material Index", "Index of active material slot"); RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING_LINKS, NULL); - + /* transform */ prop = RNA_def_property(srna, "location", PROP_FLOAT, PROP_TRANSLATION); RNA_def_property_float_sdna(prop, NULL, "loc"); @@ -2018,7 +2023,7 @@ static void rna_def_object(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Location", "Location of the object"); RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT); RNA_def_property_update(prop, NC_OBJECT | ND_TRANSFORM, "rna_Object_internal_update"); - + prop = RNA_def_property(srna, "rotation_quaternion", PROP_FLOAT, PROP_QUATERNION); RNA_def_property_float_sdna(prop, NULL, "quat"); RNA_def_property_editable_array_func(prop, "rna_Object_rotation_4d_editable"); @@ -2026,7 +2031,7 @@ static void rna_def_object(BlenderRNA *brna) RNA_def_property_float_array_default(prop, default_quat); RNA_def_property_ui_text(prop, "Quaternion Rotation", "Rotation in Quaternions"); RNA_def_property_update(prop, NC_OBJECT | ND_TRANSFORM, "rna_Object_internal_update"); - + /* XXX: for axis-angle, it would have been nice to have 2 separate fields for UI purposes, but * having a single one is better for Keyframing and other property-management situations... */ @@ -2039,21 +2044,21 @@ static void rna_def_object(BlenderRNA *brna) RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC); RNA_def_property_ui_text(prop, "Axis-Angle Rotation", "Angle of Rotation for Axis-Angle rotation representation"); RNA_def_property_update(prop, NC_OBJECT | ND_TRANSFORM, "rna_Object_internal_update"); - + prop = RNA_def_property(srna, "rotation_euler", PROP_FLOAT, PROP_EULER); RNA_def_property_float_sdna(prop, NULL, "rot"); RNA_def_property_editable_array_func(prop, "rna_Object_rotation_euler_editable"); RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC); RNA_def_property_ui_text(prop, "Euler Rotation", "Rotation in Eulers"); RNA_def_property_update(prop, NC_OBJECT | ND_TRANSFORM, "rna_Object_internal_update"); - + prop = RNA_def_property(srna, "rotation_mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "rotmode"); RNA_def_property_enum_items(prop, prop_rotmode_items); /* XXX move to using a single define of this someday */ RNA_def_property_enum_funcs(prop, NULL, "rna_Object_rotation_mode_set", NULL); RNA_def_property_ui_text(prop, "Rotation Mode", ""); RNA_def_property_update(prop, NC_OBJECT | ND_TRANSFORM, "rna_Object_internal_update"); - + prop = RNA_def_property(srna, "scale", PROP_FLOAT, PROP_XYZ); RNA_def_property_float_sdna(prop, NULL, "size"); RNA_def_property_flag(prop, PROP_PROPORTIONAL); @@ -2072,7 +2077,7 @@ static void rna_def_object(BlenderRNA *brna) RNA_def_property_ui_range(prop, 0.0f, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT); RNA_def_property_ui_text(prop, "Dimensions", "Absolute bounding box dimensions of the object"); RNA_def_property_update(prop, NC_OBJECT | ND_TRANSFORM, "rna_Object_internal_update"); - + /* delta transforms */ prop = RNA_def_property(srna, "delta_location", PROP_FLOAT, PROP_TRANSLATION); @@ -2080,20 +2085,20 @@ static void rna_def_object(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Delta Location", "Extra translation added to the location of the object"); RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT); RNA_def_property_update(prop, NC_OBJECT | ND_TRANSFORM, "rna_Object_internal_update"); - + prop = RNA_def_property(srna, "delta_rotation_euler", PROP_FLOAT, PROP_EULER); RNA_def_property_float_sdna(prop, NULL, "drot"); RNA_def_property_ui_text(prop, "Delta Rotation (Euler)", "Extra rotation added to the rotation of the object (when using Euler rotations)"); RNA_def_property_update(prop, NC_OBJECT | ND_TRANSFORM, "rna_Object_internal_update"); - + prop = RNA_def_property(srna, "delta_rotation_quaternion", PROP_FLOAT, PROP_QUATERNION); RNA_def_property_float_sdna(prop, NULL, "dquat"); RNA_def_property_float_array_default(prop, default_quat); RNA_def_property_ui_text(prop, "Delta Rotation (Quaternion)", "Extra rotation added to the rotation of the object (when using Quaternion rotations)"); RNA_def_property_update(prop, NC_OBJECT | ND_TRANSFORM, "rna_Object_internal_update"); - + #if 0 /* XXX not supported well yet... */ prop = RNA_def_property(srna, "delta_rotation_axis_angle", PROP_FLOAT, PROP_AXISANGLE); /* FIXME: this is not a single field any more! (drotAxis and drotAngle) */ @@ -2111,7 +2116,7 @@ static void rna_def_object(BlenderRNA *brna) RNA_def_property_float_array_default(prop, default_scale); RNA_def_property_ui_text(prop, "Delta Scale", "Extra scaling added to the scale of the object"); RNA_def_property_update(prop, NC_OBJECT | ND_TRANSFORM, "rna_Object_internal_update"); - + /* transform locks */ prop = RNA_def_property(srna, "lock_location", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "protectflag", OB_LOCK_LOCX); @@ -2126,7 +2131,7 @@ static void rna_def_object(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Lock Rotation", "Lock editing of rotation in the interface"); RNA_def_property_ui_icon(prop, ICON_UNLOCKED, 1); RNA_def_property_update(prop, NC_OBJECT | ND_TRANSFORM, "rna_Object_internal_update"); - + /* XXX this is sub-optimal - it really should be included above, * but due to technical reasons we can't do this! */ prop = RNA_def_property(srna, "lock_rotation_w", PROP_BOOLEAN, PROP_NONE); @@ -2204,14 +2209,14 @@ static void rna_def_object(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Vertex Groups", "Vertex groups of the object"); rna_def_object_vertex_groups(brna, prop); - + /* face maps */ prop = RNA_def_property(srna, "face_maps", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "fmaps", NULL); RNA_def_property_struct_type(prop, "FaceMap"); RNA_def_property_ui_text(prop, "Face Maps", "Maps of faces of the object"); rna_def_object_face_maps(brna, prop); - + /* empty */ prop = RNA_def_property(srna, "empty_draw_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "empty_drawtype"); @@ -2245,7 +2250,7 @@ static void rna_def_object(BlenderRNA *brna) RNA_def_property_int_sdna(prop, NULL, "index"); RNA_def_property_ui_text(prop, "Pass Index", "Index number for the \"Object Index\" render pass"); RNA_def_property_update(prop, NC_OBJECT, "rna_Object_internal_update_draw"); - + prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR); RNA_def_property_float_sdna(prop, NULL, "col"); RNA_def_property_ui_text(prop, "Color", "Object color and alpha, used when faces have the ObColor mode enabled"); @@ -2276,7 +2281,7 @@ static void rna_def_object(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Particle Systems", "Particle systems emitted from the object"); rna_def_object_particle_systems(brna, prop); - + prop = RNA_def_property(srna, "rigid_body", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "rigidbody_object"); RNA_def_property_struct_type(prop, "RigidBodyObject"); @@ -2286,7 +2291,7 @@ static void rna_def_object(BlenderRNA *brna) RNA_def_property_pointer_sdna(prop, NULL, "rigidbody_constraint"); RNA_def_property_struct_type(prop, "RigidBodyConstraint"); RNA_def_property_ui_text(prop, "Rigid Body Constraint", "Constraint constraining rigid bodies"); - + /* restrict */ prop = RNA_def_property(srna, "hide_render", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "restrictflag", OB_RESTRICT_RENDER); @@ -2302,17 +2307,12 @@ static void rna_def_object(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "duplicator_visibility_flag", OB_DUPLI_FLAG_VIEWPORT); RNA_def_property_ui_text(prop, "Display Duplicator", "Make duplicator visible in the viewport"); - prop = RNA_def_property(srna, "is_visible", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_funcs(prop, "rna_Object_is_visible_get", NULL); - RNA_def_property_ui_text(prop, "Visible", "Visible to camera rays, set only on objects evaluated by depsgraph"); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); - /* anim */ rna_def_animdata_common(srna); - + rna_def_animviz_common(srna); rna_def_motionpath_common(srna); - + /* slow parenting */ /* XXX: evil old crap */ prop = RNA_def_property(srna, "use_slow_parent", PROP_BOOLEAN, PROP_NONE); @@ -2321,7 +2321,7 @@ static void rna_def_object(BlenderRNA *brna) "Create a delay in the parent relationship (beware: this isn't renderfarm " "safe and may be invalid after jumping around the timeline)"); RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_internal_update"); - + prop = RNA_def_property(srna, "slow_parent_offset", PROP_FLOAT, PROP_NONE | PROP_UNIT_TIME); RNA_def_property_float_sdna(prop, NULL, "sf"); RNA_def_property_range(prop, MINAFRAMEF, MAXFRAMEF); @@ -2395,7 +2395,7 @@ static void rna_def_object(BlenderRNA *brna) prop = RNA_def_property(srna, "is_duplicator", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "transflag", OB_DUPLI); RNA_def_property_clear_flag(prop, PROP_EDITABLE); - + /* drawing */ prop = RNA_def_property(srna, "draw_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "dt"); @@ -2413,22 +2413,22 @@ static void rna_def_object(BlenderRNA *brna) RNA_def_property_enum_items(prop, boundtype_items); RNA_def_property_ui_text(prop, "Draw Bounds Type", "Object boundary display type"); RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); - + prop = RNA_def_property(srna, "show_name", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "dtx", OB_DRAWNAME); RNA_def_property_ui_text(prop, "Draw Name", "Display the object's name"); RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); - + prop = RNA_def_property(srna, "show_axis", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "dtx", OB_AXIS); RNA_def_property_ui_text(prop, "Draw Axes", "Display the object's origin and axes"); RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); - + prop = RNA_def_property(srna, "show_texture_space", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "dtx", OB_TEXSPACE); RNA_def_property_ui_text(prop, "Draw Texture Space", "Display the object's texture space"); RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); - + prop = RNA_def_property(srna, "show_wire", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "dtx", OB_DRAWWIRE); RNA_def_property_ui_text(prop, "Draw Wire", "Add the object's wireframe over solid drawing"); @@ -2444,13 +2444,13 @@ static void rna_def_object(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Draw Transparent", "Display material transparency in the object (unsupported for duplicator drawing)"); RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); - + prop = RNA_def_property(srna, "show_x_ray", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "dtx", OB_DRAWXRAY); RNA_def_property_ui_text(prop, "X-Ray", "Make the object draw in front of others (unsupported for duplicator drawing)"); RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); - + /* Grease Pencil */ prop = RNA_def_property(srna, "grease_pencil", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "gpd"); @@ -2458,7 +2458,7 @@ static void rna_def_object(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT); RNA_def_property_ui_text(prop, "Grease Pencil Data", "Grease Pencil data-block"); RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); - + /* pose */ prop = RNA_def_property(srna, "pose_library", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "poselib"); diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c index a837a2ff032..f86a3d8236a 100644 --- a/source/blender/makesrna/intern/rna_object_api.c +++ b/source/blender/makesrna/intern/rna_object_api.c @@ -211,14 +211,15 @@ static Mesh *rna_Object_to_mesh( static PointerRNA rna_Object_shape_key_add(Object *ob, bContext *C, ReportList *reports, const char *name, int from_mix) { + Main *bmain = CTX_data_main(C); KeyBlock *kb = NULL; - if ((kb = BKE_object_shapekey_insert(ob, name, from_mix))) { + if ((kb = BKE_object_shapekey_insert(bmain, ob, name, from_mix))) { PointerRNA keyptr; RNA_pointer_create((ID *)ob->data, &RNA_ShapeKey, kb, &keyptr); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); - + return keyptr; } else { @@ -355,7 +356,7 @@ static void rna_Object_closest_point_on_mesh( int *r_success, float r_location[3], float r_normal[3], int *r_index) { BVHTreeFromMesh treeData = {NULL}; - + if (ob->derivedFinal == NULL) { BKE_reportf(reports, RPT_ERROR, "Object '%s' has no mesh data to be used for finding nearest point", ob->id.name + 2); @@ -591,7 +592,7 @@ void RNA_api_object(StructRNA *srna) func = RNA_def_function(srna, "ray_cast", "rna_Object_ray_cast"); RNA_def_function_ui_description(func, "Cast a ray onto in object space"); RNA_def_function_flag(func, FUNC_USE_REPORTS); - + /* ray start and end */ parm = RNA_def_float_vector(func, "origin", 3, NULL, -FLT_MAX, FLT_MAX, "", "", -1e4, 1e4); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c index 4c09f7cf4cf..b79dee63136 100644 --- a/source/blender/makesrna/intern/rna_object_force.c +++ b/source/blender/makesrna/intern/rna_object_force.c @@ -219,7 +219,7 @@ static void rna_Cache_active_point_cache_index_range(PointerRNA *ptr, int *min, Object *ob = ptr->id.data; PointCache *cache = ptr->data; PTCacheID pid = BKE_ptcache_id_find(ob, NULL, cache); - + *min = 0; *max = 0; @@ -247,7 +247,7 @@ static void rna_Cache_active_point_cache_index_set(struct PointerRNA *ptr, int v Object *ob = ptr->id.data; PointCache *cache = ptr->data; PTCacheID pid = BKE_ptcache_id_find(ob, NULL, cache); - + if (pid.cache) { *(pid.cache_ptr) = BLI_findlink(pid.ptcaches, value); } @@ -527,13 +527,13 @@ static void rna_FieldSettings_dependency_update(Main *bmain, Scene *scene, Point static char *rna_FieldSettings_path(PointerRNA *ptr) { PartDeflect *pd = (PartDeflect *)ptr->data; - + /* Check through all possible places the settings can be to find the right one */ - + if (particle_id_check(ptr)) { /* particle system force field */ ParticleSettings *part = (ParticleSettings *)ptr->id.data; - + if (part->pd == pd) return BLI_sprintfN("force_field_1"); else if (part->pd2 == pd) @@ -542,7 +542,7 @@ static char *rna_FieldSettings_path(PointerRNA *ptr) else { /* object force field */ Object *ob = (Object *)ptr->id.data; - + if (ob->pd == pd) return BLI_sprintfN("field"); } @@ -580,11 +580,11 @@ static char *rna_EffectorWeight_path(PointerRNA *ptr) { EffectorWeights *ew = (EffectorWeights *)ptr->data; /* Check through all possible places the settings can be to find the right one */ - + if (particle_id_check(ptr)) { /* particle effector weights */ ParticleSettings *part = (ParticleSettings *)ptr->id.data; - + if (part->effector_weights == ew) return BLI_sprintfN("effector_weights"); } @@ -602,7 +602,7 @@ static char *rna_EffectorWeight_path(PointerRNA *ptr) return BLI_sprintfN("modifiers[\"%s\"].settings.effector_weights", name_esc); } } - + /* check cloth modifier */ md = (ModifierData *)modifiers_findByType(ob, eModifierType_Cloth); if (md) { @@ -613,7 +613,7 @@ static char *rna_EffectorWeight_path(PointerRNA *ptr) return BLI_sprintfN("modifiers[\"%s\"].settings.effector_weights", name_esc); } } - + /* check smoke modifier */ md = (ModifierData *)modifiers_findByType(ob, eModifierType_Smoke); if (md) { @@ -693,9 +693,9 @@ static const EnumPropertyItem *rna_Effector_shape_itemf(bContext *UNUSED(C), Poi if (particle_id_check(ptr)) return empty_shape_items; - + ob = (Object *)ptr->id.data; - + if (ob->type == OB_CURVE) { if (ob->pd->forcefield == PFIELD_VORTEX) return curve_vortex_shape_items; @@ -880,44 +880,44 @@ static void rna_def_collision(BlenderRNA *brna) RNA_def_struct_sdna(srna, "PartDeflect"); RNA_def_struct_path_func(srna, "rna_CollisionSettings_path"); RNA_def_struct_ui_text(srna, "Collision Settings", "Collision settings for object in physics simulation"); - + prop = RNA_def_property(srna, "use", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "deflect", 1); RNA_def_property_ui_text(prop, "Enabled", "Enable this objects as a collider for physics systems"); RNA_def_property_update(prop, 0, "rna_CollisionSettings_dependency_update"); - + /* Particle Interaction */ - + prop = RNA_def_property(srna, "damping_factor", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "pdef_damp"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Damping Factor", "Amount of damping during particle collision"); RNA_def_property_update(prop, 0, "rna_CollisionSettings_update"); - + prop = RNA_def_property(srna, "damping_random", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "pdef_rdamp"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Random Damping", "Random variation of damping"); RNA_def_property_update(prop, 0, "rna_CollisionSettings_update"); - + prop = RNA_def_property(srna, "friction_factor", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "pdef_frict"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Friction Factor", "Amount of friction during particle collision"); RNA_def_property_update(prop, 0, "rna_CollisionSettings_update"); - + prop = RNA_def_property(srna, "friction_random", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "pdef_rfrict"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Random Friction", "Random variation of friction"); RNA_def_property_update(prop, 0, "rna_CollisionSettings_update"); - + prop = RNA_def_property(srna, "permeability", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "pdef_perm"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Permeability", "Chance that the particle will pass through the mesh"); RNA_def_property_update(prop, 0, "rna_CollisionSettings_update"); - + prop = RNA_def_property(srna, "use_particle_kill", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", PDEFLE_KILL_PART); RNA_def_property_ui_text(prop, "Kill Particles", "Kill collided particles"); @@ -928,21 +928,21 @@ static void rna_def_collision(BlenderRNA *brna) RNA_def_property_range(prop, 0.0f, 10.0f); RNA_def_property_ui_text(prop, "Stickiness", "Amount of stickiness to surface collision"); RNA_def_property_update(prop, 0, "rna_CollisionSettings_update"); - + /* Soft Body and Cloth Interaction */ - + prop = RNA_def_property(srna, "thickness_inner", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "pdef_sbift"); RNA_def_property_range(prop, 0.001f, 1.0f); RNA_def_property_ui_text(prop, "Inner Thickness", "Inner face thickness (only used by softbodies)"); RNA_def_property_update(prop, 0, "rna_CollisionSettings_update"); - + prop = RNA_def_property(srna, "thickness_outer", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "pdef_sboft"); RNA_def_property_range(prop, 0.001f, 1.0f); RNA_def_property_ui_text(prop, "Outer Thickness", "Outer face thickness"); RNA_def_property_update(prop, 0, "rna_CollisionSettings_update"); - + prop = RNA_def_property(srna, "damping", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "pdef_sbdamp"); RNA_def_property_range(prop, 0.0f, 1.0f); @@ -973,7 +973,7 @@ static void rna_def_effector_weight(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", EFF_WEIGHT_DO_HAIR); RNA_def_property_ui_text(prop, "Use For Growing Hair", "Use force fields when growing hair"); RNA_def_property_update(prop, 0, "rna_EffectorWeight_update"); - + /* General */ prop = RNA_def_property(srna, "group", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "Collection"); @@ -1092,7 +1092,7 @@ static void rna_def_field(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + static const EnumPropertyItem field_type_items[] = { {0, "NONE", 0, "None", ""}, {PFIELD_FORCE, "FORCE", ICON_FORCE_FORCE, "Force", "Radial field toward the center of object"}, @@ -1122,7 +1122,7 @@ static void rna_def_field(BlenderRNA *brna) {PFIELD_FALL_CONE, "CONE", 0, "Cone", ""}, {0, NULL, 0, NULL, NULL} }; - + static const EnumPropertyItem texture_items[] = { {PFIELD_TEX_RGB, "RGB", 0, "RGB", ""}, {PFIELD_TEX_GRAD, "GRADIENT", 0, "Gradient", ""}, @@ -1136,7 +1136,7 @@ static void rna_def_field(BlenderRNA *brna) {PFIELD_Z_NEG, "NEGATIVE", 0, "-Z", ""}, {0, NULL, 0, NULL, NULL} }; - + static const EnumPropertyItem guide_kink_items[] = { {0, "NONE", 0, "Nothing", ""}, {1, "CURL", 0, "Curl", ""}, @@ -1153,9 +1153,9 @@ static void rna_def_field(BlenderRNA *brna) RNA_def_struct_path_func(srna, "rna_FieldSettings_path"); RNA_def_struct_ui_text(srna, "Field Settings", "Field settings for an object in physics simulation"); RNA_def_struct_ui_icon(srna, ICON_PHYSICS); - + /* Enums */ - + prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "forcefield"); RNA_def_property_enum_items(prop, field_type_items); @@ -1168,13 +1168,13 @@ static void rna_def_field(BlenderRNA *brna) RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_Effector_shape_itemf"); RNA_def_property_ui_text(prop, "Shape", "Which direction is used to calculate the effector force"); RNA_def_property_update(prop, 0, "rna_FieldSettings_shape_update"); - + prop = RNA_def_property(srna, "falloff_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "falloff"); RNA_def_property_enum_items(prop, falloff_items); RNA_def_property_ui_text(prop, "Fall-Off", ""); RNA_def_property_update(prop, 0, "rna_FieldSettings_update"); - + prop = RNA_def_property(srna, "texture_mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "tex_mode"); RNA_def_property_enum_items(prop, texture_items); @@ -1188,9 +1188,9 @@ static void rna_def_field(BlenderRNA *brna) RNA_def_property_enum_items(prop, zdirection_items); RNA_def_property_ui_text(prop, "Z Direction", "Effect in full or only positive/negative Z direction"); RNA_def_property_update(prop, 0, "rna_FieldSettings_update"); - + /* Float */ - + prop = RNA_def_property(srna, "strength", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "f_strength"); RNA_def_property_range(prop, -FLT_MAX, FLT_MAX); @@ -1242,38 +1242,38 @@ static void rna_def_field(BlenderRNA *brna) RNA_def_property_range(prop, 0.0f, 1000.0f); RNA_def_property_ui_text(prop, "Rest Length", "Rest length of the harmonic force"); RNA_def_property_update(prop, 0, "rna_FieldSettings_update"); - + prop = RNA_def_property(srna, "falloff_power", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "f_power"); RNA_def_property_range(prop, 0.0f, 10.0f); RNA_def_property_ui_text(prop, "Falloff Power", ""); RNA_def_property_update(prop, 0, "rna_FieldSettings_update"); - + prop = RNA_def_property(srna, "distance_min", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "mindist"); RNA_def_property_range(prop, 0.0f, 1000.0f); RNA_def_property_ui_text(prop, "Minimum Distance", "Minimum distance for the field's fall-off"); RNA_def_property_update(prop, 0, "rna_FieldSettings_update"); - + prop = RNA_def_property(srna, "distance_max", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "maxdist"); RNA_def_property_range(prop, 0.0f, FLT_MAX); RNA_def_property_ui_range(prop, 0.0f, 1000.0f, 1.0f, 3); RNA_def_property_ui_text(prop, "Maximum Distance", "Maximum distance for the field to work"); RNA_def_property_update(prop, 0, "rna_FieldSettings_update"); - + prop = RNA_def_property(srna, "radial_min", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "minrad"); RNA_def_property_range(prop, 0.0f, 1000.0f); RNA_def_property_ui_text(prop, "Minimum Radial Distance", "Minimum radial distance for the field's fall-off"); RNA_def_property_update(prop, 0, "rna_FieldSettings_update"); - + prop = RNA_def_property(srna, "radial_max", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "maxrad"); RNA_def_property_range(prop, 0.0f, 1000.0f); RNA_def_property_ui_text(prop, "Maximum Radial Distance", "Maximum radial distance for the field to work"); RNA_def_property_update(prop, 0, "rna_FieldSettings_update"); - + prop = RNA_def_property(srna, "radial_falloff", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "f_power_r"); RNA_def_property_range(prop, 0.0f, 10.0f); @@ -1286,7 +1286,7 @@ static void rna_def_field(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Nabla", "Defines size of derivative offset used for calculating gradient and curl"); RNA_def_property_update(prop, 0, "rna_FieldSettings_update"); - + prop = RNA_def_property(srna, "noise", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "f_noise"); RNA_def_property_range(prop, 0.0f, 10.0f); @@ -1299,23 +1299,23 @@ static void rna_def_field(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_FieldSettings_update"); /* Boolean */ - + prop = RNA_def_property(srna, "use_min_distance", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", PFIELD_USEMIN); RNA_def_property_ui_text(prop, "Use Min", "Use a minimum distance for the field's fall-off"); RNA_def_property_update(prop, 0, "rna_FieldSettings_update"); - + prop = RNA_def_property(srna, "use_max_distance", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", PFIELD_USEMAX); RNA_def_property_ui_text(prop, "Use Max", "Use a maximum distance for the field to work"); RNA_def_property_update(prop, 0, "rna_FieldSettings_update"); - + prop = RNA_def_property(srna, "use_radial_min", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", PFIELD_USEMINR); RNA_def_property_ui_text(prop, "Use Min", "Use a minimum radial distance for the field's fall-off"); /* "Use a minimum angle for the field's fall-off" */ RNA_def_property_update(prop, 0, "rna_FieldSettings_update"); - + prop = RNA_def_property(srna, "use_radial_max", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", PFIELD_USEMAXR); RNA_def_property_ui_text(prop, "Use Max", "Use a maximum radial distance for the field to work"); @@ -1331,12 +1331,12 @@ static void rna_def_field(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", PFIELD_GLOBAL_CO); RNA_def_property_ui_text(prop, "Use Global Coordinates", "Use effector/global coordinates for turbulence"); RNA_def_property_update(prop, 0, "rna_FieldSettings_update"); - + prop = RNA_def_property(srna, "use_2d_force", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", PFIELD_TEX_2D); RNA_def_property_ui_text(prop, "2D", "Apply force only in 2D"); RNA_def_property_update(prop, 0, "rna_FieldSettings_update"); - + prop = RNA_def_property(srna, "use_root_coords", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", PFIELD_TEX_ROOTCO); RNA_def_property_ui_text(prop, "Root Texture Coordinates", "Texture coordinates from root particle locations"); @@ -1371,9 +1371,9 @@ static void rna_def_field(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Gravity Falloff", "Multiply force by 1/distance²"); RNA_def_property_update(prop, 0, "rna_FieldSettings_update"); - + /* Pointer */ - + prop = RNA_def_property(srna, "texture", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "tex"); RNA_def_property_flag(prop, PROP_EDITABLE); @@ -1385,9 +1385,9 @@ static void rna_def_field(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Domain Object", "Select domain object of the smoke simulation"); RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_update(prop, 0, "rna_FieldSettings_update"); - + /********** Curve Guide Field Settings **********/ - + prop = RNA_def_property(srna, "guide_minimum", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "f_strength"); RNA_def_property_range(prop, 0.0f, 1000.0f); @@ -1409,29 +1409,29 @@ static void rna_def_field(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", PFIELD_GUIDE_PATH_WEIGHT); RNA_def_property_ui_text(prop, "Weights", "Use curve weights to influence the particle influence along the curve"); RNA_def_property_update(prop, 0, "rna_FieldSettings_update"); - + /* Clump Settings */ - + prop = RNA_def_property(srna, "guide_clump_amount", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "clump_fac"); RNA_def_property_range(prop, -1.0f, 1.0f); RNA_def_property_ui_text(prop, "Amount", "Amount of clumping"); RNA_def_property_update(prop, 0, "rna_FieldSettings_update"); - + prop = RNA_def_property(srna, "guide_clump_shape", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "clump_pow"); RNA_def_property_range(prop, -0.999f, 0.999f); RNA_def_property_ui_text(prop, "Shape", "Shape of clumping"); RNA_def_property_update(prop, 0, "rna_FieldSettings_update"); - + /* Kink Settings */ - + prop = RNA_def_property(srna, "guide_kink_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "kink"); RNA_def_property_enum_items(prop, guide_kink_items); RNA_def_property_ui_text(prop, "Kink", "Type of periodic offset on the curve"); RNA_def_property_update(prop, 0, "rna_FieldSettings_update"); - + prop = RNA_def_property(srna, "guide_kink_axis", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "kink_axis"); RNA_def_property_enum_items(prop, rna_enum_axis_xyz_items); @@ -1443,13 +1443,13 @@ static void rna_def_field(BlenderRNA *brna) RNA_def_property_range(prop, 0.0f, 10.0f); RNA_def_property_ui_text(prop, "Frequency", "The frequency of the offset (1/total length)"); RNA_def_property_update(prop, 0, "rna_FieldSettings_update"); - + prop = RNA_def_property(srna, "guide_kink_shape", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "kink_shape"); RNA_def_property_range(prop, -0.999f, 0.999f); RNA_def_property_ui_text(prop, "Shape", "Adjust the offset to the beginning/end"); RNA_def_property_update(prop, 0, "rna_FieldSettings_update"); - + prop = RNA_def_property(srna, "guide_kink_amplitude", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "kink_amp"); RNA_def_property_range(prop, 0.0f, 10.0f); @@ -1464,7 +1464,7 @@ static void rna_def_softbody(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + static const EnumPropertyItem collision_type_items[] = { {SBC_MODE_MANUAL, "MANUAL", 0, "Manual", "Manual adjust"}, {SBC_MODE_AVG, "AVERAGE", 0, "Average", "Average Spring length * Ball Size"}, @@ -1473,7 +1473,7 @@ static void rna_def_softbody(BlenderRNA *brna) {SBC_MODE_AVGMINMAX, "MINMAX", 0, "AvMinMax", "(Min+Max)/2 * Ball Size"}, {0, NULL, 0, NULL, NULL} }; - + static const EnumPropertyItem aerodynamics_type[] = { {0, "SIMPLE", 0, "Simple", "Edges receive a drag force from surrounding media"}, {1, "LIFT_FORCE", 0, "Lift Force", "Edges receive a lift force when passing through surrounding media"}, @@ -1484,42 +1484,42 @@ static void rna_def_softbody(BlenderRNA *brna) RNA_def_struct_sdna(srna, "SoftBody"); RNA_def_struct_path_func(srna, "rna_SoftBodySettings_path"); RNA_def_struct_ui_text(srna, "Soft Body Settings", "Soft body simulation settings for an object"); - + /* General Settings */ - + prop = RNA_def_property(srna, "friction", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "mediafrict"); RNA_def_property_range(prop, 0.0f, 50.0f); RNA_def_property_ui_text(prop, "Friction", "General media friction for point movements"); RNA_def_property_update(prop, 0, "rna_softbody_update"); - + prop = RNA_def_property(srna, "mass", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "nodemass"); RNA_def_property_range(prop, 0.0f, 50000.0f); RNA_def_property_ui_text(prop, "Mass", "General Mass value"); RNA_def_property_update(prop, 0, "rna_softbody_update"); - + prop = RNA_def_property(srna, "vertex_group_mass", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "namedVG_Mass"); RNA_def_property_ui_text(prop, "Mass Vertex Group", "Control point mass values"); RNA_def_property_string_funcs(prop, NULL, NULL, "rna_SoftBodySettings_mass_vgroup_set"); RNA_def_property_update(prop, 0, "rna_softbody_update"); - + /* no longer used */ prop = RNA_def_property(srna, "gravity", PROP_FLOAT, PROP_ACCELERATION); RNA_def_property_float_sdna(prop, NULL, "grav"); RNA_def_property_range(prop, -10.0f, 10.0f); RNA_def_property_ui_text(prop, "Gravitation", "Apply gravitation to point movement"); RNA_def_property_update(prop, 0, "rna_softbody_update"); - + prop = RNA_def_property(srna, "speed", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "physics_speed"); RNA_def_property_range(prop, 0.01f, 100.0f); RNA_def_property_ui_text(prop, "Speed", "Tweak timing for physics to control frequency and speed"); RNA_def_property_update(prop, 0, "rna_softbody_update"); - + /* Goal */ - + prop = RNA_def_property(srna, "vertex_group_goal", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "vertgroup"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); /* not impossible .. but not supported yet */ @@ -1527,7 +1527,7 @@ static void rna_def_softbody(BlenderRNA *brna) "rna_SoftBodySettings_goal_vgroup_length", "rna_SoftBodySettings_goal_vgroup_set"); RNA_def_property_ui_text(prop, "Goal Vertex Group", "Control point weight values"); - + prop = RNA_def_property(srna, "goal_min", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "mingoal"); RNA_def_property_range(prop, 0.0f, 1.0f); @@ -1547,104 +1547,104 @@ static void rna_def_softbody(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Goal Default", "Default Goal (vertex target position) value"); RNA_def_property_update(prop, 0, "rna_softbody_update"); - + prop = RNA_def_property(srna, "goal_spring", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "goalspring"); RNA_def_property_range(prop, 0.0f, 0.999f); RNA_def_property_ui_text(prop, "Goal Stiffness", "Goal (vertex target position) spring stiffness"); RNA_def_property_update(prop, 0, "rna_softbody_update"); - + prop = RNA_def_property(srna, "goal_friction", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "goalfrict"); RNA_def_property_range(prop, 0.0f, 50.0f); RNA_def_property_ui_text(prop, "Goal Damping", "Goal (vertex target position) friction"); RNA_def_property_update(prop, 0, "rna_softbody_update"); - + /* Edge Spring Settings */ - + prop = RNA_def_property(srna, "pull", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "inspring"); RNA_def_property_range(prop, 0.0f, 0.999f); RNA_def_property_ui_text(prop, "Pull", "Edge spring stiffness when longer than rest length"); RNA_def_property_update(prop, 0, "rna_softbody_update"); - + prop = RNA_def_property(srna, "push", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "inpush"); RNA_def_property_range(prop, 0.0f, 0.999f); RNA_def_property_ui_text(prop, "Push", "Edge spring stiffness when shorter than rest length"); RNA_def_property_update(prop, 0, "rna_softbody_update"); - + prop = RNA_def_property(srna, "damping", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "infrict"); RNA_def_property_range(prop, 0.0f, 50.0f); RNA_def_property_ui_text(prop, "Damp", "Edge spring friction"); RNA_def_property_update(prop, 0, "rna_softbody_update"); - + prop = RNA_def_property(srna, "spring_length", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "springpreload"); RNA_def_property_range(prop, 0.0f, 200.0f); RNA_def_property_ui_text(prop, "view_layer", "Alter spring length to shrink/blow up (unit %) 0 to disable"); RNA_def_property_update(prop, 0, "rna_softbody_update"); - + prop = RNA_def_property(srna, "aero", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "aeroedge"); RNA_def_property_range(prop, 0.0f, 30000.0f); RNA_def_property_ui_text(prop, "Aero", "Make edges 'sail'"); RNA_def_property_update(prop, 0, "rna_softbody_update"); - + prop = RNA_def_property(srna, "plastic", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "plastic"); RNA_def_property_range(prop, 0.0f, 100.0f); RNA_def_property_ui_text(prop, "Plastic", "Permanent deform"); RNA_def_property_update(prop, 0, "rna_softbody_update"); - + prop = RNA_def_property(srna, "bend", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "secondspring"); RNA_def_property_range(prop, 0.0f, 10.0f); RNA_def_property_ui_text(prop, "Bending", "Bending Stiffness"); RNA_def_property_update(prop, 0, "rna_softbody_update"); - + prop = RNA_def_property(srna, "shear", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "shearstiff"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Shear", "Shear Stiffness"); - + prop = RNA_def_property(srna, "vertex_group_spring", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "namedVG_Spring_K"); RNA_def_property_ui_text(prop, "Spring Vertex Group", "Control point spring strength values"); RNA_def_property_string_funcs(prop, NULL, NULL, "rna_SoftBodySettings_spring_vgroup_set"); RNA_def_property_update(prop, 0, "rna_softbody_update"); - + /* Collision */ - + prop = RNA_def_property(srna, "collision_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "sbc_mode"); RNA_def_property_enum_items(prop, collision_type_items); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_ui_text(prop, "Collision Type", "Choose Collision Type"); RNA_def_property_update(prop, 0, "rna_softbody_update"); - + prop = RNA_def_property(srna, "ball_size", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "colball"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); /* code is not ready for that yet */ RNA_def_property_range(prop, -10.0f, 10.0f); RNA_def_property_ui_text(prop, "Ball Size", "Absolute ball size or factor if not manually adjusted"); RNA_def_property_update(prop, 0, "rna_softbody_update"); - + prop = RNA_def_property(srna, "ball_stiff", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "ballstiff"); RNA_def_property_range(prop, 0.001f, 100.0f); RNA_def_property_ui_text(prop, "Ball Size", "Ball inflating pressure"); RNA_def_property_update(prop, 0, "rna_softbody_update"); - + prop = RNA_def_property(srna, "ball_damp", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "balldamp"); RNA_def_property_range(prop, 0.001f, 1.0f); RNA_def_property_ui_text(prop, "Ball Size", "Blending to inelastic collision"); RNA_def_property_update(prop, 0, "rna_softbody_update"); - + /* Solver */ - + prop = RNA_def_property(srna, "error_threshold", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "rklimit"); RNA_def_property_range(prop, 0.001f, 10.0f); @@ -1652,25 +1652,25 @@ static void rna_def_softbody(BlenderRNA *brna) "The Runge-Kutta ODE solver error limit, low value gives more precision, " "high values speed"); RNA_def_property_update(prop, 0, "rna_softbody_update"); - + prop = RNA_def_property(srna, "step_min", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "minloops"); RNA_def_property_range(prop, 0, 30000); RNA_def_property_ui_text(prop, "Min Step", "Minimal # solver steps/frame"); RNA_def_property_update(prop, 0, "rna_softbody_update"); - + prop = RNA_def_property(srna, "step_max", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "maxloops"); RNA_def_property_range(prop, 0, 30000); RNA_def_property_ui_text(prop, "Max Step", "Maximal # solver steps/frame"); RNA_def_property_update(prop, 0, "rna_softbody_update"); - + prop = RNA_def_property(srna, "choke", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "choke"); RNA_def_property_range(prop, 0, 100); RNA_def_property_ui_text(prop, "Choke", "'Viscosity' inside collision target"); RNA_def_property_update(prop, 0, "rna_softbody_update"); - + prop = RNA_def_property(srna, "fuzzy", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "fuzzyness"); RNA_def_property_range(prop, 1, 100); @@ -1678,16 +1678,16 @@ static void rna_def_softbody(BlenderRNA *brna) "Fuzziness while on collision, high values make collision handling faster " "but less stable"); RNA_def_property_update(prop, 0, "rna_softbody_update"); - + prop = RNA_def_property(srna, "use_auto_step", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "solverflags", SBSO_OLDERR); RNA_def_property_ui_text(prop, "V", "Use velocities for automagic step sizes"); RNA_def_property_update(prop, 0, "rna_softbody_update"); - + prop = RNA_def_property(srna, "use_diagnose", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "solverflags", SBSO_MONITOR); RNA_def_property_ui_text(prop, "Print Performance to Console", "Turn on SB diagnose console prints"); - + prop = RNA_def_property(srna, "use_estimate_matrix", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "solverflags", SBSO_ESTIMATEIPO); RNA_def_property_ui_text(prop, "Estimate matrix", "Estimate matrix... split to COM, ROT, SCALE"); @@ -1717,44 +1717,44 @@ static void rna_def_softbody(BlenderRNA *brna) /* Flags */ - + prop = RNA_def_property(srna, "use_goal", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_funcs(prop, "rna_SoftBodySettings_use_goal_get", "rna_SoftBodySettings_use_goal_set"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_ui_text(prop, "Use Goal", "Define forces for vertices to stick to animated position"); RNA_def_property_update(prop, 0, "rna_softbody_update"); - + prop = RNA_def_property(srna, "use_edges", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_funcs(prop, "rna_SoftBodySettings_use_edges_get", "rna_SoftBodySettings_use_edges_set"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_ui_text(prop, "Use Edges", "Use Edges as springs"); RNA_def_property_update(prop, 0, "rna_softbody_update"); - + prop = RNA_def_property(srna, "use_stiff_quads", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_funcs(prop, "rna_SoftBodySettings_stiff_quads_get", "rna_SoftBodySettings_stiff_quads_set"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_ui_text(prop, "Stiff Quads", "Add diagonal springs on 4-gons"); RNA_def_property_update(prop, 0, "rna_softbody_update"); - + prop = RNA_def_property(srna, "use_edge_collision", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_funcs(prop, "rna_SoftBodySettings_edge_collision_get", "rna_SoftBodySettings_edge_collision_set"); RNA_def_property_ui_text(prop, "Edge Collision", "Edges collide too"); RNA_def_property_update(prop, 0, "rna_softbody_update"); - + prop = RNA_def_property(srna, "use_face_collision", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_funcs(prop, "rna_SoftBodySettings_face_collision_get", "rna_SoftBodySettings_face_collision_set"); RNA_def_property_ui_text(prop, "Face Collision", "Faces collide too, can be very slow"); RNA_def_property_update(prop, 0, "rna_softbody_update"); - + prop = RNA_def_property(srna, "aerodynamics_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, aerodynamics_type); RNA_def_property_enum_funcs(prop, "rna_SoftBodySettings_new_aero_get", "rna_SoftBodySettings_new_aero_set", NULL); RNA_def_property_ui_text(prop, "Aerodynamics Type", "Method of calculating aerodynamic interaction"); RNA_def_property_update(prop, 0, "rna_softbody_update"); - + prop = RNA_def_property(srna, "use_self_collision", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_funcs(prop, "rna_SoftBodySettings_self_collision_get", "rna_SoftBodySettings_self_collision_set"); diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c index 844e61966bb..573bbb5345b 100644 --- a/source/blender/makesrna/intern/rna_particle.c +++ b/source/blender/makesrna/intern/rna_particle.c @@ -302,7 +302,7 @@ static void rna_Particle_uv_on_emitter(ParticleData *particle, ReportList *repor /* get uvco */ if (r_uv && ELEM(from, PART_FROM_FACE, PART_FROM_VOLUME)) { - + if (num != DMCACHE_NOTFOUND) { MFace *mface; MTFace *mtface; @@ -342,7 +342,7 @@ static void rna_ParticleSystem_co_hair(ParticleSystem *particlesystem, Object *o if (part == NULL || pars == NULL) return; - + if (part->ren_as == PART_DRAW_OB || part->ren_as == PART_DRAW_GR || part->ren_as == PART_DRAW_NOT) return; @@ -689,7 +689,7 @@ static ParticleSystem *rna_particle_system_for_target(Object *ob, ParticleTarget for (pt = psys->targets.first; pt; pt = pt->next) if (pt == target) return psys; - + return NULL; } @@ -717,7 +717,7 @@ static void rna_Particle_target_reset(Main *bmain, Scene *UNUSED(scene), Pointer else pt->flag &= ~PTARGET_VALID; } - + psys->recalc = PSYS_RECALC_RESET; DEG_id_tag_update(&ob->id, OB_RECALC_DATA); @@ -733,7 +733,7 @@ static void rna_Particle_target_redo(Main *UNUSED(bmain), Scene *UNUSED(scene), Object *ob = (Object *)ptr->id.data; ParticleTarget *pt = (ParticleTarget *)ptr->data; ParticleSystem *psys = rna_particle_system_for_target(ob, pt); - + psys->recalc = PSYS_RECALC_REDO; DEG_id_tag_update(&ob->id, OB_RECALC_DATA); @@ -745,7 +745,7 @@ static void rna_Particle_hair_dynamics_update(Main *bmain, Scene *scene, Pointer { Object *ob = (Object *)ptr->id.data; ParticleSystem *psys = (ParticleSystem *)ptr->data; - + if (psys && !psys->clmd) { psys->clmd = (ClothModifierData *)modifier_new(eModifierType_Cloth); psys->clmd->sim_parms->goalspring = 0.0f; @@ -907,26 +907,26 @@ static int rna_PartSettings_is_fluid_get(PointerRNA *ptr) static void rna_ParticleSettings_use_clump_curve_update(Main *bmain, Scene *scene, PointerRNA *ptr) { ParticleSettings *part = ptr->data; - + if (part->child_flag & PART_CHILD_USE_CLUMP_CURVE) { if (!part->clumpcurve) { BKE_particlesettings_clump_curve_init(part); } } - + rna_Particle_redo_child(bmain, scene, ptr); } static void rna_ParticleSettings_use_roughness_curve_update(Main *bmain, Scene *scene, PointerRNA *ptr) { ParticleSettings *part = ptr->data; - + if (part->child_flag & PART_CHILD_USE_ROUGH_CURVE) { if (!part->roughcurve) { BKE_particlesettings_rough_curve_init(part); } } - + rna_Particle_redo_child(bmain, scene, ptr); } @@ -1014,7 +1014,7 @@ static void rna_ParticleTarget_name_get(PointerRNA *ptr, char *str) Object *ob = (Object *) ptr->id.data; psys = BLI_findlink(&ob->particlesystem, pt->psys - 1); } - + if (psys) { if (pt->ob) sprintf(str, "%s: %s", pt->ob->id.name + 2, psys->name); @@ -1047,10 +1047,10 @@ static int particle_id_check(PointerRNA *ptr) static char *rna_SPHFluidSettings_path(PointerRNA *ptr) { SPHFluidSettings *fluid = (SPHFluidSettings *)ptr->data; - + if (particle_id_check(ptr)) { ParticleSettings *part = (ParticleSettings *)ptr->id.data; - + if (part->fluid == fluid) return BLI_sprintfN("fluid"); } @@ -1192,7 +1192,7 @@ static PointerRNA rna_Particle_field1_get(PointerRNA *ptr) /* weak */ if (!part->pd) part->pd = object_add_collision_fields(0); - + return rna_pointer_inherit_refine(ptr, &RNA_FieldSettings, part->pd); } @@ -1203,7 +1203,7 @@ static PointerRNA rna_Particle_field2_get(PointerRNA *ptr) /* weak */ if (!part->pd2) part->pd2 = object_add_collision_fields(0); - + return rna_pointer_inherit_refine(ptr, &RNA_FieldSettings, part->pd2); } @@ -1356,7 +1356,7 @@ static void rna_def_particle_hair_key(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Location (Object Space)", "Location of the hair key in object space"); RNA_def_property_float_funcs(prop, "rna_ParticleHairKey_location_object_get", "rna_ParticleHairKey_location_object_set", NULL); - + prop = RNA_def_property(srna, "co_local", PROP_FLOAT, PROP_TRANSLATION); RNA_def_property_float_sdna(prop, NULL, "co"); RNA_def_property_ui_text(prop, "Location", @@ -1742,7 +1742,7 @@ static void rna_def_particle_settings_mtex(BlenderRNA *brna) {MTEX_SPHERE, "SPHERE", 0, "Sphere", "Map with Z as central axis"}, {0, NULL, 0, NULL, NULL} }; - + static const EnumPropertyItem prop_x_mapping_items[] = { {0, "NONE", 0, "None", ""}, {1, "X", 0, "X", ""}, @@ -1750,7 +1750,7 @@ static void rna_def_particle_settings_mtex(BlenderRNA *brna) {3, "Z", 0, "Z", ""}, {0, NULL, 0, NULL, NULL} }; - + static const EnumPropertyItem prop_y_mapping_items[] = { {0, "NONE", 0, "None", ""}, {1, "X", 0, "X", ""}, @@ -1758,7 +1758,7 @@ static void rna_def_particle_settings_mtex(BlenderRNA *brna) {3, "Z", 0, "Z", ""}, {0, NULL, 0, NULL, NULL} }; - + static const EnumPropertyItem prop_z_mapping_items[] = { {0, "NONE", 0, "None", ""}, {1, "X", 0, "X", ""}, @@ -1796,19 +1796,19 @@ static void rna_def_particle_settings_mtex(BlenderRNA *brna) RNA_def_property_enum_items(prop, prop_x_mapping_items); RNA_def_property_ui_text(prop, "X Mapping", ""); RNA_def_property_update(prop, 0, "rna_Particle_reset"); - + prop = RNA_def_property(srna, "mapping_y", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "projy"); RNA_def_property_enum_items(prop, prop_y_mapping_items); RNA_def_property_ui_text(prop, "Y Mapping", ""); RNA_def_property_update(prop, 0, "rna_Particle_reset"); - + prop = RNA_def_property(srna, "mapping_z", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "projz"); RNA_def_property_enum_items(prop, prop_z_mapping_items); RNA_def_property_ui_text(prop, "Z Mapping", ""); RNA_def_property_update(prop, 0, "rna_Particle_reset"); - + prop = RNA_def_property(srna, "mapping", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, prop_mapping_items); RNA_def_property_ui_text(prop, "Mapping", ""); @@ -3073,7 +3073,7 @@ static void rna_def_particle_settings(BlenderRNA *brna) RNA_def_property_ui_range(prop, 1.0f, 100.0f, 0.1, 3); RNA_def_property_ui_text(prop, "Loop count", "Number of times the keys are looped"); RNA_def_property_update(prop, 0, "rna_Particle_redo"); - + /* modified dm support */ prop = RNA_def_property(srna, "use_modifier_stack", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "use_modifier_stack", 0); @@ -3124,7 +3124,7 @@ static void rna_def_particle_settings(BlenderRNA *brna) RNA_def_property_struct_type(prop, "BoidSettings"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Boid Settings", ""); - + /* Fluid particles */ prop = RNA_def_property(srna, "fluid", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "SPHFluidSettings"); @@ -3136,7 +3136,7 @@ static void rna_def_particle_settings(BlenderRNA *brna) RNA_def_property_struct_type(prop, "EffectorWeights"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Effector Weights", ""); - + /* animation here? */ rna_def_animdata_common(srna); @@ -3634,7 +3634,7 @@ void RNA_def_particle(BlenderRNA *brna) rna_def_fluid_settings(brna); rna_def_particle_hair_key(brna); rna_def_particle_key(brna); - + rna_def_child_particle(brna); rna_def_particle(brna); rna_def_particle_dupliweight(brna); diff --git a/source/blender/makesrna/intern/rna_pose.c b/source/blender/makesrna/intern/rna_pose.c index fb0f59a7977..6a5f6485029 100644 --- a/source/blender/makesrna/intern/rna_pose.c +++ b/source/blender/makesrna/intern/rna_pose.c @@ -176,11 +176,11 @@ static void rna_bone_group_remove(ID *id, bPose *pose, ReportList *reports, Poin void rna_ActionGroup_colorset_set(PointerRNA *ptr, int value) { bActionGroup *grp = ptr->data; - + /* ensure only valid values get set */ if ((value >= -1) && (value < 21)) { grp->customCol = value; - + /* sync colors stored with theme colors based on the index specified */ action_group_colors_sync(grp, NULL); } @@ -189,7 +189,7 @@ void rna_ActionGroup_colorset_set(PointerRNA *ptr, int value) int rna_ActionGroup_is_custom_colorset_get(PointerRNA *ptr) { bActionGroup *grp = ptr->data; - + return (grp->customCol < 0); } @@ -240,9 +240,9 @@ static void rna_Pose_ik_solver_update(Main *bmain, Scene *UNUSED(scene), Pointer BKE_pose_tag_recalc(bmain, pose); /* checks & sorts pose channels */ DEG_relations_tag_update(bmain); - + BKE_pose_update_constraint_flags(pose); - + object_test_constraints(bmain, ob); DEG_id_tag_update(&ob->id, OB_RECALC_DATA | OB_RECALC_OB); @@ -252,7 +252,7 @@ static void rna_Pose_ik_solver_update(Main *bmain, Scene *UNUSED(scene), Pointer static void rna_PoseChannel_rotation_axis_angle_get(PointerRNA *ptr, float *value) { bPoseChannel *pchan = ptr->data; - + /* for now, assume that rotation mode is axis-angle */ value[0] = pchan->rotAngle; copy_v3_v3(&value[1], pchan->rotAxis); @@ -262,22 +262,22 @@ static void rna_PoseChannel_rotation_axis_angle_get(PointerRNA *ptr, float *valu static void rna_PoseChannel_rotation_axis_angle_set(PointerRNA *ptr, const float *value) { bPoseChannel *pchan = ptr->data; - + /* for now, assume that rotation mode is axis-angle */ pchan->rotAngle = value[0]; copy_v3_v3(pchan->rotAxis, &value[1]); - + /* TODO: validate axis? */ } static void rna_PoseChannel_rotation_mode_set(PointerRNA *ptr, int value) { bPoseChannel *pchan = ptr->data; - + /* use API Method for conversions... */ BKE_rotMode_change_values(pchan->quat, pchan->eul, pchan->rotAxis, &pchan->rotAngle, pchan->rotmode, (short)value); - + /* finally, set the new rotation type */ pchan->rotmode = value; } @@ -388,12 +388,12 @@ static PointerRNA rna_PoseChannel_bone_group_get(PointerRNA *ptr) bPose *pose = (ob) ? ob->pose : NULL; bPoseChannel *pchan = (bPoseChannel *)ptr->data; bActionGroup *grp; - + if (pose) grp = BLI_findlink(&pose->agroups, pchan->agrp_index - 1); else grp = NULL; - + return rna_pointer_inherit_refine(ptr, &RNA_BoneGroup, grp); } @@ -402,7 +402,7 @@ static void rna_PoseChannel_bone_group_set(PointerRNA *ptr, PointerRNA value) Object *ob = (Object *)ptr->id.data; bPose *pose = (ob) ? ob->pose : NULL; bPoseChannel *pchan = (bPoseChannel *)ptr->data; - + if (pose) pchan->agrp_index = BLI_findindex(&pose->agroups, value.data) + 1; else @@ -426,7 +426,7 @@ static void rna_PoseChannel_bone_group_index_range(PointerRNA *ptr, int *min, in { Object *ob = (Object *)ptr->id.data; bPose *pose = (ob) ? ob->pose : NULL; - + *min = 0; *max = pose ? max_ii(0, BLI_listbase_count(&pose->agroups) - 1) : 0; } @@ -490,14 +490,14 @@ static void rna_pose_bgroup_name_index_set(PointerRNA *ptr, const char *value, s bPose *pose = (bPose *)ptr->data; bActionGroup *grp; int a; - + for (a = 1, grp = pose->agroups.first; grp; grp = grp->next, a++) { if (STREQ(grp->name, value)) { *index = a; return; } } - + *index = 0; } @@ -505,14 +505,14 @@ static void rna_pose_pgroup_name_set(PointerRNA *ptr, const char *value, char *r { bPose *pose = (bPose *)ptr->data; bActionGroup *grp; - + for (grp = pose->agroups.first; grp; grp = grp->next) { if (STREQ(grp->name, value)) { BLI_strncpy(result, value, maxlen); return; } } - + result[0] = '\0'; } #endif @@ -620,12 +620,12 @@ static int rna_PoseChannel_proxy_editable(PointerRNA *ptr, const char **r_info) Object *ob = (Object *)ptr->id.data; bArmature *arm = ob->data; bPoseChannel *pchan = (bPoseChannel *)ptr->data; - + if (ob->proxy && pchan->bone && (pchan->bone->layer & arm->layer_protected)) { *r_info = "Can't edit property of a proxy on a protected layer"; return 0; } - + return PROP_EDITABLE; } @@ -647,7 +647,7 @@ static int rna_PoseChannel_location_editable(PointerRNA *ptr, int index) static int rna_PoseChannel_scale_editable(PointerRNA *ptr, int index) { bPoseChannel *pchan = (bPoseChannel *)ptr->data; - + /* only if the axis in question is locked, not editable... */ if ((index == 0) && (pchan->protectflag & OB_LOCK_SCALEX)) return 0; @@ -662,7 +662,7 @@ static int rna_PoseChannel_scale_editable(PointerRNA *ptr, int index) static int rna_PoseChannel_rotation_euler_editable(PointerRNA *ptr, int index) { bPoseChannel *pchan = (bPoseChannel *)ptr->data; - + /* only if the axis in question is locked, not editable... */ if ((index == 0) && (pchan->protectflag & OB_LOCK_ROTX)) return 0; @@ -677,7 +677,7 @@ static int rna_PoseChannel_rotation_euler_editable(PointerRNA *ptr, int index) static int rna_PoseChannel_rotation_4d_editable(PointerRNA *ptr, int index) { bPoseChannel *pchan = (bPoseChannel *)ptr->data; - + /* only consider locks if locking components individually... */ if (pchan->protectflag & OB_LOCK_ROT4D) { /* only if the axis in question is locked, not editable... */ @@ -690,7 +690,7 @@ static int rna_PoseChannel_rotation_4d_editable(PointerRNA *ptr, int index) else if ((index == 3) && (pchan->protectflag & OB_LOCK_ROTZ)) return 0; } - + return PROP_EDITABLE; } @@ -737,7 +737,7 @@ static void rna_PoseChannel_matrix_set(PointerRNA *ptr, const float *values) void rna_def_actionbone_group_common(StructRNA *srna, int update_flag, const char *update_cb) { PropertyRNA *prop; - + /* color set + colors */ prop = RNA_def_property(srna, "color_set", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "customCol"); @@ -745,12 +745,12 @@ void rna_def_actionbone_group_common(StructRNA *srna, int update_flag, const cha RNA_def_property_enum_funcs(prop, NULL, "rna_ActionGroup_colorset_set", NULL); RNA_def_property_ui_text(prop, "Color Set", "Custom color set to use"); RNA_def_property_update(prop, update_flag, update_cb); - + prop = RNA_def_property(srna, "is_custom_color_set", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_funcs(prop, "rna_ActionGroup_is_custom_colorset_get", NULL); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Custom Color Set", "Color set is user-defined instead of a fixed theme color set"); - + /* TODO: editing the colors for this should result in changes to the color type... */ prop = RNA_def_property(srna, "colors", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); @@ -765,21 +765,21 @@ static void rna_def_bone_group(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + /* struct */ srna = RNA_def_struct(brna, "BoneGroup", NULL); RNA_def_struct_sdna(srna, "bActionGroup"); RNA_def_struct_ui_text(srna, "Bone Group", "Groups of Pose Channels (Bones)"); RNA_def_struct_ui_icon(srna, ICON_GROUP_BONE); - + /* name */ prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); RNA_def_property_ui_text(prop, "Name", ""); RNA_def_property_string_funcs(prop, NULL, NULL, "rna_BoneGroup_name_set"); RNA_def_struct_name_property(srna, prop); - + /* TODO: add some runtime-collections stuff to access grouped bones */ - + /* color set */ rna_def_actionbone_group_common(srna, NC_OBJECT | ND_POSE, "rna_Pose_update"); } @@ -854,7 +854,7 @@ static void rna_def_pose_channel(BlenderRNA *brna) RNA_def_struct_path_func(srna, "rna_PoseBone_path"); RNA_def_struct_idprops_func(srna, "rna_PoseBone_idprops"); RNA_def_struct_ui_icon(srna, ICON_BONE_DATA); - + /* Bone Constraints */ prop = RNA_def_property(srna, "constraints", PROP_COLLECTION, PROP_NONE); RNA_def_property_struct_type(prop, "Constraint"); @@ -873,7 +873,7 @@ static void rna_def_pose_channel(BlenderRNA *brna) /* Baked Bone Path cache data */ rna_def_motionpath_common(srna); - + /* Relationships to other bones */ prop = RNA_def_property(srna, "bone", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); @@ -893,7 +893,7 @@ static void rna_def_pose_channel(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_PTR_NO_OWNERSHIP); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Child", "Child of this pose bone"); - + /* Transformation settings */ prop = RNA_def_property(srna, "location", PROP_FLOAT, PROP_TRANSLATION); RNA_def_property_float_sdna(prop, NULL, "loc"); @@ -919,7 +919,7 @@ static void rna_def_pose_channel(BlenderRNA *brna) RNA_def_property_float_array_default(prop, default_quat); RNA_def_property_ui_text(prop, "Quaternion Rotation", "Rotation in Quaternions"); RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update"); - + /* XXX: for axis-angle, it would have been nice to have 2 separate fields for UI purposes, but * having a single one is better for Keyframing and other property-management situations... */ @@ -932,14 +932,14 @@ static void rna_def_pose_channel(BlenderRNA *brna) RNA_def_property_float_array_default(prop, default_axisAngle); RNA_def_property_ui_text(prop, "Axis-Angle Rotation", "Angle of Rotation for Axis-Angle rotation representation"); RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update"); - + prop = RNA_def_property(srna, "rotation_euler", PROP_FLOAT, PROP_EULER); RNA_def_property_float_sdna(prop, NULL, "eul"); RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC); RNA_def_property_editable_array_func(prop, "rna_PoseChannel_rotation_euler_editable"); RNA_def_property_ui_text(prop, "Euler Rotation", "Rotation in Eulers"); RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update"); - + prop = RNA_def_property(srna, "rotation_mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "rotmode"); RNA_def_property_enum_items(prop, rna_enum_posebone_rotmode_items); /* XXX move to using a single define of this someday */ @@ -948,19 +948,19 @@ static void rna_def_pose_channel(BlenderRNA *brna) RNA_def_property_editable_func(prop, "rna_PoseChannel_proxy_editable"); RNA_def_property_ui_text(prop, "Rotation Mode", ""); RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update"); - + /* Curved bones settings - Applied on top of restpose values */ rna_def_bone_curved_common(srna, true); - + /* Custom BBone next/prev sources */ prop = RNA_def_property(srna, "use_bbone_custom_handles", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "bboneflag", PCHAN_BBONE_CUSTOM_HANDLES); - RNA_def_property_ui_text(prop, "Use Custom Handle References", + RNA_def_property_ui_text(prop, "Use Custom Handle References", "Use custom reference bones as handles for B-Bones instead of next/previous bones, " "leave these blank to use only B-Bone offset properties to control the shape"); RNA_def_property_editable_func(prop, "rna_PoseChannel_proxy_editable"); RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update"); - + prop = RNA_def_property(srna, "bbone_custom_handle_start", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "bbone_prev"); RNA_def_property_struct_type(prop, "PoseBone"); @@ -969,14 +969,14 @@ static void rna_def_pose_channel(BlenderRNA *brna) "Bone that serves as the start handle for the B-Bone curve"); RNA_def_property_editable_func(prop, "rna_PoseChannel_proxy_editable"); RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update"); - + prop = RNA_def_property(srna, "use_bbone_relative_start_handle", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "bboneflag", PCHAN_BBONE_CUSTOM_START_REL); - RNA_def_property_ui_text(prop, "Relative B-Bone Start Handle", + RNA_def_property_ui_text(prop, "Relative B-Bone Start Handle", "Treat custom start handle position as a relative value"); RNA_def_property_editable_func(prop, "rna_PoseChannel_proxy_editable"); RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update"); - + prop = RNA_def_property(srna, "bbone_custom_handle_end", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "bbone_next"); RNA_def_property_struct_type(prop, "PoseBone"); @@ -985,14 +985,14 @@ static void rna_def_pose_channel(BlenderRNA *brna) "Bone that serves as the end handle for the B-Bone curve"); RNA_def_property_editable_func(prop, "rna_PoseChannel_proxy_editable"); RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update"); - + prop = RNA_def_property(srna, "use_bbone_relative_end_handle", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "bboneflag", PCHAN_BBONE_CUSTOM_END_REL); - RNA_def_property_ui_text(prop, "Relative B-Bone End Handle", + RNA_def_property_ui_text(prop, "Relative B-Bone End Handle", "Treat custom end handle position as a relative value"); RNA_def_property_editable_func(prop, "rna_PoseChannel_proxy_editable"); RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update"); - + /* transform matrices - should be read-only since these are set directly by AnimSys evaluation */ prop = RNA_def_property(srna, "matrix_channel", PROP_FLOAT, PROP_MATRIX); RNA_def_property_float_sdna(prop, NULL, "chan_mat"); @@ -1030,7 +1030,7 @@ static void rna_def_pose_channel(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Pose Tail Position", "Location of tail of the channel's bone"); RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT); - + /* IK Settings */ prop = RNA_def_property(srna, "is_in_ik_chain", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_funcs(prop, "rna_PoseChannel_has_ik_get", NULL); @@ -1076,19 +1076,19 @@ static void rna_def_pose_channel(BlenderRNA *brna) RNA_def_property_ui_text(prop, "IK Z Limit", "Limit movement around the Z axis"); RNA_def_property_editable_func(prop, "rna_PoseChannel_proxy_editable"); RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_IK_update"); - + prop = RNA_def_property(srna, "use_ik_rotation_control", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "ikflag", BONE_IK_ROTCTL); RNA_def_property_ui_text(prop, "IK rot control", "Apply channel rotation as IK constraint"); RNA_def_property_editable_func(prop, "rna_PoseChannel_proxy_editable"); RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_IK_update"); - + prop = RNA_def_property(srna, "use_ik_linear_control", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "ikflag", BONE_IK_LINCTL); RNA_def_property_ui_text(prop, "IK rot control", "Apply channel size as IK constraint if stretching is enabled"); RNA_def_property_editable_func(prop, "rna_PoseChannel_proxy_editable"); RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_IK_update"); - + prop = RNA_def_property(srna, "ik_min_x", PROP_FLOAT, PROP_ANGLE); RNA_def_property_float_sdna(prop, NULL, "limitmin[0]"); RNA_def_property_range(prop, -M_PI, 0.0f); @@ -1158,21 +1158,21 @@ static void rna_def_pose_channel(BlenderRNA *brna) RNA_def_property_ui_text(prop, "IK Stretch", "Allow scaling of the bone for IK"); RNA_def_property_editable_func(prop, "rna_PoseChannel_proxy_editable"); RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_IK_update"); - + prop = RNA_def_property(srna, "ik_rotation_weight", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "ikrotweight"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "IK Rot Weight", "Weight of rotation constraint for IK"); RNA_def_property_editable_func(prop, "rna_PoseChannel_proxy_editable"); RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update"); - + prop = RNA_def_property(srna, "ik_linear_weight", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "iklinweight"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "IK Lin Weight", "Weight of scale constraint for IK"); RNA_def_property_editable_func(prop, "rna_PoseChannel_proxy_editable"); RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update"); - + /* custom bone shapes */ prop = RNA_def_property(srna, "custom_shape", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "custom"); @@ -1182,7 +1182,7 @@ static void rna_def_pose_channel(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Custom Object", "Object that defines custom draw type for this bone"); RNA_def_property_editable_func(prop, "rna_PoseChannel_proxy_editable"); RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update"); - + prop = RNA_def_property(srna, "custom_shape_scale", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "custom_scale"); RNA_def_property_range(prop, 0.0f, 1000.0f); @@ -1202,7 +1202,7 @@ static void rna_def_pose_channel(BlenderRNA *brna) "Bone that defines the display transform of this custom shape"); RNA_def_property_editable_func(prop, "rna_PoseChannel_proxy_editable"); RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update"); - + /* bone groups */ prop = RNA_def_property(srna, "bone_group_index", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "agrp_index"); @@ -1213,7 +1213,7 @@ static void rna_def_pose_channel(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Bone Group Index", "Bone Group this pose channel belongs to (0=no group)"); RNA_def_property_editable_func(prop, "rna_PoseChannel_proxy_editable"); RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update"); - + prop = RNA_def_property(srna, "bone_group", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "BoneGroup"); RNA_def_property_flag(prop, PROP_EDITABLE); @@ -1222,7 +1222,7 @@ static void rna_def_pose_channel(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Bone Group", "Bone Group this pose channel belongs to"); RNA_def_property_editable_func(prop, "rna_PoseChannel_proxy_editable"); RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update"); - + /* transform locks */ prop = RNA_def_property(srna, "lock_location", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "protectflag", OB_LOCK_LOCX); @@ -1239,7 +1239,7 @@ static void rna_def_pose_channel(BlenderRNA *brna) RNA_def_property_ui_icon(prop, ICON_UNLOCKED, 1); RNA_def_property_editable_func(prop, "rna_PoseChannel_proxy_editable"); RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update"); - + /* XXX this is sub-optimal - it really should be included above, but due to technical reasons * we can't do this! */ prop = RNA_def_property(srna, "lock_rotation_w", PROP_BOOLEAN, PROP_NONE); @@ -1439,7 +1439,7 @@ static void rna_def_bone_groups(BlenderRNA *brna, PropertyRNA *cprop) "rna_Pose_active_bone_group_set", NULL, NULL); RNA_def_property_ui_text(prop, "Active Bone Group", "Active bone group for this pose"); RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update"); - + prop = RNA_def_property(srna, "active_index", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "active_group"); RNA_def_property_int_funcs(prop, "rna_Pose_active_bone_group_index_get", "rna_Pose_active_bone_group_index_set", @@ -1452,7 +1452,7 @@ static void rna_def_pose(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + /* struct definition */ srna = RNA_def_struct(brna, "Pose", NULL); RNA_def_struct_sdna(srna, "bPose"); @@ -1473,7 +1473,7 @@ static void rna_def_pose(BlenderRNA *brna) RNA_def_property_struct_type(prop, "BoneGroup"); RNA_def_property_ui_text(prop, "Bone Groups", "Groups of the bones"); rna_def_bone_groups(brna, prop); - + /* ik solvers */ prop = RNA_def_property(srna, "ik_solver", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "iksolver"); @@ -1487,10 +1487,10 @@ static void rna_def_pose(BlenderRNA *brna) RNA_def_property_pointer_funcs(prop, "rna_Pose_ikparam_get", NULL, "rna_Pose_ikparam_typef", NULL); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "IK Param", "Parameters for IK solver"); - + /* animviz */ rna_def_animviz_common(srna); - + RNA_api_pose(srna); } diff --git a/source/blender/makesrna/intern/rna_render.c b/source/blender/makesrna/intern/rna_render.c index fe12e1cd528..0dd33944dda 100644 --- a/source/blender/makesrna/intern/rna_render.c +++ b/source/blender/makesrna/intern/rna_render.c @@ -291,7 +291,7 @@ static void rna_RenderEngine_unregister(Main *bmain, StructRNA *type) if (!et) return; - + RNA_struct_free_extension(type, &et->ext); RNA_struct_free(&BLENDER_RNA, type); BLI_freelinkN(&R_engines, et); @@ -332,7 +332,7 @@ static StructRNA *rna_RenderEngine_register( break; } } - + /* create a new engine type */ et = MEM_callocN(sizeof(RenderEngineType), "python render engine"); memcpy(et, &dummyet, sizeof(dummyet)); @@ -790,7 +790,7 @@ static void rna_def_render_result(BlenderRNA *brna) FunctionRNA *func; PropertyRNA *parm; - + srna = RNA_def_struct(brna, "RenderResult", NULL); RNA_def_struct_ui_text(srna, "Render Result", "Result of rendering, including all layers and passes"); @@ -890,7 +890,7 @@ static void rna_def_render_layer(BlenderRNA *brna) FunctionRNA *func; PropertyRNA *parm; - + srna = RNA_def_struct(brna, "RenderLayer", NULL); RNA_def_struct_ui_text(srna, "Render Layer", ""); diff --git a/source/blender/makesrna/intern/rna_rigidbody.c b/source/blender/makesrna/intern/rna_rigidbody.c index 0a8a99d779a..60a1783f118 100644 --- a/source/blender/makesrna/intern/rna_rigidbody.c +++ b/source/blender/makesrna/intern/rna_rigidbody.c @@ -108,19 +108,19 @@ static const EnumPropertyItem rigidbody_mesh_source_items[] = { static void rna_RigidBodyWorld_reset(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { RigidBodyWorld *rbw = (RigidBodyWorld *)ptr->data; - + BKE_rigidbody_cache_reset(rbw); } static char *rna_RigidBodyWorld_path(PointerRNA *UNUSED(ptr)) -{ +{ return BLI_sprintfN("rigidbody_world"); } static void rna_RigidBodyWorld_num_solver_iterations_set(PointerRNA *ptr, int value) { RigidBodyWorld *rbw = (RigidBodyWorld *)ptr->data; - + rbw->num_solver_iterations = value; #ifdef WITH_BULLET @@ -133,7 +133,7 @@ static void rna_RigidBodyWorld_num_solver_iterations_set(PointerRNA *ptr, int va static void rna_RigidBodyWorld_split_impulse_set(PointerRNA *ptr, int value) { RigidBodyWorld *rbw = (RigidBodyWorld *)ptr->data; - + RB_FLAG_SET(rbw->flag, value, RBW_FLAG_USE_SPLIT_IMPULSE); #ifdef WITH_BULLET @@ -148,16 +148,16 @@ static void rna_RigidBodyWorld_split_impulse_set(PointerRNA *ptr, int value) static void rna_RigidBodyOb_reset(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr)) { RigidBodyWorld *rbw = scene->rigidbody_world; - + BKE_rigidbody_cache_reset(rbw); } static void rna_RigidBodyOb_shape_update(Main *bmain, Scene *scene, PointerRNA *ptr) { Object *ob = ptr->id.data; - + rna_RigidBodyOb_reset(bmain, scene, ptr); - + WM_main_add_notifier(NC_OBJECT | ND_DRAW, ob); } @@ -165,7 +165,7 @@ static void rna_RigidBodyOb_shape_reset(Main *UNUSED(bmain), Scene *scene, Point { RigidBodyWorld *rbw = scene->rigidbody_world; RigidBodyOb *rbo = (RigidBodyOb *)ptr->data; - + BKE_rigidbody_cache_reset(rbw); if (rbo->physics_shape) rbo->flag |= RBO_FLAG_NEEDS_RESHAPE; @@ -180,7 +180,7 @@ static char *rna_RigidBodyOb_path(PointerRNA *UNUSED(ptr)) static void rna_RigidBodyOb_type_set(PointerRNA *ptr, int value) { RigidBodyOb *rbo = (RigidBodyOb *)ptr->data; - + rbo->type = value; rbo->flag |= RBO_FLAG_NEEDS_VALIDATE; } @@ -196,7 +196,7 @@ static void rna_RigidBodyOb_shape_set(PointerRNA *ptr, int value) static void rna_RigidBodyOb_disabled_set(PointerRNA *ptr, int value) { RigidBodyOb *rbo = (RigidBodyOb *)ptr->data; - + RB_FLAG_SET(rbo->flag, !value, RBO_FLAG_DISABLED); #ifdef WITH_BULLET @@ -212,7 +212,7 @@ static void rna_RigidBodyOb_disabled_set(PointerRNA *ptr, int value) static void rna_RigidBodyOb_mass_set(PointerRNA *ptr, float value) { RigidBodyOb *rbo = (RigidBodyOb *)ptr->data; - + rbo->mass = value; #ifdef WITH_BULLET @@ -226,7 +226,7 @@ static void rna_RigidBodyOb_mass_set(PointerRNA *ptr, float value) static void rna_RigidBodyOb_friction_set(PointerRNA *ptr, float value) { RigidBodyOb *rbo = (RigidBodyOb *)ptr->data; - + rbo->friction = value; #ifdef WITH_BULLET @@ -239,7 +239,7 @@ static void rna_RigidBodyOb_friction_set(PointerRNA *ptr, float value) static void rna_RigidBodyOb_restitution_set(PointerRNA *ptr, float value) { RigidBodyOb *rbo = (RigidBodyOb *)ptr->data; - + rbo->restitution = value; #ifdef WITH_BULLET if (rbo->physics_object) { @@ -251,7 +251,7 @@ static void rna_RigidBodyOb_restitution_set(PointerRNA *ptr, float value) static void rna_RigidBodyOb_collision_margin_set(PointerRNA *ptr, float value) { RigidBodyOb *rbo = (RigidBodyOb *)ptr->data; - + rbo->margin = value; #ifdef WITH_BULLET @@ -278,7 +278,7 @@ static void rna_RigidBodyOb_collision_groups_set(PointerRNA *ptr, const int *val static void rna_RigidBodyOb_kinematic_state_set(PointerRNA *ptr, int value) { RigidBodyOb *rbo = (RigidBodyOb *)ptr->data; - + RB_FLAG_SET(rbo->flag, value, RBO_FLAG_KINEMATIC); #ifdef WITH_BULLET @@ -294,7 +294,7 @@ static void rna_RigidBodyOb_kinematic_state_set(PointerRNA *ptr, int value) static void rna_RigidBodyOb_activation_state_set(PointerRNA *ptr, int value) { RigidBodyOb *rbo = (RigidBodyOb *)ptr->data; - + RB_FLAG_SET(rbo->flag, value, RBO_FLAG_USE_DEACTIVATION); #ifdef WITH_BULLET @@ -308,7 +308,7 @@ static void rna_RigidBodyOb_activation_state_set(PointerRNA *ptr, int value) static void rna_RigidBodyOb_linear_sleepThresh_set(PointerRNA *ptr, float value) { RigidBodyOb *rbo = (RigidBodyOb *)ptr->data; - + rbo->lin_sleep_thresh = value; #ifdef WITH_BULLET @@ -322,7 +322,7 @@ static void rna_RigidBodyOb_linear_sleepThresh_set(PointerRNA *ptr, float value) static void rna_RigidBodyOb_angular_sleepThresh_set(PointerRNA *ptr, float value) { RigidBodyOb *rbo = (RigidBodyOb *)ptr->data; - + rbo->ang_sleep_thresh = value; #ifdef WITH_BULLET @@ -336,7 +336,7 @@ static void rna_RigidBodyOb_angular_sleepThresh_set(PointerRNA *ptr, float value static void rna_RigidBodyOb_linear_damping_set(PointerRNA *ptr, float value) { RigidBodyOb *rbo = (RigidBodyOb *)ptr->data; - + rbo->lin_damping = value; #ifdef WITH_BULLET @@ -350,7 +350,7 @@ static void rna_RigidBodyOb_linear_damping_set(PointerRNA *ptr, float value) static void rna_RigidBodyOb_angular_damping_set(PointerRNA *ptr, float value) { RigidBodyOb *rbo = (RigidBodyOb *)ptr->data; - + rbo->ang_damping = value; #ifdef WITH_BULLET @@ -737,7 +737,7 @@ static void rna_def_rigidbody_world(BlenderRNA *brna) RNA_def_struct_sdna(srna, "RigidBodyWorld"); RNA_def_struct_ui_text(srna, "Rigid Body World", "Self-contained rigid body simulation environment and settings"); RNA_def_struct_path_func(srna, "rna_RigidBodyWorld_path"); - + /* groups */ prop = RNA_def_property(srna, "group", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "Collection"); @@ -750,13 +750,13 @@ static void rna_def_rigidbody_world(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); RNA_def_property_ui_text(prop, "Constraints", "Collection containing rigid body constraint objects"); RNA_def_property_update(prop, NC_SCENE, "rna_RigidBodyWorld_reset"); - + /* booleans */ prop = RNA_def_property(srna, "enabled", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", RBW_FLAG_MUTED); RNA_def_property_ui_text(prop, "Enabled", "Simulation will be evaluated"); RNA_def_property_update(prop, NC_SCENE, NULL); - + /* time scale */ prop = RNA_def_property(srna, "time_scale", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "time_scale"); @@ -765,7 +765,7 @@ static void rna_def_rigidbody_world(BlenderRNA *brna) RNA_def_property_float_default(prop, 1.0f); RNA_def_property_ui_text(prop, "Time Scale", "Change the speed of the simulation"); RNA_def_property_update(prop, NC_SCENE, "rna_RigidBodyWorld_reset"); - + /* timestep */ prop = RNA_def_property(srna, "steps_per_second", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "steps_per_second"); @@ -776,7 +776,7 @@ static void rna_def_rigidbody_world(BlenderRNA *brna) "Number of simulation steps taken per second (higher values are more accurate " "but slower)"); RNA_def_property_update(prop, NC_SCENE, "rna_RigidBodyWorld_reset"); - + /* constraint solver iterations */ prop = RNA_def_property(srna, "solver_iterations", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "num_solver_iterations"); @@ -788,7 +788,7 @@ static void rna_def_rigidbody_world(BlenderRNA *brna) "Number of constraint solver iterations made per simulation step (higher values are more " "accurate but slower)"); RNA_def_property_update(prop, NC_SCENE, "rna_RigidBodyWorld_reset"); - + /* split impulse */ prop = RNA_def_property(srna, "use_split_impulse", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", RBW_FLAG_USE_SPLIT_IMPULSE); @@ -843,13 +843,13 @@ static void rna_def_rigidbody_object(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - - + + srna = RNA_def_struct(brna, "RigidBodyObject", NULL); RNA_def_struct_sdna(srna, "RigidBodyOb"); RNA_def_struct_ui_text(srna, "Rigid Body Object", "Settings for object participating in Rigid Body Simulation"); RNA_def_struct_path_func(srna, "rna_RigidBodyOb_path"); - + /* Enums */ prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "type"); @@ -858,21 +858,21 @@ static void rna_def_rigidbody_object(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Type", "Role of object in Rigid Body Simulations"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset"); - + prop = RNA_def_property(srna, "mesh_source", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "mesh_source"); RNA_def_property_enum_items(prop, rigidbody_mesh_source_items); RNA_def_property_ui_text(prop, "Mesh Source", "Source of the mesh used to create collision shape"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset"); - + /* booleans */ prop = RNA_def_property(srna, "enabled", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", RBO_FLAG_DISABLED); RNA_def_property_boolean_funcs(prop, NULL, "rna_RigidBodyOb_disabled_set"); RNA_def_property_ui_text(prop, "Enabled", "Rigid Body actively participates to the simulation"); RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset"); - + prop = RNA_def_property(srna, "collision_shape", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "shape"); RNA_def_property_enum_items(prop, rna_enum_rigidbody_object_shape_items); @@ -880,18 +880,18 @@ static void rna_def_rigidbody_object(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Collision Shape", "Collision Shape of object in Rigid Body Simulations"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_shape_update"); - + prop = RNA_def_property(srna, "kinematic", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", RBO_FLAG_KINEMATIC); RNA_def_property_boolean_funcs(prop, NULL, "rna_RigidBodyOb_kinematic_state_set"); RNA_def_property_ui_text(prop, "Kinematic", "Allow rigid body to be controlled by the animation system"); RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset"); - + prop = RNA_def_property(srna, "use_deform", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", RBO_FLAG_USE_DEFORM); RNA_def_property_ui_text(prop, "Deforming", "Rigid body deforms during simulation"); RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset"); - + /* Physics Parameters */ prop = RNA_def_property(srna, "mass", PROP_FLOAT, PROP_UNIT_MASS); RNA_def_property_float_sdna(prop, NULL, "mass"); @@ -900,10 +900,10 @@ static void rna_def_rigidbody_object(BlenderRNA *brna) RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyOb_mass_set", NULL); RNA_def_property_ui_text(prop, "Mass", "How much the object 'weighs' irrespective of gravity"); RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset"); - + /* Dynamics Parameters - Activation */ // TODO: define and figure out how to implement these - + /* Dynamics Parameters - Deactivation */ prop = RNA_def_property(srna, "use_deactivation", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", RBO_FLAG_USE_DEACTIVATION); @@ -913,13 +913,13 @@ static void rna_def_rigidbody_object(BlenderRNA *brna) "Enable deactivation of resting rigid bodies (increases performance and stability " "but can cause glitches)"); RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset"); - + prop = RNA_def_property(srna, "use_start_deactivated", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", RBO_FLAG_START_DEACTIVATED); RNA_def_property_ui_text(prop, "Start Deactivated", "Deactivate rigid body at the start of the simulation"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset"); - + prop = RNA_def_property(srna, "deactivate_linear_velocity", PROP_FLOAT, PROP_UNIT_VELOCITY); RNA_def_property_float_sdna(prop, NULL, "lin_sleep_thresh"); RNA_def_property_range(prop, FLT_MIN, FLT_MAX); // range must always be positive (and non-zero) @@ -928,7 +928,7 @@ static void rna_def_rigidbody_object(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Linear Velocity Deactivation Threshold", "Linear Velocity below which simulation stops simulating object"); RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset"); - + prop = RNA_def_property(srna, "deactivate_angular_velocity", PROP_FLOAT, PROP_UNIT_VELOCITY); RNA_def_property_float_sdna(prop, NULL, "ang_sleep_thresh"); RNA_def_property_range(prop, FLT_MIN, FLT_MAX); // range must always be positive (and non-zero) @@ -937,7 +937,7 @@ static void rna_def_rigidbody_object(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Angular Velocity Deactivation Threshold", "Angular Velocity below which simulation stops simulating object"); RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset"); - + /* Dynamics Parameters - Damping Parameters */ prop = RNA_def_property(srna, "linear_damping", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "lin_damping"); @@ -946,7 +946,7 @@ static void rna_def_rigidbody_object(BlenderRNA *brna) RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyOb_linear_damping_set", NULL); RNA_def_property_ui_text(prop, "Linear Damping", "Amount of linear velocity that is lost over time"); RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset"); - + prop = RNA_def_property(srna, "angular_damping", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "ang_damping"); RNA_def_property_range(prop, 0.0f, 1.0f); @@ -954,7 +954,7 @@ static void rna_def_rigidbody_object(BlenderRNA *brna) RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyOb_angular_damping_set", NULL); RNA_def_property_ui_text(prop, "Angular Damping", "Amount of angular velocity that is lost over time"); RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset"); - + /* Collision Parameters - Surface Parameters */ prop = RNA_def_property(srna, "friction", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "friction"); @@ -964,7 +964,7 @@ static void rna_def_rigidbody_object(BlenderRNA *brna) RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyOb_friction_set", NULL); RNA_def_property_ui_text(prop, "Friction", "Resistance of object to movement"); RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset"); - + prop = RNA_def_property(srna, "restitution", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "restitution"); RNA_def_property_range(prop, 0.0f, FLT_MAX); @@ -975,7 +975,7 @@ static void rna_def_rigidbody_object(BlenderRNA *brna) "Tendency of object to bounce after colliding with another " "(0 = stays still, 1 = perfectly elastic)"); RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset"); - + /* Collision Parameters - Sensitivity */ prop = RNA_def_property(srna, "use_margin", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", RBO_FLAG_USE_MARGIN); @@ -983,7 +983,7 @@ static void rna_def_rigidbody_object(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Collision Margin", "Use custom collision margin (some shapes will have a visible gap around them)"); RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_shape_reset"); - + prop = RNA_def_property(srna, "collision_margin", PROP_FLOAT, PROP_UNIT_LENGTH); RNA_def_property_float_sdna(prop, NULL, "margin"); RNA_def_property_range(prop, 0.0f, 1.0f); @@ -994,7 +994,7 @@ static void rna_def_rigidbody_object(BlenderRNA *brna) "Threshold of distance near surface where collisions are still considered " "(best results when non-zero)"); RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_shape_reset"); - + prop = RNA_def_property(srna, "collision_groups", PROP_BOOLEAN, PROP_LAYER_MEMBER); RNA_def_property_boolean_sdna(prop, NULL, "col_groups", 1); RNA_def_property_array(prop, 20); diff --git a/source/blender/makesrna/intern/rna_rna.c b/source/blender/makesrna/intern/rna_rna.c index 1a66174d8ce..53b98928c31 100644 --- a/source/blender/makesrna/intern/rna_rna.c +++ b/source/blender/makesrna/intern/rna_rna.c @@ -945,10 +945,10 @@ static void rna_EnumProperty_items_begin(CollectionPropertyIterator *iter, Point const EnumPropertyItem *item = NULL; int totitem; bool free; - + rna_idproperty_check(&prop, ptr); /* eprop = (EnumPropertyRNA *)prop; */ - + RNA_property_enum_items_ex( NULL, ptr, prop, STREQ(iter->prop->identifier, "enum_items_static"), &item, &totitem, &free); rna_iterator_array_begin(iter, (void *)item, sizeof(EnumPropertyItem), totitem, free, rna_enum_check_separator); @@ -2253,18 +2253,18 @@ static void rna_def_struct(BlenderRNA *brna) RNA_def_property_string_funcs(prop, "rna_Struct_identifier_get", "rna_Struct_identifier_length", NULL); RNA_def_property_ui_text(prop, "Identifier", "Unique name used in the code and scripting"); RNA_def_struct_name_property(srna, prop); - + prop = RNA_def_property(srna, "description", PROP_STRING, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_string_funcs(prop, "rna_Struct_description_get", "rna_Struct_description_length", NULL); RNA_def_property_ui_text(prop, "Description", "Description of the Struct's purpose"); - + prop = RNA_def_property(srna, "translation_context", PROP_STRING, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_string_funcs(prop, "rna_Struct_translation_context_get", "rna_Struct_translation_context_length", NULL); RNA_def_property_ui_text(prop, "Translation Context", "Translation context of the struct's name"); - + prop = RNA_def_property(srna, "base", PROP_POINTER, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_struct_type(prop, "Struct"); @@ -2356,7 +2356,7 @@ static void rna_def_property(BlenderRNA *brna) RNA_def_property_string_funcs(prop, "rna_Property_identifier_get", "rna_Property_identifier_length", NULL); RNA_def_property_ui_text(prop, "Identifier", "Unique name used in the code and scripting"); RNA_def_struct_name_property(srna, prop); - + prop = RNA_def_property(srna, "description", PROP_STRING, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_string_funcs(prop, "rna_Property_description_get", "rna_Property_description_length", NULL); @@ -2454,7 +2454,7 @@ static void rna_def_property(BlenderRNA *brna) RNA_def_property_boolean_funcs(prop, "rna_Property_is_registered_optional_get", NULL); RNA_def_property_ui_text(prop, "Registered Optionally", "Property is optionally registered as part of type registration"); - + prop = RNA_def_property(srna, "is_runtime", PROP_BOOLEAN, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_boolean_funcs(prop, "rna_Property_is_runtime_get", NULL); @@ -2522,7 +2522,7 @@ static void rna_def_function(BlenderRNA *brna) RNA_def_property_boolean_funcs(prop, "rna_Function_no_self_get", NULL); RNA_def_property_ui_text(prop, "No Self", "Function does not pass its self as an argument (becomes a static method in python)"); - + prop = RNA_def_property(srna, "use_self_type", PROP_BOOLEAN, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_boolean_funcs(prop, "rna_Function_use_self_type_get", NULL); @@ -2781,7 +2781,7 @@ void RNA_def_rna(BlenderRNA *brna) RNA_def_struct_ui_text(srna, "Collection Definition", "RNA collection property to define lists, arrays and mappings"); rna_def_pointer_property(srna, PROP_COLLECTION); - + /* Function */ rna_def_function(brna); diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 8055c8fe4d6..22986205eef 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -122,7 +122,7 @@ const EnumPropertyItem rna_enum_snap_target_items[] = { {SCE_SNAP_TARGET_ACTIVE, "ACTIVE", 0, "Active", "Snap active onto target"}, {0, NULL, 0, NULL, NULL} }; - + const EnumPropertyItem rna_enum_proportional_falloff_items[] = { {PROP_SMOOTH, "SMOOTH", ICON_SMOOTHCURVE, "Smooth", "Smooth falloff"}, {PROP_SPHERE, "SPHERE", ICON_SPHERECURVE, "Sphere", "Spherical falloff"}, @@ -419,7 +419,7 @@ static const EnumPropertyItem rna_enum_gpencil_interpolation_mode_items[] = { {0, "", 0, N_("Interpolation"), "Standard transitions between keyframes"}, {GP_IPO_LINEAR, "LINEAR", ICON_IPO_LINEAR, "Linear", "Straight-line interpolation between A and B (i.e. no ease in/out)"}, {GP_IPO_CURVEMAP, "CUSTOM", ICON_IPO_BEZIER, "Custom", "Custom interpolation defined using a curve map"}, - + /* easing */ {0, "", 0, N_("Easing (by strength)"), "Predefined inertial transitions, useful for motion graphics (from least to most ''dramatic'')"}, {GP_IPO_SINE, "SINE", ICON_IPO_SINE, "Sinusoidal", "Sinusoidal easing (weakest, almost linear but with a slight curvature)"}, @@ -429,12 +429,12 @@ static const EnumPropertyItem rna_enum_gpencil_interpolation_mode_items[] = { {GP_IPO_QUINT, "QUINT", ICON_IPO_QUINT, "Quintic", "Quintic easing"}, {GP_IPO_EXPO, "EXPO", ICON_IPO_EXPO, "Exponential", "Exponential easing (dramatic)"}, {GP_IPO_CIRC, "CIRC", ICON_IPO_CIRC, "Circular", "Circular easing (strongest and most dynamic)"}, - + {0, "", 0, N_("Dynamic Effects"), "Simple physics-inspired easing effects"}, {GP_IPO_BACK, "BACK", ICON_IPO_BACK, "Back", "Cubic easing with overshoot and settle"}, {GP_IPO_BOUNCE, "BOUNCE", ICON_IPO_BOUNCE, "Bounce", "Exponentially decaying parabolic bounce, like when objects collide"}, {GP_IPO_ELASTIC, "ELASTIC", ICON_IPO_ELASTIC, "Elastic", "Exponentially decaying sine wave, like an elastic band"}, - + {0, NULL, 0, NULL, NULL} }; @@ -524,12 +524,12 @@ static char *rna_GPencilInterpolateSettings_path(PointerRNA *UNUSED(ptr)) static void rna_GPencilInterpolateSettings_type_set(PointerRNA *ptr, int value) { GP_Interpolate_Settings *settings = (GP_Interpolate_Settings *)ptr->data; - + /* NOTE: This cast should be fine, as we have a small + finite set of values (eGP_Interpolate_Type) * that should fit well within a char */ settings->type = (char)value; - + /* init custom interpolation curve here now the first time it's used */ if ((settings->type == GP_IPO_CURVEMAP) && (settings->custom_ipo == NULL)) @@ -642,7 +642,7 @@ static void rna_GPencilBrush_name_set(PointerRNA *ptr, const char *value) static void rna_SpaceImageEditor_uv_sculpt_update(Main *bmain, Scene *scene, PointerRNA *UNUSED(ptr)) { - ED_space_image_uv_sculpt_update(bmain->wm.first, scene); + ED_space_image_uv_sculpt_update(bmain, bmain->wm.first, scene); } @@ -772,7 +772,7 @@ static void rna_Scene_framelen_update(Main *UNUSED(bmain), Scene *scene, Pointer static void rna_Scene_frame_current_set(PointerRNA *ptr, int value) { Scene *data = (Scene *)ptr->data; - + /* if negative frames aren't allowed, then we can't use them */ FRAMENUMBER_MIN_CLAMP(value); data->r.cfra = value; @@ -826,14 +826,14 @@ static void rna_Scene_end_frame_set(PointerRNA *ptr, int value) static void rna_Scene_use_preview_range_set(PointerRNA *ptr, int value) { Scene *data = (Scene *)ptr->data; - + if (value) { /* copy range from scene if not set before */ if ((data->r.psfra == data->r.pefra) && (data->r.psfra == 0)) { data->r.psfra = data->r.sfra; data->r.pefra = data->r.efra; } - + data->r.flag |= SCER_PRV_RANGE; } else @@ -844,14 +844,14 @@ static void rna_Scene_use_preview_range_set(PointerRNA *ptr, int value) static void rna_Scene_preview_range_start_frame_set(PointerRNA *ptr, int value) { Scene *data = (Scene *)ptr->data; - + /* check if enabled already */ if ((data->r.flag & SCER_PRV_RANGE) == 0) { /* set end of preview range to end frame, then clamp as per normal */ /* TODO: or just refuse to set instead? */ data->r.pefra = data->r.efra; } - + /* now set normally */ CLAMP(value, MINAFRAME, data->r.pefra); data->r.psfra = value; @@ -860,14 +860,14 @@ static void rna_Scene_preview_range_start_frame_set(PointerRNA *ptr, int value) static void rna_Scene_preview_range_end_frame_set(PointerRNA *ptr, int value) { Scene *data = (Scene *)ptr->data; - + /* check if enabled already */ if ((data->r.flag & SCER_PRV_RANGE) == 0) { /* set start of preview range to start frame, then clamp as per normal */ /* TODO: or just refuse to set instead? */ data->r.psfra = data->r.sfra; } - + /* now set normally */ CLAMP(value, data->r.psfra, MAXFRAME); data->r.pefra = value; @@ -896,7 +896,7 @@ static void rna_Scene_active_keying_set_set(PointerRNA *ptr, PointerRNA value) { Scene *scene = (Scene *)ptr->data; KeyingSet *ks = (KeyingSet *)value.data; - + scene->active_keyingset = ANIM_scene_get_keyingset_index(scene, ks); } @@ -926,7 +926,7 @@ extern ListBase builtin_keyingsets; static void rna_Scene_all_keyingsets_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) { Scene *scene = (Scene *)ptr->data; - + /* start going over the scene KeyingSets first, while we still have pointer to it * but only if we have any Keying Sets to use... */ @@ -940,13 +940,13 @@ static void rna_Scene_all_keyingsets_next(CollectionPropertyIterator *iter) { ListBaseIterator *internal = &iter->internal.listbase; KeyingSet *ks = (KeyingSet *)internal->link; - + /* if we've run out of links in Scene list, jump over to the builtins list unless we're there already */ if ((ks->next == NULL) && (ks != builtin_keyingsets.last)) internal->link = (Link *)builtin_keyingsets.first; else internal->link = (Link *)ks->next; - + iter->valid = (internal->link != NULL); } @@ -1416,7 +1416,7 @@ static const EnumPropertyItem *rna_RenderSettings_engine_itemf( tmp.name = type->name; RNA_enum_item_add(&item, &totitem, &tmp); } - + RNA_enum_item_end(&item, &totitem); *r_free = true; @@ -1432,7 +1432,7 @@ static int rna_RenderSettings_engine_get(PointerRNA *ptr) for (type = R_engines.first; type; type = type->next, a++) if (STREQ(type->idname, rd->engine)) return a; - + return 0; } @@ -1592,7 +1592,7 @@ static void object_simplify_update(Object *ob) for (psys = ob->particlesystem.first; psys; psys = psys->next) psys->recalc |= PSYS_RECALC_CHILD; - + if (ob->dup_group) { CollectionObject *cob; @@ -1617,7 +1617,7 @@ static void rna_Scene_use_simplify_update(Main *bmain, Scene *UNUSED(scene), Poi for (SETLOOPER_SET_ONLY(sce, sce_iter, base)) { object_simplify_update(base->object); } - + WM_main_add_notifier(NC_GEOM | ND_DATA, NULL); DEG_id_tag_update(&sce->id, 0); } @@ -1727,7 +1727,7 @@ static KeyingSet *rna_Scene_keying_set_new(Scene *sce, ReportList *reports, cons /* call the API func, and set the active keyingset index */ ks = BKE_keyingset_add(&sce->keyingsets, idname, name, KEYINGSET_ABSOLUTE, 0); - + if (ks) { sce->active_keyingset = BLI_listbase_count(&sce->keyingsets); return ks; @@ -1981,7 +1981,7 @@ static void rna_GPUDOFSettings_update(Main *UNUSED(bmain), Scene *scene, Pointer WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, scene); } -static void rna_Stereo3dFormat_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) +static void rna_Stereo3dFormat_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { ID *id = ptr->id.data; @@ -1996,7 +1996,7 @@ static void rna_Stereo3dFormat_update(Main *UNUSED(bmain), Scene *UNUSED(scene), ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock); if (ibuf) { - BKE_image_signal(ima, NULL, IMA_SIGNAL_FREE); + BKE_image_signal(bmain, ima, NULL, IMA_SIGNAL_FREE); } BKE_image_release_ibuf(ima, ibuf, lock); } @@ -2103,13 +2103,13 @@ static void rna_def_gpencil_interpolate(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + srna = RNA_def_struct(brna, "GPencilInterpolateSettings", NULL); RNA_def_struct_sdna(srna, "GP_Interpolate_Settings"); RNA_def_struct_path_func(srna, "rna_GPencilInterpolateSettings_path"); RNA_def_struct_ui_text(srna, "Grease Pencil Interpolate Settings", "Settings for Grease Pencil interpolation tools"); - + /* flags */ prop = RNA_def_property(srna, "interpolate_all_layers", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_TOOLFLAG_INTERPOLATE_ALL_LAYERS); @@ -2120,7 +2120,7 @@ static void rna_def_gpencil_interpolate(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_TOOLFLAG_INTERPOLATE_ONLY_SELECTED); RNA_def_property_ui_text(prop, "Interpolate Selected Strokes", "Interpolate only selected strokes in the original frame"); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); - + /* interpolation type */ prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "type"); @@ -2129,38 +2129,38 @@ static void rna_def_gpencil_interpolate(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Type", "Interpolation method to use the next time 'Interpolate Sequence' is run"); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); - + /* easing */ prop = RNA_def_property(srna, "easing", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "easing"); RNA_def_property_enum_items(prop, rna_enum_beztriple_interpolation_easing_items); - RNA_def_property_ui_text(prop, "Easing", + RNA_def_property_ui_text(prop, "Easing", "Which ends of the segment between the preceding and following grease pencil frames " "easing interpolation is applied to"); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); - + /* easing options */ prop = RNA_def_property(srna, "back", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "back"); RNA_def_property_ui_text(prop, "Back", "Amount of overshoot for 'back' easing"); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); - + prop = RNA_def_property(srna, "amplitude", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "amplitude"); RNA_def_property_range(prop, 0.0f, FLT_MAX); /* only positive values... */ RNA_def_property_ui_text(prop, "Amplitude", "Amount to boost elastic bounces for 'elastic' easing"); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); - + prop = RNA_def_property(srna, "period", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "period"); RNA_def_property_ui_text(prop, "Period", "Time between bounces for elastic easing"); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); - + /* custom curvemap */ prop = RNA_def_property(srna, "interpolation_curve", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "custom_ipo"); RNA_def_property_struct_type(prop, "CurveMapping"); - RNA_def_property_ui_text(prop, "Interpolation Curve", + RNA_def_property_ui_text(prop, "Interpolation Curve", "Custom curve to control 'sequence' interpolation between Grease Pencil frames"); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); } @@ -2368,14 +2368,14 @@ static void rna_def_transform_orientation(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + srna = RNA_def_struct(brna, "TransformOrientation", NULL); - + prop = RNA_def_property(srna, "matrix", PROP_FLOAT, PROP_MATRIX); RNA_def_property_float_sdna(prop, NULL, "mat"); RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_3x3); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); - + prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); RNA_def_struct_name_property(srna, prop); RNA_def_property_ui_text(prop, "Name", "Name of the custom transform orientation"); @@ -2394,7 +2394,7 @@ static void rna_def_tool_settings(BlenderRNA *brna) {UV_SELECT_ISLAND, "ISLAND", ICON_UV_ISLANDSEL, "Island", "Island selection mode"}, {0, NULL, 0, NULL, NULL} }; - + /* the construction of this enum is quite special - everything is stored as bitflags, * with 1st position only for for on/off (and exposed as boolean), while others are mutually * exclusive options but which will only have any effect when autokey is enabled @@ -2428,7 +2428,7 @@ static void rna_def_tool_settings(BlenderRNA *brna) {WT_VGROUP_BONE_DEFORM_OFF, "OTHER_DEFORM", 0, "Other", "Vertex Groups assigned to non Deform Bones"}, {0, NULL, 0, NULL, NULL} }; - + static const EnumPropertyItem gpencil_source_3d_items[] = { {GP_TOOL_SOURCE_SCENE, "SCENE", 0, "Scene", "Grease Pencil data attached to the current scene is used, " @@ -2438,7 +2438,7 @@ static void rna_def_tool_settings(BlenderRNA *brna) "(required when using pre 2.73 add-ons, e.g. BSurfaces)"}, {0, NULL, 0, NULL, NULL} }; - + static const EnumPropertyItem gpencil_stroke_placement_items[] = { {GP_PROJECT_VIEWSPACE, "CURSOR", 0, "Cursor", "Draw stroke at the 3D cursor"}, {0, "VIEW", 0, "View", "Stick stroke to the view "}, /* weird, GP_PROJECT_VIEWALIGN is inverted */ @@ -2446,16 +2446,16 @@ static void rna_def_tool_settings(BlenderRNA *brna) {GP_PROJECT_VIEWSPACE | GP_PROJECT_DEPTH_STROKE, "STROKE", 0, "Stroke", "Stick stroke to other strokes"}, {0, NULL, 0, NULL, NULL} }; - - + + srna = RNA_def_struct(brna, "ToolSettings", NULL); RNA_def_struct_path_func(srna, "rna_ToolSettings_path"); RNA_def_struct_ui_text(srna, "Tool Settings", ""); - + prop = RNA_def_property(srna, "sculpt", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "Sculpt"); RNA_def_property_ui_text(prop, "Sculpt", ""); - + prop = RNA_def_property(srna, "use_auto_normalize", PROP_BOOLEAN, PROP_NONE); RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); RNA_def_property_boolean_sdna(prop, NULL, "auto_normalize", 1); @@ -2575,7 +2575,7 @@ static void rna_def_tool_settings(BlenderRNA *brna) RNA_def_property_float_sdna(prop, NULL, "proportional_size"); RNA_def_property_ui_text(prop, "Proportional Size", "Display size for proportional editing circle"); RNA_def_property_range(prop, 0.00001, 5000.0); - + 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'"); @@ -2625,14 +2625,14 @@ static void rna_def_tool_settings(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_ENUM_FLAG); RNA_def_property_ui_text(prop, "Snap Element", "Type of element to snap to"); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */ - + /* node editor uses own set of snap modes */ prop = RNA_def_property(srna, "snap_node_element", PROP_ENUM, PROP_NONE); RNA_def_property_enum_bitflag_sdna(prop, NULL, "snap_node_mode"); RNA_def_property_enum_items(prop, rna_enum_snap_node_element_items); RNA_def_property_ui_text(prop, "Snap Node Element", "Type of element to snap to"); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */ - + /* image editor uses own set of snap modes */ prop = RNA_def_property(srna, "snap_uv_element", PROP_ENUM, PROP_NONE); RNA_def_property_enum_bitflag_sdna(prop, NULL, "snap_uv_mode"); @@ -2651,7 +2651,7 @@ static void rna_def_tool_settings(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Snap Peel Object", "Consider objects as whole when finding volume center"); RNA_def_property_ui_icon(prop, ICON_SNAP_PEEL_OBJECT, 0); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */ - + prop = RNA_def_property(srna, "use_snap_project", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "snap_flag", SCE_SNAP_PROJECT); RNA_def_property_ui_text(prop, "Project Individual Elements", @@ -2671,14 +2671,14 @@ static void rna_def_tool_settings(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Use Continuous Drawing", "Allow drawing multiple strokes at a time with Grease Pencil"); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* xxx: need toolbar to be redrawn... */ - + prop = RNA_def_property(srna, "use_gpencil_additive_drawing", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "gpencil_flags", GP_TOOL_FLAG_RETAIN_LAST); RNA_def_property_ui_text(prop, "Use Additive Drawing", "When creating new frames, the strokes from the previous/active frame " "are included as the basis for the new one"); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); - + prop = RNA_def_property(srna, "use_gpencil_draw_onback", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "gpencil_flags", GP_TOOL_FLAG_PAINT_ONBACK); RNA_def_property_ui_text(prop, "Draw Strokes on Back", @@ -2691,17 +2691,17 @@ static void rna_def_tool_settings(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Grease Pencil Source", "Data-block where active Grease Pencil data is found from"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); - + prop = RNA_def_property(srna, "gpencil_sculpt", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "gp_sculpt"); RNA_def_property_struct_type(prop, "GPencilSculptSettings"); RNA_def_property_ui_text(prop, "Grease Pencil Sculpt", "Settings for stroke sculpting tools and brushes"); - + prop = RNA_def_property(srna, "gpencil_interpolate", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "gp_interpolate"); RNA_def_property_struct_type(prop, "GPencilInterpolateSettings"); - RNA_def_property_ui_text(prop, "Grease Pencil Interpolate", + RNA_def_property_ui_text(prop, "Grease Pencil Interpolate", "Settings for Grease Pencil Interpolation tools"); /* Grease Pencil - Drawing brushes */ @@ -2717,12 +2717,12 @@ static void rna_def_tool_settings(BlenderRNA *brna) RNA_def_property_enum_items(prop, gpencil_stroke_placement_items); RNA_def_property_ui_text(prop, "Stroke Placement (3D View)", ""); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); - + prop = RNA_def_property(srna, "use_gpencil_stroke_endpoints", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "gpencil_v3d_align", GP_PROJECT_DEPTH_STROKE_ENDPOINTS); RNA_def_property_ui_text(prop, "Only Endpoints", "Only use the first and last parts of the stroke for snapping"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); - + /* Grease Pencil - 2D Views Stroke Placement */ prop = RNA_def_property(srna, "gpencil_stroke_placement_view2d", PROP_ENUM, PROP_NONE); RNA_def_property_enum_bitflag_sdna(prop, NULL, "gpencil_v2d_align"); @@ -2736,7 +2736,7 @@ static void rna_def_tool_settings(BlenderRNA *brna) RNA_def_property_enum_items(prop, gpencil_stroke_placement_items); RNA_def_property_ui_text(prop, "Stroke Placement (Sequencer Preview)", ""); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); - + /* Grease Pencil - Image Editor Stroke Placement */ prop = RNA_def_property(srna, "gpencil_stroke_placement_image_editor", PROP_ENUM, PROP_NONE); RNA_def_property_enum_bitflag_sdna(prop, NULL, "gpencil_ima_align"); @@ -2744,36 +2744,36 @@ static void rna_def_tool_settings(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Stroke Placement (Image Editor)", ""); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); - + /* Auto Keying */ prop = RNA_def_property(srna, "use_keyframe_insert_auto", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "autokey_mode", AUTOKEY_ON); RNA_def_property_ui_text(prop, "Auto Keying", "Automatic keyframe insertion for Objects and Bones"); RNA_def_property_ui_icon(prop, ICON_REC, 0); - + prop = RNA_def_property(srna, "auto_keying_mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_bitflag_sdna(prop, NULL, "autokey_mode"); RNA_def_property_enum_items(prop, auto_key_items); RNA_def_property_ui_text(prop, "Auto-Keying Mode", "Mode of automatic keyframe insertion for Objects and Bones"); - + prop = RNA_def_property(srna, "use_record_with_nla", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "autokey_flag", ANIMRECORD_FLAG_WITHNLA); RNA_def_property_ui_text(prop, "Layered", "Add a new NLA Track + Strip for every loop/pass made over the animation " "to allow non-destructive tweaking"); - + prop = RNA_def_property(srna, "use_keyframe_insert_keyingset", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "autokey_flag", AUTOKEY_FLAG_ONLYKEYINGSET); RNA_def_property_ui_text(prop, "Auto Keyframe Insert Keying Set", "Automatic keyframe insertion using active Keying Set only"); RNA_def_property_ui_icon(prop, ICON_KEYINGSET, 0); - + /* Keyframing */ prop = RNA_def_property(srna, "keyframe_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "keyframe_type"); RNA_def_property_enum_items(prop, rna_enum_beztriple_keyframe_type_items); RNA_def_property_ui_text(prop, "New Keyframe Type", "Type of keyframes to create when inserting keyframes"); - + /* UV */ prop = RNA_def_property(srna, "uv_select_mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "uv_selectmode"); @@ -3157,7 +3157,7 @@ static void rna_def_unit_settings(BlenderRNA *brna) {USER_UNIT_IMPERIAL, "IMPERIAL", 0, "Imperial", ""}, {0, NULL, 0, NULL, NULL} }; - + static const EnumPropertyItem rotation_units[] = { {0, "DEGREES", 0, "Degrees", "Use degrees for measuring angles and rotations"}, {USER_UNIT_ROT_RADIANS, "RADIANS", 0, "Radians", ""}, @@ -3172,7 +3172,7 @@ static void rna_def_unit_settings(BlenderRNA *brna) RNA_def_property_enum_items(prop, unit_systems); RNA_def_property_ui_text(prop, "Unit System", "The unit system to use for button display"); RNA_def_property_update(prop, NC_WINDOW, NULL); - + prop = RNA_def_property(srna, "system_rotation", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, rotation_units); RNA_def_property_ui_text(prop, "Rotation Units", "Unit to use for displaying/editing rotation values"); @@ -3284,7 +3284,7 @@ void rna_def_view_layer_common(StructRNA *srna, int scene) RNA_def_property_ui_text(prop, "Z", "Deliver Z values pass"); if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update"); else RNA_def_property_clear_flag(prop, PROP_EDITABLE); - + prop = RNA_def_property(srna, "use_pass_vector", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "passflag", SCE_PASS_VECTOR); RNA_def_property_ui_text(prop, "Vector", "Deliver speed vector pass"); @@ -3338,7 +3338,7 @@ void rna_def_view_layer_common(StructRNA *srna, int scene) RNA_def_property_ui_text(prop, "AO", "Deliver AO pass"); if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update"); else RNA_def_property_clear_flag(prop, PROP_EDITABLE); - + prop = RNA_def_property(srna, "use_pass_emit", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "passflag", SCE_PASS_EMIT); RNA_def_property_ui_text(prop, "Emit", "Deliver emission pass"); @@ -3410,7 +3410,7 @@ void rna_def_view_layer_common(StructRNA *srna, int scene) RNA_def_property_ui_text(prop, "Transmission Color", "Deliver transmission color pass"); if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update"); else RNA_def_property_clear_flag(prop, PROP_EDITABLE); - + prop = RNA_def_property(srna, "use_pass_subsurface_direct", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "passflag", SCE_PASS_SUBSURFACE_DIRECT); RNA_def_property_ui_text(prop, "Subsurface Direct", "Deliver subsurface direct pass"); @@ -4751,7 +4751,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + static const EnumPropertyItem alpha_mode_items[] = { {R_ADDSKY, "SKY", 0, "Sky", "Transparent pixels are filled with sky color"}, {R_ALPHAPREMUL, "TRANSPARENT", 0, "Transparent", "World background is transparent with premultiplied alpha"}, @@ -4845,7 +4845,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna) RNA_def_property_range(prop, 4, 65536); RNA_def_property_ui_text(prop, "Resolution X", "Number of horizontal pixels in the rendered image"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_SceneCamera_update"); - + prop = RNA_def_property(srna, "resolution_y", PROP_INT, PROP_PIXEL); RNA_def_property_int_sdna(prop, NULL, "ysch"); RNA_def_property_flag(prop, PROP_PROPORTIONAL); @@ -4853,7 +4853,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna) RNA_def_property_range(prop, 4, 65536); RNA_def_property_ui_text(prop, "Resolution Y", "Number of vertical pixels in the rendered image"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_SceneCamera_update"); - + prop = RNA_def_property(srna, "resolution_percentage", PROP_INT, PROP_PERCENTAGE); RNA_def_property_int_sdna(prop, NULL, "size"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); @@ -4861,14 +4861,14 @@ static void rna_def_scene_render_data(BlenderRNA *brna) RNA_def_property_ui_range(prop, 1, 100, 10, 1); RNA_def_property_ui_text(prop, "Resolution %", "Percentage scale for render resolution"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); - + prop = RNA_def_property(srna, "tile_x", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "tilex"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_range(prop, 8, 65536); RNA_def_property_ui_text(prop, "Tile X", "Horizontal tile size to use while rendering"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); - + prop = RNA_def_property(srna, "tile_y", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "tiley"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); @@ -4898,7 +4898,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Pixel Aspect X", "Horizontal aspect ratio - for anamorphic or non-square pixel output"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_SceneCamera_update"); - + prop = RNA_def_property(srna, "pixel_aspect_y", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "yasp"); RNA_def_property_flag(prop, PROP_PROPORTIONAL); @@ -4921,7 +4921,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna) RNA_def_property_ui_range(prop, 1, 120, 1, -1); RNA_def_property_ui_text(prop, "FPS", "Framerate, expressed in frames per second"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_fps_update"); - + prop = RNA_def_property(srna, "fps_base", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "frs_sec_base"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); @@ -4929,7 +4929,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna) RNA_def_property_ui_range(prop, 0.1f, 120.0f, 2, -1); RNA_def_property_ui_text(prop, "FPS Base", "Framerate base"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_fps_update"); - + /* frame mapping */ prop = RNA_def_property(srna, "frame_map_old", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "framapto"); @@ -4937,7 +4937,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna) RNA_def_property_range(prop, 1, 900); RNA_def_property_ui_text(prop, "Frame Map Old", "Old mapping value in frames"); RNA_def_property_update(prop, NC_SCENE | ND_FRAME, "rna_Scene_framelen_update"); - + prop = RNA_def_property(srna, "frame_map_new", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "images"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); @@ -4945,7 +4945,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Frame Map New", "How many frames the Map Old will last"); RNA_def_property_update(prop, NC_SCENE | ND_FRAME, "rna_Scene_framelen_update"); - + prop = RNA_def_property(srna, "dither_intensity", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "dither_intensity"); RNA_def_property_range(prop, 0.0f, 2.0f); @@ -4971,14 +4971,14 @@ static void rna_def_scene_render_data(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Anti-Aliasing", "Render and combine multiple samples per pixel to prevent jagged edges"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); - + prop = RNA_def_property(srna, "antialiasing_samples", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "osa"); RNA_def_property_enum_items(prop, fixed_oversample_items); RNA_def_property_ui_text(prop, "Anti-Aliasing Samples", "Amount of anti-aliasing samples per pixel"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); - + prop = RNA_def_property(srna, "use_freestyle", PROP_BOOLEAN, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_boolean_sdna(prop, NULL, "mode", R_EDGE_FRS); @@ -4994,21 +4994,21 @@ static void rna_def_scene_render_data(BlenderRNA *brna) "Number of CPU threads to use simultaneously while rendering " "(for multi-core/CPU systems)"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); - + prop = RNA_def_property(srna, "threads_mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_bitflag_sdna(prop, NULL, "mode"); RNA_def_property_enum_items(prop, threads_mode_items); RNA_def_property_enum_funcs(prop, "rna_RenderSettings_threads_mode_get", NULL, NULL); RNA_def_property_ui_text(prop, "Threads Mode", "Determine the amount of render threads used"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); - + /* motion blur */ prop = RNA_def_property(srna, "use_motion_blur", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "mode", R_MBLUR); RNA_def_property_ui_text(prop, "Motion Blur", "Use multi-sampled 3D scene motion blur"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_glsl_update"); - + prop = RNA_def_property(srna, "motion_blur_shutter", PROP_FLOAT, PROP_UNSIGNED); RNA_def_property_float_sdna(prop, NULL, "blurfac"); RNA_def_property_ui_range(prop, 0.01f, 2.0f, 1, 2); @@ -5038,7 +5038,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_ui_text(prop, "Border", "Render a user-defined border region, within the frame size "); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); - + prop = RNA_def_property(srna, "border_min_x", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "border.xmin"); RNA_def_property_range(prop, 0.0f, 1.0f); @@ -5066,24 +5066,24 @@ static void rna_def_scene_render_data(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_ui_text(prop, "Border Maximum Y", "Maximum Y value for the render border"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); - + prop = RNA_def_property(srna, "use_crop_to_border", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "mode", R_CROP); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_ui_text(prop, "Crop to Border", "Crop the rendered frame to the defined border size"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); - + prop = RNA_def_property(srna, "use_placeholder", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "mode", R_TOUCH); RNA_def_property_ui_text(prop, "Placeholders", "Create empty placeholder files while rendering frames (similar to Unix 'touch')"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); - + prop = RNA_def_property(srna, "use_overwrite", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "mode", R_NO_OVERWRITE); RNA_def_property_ui_text(prop, "Overwrite", "Overwrite existing files while rendering"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); - + prop = RNA_def_property(srna, "use_compositing", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "scemode", R_DOCOMP); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); @@ -5091,7 +5091,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna) "Process the render result through the compositing pipeline, " "if compositing nodes are enabled"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); - + prop = RNA_def_property(srna, "use_sequencer", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "scemode", R_DOSEQ); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); @@ -5099,7 +5099,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna) "Process the render (and composited) result through the video sequence " "editor pipeline, if sequencer strips exist"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); - + prop = RNA_def_property(srna, "use_file_extension", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "scemode", R_EXTENSION); RNA_def_property_ui_text(prop, "File Extensions", @@ -5131,7 +5131,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna) "Save tiles for all RenderLayers and SceneNodes to files in the temp directory " "(saves memory, required for Full Sample)"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); - + prop = RNA_def_property(srna, "use_full_sample", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "scemode", R_FULL_SAMPLE); RNA_def_property_ui_text(prop, "Full Sample", @@ -5167,7 +5167,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); /* Bake */ - + prop = RNA_def_property(srna, "bake_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_bitflag_sdna(prop, NULL, "bake_mode"); RNA_def_property_enum_items(prop, bake_mode_items); @@ -5228,23 +5228,23 @@ static void rna_def_scene_render_data(BlenderRNA *brna) "apply a user scale to the derivative map"); /* stamp */ - + prop = RNA_def_property(srna, "use_stamp_time", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "stamp", R_STAMP_TIME); RNA_def_property_ui_text(prop, "Stamp Time", "Include the rendered frame timecode as HH:MM:SS.FF in image metadata"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); - + prop = RNA_def_property(srna, "use_stamp_date", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "stamp", R_STAMP_DATE); RNA_def_property_ui_text(prop, "Stamp Date", "Include the current date in image/video metadata"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); - + prop = RNA_def_property(srna, "use_stamp_frame", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "stamp", R_STAMP_FRAME); RNA_def_property_ui_text(prop, "Stamp Frame", "Include the frame number in image metadata"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); - + prop = RNA_def_property(srna, "use_stamp_frame_range", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "stamp", R_STAMP_FRAME_RANGE); RNA_def_property_ui_text(prop, "Stamp Frame", "Include the rendered frame range in image/video metadata"); @@ -5259,27 +5259,27 @@ static void rna_def_scene_render_data(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "stamp", R_STAMP_CAMERALENS); RNA_def_property_ui_text(prop, "Stamp Lens", "Include the active camera's lens in image metadata"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); - + prop = RNA_def_property(srna, "use_stamp_scene", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "stamp", R_STAMP_SCENE); RNA_def_property_ui_text(prop, "Stamp Scene", "Include the name of the active scene in image/video metadata"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); - + prop = RNA_def_property(srna, "use_stamp_note", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "stamp", R_STAMP_NOTE); RNA_def_property_ui_text(prop, "Stamp Note", "Include a custom note in image/video metadata"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); - + prop = RNA_def_property(srna, "use_stamp_marker", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "stamp", R_STAMP_MARKER); RNA_def_property_ui_text(prop, "Stamp Marker", "Include the name of the last marker in image metadata"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); - + prop = RNA_def_property(srna, "use_stamp_filename", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "stamp", R_STAMP_FILENAME); RNA_def_property_ui_text(prop, "Stamp Filename", "Include the .blend filename in image/video metadata"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); - + prop = RNA_def_property(srna, "use_stamp_sequencer_strip", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "stamp", R_STAMP_SEQSTRIP); RNA_def_property_ui_text(prop, "Stamp Sequence Strip", @@ -5290,7 +5290,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "stamp", R_STAMP_RENDERTIME); RNA_def_property_ui_text(prop, "Stamp Render Time", "Include the render time in image metadata"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); - + prop = RNA_def_property(srna, "stamp_note_text", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "stamp_udata"); RNA_def_property_ui_text(prop, "Stamp Note Text", "Custom text to appear in the stamp note"); @@ -5328,7 +5328,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna) RNA_def_property_range(prop, 0.0, 1.0); RNA_def_property_ui_text(prop, "Text Color", "Color to use for stamp text"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); - + prop = RNA_def_property(srna, "stamp_background", PROP_FLOAT, PROP_COLOR); RNA_def_property_float_sdna(prop, NULL, "bg_stamp"); RNA_def_property_array(prop, 4); @@ -5560,7 +5560,7 @@ static void rna_def_scene_keying_sets(BlenderRNA *brna, PropertyRNA *cprop) "rna_Scene_active_keying_set_set", NULL, NULL); RNA_def_property_ui_text(prop, "Active Keying Set", "Active Keying Set used to insert/delete keyframes"); RNA_def_property_update(prop, NC_SCENE | ND_KEYINGSET, NULL); - + prop = RNA_def_property(srna, "active_index", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "active_keyingset"); RNA_def_property_int_funcs(prop, "rna_Scene_active_keying_set_index_get", @@ -5574,14 +5574,14 @@ static void rna_def_scene_keying_sets_all(BlenderRNA *brna, PropertyRNA *cprop) { StructRNA *srna; PropertyRNA *prop; - + RNA_def_property_srna(cprop, "KeyingSetsAll"); srna = RNA_def_struct(brna, "KeyingSetsAll", NULL); RNA_def_struct_sdna(srna, "Scene"); RNA_def_struct_ui_text(srna, "Keying Sets All", "All available keying sets"); - + /* NOTE: no add/remove available here, without screwing up this amalgamated list... */ - + prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "KeyingSet"); RNA_def_property_flag(prop, PROP_EDITABLE); @@ -5589,7 +5589,7 @@ static void rna_def_scene_keying_sets_all(BlenderRNA *brna, PropertyRNA *cprop) "rna_Scene_active_keying_set_set", NULL, NULL); RNA_def_property_ui_text(prop, "Active Keying Set", "Active Keying Set used to insert/delete keyframes"); RNA_def_property_update(prop, NC_SCENE | ND_KEYINGSET, NULL); - + prop = RNA_def_property(srna, "active_index", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "active_keyingset"); RNA_def_property_int_funcs(prop, "rna_Scene_active_keying_set_index_get", @@ -5673,36 +5673,6 @@ static void rna_def_scene_display(BlenderRNA *brna) StructRNA *srna; PropertyRNA *prop; -#ifdef WITH_CLAY_ENGINE - static const EnumPropertyItem clay_matcap_items[] = { - {1, "01", ICON_MATCAP_01, "", ""}, - {2, "02", ICON_MATCAP_02, "", ""}, - {3, "03", ICON_MATCAP_03, "", ""}, - {4, "04", ICON_MATCAP_04, "", ""}, - {5, "05", ICON_MATCAP_05, "", ""}, - {6, "06", ICON_MATCAP_06, "", ""}, - {7, "07", ICON_MATCAP_07, "", ""}, - {8, "08", ICON_MATCAP_08, "", ""}, - {9, "09", ICON_MATCAP_09, "", ""}, - {10, "10", ICON_MATCAP_10, "", ""}, - {11, "11", ICON_MATCAP_11, "", ""}, - {12, "12", ICON_MATCAP_12, "", ""}, - {13, "13", ICON_MATCAP_13, "", ""}, - {14, "14", ICON_MATCAP_14, "", ""}, - {15, "15", ICON_MATCAP_15, "", ""}, - {16, "16", ICON_MATCAP_16, "", ""}, - {17, "17", ICON_MATCAP_17, "", ""}, - {19, "18", ICON_MATCAP_18, "", ""}, - {19, "19", ICON_MATCAP_19, "", ""}, - {20, "20", ICON_MATCAP_20, "", ""}, - {21, "21", ICON_MATCAP_21, "", ""}, - {22, "22", ICON_MATCAP_22, "", ""}, - {23, "23", ICON_MATCAP_23, "", ""}, - {24, "24", ICON_MATCAP_24, "", ""}, - {0, NULL, 0, NULL, NULL} - }; -#endif - static float default_light_direction[3] = {-M_SQRT1_3, -M_SQRT1_3, M_SQRT1_3}; srna = RNA_def_struct(brna, "SceneDisplay", NULL); @@ -5726,43 +5696,6 @@ static void rna_def_scene_display(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_update(prop, NC_SCENE | NA_EDITED, "rna_Scene_set_update"); -#ifdef WITH_CLAY_ENGINE - /* Matcap. */ - prop = RNA_def_property(srna, "matcap_icon", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, clay_matcap_items); - RNA_def_property_enum_default(prop, 1); - RNA_def_property_ui_text(prop, "Matcap", "Image to use for Material Capture by this material"); - - prop = RNA_def_property(srna, "matcap_rotation", PROP_FLOAT, PROP_FACTOR); - RNA_def_property_float_default(prop, 0.0f); - RNA_def_property_range(prop, 0.0f, 1.0f); - RNA_def_property_ui_text(prop, "Matcap Rotation", "Orientation of the matcap on the model"); - - prop = RNA_def_property(srna, "matcap_hue", PROP_FLOAT, PROP_FACTOR); - RNA_def_property_float_default(prop, 0.5f); - RNA_def_property_range(prop, 0.0f, 1.0f); - RNA_def_property_ui_text(prop, "Matcap Hue Shift", "Hue correction of the matcap"); - - prop = RNA_def_property(srna, "matcap_saturation", PROP_FLOAT, PROP_FACTOR); - RNA_def_property_float_default(prop, 0.5f); - RNA_def_property_range(prop, 0.0f, 1.0f); - RNA_def_property_ui_text(prop, "Matcap Saturation", "Saturation correction of the matcap"); - - prop = RNA_def_property(srna, "matcap_value", PROP_FLOAT, PROP_FACTOR); - RNA_def_property_float_default(prop, 0.5f); - RNA_def_property_range(prop, 0.0f, 1.0f); - RNA_def_property_ui_text(prop, "Matcap Value", "Value correction of the matcap"); - - prop = RNA_def_property(srna, "matcap_ssao_factor_cavity", PROP_FLOAT, PROP_NONE); - RNA_def_property_float_default(prop, 1.0f); - RNA_def_property_ui_text(prop, "Cavity Strength", "Strength of the Cavity effect"); - RNA_def_property_range(prop, 0.0f, 250.0f); - - prop = RNA_def_property(srna, "matcap_ssao_factor_edge", PROP_FLOAT, PROP_NONE); - RNA_def_property_float_default(prop, 1.0f); - RNA_def_property_ui_text(prop, "Edge Strength", "Strength of the Edge effect"); - RNA_def_property_range(prop, 0.0f, 250.0f); - prop = RNA_def_property(srna, "matcap_ssao_distance", PROP_FLOAT, PROP_NONE); RNA_def_property_float_default(prop, 0.2f); RNA_def_property_ui_text(prop, "Distance", "Distance of object that contribute to the Cavity/Edge effect"); @@ -5779,12 +5712,6 @@ static void rna_def_scene_display(BlenderRNA *brna) RNA_def_property_int_default(prop, 16); RNA_def_property_ui_text(prop, "Samples", "Number of samples"); RNA_def_property_range(prop, 1, 500); - - prop = RNA_def_property(srna, "matcap_hair_brightness_randomness", PROP_FLOAT, PROP_NONE); - RNA_def_property_float_default(prop, 0.0f); - RNA_def_property_ui_text(prop, "Hair Brightness Randomness", "Brightness randomness for hair"); - RNA_def_property_range(prop, 0.0f, 1.0f); -#endif } static void rna_def_scene_eevee(BlenderRNA *brna) @@ -6177,7 +6104,7 @@ void RNA_def_scene(BlenderRNA *brna) FunctionRNA *func; PropertyRNA *parm; - + static const EnumPropertyItem audio_distance_model_items[] = { {0, "NONE", 0, "None", "No distance attenuation"}, {1, "INVERSE", 0, "Inverse", "Inverse distance model"}, @@ -6202,7 +6129,7 @@ void RNA_def_scene(BlenderRNA *brna) "defining time and render related settings"); RNA_def_struct_ui_icon(srna, ICON_SCENE_DATA); RNA_def_struct_clear_flag(srna, STRUCT_ID_REFCOUNT); - + /* Global Settings */ prop = RNA_def_property(srna, "camera", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_EDITABLE); @@ -6270,7 +6197,7 @@ void RNA_def_scene(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Current Frame", "Current Frame, to update animation data from python frame_set() instead"); RNA_def_property_update(prop, NC_SCENE | ND_FRAME, "rna_Scene_frame_update"); - + prop = RNA_def_property(srna, "frame_subframe", PROP_FLOAT, PROP_TIME); RNA_def_property_float_sdna(prop, NULL, "r.subframe"); RNA_def_property_ui_text(prop, "Current Sub-Frame", ""); @@ -6295,7 +6222,7 @@ void RNA_def_scene(BlenderRNA *brna) RNA_def_property_int_default(prop, 1); RNA_def_property_ui_text(prop, "Start Frame", "First frame of the playback/rendering range"); RNA_def_property_update(prop, NC_SCENE | ND_FRAME_RANGE, NULL); - + prop = RNA_def_property(srna, "frame_end", PROP_INT, PROP_TIME); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_int_sdna(prop, NULL, "r.efra"); @@ -6304,7 +6231,7 @@ void RNA_def_scene(BlenderRNA *brna) RNA_def_property_int_default(prop, 250); RNA_def_property_ui_text(prop, "End Frame", "Final frame of the playback/rendering range"); RNA_def_property_update(prop, NC_SCENE | ND_FRAME_RANGE, NULL); - + prop = RNA_def_property(srna, "frame_step", PROP_INT, PROP_TIME); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_int_sdna(prop, NULL, "r.frame_step"); @@ -6313,7 +6240,7 @@ void RNA_def_scene(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Frame Step", "Number of frames to skip forward while rendering/playing back each frame"); RNA_def_property_update(prop, NC_SCENE | ND_FRAME, NULL); - + prop = RNA_def_property(srna, "frame_current_final", PROP_FLOAT, PROP_TIME); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE); RNA_def_property_range(prop, MINAFRAME, MAXFRAME); @@ -6338,14 +6265,14 @@ void RNA_def_scene(BlenderRNA *brna) "OpenGL renders instead of the Render properties start/end frame range"); RNA_def_property_update(prop, NC_SCENE | ND_FRAME, NULL); RNA_def_property_ui_icon(prop, ICON_PREVIEW_RANGE, 0); - + prop = RNA_def_property(srna, "frame_preview_start", PROP_INT, PROP_TIME); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_int_sdna(prop, NULL, "r.psfra"); RNA_def_property_int_funcs(prop, NULL, "rna_Scene_preview_range_start_frame_set", NULL); RNA_def_property_ui_text(prop, "Preview Range Start Frame", "Alternative start frame for UI playback"); RNA_def_property_update(prop, NC_SCENE | ND_FRAME, NULL); - + prop = RNA_def_property(srna, "frame_preview_end", PROP_INT, PROP_TIME); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_int_sdna(prop, NULL, "r.pefra"); @@ -6368,16 +6295,16 @@ void RNA_def_scene(BlenderRNA *brna) "Consider keyframes for active Object and/or its selected bones only " "(in timeline and when jumping between keyframes)"); RNA_def_property_update(prop, NC_SCENE | ND_FRAME, NULL); - + /* Stamp */ prop = RNA_def_property(srna, "use_stamp_note", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "r.stamp_udata"); RNA_def_property_ui_text(prop, "Stamp Note", "User defined note for the render stamping"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); - + /* Animation Data (for Scene) */ rna_def_animdata_common(srna); - + /* Readonly Properties */ prop = RNA_def_property(srna, "is_nla_tweakmode", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SCE_NLA_EDIT_ON); @@ -6385,7 +6312,7 @@ void RNA_def_scene(BlenderRNA *brna) RNA_def_property_ui_text(prop, "NLA TweakMode", "Whether there is any action referenced by NLA being edited (strictly read-only)"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_GRAPH, NULL); - + /* Frame dropping flag for playback and sync enum */ #if 0 /* XXX: Is this actually needed? */ prop = RNA_def_property(srna, "use_frame_drop", PROP_BOOLEAN, PROP_NONE); @@ -6412,13 +6339,13 @@ void RNA_def_scene(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); RNA_def_property_ui_text(prop, "Use Nodes", "Enable the compositing node tree"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_use_nodes_update"); - + /* Sequencer */ prop = RNA_def_property(srna, "sequence_editor", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "ed"); RNA_def_property_struct_type(prop, "SequenceEditor"); RNA_def_property_ui_text(prop, "Sequence Editor", ""); - + /* Keying Sets */ prop = RNA_def_property(srna, "keying_sets", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "keyingsets", NULL); @@ -6426,7 +6353,7 @@ void RNA_def_scene(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Absolute Keying Sets", "Absolute Keying Sets for this Scene"); RNA_def_property_update(prop, NC_SCENE | ND_KEYINGSET, NULL); rna_def_scene_keying_sets(brna, prop); - + prop = RNA_def_property(srna, "keying_sets_all", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_funcs(prop, "rna_Scene_all_keyingsets_begin", "rna_Scene_all_keyingsets_next", "rna_iterator_listbase_end", "rna_iterator_listbase_get", @@ -6436,14 +6363,14 @@ void RNA_def_scene(BlenderRNA *brna) "All Keying Sets available for use (Builtins and Absolute Keying Sets for this Scene)"); RNA_def_property_update(prop, NC_SCENE | ND_KEYINGSET, NULL); rna_def_scene_keying_sets_all(brna, prop); - + /* Rigid Body Simulation */ prop = RNA_def_property(srna, "rigidbody_world", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "rigidbody_world"); RNA_def_property_struct_type(prop, "RigidBodyWorld"); RNA_def_property_ui_text(prop, "Rigid Body World", ""); RNA_def_property_update(prop, NC_SCENE, NULL); - + /* Tool Settings */ prop = RNA_def_property(srna, "tool_settings", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); @@ -6470,7 +6397,7 @@ void RNA_def_scene(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "physics_settings.flag", PHYS_GLOBAL_GRAVITY); RNA_def_property_ui_text(prop, "Global Gravity", "Use global gravity for all dynamics"); RNA_def_property_update(prop, 0, "rna_Physics_update"); - + /* Render Data */ prop = RNA_def_property(srna, "render", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); @@ -6505,7 +6432,7 @@ void RNA_def_scene(BlenderRNA *brna) RNA_def_property_struct_type(prop, "TransformOrientation"); RNA_def_property_pointer_funcs(prop, "rna_Scene_current_orientation_get", NULL, NULL, NULL); RNA_def_property_ui_text(prop, "Current Transform Orientation", "Current transformation orientation"); - + /* Audio Settings */ prop = RNA_def_property(srna, "use_audio", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_funcs(prop, "rna_Scene_use_audio_get", "rna_Scene_use_audio_set"); @@ -6560,7 +6487,7 @@ void RNA_def_scene(BlenderRNA *brna) RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); parm = RNA_def_string(func, "statistics", NULL, 0, "Statistics", ""); RNA_def_function_return(func, parm); - + /* Grease Pencil */ prop = RNA_def_property(srna, "grease_pencil", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "gpd"); diff --git a/source/blender/makesrna/intern/rna_scene_api.c b/source/blender/makesrna/intern/rna_scene_api.c index ba03472d8d5..003e2561a22 100644 --- a/source/blender/makesrna/intern/rna_scene_api.c +++ b/source/blender/makesrna/intern/rna_scene_api.c @@ -105,7 +105,7 @@ static void rna_Scene_frame_set(Scene *scene, Main *bmain, int frame, float subf /* cant use NC_SCENE|ND_FRAME because this causes wm_event_do_notifiers to call * BKE_scene_graph_update_for_newframe which will loose any un-keyed changes [#24690] */ /* WM_main_add_notifier(NC_SCENE|ND_FRAME, scene); */ - + /* instead just redraw the views */ WM_main_add_notifier(NC_WINDOW, NULL); } @@ -305,7 +305,7 @@ void RNA_api_scene(StructRNA *srna) parm = RNA_def_float_vector(func, "result", 2, NULL, 0.0f, FLT_MAX, "", "aspect", 0.0f, FLT_MAX); RNA_def_parameter_flags(parm, PROP_THICK_WRAP, 0); RNA_def_function_output(func, parm); - + /* Ray Cast */ func = RNA_def_function(srna, "ray_cast", "rna_Scene_ray_cast"); RNA_def_function_flag(func, FUNC_USE_MAIN); diff --git a/source/blender/makesrna/intern/rna_screen.c b/source/blender/makesrna/intern/rna_screen.c index 731333bd18a..e30b75b27bd 100644 --- a/source/blender/makesrna/intern/rna_screen.c +++ b/source/blender/makesrna/intern/rna_screen.c @@ -394,10 +394,10 @@ static void rna_def_view2d_api(StructRNA *srna) { FunctionRNA *func; PropertyRNA *parm; - + static const float view_default[2] = {0.0f, 0.0f}; static const int region_default[2] = {0.0f, 0.0f}; - + func = RNA_def_function(srna, "region_to_view", "rna_View2D_region_to_view"); RNA_def_function_ui_description(func, "Transform region coordinates to 2D view"); parm = RNA_def_int(func, "x", 0, INT_MIN, INT_MAX, "x", "Region x coordinate", -10000, 10000); @@ -428,9 +428,9 @@ static void rna_def_view2d(BlenderRNA *brna) srna = RNA_def_struct(brna, "View2D", NULL); RNA_def_struct_ui_text(srna, "View2D", "Scroll and zoom for a 2D region"); RNA_def_struct_sdna(srna, "View2D"); - + /* TODO more View2D properties could be exposed here (read-only) */ - + rna_def_view2d_api(srna); } diff --git a/source/blender/makesrna/intern/rna_sculpt_paint.c b/source/blender/makesrna/intern/rna_sculpt_paint.c index a26aceda3b9..b89b2185a38 100644 --- a/source/blender/makesrna/intern/rna_sculpt_paint.c +++ b/source/blender/makesrna/intern/rna_sculpt_paint.c @@ -40,8 +40,9 @@ #include "DNA_screen_types.h" #include "DNA_space_types.h" -#include "BKE_paint.h" +#include "BKE_main.h" #include "BKE_material.h" +#include "BKE_paint.h" #include "ED_image.h" @@ -104,9 +105,9 @@ const EnumPropertyItem rna_enum_symmetrize_direction_items[] = { #include "BKE_context.h" #include "BKE_DerivedMesh.h" -#include "BKE_pointcache.h" #include "BKE_particle.h" #include "BKE_pbvh.h" +#include "BKE_pointcache.h" #include "BKE_object.h" #include "DEG_depsgraph.h" @@ -183,7 +184,7 @@ static void rna_ParticleEdit_update(bContext *C, PointerRNA *UNUSED(ptr)) static void rna_ParticleEdit_tool_set(PointerRNA *ptr, int value) { ParticleEditSettings *pset = (ParticleEditSettings *)ptr->data; - + /* redraw hair completely if weight brush is/was used */ if ((pset->brushtype == PE_BRUSH_WEIGHT || value == PE_BRUSH_WEIGHT) && pset->object) { Object *ob = pset->object; @@ -238,7 +239,7 @@ static int rna_ParticleEdit_hair_get(PointerRNA *ptr) return (edit && edit->psys); } - + return 0; } @@ -402,7 +403,7 @@ static void rna_ImaPaint_canvas_update(bContext *C, PointerRNA *UNUSED(ptr)) Object *obedit = OBEDIT_FROM_OBACT(ob); bScreen *sc; Image *ima = scene->toolsettings->imapaint.canvas; - + for (sc = bmain->screen.first; sc; sc = sc->id.next) { ScrArea *sa; for (sa = sc->areabase.first; sa; sa = sa->next) { @@ -410,14 +411,14 @@ static void rna_ImaPaint_canvas_update(bContext *C, PointerRNA *UNUSED(ptr)) for (slink = sa->spacedata.first; slink; slink = slink->next) { if (slink->spacetype == SPACE_IMAGE) { SpaceImage *sima = (SpaceImage *)slink; - + if (!sima->pin) - ED_space_image_set(sima, scene, obedit, ima); + ED_space_image_set(bmain, sima, scene, obedit, ima); } } } } - + if (ob && ob->type == OB_MESH) { BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL); WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL); @@ -434,7 +435,7 @@ static PointerRNA rna_GPencilSculptSettings_brush_get(PointerRNA *ptr) { GP_BrushEdit_Settings *gset = (GP_BrushEdit_Settings *)ptr->data; GP_EditBrush_Data *brush = NULL; - + if ((gset->brushtype >= 0) && (gset->brushtype < TOT_GP_EDITBRUSH_TYPES)) brush = &gset->brush[gset->brushtype]; @@ -747,35 +748,35 @@ static void rna_def_image_paint(BlenderRNA *brna) "Image", "Set image for texture painting directly"}, {0, NULL, 0, NULL, NULL} }; - + srna = RNA_def_struct(brna, "ImagePaint", "Paint"); RNA_def_struct_sdna(srna, "ImagePaintSettings"); RNA_def_struct_path_func(srna, "rna_ImagePaintSettings_path"); RNA_def_struct_ui_text(srna, "Image Paint", "Properties of image and texture painting mode"); - /* functions */ + /* functions */ func = RNA_def_function(srna, "detect_data", "rna_ImaPaint_detect_data"); RNA_def_function_ui_description(func, "Check if required texpaint data exist"); /* return type */ RNA_def_function_return(func, RNA_def_boolean(func, "ok", 1, "", "")); - - /* booleans */ + + /* booleans */ prop = RNA_def_property(srna, "use_occlude", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", IMAGEPAINT_PROJECT_XRAY); RNA_def_property_ui_text(prop, "Occlude", "Only paint onto the faces directly under the brush (slower)"); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); - + prop = RNA_def_property(srna, "use_backface_culling", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", IMAGEPAINT_PROJECT_BACKFACE); RNA_def_property_ui_text(prop, "Cull", "Ignore faces pointing away from the view (faster)"); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); - + prop = RNA_def_property(srna, "use_normal_falloff", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", IMAGEPAINT_PROJECT_FLAT); RNA_def_property_ui_text(prop, "Normal", "Paint most on faces pointing towards the view"); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); - + prop = RNA_def_property(srna, "use_stencil_layer", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", IMAGEPAINT_PROJECT_LAYER_STENCIL); RNA_def_property_ui_text(prop, "Stencil Layer", "Set the mask layer from the UV map buttons"); @@ -796,13 +797,13 @@ static void rna_def_image_paint(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_EDITABLE | PROP_CONTEXT_UPDATE); RNA_def_property_ui_text(prop, "Canvas", "Image used as canvas"); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_ImaPaint_canvas_update"); - + prop = RNA_def_property(srna, "clone_image", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "clone"); RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Clone Image", "Image used as clone source"); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); - + prop = RNA_def_property(srna, "stencil_color", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_range(prop, 0.0, 1.0); RNA_def_property_float_sdna(prop, NULL, "stencil_col"); @@ -813,15 +814,15 @@ static void rna_def_image_paint(BlenderRNA *brna) RNA_def_property_range(prop, 0.0, 2.0); RNA_def_property_ui_text(prop, "Dither", "Amount of dithering when painting on byte images"); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); - + prop = RNA_def_property(srna, "use_clone_layer", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", IMAGEPAINT_PROJECT_LAYER_CLONE); RNA_def_property_ui_text(prop, "Clone Map", "Use another UV map as clone source, otherwise use the 3D cursor as the source"); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_ImaPaint_viewport_update"); - + /* integers */ - + prop = RNA_def_property(srna, "seam_bleed", PROP_INT, PROP_PIXEL); RNA_def_property_ui_range(prop, 0, 8, 0, -1); RNA_def_property_ui_text(prop, "Bleed", "Extend paint beyond the faces UVs to reduce seams (in pixels, slower)"); @@ -833,37 +834,37 @@ static void rna_def_image_paint(BlenderRNA *brna) prop = RNA_def_int_array(srna, "screen_grab_size", 2, NULL, 0, 0, "screen_grab_size", "Size to capture the image for re-projecting", 0, 0); RNA_def_property_range(prop, 512, 16384); - + prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE); RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); RNA_def_property_enum_items(prop, paint_type_items); RNA_def_property_ui_text(prop, "Mode", "Mode of operation for projection painting"); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_ImaPaint_mode_update"); - + /* Missing data */ prop = RNA_def_property(srna, "missing_uvs", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "missing_data", IMAGEPAINT_MISSING_UVS); RNA_def_property_ui_text(prop, "Missing UVs", "A UV layer is missing on the mesh"); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); - + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + prop = RNA_def_property(srna, "missing_materials", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "missing_data", IMAGEPAINT_MISSING_MATERIAL); RNA_def_property_ui_text(prop, "Missing Materials", "The mesh is missing materials"); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); prop = RNA_def_property(srna, "missing_stencil", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "missing_data", IMAGEPAINT_MISSING_STENCIL); RNA_def_property_ui_text(prop, "Missing Stencil", "Image Painting does not have a stencil"); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); prop = RNA_def_property(srna, "missing_texture", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "missing_data", IMAGEPAINT_MISSING_TEX); RNA_def_property_ui_text(prop, "Missing Texture", "Image Painting does not have a texture to paint on"); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); } static void rna_def_particle_edit(BlenderRNA *brna) @@ -1060,10 +1061,10 @@ static void rna_def_gpencil_sculpt(BlenderRNA *brna) {0, "ADD", 0, "Add", "Add effect of brush"}, {GP_EDITBRUSH_FLAG_INVERT, "SUBTRACT", 0, "Subtract", "Subtract effect of brush"}, {0, NULL, 0, NULL, NULL}}; - + StructRNA *srna; PropertyRNA *prop; - + /* == Settings == */ srna = RNA_def_struct(brna, "GPencilSculptSettings", NULL); RNA_def_struct_sdna(srna, "GP_BrushEdit_Settings"); @@ -1075,18 +1076,18 @@ static void rna_def_gpencil_sculpt(BlenderRNA *brna) RNA_def_property_enum_items(prop, rna_enum_gpencil_sculpt_brush_items); RNA_def_property_ui_text(prop, "Tool", ""); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); - + prop = RNA_def_property(srna, "brush", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "GPencilSculptBrush"); RNA_def_property_pointer_funcs(prop, "rna_GPencilSculptSettings_brush_get", NULL, NULL, NULL); RNA_def_property_ui_text(prop, "Brush", ""); - + prop = RNA_def_property(srna, "use_select_mask", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_BRUSHEDIT_FLAG_SELECT_MASK); RNA_def_property_ui_text(prop, "Selection Mask", "Only sculpt selected stroke points"); RNA_def_property_ui_icon(prop, ICON_VERTEXSEL, 0); // FIXME: this needs a custom icon RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); - + prop = RNA_def_property(srna, "affect_position", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_BRUSHEDIT_FLAG_APPLY_POSITION); RNA_def_property_ui_text(prop, "Affect Position", "The brush affects the position of the point"); @@ -1132,23 +1133,23 @@ static void rna_def_gpencil_sculpt(BlenderRNA *brna) RNA_def_property_range(prop, 0.001, 1.0); RNA_def_property_ui_text(prop, "Strength", "Brush strength"); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); - + prop = RNA_def_property(srna, "use_pressure_strength", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_EDITBRUSH_FLAG_USE_PRESSURE); RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0); RNA_def_property_ui_text(prop, "Strength Pressure", "Enable tablet pressure sensitivity for strength"); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); - + prop = RNA_def_property(srna, "use_falloff", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_EDITBRUSH_FLAG_USE_FALLOFF); RNA_def_property_ui_text(prop, "Use Falloff", "Strength of brush decays with distance from cursor"); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); - + prop = RNA_def_property(srna, "affect_pressure", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_EDITBRUSH_FLAG_SMOOTH_PRESSURE); RNA_def_property_ui_text(prop, "Affect Pressure", "Affect pressure values as well when smoothing strokes"); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); - + prop = RNA_def_property(srna, "direction", PROP_ENUM, PROP_NONE); RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag"); RNA_def_property_enum_items(prop, prop_direction_items); diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c index 33621af69af..fb6953904b3 100644 --- a/source/blender/makesrna/intern/rna_sequencer.c +++ b/source/blender/makesrna/intern/rna_sequencer.c @@ -177,7 +177,7 @@ static int rna_SequenceEditor_elements_length(PointerRNA *ptr) /* Hack? copied from sequencer.c::reload_sequence_new_file() */ size_t olen = MEM_allocN_len(seq->strip->stripdata) / sizeof(struct StripElem); - + /* the problem with seq->strip->len and seq->len is that it's discounted from the offset (hard cut trim) */ return (int) olen; } @@ -232,7 +232,7 @@ static void rna_Sequence_start_frame_set(PointerRNA *ptr, int value) { Sequence *seq = (Sequence *)ptr->data; Scene *scene = (Scene *)ptr->id.data; - + BKE_sequence_translate(scene, seq, value - seq->start); do_sequence_frame_change_update(scene, seq); } @@ -283,7 +283,7 @@ static void rna_Sequence_frame_length_set(PointerRNA *ptr, int value) { Sequence *seq = (Sequence *)ptr->data; Scene *scene = (Scene *)ptr->id.data; - + BKE_sequence_tx_set_final_right(seq, BKE_sequence_tx_get_final_left(seq, false) + value); do_sequence_frame_change_update(scene, seq); } @@ -307,7 +307,7 @@ static void rna_Sequence_channel_set(PointerRNA *ptr, int value) Scene *scene = (Scene *)ptr->id.data; Editing *ed = BKE_sequencer_editing_get(scene, false); ListBase *seqbase = BKE_sequence_seqbase(&ed->seqbase, seq); - + /* check channel increment or decrement */ const int channel_delta = (value >= seq->machine) ? 1 : -1; seq->machine = value; @@ -480,16 +480,16 @@ static void rna_Sequence_name_set(PointerRNA *ptr, const char *value) Sequence *seq = (Sequence *)ptr->data; char oldname[sizeof(seq->name)]; AnimData *adt; - + /* make a copy of the old name first */ BLI_strncpy(oldname, seq->name + 2, sizeof(seq->name) - 2); - + /* copy the new name into the name slot */ BLI_strncpy_utf8(seq->name + 2, value, sizeof(seq->name) - 2); - + /* make sure the name is unique */ BKE_sequence_base_unique_name_recursive(&scene->ed->seqbase, seq); - + /* fix all the animation data which may link to this */ /* don't rename everywhere because these are per scene */ @@ -562,7 +562,7 @@ static StructRNA *rna_Sequence_refine(struct PointerRNA *ptr) static char *rna_Sequence_path(PointerRNA *ptr) { Sequence *seq = (Sequence *)ptr->data; - + /* sequencer data comes from scene... * TODO: would be nice to make SequenceEditor data a data-block of its own (for shorter paths) */ @@ -1121,11 +1121,11 @@ static void rna_def_strip_element(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + srna = RNA_def_struct(brna, "SequenceElement", NULL); RNA_def_struct_ui_text(srna, "Sequence Element", "Sequence strip data for a single frame"); RNA_def_struct_sdna(srna, "StripElem"); - + prop = RNA_def_property(srna, "filename", PROP_STRING, PROP_FILENAME); RNA_def_property_string_sdna(prop, NULL, "name"); RNA_def_property_ui_text(prop, "Filename", "Name of the source file"); @@ -1146,7 +1146,7 @@ static void rna_def_strip_crop(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + srna = RNA_def_struct(brna, "SequenceCrop", NULL); RNA_def_struct_ui_text(srna, "Sequence Crop", "Cropping parameters for a sequence strip"); RNA_def_struct_sdna(srna, "StripCrop"); @@ -1156,13 +1156,13 @@ static void rna_def_strip_crop(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Top", "Number of pixels to crop from the top"); RNA_def_property_ui_range(prop, 0, 4096, 1, -1); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceCrop_update"); - + prop = RNA_def_property(srna, "min_y", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "bottom"); RNA_def_property_ui_text(prop, "Bottom", "Number of pixels to crop from the bottom"); RNA_def_property_ui_range(prop, 0, 4096, 1, -1); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceCrop_update"); - + prop = RNA_def_property(srna, "min_x", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "left"); RNA_def_property_ui_text(prop, "Left", "Number of pixels to crop from the left side"); @@ -1182,7 +1182,7 @@ static void rna_def_strip_transform(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + srna = RNA_def_struct(brna, "SequenceTransform", NULL); RNA_def_struct_ui_text(srna, "Sequence Transform", "Transform parameters for a sequence strip"); RNA_def_struct_sdna(srna, "StripTransform"); @@ -1222,16 +1222,16 @@ static void rna_def_strip_proxy(BlenderRNA *brna) "changes in framerate or dropouts"}, {0, NULL, 0, NULL, NULL} }; - + srna = RNA_def_struct(brna, "SequenceProxy", NULL); RNA_def_struct_ui_text(srna, "Sequence Proxy", "Proxy parameters for a sequence strip"); RNA_def_struct_sdna(srna, "StripProxy"); - + prop = RNA_def_property(srna, "directory", PROP_STRING, PROP_DIRPATH); RNA_def_property_string_sdna(prop, NULL, "dir"); RNA_def_property_ui_text(prop, "Directory", "Location to store the proxy files"); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceProxy_update"); - + prop = RNA_def_property(srna, "filepath", PROP_STRING, PROP_FILEPATH); RNA_def_property_ui_text(prop, "Path", "Location of custom proxy file"); RNA_def_property_string_funcs(prop, "rna_Sequence_proxy_filepath_get", "rna_Sequence_proxy_filepath_length", @@ -1464,7 +1464,7 @@ static void rna_def_sequence(BlenderRNA *brna) {SEQ_TYPE_COLORMIX, "COLORMIX", 0, "Color Mix", ""}, {0, NULL, 0, NULL, NULL} }; - + srna = RNA_def_struct(brna, "Sequence", NULL); RNA_def_struct_ui_text(srna, "Sequence", "Sequence strip in the sequence editor"); RNA_def_struct_refine_func(srna, "rna_Sequence_refine"); @@ -1529,7 +1529,7 @@ static void rna_def_sequence(BlenderRNA *brna) RNA_def_property_range(prop, 1, MAXFRAME); RNA_def_property_ui_text(prop, "Length", "The length of the contents of this strip before the handles are applied"); - + prop = RNA_def_property(srna, "frame_start", PROP_INT, PROP_TIME); RNA_def_property_int_sdna(prop, NULL, "start"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); @@ -1537,7 +1537,7 @@ 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"); - + prop = RNA_def_property(srna, "frame_final_start", PROP_INT, PROP_TIME); RNA_def_property_int_sdna(prop, NULL, "startdisp"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); @@ -1579,14 +1579,14 @@ static void rna_def_sequence(BlenderRNA *brna) RNA_def_property_range(prop, 0, MAXFRAME); RNA_def_property_ui_text(prop, "Start Still", ""); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_frame_change_update"); - + prop = RNA_def_property(srna, "frame_still_end", PROP_INT, PROP_TIME); RNA_def_property_int_sdna(prop, NULL, "endstill"); // RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* overlap tests */ RNA_def_property_range(prop, 0, MAXFRAME); RNA_def_property_ui_text(prop, "End Still", ""); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_frame_change_update"); - + prop = RNA_def_property(srna, "channel", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "machine"); RNA_def_property_range(prop, 1, MAXSEQ); @@ -1606,14 +1606,14 @@ 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"); - + prop = RNA_def_property(srna, "blend_alpha", PROP_FLOAT, PROP_FACTOR); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(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"); - + prop = RNA_def_property(srna, "effect_fader", PROP_FLOAT, PROP_NONE); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3); @@ -1627,7 +1627,7 @@ static void rna_def_sequence(BlenderRNA *brna) "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"); - + prop = RNA_def_property(srna, "speed_factor", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "speed_fader"); @@ -1679,7 +1679,7 @@ static void rna_def_editor(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Meta Stack", "Meta strip stack, last is currently edited meta strip"); RNA_def_property_collection_funcs(prop, NULL, NULL, NULL, "rna_SequenceEditor_meta_stack_get", NULL, NULL, NULL, NULL); - + prop = RNA_def_property(srna, "active_strip", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "act_seq"); RNA_def_property_flag(prop, PROP_EDITABLE); @@ -1884,7 +1884,7 @@ static void rna_def_image(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + srna = RNA_def_struct(brna, "ImageSequence", "Sequence"); RNA_def_struct_ui_text(srna, "Image Sequence", "Sequence strip to load one or more images"); RNA_def_struct_sdna(srna, "Sequence"); @@ -1931,7 +1931,7 @@ static void rna_def_meta(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + srna = RNA_def_struct(brna, "MetaSequence", "Sequence"); RNA_def_struct_ui_text(srna, "Meta Sequence", "Sequence strip to group other strips as a single sequence strip"); RNA_def_struct_sdna(srna, "Sequence"); @@ -1950,7 +1950,7 @@ static void rna_def_scene(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + srna = RNA_def_struct(brna, "SceneSequence", "Sequence"); RNA_def_struct_ui_text(srna, "Scene Sequence", "Sequence strip to used the rendered image of a scene"); RNA_def_struct_sdna(srna, "Sequence"); @@ -2057,7 +2057,7 @@ static void rna_def_movieclip(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + srna = RNA_def_struct(brna, "MovieClipSequence", "Sequence"); RNA_def_struct_ui_text(srna, "MovieClip Sequence", "Sequence strip to load a video from the clip editor"); RNA_def_struct_sdna(srna, "Sequence"); @@ -2101,7 +2101,7 @@ static void rna_def_sound(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + srna = RNA_def_struct(brna, "SoundSequence", "Sequence"); RNA_def_struct_ui_text(srna, "Sound Sequence", "Sequence strip defining a sound to be played over a period of time"); @@ -2140,7 +2140,7 @@ static void rna_def_sound(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_AUDIO_DRAW_WAVEFORM); RNA_def_property_ui_text(prop, "Draw Waveform", "Whether to draw the sound's waveform"); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, NULL); - + rna_def_input(srna); } @@ -2160,7 +2160,7 @@ static void rna_def_effect(BlenderRNA *brna) static void rna_def_multicam(StructRNA *srna) { PropertyRNA *prop; - + prop = RNA_def_property(srna, "multicam_source", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "multicam_source"); RNA_def_property_range(prop, 0, MAXSEQ - 1); @@ -2173,7 +2173,7 @@ static void rna_def_multicam(StructRNA *srna) static void rna_def_wipe(StructRNA *srna) { PropertyRNA *prop; - + static const EnumPropertyItem wipe_type_items[] = { {0, "SINGLE", 0, "Single", ""}, {1, "DOUBLE", 0, "Double", ""}, @@ -2209,7 +2209,7 @@ static void rna_def_wipe(StructRNA *srna) 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"); - + 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); @@ -2223,37 +2223,37 @@ static void rna_def_glow(StructRNA *srna) PropertyRNA *prop; RNA_def_struct_sdna_from(srna, "GlowVars", "effectdata"); - + prop = RNA_def_property(srna, "threshold", PROP_FLOAT, PROP_NONE); 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"); - + prop = RNA_def_property(srna, "clamp", PROP_FLOAT, PROP_NONE); 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"); - + 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"); - + 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"); - + 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"); - + 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"); @@ -2284,43 +2284,43 @@ static void rna_def_transform(StructRNA *srna) 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"); - + 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"); - + 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"); - + 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"); - + 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"); - + prop = RNA_def_property(srna, "rotation_start", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "rotIni"); RNA_def_property_range(prop, -360.0f, 360.0f); RNA_def_property_ui_text(prop, "Rotation", "Degrees to rotate the input"); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_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"); - + 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 */ @@ -2352,7 +2352,7 @@ 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"); - + 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"); diff --git a/source/blender/makesrna/intern/rna_sequencer_api.c b/source/blender/makesrna/intern/rna_sequencer_api.c index d447d2972f6..da8b19a1ff6 100644 --- a/source/blender/makesrna/intern/rna_sequencer_api.c +++ b/source/blender/makesrna/intern/rna_sequencer_api.c @@ -74,7 +74,7 @@ static void rna_Sequence_update_rnafunc(ID *id, Sequence *self, int do_data) static void rna_Sequence_swap_internal(Sequence *seq_self, ReportList *reports, Sequence *seq_other) { const char *error_msg; - + if (BKE_sequence_swap(seq_self, seq_other, &error_msg) == 0) BKE_report(reports, RPT_ERROR, error_msg); } diff --git a/source/blender/makesrna/intern/rna_smoke.c b/source/blender/makesrna/intern/rna_smoke.c index 832d5b28bd1..b4c9e7ba3a2 100644 --- a/source/blender/makesrna/intern/rna_smoke.c +++ b/source/blender/makesrna/intern/rna_smoke.c @@ -243,7 +243,7 @@ static void rna_SmokeModifier_density_grid_get(PointerRNA *ptr, float *values) float *density; BLI_rw_mutex_lock(sds->fluid_mutex, THREAD_LOCK_READ); - + if (sds->flags & MOD_SMOKE_HIGHRES && sds->wt) density = smoke_turbulence_get_density(sds->wt); else @@ -326,12 +326,12 @@ static void rna_SmokeModifier_flame_grid_get(PointerRNA *ptr, float *values) float *flame; BLI_rw_mutex_lock(sds->fluid_mutex, THREAD_LOCK_READ); - + if (sds->flags & MOD_SMOKE_HIGHRES && sds->wt) flame = smoke_turbulence_get_flame(sds->wt); else flame = smoke_get_flame(sds->fluid); - + if (flame) memcpy(values, flame, size * sizeof(float)); else @@ -973,7 +973,7 @@ static void rna_def_smoke_flow_settings(BlenderRNA *brna) RNA_def_property_ui_range(prop, -10, 10, 1, 1); RNA_def_property_ui_text(prop, "Temp. Diff.", "Temperature difference to ambient temperature"); RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset"); - + prop = RNA_def_property(srna, "particle_system", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "psys"); RNA_def_property_struct_type(prop, "ParticleSystem"); diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 3daf4ca6fe0..5ce27a533b8 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -198,11 +198,6 @@ static const EnumPropertyItem rna_enum_studio_light_items[] = { {0, NULL, 0, NULL, NULL} }; -static const EnumPropertyItem rna_enum_matcap_items[] = { - {0, "DEFAULT", 0, "Default", ""}, - {0, NULL, 0, NULL, NULL} -}; - const EnumPropertyItem rna_enum_clip_editor_mode_items[] = { {SC_MODE_TRACKING, "TRACKING", ICON_ANIM_DATA, "Tracking", "Show tracking and solving tools"}, {SC_MODE_MASKEDIT, "MASK", ICON_MOD_MASK, "Mask", "Show mask editing tools"}, @@ -671,14 +666,18 @@ static const EnumPropertyItem *rna_3DViewShading_type_itemf( return item; } -static int rna_View3DShading_studio_light_orientation_get(PointerRNA *ptr) +/* Shading.selected_studio_light */ +static PointerRNA rna_View3DShading_selected_studio_light_get(PointerRNA *ptr) { View3D *v3d = (View3D *)ptr->data; - StudioLight *sl = BKE_studiolight_find(v3d->shading.studio_light, STUDIOLIGHT_FLAG_ALL); - return sl->flag & STUDIOLIGHT_FLAG_ORIENTATIONS; -} -static void rna_View3DShading_studio_light_orientation_set(PointerRNA *UNUSED(ptr), int UNUSED(value)) -{ + StudioLight *sl; + if (v3d->shading.light == V3D_LIGHTING_MATCAP) { + sl = BKE_studiolight_find(v3d->shading.matcap, STUDIOLIGHT_FLAG_ALL); + } + else { + sl = BKE_studiolight_find(v3d->shading.studio_light, STUDIOLIGHT_FLAG_ALL); + } + return rna_pointer_inherit_refine(ptr, &RNA_StudioLight, sl); } /* shading.light */ @@ -720,20 +719,36 @@ static const EnumPropertyItem *rna_View3DShading_light_itemf( static int rna_View3DShading_studio_light_get(PointerRNA *ptr) { View3D *v3d = (View3D *)ptr->data; + char *dna_storage = v3d->shading.studio_light; + int flag = STUDIOLIGHT_ORIENTATIONS_SOLID; - if (v3d->drawtype == OB_MATERIAL) { + if (v3d->drawtype == OB_SOLID && v3d->shading.light == V3D_LIGHTING_MATCAP) { + flag = STUDIOLIGHT_ORIENTATION_VIEWNORMAL; + dna_storage = v3d->shading.matcap; + } + else if (v3d->drawtype == OB_MATERIAL) { flag = STUDIOLIGHT_ORIENTATIONS_MATERIAL_MODE; } - StudioLight *sl = BKE_studiolight_find(v3d->shading.studio_light, flag); - BLI_strncpy(v3d->shading.studio_light, sl->name, FILE_MAXFILE); + StudioLight *sl = BKE_studiolight_find(dna_storage, flag); + BLI_strncpy(dna_storage, sl->name, FILE_MAXFILE); return sl->index; } static void rna_View3DShading_studio_light_set(PointerRNA *ptr, int value) { View3D *v3d = (View3D *)ptr->data; - StudioLight *sl = BKE_studiolight_findindex(value, STUDIOLIGHT_FLAG_ALL); - BLI_strncpy(v3d->shading.studio_light, sl->name, FILE_MAXFILE); + char *dna_storage = v3d->shading.studio_light; + + int flag = STUDIOLIGHT_ORIENTATIONS_SOLID; + if (v3d->drawtype == OB_SOLID && v3d->shading.light == V3D_LIGHTING_MATCAP) { + flag = STUDIOLIGHT_ORIENTATION_VIEWNORMAL; + dna_storage = v3d->shading.matcap; + } + else if (v3d->drawtype == OB_MATERIAL) { + flag = STUDIOLIGHT_ORIENTATIONS_MATERIAL_MODE; + } + StudioLight *sl = BKE_studiolight_findindex(value, flag); + BLI_strncpy(dna_storage, sl->name, FILE_MAXFILE); } static const EnumPropertyItem *rna_View3DShading_studio_light_itemf( @@ -744,70 +759,44 @@ static const EnumPropertyItem *rna_View3DShading_studio_light_itemf( EnumPropertyItem *item = NULL; int totitem = 0; - LISTBASE_FOREACH(StudioLight *, sl, BKE_studiolight_listbase()) { - int icon_id = sl->irradiance_icon_id; - bool show_studiolight = false; + if (v3d->drawtype == OB_SOLID && v3d->shading.light == V3D_LIGHTING_MATCAP) { + const int flags = (STUDIOLIGHT_EXTERNAL_FILE | STUDIOLIGHT_ORIENTATION_VIEWNORMAL); - if ((sl->flag & STUDIOLIGHT_INTERNAL)) { - /* always show internal lights */ - show_studiolight = true; - } - else { - switch (v3d->drawtype) { - case OB_SOLID: - case OB_TEXTURE: - show_studiolight = (sl->flag & (STUDIOLIGHT_ORIENTATION_WORLD | STUDIOLIGHT_ORIENTATION_CAMERA)) > 0; - break; - - case OB_MATERIAL: - show_studiolight = (sl->flag & STUDIOLIGHT_ORIENTATION_WORLD) > 0; - icon_id = sl->radiance_icon_id; - break; + LISTBASE_FOREACH(StudioLight *, sl, BKE_studiolight_listbase()) { + int icon_id = (v3d->shading.flag & V3D_SHADING_MATCAP_FLIP_X) ? sl->icon_id_matcap_flipped: sl->icon_id_matcap; + if ((sl->flag & flags) == flags) { + EnumPropertyItem tmp = {sl->index, sl->name, icon_id, sl->name, ""}; + RNA_enum_item_add(&item, &totitem, &tmp); } } - - if (show_studiolight) { - EnumPropertyItem tmp = {sl->index, sl->name, icon_id, sl->name, ""}; - RNA_enum_item_add(&item, &totitem, &tmp); - } } + else { + LISTBASE_FOREACH(StudioLight *, sl, BKE_studiolight_listbase()) { + int icon_id = sl->icon_id_irradiance; + bool show_studiolight = false; - RNA_enum_item_end(&item, &totitem); - *r_free = true; - return item; -} -/* Matcap studiolight */ -static int rna_View3DShading_matcap_get(PointerRNA *ptr) -{ - View3D *v3d = (View3D *)ptr->data; - StudioLight *sl = BKE_studiolight_find(v3d->shading.matcap, STUDIOLIGHT_ORIENTATION_VIEWNORMAL); - BLI_strncpy(v3d->shading.matcap, sl->name, FILE_MAXFILE); - return sl->index; -} - -static void rna_View3DShading_matcap_set(PointerRNA *ptr, int value) -{ - View3D *v3d = (View3D *)ptr->data; - StudioLight *sl = BKE_studiolight_findindex(value, STUDIOLIGHT_ORIENTATION_VIEWNORMAL); - BLI_strncpy(v3d->shading.matcap, sl->name, FILE_MAXFILE); -} - -static const EnumPropertyItem *rna_View3DShading_matcap_itemf( - bContext *UNUSED(C), PointerRNA *UNUSED(ptr), - PropertyRNA *UNUSED(prop), bool *r_free) -{ - EnumPropertyItem *item = NULL; - int totitem = 0; - - const int flags = (STUDIOLIGHT_EXTERNAL_FILE | STUDIOLIGHT_ORIENTATION_VIEWNORMAL); - - LISTBASE_FOREACH(StudioLight *, sl, BKE_studiolight_listbase()) { - int icon_id = sl->irradiance_icon_id; - bool show_studiolight = (sl->flag & flags) == flags; + if ((sl->flag & STUDIOLIGHT_INTERNAL)) { + /* always show internal lights */ + show_studiolight = true; + } + else { + switch (v3d->drawtype) { + case OB_SOLID: + case OB_TEXTURE: + show_studiolight = (sl->flag & (STUDIOLIGHT_ORIENTATION_WORLD | STUDIOLIGHT_ORIENTATION_CAMERA)) > 0; + break; + + case OB_MATERIAL: + show_studiolight = (sl->flag & STUDIOLIGHT_ORIENTATION_WORLD) > 0; + icon_id = sl->icon_id_radiance; + break; + } + } - if (show_studiolight) { - EnumPropertyItem tmp = {sl->index, sl->name, icon_id, sl->name, ""}; - RNA_enum_item_add(&item, &totitem, &tmp); + if (show_studiolight) { + EnumPropertyItem tmp = {sl->index, sl->name, icon_id, sl->name, ""}; + RNA_enum_item_add(&item, &totitem, &tmp); + } } } @@ -857,7 +846,7 @@ static PointerRNA rna_SpaceImageEditor_uvedit_get(PointerRNA *ptr) static void rna_SpaceImageEditor_mode_update(Main *bmain, Scene *scene, PointerRNA *UNUSED(ptr)) { - ED_space_image_paint_update(bmain->wm.first, scene); + ED_space_image_paint_update(bmain, bmain->wm.first, scene); } @@ -931,7 +920,7 @@ static void rna_SpaceImageEditor_image_set(PointerRNA *ptr, PointerRNA value) Scene *scene = ED_screen_scene_find_with_window(sc, G.main->wm.first, &win); ViewLayer *view_layer = WM_window_get_active_view_layer(win); Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); - ED_space_image_set(sima, scene, obedit, (Image *)value.data); + ED_space_image_set(G.main, sima, scene, obedit, (Image *)value.data); } static void rna_SpaceImageEditor_mask_set(PointerRNA *ptr, PointerRNA value) @@ -1447,12 +1436,12 @@ static void rna_SpaceDopeSheetEditor_mode_update(bContext *C, PointerRNA *ptr) else saction->action = NULL; } - + /* Collapse summary channel and hide channel list for timeline */ if (saction->mode == SACTCONT_TIMELINE) { saction->ads.flag |= ADS_FLAG_SUMMARY_COLLAPSED; } - + if (sa && sa->spacedata.first == saction) { ARegion *channels_region = BKE_area_find_region_type(sa, RGN_TYPE_CHANNELS); if (channels_region) { @@ -1465,7 +1454,7 @@ static void rna_SpaceDopeSheetEditor_mode_update(bContext *C, PointerRNA *ptr) ED_region_visibility_change_update(C, channels_region); } } - + /* recalculate extents of channel list */ saction->flag |= SACTION_TEMP_NEEDCHANSYNC; } @@ -2299,14 +2288,6 @@ static void rna_def_space_view3d_shading(BlenderRNA *brna) {0, NULL, 0, NULL, NULL} }; - static const EnumPropertyItem studio_light_orientation_items[] = { - {0, "UNKNOWN", 0, "Unknown", "Studio light has no orientation"}, - {STUDIOLIGHT_ORIENTATION_CAMERA, "CAMERA", 0, "Camera", "Studio light is camera based"}, - {STUDIOLIGHT_ORIENTATION_WORLD, "WORLD", 0, "World", "Studio light is world based"}, - {STUDIOLIGHT_ORIENTATION_VIEWNORMAL, "VIEWNORMAL", 0, "Matcap", "Studio light is a matcap"}, - {0, NULL, 0, NULL, NULL} - }; - srna = RNA_def_struct(brna, "View3DShading", NULL); RNA_def_struct_sdna(srna, "View3D"); RNA_def_struct_nested(brna, srna, "SpaceView3D"); @@ -2341,13 +2322,6 @@ static void rna_def_space_view3d_shading(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Studiolight", "Studio lighting setup"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); - prop = RNA_def_property(srna, "matcap", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, rna_enum_matcap_items); - RNA_def_property_enum_default(prop, 0); - RNA_def_property_enum_funcs(prop, "rna_View3DShading_matcap_get", "rna_View3DShading_matcap_set", "rna_View3DShading_matcap_itemf"); - RNA_def_property_ui_text(prop, "Matcap", "Matcap material and lighting"); - RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); - prop = RNA_def_property(srna, "show_cavity", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "shading.flag", V3D_SHADING_CAVITY); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); @@ -2372,13 +2346,12 @@ static void rna_def_space_view3d_shading(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); - prop = RNA_def_property(srna, "studio_light_orientation", PROP_ENUM, PROP_NONE); + prop = RNA_def_property(srna, "selected_studio_light", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "StudioLight"); RNA_define_verify_sdna(0); - RNA_def_property_enum_sdna(prop, NULL, "shading.flag"); - RNA_def_property_ui_text(prop, "Studio Light Orientation", "Orientation of the studio light"); - RNA_def_property_enum_items(prop, studio_light_orientation_items); - RNA_def_property_enum_funcs(prop, "rna_View3DShading_studio_light_orientation_get", "rna_View3DShading_studio_light_orientation_set", NULL); - RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_ui_text(prop, "Studio Light", "Selected StudioLight"); + RNA_def_property_pointer_funcs(prop, "rna_View3DShading_selected_studio_light_get", NULL, NULL, NULL); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE); RNA_define_verify_sdna(1); prop = RNA_def_property(srna, "studiolight_rot_z", PROP_FLOAT, PROP_ANGLE); @@ -2583,6 +2556,12 @@ static void rna_def_space_view3d_overlay(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Motion Paths", "Show the Motion Paths Overlay"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + prop = RNA_def_property(srna, "show_onion_skins", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "overlay.flag", V3D_OVERLAY_ONION_SKINS); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_ui_text(prop, "Onion Skins", "Show the Onion Skinning Overlay"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + prop = RNA_def_property(srna, "show_look_dev", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "overlay.flag", V3D_OVERLAY_LOOK_DEV); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); @@ -3637,7 +3616,7 @@ static void rna_def_space_dopesheet(BlenderRNA *brna) RNA_def_property_enum_items(prop, autosnap_items); RNA_def_property_ui_text(prop, "Auto Snap", "Automatic time snapping settings for transformations"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_DOPESHEET, NULL); - + /* displaying cache status */ prop = RNA_def_property(srna, "show_cache", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "cache_display", TIME_CACHE_DISPLAY); diff --git a/source/blender/makesrna/intern/rna_test.c b/source/blender/makesrna/intern/rna_test.c index 46299799966..f6d38c309f3 100644 --- a/source/blender/makesrna/intern/rna_test.c +++ b/source/blender/makesrna/intern/rna_test.c @@ -150,7 +150,7 @@ void RNA_def_test(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_DYNAMIC); RNA_def_property_dynamic_array_funcs(prop, "rna_Test_idarr_get_length", "rna_Test_idarr_set_length"); RNA_def_property_int_funcs(prop, "rna_Test_idarr_get", "rna_Test_idarr_set", NULL); - + prop = RNA_def_boolean_array(srna, "bdarr", DYNAMIC_ARRAY_SIZE, NULL, "bdarr", "boolean array"); RNA_def_property_flag(prop, PROP_DYNAMIC); RNA_def_property_dynamic_array_funcs(prop, "rna_Test_bdarr_get_length", "rna_Test_bdarr_set_length"); diff --git a/source/blender/makesrna/intern/rna_text.c b/source/blender/makesrna/intern/rna_text.c index 474fc3e5dc7..1035a3f7f55 100644 --- a/source/blender/makesrna/intern/rna_text.c +++ b/source/blender/makesrna/intern/rna_text.c @@ -131,10 +131,10 @@ static void rna_def_text_line(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + srna = RNA_def_struct(brna, "TextLine", NULL); RNA_def_struct_ui_text(srna, "Text Line", "Line of text in a Text data-block"); - + prop = RNA_def_property(srna, "body", PROP_STRING, PROP_NONE); RNA_def_property_string_funcs(prop, "rna_TextLine_body_get", "rna_TextLine_body_length", "rna_TextLine_body_set"); RNA_def_property_ui_text(prop, "Line", "Text in the line"); @@ -146,12 +146,12 @@ static void rna_def_text(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + srna = RNA_def_struct(brna, "Text", "ID"); RNA_def_struct_ui_text(srna, "Text", "Text data-block referencing an external or packed text file"); RNA_def_struct_ui_icon(srna, ICON_TEXT); RNA_def_struct_clear_flag(srna, STRUCT_ID_REFCOUNT); - + prop = RNA_def_property(srna, "filepath", PROP_STRING, PROP_NONE); RNA_def_property_string_funcs(prop, "rna_Text_filename_get", "rna_Text_filename_length", "rna_Text_filename_set"); RNA_def_property_ui_text(prop, "File Path", "Filename of the text file"); @@ -170,7 +170,7 @@ static void rna_def_text(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flags", TXT_ISMEM); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Memory", "Text file is in memory, without a corresponding file on disk"); - + prop = RNA_def_property(srna, "use_module", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flags", TXT_ISSCRIPT); RNA_def_property_ui_text(prop, "Register", @@ -183,7 +183,7 @@ static void rna_def_text(BlenderRNA *brna) prop = RNA_def_property(srna, "lines", PROP_COLLECTION, PROP_NONE); RNA_def_property_struct_type(prop, "TextLine"); RNA_def_property_ui_text(prop, "Lines", "Lines of text"); - + prop = RNA_def_property(srna, "current_line", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "curl"); @@ -197,7 +197,7 @@ static void rna_def_text(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Current Character", "Index of current character in current line, and also start index of " "character in selection if one exists"); - + prop = RNA_def_property(srna, "current_line_index", PROP_INT, PROP_NONE); RNA_def_property_int_funcs(prop, "rna_Text_current_line_index_get", "rna_Text_current_line_index_set", NULL); RNA_def_property_ui_text(prop, "Current Line Index", "Index of current TextLine in TextLine collection"); @@ -209,13 +209,13 @@ static void rna_def_text(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_struct_type(prop, "TextLine"); RNA_def_property_ui_text(prop, "Selection End Line", "End line of selection"); - + prop = RNA_def_property(srna, "select_end_character", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "selc"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Selection End Character", "Index of character after end of selection in the selection end line"); - + RNA_api_text(srna); } diff --git a/source/blender/makesrna/intern/rna_texture.c b/source/blender/makesrna/intern/rna_texture.c index 5449b67c040..b848bb96392 100644 --- a/source/blender/makesrna/intern/rna_texture.c +++ b/source/blender/makesrna/intern/rna_texture.c @@ -191,7 +191,7 @@ static void rna_Texture_nodes_update(Main *UNUSED(bmain), Scene *UNUSED(scene), static void rna_Texture_type_set(PointerRNA *ptr, int value) { Tex *tex = (Tex *)ptr->data; - + BKE_texture_type_set(tex, value); } @@ -247,7 +247,7 @@ void rna_TextureSlot_update(bContext *C, PointerRNA *ptr) char *rna_TextureSlot_path(PointerRNA *ptr) { MTex *mtex = ptr->data; - + /* if there is ID-data, resolve the path using the index instead of by name, * since the name used is the name of the texture assigned, but the texture * may be used multiple times in the same stack @@ -274,7 +274,7 @@ char *rna_TextureSlot_path(PointerRNA *ptr) } } } - + /* this is a compromise for the remaining cases... */ if (mtex->tex) { char name_esc[(sizeof(mtex->tex->id.name) - 2) * 2]; @@ -293,7 +293,7 @@ static int rna_TextureSlot_name_length(PointerRNA *ptr) if (mtex->tex) return strlen(mtex->tex->id.name + 2); - + return 0; } @@ -312,7 +312,7 @@ static int rna_TextureSlot_output_node_get(PointerRNA *ptr) MTex *mtex = ptr->data; Tex *tex = mtex->tex; int cur = mtex->which_output; - + if (tex) { bNodeTree *ntree = tex->nodetree; bNode *node; @@ -325,7 +325,7 @@ static int rna_TextureSlot_output_node_get(PointerRNA *ptr) } } } - + mtex->which_output = 0; return 0; } @@ -339,18 +339,18 @@ static const EnumPropertyItem *rna_TextureSlot_output_node_itemf( Tex *tex = mtex->tex; EnumPropertyItem *item = NULL; int totitem = 0; - + if (tex) { bNodeTree *ntree = tex->nodetree; if (ntree) { EnumPropertyItem tmp = {0, "", 0, "", ""}; bNode *node; - + tmp.value = 0; tmp.name = "Not Specified"; tmp.identifier = "NOT_SPECIFIED"; RNA_enum_item_add(&item, &totitem, &tmp); - + for (node = ntree->nodes.first; node; node = node->next) { if (node->type == TEX_NODE_OUTPUT) { tmp.value = node->custom1; @@ -361,7 +361,7 @@ static const EnumPropertyItem *rna_TextureSlot_output_node_itemf( } } } - + RNA_enum_item_end(&item, &totitem); *r_free = true; @@ -382,14 +382,14 @@ static void rna_Texture_use_color_ramp_set(PointerRNA *ptr, int value) static void rna_Texture_use_nodes_update(bContext *C, PointerRNA *ptr) { Tex *tex = (Tex *)ptr->data; - + if (tex->use_nodes) { tex->type = 0; - + if (tex->nodetree == NULL) ED_node_texture_default(C, tex); } - + rna_Texture_nodes_update(CTX_data_main(C), CTX_data_scene(C), ptr); } @@ -412,7 +412,7 @@ static void rna_def_texmapping(BlenderRNA *brna) {MTEX_SPHERE, "SPHERE", 0, "Sphere", "Map with Z as central axis"}, {0, NULL, 0, NULL, NULL} }; - + static const EnumPropertyItem prop_vect_type_items[] = { {TEXMAP_TYPE_TEXTURE, "TEXTURE", 0, "Texture", "Transform a texture by inverse mapping the texture coordinate"}, {TEXMAP_TYPE_POINT, "POINT", 0, "Point", "Transform a point"}, @@ -431,7 +431,7 @@ static void rna_def_texmapping(BlenderRNA *brna) StructRNA *srna; PropertyRNA *prop; - + srna = RNA_def_struct(brna, "TexMapping", NULL); RNA_def_struct_ui_text(srna, "Texture Mapping", "Texture coordinate mapping settings"); @@ -446,34 +446,34 @@ static void rna_def_texmapping(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Location", ""); RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT); RNA_def_property_update(prop, 0, "rna_Texture_mapping_update"); - + /* Not PROP_XYZ, this is now in radians, no more degrees */ prop = RNA_def_property(srna, "rotation", PROP_FLOAT, PROP_EULER); RNA_def_property_float_sdna(prop, NULL, "rot"); RNA_def_property_ui_text(prop, "Rotation", ""); RNA_def_property_update(prop, 0, "rna_Texture_mapping_update"); - + prop = RNA_def_property(srna, "scale", PROP_FLOAT, PROP_XYZ); RNA_def_property_float_sdna(prop, NULL, "size"); RNA_def_property_flag(prop, PROP_PROPORTIONAL); RNA_def_property_ui_text(prop, "Scale", ""); RNA_def_property_update(prop, 0, "rna_Texture_mapping_update"); - + prop = RNA_def_property(srna, "min", PROP_FLOAT, PROP_XYZ); RNA_def_property_float_sdna(prop, NULL, "min"); RNA_def_property_ui_text(prop, "Minimum", "Minimum value for clipping"); RNA_def_property_update(prop, 0, "rna_Texture_mapping_update"); - + prop = RNA_def_property(srna, "max", PROP_FLOAT, PROP_XYZ); RNA_def_property_float_sdna(prop, NULL, "max"); RNA_def_property_ui_text(prop, "Maximum", "Maximum value for clipping"); RNA_def_property_update(prop, 0, "rna_Texture_mapping_update"); - + prop = RNA_def_property(srna, "use_min", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", TEXMAP_CLIP_MIN); RNA_def_property_ui_text(prop, "Has Minimum", "Whether to use minimum clipping value"); RNA_def_property_update(prop, 0, "rna_Texture_mapping_update"); - + prop = RNA_def_property(srna, "use_max", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", TEXMAP_CLIP_MAX); RNA_def_property_ui_text(prop, "Has Maximum", "Whether to use maximum clipping value"); @@ -484,13 +484,13 @@ static void rna_def_texmapping(BlenderRNA *brna) RNA_def_property_enum_items(prop, prop_xyz_mapping_items); RNA_def_property_ui_text(prop, "X Mapping", ""); RNA_def_property_update(prop, 0, "rna_Texture_mapping_update"); - + prop = RNA_def_property(srna, "mapping_y", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "projy"); RNA_def_property_enum_items(prop, prop_xyz_mapping_items); RNA_def_property_ui_text(prop, "Y Mapping", ""); RNA_def_property_update(prop, 0, "rna_Texture_mapping_update"); - + prop = RNA_def_property(srna, "mapping_z", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "projz"); RNA_def_property_enum_items(prop, prop_xyz_mapping_items); @@ -507,7 +507,7 @@ static void rna_def_colormapping(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + srna = RNA_def_struct(brna, "ColorMapping", NULL); RNA_def_struct_ui_text(srna, "Color Mapping", "Color mapping settings"); @@ -562,7 +562,7 @@ static void rna_def_mtex(BlenderRNA *brna) {0, "DUMMY", 0, "Dummy", ""}, {0, NULL, 0, NULL, NULL} }; - + srna = RNA_def_struct(brna, "TextureSlot", NULL); RNA_def_struct_sdna(srna, "MTex"); RNA_def_struct_ui_text(srna, "Texture Slot", "Texture slot defining the mapping and influence of a texture"); @@ -639,7 +639,7 @@ static void rna_def_mtex(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Default Value", "Value to use for Ref, Spec, Amb, Emit, Alpha, RayMir, TransLu and Hard"); RNA_def_property_update(prop, 0, "rna_TextureSlot_update"); - + prop = RNA_def_property(srna, "output_node", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "which_output"); RNA_def_property_enum_items(prop, output_node_items); @@ -652,24 +652,24 @@ static void rna_def_mtex(BlenderRNA *brna) static void rna_def_filter_common(StructRNA *srna) { PropertyRNA *prop; - + prop = RNA_def_property(srna, "use_mipmap", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "imaflag", TEX_MIPMAP); RNA_def_property_boolean_funcs(prop, NULL, "rna_ImageTexture_mipmap_set"); RNA_def_property_ui_text(prop, "MIP Map", "Use auto-generated MIP maps for the image"); RNA_def_property_update(prop, 0, "rna_Texture_update"); - + prop = RNA_def_property(srna, "use_mipmap_gauss", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "imaflag", TEX_GAUSS_MIP); RNA_def_property_ui_text(prop, "MIP Map Gaussian filter", "Use Gauss filter to sample down MIP maps"); RNA_def_property_update(prop, 0, "rna_Texture_update"); - + prop = RNA_def_property(srna, "filter_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "texfilter"); RNA_def_property_enum_items(prop, texture_filter_items); RNA_def_property_ui_text(prop, "Filter", "Texture filter to use for sampling image"); RNA_def_property_update(prop, 0, "rna_Texture_update"); - + prop = RNA_def_property(srna, "filter_lightprobes", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "afmax"); RNA_def_property_range(prop, 1, 256); @@ -677,7 +677,7 @@ static void rna_def_filter_common(StructRNA *srna) "Maximum number of samples (higher gives less blur at distant/oblique angles, " "but is also slower)"); RNA_def_property_update(prop, 0, "rna_Texture_update"); - + prop = RNA_def_property(srna, "filter_eccentricity", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "afmax"); RNA_def_property_range(prop, 1, 256); @@ -908,7 +908,7 @@ static void rna_def_texture_marble(BlenderRNA *brna) RNA_def_property_enum_items(prop, prop_marble_stype); RNA_def_property_ui_text(prop, "Pattern", ""); RNA_def_property_update(prop, 0, "rna_Texture_nodes_update"); - + prop = RNA_def_property(srna, "noise_basis", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "noisebasis"); RNA_def_property_enum_items(prop, prop_noise_basis_items); @@ -1016,7 +1016,7 @@ static void rna_def_texture_stucci(BlenderRNA *brna) RNA_def_property_ui_range(prop, 0.0001, 200, 10, 2); RNA_def_property_ui_text(prop, "Turbulence", "Turbulence of the noise"); RNA_def_property_update(prop, 0, "rna_Texture_update"); - + prop = RNA_def_property(srna, "noise_basis", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "noisebasis"); RNA_def_property_enum_items(prop, prop_noise_basis_items); @@ -1329,19 +1329,19 @@ static void rna_def_texture_voronoi(BlenderRNA *brna) RNA_def_property_range(prop, -2, 2); RNA_def_property_ui_text(prop, "Weight 1", "Voronoi feature weight 1"); RNA_def_property_update(prop, 0, "rna_Texture_update"); - + prop = RNA_def_property(srna, "weight_2", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "vn_w2"); RNA_def_property_range(prop, -2, 2); RNA_def_property_ui_text(prop, "Weight 2", "Voronoi feature weight 2"); RNA_def_property_update(prop, 0, "rna_Texture_update"); - + prop = RNA_def_property(srna, "weight_3", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "vn_w3"); RNA_def_property_range(prop, -2, 2); RNA_def_property_ui_text(prop, "Weight 3", "Voronoi feature weight 3"); RNA_def_property_update(prop, 0, "rna_Texture_update"); - + prop = RNA_def_property(srna, "weight_4", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "vn_w4"); RNA_def_property_range(prop, -2, 2); @@ -1451,7 +1451,7 @@ static void rna_def_texture(BlenderRNA *brna) RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", TEX_NO_CLAMP); RNA_def_property_ui_text(prop, "Clamp", "Set negative texture RGB and intensity values to zero, for some uses like displacement this option can be disabled to get the full range"); RNA_def_property_update(prop, 0, "rna_Texture_update"); - + prop = RNA_def_property(srna, "use_color_ramp", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", TEX_COLORBAND); RNA_def_property_boolean_funcs(prop, NULL, "rna_Texture_use_color_ramp_set"); @@ -1479,44 +1479,44 @@ static void rna_def_texture(BlenderRNA *brna) RNA_def_property_range(prop, 0, 2); RNA_def_property_ui_text(prop, "Saturation", "Adjust the saturation of colors in the texture"); RNA_def_property_update(prop, 0, "rna_Texture_update"); - + /* RGB Factor */ prop = RNA_def_property(srna, "factor_red", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "rfac"); RNA_def_property_range(prop, 0, 2); RNA_def_property_ui_text(prop, "Factor Red", ""); RNA_def_property_update(prop, 0, "rna_Texture_update"); - + prop = RNA_def_property(srna, "factor_green", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "gfac"); RNA_def_property_range(prop, 0, 2); RNA_def_property_ui_text(prop, "Factor Green", ""); RNA_def_property_update(prop, 0, "rna_Texture_update"); - + prop = RNA_def_property(srna, "factor_blue", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "bfac"); RNA_def_property_range(prop, 0, 2); RNA_def_property_ui_text(prop, "Factor Blue", ""); RNA_def_property_update(prop, 0, "rna_Texture_update"); - + /* Alpha for preview render */ prop = RNA_def_property(srna, "use_preview_alpha", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", TEX_PRV_ALPHA); RNA_def_property_ui_text(prop, "Show Alpha", "Show Alpha in Preview Render"); RNA_def_property_update(prop, 0, "rna_Texture_update"); - + /* nodetree */ prop = RNA_def_property(srna, "use_nodes", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "use_nodes", 1); RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); RNA_def_property_ui_text(prop, "Use Nodes", "Make this a node-based texture"); RNA_def_property_update(prop, 0, "rna_Texture_use_nodes_update"); - + prop = RNA_def_property(srna, "node_tree", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "nodetree"); RNA_def_property_ui_text(prop, "Node Tree", "Node tree for node-based textures"); RNA_def_property_update(prop, 0, "rna_Texture_nodes_update"); - + rna_def_animdata_common(srna); /* specific types */ diff --git a/source/blender/makesrna/intern/rna_ui.c b/source/blender/makesrna/intern/rna_ui.c index ce1f9efcf63..8083ae35dc1 100644 --- a/source/blender/makesrna/intern/rna_ui.c +++ b/source/blender/makesrna/intern/rna_ui.c @@ -93,7 +93,7 @@ static ARegionType *region_type_find(ReportList *reports, int space_type, int re if (art->regionid == region_type) break; } - + /* region type not found? abort */ if (art == NULL) { BKE_report(reports, RPT_ERROR, "Region not found in space type"); @@ -166,6 +166,24 @@ static void panel_draw_header(const bContext *C, Panel *pnl) RNA_parameter_list_free(&list); } +static void panel_draw_header_preset(const bContext *C, Panel *pnl) +{ + extern FunctionRNA rna_Panel_draw_header_preset_func; + + PointerRNA ptr; + ParameterList list; + FunctionRNA *func; + + RNA_pointer_create(&CTX_wm_screen(C)->id, pnl->type->ext.srna, pnl, &ptr); + func = &rna_Panel_draw_header_preset_func; + + RNA_parameter_list_create(&list, &ptr, func); + RNA_parameter_set_lookup(&list, "context", &C); + pnl->type->ext.call((bContext *)C, &ptr, func, &list); + + RNA_parameter_list_free(&list); +} + static void rna_Panel_unregister(Main *UNUSED(bmain), StructRNA *type) { ARegionType *art; @@ -175,7 +193,7 @@ static void rna_Panel_unregister(Main *UNUSED(bmain), StructRNA *type) return; if (!(art = region_type_find(NULL, pt->space_type, pt->region_type))) return; - + RNA_struct_free_extension(type, &pt->ext); RNA_struct_free(&BLENDER_RNA, type); @@ -199,7 +217,7 @@ static StructRNA *rna_Panel_register( PanelType *pt, *parent = NULL, dummypt = {NULL}; Panel dummypanel = {NULL}; PointerRNA dummyptr; - int have_function[3]; + int have_function[4]; /* setup dummy panel & panel type to store static properties in */ dummypanel.type = &dummypt; @@ -211,7 +229,7 @@ static StructRNA *rna_Panel_register( /* validate the python class */ if (validate(&dummyptr, data, have_function) != 0) return NULL; - + if (strlen(identifier) >= sizeof(dummypt.idname)) { BKE_reportf(reports, RPT_ERROR, "Registering panel class: '%s' is too long, maximum length is %d", identifier, (int)sizeof(dummypt.idname)); @@ -251,7 +269,7 @@ static StructRNA *rna_Panel_register( dummypt.parent_id, dummypt.idname); return NULL; } - + /* create a new panel type */ pt = MEM_callocN(sizeof(PanelType), "python buttons panel"); memcpy(pt, &dummypt, sizeof(dummypt)); @@ -267,6 +285,7 @@ static StructRNA *rna_Panel_register( pt->poll = (have_function[0]) ? panel_poll : NULL; pt->draw = (have_function[1]) ? panel_draw : NULL; 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) { @@ -296,7 +315,7 @@ static StructRNA *rna_Panel_register( /* update while blender is running */ WM_main_add_notifier(NC_WINDOW, NULL); - + return pt->ext.srna; } @@ -590,7 +609,7 @@ static void rna_Header_unregister(Main *UNUSED(bmain), StructRNA *type) return; if (!(art = region_type_find(NULL, ht->space_type, ht->region_type))) return; - + RNA_struct_free_extension(type, &ht->ext); RNA_struct_free(&BLENDER_RNA, type); @@ -642,7 +661,7 @@ static StructRNA *rna_Header_register( if (!RNA_struct_bl_idname_ok_or_report(reports, dummyht.idname, "_HT_")) { return NULL; } - + /* create a new header type */ ht = MEM_callocN(sizeof(HeaderType), "python buttons header"); memcpy(ht, &dummyht, sizeof(dummyht)); @@ -659,7 +678,7 @@ static StructRNA *rna_Header_register( /* update while blender is running */ WM_main_add_notifier(NC_WINDOW, NULL); - + return ht->ext.srna; } @@ -720,7 +739,7 @@ static void rna_Menu_unregister(Main *UNUSED(bmain), StructRNA *type) if (!mt) return; - + RNA_struct_free_extension(type, &mt->ext); RNA_struct_free(&BLENDER_RNA, type); @@ -754,7 +773,7 @@ static StructRNA *rna_Menu_register( /* validate the python class */ if (validate(&dummymtr, data, have_function) != 0) return NULL; - + if (strlen(identifier) >= sizeof(dummymt.idname)) { BKE_reportf(reports, RPT_ERROR, "Registering menu class: '%s' is too long, maximum length is %d", identifier, (int)sizeof(dummymt.idname)); @@ -772,7 +791,7 @@ static StructRNA *rna_Menu_register( if (!RNA_struct_bl_idname_ok_or_report(reports, dummymt.idname, "_MT_")) { return NULL; } - + /* create a new menu type */ if (_menu_descr[0]) { description_size = strlen(_menu_descr) + 1; @@ -812,7 +831,7 @@ static StructRNA *rna_Menu_register( /* update while blender is running */ WM_main_add_notifier(NC_WINDOW, NULL); - + return mt->ext.srna; } @@ -958,7 +977,7 @@ static void rna_def_ui_layout(BlenderRNA *brna) {UI_LAYOUT_ALIGN_RIGHT, "RIGHT", 0, "Right", ""}, {0, NULL, 0, NULL, NULL} }; - + static const EnumPropertyItem emboss_items[] = { {UI_EMBOSS, "NORMAL", 0, "Normal", "Draw standard button emboss style"}, {UI_EMBOSS_NONE, "NONE", 0, "None", "Draw only text and icons"}, @@ -975,15 +994,15 @@ static void rna_def_ui_layout(BlenderRNA *brna) prop = RNA_def_property(srna, "active", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_funcs(prop, "rna_UILayout_active_get", "rna_UILayout_active_set"); - + prop = RNA_def_property(srna, "operator_context", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, rna_enum_operator_context_items); RNA_def_property_enum_funcs(prop, "rna_UILayout_op_context_get", "rna_UILayout_op_context_set", NULL); - + prop = RNA_def_property(srna, "enabled", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_funcs(prop, "rna_UILayout_enabled_get", "rna_UILayout_enabled_set"); RNA_def_property_ui_text(prop, "Enabled", "When false, this (sub)layout is grayed out"); - + prop = RNA_def_property(srna, "alert", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_funcs(prop, "rna_UILayout_alert_get", "rna_UILayout_alert_set"); @@ -999,7 +1018,7 @@ static void rna_def_ui_layout(BlenderRNA *brna) prop = RNA_def_property(srna, "scale_x", PROP_FLOAT, PROP_UNSIGNED); RNA_def_property_float_funcs(prop, "rna_UILayout_scale_x_get", "rna_UILayout_scale_x_set", NULL); RNA_def_property_ui_text(prop, "Scale X", "Scale factor along the X for items in this (sub)layout"); - + prop = RNA_def_property(srna, "scale_y", PROP_FLOAT, PROP_UNSIGNED); RNA_def_property_float_funcs(prop, "rna_UILayout_scale_y_get", "rna_UILayout_scale_y_set", NULL); RNA_def_property_ui_text(prop, "Scale Y", "Scale factor along the Y for items in this (sub)layout"); @@ -1008,7 +1027,7 @@ static void rna_def_ui_layout(BlenderRNA *brna) prop = RNA_def_property(srna, "emboss", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, emboss_items); RNA_def_property_enum_funcs(prop, "rna_UILayout_emboss_get", "rna_UILayout_emboss_set", NULL); - + prop = RNA_def_property(srna, "use_property_split", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_funcs(prop, "rna_UILayout_property_split_get", "rna_UILayout_property_split_set"); } @@ -1019,7 +1038,7 @@ static void rna_def_panel(BlenderRNA *brna) PropertyRNA *prop; PropertyRNA *parm; FunctionRNA *func; - + static const EnumPropertyItem panel_flag_items[] = { {PNL_DEFAULT_CLOSED, "DEFAULT_CLOSED", 0, "Default Closed", "Defines if the panel has to be open or collapsed at the time of its creation"}, @@ -1028,7 +1047,7 @@ static void rna_def_panel(BlenderRNA *brna) "arrow to collapse the panel and the label (see bl_label)"}, {0, NULL, 0, NULL, NULL} }; - + srna = RNA_def_struct(brna, "Panel", NULL); RNA_def_struct_ui_text(srna, "Panel", "Panel containing UI elements"); RNA_def_struct_sdna(srna, "Panel"); @@ -1058,14 +1077,20 @@ static void rna_def_panel(BlenderRNA *brna) parm = RNA_def_pointer(func, "context", "Context", "", ""); RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + func = RNA_def_function(srna, "draw_header_preset", NULL); + RNA_def_function_ui_description(func, "Draw UI elements for presets in the panel's header"); + RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL); + parm = RNA_def_pointer(func, "context", "Context", "", ""); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + prop = RNA_def_property(srna, "layout", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "UILayout"); RNA_def_property_ui_text(prop, "Layout", "Defines the structure of the panel in the UI"); - + prop = RNA_def_property(srna, "text", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "drawname"); RNA_def_property_ui_text(prop, "Text", "XXX todo"); - + /* registration */ prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "type->idname"); @@ -1102,7 +1127,7 @@ static void rna_def_panel(BlenderRNA *brna) RNA_def_property_enum_items(prop, rna_enum_space_type_items); RNA_def_property_flag(prop, PROP_REGISTER); RNA_def_property_ui_text(prop, "Space type", "The space where the panel is going to be used in"); - + prop = RNA_def_property(srna, "bl_region_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "type->region_type"); RNA_def_property_enum_items(prop, rna_enum_region_type_items); @@ -1115,7 +1140,7 @@ static void rna_def_panel(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Context", "The context in which the panel belongs to. (TODO: explain the " "possible combinations bl_context/bl_region_type/bl_space_type)"); - + prop = RNA_def_property(srna, "bl_options", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "type->flag"); RNA_def_property_enum_items(prop, panel_flag_items); @@ -1132,6 +1157,11 @@ static void rna_def_panel(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Pin", ""); /* XXX, should only tag region for redraw */ RNA_def_property_update(prop, NC_WINDOW, NULL); + + prop = RNA_def_property(srna, "is_popover", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", PNL_POPOVER); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Popover", ""); } static void rna_def_uilist(BlenderRNA *brna) @@ -1263,7 +1293,7 @@ static void rna_def_header(BlenderRNA *brna) PropertyRNA *prop; PropertyRNA *parm; FunctionRNA *func; - + srna = RNA_def_struct(brna, "Header", NULL); RNA_def_struct_ui_text(srna, "Header", "Editor header containing UI elements"); RNA_def_struct_sdna(srna, "Header"); @@ -1318,7 +1348,7 @@ static void rna_def_menu(BlenderRNA *brna) PropertyRNA *prop; PropertyRNA *parm; FunctionRNA *func; - + srna = RNA_def_struct(brna, "Menu", NULL); RNA_def_struct_ui_text(srna, "Menu", "Editor menu containing buttons"); RNA_def_struct_sdna(srna, "Menu"); diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c index d61f6166889..9377ef8a925 100644 --- a/source/blender/makesrna/intern/rna_ui_api.c +++ b/source/blender/makesrna/intern/rna_ui_api.c @@ -95,9 +95,10 @@ const char *rna_translate_ui_text( return BLT_pgettext(BLT_I18NCONTEXT_DEFAULT, text); } -static void rna_uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname, const char *name, const char *text_ctxt, - int translate, int icon, int expand, int slider, int toggle, int icon_only, int event, - int full_event, int emboss, int index, int icon_value) +static void rna_uiItemR( + uiLayout *layout, PointerRNA *ptr, const char *propname, const char *name, const char *text_ctxt, + int translate, int icon, int expand, int slider, int toggle, int icon_only, int event, + int full_event, int emboss, int index, int icon_value) { PropertyRNA *prop = RNA_struct_find_property(ptr, propname); int flag = 0; @@ -125,8 +126,9 @@ static void rna_uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname, uiItemFullR(layout, ptr, prop, index, 0, flag, name, icon); } -static void rna_uiItemMenuEnumR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *name, - const char *text_ctxt, int translate, int icon) +static void rna_uiItemMenuEnumR( + uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *name, + const char *text_ctxt, int translate, int icon) { PropertyRNA *prop = RNA_struct_find_property(ptr, propname); @@ -140,8 +142,9 @@ static void rna_uiItemMenuEnumR(uiLayout *layout, struct PointerRNA *ptr, const uiItemMenuEnumR_prop(layout, ptr, prop, name, icon); } -static void rna_uiItemEnumR_string(uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *value, - const char *name, const char *text_ctxt, int translate, int icon) +static void rna_uiItemEnumR_string( + uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *value, + const char *name, const char *text_ctxt, int translate, int icon) { PropertyRNA *prop = RNA_struct_find_property(ptr, propname); @@ -157,9 +160,10 @@ static void rna_uiItemEnumR_string(uiLayout *layout, struct PointerRNA *ptr, con uiItemEnumR_string(layout, ptr, propname, value, name, icon); } -static void rna_uiItemPointerR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, - struct PointerRNA *searchptr, const char *searchpropname, - const char *name, const char *text_ctxt, int translate, int icon) +static void rna_uiItemPointerR( + uiLayout *layout, struct PointerRNA *ptr, const char *propname, + struct PointerRNA *searchptr, const char *searchpropname, + const char *name, const char *text_ctxt, int translate, int icon) { PropertyRNA *prop = RNA_struct_find_property(ptr, propname); @@ -226,8 +230,9 @@ static PointerRNA rna_uiItemOMenuHold( } -static void rna_uiItemMenuEnumO(uiLayout *layout, bContext *C, const char *opname, const char *propname, const char *name, - const char *text_ctxt, int translate, int icon) +static void rna_uiItemMenuEnumO( + uiLayout *layout, bContext *C, const char *opname, const char *propname, const char *name, + const char *text_ctxt, int translate, int icon) { wmOperatorType *ot = WM_operatortype_find(opname, 0); /* print error next */ @@ -242,8 +247,9 @@ static void rna_uiItemMenuEnumO(uiLayout *layout, bContext *C, const char *opnam uiItemMenuEnumO_ptr(layout, C, ot, propname, name, icon); } -static void rna_uiItemL(uiLayout *layout, const char *name, const char *text_ctxt, int translate, - int icon, int icon_value) +static void rna_uiItemL( + uiLayout *layout, const char *name, const char *text_ctxt, int translate, + int icon, int icon_value) { /* Get translated name (label). */ name = rna_translate_ui_text(name, text_ctxt, NULL, NULL, translate); @@ -255,8 +261,9 @@ static void rna_uiItemL(uiLayout *layout, const char *name, const char *text_ctx uiItemL(layout, name, icon); } -static void rna_uiItemM(uiLayout *layout, bContext *C, const char *menuname, const char *name, const char *text_ctxt, - int translate, int icon, int icon_value) +static void rna_uiItemM( + uiLayout *layout, bContext *C, const char *menuname, const char *name, const char *text_ctxt, + int translate, int icon, int icon_value) { /* Get translated name (label). */ name = rna_translate_ui_text(name, text_ctxt, NULL, NULL, translate); @@ -291,8 +298,9 @@ static void rna_uiItemPopoverPanelFromGroup( uiItemPopoverPanelFromGroup(layout, C, space_id, region_id, context, category); } -static void rna_uiTemplateAnyID(uiLayout *layout, PointerRNA *ptr, const char *propname, const char *proptypename, - const char *name, const char *text_ctxt, int translate) +static void rna_uiTemplateAnyID( + uiLayout *layout, PointerRNA *ptr, const char *propname, const char *proptypename, + const char *name, const char *text_ctxt, int translate) { PropertyRNA *prop = RNA_struct_find_property(ptr, propname); @@ -308,8 +316,9 @@ static void rna_uiTemplateAnyID(uiLayout *layout, PointerRNA *ptr, const char *p uiTemplateAnyID(layout, ptr, propname, proptypename, name); } -static void rna_uiTemplatePathBuilder(uiLayout *layout, PointerRNA *ptr, const char *propname, PointerRNA *root_ptr, - const char *name, const char *text_ctxt, int translate) +static void rna_uiTemplatePathBuilder( + uiLayout *layout, PointerRNA *ptr, const char *propname, PointerRNA *root_ptr, + const char *name, const char *text_ctxt, int translate) { PropertyRNA *prop = RNA_struct_find_property(ptr, propname); @@ -360,8 +369,9 @@ static const char *rna_ui_get_enum_name(bContext *C, PointerRNA *ptr, const char return name; } -static const char *rna_ui_get_enum_description(bContext *C, PointerRNA *ptr, const char *propname, - const char *identifier) +static const char *rna_ui_get_enum_description( + bContext *C, PointerRNA *ptr, const char *propname, + const char *identifier) { PropertyRNA *prop = NULL; const EnumPropertyItem *items = NULL, *item; @@ -493,7 +503,7 @@ void RNA_api_ui_layout(StructRNA *srna) "Sub-layout. Items placed in this sublayout are placed next to each other " "in a row"); RNA_def_boolean(func, "align", false, "", "Align buttons to each other"); - + func = RNA_def_function(srna, "column", "uiLayoutColumn"); parm = RNA_def_pointer(func, "layout", "UILayout", "", "Sub-layout to put items in"); RNA_def_function_return(func, parm); @@ -508,13 +518,26 @@ void RNA_api_ui_layout(StructRNA *srna) RNA_def_function_return(func, parm); RNA_def_boolean(func, "align", false, "", "Align buttons to each other"); + func = RNA_def_function(srna, "grid_flow", "uiLayoutGridFlow"); + RNA_def_boolean(func, "row_major", false, "", "Fill row by row, instead of column by column"); + RNA_def_int(func, "num_columns", 0, INT_MIN, INT_MAX, "", + "Number of columns, positive are absolute fixed numbers, 0 is automatic, negative are " + "automatic multiple numbers along major axis (e.g. -2 will only produce 2, 4, 6 etc. " + "columns for row major layout, and 2, 4, 6 etc. rows for column major layout)", + INT_MIN, INT_MAX); + RNA_def_boolean(func, "even_columns", false, "", "All columns will have the same width"); + RNA_def_boolean(func, "even_rows", false, "", "All rows will have the same height"); + RNA_def_boolean(func, "align", false, "", "Align buttons to each other"); + parm = RNA_def_pointer(func, "layout", "UILayout", "", "Sub-layout to put items in"); + RNA_def_function_return(func, parm); + /* box layout */ func = RNA_def_function(srna, "box", "uiLayoutBox"); parm = RNA_def_pointer(func, "layout", "UILayout", "", "Sub-layout to put items in"); RNA_def_function_return(func, parm); RNA_def_function_ui_description(func, "Sublayout (items placed in this sublayout are placed " "under each other in a column and are surrounded by a box)"); - + /* split layout */ func = RNA_def_function(srna, "split", "uiLayoutSplit"); parm = RNA_def_pointer(func, "layout", "UILayout", "", "Sub-layout to put items in"); @@ -719,13 +742,16 @@ void RNA_api_ui_layout(StructRNA *srna) func = RNA_def_function(srna, "separator", "uiItemS"); RNA_def_function_ui_description(func, "Item. Inserts empty space into the layout between items"); + func = RNA_def_function(srna, "separator_spacer", "uiItemSpacer"); + RNA_def_function_ui_description(func, "Item. Inserts horizontal spacing empty space into the layout between items"); + /* context */ func = RNA_def_function(srna, "context_pointer_set", "uiLayoutSetContextPointer"); parm = RNA_def_string(func, "name", NULL, 0, "Name", "Name of entry in the context"); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); parm = RNA_def_pointer(func, "data", "AnyType", "", "Pointer to put in context"); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED | PARM_RNAPTR); - + /* templates */ func = RNA_def_function(srna, "template_header", "uiTemplateHeader"); RNA_def_function_flag(func, FUNC_USE_CONTEXT); @@ -802,7 +828,7 @@ void RNA_api_ui_layout(StructRNA *srna) parm = RNA_def_pointer(func, "root", "ID", "", "ID-block from which path is evaluated from"); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED | PARM_RNAPTR); api_ui_item_common_text(func); - + func = RNA_def_function(srna, "template_modifier", "uiTemplateModifier"); RNA_def_function_flag(func, FUNC_USE_CONTEXT); RNA_def_function_ui_description(func, "Generates the UI layout for modifiers"); @@ -843,6 +869,12 @@ void RNA_api_ui_layout(StructRNA *srna) api_ui_item_rna_common(func); RNA_def_boolean(func, "expand", false, "", "Expand button to show more detail"); + func = RNA_def_function(srna, "template_icon", "uiTemplateIcon"); + RNA_def_function_ui_description(func, "Display a large icon"); + parm = RNA_def_int(func, "icon_value", 0, 0, INT_MAX, "Icon to display", "", 0, INT_MAX); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + RNA_def_float(func, "scale", 1.0f, 1.0f, 100.0f, "Scale", "Scale the icon size (by the button size)", 1.0f, 100.0f); + func = RNA_def_function(srna, "template_icon_view", "uiTemplateIconView"); RNA_def_function_ui_description(func, "Enum. Large widget showing Icon previews"); api_ui_item_rna_common(func); @@ -852,15 +884,15 @@ void RNA_api_ui_layout(StructRNA *srna) func = RNA_def_function(srna, "template_histogram", "uiTemplateHistogram"); RNA_def_function_ui_description(func, "Item. A histogramm widget to analyze imaga data"); api_ui_item_rna_common(func); - + func = RNA_def_function(srna, "template_waveform", "uiTemplateWaveform"); RNA_def_function_ui_description(func, "Item. A waveform widget to analyze imaga data"); api_ui_item_rna_common(func); - + func = RNA_def_function(srna, "template_vectorscope", "uiTemplateVectorscope"); RNA_def_function_ui_description(func, "Item. A vectorscope widget to analyze imaga data"); api_ui_item_rna_common(func); - + func = RNA_def_function(srna, "template_layers", "uiTemplateLayers"); api_ui_item_rna_common(func); parm = RNA_def_pointer(func, "used_layers_data", "AnyType", "", "Data from which to take property"); @@ -869,7 +901,7 @@ void RNA_api_ui_layout(StructRNA *srna) RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); parm = RNA_def_int(func, "active_layer", 0, 0, INT_MAX, "Active Layer", "", 0, INT_MAX); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); - + func = RNA_def_function(srna, "template_color_picker", "uiTemplateColorPicker"); RNA_def_function_ui_description(func, "Item. A color wheel widget to pick colors"); api_ui_item_rna_common(func); @@ -985,7 +1017,7 @@ void RNA_api_ui_layout(StructRNA *srna) func = RNA_def_function(srna, "template_edit_mode_selection", "uiTemplateEditModeSelection"); RNA_def_function_flag(func, FUNC_USE_CONTEXT); RNA_def_function_ui_description(func, "Inserts common 3DView Edit modes header UI (selector for selection mode)"); - + func = RNA_def_function(srna, "template_reports_banner", "uiTemplateReportsBanner"); RNA_def_function_flag(func, FUNC_USE_CONTEXT); @@ -1021,10 +1053,6 @@ void RNA_api_ui_layout(StructRNA *srna) RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); RNA_def_string(func, "name", NULL, 0, "", ""); - func = RNA_def_function(srna, "introspect", "uiLayoutIntrospect"); - parm = RNA_def_string(func, "string", NULL, 1024 * 1024, "Descr", "DESCR"); - RNA_def_function_return(func, parm); - /* color management templates */ func = RNA_def_function(srna, "template_colorspace_settings", "uiTemplateColorspaceSettings"); RNA_def_function_ui_description(func, "Item. A widget to control input color space settings."); diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 1cd3a8b83d7..3b9aa5bbaa4 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -78,11 +78,6 @@ const EnumPropertyItem rna_enum_navigation_mode_items[] = { {0, NULL, 0, NULL, NULL} }; -static const EnumPropertyItem rna_enum_studio_light_icons_id_items[] = { - {0, "DEFAULT", 0, "Default", ""}, - {0, NULL, 0, NULL, NULL} -}; - #if defined(WITH_INTERNATIONAL) || !defined(RNA_RUNTIME) static const EnumPropertyItem rna_enum_language_default_items[] = { @@ -191,7 +186,7 @@ static void rna_userdef_show_manipulator_update(Main *bmain, Scene *scene, Point } } } - + rna_userdef_update(bmain, scene, ptr); } @@ -258,7 +253,7 @@ static int rna_userdef_autokeymode_get(PointerRNA *ptr) { UserDef *userdef = (UserDef *)ptr->data; short retval = userdef->autokey_mode; - + if (!(userdef->autokey_mode & AUTOKEY_ON)) retval |= AUTOKEY_ON; @@ -291,10 +286,10 @@ static void rna_userdef_timecode_style_set(PointerRNA *ptr, int value) { UserDef *userdef = (UserDef *)ptr->data; int required_size = userdef->v2d_min_gridsize; - + /* set the timecode style */ userdef->timecode_style = value; - + /* adjust the v2d gridsize if needed so that timecodes don't overlap * NOTE: most of these have been hand-picked to avoid overlaps while still keeping * things from getting too blown out @@ -316,7 +311,7 @@ static void rna_userdef_timecode_style_set(PointerRNA *ptr, int value) required_size = 45; break; } - + if (U.v2d_min_gridsize < required_size) U.v2d_min_gridsize = required_size; } @@ -704,38 +699,6 @@ static int rna_UserDef_studiolight_index_get(PointerRNA *ptr) return sl->index; } -/* StudioLight.icon_id */ -static int rna_UserDef_studiolight_icon_id_get(PointerRNA *ptr) -{ - StudioLight *sl = (StudioLight *)ptr->data; - if (sl->flag & (STUDIOLIGHT_ORIENTATION_VIEWNORMAL | STUDIOLIGHT_ORIENTATION_CAMERA)) { - return 1; - } - return 0; -} - -static const EnumPropertyItem *rna_UserDef_studiolight_icon_id_itemf( - bContext *UNUSED(C), PointerRNA *ptr, - PropertyRNA *UNUSED(prop), bool *r_free) -{ - EnumPropertyItem *item = NULL; - int totitem = 0; - StudioLight *sl = (StudioLight *)ptr->data; - - if ((sl->flag & (STUDIOLIGHT_ORIENTATION_VIEWNORMAL | STUDIOLIGHT_ORIENTATION_CAMERA)) == 0) - { - EnumPropertyItem tmp = {0, sl->name, sl->radiance_icon_id, sl->name, ""}; - RNA_enum_item_add(&item, &totitem, &tmp); - } - { - EnumPropertyItem tmp = {1, sl->name, sl->irradiance_icon_id, sl->name, ""}; - RNA_enum_item_add(&item, &totitem, &tmp); - } - RNA_enum_item_end(&item, &totitem); - *r_free = true; - return item; -} - /* StudioLight.is_user_defined */ static int rna_UserDef_studiolight_is_user_defined_get(PointerRNA *ptr) { @@ -751,10 +714,10 @@ static int rna_UserDef_studiolight_show_expanded_get(PointerRNA *ptr) } static void rna_UserDef_studiolight_show_expanded_set(PointerRNA *ptr, const bool value) -{ +{ StudioLight *sl = (StudioLight *)ptr->data; sl->flag ^= STUDIOLIGHT_UI_EXPANDED; - sl->flag |= value?STUDIOLIGHT_UI_EXPANDED: 0; + sl->flag |= value ? STUDIOLIGHT_UI_EXPANDED : 0; } @@ -798,7 +761,7 @@ static void rna_def_userdef_theme_ui_font_style(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + static const EnumPropertyItem font_kerning_style[] = { {0, "UNFITTED", 0, "Unfitted", "Use scaled but un-grid-fitted kerning distances"}, {1, "FITTED", 0, "Fitted", "Use scaled and grid-fitted kerning distances"}, @@ -809,7 +772,7 @@ static void rna_def_userdef_theme_ui_font_style(BlenderRNA *brna) RNA_def_struct_sdna(srna, "uiFontStyle"); RNA_def_struct_clear_flag(srna, STRUCT_UNDO); RNA_def_struct_ui_text(srna, "Font Style", "Theme settings for Font"); - + prop = RNA_def_property(srna, "points", PROP_INT, PROP_NONE); RNA_def_property_range(prop, 6, 48); RNA_def_property_ui_text(prop, "Points", ""); @@ -825,13 +788,13 @@ static void rna_def_userdef_theme_ui_font_style(BlenderRNA *brna) RNA_def_property_range(prop, 0, 5); RNA_def_property_ui_text(prop, "Shadow Size", "Shadow size (0, 3 and 5 supported)"); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "shadow_offset_x", PROP_INT, PROP_PIXEL); RNA_def_property_int_sdna(prop, NULL, "shadx"); RNA_def_property_range(prop, -10, 10); RNA_def_property_ui_text(prop, "Shadow X Offset", "Shadow offset in pixels"); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "shadow_offset_y", PROP_INT, PROP_PIXEL); RNA_def_property_int_sdna(prop, NULL, "shady"); RNA_def_property_range(prop, -10, 10); @@ -855,14 +818,14 @@ static void rna_def_userdef_theme_ui_style(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + rna_def_userdef_theme_ui_font_style(brna); - + srna = RNA_def_struct(brna, "ThemeStyle", NULL); RNA_def_struct_sdna(srna, "uiStyle"); RNA_def_struct_clear_flag(srna, STRUCT_UNDO); RNA_def_struct_ui_text(srna, "Style", "Theme settings for style sets"); - + prop = RNA_def_property(srna, "panel_title", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); @@ -877,66 +840,66 @@ static void rna_def_userdef_theme_ui_style(BlenderRNA *brna) RNA_def_property_struct_type(prop, "ThemeFontStyle"); RNA_def_property_ui_text(prop, "Widget Label Style", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "widget", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "widget"); RNA_def_property_struct_type(prop, "ThemeFontStyle"); RNA_def_property_ui_text(prop, "Widget Style", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + } static void rna_def_userdef_theme_ui_wcol(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + srna = RNA_def_struct(brna, "ThemeWidgetColors", NULL); RNA_def_struct_sdna(srna, "uiWidgetColors"); RNA_def_struct_clear_flag(srna, STRUCT_UNDO); RNA_def_struct_ui_text(srna, "Theme Widget Color Set", "Theme settings for widget color sets"); - + prop = RNA_def_property(srna, "outline", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Outline", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "inner", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_array(prop, 4); RNA_def_property_ui_text(prop, "Inner", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "inner_sel", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_array(prop, 4); RNA_def_property_ui_text(prop, "Inner Selected", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "item", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_array(prop, 4); RNA_def_property_ui_text(prop, "Item", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "text", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Text", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "text_sel", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Text Selected", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "show_shaded", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "shaded", 1); RNA_def_property_ui_text(prop, "Shaded", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "shadetop", PROP_INT, PROP_NONE); RNA_def_property_range(prop, -100, 100); RNA_def_property_ui_text(prop, "Shade Top", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "shadedown", PROP_INT, PROP_NONE); RNA_def_property_range(prop, -100, 100); RNA_def_property_ui_text(prop, "Shade Down", ""); @@ -952,12 +915,12 @@ static void rna_def_userdef_theme_ui_wcol_state(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + srna = RNA_def_struct(brna, "ThemeWidgetStateColors", NULL); RNA_def_struct_sdna(srna, "uiWidgetStateColors"); RNA_def_struct_clear_flag(srna, STRUCT_UNDO); RNA_def_struct_ui_text(srna, "Theme Widget State Color", "Theme settings for widget state colors"); - + prop = RNA_def_property(srna, "inner_anim", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Animated", ""); @@ -967,7 +930,7 @@ static void rna_def_userdef_theme_ui_wcol_state(BlenderRNA *brna) RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Animated Selected", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "inner_key", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Keyframe", ""); @@ -1007,16 +970,16 @@ static void rna_def_userdef_theme_ui_panel(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + srna = RNA_def_struct(brna, "ThemePanelColors", NULL); RNA_def_struct_sdna(srna, "uiPanelColors"); RNA_def_struct_clear_flag(srna, STRUCT_UNDO); RNA_def_struct_ui_text(srna, "Theme Panel Color", "Theme settings for panel colors"); - + prop = RNA_def_property(srna, "header", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_ui_text(prop, "Header", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "back", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_ui_text(prop, "Background", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); @@ -1024,7 +987,7 @@ static void rna_def_userdef_theme_ui_panel(BlenderRNA *brna) prop = RNA_def_property(srna, "sub_back", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_ui_text(prop, "Sub Background", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "show_header", PROP_BOOLEAN, PROP_NONE); RNA_def_property_ui_text(prop, "Show Header", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); @@ -1079,7 +1042,7 @@ static void rna_def_userdef_theme_ui(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_ui_text(prop, "Regular Widget Colors", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "wcol_tool", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_ui_text(prop, "Tool Widget Colors", ""); @@ -1089,17 +1052,17 @@ static void rna_def_userdef_theme_ui(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_ui_text(prop, "Toolbar Item Widget Colors", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "wcol_radio", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_ui_text(prop, "Radio Widget Colors", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "wcol_text", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_ui_text(prop, "Text Widget Colors", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "wcol_option", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_ui_text(prop, "Option Widget Colors", ""); @@ -1109,32 +1072,32 @@ static void rna_def_userdef_theme_ui(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_ui_text(prop, "Toggle Widget Colors", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "wcol_num", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_ui_text(prop, "Number Widget Colors", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "wcol_numslider", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_ui_text(prop, "Slider Widget Colors", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "wcol_box", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_ui_text(prop, "Box Backdrop Colors", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "wcol_menu", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_ui_text(prop, "Menu Widget Colors", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "wcol_pulldown", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_ui_text(prop, "Pulldown Widget Colors", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "wcol_menu_back", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_ui_text(prop, "Menu Backdrop Colors", ""); @@ -1149,7 +1112,7 @@ static void rna_def_userdef_theme_ui(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_ui_text(prop, "Tooltip Colors", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "wcol_menu_item", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_ui_text(prop, "Menu Item Colors", ""); @@ -1159,7 +1122,7 @@ static void rna_def_userdef_theme_ui(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_ui_text(prop, "Scroll Widget Colors", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "wcol_progress", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_ui_text(prop, "Progress Bar Widget Colors", ""); @@ -1184,12 +1147,12 @@ static void rna_def_userdef_theme_ui(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Menu Shadow Strength", "Blending factor for menu shadows"); RNA_def_property_range(prop, 0.01f, 1.0f); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "menu_shadow_width", PROP_INT, PROP_PIXEL); RNA_def_property_ui_text(prop, "Menu Shadow Width", "Width of menu shadows, set to zero to disable"); RNA_def_property_range(prop, 0.0f, 24.0f); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "icon_file", PROP_STRING, PROP_FILEPATH); RNA_def_property_string_sdna(prop, NULL, "iconfile"); RNA_def_property_ui_text(prop, "Icon File", ""); @@ -1202,7 +1165,7 @@ static void rna_def_userdef_theme_ui(BlenderRNA *brna) prop = RNA_def_property(srna, "icon_saturation", PROP_FLOAT, PROP_FACTOR); RNA_def_property_ui_text(prop, "Icon Saturation", "Saturation of icons in the interface"); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "widget_emboss", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "widget_emboss"); RNA_def_property_array(prop, 4); @@ -1221,13 +1184,13 @@ static void rna_def_userdef_theme_ui(BlenderRNA *brna) RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "X Axis", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "axis_y", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "yaxis"); RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Y Axis", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "axis_z", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "zaxis"); RNA_def_property_array(prop, 3); @@ -1500,7 +1463,7 @@ static void rna_def_userdef_theme_spaces_edge(StructRNA *srna) RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Edge Sharp", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "edge_crease", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Edge Crease", ""); @@ -1571,7 +1534,7 @@ static void rna_def_userdef_theme_spaces_curves(StructRNA *srna, bool incl_nurbs bool incl_vector, bool incl_verthandle) { PropertyRNA *prop; - + if (incl_nurbs) { prop = RNA_def_property(srna, "nurb_uline", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "nurb_uline"); @@ -1661,7 +1624,7 @@ static void rna_def_userdef_theme_spaces_curves(StructRNA *srna, bool incl_nurbs RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Auto-Clamped handle color", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "handle_sel_auto_clamped", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "handle_sel_auto_clamped"); RNA_def_property_array(prop, 3); @@ -1746,11 +1709,16 @@ static void rna_def_userdef_theme_space_view3d(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Wire", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); + prop = RNA_def_property(srna, "wire_inactive", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Wire Inactive", "Color for wireframe when in edit mode, but edge selection is not active"); + RNA_def_property_update(prop, 0, "rna_userdef_update"); + prop = RNA_def_property(srna, "wire_edit", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_array(prop, 3); - RNA_def_property_ui_text(prop, "Wire Edit", ""); + RNA_def_property_ui_text(prop, "Wire Edit", "Color for wireframe when in edit mode, but edge selection is active"); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + /* Grease Pencil */ @@ -1941,7 +1909,7 @@ static void rna_def_userdef_theme_space_graph(BlenderRNA *brna) RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Current Frame", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "window_sliders", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "shade1"); RNA_def_property_array(prop, 3); @@ -1953,19 +1921,19 @@ static void rna_def_userdef_theme_space_graph(BlenderRNA *brna) RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Channels Region", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "dopesheet_channel", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "ds_channel"); RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Dope Sheet Channel", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "dopesheet_subchannel", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "ds_subchannel"); RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Dope Sheet Sub-Channel", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "channel_group", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "group"); RNA_def_property_array(prop, 3); @@ -1977,7 +1945,7 @@ static void rna_def_userdef_theme_space_graph(BlenderRNA *brna) RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Active Channel Group", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + rna_def_userdef_theme_spaces_vertex(srna); rna_def_userdef_theme_spaces_curves(srna, false, true, true, true); } @@ -2053,33 +2021,33 @@ static void rna_def_userdef_theme_space_console(BlenderRNA *brna) RNA_def_struct_sdna(srna, "ThemeSpace"); RNA_def_struct_clear_flag(srna, STRUCT_UNDO); RNA_def_struct_ui_text(srna, "Theme Console", "Theme settings for the Console"); - + rna_def_userdef_theme_spaces_main(srna); - + prop = RNA_def_property(srna, "line_output", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "console_output"); RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Line Output", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "line_input", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "console_input"); RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Line Input", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "line_info", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "console_info"); RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Line Info", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "line_error", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "console_error"); RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Line Error", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "cursor", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "console_cursor"); RNA_def_property_array(prop, 3); @@ -2210,13 +2178,13 @@ static void rna_def_userdef_theme_space_text(BlenderRNA *brna) RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Cursor", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "syntax_builtin", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "syntaxb"); RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Syntax Built-in", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "syntax_symbols", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "syntaxs"); RNA_def_property_array(prop, 3); @@ -2246,7 +2214,7 @@ static void rna_def_userdef_theme_space_text(BlenderRNA *brna) RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Syntax Comment", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "syntax_string", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "syntaxl"); RNA_def_property_array(prop, 3); @@ -2274,7 +2242,7 @@ 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); @@ -2318,13 +2286,13 @@ static void rna_def_userdef_theme_space_node(BlenderRNA *brna) RNA_def_property_array(prop, 4); RNA_def_property_ui_text(prop, "Node Backdrop", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "converter_node", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "syntaxv"); RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Converter Node", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "color_node", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "syntaxb"); RNA_def_property_array(prop, 3); @@ -2348,7 +2316,7 @@ static void rna_def_userdef_theme_space_node(BlenderRNA *brna) RNA_def_property_array(prop, 4); RNA_def_property_ui_text(prop, "Frame Node", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "matte_node", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "syntaxs"); RNA_def_property_array(prop, 3); @@ -2455,7 +2423,7 @@ static void rna_def_userdef_theme_space_image(BlenderRNA *brna) rna_def_userdef_theme_spaces_gpencil(srna); rna_def_userdef_theme_spaces_vertex(srna); rna_def_userdef_theme_spaces_face(srna); - + prop = RNA_def_property(srna, "editmesh_active", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_array(prop, 4); @@ -2645,7 +2613,7 @@ static void rna_def_userdef_theme_space_seq(BlenderRNA *brna) RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Draw Action", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "preview_back", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "preview_back"); RNA_def_property_array(prop, 3); @@ -2684,13 +2652,13 @@ static void rna_def_userdef_theme_space_action(BlenderRNA *brna) RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Grid", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "frame_current", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "cframe"); RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Current Frame", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "value_sliders", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "face"); RNA_def_property_array(prop, 3); @@ -2702,21 +2670,21 @@ static void rna_def_userdef_theme_space_action(BlenderRNA *brna) RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "View Sliders", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - - + + prop = RNA_def_property(srna, "dopesheet_channel", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "ds_channel"); RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Dope Sheet Channel", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "dopesheet_subchannel", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "ds_subchannel"); RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Dope Sheet Sub-Channel", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - - + + prop = RNA_def_property(srna, "channels", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "shade2"); RNA_def_property_array(prop, 3); @@ -2740,8 +2708,8 @@ static void rna_def_userdef_theme_space_action(BlenderRNA *brna) RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Active Channel Group", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - - + + prop = RNA_def_property(srna, "long_key", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "strip"); RNA_def_property_array(prop, 3); @@ -2754,76 +2722,76 @@ static void rna_def_userdef_theme_space_action(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Long Key Selected", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - - + + prop = RNA_def_property(srna, "keyframe", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "keytype_keyframe"); RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Keyframe", "Color of Keyframe"); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "keyframe_selected", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "keytype_keyframe_select"); RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Keyframe Selected", "Color of selected keyframe"); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "keyframe_extreme", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "keytype_extreme"); RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Extreme Keyframe", "Color of extreme keyframe"); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "keyframe_extreme_selected", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "keytype_extreme_select"); RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Extreme Keyframe Selected", "Color of selected extreme keyframe"); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "keyframe_breakdown", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "keytype_breakdown"); RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Breakdown Keyframe", "Color of breakdown keyframe"); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "keyframe_breakdown_selected", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "keytype_breakdown_select"); RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Breakdown Keyframe Selected", "Color of selected breakdown keyframe"); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "keyframe_jitter", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "keytype_jitter"); RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Jitter Keyframe", "Color of jitter keyframe"); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "keyframe_jitter_selected", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "keytype_jitter_select"); RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Jitter Keyframe Selected", "Color of selected jitter keyframe"); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "keyframe_border", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "keyborder"); RNA_def_property_array(prop, 4); RNA_def_property_ui_text(prop, "Keyframe Border", "Color of keyframe border"); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "keyframe_border_selected", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "keyborder_select"); RNA_def_property_array(prop, 4); RNA_def_property_ui_text(prop, "Keyframe Border Selected", "Color of selected keyframe border"); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "keyframe_scale_factor", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "keyframe_scale_fac"); RNA_def_property_float_default(prop, 1.0f); RNA_def_property_ui_text(prop, "Keyframe Scale Factor", "Scale factor for adjusting the height of keyframes"); RNA_def_property_range(prop, 0.8f, 5.0f); /* Note: These limits prevent buttons overlapping (min), and excessive size... (max) */ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_DOPESHEET, "rna_userdef_update"); - - + + prop = RNA_def_property(srna, "summary", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "anim_active"); RNA_def_property_array(prop, 4); @@ -2855,94 +2823,94 @@ static void rna_def_userdef_theme_space_nla(BlenderRNA *brna) RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "View Sliders", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "active_action", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "anim_active"); RNA_def_property_array(prop, 4); RNA_def_property_ui_text(prop, "Active Action", "Animation data-block has active action"); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "active_action_unset", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "anim_non_active"); RNA_def_property_array(prop, 4); RNA_def_property_ui_text(prop, "No Active Action", "Animation data-block doesn't have active action"); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "strips", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "strip"); RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Strips", "Action-Clip Strip - Unselected"); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "strips_selected", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "strip_select"); RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Strips Selected", "Action-Clip Strip - Selected"); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "transition_strips", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "nla_transition"); RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Transitions", "Transition Strip - Unselected"); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "transition_strips_selected", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "nla_transition_sel"); RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Transitions Selected", "Transition Strip - Selected"); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "meta_strips", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "nla_meta"); RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Meta Strips", "Meta Strip - Unselected (for grouping related strips)"); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "meta_strips_selected", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "nla_meta_sel"); RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Meta Strips Selected", "Meta Strip - Selected (for grouping related strips)"); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "sound_strips", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "nla_sound"); RNA_def_property_array(prop, 3); - RNA_def_property_ui_text(prop, "Sound Strips", + RNA_def_property_ui_text(prop, "Sound Strips", "Sound Strip - Unselected (for timing speaker sounds)"); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "sound_strips_selected", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "nla_sound_sel"); RNA_def_property_array(prop, 3); - RNA_def_property_ui_text(prop, "Sound Strips Selected", + RNA_def_property_ui_text(prop, "Sound Strips Selected", "Sound Strip - Selected (for timing speaker sounds)"); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "tweak", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "nla_tweaking"); RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Tweak", "Color for strip/action being 'tweaked' or edited"); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "tweak_duplicate", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "nla_tweakdupli"); RNA_def_property_array(prop, 3); - RNA_def_property_ui_text(prop, "Tweak Duplicate Flag", + RNA_def_property_ui_text(prop, "Tweak Duplicate Flag", "Warning/error indicator color for strips referencing the strip being tweaked"); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "keyframe_border", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "keyborder"); RNA_def_property_array(prop, 4); RNA_def_property_ui_text(prop, "Keyframe Border", "Color of keyframe border"); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "keyframe_border_selected", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "keyborder_select"); RNA_def_property_array(prop, 4); RNA_def_property_ui_text(prop, "Keyframe Border Selected", "Color of selected keyframe border"); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "frame_current", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "cframe"); RNA_def_property_array(prop, 3); @@ -2998,7 +2966,7 @@ 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); @@ -3102,7 +3070,7 @@ static void rna_def_userdef_themes(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + static const EnumPropertyItem active_theme_area[] = { {0, "USER_INTERFACE", ICON_UI, "User Interface", ""}, {19, "STYLE", ICON_FONTPREVIEW, "Text Style", ""}, @@ -3227,7 +3195,7 @@ static void rna_def_userdef_themes(BlenderRNA *brna) RNA_def_property_pointer_sdna(prop, NULL, "tuserpref"); RNA_def_property_struct_type(prop, "ThemeUserPreferences"); RNA_def_property_ui_text(prop, "User Preferences", ""); - + prop = RNA_def_property(srna, "console", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "tconsole"); @@ -3315,12 +3283,6 @@ static void rna_def_userdef_studiolight(BlenderRNA *brna) RNA_def_property_enum_funcs(prop, "rna_UserDef_studiolight_orientation_get", "rna_UserDef_studiolight_orientation_set", NULL); RNA_def_property_ui_text(prop, "Orientation", ""); - prop = RNA_def_property(srna, "icon_id", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_funcs(prop, "rna_UserDef_studiolight_icon_id_get", NULL, "rna_UserDef_studiolight_icon_id_itemf"); - RNA_def_property_enum_items(prop, rna_enum_studio_light_icons_id_items); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "Preview", "Preview of the studiolight"); - prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); RNA_def_property_string_funcs(prop, "rna_UserDef_studiolight_name_get", "rna_UserDef_studiolight_name_length", NULL); RNA_def_property_ui_text(prop, "Name", ""); @@ -3380,14 +3342,14 @@ static void rna_def_userdef_addon_pref(BlenderRNA *brna) static void rna_def_userdef_dothemes(BlenderRNA *brna) { - + rna_def_userdef_theme_ui_style(brna); rna_def_userdef_theme_ui(brna); rna_def_userdef_theme_space_generic(brna); rna_def_userdef_theme_space_gradient(brna); rna_def_userdef_theme_space_list_generic(brna); - + rna_def_userdef_theme_space_view3d(brna); rna_def_userdef_theme_space_graph(brna); rna_def_userdef_theme_space_file(brna); @@ -3419,7 +3381,7 @@ static void rna_def_userdef_solidlight(BlenderRNA *brna) RNA_def_struct_sdna(srna, "SolidLight"); RNA_def_struct_clear_flag(srna, STRUCT_UNDO); RNA_def_struct_ui_text(srna, "Solid Light", "Light used for OpenGL lighting in solid draw mode"); - + prop = RNA_def_property(srna, "use", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", 1); RNA_def_property_ui_text(prop, "Enabled", "Enable this OpenGL light in solid draw mode"); @@ -3524,7 +3486,7 @@ static void rna_def_userdef_view(BlenderRNA *brna) PropertyRNA *prop; StructRNA *srna; - + srna = RNA_def_struct(brna, "UserPreferencesView", NULL); RNA_def_struct_sdna(srna, "UserDef"); RNA_def_struct_nested(brna, srna, "UserPreferences"); @@ -3596,7 +3558,7 @@ static void rna_def_userdef_view(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_MENUOPENAUTO); RNA_def_property_ui_text(prop, "Open On Mouse Over", "Open menu buttons and pulldowns automatically when the mouse is hovering"); - + prop = RNA_def_property(srna, "open_toplevel_delay", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "menuthreshold1"); RNA_def_property_range(prop, 1, 40); @@ -3700,7 +3662,7 @@ static void rna_def_userdef_view(BlenderRNA *brna) prop = RNA_def_property(srna, "use_rotate_around_active", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_ORBIT_SELECTION); RNA_def_property_ui_text(prop, "Rotate Around Selection", "Use selection as the pivot point"); - + /* mini axis */ prop = RNA_def_property(srna, "show_mini_axis", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_SHOW_ROTVIEWICON); @@ -3740,7 +3702,7 @@ static void rna_def_userdef_view(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "manipulator_flag", USER_MANIPULATOR_DRAW_NAVIGATE); RNA_def_property_ui_text(prop, "Navigate Manipulator", "Use 3D navigation manipulator"); RNA_def_property_update(prop, 0, "rna_userdef_show_manipulator_update"); - + /* TODO, expose once it's working. */ #if 0 prop = RNA_def_property(srna, "show_manipulator_shaded", PROP_BOOLEAN, PROP_NONE); @@ -3761,7 +3723,7 @@ static void rna_def_userdef_view(BlenderRNA *brna) RNA_def_property_range(prop, 4, 10); RNA_def_property_ui_text(prop, "Object Origin Size", "Diameter in Pixels for Object/Lamp origin display"); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + /* View2D Grid Displays */ prop = RNA_def_property(srna, "view2d_grid_spacing_min", PROP_INT, PROP_PIXEL); RNA_def_property_int_sdna(prop, NULL, "v2d_min_gridsize"); @@ -3769,7 +3731,7 @@ static void rna_def_userdef_view(BlenderRNA *brna) RNA_def_property_ui_text(prop, "2D View Minimum Grid Spacing", "Minimum number of pixels between each gridline in 2D Viewports"); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + /* TODO: add a setter for this, so that we can bump up the minimum size as necessary... */ prop = RNA_def_property(srna, "timecode_style", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, timecode_styles); @@ -3806,14 +3768,14 @@ static void rna_def_userdef_edit(BlenderRNA *brna) {AUTOKEY_MODE_EDITKEYS, "REPLACE_KEYS", 0, "Replace", ""}, {0, NULL, 0, NULL, NULL} }; - + static const EnumPropertyItem material_link_items[] = { {0, "OBDATA", 0, "ObData", "Toggle whether the material is linked to object data or the object block"}, {USER_MAT_ON_OB, "OBJECT", 0, "Object", "Toggle whether the material is linked to object data or the object block"}, {0, NULL, 0, NULL, NULL} }; - + static const EnumPropertyItem object_align_items[] = { {0, "WORLD", 0, "World", "Align newly added objects to the world coordinate system"}, {USER_ADD_VIEWALIGNED, "VIEW", 0, "View", "Align newly added objects facing the active 3D View direction"}, @@ -3825,15 +3787,15 @@ static void rna_def_userdef_edit(BlenderRNA *brna) RNA_def_struct_nested(brna, srna, "UserPreferences"); RNA_def_struct_clear_flag(srna, STRUCT_UNDO); RNA_def_struct_ui_text(srna, "Edit Methods", "Settings for interacting with Blender data"); - + /* Edit Methods */ - + prop = RNA_def_property(srna, "material_link", PROP_ENUM, PROP_NONE); RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag"); RNA_def_property_enum_items(prop, material_link_items); RNA_def_property_ui_text(prop, "Material Link To", "Toggle whether the material is linked to object data or the object block"); - + prop = RNA_def_property(srna, "object_align", PROP_ENUM, PROP_NONE); RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag"); RNA_def_property_enum_items(prop, object_align_items); @@ -3849,7 +3811,7 @@ static void rna_def_userdef_edit(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_RELEASECONFIRM); RNA_def_property_ui_text(prop, "Release confirms", "Moving things with a mouse drag confirms when releasing the button"); - + /* Undo */ prop = RNA_def_property(srna, "undo_steps", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "undosteps"); @@ -3892,7 +3854,7 @@ static void rna_def_userdef_edit(BlenderRNA *brna) RNA_def_property_boolean_negative_sdna(prop, NULL, "autokey_flag", AUTOKEY_FLAG_NOWARNING); RNA_def_property_ui_text(prop, "Show Auto Keying Warning", "Show warning indicators when transforming objects and bones if auto keying is enabled"); - + /* keyframing settings */ prop = RNA_def_property(srna, "use_keyframe_insert_needed", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "autokey_flag", AUTOKEY_FLAG_INSERTNEEDED); @@ -3901,13 +3863,13 @@ static void rna_def_userdef_edit(BlenderRNA *brna) prop = RNA_def_property(srna, "use_visual_keying", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "autokey_flag", AUTOKEY_FLAG_AUTOMATKEY); RNA_def_property_ui_text(prop, "Visual Keying", "Use Visual keying automatically for constrained objects"); - + prop = RNA_def_property(srna, "use_insertkey_xyz_to_rgb", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "autokey_flag", AUTOKEY_FLAG_XYZ2RGB); RNA_def_property_ui_text(prop, "New F-Curve Colors - XYZ to RGB", "Color for newly added transformation F-Curves (Location, Rotation, Scale) " "and also Color is based on the transform axis"); - + prop = RNA_def_property(srna, "keyframe_new_interpolation_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, rna_enum_beztriple_interpolation_mode_items); RNA_def_property_enum_sdna(prop, NULL, "ipo_new"); @@ -3919,7 +3881,7 @@ static void rna_def_userdef_edit(BlenderRNA *brna) RNA_def_property_enum_items(prop, rna_enum_keyframe_handle_type_items); RNA_def_property_enum_sdna(prop, NULL, "keyhandles_new"); RNA_def_property_ui_text(prop, "New Handles Type", "Handle type for handles of new keyframes"); - + /* frame numbers */ prop = RNA_def_property(srna, "use_negative_frames", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", USER_NONEGFRAMES); @@ -3933,7 +3895,7 @@ static void rna_def_userdef_edit(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Unselected F-Curve Visibility", "Amount that unselected F-Curves stand out from the background (Graph Editor)"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_GRAPH, NULL); - + /* grease pencil */ prop = RNA_def_property(srna, "grease_pencil_manhattan_distance", PROP_INT, PROP_PIXEL); RNA_def_property_int_sdna(prop, NULL, "gp_manhattendist"); @@ -3955,13 +3917,13 @@ static void rna_def_userdef_edit(BlenderRNA *brna) RNA_def_property_int_sdna(prop, NULL, "gp_eraser"); RNA_def_property_range(prop, 1, 500); RNA_def_property_ui_text(prop, "Grease Pencil Eraser Radius", "Radius of eraser 'brush'"); - - + + prop = RNA_def_property(srna, "grease_pencil_default_color", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "gpencil_new_layer_col"); RNA_def_property_array(prop, 4); RNA_def_property_ui_text(prop, "Grease Pencil Default Color", "Color of new Grease Pencil layers"); - + /* sculpt and paint */ prop = RNA_def_property(srna, "sculpt_paint_overlay_color", PROP_FLOAT, PROP_COLOR_GAMMA); @@ -3977,7 +3939,7 @@ static void rna_def_userdef_edit(BlenderRNA *brna) prop = RNA_def_property(srna, "use_duplicate_surface", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "dupflag", USER_DUP_SURF); RNA_def_property_ui_text(prop, "Duplicate Surface", "Causes surface data to be duplicated with the object"); - + prop = RNA_def_property(srna, "use_duplicate_curve", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "dupflag", USER_DUP_CURVE); RNA_def_property_ui_text(prop, "Duplicate Curve", "Causes curve data to be duplicated with the object"); @@ -3989,7 +3951,7 @@ static void rna_def_userdef_edit(BlenderRNA *brna) prop = RNA_def_property(srna, "use_duplicate_metaball", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "dupflag", USER_DUP_MBALL); RNA_def_property_ui_text(prop, "Duplicate Metaball", "Causes metaball data to be duplicated with the object"); - + prop = RNA_def_property(srna, "use_duplicate_armature", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "dupflag", USER_DUP_ARM); RNA_def_property_ui_text(prop, "Duplicate Armature", "Causes armature data to be duplicated with the object"); @@ -4005,7 +3967,7 @@ static void rna_def_userdef_edit(BlenderRNA *brna) prop = RNA_def_property(srna, "use_duplicate_texture", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "dupflag", USER_DUP_TEX); RNA_def_property_ui_text(prop, "Duplicate Texture", "Causes texture data to be duplicated with the object"); - + /* xxx */ prop = RNA_def_property(srna, "use_duplicate_fcurve", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "dupflag", USER_DUP_IPO); @@ -4014,7 +3976,7 @@ static void rna_def_userdef_edit(BlenderRNA *brna) prop = RNA_def_property(srna, "use_duplicate_action", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "dupflag", USER_DUP_ACT); RNA_def_property_ui_text(prop, "Duplicate Action", "Causes actions to be duplicated with the object"); - + prop = RNA_def_property(srna, "use_duplicate_particle", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "dupflag", USER_DUP_PSYS); RNA_def_property_ui_text(prop, "Duplicate Particle", "Causes particle systems to be duplicated with the object"); @@ -4105,7 +4067,7 @@ static void rna_def_userdef_system(BlenderRNA *brna) {USER_CP_SQUARE_HV, "SQUARE_HV", 0, "Square (HV + S)", "A square showing Hue/Value, with Saturation slider"}, {0, NULL, 0, NULL, NULL} }; - + static const EnumPropertyItem multi_sample_levels[] = { {USER_MULTISAMPLE_NONE, "NONE", 0, "No MultiSample", "Do not use OpenGL MultiSample"}, {USER_MULTISAMPLE_2, "2", 0, "MultiSample: 2", "Use 2x OpenGL MultiSample (requires restart)"}, @@ -4136,7 +4098,7 @@ static void rna_def_userdef_system(BlenderRNA *brna) RNA_def_struct_ui_text(srna, "System & OpenGL", "Graphics driver and operating system settings"); /* Language */ - + prop = RNA_def_property(srna, "use_international_fonts", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "transopts", USER_DOTRANSLATE); RNA_def_property_ui_text(prop, "International Fonts", "Use international fonts"); @@ -4236,7 +4198,7 @@ static void rna_def_userdef_system(BlenderRNA *brna) RNA_def_property_enum_sdna(prop, NULL, "color_picker_type"); RNA_def_property_ui_text(prop, "Color Picker Type", "Different styles of displaying the color picker widget"); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "use_preview_images", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_ALLWINCODECS); RNA_def_property_ui_text(prop, "Enable All Codecs", @@ -4296,7 +4258,7 @@ static void rna_def_userdef_system(BlenderRNA *brna) "Quality of the anisotropic filtering (values greater than 1.0 enable anisotropic " "filtering)"); RNA_def_property_update(prop, 0, "rna_userdef_anisotropic_update"); - + prop = RNA_def_property(srna, "gl_texture_limit", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "glreslimit"); RNA_def_property_enum_items(prop, gl_texture_clamp_items); @@ -4385,7 +4347,7 @@ static void rna_def_userdef_system(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "uiflag2", USER_REGION_OVERLAP); RNA_def_property_ui_text(prop, "Region Overlap", "Draw tool/property regions over the main region, when using Triple Buffer"); - RNA_def_property_update(prop, 0, "rna_userdef_dpi_update"); + RNA_def_property_update(prop, 0, "rna_userdef_dpi_update"); #ifdef WITH_OPENSUBDIV prop = RNA_def_property(srna, "opensubdiv_compute_type", PROP_ENUM, PROP_NONE); @@ -4444,44 +4406,44 @@ static void rna_def_userdef_input(BlenderRNA *brna) "Zoom in and out like scaling the view, mouse movements relative to center"}, {0, NULL, 0, NULL, NULL} }; - + static const EnumPropertyItem view_zoom_axes[] = { {0, "VERTICAL", 0, "Vertical", "Zoom in and out based on vertical mouse movement"}, {USER_ZOOM_HORIZ, "HORIZONTAL", 0, "Horizontal", "Zoom in and out based on horizontal mouse movement"}, {0, NULL, 0, NULL, NULL} }; - + srna = RNA_def_struct(brna, "UserPreferencesInput", NULL); RNA_def_struct_sdna(srna, "UserDef"); RNA_def_struct_nested(brna, srna, "UserPreferences"); RNA_def_struct_clear_flag(srna, STRUCT_UNDO); RNA_def_struct_ui_text(srna, "Input", "Settings for input devices"); - + prop = RNA_def_property(srna, "select_mouse", PROP_ENUM, PROP_NONE); RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag"); RNA_def_property_enum_items(prop, select_mouse_items); RNA_def_property_enum_funcs(prop, NULL, "rna_userdef_select_mouse_set", NULL); RNA_def_property_ui_text(prop, "Select Mouse", "Mouse button used for selection"); - + prop = RNA_def_property(srna, "view_zoom_method", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "viewzoom"); RNA_def_property_enum_items(prop, view_zoom_styles); RNA_def_property_ui_text(prop, "Zoom Style", "Which style to use for viewport scaling"); - + prop = RNA_def_property(srna, "view_zoom_axis", PROP_ENUM, PROP_NONE); RNA_def_property_enum_bitflag_sdna(prop, NULL, "uiflag"); RNA_def_property_enum_items(prop, view_zoom_axes); RNA_def_property_ui_text(prop, "Zoom Axis", "Axis of mouse movement to zoom in or out on"); - + prop = RNA_def_property(srna, "invert_mouse_zoom", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_ZOOM_INVERT); RNA_def_property_ui_text(prop, "Invert Zoom Direction", "Invert the axis of mouse movement for zooming"); - + prop = RNA_def_property(srna, "view_rotate_method", PROP_ENUM, PROP_NONE); RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag"); RNA_def_property_enum_items(prop, view_rotation_items); RNA_def_property_ui_text(prop, "View Rotation", "Rotation style in the viewport"); - + prop = RNA_def_property(srna, "use_mouse_continuous", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_CONTINUOUS_MOUSE); RNA_def_property_ui_text(prop, "Continuous Grab", @@ -4519,7 +4481,7 @@ static void rna_def_userdef_input(BlenderRNA *brna) prop = RNA_def_property(srna, "ndof_sensitivity", PROP_FLOAT, PROP_NONE); RNA_def_property_range(prop, 0.01f, 40.0f); RNA_def_property_ui_text(prop, "Sensitivity", "Overall sensitivity of the 3D Mouse for panning"); - + prop = RNA_def_property(srna, "ndof_orbit_sensitivity", PROP_FLOAT, PROP_NONE); RNA_def_property_range(prop, 0.01f, 40.0f); RNA_def_property_ui_text(prop, "Orbit Sensitivity", "Overall sensitivity of the 3D Mouse for orbiting"); @@ -4543,7 +4505,7 @@ static void rna_def_userdef_input(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "ndof_flag", NDOF_SHOW_GUIDE); RNA_def_property_ui_text(prop, "Show Navigation Guide", "Display the center and axis during rotation"); /* TODO: update description when fly-mode visuals are in place ("projected position in fly mode")*/ - + /* 3D view */ prop = RNA_def_property(srna, "ndof_view_navigate_method", PROP_ENUM, PROP_NONE); RNA_def_property_enum_bitflag_sdna(prop, NULL, "ndof_flag"); @@ -4615,13 +4577,13 @@ static void rna_def_userdef_input(BlenderRNA *brna) prop = RNA_def_property(srna, "use_emulate_numpad", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_NONUMPAD); RNA_def_property_ui_text(prop, "Emulate Numpad", "Main 1 to 0 keys act as the numpad ones (useful for laptops)"); - + /* middle mouse button */ prop = RNA_def_property(srna, "use_mouse_mmb_paste", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_MMB_PASTE); RNA_def_property_ui_text(prop, "Middle Mouse Paste", "In text window, paste with middle mouse button instead of panning"); - + prop = RNA_def_property(srna, "invert_zoom_wheel", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_WHEELZOOMDIR); RNA_def_property_ui_text(prop, "Wheel Invert Zoom", "Swap the Mouse Wheel zoom direction"); @@ -4630,7 +4592,7 @@ static void rna_def_userdef_input(BlenderRNA *brna) RNA_def_property_int_sdna(prop, NULL, "wheellinescroll"); RNA_def_property_range(prop, 0, 32); RNA_def_property_ui_text(prop, "Wheel Scroll Lines", "Number of lines scrolled at a time with the mouse wheel"); - + prop = RNA_def_property(srna, "use_trackpad_natural", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "uiflag2", USER_TRACKPAD_NATURAL); RNA_def_property_ui_text(prop, "Trackpad Natural", @@ -4645,7 +4607,7 @@ static void rna_def_userdef_filepaths(BlenderRNA *brna) { PropertyRNA *prop; StructRNA *srna; - + static const EnumPropertyItem anim_player_presets[] = { {0, "INTERNAL", 0, "Internal", "Built-in animation player"}, {2, "DJV", 0, "Djv", "Open source frame player: http://djv.sourceforge.net"}, @@ -4655,22 +4617,22 @@ static void rna_def_userdef_filepaths(BlenderRNA *brna) {50, "CUSTOM", 0, "Custom", "Custom animation player executable path"}, {0, NULL, 0, NULL, NULL} }; - + srna = RNA_def_struct(brna, "UserPreferencesFilePaths", NULL); RNA_def_struct_sdna(srna, "UserDef"); RNA_def_struct_nested(brna, srna, "UserPreferences"); RNA_def_struct_clear_flag(srna, STRUCT_UNDO); RNA_def_struct_ui_text(srna, "File Paths", "Default paths for external files"); - + prop = RNA_def_property(srna, "show_hidden_files_datablocks", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_HIDE_DOT); RNA_def_property_ui_text(prop, "Hide Dot Files/Data-Blocks", "Hide files/data-blocks that start with a dot (.*)"); - + prop = RNA_def_property(srna, "use_filter_files", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_FILTERFILEEXTS); RNA_def_property_ui_text(prop, "Filter File Extensions", "Display only files with extensions in the image select window"); - + prop = RNA_def_property(srna, "hide_recent_locations", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_HIDE_RECENT); RNA_def_property_ui_text(prop, "Hide Recent Locations", "Hide recent locations in the file selector"); @@ -4686,7 +4648,7 @@ static void rna_def_userdef_filepaths(BlenderRNA *brna) prop = RNA_def_property(srna, "use_relative_paths", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_RELPATHS); RNA_def_property_ui_text(prop, "Relative Paths", "Default relative path option for the file selector"); - + prop = RNA_def_property(srna, "use_file_compression", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_FILECOMPRESS); RNA_def_property_ui_text(prop, "Compress File", "Enable file compression when saving .blend files"); @@ -4738,7 +4700,7 @@ static void rna_def_userdef_filepaths(BlenderRNA *brna) prop = RNA_def_property(srna, "image_editor", PROP_STRING, PROP_FILEPATH); RNA_def_property_string_sdna(prop, NULL, "image_editor"); RNA_def_property_ui_text(prop, "Image Editor", "Path to an image editor"); - + prop = RNA_def_property(srna, "animation_player", PROP_STRING, PROP_FILEPATH); RNA_def_property_string_sdna(prop, NULL, "anim_player"); RNA_def_property_ui_text(prop, "Animation Player", "Path to a custom animation/frame sequence player"); @@ -4747,7 +4709,7 @@ static void rna_def_userdef_filepaths(BlenderRNA *brna) RNA_def_property_enum_sdna(prop, NULL, "anim_player_preset"); RNA_def_property_enum_items(prop, anim_player_presets); RNA_def_property_ui_text(prop, "Animation Player Preset", "Preset configs for external animation players"); - + /* Autosave */ prop = RNA_def_property(srna, "save_version", PROP_INT, PROP_NONE); @@ -4773,7 +4735,7 @@ static void rna_def_userdef_filepaths(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "uiflag2", USER_KEEP_SESSION); RNA_def_property_ui_text(prop, "Keep Session", "Always load session recovery and save it after quitting Blender"); - + prop = RNA_def_property(srna, "recent_files", PROP_INT, PROP_NONE); RNA_def_property_range(prop, 0, 30); RNA_def_property_ui_text(prop, "Recent Files", "Maximum number of recently opened files to remember"); @@ -4884,7 +4846,7 @@ void RNA_def_userdef(BlenderRNA *brna) RNA_def_property_collection_sdna(prop, NULL, "uistyles", NULL); RNA_def_property_struct_type(prop, "ThemeStyle"); RNA_def_property_ui_text(prop, "Styles", ""); - + prop = RNA_def_property(srna, "addons", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "addons", NULL); RNA_def_property_struct_type(prop, "Addon"); @@ -4909,25 +4871,25 @@ void RNA_def_userdef(BlenderRNA *brna) RNA_def_property_struct_type(prop, "UserPreferencesEdit"); RNA_def_property_pointer_funcs(prop, "rna_UserDef_edit_get", NULL, NULL, NULL); RNA_def_property_ui_text(prop, "Edit Methods", "Settings for interacting with Blender data"); - + prop = RNA_def_property(srna, "inputs", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_struct_type(prop, "UserPreferencesInput"); RNA_def_property_pointer_funcs(prop, "rna_UserDef_input_get", NULL, NULL, NULL); RNA_def_property_ui_text(prop, "Inputs", "Settings for input devices"); - + prop = RNA_def_property(srna, "filepaths", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_struct_type(prop, "UserPreferencesFilePaths"); RNA_def_property_pointer_funcs(prop, "rna_UserDef_filepaths_get", NULL, NULL, NULL); RNA_def_property_ui_text(prop, "File Paths", "Default paths for external files"); - + prop = RNA_def_property(srna, "system", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_struct_type(prop, "UserPreferencesSystem"); RNA_def_property_pointer_funcs(prop, "rna_UserDef_system_get", NULL, NULL, NULL); RNA_def_property_ui_text(prop, "System & OpenGL", "Graphics driver and operating system settings"); - + prop = RNA_def_int_vector(srna, "version", 3, NULL, 0, INT_MAX, "Version", "Version of Blender the userpref.blend was saved with", 0, INT_MAX); RNA_def_property_int_funcs(prop, "rna_userdef_version_get", NULL, NULL); @@ -4936,9 +4898,10 @@ void RNA_def_userdef(BlenderRNA *brna) prop = RNA_def_property(srna, "studio_lights", PROP_COLLECTION, PROP_NONE); RNA_def_property_struct_type(prop, "StudioLight"); - RNA_def_property_collection_funcs(prop, "rna_UserDef_studiolight_begin", "rna_iterator_listbase_next", - "rna_iterator_listbase_end", "rna_iterator_listbase_get", - NULL, NULL, NULL, NULL); + RNA_def_property_collection_funcs( + prop, "rna_UserDef_studiolight_begin", "rna_iterator_listbase_next", + "rna_iterator_listbase_end", "rna_iterator_listbase_get", + NULL, NULL, NULL, NULL); func = RNA_def_function(srna, "studio_lights_refresh", "rna_UserDef_studiolight_refresh"); RNA_def_function_ui_description(func, "Refresh Studio Lights"); @@ -4954,7 +4917,7 @@ void RNA_def_userdef(BlenderRNA *brna) rna_def_userdef_addon_pref(brna); rna_def_userdef_studiolight(brna); rna_def_userdef_pathcompare(brna); - + } #endif diff --git a/source/blender/makesrna/intern/rna_vfont.c b/source/blender/makesrna/intern/rna_vfont.c index 78d46d35246..487b5220c86 100644 --- a/source/blender/makesrna/intern/rna_vfont.c +++ b/source/blender/makesrna/intern/rna_vfont.c @@ -70,7 +70,7 @@ void RNA_def_vfont(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + srna = RNA_def_struct(brna, "VectorFont", "ID"); RNA_def_struct_ui_text(srna, "Vector Font", "Vector font for Text objects"); RNA_def_struct_sdna(srna, "VFont"); diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c index 3aa59ca564f..c4e15174c88 100644 --- a/source/blender/makesrna/intern/rna_wm.c +++ b/source/blender/makesrna/intern/rna_wm.c @@ -500,7 +500,7 @@ static wmOperator *rna_OperatorProperties_find_operator(PointerRNA *ptr) } } } - + return NULL; } @@ -796,7 +796,7 @@ static PointerRNA rna_KeyMapItem_properties_get(PointerRNA *ptr) if (kmi->ptr) return *(kmi->ptr); - + /*return rna_pointer_inherit_refine(ptr, &RNA_OperatorProperties, op->properties); */ return PointerRNA_NULL; } @@ -848,7 +848,7 @@ static void rna_wmKeyMapItem_map_type_set(PointerRNA *ptr, int value) static void rna_wmKeyMapItem_keymodifier_set(PointerRNA *ptr, int value) { wmKeyMapItem *kmi = ptr->data; - + /* XXX, this should really be managed in an _itemf function, * giving a list of valid enums, then silently changing them when they are set is not * a good precedent, don't do this unless you have a good reason! */ @@ -976,7 +976,7 @@ static PointerRNA rna_WindowManager_active_keyconfig_get(PointerRNA *ptr) if (!kc) kc = wm->defaultconf; - + return rna_pointer_inherit_refine(ptr, &RNA_KeyConfig, kc); } @@ -1611,13 +1611,13 @@ static void rna_def_operator(BlenderRNA *brna) RNA_def_property_struct_type(prop, "OperatorProperties"); RNA_def_property_ui_text(prop, "Properties", ""); RNA_def_property_pointer_funcs(prop, "rna_Operator_properties_get", NULL, NULL, NULL); - + prop = RNA_def_property(srna, "has_reports", PROP_BOOLEAN, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* this is 'virtual' property */ RNA_def_property_boolean_funcs(prop, "rna_Operator_has_reports_get", NULL); RNA_def_property_ui_text(prop, "Has Reports", "Operator has a set of reports (warnings and errors) from last execution"); - + prop = RNA_def_property(srna, "layout", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "UILayout"); @@ -1819,12 +1819,12 @@ static void rna_def_operator_filelist_element(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_IDPROPERTY); RNA_def_property_ui_text(prop, "Name", "Name of a file or directory within a file list"); } - + static void rna_def_event(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + srna = RNA_def_struct(brna, "Event", NULL); RNA_def_struct_ui_text(srna, "Event", "Window Manager Event"); RNA_def_struct_sdna(srna, "wmEvent"); @@ -1849,7 +1849,7 @@ static void rna_def_event(BlenderRNA *brna) RNA_def_property_enum_items(prop, rna_enum_event_value_items); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Value", "The type of event, only applies to some"); - + prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "type"); RNA_def_property_enum_items(prop, rna_enum_event_type_items); @@ -1863,7 +1863,7 @@ static void rna_def_event(BlenderRNA *brna) RNA_def_property_int_sdna(prop, NULL, "x"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Mouse X Position", "The window relative horizontal location of the mouse"); - + prop = RNA_def_property(srna, "mouse_y", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "y"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); @@ -1878,12 +1878,12 @@ static void rna_def_event(BlenderRNA *brna) RNA_def_property_int_sdna(prop, NULL, "mval[1]"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Mouse Y Position", "The region relative vertical location of the mouse"); - + prop = RNA_def_property(srna, "mouse_prev_x", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "prevx"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Mouse Previous X Position", "The window relative horizontal location of the mouse"); - + prop = RNA_def_property(srna, "mouse_prev_y", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "prevy"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); @@ -1915,17 +1915,17 @@ static void rna_def_event(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "shift", 1); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Shift", "True when the Shift key is held"); - + prop = RNA_def_property(srna, "ctrl", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "ctrl", 1); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Ctrl", "True when the Ctrl key is held"); - + prop = RNA_def_property(srna, "alt", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "alt", 1); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Alt", "True when the Alt/Option key is held"); - + prop = RNA_def_property(srna, "oskey", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "oskey", 1); RNA_def_property_clear_flag(prop, PROP_EDITABLE); @@ -2119,7 +2119,7 @@ static void rna_def_wm_keyconfigs(BlenderRNA *brna, PropertyRNA *cprop) "rna_WindowManager_active_keyconfig_set", NULL, NULL); RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Active KeyConfig", "Active key configuration (preset)"); - + prop = RNA_def_property(srna, "default", PROP_POINTER, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "defaultconf"); RNA_def_property_struct_type(prop, "KeyConfig"); @@ -2138,7 +2138,7 @@ static void rna_def_wm_keyconfigs(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_property_ui_text(prop, "User Key Configuration", "Final key configuration that combines keymaps from the active and add-on configurations, " "and can be edited by the user"); - + RNA_api_keyconfigs(srna); } @@ -2177,7 +2177,7 @@ static void rna_def_windowmanager(BlenderRNA *brna) static void rna_def_keymap_items(BlenderRNA *brna, PropertyRNA *cprop) { StructRNA *srna; - + RNA_def_property_srna(cprop, "KeyMapItems"); srna = RNA_def_struct(brna, "KeyMapItems", NULL); RNA_def_struct_sdna(srna, "wmKeyMap"); @@ -2282,7 +2282,7 @@ static void rna_def_keyconfig(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", KEYMAP_EXPANDED); RNA_def_property_ui_text(prop, "Items Expanded", "Expanded in the user interface"); RNA_def_property_ui_icon(prop, ICON_TRIA_RIGHT, 1); - + prop = RNA_def_property(srna, "show_expanded_children", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", KEYMAP_CHILDREN_EXPANDED); RNA_def_property_ui_text(prop, "Children Expanded", "Children expanded in the user interface"); @@ -2310,7 +2310,7 @@ static void rna_def_keyconfig(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Name", "Name of operator (translated) to call on input event"); RNA_def_property_string_funcs(prop, "rna_wmKeyMapItem_name_get", "rna_wmKeyMapItem_name_length", NULL); - + prop = RNA_def_property(srna, "properties", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "OperatorProperties"); RNA_def_property_pointer_funcs(prop, "rna_KeyMapItem_properties_get", NULL, NULL, NULL); diff --git a/source/blender/makesrna/intern/rna_wm_api.c b/source/blender/makesrna/intern/rna_wm_api.c index ab534159a9e..aff696696af 100644 --- a/source/blender/makesrna/intern/rna_wm_api.c +++ b/source/blender/makesrna/intern/rna_wm_api.c @@ -98,7 +98,7 @@ static int rna_Operator_is_repeat(wmOperator *op, bContext *C) static void rna_Operator_enum_search_invoke(bContext *C, wmOperator *op) { WM_enum_search_invoke(C, op, NULL); - + } static int rna_event_modal_handler_add(struct bContext *C, struct wmOperator *operator) @@ -202,8 +202,9 @@ static int rna_Operator_props_popup(bContext *C, wmOperator *op, wmEvent *event) return WM_operator_props_popup(C, op, event); } -static wmKeyMapItem *rna_KeyMap_item_new(wmKeyMap *km, ReportList *reports, const char *idname, int type, int value, - int any, int shift, int ctrl, int alt, int oskey, int keymodifier, int head) +static wmKeyMapItem *rna_KeyMap_item_new( + wmKeyMap *km, ReportList *reports, const char *idname, int type, int value, + int any, int shift, int ctrl, int alt, int oskey, int keymodifier, int head) { /* wmWindowManager *wm = CTX_wm_manager(C); */ wmKeyMapItem *kmi = NULL; @@ -224,24 +225,25 @@ static wmKeyMapItem *rna_KeyMap_item_new(wmKeyMap *km, ReportList *reports, cons if (oskey) modifier |= KM_OSKEY; if (any) modifier = KM_ANY; - + /* create keymap item */ kmi = WM_keymap_add_item(km, idname_bl, type, value, modifier, keymodifier); - - /* [#32437] allow scripts to define hotkeys that get added to start of keymap + + /* [#32437] allow scripts to define hotkeys that get added to start of keymap * so that they stand a chance against catch-all defines later on */ if (head) { BLI_remlink(&km->items, kmi); BLI_addhead(&km->items, kmi); } - + return kmi; } -static wmKeyMapItem *rna_KeyMap_item_new_modal(wmKeyMap *km, ReportList *reports, const char *propvalue_str, - int type, int value, int any, int shift, int ctrl, int alt, - int oskey, int keymodifier) +static wmKeyMapItem *rna_KeyMap_item_new_modal( + wmKeyMap *km, ReportList *reports, const char *propvalue_str, + int type, int value, int any, int shift, int ctrl, int alt, + int oskey, int keymodifier) { int modifier = 0; int propvalue = 0; @@ -694,7 +696,7 @@ void RNA_api_operator(StructRNA *srna) parm = RNA_def_boolean(func, "result", 0, "result", ""); /* better name? */ RNA_def_function_return(func, parm); - + /* invoke */ func = RNA_def_function(srna, "invoke", NULL); RNA_def_function_ui_description(func, "Invoke the operator"); @@ -822,7 +824,7 @@ void RNA_api_keymapitems(StructRNA *srna) RNA_def_boolean(func, "alt", 0, "Alt", ""); RNA_def_boolean(func, "oskey", 0, "OS Key", ""); RNA_def_enum(func, "key_modifier", rna_enum_event_type_items, 0, "Key Modifier", ""); - RNA_def_boolean(func, "head", 0, "At Head", + RNA_def_boolean(func, "head", 0, "At Head", "Force item to be added at start (not end) of key map so that " "it doesn't get blocked by an existing key map item"); parm = RNA_def_pointer(func, "item", "KeyMapItem", "Item", "Added key map item"); @@ -844,7 +846,7 @@ void RNA_api_keymapitems(StructRNA *srna) RNA_def_enum(func, "key_modifier", rna_enum_event_type_items, 0, "Key Modifier", ""); parm = RNA_def_pointer(func, "item", "KeyMapItem", "Item", "Added key map item"); RNA_def_function_return(func, parm); - + func = RNA_def_function(srna, "remove", "rna_KeyMap_item_remove"); RNA_def_function_flag(func, FUNC_USE_REPORTS); parm = RNA_def_pointer(func, "item", "KeyMapItem", "Item", ""); diff --git a/source/blender/makesrna/intern/rna_world.c b/source/blender/makesrna/intern/rna_world.c index 92fbbd61898..ead67814f01 100644 --- a/source/blender/makesrna/intern/rna_world.c +++ b/source/blender/makesrna/intern/rna_world.c @@ -143,7 +143,7 @@ static void rna_def_world_mist(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + static const EnumPropertyItem falloff_items[] = { {WO_MIST_QUADRATIC, "QUADRATIC", 0, "Quadratic", "Use quadratic progression"}, {WO_MIST_LINEAR, "LINEAR", 0, "Linear", "Use linear progression"}, @@ -186,7 +186,7 @@ static void rna_def_world_mist(BlenderRNA *brna) RNA_def_property_range(prop, 0, 100); RNA_def_property_ui_text(prop, "Height", "Control how much mist density decreases with height"); RNA_def_property_update(prop, 0, "rna_World_update"); - + prop = RNA_def_property(srna, "falloff", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "mistype"); RNA_def_property_enum_items(prop, falloff_items); @@ -214,7 +214,7 @@ void RNA_def_world(BlenderRNA *brna) /* RNA_def_property_update(prop, 0, "rna_World_update"); */ /* render-only uses this */ RNA_def_property_update(prop, 0, "rna_World_draw_update"); - + /* nested structs */ prop = RNA_def_property(srna, "light_settings", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); diff --git a/source/blender/makesrna/rna_cleanup/rna_cleaner.py b/source/blender/makesrna/rna_cleanup/rna_cleaner.py index 8b4b10c490e..0b80a711c3b 100755 --- a/source/blender/makesrna/rna_cleanup/rna_cleaner.py +++ b/source/blender/makesrna/rna_cleanup/rna_cleaner.py @@ -19,7 +19,7 @@ def font_bold(mystring): font_bold = "\033[1m" font_reset = "\033[0;0m" return font_bold + mystring + font_reset - + def usage(): """ @@ -102,30 +102,30 @@ def get_props_from_txt(input_filename): """ If the file is *.txt, the script assumes it is formatted as outlined in this script docstring """ - + file=open(input_filename,'r') file_lines=file.readlines() file.close() props_list=[] props_length_max=[0,0,0,0,0,0,0,0] - + done_text = "+" done = 0 tot = 0 - + for iii, line in enumerate(file_lines): - + # debug #print(line) line_strip = line.strip() # empty line or comment if not line_strip: continue - + if line_strip == "EOF": break - + if line.startswith("#"): line = line[1:] @@ -162,18 +162,18 @@ def get_props_from_txt(input_filename): # changed changed = check_if_changed(bfrom, bto) - + # lists formatting props=[comment, changed, bclass, bfrom, bto, kwcheck, btype, description] props_list.append(props) props_length_max=list(map(max,zip(props_length_max,list(map(len,props))))) - + if done_text in comment: done += 1 tot += 1 - + print("Total done %.2f" % (done / tot * 100.0) ) - + return (props_list,props_length_max) @@ -181,7 +181,7 @@ def get_props_from_py(input_filename): """ If the file is *.py, the script assumes it contains a python list (as "rna_api=[...]") This means that this script executes the text in the py file with an exec(text). - """ + """ # adds the list "rna_api" to this function's scope rna_api = __import__(input_filename[:-3]).rna_api @@ -205,7 +205,7 @@ def get_props(input_filename): props_list,props_length_max = get_props_from_py(input_filename) return (props_list,props_length_max) - + def sort(props_list, sort_priority): """ reminder @@ -221,7 +221,7 @@ def sort(props_list, sort_priority): props_list = sorted(props_list, key=lambda p: p[i], reverse=True) else: props_list = sorted(props_list, key=lambda p: p[i]) - + print ('\nSorted by %s.' % font_bold(sort_priority)) return props_list @@ -260,11 +260,11 @@ def write_files(basename, props_list, props_length_max): props_list = [['NOTE', 'CHANGED', 'CLASS', 'FROM', 'TO', 'KEYWORD-CHECK', 'TYPE', 'DESCRIPTION']] + props_list for props in props_list: #txt - + # quick way we can tell if it changed if props[3] == props[4]: txt += "#" else: txt += " " - + if props[0] != '': txt += '%s * ' % props[0] # comment txt += '%s.%s -> %s: %s "%s"\n' % tuple(props[2:5] + props[6:]) # skipping keyword-check # rna_api @@ -279,7 +279,7 @@ def write_files(basename, props_list, props_length_max): f_txt.write(txt) f_py.write("rna_api = [\n%s]\n" % py) f_rna.write("rna_api = [\n%s]\n" % rna) - + # write useful py script, wont hurt f_py.write("\n'''\n") f_py.write("for p_note, p_changed, p_class, p_from, p_to, p_check, p_type, p_desc in rna_api:\n") diff --git a/source/blender/makesrna/rna_cleanup/rna_cleaner_merge.py b/source/blender/makesrna/rna_cleanup/rna_cleaner_merge.py index 17ea5f9b0bd..a5d5cebcbb7 100755 --- a/source/blender/makesrna/rna_cleanup/rna_cleaner_merge.py +++ b/source/blender/makesrna/rna_cleanup/rna_cleaner_merge.py @@ -7,38 +7,38 @@ Example usage: python3 rna_cleaner_merge.py out_work.py rna_booleans_work.py ''' def main(): - + def work_line_id(line): return line[2].split("|")[-1], line[3] # class/from - - + + if not (sys.argv[-1].endswith(".py") and sys.argv[-2].endswith(".py")): print("Only accepts 2 py files as arguments.") - + sys.path.insert(0, ".") mod_from = __import__(sys.argv[-1][:-3]) mod_to = __import__(sys.argv[-2][:-3]) - + mod_to_dict = dict([(work_line_id(line), line) for line in mod_to.rna_api]) mod_from_dict = dict([(work_line_id(line), line) for line in mod_from.rna_api]) - + rna_api_new = [] - + for key, val_orig in mod_to_dict.items(): try: val_new = mod_from_dict.pop(key) except: # print("not found", key) val_new = val_orig - + # always take the class from the base val = list(val_orig) val[0] = val_new[0] # comment val[4] = val_new[4] # -> to val = tuple(val) rna_api_new.append(val) - + def write_work_file(file_path, rna_api): rna_api = list(rna_api) rna_api.sort(key=work_line_id) @@ -51,7 +51,7 @@ def main(): file_path = sys.argv[-2][:-3] + "_merged.py" write_work_file(file_path, rna_api_new) - + if mod_from_dict: file_path = sys.argv[-2][:-3] + "_lost.py" write_work_file(file_path, list(mod_from_dict.values())) diff --git a/source/blender/modifiers/intern/MOD_boolean.c b/source/blender/modifiers/intern/MOD_boolean.c index f2c0baedc01..a2b300b40dc 100644 --- a/source/blender/modifiers/intern/MOD_boolean.c +++ b/source/blender/modifiers/intern/MOD_boolean.c @@ -170,13 +170,14 @@ static int bm_face_isect_pair(BMFace *f, void *UNUSED(user_data)) static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) { BooleanModifierData *bmd = (BooleanModifierData *) md; - Mesh *result; + Mesh *result = mesh; Mesh *mesh_other; bool mesh_other_free; - if (!bmd->object) - return mesh; + if (!bmd->object) { + return result; + } Object *ob_eval = DEG_get_evaluated_object(ctx->depsgraph, bmd->object); mesh_other = BKE_modifier_get_evaluated_mesh_from_evaluated_object(ob_eval, &mesh_other_free); diff --git a/source/blender/modifiers/intern/MOD_edgesplit.c b/source/blender/modifiers/intern/MOD_edgesplit.c index e8ffddbde4e..e1806dc8283 100644 --- a/source/blender/modifiers/intern/MOD_edgesplit.c +++ b/source/blender/modifiers/intern/MOD_edgesplit.c @@ -107,8 +107,7 @@ static Mesh *doEdgeSplit(Mesh *mesh, EdgeSplitModifierData *emd, const ModifierE /* BM_mesh_validate(bm); */ /* for troubleshooting */ - result = BKE_id_new_nomain(ID_ME, mesh->id.name); - BM_mesh_bm_to_me(bm, result, &((struct BMeshToMeshParams){0})); + result = BKE_bmesh_to_mesh_nomain(bm, &((struct BMeshToMeshParams){0})); BM_mesh_free(bm); result->runtime.cd_dirty_vert |= CD_MASK_NORMAL; diff --git a/source/blender/modifiers/intern/MOD_fluidsim_util.c b/source/blender/modifiers/intern/MOD_fluidsim_util.c index f4b39f1eab9..4bcc14236a0 100644 --- a/source/blender/modifiers/intern/MOD_fluidsim_util.c +++ b/source/blender/modifiers/intern/MOD_fluidsim_util.c @@ -431,7 +431,7 @@ static void fluidsim_read_vel_cache(FluidsimModifierData *fluidmd, DerivedMesh * } static DerivedMesh *fluidsim_read_cache( - Main *bmain, Object *ob, DerivedMesh *orgdm, + Object *ob, DerivedMesh *orgdm, FluidsimModifierData *fluidmd, int framenr, int useRenderParams) { int curFrame = framenr /* - 1 */ /*scene->r.sfra*/; /* start with 0 at start frame */ @@ -466,7 +466,7 @@ static DerivedMesh *fluidsim_read_cache( /* offset baked frame */ curFrame += fss->frameOffset; - BLI_path_abs(targetFile, modifier_path_relbase(bmain, ob)); + BLI_path_abs(targetFile, modifier_path_relbase_from_global(ob)); BLI_path_frame(targetFile, curFrame, 0); // fixed #frame-no /* assign material + flags to new dm @@ -552,7 +552,7 @@ DerivedMesh *fluidsimModifier_do( /* try to read from cache */ /* if the frame is there, fine, otherwise don't do anything */ - if ((result = fluidsim_read_cache(G.main, ob, dm, fluidmd, framenr, useRenderParams))) + if ((result = fluidsim_read_cache(ob, dm, fluidmd, framenr, useRenderParams))) return result; return dm; diff --git a/source/blender/modifiers/intern/MOD_meshcache.c b/source/blender/modifiers/intern/MOD_meshcache.c index 5d8ac9e5638..50765079785 100644 --- a/source/blender/modifiers/intern/MOD_meshcache.c +++ b/source/blender/modifiers/intern/MOD_meshcache.c @@ -152,7 +152,7 @@ static void meshcache_do( /* would be nice if we could avoid doing this _every_ frame */ BLI_strncpy(filepath, mcmd->filepath, sizeof(filepath)); - BLI_path_abs(filepath, ID_BLEND_PATH(G.main, (ID *)ob)); + BLI_path_abs(filepath, ID_BLEND_PATH_FROM_GLOBAL((ID *)ob)); switch (mcmd->type) { case MOD_MESHCACHE_TYPE_MDD: diff --git a/source/blender/modifiers/intern/MOD_normal_edit.c b/source/blender/modifiers/intern/MOD_normal_edit.c index 08dbcf81256..935d99e4a21 100644 --- a/source/blender/modifiers/intern/MOD_normal_edit.c +++ b/source/blender/modifiers/intern/MOD_normal_edit.c @@ -201,6 +201,7 @@ static void normalEditModifier_do_radial( MVert *mvert, const int num_verts, MEdge *medge, const int num_edges, MLoop *mloop, const int num_loops, MPoly *mpoly, const int num_polys) { + const bool do_polynors_fix = (enmd->flag & MOD_NORMALEDIT_NO_POLYNORS_FIX) == 0; int i; float (*cos)[3] = MEM_malloc_arrayN((size_t)num_verts, sizeof(*cos), __func__); @@ -278,7 +279,7 @@ static void normalEditModifier_do_radial( mix_limit, mix_mode, num_verts, mloop, loopnors, nos, num_loops); } - if (polygons_check_flip(mloop, nos, &mesh->ldata, mpoly, polynors, num_polys)) { + if (do_polynors_fix && polygons_check_flip(mloop, nos, &mesh->ldata, mpoly, polynors, num_polys)) { /* XXX TODO is this still needed? */ // mesh->dirty |= DM_DIRTY_TESS_CDLAYERS; /* We need to recompute vertex normals! */ @@ -301,6 +302,7 @@ static void normalEditModifier_do_directional( MVert *mvert, const int num_verts, MEdge *medge, const int num_edges, MLoop *mloop, const int num_loops, MPoly *mpoly, const int num_polys) { + const bool do_polynors_fix = (enmd->flag & MOD_NORMALEDIT_NO_POLYNORS_FIX) == 0; const bool use_parallel_normals = (enmd->flag & MOD_NORMALEDIT_USE_DIRECTION_PARALLEL) != 0; float (*nos)[3] = MEM_malloc_arrayN((size_t)num_loops, sizeof(*nos), __func__); @@ -357,7 +359,7 @@ static void normalEditModifier_do_directional( mix_limit, mix_mode, num_verts, mloop, loopnors, nos, num_loops); } - if (polygons_check_flip(mloop, nos, &mesh->ldata, mpoly, polynors, num_polys)) { + if (do_polynors_fix && polygons_check_flip(mloop, nos, &mesh->ldata, mpoly, polynors, num_polys)) { mesh->runtime.cd_dirty_vert |= CD_MASK_NORMAL; } diff --git a/source/blender/modifiers/intern/MOD_ocean.c b/source/blender/modifiers/intern/MOD_ocean.c index 921677ce1b1..af5b537ca52 100644 --- a/source/blender/modifiers/intern/MOD_ocean.c +++ b/source/blender/modifiers/intern/MOD_ocean.c @@ -49,9 +49,9 @@ #include "MOD_modifiertypes.h" #ifdef WITH_OCEANSIM -static void init_cache_data(Main *bmain, Object *ob, struct OceanModifierData *omd) +static void init_cache_data(Object *ob, struct OceanModifierData *omd) { - const char *relbase = modifier_path_relbase(bmain, ob); + const char *relbase = modifier_path_relbase_from_global(ob); omd->oceancache = BKE_ocean_init_cache(omd->cachepath, relbase, omd->bakestart, omd->bakeend, omd->wave_scale, @@ -448,7 +448,7 @@ static DerivedMesh *doOcean( /* do ocean simulation */ if (omd->cached == true) { if (!omd->oceancache) { - init_cache_data(G.main, ob, omd); + init_cache_data(ob, omd); } BKE_ocean_simulate_cache(omd->oceancache, md->scene->r.cfra); } diff --git a/source/blender/nodes/composite/node_composite_tree.c b/source/blender/nodes/composite/node_composite_tree.c index 2c123fdbf7e..43beb1656a2 100644 --- a/source/blender/nodes/composite/node_composite_tree.c +++ b/source/blender/nodes/composite/node_composite_tree.c @@ -134,7 +134,7 @@ static void local_sync(bNodeTree *localtree, bNodeTree *ntree) BKE_node_preview_sync_tree(ntree, localtree); } -static void local_merge(bNodeTree *localtree, bNodeTree *ntree) +static void local_merge(Main *bmain, bNodeTree *localtree, bNodeTree *ntree) { bNode *lnode; bNodeSocket *lsock; @@ -147,7 +147,7 @@ static void local_merge(bNodeTree *localtree, bNodeTree *ntree) if (ELEM(lnode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) { if (lnode->id && (lnode->flag & NODE_DO_OUTPUT)) { /* image_merge does sanity check for pointers */ - BKE_image_merge((Image *)lnode->new_node->id, (Image *)lnode->id); + BKE_image_merge(bmain, (Image *)lnode->new_node->id, (Image *)lnode->id); } } else if (lnode->type == CMP_NODE_MOVIEDISTORTION) { diff --git a/source/blender/nodes/composite/nodes/node_composite_splitViewer.c b/source/blender/nodes/composite/nodes/node_composite_splitViewer.c index dbe47066f66..f7008bc9ae4 100644 --- a/source/blender/nodes/composite/nodes/node_composite_splitViewer.c +++ b/source/blender/nodes/composite/nodes/node_composite_splitViewer.c @@ -33,6 +33,7 @@ #include "node_composite_util.h" #include "BKE_image.h" +#include "BKE_global.h" /* **************** SPLIT VIEWER ******************** */ static bNodeSocketTemplate cmp_node_splitviewer_in[] = { @@ -50,7 +51,7 @@ static void node_composit_init_splitviewer(bNodeTree *UNUSED(ntree), bNode *node iuser->ok = 1; node->custom1 = 50; /* default 50% split */ - node->id = (ID *)BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node"); + node->id = (ID *)BKE_image_verify_viewer(G.main, IMA_TYPE_COMPOSITE, "Viewer Node"); } void register_node_type_cmp_splitviewer(void) diff --git a/source/blender/nodes/composite/nodes/node_composite_viewer.c b/source/blender/nodes/composite/nodes/node_composite_viewer.c index a10ba02b38e..f82b0d7206a 100644 --- a/source/blender/nodes/composite/nodes/node_composite_viewer.c +++ b/source/blender/nodes/composite/nodes/node_composite_viewer.c @@ -33,6 +33,7 @@ #include "node_composite_util.h" #include "BKE_image.h" +#include "BKE_global.h" /* **************** VIEWER ******************** */ @@ -53,7 +54,7 @@ static void node_composit_init_viewer(bNodeTree *UNUSED(ntree), bNode *node) node->custom3 = 0.5f; node->custom4 = 0.5f; - node->id = (ID *)BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node"); + node->id = (ID *)BKE_image_verify_viewer(G.main, IMA_TYPE_COMPOSITE, "Viewer Node"); } void register_node_type_cmp_viewer(void) diff --git a/source/blender/nodes/shader/node_shader_tree.c b/source/blender/nodes/shader/node_shader_tree.c index fcb21982661..9d77d45dedf 100644 --- a/source/blender/nodes/shader/node_shader_tree.c +++ b/source/blender/nodes/shader/node_shader_tree.c @@ -153,7 +153,7 @@ static void local_sync(bNodeTree *localtree, bNodeTree *ntree) BKE_node_preview_sync_tree(ntree, localtree); } -static void local_merge(bNodeTree *localtree, bNodeTree *ntree) +static void local_merge(Main *UNUSED(bmain), bNodeTree *localtree, bNodeTree *ntree) { BKE_node_preview_merge_tree(ntree, localtree, true); } diff --git a/source/blender/nodes/shader/nodes/node_shader_geom.c b/source/blender/nodes/shader/nodes/node_shader_geom.c deleted file mode 100644 index 0a51ee8dc68..00000000000 --- a/source/blender/nodes/shader/nodes/node_shader_geom.c +++ /dev/null @@ -1,163 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2005 Blender Foundation. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/nodes/shader/nodes/node_shader_geom.c - * \ingroup shdnodes - */ - - -#include "node_shader_util.h" - -#include "DNA_customdata_types.h" - -/* **************** GEOMETRY ******************** */ - -/* output socket type definition */ -static bNodeSocketTemplate sh_node_geom_out[] = { - { SOCK_VECTOR, 0, N_("Global")}, - { SOCK_VECTOR, 0, N_("Local")}, - { SOCK_VECTOR, 0, N_("View")}, - { SOCK_VECTOR, 0, N_("Orco")}, - { SOCK_VECTOR, 0, N_("UV")}, - { SOCK_VECTOR, 0, N_("Normal")}, - { SOCK_RGBA, 0, N_("Vertex Color")}, - { SOCK_FLOAT, 0, N_("Vertex Alpha")}, - { SOCK_FLOAT, 0, N_("Front/Back")}, - { -1, 0, "" } -}; - -/* node execute callback */ -static void node_shader_exec_geom(void *data, int UNUSED(thread), bNode *node, bNodeExecData *UNUSED(execdata), bNodeStack **UNUSED(in), bNodeStack **out) -{ - if (data) { - ShadeInput *shi = ((ShaderCallData *)data)->shi; - NodeGeometry *ngeo = (NodeGeometry *)node->storage; - ShadeInputUV *suv = &shi->uv[shi->actuv]; - static float defaultvcol[4] = {1.0f, 1.0f, 1.0f, 1.0f}; - int i; - - if (ngeo->uvname[0]) { - /* find uv map by name */ - for (i = 0; i < shi->totuv; i++) { - if (STREQ(shi->uv[i].name, ngeo->uvname)) { - suv = &shi->uv[i]; - break; - } - } - } - - /* out: global, local, view, orco, uv, normal, vertex color */ - copy_v3_v3(out[GEOM_OUT_GLOB]->vec, shi->gl); - copy_v3_v3(out[GEOM_OUT_LOCAL]->vec, shi->co); - copy_v3_v3(out[GEOM_OUT_VIEW]->vec, shi->view); - copy_v3_v3(out[GEOM_OUT_ORCO]->vec, shi->lo); - copy_v3_v3(out[GEOM_OUT_UV]->vec, suv->uv); - copy_v3_v3(out[GEOM_OUT_NORMAL]->vec, shi->vno); - - if (shi->use_world_space_shading) { - negate_v3(out[GEOM_OUT_NORMAL]->vec); - mul_mat3_m4_v3((float (*)[4])RE_render_current_get_matrix(RE_VIEWINV_MATRIX), out[GEOM_OUT_NORMAL]->vec); - } - if (shi->totcol) { - /* find vertex color layer by name */ - ShadeInputCol *scol = &shi->col[0]; - - if (ngeo->colname[0]) { - for (i = 0; i < shi->totcol; i++) { - if (STREQ(shi->col[i].name, ngeo->colname)) { - scol = &shi->col[i]; - break; - } - } - } - - srgb_to_linearrgb_v3_v3(out[GEOM_OUT_VCOL]->vec, scol->col); - out[GEOM_OUT_VCOL]->vec[3] = scol->col[3]; - out[GEOM_OUT_VCOL_ALPHA]->vec[0] = scol->col[3]; - } - else { - memcpy(out[GEOM_OUT_VCOL]->vec, defaultvcol, sizeof(defaultvcol)); - out[GEOM_OUT_VCOL_ALPHA]->vec[0] = 1.0f; - } - - if (shi->osatex) { - out[GEOM_OUT_GLOB]->data = shi->dxgl; - out[GEOM_OUT_GLOB]->datatype = NS_OSA_VECTORS; - out[GEOM_OUT_LOCAL]->data = shi->dxco; - out[GEOM_OUT_LOCAL]->datatype = NS_OSA_VECTORS; - out[GEOM_OUT_VIEW]->data = &shi->dxview; - out[GEOM_OUT_VIEW]->datatype = NS_OSA_VALUES; - out[GEOM_OUT_ORCO]->data = shi->dxlo; - out[GEOM_OUT_ORCO]->datatype = NS_OSA_VECTORS; - out[GEOM_OUT_UV]->data = suv->dxuv; - out[GEOM_OUT_UV]->datatype = NS_OSA_VECTORS; - out[GEOM_OUT_NORMAL]->data = shi->dxno; - out[GEOM_OUT_NORMAL]->datatype = NS_OSA_VECTORS; - } - - /* front/back, normal flipping was stored */ - out[GEOM_OUT_FRONTBACK]->vec[0] = (shi->flippednor) ? 0.0f : 1.0f; - } -} - -static void node_shader_init_geometry(bNodeTree *UNUSED(ntree), bNode *node) -{ - node->storage = MEM_callocN(sizeof(NodeGeometry), "NodeGeometry"); -} - -static int gpu_shader_geom(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) -{ - NodeGeometry *ngeo = (NodeGeometry *)node->storage; - GPUNodeLink *orco = GPU_attribute(CD_ORCO, ""); - GPUNodeLink *mtface = GPU_attribute(CD_MTFACE, ngeo->uvname); - GPUNodeLink *mcol = GPU_attribute(CD_MCOL, ngeo->colname); - - bool ret = GPU_stack_link(mat, "geom", in, out, - GPU_builtin(GPU_VIEW_POSITION), GPU_builtin(GPU_VIEW_NORMAL), - GPU_builtin(GPU_INVERSE_VIEW_MATRIX), orco, mtface, mcol); - if (GPU_material_use_world_space_shading(mat)) { - GPU_link(mat, "vec_math_negate", out[5].link, &out[5].link); - ret &= GPU_link(mat, "direction_transform_m4v3", out[5].link, GPU_builtin(GPU_INVERSE_VIEW_MATRIX), &out[5].link); - } - return ret; -} - -/* node type definition */ -void register_node_type_sh_geom(void) -{ - static bNodeType ntype; - - sh_node_type_base(&ntype, SH_NODE_GEOMETRY, "Geometry", NODE_CLASS_INPUT, 0); - node_type_compatibility(&ntype, NODE_OLD_SHADING); - node_type_socket_templates(&ntype, NULL, sh_node_geom_out); - node_type_init(&ntype, node_shader_init_geometry); - node_type_storage(&ntype, "NodeGeometry", node_free_standard_storage, node_copy_standard_storage); - node_type_exec(&ntype, NULL, NULL, node_shader_exec_geom); - node_type_gpu(&ntype, gpu_shader_geom); - - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/shader/nodes/node_shader_material.c b/source/blender/nodes/shader/nodes/node_shader_material.c deleted file mode 100644 index 8a73ddc1194..00000000000 --- a/source/blender/nodes/shader/nodes/node_shader_material.c +++ /dev/null @@ -1,374 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2005 Blender Foundation. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/nodes/shader/nodes/node_shader_material.c - * \ingroup shdnodes - */ - -#include "node_shader_util.h" - -/* **************** MATERIAL ******************** */ - -static bNodeSocketTemplate sh_node_material_in[] = { - { SOCK_RGBA, 1, N_("Color"), 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 1, N_("Spec"), 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_FLOAT, 1, N_("DiffuseIntensity"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_NONE}, - { SOCK_VECTOR, 1, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_DIRECTION}, - { -1, 0, "" } -}; - -static bNodeSocketTemplate sh_node_material_out[] = { - { SOCK_RGBA, 0, N_("Color")}, - { SOCK_FLOAT, 0, N_("Alpha")}, - { SOCK_VECTOR, 0, N_("Normal")}, - { -1, 0, "" } -}; - -/* **************** EXTENDED MATERIAL ******************** */ - -static bNodeSocketTemplate sh_node_material_ext_in[] = { - { SOCK_RGBA, 1, N_("Color"), 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 1, N_("Spec"), 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_FLOAT, 1, N_("DiffuseIntensity"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_NONE}, - { SOCK_VECTOR, 1, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_DIRECTION}, - { SOCK_RGBA, 1, N_("Mirror"), 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_FLOAT, 1, N_("Ambient"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_NONE}, - { SOCK_FLOAT, 1, N_("Emit"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_UNSIGNED}, - { SOCK_FLOAT, 1, N_("SpecTra"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_NONE}, - { SOCK_FLOAT, 1, N_("Reflectivity"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE}, - { SOCK_FLOAT, 1, N_("Alpha"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_UNSIGNED}, - { SOCK_FLOAT, 1, N_("Translucency"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_NONE}, - { -1, 0, "" } -}; - -static bNodeSocketTemplate sh_node_material_ext_out[] = { - { SOCK_RGBA, 0, N_("Color")}, - { SOCK_FLOAT, 0, N_("Alpha")}, - { SOCK_VECTOR, 0, N_("Normal")}, - { SOCK_RGBA, 0, N_("Diffuse")}, - { SOCK_RGBA, 0, N_("Spec")}, - { SOCK_RGBA, 0, N_("AO")}, - { -1, 0, "" } -}; - -static void node_shader_exec_material(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out) -{ - if (data && node->id) { - ShadeResult shrnode; - ShadeInput *shi; - ShaderCallData *shcd = data; - float col[4]; - bNodeSocket *sock; - char hasinput[NUM_MAT_IN] = {'\0'}; - int i, mode; - - /* note: cannot use the in[]->hasinput flags directly, as these are not necessarily - * the constant input stack values (e.g. in case material node is inside a group). - * we just want to know if a node input uses external data or the material setting. - * this is an ugly hack, but so is this node as a whole. - */ - for (sock = node->inputs.first, i = 0; sock; sock = sock->next, ++i) - hasinput[i] = (sock->link != NULL); - - shi = shcd->shi; - shi->mat = (Material *)node->id; - - /* copy all relevant material vars, note, keep this synced with render_types.h */ - memcpy(&shi->r, &shi->mat->r, 23 * sizeof(float)); - shi->har = shi->mat->har; - - /* write values */ - if (hasinput[MAT_IN_COLOR]) - nodestack_get_vec(&shi->r, SOCK_VECTOR, in[MAT_IN_COLOR]); - - if (hasinput[MAT_IN_SPEC]) - nodestack_get_vec(&shi->specr, SOCK_VECTOR, in[MAT_IN_SPEC]); - - if (hasinput[MAT_IN_REFL]) - nodestack_get_vec(&shi->refl, SOCK_FLOAT, in[MAT_IN_REFL]); - - /* retrieve normal */ - if (hasinput[MAT_IN_NORMAL]) { - nodestack_get_vec(shi->vn, SOCK_VECTOR, in[MAT_IN_NORMAL]); - if (shi->use_world_space_shading) { - negate_v3(shi->vn); - mul_mat3_m4_v3((float (*)[4])RE_render_current_get_matrix(RE_VIEW_MATRIX), shi->vn); - } - normalize_v3(shi->vn); - } - else - copy_v3_v3(shi->vn, shi->vno); - - /* custom option to flip normal */ - if (node->custom1 & SH_NODE_MAT_NEG) { - negate_v3(shi->vn); - } - - if (node->type == SH_NODE_MATERIAL_EXT) { - if (hasinput[MAT_IN_MIR]) - nodestack_get_vec(&shi->mirr, SOCK_VECTOR, in[MAT_IN_MIR]); - if (hasinput[MAT_IN_AMB]) - nodestack_get_vec(&shi->amb, SOCK_FLOAT, in[MAT_IN_AMB]); - if (hasinput[MAT_IN_EMIT]) - nodestack_get_vec(&shi->emit, SOCK_FLOAT, in[MAT_IN_EMIT]); - if (hasinput[MAT_IN_SPECTRA]) - nodestack_get_vec(&shi->spectra, SOCK_FLOAT, in[MAT_IN_SPECTRA]); - if (hasinput[MAT_IN_RAY_MIRROR]) - nodestack_get_vec(&shi->ray_mirror, SOCK_FLOAT, in[MAT_IN_RAY_MIRROR]); - if (hasinput[MAT_IN_ALPHA]) - nodestack_get_vec(&shi->alpha, SOCK_FLOAT, in[MAT_IN_ALPHA]); - if (hasinput[MAT_IN_TRANSLUCENCY]) - nodestack_get_vec(&shi->translucency, SOCK_FLOAT, in[MAT_IN_TRANSLUCENCY]); - } - - /* make alpha output give results even if transparency is only enabled on - * the material linked in this not and not on the parent material */ - mode = shi->mode; - if (shi->mat->mode & MA_TRANSP) - shi->mode |= MA_TRANSP; - - shi->nodes = 1; /* temp hack to prevent trashadow recursion */ - node_shader_lamp_loop(shi, &shrnode); /* clears shrnode */ - shi->nodes = 0; - - shi->mode = mode; - - /* write to outputs */ - if (node->custom1 & SH_NODE_MAT_DIFF) { - copy_v3_v3(col, shrnode.combined); - if (!(node->custom1 & SH_NODE_MAT_SPEC)) { - sub_v3_v3(col, shrnode.spec); - } - } - else if (node->custom1 & SH_NODE_MAT_SPEC) { - copy_v3_v3(col, shrnode.spec); - } - else - col[0] = col[1] = col[2] = 0.0f; - - col[3] = shrnode.alpha; - - if (shi->do_preview) - BKE_node_preview_set_pixel(execdata->preview, col, shi->xs, shi->ys, shi->do_manage); - - copy_v3_v3(out[MAT_OUT_COLOR]->vec, col); - out[MAT_OUT_ALPHA]->vec[0] = shrnode.alpha; - - if (node->custom1 & SH_NODE_MAT_NEG) { - shi->vn[0] = -shi->vn[0]; - shi->vn[1] = -shi->vn[1]; - shi->vn[2] = -shi->vn[2]; - } - - copy_v3_v3(out[MAT_OUT_NORMAL]->vec, shi->vn); - - if (shi->use_world_space_shading) { - negate_v3(out[MAT_OUT_NORMAL]->vec); - mul_mat3_m4_v3((float (*)[4])RE_render_current_get_matrix(RE_VIEWINV_MATRIX), out[MAT_OUT_NORMAL]->vec); - } - /* Extended material options */ - if (node->type == SH_NODE_MATERIAL_EXT) { - /* Shadow, Reflect, Refract, Radiosity, Speed seem to cause problems inside - * a node tree :( */ - copy_v3_v3(out[MAT_OUT_DIFFUSE]->vec, shrnode.diffshad); - copy_v3_v3(out[MAT_OUT_SPEC]->vec, shrnode.spec); - copy_v3_v3(out[MAT_OUT_AO]->vec, shrnode.ao); - } - - /* copy passes, now just active node */ - if (node->flag & NODE_ACTIVE_ID) { - float combined[4], alpha; - - copy_v4_v4(combined, shcd->shr->combined); - alpha = shcd->shr->alpha; - - *(shcd->shr) = shrnode; - - copy_v4_v4(shcd->shr->combined, combined); - shcd->shr->alpha = alpha; - } - } -} - - -static void node_shader_init_material(bNodeTree *UNUSED(ntree), bNode *node) -{ - node->custom1 = SH_NODE_MAT_DIFF | SH_NODE_MAT_SPEC; -} - -/* XXX this is also done as a local static function in gpu_codegen.c, - * but we need this to hack around the crappy material node. - */ -static GPUNodeLink *gpu_get_input_link(GPUMaterial *mat, GPUNodeStack *in) -{ - if (in->link) { - return in->link; - } - else { - GPUNodeLink *result = NULL; - - /* note GPU_uniform() is only intended to be used as a parameter to - * GPU_link(), returning it directly results in leaks or double frees */ - if (in->type == GPU_FLOAT) - GPU_link(mat, "set_value", GPU_uniform(in->vec), &result); - else if (in->type == GPU_VEC3) - GPU_link(mat, "set_rgb", GPU_uniform(in->vec), &result); - else if (in->type == GPU_VEC4) - GPU_link(mat, "set_rgba", GPU_uniform(in->vec), &result); - else - BLI_assert(0); - - return result; - } -} - -static int gpu_shader_material(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) -{ - if (node->id) { - GPUShadeInput shi; - GPUShadeResult shr; - bNodeSocket *sock; - char hasinput[NUM_MAT_IN] = {'\0'}; - int i; - - /* note: cannot use the in[]->hasinput flags directly, as these are not necessarily - * the constant input stack values (e.g. in case material node is inside a group). - * we just want to know if a node input uses external data or the material setting. - */ - for (sock = node->inputs.first, i = 0; sock; sock = sock->next, ++i) - hasinput[i] = (sock->link != NULL); - - GPU_shadeinput_set(mat, (Material *)node->id, &shi); - - /* write values */ - if (hasinput[MAT_IN_COLOR]) - shi.rgb = gpu_get_input_link(mat, &in[MAT_IN_COLOR]); - - if (hasinput[MAT_IN_SPEC]) - shi.specrgb = gpu_get_input_link(mat, &in[MAT_IN_SPEC]); - - if (hasinput[MAT_IN_REFL]) - shi.refl = gpu_get_input_link(mat, &in[MAT_IN_REFL]); - - /* retrieve normal */ - if (hasinput[MAT_IN_NORMAL]) { - GPUNodeLink *tmp; - shi.vn = gpu_get_input_link(mat, &in[MAT_IN_NORMAL]); - if (GPU_material_use_world_space_shading(mat)) { - GPU_link(mat, "vec_math_negate", shi.vn, &shi.vn); - GPU_link(mat, "direction_transform_m4v3", shi.vn, GPU_builtin(GPU_VIEW_MATRIX), &shi.vn); - } - GPU_link(mat, "vec_math_normalize", shi.vn, &shi.vn, &tmp); - } - - /* custom option to flip normal */ - if (node->custom1 & SH_NODE_MAT_NEG) - GPU_link(mat, "vec_math_negate", shi.vn, &shi.vn); - - if (node->type == SH_NODE_MATERIAL_EXT) { - if (hasinput[MAT_IN_MIR]) - shi.mir = gpu_get_input_link(mat, &in[MAT_IN_MIR]); - if (hasinput[MAT_IN_AMB]) - shi.amb = gpu_get_input_link(mat, &in[MAT_IN_AMB]); - if (hasinput[MAT_IN_EMIT]) - shi.emit = gpu_get_input_link(mat, &in[MAT_IN_EMIT]); - if (hasinput[MAT_IN_SPECTRA]) - shi.spectra = gpu_get_input_link(mat, &in[MAT_IN_SPECTRA]); - if (hasinput[MAT_IN_ALPHA]) - shi.alpha = gpu_get_input_link(mat, &in[MAT_IN_ALPHA]); - } - - GPU_shaderesult_set(&shi, &shr); /* clears shr */ - - /* write to outputs */ - if (node->custom1 & SH_NODE_MAT_DIFF) { - out[MAT_OUT_COLOR].link = shr.combined; - - if (!(node->custom1 & SH_NODE_MAT_SPEC)) { - GPUNodeLink *link; - GPU_link(mat, "vec_math_sub", shr.combined, shr.spec, &out[MAT_OUT_COLOR].link, &link); - } - } - else if (node->custom1 & SH_NODE_MAT_SPEC) { - out[MAT_OUT_COLOR].link = shr.spec; - } - else - GPU_link(mat, "set_rgb_zero", &out[MAT_OUT_COLOR].link); - - GPU_link(mat, "mtex_alpha_to_col", out[MAT_OUT_COLOR].link, shr.alpha, &out[MAT_OUT_COLOR].link); - - out[MAT_OUT_ALPHA].link = shr.alpha; // - - if (node->custom1 & SH_NODE_MAT_NEG) - GPU_link(mat, "vec_math_negate", shi.vn, &shi.vn); - out[MAT_OUT_NORMAL].link = shi.vn; - if (GPU_material_use_world_space_shading(mat)) { - GPU_link(mat, "vec_math_negate", out[MAT_OUT_NORMAL].link, &out[MAT_OUT_NORMAL].link); - GPU_link(mat, "direction_transform_m4v3", out[MAT_OUT_NORMAL].link, GPU_builtin(GPU_INVERSE_VIEW_MATRIX), &out[MAT_OUT_NORMAL].link); - } - - if (node->type == SH_NODE_MATERIAL_EXT) { - out[MAT_OUT_DIFFUSE].link = shr.diff; - out[MAT_OUT_SPEC].link = shr.spec; - GPU_link(mat, "set_rgb_one", &out[MAT_OUT_AO].link); - } - - return 1; - } - - return 0; -} - -void register_node_type_sh_material(void) -{ - static bNodeType ntype; - - sh_node_type_base(&ntype, SH_NODE_MATERIAL, "Material", NODE_CLASS_INPUT, NODE_PREVIEW); - node_type_compatibility(&ntype, NODE_OLD_SHADING); - node_type_socket_templates(&ntype, sh_node_material_in, sh_node_material_out); - node_type_init(&ntype, node_shader_init_material); - node_type_exec(&ntype, NULL, NULL, node_shader_exec_material); - node_type_gpu(&ntype, gpu_shader_material); - - nodeRegisterType(&ntype); -} - - -void register_node_type_sh_material_ext(void) -{ - static bNodeType ntype; - - sh_node_type_base(&ntype, SH_NODE_MATERIAL_EXT, "Extended Material", NODE_CLASS_INPUT, NODE_PREVIEW); - node_type_compatibility(&ntype, NODE_OLD_SHADING); - node_type_socket_templates(&ntype, sh_node_material_ext_in, sh_node_material_ext_out); - node_type_init(&ntype, node_shader_init_material); - node_type_size_preset(&ntype, NODE_SIZE_MIDDLE); - node_type_exec(&ntype, NULL, NULL, node_shader_exec_material); - node_type_gpu(&ntype, gpu_shader_material); - - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/shader/nodes/node_shader_output.c b/source/blender/nodes/shader/nodes/node_shader_output.c deleted file mode 100644 index 5b1a68b4bf9..00000000000 --- a/source/blender/nodes/shader/nodes/node_shader_output.c +++ /dev/null @@ -1,97 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2005 Blender Foundation. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/nodes/shader/nodes/node_shader_output.c - * \ingroup shdnodes - */ - - -#include "node_shader_util.h" - -/* **************** OUTPUT ******************** */ -static bNodeSocketTemplate sh_node_output_in[] = { - { SOCK_RGBA, 1, N_("Color"), 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_FLOAT, 1, N_("Alpha"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE}, - { -1, 0, "" } -}; - -static void node_shader_exec_output(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **UNUSED(out)) -{ - if (data) { - ShadeInput *shi = ((ShaderCallData *)data)->shi; - float col[4]; - - /* stack order input sockets: col, alpha, normal */ - nodestack_get_vec(col, SOCK_VECTOR, in[0]); - nodestack_get_vec(col + 3, SOCK_FLOAT, in[1]); - - if (shi->do_preview) { - BKE_node_preview_set_pixel(execdata->preview, col, shi->xs, shi->ys, shi->do_manage); - node->lasty = shi->ys; - } - - if (node->flag & NODE_DO_OUTPUT) { - ShadeResult *shr = ((ShaderCallData *)data)->shr; - - copy_v4_v4(shr->combined, col); - shr->alpha = col[3]; - - // copy_v3_v3(shr->nor, in[3]->vec); - } - } -} - -static int gpu_shader_output(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) -{ - GPUNodeLink *outlink; - -#if 0 - if (in[1].hasinput) - GPU_material_enable_alpha(mat); -#endif - - GPU_stack_link(mat, "output_node", in, out, &outlink); - GPU_material_output_link(mat, outlink); - - return 1; -} - -void register_node_type_sh_output(void) -{ - static bNodeType ntype; - - sh_node_type_base(&ntype, SH_NODE_OUTPUT, "Output", NODE_CLASS_OUTPUT, NODE_PREVIEW); - node_type_compatibility(&ntype, NODE_OLD_SHADING); - node_type_socket_templates(&ntype, sh_node_output_in, NULL); - node_type_exec(&ntype, NULL, NULL, node_shader_exec_output); - node_type_gpu(&ntype, gpu_shader_output); - - /* Do not allow muting output node. */ - node_type_internal_links(&ntype, NULL); - - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/shader/nodes/node_shader_texture.c b/source/blender/nodes/shader/nodes/node_shader_texture.c deleted file mode 100644 index 737ec7d1c4b..00000000000 --- a/source/blender/nodes/shader/nodes/node_shader_texture.c +++ /dev/null @@ -1,166 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2005 Blender Foundation. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/nodes/shader/nodes/node_shader_texture.c - * \ingroup shdnodes - */ - -#include "DNA_texture_types.h" - -#include "node_shader_util.h" - -#include "GPU_material.h" - -/* **************** TEXTURE ******************** */ -static bNodeSocketTemplate sh_node_texture_in[] = { - { SOCK_VECTOR, 1, "Vector", 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, /* no limit */ - { -1, 0, "" } -}; -static bNodeSocketTemplate sh_node_texture_out[] = { - { SOCK_FLOAT, 0, N_("Value"), 0, 0, 0, 0, 0, 0, PROP_NONE, SOCK_NO_INTERNAL_LINK}, - { SOCK_RGBA, 0, N_("Color"), 0, 0, 0, 0, 0, 0, PROP_NONE, SOCK_NO_INTERNAL_LINK}, - { SOCK_VECTOR, 0, N_("Normal"), 0, 0, 0, 0, 0, 0, PROP_NONE, SOCK_NO_INTERNAL_LINK}, - { -1, 0, "" } -}; - -static void node_shader_exec_texture(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out) -{ - if (data && node->id) { - ShadeInput *shi = ((ShaderCallData *)data)->shi; - TexResult texres; - bNodeSocket *sock_vector = node->inputs.first; - float vec[3], nor[3] = {0.0f, 0.0f, 0.0f}; - int retval; - short which_output = node->custom1; - - short thread = shi->thread; - - /* out: value, color, normal */ - - /* we should find out if a normal as output is needed, for now we do all */ - texres.nor = nor; - texres.tr = texres.tg = texres.tb = 0.0f; - - /* don't use in[0]->hasinput, see material node for explanation */ - if (sock_vector->link) { - nodestack_get_vec(vec, SOCK_VECTOR, in[0]); - - if (in[0]->datatype == NS_OSA_VECTORS) { - float *fp = in[0]->data; - retval = multitex_nodes((Tex *)node->id, vec, fp, fp + 3, shi->osatex, &texres, thread, which_output, NULL, NULL, NULL); - } - else if (in[0]->datatype == NS_OSA_VALUES) { - const float *fp = in[0]->data; - float dxt[3], dyt[3]; - - dxt[0] = fp[0]; dxt[1] = dxt[2] = 0.0f; - dyt[0] = fp[1]; dyt[1] = dyt[2] = 0.0f; - retval = multitex_nodes((Tex *)node->id, vec, dxt, dyt, shi->osatex, &texres, thread, which_output, NULL, NULL, NULL); - } - else - retval = multitex_nodes((Tex *)node->id, vec, NULL, NULL, 0, &texres, thread, which_output, NULL, NULL, NULL); - } - else { - copy_v3_v3(vec, shi->lo); - retval = multitex_nodes((Tex *)node->id, vec, NULL, NULL, 0, &texres, thread, which_output, NULL, NULL, NULL); - } - - /* stupid exception */ - if ( ((Tex *)node->id)->type == TEX_STUCCI) { - texres.tin = 0.5f + 0.7f * texres.nor[0]; - CLAMP(texres.tin, 0.0f, 1.0f); - } - - /* intensity and color need some handling */ - if (texres.talpha) - out[0]->vec[0] = texres.ta; - else - out[0]->vec[0] = texres.tin; - - if ((retval & TEX_RGB) == 0) { - copy_v3_fl(out[1]->vec, out[0]->vec[0]); - out[1]->vec[3] = 1.0f; - } - else { - copy_v3_v3(out[1]->vec, &texres.tr); - out[1]->vec[3] = 1.0f; - } - - copy_v3_v3(out[2]->vec, nor); - - if (shi->do_preview) { - BKE_node_preview_set_pixel(execdata->preview, out[1]->vec, shi->xs, shi->ys, shi->do_manage); - } - - } -} - -static int gpu_shader_texture(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) -{ - Tex *tex = (Tex *)node->id; - - if (tex && tex->ima && (tex->type == TEX_IMAGE || tex->type == TEX_ENVMAP)) { - if (tex->type == TEX_IMAGE) { - GPUNodeLink *texlink = GPU_image(tex->ima, &tex->iuser, false); - GPU_stack_link(mat, "texture_image", in, out, texlink); - } - else { /* TEX_ENVMAP */ - if (!in[0].link) - in[0].link = GPU_uniform(in[0].vec); - if (!GPU_material_use_world_space_shading(mat)) - GPU_link(mat, "direction_transform_m4v3", in[0].link, GPU_builtin(GPU_INVERSE_VIEW_MATRIX), &in[0].link); - GPU_link(mat, "mtex_cube_map_refl_from_refldir", - GPU_cube_map(tex->ima, &tex->iuser, false), in[0].link, &out[0].link, &out[1].link); - GPU_link(mat, "color_to_normal", out[1].link, &out[2].link); - } - - ImBuf *ibuf = BKE_image_acquire_ibuf(tex->ima, &tex->iuser, NULL); - if (ibuf && (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) == 0 && - GPU_material_do_color_management(mat)) - { - GPU_link(mat, "srgb_to_linearrgb", out[1].link, &out[1].link); - } - BKE_image_release_ibuf(tex->ima, ibuf, NULL); - - return true; - } - - return false; -} - -void register_node_type_sh_texture(void) -{ - static bNodeType ntype; - - sh_node_type_base(&ntype, SH_NODE_TEXTURE, "Texture", NODE_CLASS_INPUT, NODE_PREVIEW); - node_type_compatibility(&ntype, NODE_OLD_SHADING); - node_type_socket_templates(&ntype, sh_node_texture_in, sh_node_texture_out); - node_type_exec(&ntype, NULL, NULL, node_shader_exec_texture); - node_type_gpu(&ntype, gpu_shader_texture); - - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/texture/node_texture_tree.c b/source/blender/nodes/texture/node_texture_tree.c index 5dbcece0a84..551d955c70f 100644 --- a/source/blender/nodes/texture/node_texture_tree.c +++ b/source/blender/nodes/texture/node_texture_tree.c @@ -141,7 +141,7 @@ static void local_sync(bNodeTree *localtree, bNodeTree *ntree) BKE_node_preview_sync_tree(ntree, localtree); } -static void local_merge(bNodeTree *localtree, bNodeTree *ntree) +static void local_merge(Main *UNUSED(bmain), bNodeTree *localtree, bNodeTree *ntree) { BKE_node_preview_merge_tree(ntree, localtree, true); } diff --git a/source/blender/python/BPY_extern.h b/source/blender/python/BPY_extern.h index b4c36a7c516..da1b031f1c0 100644 --- a/source/blender/python/BPY_extern.h +++ b/source/blender/python/BPY_extern.h @@ -87,7 +87,8 @@ void BPY_modules_load_user(struct bContext *C); void BPY_app_handlers_reset(const short do_all); void BPY_driver_reset(void); -float BPY_driver_exec(struct PathResolvedRNA *anim_rna, struct ChannelDriver *driver, const float evaltime); +float BPY_driver_exec(struct PathResolvedRNA *anim_rna, struct ChannelDriver *driver, + struct ChannelDriver *driver_orig, const float evaltime); void BPY_DECREF(void *pyob_ptr); /* Py_DECREF() */ void BPY_DECREF_RNA_INVALIDATE(void *pyob_ptr); diff --git a/source/blender/python/bmesh/bmesh_py_types.c b/source/blender/python/bmesh/bmesh_py_types.c index c6a67a1b2dd..c2d159538cb 100644 --- a/source/blender/python/bmesh/bmesh_py_types.c +++ b/source/blender/python/bmesh/bmesh_py_types.c @@ -36,6 +36,7 @@ #include "BKE_customdata.h" #include "BKE_DerivedMesh.h" +#include "BKE_global.h" #include "DEG_depsgraph.h" @@ -903,6 +904,7 @@ static PyObject *bpy_bmesh_to_mesh(BPy_BMesh *self, PyObject *args) bm = self->bm; BM_mesh_bm_to_me( + G.main, /* XXX UGLY! */ bm, me, (&(struct BMeshToMeshParams){ .calc_object_remap = true, diff --git a/source/blender/python/intern/bpy_driver.c b/source/blender/python/intern/bpy_driver.c index 215a64a4449..96bfa9f26d3 100644 --- a/source/blender/python/intern/bpy_driver.c +++ b/source/blender/python/intern/bpy_driver.c @@ -48,6 +48,8 @@ #include "bpy_driver.h" +#include "BPY_extern.h" + extern void BPY_update_rna_module(void); #define USE_RNA_AS_PYOBJECT @@ -196,8 +198,12 @@ static void pydriver_error(ChannelDriver *driver) * (new)note: checking if python is running is not threadsafe [#28114] * now release the GIL on python operator execution instead, using * PyEval_SaveThread() / PyEval_RestoreThread() so we don't lock up blender. + * + * For copy-on-write we always cache expressions and write errors in the + * original driver, otherwise these would get freed while editing. Due to + * the GIL this is thread-safe. */ -float BPY_driver_exec(struct PathResolvedRNA *anim_rna, ChannelDriver *driver, const float evaltime) +float BPY_driver_exec(struct PathResolvedRNA *anim_rna, ChannelDriver *driver, ChannelDriver *driver_orig, const float evaltime) { PyObject *driver_vars = NULL; PyObject *retval = NULL; @@ -213,7 +219,7 @@ float BPY_driver_exec(struct PathResolvedRNA *anim_rna, ChannelDriver *driver, c int i; /* get the py expression to be evaluated */ - expr = driver->expression; + expr = driver_orig->expression; if (expr[0] == '\0') return 0.0f; @@ -249,47 +255,47 @@ float BPY_driver_exec(struct PathResolvedRNA *anim_rna, ChannelDriver *driver, c /* update global namespace */ bpy_pydriver_namespace_update_frame(evaltime); - if (driver->flag & DRIVER_FLAG_USE_SELF) { + if (driver_orig->flag & DRIVER_FLAG_USE_SELF) { bpy_pydriver_namespace_update_self(anim_rna); } else { bpy_pydriver_namespace_clear_self(); } - if (driver->expr_comp == NULL) - driver->flag |= DRIVER_FLAG_RECOMPILE; + if (driver_orig->expr_comp == NULL) + driver_orig->flag |= DRIVER_FLAG_RECOMPILE; /* compile the expression first if it hasn't been compiled or needs to be rebuilt */ - if (driver->flag & DRIVER_FLAG_RECOMPILE) { - Py_XDECREF(driver->expr_comp); - driver->expr_comp = PyTuple_New(2); + if (driver_orig->flag & DRIVER_FLAG_RECOMPILE) { + Py_XDECREF(driver_orig->expr_comp); + driver_orig->expr_comp = PyTuple_New(2); expr_code = Py_CompileString(expr, "<bpy driver>", Py_eval_input); - PyTuple_SET_ITEM(((PyObject *)driver->expr_comp), 0, expr_code); + PyTuple_SET_ITEM(((PyObject *)driver_orig->expr_comp), 0, expr_code); - driver->flag &= ~DRIVER_FLAG_RECOMPILE; - driver->flag |= DRIVER_FLAG_RENAMEVAR; /* maybe this can be removed but for now best keep until were sure */ + driver_orig->flag &= ~DRIVER_FLAG_RECOMPILE; + driver_orig->flag |= DRIVER_FLAG_RENAMEVAR; /* maybe this can be removed but for now best keep until were sure */ } else { - expr_code = PyTuple_GET_ITEM(((PyObject *)driver->expr_comp), 0); + expr_code = PyTuple_GET_ITEM(((PyObject *)driver_orig->expr_comp), 0); } - if (driver->flag & DRIVER_FLAG_RENAMEVAR) { + if (driver_orig->flag & DRIVER_FLAG_RENAMEVAR) { /* may not be set */ - expr_vars = PyTuple_GET_ITEM(((PyObject *)driver->expr_comp), 1); + expr_vars = PyTuple_GET_ITEM(((PyObject *)driver_orig->expr_comp), 1); Py_XDECREF(expr_vars); - expr_vars = PyTuple_New(BLI_listbase_count(&driver->variables)); - PyTuple_SET_ITEM(((PyObject *)driver->expr_comp), 1, expr_vars); + expr_vars = PyTuple_New(BLI_listbase_count(&driver_orig->variables)); + PyTuple_SET_ITEM(((PyObject *)driver_orig->expr_comp), 1, expr_vars); - for (dvar = driver->variables.first, i = 0; dvar; dvar = dvar->next) { + for (dvar = driver_orig->variables.first, i = 0; dvar; dvar = dvar->next) { PyTuple_SET_ITEM(expr_vars, i++, PyUnicode_FromString(dvar->name)); } - driver->flag &= ~DRIVER_FLAG_RENAMEVAR; + driver_orig->flag &= ~DRIVER_FLAG_RENAMEVAR; } else { - expr_vars = PyTuple_GET_ITEM(((PyObject *)driver->expr_comp), 1); + expr_vars = PyTuple_GET_ITEM(((PyObject *)driver_orig->expr_comp), 1); } /* add target values to a dict that will be used as '__locals__' dict */ diff --git a/source/blender/python/intern/bpy_driver.h b/source/blender/python/intern/bpy_driver.h index 017a6fe89c5..971cbdf901f 100644 --- a/source/blender/python/intern/bpy_driver.h +++ b/source/blender/python/intern/bpy_driver.h @@ -27,14 +27,7 @@ #ifndef __BPY_DRIVER_H__ #define __BPY_DRIVER_H__ -struct ChannelDriver; -struct PathResolvedRNA; - int bpy_pydriver_create_dict(void); extern PyObject *bpy_pydriver_Dict; -/* externals */ -float BPY_driver_exec(struct PathResolvedRNA *anim_rna, struct ChannelDriver *driver, const float evaltime); -void BPY_driver_reset(void); - #endif /* __BPY_DRIVER_H__ */ diff --git a/source/blender/python/intern/bpy_rna_callback.c b/source/blender/python/intern/bpy_rna_callback.c index 45d556d68e9..7adb1d40fcc 100644 --- a/source/blender/python/intern/bpy_rna_callback.c +++ b/source/blender/python/intern/bpy_rna_callback.c @@ -101,7 +101,10 @@ PyObject *pyrna_callback_add(BPy_StructRNA *self, PyObject *args) if (RNA_struct_is_a(self->ptr.type, &RNA_Region)) { if (cb_event_str) { - if (pyrna_enum_value_from_id(region_draw_mode_items, cb_event_str, &cb_event, "bpy_struct.callback_add()") == -1) { + if (pyrna_enum_value_from_id( + region_draw_mode_items, cb_event_str, + &cb_event, "bpy_struct.callback_add()") == -1) + { return NULL; } } @@ -210,10 +213,16 @@ PyObject *pyrna_callback_classmethod_add(PyObject *UNUSED(self), PyObject *args) return NULL; } - if (pyrna_enum_value_from_id(region_draw_mode_items, cb_event_str, &cb_event, "bpy_struct.callback_add()") == -1) { + if (pyrna_enum_value_from_id( + region_draw_mode_items, cb_event_str, + &cb_event, "bpy_struct.callback_add()") == -1) + { return NULL; } - else if (pyrna_enum_value_from_id(rna_enum_region_type_items, cb_regiontype_str, &cb_regiontype, "bpy_struct.callback_add()") == -1) { + else if (pyrna_enum_value_from_id( + rna_enum_region_type_items, cb_regiontype_str, + &cb_regiontype, "bpy_struct.callback_add()") == -1) + { return NULL; } else { @@ -225,7 +234,10 @@ PyObject *pyrna_callback_classmethod_add(PyObject *UNUSED(self), PyObject *args) else { SpaceType *st = BKE_spacetype_from_id(spaceid); ARegionType *art = BKE_regiontype_from_id(st, cb_regiontype); - + if (art == NULL) { + PyErr_Format(PyExc_TypeError, "region type '%.200s' not in space", cb_regiontype_str); + return NULL; + } handle = ED_region_draw_cb_activate(art, cb_region_draw, (void *)args, cb_event); Py_INCREF(args); } @@ -276,7 +288,10 @@ PyObject *pyrna_callback_classmethod_remove(PyObject *UNUSED(self), PyObject *ar customdata = ED_region_draw_cb_customdata(handle); Py_DECREF((PyObject *)customdata); - if (pyrna_enum_value_from_id(rna_enum_region_type_items, cb_regiontype_str, &cb_regiontype, "bpy_struct.callback_remove()") == -1) { + if (pyrna_enum_value_from_id( + rna_enum_region_type_items, cb_regiontype_str, + &cb_regiontype, "bpy_struct.callback_remove()") == -1) + { return NULL; } else { @@ -288,7 +303,10 @@ PyObject *pyrna_callback_classmethod_remove(PyObject *UNUSED(self), PyObject *ar else { SpaceType *st = BKE_spacetype_from_id(spaceid); ARegionType *art = BKE_regiontype_from_id(st, cb_regiontype); - + if (art == NULL) { + PyErr_Format(PyExc_TypeError, "region type '%.200s' not in space", cb_regiontype_str); + return NULL; + } ED_region_draw_cb_exit(art, handle); } } diff --git a/source/blender/render/CMakeLists.txt b/source/blender/render/CMakeLists.txt index 359369228f8..d3fef51e9e9 100644 --- a/source/blender/render/CMakeLists.txt +++ b/source/blender/render/CMakeLists.txt @@ -44,7 +44,7 @@ set(INC ) set(INC_SYS - + ${GLEW_INCLUDE_PATH} ) set(SRC diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h index 660e81eb022..bde3c1c8cb3 100644 --- a/source/blender/render/extern/include/RE_pipeline.h +++ b/source/blender/render/extern/include/RE_pipeline.h @@ -221,6 +221,7 @@ void RE_ReleaseResultImageViews(struct Render *re, struct RenderResult *rr); void RE_AcquireResultImage(struct Render *re, struct RenderResult *rr, const int view_id); void RE_ReleaseResultImage(struct Render *re); void RE_SwapResult(struct Render *re, struct RenderResult **rr); +void RE_ClearResult(struct Render *re); struct RenderStats *RE_GetStats(struct Render *re); void RE_ResultGet32(struct Render *re, unsigned int *rect); @@ -311,6 +312,13 @@ void RE_draw_lock_cb (struct Render *re, void *handle, void (*f)(void *handle, void RE_test_break_cb (struct Render *re, void *handle, int (*f)(void *handle)); void RE_current_scene_update_cb(struct Render *re, void *handle, void (*f)(void *handle, struct Scene *scene)); +/* TODO replace by a simple set and get draw manager. */ +void RE_gl_context_create(Render *re); +void RE_gl_context_destroy(Render *re); +void RE_gl_context_set(Render *re, void *gl_context); +void *RE_gl_context_get(Render *re); +void *RE_gwn_context_get(Render *re); + /* should move to kernel once... still unsure on how/where */ float RE_filter_value(int type, float x); diff --git a/source/blender/render/intern/include/envmap.h b/source/blender/render/intern/include/envmap.h deleted file mode 100644 index c66427ae788..00000000000 --- a/source/blender/render/intern/include/envmap.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * envmap_ext.h - * - * - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/render/intern/include/envmap.h - * \ingroup render - */ - - -#ifndef __ENVMAP_H__ -#define __ENVMAP_H__ - -/** - * Make environment maps for all objects in the scene that have an - * environment map as texture. - * (initrender.c) - */ - -struct Render; -struct TexResult; -struct ImagePool; - -void make_envmaps(struct Render *re); -int envmaptex(struct Tex *tex, const float texvec[3], float dxt[3], float dyt[3], int osatex, struct TexResult *texres, struct ImagePool *pool, const bool skip_image_load); -void env_rotate_scene(struct Render *re, float mat[4][4], int do_rotate); - -#endif /* __ENVMAP_H__ */ - diff --git a/source/blender/render/intern/include/pixelblending.h b/source/blender/render/intern/include/pixelblending.h deleted file mode 100644 index 022510c7132..00000000000 --- a/source/blender/render/intern/include/pixelblending.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * Contributor(s): 2004-2006 Blender Foundation, full recode - * - * ***** END GPL/BL DUAL LICENSE BLOCK ***** - */ - -/** \file blender/render/intern/include/pixelblending.h - * \ingroup render - */ - - -#ifndef __PIXELBLENDING_H__ -#define __PIXELBLENDING_H__ - - -/** - * add 1 pixel to into filtered three lines - * (float vecs to float vec) - */ -void add_filt_fmask(unsigned int mask, const float col[4], float *rowbuf, int row_w); -void add_filt_fmask_pixsize(unsigned int mask, float *in, float *rowbuf, int row_w, int pixsize); -void add_filt_fmask_coord(float filt[3][3], const float col[4], float *rowbuf, int row_stride, int x, int y, rcti *mask); -void mask_array(unsigned int mask, float filt[3][3]); - -/** - * Alpha-over blending for floats. - */ -void addAlphaOverFloat(float dest[4], const float source[4]); - -/** - * Alpha-under blending for floats. - */ -void addAlphaUnderFloat(float dest[4], const float source[4]); - - -/** - * Same for floats - */ -void addalphaAddfacFloat(float dest[4], const float source[4], char addfac); - -/** - * dest = dest + source - */ -void addalphaAddFloat(float dest[4], const float source[4]); - -#endif /* __PIXELBLENDING_H__ */ diff --git a/source/blender/render/intern/include/pixelshading.h b/source/blender/render/intern/include/pixelshading.h deleted file mode 100644 index 0e630eda475..00000000000 --- a/source/blender/render/intern/include/pixelshading.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * Contributor(s): 2004-2006, Blender Foundation, full recode - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/render/intern/include/pixelshading.h - * \ingroup render - * - * These functions determine what actual color a pixel will have. - */ - -#ifndef __PIXELSHADING_H__ -#define __PIXELSHADING_H__ - - -/** - * Render the pixel at (x,y) for object ap. Apply the jitter mask. - * Output is given in float collector[4]. The type vector: - * t[0] - min. distance - * t[1] - face/halo index - * t[2] - jitter mask - * t[3] - type ZB_POLY or ZB_HALO - * t[4] - max. distance - * mask is pixel coverage in bits - * \return pointer to the object - */ -int shadeHaloFloat(HaloRen *har, - float *col, int zz, - float dist, float xn, - float yn, short flarec); - -/** - * Render the sky at pixel (x, y). - */ -void shadeSkyPixel(float collector[4], float fx, float fy, short thread); -void shadeSkyView(float col_r[3], const float rco[3], const float view[3], const float dxyview[2], short thread); -void shadeAtmPixel(struct SunSky *sunsky, float *collector, float fx, float fy, float distance); -void shadeSunView(float col_r[3], const float view[3]); -/* ------------------------------------------------------------------------- */ - -#endif - diff --git a/source/blender/render/intern/include/pointdensity.h b/source/blender/render/intern/include/pointdensity.h deleted file mode 100644 index eadf714c1ba..00000000000 --- a/source/blender/render/intern/include/pointdensity.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): Matt Ebb - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/render/intern/include/pointdensity.h - * \ingroup render - */ - - -#ifndef __POINTDENSITY_H__ -#define __POINTDENSITY_H__ - -/** - * Make point density kd-trees for all point density textures in the scene - */ - -struct PointDensity; -struct Render; -struct TexResult; - -void free_pointdensity(struct PointDensity *pd); -void cache_pointdensity(struct Render *re, struct PointDensity *pd); -void make_pointdensities(struct Render *re); -void free_pointdensities(struct Render *re); -int pointdensitytex(struct Tex *tex, const float texvec[3], struct TexResult *texres); - -#endif /* __POINTDENSITY_H__ */ - diff --git a/source/blender/render/intern/include/raycounter.h b/source/blender/render/intern/include/raycounter.h deleted file mode 100644 index e16c6e13c7e..00000000000 --- a/source/blender/render/intern/include/raycounter.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2009 Blender Foundation. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): André Pinto. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/render/intern/include/raycounter.h - * \ingroup render - */ - - -#ifndef __RAYCOUNTER_H__ -#define __RAYCOUNTER_H__ - -//#define RE_RAYCOUNTER /* enable counters per ray, useful for measuring raytrace structures performance */ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef RE_RAYCOUNTER - -/* ray counter functions */ - -typedef struct RayCounter { - struct { - unsigned long long test, hit; - } faces, bb, simd_bb, raycast, raytrace_hint, rayshadow_last_hit; -} RayCounter; - -#define RE_RC_INIT(isec, shi) (isec).raycounter = &((shi).shading.raycounter) -void RE_RC_INFO(RayCounter *rc); -void RE_RC_MERGE(RayCounter *rc, RayCounter *tmp); -#define RE_RC_COUNT(var) (var)++ - -extern RayCounter re_rc_counter[]; - -#else - -/* ray counter stubs */ - -#define RE_RC_INIT(isec,shi) -#define RE_RC_INFO(rc) -#define RE_RC_MERGE(dest,src) -#define RE_RC_COUNT(var) - -#endif - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/source/blender/render/intern/include/rayintersection.h b/source/blender/render/intern/include/rayintersection.h deleted file mode 100644 index a303301ad3b..00000000000 --- a/source/blender/render/intern/include/rayintersection.h +++ /dev/null @@ -1,136 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2007 Blender Foundation. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): André Pinto. - * - * ***** END GPL LICENSE BLOCK ***** - * RE_raytrace.h: ray tracing api, can be used independently from the renderer. - */ - -/** \file blender/render/intern/include/rayintersection.h - * \ingroup render - */ - - -#ifndef __RAYINTERSECTION_H__ -#define __RAYINTERSECTION_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "BLI_math_geom.h" - -struct RayObject; - -/* Ray Hints */ - -#define RE_RAY_LCTS_MAX_SIZE 256 -#define RT_USE_LAST_HIT /* last shadow hit is reused before raycasting on whole tree */ -//#define RT_USE_HINT /* last hit object is reused before raycasting on whole tree */ - -typedef struct LCTSHint { - int size; - struct RayObject *stack[RE_RAY_LCTS_MAX_SIZE]; -} LCTSHint; - -typedef struct RayHint { - union { LCTSHint lcts; } data; -} RayHint; - -/* Ray Intersection */ - -typedef struct Isect { - /* ray start, direction (normalized vector), and max distance. on hit, - * the distance is modified to be the distance to the hit point. */ - float start[3]; - float dir[3]; - float dist; - - /* for envmap and incremental view update renders */ - float origstart[3]; - float origdir[3]; - - /* precomputed values to accelerate bounding box intersection */ - int bv_index[6]; - float idot_axis[3]; - - /* intersection options */ - int mode; /* RE_RAY_SHADOW, RE_RAY_MIRROR, RE_RAY_SHADOW_TRA */ - int lay; /* -1 default, set for layer lamps */ - int skip; /* skip flags */ - int check; /* check flags */ - void *userdata; /* used by bake check */ - - /* hit information */ - float u, v; - int isect; /* which half of quad */ - - struct { - void *ob; - void *face; - } hit, orig; - - /* last hit optimization */ - struct RayObject *last_hit; - - /* hints */ -#ifdef RT_USE_HINT - RayTraceHint *hint, *hit_hint; -#endif - RayHint *hint; - - /* ray counter */ -#ifdef RE_RAYCOUNTER - RayCounter *raycounter; -#endif - - /* Precalculated coefficients for watertight intersection check. */ - struct IsectRayPrecalc isect_precalc; -} Isect; - -/* ray types */ -#define RE_RAY_SHADOW 0 -#define RE_RAY_MIRROR 1 -#define RE_RAY_SHADOW_TRA 2 - -/* skip options */ -#define RE_SKIP_CULLFACE (1 << 0) -/* if using this flag then *face should be a pointer to a VlakRen */ -#define RE_SKIP_VLR_NEIGHBOUR (1 << 1) - -/* check options */ -#define RE_CHECK_VLR_NONE 0 -#define RE_CHECK_VLR_RENDER 1 -#define RE_CHECK_VLR_NON_SOLID_MATERIAL 2 -#define RE_CHECK_VLR_BAKE 3 - -/* arbitrary, but can't use e.g. FLT_MAX because of precision issues */ -#define RE_RAYTRACE_MAXDIST 1e15f -#define RE_RAYTRACE_EPSILON 0.0f - -#ifdef __cplusplus -} -#endif - -#endif /* __RAYINTERSECTION_H__ */ - diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h index fd24f4eb053..134fa56f01c 100644 --- a/source/blender/render/intern/include/render_types.h +++ b/source/blender/render/intern/include/render_types.h @@ -157,6 +157,11 @@ struct Render { void **movie_ctx_arr; char viewname[MAX_NAME]; + + /* TODO replace by a whole draw manager. */ + void *gl_context; + void *gwn_context; + bool gl_context_ownership; }; /* **************** defines ********************* */ diff --git a/source/blender/render/intern/include/rendercore.h b/source/blender/render/intern/include/rendercore.h deleted file mode 100644 index aa3efca9e5b..00000000000 --- a/source/blender/render/intern/include/rendercore.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -#ifndef __RENDERCORE_H__ -#define __RENDERCORE_H__ - -/** \file blender/render/intern/include/rendercore.h - * \ingroup render - */ - -#include "render_types.h" - -#include "RE_engine.h" - -#include "DNA_node_types.h" - -#include "NOD_composite.h" - -struct ShadeInput; -struct ShadeResult; -struct World; -struct RenderPart; -struct RenderLayer; -struct RayObject; - -/* ------------------------------------------------------------------------- */ - -typedef struct PixStr { - struct PixStr *next; - int obi, facenr, z, maskz; - unsigned short mask; - short shadfac; -} PixStr; - -typedef struct PixStrMain { - struct PixStrMain *next, *prev; - struct PixStr *ps; - int counter; -} PixStrMain; - -/* ------------------------------------------------------------------------- */ - - -void calc_view_vector(float view[3], float x, float y); -float mistfactor(float zcor, const float co[3]); /* dist and height, return alpha */ - -void renderspothalo(struct ShadeInput *shi, float col[4], float alpha); -void add_halo_flare(Render *re); - -void calc_renderco_zbuf(float co[3], const float view[3], int z); -void calc_renderco_ortho(float co[3], float x, float y, int z); - -int count_mask(unsigned short mask); - -void zbufshade_tile(struct RenderPart *pa); -void zbufshadeDA_tile(struct RenderPart *pa); - -void zbufshade_sss_tile(struct RenderPart *pa); - -int get_sample_layers(struct RenderPart *pa, struct RenderLayer *rl, struct RenderLayer **rlpp); - -void render_internal_update_passes(struct RenderEngine *engine, struct Scene *scene, struct SceneRenderLayer *srl); - - -/* -------- ray.c ------- */ - -struct RayObject *RE_rayobject_create(int type, int size, int octree_resolution); - -extern void freeraytree(Render *re); -extern void makeraytree(Render *re); -struct RayObject* makeraytree_object(Render *re, ObjectInstanceRen *obi); - -extern void ray_shadow(ShadeInput *shi, LampRen *lar, float shadfac[4]); -extern void ray_trace(ShadeInput *shi, ShadeResult *); -extern void ray_ao(ShadeInput *shi, float ao[3], float env[3]); -extern void init_jitter_plane(LampRen *lar); -extern void init_ao_sphere(Render *re, struct World *wrld); -extern void init_render_qmcsampler(Render *re); -extern void free_render_qmcsampler(Render *re); - -#endif /* __RENDERCORE_H__ */ diff --git a/source/blender/render/intern/include/shading.h b/source/blender/render/intern/include/shading.h deleted file mode 100644 index e306c3c075c..00000000000 --- a/source/blender/render/intern/include/shading.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2006 Blender Foundation - * All rights reserved. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/render/intern/include/shading.h - * \ingroup render - */ - - -struct ShadeInput; -struct ShadeResult; -struct RenderPart; -struct RenderLayer; -struct PixStr; -struct LampRen; -struct VlakRen; -struct StrandPoint; -struct ObjectInstanceRen; -struct Isect; - -/* shadeinput.c */ - -#define RE_MAX_OSA 16 - -/* needed to calculate shadow and AO for an entire pixel */ -typedef struct ShadeSample { - int tot; /* amount of shi in use, can be 1 for not FULL_OSA */ - - RenderLayer *rlpp[RE_MAX_OSA]; /* fast lookup from sample to renderlayer (fullsample buf) */ - - /* could be malloced once */ - ShadeInput shi[RE_MAX_OSA]; - ShadeResult shr[RE_MAX_OSA]; -} ShadeSample; - - - /* also the node shader callback */ -void shade_material_loop(struct ShadeInput *shi, struct ShadeResult *shr); - -void shade_input_set_triangle_i(struct ShadeInput *shi, struct ObjectInstanceRen *obi, struct VlakRen *vlr, short i1, short i2, short i3); -void shade_input_set_triangle(struct ShadeInput *shi, int obi, int facenr, int normal_flip); -void shade_input_copy_triangle(struct ShadeInput *shi, struct ShadeInput *from); -void shade_input_calc_viewco(struct ShadeInput *shi, float x, float y, float z, float view[3], float dxyview[2], float co[3], float dxco[3], float dyco[3]); -void shade_input_set_viewco(struct ShadeInput *shi, float x, float y, float sx, float sy, float z); -void shade_input_set_uv(struct ShadeInput *shi); -void shade_input_set_normals(struct ShadeInput *shi); -void shade_input_set_vertex_normals(struct ShadeInput *shi); -void shade_input_flip_normals(struct ShadeInput *shi); -void shade_input_set_shade_texco(struct ShadeInput *shi); -void shade_input_set_strand(struct ShadeInput *shi, struct StrandRen *strand, struct StrandPoint *spoint); -void shade_input_set_strand_texco(struct ShadeInput *shi, struct StrandRen *strand, struct StrandVert *svert, struct StrandPoint *spoint); -void shade_input_do_shade(struct ShadeInput *shi, struct ShadeResult *shr); - -void shade_input_init_material(struct ShadeInput *shi); -void shade_input_initialize(struct ShadeInput *shi, struct RenderPart *pa, struct RenderLayer *rl, int sample); - -void shade_sample_initialize(struct ShadeSample *ssamp, struct RenderPart *pa, struct RenderLayer *rl); -void shade_samples_do_AO(struct ShadeSample *ssamp); -void shade_samples_fill_with_ps(struct ShadeSample *ssamp, struct PixStr *ps, int x, int y); -int shade_samples(struct ShadeSample *ssamp, struct PixStr *ps, int x, int y); - -void vlr_set_uv_indices(struct VlakRen *vlr, int *i1, int *i2, int *i3); - -void calc_R_ref(struct ShadeInput *shi); - -void barycentric_differentials_from_position( - const float co[3], const float v1[3], const float v2[3], const float v3[3], - const float dxco[3], const float dyco[3], const float facenor[3], const bool differentials, - float *u, float *v, float *dx_u, float *dx_v, float *dy_u, float *dy_v); - -/* shadeoutput. */ -void shade_lamp_loop(struct ShadeInput *shi, struct ShadeResult *shr); - -void shade_color(struct ShadeInput *shi, ShadeResult *shr); - -void ambient_occlusion(struct ShadeInput *shi); -void environment_lighting_apply(struct ShadeInput *shi, struct ShadeResult *shr); - -ListBase *get_lights(struct ShadeInput *shi); -float lamp_get_visibility(struct LampRen *lar, const float co[3], float lv[3], float *dist); -void lamp_get_shadow(struct LampRen *lar, ShadeInput *shi, float inp, float shadfac[4], int do_real); - -float fresnel_fac(const float view[3], const float vn[3], float fresnel, float fac); - -/* rayshade.c */ -extern void shade_ray(struct Isect *is, struct ShadeInput *shi, struct ShadeResult *shr); diff --git a/source/blender/render/intern/include/strand.h b/source/blender/render/intern/include/strand.h deleted file mode 100644 index f4e22c78b42..00000000000 --- a/source/blender/render/intern/include/strand.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * Contributor(s): Brecht Van Lommel. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/render/intern/include/strand.h - * \ingroup render - */ - - -#ifndef __STRAND_H__ -#define __STRAND_H__ - -struct StrandVert; -struct StrandRen; -struct StrandBuffer; -struct ShadeSample; -struct StrandPart; -struct Render; -struct ZSpan; -struct ObjectInstanceRen; -struct StrandSurface; -struct DerivedMesh; -struct ObjectRen; - -typedef struct StrandPoint { - /* position within segment */ - float t; - - /* camera space */ - float co[3]; - float nor[3]; - float tan[3]; - float strandco; - float width; - - /* derivatives */ - float dtco[3], dsco[3]; - float dtstrandco; - - /* outer points */ - float co1[3], co2[3]; - float hoco1[4], hoco2[4]; - float zco1[3], zco2[3]; - int clip1, clip2; - - /* screen space */ - float hoco[4]; - float x, y; - - /* simplification */ - float alpha; -} StrandPoint; - -typedef struct StrandSegment { - struct StrandVert *v[4]; - struct StrandRen *strand; - struct StrandBuffer *buffer; - struct ObjectInstanceRen *obi; - float sqadaptcos; - - StrandPoint point1, point2; - int shaded; -} StrandSegment; - -struct StrandShadeCache; -typedef struct StrandShadeCache StrandShadeCache; - -void strand_eval_point(StrandSegment *sseg, StrandPoint *spoint); -void render_strand_segment(struct Render *re, float winmat[4][4], struct StrandPart *spart, struct ZSpan *zspan, int totzspan, StrandSegment *sseg); -void strand_minmax(struct StrandRen *strand, float min[3], float max[3], const float width); - -struct StrandSurface *cache_strand_surface(struct Render *re, struct ObjectRen *obr, struct DerivedMesh *dm, float mat[4][4], int timeoffset); -void free_strand_surface(struct Render *re); - -struct StrandShadeCache *strand_shade_cache_create(void); -void strand_shade_cache_free(struct StrandShadeCache *cache); -void strand_shade_segment(struct Render *re, struct StrandShadeCache *cache, struct StrandSegment *sseg, struct ShadeSample *ssamp, float t, float s, int addpassflag); -void strand_shade_unref(struct StrandShadeCache *cache, struct ObjectInstanceRen *obi, struct StrandVert *svert); - -#endif - diff --git a/source/blender/render/intern/include/sunsky.h b/source/blender/render/intern/include/sunsky.h deleted file mode 100644 index c608f9fc48c..00000000000 --- a/source/blender/render/intern/include/sunsky.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * Contributor(s): zaghaghi - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/render/intern/include/sunsky.h - * \ingroup render - */ - -#ifndef __SUNSKY_H__ -#define __SUNSKY_H__ - -// #define SPECTRUM_MAX_COMPONENTS 100 - -typedef struct SunSky { - short effect_type, skyblendtype, sky_colorspace; - float turbidity; - float theta, phi; - - float toSun[3]; - - /*float sunSpectralRaddata[SPECTRUM_MAX_COMPONENTS];*/ - float sunSolidAngle; - - float zenith_Y, zenith_x, zenith_y; - - float perez_Y[5], perez_x[5], perez_y[5]; - - /* suggested by glome in patch [#8063] */ - float horizon_brightness; - float spread; - float sun_brightness; - float sun_size; - float backscattered_light; - float skyblendfac; - float sky_exposure; - - float atm_HGg; - - float atm_SunIntensity; - float atm_InscatteringMultiplier; - float atm_ExtinctionMultiplier; - float atm_BetaRayMultiplier; - float atm_BetaMieMultiplier; - float atm_DistanceMultiplier; - - float atm_BetaRay[3]; - float atm_BetaDashRay[3]; - float atm_BetaMie[3]; - float atm_BetaDashMie[3]; - float atm_BetaRM[3]; -} SunSky; - -void InitSunSky(struct SunSky *sunsky, float turb, const float toSun[3], float horizon_brightness, - float spread, float sun_brightness, float sun_size, float back_scatter, - float skyblendfac, short skyblendtype, float sky_exposure, float sky_colorspace); - -void GetSkyXYZRadiance(struct SunSky *sunsky, float theta, float phi, float color_out[3]); -void GetSkyXYZRadiancef(struct SunSky *sunsky, const float varg[3], float color_out[3]); -void InitAtmosphere(struct SunSky *sunSky, float sun_intens, float mief, float rayf, float inscattf, float extincf, float disf); -void AtmospherePixleShader(struct SunSky *sunSky, float view[3], float s, float rgb[3]); -void ClipColor(float c[3]); - -#endif /*__SUNSKY_H__*/ diff --git a/source/blender/render/intern/include/texture_ocean.h b/source/blender/render/intern/include/texture_ocean.h deleted file mode 100644 index 6d7bc6fe7b0..00000000000 --- a/source/blender/render/intern/include/texture_ocean.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * Contributors: Matt Ebb - * - * ***** END GPL LICENSE BLOCK ***** - */ - -#ifndef __TEXTURE_OCEAN_H__ -#define __TEXTURE_OCEAN_H__ - -/** \file blender/render/intern/include/texture_ocean.h - * \ingroup render - */ - -int ocean_texture(struct Tex *tex, const float texvec[2], struct TexResult *texres); - -#endif /* __TEXTURE_OCEAN_H__ */ diff --git a/source/blender/render/intern/include/voxeldata.h b/source/blender/render/intern/include/voxeldata.h deleted file mode 100644 index 041ca78a799..00000000000 --- a/source/blender/render/intern/include/voxeldata.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): Raul Fernandez Hernandez (Farsthary), Matt Ebb. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/render/intern/include/voxeldata.h - * \ingroup render - */ - -#ifndef __VOXELDATA_H__ -#define __VOXELDATA_H__ - -struct Render; -struct TexResult; - -typedef struct VoxelDataHeader { - int resolX, resolY, resolZ; - int frames; -} VoxelDataHeader; - -void cache_voxeldata(Tex *tex, int scene_frame); -void make_voxeldata(struct Render *re); -int voxeldatatex(struct Tex *tex, const float texvec[3], struct TexResult *texres); - -#endif /* __VOXELDATA_H__ */ diff --git a/source/blender/render/intern/raytrace/bvh.h b/source/blender/render/intern/raytrace/bvh.h deleted file mode 100644 index 0f9a506762b..00000000000 --- a/source/blender/render/intern/raytrace/bvh.h +++ /dev/null @@ -1,407 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2009 Blender Foundation. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): André Pinto. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/render/intern/raytrace/bvh.h - * \ingroup render - */ - - -#include "MEM_guardedalloc.h" - -#include "BLI_math.h" - -#include "raycounter.h" -#include "rayintersection.h" -#include "rayobject.h" -#include "rayobject_hint.h" -#include "rayobject_rtbuild.h" - -#include <assert.h> - -#ifdef __SSE__ -#include <xmmintrin.h> -#endif - -#ifndef __BVH_H__ -#define __BVH_H__ - -#ifdef __SSE__ -inline int test_bb_group4(__m128 *bb_group, const Isect *isec) -{ - const __m128 tmin0 = _mm_setzero_ps(); - const __m128 tmax0 = _mm_set_ps1(isec->dist); - - float start[3], idot_axis[3]; - copy_v3_v3(start, isec->start); - copy_v3_v3(idot_axis, isec->idot_axis); - - const __m128 tmin1 = _mm_max_ps(tmin0, _mm_mul_ps(_mm_sub_ps(bb_group[isec->bv_index[0]], _mm_set_ps1(start[0]) ), _mm_set_ps1(idot_axis[0])) ); - const __m128 tmax1 = _mm_min_ps(tmax0, _mm_mul_ps(_mm_sub_ps(bb_group[isec->bv_index[1]], _mm_set_ps1(start[0]) ), _mm_set_ps1(idot_axis[0])) ); - const __m128 tmin2 = _mm_max_ps(tmin1, _mm_mul_ps(_mm_sub_ps(bb_group[isec->bv_index[2]], _mm_set_ps1(start[1]) ), _mm_set_ps1(idot_axis[1])) ); - const __m128 tmax2 = _mm_min_ps(tmax1, _mm_mul_ps(_mm_sub_ps(bb_group[isec->bv_index[3]], _mm_set_ps1(start[1]) ), _mm_set_ps1(idot_axis[1])) ); - const __m128 tmin3 = _mm_max_ps(tmin2, _mm_mul_ps(_mm_sub_ps(bb_group[isec->bv_index[4]], _mm_set_ps1(start[2]) ), _mm_set_ps1(idot_axis[2])) ); - const __m128 tmax3 = _mm_min_ps(tmax2, _mm_mul_ps(_mm_sub_ps(bb_group[isec->bv_index[5]], _mm_set_ps1(start[2]) ), _mm_set_ps1(idot_axis[2])) ); - - return _mm_movemask_ps(_mm_cmpge_ps(tmax3, tmin3)); -} -#endif - -/* - * Determines the distance that the ray must travel to hit the bounding volume of the given node - * Based on Tactical Optimization of Ray/Box Intersection, by Graham Fyffe - * [http://tog.acm.org/resources/RTNews/html/rtnv21n1.html#art9] - */ -static inline int rayobject_bb_intersect_test(const Isect *isec, const float *_bb) -{ - const float *bb = _bb; - - float t1x = (bb[isec->bv_index[0]] - isec->start[0]) * isec->idot_axis[0]; - float t2x = (bb[isec->bv_index[1]] - isec->start[0]) * isec->idot_axis[0]; - float t1y = (bb[isec->bv_index[2]] - isec->start[1]) * isec->idot_axis[1]; - float t2y = (bb[isec->bv_index[3]] - isec->start[1]) * isec->idot_axis[1]; - float t1z = (bb[isec->bv_index[4]] - isec->start[2]) * isec->idot_axis[2]; - float t2z = (bb[isec->bv_index[5]] - isec->start[2]) * isec->idot_axis[2]; - - RE_RC_COUNT(isec->raycounter->bb.test); - - if (t1x > t2y || t2x < t1y || t1x > t2z || t2x < t1z || t1y > t2z || t2y < t1z) return 0; - if (t2x < 0.0f || t2y < 0.0f || t2z < 0.0f) return 0; - if (t1x > isec->dist || t1y > isec->dist || t1z > isec->dist) return 0; - RE_RC_COUNT(isec->raycounter->bb.hit); - - return 1; -} - -/* bvh tree generics */ -template<class Tree> static void bvh_add(Tree *obj, RayObject *ob) -{ - rtbuild_add(obj->builder, ob); -} - -template<class Node> -inline bool is_leaf(Node *node) -{ - return !RE_rayobject_isAligned(node); -} - -template<class Tree> static void bvh_done(Tree *obj); - -template<class Tree> -static void bvh_free(Tree *obj) -{ - if (obj->builder) - rtbuild_free(obj->builder); - - if (obj->node_arena) - BLI_memarena_free(obj->node_arena); - - MEM_freeN(obj); -} - -template<class Tree> -static void bvh_bb(Tree *obj, float *min, float *max) -{ - if (obj->root) - bvh_node_merge_bb(obj->root, min, max); -} - - -template<class Tree> -static float bvh_cost(Tree *obj) -{ - assert(obj->cost >= 0.0f); - return obj->cost; -} - - - -/* bvh tree nodes generics */ -template<class Node> static inline int bvh_node_hit_test(Node *node, Isect *isec) -{ - return rayobject_bb_intersect_test(isec, (const float *)node->bb); -} - - -template<class Node> -static inline void bvh_node_merge_bb(Node *node, float min[3], float max[3]) -{ - if (is_leaf(node)) { - RE_rayobject_merge_bb((RayObject *)node, min, max); - } - else { - DO_MIN(node->bb, min); - DO_MAX(node->bb + 3, max); - } -} - - - -/* - * recursively transverse a BVH looking for a rayhit using a local stack - */ -template<class Node> static inline void bvh_node_push_childs(Node *node, Isect *isec, Node **stack, int &stack_pos); - -template<class Node, int MAX_STACK_SIZE, bool TEST_ROOT, bool SHADOW> -static int bvh_node_stack_raycast(Node *root, Isect *isec) -{ - Node *stack[MAX_STACK_SIZE]; - int hit = 0, stack_pos = 0; - - if (!TEST_ROOT && !is_leaf(root)) - bvh_node_push_childs(root, isec, stack, stack_pos); - else - stack[stack_pos++] = root; - - while (stack_pos) { - Node *node = stack[--stack_pos]; - if (!is_leaf(node)) { - if (bvh_node_hit_test(node, isec)) { - bvh_node_push_childs(node, isec, stack, stack_pos); - assert(stack_pos <= MAX_STACK_SIZE); - } - } - else { - hit |= RE_rayobject_intersect( (RayObject *)node, isec); - if (SHADOW && hit) return hit; - } - } - return hit; -} - - -#ifdef __SSE__ -/* - * Generic SIMD bvh recursion - * this was created to be able to use any simd (with the cost of some memmoves) - * it can take advantage of any SIMD width and doens't needs any special tree care - */ -template<class Node, int MAX_STACK_SIZE, bool TEST_ROOT> -static int bvh_node_stack_raycast_simd(Node *root, Isect *isec) -{ - Node *stack[MAX_STACK_SIZE]; - - int hit = 0, stack_pos = 0; - - if (!TEST_ROOT) { - if (!is_leaf(root)) { - if (!is_leaf(root->child)) - bvh_node_push_childs(root, isec, stack, stack_pos); - else - return RE_rayobject_intersect( (RayObject *)root->child, isec); - } - else - return RE_rayobject_intersect( (RayObject *)root, isec); - } - else { - if (!is_leaf(root)) - stack[stack_pos++] = root; - else - return RE_rayobject_intersect( (RayObject *)root, isec); - } - - while (true) { - //Use SIMD 4 - if (stack_pos >= 4) { - __m128 t_bb[6]; - Node *t_node[4]; - - stack_pos -= 4; - - /* prepare the 4BB for SIMD */ - t_node[0] = stack[stack_pos + 0]->child; - t_node[1] = stack[stack_pos + 1]->child; - t_node[2] = stack[stack_pos + 2]->child; - t_node[3] = stack[stack_pos + 3]->child; - - const float *bb0 = stack[stack_pos + 0]->bb; - const float *bb1 = stack[stack_pos + 1]->bb; - const float *bb2 = stack[stack_pos + 2]->bb; - const float *bb3 = stack[stack_pos + 3]->bb; - - const __m128 x0y0x1y1 = _mm_shuffle_ps(_mm_load_ps(bb0), _mm_load_ps(bb1), _MM_SHUFFLE(1, 0, 1, 0) ); - const __m128 x2y2x3y3 = _mm_shuffle_ps(_mm_load_ps(bb2), _mm_load_ps(bb3), _MM_SHUFFLE(1, 0, 1, 0) ); - t_bb[0] = _mm_shuffle_ps(x0y0x1y1, x2y2x3y3, _MM_SHUFFLE(2, 0, 2, 0) ); - t_bb[1] = _mm_shuffle_ps(x0y0x1y1, x2y2x3y3, _MM_SHUFFLE(3, 1, 3, 1) ); - - const __m128 z0X0z1X1 = _mm_shuffle_ps(_mm_load_ps(bb0), _mm_load_ps(bb1), _MM_SHUFFLE(3, 2, 3, 2) ); - const __m128 z2X2z3X3 = _mm_shuffle_ps(_mm_load_ps(bb2), _mm_load_ps(bb3), _MM_SHUFFLE(3, 2, 3, 2) ); - t_bb[2] = _mm_shuffle_ps(z0X0z1X1, z2X2z3X3, _MM_SHUFFLE(2, 0, 2, 0) ); - t_bb[3] = _mm_shuffle_ps(z0X0z1X1, z2X2z3X3, _MM_SHUFFLE(3, 1, 3, 1) ); - - const __m128 Y0Z0Y1Z1 = _mm_shuffle_ps(_mm_load_ps(bb0 + 4), _mm_load_ps(bb1 + 4), _MM_SHUFFLE(1, 0, 1, 0) ); - const __m128 Y2Z2Y3Z3 = _mm_shuffle_ps(_mm_load_ps(bb2 + 4), _mm_load_ps(bb3 + 4), _MM_SHUFFLE(1, 0, 1, 0) ); - t_bb[4] = _mm_shuffle_ps(Y0Z0Y1Z1, Y2Z2Y3Z3, _MM_SHUFFLE(2, 0, 2, 0) ); - t_bb[5] = _mm_shuffle_ps(Y0Z0Y1Z1, Y2Z2Y3Z3, _MM_SHUFFLE(3, 1, 3, 1) ); -#if 0 - for (int i = 0; i < 4; i++) - { - Node *t = stack[stack_pos + i]; - assert(!is_leaf(t)); - - float *bb = ((float *)t_bb) + i; - bb[4 * 0] = t->bb[0]; - bb[4 * 1] = t->bb[1]; - bb[4 * 2] = t->bb[2]; - bb[4 * 3] = t->bb[3]; - bb[4 * 4] = t->bb[4]; - bb[4 * 5] = t->bb[5]; - t_node[i] = t->child; - } -#endif - RE_RC_COUNT(isec->raycounter->simd_bb.test); - int res = test_bb_group4(t_bb, isec); - - for (int i = 0; i < 4; i++) - if (res & (1 << i)) { - RE_RC_COUNT(isec->raycounter->simd_bb.hit); - if (!is_leaf(t_node[i])) { - for (Node *t = t_node[i]; t; t = t->sibling) { - assert(stack_pos < MAX_STACK_SIZE); - stack[stack_pos++] = t; - } - } - else { - hit |= RE_rayobject_intersect( (RayObject *)t_node[i], isec); - if (hit && isec->mode == RE_RAY_SHADOW) return hit; - } - } - } - else if (stack_pos > 0) { - Node *node = stack[--stack_pos]; - assert(!is_leaf(node)); - - if (bvh_node_hit_test(node, isec)) { - if (!is_leaf(node->child)) { - bvh_node_push_childs(node, isec, stack, stack_pos); - assert(stack_pos <= MAX_STACK_SIZE); - } - else { - hit |= RE_rayobject_intersect( (RayObject *)node->child, isec); - if (hit && isec->mode == RE_RAY_SHADOW) return hit; - } - } - } - else break; - } - return hit; -} -#endif - -/* - * recursively transverse a BVH looking for a rayhit using system stack - */ -#if 0 -template<class Node> -static int bvh_node_raycast(Node *node, Isect *isec) -{ - int hit = 0; - if (bvh_test_node(node, isec)) - { - if (isec->idot_axis[node->split_axis] > 0.0f) - { - int i; - for (i = 0; i < BVH_NCHILDS; i++) - if (!is_leaf(node->child[i])) - { - if (node->child[i] == 0) break; - - hit |= bvh_node_raycast(node->child[i], isec); - if (hit && isec->mode == RE_RAY_SHADOW) return hit; - } - else { - hit |= RE_rayobject_intersect( (RayObject *)node->child[i], isec); - if (hit && isec->mode == RE_RAY_SHADOW) return hit; - } - } - else { - int i; - for (i = BVH_NCHILDS - 1; i >= 0; i--) - if (!is_leaf(node->child[i])) - { - if (node->child[i]) - { - hit |= dfs_raycast(node->child[i], isec); - if (hit && isec->mode == RE_RAY_SHADOW) return hit; - } - } - else { - hit |= RE_rayobject_intersect( (RayObject *)node->child[i], isec); - if (hit && isec->mode == RE_RAY_SHADOW) return hit; - } - } - } - return hit; -} -#endif - -template<class Node, class HintObject> -static void bvh_dfs_make_hint(Node *node, LCTSHint *hint, int reserve_space, HintObject *hintObject) -{ - assert(hint->size + reserve_space + 1 <= RE_RAY_LCTS_MAX_SIZE); - - if (is_leaf(node)) { - hint->stack[hint->size++] = (RayObject *)node; - } - else { - int childs = count_childs(node); - if (hint->size + reserve_space + childs <= RE_RAY_LCTS_MAX_SIZE) { - int result = hint_test_bb(hintObject, node->bb, node->bb + 3); - if (result == HINT_RECURSE) { - /* We are 100% sure the ray will be pass inside this node */ - bvh_dfs_make_hint_push_siblings(node->child, hint, reserve_space, hintObject); - } - else if (result == HINT_ACCEPT) { - hint->stack[hint->size++] = (RayObject *)node; - } - } - else { - hint->stack[hint->size++] = (RayObject *)node; - } - } -} - - -template<class Tree> -static RayObjectAPI *bvh_get_api(int maxstacksize); - - -template<class Tree, int DFS_STACK_SIZE> -static inline RayObject *bvh_create_tree(int size) -{ - Tree *obj = (Tree *)MEM_callocN(sizeof(Tree), "BVHTree"); - assert(RE_rayobject_isAligned(obj)); /* RayObject API assumes real data to be 4-byte aligned */ - - obj->rayobj.api = bvh_get_api<Tree>(DFS_STACK_SIZE); - obj->root = NULL; - - obj->node_arena = NULL; - obj->builder = rtbuild_create(size); - - return RE_rayobject_unalignRayAPI((RayObject *) obj); -} - -#endif diff --git a/source/blender/render/intern/raytrace/rayobject.cpp b/source/blender/render/intern/raytrace/rayobject.cpp deleted file mode 100644 index fee877b311d..00000000000 --- a/source/blender/render/intern/raytrace/rayobject.cpp +++ /dev/null @@ -1,534 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2009 Blender Foundation. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): André Pinto. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/render/intern/raytrace/rayobject.cpp - * \ingroup render - */ - - -#include <assert.h> - -#include "MEM_guardedalloc.h" - -#include "BLI_math.h" -#include "BLI_utildefines.h" - -#include "DNA_material_types.h" - -#include "rayintersection.h" -#include "rayobject.h" -#include "raycounter.h" -#include "render_types.h" -#include "renderdatabase.h" - -/* RayFace - * - * note we force always inline here, because compiler refuses to otherwise - * because function is too long. Since this is code that is called billions - * of times we really do want to inline. */ - -MALWAYS_INLINE RayObject *rayface_from_coords(RayFace *rayface, void *ob, void *face, - float *v1, float *v2, float *v3, float *v4) -{ - rayface->ob = ob; - rayface->face = face; - - copy_v3_v3(rayface->v1, v1); - copy_v3_v3(rayface->v2, v2); - copy_v3_v3(rayface->v3, v3); - - if (v4) { - copy_v3_v3(rayface->v4, v4); - rayface->quad = 1; - } - else { - rayface->quad = 0; - } - - return RE_rayobject_unalignRayFace(rayface); -} - -MALWAYS_INLINE void rayface_from_vlak(RayFace *rayface, ObjectInstanceRen *obi, VlakRen *vlr) -{ - rayface_from_coords(rayface, obi, vlr, vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->v4 ? vlr->v4->co : NULL); - - if (obi->transform_primitives) { - mul_m4_v3(obi->mat, rayface->v1); - mul_m4_v3(obi->mat, rayface->v2); - mul_m4_v3(obi->mat, rayface->v3); - - if (RE_rayface_isQuad(rayface)) - mul_m4_v3(obi->mat, rayface->v4); - } -} - -RayObject *RE_rayface_from_vlak(RayFace *rayface, ObjectInstanceRen *obi, VlakRen *vlr) -{ - return rayface_from_coords(rayface, obi, vlr, vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->v4 ? vlr->v4->co : NULL); -} - -RayObject *RE_rayface_from_coords(RayFace *rayface, void *ob, void *face, float *v1, float *v2, float *v3, float *v4) -{ - return rayface_from_coords(rayface, ob, face, v1, v2, v3, v4); -} - -/* VlakPrimitive */ - -RayObject *RE_vlakprimitive_from_vlak(VlakPrimitive *face, struct ObjectInstanceRen *obi, struct VlakRen *vlr) -{ - face->ob = obi; - face->face = vlr; - - return RE_rayobject_unalignVlakPrimitive(face); -} - -/* Checks for ignoring faces or materials */ - -MALWAYS_INLINE int vlr_check_intersect(Isect *is, ObjectInstanceRen *obi, VlakRen *vlr) -{ - /* for baking selected to active non-traceable materials might still - * be in the raytree */ - if (!(vlr->flag & R_TRACEBLE)) - return 0; - - /* I know... cpu cycle waste, might do smarter once */ - if (is->mode == RE_RAY_MIRROR) - return !(vlr->mat->mode & MA_ONLYCAST); - else - return (vlr->mat->mode2 & MA_CASTSHADOW) && (is->lay & obi->lay); -} - -MALWAYS_INLINE int vlr_check_intersect_solid(Isect *UNUSED(is), ObjectInstanceRen *UNUSED(obi), VlakRen *vlr) -{ - /* solid material types only */ - if (vlr->mat->material_type == MA_TYPE_SURFACE) - return 1; - else - return 0; -} - -MALWAYS_INLINE int vlr_check_bake(Isect *is, ObjectInstanceRen *obi, VlakRen *UNUSED(vlr)) -{ - return (obi->obr->ob != is->userdata) && (obi->obr->ob->flag & SELECT); -} - -/* Ray Triangle/Quad Intersection */ - -static bool isect_ray_tri_watertight_no_sign_check_v3( - const float ray_origin[3], const struct IsectRayPrecalc *isect_precalc, - const float v0[3], const float v1[3], const float v2[3], - float *r_lambda, float r_uv[2]) -{ - const int kx = isect_precalc->kx; - const int ky = isect_precalc->ky; - const int kz = isect_precalc->kz; - const float sx = isect_precalc->sx; - const float sy = isect_precalc->sy; - const float sz = isect_precalc->sz; - - /* Calculate vertices relative to ray origin. */ - const float a[3] = {v0[0] - ray_origin[0], v0[1] - ray_origin[1], v0[2] - ray_origin[2]}; - const float b[3] = {v1[0] - ray_origin[0], v1[1] - ray_origin[1], v1[2] - ray_origin[2]}; - const float c[3] = {v2[0] - ray_origin[0], v2[1] - ray_origin[1], v2[2] - ray_origin[2]}; - - const float a_kx = a[kx], a_ky = a[ky], a_kz = a[kz]; - const float b_kx = b[kx], b_ky = b[ky], b_kz = b[kz]; - const float c_kx = c[kx], c_ky = c[ky], c_kz = c[kz]; - - /* Perform shear and scale of vertices. */ - const float ax = a_kx - sx * a_kz; - const float ay = a_ky - sy * a_kz; - const float bx = b_kx - sx * b_kz; - const float by = b_ky - sy * b_kz; - const float cx = c_kx - sx * c_kz; - const float cy = c_ky - sy * c_kz; - - /* Calculate scaled barycentric coordinates. */ - const float u = cx * by - cy * bx; - const float v = ax * cy - ay * cx; - const float w = bx * ay - by * ax; - float det; - - if ((u < 0.0f || v < 0.0f || w < 0.0f) && - (u > 0.0f || v > 0.0f || w > 0.0f)) - { - return false; - } - - /* Calculate determinant. */ - det = u + v + w; - if (UNLIKELY(det == 0.0f)) { - return false; - } - else { - /* Calculate scaled z-coordinates of vertices and use them to calculate - * the hit distance. - */ - const float t = (u * a_kz + v * b_kz + w * c_kz) * sz; - /* Normalize u, v and t. */ - const float inv_det = 1.0f / det; - if (r_uv) { - r_uv[0] = u * inv_det; - r_uv[1] = v * inv_det; - } - *r_lambda = t * inv_det; - return true; - } -} - -MALWAYS_INLINE int isec_tri_quad(const float start[3], - const struct IsectRayPrecalc *isect_precalc, - const RayFace *face, - float r_uv[2], float *r_lambda) -{ - float uv[2], l; - - if (isect_ray_tri_watertight_v3(start, isect_precalc, face->v1, face->v2, face->v3, &l, uv)) { - /* check if intersection is within ray length */ - if (l > -RE_RAYTRACE_EPSILON && l < *r_lambda) { - r_uv[0] = -uv[0]; - r_uv[1] = -uv[1]; - *r_lambda = l; - return 1; - } - } - - /* intersect second triangle in quad */ - if (RE_rayface_isQuad(face)) { - if (isect_ray_tri_watertight_v3(start, isect_precalc, face->v1, face->v3, face->v4, &l, uv)) { - /* check if intersection is within ray length */ - if (l > -RE_RAYTRACE_EPSILON && l < *r_lambda) { - r_uv[0] = -uv[0]; - r_uv[1] = -uv[1]; - *r_lambda = l; - return 2; - } - } - } - - return 0; -} - -/* Simpler yes/no Ray Triangle/Quad Intersection */ - -MALWAYS_INLINE int isec_tri_quad_neighbour(const float start[3], - const float dir[3], - const RayFace *face) -{ - float r[3]; - struct IsectRayPrecalc isect_precalc; - float uv[2], l; - - negate_v3_v3(r, dir); /* note, different than above function */ - - isect_ray_tri_watertight_v3_precalc(&isect_precalc, r); - - if (isect_ray_tri_watertight_no_sign_check_v3(start, &isect_precalc, face->v1, face->v2, face->v3, &l, uv)) { - return 1; - } - - /* intersect second triangle in quad */ - if (RE_rayface_isQuad(face)) { - if (isect_ray_tri_watertight_no_sign_check_v3(start, &isect_precalc, face->v1, face->v3, face->v4, &l, uv)) { - return 2; - } - } - - return 0; -} - -/* RayFace intersection with checks and neighbor verifaction included, - * Isect is modified if the face is hit. */ - -MALWAYS_INLINE int intersect_rayface(RayObject *hit_obj, RayFace *face, Isect *is) -{ - float dist, uv[2]; - int ok = 0; - - /* avoid self-intersection */ - if (is->orig.ob == face->ob && is->orig.face == face->face) - return 0; - - /* check if we should intersect this face */ - if (is->check == RE_CHECK_VLR_RENDER) { - if (vlr_check_intersect(is, (ObjectInstanceRen *)face->ob, (VlakRen *)face->face) == 0) - return 0; - } - else if (is->check == RE_CHECK_VLR_NON_SOLID_MATERIAL) { - if (vlr_check_intersect(is, (ObjectInstanceRen *)face->ob, (VlakRen *)face->face) == 0) - return 0; - if (vlr_check_intersect_solid(is, (ObjectInstanceRen *)face->ob, (VlakRen *)face->face) == 0) - return 0; - } - else if (is->check == RE_CHECK_VLR_BAKE) { - if (vlr_check_bake(is, (ObjectInstanceRen *)face->ob, (VlakRen *)face->face) == 0) - return 0; - } - - /* ray counter */ - RE_RC_COUNT(is->raycounter->faces.test); - - dist = is->dist; - ok = isec_tri_quad(is->start, &is->isect_precalc, face, uv, &dist); - - if (ok) { - - /* when a shadow ray leaves a face, it can be little outside the edges - * of it, causing intersection to be detected in its neighbor face */ - if (is->skip & RE_SKIP_VLR_NEIGHBOUR) { - if (dist < 0.1f && is->orig.ob == face->ob) { - VlakRen *a = (VlakRen *)is->orig.face; - VlakRen *b = (VlakRen *)face->face; - ObjectRen *obr = ((ObjectInstanceRen *)face->ob)->obr; - - VertRen **va, **vb; - int *org_idx_a, *org_idx_b; - int i, j; - bool is_neighbor = false; - - /* "same" vertex means either the actual same VertRen, or the same 'final org index', if available - * (autosmooth only, currently). */ - for (i = 0, va = &a->v1; !is_neighbor && i < 4 && *va; ++i, ++va) { - org_idx_a = RE_vertren_get_origindex(obr, *va, false); - for (j = 0, vb = &b->v1; !is_neighbor && j < 4 && *vb; ++j, ++vb) { - if (*va == *vb) { - is_neighbor = true; - } - else if (org_idx_a) { - org_idx_b = RE_vertren_get_origindex(obr, *vb, 0); - if (org_idx_b && *org_idx_a == *org_idx_b) { - is_neighbor = true; - } - } - } - } - - /* So there's a shared edge or vertex, let's intersect ray with self, if that's true - * we can safely return 1, otherwise we assume the intersection is invalid, 0 */ - if (is_neighbor) { - /* create RayFace from original face, transformed if necessary */ - RayFace origface; - ObjectInstanceRen *ob = (ObjectInstanceRen *)is->orig.ob; - rayface_from_vlak(&origface, ob, (VlakRen *)is->orig.face); - - if (!isec_tri_quad_neighbour(is->start, is->dir, &origface)) { - return 0; - } - } - } - } - - RE_RC_COUNT(is->raycounter->faces.hit); - - is->isect = ok; // which half of the quad - is->dist = dist; - is->u = uv[0]; is->v = uv[1]; - - is->hit.ob = face->ob; - is->hit.face = face->face; -#ifdef RT_USE_LAST_HIT - is->last_hit = hit_obj; -#endif - return 1; - } - - return 0; -} - -/* Intersection */ - -int RE_rayobject_raycast(RayObject *r, Isect *isec) -{ - int i; - - /* Pre-calculate orientation for watertight intersection checks. */ - isect_ray_tri_watertight_v3_precalc(&isec->isect_precalc, isec->dir); - - RE_RC_COUNT(isec->raycounter->raycast.test); - - /* setup vars used on raycast */ - for (i = 0; i < 3; i++) { - isec->idot_axis[i] = 1.0f / isec->dir[i]; - - isec->bv_index[2 * i] = isec->idot_axis[i] < 0.0f ? 1 : 0; - isec->bv_index[2 * i + 1] = 1 - isec->bv_index[2 * i]; - - isec->bv_index[2 * i] = i + 3 * isec->bv_index[2 * i]; - isec->bv_index[2 * i + 1] = i + 3 * isec->bv_index[2 * i + 1]; - } - -#ifdef RT_USE_LAST_HIT - /* last hit heuristic */ - if (isec->mode == RE_RAY_SHADOW && isec->last_hit) { - RE_RC_COUNT(isec->raycounter->rayshadow_last_hit.test); - - if (RE_rayobject_intersect(isec->last_hit, isec)) { - RE_RC_COUNT(isec->raycounter->raycast.hit); - RE_RC_COUNT(isec->raycounter->rayshadow_last_hit.hit); - return 1; - } - } -#endif - -#ifdef RT_USE_HINT - isec->hit_hint = 0; -#endif - - if (RE_rayobject_intersect(r, isec)) { - RE_RC_COUNT(isec->raycounter->raycast.hit); - -#ifdef RT_USE_HINT - isec->hint = isec->hit_hint; -#endif - return 1; - } - - return 0; -} - -int RE_rayobject_intersect(RayObject *r, Isect *i) -{ - if (RE_rayobject_isRayFace(r)) { - return intersect_rayface(r, (RayFace *) RE_rayobject_align(r), i); - } - else if (RE_rayobject_isVlakPrimitive(r)) { - //TODO optimize (useless copy to RayFace to avoid duplicate code) - VlakPrimitive *face = (VlakPrimitive *) RE_rayobject_align(r); - RayFace nface; - rayface_from_vlak(&nface, face->ob, face->face); - - return intersect_rayface(r, &nface, i); - } - else if (RE_rayobject_isRayAPI(r)) { - r = RE_rayobject_align(r); - return r->api->raycast(r, i); - } - else { - assert(0); - return 0; - } -} - -/* Building */ - -void RE_rayobject_add(RayObject *r, RayObject *o) -{ - r = RE_rayobject_align(r); - return r->api->add(r, o); -} - -void RE_rayobject_done(RayObject *r) -{ - r = RE_rayobject_align(r); - r->api->done(r); -} - -void RE_rayobject_free(RayObject *r) -{ - r = RE_rayobject_align(r); - r->api->free(r); -} - -float RE_rayobject_cost(RayObject *r) -{ - if (RE_rayobject_isRayFace(r) || RE_rayobject_isVlakPrimitive(r)) { - return 1.0f; - } - else if (RE_rayobject_isRayAPI(r)) { - r = RE_rayobject_align(r); - return r->api->cost(r); - } - else { - assert(0); - return 1.0f; - } -} - -/* Bounding Boxes */ - -void RE_rayobject_merge_bb(RayObject *r, float min[3], float max[3]) -{ - if (RE_rayobject_isRayFace(r)) { - RayFace *face = (RayFace *) RE_rayobject_align(r); - - DO_MINMAX(face->v1, min, max); - DO_MINMAX(face->v2, min, max); - DO_MINMAX(face->v3, min, max); - if (RE_rayface_isQuad(face)) DO_MINMAX(face->v4, min, max); - } - else if (RE_rayobject_isVlakPrimitive(r)) { - VlakPrimitive *face = (VlakPrimitive *) RE_rayobject_align(r); - RayFace nface; - rayface_from_vlak(&nface, face->ob, face->face); - - DO_MINMAX(nface.v1, min, max); - DO_MINMAX(nface.v2, min, max); - DO_MINMAX(nface.v3, min, max); - if (RE_rayface_isQuad(&nface)) DO_MINMAX(nface.v4, min, max); - } - else if (RE_rayobject_isRayAPI(r)) { - r = RE_rayobject_align(r); - r->api->bb(r, min, max); - } - else - assert(0); -} - -/* Hints */ - -void RE_rayobject_hint_bb(RayObject *r, RayHint *hint, float *min, float *max) -{ - if (RE_rayobject_isRayFace(r) || RE_rayobject_isVlakPrimitive(r)) { - return; - } - else if (RE_rayobject_isRayAPI(r)) { - r = RE_rayobject_align(r); - return r->api->hint_bb(r, hint, min, max); - } - else - assert(0); -} - -/* RayObjectControl */ - -int RE_rayobjectcontrol_test_break(RayObjectControl *control) -{ - if (control->test_break) - return control->test_break(control->data); - - return 0; -} - -void RE_rayobject_set_control(RayObject *r, void *data, RE_rayobjectcontrol_test_break_callback test_break) -{ - if (RE_rayobject_isRayAPI(r)) { - r = RE_rayobject_align(r); - r->control.data = data; - r->control.test_break = test_break; - } -} - diff --git a/source/blender/render/intern/raytrace/rayobject_hint.h b/source/blender/render/intern/raytrace/rayobject_hint.h deleted file mode 100644 index 88a32819bd2..00000000000 --- a/source/blender/render/intern/raytrace/rayobject_hint.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2009 Blender Foundation. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): André Pinto. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/render/intern/raytrace/rayobject_hint.h - * \ingroup render - */ - - -#ifndef __RAYOBJECT_HINT_H__ -#define __RAYOBJECT_HINT_H__ - -#define HINT_RECURSE 1 -#define HINT_ACCEPT 0 -#define HINT_DISCARD -1 - -struct HintBB { - float bb[6]; -}; - -inline int hint_test_bb(HintBB *obj, float *Nmin, float *Nmax) -{ - if (bb_fits_inside(Nmin, Nmax, obj->bb, obj->bb + 3) ) - return HINT_RECURSE; - else - return HINT_ACCEPT; -} -#if 0 -struct HintFrustum { - float co[3]; - float no[4][3]; -}; - -inline int hint_test_bb(HintFrustum &obj, float *Nmin, float *Nmax) -{ - //if frustum inside BB - { - return HINT_RECURSE; - } - //if BB outside frustum - { - return HINT_DISCARD; - } - - return HINT_ACCEPT; -} -#endif - -#endif /* __RAYOBJECT_HINT_H__ */ diff --git a/source/blender/render/intern/raytrace/rayobject_instance.cpp b/source/blender/render/intern/raytrace/rayobject_instance.cpp deleted file mode 100644 index 361e7963d96..00000000000 --- a/source/blender/render/intern/raytrace/rayobject_instance.cpp +++ /dev/null @@ -1,211 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2009 Blender Foundation. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): André Pinto. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/render/intern/raytrace/rayobject_instance.cpp - * \ingroup render - */ - - -#include <assert.h> - -#include "MEM_guardedalloc.h" - -#include "BLI_math.h" -#include "BLI_utildefines.h" - -#include "rayintersection.h" -#include "rayobject.h" - -#define RE_COST_INSTANCE (1.0f) - -static int RE_rayobject_instance_intersect(RayObject *o, Isect *isec); -static void RE_rayobject_instance_free(RayObject *o); -static void RE_rayobject_instance_bb(RayObject *o, float *min, float *max); -static float RE_rayobject_instance_cost(RayObject *o); - -static void RE_rayobject_instance_hint_bb(RayObject *UNUSED(o), RayHint *UNUSED(hint), - float *UNUSED(min), float *UNUSED(max)) -{} - -static RayObjectAPI instance_api = -{ - RE_rayobject_instance_intersect, - NULL, //static void RE_rayobject_instance_add(RayObject *o, RayObject *ob); - NULL, //static void RE_rayobject_instance_done(RayObject *o); - RE_rayobject_instance_free, - RE_rayobject_instance_bb, - RE_rayobject_instance_cost, - RE_rayobject_instance_hint_bb -}; - -typedef struct InstanceRayObject { - RayObject rayobj; - RayObject *target; - - void *ob; //Object represented by this instance - void *target_ob; //Object represented by the inner RayObject, needed to handle self-intersection - - float global2target[4][4]; - float target2global[4][4]; - -} InstanceRayObject; - - -RayObject *RE_rayobject_instance_create(RayObject *target, float transform[4][4], void *ob, void *target_ob) -{ - InstanceRayObject *obj = (InstanceRayObject *)MEM_callocN(sizeof(InstanceRayObject), "InstanceRayObject"); - assert(RE_rayobject_isAligned(obj) ); /* RayObject API assumes real data to be 4-byte aligned */ - - obj->rayobj.api = &instance_api; - obj->target = target; - obj->ob = ob; - obj->target_ob = target_ob; - - copy_m4_m4(obj->target2global, transform); - invert_m4_m4(obj->global2target, obj->target2global); - - return RE_rayobject_unalignRayAPI((RayObject *) obj); -} - -static int RE_rayobject_instance_intersect(RayObject *o, Isect *isec) -{ - InstanceRayObject *obj = (InstanceRayObject *)o; - float start[3], dir[3], idot_axis[3], dist; - int changed = 0, i, res; - - // TODO - this is disabling self intersection on instances - if (isec->orig.ob == obj->ob && obj->ob) { - changed = 1; - isec->orig.ob = obj->target_ob; - } - - // backup old values - copy_v3_v3(start, isec->start); - copy_v3_v3(dir, isec->dir); - copy_v3_v3(idot_axis, isec->idot_axis); - dist = isec->dist; - - // transform to target coordinates system - mul_m4_v3(obj->global2target, isec->start); - mul_mat3_m4_v3(obj->global2target, isec->dir); - isec->dist *= normalize_v3(isec->dir); - - // update idot_axis and bv_index - for (i = 0; i < 3; i++) { - isec->idot_axis[i] = 1.0f / isec->dir[i]; - - isec->bv_index[2 * i] = isec->idot_axis[i] < 0.0f ? 1 : 0; - isec->bv_index[2 * i + 1] = 1 - isec->bv_index[2 * i]; - - isec->bv_index[2 * i] = i + 3 * isec->bv_index[2 * i]; - isec->bv_index[2 * i + 1] = i + 3 * isec->bv_index[2 * i + 1]; - } - - // Pre-calculate orientation for watertight intersection checks. - isect_ray_tri_watertight_v3_precalc(&isec->isect_precalc, isec->dir); - - // raycast - res = RE_rayobject_intersect(obj->target, isec); - - // map dist into original coordinate space - if (res == 0) { - isec->dist = dist; - } - else { - // note we don't just multiply dist, because of possible - // non-uniform scaling in the transform matrix - float vec[3]; - - mul_v3_v3fl(vec, isec->dir, isec->dist); - mul_mat3_m4_v3(obj->target2global, vec); - - isec->dist = len_v3(vec); - isec->hit.ob = obj->ob; - -#ifdef RT_USE_LAST_HIT - // TODO support for last hit optimization in instances that can jump - // directly to the last hit face. - // For now it jumps directly to the last-hit instance root node. - isec->last_hit = RE_rayobject_unalignRayAPI((RayObject *) obj); -#endif - } - - // restore values - copy_v3_v3(isec->start, start); - copy_v3_v3(isec->dir, dir); - copy_v3_v3(isec->idot_axis, idot_axis); - - if (changed) - isec->orig.ob = obj->ob; - - // restore bv_index - for (i = 0; i < 3; i++) { - isec->bv_index[2 * i] = isec->idot_axis[i] < 0.0f ? 1 : 0; - isec->bv_index[2 * i + 1] = 1 - isec->bv_index[2 * i]; - - isec->bv_index[2 * i] = i + 3 * isec->bv_index[2 * i]; - isec->bv_index[2 * i + 1] = i + 3 * isec->bv_index[2 * i + 1]; - } - - // Pre-calculate orientation for watertight intersection checks. - isect_ray_tri_watertight_v3_precalc(&isec->isect_precalc, isec->dir); - - return res; -} - -static void RE_rayobject_instance_free(RayObject *o) -{ - InstanceRayObject *obj = (InstanceRayObject *)o; - MEM_freeN(obj); -} - -static float RE_rayobject_instance_cost(RayObject *o) -{ - InstanceRayObject *obj = (InstanceRayObject *)o; - return RE_rayobject_cost(obj->target) + RE_COST_INSTANCE; -} - -static void RE_rayobject_instance_bb(RayObject *o, float *min, float *max) -{ - //TODO: - // *better bb.. calculated without rotations of bb - // *maybe cache that better-fitted-BB at the InstanceRayObject - InstanceRayObject *obj = (InstanceRayObject *)o; - - float m[3], M[3], t[3]; - int i, j; - INIT_MINMAX(m, M); - RE_rayobject_merge_bb(obj->target, m, M); - - //There must be a faster way than rotating all the 8 vertexs of the BB - for (i = 0; i < 8; i++) { - for (j = 0; j < 3; j++) t[j] = (i & (1 << j)) ? M[j] : m[j]; - mul_m4_v3(obj->target2global, t); - DO_MINMAX(t, min, max); - } -} - diff --git a/source/blender/render/intern/raytrace/rayobject_octree.cpp b/source/blender/render/intern/raytrace/rayobject_octree.cpp deleted file mode 100644 index 4b73e64ca45..00000000000 --- a/source/blender/render/intern/raytrace/rayobject_octree.cpp +++ /dev/null @@ -1,1101 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 1990-1998 NeoGeo BV. - * All rights reserved. - * - * Contributors: 2004/2005 Blender Foundation, full recode - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/render/intern/raytrace/rayobject_octree.cpp - * \ingroup render - */ - - -/* IMPORTANT NOTE: this code must be independent of any other render code - * to use it outside the renderer! */ - -#include <math.h> -#include <string.h> -#include <stdlib.h> -#include <float.h> -#include <assert.h> - -#include "MEM_guardedalloc.h" - -#include "DNA_material_types.h" - -#include "BLI_math.h" -#include "BLI_utildefines.h" - -#include "rayintersection.h" -#include "rayobject.h" - -/* ********** structs *************** */ -#define BRANCH_ARRAY 1024 -#define NODE_ARRAY 4096 - -typedef struct Branch { - struct Branch *b[8]; -} Branch; - -typedef struct OcVal { - short ocx, ocy, ocz; -} OcVal; - -typedef struct Node { - struct RayFace *v[8]; - struct OcVal ov[8]; - struct Node *next; -} Node; - -typedef struct Octree { - RayObject rayobj; - - struct Branch **adrbranch; - struct Node **adrnode; - float ocsize; /* ocsize: mult factor, max size octree */ - float ocfacx, ocfacy, ocfacz; - float min[3], max[3]; - int ocres; - int branchcount, nodecount; - - /* during building only */ - char *ocface; - - RayFace **ro_nodes; - int ro_nodes_size, ro_nodes_used; - -} Octree; - -static int RE_rayobject_octree_intersect(RayObject *o, Isect *isec); -static void RE_rayobject_octree_add(RayObject *o, RayObject *ob); -static void RE_rayobject_octree_done(RayObject *o); -static void RE_rayobject_octree_free(RayObject *o); -static void RE_rayobject_octree_bb(RayObject *o, float *min, float *max); - -/* - * This function is not expected to be called by current code state. - */ -static float RE_rayobject_octree_cost(RayObject *UNUSED(o)) -{ - return 1.0; -} - -static void RE_rayobject_octree_hint_bb(RayObject *UNUSED(o), RayHint *UNUSED(hint), - float *UNUSED(min), float *UNUSED(max)) -{ - return; -} - -static RayObjectAPI octree_api = -{ - RE_rayobject_octree_intersect, - RE_rayobject_octree_add, - RE_rayobject_octree_done, - RE_rayobject_octree_free, - RE_rayobject_octree_bb, - RE_rayobject_octree_cost, - RE_rayobject_octree_hint_bb -}; - -/* **************** ocval method ******************* */ -/* within one octree node, a set of 3x15 bits defines a 'boundbox' to OR with */ - -#define OCVALRES 15 -#define BROW16(min, max) \ - (((max) >= OCVALRES ? 0xFFFF : (1 << ((max) + 1)) - 1) - (((min) > 0) ? ((1 << (min)) - 1) : 0)) - -static void calc_ocval_face(float *v1, float *v2, float *v3, float *v4, short x, short y, short z, OcVal *ov) -{ - float min[3], max[3]; - int ocmin, ocmax; - - copy_v3_v3(min, v1); - copy_v3_v3(max, v1); - DO_MINMAX(v2, min, max); - DO_MINMAX(v3, min, max); - if (v4) { - DO_MINMAX(v4, min, max); - } - - ocmin = OCVALRES * (min[0] - x); - ocmax = OCVALRES * (max[0] - x); - ov->ocx = BROW16(ocmin, ocmax); - - ocmin = OCVALRES * (min[1] - y); - ocmax = OCVALRES * (max[1] - y); - ov->ocy = BROW16(ocmin, ocmax); - - ocmin = OCVALRES * (min[2] - z); - ocmax = OCVALRES * (max[2] - z); - ov->ocz = BROW16(ocmin, ocmax); - -} - -static void calc_ocval_ray(OcVal *ov, float xo, float yo, float zo, float *vec1, float *vec2) -{ - int ocmin, ocmax; - - if (vec1[0] < vec2[0]) { - ocmin = OCVALRES * (vec1[0] - xo); - ocmax = OCVALRES * (vec2[0] - xo); - } - else { - ocmin = OCVALRES * (vec2[0] - xo); - ocmax = OCVALRES * (vec1[0] - xo); - } - ov->ocx = BROW16(ocmin, ocmax); - - if (vec1[1] < vec2[1]) { - ocmin = OCVALRES * (vec1[1] - yo); - ocmax = OCVALRES * (vec2[1] - yo); - } - else { - ocmin = OCVALRES * (vec2[1] - yo); - ocmax = OCVALRES * (vec1[1] - yo); - } - ov->ocy = BROW16(ocmin, ocmax); - - if (vec1[2] < vec2[2]) { - ocmin = OCVALRES * (vec1[2] - zo); - ocmax = OCVALRES * (vec2[2] - zo); - } - else { - ocmin = OCVALRES * (vec2[2] - zo); - ocmax = OCVALRES * (vec1[2] - zo); - } - ov->ocz = BROW16(ocmin, ocmax); -} - -/* ************* octree ************** */ - -static Branch *addbranch(Octree *oc, Branch *br, short ocb) -{ - int index; - - if (br->b[ocb]) return br->b[ocb]; - - oc->branchcount++; - index = oc->branchcount >> 12; - - if (oc->adrbranch[index] == NULL) - oc->adrbranch[index] = (Branch *)MEM_callocN(4096 * sizeof(Branch), "new oc branch"); - - if (oc->branchcount >= BRANCH_ARRAY * 4096) { - printf("error; octree branches full\n"); - oc->branchcount = 0; - } - - return br->b[ocb] = oc->adrbranch[index] + (oc->branchcount & 4095); -} - -static Node *addnode(Octree *oc) -{ - int index; - - oc->nodecount++; - index = oc->nodecount >> 12; - - if (oc->adrnode[index] == NULL) - oc->adrnode[index] = (Node *)MEM_callocN(4096 * sizeof(Node), "addnode"); - - if (oc->nodecount > NODE_ARRAY * NODE_ARRAY) { - printf("error; octree nodes full\n"); - oc->nodecount = 0; - } - - return oc->adrnode[index] + (oc->nodecount & 4095); -} - -static bool face_in_node(RayFace *face, short x, short y, short z, float rtf[4][3]) -{ - static float nor[3], d; - float fx, fy, fz; - - // init static vars - if (face) { - normal_tri_v3(nor, rtf[0], rtf[1], rtf[2]); - d = -nor[0] * rtf[0][0] - nor[1] * rtf[0][1] - nor[2] * rtf[0][2]; - return 0; - } - - fx = x; - fy = y; - fz = z; - - if ((fx) * nor[0] + (fy) * nor[1] + (fz) * nor[2] + d > 0.0f) { - if ((fx + 1) * nor[0] + (fy ) * nor[1] + (fz ) * nor[2] + d < 0.0f) return 1; - if ((fx ) * nor[0] + (fy + 1) * nor[1] + (fz ) * nor[2] + d < 0.0f) return 1; - if ((fx + 1) * nor[0] + (fy + 1) * nor[1] + (fz ) * nor[2] + d < 0.0f) return 1; - - if ((fx ) * nor[0] + (fy ) * nor[1] + (fz + 1) * nor[2] + d < 0.0f) return 1; - if ((fx + 1) * nor[0] + (fy ) * nor[1] + (fz + 1) * nor[2] + d < 0.0f) return 1; - if ((fx ) * nor[0] + (fy + 1) * nor[1] + (fz + 1) * nor[2] + d < 0.0f) return 1; - if ((fx + 1) * nor[0] + (fy + 1) * nor[1] + (fz + 1) * nor[2] + d < 0.0f) return 1; - } - else { - if ((fx + 1) * nor[0] + (fy ) * nor[1] + (fz ) * nor[2] + d > 0.0f) return 1; - if ((fx ) * nor[0] + (fy + 1) * nor[1] + (fz ) * nor[2] + d > 0.0f) return 1; - if ((fx + 1) * nor[0] + (fy + 1) * nor[1] + (fz ) * nor[2] + d > 0.0f) return 1; - - if ((fx ) * nor[0] + (fy ) * nor[1] + (fz + 1) * nor[2] + d > 0.0f) return 1; - if ((fx + 1) * nor[0] + (fy ) * nor[1] + (fz + 1) * nor[2] + d > 0.0f) return 1; - if ((fx ) * nor[0] + (fy + 1) * nor[1] + (fz + 1) * nor[2] + d > 0.0f) return 1; - if ((fx + 1) * nor[0] + (fy + 1) * nor[1] + (fz + 1) * nor[2] + d > 0.0f) return 1; - } - - return 0; -} - -static void ocwrite(Octree *oc, RayFace *face, int quad, short x, short y, short z, float rtf[4][3]) -{ - Branch *br; - Node *no; - short a, oc0, oc1, oc2, oc3, oc4, oc5; - - x <<= 2; - y <<= 1; - - br = oc->adrbranch[0]; - - if (oc->ocres == 512) { - oc0 = ((x & 1024) + (y & 512) + (z & 256)) >> 8; - br = addbranch(oc, br, oc0); - } - if (oc->ocres >= 256) { - oc0 = ((x & 512) + (y & 256) + (z & 128)) >> 7; - br = addbranch(oc, br, oc0); - } - if (oc->ocres >= 128) { - oc0 = ((x & 256) + (y & 128) + (z & 64)) >> 6; - br = addbranch(oc, br, oc0); - } - - oc0 = ((x & 128) + (y & 64) + (z & 32)) >> 5; - oc1 = ((x & 64) + (y & 32) + (z & 16)) >> 4; - oc2 = ((x & 32) + (y & 16) + (z & 8)) >> 3; - oc3 = ((x & 16) + (y & 8) + (z & 4)) >> 2; - oc4 = ((x & 8) + (y & 4) + (z & 2)) >> 1; - oc5 = ((x & 4) + (y & 2) + (z & 1)); - - br = addbranch(oc, br, oc0); - br = addbranch(oc, br, oc1); - br = addbranch(oc, br, oc2); - br = addbranch(oc, br, oc3); - br = addbranch(oc, br, oc4); - no = (Node *)br->b[oc5]; - if (no == NULL) br->b[oc5] = (Branch *)(no = addnode(oc)); - - while (no->next) no = no->next; - - a = 0; - if (no->v[7]) { /* node full */ - no->next = addnode(oc); - no = no->next; - } - else { - while (no->v[a] != NULL) a++; - } - - no->v[a] = (RayFace *) RE_rayobject_align(face); - - if (quad) - calc_ocval_face(rtf[0], rtf[1], rtf[2], rtf[3], x >> 2, y >> 1, z, &no->ov[a]); - else - calc_ocval_face(rtf[0], rtf[1], rtf[2], NULL, x >> 2, y >> 1, z, &no->ov[a]); -} - -static void d2dda(Octree *oc, short b1, short b2, short c1, short c2, char *ocface, short rts[4][3], float rtf[4][3]) -{ - int ocx1, ocx2, ocy1, ocy2; - int x, y, dx = 0, dy = 0; - float ox1, ox2, oy1, oy2; - float lambda, lambda_o, lambda_x, lambda_y, ldx, ldy; - - ocx1 = rts[b1][c1]; - ocy1 = rts[b1][c2]; - ocx2 = rts[b2][c1]; - ocy2 = rts[b2][c2]; - - if (ocx1 == ocx2 && ocy1 == ocy2) { - ocface[oc->ocres * ocx1 + ocy1] = 1; - return; - } - - ox1 = rtf[b1][c1]; - oy1 = rtf[b1][c2]; - ox2 = rtf[b2][c1]; - oy2 = rtf[b2][c2]; - - if (ox1 != ox2) { - if (ox2 - ox1 > 0.0f) { - lambda_x = (ox1 - ocx1 - 1.0f) / (ox1 - ox2); - ldx = -1.0f / (ox1 - ox2); - dx = 1; - } - else { - lambda_x = (ox1 - ocx1) / (ox1 - ox2); - ldx = 1.0f / (ox1 - ox2); - dx = -1; - } - } - else { - lambda_x = 1.0f; - ldx = 0; - } - - if (oy1 != oy2) { - if (oy2 - oy1 > 0.0f) { - lambda_y = (oy1 - ocy1 - 1.0f) / (oy1 - oy2); - ldy = -1.0f / (oy1 - oy2); - dy = 1; - } - else { - lambda_y = (oy1 - ocy1) / (oy1 - oy2); - ldy = 1.0f / (oy1 - oy2); - dy = -1; - } - } - else { - lambda_y = 1.0f; - ldy = 0; - } - - x = ocx1; y = ocy1; - lambda = MIN2(lambda_x, lambda_y); - - while (true) { - - if (x < 0 || y < 0 || x >= oc->ocres || y >= oc->ocres) { - /* pass*/ - } - else { - ocface[oc->ocres * x + y] = 1; - } - - lambda_o = lambda; - if (lambda_x == lambda_y) { - lambda_x += ldx; - x += dx; - lambda_y += ldy; - y += dy; - } - else { - if (lambda_x < lambda_y) { - lambda_x += ldx; - x += dx; - } - else { - lambda_y += ldy; - y += dy; - } - } - lambda = MIN2(lambda_x, lambda_y); - if (lambda == lambda_o) break; - if (lambda >= 1.0f) break; - } - ocface[oc->ocres * ocx2 + ocy2] = 1; -} - -static void filltriangle(Octree *oc, short c1, short c2, char *ocface, short *ocmin, short *ocmax) -{ - int a, x, y, y1, y2; - - for (x = ocmin[c1]; x <= ocmax[c1]; x++) { - a = oc->ocres * x; - for (y = ocmin[c2]; y <= ocmax[c2]; y++) { - if (ocface[a + y]) { - y++; - while (ocface[a + y] && y != ocmax[c2]) y++; - for (y1 = ocmax[c2]; y1 > y; y1--) { - if (ocface[a + y1]) { - for (y2 = y; y2 <= y1; y2++) ocface[a + y2] = 1; - y1 = 0; - } - } - y = ocmax[c2]; - } - } - } -} - -static void RE_rayobject_octree_free(RayObject *tree) -{ - Octree *oc = (Octree *)tree; - -#if 0 - printf("branches %d nodes %d\n", oc->branchcount, oc->nodecount); - printf("raycount %d\n", raycount); - printf("ray coherent %d\n", coherent_ray); - printf("accepted %d rejected %d\n", accepted, rejected); -#endif - if (oc->ocface) - MEM_freeN(oc->ocface); - - if (oc->adrbranch) { - int a = 0; - while (oc->adrbranch[a]) { - MEM_freeN(oc->adrbranch[a]); - oc->adrbranch[a] = NULL; - a++; - } - MEM_freeN(oc->adrbranch); - oc->adrbranch = NULL; - } - oc->branchcount = 0; - - if (oc->adrnode) { - int a = 0; - while (oc->adrnode[a]) { - MEM_freeN(oc->adrnode[a]); - oc->adrnode[a] = NULL; - a++; - } - MEM_freeN(oc->adrnode); - oc->adrnode = NULL; - } - oc->nodecount = 0; - - MEM_freeN(oc); -} - - -RayObject *RE_rayobject_octree_create(int ocres, int size) -{ - Octree *oc = (Octree *)MEM_callocN(sizeof(Octree), "Octree"); - assert(RE_rayobject_isAligned(oc) ); /* RayObject API assumes real data to be 4-byte aligned */ - - oc->rayobj.api = &octree_api; - - oc->ocres = ocres; - - oc->ro_nodes = (RayFace **)MEM_callocN(sizeof(RayFace *) * size, "octree rayobject nodes"); - oc->ro_nodes_size = size; - oc->ro_nodes_used = 0; - - - return RE_rayobject_unalignRayAPI((RayObject *) oc); -} - - -static void RE_rayobject_octree_add(RayObject *tree, RayObject *node) -{ - Octree *oc = (Octree *)tree; - - assert(RE_rayobject_isRayFace(node) ); - assert(oc->ro_nodes_used < oc->ro_nodes_size); - oc->ro_nodes[oc->ro_nodes_used++] = (RayFace *)RE_rayobject_align(node); -} - -static void octree_fill_rayface(Octree *oc, RayFace *face) -{ - float ocfac[3], rtf[4][3]; - float co1[3], co2[3], co3[3], co4[3]; - short rts[4][3]; - short ocmin[3], ocmax[3]; - char *ocface = oc->ocface; // front, top, size view of face, to fill in - int a, b, c, oc1, oc2, oc3, oc4, x, y, z, ocres2; - - ocfac[0] = oc->ocfacx; - ocfac[1] = oc->ocfacy; - ocfac[2] = oc->ocfacz; - - ocres2 = oc->ocres * oc->ocres; - - copy_v3_v3(co1, face->v1); - copy_v3_v3(co2, face->v2); - copy_v3_v3(co3, face->v3); - if (RE_rayface_isQuad(face)) - copy_v3_v3(co4, face->v4); - - for (c = 0; c < 3; c++) { - rtf[0][c] = (co1[c] - oc->min[c]) * ocfac[c]; - rts[0][c] = (short)rtf[0][c]; - rtf[1][c] = (co2[c] - oc->min[c]) * ocfac[c]; - rts[1][c] = (short)rtf[1][c]; - rtf[2][c] = (co3[c] - oc->min[c]) * ocfac[c]; - rts[2][c] = (short)rtf[2][c]; - if (RE_rayface_isQuad(face)) { - rtf[3][c] = (co4[c] - oc->min[c]) * ocfac[c]; - rts[3][c] = (short)rtf[3][c]; - } - } - - for (c = 0; c < 3; c++) { - oc1 = rts[0][c]; - oc2 = rts[1][c]; - oc3 = rts[2][c]; - if (!RE_rayface_isQuad(face)) { - ocmin[c] = min_iii(oc1, oc2, oc3); - ocmax[c] = max_iii(oc1, oc2, oc3); - } - else { - oc4 = rts[3][c]; - ocmin[c] = min_iiii(oc1, oc2, oc3, oc4); - ocmax[c] = max_iiii(oc1, oc2, oc3, oc4); - } - if (ocmax[c] > oc->ocres - 1) ocmax[c] = oc->ocres - 1; - if (ocmin[c] < 0) ocmin[c] = 0; - } - - if (ocmin[0] == ocmax[0] && ocmin[1] == ocmax[1] && ocmin[2] == ocmax[2]) { - ocwrite(oc, face, RE_rayface_isQuad(face), ocmin[0], ocmin[1], ocmin[2], rtf); - } - else { - - d2dda(oc, 0, 1, 0, 1, ocface + ocres2, rts, rtf); - d2dda(oc, 0, 1, 0, 2, ocface, rts, rtf); - d2dda(oc, 0, 1, 1, 2, ocface + 2 * ocres2, rts, rtf); - d2dda(oc, 1, 2, 0, 1, ocface + ocres2, rts, rtf); - d2dda(oc, 1, 2, 0, 2, ocface, rts, rtf); - d2dda(oc, 1, 2, 1, 2, ocface + 2 * ocres2, rts, rtf); - if (!RE_rayface_isQuad(face)) { - d2dda(oc, 2, 0, 0, 1, ocface + ocres2, rts, rtf); - d2dda(oc, 2, 0, 0, 2, ocface, rts, rtf); - d2dda(oc, 2, 0, 1, 2, ocface + 2 * ocres2, rts, rtf); - } - else { - d2dda(oc, 2, 3, 0, 1, ocface + ocres2, rts, rtf); - d2dda(oc, 2, 3, 0, 2, ocface, rts, rtf); - d2dda(oc, 2, 3, 1, 2, ocface + 2 * ocres2, rts, rtf); - d2dda(oc, 3, 0, 0, 1, ocface + ocres2, rts, rtf); - d2dda(oc, 3, 0, 0, 2, ocface, rts, rtf); - d2dda(oc, 3, 0, 1, 2, ocface + 2 * ocres2, rts, rtf); - } - /* nothing todo with triangle..., just fills :) */ - filltriangle(oc, 0, 1, ocface + ocres2, ocmin, ocmax); - filltriangle(oc, 0, 2, ocface, ocmin, ocmax); - filltriangle(oc, 1, 2, ocface + 2 * ocres2, ocmin, ocmax); - - /* init static vars here */ - face_in_node(face, 0, 0, 0, rtf); - - for (x = ocmin[0]; x <= ocmax[0]; x++) { - a = oc->ocres * x; - for (y = ocmin[1]; y <= ocmax[1]; y++) { - if (ocface[a + y + ocres2]) { - b = oc->ocres * y + 2 * ocres2; - for (z = ocmin[2]; z <= ocmax[2]; z++) { - if (ocface[b + z] && ocface[a + z]) { - if (face_in_node(NULL, x, y, z, rtf)) - ocwrite(oc, face, RE_rayface_isQuad(face), x, y, z, rtf); - } - } - } - } - } - - /* same loops to clear octree, doubt it can be done smarter */ - for (x = ocmin[0]; x <= ocmax[0]; x++) { - a = oc->ocres * x; - for (y = ocmin[1]; y <= ocmax[1]; y++) { - /* x-y */ - ocface[a + y + ocres2] = 0; - - b = oc->ocres * y + 2 * ocres2; - for (z = ocmin[2]; z <= ocmax[2]; z++) { - /* y-z */ - ocface[b + z] = 0; - /* x-z */ - ocface[a + z] = 0; - } - } - } - } -} - -static void RE_rayobject_octree_done(RayObject *tree) -{ - Octree *oc = (Octree *)tree; - int c; - float t00, t01, t02; - int ocres2 = oc->ocres * oc->ocres; - - INIT_MINMAX(oc->min, oc->max); - - /* Calculate Bounding Box */ - for (c = 0; c < oc->ro_nodes_used; c++) - RE_rayobject_merge_bb(RE_rayobject_unalignRayFace(oc->ro_nodes[c]), oc->min, oc->max); - - /* Alloc memory */ - oc->adrbranch = (Branch **)MEM_callocN(sizeof(void *) * BRANCH_ARRAY, "octree branches"); - oc->adrnode = (Node **)MEM_callocN(sizeof(void *) * NODE_ARRAY, "octree nodes"); - - oc->adrbranch[0] = (Branch *)MEM_callocN(4096 * sizeof(Branch), "makeoctree"); - - /* the lookup table, per face, for which nodes to fill in */ - oc->ocface = (char *)MEM_callocN(3 * ocres2 + 8, "ocface"); - memset(oc->ocface, 0, 3 * ocres2); - - for (c = 0; c < 3; c++) { /* octree enlarge, still needed? */ - oc->min[c] -= 0.01f; - oc->max[c] += 0.01f; - } - - t00 = oc->max[0] - oc->min[0]; - t01 = oc->max[1] - oc->min[1]; - t02 = oc->max[2] - oc->min[2]; - - /* this minus 0.1 is old safety... seems to be needed? */ - oc->ocfacx = (oc->ocres - 0.1f) / t00; - oc->ocfacy = (oc->ocres - 0.1f) / t01; - oc->ocfacz = (oc->ocres - 0.1f) / t02; - - oc->ocsize = sqrtf(t00 * t00 + t01 * t01 + t02 * t02); /* global, max size octree */ - - for (c = 0; c < oc->ro_nodes_used; c++) { - octree_fill_rayface(oc, oc->ro_nodes[c]); - } - - MEM_freeN(oc->ocface); - oc->ocface = NULL; - MEM_freeN(oc->ro_nodes); - oc->ro_nodes = NULL; - -#if 0 - printf("%f %f - %f\n", oc->min[0], oc->max[0], oc->ocfacx); - printf("%f %f - %f\n", oc->min[1], oc->max[1], oc->ocfacy); - printf("%f %f - %f\n", oc->min[2], oc->max[2], oc->ocfacz); -#endif -} - -static void RE_rayobject_octree_bb(RayObject *tree, float *min, float *max) -{ - Octree *oc = (Octree *)tree; - DO_MINMAX(oc->min, min, max); - DO_MINMAX(oc->max, min, max); -} - -/* check all faces in this node */ -static int testnode(Octree *UNUSED(oc), Isect *is, Node *no, OcVal ocval) -{ - short nr = 0; - - /* return on any first hit */ - if (is->mode == RE_RAY_SHADOW) { - - for (; no; no = no->next) { - for (nr = 0; nr < 8; nr++) { - RayFace *face = no->v[nr]; - OcVal *ov = no->ov + nr; - - if (!face) break; - - if ( (ov->ocx & ocval.ocx) && (ov->ocy & ocval.ocy) && (ov->ocz & ocval.ocz) ) { - if (RE_rayobject_intersect(RE_rayobject_unalignRayFace(face), is) ) - return 1; - } - } - } - } - else { - /* else mirror or glass or shadowtra, return closest face */ - int found = 0; - - for (; no; no = no->next) { - for (nr = 0; nr < 8; nr++) { - RayFace *face = no->v[nr]; - OcVal *ov = no->ov + nr; - - if (!face) break; - - if ( (ov->ocx & ocval.ocx) && (ov->ocy & ocval.ocy) && (ov->ocz & ocval.ocz) ) { - if (RE_rayobject_intersect(RE_rayobject_unalignRayFace(face), is) ) { - found = 1; - } - } - } - } - - return found; - } - - return 0; -} - -/* find the Node for the octree coord x y z */ -static Node *ocread(Octree *oc, int x, int y, int z) -{ - Branch *br; - int oc1; - - x <<= 2; - y <<= 1; - - br = oc->adrbranch[0]; - - if (oc->ocres == 512) { - oc1 = ((x & 1024) + (y & 512) + (z & 256)) >> 8; - br = br->b[oc1]; - if (br == NULL) { - return NULL; - } - } - if (oc->ocres >= 256) { - oc1 = ((x & 512) + (y & 256) + (z & 128)) >> 7; - br = br->b[oc1]; - if (br == NULL) { - return NULL; - } - } - if (oc->ocres >= 128) { - oc1 = ((x & 256) + (y & 128) + (z & 64)) >> 6; - br = br->b[oc1]; - if (br == NULL) { - return NULL; - } - } - - oc1 = ((x & 128) + (y & 64) + (z & 32)) >> 5; - br = br->b[oc1]; - if (br) { - oc1 = ((x & 64) + (y & 32) + (z & 16)) >> 4; - br = br->b[oc1]; - if (br) { - oc1 = ((x & 32) + (y & 16) + (z & 8)) >> 3; - br = br->b[oc1]; - if (br) { - oc1 = ((x & 16) + (y & 8) + (z & 4)) >> 2; - br = br->b[oc1]; - if (br) { - oc1 = ((x & 8) + (y & 4) + (z & 2)) >> 1; - br = br->b[oc1]; - if (br) { - oc1 = ((x & 4) + (y & 2) + (z & 1)); - return (Node *)br->b[oc1]; - } - } - } - } - } - - return NULL; -} - -static int cliptest(float p, float q, float *u1, float *u2) -{ - float r; - - if (p < 0.0f) { - if (q < p) return 0; - else if (q < 0.0f) { - r = q / p; - if (r > *u2) return 0; - else if (r > *u1) *u1 = r; - } - } - else { - if (p > 0.0f) { - if (q < 0.0f) return 0; - else if (q < p) { - r = q / p; - if (r < *u1) return 0; - else if (r < *u2) *u2 = r; - } - } - else if (q < 0.0f) return 0; - } - return 1; -} - -/* extensive coherence checks/storage cancels out the benefit of it, and gives errors... we - * need better methods, sample code commented out below (ton) */ - -#if 0 - -in top : static int coh_nodes[16 * 16 * 16][6]; -in makeoctree : memset(coh_nodes, 0, sizeof(coh_nodes)); - -static void add_coherence_test(int ocx1, int ocx2, int ocy1, int ocy2, int ocz1, int ocz2) -{ - short *sp; - - sp = coh_nodes[(ocx2 & 15) + 16 * (ocy2 & 15) + 256 * (ocz2 & 15)]; - sp[0] = ocx1; sp[1] = ocy1; sp[2] = ocz1; - sp[3] = ocx2; sp[4] = ocy2; sp[5] = ocz2; - -} - -static int do_coherence_test(int ocx1, int ocx2, int ocy1, int ocy2, int ocz1, int ocz2) -{ - short *sp; - - sp = coh_nodes[(ocx2 & 15) + 16 * (ocy2 & 15) + 256 * (ocz2 & 15)]; - if (sp[0] == ocx1 && sp[1] == ocy1 && sp[2] == ocz1 && - sp[3] == ocx2 && sp[4] == ocy2 && sp[5] == ocz2) return 1; - return 0; -} - -#endif - -/* return 1: found valid intersection */ -/* starts with is->orig.face */ -static int RE_rayobject_octree_intersect(RayObject *tree, Isect *is) -{ - Octree *oc = (Octree *)tree; - Node *no; - OcVal ocval; - float vec1[3], vec2[3], start[3], end[3]; - float u1, u2, ox1, ox2, oy1, oy2, oz1, oz2; - float lambda_o, lambda_x, ldx, lambda_y, ldy, lambda_z, ldz, dda_lambda; - float o_lambda = 0; - int dx, dy, dz; - int xo, yo, zo, c1 = 0; - int ocx1, ocx2, ocy1, ocy2, ocz1, ocz2; - - /* clip with octree */ - if (oc->branchcount == 0) return 0; - - /* do this before intersect calls */ -#if 0 - is->facecontr = NULL; /* to check shared edge */ - is->obcontr = 0; - is->faceisect = is->isect = 0; /* shared edge, quad half flag */ - is->userdata = oc->userdata; -#endif - - copy_v3_v3(start, is->start); - madd_v3_v3v3fl(end, is->start, is->dir, is->dist); - ldx = is->dir[0] * is->dist; - o_lambda = is->dist; - u1 = 0.0f; - u2 = 1.0f; - - /* clip with octree cube */ - if (cliptest(-ldx, start[0] - oc->min[0], &u1, &u2)) { - if (cliptest(ldx, oc->max[0] - start[0], &u1, &u2)) { - ldy = is->dir[1] * is->dist; - if (cliptest(-ldy, start[1] - oc->min[1], &u1, &u2)) { - if (cliptest(ldy, oc->max[1] - start[1], &u1, &u2)) { - ldz = is->dir[2] * is->dist; - if (cliptest(-ldz, start[2] - oc->min[2], &u1, &u2)) { - if (cliptest(ldz, oc->max[2] - start[2], &u1, &u2)) { - c1 = 1; - if (u2 < 1.0f) { - end[0] = start[0] + u2 * ldx; - end[1] = start[1] + u2 * ldy; - end[2] = start[2] + u2 * ldz; - } - - if (u1 > 0.0f) { - start[0] += u1 * ldx; - start[1] += u1 * ldy; - start[2] += u1 * ldz; - } - } - } - } - } - } - } - - if (c1 == 0) return 0; - - /* reset static variables in ocread */ - //ocread(oc, oc->ocres, 0, 0); - - /* setup 3dda to traverse octree */ - ox1 = (start[0] - oc->min[0]) * oc->ocfacx; - oy1 = (start[1] - oc->min[1]) * oc->ocfacy; - oz1 = (start[2] - oc->min[2]) * oc->ocfacz; - ox2 = (end[0] - oc->min[0]) * oc->ocfacx; - oy2 = (end[1] - oc->min[1]) * oc->ocfacy; - oz2 = (end[2] - oc->min[2]) * oc->ocfacz; - - ocx1 = (int)ox1; - ocy1 = (int)oy1; - ocz1 = (int)oz1; - ocx2 = (int)ox2; - ocy2 = (int)oy2; - ocz2 = (int)oz2; - - if (ocx1 == ocx2 && ocy1 == ocy2 && ocz1 == ocz2) { - no = ocread(oc, ocx1, ocy1, ocz1); - if (no) { - /* exact intersection with node */ - vec1[0] = ox1; vec1[1] = oy1; vec1[2] = oz1; - vec2[0] = ox2; vec2[1] = oy2; vec2[2] = oz2; - calc_ocval_ray(&ocval, (float)ocx1, (float)ocy1, (float)ocz1, vec1, vec2); - if (testnode(oc, is, no, ocval) ) return 1; - } - } - else { - int found = 0; - //static int coh_ocx1, coh_ocx2, coh_ocy1, coh_ocy2, coh_ocz1, coh_ocz2; - float dox, doy, doz; - int eqval; - - /* calc lambda en ld */ - dox = ox1 - ox2; - doy = oy1 - oy2; - doz = oz1 - oz2; - - if (dox < -FLT_EPSILON) { - ldx = -1.0f / dox; - lambda_x = (ocx1 - ox1 + 1.0f) * ldx; - dx = 1; - } - else if (dox > FLT_EPSILON) { - ldx = 1.0f / dox; - lambda_x = (ox1 - ocx1) * ldx; - dx = -1; - } - else { - lambda_x = 1.0f; - ldx = 0; - dx = 0; - } - - if (doy < -FLT_EPSILON) { - ldy = -1.0f / doy; - lambda_y = (ocy1 - oy1 + 1.0f) * ldy; - dy = 1; - } - else if (doy > FLT_EPSILON) { - ldy = 1.0f / doy; - lambda_y = (oy1 - ocy1) * ldy; - dy = -1; - } - else { - lambda_y = 1.0f; - ldy = 0; - dy = 0; - } - - if (doz < -FLT_EPSILON) { - ldz = -1.0f / doz; - lambda_z = (ocz1 - oz1 + 1.0f) * ldz; - dz = 1; - } - else if (doz > FLT_EPSILON) { - ldz = 1.0f / doz; - lambda_z = (oz1 - ocz1) * ldz; - dz = -1; - } - else { - lambda_z = 1.0f; - ldz = 0; - dz = 0; - } - - xo = ocx1; yo = ocy1; zo = ocz1; - dda_lambda = min_fff(lambda_x, lambda_y, lambda_z); - - vec2[0] = ox1; - vec2[1] = oy1; - vec2[2] = oz1; - - /* this loop has been constructed to make sure the first and last node of ray - * are always included, even when dda_lambda==1.0f or larger */ - - while (true) { - - no = ocread(oc, xo, yo, zo); - if (no) { - - /* calculate ray intersection with octree node */ - copy_v3_v3(vec1, vec2); - // dox, y, z is negative - vec2[0] = ox1 - dda_lambda * dox; - vec2[1] = oy1 - dda_lambda * doy; - vec2[2] = oz1 - dda_lambda * doz; - calc_ocval_ray(&ocval, (float)xo, (float)yo, (float)zo, vec1, vec2); - - //is->dist = (u1 + dda_lambda * (u2 - u1)) * o_lambda; - if (testnode(oc, is, no, ocval) ) - found = 1; - - if (is->dist < (u1 + dda_lambda * (u2 - u1)) * o_lambda) - return found; - } - - - lambda_o = dda_lambda; - - /* traversing octree nodes need careful detection of smallest values, with proper - * exceptions for equal lambdas */ - eqval = (lambda_x == lambda_y); - if (lambda_y == lambda_z) eqval += 2; - if (lambda_x == lambda_z) eqval += 4; - - if (eqval) { // only 4 cases exist! - if (eqval == 7) { // x=y=z - xo += dx; lambda_x += ldx; - yo += dy; lambda_y += ldy; - zo += dz; lambda_z += ldz; - } - else if (eqval == 1) { // x=y - if (lambda_y < lambda_z) { - xo += dx; lambda_x += ldx; - yo += dy; lambda_y += ldy; - } - else { - zo += dz; lambda_z += ldz; - } - } - else if (eqval == 2) { // y=z - if (lambda_x < lambda_y) { - xo += dx; lambda_x += ldx; - } - else { - yo += dy; lambda_y += ldy; - zo += dz; lambda_z += ldz; - } - } - else { // x=z - if (lambda_y < lambda_x) { - yo += dy; lambda_y += ldy; - } - else { - xo += dx; lambda_x += ldx; - zo += dz; lambda_z += ldz; - } - } - } - else { // all three different, just three cases exist - eqval = (lambda_x < lambda_y); - if (lambda_y < lambda_z) eqval += 2; - if (lambda_x < lambda_z) eqval += 4; - - if (eqval == 7 || eqval == 5) { // x smallest - xo += dx; lambda_x += ldx; - } - else if (eqval == 2 || eqval == 6) { // y smallest - yo += dy; lambda_y += ldy; - } - else { // z smallest - zo += dz; lambda_z += ldz; - } - - } - - dda_lambda = min_fff(lambda_x, lambda_y, lambda_z); - if (dda_lambda == lambda_o) break; - /* to make sure the last node is always checked */ - if (lambda_o >= 1.0f) break; - } - } - - /* reached end, no intersections found */ - return 0; -} - - - diff --git a/source/blender/render/intern/raytrace/rayobject_qbvh.cpp b/source/blender/render/intern/raytrace/rayobject_qbvh.cpp deleted file mode 100644 index 8e3dd87efd1..00000000000 --- a/source/blender/render/intern/raytrace/rayobject_qbvh.cpp +++ /dev/null @@ -1,160 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2009 Blender Foundation. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): André Pinto. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/render/intern/raytrace/rayobject_qbvh.cpp - * \ingroup render - */ - - -#include "MEM_guardedalloc.h" - -#include "BLI_utildefines.h" - -#include "vbvh.h" -#include "svbvh.h" -#include "reorganize.h" - -#ifdef __SSE__ - -#define DFS_STACK_SIZE 256 - -struct QBVHTree { - RayObject rayobj; - - SVBVHNode *root; - MemArena *node_arena; - - float cost; - RTBuilder *builder; -}; - - -template<> -void bvh_done<QBVHTree>(QBVHTree *obj) -{ - rtbuild_done(obj->builder, &obj->rayobj.control); - - //TODO find a away to exactly calculate the needed memory - MemArena *arena1 = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "qbvh arena"); - BLI_memarena_use_malloc(arena1); - - MemArena *arena2 = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "qbvh arena 2"); - BLI_memarena_use_malloc(arena2); - BLI_memarena_use_align(arena2, 16); - - //Build and optimize the tree - //TODO do this in 1 pass (half memory usage during building) - VBVHNode *root = BuildBinaryVBVH<VBVHNode>(arena1, &obj->rayobj.control).transform(obj->builder); - - if (RE_rayobjectcontrol_test_break(&obj->rayobj.control)) { - BLI_memarena_free(arena1); - BLI_memarena_free(arena2); - return; - } - - if (root) { - pushup_simd<VBVHNode, 4>(root); - obj->root = Reorganize_SVBVH<VBVHNode>(arena2).transform(root); - } - else - obj->root = NULL; - - //Free data - BLI_memarena_free(arena1); - - obj->node_arena = arena2; - obj->cost = 1.0; - - rtbuild_free(obj->builder); - obj->builder = NULL; -} - -template<int StackSize> -static int intersect(QBVHTree *obj, Isect *isec) -{ - //TODO renable hint support - if (RE_rayobject_isAligned(obj->root)) { - if (isec->mode == RE_RAY_SHADOW) - return svbvh_node_stack_raycast<StackSize, true>(obj->root, isec); - else - return svbvh_node_stack_raycast<StackSize, false>(obj->root, isec); - } - else - return RE_rayobject_intersect((RayObject *)obj->root, isec); -} - -template<class Tree> -static void bvh_hint_bb(Tree *tree, LCTSHint *hint, float *UNUSED(min), float *UNUSED(max)) -{ - //TODO renable hint support - { - hint->size = 0; - hint->stack[hint->size++] = (RayObject *)tree->root; - } -} -/* the cast to pointer function is needed to workarround gcc bug: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11407 */ -template<class Tree, int STACK_SIZE> -static RayObjectAPI make_api() -{ - static RayObjectAPI api = - { - (RE_rayobject_raycast_callback) ((int (*)(Tree *, Isect *)) & intersect<STACK_SIZE>), - (RE_rayobject_add_callback) ((void (*)(Tree *, RayObject *)) & bvh_add<Tree>), - (RE_rayobject_done_callback) ((void (*)(Tree *)) & bvh_done<Tree>), - (RE_rayobject_free_callback) ((void (*)(Tree *)) & bvh_free<Tree>), - (RE_rayobject_merge_bb_callback)((void (*)(Tree *, float *, float *)) & bvh_bb<Tree>), - (RE_rayobject_cost_callback) ((float (*)(Tree *)) & bvh_cost<Tree>), - (RE_rayobject_hint_bb_callback) ((void (*)(Tree *, LCTSHint *, float *, float *)) & bvh_hint_bb<Tree>) - }; - - return api; -} - -template<class Tree> -RayObjectAPI *bvh_get_api(int maxstacksize) -{ - static RayObjectAPI bvh_api256 = make_api<Tree, 1024>(); - - if (maxstacksize <= 1024) return &bvh_api256; - assert(maxstacksize <= 256); - return NULL; -} - -RayObject *RE_rayobject_qbvh_create(int size) -{ - return bvh_create_tree<QBVHTree, DFS_STACK_SIZE>(size); -} - -#else - -RayObject *RE_rayobject_qbvh_create(int UNUSED(size)) -{ - puts("WARNING: SSE disabled at compile time\n"); - return NULL; -} - -#endif diff --git a/source/blender/render/intern/raytrace/rayobject_raycounter.cpp b/source/blender/render/intern/raytrace/rayobject_raycounter.cpp deleted file mode 100644 index 429c47f1c0f..00000000000 --- a/source/blender/render/intern/raytrace/rayobject_raycounter.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2009 Blender Foundation. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): André Pinto. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/render/intern/raytrace/rayobject_raycounter.cpp - * \ingroup render - */ - - -#include "rayobject.h" -#include "raycounter.h" - -#ifdef RE_RAYCOUNTER - -void RE_RC_INFO(RayCounter *info) -{ - printf("----------- Raycast counter --------\n"); - printf("Rays total: %llu\n", info->raycast.test ); - printf("Rays hit: %llu\n", info->raycast.hit ); - printf("\n"); - printf("BB tests: %llu\n", info->bb.test ); - printf("BB hits: %llu\n", info->bb.hit ); - printf("\n"); - printf("SIMD BB tests: %llu\n", info->simd_bb.test ); - printf("SIMD BB hits: %llu\n", info->simd_bb.hit ); - printf("\n"); - printf("Primitives tests: %llu\n", info->faces.test ); - printf("Primitives hits: %llu\n", info->faces.hit ); - printf("------------------------------------\n"); - printf("Shadow last-hit tests per ray: %f\n", info->rayshadow_last_hit.test / ((float)info->raycast.test) ); - printf("Shadow last-hit hits per ray: %f\n", info->rayshadow_last_hit.hit / ((float)info->raycast.test) ); - printf("\n"); - printf("Hint tests per ray: %f\n", info->raytrace_hint.test / ((float)info->raycast.test) ); - printf("Hint hits per ray: %f\n", info->raytrace_hint.hit / ((float)info->raycast.test) ); - printf("\n"); - printf("BB tests per ray: %f\n", info->bb.test / ((float)info->raycast.test) ); - printf("BB hits per ray: %f\n", info->bb.hit / ((float)info->raycast.test) ); - printf("\n"); - printf("SIMD tests per ray: %f\n", info->simd_bb.test / ((float)info->raycast.test) ); - printf("SIMD hits per ray: %f\n", info->simd_bb.hit / ((float)info->raycast.test) ); - printf("\n"); - printf("Primitives tests per ray: %f\n", info->faces.test / ((float)info->raycast.test) ); - printf("Primitives hits per ray: %f\n", info->faces.hit / ((float)info->raycast.test) ); - printf("------------------------------------\n"); -} - -void RE_RC_MERGE(RayCounter *dest, RayCounter *tmp) -{ - dest->faces.test += tmp->faces.test; - dest->faces.hit += tmp->faces.hit; - - dest->bb.test += tmp->bb.test; - dest->bb.hit += tmp->bb.hit; - - dest->simd_bb.test += tmp->simd_bb.test; - dest->simd_bb.hit += tmp->simd_bb.hit; - - dest->raycast.test += tmp->raycast.test; - dest->raycast.hit += tmp->raycast.hit; - - dest->rayshadow_last_hit.test += tmp->rayshadow_last_hit.test; - dest->rayshadow_last_hit.hit += tmp->rayshadow_last_hit.hit; - - dest->raytrace_hint.test += tmp->raytrace_hint.test; - dest->raytrace_hint.hit += tmp->raytrace_hint.hit; -} - -#endif diff --git a/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp b/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp deleted file mode 100644 index 51f89784674..00000000000 --- a/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp +++ /dev/null @@ -1,531 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2009 Blender Foundation. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): André Pinto. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/render/intern/raytrace/rayobject_rtbuild.cpp - * \ingroup render - */ - - -#include <assert.h> -#include <stdlib.h> -#include <algorithm> - -#if __cplusplus >= 201103L -#include <cmath> -using std::isfinite; -#else -#include <math.h> -#endif - -#include "rayobject_rtbuild.h" - -#include "MEM_guardedalloc.h" - -#include "BLI_math.h" -#include "BLI_utildefines.h" - -static bool selected_node(RTBuilder::Object *node) -{ - return node->selected; -} - -static void rtbuild_init(RTBuilder *b) -{ - b->split_axis = -1; - b->primitives.begin = NULL; - b->primitives.end = NULL; - b->primitives.maxsize = 0; - b->depth = 0; - - for (int i = 0; i < RTBUILD_MAX_CHILDS; i++) - b->child_offset[i] = 0; - - for (int i = 0; i < 3; i++) - b->sorted_begin[i] = b->sorted_end[i] = NULL; - - INIT_MINMAX(b->bb, b->bb + 3); -} - -RTBuilder *rtbuild_create(int size) -{ - RTBuilder *builder = (RTBuilder *) MEM_mallocN(sizeof(RTBuilder), "RTBuilder"); - RTBuilder::Object *memblock = (RTBuilder::Object *)MEM_mallocN(sizeof(RTBuilder::Object) * size, "RTBuilder.objects"); - - - rtbuild_init(builder); - - builder->primitives.begin = builder->primitives.end = memblock; - builder->primitives.maxsize = size; - - for (int i = 0; i < 3; i++) { - builder->sorted_begin[i] = (RTBuilder::Object **)MEM_mallocN(sizeof(RTBuilder::Object *) * size, "RTBuilder.sorted_objects"); - builder->sorted_end[i] = builder->sorted_begin[i]; - } - - - return builder; -} - -void rtbuild_free(RTBuilder *b) -{ - if (b->primitives.begin) MEM_freeN(b->primitives.begin); - - for (int i = 0; i < 3; i++) - if (b->sorted_begin[i]) - MEM_freeN(b->sorted_begin[i]); - - MEM_freeN(b); -} - -void rtbuild_add(RTBuilder *b, RayObject *o) -{ - float bb[6]; - - assert(b->primitives.begin + b->primitives.maxsize != b->primitives.end); - - INIT_MINMAX(bb, bb + 3); - RE_rayobject_merge_bb(o, bb, bb + 3); - - /* skip objects with invalid bounding boxes, nan causes DO_MINMAX - * to do nothing, so we get these invalid values. this shouldn't - * happen usually, but bugs earlier in the pipeline can cause it. */ - if (bb[0] > bb[3] || bb[1] > bb[4] || bb[2] > bb[5]) - return; - /* skip objects with inf bounding boxes */ - if (!isfinite(bb[0]) || !isfinite(bb[1]) || !isfinite(bb[2])) - return; - if (!isfinite(bb[3]) || !isfinite(bb[4]) || !isfinite(bb[5])) - return; - /* skip objects with zero bounding box, they are of no use, and - * will give problems in rtbuild_heuristic_object_split later */ - if (bb[0] == bb[3] && bb[1] == bb[4] && bb[2] == bb[5]) - return; - - copy_v3_v3(b->primitives.end->bb, bb); - copy_v3_v3(b->primitives.end->bb + 3, bb + 3); - b->primitives.end->obj = o; - b->primitives.end->cost = RE_rayobject_cost(o); - - for (int i = 0; i < 3; i++) { - *(b->sorted_end[i]) = b->primitives.end; - b->sorted_end[i]++; - } - b->primitives.end++; -} - -int rtbuild_size(RTBuilder *b) -{ - return b->sorted_end[0] - b->sorted_begin[0]; -} - - -template<class Obj, int Axis> -static bool obj_bb_compare(const Obj &a, const Obj &b) -{ - if (a->bb[Axis] != b->bb[Axis]) - return a->bb[Axis] < b->bb[Axis]; - return a->obj < b->obj; -} - -template<class Item> -static void object_sort(Item *begin, Item *end, int axis) -{ - if (axis == 0) return std::sort(begin, end, obj_bb_compare<Item, 0> ); - if (axis == 1) return std::sort(begin, end, obj_bb_compare<Item, 1> ); - if (axis == 2) return std::sort(begin, end, obj_bb_compare<Item, 2> ); - assert(false); -} - -void rtbuild_done(RTBuilder *b, RayObjectControl *ctrl) -{ - for (int i = 0; i < 3; i++) { - if (b->sorted_begin[i]) { - if (RE_rayobjectcontrol_test_break(ctrl)) break; - object_sort(b->sorted_begin[i], b->sorted_end[i], i); - } - } -} - -RayObject *rtbuild_get_primitive(RTBuilder *b, int index) -{ - return b->sorted_begin[0][index]->obj; -} - -RTBuilder *rtbuild_get_child(RTBuilder *b, int child, RTBuilder *tmp) -{ - rtbuild_init(tmp); - - tmp->depth = b->depth + 1; - - for (int i = 0; i < 3; i++) - if (b->sorted_begin[i]) { - tmp->sorted_begin[i] = b->sorted_begin[i] + b->child_offset[child]; - tmp->sorted_end[i] = b->sorted_begin[i] + b->child_offset[child + 1]; - } - else { - tmp->sorted_begin[i] = NULL; - tmp->sorted_end[i] = NULL; - } - - return tmp; -} - -static void rtbuild_calc_bb(RTBuilder *b) -{ - if (b->bb[0] == 1.0e30f) { - for (RTBuilder::Object **index = b->sorted_begin[0]; index != b->sorted_end[0]; index++) - RE_rayobject_merge_bb( (*index)->obj, b->bb, b->bb + 3); - } -} - -void rtbuild_merge_bb(RTBuilder *b, float min[3], float max[3]) -{ - rtbuild_calc_bb(b); - DO_MIN(b->bb, min); - DO_MAX(b->bb + 3, max); -} - -#if 0 -int rtbuild_get_largest_axis(RTBuilder *b) -{ - rtbuild_calc_bb(b); - return bb_largest_axis(b->bb, b->bb + 3); -} - -//Left balanced tree -int rtbuild_mean_split(RTBuilder *b, int nchilds, int axis) -{ - int i; - int mleafs_per_child, Mleafs_per_child; - int tot_leafs = rtbuild_size(b); - int missing_leafs; - - long long s; - - assert(nchilds <= RTBUILD_MAX_CHILDS); - - //TODO optimize calc of leafs_per_child - for (s = nchilds; s < tot_leafs; s *= nchilds) ; - Mleafs_per_child = s / nchilds; - mleafs_per_child = Mleafs_per_child / nchilds; - - //split min leafs per child - b->child_offset[0] = 0; - for (i = 1; i <= nchilds; i++) - b->child_offset[i] = mleafs_per_child; - - //split remaining leafs - missing_leafs = tot_leafs - mleafs_per_child * nchilds; - for (i = 1; i <= nchilds; i++) - { - if (missing_leafs > Mleafs_per_child - mleafs_per_child) - { - b->child_offset[i] += Mleafs_per_child - mleafs_per_child; - missing_leafs -= Mleafs_per_child - mleafs_per_child; - } - else { - b->child_offset[i] += missing_leafs; - missing_leafs = 0; - break; - } - } - - //adjust for accumulative offsets - for (i = 1; i <= nchilds; i++) - b->child_offset[i] += b->child_offset[i - 1]; - - //Count created childs - for (i = nchilds; b->child_offset[i] == b->child_offset[i - 1]; i--) ; - split_leafs(b, b->child_offset, i, axis); - - assert(b->child_offset[0] == 0 && b->child_offset[i] == tot_leafs); - return i; -} - - -int rtbuild_mean_split_largest_axis(RTBuilder *b, int nchilds) -{ - int axis = rtbuild_get_largest_axis(b); - return rtbuild_mean_split(b, nchilds, axis); -} -#endif - -/* - * "separators" is an array of dim NCHILDS-1 - * and indicates where to cut the childs - */ -#if 0 -int rtbuild_median_split(RTBuilder *b, float *separators, int nchilds, int axis) -{ - int size = rtbuild_size(b); - - assert(nchilds <= RTBUILD_MAX_CHILDS); - if (size <= nchilds) - { - return rtbuild_mean_split(b, nchilds, axis); - } - else { - int i; - - b->split_axis = axis; - - //Calculate child offsets - b->child_offset[0] = 0; - for (i = 0; i < nchilds - 1; i++) - b->child_offset[i + 1] = split_leafs_by_plane(b, b->child_offset[i], size, separators[i]); - b->child_offset[nchilds] = size; - - for (i = 0; i < nchilds; i++) - if (b->child_offset[i + 1] - b->child_offset[i] == size) - return rtbuild_mean_split(b, nchilds, axis); - - return nchilds; - } -} - -int rtbuild_median_split_largest_axis(RTBuilder *b, int nchilds) -{ - int la, i; - float separators[RTBUILD_MAX_CHILDS]; - - rtbuild_calc_bb(b); - - la = bb_largest_axis(b->bb, b->bb + 3); - for (i = 1; i < nchilds; i++) - separators[i - 1] = (b->bb[la + 3] - b->bb[la]) * i / nchilds; - - return rtbuild_median_split(b, separators, nchilds, la); -} -#endif - -//Heuristics Object Splitter - - -struct SweepCost { - float bb[6]; - float cost; -}; - -/* Object Surface Area Heuristic splitter */ -int rtbuild_heuristic_object_split(RTBuilder *b, int nchilds) -{ - int size = rtbuild_size(b); - assert(nchilds == 2); - assert(size > 1); - int baxis = -1, boffset = 0; - - if (size > nchilds) { - if (b->depth > RTBUILD_MAX_SAH_DEPTH) { - // for degenerate cases we avoid running out of stack space - // by simply splitting the children in the middle - b->child_offset[0] = 0; - b->child_offset[1] = (size+1)/2; - b->child_offset[2] = size; - return 2; - } - - float bcost = FLT_MAX; - baxis = -1; - boffset = size / 2; - - SweepCost *sweep = (SweepCost *)MEM_mallocN(sizeof(SweepCost) * size, "RTBuilder.HeuristicSweep"); - - for (int axis = 0; axis < 3; axis++) { - SweepCost sweep_left; - - RTBuilder::Object **obj = b->sorted_begin[axis]; - -// float right_cost = 0; - for (int i = size - 1; i >= 0; i--) { - if (i == size - 1) { - copy_v3_v3(sweep[i].bb, obj[i]->bb); - copy_v3_v3(sweep[i].bb + 3, obj[i]->bb + 3); - sweep[i].cost = obj[i]->cost; - } - else { - sweep[i].bb[0] = min_ff(obj[i]->bb[0], sweep[i + 1].bb[0]); - sweep[i].bb[1] = min_ff(obj[i]->bb[1], sweep[i + 1].bb[1]); - sweep[i].bb[2] = min_ff(obj[i]->bb[2], sweep[i + 1].bb[2]); - sweep[i].bb[3] = max_ff(obj[i]->bb[3], sweep[i + 1].bb[3]); - sweep[i].bb[4] = max_ff(obj[i]->bb[4], sweep[i + 1].bb[4]); - sweep[i].bb[5] = max_ff(obj[i]->bb[5], sweep[i + 1].bb[5]); - sweep[i].cost = obj[i]->cost + sweep[i + 1].cost; - } -// right_cost += obj[i]->cost; - } - - sweep_left.bb[0] = obj[0]->bb[0]; - sweep_left.bb[1] = obj[0]->bb[1]; - sweep_left.bb[2] = obj[0]->bb[2]; - sweep_left.bb[3] = obj[0]->bb[3]; - sweep_left.bb[4] = obj[0]->bb[4]; - sweep_left.bb[5] = obj[0]->bb[5]; - sweep_left.cost = obj[0]->cost; - -// right_cost -= obj[0]->cost; if (right_cost < 0) right_cost = 0; - - for (int i = 1; i < size; i++) { - //Worst case heuristic (cost of each child is linear) - float hcost, left_side, right_side; - - // not using log seems to have no impact on raytracing perf, but - // makes tree construction quicker, left out for now to test (brecht) - // left_side = bb_area(sweep_left.bb, sweep_left.bb + 3) * (sweep_left.cost + logf((float)i)); - // right_side = bb_area(sweep[i].bb, sweep[i].bb + 3) * (sweep[i].cost + logf((float)size - i)); - left_side = bb_area(sweep_left.bb, sweep_left.bb + 3) * (sweep_left.cost); - right_side = bb_area(sweep[i].bb, sweep[i].bb + 3) * (sweep[i].cost); - hcost = left_side + right_side; - - assert(left_side >= 0); - assert(right_side >= 0); - - if (left_side > bcost) break; //No way we can find a better heuristic in this axis - - assert(hcost >= 0); - // this makes sure the tree built is the same whatever is the order of the sorting axis - if (hcost < bcost || (hcost == bcost && axis < baxis)) { - bcost = hcost; - baxis = axis; - boffset = i; - } - DO_MIN(obj[i]->bb, sweep_left.bb); - DO_MAX(obj[i]->bb + 3, sweep_left.bb + 3); - - sweep_left.cost += obj[i]->cost; -// right_cost -= obj[i]->cost; if (right_cost < 0) right_cost = 0; - } - - //assert(baxis >= 0 && baxis < 3); - if (!(baxis >= 0 && baxis < 3)) - baxis = 0; - } - - - MEM_freeN(sweep); - } - else if (size == 2) { - baxis = 0; - boffset = 1; - } - else if (size == 1) { - b->child_offset[0] = 0; - b->child_offset[1] = 1; - return 1; - } - - b->child_offset[0] = 0; - b->child_offset[1] = boffset; - b->child_offset[2] = size; - - - /* Adjust sorted arrays for childs */ - for (int i = 0; i < boffset; i++) b->sorted_begin[baxis][i]->selected = true; - for (int i = boffset; i < size; i++) b->sorted_begin[baxis][i]->selected = false; - for (int i = 0; i < 3; i++) - std::stable_partition(b->sorted_begin[i], b->sorted_end[i], selected_node); - - return nchilds; -} - -/* - * Helper code - * PARTITION code / used on mean-split - * basically this a std::nth_element (like on C++ STL algorithm) - */ -#if 0 -static void split_leafs(RTBuilder *b, int *nth, int partitions, int split_axis) -{ - int i; - b->split_axis = split_axis; - - for (i = 0; i < partitions - 1; i++) - { - assert(nth[i] < nth[i + 1] && nth[i + 1] < nth[partitions]); - - if (split_axis == 0) std::nth_element(b, nth[i], nth[i + 1], nth[partitions], obj_bb_compare<RTBuilder::Object, 0>); - if (split_axis == 1) std::nth_element(b, nth[i], nth[i + 1], nth[partitions], obj_bb_compare<RTBuilder::Object, 1>); - if (split_axis == 2) std::nth_element(b, nth[i], nth[i + 1], nth[partitions], obj_bb_compare<RTBuilder::Object, 2>); - } -} -#endif - -/* - * Bounding Box utils - */ -float bb_volume(const float min[3], const float max[3]) -{ - return (max[0] - min[0]) * (max[1] - min[1]) * (max[2] - min[2]); -} - -float bb_area(const float min[3], const float max[3]) -{ - float sub[3], a; - sub[0] = max[0] - min[0]; - sub[1] = max[1] - min[1]; - sub[2] = max[2] - min[2]; - - a = (sub[0] * sub[1] + sub[0] * sub[2] + sub[1] * sub[2]) * 2.0f; - /* used to have an assert() here on negative results - * however, in this case its likely some overflow or ffast math error. - * so just return 0.0f instead. */ - return a < 0.0f ? 0.0f : a; -} - -int bb_largest_axis(const float min[3], const float max[3]) -{ - float sub[3]; - - sub[0] = max[0] - min[0]; - sub[1] = max[1] - min[1]; - sub[2] = max[2] - min[2]; - if (sub[0] > sub[1]) { - if (sub[0] > sub[2]) - return 0; - else - return 2; - } - else { - if (sub[1] > sub[2]) - return 1; - else - return 2; - } -} - -/* only returns 0 if merging inner and outerbox would create a box larger than outer box */ -int bb_fits_inside(const float outer_min[3], const float outer_max[3], - const float inner_min[3], const float inner_max[3]) -{ - int i; - for (i = 0; i < 3; i++) - if (outer_min[i] > inner_min[i]) return 0; - - for (i = 0; i < 3; i++) - if (outer_max[i] < inner_max[i]) return 0; - - return 1; -} diff --git a/source/blender/render/intern/raytrace/rayobject_rtbuild.h b/source/blender/render/intern/raytrace/rayobject_rtbuild.h deleted file mode 100644 index fc42bc36d92..00000000000 --- a/source/blender/render/intern/raytrace/rayobject_rtbuild.h +++ /dev/null @@ -1,125 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2009 Blender Foundation. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): André Pinto. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/render/intern/raytrace/rayobject_rtbuild.h - * \ingroup render - */ - -#ifndef __RAYOBJECT_RTBUILD_H__ -#define __RAYOBJECT_RTBUILD_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "rayobject.h" - - -/* - * Ray Tree Builder - * this structs helps building any type of tree - * it contains several methods to organize/split nodes - * allowing to create a given tree on the fly. - * - * Idea is that other trees BVH, BIH can use this code to - * generate with simple calls, and then convert to the theirs - * specific structure on the fly. - */ -#define RTBUILD_MAX_CHILDS 32 -#define RTBUILD_MAX_SAH_DEPTH 256 - - -typedef struct RTBuilder { - struct Object { - RayObject *obj; - float cost; - float bb[6]; - int selected; - }; - - /* list to all primitives added in this tree */ - struct { - Object *begin, *end; - int maxsize; - } primitives; - - /* sorted list of rayobjects */ - struct Object **sorted_begin[3], **sorted_end[3]; - - /* axis used (if any) on the split method */ - int split_axis; - - /* child partitions calculated during splitting */ - int child_offset[RTBUILD_MAX_CHILDS + 1]; - -// int child_sorted_axis; /* -1 if not sorted */ - - float bb[6]; - - /* current depth */ - int depth; -} RTBuilder; - -/* used during creation */ -RTBuilder *rtbuild_create(int size); -void rtbuild_free(RTBuilder *b); -void rtbuild_add(RTBuilder *b, RayObject *o); -void rtbuild_done(RTBuilder *b, RayObjectControl *c); -void rtbuild_merge_bb(RTBuilder *b, float min[3], float max[3]); -int rtbuild_size(RTBuilder *b); - -RayObject *rtbuild_get_primitive(RTBuilder *b, int offset); - -/* used during tree reorganization */ -RTBuilder *rtbuild_get_child(RTBuilder *b, int child, RTBuilder *tmp); - -/* Calculates child partitions and returns number of efectively needed partitions */ -int rtbuild_get_largest_axis(RTBuilder *b); - -//Object partition -int rtbuild_mean_split(RTBuilder *b, int nchilds, int axis); -int rtbuild_mean_split_largest_axis(RTBuilder *b, int nchilds); - -int rtbuild_heuristic_object_split(RTBuilder *b, int nchilds); - -//Space partition -int rtbuild_median_split(RTBuilder *b, float *separators, int nchilds, int axis); -int rtbuild_median_split_largest_axis(RTBuilder *b, int nchilds); - - -/* bb utils */ -float bb_area(const float min[3], const float max[3]); -float bb_volume(const float min[3], const float max[3]); -int bb_largest_axis(const float min[3], const float max[3]); -int bb_fits_inside(const float outer_min[3], const float outer_max[3], - const float inner_min[3], const float inner_max[3]); - -#ifdef __cplusplus -} -#endif - -#endif /* __RAYOBJECT_RTBUILD_H__ */ diff --git a/source/blender/render/intern/raytrace/rayobject_svbvh.cpp b/source/blender/render/intern/raytrace/rayobject_svbvh.cpp deleted file mode 100644 index fcd692fac02..00000000000 --- a/source/blender/render/intern/raytrace/rayobject_svbvh.cpp +++ /dev/null @@ -1,192 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2009 Blender Foundation. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): André Pinto. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/render/intern/raytrace/rayobject_svbvh.cpp - * \ingroup render - */ - - -#include "MEM_guardedalloc.h" - -#include "BLI_utildefines.h" - -#include "vbvh.h" -#include "svbvh.h" -#include "reorganize.h" - -#ifdef __SSE__ - -#define DFS_STACK_SIZE 256 - -struct SVBVHTree { - RayObject rayobj; - - SVBVHNode *root; - MemArena *node_arena; - - float cost; - RTBuilder *builder; -}; - -/* - * Cost to test N childs - */ -struct PackCost { - float operator()(int n) - { - return (n / 4) + ((n % 4) > 2 ? 1 : n % 4); - } -}; - - -template<> -void bvh_done<SVBVHTree>(SVBVHTree *obj) -{ - rtbuild_done(obj->builder, &obj->rayobj.control); - - //TODO find a away to exactly calculate the needed memory - MemArena *arena1 = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "svbvh arena"); - BLI_memarena_use_malloc(arena1); - - MemArena *arena2 = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "svbvh arena2"); - BLI_memarena_use_malloc(arena2); - BLI_memarena_use_align(arena2, 16); - - //Build and optimize the tree - if (0) { - VBVHNode *root = BuildBinaryVBVH<VBVHNode>(arena1, &obj->rayobj.control).transform(obj->builder); - - if (RE_rayobjectcontrol_test_break(&obj->rayobj.control)) { - BLI_memarena_free(arena1); - BLI_memarena_free(arena2); - return; - } - - reorganize(root); - remove_useless(root, &root); - bvh_refit(root); - - pushup(root); - pushdown(root); - pushup_simd<VBVHNode, 4>(root); - - obj->root = Reorganize_SVBVH<VBVHNode>(arena2).transform(root); - } - else { - //Finds the optimal packing of this tree using a given cost model - //TODO this uses quite a lot of memory, find ways to reduce memory usage during building - OVBVHNode *root = BuildBinaryVBVH<OVBVHNode>(arena1, &obj->rayobj.control).transform(obj->builder); - - if (RE_rayobjectcontrol_test_break(&obj->rayobj.control)) { - BLI_memarena_free(arena1); - BLI_memarena_free(arena2); - return; - } - - if (root) { - VBVH_optimalPackSIMD<OVBVHNode, PackCost>(PackCost()).transform(root); - obj->root = Reorganize_SVBVH<OVBVHNode>(arena2).transform(root); - } - else - obj->root = NULL; - } - - //Free data - BLI_memarena_free(arena1); - - obj->node_arena = arena2; - obj->cost = 1.0; - - rtbuild_free(obj->builder); - obj->builder = NULL; -} - -template<int StackSize> -static int intersect(SVBVHTree *obj, Isect *isec) -{ - //TODO renable hint support - if (RE_rayobject_isAligned(obj->root)) { - if (isec->mode == RE_RAY_SHADOW) - return svbvh_node_stack_raycast<StackSize, true>(obj->root, isec); - else - return svbvh_node_stack_raycast<StackSize, false>(obj->root, isec); - } - else - return RE_rayobject_intersect( (RayObject *) obj->root, isec); -} - -template<class Tree> -static void bvh_hint_bb(Tree *tree, LCTSHint *hint, float *UNUSED(min), float *UNUSED(max)) -{ - //TODO renable hint support - { - hint->size = 0; - hint->stack[hint->size++] = (RayObject *)tree->root; - } -} -/* the cast to pointer function is needed to workarround gcc bug: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11407 */ -template<class Tree, int STACK_SIZE> -static RayObjectAPI make_api() -{ - static RayObjectAPI api = - { - (RE_rayobject_raycast_callback) ((int (*)(Tree *, Isect *)) & intersect<STACK_SIZE>), - (RE_rayobject_add_callback) ((void (*)(Tree *, RayObject *)) & bvh_add<Tree>), - (RE_rayobject_done_callback) ((void (*)(Tree *)) & bvh_done<Tree>), - (RE_rayobject_free_callback) ((void (*)(Tree *)) & bvh_free<Tree>), - (RE_rayobject_merge_bb_callback)((void (*)(Tree *, float *, float *)) & bvh_bb<Tree>), - (RE_rayobject_cost_callback) ((float (*)(Tree *)) & bvh_cost<Tree>), - (RE_rayobject_hint_bb_callback) ((void (*)(Tree *, LCTSHint *, float *, float *)) & bvh_hint_bb<Tree>) - }; - - return api; -} - -template<class Tree> -static RayObjectAPI *bvh_get_api(int maxstacksize) -{ - static RayObjectAPI bvh_api256 = make_api<Tree, 1024>(); - - if (maxstacksize <= 1024) return &bvh_api256; - assert(maxstacksize <= 256); - return NULL; -} - -RayObject *RE_rayobject_svbvh_create(int size) -{ - return bvh_create_tree<SVBVHTree, DFS_STACK_SIZE>(size); -} - -#else - -RayObject *RE_rayobject_svbvh_create(int UNUSED(size)) -{ - puts("WARNING: SSE disabled at compile time\n"); - return NULL; -} - -#endif diff --git a/source/blender/render/intern/raytrace/rayobject_vbvh.cpp b/source/blender/render/intern/raytrace/rayobject_vbvh.cpp deleted file mode 100644 index b63a11047dd..00000000000 --- a/source/blender/render/intern/raytrace/rayobject_vbvh.cpp +++ /dev/null @@ -1,206 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2009 Blender Foundation. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): André Pinto. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/render/intern/raytrace/rayobject_vbvh.cpp - * \ingroup render - */ - - -int tot_pushup = 0; -int tot_pushdown = 0; -int tot_hints = 0; - -#include <assert.h> - -#include "MEM_guardedalloc.h" - -#include "BLI_math.h" -#include "BLI_memarena.h" -#include "BLI_utildefines.h" - -#include "BKE_global.h" - -#include "rayintersection.h" -#include "rayobject.h" -#include "rayobject_rtbuild.h" - -#include "reorganize.h" -#include "bvh.h" -#include "vbvh.h" - -#include <queue> -#include <algorithm> - -#define DFS_STACK_SIZE 256 - -struct VBVHTree { - RayObject rayobj; - VBVHNode *root; - MemArena *node_arena; - float cost; - RTBuilder *builder; -}; - -/* - * Cost to test N childs - */ -struct PackCost { - float operator()(int n) - { - return n; - } -}; - -template<> -void bvh_done<VBVHTree>(VBVHTree *obj) -{ - rtbuild_done(obj->builder, &obj->rayobj.control); - - //TODO find a away to exactly calculate the needed memory - MemArena *arena1 = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "vbvh arena"); - BLI_memarena_use_malloc(arena1); - - //Build and optimize the tree - if (1) { - VBVHNode *root = BuildBinaryVBVH<VBVHNode>(arena1, &obj->rayobj.control).transform(obj->builder); - if (RE_rayobjectcontrol_test_break(&obj->rayobj.control)) { - BLI_memarena_free(arena1); - return; - } - - if (root) { - reorganize(root); - remove_useless(root, &root); - bvh_refit(root); - - pushup(root); - pushdown(root); - obj->root = root; - } - else - obj->root = NULL; - } - else { - /* TODO */ -#if 0 - MemArena *arena2 = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "vbvh arena2"); - BLI_memarena_use_malloc(arena2); - - //Finds the optimal packing of this tree using a given cost model - //TODO this uses quite a lot of memory, find ways to reduce memory usage during building - OVBVHNode *root = BuildBinaryVBVH<OVBVHNode>(arena2).transform(obj->builder); - VBVH_optimalPackSIMD<OVBVHNode, PackCost>(PackCost()).transform(root); - obj->root = Reorganize_VBVH<OVBVHNode>(arena1).transform(root); - - BLI_memarena_free(arena2); -#endif - } - - //Cleanup - rtbuild_free(obj->builder); - obj->builder = NULL; - - obj->node_arena = arena1; - obj->cost = 1.0; -} - -template<int StackSize> -static int intersect(VBVHTree *obj, Isect *isec) -{ - //TODO renable hint support - if (RE_rayobject_isAligned(obj->root)) { - if (isec->mode == RE_RAY_SHADOW) - return bvh_node_stack_raycast<VBVHNode, StackSize, false, true>(obj->root, isec); - else - return bvh_node_stack_raycast<VBVHNode, StackSize, false, false>(obj->root, isec); - } - else - return RE_rayobject_intersect( (RayObject *) obj->root, isec); -} - -template<class Tree> -static void bvh_hint_bb(Tree *tree, LCTSHint *hint, float *UNUSED(min), float *UNUSED(max)) -{ - //TODO renable hint support - { - hint->size = 0; - hint->stack[hint->size++] = (RayObject *)tree->root; - } -} - -#if 0 /* UNUSED */ -static void bfree(VBVHTree *tree) -{ - if (tot_pushup + tot_pushdown + tot_hints + tot_moves) { - if (G.debug & G_DEBUG) { - printf("tot pushups: %d\n", tot_pushup); - printf("tot pushdowns: %d\n", tot_pushdown); - printf("tot moves: %d\n", tot_moves); - printf("tot hints created: %d\n", tot_hints); - } - - tot_pushup = 0; - tot_pushdown = 0; - tot_hints = 0; - tot_moves = 0; - } - bvh_free(tree); -} -#endif - -/* the cast to pointer function is needed to workarround gcc bug: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11407 */ -template<class Tree, int STACK_SIZE> -static RayObjectAPI make_api() -{ - static RayObjectAPI api = - { - (RE_rayobject_raycast_callback) ((int (*)(Tree *, Isect *)) & intersect<STACK_SIZE>), - (RE_rayobject_add_callback) ((void (*)(Tree *, RayObject *)) & bvh_add<Tree>), - (RE_rayobject_done_callback) ((void (*)(Tree *)) & bvh_done<Tree>), - (RE_rayobject_free_callback) ((void (*)(Tree *)) & bvh_free<Tree>), - (RE_rayobject_merge_bb_callback)((void (*)(Tree *, float *, float *)) & bvh_bb<Tree>), - (RE_rayobject_cost_callback) ((float (*)(Tree *)) & bvh_cost<Tree>), - (RE_rayobject_hint_bb_callback) ((void (*)(Tree *, LCTSHint *, float *, float *)) & bvh_hint_bb<Tree>) - }; - - return api; -} - -template<class Tree> -RayObjectAPI *bvh_get_api(int maxstacksize) -{ - static RayObjectAPI bvh_api256 = make_api<Tree, 1024>(); - - if (maxstacksize <= 1024) return &bvh_api256; - assert(maxstacksize <= 256); - return 0; -} - -RayObject *RE_rayobject_vbvh_create(int size) -{ - return bvh_create_tree<VBVHTree, DFS_STACK_SIZE>(size); -} diff --git a/source/blender/render/intern/raytrace/reorganize.h b/source/blender/render/intern/raytrace/reorganize.h deleted file mode 100644 index 3fdd3363edb..00000000000 --- a/source/blender/render/intern/raytrace/reorganize.h +++ /dev/null @@ -1,513 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2009 Blender Foundation. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): André Pinto. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/render/intern/raytrace/reorganize.h - * \ingroup render - */ - - -#include <float.h> -#include <math.h> -#include <stdio.h> - -#include <algorithm> -#include <queue> -#include <vector> - -#include "BKE_global.h" - -#ifdef _WIN32 -# ifdef INFINITY -# undef INFINITY -# endif -# define INFINITY FLT_MAX // in mingw math.h: (1.0F/0.0F). This generates compile error, though. -#endif - -extern int tot_pushup; -extern int tot_pushdown; - -#if !defined(INFINITY) && defined(HUGE_VAL) -#define INFINITY HUGE_VAL -#endif - -template<class Node> -static bool node_fits_inside(Node *a, Node *b) -{ - return bb_fits_inside(b->bb, b->bb + 3, a->bb, a->bb + 3); -} - -template<class Node> -static void reorganize_find_fittest_parent(Node *tree, Node *node, std::pair<float, Node *> &cost) -{ - std::queue<Node *> q; - q.push(tree); - - while (!q.empty()) { - Node *parent = q.front(); - q.pop(); - - if (parent == node) continue; - if (node_fits_inside(node, parent) && RE_rayobject_isAligned(parent->child) ) { - float pcost = bb_area(parent->bb, parent->bb + 3); - cost = std::min(cost, std::make_pair(pcost, parent) ); - for (Node *child = parent->child; child; child = child->sibling) - q.push(child); - } - } -} - -template<class Node> -static void reorganize(Node *root) -{ - std::queue<Node *> q; - - q.push(root); - while (!q.empty()) { - Node *node = q.front(); - q.pop(); - - if (RE_rayobject_isAligned(node->child)) { - for (Node **prev = &node->child; *prev; ) { - assert(RE_rayobject_isAligned(*prev)); - q.push(*prev); - - std::pair<float, Node *> best(FLT_MAX, root); - reorganize_find_fittest_parent(root, *prev, best); - - if (best.second == node) { - //Already inside the fitnest BB - prev = &(*prev)->sibling; - } - else { - Node *tmp = *prev; - *prev = (*prev)->sibling; - - tmp->sibling = best.second->child; - best.second->child = tmp; - } - - - } - } - if (node != root) { - } - } -} - -/* - * Prunes useless nodes from trees: - * erases nodes with total amount of primitives = 0 - * prunes nodes with only one child (except if that child is a primitive) - */ -template<class Node> -static void remove_useless(Node *node, Node **new_node) -{ - if (RE_rayobject_isAligned(node->child) ) { - - for (Node **prev = &node->child; *prev; ) { - Node *next = (*prev)->sibling; - remove_useless(*prev, prev); - if (*prev == NULL) - *prev = next; - else { - (*prev)->sibling = next; - prev = &((*prev)->sibling); - } - } - } - if (node->child) { - if (RE_rayobject_isAligned(node->child) && node->child->sibling == 0) - *new_node = node->child; - } - else if (node->child == NULL) { - *new_node = NULL; - } -} - -/* - * Minimizes expected number of BBtest by colapsing nodes - * it uses surface area heuristic for determining whether a node should be colapsed - */ -template<class Node> -static void pushup(Node *parent) -{ - if (is_leaf(parent)) return; - - float p_area = bb_area(parent->bb, parent->bb + 3); - Node **prev = &parent->child; - for (Node *child = parent->child; RE_rayobject_isAligned(child) && child; ) { - const float c_area = bb_area(child->bb, child->bb + 3); - const int nchilds = count_childs(child); - float original_cost = ((p_area != 0.0f) ? (c_area / p_area) * nchilds : 1.0f) + 1; - float flatten_cost = nchilds; - if (flatten_cost < original_cost && nchilds >= 2) { - append_sibling(child, child->child); - child = child->sibling; - *prev = child; - -// *prev = child->child; -// append_sibling( *prev, child->sibling ); -// child = *prev; - tot_pushup++; - } - else { - *prev = child; - prev = &(*prev)->sibling; - child = *prev; - } - } - - for (Node *child = parent->child; RE_rayobject_isAligned(child) && child; child = child->sibling) - pushup(child); -} - -/* - * try to optimize number of childs to be a multiple of SSize - */ -template<class Node, int SSize> -static void pushup_simd(Node *parent) -{ - if (is_leaf(parent)) return; - - int n = count_childs(parent); - - Node **prev = &parent->child; - for (Node *child = parent->child; RE_rayobject_isAligned(child) && child; ) { - int cn = count_childs(child); - if (cn - 1 <= (SSize - (n % SSize) ) % SSize && RE_rayobject_isAligned(child->child) ) { - n += (cn - 1); - append_sibling(child, child->child); - child = child->sibling; - *prev = child; - } - else { - *prev = child; - prev = &(*prev)->sibling; - child = *prev; - } - } - - for (Node *child = parent->child; RE_rayobject_isAligned(child) && child; child = child->sibling) - pushup_simd<Node, SSize>(child); -} - - -/* - * Pushdown - * makes sure no child fits inside any of its sibling - */ -template<class Node> -static void pushdown(Node *parent) -{ - Node **s_child = &parent->child; - Node *child = parent->child; - - while (child && RE_rayobject_isAligned(child)) { - Node *next = child->sibling; - Node **next_s_child = &child->sibling; - - //assert(bb_fits_inside(parent->bb, parent->bb+3, child->bb, child->bb+3)); - - for (Node *i = parent->child; RE_rayobject_isAligned(i) && i; i = i->sibling) - if (child != i && bb_fits_inside(i->bb, i->bb + 3, child->bb, child->bb + 3) && RE_rayobject_isAligned(i->child)) { -// todo optimize (should the one with the smallest area?) -// float ia = bb_area(i->bb, i->bb+3) -// if (child->i) - *s_child = child->sibling; - child->sibling = i->child; - i->child = child; - next_s_child = s_child; - - tot_pushdown++; - break; - } - child = next; - s_child = next_s_child; - } - - for (Node *i = parent->child; RE_rayobject_isAligned(i) && i; i = i->sibling) { - pushdown(i); - } -} - - -/* - * BVH refit - * readjust nodes BB (useful if nodes childs where modified) - */ -template<class Node> -static float bvh_refit(Node *node) -{ - if (is_leaf(node)) return 0; - if (is_leaf(node->child)) return 0; - - float total = 0; - - for (Node *child = node->child; child; child = child->sibling) - total += bvh_refit(child); - - float old_area = bb_area(node->bb, node->bb + 3); - INIT_MINMAX(node->bb, node->bb + 3); - for (Node *child = node->child; child; child = child->sibling) { - DO_MIN(child->bb, node->bb); - DO_MAX(child->bb + 3, node->bb + 3); - } - total += old_area - bb_area(node->bb, node->bb + 3); - return total; -} - - -/* - * this finds the best way to packing a tree according to a given test cost function - * with the purpose to reduce the expected cost (eg.: number of BB tests). - */ -#include <vector> -#define MAX_CUT_SIZE 4 /* svbvh assumes max 4 children! */ -#define MAX_OPTIMIZE_CHILDS MAX_CUT_SIZE - -#define CUT_SIZE_IS_VALID(cut_size) ((cut_size) < MAX_CUT_SIZE && (cut_size) >= 0) -#define CUT_SIZE_INVALID -1 - - -struct OVBVHNode { - float bb[6]; - - OVBVHNode *child; - OVBVHNode *sibling; - - /* - * Returns min cost to represent the subtree starting at the given node, - * allowing it to have a given cutsize - */ - float cut_cost[MAX_CUT_SIZE]; - float get_cost(int cutsize) - { - assert(CUT_SIZE_IS_VALID(cutsize - 1)); - return cut_cost[cutsize - 1]; - } - - /* - * This saves the cut size of this child, when parent is reaching - * its minimum cut with the given cut size - */ - int cut_size[MAX_CUT_SIZE]; - int get_cut_size(int parent_cut_size) - { - assert(CUT_SIZE_IS_VALID(parent_cut_size - 1)); - return cut_size[parent_cut_size - 1]; - } - - /* - * Reorganize the node based on calculated cut costs - */ - int best_cutsize; - void set_cut(int cutsize, OVBVHNode ***cut) - { - if (cutsize == 1) { - **cut = this; - *cut = &(**cut)->sibling; - } - else { - if (cutsize > MAX_CUT_SIZE) { - for (OVBVHNode *child = this->child; child && RE_rayobject_isAligned(child); child = child->sibling) { - child->set_cut(1, cut); - cutsize--; - } - assert(cutsize == 0); - } - else { - for (OVBVHNode *child = this->child; child && RE_rayobject_isAligned(child); child = child->sibling) { - child->set_cut(child->get_cut_size(cutsize), cut); - } - } - } - } - - void optimize() - { - if (RE_rayobject_isAligned(this->child)) { - //Calc new childs - if (this->best_cutsize != CUT_SIZE_INVALID) { - OVBVHNode **cut = &(this->child); - set_cut(this->best_cutsize, &cut); - *cut = NULL; - } - - //Optimize new childs - for (OVBVHNode *child = this->child; child && RE_rayobject_isAligned(child); child = child->sibling) - child->optimize(); - } - } -}; - -/* - * Calculates an optimal SIMD packing - * - */ -template<class Node, class TestCost> -struct VBVH_optimalPackSIMD { - TestCost testcost; - - VBVH_optimalPackSIMD(TestCost testcost) - { - this->testcost = testcost; - } - - /* - * calc best cut on a node - */ - struct calc_best { - Node *child[MAX_OPTIMIZE_CHILDS]; - float child_hit_prob[MAX_OPTIMIZE_CHILDS]; - - calc_best(Node *node) - { - int nchilds = 0; - //Fetch childs and needed data - { - float parent_area = bb_area(node->bb, node->bb + 3); - for (Node *child = node->child; child && RE_rayobject_isAligned(child); child = child->sibling) { - this->child[nchilds] = child; - this->child_hit_prob[nchilds] = (parent_area != 0.0f) ? bb_area(child->bb, child->bb + 3) / parent_area : 1.0f; - nchilds++; - } - - assert(nchilds >= 2 && nchilds <= MAX_OPTIMIZE_CHILDS); - } - - - //Build DP table to find minimum cost to represent this node with a given cutsize - int bt[MAX_OPTIMIZE_CHILDS + 1][MAX_CUT_SIZE + 1]; //backtrace table - float cost[MAX_OPTIMIZE_CHILDS + 1][MAX_CUT_SIZE + 1]; //cost table (can be reduced to float[2][MAX_CUT_COST]) - - for (int i = 0; i <= nchilds; i++) { - for (int j = 0; j <= MAX_CUT_SIZE; j++) { - cost[i][j] = INFINITY; - } - } - - cost[0][0] = 0; - - for (int i = 1; i <= nchilds; i++) { - for (int size = i - 1; size /*+(nchilds-i)*/ <= MAX_CUT_SIZE; size++) { - for (int cut = 1; cut + size /*+(nchilds-i)*/ <= MAX_CUT_SIZE; cut++) { - float new_cost = cost[i - 1][size] + child_hit_prob[i - 1] * child[i - 1]->get_cost(cut); - if (new_cost < cost[i][size + cut]) { - cost[i][size + cut] = new_cost; - bt[i][size + cut] = cut; - } - } - } - } - - /* Save the ways to archive the minimum cost with a given cutsize */ - for (int i = nchilds; i <= MAX_CUT_SIZE; i++) { - node->cut_cost[i - 1] = cost[nchilds][i]; - if (cost[nchilds][i] < INFINITY) { - int current_size = i; - for (int j = nchilds; j > 0; j--) { - child[j - 1]->cut_size[i - 1] = bt[j][current_size]; - current_size -= bt[j][current_size]; - } - } - } - } - }; - - void calc_costs(Node *node) - { - - if (RE_rayobject_isAligned(node->child) ) { - int nchilds = 0; - for (Node *child = node->child; child && RE_rayobject_isAligned(child); child = child->sibling) { - calc_costs(child); - nchilds++; - } - - for (int i = 0; i < MAX_CUT_SIZE; i++) - node->cut_cost[i] = INFINITY; - - //We are not allowed to look on nodes with with so many childs - if (nchilds > MAX_CUT_SIZE) { - float cost = 0; - - float parent_area = bb_area(node->bb, node->bb + 3); - for (Node *child = node->child; child && RE_rayobject_isAligned(child); child = child->sibling) { - cost += ((parent_area != 0.0f) ? (bb_area(child->bb, child->bb + 3) / parent_area) : 1.0f) * child->get_cost(1); - } - - cost += testcost(nchilds); - node->cut_cost[0] = cost; - node->best_cutsize = nchilds; - } - else { - calc_best calc(node); - - //calc expected cost if we optimaly pack this node - for (int cutsize = nchilds; cutsize <= MAX_CUT_SIZE; cutsize++) { - float m = node->get_cost(cutsize) + testcost(cutsize); - if (m < node->cut_cost[0]) { - node->cut_cost[0] = m; - node->best_cutsize = cutsize; - } - } - } - - if (node->cut_cost[0] == INFINITY) { - node->best_cutsize = CUT_SIZE_INVALID; - } - } - else { - node->cut_cost[0] = 1.0f; - for (int i = 1; i < MAX_CUT_SIZE; i++) - node->cut_cost[i] = INFINITY; - - /* node->best_cutsize can remain unset here */ - } - } - - Node *transform(Node *node) - { - if (RE_rayobject_isAligned(node->child)) { -#ifdef DEBUG - static int num = 0; - bool first = false; - if (num == 0) { num++; first = true; } -#endif - - calc_costs(node); - -#ifdef DEBUG - if (first && G.debug) { - printf("expected cost = %f (%d)\n", node->cut_cost[0], node->best_cutsize); - } -#endif - node->optimize(); - } - return node; - } -}; diff --git a/source/blender/render/intern/raytrace/svbvh.h b/source/blender/render/intern/raytrace/svbvh.h deleted file mode 100644 index 0a5690deb46..00000000000 --- a/source/blender/render/intern/raytrace/svbvh.h +++ /dev/null @@ -1,317 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2009 Blender Foundation. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): André Pinto. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/render/intern/raytrace/svbvh.h - * \ingroup render - */ - -#ifndef __SVBVH_H__ -#define __SVBVH_H__ - -#ifdef __SSE__ - -#include "bvh.h" -#include "BLI_memarena.h" -#include <algorithm> - -struct SVBVHNode { - float child_bb[24]; - SVBVHNode *child[4]; - int nchilds; -}; - -static int svbvh_bb_intersect_test_simd4(const Isect *isec, const __m128 *bb_group) -{ - const __m128 tmin0 = _mm_setzero_ps(); - const __m128 tmax0 = _mm_set_ps1(isec->dist); - - const __m128 start0 = _mm_set_ps1(isec->start[0]); - const __m128 start1 = _mm_set_ps1(isec->start[1]); - const __m128 start2 = _mm_set_ps1(isec->start[2]); - const __m128 sub0 = _mm_sub_ps(bb_group[isec->bv_index[0]], start0); - const __m128 sub1 = _mm_sub_ps(bb_group[isec->bv_index[1]], start0); - const __m128 sub2 = _mm_sub_ps(bb_group[isec->bv_index[2]], start1); - const __m128 sub3 = _mm_sub_ps(bb_group[isec->bv_index[3]], start1); - const __m128 sub4 = _mm_sub_ps(bb_group[isec->bv_index[4]], start2); - const __m128 sub5 = _mm_sub_ps(bb_group[isec->bv_index[5]], start2); - const __m128 idot_axis0 = _mm_set_ps1(isec->idot_axis[0]); - const __m128 idot_axis1 = _mm_set_ps1(isec->idot_axis[1]); - const __m128 idot_axis2 = _mm_set_ps1(isec->idot_axis[2]); - const __m128 mul0 = _mm_mul_ps(sub0, idot_axis0); - const __m128 mul1 = _mm_mul_ps(sub1, idot_axis0); - const __m128 mul2 = _mm_mul_ps(sub2, idot_axis1); - const __m128 mul3 = _mm_mul_ps(sub3, idot_axis1); - const __m128 mul4 = _mm_mul_ps(sub4, idot_axis2); - const __m128 mul5 = _mm_mul_ps(sub5, idot_axis2); - const __m128 tmin1 = _mm_max_ps(tmin0, mul0); - const __m128 tmax1 = _mm_min_ps(tmax0, mul1); - const __m128 tmin2 = _mm_max_ps(tmin1, mul2); - const __m128 tmax2 = _mm_min_ps(tmax1, mul3); - const __m128 tmin3 = _mm_max_ps(tmin2, mul4); - const __m128 tmax3 = _mm_min_ps(tmax2, mul5); - - return _mm_movemask_ps(_mm_cmpge_ps(tmax3, tmin3)); -} - -static int svbvh_bb_intersect_test(const Isect *isec, const float *_bb) -{ - const float *bb = _bb; - - float t1x = (bb[isec->bv_index[0]] - isec->start[0]) * isec->idot_axis[0]; - float t2x = (bb[isec->bv_index[1]] - isec->start[0]) * isec->idot_axis[0]; - float t1y = (bb[isec->bv_index[2]] - isec->start[1]) * isec->idot_axis[1]; - float t2y = (bb[isec->bv_index[3]] - isec->start[1]) * isec->idot_axis[1]; - float t1z = (bb[isec->bv_index[4]] - isec->start[2]) * isec->idot_axis[2]; - float t2z = (bb[isec->bv_index[5]] - isec->start[2]) * isec->idot_axis[2]; - - RE_RC_COUNT(isec->raycounter->bb.test); - - if (t1x > t2y || t2x < t1y || t1x > t2z || t2x < t1z || t1y > t2z || t2y < t1z) return 0; - if (t2x < 0.0f || t2y < 0.0f || t2z < 0.0f) return 0; - if (t1x > isec->dist || t1y > isec->dist || t1z > isec->dist) return 0; - - RE_RC_COUNT(isec->raycounter->bb.hit); - - return 1; -} - -static bool svbvh_node_is_leaf(const SVBVHNode *node) -{ - return !RE_rayobject_isAligned(node); -} - -template<int MAX_STACK_SIZE, bool SHADOW> -static int svbvh_node_stack_raycast(SVBVHNode *root, Isect *isec) -{ - SVBVHNode *stack[MAX_STACK_SIZE], *node; - int hit = 0, stack_pos = 0; - - stack[stack_pos++] = root; - - while (stack_pos) { - node = stack[--stack_pos]; - - if (!svbvh_node_is_leaf(node)) { - int nchilds = node->nchilds; - - if (nchilds == 4) { - float *child_bb = node->child_bb; - int res = svbvh_bb_intersect_test_simd4(isec, ((__m128 *) (child_bb))); - SVBVHNode **child = node->child; - - RE_RC_COUNT(isec->raycounter->simd_bb.test); - - if (res & 1) { stack[stack_pos++] = child[0]; RE_RC_COUNT(isec->raycounter->simd_bb.hit); } - if (res & 2) { stack[stack_pos++] = child[1]; RE_RC_COUNT(isec->raycounter->simd_bb.hit); } - if (res & 4) { stack[stack_pos++] = child[2]; RE_RC_COUNT(isec->raycounter->simd_bb.hit); } - if (res & 8) { stack[stack_pos++] = child[3]; RE_RC_COUNT(isec->raycounter->simd_bb.hit); } - } - else { - float *child_bb = node->child_bb; - SVBVHNode **child = node->child; - int i; - - for (i = 0; i < nchilds; i++) { - if (svbvh_bb_intersect_test(isec, (float *)child_bb + 6 * i)) { - stack[stack_pos++] = child[i]; - } - } - } - } - else { - hit |= RE_rayobject_intersect((RayObject *)node, isec); - if (SHADOW && hit) break; - } - } - - return hit; -} - - -template<> -inline void bvh_node_merge_bb<SVBVHNode>(SVBVHNode *node, float min[3], float max[3]) -{ - if (is_leaf(node)) { - RE_rayobject_merge_bb((RayObject *)node, min, max); - } - else { - int i; - for (i = 0; i + 4 <= node->nchilds; i += 4) { - float *res = node->child_bb + 6 * i; - for (int j = 0; j < 3; j++) { - min[j] = min_ff(min[j], - min_ffff(res[4 * j + 0], - res[4 * j + 1], - res[4 * j + 2], - res[4 * j + 3])); - } - for (int j = 0; j < 3; j++) { - max[j] = max_ff(max[j], - max_ffff(res[4 * (j + 3) + 0], - res[4 * (j + 3) + 1], - res[4 * (j + 3) + 2], - res[4 * (j + 3) + 3])); - } - } - - for (; i < node->nchilds; i++) { - DO_MIN(node->child_bb + 6 * i, min); - DO_MAX(node->child_bb + 3 + 6 * i, max); - } - } -} - - - -/* - * Builds a SVBVH tree form a VBVHTree - */ -template<class OldNode> -struct Reorganize_SVBVH { - MemArena *arena; - - float childs_per_node; - int nodes_with_childs[16]; - int useless_bb; - int nodes; - - Reorganize_SVBVH(MemArena *a) - { - arena = a; - nodes = 0; - childs_per_node = 0; - useless_bb = 0; - - for (int i = 0; i < 16; i++) { - nodes_with_childs[i] = 0; - } - } - - ~Reorganize_SVBVH() - { -#if 0 - { - printf("%f childs per node\n", childs_per_node / nodes); - printf("%d childs BB are useless\n", useless_bb); - for (int i = 0; i < 16; i++) { - printf("%i childs per node: %d/%d = %f\n", i, nodes_with_childs[i], nodes, nodes_with_childs[i] / float(nodes)); - } - } -#endif - } - - SVBVHNode *create_node(int nchilds) - { - SVBVHNode *node = (SVBVHNode *)BLI_memarena_alloc(arena, sizeof(SVBVHNode)); - node->nchilds = nchilds; - - return node; - } - - void copy_bb(float bb[6], const float old_bb[6]) - { - std::copy(old_bb, old_bb + 6, bb); - } - - void prepare_for_simd(SVBVHNode *node) - { - int i = 0; - while (i + 4 <= node->nchilds) { - float vec_tmp[4 * 6]; - float *res = node->child_bb + 6 * i; - std::copy(res, res + 6 * 4, vec_tmp); - - for (int j = 0; j < 6; j++) { - res[4 * j + 0] = vec_tmp[6 * 0 + j]; - res[4 * j + 1] = vec_tmp[6 * 1 + j]; - res[4 * j + 2] = vec_tmp[6 * 2 + j]; - res[4 * j + 3] = vec_tmp[6 * 3 + j]; - } - - i += 4; - } - } - - /* amt must be power of two */ - inline int padup(int num, int amt) - { - return ((num + (amt - 1)) & ~(amt - 1)); - } - - SVBVHNode *transform(OldNode *old) - { - if (is_leaf(old)) - return (SVBVHNode *)old; - if (is_leaf(old->child)) - return (SVBVHNode *)old->child; - - int nchilds = count_childs(old); - int alloc_childs = nchilds; - if (nchilds % 4 > 2) - alloc_childs = padup(nchilds, 4); - - SVBVHNode *node = create_node(alloc_childs); - - childs_per_node += nchilds; - nodes++; - if (nchilds < 16) - nodes_with_childs[nchilds]++; - - useless_bb += alloc_childs - nchilds; - while (alloc_childs > nchilds) { - const static float def_bb[6] = {FLT_MAX, FLT_MAX, FLT_MAX, -FLT_MAX, -FLT_MAX, -FLT_MAX}; - alloc_childs--; - node->child[alloc_childs] = NULL; - copy_bb(node->child_bb + alloc_childs * 6, def_bb); - } - - int i = nchilds; - for (OldNode *o_child = old->child; o_child; o_child = o_child->sibling) { - i--; - node->child[i] = transform(o_child); - if (is_leaf(o_child)) { - float bb[6]; - INIT_MINMAX(bb, bb + 3); - RE_rayobject_merge_bb((RayObject *)o_child, bb, bb + 3); - copy_bb(node->child_bb + i * 6, bb); - break; - } - else { - copy_bb(node->child_bb + i * 6, o_child->bb); - } - } - assert(i == 0); - - prepare_for_simd(node); - - return node; - } -}; - -#endif /* __SSE__ */ - -#endif /* __SVBVH_H__ */ diff --git a/source/blender/render/intern/raytrace/vbvh.h b/source/blender/render/intern/raytrace/vbvh.h deleted file mode 100644 index 0b0bbd19116..00000000000 --- a/source/blender/render/intern/raytrace/vbvh.h +++ /dev/null @@ -1,238 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2009 Blender Foundation. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): André Pinto. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/render/intern/raytrace/vbvh.h - * \ingroup render - */ - - -#include <assert.h> -#include <algorithm> - -#include "BLI_memarena.h" - -#include "rayobject_rtbuild.h" - -/* - * VBVHNode represents a BVHNode with support for a variable number of childrens - */ -struct VBVHNode { - float bb[6]; - - VBVHNode *child; - VBVHNode *sibling; -}; - - -/* - * Push nodes (used on dfs) - */ -template<class Node> -inline static void bvh_node_push_childs(Node *node, Isect *UNUSED(isec), Node **stack, int &stack_pos) -{ - Node *child = node->child; - - if (is_leaf(child)) { - stack[stack_pos++] = child; - } - else { - while (child) { - /* Skips BB tests on primitives */ -#if 0 - if (is_leaf(child->child)) { - stack[stack_pos++] = child->child; - } - else -#endif - { - stack[stack_pos++] = child; - } - - child = child->sibling; - } - } -} - - -template<class Node> -static int count_childs(Node *parent) -{ - int n = 0; - for (Node *i = parent->child; i; i = i->sibling) { - n++; - if (is_leaf(i)) - break; - } - - return n; -} - - -template<class Node> -static void append_sibling(Node *node, Node *sibling) -{ - while (node->sibling) - node = node->sibling; - - node->sibling = sibling; -} - - -/* - * Builds a binary VBVH from a rtbuild - */ -template<class Node> -struct BuildBinaryVBVH { - MemArena *arena; - RayObjectControl *control; - - void test_break() - { - if (RE_rayobjectcontrol_test_break(control)) - throw "Stop"; - } - - BuildBinaryVBVH(MemArena *a, RayObjectControl *c) - { - arena = a; - control = c; - } - - Node *create_node() - { - Node *node = (Node *)BLI_memarena_alloc(arena, sizeof(Node) ); - assert(RE_rayobject_isAligned(node)); - - node->sibling = NULL; - node->child = NULL; - - return node; - } - - int rtbuild_split(RTBuilder *builder) - { - return ::rtbuild_heuristic_object_split(builder, 2); - } - - Node *transform(RTBuilder *builder) - { - try - { - return _transform(builder); - - } catch (...) - { - } - return NULL; - } - - Node *_transform(RTBuilder *builder) - { - int size = rtbuild_size(builder); - - if (size == 0) { - return NULL; - } - else if (size == 1) { - Node *node = create_node(); - INIT_MINMAX(node->bb, node->bb + 3); - rtbuild_merge_bb(builder, node->bb, node->bb + 3); - node->child = (Node *) rtbuild_get_primitive(builder, 0); - return node; - } - else { - test_break(); - - Node *node = create_node(); - - Node **child = &node->child; - - int nc = rtbuild_split(builder); - INIT_MINMAX(node->bb, node->bb + 3); - - assert(nc == 2); - for (int i = 0; i < nc; i++) { - RTBuilder tmp; - rtbuild_get_child(builder, i, &tmp); - - *child = _transform(&tmp); - DO_MIN((*child)->bb, node->bb); - DO_MAX((*child)->bb + 3, node->bb + 3); - child = &((*child)->sibling); - } - - *child = NULL; - return node; - } - } -}; - -#if 0 -template<class Tree, class OldNode> -struct Reorganize_VBVH { - Tree *tree; - - Reorganize_VBVH(Tree *t) - { - tree = t; - } - - VBVHNode *create_node() - { - VBVHNode *node = (VBVHNode *)BLI_memarena_alloc(tree->node_arena, sizeof(VBVHNode)); - return node; - } - - void copy_bb(VBVHNode *node, OldNode *old) - { - std::copy(old->bb, old->bb + 6, node->bb); - } - - VBVHNode *transform(OldNode *old) - { - if (is_leaf(old)) - return (VBVHNode *)old; - - VBVHNode *node = create_node(); - VBVHNode **child_ptr = &node->child; - node->sibling = 0; - - copy_bb(node, old); - - for (OldNode *o_child = old->child; o_child; o_child = o_child->sibling) - { - VBVHNode *n_child = transform(o_child); - *child_ptr = n_child; - if (is_leaf(n_child)) return node; - child_ptr = &n_child->sibling; - } - *child_ptr = 0; - - return node; - } -}; -#endif diff --git a/source/blender/render/intern/source/bake.c b/source/blender/render/intern/source/bake.c deleted file mode 100644 index 4a7962b1776..00000000000 --- a/source/blender/render/intern/source/bake.c +++ /dev/null @@ -1,1342 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * Contributors: 2004/2005/2006 Blender Foundation, full recode - * Contributors: Vertex color baking, Copyright 2011 AutoCRC - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/render/intern/source/bake.c - * \ingroup render - */ - - -/* system includes */ -#include <stdio.h> -#include <string.h> - -/* External modules: */ -#include "MEM_guardedalloc.h" - -#include "BLI_math.h" -#include "BLI_rand.h" -#include "BLI_threads.h" -#include "BLI_utildefines.h" - -#include "DNA_image_types.h" -#include "DNA_material_types.h" -#include "DNA_mesh_types.h" -#include "DNA_meshdata_types.h" - -#include "BKE_customdata.h" -#include "BKE_global.h" -#include "BKE_image.h" -#include "BKE_main.h" -#include "BKE_node.h" -#include "BKE_scene.h" -#include "BKE_library.h" - -#include "IMB_imbuf_types.h" -#include "IMB_imbuf.h" -#include "IMB_colormanagement.h" - -/* local include */ -#include "rayintersection.h" -#include "rayobject.h" -#include "render_types.h" -#include "renderdatabase.h" -#include "shading.h" -#include "zbuf.h" - -#include "PIL_time.h" - -/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -/* defined in pipeline.c, is hardcopy of active dynamic allocated Render */ -/* only to be used here in this file, it's for speed */ -extern struct Render R; -/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ - - -/* ************************* bake ************************ */ - - -typedef struct BakeShade { - int thread; - - ShadeSample ssamp; - ObjectInstanceRen *obi; - VlakRen *vlr; - - ZSpan *zspan; - Image *ima; - ImBuf *ibuf; - - int rectx, recty, quad, type, vdone; - bool ready; - - float dir[3]; - Object *actob; - - /* Output: vertex color or image data. If vcol is not NULL, rect and - * rect_float should be NULL. */ - MPoly *mpoly; - MLoop *mloop; - MLoopCol *vcol; - - unsigned int *rect; - float *rect_float; - - /* displacement buffer used for normalization with unknown maximal distance */ - bool use_displacement_buffer; - float *displacement_buffer; - float displacement_min, displacement_max; - - bool use_mask; - char *rect_mask; /* bake pixel mask */ - - float dxco[3], dyco[3]; - - short *do_update; - - struct ColorSpace *rect_colorspace; -} BakeShade; - -static void bake_set_shade_input(ObjectInstanceRen *obi, VlakRen *vlr, ShadeInput *shi, int quad, int UNUSED(isect), int x, int y, float u, float v) -{ - if (quad) - shade_input_set_triangle_i(shi, obi, vlr, 0, 2, 3); - else - shade_input_set_triangle_i(shi, obi, vlr, 0, 1, 2); - - /* cache for shadow */ - shi->samplenr = R.shadowsamplenr[shi->thread]++; - - shi->mask = 0xFFFF; /* all samples */ - - shi->u = -u; - shi->v = -v; - shi->xs = x; - shi->ys = y; - - shade_input_set_uv(shi); - shade_input_set_normals(shi); - - /* no normal flip */ - if (shi->flippednor) - shade_input_flip_normals(shi); - - /* set up view vector to look right at the surface (note that the normal - * is negated in the renderer so it does not need to be done here) */ - shi->view[0] = shi->vn[0]; - shi->view[1] = shi->vn[1]; - shi->view[2] = shi->vn[2]; -} - -static void bake_shade(void *handle, Object *ob, ShadeInput *shi, int UNUSED(quad), int x, int y, float UNUSED(u), float UNUSED(v), float *tvn, float *ttang) -{ - BakeShade *bs = handle; - ShadeSample *ssamp = &bs->ssamp; - ShadeResult shr; - VlakRen *vlr = shi->vlr; - - shade_input_init_material(shi); - - if (bs->type == RE_BAKE_AO) { - ambient_occlusion(shi); - - if (R.r.bake_flag & R_BAKE_NORMALIZE) { - copy_v3_v3(shr.combined, shi->ao); - } - else { - zero_v3(shr.combined); - environment_lighting_apply(shi, &shr); - } - } - else { - if (bs->type == RE_BAKE_SHADOW) /* Why do shadows set the color anyhow?, ignore material color for baking */ - shi->r = shi->g = shi->b = 1.0f; - - shade_input_set_shade_texco(shi); - - /* only do AO for a full bake (and obviously AO bakes) - * AO for light bakes is a leftover and might not be needed */ - if (ELEM(bs->type, RE_BAKE_ALL, RE_BAKE_AO, RE_BAKE_LIGHT)) - shade_samples_do_AO(ssamp); - - if (shi->mat->nodetree && shi->mat->use_nodes) { - ntreeShaderExecTree(shi->mat->nodetree, shi, &shr); - shi->mat = vlr->mat; /* shi->mat is being set in nodetree */ - } - else - shade_material_loop(shi, &shr); - - if (bs->type == RE_BAKE_NORMALS) { - float nor[3]; - - copy_v3_v3(nor, shi->vn); - - if (R.r.bake_normal_space == R_BAKE_SPACE_CAMERA) { - /* pass */ - } - else if (R.r.bake_normal_space == R_BAKE_SPACE_TANGENT) { - float mat[3][3], imat[3][3]; - - /* bitangent */ - if (tvn && ttang) { - copy_v3_v3(mat[0], ttang); - cross_v3_v3v3(mat[1], tvn, ttang); - mul_v3_fl(mat[1], ttang[3]); - copy_v3_v3(mat[2], tvn); - } - else { - copy_v3_v3(mat[0], shi->nmaptang); - cross_v3_v3v3(mat[1], shi->nmapnorm, shi->nmaptang); - mul_v3_fl(mat[1], shi->nmaptang[3]); - copy_v3_v3(mat[2], shi->nmapnorm); - } - - invert_m3_m3(imat, mat); - mul_m3_v3(imat, nor); - } - else if (R.r.bake_normal_space == R_BAKE_SPACE_OBJECT) - mul_mat3_m4_v3(ob->imat_ren, nor); /* ob->imat_ren includes viewinv! */ - else if (R.r.bake_normal_space == R_BAKE_SPACE_WORLD) - mul_mat3_m4_v3(R.viewinv, nor); - - normalize_v3(nor); /* in case object has scaling */ - - /* The invert of the red channel is to make - * the normal map compliant with the outside world. - * It needs to be done because in Blender - * the normal used in the renderer points inward. It is generated - * this way in calc_vertexnormals(). Should this ever change - * this negate must be removed. - * - * there is also a small 1e-5f bias for precision issues. otherwise - * we randomly get 127 or 128 for neutral colors. we choose 128 - * because it is the convention flat color. * */ - shr.combined[0] = (-nor[0]) / 2.0f + 0.5f + 1e-5f; - shr.combined[1] = nor[1] / 2.0f + 0.5f + 1e-5f; - shr.combined[2] = nor[2] / 2.0f + 0.5f + 1e-5f; - } - else if (bs->type == RE_BAKE_TEXTURE) { - copy_v3_v3(shr.combined, &shi->r); - shr.alpha = shi->alpha; - } - else if (bs->type == RE_BAKE_SHADOW) { - copy_v3_v3(shr.combined, shr.shad); - shr.alpha = shi->alpha; - } - else if (bs->type == RE_BAKE_SPEC_COLOR) { - copy_v3_v3(shr.combined, &shi->specr); - shr.alpha = 1.0f; - } - else if (bs->type == RE_BAKE_SPEC_INTENSITY) { - copy_v3_fl(shr.combined, shi->spec); - shr.alpha = 1.0f; - } - else if (bs->type == RE_BAKE_MIRROR_COLOR) { - copy_v3_v3(shr.combined, &shi->mirr); - shr.alpha = 1.0f; - } - else if (bs->type == RE_BAKE_MIRROR_INTENSITY) { - copy_v3_fl(shr.combined, shi->ray_mirror); - shr.alpha = 1.0f; - } - else if (bs->type == RE_BAKE_ALPHA) { - copy_v3_fl(shr.combined, shi->alpha); - shr.alpha = 1.0f; - } - else if (bs->type == RE_BAKE_EMIT) { - copy_v3_fl(shr.combined, shi->emit); - shr.alpha = 1.0f; - } - else if (bs->type == RE_BAKE_VERTEX_COLORS) { - copy_v3_v3(shr.combined, shi->vcol); - shr.alpha = shi->vcol[3]; - } - } - - if (bs->rect_float && !bs->vcol) { - float *col = bs->rect_float + 4 * (bs->rectx * y + x); - copy_v3_v3(col, shr.combined); - if (bs->type == RE_BAKE_ALL || bs->type == RE_BAKE_TEXTURE || bs->type == RE_BAKE_VERTEX_COLORS) { - col[3] = shr.alpha; - } - else { - col[3] = 1.0; - } - } - else { - /* Target is char (LDR). */ - unsigned char col[4]; - - if (ELEM(bs->type, RE_BAKE_ALL, RE_BAKE_TEXTURE)) { - float rgb[3]; - - copy_v3_v3(rgb, shr.combined); - if (R.scene_color_manage) { - /* Vertex colors have no way to specify color space, so they - * default to sRGB. */ - if (!bs->vcol) - IMB_colormanagement_scene_linear_to_colorspace_v3(rgb, bs->rect_colorspace); - else - linearrgb_to_srgb_v3_v3(rgb, rgb); - } - rgb_float_to_uchar(col, rgb); - } - else { - rgb_float_to_uchar(col, shr.combined); - } - - if (ELEM(bs->type, RE_BAKE_ALL, RE_BAKE_TEXTURE, RE_BAKE_VERTEX_COLORS)) { - col[3] = unit_float_to_uchar_clamp(shr.alpha); - } - else { - col[3] = 255; - } - - if (bs->vcol) { - /* Vertex color baking. Vcol has no useful alpha channel (it exists - * but is used only for vertex painting). */ - bs->vcol->r = col[0]; - bs->vcol->g = col[1]; - bs->vcol->b = col[2]; - } - else { - unsigned char *imcol = (unsigned char *)(bs->rect + bs->rectx * y + x); - copy_v4_v4_uchar(imcol, col); - } - - } - - if (bs->rect_mask) { - bs->rect_mask[bs->rectx * y + x] = FILTER_MASK_USED; - } - - if (bs->do_update) { - *bs->do_update = true; - } -} - -static void bake_displacement(void *handle, ShadeInput *UNUSED(shi), float dist, int x, int y) -{ - BakeShade *bs = handle; - float disp; - - if (R.r.bake_flag & R_BAKE_NORMALIZE) { - if (R.r.bake_maxdist) - disp = (dist + R.r.bake_maxdist) / (R.r.bake_maxdist * 2); /* alter the range from [-bake_maxdist, bake_maxdist] to [0, 1]*/ - else - disp = dist; - } - else { - disp = 0.5f + dist; /* alter the range from [-0.5,0.5] to [0,1]*/ - } - - if (bs->displacement_buffer) { - float *displacement = bs->displacement_buffer + (bs->rectx * y + x); - *displacement = disp; - bs->displacement_min = min_ff(bs->displacement_min, disp); - bs->displacement_max = max_ff(bs->displacement_max, disp); - } - - if (bs->rect_float && !bs->vcol) { - float *col = bs->rect_float + 4 * (bs->rectx * y + x); - col[0] = col[1] = col[2] = disp; - col[3] = 1.0f; - } - else { - /* Target is char (LDR). */ - unsigned char col[4]; - col[0] = col[1] = col[2] = unit_float_to_uchar_clamp(disp); - col[3] = 255; - - if (bs->vcol) { - /* Vertex color baking. Vcol has no useful alpha channel (it exists - * but is used only for vertex painting). */ - bs->vcol->r = col[0]; - bs->vcol->g = col[1]; - bs->vcol->b = col[2]; - } - else { - unsigned char *imcol = (unsigned char *)(bs->rect + bs->rectx * y + x); - copy_v4_v4_uchar(imcol, col); - } - } - if (bs->rect_mask) { - bs->rect_mask[bs->rectx * y + x] = FILTER_MASK_USED; - } -} - -static int bake_intersect_tree(RayObject *raytree, Isect *isect, float *start, float *dir, float sign, float *hitco, float *dist) -{ - float maxdist; - int hit; - - /* might be useful to make a user setting for maxsize*/ - if (R.r.bake_maxdist > 0.0f) - maxdist = R.r.bake_maxdist; - else - maxdist = RE_RAYTRACE_MAXDIST + R.r.bake_biasdist; - - /* 'dir' is always normalized */ - madd_v3_v3v3fl(isect->start, start, dir, -R.r.bake_biasdist); - - mul_v3_v3fl(isect->dir, dir, sign); - - isect->dist = maxdist; - - hit = RE_rayobject_raycast(raytree, isect); - if (hit) { - madd_v3_v3v3fl(hitco, isect->start, isect->dir, isect->dist); - - *dist = isect->dist; - } - - return hit; -} - -static void bake_set_vlr_dxyco(BakeShade *bs, float *uv1, float *uv2, float *uv3) -{ - VlakRen *vlr = bs->vlr; - float A, d1, d2, d3, *v1, *v2, *v3; - - if (bs->quad) { - v1 = vlr->v1->co; - v2 = vlr->v3->co; - v3 = vlr->v4->co; - } - else { - v1 = vlr->v1->co; - v2 = vlr->v2->co; - v3 = vlr->v3->co; - } - - /* formula derived from barycentric coordinates: - * (uvArea1*v1 + uvArea2*v2 + uvArea3*v3)/uvArea - * then taking u and v partial derivatives to get dxco and dyco */ - A = (uv2[0] - uv1[0]) * (uv3[1] - uv1[1]) - (uv3[0] - uv1[0]) * (uv2[1] - uv1[1]); - - if (fabsf(A) > FLT_EPSILON) { - A = 0.5f / A; - - d1 = uv2[1] - uv3[1]; - d2 = uv3[1] - uv1[1]; - d3 = uv1[1] - uv2[1]; - bs->dxco[0] = (v1[0] * d1 + v2[0] * d2 + v3[0] * d3) * A; - bs->dxco[1] = (v1[1] * d1 + v2[1] * d2 + v3[1] * d3) * A; - bs->dxco[2] = (v1[2] * d1 + v2[2] * d2 + v3[2] * d3) * A; - - d1 = uv3[0] - uv2[0]; - d2 = uv1[0] - uv3[0]; - d3 = uv2[0] - uv1[0]; - bs->dyco[0] = (v1[0] * d1 + v2[0] * d2 + v3[0] * d3) * A; - bs->dyco[1] = (v1[1] * d1 + v2[1] * d2 + v3[1] * d3) * A; - bs->dyco[2] = (v1[2] * d1 + v2[2] * d2 + v3[2] * d3) * A; - } - else { - bs->dxco[0] = bs->dxco[1] = bs->dxco[2] = 0.0f; - bs->dyco[0] = bs->dyco[1] = bs->dyco[2] = 0.0f; - } - - if (bs->obi->flag & R_TRANSFORMED) { - mul_m3_v3(bs->obi->nmat, bs->dxco); - mul_m3_v3(bs->obi->nmat, bs->dyco); - } -} - -static void do_bake_shade(void *handle, int x, int y, float u, float v) -{ - BakeShade *bs = handle; - VlakRen *vlr = bs->vlr; - ObjectInstanceRen *obi = bs->obi; - Object *ob = obi->obr->ob; - float l, *v1, *v2, *v3, tvn[3], ttang[4]; - int quad; - ShadeSample *ssamp = &bs->ssamp; - ShadeInput *shi = ssamp->shi; - - /* fast threadsafe break test */ - if (R.test_break(R.tbh)) - return; - - /* setup render coordinates */ - if (bs->quad) { - v1 = vlr->v1->co; - v2 = vlr->v3->co; - v3 = vlr->v4->co; - } - else { - v1 = vlr->v1->co; - v2 = vlr->v2->co; - v3 = vlr->v3->co; - } - - l = 1.0f - u - v; - - /* shrink barycentric coordinates inwards slightly to avoid some issues - * where baking selected to active might just miss the other face at the - * near the edge of a face */ - if (bs->actob) { - const float eps = 1.0f - 1e-4f; - float invsum; - - u = (u - 0.5f) * eps + 0.5f; - v = (v - 0.5f) * eps + 0.5f; - l = (l - 0.5f) * eps + 0.5f; - - invsum = 1.0f / (u + v + l); - - u *= invsum; - v *= invsum; - l *= invsum; - } - - /* renderco */ - shi->co[0] = l * v3[0] + u * v1[0] + v * v2[0]; - shi->co[1] = l * v3[1] + u * v1[1] + v * v2[1]; - shi->co[2] = l * v3[2] + u * v1[2] + v * v2[2]; - - /* avoid self shadow with vertex bake from adjacent faces [#33729] */ - if ((bs->vcol != NULL) && (bs->actob == NULL)) { - madd_v3_v3fl(shi->co, vlr->n, 0.0001f); - } - - if (obi->flag & R_TRANSFORMED) - mul_m4_v3(obi->mat, shi->co); - - copy_v3_v3(shi->dxco, bs->dxco); - copy_v3_v3(shi->dyco, bs->dyco); - - quad = bs->quad; - bake_set_shade_input(obi, vlr, shi, quad, 0, x, y, u, v); - - if (bs->type == RE_BAKE_NORMALS && R.r.bake_normal_space == R_BAKE_SPACE_TANGENT) { - shade_input_set_shade_texco(shi); - copy_v3_v3(tvn, shi->nmapnorm); - copy_v4_v4(ttang, shi->nmaptang); - } - - /* if we are doing selected to active baking, find point on other face */ - if (bs->actob) { - Isect isec, minisec; - float co[3], minco[3], dist, mindist = 0.0f; - int hit, sign, dir = 1; - - /* intersect with ray going forward and backward*/ - hit = 0; - memset(&minisec, 0, sizeof(minisec)); - minco[0] = minco[1] = minco[2] = 0.0f; - - copy_v3_v3(bs->dir, shi->vn); - - for (sign = -1; sign <= 1; sign += 2) { - memset(&isec, 0, sizeof(isec)); - isec.mode = RE_RAY_MIRROR; - - isec.orig.ob = obi; - isec.orig.face = vlr; - isec.userdata = bs->actob; - isec.check = RE_CHECK_VLR_BAKE; - isec.skip = RE_SKIP_VLR_NEIGHBOUR; - - if (bake_intersect_tree(R.raytree, &isec, shi->co, shi->vn, sign, co, &dist)) { - if (!hit || len_squared_v3v3(shi->co, co) < len_squared_v3v3(shi->co, minco)) { - minisec = isec; - mindist = dist; - copy_v3_v3(minco, co); - hit = 1; - dir = sign; - } - } - } - - if (ELEM(bs->type, RE_BAKE_DISPLACEMENT, RE_BAKE_DERIVATIVE)) { - if (hit) - bake_displacement(handle, shi, (dir == -1) ? mindist : -mindist, x, y); - else - bake_displacement(handle, shi, 0.0f, x, y); - return; - } - - /* if hit, we shade from the new point, otherwise from point one starting face */ - if (hit) { - obi = (ObjectInstanceRen *)minisec.hit.ob; - vlr = (VlakRen *)minisec.hit.face; - quad = (minisec.isect == 2); - copy_v3_v3(shi->co, minco); - - u = -minisec.u; - v = -minisec.v; - bake_set_shade_input(obi, vlr, shi, quad, 1, x, y, u, v); - } - } - - if (bs->type == RE_BAKE_NORMALS && R.r.bake_normal_space == R_BAKE_SPACE_TANGENT) - bake_shade(handle, ob, shi, quad, x, y, u, v, tvn, ttang); - else - bake_shade(handle, ob, shi, quad, x, y, u, v, NULL, NULL); -} - -static int get_next_bake_face(BakeShade *bs) -{ - ObjectRen *obr; - VlakRen *vlr; - MTFace *tface; - static int v = 0, vdone = false; - static ObjectInstanceRen *obi = NULL; - - if (bs == NULL) { - vlr = NULL; - v = vdone = false; - obi = R.instancetable.first; - return 0; - } - - BLI_thread_lock(LOCK_CUSTOM1); - - for (; obi; obi = obi->next, v = 0) { - obr = obi->obr; - - /* only allow non instances here */ - if (obr->flag & R_INSTANCEABLE) - continue; - - for (; v < obr->totvlak; v++) { - vlr = RE_findOrAddVlak(obr, v); - - if ((bs->actob && bs->actob == obr->ob) || (!bs->actob && (obr->ob->flag & SELECT))) { - if (R.r.bake_flag & R_BAKE_VCOL) { - /* Gather face data for vertex color bake */ - Mesh *me; - int *origindex, vcollayer; - CustomDataLayer *cdl; - - if (obr->ob->type != OB_MESH) - continue; - me = obr->ob->data; - - origindex = RE_vlakren_get_origindex(obr, vlr, 0); - if (origindex == NULL) - continue; - if (*origindex >= me->totpoly) { - /* Small hack for Array modifier, which gives false - * original indices - z0r */ - continue; - } -#if 0 - /* Only shade selected faces. */ - if ((me->mface[*origindex].flag & ME_FACE_SEL) == 0) - continue; -#endif - - vcollayer = CustomData_get_render_layer_index(&me->ldata, CD_MLOOPCOL); - if (vcollayer == -1) - continue; - - cdl = &me->ldata.layers[vcollayer]; - bs->mpoly = me->mpoly + *origindex; - bs->vcol = ((MLoopCol *)cdl->data) + bs->mpoly->loopstart; - bs->mloop = me->mloop + bs->mpoly->loopstart; - - /* Tag mesh for reevaluation. */ - me->id.tag |= LIB_TAG_DOIT; - } - else { - Image *ima = NULL; - ImBuf *ibuf = NULL; - const float vec_alpha[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - const float vec_solid[4] = {0.0f, 0.0f, 0.0f, 1.0f}; - const float nor_alpha[4] = {0.5f, 0.5f, 1.0f, 0.0f}; - const float nor_solid[4] = {0.5f, 0.5f, 1.0f, 1.0f}; - const float disp_alpha[4] = {0.5f, 0.5f, 0.5f, 0.0f}; - const float disp_solid[4] = {0.5f, 0.5f, 0.5f, 1.0f}; - - tface = RE_vlakren_get_tface(obr, vlr, obr->bakemtface, NULL, 0); - - if (!tface || !tface->tpage) - continue; - - ima = tface->tpage; - ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); - - if (ibuf == NULL) - continue; - - if (ibuf->rect == NULL && ibuf->rect_float == NULL) { - BKE_image_release_ibuf(ima, ibuf, NULL); - continue; - } - - if (ibuf->rect_float && !(ibuf->channels == 0 || ibuf->channels == 4)) { - BKE_image_release_ibuf(ima, ibuf, NULL); - continue; - } - - if (ima->flag & IMA_USED_FOR_RENDER) { - ima->id.tag &= ~LIB_TAG_DOIT; - BKE_image_release_ibuf(ima, ibuf, NULL); - continue; - } - - /* find the image for the first time? */ - if (ima->id.tag & LIB_TAG_DOIT) { - ima->id.tag &= ~LIB_TAG_DOIT; - - /* we either fill in float or char, this ensures things go fine */ - if (ibuf->rect_float) - imb_freerectImBuf(ibuf); - /* clear image */ - if (R.r.bake_flag & R_BAKE_CLEAR) { - if (R.r.bake_mode == RE_BAKE_NORMALS && R.r.bake_normal_space == R_BAKE_SPACE_TANGENT) - IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? nor_alpha : nor_solid); - else if (ELEM(R.r.bake_mode, RE_BAKE_DISPLACEMENT, RE_BAKE_DERIVATIVE)) - IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? disp_alpha : disp_solid); - else - IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? vec_alpha : vec_solid); - } - /* might be read by UI to set active image for display */ - R.bakebuf = ima; - } - - /* Tag image for redraw. */ - ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; - BKE_image_release_ibuf(ima, ibuf, NULL); - } - - bs->obi = obi; - bs->vlr = vlr; - bs->vdone++; /* only for error message if nothing was rendered */ - v++; - BLI_thread_unlock(LOCK_CUSTOM1); - return 1; - } - } - } - - BLI_thread_unlock(LOCK_CUSTOM1); - return 0; -} - -static void bake_single_vertex(BakeShade *bs, VertRen *vert, float u, float v) -{ - int *origindex, i; - MLoopCol *basevcol; - MLoop *mloop; - - /* per vertex fixed seed */ - BLI_thread_srandom(bs->thread, vert->index); - - origindex = RE_vertren_get_origindex(bs->obi->obr, vert, 0); - if (!origindex || *origindex == ORIGINDEX_NONE) - return; - - /* Search for matching vertex index and apply shading. */ - for (i = 0; i < bs->mpoly->totloop; i++) { - mloop = bs->mloop + i; - if (mloop->v != *origindex) - continue; - basevcol = bs->vcol; - bs->vcol = basevcol + i; - do_bake_shade(bs, 0, 0, u, v); - bs->vcol = basevcol; - break; - } -} - -/* Bake all vertices of a face. Actually, this still works on a face-by-face - * basis, and each vertex on each face is shaded. Vertex colors are a property - * of loops, not vertices. */ -static void shade_verts(BakeShade *bs) -{ - VlakRen *vlr = bs->vlr; - - /* Disable baking to image; write to vcol instead. vcol pointer is set in - * bake_single_vertex. */ - bs->ima = NULL; - bs->rect = NULL; - bs->rect_float = NULL; - bs->displacement_buffer = NULL; - bs->displacement_min = FLT_MAX; - bs->displacement_max = -FLT_MAX; - - bs->quad = 0; - - /* No anti-aliasing for vertices. */ - zero_v3(bs->dxco); - zero_v3(bs->dyco); - - /* Shade each vertex of the face. u and v are barycentric coordinates; since - * we're only interested in vertices, these will be 0 or 1. */ - if ((vlr->flag & R_FACE_SPLIT) == 0) { - /* Processing triangle face, whole quad, or first half of split quad. */ - - bake_single_vertex(bs, bs->vlr->v1, 1.0f, 0.0f); - bake_single_vertex(bs, bs->vlr->v2, 0.0f, 1.0f); - bake_single_vertex(bs, bs->vlr->v3, 0.0f, 0.0f); - - if (vlr->v4) { - bs->quad = 1; - bake_single_vertex(bs, bs->vlr->v4, 0.0f, 0.0f); - } - } - else { - /* Processing second half of split quad. Only one vertex to go. */ - if (vlr->flag & R_DIVIDE_24) { - bake_single_vertex(bs, bs->vlr->v2, 0.0f, 1.0f); - } - else { - bake_single_vertex(bs, bs->vlr->v3, 0.0f, 0.0f); - } - } -} - -/* already have tested for tface and ima and zspan */ -static void shade_tface(BakeShade *bs) -{ - VlakRen *vlr = bs->vlr; - ObjectInstanceRen *obi = bs->obi; - ObjectRen *obr = obi->obr; - MTFace *tface = RE_vlakren_get_tface(obr, vlr, obr->bakemtface, NULL, 0); - Image *ima = tface->tpage; - float vec[4][2]; - int a, i1, i2, i3; - - /* per face fixed seed */ - BLI_thread_srandom(bs->thread, vlr->index); - - /* check valid zspan */ - if (ima != bs->ima) { - BKE_image_release_ibuf(bs->ima, bs->ibuf, NULL); - - bs->ima = ima; - bs->ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); - /* note, these calls only free/fill contents of zspan struct, not zspan itself */ - zbuf_free_span(bs->zspan); - zbuf_alloc_span(bs->zspan, bs->ibuf->x, bs->ibuf->y, R.clipcrop); - } - - bs->rectx = bs->ibuf->x; - bs->recty = bs->ibuf->y; - bs->rect = bs->ibuf->rect; - bs->rect_colorspace = bs->ibuf->rect_colorspace; - bs->rect_float = bs->ibuf->rect_float; - bs->vcol = NULL; - bs->quad = 0; - bs->rect_mask = NULL; - bs->displacement_buffer = NULL; - - if (bs->use_mask || bs->use_displacement_buffer) { - BakeImBufuserData *userdata = bs->ibuf->userdata; - if (userdata == NULL) { - BLI_thread_lock(LOCK_CUSTOM1); - userdata = bs->ibuf->userdata; - if (userdata == NULL) /* since the thread was locked, its possible another thread alloced the value */ - userdata = MEM_callocN(sizeof(BakeImBufuserData), "BakeImBufuserData"); - - if (bs->use_mask) { - if (userdata->mask_buffer == NULL) { - userdata->mask_buffer = MEM_callocN(sizeof(char) * bs->rectx * bs->recty, "BakeMask"); - } - } - - if (bs->use_displacement_buffer) { - if (userdata->displacement_buffer == NULL) { - userdata->displacement_buffer = MEM_callocN(sizeof(float) * bs->rectx * bs->recty, "BakeDisp"); - } - } - - bs->ibuf->userdata = userdata; - - BLI_thread_unlock(LOCK_CUSTOM1); - } - - bs->rect_mask = userdata->mask_buffer; - bs->displacement_buffer = userdata->displacement_buffer; - } - - /* get pixel level vertex coordinates */ - for (a = 0; a < 4; a++) { - /* Note, workaround for pixel aligned UVs which are common and can screw up our intersection tests - * where a pixel gets in between 2 faces or the middle of a quad, - * camera aligned quads also have this problem but they are less common. - * Add a small offset to the UVs, fixes bug #18685 - Campbell */ - vec[a][0] = tface->uv[a][0] * (float)bs->rectx - (0.5f + 0.001f); - vec[a][1] = tface->uv[a][1] * (float)bs->recty - (0.5f + 0.002f); - } - - /* UV indices have to be corrected for possible quad->tria splits */ - i1 = 0; i2 = 1; i3 = 2; - vlr_set_uv_indices(vlr, &i1, &i2, &i3); - bake_set_vlr_dxyco(bs, vec[i1], vec[i2], vec[i3]); - zspan_scanconvert(bs->zspan, bs, vec[i1], vec[i2], vec[i3], do_bake_shade); - - if (vlr->v4) { - bs->quad = 1; - bake_set_vlr_dxyco(bs, vec[0], vec[2], vec[3]); - zspan_scanconvert(bs->zspan, bs, vec[0], vec[2], vec[3], do_bake_shade); - } -} - -static void *do_bake_thread(void *bs_v) -{ - BakeShade *bs = bs_v; - - while (get_next_bake_face(bs)) { - if (R.r.bake_flag & R_BAKE_VCOL) { - shade_verts(bs); - } - else { - shade_tface(bs); - } - - /* fast threadsafe break test */ - if (R.test_break(R.tbh)) - break; - - /* access is not threadsafe but since its just true/false probably ok - * only used for interactive baking */ - if (bs->do_update) { - *bs->do_update = true; - } - } - bs->ready = true; - - BKE_image_release_ibuf(bs->ima, bs->ibuf, NULL); - - return NULL; -} - -void RE_bake_ibuf_filter(ImBuf *ibuf, char *mask, const int filter) -{ - /* must check before filtering */ - const bool is_new_alpha = (ibuf->planes != R_IMF_PLANES_RGBA) && BKE_imbuf_alpha_test(ibuf); - - /* Margin */ - if (filter) { - IMB_filter_extend(ibuf, mask, filter); - } - - /* if the bake results in new alpha then change the image setting */ - if (is_new_alpha) { - ibuf->planes = R_IMF_PLANES_RGBA; - } - else { - if (filter && ibuf->planes != R_IMF_PLANES_RGBA) { - /* clear alpha added by filtering */ - IMB_rectfill_alpha(ibuf, 1.0f); - } - } -} - -void RE_bake_ibuf_normalize_displacement(ImBuf *ibuf, float *displacement, char *mask, float displacement_min, float displacement_max) -{ - int i; - const float *current_displacement = displacement; - const char *current_mask = mask; - float max_distance; - - max_distance = max_ff(fabsf(displacement_min), fabsf(displacement_max)); - - for (i = 0; i < ibuf->x * ibuf->y; i++) { - if (*current_mask == FILTER_MASK_USED) { - float normalized_displacement; - - if (max_distance > 1e-5f) - normalized_displacement = (*current_displacement + max_distance) / (max_distance * 2); - else - normalized_displacement = 0.5f; - - if (ibuf->rect_float) { - /* currently baking happens to RGBA only */ - float *fp = ibuf->rect_float + i * 4; - fp[0] = fp[1] = fp[2] = normalized_displacement; - fp[3] = 1.0f; - } - - if (ibuf->rect) { - unsigned char *cp = (unsigned char *) (ibuf->rect + i); - cp[0] = cp[1] = cp[2] = unit_float_to_uchar_clamp(normalized_displacement); - cp[3] = 255; - } - } - - current_displacement++; - current_mask++; - } -} - -/* using object selection tags, the faces with UV maps get baked */ -/* render should have been setup */ -/* returns 0 if nothing was handled */ -int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_update, float *progress) -{ - BakeShade *handles; - ListBase threads; - Image *ima; - int a, vdone = false, result = BAKE_RESULT_OK; - bool use_mask = false; - bool use_displacement_buffer = false; - bool do_manage = false; - - if (ELEM(type, RE_BAKE_ALL, RE_BAKE_TEXTURE)) { - do_manage = BKE_scene_check_color_management_enabled(re->scene); - } - - re->scene_color_manage = BKE_scene_check_color_management_enabled(re->scene); - - /* initialize render global */ - R = *re; - R.bakebuf = NULL; - - /* initialize static vars */ - get_next_bake_face(NULL); - - /* do we need a mask? */ - if (re->r.bake_filter) - use_mask = true; - - /* do we need buffer to store displacements */ - if (ELEM(type, RE_BAKE_DISPLACEMENT, RE_BAKE_DERIVATIVE)) { - if (((R.r.bake_flag & R_BAKE_NORMALIZE) && R.r.bake_maxdist == 0.0f) || - (type == RE_BAKE_DERIVATIVE)) - { - use_displacement_buffer = true; - use_mask = true; - } - } - - /* baker uses this flag to detect if image was initialized */ - if ((R.r.bake_flag & R_BAKE_VCOL) == 0) { - for (ima = G.main->image.first; ima; ima = ima->id.next) { - ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); - ima->id.tag |= LIB_TAG_DOIT; - ima->flag &= ~IMA_USED_FOR_RENDER; - if (ibuf) { - ibuf->userdata = NULL; /* use for masking if needed */ - } - BKE_image_release_ibuf(ima, ibuf, NULL); - } - } - - if (R.r.bake_flag & R_BAKE_VCOL) { - /* untag all meshes */ - BKE_main_id_tag_listbase(&G.main->mesh, LIB_TAG_DOIT, false); - } - - BLI_threadpool_init(&threads, do_bake_thread, re->r.threads); - - handles = MEM_callocN(sizeof(BakeShade) * re->r.threads, "BakeShade"); - - /* get the threads running */ - for (a = 0; a < re->r.threads; a++) { - handles[a].thread = a; - - /* set defaults in handles */ - handles[a].ssamp.shi[0].lay = re->lay; - - if (type == RE_BAKE_SHADOW) { - handles[a].ssamp.shi[0].passflag = SCE_PASS_SHADOW; - } - else { - handles[a].ssamp.shi[0].passflag = SCE_PASS_COMBINED; - } - handles[a].ssamp.shi[0].combinedflag = ~(SCE_PASS_SPEC); - handles[a].ssamp.shi[0].thread = a; - handles[a].ssamp.shi[0].do_manage = do_manage; - handles[a].ssamp.tot = 1; - - handles[a].type = type; - handles[a].actob = actob; - if (R.r.bake_flag & R_BAKE_VCOL) - handles[a].zspan = NULL; - else - handles[a].zspan = MEM_callocN(sizeof(ZSpan), "zspan for bake"); - - handles[a].use_mask = use_mask; - handles[a].use_displacement_buffer = use_displacement_buffer; - - handles[a].do_update = do_update; /* use to tell the view to update */ - - handles[a].displacement_min = FLT_MAX; - handles[a].displacement_max = -FLT_MAX; - - BLI_threadpool_insert(&threads, &handles[a]); - } - - /* wait for everything to be done */ - a = 0; - while (a != re->r.threads) { - PIL_sleep_ms(50); - - /* calculate progress */ - for (vdone = false, a = 0; a < re->r.threads; a++) - vdone += handles[a].vdone; - if (progress) - *progress = (float)(vdone / (float)re->totvlak); - - for (a = 0; a < re->r.threads; a++) { - if (handles[a].ready == false) { - break; - } - } - } - - /* filter and refresh images */ - if ((R.r.bake_flag & R_BAKE_VCOL) == 0) { - float displacement_min = FLT_MAX, displacement_max = -FLT_MAX; - - if (use_displacement_buffer) { - for (a = 0; a < re->r.threads; a++) { - displacement_min = min_ff(displacement_min, handles[a].displacement_min); - displacement_max = max_ff(displacement_max, handles[a].displacement_max); - } - } - - for (ima = G.main->image.first; ima; ima = ima->id.next) { - if ((ima->id.tag & LIB_TAG_DOIT) == 0) { - ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); - BakeImBufuserData *userdata; - - if (ima->flag & IMA_USED_FOR_RENDER) - result = BAKE_RESULT_FEEDBACK_LOOP; - - if (!ibuf) - continue; - - userdata = (BakeImBufuserData *)ibuf->userdata; - if (userdata) { - if (use_displacement_buffer) { - if (type == RE_BAKE_DERIVATIVE) { - float user_scale = (R.r.bake_flag & R_BAKE_USERSCALE) ? R.r.bake_user_scale : -1.0f; - RE_bake_make_derivative(ibuf, userdata->displacement_buffer, userdata->mask_buffer, - displacement_min, displacement_max, user_scale); - } - else { - RE_bake_ibuf_normalize_displacement(ibuf, userdata->displacement_buffer, userdata->mask_buffer, - displacement_min, displacement_max); - } - } - - RE_bake_ibuf_filter(ibuf, userdata->mask_buffer, re->r.bake_filter); - } - - ibuf->userflags |= IB_BITMAPDIRTY; - BKE_image_release_ibuf(ima, ibuf, NULL); - } - } - - /* calculate return value */ - for (a = 0; a < re->r.threads; a++) { - zbuf_free_span(handles[a].zspan); - MEM_freeN(handles[a].zspan); - } - } - - MEM_freeN(handles); - - BLI_threadpool_end(&threads); - - if (vdone == 0) { - result = BAKE_RESULT_NO_OBJECTS; - } - - return result; -} - -struct Image *RE_bake_shade_get_image(void) -{ - return R.bakebuf; -} - -/* **************** Derivative Maps Baker **************** */ - -static void add_single_heights_margin(const ImBuf *ibuf, const char *mask, float *heights_buffer) -{ - int x, y; - - for (y = 0; y < ibuf->y; y++) { - for (x = 0; x < ibuf->x; x++) { - int index = ibuf->x * y + x; - - /* If unassigned pixel, look for neighbors. */ - if (mask[index] != FILTER_MASK_USED) { - float height_acc = 0; - int denom = 0; - int i, j; - - for (j = -1; j <= 1; j++) - for (i = -1; i <= 1; i++) { - int w = (i == 0 ? 1 : 0) + (j == 0 ? 1 : 0) + 1; - - if (i != 0 || j != 0) { - int index2 = 0; - int x0 = x + i; - int y0 = y + j; - - CLAMP(x0, 0, ibuf->x - 1); - CLAMP(y0, 0, ibuf->y - 1); - - index2 = ibuf->x * y0 + x0; - - if (mask[index2] == FILTER_MASK_USED) { - height_acc += w * heights_buffer[index2]; - denom += w; - } - } - } - - /* Insert final value. */ - if (denom > 0) { - heights_buffer[index] = height_acc / denom; - } - } - } - } -} - -/* returns user-scale */ -float RE_bake_make_derivative(ImBuf *ibuf, float *heights_buffer, const char *mask, - const float height_min, const float height_max, - const float fmult) -{ - const float delta_height = height_max - height_min; - const float denom = delta_height > 0.0f ? (8 * delta_height) : 1.0f; - bool auto_range_fit = fmult <= 0.0f; - float max_num_deriv = -1.0f; - int x, y, index; - - /* Need a single margin to calculate good derivatives. */ - add_single_heights_margin(ibuf, mask, heights_buffer); - - if (auto_range_fit) { - /* If automatic range fitting is enabled. */ - for (y = 0; y < ibuf->y; y++) { - const int Yu = y == (ibuf->y - 1) ? (ibuf->y - 1) : (y + 1); - const int Yc = y; - const int Yd = y == 0 ? 0 : (y - 1); - - for (x = 0; x < ibuf->x; x++) { - const int Xl = x == 0 ? 0 : (x - 1); - const int Xc = x; - const int Xr = x == (ibuf->x - 1) ? (ibuf->x - 1) : (x + 1); - - const float Hcy = heights_buffer[Yc * ibuf->x + Xr] - heights_buffer[Yc * ibuf->x + Xl]; - const float Hu = heights_buffer[Yu * ibuf->x + Xr] - heights_buffer[Yu * ibuf->x + Xl]; - const float Hd = heights_buffer[Yd * ibuf->x + Xr] - heights_buffer[Yd * ibuf->x + Xl]; - - const float Hl = heights_buffer[Yu * ibuf->x + Xl] - heights_buffer[Yd * ibuf->x + Xl]; - const float Hcx = heights_buffer[Yu * ibuf->x + Xc] - heights_buffer[Yd * ibuf->x + Xc]; - const float Hr = heights_buffer[Yu * ibuf->x + Xr] - heights_buffer[Yd * ibuf->x + Xr]; - - /* This corresponds to using the sobel kernel on the heights buffer - * to obtain the derivative multiplied by 8. - */ - const float deriv_x = Hu + 2 * Hcy + Hd; - const float deriv_y = Hr + 2 * Hcx + Hl; - - /* early out */ - index = ibuf->x * y + x; - if (mask[index] != FILTER_MASK_USED) { - continue; - } - - /* Widen bound. */ - if (fabsf(deriv_x) > max_num_deriv) { - max_num_deriv = fabsf(deriv_x); - } - - if (fabsf(deriv_y) > max_num_deriv) { - max_num_deriv = fabsf(deriv_y); - } - } - } - } - - /* Output derivatives. */ - auto_range_fit &= (max_num_deriv > 0); - for (y = 0; y < ibuf->y; y++) { - const int Yu = y == (ibuf->y - 1) ? (ibuf->y - 1) : (y + 1); - const int Yc = y; - const int Yd = y == 0 ? 0 : (y - 1); - - for (x = 0; x < ibuf->x; x++) { - const int Xl = x == 0 ? 0 : (x - 1); - const int Xc = x; - const int Xr = x == (ibuf->x - 1) ? (ibuf->x - 1) : (x + 1); - - const float Hcy = heights_buffer[Yc * ibuf->x + Xr] - heights_buffer[Yc * ibuf->x + Xl]; - const float Hu = heights_buffer[Yu * ibuf->x + Xr] - heights_buffer[Yu * ibuf->x + Xl]; - const float Hd = heights_buffer[Yd * ibuf->x + Xr] - heights_buffer[Yd * ibuf->x + Xl]; - - const float Hl = heights_buffer[Yu * ibuf->x + Xl] - heights_buffer[Yd * ibuf->x + Xl]; - const float Hcx = heights_buffer[Yu * ibuf->x + Xc] - heights_buffer[Yd * ibuf->x + Xc]; - const float Hr = heights_buffer[Yu * ibuf->x + Xr] - heights_buffer[Yd * ibuf->x + Xr]; - - /* This corresponds to using the sobel kernel on the heights buffer - * to obtain the derivative multiplied by 8. - */ - float deriv_x = Hu + 2 * Hcy + Hd; - float deriv_y = Hr + 2 * Hcx + Hl; - - /* Early out. */ - index = ibuf->x * y + x; - if (mask[index] != FILTER_MASK_USED) { - continue; - } - - if (auto_range_fit) { - deriv_x /= max_num_deriv; - deriv_y /= max_num_deriv; - } - else { - deriv_x *= (fmult / denom); - deriv_y *= (fmult / denom); - } - - deriv_x = deriv_x * 0.5f + 0.5f; - deriv_y = deriv_y * 0.5f + 0.5f; - - /* Clamp. */ - CLAMP(deriv_x, 0.0f, 1.0f); - CLAMP(deriv_y, 0.0f, 1.0f); - - /* Write out derivatives. */ - if (ibuf->rect_float) { - float *rrgbf = ibuf->rect_float + index * 4; - - rrgbf[0] = deriv_x; - rrgbf[1] = deriv_y; - rrgbf[2] = 0.0f; - rrgbf[3] = 1.0f; - } - else { - char *rrgb = (char *)ibuf->rect + index * 4; - - rrgb[0] = unit_float_to_uchar_clamp(deriv_x); - rrgb[1] = unit_float_to_uchar_clamp(deriv_y); - rrgb[2] = 0; - rrgb[3] = 255; - } - } - } - - /* Eeturn user-scale (for rendering). */ - return auto_range_fit ? (max_num_deriv / denom) : (fmult > 0.0f ? (1.0f / fmult) : 0.0f); -} diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c deleted file mode 100644 index 8675ffec313..00000000000 --- a/source/blender/render/intern/source/convertblender.c +++ /dev/null @@ -1,6014 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * Contributors: 2004/2005/2006 Blender Foundation, full recode - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/render/intern/source/convertblender.c - * \ingroup render - */ - -#include <math.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <limits.h> - -#include "MEM_guardedalloc.h" - -#include "BLI_math.h" -#include "BLI_blenlib.h" -#include "BLI_utildefines.h" -#include "BLI_rand.h" -#include "BLI_memarena.h" -#ifdef WITH_FREESTYLE -# include "BLI_edgehash.h" -#endif - -#include "BLT_translation.h" - -#include "DNA_material_types.h" -#include "DNA_curve_types.h" -#include "DNA_group_types.h" -#include "DNA_lamp_types.h" -#include "DNA_image_types.h" -#include "DNA_mesh_types.h" -#include "DNA_meshdata_types.h" -#include "DNA_modifier_types.h" -#include "DNA_node_types.h" -#include "DNA_object_types.h" -#include "DNA_object_fluidsim_types.h" -#include "DNA_particle_types.h" -#include "DNA_scene_types.h" -#include "DNA_texture_types.h" - -#include "BKE_anim.h" -#include "BKE_curve.h" -#include "BKE_customdata.h" -#include "BKE_colortools.h" -#include "BKE_displist.h" -#include "BKE_depsgraph.h" -#include "BKE_DerivedMesh.h" -#include "BKE_global.h" -#include "BKE_key.h" -#include "BKE_image.h" -#include "BKE_lattice.h" -#include "BKE_material.h" -#include "BKE_main.h" -#include "BKE_mball.h" -#include "BKE_mesh.h" -#include "BKE_modifier.h" -#include "BKE_node.h" -#include "BKE_object.h" -#include "BKE_particle.h" -#include "BKE_scene.h" - -#include "PIL_time.h" - -#include "envmap.h" -#include "occlusion.h" -#include "pointdensity.h" -#include "voxeldata.h" -#include "render_types.h" -#include "rendercore.h" -#include "renderdatabase.h" -#include "renderpipeline.h" -#include "shadbuf.h" -#include "shading.h" -#include "strand.h" -#include "texture.h" -#include "volume_precache.h" -#include "sss.h" -#include "zbuf.h" -#include "sunsky.h" - -/* 10 times larger than normal epsilon, test it on default nurbs sphere with ray_transp (for quad detection) */ -/* or for checking vertex normal flips */ -#define FLT_EPSILON10 1.19209290e-06F - -/* could enable at some point but for now there are far too many conversions */ -#ifdef __GNUC__ -# pragma GCC diagnostic ignored "-Wdouble-promotion" -#endif - -/* ------------------------------------------------------------------------- */ -/* tool functions/defines for ad hoc simplification and possible future - * cleanup */ -/* ------------------------------------------------------------------------- */ - -#define UVTOINDEX(u, v) (startvlak + (u) * sizev + (v)) -/* - * - * NOTE THAT U/V COORDINATES ARE SOMETIMES SWAPPED !! - * - * ^ ()----p4----p3----() - * | | | | | - * u | | F1 | F2 | - * | | | | - * ()----p1----p2----() - * v -> - */ - -/* ------------------------------------------------------------------------- */ - -#define CD_MASK_RENDER_INTERNAL \ - (CD_MASK_BAREMESH | CD_MASK_MFACE | CD_MASK_MTFACE | CD_MASK_MCOL) - -static void split_v_renderfaces(ObjectRen *obr, int startvlak, int UNUSED(startvert), int UNUSED(usize), int vsize, int uIndex, int UNUSED(cyclu), int cyclv) -{ - int vLen = vsize-1+(!!cyclv); - int v; - - for (v=0; v<vLen; v++) { - VlakRen *vlr = RE_findOrAddVlak(obr, startvlak + vLen*uIndex + v); - VlakRen *vlr_other; - VertRen *vert = RE_vertren_copy(obr, vlr->v2); - - if (cyclv) { - vlr->v2 = vert; - - if (v == vLen - 1) { - vlr_other = RE_findOrAddVlak(obr, startvlak + vLen*uIndex + 0); - vlr_other->v1 = vert; - } - else { - vlr_other = RE_findOrAddVlak(obr, startvlak + vLen*uIndex + v+1); - vlr_other->v1 = vert; - } - } - else { - vlr->v2 = vert; - - if (v < vLen - 1) { - vlr_other = RE_findOrAddVlak(obr, startvlak + vLen*uIndex + v+1); - vlr_other->v1 = vert; - } - - if (v == 0) { - vlr->v1 = RE_vertren_copy(obr, vlr->v1); - } - } - } -} - -/* ------------------------------------------------------------------------- */ -/* Stress, tangents and normals */ -/* ------------------------------------------------------------------------- */ - -static void calc_edge_stress_add(float *accum, VertRen *v1, VertRen *v2) -{ - float len= len_v3v3(v1->co, v2->co)/len_v3v3(v1->orco, v2->orco); - float *acc; - - acc= accum + 2*v1->index; - acc[0]+= len; - acc[1]+= 1.0f; - - acc= accum + 2*v2->index; - acc[0]+= len; - acc[1]+= 1.0f; -} - -static void calc_edge_stress(Render *UNUSED(re), ObjectRen *obr, Mesh *me) -{ - float loc[3], size[3], *accum, *acc, *accumoffs, *stress; - int a; - - if (obr->totvert==0) return; - - BKE_mesh_texspace_get(me, loc, NULL, size); - - accum= MEM_callocN(2*sizeof(float)*obr->totvert, "temp accum for stress"); - - /* de-normalize orco */ - for (a=0; a<obr->totvert; a++) { - VertRen *ver= RE_findOrAddVert(obr, a); - if (ver->orco) { - ver->orco[0]= ver->orco[0]*size[0] +loc[0]; - ver->orco[1]= ver->orco[1]*size[1] +loc[1]; - ver->orco[2]= ver->orco[2]*size[2] +loc[2]; - } - } - - /* add stress values */ - accumoffs= accum; /* so we can use vertex index */ - for (a=0; a<obr->totvlak; a++) { - VlakRen *vlr= RE_findOrAddVlak(obr, a); - - if (vlr->v1->orco && vlr->v4) { - calc_edge_stress_add(accumoffs, vlr->v1, vlr->v2); - calc_edge_stress_add(accumoffs, vlr->v2, vlr->v3); - calc_edge_stress_add(accumoffs, vlr->v3, vlr->v1); - if (vlr->v4) { - calc_edge_stress_add(accumoffs, vlr->v3, vlr->v4); - calc_edge_stress_add(accumoffs, vlr->v4, vlr->v1); - calc_edge_stress_add(accumoffs, vlr->v2, vlr->v4); - } - } - } - - for (a=0; a<obr->totvert; a++) { - VertRen *ver= RE_findOrAddVert(obr, a); - if (ver->orco) { - /* find stress value */ - acc= accumoffs + 2*ver->index; - if (acc[1]!=0.0f) - acc[0]/= acc[1]; - stress= RE_vertren_get_stress(obr, ver, 1); - *stress= *acc; - - /* restore orcos */ - ver->orco[0] = (ver->orco[0]-loc[0])/size[0]; - ver->orco[1] = (ver->orco[1]-loc[1])/size[1]; - ver->orco[2] = (ver->orco[2]-loc[2])/size[2]; - } - } - - MEM_freeN(accum); -} - -/* gets tangent from tface or orco */ -static void calc_tangent_vector(ObjectRen *obr, VlakRen *vlr, int do_tangent) -{ - MTFace *tface= RE_vlakren_get_tface(obr, vlr, obr->actmtface, NULL, 0); - VertRen *v1=vlr->v1, *v2=vlr->v2, *v3=vlr->v3, *v4=vlr->v4; - float tang[3], *tav; - float *uv1, *uv2, *uv3, *uv4; - float uv[4][2]; - - if (tface) { - uv1= tface->uv[0]; - uv2= tface->uv[1]; - uv3= tface->uv[2]; - uv4= tface->uv[3]; - } - else if (v1->orco) { - uv1= uv[0]; uv2= uv[1]; uv3= uv[2]; uv4= uv[3]; - map_to_sphere(&uv[0][0], &uv[0][1], v1->orco[0], v1->orco[1], v1->orco[2]); - map_to_sphere(&uv[1][0], &uv[1][1], v2->orco[0], v2->orco[1], v2->orco[2]); - map_to_sphere(&uv[2][0], &uv[2][1], v3->orco[0], v3->orco[1], v3->orco[2]); - if (v4) - map_to_sphere(&uv[3][0], &uv[3][1], v4->orco[0], v4->orco[1], v4->orco[2]); - } - else return; - - tangent_from_uv_v3(uv1, uv2, uv3, v1->co, v2->co, v3->co, vlr->n, tang); - - if (do_tangent) { - tav= RE_vertren_get_tangent(obr, v1, 1); - add_v3_v3(tav, tang); - tav= RE_vertren_get_tangent(obr, v2, 1); - add_v3_v3(tav, tang); - tav= RE_vertren_get_tangent(obr, v3, 1); - add_v3_v3(tav, tang); - } - - if (v4) { - tangent_from_uv_v3(uv1, uv3, uv4, v1->co, v3->co, v4->co, vlr->n, tang); - - if (do_tangent) { - tav= RE_vertren_get_tangent(obr, v1, 1); - add_v3_v3(tav, tang); - tav= RE_vertren_get_tangent(obr, v3, 1); - add_v3_v3(tav, tang); - tav= RE_vertren_get_tangent(obr, v4, 1); - add_v3_v3(tav, tang); - } - } -} - - - -/**************************************************************** - ************ tangent space generation interface **************** - ****************************************************************/ - -typedef struct { - ObjectRen *obr; - int mtface_index; -} SRenderMeshToTangent; - -/* interface */ -#include "mikktspace.h" - -static int GetNumFaces(const SMikkTSpaceContext *pContext) -{ - SRenderMeshToTangent *pMesh = (SRenderMeshToTangent *) pContext->m_pUserData; - return pMesh->obr->totvlak; -} - -static int GetNumVertsOfFace(const SMikkTSpaceContext *pContext, const int face_num) -{ - SRenderMeshToTangent *pMesh = (SRenderMeshToTangent *) pContext->m_pUserData; - VlakRen *vlr= RE_findOrAddVlak(pMesh->obr, face_num); - return vlr->v4!=NULL ? 4 : 3; -} - -static void GetPosition(const SMikkTSpaceContext *pContext, float r_co[3], const int face_num, const int vert_index) -{ - //assert(vert_index>=0 && vert_index<4); - SRenderMeshToTangent *pMesh = (SRenderMeshToTangent *) pContext->m_pUserData; - VlakRen *vlr= RE_findOrAddVlak(pMesh->obr, face_num); - const float *co = (&vlr->v1)[vert_index]->co; - copy_v3_v3(r_co, co); -} - -static void GetTextureCoordinate(const SMikkTSpaceContext *pContext, float r_uv[2], const int face_num, const int vert_index) -{ - //assert(vert_index>=0 && vert_index<4); - SRenderMeshToTangent *pMesh = (SRenderMeshToTangent *) pContext->m_pUserData; - VlakRen *vlr= RE_findOrAddVlak(pMesh->obr, face_num); - MTFace *tface= RE_vlakren_get_tface(pMesh->obr, vlr, pMesh->mtface_index, NULL, 0); - const float *coord; - - if (tface != NULL) { - coord= tface->uv[vert_index]; - copy_v2_v2(r_uv, coord); - } - else if ((coord = (&vlr->v1)[vert_index]->orco)) { - map_to_sphere(&r_uv[0], &r_uv[1], coord[0], coord[1], coord[2]); - } - else { /* else we get un-initialized value, 0.0 ok default? */ - zero_v2(r_uv); - } -} - -static void GetNormal(const SMikkTSpaceContext *pContext, float r_no[3], const int face_num, const int vert_index) -{ - //assert(vert_index>=0 && vert_index<4); - SRenderMeshToTangent *pMesh = (SRenderMeshToTangent *) pContext->m_pUserData; - VlakRen *vlr= RE_findOrAddVlak(pMesh->obr, face_num); - - if (vlr->flag & ME_SMOOTH) { - const float *n = (&vlr->v1)[vert_index]->n; - copy_v3_v3(r_no, n); - } - else { - negate_v3_v3(r_no, vlr->n); - } -} -static void SetTSpace(const SMikkTSpaceContext *pContext, const float fvTangent[3], const float fSign, const int face_num, const int iVert) -{ - //assert(vert_index>=0 && vert_index<4); - SRenderMeshToTangent *pMesh = (SRenderMeshToTangent *) pContext->m_pUserData; - VlakRen *vlr = RE_findOrAddVlak(pMesh->obr, face_num); - float *ftang = RE_vlakren_get_nmap_tangent(pMesh->obr, vlr, pMesh->mtface_index, true); - if (ftang!=NULL) { - copy_v3_v3(&ftang[iVert*4+0], fvTangent); - ftang[iVert*4+3]=fSign; - } -} - -static void calc_vertexnormals(Render *UNUSED(re), ObjectRen *obr, bool do_vertex_normal, bool do_tangent, bool do_nmap_tangent) -{ - int a; - - /* clear all vertex normals */ - if (do_vertex_normal) { - for (a=0; a<obr->totvert; a++) { - VertRen *ver= RE_findOrAddVert(obr, a); - ver->n[0]=ver->n[1]=ver->n[2]= 0.0f; - } - } - - /* calculate cos of angles and point-masses, use as weight factor to - * add face normal to vertex */ - for (a=0; a<obr->totvlak; a++) { - VlakRen *vlr= RE_findOrAddVlak(obr, a); - if (do_vertex_normal && vlr->flag & ME_SMOOTH) { - float *n4= (vlr->v4)? vlr->v4->n: NULL; - const float *c4= (vlr->v4)? vlr->v4->co: NULL; - - accumulate_vertex_normals_v3(vlr->v1->n, vlr->v2->n, vlr->v3->n, n4, - vlr->n, vlr->v1->co, vlr->v2->co, vlr->v3->co, c4); - } - if (do_tangent) { - /* tangents still need to be calculated for flat faces too */ - /* weighting removed, they are not vertexnormals */ - calc_tangent_vector(obr, vlr, do_tangent); - } - } - - /* do solid faces */ - for (a=0; a<obr->totvlak; a++) { - VlakRen *vlr= RE_findOrAddVlak(obr, a); - - if (do_vertex_normal && (vlr->flag & ME_SMOOTH)==0) { - if (is_zero_v3(vlr->v1->n)) copy_v3_v3(vlr->v1->n, vlr->n); - if (is_zero_v3(vlr->v2->n)) copy_v3_v3(vlr->v2->n, vlr->n); - if (is_zero_v3(vlr->v3->n)) copy_v3_v3(vlr->v3->n, vlr->n); - if (vlr->v4 && is_zero_v3(vlr->v4->n)) copy_v3_v3(vlr->v4->n, vlr->n); - } - } - - /* normalize vertex normals */ - for (a=0; a<obr->totvert; a++) { - VertRen *ver= RE_findOrAddVert(obr, a); - normalize_v3(ver->n); - if (do_tangent) { - float *tav= RE_vertren_get_tangent(obr, ver, 0); - if (tav) { - /* orthonorm. */ - const float tdn = dot_v3v3(tav, ver->n); - tav[0] -= ver->n[0]*tdn; - tav[1] -= ver->n[1]*tdn; - tav[2] -= ver->n[2]*tdn; - normalize_v3(tav); - } - } - } - - /* normal mapping tangent with mikktspace */ - if (do_nmap_tangent != false) { - SRenderMeshToTangent mesh2tangent; - SMikkTSpaceContext sContext; - SMikkTSpaceInterface sInterface; - memset(&mesh2tangent, 0, sizeof(SRenderMeshToTangent)); - memset(&sContext, 0, sizeof(SMikkTSpaceContext)); - memset(&sInterface, 0, sizeof(SMikkTSpaceInterface)); - - mesh2tangent.obr = obr; - - sContext.m_pUserData = &mesh2tangent; - sContext.m_pInterface = &sInterface; - sInterface.m_getNumFaces = GetNumFaces; - sInterface.m_getNumVerticesOfFace = GetNumVertsOfFace; - sInterface.m_getPosition = GetPosition; - sInterface.m_getTexCoord = GetTextureCoordinate; - sInterface.m_getNormal = GetNormal; - sInterface.m_setTSpaceBasic = SetTSpace; - - for (a = 0; a < MAX_MTFACE; a++) { - if (obr->tangent_mask & 1 << a) { - mesh2tangent.mtface_index = a; - genTangSpaceDefault(&sContext); - } - } - } -} - -/* ------------------------------------------------------------------------- */ -/* Autosmoothing: */ -/* ------------------------------------------------------------------------- */ - -typedef struct ASvert { - int totface; - ListBase faces; -} ASvert; - -typedef struct ASface { - struct ASface *next, *prev; - VlakRen *vlr[4]; - VertRen *nver[4]; -} ASface; - -static int as_addvert(ASvert *asv, VertRen *v1, VlakRen *vlr) -{ - ASface *asf; - int a = -1; - - if (v1 == NULL) - return a; - - asf = asv->faces.last; - if (asf) { - for (a = 0; a < 4 && asf->vlr[a]; a++) { - } - } - else { - a = 4; - } - - /* new face struct */ - if (a == 4) { - a = 0; - asf = MEM_callocN(sizeof(ASface), "asface"); - BLI_addtail(&asv->faces, asf); - } - - asf->vlr[a] = vlr; - asv->totface++; - - return a; -} - -static VertRen *as_findvertex_lnor(VlakRen *vlr, VertRen *ver, ASvert *asv, const float lnor[3]) -{ - /* return when new vertex already was made, or existing one is OK */ - ASface *asf; - int a; - - /* First face, we can use existing vert and assign it current lnor! */ - if (asv->totface == 1) { - copy_v3_v3(ver->n, lnor); - return ver; - } - - /* In case existing ver has same normal as current lnor, we can simply use it! */ - if (equals_v3v3(lnor, ver->n)) { - return ver; - } - - asf = asv->faces.first; - while (asf) { - for (a = 0; a < 4; a++) { - if (asf->vlr[a] && asf->vlr[a] != vlr) { - /* this face already made a copy for this vertex! */ - if (asf->nver[a]) { - if (equals_v3v3(lnor, asf->nver[a]->n)) { - return asf->nver[a]; - } - } - } - } - asf = asf->next; - } - - return NULL; -} - -static void as_addvert_lnor(ObjectRen *obr, ASvert *asv, VertRen *ver, VlakRen *vlr, const short _lnor[3]) -{ - VertRen *v1; - ASface *asf; - int asf_idx; - float lnor[3]; - - normal_short_to_float_v3(lnor, _lnor); - - asf_idx = as_addvert(asv, ver, vlr); - if (asf_idx < 0) { - return; - } - asf = asv->faces.last; - - /* already made a new vertex within threshold? */ - v1 = as_findvertex_lnor(vlr, ver, asv, lnor); - if (v1 == NULL) { - /* make a new vertex */ - v1 = RE_vertren_copy(obr, ver); - copy_v3_v3(v1->n, lnor); - } - if (v1 != ver) { - asf->nver[asf_idx] = v1; - if (vlr->v1 == ver) vlr->v1 = v1; - if (vlr->v2 == ver) vlr->v2 = v1; - if (vlr->v3 == ver) vlr->v3 = v1; - if (vlr->v4 == ver) vlr->v4 = v1; - } -} - -/* note; autosmooth happens in object space still, after applying autosmooth we rotate */ -/* note2; actually, when original mesh and displist are equal sized, face normals are from original mesh */ -static void autosmooth(Render *UNUSED(re), ObjectRen *obr, float mat[4][4], short (*lnors)[4][3]) -{ - ASvert *asverts; - VertRen *ver; - VlakRen *vlr; - int a, totvert; - - float rot[3][3]; - - /* Note: For normals, we only want rotation, not scaling component. - * Negative scales (aka mirroring) give wrong results, see T44102. */ - if (lnors) { - float mat3[3][3], size[3]; - - copy_m3_m4(mat3, mat); - mat3_to_rot_size(rot, size, mat3); - } - - if (obr->totvert == 0) - return; - - totvert = obr->totvert; - asverts = MEM_callocN(sizeof(ASvert) * totvert, "all smooth verts"); - - if (lnors) { - /* We construct listbase of all vertices and pointers to faces, and add new verts when needed - * (i.e. when existing ones do not share the same (loop)normal). - */ - for (a = 0; a < obr->totvlak; a++, lnors++) { - vlr = RE_findOrAddVlak(obr, a); - /* skip wire faces */ - if (vlr->v2 != vlr->v3) { - as_addvert_lnor(obr, asverts+vlr->v1->index, vlr->v1, vlr, (const short*)lnors[0][0]); - as_addvert_lnor(obr, asverts+vlr->v2->index, vlr->v2, vlr, (const short*)lnors[0][1]); - as_addvert_lnor(obr, asverts+vlr->v3->index, vlr->v3, vlr, (const short*)lnors[0][2]); - if (vlr->v4) - as_addvert_lnor(obr, asverts+vlr->v4->index, vlr->v4, vlr, (const short*)lnors[0][3]); - } - } - } - - /* free */ - for (a = 0; a < totvert; a++) { - BLI_freelistN(&asverts[a].faces); - } - MEM_freeN(asverts); - - /* rotate vertices and calculate normal of faces */ - for (a = 0; a < obr->totvert; a++) { - ver = RE_findOrAddVert(obr, a); - mul_m4_v3(mat, ver->co); - if (lnors) { - mul_m3_v3(rot, ver->n); - negate_v3(ver->n); - } - } - for (a = 0; a < obr->totvlak; a++) { - vlr = RE_findOrAddVlak(obr, a); - - /* skip wire faces */ - if (vlr->v2 != vlr->v3) { - if (vlr->v4) - normal_quad_v3(vlr->n, vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co); - else - normal_tri_v3(vlr->n, vlr->v3->co, vlr->v2->co, vlr->v1->co); - } - } -} - -/* ------------------------------------------------------------------------- */ -/* Orco hash and Materials */ -/* ------------------------------------------------------------------------- */ - -static float *get_object_orco(Render *re, void *ob) -{ - if (!re->orco_hash) { - return NULL; - } - - return BLI_ghash_lookup(re->orco_hash, ob); -} - -static void set_object_orco(Render *re, void *ob, float *orco) -{ - if (!re->orco_hash) - re->orco_hash = BLI_ghash_ptr_new("set_object_orco gh"); - - BLI_ghash_insert(re->orco_hash, ob, orco); -} - -static void free_mesh_orco_hash(Render *re) -{ - if (re->orco_hash) { - BLI_ghash_free(re->orco_hash, NULL, MEM_freeN); - re->orco_hash = NULL; - } -} - -static void check_material_mapto(Material *ma) -{ - int a; - ma->mapto_textured = 0; - - /* cache which inputs are actually textured. - * this can avoid a bit of time spent iterating through all the texture slots, map inputs and map tos - * every time a property which may or may not be textured is accessed */ - - for (a=0; a<MAX_MTEX; a++) { - if (ma->mtex[a] && ma->mtex[a]->tex) { - /* currently used only in volume render, so we'll check for those flags */ - if (ma->mtex[a]->mapto & MAP_DENSITY) ma->mapto_textured |= MAP_DENSITY; - if (ma->mtex[a]->mapto & MAP_EMISSION) ma->mapto_textured |= MAP_EMISSION; - if (ma->mtex[a]->mapto & MAP_EMISSION_COL) ma->mapto_textured |= MAP_EMISSION_COL; - if (ma->mtex[a]->mapto & MAP_SCATTERING) ma->mapto_textured |= MAP_SCATTERING; - if (ma->mtex[a]->mapto & MAP_TRANSMISSION_COL) ma->mapto_textured |= MAP_TRANSMISSION_COL; - if (ma->mtex[a]->mapto & MAP_REFLECTION) ma->mapto_textured |= MAP_REFLECTION; - if (ma->mtex[a]->mapto & MAP_REFLECTION_COL) ma->mapto_textured |= MAP_REFLECTION_COL; - } - } -} -static void flag_render_node_material(Render *re, bNodeTree *ntree) -{ - bNode *node; - - for (node = ntree->nodes.first; node; node = node->next) { - if (node->id) { - if (GS(node->id->name)==ID_MA) { - Material *ma= (Material *)node->id; - - if ((ma->mode & MA_TRANSP) && (ma->mode & MA_ZTRANSP)) - re->flag |= R_ZTRA; - - ma->flag |= MA_IS_USED; - } - else if (node->type==NODE_GROUP) - flag_render_node_material(re, (bNodeTree *)node->id); - } - } -} - -static Material *give_render_material(Render *re, Object *ob, short nr) -{ - extern Material defmaterial; /* material.c */ - Material *ma; - - ma= give_current_material(ob, nr); - if (ma==NULL) - ma= &defmaterial; - - if (re->r.mode & R_SPEED) ma->texco |= NEED_UV; - - if (ma->material_type == MA_TYPE_VOLUME) { - ma->mode |= MA_TRANSP; - ma->mode &= ~MA_SHADBUF; - } - if ((ma->mode & MA_TRANSP) && (ma->mode & MA_ZTRANSP)) - re->flag |= R_ZTRA; - - /* for light groups and SSS */ - ma->flag |= MA_IS_USED; - - if (ma->nodetree && ma->use_nodes) - flag_render_node_material(re, ma->nodetree); - - check_material_mapto(ma); - - return ma; -} - -/* ------------------------------------------------------------------------- */ -/* Particles */ -/* ------------------------------------------------------------------------- */ -typedef struct ParticleStrandData { - struct MCol *mcol; - float *orco, *uvco, *surfnor; - float time, adapt_angle, adapt_pix, size; - int totuv, totcol; - int first, line, adapt, override_uv; -} -ParticleStrandData; -/* future thread problem... */ -static void static_particle_strand(Render *re, ObjectRen *obr, Material *ma, ParticleStrandData *sd, const float vec[3], const float vec1[3]) -{ - static VertRen *v1= NULL, *v2= NULL; - VlakRen *vlr= NULL; - float nor[3], cross[3], crosslen, w, dx, dy, width; - static float anor[3], avec[3]; - int flag, i; - static int second=0; - - sub_v3_v3v3(nor, vec, vec1); - normalize_v3(nor); /* nor needed as tangent */ - cross_v3_v3v3(cross, vec, nor); - - /* turn cross in pixelsize */ - w= vec[2]*re->winmat[2][3] + re->winmat[3][3]; - dx= re->winx*cross[0]*re->winmat[0][0]; - dy= re->winy*cross[1]*re->winmat[1][1]; - w = sqrtf(dx * dx + dy * dy) / w; - - if (w!=0.0f) { - float fac; - if (ma->strand_ease!=0.0f) { - if (ma->strand_ease<0.0f) - fac= pow(sd->time, 1.0f+ma->strand_ease); - else - fac= pow(sd->time, 1.0f/(1.0f-ma->strand_ease)); - } - else fac= sd->time; - - width= ((1.0f-fac)*ma->strand_sta + (fac)*ma->strand_end); - - /* use actual Blender units for strand width and fall back to minimum width */ - if (ma->mode & MA_STR_B_UNITS) { - crosslen= len_v3(cross); - w= 2.0f*crosslen*ma->strand_min/w; - - if (width < w) - width= w; - - /*cross is the radius of the strand so we want it to be half of full width */ - mul_v3_fl(cross, 0.5f/crosslen); - } - else - width/=w; - - mul_v3_fl(cross, width); - } - - if (ma->mode & MA_TANGENT_STR) - flag= R_SMOOTH|R_TANGENT; - else - flag= R_SMOOTH; - - /* only 1 pixel wide strands filled in as quads now, otherwise zbuf errors */ - if (ma->strand_sta==1.0f) - flag |= R_STRAND; - - /* single face line */ - if (sd->line) { - vlr= RE_findOrAddVlak(obr, obr->totvlak++); - vlr->flag= flag; - vlr->v1= RE_findOrAddVert(obr, obr->totvert++); - vlr->v2= RE_findOrAddVert(obr, obr->totvert++); - vlr->v3= RE_findOrAddVert(obr, obr->totvert++); - vlr->v4= RE_findOrAddVert(obr, obr->totvert++); - - copy_v3_v3(vlr->v1->co, vec); - add_v3_v3(vlr->v1->co, cross); - copy_v3_v3(vlr->v1->n, nor); - vlr->v1->orco= sd->orco; - vlr->v1->accum = -1.0f; /* accum abuse for strand texco */ - - copy_v3_v3(vlr->v2->co, vec); - sub_v3_v3v3(vlr->v2->co, vlr->v2->co, cross); - copy_v3_v3(vlr->v2->n, nor); - vlr->v2->orco= sd->orco; - vlr->v2->accum= vlr->v1->accum; - - copy_v3_v3(vlr->v4->co, vec1); - add_v3_v3(vlr->v4->co, cross); - copy_v3_v3(vlr->v4->n, nor); - vlr->v4->orco= sd->orco; - vlr->v4->accum = 1.0f; /* accum abuse for strand texco */ - - copy_v3_v3(vlr->v3->co, vec1); - sub_v3_v3v3(vlr->v3->co, vlr->v3->co, cross); - copy_v3_v3(vlr->v3->n, nor); - vlr->v3->orco= sd->orco; - vlr->v3->accum= vlr->v4->accum; - - normal_quad_v3(vlr->n, vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co); - - vlr->mat= ma; - vlr->ec= ME_V2V3; - - if (sd->surfnor) { - float *snor= RE_vlakren_get_surfnor(obr, vlr, 1); - copy_v3_v3(snor, sd->surfnor); - } - - if (sd->uvco) { - for (i=0; i<sd->totuv; i++) { - MTFace *mtf; - mtf=RE_vlakren_get_tface(obr, vlr, i, NULL, 1); - mtf->uv[0][0]=mtf->uv[1][0]= - mtf->uv[2][0]=mtf->uv[3][0]=(sd->uvco+2*i)[0]; - mtf->uv[0][1]=mtf->uv[1][1]= - mtf->uv[2][1]=mtf->uv[3][1]=(sd->uvco+2*i)[1]; - } - if (sd->override_uv>=0) { - MTFace *mtf; - mtf=RE_vlakren_get_tface(obr, vlr, sd->override_uv, NULL, 0); - - mtf->uv[0][0]=mtf->uv[3][0]=0.0f; - mtf->uv[1][0]=mtf->uv[2][0]=1.0f; - - mtf->uv[0][1]=mtf->uv[1][1]=0.0f; - mtf->uv[2][1]=mtf->uv[3][1]=1.0f; - } - } - if (sd->mcol) { - for (i=0; i<sd->totcol; i++) { - MCol *mc; - mc=RE_vlakren_get_mcol(obr, vlr, i, NULL, 1); - mc[0]=mc[1]=mc[2]=mc[3]=sd->mcol[i]; - mc[0]=mc[1]=mc[2]=mc[3]=sd->mcol[i]; - } - } - } - /* first two vertices of a strand */ - else if (sd->first) { - if (sd->adapt) { - copy_v3_v3(anor, nor); - copy_v3_v3(avec, vec); - second=1; - } - - v1= RE_findOrAddVert(obr, obr->totvert++); - v2= RE_findOrAddVert(obr, obr->totvert++); - - copy_v3_v3(v1->co, vec); - add_v3_v3(v1->co, cross); - copy_v3_v3(v1->n, nor); - v1->orco= sd->orco; - v1->accum = -1.0f; /* accum abuse for strand texco */ - - copy_v3_v3(v2->co, vec); - sub_v3_v3v3(v2->co, v2->co, cross); - copy_v3_v3(v2->n, nor); - v2->orco= sd->orco; - v2->accum= v1->accum; - } - /* more vertices & faces to strand */ - else { - if (sd->adapt==0 || second) { - vlr= RE_findOrAddVlak(obr, obr->totvlak++); - vlr->flag= flag; - vlr->v1= v1; - vlr->v2= v2; - vlr->v3= RE_findOrAddVert(obr, obr->totvert++); - vlr->v4= RE_findOrAddVert(obr, obr->totvert++); - - v1= vlr->v4; /* cycle */ - v2= vlr->v3; /* cycle */ - - - if (sd->adapt) { - second=0; - copy_v3_v3(anor, nor); - copy_v3_v3(avec, vec); - } - - } - else if (sd->adapt) { - float dvec[3], pvec[3]; - sub_v3_v3v3(dvec, avec, vec); - project_v3_v3v3(pvec, dvec, vec); - sub_v3_v3v3(dvec, dvec, pvec); - - w= vec[2]*re->winmat[2][3] + re->winmat[3][3]; - dx= re->winx*dvec[0]*re->winmat[0][0]/w; - dy= re->winy*dvec[1]*re->winmat[1][1]/w; - w = sqrtf(dx * dx + dy * dy); - if (dot_v3v3(anor, nor)<sd->adapt_angle && w>sd->adapt_pix) { - vlr= RE_findOrAddVlak(obr, obr->totvlak++); - vlr->flag= flag; - vlr->v1= v1; - vlr->v2= v2; - vlr->v3= RE_findOrAddVert(obr, obr->totvert++); - vlr->v4= RE_findOrAddVert(obr, obr->totvert++); - - v1= vlr->v4; /* cycle */ - v2= vlr->v3; /* cycle */ - - copy_v3_v3(anor, nor); - copy_v3_v3(avec, vec); - } - else { - vlr= RE_findOrAddVlak(obr, obr->totvlak-1); - } - } - - copy_v3_v3(vlr->v4->co, vec); - add_v3_v3(vlr->v4->co, cross); - copy_v3_v3(vlr->v4->n, nor); - vlr->v4->orco= sd->orco; - vlr->v4->accum= -1.0f + 2.0f * sd->time; /* accum abuse for strand texco */ - - copy_v3_v3(vlr->v3->co, vec); - sub_v3_v3v3(vlr->v3->co, vlr->v3->co, cross); - copy_v3_v3(vlr->v3->n, nor); - vlr->v3->orco= sd->orco; - vlr->v3->accum= vlr->v4->accum; - - normal_quad_v3(vlr->n, vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co); - - vlr->mat= ma; - vlr->ec= ME_V2V3; - - if (sd->surfnor) { - float *snor= RE_vlakren_get_surfnor(obr, vlr, 1); - copy_v3_v3(snor, sd->surfnor); - } - - if (sd->uvco) { - for (i=0; i<sd->totuv; i++) { - MTFace *mtf; - mtf=RE_vlakren_get_tface(obr, vlr, i, NULL, 1); - mtf->uv[0][0]=mtf->uv[1][0]= - mtf->uv[2][0]=mtf->uv[3][0]=(sd->uvco+2*i)[0]; - mtf->uv[0][1]=mtf->uv[1][1]= - mtf->uv[2][1]=mtf->uv[3][1]=(sd->uvco+2*i)[1]; - } - if (sd->override_uv>=0) { - MTFace *mtf; - mtf=RE_vlakren_get_tface(obr, vlr, sd->override_uv, NULL, 0); - - mtf->uv[0][0]=mtf->uv[3][0]=0.0f; - mtf->uv[1][0]=mtf->uv[2][0]=1.0f; - - mtf->uv[0][1]=mtf->uv[1][1]=(vlr->v1->accum+1.0f)/2.0f; - mtf->uv[2][1]=mtf->uv[3][1]=(vlr->v3->accum+1.0f)/2.0f; - } - } - if (sd->mcol) { - for (i=0; i<sd->totcol; i++) { - MCol *mc; - mc=RE_vlakren_get_mcol(obr, vlr, i, NULL, 1); - mc[0]=mc[1]=mc[2]=mc[3]=sd->mcol[i]; - mc[0]=mc[1]=mc[2]=mc[3]=sd->mcol[i]; - } - } - } -} - -static void static_particle_wire(ObjectRen *obr, Material *ma, const float vec[3], const float vec1[3], int first, int line) -{ - VlakRen *vlr; - static VertRen *v1; - - if (line) { - vlr= RE_findOrAddVlak(obr, obr->totvlak++); - vlr->v1= RE_findOrAddVert(obr, obr->totvert++); - vlr->v2= RE_findOrAddVert(obr, obr->totvert++); - vlr->v3= vlr->v2; - vlr->v4= NULL; - - copy_v3_v3(vlr->v1->co, vec); - copy_v3_v3(vlr->v2->co, vec1); - - sub_v3_v3v3(vlr->n, vec, vec1); - normalize_v3(vlr->n); - copy_v3_v3(vlr->v1->n, vlr->n); - copy_v3_v3(vlr->v2->n, vlr->n); - - vlr->mat= ma; - vlr->ec= ME_V1V2; - - } - else if (first) { - v1= RE_findOrAddVert(obr, obr->totvert++); - copy_v3_v3(v1->co, vec); - } - else { - vlr= RE_findOrAddVlak(obr, obr->totvlak++); - vlr->v1= v1; - vlr->v2= RE_findOrAddVert(obr, obr->totvert++); - vlr->v3= vlr->v2; - vlr->v4= NULL; - - v1= vlr->v2; /* cycle */ - copy_v3_v3(v1->co, vec); - - sub_v3_v3v3(vlr->n, vec, vec1); - normalize_v3(vlr->n); - copy_v3_v3(v1->n, vlr->n); - - vlr->mat= ma; - vlr->ec= ME_V1V2; - } - -} - -static void particle_curve(Render *re, ObjectRen *obr, DerivedMesh *dm, Material *ma, ParticleStrandData *sd, - const float loc[3], const float loc1[3], int seed, float *pa_co) -{ - HaloRen *har = NULL; - - if (ma->material_type == MA_TYPE_WIRE) - static_particle_wire(obr, ma, loc, loc1, sd->first, sd->line); - else if (ma->material_type == MA_TYPE_HALO) { - har= RE_inithalo_particle(re, obr, dm, ma, loc, loc1, sd->orco, sd->uvco, sd->size, 1.0, seed, pa_co); - if (har) har->lay= obr->ob->lay; - } - else - static_particle_strand(re, obr, ma, sd, loc, loc1); -} -static void particle_billboard(Render *re, ObjectRen *obr, Material *ma, ParticleBillboardData *bb) -{ - VlakRen *vlr; - MTFace *mtf; - float xvec[3], yvec[3], zvec[3], bb_center[3]; - /* Number of tiles */ - int totsplit = bb->uv_split * bb->uv_split; - int tile, x, y; - /* Tile offsets */ - float uvx = 0.0f, uvy = 0.0f, uvdx = 1.0f, uvdy = 1.0f, time = 0.0f; - - vlr= RE_findOrAddVlak(obr, obr->totvlak++); - vlr->v1= RE_findOrAddVert(obr, obr->totvert++); - vlr->v2= RE_findOrAddVert(obr, obr->totvert++); - vlr->v3= RE_findOrAddVert(obr, obr->totvert++); - vlr->v4= RE_findOrAddVert(obr, obr->totvert++); - - psys_make_billboard(bb, xvec, yvec, zvec, bb_center); - - add_v3_v3v3(vlr->v1->co, bb_center, xvec); - add_v3_v3(vlr->v1->co, yvec); - mul_m4_v3(re->viewmat, vlr->v1->co); - - sub_v3_v3v3(vlr->v2->co, bb_center, xvec); - add_v3_v3(vlr->v2->co, yvec); - mul_m4_v3(re->viewmat, vlr->v2->co); - - sub_v3_v3v3(vlr->v3->co, bb_center, xvec); - sub_v3_v3v3(vlr->v3->co, vlr->v3->co, yvec); - mul_m4_v3(re->viewmat, vlr->v3->co); - - add_v3_v3v3(vlr->v4->co, bb_center, xvec); - sub_v3_v3(vlr->v4->co, yvec); - mul_m4_v3(re->viewmat, vlr->v4->co); - - normal_quad_v3(vlr->n, vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co); - copy_v3_v3(vlr->v1->n, vlr->n); - copy_v3_v3(vlr->v2->n, vlr->n); - copy_v3_v3(vlr->v3->n, vlr->n); - copy_v3_v3(vlr->v4->n, vlr->n); - - vlr->mat= ma; - vlr->ec= ME_V2V3; - - if (bb->uv_split > 1) { - uvdx = uvdy = 1.0f / (float)bb->uv_split; - - if (ELEM(bb->anim, PART_BB_ANIM_AGE, PART_BB_ANIM_FRAME)) { - if (bb->anim == PART_BB_ANIM_FRAME) - time = ((int)(bb->time * bb->lifetime) % totsplit)/(float)totsplit; - else - time = bb->time; - } - else if (bb->anim == PART_BB_ANIM_ANGLE) { - if (bb->align == PART_BB_VIEW) { - time = (float)fmod((bb->tilt + 1.0f) / 2.0f, 1.0); - } - else { - float axis1[3] = {0.0f, 0.0f, 0.0f}; - float axis2[3] = {0.0f, 0.0f, 0.0f}; - - axis1[(bb->align + 1) % 3] = 1.0f; - axis2[(bb->align + 2) % 3] = 1.0f; - - if (bb->lock == 0) { - zvec[bb->align] = 0.0f; - normalize_v3(zvec); - } - - time = saacos(dot_v3v3(zvec, axis1)) / (float)M_PI; - - if (dot_v3v3(zvec, axis2) < 0.0f) - time = 1.0f - time / 2.0f; - else - time /= 2.0f; - } - } - - if (bb->split_offset == PART_BB_OFF_LINEAR) - time = (float)fmod(time + (float)bb->num / (float)totsplit, 1.0f); - else if (bb->split_offset==PART_BB_OFF_RANDOM) - time = (float)fmod(time + bb->random, 1.0f); - - /* Find the coordinates in tile space (integer), then convert to UV - * space (float). Note that Y is flipped. */ - tile = (int)((time + FLT_EPSILON10) * totsplit); - x = tile % bb->uv_split; - y = tile / bb->uv_split; - y = (bb->uv_split - 1) - y; - uvx = uvdx * x; - uvy = uvdy * y; - } - - /* normal UVs */ - if (bb->uv[0] >= 0) { - mtf = RE_vlakren_get_tface(obr, vlr, bb->uv[0], NULL, 1); - mtf->uv[0][0] = 1.0f; - mtf->uv[0][1] = 1.0f; - mtf->uv[1][0] = 0.0f; - mtf->uv[1][1] = 1.0f; - mtf->uv[2][0] = 0.0f; - mtf->uv[2][1] = 0.0f; - mtf->uv[3][0] = 1.0f; - mtf->uv[3][1] = 0.0f; - } - - /* time-index UVs */ - if (bb->uv[1] >= 0) { - mtf = RE_vlakren_get_tface(obr, vlr, bb->uv[1], NULL, 1); - mtf->uv[0][0] = mtf->uv[1][0] = mtf->uv[2][0] = mtf->uv[3][0] = bb->time; - mtf->uv[0][1] = mtf->uv[1][1] = mtf->uv[2][1] = mtf->uv[3][1] = (float)bb->num/(float)bb->totnum; - } - - /* split UVs */ - if (bb->uv_split > 1 && bb->uv[2] >= 0) { - mtf = RE_vlakren_get_tface(obr, vlr, bb->uv[2], NULL, 1); - mtf->uv[0][0] = uvx + uvdx; - mtf->uv[0][1] = uvy + uvdy; - mtf->uv[1][0] = uvx; - mtf->uv[1][1] = uvy + uvdy; - mtf->uv[2][0] = uvx; - mtf->uv[2][1] = uvy; - mtf->uv[3][0] = uvx + uvdx; - mtf->uv[3][1] = uvy; - } -} -static void particle_normal_ren(short ren_as, ParticleSettings *part, Render *re, ObjectRen *obr, DerivedMesh *dm, Material *ma, ParticleStrandData *sd, ParticleBillboardData *bb, ParticleKey *state, int seed, float hasize, float *pa_co) -{ - float loc[3], loc0[3], loc1[3], vel[3]; - - copy_v3_v3(loc, state->co); - - if (ren_as != PART_DRAW_BB) - mul_m4_v3(re->viewmat, loc); - - switch (ren_as) { - case PART_DRAW_LINE: - sd->line = 1; - sd->time = 0.0f; - sd->size = hasize; - - mul_v3_mat3_m4v3(vel, re->viewmat, state->vel); - normalize_v3(vel); - - if (part->draw & PART_DRAW_VEL_LENGTH) - mul_v3_fl(vel, len_v3(state->vel)); - - madd_v3_v3v3fl(loc0, loc, vel, -part->draw_line[0]); - madd_v3_v3v3fl(loc1, loc, vel, part->draw_line[1]); - - particle_curve(re, obr, dm, ma, sd, loc0, loc1, seed, pa_co); - - break; - - case PART_DRAW_BB: - - copy_v3_v3(bb->vec, loc); - copy_v3_v3(bb->vel, state->vel); - - particle_billboard(re, obr, ma, bb); - - break; - - default: - { - HaloRen *har = NULL; - - har = RE_inithalo_particle(re, obr, dm, ma, loc, NULL, sd->orco, sd->uvco, hasize, 0.0, seed, pa_co); - - if (har) har->lay= obr->ob->lay; - - break; - } - } -} -static void get_particle_uvco_mcol(short from, DerivedMesh *dm, float *fuv, int num, ParticleStrandData *sd) -{ - int i; - - /* get uvco */ - if (sd->uvco && ELEM(from, PART_FROM_FACE, PART_FROM_VOLUME)) { - for (i=0; i<sd->totuv; i++) { - if (!ELEM(num, DMCACHE_NOTFOUND, DMCACHE_ISCHILD)) { - MFace *mface = dm->getTessFaceData(dm, num, CD_MFACE); - MTFace *mtface = (MTFace*)CustomData_get_layer_n(&dm->faceData, CD_MTFACE, i); - mtface += num; - - psys_interpolate_uvs(mtface, mface->v4, fuv, sd->uvco + 2 * i); - } - else { - sd->uvco[2*i] = 0.0f; - sd->uvco[2*i + 1] = 0.0f; - } - } - } - - /* get mcol */ - if (sd->mcol && ELEM(from, PART_FROM_FACE, PART_FROM_VOLUME)) { - for (i=0; i<sd->totcol; i++) { - if (!ELEM(num, DMCACHE_NOTFOUND, DMCACHE_ISCHILD)) { - MFace *mface = dm->getTessFaceData(dm, num, CD_MFACE); - MCol *mc = (MCol*)CustomData_get_layer_n(&dm->faceData, CD_MCOL, i); - mc += num * 4; - - psys_interpolate_mcol(mc, mface->v4, fuv, sd->mcol + i); - } - else - memset(&sd->mcol[i], 0, sizeof(MCol)); - } - } -} -static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem *psys, int timeoffset) -{ - Object *ob= obr->ob; -// Object *tob=0; - Material *ma = NULL; - ParticleSystemModifierData *psmd; - ParticleSystem *tpsys = NULL; - ParticleSettings *part, *tpart = NULL; - ParticleData *pars, *pa = NULL, *tpa = NULL; - ParticleKey *states = NULL; - ParticleKey state; - ParticleCacheKey *cache = NULL; - ParticleBillboardData bb; - ParticleSimulationData sim = {NULL}; - ParticleStrandData sd; - StrandBuffer *strandbuf = NULL; - StrandVert *svert = NULL; - StrandBound *sbound = NULL; - StrandRen *strand = NULL; - RNG *rng = NULL; - float loc[3], loc1[3], loc0[3], mat[4][4], nmat[3][3], co[3], nor[3], duplimat[4][4]; - float strandlen=0.0f, curlen=0.0f; - float hasize, pa_size, r_tilt, r_length; - float pa_time, pa_birthtime, pa_dietime; - float random, simplify[2], pa_co[3]; - const float cfra= BKE_scene_frame_get(re->scene); - int i, a, k, max_k=0, totpart; - bool do_simplify = false, do_surfacecache = false, use_duplimat = false; - int totchild=0, step_nbr; - int seed, path_nbr=0, orco1=0, num; - int totface; - - const int *index_mf_to_mpoly = NULL; - const int *index_mp_to_orig = NULL; - -/* 1. check that everything is ok & updated */ - if (psys==NULL) - return 0; - - part=psys->part; - pars=psys->particles; - - if (part==NULL || pars==NULL || !psys_check_enabled(ob, psys, G.is_rendering)) - return 0; - - if (part->ren_as==PART_DRAW_OB || part->ren_as==PART_DRAW_GR || part->ren_as==PART_DRAW_NOT) - return 1; - - if ((re->r.scemode & R_VIEWPORT_PREVIEW) && (ob->mode & OB_MODE_PARTICLE_EDIT)) - return 0; - - if (part->ren_as == PART_DRAW_BB && part->bb_ob == NULL && RE_GetCamera(re) == NULL) - return 0; - -/* 2. start initializing things */ - - /* last possibility to bail out! */ - psmd = psys_get_modifier(ob, psys); - if (!(psmd->modifier.mode & eModifierMode_Render)) - return 0; - - sim.scene= re->scene; - sim.ob= ob; - sim.psys= psys; - sim.psmd= psmd; - - if (part->phystype==PART_PHYS_KEYED) - psys_count_keyed_targets(&sim); - - totchild=psys->totchild; - - /* can happen for disconnected/global hair */ - if (part->type==PART_HAIR && !psys->childcache) - totchild= 0; - - if (re->r.scemode & R_VIEWPORT_PREVIEW) { /* preview render */ - totchild = (int)((float)totchild * (float)part->disp / 100.0f); - step_nbr = 1 << part->draw_step; - } - else { - step_nbr = 1 << part->ren_step; - } - if (ELEM(part->kink, PART_KINK_SPIRAL)) - step_nbr += part->kink_extra_steps; - - psys->flag |= PSYS_DRAWING; - - rng= BLI_rng_new(psys->seed); - - totpart=psys->totpart; - - memset(&sd, 0, sizeof(ParticleStrandData)); - sd.override_uv = -1; - -/* 2.1 setup material stff */ - ma= give_render_material(re, ob, part->omat); - -#if 0 /* XXX old animation system */ - if (ma->ipo) { - calc_ipo(ma->ipo, cfra); - execute_ipo((ID *)ma, ma->ipo); - } -#endif /* XXX old animation system */ - - hasize = ma->hasize; - seed = ma->seed1; - - re->flag |= R_HALO; - - RE_set_customdata_names(obr, &psmd->dm_final->faceData); - sd.totuv = CustomData_number_of_layers(&psmd->dm_final->faceData, CD_MTFACE); - sd.totcol = CustomData_number_of_layers(&psmd->dm_final->faceData, CD_MCOL); - - if (ma->texco & TEXCO_UV && sd.totuv) { - sd.uvco = MEM_callocN(sd.totuv * 2 * sizeof(float), "particle_uvs"); - - if (ma->strand_uvname[0]) { - sd.override_uv = CustomData_get_named_layer_index(&psmd->dm_final->faceData, CD_MTFACE, ma->strand_uvname); - sd.override_uv -= CustomData_get_layer_index(&psmd->dm_final->faceData, CD_MTFACE); - } - } - else - sd.uvco = NULL; - - if (sd.totcol) - sd.mcol = MEM_callocN(sd.totcol * sizeof(MCol), "particle_mcols"); - -/* 2.2 setup billboards */ - if (part->ren_as == PART_DRAW_BB) { - int first_uv = CustomData_get_layer_index(&psmd->dm_final->faceData, CD_MTFACE); - - bb.uv[0] = CustomData_get_named_layer_index(&psmd->dm_final->faceData, CD_MTFACE, psys->bb_uvname[0]); - if (bb.uv[0] < 0) - bb.uv[0] = CustomData_get_active_layer_index(&psmd->dm_final->faceData, CD_MTFACE); - - bb.uv[1] = CustomData_get_named_layer_index(&psmd->dm_final->faceData, CD_MTFACE, psys->bb_uvname[1]); - - bb.uv[2] = CustomData_get_named_layer_index(&psmd->dm_final->faceData, CD_MTFACE, psys->bb_uvname[2]); - - if (first_uv >= 0) { - bb.uv[0] -= first_uv; - bb.uv[1] -= first_uv; - bb.uv[2] -= first_uv; - } - - bb.align = part->bb_align; - bb.anim = part->bb_anim; - bb.lock = part->draw & PART_DRAW_BB_LOCK; - bb.ob = (part->bb_ob ? part->bb_ob : RE_GetCamera(re)); - bb.split_offset = part->bb_split_offset; - bb.totnum = totpart+totchild; - bb.uv_split = part->bb_uv_split; - } - -/* 2.5 setup matrices */ - mul_m4_m4m4(mat, re->viewmat, ob->obmat); - invert_m4_m4(ob->imat, mat); /* need to be that way, for imat texture */ - transpose_m3_m4(nmat, ob->imat); - - if (psys->flag & PSYS_USE_IMAT) { - /* psys->imat is the original emitter's inverse matrix, ob->obmat is the duplicated object's matrix */ - mul_m4_m4m4(duplimat, ob->obmat, psys->imat); - use_duplimat = true; - } - -/* 2.6 setup strand rendering */ - if (part->ren_as == PART_DRAW_PATH && psys->pathcache) { - path_nbr = step_nbr; - - if (path_nbr) { - if (!ELEM(ma->material_type, MA_TYPE_HALO, MA_TYPE_WIRE)) { - sd.orco = get_object_orco(re, psys); - if (!sd.orco) { - sd.orco = MEM_mallocN(3*sizeof(float)*(totpart+totchild), "particle orcos"); - set_object_orco(re, psys, sd.orco); - } - } - } - - if (part->draw & PART_DRAW_REN_ADAPT) { - sd.adapt = 1; - sd.adapt_pix = (float)part->adapt_pix; - sd.adapt_angle = cosf(DEG2RADF((float)part->adapt_angle)); - } - - if (part->draw & PART_DRAW_REN_STRAND) { - strandbuf= RE_addStrandBuffer(obr, (totpart+totchild)*(path_nbr+1)); - strandbuf->ma= ma; - strandbuf->lay= ob->lay; - copy_m4_m4(strandbuf->winmat, re->winmat); - strandbuf->winx= re->winx; - strandbuf->winy= re->winy; - strandbuf->maxdepth= 2; - strandbuf->adaptcos= cosf(DEG2RADF((float)part->adapt_angle)); - strandbuf->overrideuv= sd.override_uv; - strandbuf->minwidth= ma->strand_min; - - if (ma->strand_widthfade == 0.0f) - strandbuf->widthfade= -1.0f; - else if (ma->strand_widthfade >= 1.0f) - strandbuf->widthfade= 2.0f - ma->strand_widthfade; - else - strandbuf->widthfade= 1.0f/MAX2(ma->strand_widthfade, 1e-5f); - - if (part->flag & PART_HAIR_BSPLINE) - strandbuf->flag |= R_STRAND_BSPLINE; - if (ma->mode & MA_STR_B_UNITS) - strandbuf->flag |= R_STRAND_B_UNITS; - - svert= strandbuf->vert; - - if (re->r.mode & R_SPEED) - do_surfacecache = true; - else if ((re->wrld.mode & (WO_AMB_OCC|WO_ENV_LIGHT|WO_INDIRECT_LIGHT)) && (re->wrld.ao_gather_method == WO_AOGATHER_APPROX)) - if (ma->amb != 0.0f) - do_surfacecache = true; - - totface= psmd->dm_final->getNumTessFaces(psmd->dm_final); - index_mf_to_mpoly = psmd->dm_final->getTessFaceDataArray(psmd->dm_final, CD_ORIGINDEX); - index_mp_to_orig = psmd->dm_final->getPolyDataArray(psmd->dm_final, CD_ORIGINDEX); - if (index_mf_to_mpoly == NULL) { - index_mp_to_orig = NULL; - } - for (a=0; a<totface; a++) - strandbuf->totbound = max_ii(strandbuf->totbound, (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, a): a); - - strandbuf->totbound++; - strandbuf->bound= MEM_callocN(sizeof(StrandBound)*strandbuf->totbound, "StrandBound"); - sbound= strandbuf->bound; - sbound->start= sbound->end= 0; - } - } - - if (sd.orco == NULL) { - sd.orco = MEM_mallocN(3 * sizeof(float), "particle orco"); - orco1 = 1; - } - - if (path_nbr == 0) - psys->lattice_deform_data = psys_create_lattice_deform_data(&sim); - -/* 3. start creating renderable things */ - for (a=0, pa=pars; a<totpart+totchild; a++, pa++, seed++) { - random = BLI_rng_get_float(rng); - /* setup per particle individual stuff */ - if (a<totpart) { - if (pa->flag & PARS_UNEXIST) continue; - - pa_time=(cfra-pa->time)/pa->lifetime; - pa_birthtime = pa->time; - pa_dietime = pa->dietime; - - hasize = ma->hasize; - - /* XXX 'tpsys' is alwyas NULL, this code won't run! */ - /* get orco */ - if (tpsys && part->phystype == PART_PHYS_NO) { - tpa = tpsys->particles + pa->num; - psys_particle_on_emitter( - psmd, - tpart->from, tpa->num, pa->num_dmcache, tpa->fuv, - tpa->foffset, co, nor, NULL, NULL, sd.orco, NULL); - } - else { - psys_particle_on_emitter( - psmd, - part->from, pa->num, pa->num_dmcache, - pa->fuv, pa->foffset, co, nor, NULL, NULL, sd.orco, NULL); - } - - /* get uvco & mcol */ - num= pa->num_dmcache; - - if (num == DMCACHE_NOTFOUND) - if (pa->num < psmd->dm_final->getNumTessFaces(psmd->dm_final)) - num= pa->num; - - get_particle_uvco_mcol(part->from, psmd->dm_final, pa->fuv, num, &sd); - - pa_size = pa->size; - - r_tilt = 2.0f*(psys_frand(psys, a) - 0.5f); - r_length = psys_frand(psys, a+1); - - if (path_nbr) { - cache = psys->pathcache[a]; - max_k = (int)cache->segments; - } - - if (totchild && (part->draw&PART_DRAW_PARENT)==0) continue; - } - else { - ChildParticle *cpa= psys->child+a-totpart; - - if (path_nbr) { - cache = psys->childcache[a-totpart]; - - if (cache->segments < 0) - continue; - - max_k = (int)cache->segments; - } - - pa_time = psys_get_child_time(psys, cpa, cfra, &pa_birthtime, &pa_dietime); - pa_size = psys_get_child_size(psys, cpa, cfra, &pa_time); - - r_tilt = 2.0f*(psys_frand(psys, a + 21) - 0.5f); - r_length = psys_frand(psys, a + 22); - - num = cpa->num; - - /* get orco */ - if (part->childtype == PART_CHILD_FACES) { - psys_particle_on_emitter( - psmd, - PART_FROM_FACE, cpa->num, DMCACHE_ISCHILD, - cpa->fuv, cpa->foffset, co, nor, NULL, NULL, sd.orco, NULL); - } - else { - ParticleData *par = psys->particles + cpa->parent; - psys_particle_on_emitter( - psmd, - part->from, par->num, DMCACHE_ISCHILD, par->fuv, - par->foffset, co, nor, NULL, NULL, sd.orco, NULL); - } - - /* get uvco & mcol */ - if (part->childtype==PART_CHILD_FACES) { - get_particle_uvco_mcol(PART_FROM_FACE, psmd->dm_final, cpa->fuv, cpa->num, &sd); - } - else { - ParticleData *parent = psys->particles + cpa->parent; - num = parent->num_dmcache; - - if (num == DMCACHE_NOTFOUND) - if (parent->num < psmd->dm_final->getNumTessFaces(psmd->dm_final)) - num = parent->num; - - get_particle_uvco_mcol(part->from, psmd->dm_final, parent->fuv, num, &sd); - } - - do_simplify = psys_render_simplify_params(psys, cpa, simplify); - - if (strandbuf) { - int orignum = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, cpa->num) : cpa->num; - - if ((orignum > sbound - strandbuf->bound) && - (orignum < strandbuf->totbound)) - { - sbound = &strandbuf->bound[orignum]; - sbound->start = sbound->end = obr->totstrand; - } - } - } - - /* TEXCO_PARTICLE */ - pa_co[0] = pa_time; - pa_co[1] = 0.f; - pa_co[2] = 0.f; - - /* surface normal shading setup */ - if (ma->mode_l & MA_STR_SURFDIFF) { - mul_m3_v3(nmat, nor); - sd.surfnor= nor; - } - else - sd.surfnor= NULL; - - /* strand render setup */ - if (strandbuf) { - strand= RE_findOrAddStrand(obr, obr->totstrand++); - strand->buffer= strandbuf; - strand->vert= svert; - copy_v3_v3(strand->orco, sd.orco); - - if (do_simplify) { - float *ssimplify= RE_strandren_get_simplify(obr, strand, 1); - ssimplify[0]= simplify[0]; - ssimplify[1]= simplify[1]; - } - - if (sd.surfnor) { - float *snor= RE_strandren_get_surfnor(obr, strand, 1); - copy_v3_v3(snor, sd.surfnor); - } - - if (do_surfacecache && num >= 0) { - int *facenum= RE_strandren_get_face(obr, strand, 1); - *facenum= num; - } - - if (sd.uvco) { - for (i=0; i<sd.totuv; i++) { - if (i != sd.override_uv) { - float *uv= RE_strandren_get_uv(obr, strand, i, NULL, 1); - - uv[0]= sd.uvco[2*i]; - uv[1]= sd.uvco[2*i+1]; - } - } - } - if (sd.mcol) { - for (i=0; i<sd.totcol; i++) { - MCol *mc= RE_strandren_get_mcol(obr, strand, i, NULL, 1); - *mc = sd.mcol[i]; - } - } - - sbound->end++; - } - - /* strandco computation setup */ - if (path_nbr) { - strandlen= 0.0f; - curlen= 0.0f; - for (k=1; k<=path_nbr; k++) - if (k<=max_k) - strandlen += len_v3v3((cache+k-1)->co, (cache+k)->co); - } - - if (path_nbr) { - /* render strands */ - for (k=0; k<=path_nbr; k++) { - float time; - - if (k<=max_k) { - copy_v3_v3(state.co, (cache+k)->co); - copy_v3_v3(state.vel, (cache+k)->vel); - } - else - continue; - - if (k > 0) - curlen += len_v3v3((cache+k-1)->co, (cache+k)->co); - time= curlen/strandlen; - - copy_v3_v3(loc, state.co); - mul_m4_v3(re->viewmat, loc); - - if (strandbuf) { - copy_v3_v3(svert->co, loc); - svert->strandco= -1.0f + 2.0f*time; - svert++; - strand->totvert++; - } - else { - sd.size = hasize; - - if (k==1) { - sd.first = 1; - sd.time = 0.0f; - sub_v3_v3v3(loc0, loc1, loc); - add_v3_v3v3(loc0, loc1, loc0); - - particle_curve(re, obr, psmd->dm_final, ma, &sd, loc1, loc0, seed, pa_co); - } - - sd.first = 0; - sd.time = time; - - if (k) - particle_curve(re, obr, psmd->dm_final, ma, &sd, loc, loc1, seed, pa_co); - - copy_v3_v3(loc1, loc); - } - } - - } - else { - /* render normal particles */ - if (part->trail_count > 1) { - float length = part->path_end * (1.0f - part->randlength * r_length); - int trail_count = part->trail_count * (1.0f - part->randlength * r_length); - float ct = (part->draw & PART_ABS_PATH_TIME) ? cfra : pa_time; - float dt = length / (trail_count ? (float)trail_count : 1.0f); - - /* make sure we have pointcache in memory before getting particle on path */ - psys_make_temp_pointcache(ob, psys); - - for (i=0; i < trail_count; i++, ct -= dt) { - if (part->draw & PART_ABS_PATH_TIME) { - if (ct < pa_birthtime || ct > pa_dietime) - continue; - } - else if (ct < 0.0f || ct > 1.0f) - continue; - - state.time = (part->draw & PART_ABS_PATH_TIME) ? -ct : ct; - psys_get_particle_on_path(&sim, a, &state, 1); - - if (psys->parent) - mul_m4_v3(psys->parent->obmat, state.co); - - if (use_duplimat) - mul_m4_v4(duplimat, state.co); - - if (part->ren_as == PART_DRAW_BB) { - bb.random = random; - bb.offset[0] = part->bb_offset[0]; - bb.offset[1] = part->bb_offset[1]; - bb.size[0] = part->bb_size[0] * pa_size; - if (part->bb_align==PART_BB_VEL) { - float pa_vel = len_v3(state.vel); - float head = part->bb_vel_head*pa_vel; - float tail = part->bb_vel_tail*pa_vel; - bb.size[1] = part->bb_size[1]*pa_size + head + tail; - /* use offset to adjust the particle center. this is relative to size, so need to divide! */ - if (bb.size[1] > 0.0f) - bb.offset[1] += (head-tail) / bb.size[1]; - } - else - bb.size[1] = part->bb_size[1] * pa_size; - bb.tilt = part->bb_tilt * (1.0f - part->bb_rand_tilt * r_tilt); - bb.time = ct; - bb.num = a; - } - - pa_co[0] = (part->draw & PART_ABS_PATH_TIME) ? (ct-pa_birthtime)/(pa_dietime-pa_birthtime) : ct; - pa_co[1] = (float)i/(float)(trail_count-1); - - particle_normal_ren(part->ren_as, part, re, obr, psmd->dm_final, ma, &sd, &bb, &state, seed, hasize, pa_co); - } - } - else { - state.time=cfra; - if (psys_get_particle_state(&sim, a, &state, 0)==0) - continue; - - if (psys->parent) - mul_m4_v3(psys->parent->obmat, state.co); - - if (use_duplimat) - mul_m4_v3(duplimat, state.co); - - if (part->ren_as == PART_DRAW_BB) { - bb.random = random; - bb.offset[0] = part->bb_offset[0]; - bb.offset[1] = part->bb_offset[1]; - bb.size[0] = part->bb_size[0] * pa_size; - if (part->bb_align==PART_BB_VEL) { - float pa_vel = len_v3(state.vel); - float head = part->bb_vel_head*pa_vel; - float tail = part->bb_vel_tail*pa_vel; - bb.size[1] = part->bb_size[1]*pa_size + head + tail; - /* use offset to adjust the particle center. this is relative to size, so need to divide! */ - if (bb.size[1] > 0.0f) - bb.offset[1] += (head-tail) / bb.size[1]; - } - else - bb.size[1] = part->bb_size[1] * pa_size; - bb.tilt = part->bb_tilt * (1.0f - part->bb_rand_tilt * r_tilt); - bb.time = pa_time; - bb.num = a; - bb.lifetime = pa_dietime-pa_birthtime; - } - - particle_normal_ren(part->ren_as, part, re, obr, psmd->dm_final, ma, &sd, &bb, &state, seed, hasize, pa_co); - } - } - - if (orco1==0) - sd.orco+=3; - - if (re->test_break(re->tbh)) - break; - } - - if (do_surfacecache) - strandbuf->surface= cache_strand_surface(re, obr, psmd->dm_final, mat, timeoffset); - -/* 4. clean up */ -#if 0 /* XXX old animation system */ - if (ma) do_mat_ipo(re->scene, ma); -#endif /* XXX old animation system */ - - if (orco1) - MEM_freeN(sd.orco); - - if (sd.uvco) - MEM_freeN(sd.uvco); - - if (sd.mcol) - MEM_freeN(sd.mcol); - - if (states) - MEM_freeN(states); - - BLI_rng_free(rng); - - psys->flag &= ~PSYS_DRAWING; - - if (psys->lattice_deform_data) { - end_latt_deform(psys->lattice_deform_data); - psys->lattice_deform_data = NULL; - } - - if (path_nbr && (ma->mode_l & MA_TANGENT_STR)==0) - calc_vertexnormals(re, obr, 1, 0, 0); - - return 1; -} - -/* ------------------------------------------------------------------------- */ -/* Halo's */ -/* ------------------------------------------------------------------------- */ - -static void make_render_halos(Render *re, ObjectRen *obr, Mesh *UNUSED(me), int totvert, MVert *mvert, Material *ma, float *orco) -{ - Object *ob= obr->ob; - HaloRen *har; - float xn, yn, zn, nor[3], view[3]; - float vec[3], hasize, mat[4][4], imat[3][3]; - int a, ok, seed= ma->seed1; - - mul_m4_m4m4(mat, re->viewmat, ob->obmat); - copy_m3_m4(imat, ob->imat); - - re->flag |= R_HALO; - - for (a=0; a<totvert; a++, mvert++) { - ok= 1; - - if (ok) { - hasize= ma->hasize; - - copy_v3_v3(vec, mvert->co); - mul_m4_v3(mat, vec); - - if (ma->mode & MA_HALOPUNO) { - xn= mvert->no[0]; - yn= mvert->no[1]; - zn= mvert->no[2]; - - /* transpose ! */ - nor[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn; - nor[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn; - nor[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn; - normalize_v3(nor); - - copy_v3_v3(view, vec); - normalize_v3(view); - - zn = dot_v3v3(nor, view); - if (zn>=0.0f) hasize= 0.0f; - else hasize*= zn*zn*zn*zn; - } - - if (orco) har= RE_inithalo(re, obr, ma, vec, NULL, orco, hasize, 0.0, seed); - else har= RE_inithalo(re, obr, ma, vec, NULL, mvert->co, hasize, 0.0, seed); - if (har) har->lay= ob->lay; - } - if (orco) orco+= 3; - seed++; - } -} - -static int verghalo(const void *a1, const void *a2) -{ - const HaloRen *har1= *(const HaloRen**)a1; - const HaloRen *har2= *(const HaloRen**)a2; - - if (har1->zs < har2->zs) return 1; - else if (har1->zs > har2->zs) return -1; - return 0; -} - -static void sort_halos(Render *re, int totsort) -{ - ObjectRen *obr; - HaloRen *har= NULL, **haso; - int a; - - if (re->tothalo==0) return; - - re->sortedhalos= MEM_callocN(sizeof(HaloRen*)*re->tothalo, "sorthalos"); - haso= re->sortedhalos; - - for (obr=re->objecttable.first; obr; obr=obr->next) { - for (a=0; a<obr->tothalo; a++) { - if ((a & 255)==0) har= obr->bloha[a>>8]; - else har++; - - *(haso++)= har; - } - } - - qsort(re->sortedhalos, totsort, sizeof(HaloRen*), verghalo); -} - -/* ------------------------------------------------------------------------- */ -/* Displacement Mapping */ -/* ------------------------------------------------------------------------- */ - -static short test_for_displace(Render *re, Object *ob) -{ - /* return 1 when this object uses displacement textures. */ - Material *ma; - int i; - - for (i=1; i<=ob->totcol; i++) { - ma=give_render_material(re, ob, i); - /* ma->mapto is ORed total of all mapto channels */ - if (ma && (ma->mapto & MAP_DISPLACE)) return 1; - } - return 0; -} - -static void displace_render_vert(Render *re, ObjectRen *obr, ShadeInput *shi, VertRen *vr, int vindex, float *scale) -{ - MTFace *tface; - short texco= shi->mat->texco; - float sample=0, displace[3]; - char *name; - int i; - - /* shi->co is current render coord, just make sure at least some vector is here */ - copy_v3_v3(shi->co, vr->co); - /* vertex normal is used for textures type 'col' and 'var' */ - copy_v3_v3(shi->vn, vr->n); - - if (texco & TEXCO_UV) { - shi->totuv= 0; - shi->actuv= obr->actmtface; - - for (i=0; (tface=RE_vlakren_get_tface(obr, shi->vlr, i, &name, 0)); i++) { - ShadeInputUV *suv= &shi->uv[i]; - - /* shi.uv needs scale correction from tface uv */ - suv->uv[0]= 2*tface->uv[vindex][0]-1.0f; - suv->uv[1]= 2*tface->uv[vindex][1]-1.0f; - suv->uv[2]= 0.0f; - suv->name= name; - shi->totuv++; - } - } - - /* set all rendercoords, 'texco' is an ORed value for all textures needed */ - if ((texco & TEXCO_ORCO) && (vr->orco)) { - copy_v3_v3(shi->lo, vr->orco); - } - if (texco & TEXCO_GLOB) { - copy_v3_v3(shi->gl, shi->co); - mul_m4_v3(re->viewinv, shi->gl); - } - if (texco & TEXCO_NORM) { - copy_v3_v3(shi->orn, shi->vn); - } - if (texco & TEXCO_REFL) { - /* not (yet?) */ - } - if (texco & TEXCO_STRESS) { - const float *s= RE_vertren_get_stress(obr, vr, 0); - - if (s) { - shi->stress= *s; - if (shi->stress<1.0f) shi->stress-= 1.0f; - else shi->stress= (shi->stress-1.0f)/shi->stress; - } - else - shi->stress= 0.0f; - } - - shi->displace[0]= shi->displace[1]= shi->displace[2]= 0.0; - - do_material_tex(shi, re); - - //printf("no=%f, %f, %f\nbefore co=%f, %f, %f\n", vr->n[0], vr->n[1], vr->n[2], - //vr->co[0], vr->co[1], vr->co[2]); - - displace[0]= shi->displace[0] * scale[0]; - displace[1]= shi->displace[1] * scale[1]; - displace[2]= shi->displace[2] * scale[2]; - - /* 0.5 could become button once? */ - vr->co[0] += displace[0]; - vr->co[1] += displace[1]; - vr->co[2] += displace[2]; - - //printf("after co=%f, %f, %f\n", vr->co[0], vr->co[1], vr->co[2]); - - /* we just don't do this vertex again, bad luck for other face using same vertex with - * different material... */ - vr->flag |= 1; - - /* Pass sample back so displace_face can decide which way to split the quad */ - sample = shi->displace[0]*shi->displace[0]; - sample += shi->displace[1]*shi->displace[1]; - sample += shi->displace[2]*shi->displace[2]; - - vr->accum=sample; - /* Should be sqrt(sample), but I'm only looking for "bigger". Save the cycles. */ - return; -} - -static void displace_render_face(Render *re, ObjectRen *obr, VlakRen *vlr, float *scale) -{ - ShadeInput shi; - - /* Warning, This is not that nice, and possibly a bit slow, - * however some variables were not initialized properly in, unless using shade_input_initialize(...), we need to do a memset */ - memset(&shi, 0, sizeof(ShadeInput)); - /* end warning! - Campbell */ - - /* set up shadeinput struct for multitex() */ - - /* memset above means we don't need this */ - /*shi.osatex= 0;*/ /* signal not to use dx[] and dy[] texture AA vectors */ - - shi.obr= obr; - shi.vlr= vlr; /* current render face */ - shi.mat= vlr->mat; /* current input material */ - shi.thread= 0; - - /* TODO, assign these, displacement with new bumpmap is skipped without - campbell */ -#if 0 - /* order is not known ? */ - shi.v1= vlr->v1; - shi.v2= vlr->v2; - shi.v3= vlr->v3; -#endif - - /* Displace the verts, flag is set when done */ - if (!vlr->v1->flag) - displace_render_vert(re, obr, &shi, vlr->v1, 0, scale); - - if (!vlr->v2->flag) - displace_render_vert(re, obr, &shi, vlr->v2, 1, scale); - - if (!vlr->v3->flag) - displace_render_vert(re, obr, &shi, vlr->v3, 2, scale); - - if (vlr->v4) { - if (!vlr->v4->flag) - displace_render_vert(re, obr, &shi, vlr->v4, 3, scale); - - /* closest in displace value. This will help smooth edges. */ - if (fabsf(vlr->v1->accum - vlr->v3->accum) > fabsf(vlr->v2->accum - vlr->v4->accum)) vlr->flag |= R_DIVIDE_24; - else vlr->flag &= ~R_DIVIDE_24; - } - - /* Recalculate the face normal - if flipped before, flip now */ - if (vlr->v4) { - normal_quad_v3(vlr->n, vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co); - } - else { - normal_tri_v3(vlr->n, vlr->v3->co, vlr->v2->co, vlr->v1->co); - } -} - -static void displace(Render *re, ObjectRen *obr) -{ - VertRen *vr; - VlakRen *vlr; -// float min[3]={1e30, 1e30, 1e30}, max[3]={-1e30, -1e30, -1e30}; - float scale[3]={1.0f, 1.0f, 1.0f}, temp[3];//, xn - int i; //, texflag=0; - Object *obt; - - /* Object Size with parenting */ - obt=obr->ob; - while (obt) { - mul_v3_v3v3(temp, obt->size, obt->dscale); - scale[0]*=temp[0]; scale[1]*=temp[1]; scale[2]*=temp[2]; - obt=obt->parent; - } - - /* Clear all flags */ - for (i=0; i<obr->totvert; i++) { - vr= RE_findOrAddVert(obr, i); - vr->flag= 0; - } - - for (i=0; i<obr->totvlak; i++) { - vlr=RE_findOrAddVlak(obr, i); - displace_render_face(re, obr, vlr, scale); - } - - /* Recalc vertex normals */ - calc_vertexnormals(re, obr, 1, 0, 0); -} - -/* ------------------------------------------------------------------------- */ -/* Metaball */ -/* ------------------------------------------------------------------------- */ - -static void init_render_mball(Render *re, ObjectRen *obr) -{ - Object *ob= obr->ob; - DispList *dl; - VertRen *ver; - VlakRen *vlr, *vlr1; - Material *ma; - float *data, *nors, *orco=NULL, mat[4][4], imat[3][3], xn, yn, zn; - int a, need_orco, vlakindex, *index, negative_scale; - ListBase dispbase= {NULL, NULL}; - - if (ob!=BKE_mball_basis_find(re->eval_ctx, re->scene, ob)) - return; - - mul_m4_m4m4(mat, re->viewmat, ob->obmat); - invert_m4_m4(ob->imat, mat); - copy_m3_m4(imat, ob->imat); - negative_scale = is_negative_m4(mat); - - ma= give_render_material(re, ob, 1); - - need_orco= 0; - if (ma->texco & TEXCO_ORCO) { - need_orco= 1; - } - - BKE_displist_make_mball_forRender(re->eval_ctx, re->scene, ob, &dispbase); - dl= dispbase.first; - if (dl == NULL) return; - - data= dl->verts; - nors= dl->nors; - if (need_orco) { - orco= get_object_orco(re, ob); - - if (!orco) { - /* orco hasn't been found in cache - create new one and add to cache */ - orco= BKE_mball_make_orco(ob, &dispbase); - set_object_orco(re, ob, orco); - } - } - - for (a=0; a<dl->nr; a++, data+=3, nors+=3) { - - ver= RE_findOrAddVert(obr, obr->totvert++); - copy_v3_v3(ver->co, data); - mul_m4_v3(mat, ver->co); - - /* render normals are inverted */ - xn= -nors[0]; - yn= -nors[1]; - zn= -nors[2]; - - /* transpose ! */ - ver->n[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn; - ver->n[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn; - ver->n[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn; - normalize_v3(ver->n); - //if (ob->transflag & OB_NEG_SCALE) negate_v3(ver->n); - - if (need_orco) { - ver->orco= orco; - orco+=3; - } - } - - index= dl->index; - for (a=0; a<dl->parts; a++, index+=4) { - - vlr= RE_findOrAddVlak(obr, obr->totvlak++); - vlr->v1= RE_findOrAddVert(obr, index[0]); - vlr->v2= RE_findOrAddVert(obr, index[1]); - vlr->v3= RE_findOrAddVert(obr, index[2]); - vlr->v4 = NULL; - - if (negative_scale) - normal_tri_v3(vlr->n, vlr->v1->co, vlr->v2->co, vlr->v3->co); - else - normal_tri_v3(vlr->n, vlr->v3->co, vlr->v2->co, vlr->v1->co); - - vlr->mat= ma; - vlr->flag= ME_SMOOTH; - vlr->ec= 0; - - /* mball -too bad- always has triangles, because quads can be non-planar */ - if (index[3] && index[3]!=index[2]) { - vlr1= RE_findOrAddVlak(obr, obr->totvlak++); - vlakindex= vlr1->index; - *vlr1= *vlr; - vlr1->index= vlakindex; - vlr1->v2= vlr1->v3; - vlr1->v3= RE_findOrAddVert(obr, index[3]); - if (negative_scale) - normal_tri_v3(vlr1->n, vlr1->v1->co, vlr1->v2->co, vlr1->v3->co); - else - normal_tri_v3(vlr1->n, vlr1->v3->co, vlr1->v2->co, vlr1->v1->co); - } - } - - /* enforce display lists remade */ - BKE_displist_free(&dispbase); -} - -/* ------------------------------------------------------------------------- */ -/* Surfaces and Curves */ -/* ------------------------------------------------------------------------- */ - -/* returns amount of vertices added for orco */ -static int dl_surf_to_renderdata(ObjectRen *obr, DispList *dl, Material **matar, float *orco, float mat[4][4]) -{ - VertRen *v1, *v2, *v3, *v4, *ver; - VlakRen *vlr, *vlr1, *vlr2, *vlr3; - float *data, n1[3]; - int u, v, orcoret= 0; - int p1, p2, p3, p4, a; - int sizeu, nsizeu, sizev, nsizev; - int startvert, startvlak; - - startvert= obr->totvert; - nsizeu = sizeu = dl->parts; nsizev = sizev = dl->nr; - - data= dl->verts; - for (u = 0; u < sizeu; u++) { - v1 = RE_findOrAddVert(obr, obr->totvert++); /* save this for possible V wrapping */ - copy_v3_v3(v1->co, data); data += 3; - if (orco) { - v1->orco= orco; orco+= 3; orcoret++; - } - mul_m4_v3(mat, v1->co); - - for (v = 1; v < sizev; v++) { - ver= RE_findOrAddVert(obr, obr->totvert++); - copy_v3_v3(ver->co, data); data += 3; - if (orco) { - ver->orco= orco; orco+= 3; orcoret++; - } - mul_m4_v3(mat, ver->co); - } - /* if V-cyclic, add extra vertices at end of the row */ - if (dl->flag & DL_CYCL_U) { - ver= RE_findOrAddVert(obr, obr->totvert++); - copy_v3_v3(ver->co, v1->co); - if (orco) { - ver->orco= orco; orco+=3; orcoret++; //orcobase + 3*(u*sizev + 0); - } - } - } - - /* Done before next loop to get corner vert */ - if (dl->flag & DL_CYCL_U) nsizev++; - if (dl->flag & DL_CYCL_V) nsizeu++; - - /* if U cyclic, add extra row at end of column */ - if (dl->flag & DL_CYCL_V) { - for (v = 0; v < nsizev; v++) { - v1= RE_findOrAddVert(obr, startvert + v); - ver= RE_findOrAddVert(obr, obr->totvert++); - copy_v3_v3(ver->co, v1->co); - if (orco) { - ver->orco= orco; orco+=3; orcoret++; //ver->orco= orcobase + 3*(0*sizev + v); - } - } - } - - sizeu = nsizeu; - sizev = nsizev; - - startvlak= obr->totvlak; - - for (u = 0; u < sizeu - 1; u++) { - p1 = startvert + u * sizev; /* walk through face list */ - p2 = p1 + 1; - p3 = p2 + sizev; - p4 = p3 - 1; - - for (v = 0; v < sizev - 1; v++) { - v1= RE_findOrAddVert(obr, p1); - v2= RE_findOrAddVert(obr, p2); - v3= RE_findOrAddVert(obr, p3); - v4= RE_findOrAddVert(obr, p4); - - vlr= RE_findOrAddVlak(obr, obr->totvlak++); - vlr->v1= v1; vlr->v2= v2; vlr->v3= v3; vlr->v4= v4; - - normal_quad_v3(n1, vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co); - - copy_v3_v3(vlr->n, n1); - - vlr->mat= matar[ dl->col]; - vlr->ec= ME_V1V2+ME_V2V3; - vlr->flag= dl->rt; - - add_v3_v3(v1->n, n1); - add_v3_v3(v2->n, n1); - add_v3_v3(v3->n, n1); - add_v3_v3(v4->n, n1); - - p1++; p2++; p3++; p4++; - } - } - /* fix normals for U resp. V cyclic faces */ - sizeu--; sizev--; /* dec size for face array */ - if (dl->flag & DL_CYCL_V) { - - for (v = 0; v < sizev; v++) { - /* optimize! :*/ - vlr= RE_findOrAddVlak(obr, UVTOINDEX(sizeu - 1, v)); - vlr1= RE_findOrAddVlak(obr, UVTOINDEX(0, v)); - add_v3_v3(vlr1->v1->n, vlr->n); - add_v3_v3(vlr1->v2->n, vlr->n); - add_v3_v3(vlr->v3->n, vlr1->n); - add_v3_v3(vlr->v4->n, vlr1->n); - } - } - if (dl->flag & DL_CYCL_U) { - - for (u = 0; u < sizeu; u++) { - /* optimize! :*/ - vlr= RE_findOrAddVlak(obr, UVTOINDEX(u, 0)); - vlr1= RE_findOrAddVlak(obr, UVTOINDEX(u, sizev-1)); - add_v3_v3(vlr1->v2->n, vlr->n); - add_v3_v3(vlr1->v3->n, vlr->n); - add_v3_v3(vlr->v1->n, vlr1->n); - add_v3_v3(vlr->v4->n, vlr1->n); - } - } - - /* last vertex is an extra case: - * - * ^ ()----()----()----() - * | | | || | - * u | |(0,n)||(0,0)| - * | | || | - * ()====()====[]====() - * | | || | - * | |(m,n)||(m,0)| - * | | || | - * ()----()----()----() - * v -> - * - * vertex [] is no longer shared, therefore distribute - * normals of the surrounding faces to all of the duplicates of [] - */ - - if ((dl->flag & DL_CYCL_V) && (dl->flag & DL_CYCL_U)) { - vlr= RE_findOrAddVlak(obr, UVTOINDEX(sizeu - 1, sizev - 1)); /* (m, n) */ - vlr1= RE_findOrAddVlak(obr, UVTOINDEX(0, 0)); /* (0, 0) */ - add_v3_v3v3(n1, vlr->n, vlr1->n); - vlr2= RE_findOrAddVlak(obr, UVTOINDEX(0, sizev-1)); /* (0, n) */ - add_v3_v3(n1, vlr2->n); - vlr3= RE_findOrAddVlak(obr, UVTOINDEX(sizeu-1, 0)); /* (m, 0) */ - add_v3_v3(n1, vlr3->n); - copy_v3_v3(vlr->v3->n, n1); - copy_v3_v3(vlr1->v1->n, n1); - copy_v3_v3(vlr2->v2->n, n1); - copy_v3_v3(vlr3->v4->n, n1); - } - for (a = startvert; a < obr->totvert; a++) { - ver= RE_findOrAddVert(obr, a); - normalize_v3(ver->n); - } - - - return orcoret; -} - -static void init_render_dm(DerivedMesh *dm, Render *re, ObjectRen *obr, - int timeoffset, float *orco, float mat[4][4]) -{ - Object *ob= obr->ob; - int a, end, totvert, vertofs; - short mat_iter; - VertRen *ver; - VlakRen *vlr; - MVert *mvert = NULL; - MFace *mface; - Material *ma; -#ifdef WITH_FREESTYLE - const int *index_mf_to_mpoly = NULL; - const int *index_mp_to_orig = NULL; - FreestyleFace *ffa = NULL; -#endif - /* Curve *cu= ELEM(ob->type, OB_FONT, OB_CURVE) ? ob->data : NULL; */ - - mvert= dm->getVertArray(dm); - totvert= dm->getNumVerts(dm); - - for (a=0; a<totvert; a++, mvert++) { - ver= RE_findOrAddVert(obr, obr->totvert++); - copy_v3_v3(ver->co, mvert->co); - mul_m4_v3(mat, ver->co); - - if (orco) { - ver->orco= orco; - orco+=3; - } - } - - if (!timeoffset) { - /* store customdata names, because DerivedMesh is freed */ - RE_set_customdata_names(obr, &dm->faceData); - - /* still to do for keys: the correct local texture coordinate */ - - /* faces in order of color blocks */ - vertofs= obr->totvert - totvert; - for (mat_iter= 0; (mat_iter < ob->totcol || (mat_iter==0 && ob->totcol==0)); mat_iter++) { - - ma= give_render_material(re, ob, mat_iter+1); - end= dm->getNumTessFaces(dm); - mface= dm->getTessFaceArray(dm); - -#ifdef WITH_FREESTYLE - if (ob->type == OB_MESH) { - Mesh *me= ob->data; - index_mf_to_mpoly= dm->getTessFaceDataArray(dm, CD_ORIGINDEX); - index_mp_to_orig= dm->getPolyDataArray(dm, CD_ORIGINDEX); - ffa= CustomData_get_layer(&me->pdata, CD_FREESTYLE_FACE); - } -#endif - - for (a=0; a<end; a++, mface++) { - int v1, v2, v3, v4, flag; - - if (mface->mat_nr == mat_iter) { - float len; - - v1= mface->v1; - v2= mface->v2; - v3= mface->v3; - v4= mface->v4; - flag= mface->flag & ME_SMOOTH; - - vlr= RE_findOrAddVlak(obr, obr->totvlak++); - vlr->v1= RE_findOrAddVert(obr, vertofs+v1); - vlr->v2= RE_findOrAddVert(obr, vertofs+v2); - vlr->v3= RE_findOrAddVert(obr, vertofs+v3); - if (v4) vlr->v4= RE_findOrAddVert(obr, vertofs+v4); - else vlr->v4 = NULL; - - /* render normals are inverted in render */ - if (vlr->v4) - len= normal_quad_v3(vlr->n, vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co); - else - len= normal_tri_v3(vlr->n, vlr->v3->co, vlr->v2->co, vlr->v1->co); - - vlr->mat= ma; - vlr->flag= flag; - vlr->ec= 0; /* mesh edges rendered separately */ -#ifdef WITH_FREESTYLE - if (ffa) { - int index = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, a) : a; - vlr->freestyle_face_mark= (ffa[index].flag & FREESTYLE_FACE_MARK) ? 1 : 0; - } - else { - vlr->freestyle_face_mark= 0; - } -#endif - - if (len==0) obr->totvlak--; - else { - CustomDataLayer *layer; - MTFace *mtface, *mtf; - MCol *mcol, *mc; - int index, mtfn= 0, mcn= 0; - char *name; - - for (index=0; index<dm->faceData.totlayer; index++) { - layer= &dm->faceData.layers[index]; - name= layer->name; - - if (layer->type == CD_MTFACE && mtfn < MAX_MTFACE) { - mtf= RE_vlakren_get_tface(obr, vlr, mtfn++, &name, 1); - mtface= (MTFace*)layer->data; - *mtf= mtface[a]; - } - else if (layer->type == CD_MCOL && mcn < MAX_MCOL) { - mc= RE_vlakren_get_mcol(obr, vlr, mcn++, &name, 1); - mcol= (MCol*)layer->data; - memcpy(mc, &mcol[a*4], sizeof(MCol)*4); - } - } - } - } - } - } - - /* Normals */ - calc_vertexnormals(re, obr, 1, 0, 0); - } - -} - -static void init_render_surf(Render *re, ObjectRen *obr, int timeoffset) -{ - Object *ob= obr->ob; - Nurb *nu = NULL; - Curve *cu; - ListBase displist= {NULL, NULL}; - DispList *dl; - Material **matar; - float *orco=NULL, mat[4][4]; - int a, totmat; - bool need_orco = false; - DerivedMesh *dm= NULL; - - cu= ob->data; - nu= cu->nurb.first; - if (nu == NULL) return; - - mul_m4_m4m4(mat, re->viewmat, ob->obmat); - invert_m4_m4(ob->imat, mat); - - /* material array */ - totmat= ob->totcol+1; - matar= MEM_callocN(sizeof(Material*)*totmat, "init_render_surf matar"); - - for (a=0; a<totmat; a++) { - matar[a]= give_render_material(re, ob, a+1); - - if (matar[a] && matar[a]->texco & TEXCO_ORCO) - need_orco= 1; - } - - if (ob->parent && (ob->parent->type==OB_LATTICE)) need_orco= 1; - - BKE_displist_make_surf(re->scene, ob, &displist, &dm, 1, 0, 1); - - if (dm) { - if (need_orco) { - orco = get_object_orco(re, ob); - if (!orco) { - orco= BKE_displist_make_orco(re->scene, ob, dm, true, true); - if (orco) { - set_object_orco(re, ob, orco); - } - } - } - - init_render_dm(dm, re, obr, timeoffset, orco, mat); - dm->release(dm); - } - else { - if (need_orco) { - orco = get_object_orco(re, ob); - if (!orco) { - orco = BKE_curve_surf_make_orco(ob); - set_object_orco(re, ob, orco); - } - } - - /* walk along displaylist and create rendervertices/-faces */ - for (dl=displist.first; dl; dl=dl->next) { - /* watch out: u ^= y, v ^= x !! */ - if (dl->type==DL_SURF) - orco+= 3*dl_surf_to_renderdata(obr, dl, matar, orco, mat); - } - } - - BKE_displist_free(&displist); - - MEM_freeN(matar); -} - -static void init_render_curve(Render *re, ObjectRen *obr, int timeoffset) -{ - Object *ob= obr->ob; - Curve *cu; - VertRen *ver; - VlakRen *vlr; - DispList *dl; - DerivedMesh *dm = NULL; - ListBase disp={NULL, NULL}; - Material **matar; - float *data, *fp, *orco=NULL; - float n[3], mat[4][4], nmat[4][4]; - int nr, startvert, a, b, negative_scale; - bool need_orco = false; - int totmat; - - cu= ob->data; - if (ob->type==OB_FONT && cu->str==NULL) return; - else if (ob->type==OB_CURVE && cu->nurb.first==NULL) return; - - BKE_displist_make_curveTypes_forRender(re->scene, ob, &disp, &dm, false, true); - dl= disp.first; - if (dl==NULL) return; - - mul_m4_m4m4(mat, re->viewmat, ob->obmat); - invert_m4_m4(ob->imat, mat); - negative_scale = is_negative_m4(mat); - - /* local object -> world space transform for normals */ - transpose_m4_m4(nmat, mat); - invert_m4(nmat); - - /* material array */ - totmat= ob->totcol+1; - matar= MEM_callocN(sizeof(Material*)*totmat, "init_render_surf matar"); - - for (a=0; a<totmat; a++) { - matar[a]= give_render_material(re, ob, a+1); - - if (matar[a] && matar[a]->texco & TEXCO_ORCO) - need_orco= 1; - } - - if (dm) { - if (need_orco) { - orco = get_object_orco(re, ob); - if (!orco) { - orco = BKE_displist_make_orco(re->scene, ob, dm, true, true); - if (orco) { - set_object_orco(re, ob, orco); - } - } - } - - init_render_dm(dm, re, obr, timeoffset, orco, mat); - dm->release(dm); - } - else { - if (need_orco) { - orco = get_object_orco(re, ob); - if (!orco) { - orco = BKE_curve_make_orco(re->scene, ob, NULL); - set_object_orco(re, ob, orco); - } - } - - while (dl) { - if (dl->col > ob->totcol) { - /* pass */ - } - else if (dl->type==DL_INDEX3) { - const int *index; - - startvert= obr->totvert; - data= dl->verts; - - for (a=0; a<dl->nr; a++, data+=3) { - ver= RE_findOrAddVert(obr, obr->totvert++); - copy_v3_v3(ver->co, data); - - mul_m4_v3(mat, ver->co); - - if (orco) { - ver->orco = orco; - orco += 3; - } - } - - if (timeoffset==0) { - float tmp[3]; - const int startvlak= obr->totvlak; - - zero_v3(n); - index= dl->index; - for (a=0; a<dl->parts; a++, index+=3) { - int v1 = index[0], v2 = index[2], v3 = index[1]; - float *co1 = &dl->verts[v1 * 3], - *co2 = &dl->verts[v2 * 3], - *co3 = &dl->verts[v3 * 3]; - - vlr= RE_findOrAddVlak(obr, obr->totvlak++); - vlr->v1= RE_findOrAddVert(obr, startvert + v1); - vlr->v2= RE_findOrAddVert(obr, startvert + v2); - vlr->v3= RE_findOrAddVert(obr, startvert + v3); - vlr->v4= NULL; - - /* to prevent float accuracy issues, we calculate normal in local object space (not world) */ - if (normal_tri_v3(tmp, co1, co2, co3) > FLT_EPSILON) { - if (negative_scale == false) { - add_v3_v3(n, tmp); - } - else { - sub_v3_v3(n, tmp); - } - } - - vlr->mat= matar[ dl->col ]; - vlr->flag= 0; - vlr->ec= 0; - } - - /* transform normal to world space */ - mul_m4_v3(nmat, n); - normalize_v3(n); - - /* vertex normals */ - for (a= startvlak; a<obr->totvlak; a++) { - vlr= RE_findOrAddVlak(obr, a); - - copy_v3_v3(vlr->n, n); - add_v3_v3(vlr->v1->n, vlr->n); - add_v3_v3(vlr->v3->n, vlr->n); - add_v3_v3(vlr->v2->n, vlr->n); - } - for (a=startvert; a<obr->totvert; a++) { - ver= RE_findOrAddVert(obr, a); - normalize_v3(ver->n); - } - } - } - else if (dl->type==DL_SURF) { - - /* cyclic U means an extruded full circular curve, we skip bevel splitting then */ - if (dl->flag & DL_CYCL_U) { - orco+= 3*dl_surf_to_renderdata(obr, dl, matar, orco, mat); - } - else { - int p1, p2, p3, p4; - - fp= dl->verts; - startvert= obr->totvert; - nr= dl->nr*dl->parts; - - while (nr--) { - ver= RE_findOrAddVert(obr, obr->totvert++); - - copy_v3_v3(ver->co, fp); - mul_m4_v3(mat, ver->co); - fp+= 3; - - if (orco) { - ver->orco = orco; - orco += 3; - } - } - - if (dl->flag & DL_CYCL_V && orco) { - fp = dl->verts; - nr = dl->nr; - while (nr--) { - ver = RE_findOrAddVert(obr, obr->totvert++); - copy_v3_v3(ver->co, fp); - mul_m4_v3(mat, ver->co); - ver->orco = orco; - fp += 3; - orco += 3; - } - } - - if (dl->bevel_split || timeoffset == 0) { - const int startvlak= obr->totvlak; - - for (a=0; a<dl->parts; a++) { - - if (BKE_displist_surfindex_get(dl, a, &b, &p1, &p2, &p3, &p4)==0) - break; - - p1+= startvert; - p2+= startvert; - p3+= startvert; - p4+= startvert; - - if (dl->flag & DL_CYCL_V && orco && a == dl->parts - 1) { - p3 = p1 + dl->nr; - p4 = p2 + dl->nr; - } - - for (; b<dl->nr; b++) { - vlr= RE_findOrAddVlak(obr, obr->totvlak++); - /* important 1 offset in order is kept [#24913] */ - vlr->v1= RE_findOrAddVert(obr, p2); - vlr->v2= RE_findOrAddVert(obr, p1); - vlr->v3= RE_findOrAddVert(obr, p3); - vlr->v4= RE_findOrAddVert(obr, p4); - vlr->ec= ME_V2V3+ME_V3V4; - if (a==0) vlr->ec+= ME_V1V2; - - vlr->flag= dl->rt; - - normal_quad_v3(vlr->n, vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co); - vlr->mat= matar[ dl->col ]; - - p4= p3; - p3++; - p2= p1; - p1++; - } - } - - if (dl->bevel_split) { - for (a = 0; a < dl->parts - 1 + !!(dl->flag & DL_CYCL_V); a++) { - if (BLI_BITMAP_TEST(dl->bevel_split, a)) { - split_v_renderfaces( - obr, startvlak, startvert, dl->parts, dl->nr, a, - /* intentionally swap (v, u) --> (u, v) */ - dl->flag & DL_CYCL_V, dl->flag & DL_CYCL_U); - } - } - } - - /* vertex normals */ - for (a= startvlak; a<obr->totvlak; a++) { - vlr= RE_findOrAddVlak(obr, a); - - add_v3_v3(vlr->v1->n, vlr->n); - add_v3_v3(vlr->v3->n, vlr->n); - add_v3_v3(vlr->v2->n, vlr->n); - add_v3_v3(vlr->v4->n, vlr->n); - } - for (a=startvert; a<obr->totvert; a++) { - ver= RE_findOrAddVert(obr, a); - normalize_v3(ver->n); - } - } - } - } - - dl= dl->next; - } - } - - BKE_displist_free(&disp); - - MEM_freeN(matar); -} - -/* ------------------------------------------------------------------------- */ -/* Mesh */ -/* ------------------------------------------------------------------------- */ - -struct edgesort { - unsigned int v1, v2; - int f; - unsigned int i1, i2; -}; - -/* edges have to be added with lowest index first for sorting */ -static void to_edgesort(struct edgesort *ed, - unsigned int i1, unsigned int i2, - unsigned int v1, unsigned int v2, int f) -{ - if (v1 > v2) { - SWAP(unsigned int, v1, v2); - SWAP(unsigned int, i1, i2); - } - - ed->v1= v1; - ed->v2= v2; - ed->i1= i1; - ed->i2= i2; - ed->f = f; -} - -static int vergedgesort(const void *v1, const void *v2) -{ - const struct edgesort *x1=v1, *x2=v2; - - if ( x1->v1 > x2->v1) return 1; - else if ( x1->v1 < x2->v1) return -1; - else if ( x1->v2 > x2->v2) return 1; - else if ( x1->v2 < x2->v2) return -1; - - return 0; -} - -static struct edgesort *make_mesh_edge_lookup(DerivedMesh *dm, int *totedgesort) -{ - MFace *mf, *mface; - MTFace *tface=NULL; - struct edgesort *edsort, *ed; - unsigned int *mcol=NULL; - int a, totedge=0, totface; - - mface= dm->getTessFaceArray(dm); - totface= dm->getNumTessFaces(dm); - tface= dm->getTessFaceDataArray(dm, CD_MTFACE); - mcol= dm->getTessFaceDataArray(dm, CD_MCOL); - - if (mcol==NULL && tface==NULL) return NULL; - - /* make sorted table with edges and face indices in it */ - for (a= totface, mf= mface; a>0; a--, mf++) { - totedge += mf->v4 ? 4 : 3; - } - - if (totedge==0) - return NULL; - - ed= edsort= MEM_callocN(totedge*sizeof(struct edgesort), "edgesort"); - - for (a=0, mf=mface; a<totface; a++, mf++) { - to_edgesort(ed++, 0, 1, mf->v1, mf->v2, a); - to_edgesort(ed++, 1, 2, mf->v2, mf->v3, a); - if (mf->v4) { - to_edgesort(ed++, 2, 3, mf->v3, mf->v4, a); - to_edgesort(ed++, 3, 0, mf->v4, mf->v1, a); - } - else { - to_edgesort(ed++, 2, 3, mf->v3, mf->v1, a); - } - } - - qsort(edsort, totedge, sizeof(struct edgesort), vergedgesort); - - *totedgesort= totedge; - - return edsort; -} - -static void use_mesh_edge_lookup(ObjectRen *obr, DerivedMesh *dm, MEdge *medge, VlakRen *vlr, struct edgesort *edgetable, int totedge) -{ - struct edgesort ed, *edp; - CustomDataLayer *layer; - MTFace *mtface, *mtf; - MCol *mcol, *mc; - int index, mtfn, mcn; - char *name; - - if (medge->v1 < medge->v2) { - ed.v1= medge->v1; - ed.v2= medge->v2; - } - else { - ed.v1= medge->v2; - ed.v2= medge->v1; - } - - edp= bsearch(&ed, edgetable, totedge, sizeof(struct edgesort), vergedgesort); - - /* since edges have different index ordering, we have to duplicate mcol and tface */ - if (edp) { - mtfn= mcn= 0; - - for (index=0; index<dm->faceData.totlayer; index++) { - layer= &dm->faceData.layers[index]; - name= layer->name; - - if (layer->type == CD_MTFACE && mtfn < MAX_MTFACE) { - mtface= &((MTFace*)layer->data)[edp->f]; - mtf= RE_vlakren_get_tface(obr, vlr, mtfn++, &name, 1); - - *mtf= *mtface; - - memcpy(mtf->uv[0], mtface->uv[edp->i1], sizeof(float)*2); - memcpy(mtf->uv[1], mtface->uv[edp->i2], sizeof(float)*2); - memcpy(mtf->uv[2], mtface->uv[1], sizeof(float)*2); - memcpy(mtf->uv[3], mtface->uv[1], sizeof(float)*2); - } - else if (layer->type == CD_MCOL && mcn < MAX_MCOL) { - mcol= &((MCol*)layer->data)[edp->f*4]; - mc= RE_vlakren_get_mcol(obr, vlr, mcn++, &name, 1); - - mc[0]= mcol[edp->i1]; - mc[1]= mc[2]= mc[3]= mcol[edp->i2]; - } - } - } -} - -static void free_camera_inside_volumes(Render *re) -{ - BLI_freelistN(&re->render_volumes_inside); -} - -static void init_camera_inside_volumes(Render *re) -{ - ObjectInstanceRen *obi; - VolumeOb *vo; - /* coordinates are all in camera space, so camera coordinate is zero. we also - * add an offset for the clip start, however note that with clip start it's - * actually impossible to do a single 'inside' test, since there will not be - * a single point where all camera rays start from, though for small clip start - * they will be close together. */ - float co[3] = {0.f, 0.f, -re->clipsta}; - - for (vo= re->volumes.first; vo; vo= vo->next) { - for (obi= re->instancetable.first; obi; obi= obi->next) { - if (obi->obr == vo->obr) { - if (point_inside_volume_objectinstance(re, obi, co)) { - MatInside *mi; - - mi = MEM_mallocN(sizeof(MatInside), "camera inside material"); - mi->ma = vo->ma; - mi->obi = obi; - - BLI_addtail(&(re->render_volumes_inside), mi); - } - } - } - } - - -#if 0 /* debug */ - { - MatInside *m; - for (m = re->render_volumes_inside.first; m; m = m->next) { - printf("matinside: ma: %s\n", m->ma->id.name + 2); - } - } -#endif -} - -static void add_volume(Render *re, ObjectRen *obr, Material *ma) -{ - struct VolumeOb *vo; - - vo = MEM_mallocN(sizeof(VolumeOb), "volume object"); - - vo->ma = ma; - vo->obr = obr; - - BLI_addtail(&re->volumes, vo); -} - -#ifdef WITH_FREESTYLE -static EdgeHash *make_freestyle_edge_mark_hash(DerivedMesh *dm) -{ - EdgeHash *edge_hash= NULL; - FreestyleEdge *fed; - MEdge *medge; - int totedge, a; - - medge = dm->getEdgeArray(dm); - totedge = dm->getNumEdges(dm); - fed = dm->getEdgeDataArray(dm, CD_FREESTYLE_EDGE); - if (fed) { - edge_hash = BLI_edgehash_new(__func__); - for (a = 0; a < totedge; a++) { - if (fed[a].flag & FREESTYLE_EDGE_MARK) - BLI_edgehash_insert(edge_hash, medge[a].v1, medge[a].v2, medge+a); - } - } - return edge_hash; -} - -static bool has_freestyle_edge_mark(EdgeHash *edge_hash, int v1, int v2) -{ - MEdge *medge= BLI_edgehash_lookup(edge_hash, v1, v2); - return (!medge) ? 0 : 1; -} -#endif - -static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset) -{ - Object *ob= obr->ob; - Mesh *me; - MVert *mvert = NULL; - MFace *mface; - VlakRen *vlr; //, *vlr1; - VertRen *ver; - Material *ma; - DerivedMesh *dm; - CustomDataMask mask; - float xn, yn, zn, imat[3][3], mat[4][4]; //nor[3], - float *orco = NULL; - short (*loop_nors)[4][3] = NULL; - bool need_orco = false, need_stress = false, need_tangent = false, need_origindex = false; - bool need_nmap_tangent_concrete = false; - int a, a1, ok, vertofs; - int end, totvert = 0; - bool do_autosmooth = false, do_displace = false; - bool use_original_normals = false; - int recalc_normals = 0; /* false by default */ - int negative_scale; -#ifdef WITH_FREESTYLE - FreestyleFace *ffa; -#endif - - me= ob->data; - - mul_m4_m4m4(mat, re->viewmat, ob->obmat); - invert_m4_m4(ob->imat, mat); - copy_m3_m4(imat, ob->imat); - negative_scale= is_negative_m4(mat); - - need_orco= 0; - for (a=1; a<=ob->totcol; a++) { - ma= give_render_material(re, ob, a); - if (ma) { - if (ma->texco & (TEXCO_ORCO|TEXCO_STRESS)) - need_orco= 1; - if (ma->texco & TEXCO_STRESS) - need_stress= 1; - /* normalmaps, test if tangents needed, separated from shading */ - if (ma->mode_l & MA_TANGENT_V) { - need_tangent= 1; - if (me->mtpoly==NULL) - need_orco= 1; - } - if (ma->mode_l & MA_NORMAP_TANG) { - if (me->mtpoly==NULL) { - need_orco= 1; - } - need_tangent= 1; - } - if (ma->mode2_l & MA_TANGENT_CONCRETE) { - need_nmap_tangent_concrete = true; - } - } - } - - if (re->flag & R_NEED_TANGENT) { - /* exception for tangent space baking */ - if (me->mtpoly==NULL) { - need_orco= 1; - } - need_tangent= 1; - } - - /* check autosmooth and displacement, we then have to skip only-verts optimize - * Note: not sure what we want to give higher priority, currently do_displace - * takes precedence over do_autosmooth. - */ - do_displace = test_for_displace(re, ob); - do_autosmooth = ((me->flag & ME_AUTOSMOOTH) != 0) && !do_displace; - if (do_autosmooth || do_displace) - timeoffset = 0; - - /* origindex currently used when using autosmooth, or baking to vertex colors. */ - need_origindex = (do_autosmooth || ((re->flag & R_BAKING) && (re->r.bake_flag & R_BAKE_VCOL))); - - mask = CD_MASK_RENDER_INTERNAL; - if (!timeoffset) - if (need_orco) - mask |= CD_MASK_ORCO; - -#ifdef WITH_FREESTYLE - mask |= CD_MASK_ORIGINDEX | CD_MASK_FREESTYLE_EDGE | CD_MASK_FREESTYLE_FACE; -#endif - - if (re->r.scemode & R_VIEWPORT_PREVIEW) - dm= mesh_create_derived_view(re->scene, ob, mask); - else - dm= mesh_create_derived_render(re->scene, ob, mask); - if (dm==NULL) return; /* in case duplicated object fails? */ - - mvert= dm->getVertArray(dm); - totvert= dm->getNumVerts(dm); - - if (totvert == 0) { - dm->release(dm); - return; - } - - if (mask & CD_MASK_ORCO) { - orco = get_object_orco(re, ob); - if (!orco) { - orco= dm->getVertDataArray(dm, CD_ORCO); - if (orco) { - orco= MEM_dupallocN(orco); - set_object_orco(re, ob, orco); - } - } - } - - /* attempt to autsmooth on original mesh, only without subsurf */ - if (do_autosmooth && me->totvert==totvert && me->totface==dm->getNumTessFaces(dm)) - use_original_normals= true; - - ma= give_render_material(re, ob, 1); - - - if (ma->material_type == MA_TYPE_HALO) { - make_render_halos(re, obr, me, totvert, mvert, ma, orco); - } - else { - const int *index_vert_orig = NULL; - const int *index_mf_to_mpoly = NULL; - const int *index_mp_to_orig = NULL; - if (need_origindex) { - index_vert_orig = dm->getVertDataArray(dm, CD_ORIGINDEX); - /* double lookup for faces -> polys */ -#ifdef WITH_FREESTYLE - index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX); - index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX); -#endif - } - - for (a=0; a<totvert; a++, mvert++) { - ver= RE_findOrAddVert(obr, obr->totvert++); - copy_v3_v3(ver->co, mvert->co); - if (do_autosmooth == false) { /* autosmooth on original unrotated data to prevent differences between frames */ - normal_short_to_float_v3(ver->n, mvert->no); - mul_m4_v3(mat, ver->co); - mul_transposed_m3_v3(imat, ver->n); - normalize_v3(ver->n); - negate_v3(ver->n); - } - - if (orco) { - ver->orco= orco; - orco+=3; - } - - if (need_origindex) { - int *origindex; - origindex = RE_vertren_get_origindex(obr, ver, 1); - - /* Use orig index array if it's available (e.g. in the presence - * of modifiers). */ - if (index_vert_orig) - *origindex = index_vert_orig[a]; - else - *origindex = a; - } - } - - if (!timeoffset) { - short (*lnp)[4][3] = NULL; -#ifdef WITH_FREESTYLE - EdgeHash *edge_hash; - - /* create a hash table of Freestyle edge marks */ - edge_hash = make_freestyle_edge_mark_hash(dm); -#endif - - /* store customdata names, because DerivedMesh is freed */ - RE_set_customdata_names(obr, &dm->faceData); - - /* add tangent layers if we need */ - if ((ma->nmap_tangent_names_count && need_nmap_tangent_concrete) || need_tangent) { - dm->calcLoopTangents( - dm, need_tangent, - (const char (*)[MAX_NAME])ma->nmap_tangent_names, ma->nmap_tangent_names_count); - obr->tangent_mask = dm->tangent_mask; - DM_generate_tangent_tessface_data(dm, need_nmap_tangent_concrete || need_tangent); - } - - /* still to do for keys: the correct local texture coordinate */ - - /* faces in order of color blocks */ - vertofs= obr->totvert - totvert; - for (a1=0; (a1<ob->totcol || (a1==0 && ob->totcol==0)); a1++) { - - ma= give_render_material(re, ob, a1+1); - - /* test for 100% transparent */ - ok = 1; - if ((ma->alpha == 0.0f) && - (ma->spectra == 0.0f) && - /* No need to test filter here, it's only active with MA_RAYTRANSP and we check against it below. */ - /* (ma->filter == 0.0f) && */ - (ma->mode & MA_TRANSP) && - (ma->mode & (MA_RAYTRANSP | MA_RAYMIRROR)) == 0) - { - ok = 0; - /* texture on transparency? */ - for (a=0; a<MAX_MTEX; a++) { - if (ma->mtex[a] && ma->mtex[a]->tex) { - if (ma->mtex[a]->mapto & MAP_ALPHA) ok= 1; - } - } - } - - /* if wire material, and we got edges, don't do the faces */ - if (ma->material_type == MA_TYPE_WIRE) { - end= dm->getNumEdges(dm); - if (end) ok= 0; - } - - if (ok) { - end= dm->getNumTessFaces(dm); - mface= dm->getTessFaceArray(dm); - if (!loop_nors && do_autosmooth && - (dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL) != NULL)) - { - lnp = loop_nors = MEM_mallocN(sizeof(*loop_nors) * end, __func__); - } -#ifdef WITH_FREESTYLE - index_mf_to_mpoly= dm->getTessFaceDataArray(dm, CD_ORIGINDEX); - index_mp_to_orig= dm->getPolyDataArray(dm, CD_ORIGINDEX); - ffa= CustomData_get_layer(&me->pdata, CD_FREESTYLE_FACE); -#endif - - for (a=0; a<end; a++, mface++) { - int v1, v2, v3, v4, flag; - - if ( mface->mat_nr==a1 ) { - float len; - bool reverse_verts = (negative_scale != 0 && do_autosmooth == false); - int rev_tab[] = {reverse_verts==0 ? 0 : 2, 1, reverse_verts==0 ? 2 : 0, 3}; - v1= reverse_verts==0 ? mface->v1 : mface->v3; - v2= mface->v2; - v3= reverse_verts==0 ? mface->v3 : mface->v1; - v4= mface->v4; - flag = do_autosmooth ? ME_SMOOTH : mface->flag & ME_SMOOTH; - - vlr= RE_findOrAddVlak(obr, obr->totvlak++); - vlr->v1= RE_findOrAddVert(obr, vertofs+v1); - vlr->v2= RE_findOrAddVert(obr, vertofs+v2); - vlr->v3= RE_findOrAddVert(obr, vertofs+v3); - if (v4) vlr->v4 = RE_findOrAddVert(obr, vertofs+v4); - else vlr->v4 = NULL; - -#ifdef WITH_FREESTYLE - /* Freestyle edge/face marks */ - if (edge_hash) { - int edge_mark = 0; - - if (has_freestyle_edge_mark(edge_hash, v1, v2)) edge_mark |= R_EDGE_V1V2; - if (has_freestyle_edge_mark(edge_hash, v2, v3)) edge_mark |= R_EDGE_V2V3; - if (!v4) { - if (has_freestyle_edge_mark(edge_hash, v3, v1)) edge_mark |= R_EDGE_V3V1; - } - else { - if (has_freestyle_edge_mark(edge_hash, v3, v4)) edge_mark |= R_EDGE_V3V4; - if (has_freestyle_edge_mark(edge_hash, v4, v1)) edge_mark |= R_EDGE_V4V1; - } - vlr->freestyle_edge_mark= edge_mark; - } - if (ffa) { - int index = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, a) : a; - vlr->freestyle_face_mark= (ffa[index].flag & FREESTYLE_FACE_MARK) ? 1 : 0; - } - else { - vlr->freestyle_face_mark= 0; - } -#endif - - /* render normals are inverted in render */ - if (use_original_normals) { - MFace *mf= me->mface+a; - MVert *mv= me->mvert; - - if (vlr->v4) - len= normal_quad_v3(vlr->n, mv[mf->v4].co, mv[mf->v3].co, mv[mf->v2].co, mv[mf->v1].co); - else - len= normal_tri_v3(vlr->n, mv[mf->v3].co, mv[mf->v2].co, mv[mf->v1].co); - } - else { - if (vlr->v4) - len= normal_quad_v3(vlr->n, vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co); - else - len= normal_tri_v3(vlr->n, vlr->v3->co, vlr->v2->co, vlr->v1->co); - } - - vlr->mat= ma; - vlr->flag= flag; - vlr->ec= 0; /* mesh edges rendered separately */ - - if (len==0) obr->totvlak--; - else { - CustomDataLayer *layer; - MTFace *mtface, *mtf; - MCol *mcol, *mc; - int index, mtfn= 0, mcn= 0, mln = 0, vindex; - char *name; - int nr_verts = v4!=0 ? 4 : 3; - - for (index=0; index<dm->faceData.totlayer; index++) { - layer= &dm->faceData.layers[index]; - name= layer->name; - - if (layer->type == CD_MTFACE && mtfn < MAX_MTFACE) { - int t; - mtf= RE_vlakren_get_tface(obr, vlr, mtfn++, &name, 1); - mtface= (MTFace*)layer->data; - *mtf = mtface[a]; /* copy face info */ - for (vindex=0; vindex<nr_verts; vindex++) - for (t=0; t<2; t++) - mtf->uv[vindex][t]=mtface[a].uv[rev_tab[vindex]][t]; - } - else if (layer->type == CD_MCOL && mcn < MAX_MCOL) { - mc= RE_vlakren_get_mcol(obr, vlr, mcn++, &name, 1); - mcol= (MCol*)layer->data; - for (vindex=0; vindex<nr_verts; vindex++) - mc[vindex]=mcol[a*4+rev_tab[vindex]]; - } - else if (layer->type == CD_TANGENT) { - if (need_nmap_tangent_concrete || need_tangent) { - int uv_start = CustomData_get_layer_index(&dm->faceData, CD_MTFACE); - int uv_index = CustomData_get_named_layer_index(&dm->faceData, CD_MTFACE, layer->name); - - /* if there are no UVs, orco tangents are in first slot */ - int n = (uv_start >= 0 && uv_index >= 0) ? uv_index - uv_start : 0; - - const float *tangent = (const float *) layer->data; - float *ftang = RE_vlakren_get_nmap_tangent(obr, vlr, n, true); - - for (vindex=0; vindex<nr_verts; vindex++) { - copy_v4_v4(ftang+vindex*4, tangent+a*16+rev_tab[vindex]*4); - mul_mat3_m4_v3(mat, ftang+vindex*4); - normalize_v3(ftang+vindex*4); - } - } - } - else if (layer->type == CD_TESSLOOPNORMAL && mln < 1) { - if (loop_nors) { - const short (*lnors)[4][3] = (const short (*)[4][3])layer->data; - for (vindex = 0; vindex < 4; vindex++) { - //print_v3("lnors[a][rev_tab[vindex]]", lnors[a][rev_tab[vindex]]); - copy_v3_v3_short((short *)lnp[0][vindex], lnors[a][rev_tab[vindex]]); - /* If we copy loop normals, we are doing autosmooth, so we are still - * in object space, no need to multiply with mat! - */ - } - lnp++; - } - mln++; - } - } - - if (need_origindex) { - /* Find original index of mpoly for this tessface. Options: - * - Modified mesh; two-step look up from tessface -> modified mpoly -> original mpoly - * - OR Tesselated mesh; look up from tessface -> mpoly - * - OR Failsafe; tessface == mpoly. Could probably assert(false) in this case? */ - int *origindex; - origindex = RE_vlakren_get_origindex(obr, vlr, 1); - if (index_mf_to_mpoly && index_mp_to_orig) - *origindex = DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, a); - else if (index_mf_to_mpoly) - *origindex = index_mf_to_mpoly[a]; - else - *origindex = a; - } - } - } - } - } - } - -#ifdef WITH_FREESTYLE - /* release the hash table of Freestyle edge marks */ - if (edge_hash) - BLI_edgehash_free(edge_hash, NULL); -#endif - - /* exception... we do edges for wire mode. potential conflict when faces exist... */ - end= dm->getNumEdges(dm); - mvert= dm->getVertArray(dm); - ma= give_render_material(re, ob, 1); - if (end && (ma->material_type == MA_TYPE_WIRE)) { - MEdge *medge; - struct edgesort *edgetable; - int totedge= 0; - recalc_normals= 1; - - medge= dm->getEdgeArray(dm); - - /* we want edges to have UV and vcol too... */ - edgetable= make_mesh_edge_lookup(dm, &totedge); - - for (a1=0; a1<end; a1++, medge++) { - if (medge->flag&ME_EDGERENDER) { - MVert *v0 = &mvert[medge->v1]; - MVert *v1 = &mvert[medge->v2]; - - vlr= RE_findOrAddVlak(obr, obr->totvlak++); - vlr->v1= RE_findOrAddVert(obr, vertofs+medge->v1); - vlr->v2= RE_findOrAddVert(obr, vertofs+medge->v2); - vlr->v3= vlr->v2; - vlr->v4= NULL; - - if (edgetable) - use_mesh_edge_lookup(obr, dm, medge, vlr, edgetable, totedge); - - xn= -(v0->no[0]+v1->no[0]); - yn= -(v0->no[1]+v1->no[1]); - zn= -(v0->no[2]+v1->no[2]); - /* transpose ! */ - vlr->n[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn; - vlr->n[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn; - vlr->n[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn; - normalize_v3(vlr->n); - - vlr->mat= ma; - vlr->flag= 0; - vlr->ec= ME_V1V2; - } - } - if (edgetable) - MEM_freeN(edgetable); - } - } - } - - if (!timeoffset) { - if (need_stress) - calc_edge_stress(re, obr, me); - - if (do_displace) { - calc_vertexnormals(re, obr, 1, 0, 0); - displace(re, obr); - recalc_normals = 0; /* Already computed by displace! */ - } - else if (do_autosmooth) { - recalc_normals = (loop_nors == NULL); /* Should never happen, but better be safe than sorry. */ - autosmooth(re, obr, mat, loop_nors); - } - - if (recalc_normals!=0 || need_tangent!=0) - calc_vertexnormals(re, obr, recalc_normals, need_tangent, need_nmap_tangent_concrete); - } - - MEM_SAFE_FREE(loop_nors); - - dm->release(dm); -} - -/* ------------------------------------------------------------------------- */ -/* Lamps and Shadowbuffers */ -/* ------------------------------------------------------------------------- */ - -static void initshadowbuf(Render *re, LampRen *lar, float mat[4][4]) -{ - struct ShadBuf *shb; - float viewinv[4][4]; - - /* if (la->spsi<16) return; */ - - /* memory alloc */ - shb= (struct ShadBuf *)MEM_callocN(sizeof(struct ShadBuf), "initshadbuf"); - lar->shb= shb; - - if (shb==NULL) return; - - VECCOPY(shb->co, lar->co); /* int copy */ - - /* percentage render: keep track of min and max */ - shb->size= (lar->bufsize*re->r.size)/100; - - if (shb->size<512) shb->size= 512; - else if (shb->size > lar->bufsize) shb->size= lar->bufsize; - - shb->size &= ~15; /* make sure its multiples of 16 */ - - shb->samp= lar->samp; - shb->soft= lar->soft; - shb->shadhalostep= lar->shadhalostep; - - normalize_m4(mat); - invert_m4_m4(shb->winmat, mat); /* winmat is temp */ - - /* matrix: combination of inverse view and lampmat */ - /* calculate again: the ortho-render has no correct viewinv */ - invert_m4_m4(viewinv, re->viewmat); - mul_m4_m4m4(shb->viewmat, shb->winmat, viewinv); - - /* projection */ - shb->d= lar->clipsta; - shb->clipend= lar->clipend; - - /* bias is percentage, made 2x larger because of correction for angle of incidence */ - /* when a ray is closer to parallel of a face, bias value is increased during render */ - shb->bias= (0.02f*lar->bias)*0x7FFFFFFF; - - /* halfway method (average of first and 2nd z) reduces bias issues */ - if (ELEM(lar->buftype, LA_SHADBUF_HALFWAY, LA_SHADBUF_DEEP)) - shb->bias= 0.1f*shb->bias; - - shb->compressthresh= lar->compressthresh; -} - -void area_lamp_vectors(LampRen *lar) -{ - float xsize= 0.5f*lar->area_size, ysize= 0.5f*lar->area_sizey, multifac; - - /* make it smaller, so area light can be multisampled */ - multifac= 1.0f/sqrtf((float)lar->ray_totsamp); - xsize *= multifac; - ysize *= multifac; - - /* corner vectors */ - lar->area[0][0]= lar->co[0] - xsize*lar->mat[0][0] - ysize*lar->mat[1][0]; - lar->area[0][1]= lar->co[1] - xsize*lar->mat[0][1] - ysize*lar->mat[1][1]; - lar->area[0][2]= lar->co[2] - xsize*lar->mat[0][2] - ysize*lar->mat[1][2]; - - /* corner vectors */ - lar->area[1][0]= lar->co[0] - xsize*lar->mat[0][0] + ysize*lar->mat[1][0]; - lar->area[1][1]= lar->co[1] - xsize*lar->mat[0][1] + ysize*lar->mat[1][1]; - lar->area[1][2]= lar->co[2] - xsize*lar->mat[0][2] + ysize*lar->mat[1][2]; - - /* corner vectors */ - lar->area[2][0]= lar->co[0] + xsize*lar->mat[0][0] + ysize*lar->mat[1][0]; - lar->area[2][1]= lar->co[1] + xsize*lar->mat[0][1] + ysize*lar->mat[1][1]; - lar->area[2][2]= lar->co[2] + xsize*lar->mat[0][2] + ysize*lar->mat[1][2]; - - /* corner vectors */ - lar->area[3][0]= lar->co[0] + xsize*lar->mat[0][0] - ysize*lar->mat[1][0]; - lar->area[3][1]= lar->co[1] + xsize*lar->mat[0][1] - ysize*lar->mat[1][1]; - lar->area[3][2]= lar->co[2] + xsize*lar->mat[0][2] - ysize*lar->mat[1][2]; - /* only for correction button size, matrix size works on energy */ - lar->areasize= lar->dist*lar->dist/(4.0f*xsize*ysize); -} - -/* If lar takes more lamp data, the decoupling will be better. */ -static GroupObject *add_render_lamp(Render *re, Object *ob) -{ - Lamp *la= ob->data; - LampRen *lar; - GroupObject *go; - float mat[4][4], angle, xn, yn; - float vec[3]; - int c; - - /* previewrender sets this to zero... prevent accidents */ - if (la==NULL) return NULL; - - /* prevent only shadow from rendering light */ - if (la->mode & LA_ONLYSHADOW) - if ((re->r.mode & R_SHADOW)==0) - return NULL; - - re->totlamp++; - - /* groups is used to unify support for lightgroups, this is the global lightgroup */ - go= MEM_callocN(sizeof(GroupObject), "groupobject"); - BLI_addtail(&re->lights, go); - go->ob= ob; - /* lamprens are in own list, for freeing */ - lar= (LampRen *)MEM_callocN(sizeof(LampRen), "lampren"); - BLI_addtail(&re->lampren, lar); - go->lampren= lar; - - mul_m4_m4m4(mat, re->viewmat, ob->obmat); - invert_m4_m4(ob->imat, mat); - - copy_m4_m4(lar->lampmat, ob->obmat); - copy_m3_m4(lar->mat, mat); - copy_m3_m4(lar->imat, ob->imat); - - lar->bufsize = la->bufsize; - lar->samp = la->samp; - lar->buffers= la->buffers; - if (lar->buffers==0) lar->buffers= 1; - lar->buftype= la->buftype; - lar->filtertype= la->filtertype; - lar->soft = la->soft; - lar->shadhalostep = la->shadhalostep; - lar->clipsta = la->clipsta; - lar->clipend = la->clipend; - - lar->bias = la->bias; - lar->compressthresh = la->compressthresh; - - lar->type= la->type; - lar->mode= la->mode; - - lar->energy= la->energy; - if (la->mode & LA_NEG) lar->energy= -lar->energy; - - lar->vec[0]= -mat[2][0]; - lar->vec[1]= -mat[2][1]; - lar->vec[2]= -mat[2][2]; - normalize_v3(lar->vec); - lar->co[0]= mat[3][0]; - lar->co[1]= mat[3][1]; - lar->co[2]= mat[3][2]; - lar->dist= la->dist; - lar->haint= la->haint; - lar->distkw= lar->dist*lar->dist; - lar->r= lar->energy*la->r; - lar->g= lar->energy*la->g; - lar->b= lar->energy*la->b; - lar->shdwr= la->shdwr; - lar->shdwg= la->shdwg; - lar->shdwb= la->shdwb; - lar->k= la->k; - - /* area */ - lar->ray_samp= la->ray_samp; - lar->ray_sampy= la->ray_sampy; - lar->ray_sampz= la->ray_sampz; - - lar->area_size= la->area_size; - lar->area_sizey= la->area_sizey; - lar->area_sizez= la->area_sizez; - - lar->area_shape= la->area_shape; - - /* Annoying, lamp UI does this, but the UI might not have been used? - add here too. - * make sure this matches buttons_shading.c's logic */ - if (ELEM(la->type, LA_AREA, LA_SPOT, LA_SUN, LA_LOCAL) && (la->mode & LA_SHAD_RAY)) - if (ELEM(la->type, LA_SPOT, LA_SUN, LA_LOCAL)) - if (la->ray_samp_method == LA_SAMP_CONSTANT) la->ray_samp_method = LA_SAMP_HALTON; - - lar->ray_samp_method= la->ray_samp_method; - lar->ray_samp_type= la->ray_samp_type; - - lar->adapt_thresh= la->adapt_thresh; - lar->sunsky = NULL; - - if ( ELEM(lar->type, LA_SPOT, LA_LOCAL)) { - lar->ray_totsamp= lar->ray_samp*lar->ray_samp; - lar->area_shape = LA_AREA_SQUARE; - lar->area_sizey= lar->area_size; - } - else if (lar->type==LA_AREA) { - switch (lar->area_shape) { - case LA_AREA_SQUARE: - lar->ray_totsamp= lar->ray_samp*lar->ray_samp; - lar->ray_sampy= lar->ray_samp; - lar->area_sizey= lar->area_size; - break; - case LA_AREA_RECT: - lar->ray_totsamp= lar->ray_samp*lar->ray_sampy; - break; - case LA_AREA_CUBE: - lar->ray_totsamp= lar->ray_samp*lar->ray_samp*lar->ray_samp; - lar->ray_sampy= lar->ray_samp; - lar->ray_sampz= lar->ray_samp; - lar->area_sizey= lar->area_size; - lar->area_sizez= lar->area_size; - break; - case LA_AREA_BOX: - lar->ray_totsamp= lar->ray_samp*lar->ray_sampy*lar->ray_sampz; - break; - } - - area_lamp_vectors(lar); - init_jitter_plane(lar); /* subsamples */ - } - else if (lar->type==LA_SUN) { - lar->ray_totsamp= lar->ray_samp*lar->ray_samp; - lar->area_shape = LA_AREA_SQUARE; - lar->area_sizey= lar->area_size; - - if ((la->sun_effect_type & LA_SUN_EFFECT_SKY) || - (la->sun_effect_type & LA_SUN_EFFECT_AP)) - { - lar->sunsky = (struct SunSky*)MEM_callocN(sizeof(struct SunSky), "sunskyren"); - lar->sunsky->effect_type = la->sun_effect_type; - - copy_v3_v3(vec, ob->obmat[2]); - normalize_v3(vec); - - InitSunSky( - lar->sunsky, la->atm_turbidity, vec, la->horizon_brightness, - la->spread, la->sun_brightness, la->sun_size, la->backscattered_light, - la->skyblendfac, la->skyblendtype, la->sky_exposure, la->sky_colorspace); - InitAtmosphere( - lar->sunsky, la->sun_intensity, 1.0, 1.0, la->atm_inscattering_factor, la->atm_extinction_factor, - la->atm_distance_factor); - } - } - else lar->ray_totsamp= 0; - - lar->spotsi= la->spotsize; - if (lar->mode & LA_HALO) { - if (lar->spotsi > DEG2RADF(170.0f)) lar->spotsi = DEG2RADF(170.0f); - } - lar->spotsi= cosf(lar->spotsi * 0.5f); - lar->spotbl= (1.0f-lar->spotsi)*la->spotblend; - - memcpy(lar->mtex, la->mtex, MAX_MTEX*sizeof(void *)); - - lar->lay = ob->lay & 0xFFFFFF; /* higher 8 bits are localview layers */ - - lar->falloff_type = la->falloff_type; - lar->ld1= la->att1; - lar->ld2= la->att2; - lar->coeff_const= la->coeff_const; - lar->coeff_lin= la->coeff_lin; - lar->coeff_quad= la->coeff_quad; - lar->curfalloff = curvemapping_copy(la->curfalloff); - - if (lar->curfalloff) { - /* so threads don't conflict on init */ - curvemapping_initialize(lar->curfalloff); - } - - if (lar->type==LA_SPOT) { - - normalize_v3(lar->imat[0]); - normalize_v3(lar->imat[1]); - normalize_v3(lar->imat[2]); - - xn = saacos(lar->spotsi); - xn = sinf(xn) / cosf(xn); - lar->spottexfac= 1.0f/(xn); - - if (lar->mode & LA_ONLYSHADOW) { - if ((lar->mode & (LA_SHAD_BUF|LA_SHAD_RAY))==0) lar->mode -= LA_ONLYSHADOW; - } - - } - - /* set flag for spothalo en initvars */ - if ((la->type == LA_SPOT) && (la->mode & LA_HALO) && - (!(la->mode & LA_SHAD_BUF) || la->buftype != LA_SHADBUF_DEEP)) - { - if (la->haint>0.0f) { - re->flag |= R_LAMPHALO; - - /* camera position (0, 0, 0) rotate around lamp */ - lar->sh_invcampos[0]= -lar->co[0]; - lar->sh_invcampos[1]= -lar->co[1]; - lar->sh_invcampos[2]= -lar->co[2]; - mul_m3_v3(lar->imat, lar->sh_invcampos); - - /* z factor, for a normalized volume */ - angle= saacos(lar->spotsi); - xn= lar->spotsi; - yn = sinf(angle); - lar->sh_zfac= yn/xn; - /* pre-scale */ - lar->sh_invcampos[2]*= lar->sh_zfac; - - /* halfway shadow buffer doesn't work for volumetric effects */ - if (ELEM(lar->buftype, LA_SHADBUF_HALFWAY, LA_SHADBUF_DEEP)) - lar->buftype = LA_SHADBUF_REGULAR; - - } - } - else if (la->type==LA_HEMI) { - lar->mode &= ~(LA_SHAD_RAY|LA_SHAD_BUF); - } - - for (c=0; c<MAX_MTEX; c++) { - if (la->mtex[c] && la->mtex[c]->tex) { - if (la->mtex[c]->mapto & LAMAP_COL) - lar->mode |= LA_TEXTURE; - if (la->mtex[c]->mapto & LAMAP_SHAD) - lar->mode |= LA_SHAD_TEX; - - if (G.is_rendering) { - if (re->osa) { - if (la->mtex[c]->tex->type==TEX_IMAGE) lar->mode |= LA_OSATEX; - } - } - } - } - - /* old code checked for internal render (aka not yafray) */ - { - /* to make sure we can check ray shadow easily in the render code */ - if (lar->mode & LA_SHAD_RAY) { - if ( (re->r.mode & R_RAYTRACE)==0) - lar->mode &= ~LA_SHAD_RAY; - } - - - if (re->r.mode & R_SHADOW) { - - if (la->type==LA_AREA && (lar->mode & LA_SHAD_RAY) && (lar->ray_samp_method == LA_SAMP_CONSTANT)) { - init_jitter_plane(lar); - } - else if (la->type==LA_SPOT && (lar->mode & LA_SHAD_BUF) ) { - /* Per lamp, one shadow buffer is made. */ - lar->bufflag= la->bufflag; - copy_m4_m4(mat, ob->obmat); - initshadowbuf(re, lar, mat); /* mat is altered */ - } - - - /* this is the way used all over to check for shadow */ - if (lar->shb || (lar->mode & LA_SHAD_RAY)) { - LampShadowSample *ls; - LampShadowSubSample *lss; - int a, b; - - memset(re->shadowsamplenr, 0, sizeof(re->shadowsamplenr)); - - lar->shadsamp= MEM_mallocN(re->r.threads*sizeof(LampShadowSample), "lamp shadow sample"); - ls= lar->shadsamp; - - /* shadfacs actually mean light, let's put them to 1 to prevent unitialized accidents */ - for (a=0; a<re->r.threads; a++, ls++) { - lss= ls->s; - for (b=0; b<re->r.osa; b++, lss++) { - lss->samplenr= -1; /* used to detect whether we store or read */ - lss->shadfac[0]= 1.0f; - lss->shadfac[1]= 1.0f; - lss->shadfac[2]= 1.0f; - lss->shadfac[3]= 1.0f; - } - } - } - } - } - - return go; -} - -static bool is_object_restricted(Render *re, Object *ob) -{ - if (re->r.scemode & R_VIEWPORT_PREVIEW) - return (ob->restrictflag & OB_RESTRICT_VIEW) != 0; - else - return (ob->restrictflag & OB_RESTRICT_RENDER) != 0; -} - -static bool is_object_hidden(Render *re, Object *ob) -{ - if (is_object_restricted(re, ob)) - return true; - - if (re->r.scemode & R_VIEWPORT_PREVIEW) { - /* Mesh deform cages and so on mess up the preview. To avoid the problem, - * viewport doesn't show mesh object if its draw type is bounding box or wireframe. - * Unless it's an active smoke domain! - */ - ModifierData *md = NULL; - - if ((md = modifiers_findByType(ob, eModifierType_Smoke)) && - (modifier_isEnabled(re->scene, md, eModifierMode_Realtime))) - { - return false; - } - return ELEM(ob->dt, OB_BOUNDBOX, OB_WIRE); - } - else { - return false; - } -} - -/* layflag: allows material group to ignore layerflag */ -static void add_lightgroup(Render *re, Group *group, int exclusive) -{ - GroupObject *go, *gol; - - group->id.tag &= ~LIB_TAG_DOIT; - - /* it's a bit too many loops in loops... but will survive */ - /* note that 'exclusive' will remove it from the global list */ - for (go= group->gobject.first; go; go= go->next) { - go->lampren= NULL; - - if (is_object_hidden(re, go->ob)) - continue; - - if (go->ob->lay & re->lay) { - if (go->ob && go->ob->type==OB_LAMP) { - for (gol= re->lights.first; gol; gol= gol->next) { - if (gol->ob==go->ob) { - go->lampren= gol->lampren; - break; - } - } - if (go->lampren==NULL) - gol= add_render_lamp(re, go->ob); - if (gol && exclusive) { - BLI_remlink(&re->lights, gol); - MEM_freeN(gol); - } - } - } - } -} - -static void set_material_lightgroups(Render *re) -{ - Group *group; - Material *ma; - - /* not for preview render */ - if (re->scene->r.scemode & (R_BUTS_PREVIEW|R_VIEWPORT_PREVIEW)) - return; - - for (group= re->main->group.first; group; group=group->id.next) - group->id.tag |= LIB_TAG_DOIT; - - /* it's a bit too many loops in loops... but will survive */ - /* hola! materials not in use...? */ - for (ma= re->main->mat.first; ma; ma=ma->id.next) { - if (ma->group && (ma->group->id.tag & LIB_TAG_DOIT)) - add_lightgroup(re, ma->group, ma->mode & MA_GROUP_NOLAY); - } -} - -static void set_renderlayer_lightgroups(Render *re, Scene *sce) -{ - SceneRenderLayer *srl; - - for (srl= sce->r.layers.first; srl; srl= srl->next) { - if (srl->light_override) - add_lightgroup(re, srl->light_override, 0); - } -} - -/* ------------------------------------------------------------------------- */ -/* World */ -/* ------------------------------------------------------------------------- */ - -void init_render_world(Render *re) -{ - void *wrld_prev[2] = { - re->wrld.aotables, - re->wrld.aosphere, - }; - - int a; - - if (re->scene && re->scene->world) { - re->wrld = *(re->scene->world); - - copy_v3_v3(re->grvec, re->viewmat[2]); - normalize_v3(re->grvec); - copy_m3_m4(re->imat, re->viewinv); - - for (a=0; a<MAX_MTEX; a++) - if (re->wrld.mtex[a] && re->wrld.mtex[a]->tex) re->wrld.skytype |= WO_SKYTEX; - - /* AO samples should be OSA minimum */ - if (re->osa) - while (re->wrld.aosamp*re->wrld.aosamp < re->osa) - re->wrld.aosamp++; - if (!(re->r.mode & R_RAYTRACE) && (re->wrld.ao_gather_method == WO_AOGATHER_RAYTRACE)) - re->wrld.mode &= ~(WO_AMB_OCC|WO_ENV_LIGHT|WO_INDIRECT_LIGHT); - } - else { - memset(&re->wrld, 0, sizeof(World)); - re->wrld.exp= 0.0f; - re->wrld.range= 1.0f; - - /* for mist pass */ - re->wrld.miststa= re->clipsta; - re->wrld.mistdist= re->clipend-re->clipsta; - re->wrld.misi= 1.0f; - } - - re->wrld.linfac= 1.0f + powf((2.0f*re->wrld.exp + 0.5f), -10); - re->wrld.logfac= logf((re->wrld.linfac-1.0f)/re->wrld.linfac) / re->wrld.range; - - /* restore runtime vars, needed for viewport rendering [#36005] */ - re->wrld.aotables = wrld_prev[0]; - re->wrld.aosphere = wrld_prev[1]; -} - - - -/* ------------------------------------------------------------------------- */ -/* Object Finalization */ -/* ------------------------------------------------------------------------- */ - -/* prevent phong interpolation for giving ray shadow errors (terminator problem) */ -static void set_phong_threshold(ObjectRen *obr) -{ -// VertRen *ver; - VlakRen *vlr; - float thresh= 0.0, dot; - int tot=0, i; - - /* Added check for 'pointy' situations, only dotproducts of 0.9 and larger - * are taken into account. This threshold is meant to work on smooth geometry, not - * for extreme cases (ton) */ - - for (i=0; i<obr->totvlak; i++) { - vlr= RE_findOrAddVlak(obr, i); - if ((vlr->flag & R_SMOOTH) && (vlr->flag & R_STRAND)==0) { - dot= dot_v3v3(vlr->n, vlr->v1->n); - dot= ABS(dot); - if (dot>0.9f) { - thresh+= dot; tot++; - } - dot= dot_v3v3(vlr->n, vlr->v2->n); - dot= ABS(dot); - if (dot>0.9f) { - thresh+= dot; tot++; - } - - dot= dot_v3v3(vlr->n, vlr->v3->n); - dot= ABS(dot); - if (dot>0.9f) { - thresh+= dot; tot++; - } - - if (vlr->v4) { - dot= dot_v3v3(vlr->n, vlr->v4->n); - dot= ABS(dot); - if (dot>0.9f) { - thresh+= dot; tot++; - } - } - } - } - - if (tot) { - thresh/= (float)tot; - obr->ob->smoothresh= cosf(0.5f*(float)M_PI-saacos(thresh)); - } -} - -/* per face check if all samples should be taken. - * if raytrace or multisample, do always for raytraced material, or when material full_osa set */ -static void set_fullsample_trace_flag(Render *re, ObjectRen *obr) -{ - VlakRen *vlr; - int a, trace, mode, osa; - - osa= re->osa; - trace= re->r.mode & R_RAYTRACE; - - for (a=obr->totvlak-1; a>=0; a--) { - vlr= RE_findOrAddVlak(obr, a); - mode= vlr->mat->mode; - - if (trace && (mode & MA_TRACEBLE)) - vlr->flag |= R_TRACEBLE; - - if (osa) { - if (mode & MA_FULL_OSA) { - vlr->flag |= R_FULL_OSA; - } - else if (trace) { - if (mode & MA_SHLESS) { - /* pass */ - } - else if (vlr->mat->material_type == MA_TYPE_VOLUME) { - /* pass */ - } - else if ((mode & MA_RAYMIRROR) || ((mode & MA_TRANSP) && (mode & MA_RAYTRANSP))) { - /* for blurry reflect/refract, better to take more samples - * inside the raytrace than as OSA samples */ - if ((vlr->mat->gloss_mir == 1.0f) && (vlr->mat->gloss_tra == 1.0f)) - vlr->flag |= R_FULL_OSA; - } - } - } - } -} - -/* split quads for predictable baking - * dir 1 == (0, 1, 2) (0, 2, 3), 2 == (1, 3, 0) (1, 2, 3) - */ -static void split_quads(ObjectRen *obr, int dir) -{ - VlakRen *vlr, *vlr1; - int a; - - for (a=obr->totvlak-1; a>=0; a--) { - vlr= RE_findOrAddVlak(obr, a); - - /* test if rendering as a quad or triangle, skip wire */ - if ((vlr->flag & R_STRAND)==0 && (vlr->mat->material_type != MA_TYPE_WIRE)) { - - if (vlr->v4) { - - vlr1= RE_vlakren_copy(obr, vlr); - vlr1->flag |= R_FACE_SPLIT; - - if ( dir==2 ) vlr->flag |= R_DIVIDE_24; - else vlr->flag &= ~R_DIVIDE_24; - - /* new vertex pointers */ - if (vlr->flag & R_DIVIDE_24) { - vlr1->v1= vlr->v2; - vlr1->v2= vlr->v3; - vlr1->v3= vlr->v4; - - vlr->v3 = vlr->v4; - - vlr1->flag |= R_DIVIDE_24; - } - else { - vlr1->v1= vlr->v1; - vlr1->v2= vlr->v3; - vlr1->v3= vlr->v4; - - vlr1->flag &= ~R_DIVIDE_24; - } - vlr->v4 = vlr1->v4 = NULL; - -#ifdef WITH_FREESTYLE - /* Freestyle edge marks */ - if (vlr->flag & R_DIVIDE_24) { - vlr1->freestyle_edge_mark= - ((vlr->freestyle_edge_mark & R_EDGE_V2V3) ? R_EDGE_V1V2 : 0) | - ((vlr->freestyle_edge_mark & R_EDGE_V3V4) ? R_EDGE_V2V3 : 0); - vlr->freestyle_edge_mark= - ((vlr->freestyle_edge_mark & R_EDGE_V1V2) ? R_EDGE_V1V2 : 0) | - ((vlr->freestyle_edge_mark & R_EDGE_V4V1) ? R_EDGE_V3V1 : 0); - } - else { - vlr1->freestyle_edge_mark= - ((vlr->freestyle_edge_mark & R_EDGE_V3V4) ? R_EDGE_V2V3 : 0) | - ((vlr->freestyle_edge_mark & R_EDGE_V4V1) ? R_EDGE_V3V1 : 0); - vlr->freestyle_edge_mark= - ((vlr->freestyle_edge_mark & R_EDGE_V1V2) ? R_EDGE_V1V2 : 0) | - ((vlr->freestyle_edge_mark & R_EDGE_V2V3) ? R_EDGE_V2V3 : 0); - } -#endif - - /* new normals */ - normal_tri_v3(vlr->n, vlr->v3->co, vlr->v2->co, vlr->v1->co); - normal_tri_v3(vlr1->n, vlr1->v3->co, vlr1->v2->co, vlr1->v1->co); - } - /* clear the flag when not divided */ - else vlr->flag &= ~R_DIVIDE_24; - } - } -} - -static void check_non_flat_quads(ObjectRen *obr) -{ - VlakRen *vlr, *vlr1; - VertRen *v1, *v2, *v3, *v4; - float nor[3], xn, flen; - int a; - - for (a=obr->totvlak-1; a>=0; a--) { - vlr= RE_findOrAddVlak(obr, a); - - /* test if rendering as a quad or triangle, skip wire */ - if (vlr->v4 && (vlr->flag & R_STRAND)==0 && (vlr->mat->material_type != MA_TYPE_WIRE)) { - - /* check if quad is actually triangle */ - v1= vlr->v1; - v2= vlr->v2; - v3= vlr->v3; - v4= vlr->v4; - sub_v3_v3v3(nor, v1->co, v2->co); - if ( ABS(nor[0])<FLT_EPSILON10 && ABS(nor[1])<FLT_EPSILON10 && ABS(nor[2])<FLT_EPSILON10 ) { - vlr->v1= v2; - vlr->v2= v3; - vlr->v3= v4; - vlr->v4= NULL; - vlr->flag |= (R_DIVIDE_24 | R_FACE_SPLIT); - } - else { - sub_v3_v3v3(nor, v2->co, v3->co); - if ( ABS(nor[0])<FLT_EPSILON10 && ABS(nor[1])<FLT_EPSILON10 && ABS(nor[2])<FLT_EPSILON10 ) { - vlr->v2= v3; - vlr->v3= v4; - vlr->v4= NULL; - vlr->flag |= R_FACE_SPLIT; - } - else { - sub_v3_v3v3(nor, v3->co, v4->co); - if ( ABS(nor[0])<FLT_EPSILON10 && ABS(nor[1])<FLT_EPSILON10 && ABS(nor[2])<FLT_EPSILON10 ) { - vlr->v4= NULL; - } - else { - sub_v3_v3v3(nor, v4->co, v1->co); - if ( ABS(nor[0])<FLT_EPSILON10 && ABS(nor[1])<FLT_EPSILON10 && ABS(nor[2])<FLT_EPSILON10 ) { - vlr->v4= NULL; - } - } - } - } - - if (vlr->v4) { - - /* Face is divided along edge with the least gradient */ - /* Flagged with R_DIVIDE_24 if divide is from vert 2 to 4 */ - /* 4---3 4---3 */ - /* |\ 1| or |1 /| */ - /* |0\ | |/ 0| */ - /* 1---2 1---2 0 = orig face, 1 = new face */ - - /* render normals are inverted in render! we calculate normal of single tria here */ - flen= normal_tri_v3(nor, vlr->v4->co, vlr->v3->co, vlr->v1->co); - if (flen==0.0f) normal_tri_v3(nor, vlr->v4->co, vlr->v2->co, vlr->v1->co); - - xn = dot_v3v3(nor, vlr->n); - - if (ABS(xn) < 0.999995f ) { /* checked on noisy fractal grid */ - - float d1, d2; - - vlr1= RE_vlakren_copy(obr, vlr); - vlr1->flag |= R_FACE_SPLIT; - - /* split direction based on vnorms */ - normal_tri_v3(nor, vlr->v1->co, vlr->v2->co, vlr->v3->co); - d1 = dot_v3v3(nor, vlr->v1->n); - - normal_tri_v3(nor, vlr->v2->co, vlr->v3->co, vlr->v4->co); - d2 = dot_v3v3(nor, vlr->v2->n); - - if (fabsf(d1) < fabsf(d2) ) vlr->flag |= R_DIVIDE_24; - else vlr->flag &= ~R_DIVIDE_24; - - /* new vertex pointers */ - if (vlr->flag & R_DIVIDE_24) { - vlr1->v1= vlr->v2; - vlr1->v2= vlr->v3; - vlr1->v3= vlr->v4; - - vlr->v3 = vlr->v4; - - vlr1->flag |= R_DIVIDE_24; - } - else { - vlr1->v1= vlr->v1; - vlr1->v2= vlr->v3; - vlr1->v3= vlr->v4; - - vlr1->flag &= ~R_DIVIDE_24; - } - vlr->v4 = vlr1->v4 = NULL; - - /* new normals */ - normal_tri_v3(vlr->n, vlr->v3->co, vlr->v2->co, vlr->v1->co); - normal_tri_v3(vlr1->n, vlr1->v3->co, vlr1->v2->co, vlr1->v1->co); - -#ifdef WITH_FREESTYLE - /* Freestyle edge marks */ - if (vlr->flag & R_DIVIDE_24) { - vlr1->freestyle_edge_mark= - ((vlr->freestyle_edge_mark & R_EDGE_V2V3) ? R_EDGE_V1V2 : 0) | - ((vlr->freestyle_edge_mark & R_EDGE_V3V4) ? R_EDGE_V2V3 : 0); - vlr->freestyle_edge_mark= - ((vlr->freestyle_edge_mark & R_EDGE_V1V2) ? R_EDGE_V1V2 : 0) | - ((vlr->freestyle_edge_mark & R_EDGE_V4V1) ? R_EDGE_V3V1 : 0); - } - else { - vlr1->freestyle_edge_mark= - ((vlr->freestyle_edge_mark & R_EDGE_V3V4) ? R_EDGE_V2V3 : 0) | - ((vlr->freestyle_edge_mark & R_EDGE_V4V1) ? R_EDGE_V3V1 : 0); - vlr->freestyle_edge_mark= - ((vlr->freestyle_edge_mark & R_EDGE_V1V2) ? R_EDGE_V1V2 : 0) | - ((vlr->freestyle_edge_mark & R_EDGE_V2V3) ? R_EDGE_V2V3 : 0); - } -#endif - } - /* clear the flag when not divided */ - else vlr->flag &= ~R_DIVIDE_24; - } - } - } -} - -static void finalize_render_object(Render *re, ObjectRen *obr, int timeoffset) -{ - Object *ob= obr->ob; - VertRen *ver= NULL; - StrandRen *strand= NULL; - StrandBound *sbound= NULL; - float min[3], max[3], smin[3], smax[3]; - int a, b; - - if (obr->totvert || obr->totvlak || obr->tothalo || obr->totstrand) { - /* the exception below is because displace code now is in init_render_mesh call, - * I will look at means to have autosmooth enabled for all object types - * and have it as general postprocess, like displace */ - if (ob->type!=OB_MESH && test_for_displace(re, ob)) - displace(re, obr); - - if (!timeoffset) { - /* phong normal interpolation can cause error in tracing - * (terminator problem) */ - ob->smoothresh= 0.0; - if ((re->r.mode & R_RAYTRACE) && (re->r.mode & R_SHADOW)) - set_phong_threshold(obr); - - if (re->flag & R_BAKING && re->r.bake_quad_split != 0) { - /* Baking lets us define a quad split order */ - split_quads(obr, re->r.bake_quad_split); - } - else if (BKE_object_is_animated(re->scene, ob)) - split_quads(obr, 1); - else { - if ((re->r.mode & R_SIMPLIFY && re->r.simplify_flag & R_SIMPLE_NO_TRIANGULATE) == 0) - check_non_flat_quads(obr); - } - - set_fullsample_trace_flag(re, obr); - - /* compute bounding boxes for clipping */ - INIT_MINMAX(min, max); - for (a=0; a<obr->totvert; a++) { - if ((a & 255)==0) ver= obr->vertnodes[a>>8].vert; - else ver++; - - minmax_v3v3_v3(min, max, ver->co); - } - - if (obr->strandbuf) { - float width; - - /* compute average bounding box of strandpoint itself (width) */ - if (obr->strandbuf->flag & R_STRAND_B_UNITS) - obr->strandbuf->maxwidth = max_ff(obr->strandbuf->ma->strand_sta, obr->strandbuf->ma->strand_end); - else - obr->strandbuf->maxwidth= 0.0f; - - width= obr->strandbuf->maxwidth; - sbound= obr->strandbuf->bound; - for (b=0; b<obr->strandbuf->totbound; b++, sbound++) { - - INIT_MINMAX(smin, smax); - - for (a=sbound->start; a<sbound->end; a++) { - strand= RE_findOrAddStrand(obr, a); - strand_minmax(strand, smin, smax, width); - } - - copy_v3_v3(sbound->boundbox[0], smin); - copy_v3_v3(sbound->boundbox[1], smax); - - minmax_v3v3_v3(min, max, smin); - minmax_v3v3_v3(min, max, smax); - } - } - - copy_v3_v3(obr->boundbox[0], min); - copy_v3_v3(obr->boundbox[1], max); - } - } -} - -/* ------------------------------------------------------------------------- */ -/* Database */ -/* ------------------------------------------------------------------------- */ - -static int render_object_type(short type) -{ - return OB_TYPE_SUPPORT_MATERIAL(type); -} - -static void find_dupli_instances(Render *re, ObjectRen *obr, DupliObject *dob) -{ - ObjectInstanceRen *obi; - float imat[4][4], obmat[4][4], obimat[4][4], nmat[3][3]; - int first = 1; - - mul_m4_m4m4(obmat, re->viewmat, obr->obmat); - invert_m4_m4(imat, obmat); - - /* for objects instanced by dupliverts/faces/particles, we go over the - * list of instances to find ones that instance obr, and setup their - * matrices and obr pointer */ - for (obi=re->instancetable.last; obi; obi=obi->prev) { - if (!obi->obr && obi->ob == obr->ob && obi->psysindex == obr->psysindex) { - obi->obr= obr; - - /* compute difference between object matrix and - * object matrix with dupli transform, in viewspace */ - copy_m4_m4(obimat, obi->mat); - mul_m4_m4m4(obi->mat, obimat, imat); - - copy_m3_m4(nmat, obi->mat); - invert_m3_m3(obi->nmat, nmat); - transpose_m3(obi->nmat); - - if (dob) { - copy_v3_v3(obi->dupliorco, dob->orco); - obi->dupliuv[0]= dob->uv[0]; - obi->dupliuv[1]= dob->uv[1]; - } - - if (!first) { - re->totvert += obr->totvert; - re->totvlak += obr->totvlak; - re->tothalo += obr->tothalo; - re->totstrand += obr->totstrand; - } - else - first= 0; - } - } -} - -static void assign_dupligroup_dupli(Render *re, ObjectInstanceRen *obi, ObjectRen *obr, DupliObject *dob) -{ - float imat[4][4], obmat[4][4], obimat[4][4], nmat[3][3]; - - mul_m4_m4m4(obmat, re->viewmat, obr->obmat); - invert_m4_m4(imat, obmat); - - obi->obr= obr; - - /* compute difference between object matrix and - * object matrix with dupli transform, in viewspace */ - copy_m4_m4(obimat, obi->mat); - mul_m4_m4m4(obi->mat, obimat, imat); - - copy_m3_m4(nmat, obi->mat); - invert_m3_m3(obi->nmat, nmat); - transpose_m3(obi->nmat); - - if (dob) { - copy_v3_v3(obi->dupliorco, dob->orco); - obi->dupliuv[0]= dob->uv[0]; - obi->dupliuv[1]= dob->uv[1]; - } - - re->totvert += obr->totvert; - re->totvlak += obr->totvlak; - re->tothalo += obr->tothalo; - re->totstrand += obr->totstrand; -} - -static ObjectRen *find_dupligroup_dupli(Render *re, Object *ob, int psysindex) -{ - ObjectRen *obr; - - /* if the object is itself instanced, we don't want to create an instance - * for it */ - if (ob->transflag & OB_RENDER_DUPLI) - return NULL; - - /* try to find an object that was already created so we can reuse it - * and save memory */ - for (obr=re->objecttable.first; obr; obr=obr->next) - if (obr->ob == ob && obr->psysindex == psysindex && (obr->flag & R_INSTANCEABLE)) - return obr; - - return NULL; -} - -static void set_dupli_tex_mat(Render *re, ObjectInstanceRen *obi, DupliObject *dob, float omat[4][4]) -{ - /* For duplis we need to have a matrix that transform the coordinate back - * to it's original position, without the dupli transforms. We also check - * the matrix is actually needed, to save memory on lots of dupliverts for - * example */ - static Object *lastob= NULL; - static int needtexmat= 0; - - /* init */ - if (!re) { - lastob= NULL; - needtexmat= 0; - return; - } - - /* check if we actually need it */ - if (lastob != dob->ob) { - Material ***material; - short a, *totmaterial; - - lastob= dob->ob; - needtexmat= 0; - - totmaterial= give_totcolp(dob->ob); - material= give_matarar(dob->ob); - - if (totmaterial && material) - for (a= 0; a<*totmaterial; a++) - if ((*material)[a] && (*material)[a]->texco & TEXCO_OBJECT) - needtexmat= 1; - } - - if (needtexmat) { - float imat[4][4]; - - obi->duplitexmat= BLI_memarena_alloc(re->memArena, sizeof(float)*4*4); - invert_m4_m4(imat, dob->mat); - mul_m4_series(obi->duplitexmat, re->viewmat, omat, imat, re->viewinv); - } - - copy_v3_v3(obi->dupliorco, dob->orco); - copy_v2_v2(obi->dupliuv, dob->uv); -} - -static void init_render_object_data(Render *re, ObjectRen *obr, int timeoffset) -{ - Object *ob= obr->ob; - ParticleSystem *psys; - int i; - - if (obr->psysindex) { - if ((!obr->prev || obr->prev->ob != ob || (obr->prev->flag & R_INSTANCEABLE)==0) && ob->type==OB_MESH) { - /* the emitter mesh wasn't rendered so the modifier stack wasn't - * evaluated with render settings */ - DerivedMesh *dm; - const CustomDataMask mask = CD_MASK_RENDER_INTERNAL; - - if (re->r.scemode & R_VIEWPORT_PREVIEW) - dm = mesh_create_derived_view(re->scene, ob, mask); - else - dm = mesh_create_derived_render(re->scene, ob, mask); - dm->release(dm); - } - - for (psys=ob->particlesystem.first, i=0; i<obr->psysindex-1; i++) - psys= psys->next; - - render_new_particle_system(re, obr, psys, timeoffset); - } - else { - if (ELEM(ob->type, OB_FONT, OB_CURVE)) - init_render_curve(re, obr, timeoffset); - else if (ob->type==OB_SURF) - init_render_surf(re, obr, timeoffset); - else if (ob->type==OB_MESH) - init_render_mesh(re, obr, timeoffset); - else if (ob->type==OB_MBALL) - init_render_mball(re, obr); - } - - finalize_render_object(re, obr, timeoffset); - - re->totvert += obr->totvert; - re->totvlak += obr->totvlak; - re->tothalo += obr->tothalo; - re->totstrand += obr->totstrand; -} - -static void add_render_object(Render *re, Object *ob, Object *par, DupliObject *dob, float omat[4][4], int timeoffset) -{ - ObjectRen *obr; - ObjectInstanceRen *obi; - ParticleSystem *psys; - int show_emitter, allow_render= 1, index, psysindex, i; - - index= (dob)? dob->persistent_id[0]: 0; - - /* It seems that we may generate psys->renderdata recursively in some nasty intricated cases of - * several levels of bupliobject (see T51524). - * For now, basic rule is, do not restore psys if it was already in 'render state'. - * Another, more robust solution could be to add some reference counting to that renderdata... */ - bool psys_has_renderdata = false; - - /* the emitter has to be processed first (render levels of modifiers) */ - /* so here we only check if the emitter should be rendered */ - if (ob->particlesystem.first) { - show_emitter= 0; - for (psys=ob->particlesystem.first; psys; psys=psys->next) { - show_emitter += psys->part->draw & PART_DRAW_EMITTER; - if (!(re->r.scemode & R_VIEWPORT_PREVIEW)) { - psys_has_renderdata |= (psys->renderdata != NULL); - psys_render_set(ob, psys, re->viewmat, re->winmat, re->winx, re->winy, timeoffset); - } - } - - /* if no psys has "show emitter" selected don't render emitter */ - if (show_emitter == 0) - allow_render= 0; - } - - /* one render object for the data itself */ - if (allow_render) { - obr= RE_addRenderObject(re, ob, par, index, 0, ob->lay); - if ((dob && !dob->animated) || (ob->transflag & OB_RENDER_DUPLI)) { - obr->flag |= R_INSTANCEABLE; - copy_m4_m4(obr->obmat, ob->obmat); - } - init_render_object_data(re, obr, timeoffset); - - /* only add instance for objects that have not been used for dupli */ - if (!(ob->transflag & OB_RENDER_DUPLI)) { - obi = RE_addRenderInstance(re, obr, ob, par, index, 0, NULL, ob->lay, dob); - if (dob) set_dupli_tex_mat(re, obi, dob, omat); - } - else - find_dupli_instances(re, obr, dob); - - for (i=1; i<=ob->totcol; i++) { - Material* ma = give_render_material(re, ob, i); - if (ma && ma->material_type == MA_TYPE_VOLUME) - add_volume(re, obr, ma); - } - } - - /* and one render object per particle system */ - if (ob->particlesystem.first) { - psysindex= 1; - for (psys=ob->particlesystem.first; psys; psys=psys->next, psysindex++) { - if (!psys_check_enabled(ob, psys, G.is_rendering)) - continue; - - obr= RE_addRenderObject(re, ob, par, index, psysindex, ob->lay); - if ((dob && !dob->animated) || (ob->transflag & OB_RENDER_DUPLI)) { - obr->flag |= R_INSTANCEABLE; - copy_m4_m4(obr->obmat, ob->obmat); - } - if (dob) - psys->flag |= PSYS_USE_IMAT; - init_render_object_data(re, obr, timeoffset); - if (!(re->r.scemode & R_VIEWPORT_PREVIEW) && !psys_has_renderdata) { - psys_render_restore(ob, psys); - } - psys->flag &= ~PSYS_USE_IMAT; - - /* only add instance for objects that have not been used for dupli */ - if (!(ob->transflag & OB_RENDER_DUPLI)) { - obi = RE_addRenderInstance(re, obr, ob, par, index, psysindex, NULL, ob->lay, dob); - if (dob) set_dupli_tex_mat(re, obi, dob, omat); - } - else - find_dupli_instances(re, obr, dob); - } - } -} - -/* par = pointer to duplicator parent, needed for object lookup table */ -/* index = when duplicater copies same object (particle), the counter */ -static void init_render_object(Render *re, Object *ob, Object *par, DupliObject *dob, float omat[4][4], int timeoffset) -{ - static double lasttime= 0.0; - double time; - float mat[4][4]; - - if (ob->type==OB_LAMP) - add_render_lamp(re, ob); - else if (render_object_type(ob->type)) - add_render_object(re, ob, par, dob, omat, timeoffset); - else { - mul_m4_m4m4(mat, re->viewmat, ob->obmat); - invert_m4_m4(ob->imat, mat); - } - - time= PIL_check_seconds_timer(); - if (time - lasttime > 1.0) { - lasttime= time; - /* clumsy copying still */ - re->i.totvert= re->totvert; - re->i.totface= re->totvlak; - re->i.totstrand= re->totstrand; - re->i.tothalo= re->tothalo; - re->i.totlamp= re->totlamp; - re->stats_draw(re->sdh, &re->i); - } - - ob->flag |= OB_DONE; -} - -void RE_Database_Free(Render *re) -{ - LampRen *lar; - - /* will crash if we try to free empty database */ - if (!re->i.convertdone) - return; - - /* statistics for debugging render memory usage */ - if ((G.debug & G_DEBUG) && (G.is_rendering)) { - if ((re->r.scemode & (R_BUTS_PREVIEW|R_VIEWPORT_PREVIEW))==0) { - BKE_image_print_memlist(); - MEM_printmemlist_stats(); - } - } - - /* FREE */ - - for (lar= re->lampren.first; lar; lar= lar->next) { - freeshadowbuf(lar); - if (lar->jitter) MEM_freeN(lar->jitter); - if (lar->shadsamp) MEM_freeN(lar->shadsamp); - if (lar->sunsky) MEM_freeN(lar->sunsky); - curvemapping_free(lar->curfalloff); - } - - free_volume_precache(re); - - BLI_freelistN(&re->lampren); - BLI_freelistN(&re->lights); - - free_renderdata_tables(re); - - /* free orco */ - free_mesh_orco_hash(re); - - if (re->main) { - end_render_materials(re->main); - end_render_textures(re); - free_pointdensities(re); - } - - free_camera_inside_volumes(re); - - if (re->wrld.aosphere) { - MEM_freeN(re->wrld.aosphere); - re->wrld.aosphere= NULL; - if (re->scene && re->scene->world) - re->scene->world->aosphere= NULL; - } - if (re->wrld.aotables) { - MEM_freeN(re->wrld.aotables); - re->wrld.aotables= NULL; - if (re->scene && re->scene->world) - re->scene->world->aotables= NULL; - } - if (re->r.mode & R_RAYTRACE) - free_render_qmcsampler(re); - - if (re->r.mode & R_RAYTRACE) freeraytree(re); - - free_sss(re); - free_occ(re); - free_strand_surface(re); - - re->totvlak=re->totvert=re->totstrand=re->totlamp=re->tothalo= 0; - re->i.convertdone = false; - - re->bakebuf= NULL; - - if (re->scene) - if (re->scene->r.scemode & R_FREE_IMAGE) - if ((re->r.scemode & (R_BUTS_PREVIEW|R_VIEWPORT_PREVIEW))==0) - BKE_image_free_all_textures(); - - if (re->memArena) { - BLI_memarena_free(re->memArena); - re->memArena = NULL; - } -} - -static int allow_render_object(Render *re, Object *ob, int nolamps, int onlyselected, Object *actob) -{ - if (is_object_hidden(re, ob)) - return 0; - - /* Only handle dupli-hiding here if there is no particle systems. Else, let those handle show/noshow. */ - if (!ob->particlesystem.first) { - if ((ob->transflag & OB_DUPLI) && !(ob->transflag & OB_DUPLIFRAMES)) { - return 0; - } - } - - /* don't add non-basic meta objects, ends up having renderobjects with no geometry */ - if (ob->type == OB_MBALL && ob!=BKE_mball_basis_find(re->eval_ctx, re->scene, ob)) - return 0; - - if (nolamps && (ob->type==OB_LAMP)) - return 0; - - if (onlyselected && (ob!=actob && !(ob->flag & SELECT))) - return 0; - - return 1; -} - -static int allow_render_dupli_instance(Render *UNUSED(re), DupliObject *dob, Object *obd) -{ - ParticleSystem *psys; - Material *ma; - short a, *totmaterial; - - /* don't allow objects with halos. we need to have - * all halo's to sort them globally in advance */ - totmaterial= give_totcolp(obd); - - if (totmaterial) { - for (a= 0; a<*totmaterial; a++) { - ma= give_current_material(obd, a + 1); - if (ma && (ma->material_type == MA_TYPE_HALO)) - return 0; - } - } - - for (psys=obd->particlesystem.first; psys; psys=psys->next) - if (!ELEM(psys->part->ren_as, PART_DRAW_BB, PART_DRAW_LINE, PART_DRAW_PATH, PART_DRAW_OB, PART_DRAW_GR)) - return 0; - - /* don't allow lamp, animated duplis, or radio render */ - return (render_object_type(obd->type) && - (!(dob->type == OB_DUPLIGROUP) || !dob->animated)); -} - -static void dupli_render_particle_set(Render *re, Object *ob, int timeoffset, int level, int enable) -{ - /* ugly function, but we need to set particle systems to their render - * settings before calling object_duplilist, to get render level duplis */ - Group *group; - GroupObject *go; - ParticleSystem *psys; - DerivedMesh *dm; - - if (re->r.scemode & R_VIEWPORT_PREVIEW) - return; - - if (level >= MAX_DUPLI_RECUR) - return; - - if (ob->transflag & OB_DUPLIPARTS) { - for (psys=ob->particlesystem.first; psys; psys=psys->next) { - if (ELEM(psys->part->ren_as, PART_DRAW_OB, PART_DRAW_GR)) { - if (enable) - psys_render_set(ob, psys, re->viewmat, re->winmat, re->winx, re->winy, timeoffset); - else - psys_render_restore(ob, psys); - } - } - - if (enable) { - /* this is to make sure we get render level duplis in groups: - * the derivedmesh must be created before init_render_mesh, - * since object_duplilist does dupliparticles before that */ - dm = mesh_create_derived_render(re->scene, ob, CD_MASK_RENDER_INTERNAL); - dm->release(dm); - - for (psys=ob->particlesystem.first; psys; psys=psys->next) - psys_get_modifier(ob, psys)->flag &= ~eParticleSystemFlag_psys_updated; - } - } - - if (ob->dup_group==NULL) return; - group= ob->dup_group; - - for (go= group->gobject.first; go; go= go->next) - dupli_render_particle_set(re, go->ob, timeoffset, level+1, enable); -} - -static int get_vector_renderlayers(Scene *sce) -{ - SceneRenderLayer *srl; - unsigned int lay= 0; - - for (srl= sce->r.layers.first; srl; srl= srl->next) - if (srl->passflag & SCE_PASS_VECTOR) - lay |= srl->lay; - - return lay; -} - -static void add_group_render_dupli_obs(Render *re, Group *group, int nolamps, int onlyselected, Object *actob, int timeoffset, int level) -{ - GroupObject *go; - Object *ob; - - /* simple preventing of too deep nested groups */ - if (level>MAX_DUPLI_RECUR) return; - - /* recursively go into dupligroups to find objects with OB_RENDER_DUPLI - * that were not created yet */ - for (go= group->gobject.first; go; go= go->next) { - ob= go->ob; - - if (ob->flag & OB_DONE) { - if (ob->transflag & OB_RENDER_DUPLI) { - if (allow_render_object(re, ob, nolamps, onlyselected, actob)) { - init_render_object(re, ob, NULL, NULL, NULL, timeoffset); - ob->transflag &= ~OB_RENDER_DUPLI; - - if (ob->dup_group) - add_group_render_dupli_obs(re, ob->dup_group, nolamps, onlyselected, actob, timeoffset, level+1); - } - } - } - } -} - -static void database_init_objects(Render *re, unsigned int renderlay, int nolamps, int onlyselected, Object *actob, int timeoffset) -{ - Base *base; - Object *ob; - Group *group; - ObjectInstanceRen *obi; - Scene *sce_iter; - int lay, vectorlay; - - /* for duplis we need the Object texture mapping to work as if - * untransformed, set_dupli_tex_mat sets the matrix to allow that - * NULL is just for init */ - set_dupli_tex_mat(NULL, NULL, NULL, NULL); - - /* loop over all objects rather then using SETLOOPER because we may - * reference an mtex-mapped object which isn't rendered or is an - * empty in a dupli group. We could scan all render material/lamp/world - * mtex's for mapto objects but its easier just to set the - * 'imat' / 'imat_ren' on all and unlikely to be a performance hit - * See bug: [#28744] - campbell */ - for (ob= re->main->object.first; ob; ob= ob->id.next) { - float mat[4][4]; - - /* imat objects has to be done here, since displace can have texture using Object map-input */ - mul_m4_m4m4(mat, re->viewmat, ob->obmat); - invert_m4_m4(ob->imat_ren, mat); - copy_m4_m4(ob->imat, ob->imat_ren); - /* each object should only be rendered once */ - ob->flag &= ~OB_DONE; - ob->transflag &= ~OB_RENDER_DUPLI; - } - - for (SETLOOPER(re->scene, sce_iter, base)) { - ob= base->object; - - /* in the prev/next pass for making speed vectors, avoid creating - * objects that are not on a renderlayer with a vector pass, can - * save a lot of time in complex scenes */ - vectorlay= get_vector_renderlayers(re->scene); - lay= (timeoffset)? renderlay & vectorlay: renderlay; - - /* if the object has been restricted from rendering in the outliner, ignore it */ - if (is_object_restricted(re, ob)) continue; - - /* OB_DONE means the object itself got duplicated, so was already converted */ - if (ob->flag & OB_DONE) { - /* OB_RENDER_DUPLI means instances for it were already created, now - * it still needs to create the ObjectRen containing the data */ - if (ob->transflag & OB_RENDER_DUPLI) { - if (allow_render_object(re, ob, nolamps, onlyselected, actob)) { - init_render_object(re, ob, NULL, NULL, NULL, timeoffset); - ob->transflag &= ~OB_RENDER_DUPLI; - } - } - } - else if ((base->lay & lay) || (ob->type==OB_LAMP && (base->lay & re->lay)) ) { - if ((ob->transflag & OB_DUPLI) && (ob->type!=OB_MBALL)) { - DupliObject *dob; - ListBase *duplilist; - DupliApplyData *duplilist_apply_data = NULL; - int i; - - /* create list of duplis generated by this object, particle - * system need to have render settings set for dupli particles */ - dupli_render_particle_set(re, ob, timeoffset, 0, 1); - duplilist = object_duplilist(re->eval_ctx, re->scene, ob); - duplilist_apply_data = duplilist_apply(ob, NULL, duplilist); - /* postpone 'dupli_render_particle_set', since RE_addRenderInstance reads - * index values from 'dob->persistent_id[0]', referencing 'psys->child' which - * may be smaller once the particle system is restored, see: T45563. */ - - for (dob= duplilist->first, i = 0; dob; dob= dob->next, ++i) { - DupliExtraData *dob_extra = &duplilist_apply_data->extra[i]; - Object *obd= dob->ob; - - copy_m4_m4(obd->obmat, dob->mat); - - /* group duplis need to set ob matrices correct, for deform. so no_draw is part handled */ - if (!(obd->transflag & OB_RENDER_DUPLI) && dob->no_draw) - continue; - - if (is_object_hidden(re, obd)) - continue; - - if (obd->type==OB_MBALL) - continue; - - if (!allow_render_object(re, obd, nolamps, onlyselected, actob)) - continue; - - if (allow_render_dupli_instance(re, dob, obd)) { - ParticleSystem *psys; - ObjectRen *obr = NULL; - int psysindex; - float mat[4][4]; - - obi=NULL; - - /* instances instead of the actual object are added in two cases, either - * this is a duplivert/face/particle, or it is a non-animated object in - * a dupligroup that has already been created before */ - if (dob->type != OB_DUPLIGROUP || (obr=find_dupligroup_dupli(re, obd, 0))) { - mul_m4_m4m4(mat, re->viewmat, dob->mat); - /* ob = particle system, use that layer */ - obi = RE_addRenderInstance(re, NULL, obd, ob, dob->persistent_id[0], 0, mat, ob->lay, dob); - - /* fill in instance variables for texturing */ - set_dupli_tex_mat(re, obi, dob, dob_extra->obmat); - if (dob->type != OB_DUPLIGROUP) { - copy_v3_v3(obi->dupliorco, dob->orco); - obi->dupliuv[0]= dob->uv[0]; - obi->dupliuv[1]= dob->uv[1]; - } - else { - /* for the second case, setup instance to point to the already - * created object, and possibly setup instances if this object - * itself was duplicated. for the first case find_dupli_instances - * will be called later. */ - assign_dupligroup_dupli(re, obi, obr, dob); - if (obd->transflag & OB_RENDER_DUPLI) - find_dupli_instances(re, obr, dob); - } - } - - /* same logic for particles, each particle system has it's own object, so - * need to go over them separately */ - psysindex= 1; - for (psys=obd->particlesystem.first; psys; psys=psys->next) { - if (dob->type != OB_DUPLIGROUP || (obr=find_dupligroup_dupli(re, obd, psysindex))) { - if (obi == NULL) - mul_m4_m4m4(mat, re->viewmat, dob->mat); - obi = RE_addRenderInstance(re, NULL, obd, ob, dob->persistent_id[0], psysindex++, mat, obd->lay, dob); - - set_dupli_tex_mat(re, obi, dob, dob_extra->obmat); - if (dob->type != OB_DUPLIGROUP) { - copy_v3_v3(obi->dupliorco, dob->orco); - obi->dupliuv[0]= dob->uv[0]; - obi->dupliuv[1]= dob->uv[1]; - } - else { - assign_dupligroup_dupli(re, obi, obr, dob); - if (obd->transflag & OB_RENDER_DUPLI) - find_dupli_instances(re, obr, dob); - } - } - } - - if (obi==NULL) - /* can't instance, just create the object */ - init_render_object(re, obd, ob, dob, dob_extra->obmat, timeoffset); - - if (dob->type != OB_DUPLIGROUP) { - obd->flag |= OB_DONE; - obd->transflag |= OB_RENDER_DUPLI; - } - } - else - init_render_object(re, obd, ob, dob, dob_extra->obmat, timeoffset); - - if (re->test_break(re->tbh)) break; - } - - /* restore particle system */ - dupli_render_particle_set(re, ob, timeoffset, 0, false); - - if (duplilist_apply_data) { - duplilist_restore(duplilist, duplilist_apply_data); - duplilist_free_apply_data(duplilist_apply_data); - } - free_object_duplilist(duplilist); - - if (allow_render_object(re, ob, nolamps, onlyselected, actob)) - init_render_object(re, ob, NULL, NULL, NULL, timeoffset); - } - else if (allow_render_object(re, ob, nolamps, onlyselected, actob)) - init_render_object(re, ob, NULL, NULL, NULL, timeoffset); - } - - if (re->test_break(re->tbh)) break; - } - - /* objects in groups with OB_RENDER_DUPLI set still need to be created, - * since they may not be part of the scene */ - for (group= re->main->group.first; group; group=group->id.next) - add_group_render_dupli_obs(re, group, nolamps, onlyselected, actob, timeoffset, 0); - - if (!re->test_break(re->tbh)) - RE_makeRenderInstances(re); -} - -/* used to be 'rotate scene' */ -void RE_Database_FromScene(Render *re, Main *bmain, Scene *scene, unsigned int lay, int use_camera_view) -{ - Scene *sce; - Object *camera; - float mat[4][4]; - float amb[3]; - - re->main= bmain; - re->scene= scene; - re->lay= lay; - - if (re->r.scemode & R_VIEWPORT_PREVIEW) - re->scene_color_manage = BKE_scene_check_color_management_enabled(scene); - - /* scene needs to be set to get camera */ - camera= RE_GetCamera(re); - - /* per second, per object, stats print this */ - re->i.infostr= "Preparing Scene data"; - re->i.cfra= scene->r.cfra; - BLI_strncpy(re->i.scene_name, scene->id.name + 2, sizeof(re->i.scene_name)); - - /* XXX add test if dbase was filled already? */ - - re->memArena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "render db arena"); - re->totvlak=re->totvert=re->totstrand=re->totlamp=re->tothalo= 0; - re->lights.first= re->lights.last= NULL; - re->lampren.first= re->lampren.last= NULL; - - re->i.partsdone = false; /* signal now in use for previewrender */ - - /* in localview, lamps are using normal layers, objects only local bits */ - if (re->lay & 0xFF000000) - lay &= 0xFF000000; - - /* applies changes fully */ - if ((re->r.scemode & (R_NO_FRAME_UPDATE|R_BUTS_PREVIEW|R_VIEWPORT_PREVIEW))==0) { - BKE_scene_update_for_newframe(re->eval_ctx, re->main, re->scene, lay); - render_update_anim_renderdata(re, &re->scene->r); - } - - /* if no camera, viewmat should have been set! */ - if (use_camera_view && camera) { - /* called before but need to call again in case of lens animation from the - * above call to BKE_scene_update_for_newframe, fixes bug. [#22702]. - * following calls don't depend on 'RE_SetCamera' */ - RE_SetCamera(re, camera); - RE_GetCameraModelMatrix(re, camera, mat); - invert_m4(mat); - RE_SetView(re, mat); - - /* force correct matrix for scaled cameras */ - DAG_id_tag_update_ex(re->main, &camera->id, OB_RECALC_OB); - } - - /* store for incremental render, viewmat rotates dbase */ - copy_m4_m4(re->viewmat_orig, re->viewmat); - - init_render_world(re); /* do first, because of ambient. also requires re->osa set correct */ - if (re->r.mode & R_RAYTRACE) { - init_render_qmcsampler(re); - - if (re->wrld.mode & (WO_AMB_OCC|WO_ENV_LIGHT|WO_INDIRECT_LIGHT)) - if (re->wrld.ao_samp_method == WO_AOSAMP_CONSTANT) - init_ao_sphere(re, &re->wrld); - } - - /* still bad... doing all */ - init_render_textures(re); - copy_v3_v3(amb, &re->wrld.ambr); - init_render_materials(re->main, re->r.mode, amb, (re->r.scemode & R_BUTS_PREVIEW) == 0); - set_node_shader_lamp_loop(shade_material_loop); - - /* MAKE RENDER DATA */ - database_init_objects(re, lay, 0, 0, NULL, 0); - - if (!re->test_break(re->tbh)) { - set_material_lightgroups(re); - for (sce= re->scene; sce; sce= sce->set) - set_renderlayer_lightgroups(re, sce); - - /* for now some clumsy copying still */ - re->i.totvert= re->totvert; - re->i.totface= re->totvlak; - re->i.totstrand= re->totstrand; - re->i.tothalo= re->tothalo; - re->i.totlamp= re->totlamp; - re->stats_draw(re->sdh, &re->i); - } -} - -void RE_Database_Preprocess(Render *re) -{ - if (!re->test_break(re->tbh)) { - int tothalo; - - tothalo= re->tothalo; - sort_halos(re, tothalo); - - init_camera_inside_volumes(re); - - re->i.infostr = IFACE_("Creating Shadowbuffers"); - re->stats_draw(re->sdh, &re->i); - - /* SHADOW BUFFER */ - threaded_makeshadowbufs(re); - - /* old code checked for internal render (aka not yafray) */ - { - /* raytree */ - if (!re->test_break(re->tbh)) { - if (re->r.mode & R_RAYTRACE) { - makeraytree(re); - } - } - /* ENVIRONMENT MAPS */ - if (!re->test_break(re->tbh)) - make_envmaps(re); - - /* point density texture */ - if (!re->test_break(re->tbh)) - make_pointdensities(re); - /* voxel data texture */ - if (!re->test_break(re->tbh)) - make_voxeldata(re); - } - - if (!re->test_break(re->tbh)) - project_renderdata(re, projectverto, (re->r.mode & R_PANORAMA) != 0, 0, 1); - - /* Occlusion */ - if ((re->wrld.mode & (WO_AMB_OCC|WO_ENV_LIGHT|WO_INDIRECT_LIGHT)) && !re->test_break(re->tbh)) - if (re->wrld.ao_gather_method == WO_AOGATHER_APPROX) - if (re->r.mode & R_SHADOW) - make_occ_tree(re); - - /* SSS */ - if ((re->r.mode & R_SSS) && !re->test_break(re->tbh)) - make_sss_tree(re); - - if (!re->test_break(re->tbh)) - if (re->r.mode & R_RAYTRACE) - volume_precache(re); - } - - re->i.convertdone = true; - - if (re->test_break(re->tbh)) - RE_Database_Free(re); - - re->i.infostr = NULL; - re->stats_draw(re->sdh, &re->i); -} - -/* exported call to recalculate hoco for vertices, when winmat changed */ -void RE_DataBase_ApplyWindow(Render *re) -{ - project_renderdata(re, projectverto, 0, 0, 0); -} - -/* exported call to rotate render data again, when viewmat changed */ -void RE_DataBase_IncrementalView(Render *re, float viewmat[4][4], int restore) -{ - float oldviewinv[4][4], tmat[4][4]; - - invert_m4_m4(oldviewinv, re->viewmat_orig); - - /* we have to correct for the already rotated vertexcoords */ - mul_m4_m4m4(tmat, viewmat, oldviewinv); - - copy_m4_m4(re->viewmat, viewmat); - invert_m4_m4(re->viewinv, re->viewmat); - - init_camera_inside_volumes(re); - - env_rotate_scene(re, tmat, !restore); - - /* SSS points distribution depends on view */ - if ((re->r.mode & R_SSS) && !re->test_break(re->tbh)) - make_sss_tree(re); -} - - -void RE_DataBase_GetView(Render *re, float mat[4][4]) -{ - copy_m4_m4(mat, re->viewmat); -} - -/* ------------------------------------------------------------------------- */ -/* Speed Vectors */ -/* ------------------------------------------------------------------------- */ - -static void database_fromscene_vectors(Render *re, Scene *scene, unsigned int lay, int timeoffset) -{ - Object *camera= RE_GetCamera(re); - float mat[4][4]; - - re->scene= scene; - re->lay= lay; - - /* XXX add test if dbase was filled already? */ - - re->memArena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "vector render db arena"); - re->totvlak=re->totvert=re->totstrand=re->totlamp=re->tothalo= 0; - re->i.totface=re->i.totvert=re->i.totstrand=re->i.totlamp=re->i.tothalo= 0; - re->lights.first= re->lights.last= NULL; - - /* in localview, lamps are using normal layers, objects only local bits */ - if (re->lay & 0xFF000000) - lay &= 0xFF000000; - - /* applies changes fully */ - scene->r.cfra += timeoffset; - BKE_scene_update_for_newframe(re->eval_ctx, re->main, re->scene, lay); - - /* if no camera, viewmat should have been set! */ - if (camera) { - RE_GetCameraModelMatrix(re, camera, mat); - normalize_m4(mat); - invert_m4(mat); - RE_SetView(re, mat); - } - - /* MAKE RENDER DATA */ - database_init_objects(re, lay, 0, 0, NULL, timeoffset); - - if (!re->test_break(re->tbh)) - project_renderdata(re, projectverto, (re->r.mode & R_PANORAMA) != 0, 0, 1); - - /* do this in end, particles for example need cfra */ - scene->r.cfra -= timeoffset; -} - -/* choose to use static, to prevent giving too many args to this call */ -static void speedvector_project(Render *re, float zco[2], const float co[3], const float ho[4]) -{ - static float pixelphix=0.0f, pixelphiy=0.0f, zmulx=0.0f, zmuly=0.0f; - static int pano= 0; - float div; - - /* initialize */ - if (re) { - pano= re->r.mode & R_PANORAMA; - - /* precalculate amount of radians 1 pixel rotates */ - if (pano) { - /* size of 1 pixel mapped to viewplane coords */ - float psize; - - psize = BLI_rctf_size_x(&re->viewplane) / (float)re->winx; - /* x angle of a pixel */ - pixelphix = atan(psize / re->clipsta); - - psize = BLI_rctf_size_y(&re->viewplane) / (float)re->winy; - /* y angle of a pixel */ - pixelphiy = atan(psize / re->clipsta); - } - zmulx= re->winx/2; - zmuly= re->winy/2; - - return; - } - - /* now map hocos to screenspace, uses very primitive clip still */ - if (ho[3]<0.1f) div= 10.0f; - else div= 1.0f/ho[3]; - - /* use cylinder projection */ - if (pano) { - float vec[3], ang; - /* angle between (0, 0, -1) and (co) */ - copy_v3_v3(vec, co); - - ang= saacos(-vec[2]/sqrtf(vec[0]*vec[0] + vec[2]*vec[2])); - if (vec[0]<0.0f) ang= -ang; - zco[0]= ang/pixelphix + zmulx; - - ang= 0.5f*(float)M_PI - saacos(vec[1] / len_v3(vec)); - zco[1]= ang/pixelphiy + zmuly; - - } - else { - zco[0]= zmulx*(1.0f+ho[0]*div); - zco[1]= zmuly*(1.0f+ho[1]*div); - } -} - -static void calculate_speedvector(const float vectors[2], int step, float winsq, float winroot, const float co[3], const float ho[4], float speed[4]) -{ - float zco[2], len; - - speedvector_project(NULL, zco, co, ho); - - zco[0]= vectors[0] - zco[0]; - zco[1]= vectors[1] - zco[1]; - - /* enable nice masks for hardly moving stuff or float inaccuracy */ - if (zco[0]<0.1f && zco[0]>-0.1f && zco[1]<0.1f && zco[1]>-0.1f ) { - zco[0]= 0.0f; - zco[1]= 0.0f; - } - - /* maximize speed for image width, otherwise it never looks good */ - len= zco[0]*zco[0] + zco[1]*zco[1]; - if (len > winsq) { - len= winroot/sqrtf(len); - zco[0]*= len; - zco[1]*= len; - } - - /* note; in main vecblur loop speedvec is negated again */ - if (step) { - speed[2]= -zco[0]; - speed[3]= -zco[1]; - } - else { - speed[0]= zco[0]; - speed[1]= zco[1]; - } -} - -static float *calculate_strandsurface_speedvectors(Render *re, ObjectInstanceRen *obi, StrandSurface *mesh) -{ - if (mesh->co && mesh->prevco && mesh->nextco) { - float winsq= (float)re->winx*(float)re->winy; /* int's can wrap on large images */ - float winroot= sqrtf(winsq); - float (*winspeed)[4]; - float ho[4], prevho[4], nextho[4], winmat[4][4], vec[2]; - int a; - - if (obi->flag & R_TRANSFORMED) - mul_m4_m4m4(winmat, re->winmat, obi->mat); - else - copy_m4_m4(winmat, re->winmat); - - winspeed= MEM_callocN(sizeof(float)*4*mesh->totvert, "StrandSurfWin"); - - for (a=0; a<mesh->totvert; a++) { - projectvert(mesh->co[a], winmat, ho); - - projectvert(mesh->prevco[a], winmat, prevho); - speedvector_project(NULL, vec, mesh->prevco[a], prevho); - calculate_speedvector(vec, 0, winsq, winroot, mesh->co[a], ho, winspeed[a]); - - projectvert(mesh->nextco[a], winmat, nextho); - speedvector_project(NULL, vec, mesh->nextco[a], nextho); - calculate_speedvector(vec, 1, winsq, winroot, mesh->co[a], ho, winspeed[a]); - } - - return (float *)winspeed; - } - - return NULL; -} - -static void calculate_speedvectors(Render *re, ObjectInstanceRen *obi, float *vectors, int step) -{ - ObjectRen *obr= obi->obr; - VertRen *ver= NULL; - StrandRen *strand= NULL; - StrandBuffer *strandbuf; - StrandSurface *mesh= NULL; - float *speed, (*winspeed)[4]=NULL, ho[4], winmat[4][4]; - float *co1, *co2, *co3, *co4, w[4]; - float winsq = (float)re->winx * (float)re->winy, winroot = sqrtf(winsq); /* int's can wrap on large images */ - int a, *face, *index; - - if (obi->flag & R_TRANSFORMED) - mul_m4_m4m4(winmat, re->winmat, obi->mat); - else - copy_m4_m4(winmat, re->winmat); - - if (obr->vertnodes) { - for (a=0; a<obr->totvert; a++, vectors+=2) { - if ((a & 255)==0) ver= obr->vertnodes[a>>8].vert; - else ver++; - - speed= RE_vertren_get_winspeed(obi, ver, 1); - projectvert(ver->co, winmat, ho); - calculate_speedvector(vectors, step, winsq, winroot, ver->co, ho, speed); - } - } - - if (obr->strandnodes) { - strandbuf= obr->strandbuf; - mesh= (strandbuf)? strandbuf->surface: NULL; - - /* compute speed vectors at surface vertices */ - if (mesh) - winspeed= (float(*)[4])calculate_strandsurface_speedvectors(re, obi, mesh); - - if (winspeed) { - for (a=0; a<obr->totstrand; a++, vectors+=2) { - if ((a & 255)==0) strand= obr->strandnodes[a>>8].strand; - else strand++; - - index= RE_strandren_get_face(obr, strand, 0); - if (index && *index < mesh->totface) { - speed= RE_strandren_get_winspeed(obi, strand, 1); - - /* interpolate speed vectors from strand surface */ - face= mesh->face[*index]; - - co1 = mesh->co[face[0]]; - co2 = mesh->co[face[1]]; - co3 = mesh->co[face[2]]; - - if (face[3]) { - co4 = mesh->co[face[3]]; - interp_weights_quad_v3(w, co1, co2, co3, co4, strand->vert->co); - } - else { - interp_weights_tri_v3(w, co1, co2, co3, strand->vert->co); - } - - zero_v4(speed); - madd_v4_v4fl(speed, winspeed[face[0]], w[0]); - madd_v4_v4fl(speed, winspeed[face[1]], w[1]); - madd_v4_v4fl(speed, winspeed[face[2]], w[2]); - if (face[3]) - madd_v4_v4fl(speed, winspeed[face[3]], w[3]); - } - } - - MEM_freeN(winspeed); - } - } -} - -static int load_fluidsimspeedvectors(Render *re, ObjectInstanceRen *obi, float *vectors, int step) -{ - ObjectRen *obr= obi->obr; - Object *fsob= obr->ob; - VertRen *ver= NULL; - float *speed, div, zco[2], avgvel[4] = {0.0, 0.0, 0.0, 0.0}; - float zmulx= re->winx/2, zmuly= re->winy/2, len; - float winsq = (float)re->winx * (float)re->winy, winroot= sqrtf(winsq); /* int's can wrap on large images */ - int a, j; - float hoco[4], ho[4], fsvec[4], camco[4]; - float mat[4][4], winmat[4][4]; - float imat[4][4]; - FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(fsob, eModifierType_Fluidsim); - FluidsimSettings *fss; - FluidVertexVelocity *velarray = NULL; - - /* only one step needed */ - if (step) return 1; - - if (fluidmd) - fss = fluidmd->fss; - else - return 0; - - copy_m4_m4(mat, re->viewmat); - invert_m4_m4(imat, mat); - - /* set first vertex OK */ - if (!fss->meshVelocities) return 0; - - if ( obr->totvert != fss->totvert) { - //fprintf(stderr, "load_fluidsimspeedvectors - modified fluidsim mesh, not using speed vectors (%d,%d)...\n", obr->totvert, fsob->fluidsimSettings->meshSurface->totvert); // DEBUG - return 0; - } - - velarray = fss->meshVelocities; - - if (obi->flag & R_TRANSFORMED) - mul_m4_m4m4(winmat, re->winmat, obi->mat); - else - copy_m4_m4(winmat, re->winmat); - - /* (bad) HACK calculate average velocity */ - /* better solution would be fixing getVelocityAt() in intern/elbeem/intern/solver_util.cpp - * so that also small drops/little water volumes return a velocity != 0. - * But I had no luck in fixing that function - DG */ - for (a=0; a<obr->totvert; a++) { - for (j=0;j<3;j++) avgvel[j] += velarray[a].vel[j]; - - } - for (j=0;j<3;j++) avgvel[j] /= (float)(obr->totvert); - - - for (a=0; a<obr->totvert; a++, vectors+=2) { - if ((a & 255)==0) - ver= obr->vertnodes[a>>8].vert; - else - ver++; - - /* get fluid velocity */ - fsvec[3] = 0.0f; - //fsvec[0] = fsvec[1] = fsvec[2] = fsvec[3] = 0.0; fsvec[2] = 2.0f; // NT fixed test - for (j=0;j<3;j++) fsvec[j] = velarray[a].vel[j]; - - /* (bad) HACK insert average velocity if none is there (see previous comment) */ - if ((fsvec[0] == 0.0f) && (fsvec[1] == 0.0f) && (fsvec[2] == 0.0f)) { - fsvec[0] = avgvel[0]; - fsvec[1] = avgvel[1]; - fsvec[2] = avgvel[2]; - } - - /* transform (=rotate) to cam space */ - camco[0] = dot_v3v3(imat[0], fsvec); - camco[1] = dot_v3v3(imat[1], fsvec); - camco[2] = dot_v3v3(imat[2], fsvec); - - /* get homogeneous coordinates */ - projectvert(camco, winmat, hoco); - projectvert(ver->co, winmat, ho); - - /* now map hocos to screenspace, uses very primitive clip still */ - /* use ho[3] of original vertex, xy component of vel. direction */ - if (ho[3]<0.1f) div= 10.0f; - else div= 1.0f/ho[3]; - zco[0]= zmulx*hoco[0]*div; - zco[1]= zmuly*hoco[1]*div; - - /* maximize speed as usual */ - len= zco[0]*zco[0] + zco[1]*zco[1]; - if (len > winsq) { - len= winroot/sqrtf(len); - zco[0]*= len; zco[1]*= len; - } - - speed= RE_vertren_get_winspeed(obi, ver, 1); - /* set both to the same value */ - speed[0]= speed[2]= zco[0]; - speed[1]= speed[3]= zco[1]; - //if (a < 20) fprintf(stderr,"speed %d %f,%f | camco %f,%f,%f | hoco %f,%f,%f,%f\n", a, speed[0], speed[1], camco[0],camco[1], camco[2], hoco[0],hoco[1], hoco[2],hoco[3]); // NT DEBUG - } - - return 1; -} - -/* makes copy per object of all vectors */ -/* result should be that we can free entire database */ -static void copy_dbase_object_vectors(Render *re, ListBase *lb) -{ - ObjectInstanceRen *obi, *obilb; - ObjectRen *obr; - VertRen *ver= NULL; - float *vec, ho[4], winmat[4][4]; - int a, totvector; - - for (obi= re->instancetable.first; obi; obi= obi->next) { - obr= obi->obr; - - obilb= MEM_mallocN(sizeof(ObjectInstanceRen), "ObInstanceVector"); - memcpy(obilb, obi, sizeof(ObjectInstanceRen)); - BLI_addtail(lb, obilb); - - obilb->totvector= totvector= obr->totvert; - - if (totvector > 0) { - vec= obilb->vectors= MEM_mallocN(2*sizeof(float)*totvector, "vector array"); - - if (obi->flag & R_TRANSFORMED) - mul_m4_m4m4(winmat, re->winmat, obi->mat); - else - copy_m4_m4(winmat, re->winmat); - - for (a=0; a<obr->totvert; a++, vec+=2) { - if ((a & 255)==0) ver= obr->vertnodes[a>>8].vert; - else ver++; - - projectvert(ver->co, winmat, ho); - speedvector_project(NULL, vec, ver->co, ho); - } - } - } -} - -static void free_dbase_object_vectors(ListBase *lb) -{ - ObjectInstanceRen *obi; - - for (obi= lb->first; obi; obi= obi->next) - if (obi->vectors) - MEM_freeN(obi->vectors); - BLI_freelistN(lb); -} - -void RE_Database_FromScene_Vectors(Render *re, Main *bmain, Scene *sce, unsigned int lay) -{ - ObjectInstanceRen *obi, *oldobi; - StrandSurface *mesh; - ListBase *table; - ListBase oldtable= {NULL, NULL}, newtable= {NULL, NULL}; - ListBase strandsurface; - int step; - - re->i.infostr = IFACE_("Calculating previous frame vectors"); - re->r.mode |= R_SPEED; - - speedvector_project(re, NULL, NULL, NULL); /* initializes projection code */ - - /* creates entire dbase */ - database_fromscene_vectors(re, sce, lay, -1); - - /* copy away vertex info */ - copy_dbase_object_vectors(re, &oldtable); - - /* free dbase and make the future one */ - strandsurface= re->strandsurface; - memset(&re->strandsurface, 0, sizeof(ListBase)); - re->i.convertdone = true; - RE_Database_Free(re); - re->strandsurface= strandsurface; - - if (!re->test_break(re->tbh)) { - /* creates entire dbase */ - re->i.infostr = IFACE_("Calculating next frame vectors"); - - database_fromscene_vectors(re, sce, lay, +1); - } - /* copy away vertex info */ - copy_dbase_object_vectors(re, &newtable); - - /* free dbase and make the real one */ - strandsurface= re->strandsurface; - memset(&re->strandsurface, 0, sizeof(ListBase)); - re->i.convertdone = true; - RE_Database_Free(re); - re->strandsurface= strandsurface; - - if (!re->test_break(re->tbh)) { - RE_Database_FromScene(re, bmain, sce, lay, 1); - RE_Database_Preprocess(re); - } - - if (!re->test_break(re->tbh)) { - int vectorlay= get_vector_renderlayers(re->scene); - - for (step= 0; step<2; step++) { - - if (step) - table= &newtable; - else - table= &oldtable; - - oldobi= table->first; - for (obi= re->instancetable.first; obi && oldobi; obi= obi->next) { - int ok= 1; - FluidsimModifierData *fluidmd; - - if (!(obi->lay & vectorlay)) - continue; - - obi->totvector= obi->obr->totvert; - - /* find matching object in old table */ - if (oldobi->ob!=obi->ob || oldobi->par!=obi->par || oldobi->index!=obi->index || oldobi->psysindex!=obi->psysindex) { - ok= 0; - for (oldobi= table->first; oldobi; oldobi= oldobi->next) - if (oldobi->ob==obi->ob && oldobi->par==obi->par && oldobi->index==obi->index && oldobi->psysindex==obi->psysindex) - break; - if (oldobi==NULL) - oldobi= table->first; - else - ok= 1; - } - if (ok==0) { - printf("speed table: missing object %s\n", obi->ob->id.name + 2); - continue; - } - - /* NT check for fluidsim special treatment */ - fluidmd = (FluidsimModifierData *)modifiers_findByType(obi->ob, eModifierType_Fluidsim); - if (fluidmd && fluidmd->fss && (fluidmd->fss->type & OB_FLUIDSIM_DOMAIN)) { - /* use preloaded per vertex simulation data, only does calculation for step=1 */ - /* NOTE/FIXME - velocities and meshes loaded unnecessarily often during the database_fromscene_vectors calls... */ - load_fluidsimspeedvectors(re, obi, oldobi->vectors, step); - } - else { - /* check if both have same amounts of vertices */ - if (obi->totvector==oldobi->totvector) - calculate_speedvectors(re, obi, oldobi->vectors, step); - else - printf("Warning: object %s has different amount of vertices or strands on other frame\n", obi->ob->id.name + 2); - } /* not fluidsim */ - - oldobi= oldobi->next; - } - } - } - - free_dbase_object_vectors(&oldtable); - free_dbase_object_vectors(&newtable); - - for (mesh=re->strandsurface.first; mesh; mesh=mesh->next) { - if (mesh->prevco) { - MEM_freeN(mesh->prevco); - mesh->prevco= NULL; - } - if (mesh->nextco) { - MEM_freeN(mesh->nextco); - mesh->nextco= NULL; - } - } - - re->i.infostr = NULL; - re->stats_draw(re->sdh, &re->i); -} - - -/* ------------------------------------------------------------------------- */ -/* Baking */ -/* ------------------------------------------------------------------------- */ - -/* setup for shaded view or bake, so only lamps and materials are initialized */ -/* type: - * RE_BAKE_LIGHT: for shaded view, only add lamps - * RE_BAKE_ALL: for baking, all lamps and objects - * RE_BAKE_NORMALS:for baking, no lamps and only selected objects - * RE_BAKE_AO: for baking, no lamps, but all objects - * RE_BAKE_TEXTURE:for baking, no lamps, only selected objects - * RE_BAKE_VERTEX_COLORS:for baking, no lamps, only selected objects - * RE_BAKE_DISPLACEMENT:for baking, no lamps, only selected objects - * RE_BAKE_DERIVATIVE:for baking, no lamps, only selected objects - * RE_BAKE_SHADOW: for baking, only shadows, but all objects - */ -void RE_Database_Baking(Render *re, Main *bmain, Scene *scene, unsigned int lay, const int type, Object *actob) -{ - Object *camera; - float mat[4][4]; - float amb[3]; - const short onlyselected= !ELEM(type, RE_BAKE_LIGHT, RE_BAKE_ALL, RE_BAKE_SHADOW, RE_BAKE_AO, RE_BAKE_VERTEX_COLORS); - const short nolamps= ELEM(type, RE_BAKE_NORMALS, RE_BAKE_TEXTURE, RE_BAKE_DISPLACEMENT, RE_BAKE_DERIVATIVE, RE_BAKE_VERTEX_COLORS); - - re->main= bmain; - re->scene= scene; - re->lay= lay; - - /* renderdata setup and exceptions */ - render_copy_renderdata(&re->r, &scene->r); - - RE_init_threadcount(re); - - re->flag |= R_BAKING; - re->excludeob= actob; - if (actob) - re->flag |= R_BAKE_TRACE; - - if (type==RE_BAKE_NORMALS && re->r.bake_normal_space==R_BAKE_SPACE_TANGENT) - re->flag |= R_NEED_TANGENT; - - if (type==RE_BAKE_VERTEX_COLORS) - re->flag |= R_NEED_VCOL; - - if (!actob && ELEM(type, RE_BAKE_LIGHT, RE_BAKE_NORMALS, RE_BAKE_TEXTURE, RE_BAKE_DISPLACEMENT, RE_BAKE_DERIVATIVE, RE_BAKE_VERTEX_COLORS)) { - re->r.mode &= ~R_SHADOW; - re->r.mode &= ~R_RAYTRACE; - } - - if (!actob && (type==RE_BAKE_SHADOW)) { - re->r.mode |= R_SHADOW; - } - - /* setup render stuff */ - re->memArena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "bake db arena"); - - re->totvlak=re->totvert=re->totstrand=re->totlamp=re->tothalo= 0; - re->lights.first= re->lights.last= NULL; - re->lampren.first= re->lampren.last= NULL; - - /* in localview, lamps are using normal layers, objects only local bits */ - if (re->lay & 0xFF000000) - lay &= 0xFF000000; - - camera= RE_GetCamera(re); - - /* if no camera, set unit */ - if (camera) { - normalize_m4_m4(mat, camera->obmat); - invert_m4(mat); - RE_SetView(re, mat); - } - else { - unit_m4(mat); - RE_SetView(re, mat); - } - copy_m3_m4(re->imat, re->viewinv); - - /* TODO: deep shadow maps + baking + strands */ - /* strands use the window matrix and view size, there is to correct - * window matrix but at least avoids malloc and crash loop [#27807] */ - unit_m4(re->winmat); - re->winx= re->winy= 256; - /* done setting dummy values */ - - init_render_world(re); /* do first, because of ambient. also requires re->osa set correct */ - if (re->r.mode & R_RAYTRACE) { - init_render_qmcsampler(re); - - if (re->wrld.mode & (WO_AMB_OCC|WO_ENV_LIGHT|WO_INDIRECT_LIGHT)) - if (re->wrld.ao_samp_method == WO_AOSAMP_CONSTANT) - init_ao_sphere(re, &re->wrld); - } - - /* still bad... doing all */ - init_render_textures(re); - - copy_v3_v3(amb, &re->wrld.ambr); - init_render_materials(re->main, re->r.mode, amb, true); - - set_node_shader_lamp_loop(shade_material_loop); - - /* MAKE RENDER DATA */ - database_init_objects(re, lay, nolamps, onlyselected, actob, 0); - - set_material_lightgroups(re); - - /* SHADOW BUFFER */ - if (type!=RE_BAKE_LIGHT) - if (re->r.mode & R_SHADOW) - threaded_makeshadowbufs(re); - - /* raytree */ - if (!re->test_break(re->tbh)) - if (re->r.mode & R_RAYTRACE) - makeraytree(re); - - /* point density texture */ - if (!re->test_break(re->tbh)) - make_pointdensities(re); - - /* voxel data texture */ - if (!re->test_break(re->tbh)) - make_voxeldata(re); - - /* occlusion */ - if ((re->wrld.mode & (WO_AMB_OCC|WO_ENV_LIGHT|WO_INDIRECT_LIGHT)) && !re->test_break(re->tbh)) - if (re->wrld.ao_gather_method == WO_AOGATHER_APPROX) - if (re->r.mode & R_SHADOW) - make_occ_tree(re); - - re->i.convertdone = true; -} diff --git a/source/blender/render/intern/source/envmap.c b/source/blender/render/intern/source/envmap.c deleted file mode 100644 index 85a6af92a28..00000000000 --- a/source/blender/render/intern/source/envmap.c +++ /dev/null @@ -1,822 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * Contributors: 2004/2005/2006 Blender Foundation, full recode - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/render/intern/source/envmap.c - * \ingroup render - */ - -#include <math.h> -#include <string.h> - -/* external modules: */ - -#include "BLI_math.h" -#include "BLI_blenlib.h" -#include "BLI_threads.h" -#include "BLI_utildefines.h" - -#include "BLT_translation.h" - -#include "IMB_imbuf_types.h" -#include "IMB_imbuf.h" /* for rectcpy */ - -#include "DNA_group_types.h" -#include "DNA_image_types.h" -#include "DNA_lamp_types.h" -#include "DNA_object_types.h" -#include "DNA_scene_types.h" -#include "DNA_texture_types.h" - -#include "BKE_main.h" -#include "BKE_image.h" /* BKE_imbuf_write */ -#include "BKE_texture.h" -#include "BKE_scene.h" - -/* this module */ -#include "render_types.h" -#include "envmap.h" -#include "renderdatabase.h" -#include "renderpipeline.h" -#include "texture.h" -#include "zbuf.h" -#include "render_result.h" - -/* ------------------------------------------------------------------------- */ - -static void envmap_split_ima(EnvMap *env, ImBuf *ibuf) -{ - int dx, part; - - /* after lock we test cube[1], if set the other thread has done it fine */ - BLI_thread_lock(LOCK_IMAGE); - if (env->cube[1] == NULL) { - - BKE_texture_envmap_free_data(env); - - dx = ibuf->y; - dx /= 2; - if (3 * dx == ibuf->x) { - env->type = ENV_CUBE; - env->ok = ENV_OSA; - } - else if (ibuf->x == ibuf->y) { - env->type = ENV_PLANE; - env->ok = ENV_OSA; - } - else { - printf("Incorrect envmap size\n"); - env->ok = 0; - env->ima->ok = 0; - } - - if (env->ok) { - if (env->type == ENV_CUBE) { - for (part = 0; part < 6; part++) { - env->cube[part] = IMB_allocImBuf(dx, dx, 24, IB_rect | IB_rectfloat); - } - IMB_float_from_rect(ibuf); - - IMB_rectcpy(env->cube[0], ibuf, - 0, 0, 0, 0, dx, dx); - IMB_rectcpy(env->cube[1], ibuf, - 0, 0, dx, 0, dx, dx); - IMB_rectcpy(env->cube[2], ibuf, - 0, 0, 2 * dx, 0, dx, dx); - IMB_rectcpy(env->cube[3], ibuf, - 0, 0, 0, dx, dx, dx); - IMB_rectcpy(env->cube[4], ibuf, - 0, 0, dx, dx, dx, dx); - IMB_rectcpy(env->cube[5], ibuf, - 0, 0, 2 * dx, dx, dx, dx); - - } - else { /* ENV_PLANE */ - env->cube[1] = IMB_dupImBuf(ibuf); - IMB_float_from_rect(env->cube[1]); - } - } - } - BLI_thread_unlock(LOCK_IMAGE); -} - -/* ------------------------------------------------------------------------- */ -/* ****************** RENDER ********************** */ - -/* copy current render */ -static Render *envmap_render_copy(Render *re, EnvMap *env) -{ - Render *envre; - float viewscale; - int cuberes; - - envre = RE_NewRender("Envmap"); - - env->lastsize = re->r.size; - cuberes = (env->cuberes * re->r.size) / 100; - cuberes &= 0xFFFC; - - /* this flag has R_ZTRA in it for example */ - envre->flag = re->flag; - - /* set up renderdata */ - render_copy_renderdata(&envre->r, &re->r); - envre->r.mode &= ~(R_BORDER | R_PANORAMA | R_ORTHO | R_MBLUR); - BLI_freelistN(&envre->r.layers); - BLI_freelistN(&envre->r.views); - envre->r.filtertype = 0; - envre->r.tilex = envre->r.xsch / 2; - envre->r.tiley = envre->r.ysch / 2; - envre->r.size = 100; - envre->r.yasp = envre->r.xasp = 1; - - RE_InitState(envre, NULL, &envre->r, NULL, cuberes, cuberes, NULL); - envre->main = re->main; - envre->scene = re->scene; /* unsure about this... */ - envre->scene_color_manage = re->scene_color_manage; - envre->lay = re->lay; - - /* view stuff in env render */ - viewscale = (env->type == ENV_PLANE) ? env->viewscale : 1.0f; - RE_SetEnvmapCamera(envre, env->object, viewscale, env->clipsta, env->clipend); - copy_m4_m4(envre->viewmat_orig, re->viewmat_orig); - - /* callbacks */ - envre->display_update = re->display_update; - envre->duh = re->duh; - envre->test_break = re->test_break; - envre->tbh = re->tbh; - envre->current_scene_update = re->current_scene_update; - envre->suh = re->suh; - - /* and for the evil stuff; copy the database... */ - envre->totvlak = re->totvlak; - envre->totvert = re->totvert; - envre->tothalo = re->tothalo; - envre->totstrand = re->totstrand; - envre->totlamp = re->totlamp; - envre->sortedhalos = re->sortedhalos; - envre->lights = re->lights; - envre->objecttable = re->objecttable; - envre->customdata_names = re->customdata_names; - envre->raytree = re->raytree; - envre->totinstance = re->totinstance; - envre->instancetable = re->instancetable; - envre->objectinstance = re->objectinstance; - envre->qmcsamplers = re->qmcsamplers; - - return envre; -} - -static void envmap_free_render_copy(Render *envre) -{ - - envre->totvlak = 0; - envre->totvert = 0; - envre->tothalo = 0; - envre->totstrand = 0; - envre->totlamp = 0; - envre->totinstance = 0; - envre->sortedhalos = NULL; - BLI_listbase_clear(&envre->lights); - BLI_listbase_clear(&envre->objecttable); - BLI_listbase_clear(&envre->customdata_names); - envre->raytree = NULL; - BLI_listbase_clear(&envre->instancetable); - envre->objectinstance = NULL; - envre->qmcsamplers = NULL; - - RE_FreeRender(envre); -} - -/* ------------------------------------------------------------------------- */ - -static void envmap_transmatrix(float mat[4][4], int part) -{ - float tmat[4][4], eul[3], rotmat[4][4]; - - eul[0] = eul[1] = eul[2] = 0.0; - - if (part == 0) { /* neg z */ - /* pass */ - } - else if (part == 1) { /* pos z */ - eul[0] = M_PI; - } - else if (part == 2) { /* pos y */ - eul[0] = M_PI / 2.0; - } - else if (part == 3) { /* neg x */ - eul[0] = M_PI / 2.0; - eul[2] = M_PI / 2.0; - } - else if (part == 4) { /* neg y */ - eul[0] = M_PI / 2.0; - eul[2] = M_PI; - } - else { /* pos x */ - eul[0] = M_PI / 2.0; - eul[2] = -M_PI / 2.0; - } - - copy_m4_m4(tmat, mat); - eul_to_mat4(rotmat, eul); - mul_m4_m4m4(mat, tmat, rotmat); -} -/* ------------------------------------------------------------------------- */ - -static void env_set_imats(Render *re) -{ - Base *base; - float mat[4][4]; - - base = re->scene->base.first; - while (base) { - mul_m4_m4m4(mat, re->viewmat, base->object->obmat); - invert_m4_m4(base->object->imat, mat); - - base = base->next; - } - -} - -/* ------------------------------------------------------------------------- */ - -void env_rotate_scene(Render *re, float mat[4][4], int do_rotate) -{ - ObjectRen *obr; - ObjectInstanceRen *obi; - LampRen *lar = NULL; - HaloRen *har = NULL; - float imat[3][3], mat_inverse[4][4], smat[4][4], tmat[4][4], cmat[3][3], tmpmat[4][4]; - int a; - - if (do_rotate == 0) { - invert_m4_m4(tmat, mat); - copy_m3_m4(imat, tmat); - - copy_m4_m4(mat_inverse, mat); - } - else { - copy_m4_m4(tmat, mat); - copy_m3_m4(imat, mat); - - invert_m4_m4(mat_inverse, tmat); - } - - for (obi = re->instancetable.first; obi; obi = obi->next) { - /* append or set matrix depending on dupli */ - if (obi->flag & R_DUPLI_TRANSFORMED) { - copy_m4_m4(tmpmat, obi->mat); - mul_m4_m4m4(obi->mat, tmat, tmpmat); - } - else if (do_rotate == 1) - copy_m4_m4(obi->mat, tmat); - else - unit_m4(obi->mat); - - copy_m3_m4(cmat, obi->mat); - invert_m3_m3(obi->nmat, cmat); - transpose_m3(obi->nmat); - - /* indicate the renderer has to use transform matrices */ - if (do_rotate == 0) - obi->flag &= ~R_ENV_TRANSFORMED; - else { - obi->flag |= R_ENV_TRANSFORMED; - copy_m4_m4(obi->imat, mat_inverse); - } - } - - - for (obr = re->objecttable.first; obr; obr = obr->next) { - for (a = 0; a < obr->tothalo; a++) { - if ((a & 255) == 0) har = obr->bloha[a >> 8]; - else har++; - - mul_m4_v3(tmat, har->co); - } - - /* imat_ren is needed for correct texture coordinates */ - mul_m4_m4m4(obr->ob->imat_ren, re->viewmat, obr->ob->obmat); - invert_m4(obr->ob->imat_ren); - } - - for (lar = re->lampren.first; lar; lar = lar->next) { - float lamp_imat[4][4]; - - /* copy from add_render_lamp */ - if (do_rotate == 1) - mul_m4_m4m4(tmpmat, re->viewmat, lar->lampmat); - else - mul_m4_m4m4(tmpmat, re->viewmat_orig, lar->lampmat); - - invert_m4_m4(lamp_imat, tmpmat); - copy_m3_m4(lar->mat, tmpmat); - copy_m3_m4(lar->imat, lamp_imat); - - lar->vec[0]= -tmpmat[2][0]; - lar->vec[1]= -tmpmat[2][1]; - lar->vec[2]= -tmpmat[2][2]; - normalize_v3(lar->vec); - lar->co[0]= tmpmat[3][0]; - lar->co[1]= tmpmat[3][1]; - lar->co[2]= tmpmat[3][2]; - - if (lar->type == LA_AREA) { - area_lamp_vectors(lar); - } - else if (lar->type == LA_SPOT) { - normalize_v3(lar->imat[0]); - normalize_v3(lar->imat[1]); - normalize_v3(lar->imat[2]); - - lar->sh_invcampos[0] = -lar->co[0]; - lar->sh_invcampos[1] = -lar->co[1]; - lar->sh_invcampos[2] = -lar->co[2]; - mul_m3_v3(lar->imat, lar->sh_invcampos); - lar->sh_invcampos[2] *= lar->sh_zfac; - - if (lar->shb) { - if (do_rotate == 1) { - mul_m4_m4m4(smat, lar->shb->viewmat, mat_inverse); - mul_m4_m4m4(lar->shb->persmat, lar->shb->winmat, smat); - } - else mul_m4_m4m4(lar->shb->persmat, lar->shb->winmat, lar->shb->viewmat); - } - } - } - - if (do_rotate) { - init_render_world(re); - env_set_imats(re); - } -} - -/* ------------------------------------------------------------------------- */ - -static void env_layerflags(Render *re, unsigned int notlay) -{ - ObjectRen *obr; - VlakRen *vlr = NULL; - int a; - - /* invert notlay, so if face is in multiple layers it will still be visible, - * unless all 'notlay' bits match the face bits. - * face: 0110 - * not: 0100 - * ~not: 1011 - * now (face & ~not) is true - */ - - notlay = ~notlay; - - for (obr = re->objecttable.first; obr; obr = obr->next) { - if ((obr->lay & notlay) == 0) { - for (a = 0; a < obr->totvlak; a++) { - if ((a & 255) == 0) vlr = obr->vlaknodes[a >> 8].vlak; - else vlr++; - - vlr->flag |= R_HIDDEN; - } - } - } -} - -static void env_hideobject(Render *re, Object *ob) -{ - ObjectRen *obr; - VlakRen *vlr = NULL; - int a; - - for (obr = re->objecttable.first; obr; obr = obr->next) { - for (a = 0; a < obr->totvlak; a++) { - if ((a & 255) == 0) vlr = obr->vlaknodes[a >> 8].vlak; - else vlr++; - - if (obr->ob == ob) - vlr->flag |= R_HIDDEN; - } - } -} - -static void env_showobjects(Render *re) -{ - ObjectRen *obr; - VlakRen *vlr = NULL; - int a; - - for (obr = re->objecttable.first; obr; obr = obr->next) { - for (a = 0; a < obr->totvlak; a++) { - if ((a & 255) == 0) vlr = obr->vlaknodes[a >> 8].vlak; - else vlr++; - - vlr->flag &= ~R_HIDDEN; - } - } -} - -/* ------------------------------------------------------------------------- */ - -static void render_envmap(Render *re, EnvMap *env) -{ - /* only the cubemap and planar map is implemented */ - Render *envre; - ImBuf *ibuf; - float orthmat[4][4]; - float oldviewinv[4][4], mat[4][4], tmat[4][4]; - short part; - - /* need a recalc: ortho-render has no correct viewinv */ - invert_m4_m4(oldviewinv, re->viewmat); - - envre = envmap_render_copy(re, env); - - /* precalc orthmat for object */ - copy_m4_m4(orthmat, env->object->obmat); - normalize_m4(orthmat); - - /* need imat later for texture imat */ - mul_m4_m4m4(mat, re->viewmat, orthmat); - invert_m4_m4(tmat, mat); - copy_m3_m4(env->obimat, tmat); - - for (part = 0; part < 6; part++) { - if (env->type == ENV_PLANE && part != 1) - continue; - - re->display_clear(re->dch, envre->result); - - copy_m4_m4(tmat, orthmat); - envmap_transmatrix(tmat, part); - invert_m4_m4(mat, tmat); - /* mat now is the camera 'viewmat' */ - - copy_m4_m4(envre->viewmat, mat); - copy_m4_m4(envre->viewinv, tmat); - - /* we have to correct for the already rotated vertexcoords */ - mul_m4_m4m4(tmat, envre->viewmat, oldviewinv); - invert_m4_m4(env->imat, tmat); - - env_rotate_scene(envre, tmat, 1); - project_renderdata(envre, projectverto, 0, 0, 1); - env_layerflags(envre, env->notlay); - env_hideobject(envre, env->object); - - if (re->test_break(re->tbh) == 0) { - RE_TileProcessor(envre); - } - - /* rotate back */ - env_showobjects(envre); - env_rotate_scene(envre, tmat, 0); - - if (re->test_break(re->tbh) == 0) { - int y; - float *alpha; - float *rect; - - if (envre->result->do_exr_tile) { - BLI_rw_mutex_lock(&envre->resultmutex, THREAD_LOCK_WRITE); - render_result_exr_file_end(envre); - BLI_rw_mutex_unlock(&envre->resultmutex); - } - - RenderLayer *rl = envre->result->layers.first; - - /* envmap is rendered independently of multiview */ - rect = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, ""); - ibuf = IMB_allocImBuf(envre->rectx, envre->recty, 24, IB_rect | IB_rectfloat); - memcpy(ibuf->rect_float, rect, ibuf->channels * ibuf->x * ibuf->y * sizeof(float)); - - /* envmap renders without alpha */ - alpha = ibuf->rect_float + 3; - for (y = ibuf->x * ibuf->y - 1; y >= 0; y--, alpha += 4) - *alpha = 1.0; - - env->cube[part] = ibuf; - } - - if (re->test_break(re->tbh)) break; - - } - - if (re->test_break(re->tbh)) BKE_texture_envmap_free_data(env); - else { - if (envre->r.mode & R_OSA) env->ok = ENV_OSA; - else env->ok = ENV_NORMAL; - env->lastframe = re->scene->r.cfra; - } - - /* restore */ - envmap_free_render_copy(envre); - env_set_imats(re); - -} - -/* ------------------------------------------------------------------------- */ - -void make_envmaps(Render *re) -{ - Tex *tex; - bool do_init = false; - int depth = 0, trace; - - if (!(re->r.mode & R_ENVMAP)) return; - - /* we don't raytrace, disabling the flag will cause ray_transp render solid */ - trace = (re->r.mode & R_RAYTRACE); - re->r.mode &= ~R_RAYTRACE; - - re->i.infostr = IFACE_("Creating Environment maps"); - re->stats_draw(re->sdh, &re->i); - - /* 5 = hardcoded max recursion level */ - while (depth < 5) { - tex = re->main->tex.first; - while (tex) { - if (tex->id.us && tex->type == TEX_ENVMAP) { - if (tex->env && tex->env->object) { - EnvMap *env = tex->env; - - if (env->object->lay & re->lay) { - if (env->stype == ENV_LOAD) { - float orthmat[4][4], mat[4][4], tmat[4][4]; - - /* precalc orthmat for object */ - copy_m4_m4(orthmat, env->object->obmat); - normalize_m4(orthmat); - - /* need imat later for texture imat */ - mul_m4_m4m4(mat, re->viewmat, orthmat); - invert_m4_m4(tmat, mat); - copy_m3_m4(env->obimat, tmat); - } - else { - - /* decide if to render an envmap (again) */ - if (env->depth >= depth) { - - /* set 'recalc' to make sure it does an entire loop of recalcs */ - - if (env->ok) { - /* free when OSA, and old one isn't OSA */ - if ((re->r.mode & R_OSA) && env->ok == ENV_NORMAL) - BKE_texture_envmap_free_data(env); - /* free when size larger */ - else if (env->lastsize < re->r.size) - BKE_texture_envmap_free_data(env); - /* free when env is in recalcmode */ - else if (env->recalc) - BKE_texture_envmap_free_data(env); - } - - if (env->ok == 0 && depth == 0) env->recalc = 1; - - if (env->ok == 0) { - do_init = true; - render_envmap(re, env); - - if (depth == env->depth) env->recalc = 0; - } - } - } - } - } - } - tex = tex->id.next; - } - depth++; - } - - if (do_init) { - re->display_init(re->dih, re->result); - re->display_clear(re->dch, re->result); - // re->flag |= R_REDRAW_PRV; - } - /* restore */ - re->r.mode |= trace; - -} - -/* ------------------------------------------------------------------------- */ - -static int envcube_isect(EnvMap *env, const float vec[3], float answ[2]) -{ - float lambda; - int face; - - if (env->type == ENV_PLANE) { - face = 1; - - lambda = 1.0f / vec[2]; - answ[0] = env->viewscale * lambda * vec[0]; - answ[1] = -env->viewscale * lambda * vec[1]; - } - else { - /* which face */ - if (vec[2] <= -fabsf(vec[0]) && vec[2] <= -fabsf(vec[1]) ) { - face = 0; - lambda = -1.0f / vec[2]; - answ[0] = lambda * vec[0]; - answ[1] = lambda * vec[1]; - } - else if (vec[2] >= fabsf(vec[0]) && vec[2] >= fabsf(vec[1])) { - face = 1; - lambda = 1.0f / vec[2]; - answ[0] = lambda * vec[0]; - answ[1] = -lambda * vec[1]; - } - else if (vec[1] >= fabsf(vec[0])) { - face = 2; - lambda = 1.0f / vec[1]; - answ[0] = lambda * vec[0]; - answ[1] = lambda * vec[2]; - } - else if (vec[0] <= -fabsf(vec[1])) { - face = 3; - lambda = -1.0f / vec[0]; - answ[0] = lambda * vec[1]; - answ[1] = lambda * vec[2]; - } - else if (vec[1] <= -fabsf(vec[0])) { - face = 4; - lambda = -1.0f / vec[1]; - answ[0] = -lambda * vec[0]; - answ[1] = lambda * vec[2]; - } - else { - face = 5; - lambda = 1.0f / vec[0]; - answ[0] = -lambda * vec[1]; - answ[1] = lambda * vec[2]; - } - } - - answ[0] = 0.5f + 0.5f * answ[0]; - answ[1] = 0.5f + 0.5f * answ[1]; - return face; -} - -/* ------------------------------------------------------------------------- */ - -static void set_dxtdyt(float r_dxt[3], float r_dyt[3], const float dxt[3], const float dyt[3], int face) -{ - if (face == 2 || face == 4) { - r_dxt[0] = dxt[0]; - r_dyt[0] = dyt[0]; - r_dxt[1] = dxt[2]; - r_dyt[1] = dyt[2]; - } - else if (face == 3 || face == 5) { - r_dxt[0] = dxt[1]; - r_dxt[1] = dxt[2]; - r_dyt[0] = dyt[1]; - r_dyt[1] = dyt[2]; - } - else { - r_dxt[0] = dxt[0]; - r_dyt[0] = dyt[0]; - r_dxt[1] = dxt[1]; - r_dyt[1] = dyt[1]; - } -} - -/* ------------------------------------------------------------------------- */ - -int envmaptex(Tex *tex, const float texvec[3], float dxt[3], float dyt[3], int osatex, TexResult *texres, struct ImagePool *pool, const bool skip_load_image) -{ - extern Render R; /* only in this call */ - /* texvec should be the already reflected normal */ - EnvMap *env; - ImBuf *ibuf; - float fac, vec[3], sco[3], dxts[3], dyts[3]; - int face, face1; - - env = tex->env; - if (env == NULL || (env->stype != ENV_LOAD && env->object == NULL)) { - texres->tin = 0.0; - return 0; - } - - if (env->stype == ENV_LOAD) { - env->ima = tex->ima; - if (env->ima && env->ima->ok) { - if (env->cube[1] == NULL) { - ImBuf *ibuf_ima = BKE_image_pool_acquire_ibuf(env->ima, NULL, pool); - if (ibuf_ima) - envmap_split_ima(env, ibuf_ima); - else - env->ok = 0; - - if (env->type == ENV_PLANE) - tex->extend = TEX_EXTEND; - - BKE_image_pool_release_ibuf(env->ima, ibuf_ima, pool); - } - } - } - - if (env->ok == 0) { - texres->tin = 0.0; - return 0; - } - - /* rotate to envmap space, if object is set */ - copy_v3_v3(vec, texvec); - if (env->object) { - mul_m3_v3(env->obimat, vec); - if (osatex) { - mul_m3_v3(env->obimat, dxt); - mul_m3_v3(env->obimat, dyt); - } - } - else { - if (!BKE_scene_use_world_space_shading(R.scene)) { - // texvec is in view space - mul_mat3_m4_v3(R.viewinv, vec); - if (osatex) { - mul_mat3_m4_v3(R.viewinv, dxt); - mul_mat3_m4_v3(R.viewinv, dyt); - } - } - } - - face = envcube_isect(env, vec, sco); - ibuf = env->cube[face]; - - if (osatex) { - set_dxtdyt(dxts, dyts, dxt, dyt, face); - imagewraposa(tex, NULL, ibuf, sco, dxts, dyts, texres, pool, skip_load_image); - - /* edges? */ - - if (texres->ta < 1.0f) { - TexResult texr1, texr2; - - texr1.nor = texr2.nor = NULL; - texr1.talpha = texr2.talpha = texres->talpha; /* boxclip expects this initialized */ - - add_v3_v3(vec, dxt); - face1 = envcube_isect(env, vec, sco); - sub_v3_v3(vec, dxt); - - if (face != face1) { - ibuf = env->cube[face1]; - set_dxtdyt(dxts, dyts, dxt, dyt, face1); - imagewraposa(tex, NULL, ibuf, sco, dxts, dyts, &texr1, pool, skip_load_image); - } - else texr1.tr = texr1.tg = texr1.tb = texr1.ta = 0.0; - - /* here was the nasty bug! results were not zero-ed. FPE! */ - - add_v3_v3(vec, dyt); - face1 = envcube_isect(env, vec, sco); - sub_v3_v3(vec, dyt); - - if (face != face1) { - ibuf = env->cube[face1]; - set_dxtdyt(dxts, dyts, dxt, dyt, face1); - imagewraposa(tex, NULL, ibuf, sco, dxts, dyts, &texr2, pool, skip_load_image); - } - else texr2.tr = texr2.tg = texr2.tb = texr2.ta = 0.0; - - fac = (texres->ta + texr1.ta + texr2.ta); - if (fac != 0.0f) { - fac = 1.0f / fac; - - texres->tr = fac * (texres->ta * texres->tr + texr1.ta * texr1.tr + texr2.ta * texr2.tr); - texres->tg = fac * (texres->ta * texres->tg + texr1.ta * texr1.tg + texr2.ta * texr2.tg); - texres->tb = fac * (texres->ta * texres->tb + texr1.ta * texr1.tb + texr2.ta * texr2.tb); - } - texres->ta = 1.0; - } - } - else { - imagewrap(tex, NULL, ibuf, sco, texres, pool, skip_load_image); - } - - return 1; -} diff --git a/source/blender/render/intern/source/occlusion.c b/source/blender/render/intern/source/occlusion.c deleted file mode 100644 index 8aa90a390b3..00000000000 --- a/source/blender/render/intern/source/occlusion.c +++ /dev/null @@ -1,1533 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2008 Blender Foundation. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): Brecht Van Lommel. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/render/intern/source/occlusion.c - * \ingroup render - */ - -#include <math.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "MEM_guardedalloc.h" - -#include "DNA_material_types.h" - -#include "BLI_math.h" -#include "BLI_memarena.h" -#include "BLI_threads.h" -#include "BLI_utildefines.h" - -#include "BLT_translation.h" - -#include "BKE_node.h" -#include "BKE_scene.h" - - -#include "RE_shader_ext.h" - -/* local includes */ -#include "occlusion.h" -#include "render_types.h" -#include "rendercore.h" -#include "renderdatabase.h" -#include "shading.h" - -/* ------------------------- Declarations --------------------------- */ - -#define INVPI ((float)M_1_PI) -#define TOTCHILD 8 -#define CACHE_STEP 3 - -typedef struct OcclusionCacheSample { - float co[3], n[3], ao[3], env[3], indirect[3], intensity, dist2; - int x, y, filled; -} OcclusionCacheSample; - -typedef struct OcclusionCache { - OcclusionCacheSample *sample; - int x, y, w, h, step; -} OcclusionCache; - -typedef struct OccFace { - int obi; - int facenr; -} OccFace; - -typedef struct OccNode { - float co[3], area; - float sh[9], dco; - float occlusion, rad[3]; - int childflag; - union { - //OccFace face; - int face; - struct OccNode *node; - } child[TOTCHILD]; -} OccNode; - -typedef struct OcclusionTree { - MemArena *arena; - - float (*co)[3]; /* temporary during build */ - - OccFace *face; /* instance and face indices */ - float *occlusion; /* occlusion for faces */ - float (*rad)[3]; /* radiance for faces */ - - OccNode *root; - - OccNode **stack[BLENDER_MAX_THREADS]; - int maxdepth; - - int totface; - - float error; - float distfac; - - int dothreadedbuild; - int totbuildthread; - int doindirect; - - OcclusionCache *cache; - - int num_threads; -} OcclusionTree; - -typedef struct OcclusionThread { - Render *re; - StrandSurface *mesh; - float (*faceao)[3]; - float (*faceenv)[3]; - float (*faceindirect)[3]; - int begin, end; - int thread; -} OcclusionThread; - -typedef struct OcclusionBuildThread { - OcclusionTree *tree; - int begin, end, depth; - OccNode *node; -} OcclusionBuildThread; - -/* ------------------------- Shading --------------------------- */ - -extern Render R; /* meh */ - -static void occ_shade(ShadeSample *ssamp, ObjectInstanceRen *obi, VlakRen *vlr, float *rad) -{ - ShadeInput *shi = ssamp->shi; - ShadeResult *shr = ssamp->shr; - float l, u, v, *v1, *v2, *v3; - - /* init */ - if (vlr->v4) { - shi->u = u = 0.5f; - shi->v = v = 0.5f; - } - else { - shi->u = u = 1.0f / 3.0f; - shi->v = v = 1.0f / 3.0f; - } - - /* setup render coordinates */ - v1 = vlr->v1->co; - v2 = vlr->v2->co; - v3 = vlr->v3->co; - - /* renderco */ - l = 1.0f - u - v; - - shi->co[0] = l * v3[0] + u * v1[0] + v * v2[0]; - shi->co[1] = l * v3[1] + u * v1[1] + v * v2[1]; - shi->co[2] = l * v3[2] + u * v1[2] + v * v2[2]; - - shade_input_set_triangle_i(shi, obi, vlr, 0, 1, 2); - - /* set up view vector */ - copy_v3_v3(shi->view, shi->co); - normalize_v3(shi->view); - - /* cache for shadow */ - shi->samplenr++; - - shi->xs = 0; /* TODO */ - shi->ys = 0; - - shade_input_set_normals(shi); - - /* no normal flip */ - if (shi->flippednor) - shade_input_flip_normals(shi); - - madd_v3_v3fl(shi->co, shi->facenor, -0.0001f); /* ugly.. */ - - /* not a pretty solution, but fixes common cases */ - if (shi->obr->ob && shi->obr->ob->transflag & OB_NEG_SCALE) { - negate_v3(shi->vn); - negate_v3(shi->vno); - negate_v3(shi->nmapnorm); - } - - /* init material vars */ - shade_input_init_material(shi); - - /* render */ - shade_input_set_shade_texco(shi); - - if (shi->mat->nodetree && shi->mat->use_nodes) { - ntreeShaderExecTree(shi->mat->nodetree, shi, shr); - shi->mat = vlr->mat; /* shi->mat is being set in nodetree */ - } - else { - shade_material_loop(shi, shr); - } - - copy_v3_v3(rad, shr->combined); -} - -static void occ_build_shade(Render *re, OcclusionTree *tree) -{ - ShadeSample ssamp; - ObjectInstanceRen *obi; - VlakRen *vlr; - int a; - - R = *re; - - /* setup shade sample with correct passes */ - memset(&ssamp, 0, sizeof(ShadeSample)); - ssamp.shi[0].lay = re->lay; - ssamp.shi[0].passflag = SCE_PASS_DIFFUSE | SCE_PASS_RGBA; - ssamp.shi[0].combinedflag = ~(SCE_PASS_SPEC); - ssamp.tot = 1; - - for (a = 0; a < tree->totface; a++) { - obi = &R.objectinstance[tree->face[a].obi]; - vlr = RE_findOrAddVlak(obi->obr, tree->face[a].facenr); - - occ_shade(&ssamp, obi, vlr, tree->rad[a]); - - if (re->test_break(re->tbh)) - break; - } -} - -/* ------------------------- Spherical Harmonics --------------------------- */ - -/* Use 2nd order SH => 9 coefficients, stored in this order: - * 0 = (0,0), - * 1 = (1,-1), 2 = (1,0), 3 = (1,1), - * 4 = (2,-2), 5 = (2,-1), 6 = (2,0), 7 = (2,1), 8 = (2,2) */ - -static void sh_copy(float *shresult, float *sh) -{ - memcpy(shresult, sh, sizeof(float) * 9); -} - -static void sh_mul(float *sh, float f) -{ - int i; - - for (i = 0; i < 9; i++) - sh[i] *= f; -} - -static void sh_add(float *shresult, float *sh1, float *sh2) -{ - int i; - - for (i = 0; i < 9; i++) - shresult[i] = sh1[i] + sh2[i]; -} - -static void sh_from_disc(float *n, float area, float *shresult) -{ - /* See formula (3) in: - * "An Efficient Representation for Irradiance Environment Maps" */ - float sh[9], x, y, z; - - x = n[0]; - y = n[1]; - z = n[2]; - - sh[0] = 0.282095f; - - sh[1] = 0.488603f * y; - sh[2] = 0.488603f * z; - sh[3] = 0.488603f * x; - - sh[4] = 1.092548f * x * y; - sh[5] = 1.092548f * y * z; - sh[6] = 0.315392f * (3.0f * z * z - 1.0f); - sh[7] = 1.092548f * x * z; - sh[8] = 0.546274f * (x * x - y * y); - - sh_mul(sh, area); - sh_copy(shresult, sh); -} - -static float sh_eval(float *sh, float *v) -{ - /* See formula (13) in: - * "An Efficient Representation for Irradiance Environment Maps" */ - static const float c1 = 0.429043f, c2 = 0.511664f, c3 = 0.743125f; - static const float c4 = 0.886227f, c5 = 0.247708f; - float x, y, z, sum; - - x = v[0]; - y = v[1]; - z = v[2]; - - sum = c1 * sh[8] * (x * x - y * y); - sum += c3 * sh[6] * z * z; - sum += c4 * sh[0]; - sum += -c5 * sh[6]; - sum += 2.0f * c1 * (sh[4] * x * y + sh[7] * x * z + sh[5] * y * z); - sum += 2.0f * c2 * (sh[3] * x + sh[1] * y + sh[2] * z); - - return sum; -} - -/* ------------------------------ Building --------------------------------- */ - -static void occ_face(const OccFace *face, float co[3], float normal[3], float *area) -{ - ObjectInstanceRen *obi; - VlakRen *vlr; - float v1[3], v2[3], v3[3], v4[3]; - - obi = &R.objectinstance[face->obi]; - vlr = RE_findOrAddVlak(obi->obr, face->facenr); - - if (co) { - if (vlr->v4) - mid_v3_v3v3(co, vlr->v1->co, vlr->v3->co); - else - mid_v3_v3v3v3(co, vlr->v1->co, vlr->v2->co, vlr->v3->co); - - if (obi->flag & R_TRANSFORMED) - mul_m4_v3(obi->mat, co); - } - - if (normal) { - normal[0] = -vlr->n[0]; - normal[1] = -vlr->n[1]; - normal[2] = -vlr->n[2]; - - if (obi->flag & R_TRANSFORMED) - mul_m3_v3(obi->nmat, normal); - } - - if (area) { - copy_v3_v3(v1, vlr->v1->co); - copy_v3_v3(v2, vlr->v2->co); - copy_v3_v3(v3, vlr->v3->co); - if (vlr->v4) copy_v3_v3(v4, vlr->v4->co); - - if (obi->flag & R_TRANSFORMED) { - mul_m4_v3(obi->mat, v1); - mul_m4_v3(obi->mat, v2); - mul_m4_v3(obi->mat, v3); - if (vlr->v4) mul_m4_v3(obi->mat, v4); - } - - /* todo: correct area for instances */ - if (vlr->v4) - *area = area_quad_v3(v1, v2, v3, v4); - else - *area = area_tri_v3(v1, v2, v3); - } -} - -static void occ_sum_occlusion(OcclusionTree *tree, OccNode *node) -{ - OccNode *child; - float occ, area, totarea, rad[3]; - int a, b, indirect = tree->doindirect; - - occ = 0.0f; - totarea = 0.0f; - if (indirect) zero_v3(rad); - - for (b = 0; b < TOTCHILD; b++) { - if (node->childflag & (1 << b)) { - a = node->child[b].face; - occ_face(&tree->face[a], NULL, NULL, &area); - occ += area * tree->occlusion[a]; - if (indirect) madd_v3_v3fl(rad, tree->rad[a], area); - totarea += area; - } - else if (node->child[b].node) { - child = node->child[b].node; - occ_sum_occlusion(tree, child); - - occ += child->area * child->occlusion; - if (indirect) madd_v3_v3fl(rad, child->rad, child->area); - totarea += child->area; - } - } - - if (totarea != 0.0f) { - occ /= totarea; - if (indirect) mul_v3_fl(rad, 1.0f / totarea); - } - - node->occlusion = occ; - if (indirect) copy_v3_v3(node->rad, rad); -} - -static int occ_find_bbox_axis(OcclusionTree *tree, int begin, int end, float *min, float *max) -{ - float len, maxlen = -1.0f; - int a, axis = 0; - - INIT_MINMAX(min, max); - - for (a = begin; a < end; a++) { - minmax_v3v3_v3(min, max, tree->co[a]); - } - - for (a = 0; a < 3; a++) { - len = max[a] - min[a]; - - if (len > maxlen) { - maxlen = len; - axis = a; - } - } - - return axis; -} - -static void occ_node_from_face(OccFace *face, OccNode *node) -{ - float n[3]; - - occ_face(face, node->co, n, &node->area); - node->dco = 0.0f; - sh_from_disc(n, node->area, node->sh); -} - -static void occ_build_dco(OcclusionTree *tree, OccNode *node, const float co[3], float *dco) -{ - int b; - for (b = 0; b < TOTCHILD; b++) { - float dist, d[3], nco[3]; - - if (node->childflag & (1 << b)) { - occ_face(tree->face + node->child[b].face, nco, NULL, NULL); - } - else if (node->child[b].node) { - OccNode *child = node->child[b].node; - occ_build_dco(tree, child, co, dco); - copy_v3_v3(nco, child->co); - } - else { - continue; - } - - sub_v3_v3v3(d, nco, co); - dist = dot_v3v3(d, d); - if (dist > *dco) - *dco = dist; - } -} - -static void occ_build_split(OcclusionTree *tree, int begin, int end, int *split) -{ - float min[3], max[3], mid; - int axis, a, enda; - - /* split in middle of boundbox. this seems faster than median split - * on complex scenes, possibly since it avoids two distant faces to - * be in the same node better? */ - axis = occ_find_bbox_axis(tree, begin, end, min, max); - mid = 0.5f * (min[axis] + max[axis]); - - a = begin; - enda = end; - while (a < enda) { - if (tree->co[a][axis] > mid) { - enda--; - SWAP(OccFace, tree->face[a], tree->face[enda]); - swap_v3_v3(tree->co[a], tree->co[enda]); - } - else - a++; - } - - *split = enda; -} - -static void occ_build_8_split(OcclusionTree *tree, int begin, int end, int *offset, int *count) -{ - /* split faces into eight groups */ - int b, splitx, splity[2], splitz[4]; - - occ_build_split(tree, begin, end, &splitx); - - /* force split if none found, to deal with degenerate geometry */ - if (splitx == begin || splitx == end) - splitx = (begin + end) / 2; - - occ_build_split(tree, begin, splitx, &splity[0]); - occ_build_split(tree, splitx, end, &splity[1]); - - occ_build_split(tree, begin, splity[0], &splitz[0]); - occ_build_split(tree, splity[0], splitx, &splitz[1]); - occ_build_split(tree, splitx, splity[1], &splitz[2]); - occ_build_split(tree, splity[1], end, &splitz[3]); - - offset[0] = begin; - offset[1] = splitz[0]; - offset[2] = splity[0]; - offset[3] = splitz[1]; - offset[4] = splitx; - offset[5] = splitz[2]; - offset[6] = splity[1]; - offset[7] = splitz[3]; - - for (b = 0; b < 7; b++) - count[b] = offset[b + 1] - offset[b]; - count[7] = end - offset[7]; -} - -static void occ_build_recursive(OcclusionTree *tree, OccNode *node, int begin, int end, int depth); - -static void *exec_occ_build(void *data) -{ - OcclusionBuildThread *othread = (OcclusionBuildThread *)data; - - occ_build_recursive(othread->tree, othread->node, othread->begin, othread->end, othread->depth); - - return NULL; -} - -static void occ_build_recursive(OcclusionTree *tree, OccNode *node, int begin, int end, int depth) -{ - ListBase threads; - OcclusionBuildThread othreads[BLENDER_MAX_THREADS]; - OccNode *child, tmpnode; - /* OccFace *face; */ - int a, b, totthread = 0, offset[TOTCHILD], count[TOTCHILD]; - - /* add a new node */ - node->occlusion = 1.0f; - - /* leaf node with only children */ - if (end - begin <= TOTCHILD) { - for (a = begin, b = 0; a < end; a++, b++) { - /* face= &tree->face[a]; */ - node->child[b].face = a; - node->childflag |= (1 << b); - } - } - else { - /* order faces */ - occ_build_8_split(tree, begin, end, offset, count); - - if (depth == 1 && tree->dothreadedbuild) - BLI_threadpool_init(&threads, exec_occ_build, tree->totbuildthread); - - for (b = 0; b < TOTCHILD; b++) { - if (count[b] == 0) { - node->child[b].node = NULL; - } - else if (count[b] == 1) { - /* face= &tree->face[offset[b]]; */ - node->child[b].face = offset[b]; - node->childflag |= (1 << b); - } - else { - if (tree->dothreadedbuild) - BLI_thread_lock(LOCK_CUSTOM1); - - child = BLI_memarena_alloc(tree->arena, sizeof(OccNode)); - node->child[b].node = child; - - /* keep track of maximum depth for stack */ - if (depth >= tree->maxdepth) - tree->maxdepth = depth + 1; - - if (tree->dothreadedbuild) - BLI_thread_unlock(LOCK_CUSTOM1); - - if (depth == 1 && tree->dothreadedbuild) { - othreads[totthread].tree = tree; - othreads[totthread].node = child; - othreads[totthread].begin = offset[b]; - othreads[totthread].end = offset[b] + count[b]; - othreads[totthread].depth = depth + 1; - BLI_threadpool_insert(&threads, &othreads[totthread]); - totthread++; - } - else - occ_build_recursive(tree, child, offset[b], offset[b] + count[b], depth + 1); - } - } - - if (depth == 1 && tree->dothreadedbuild) - BLI_threadpool_end(&threads); - } - - /* combine area, position and sh */ - for (b = 0; b < TOTCHILD; b++) { - if (node->childflag & (1 << b)) { - child = &tmpnode; - occ_node_from_face(tree->face + node->child[b].face, &tmpnode); - } - else { - child = node->child[b].node; - } - - if (child) { - node->area += child->area; - sh_add(node->sh, node->sh, child->sh); - madd_v3_v3fl(node->co, child->co, child->area); - } - } - - if (node->area != 0.0f) - mul_v3_fl(node->co, 1.0f / node->area); - - /* compute maximum distance from center */ - node->dco = 0.0f; - if (node->area > 0.0f) - occ_build_dco(tree, node, node->co, &node->dco); -} - -static void occ_build_sh_normalize(OccNode *node) -{ - /* normalize spherical harmonics to not include area, so - * we can clamp the dot product and then multiply by area */ - int b; - - if (node->area != 0.0f) - sh_mul(node->sh, 1.0f / node->area); - - for (b = 0; b < TOTCHILD; b++) { - if (node->childflag & (1 << b)) { - /* pass */ - } - else if (node->child[b].node) { - occ_build_sh_normalize(node->child[b].node); - } - } -} - -static OcclusionTree *occ_tree_build(Render *re) -{ - const int num_threads = re->r.threads; - OcclusionTree *tree; - ObjectInstanceRen *obi; - ObjectRen *obr; - Material *ma; - VlakRen *vlr = NULL; - int a, b, c, totface; - - /* count */ - totface = 0; - for (obi = re->instancetable.first; obi; obi = obi->next) { - obr = obi->obr; - for (a = 0; a < obr->totvlak; a++) { - if ((a & 255) == 0) vlr = obr->vlaknodes[a >> 8].vlak; - else vlr++; - - ma = vlr->mat; - - if ((ma->shade_flag & MA_APPROX_OCCLUSION) && (ma->material_type == MA_TYPE_SURFACE)) - totface++; - } - } - - if (totface == 0) - return NULL; - - tree = MEM_callocN(sizeof(OcclusionTree), "OcclusionTree"); - tree->totface = totface; - - /* parameters */ - tree->error = get_render_aosss_error(&re->r, re->wrld.ao_approx_error); - tree->distfac = (re->wrld.aomode & WO_AODIST) ? re->wrld.aodistfac : 0.0f; - tree->doindirect = (re->wrld.ao_indirect_energy > 0.0f && re->wrld.ao_indirect_bounces > 0); - - /* allocation */ - tree->arena = BLI_memarena_new(0x8000 * sizeof(OccNode), "occ tree arena"); - BLI_memarena_use_calloc(tree->arena); - - if (re->wrld.aomode & WO_AOCACHE) - tree->cache = MEM_callocN(sizeof(OcclusionCache) * num_threads, "OcclusionCache"); - - tree->face = MEM_callocN(sizeof(OccFace) * totface, "OcclusionFace"); - tree->co = MEM_callocN(sizeof(float) * 3 * totface, "OcclusionCo"); - tree->occlusion = MEM_callocN(sizeof(float) * totface, "OcclusionOcclusion"); - - if (tree->doindirect) - tree->rad = MEM_callocN(sizeof(float) * 3 * totface, "OcclusionRad"); - - /* make array of face pointers */ - for (b = 0, c = 0, obi = re->instancetable.first; obi; obi = obi->next, c++) { - obr = obi->obr; - for (a = 0; a < obr->totvlak; a++) { - if ((a & 255) == 0) vlr = obr->vlaknodes[a >> 8].vlak; - else vlr++; - - ma = vlr->mat; - - if ((ma->shade_flag & MA_APPROX_OCCLUSION) && (ma->material_type == MA_TYPE_SURFACE)) { - tree->face[b].obi = c; - tree->face[b].facenr = a; - tree->occlusion[b] = 1.0f; - occ_face(&tree->face[b], tree->co[b], NULL, NULL); - b++; - } - } - } - - /* threads */ - tree->totbuildthread = (re->r.threads > 1 && totface > 10000) ? 8 : 1; - tree->dothreadedbuild = (tree->totbuildthread > 1); - - /* recurse */ - tree->root = BLI_memarena_alloc(tree->arena, sizeof(OccNode)); - tree->maxdepth = 1; - occ_build_recursive(tree, tree->root, 0, totface, 1); - - if (tree->doindirect) { - if (!(re->test_break(re->tbh))) - occ_build_shade(re, tree); - - if (!(re->test_break(re->tbh))) - occ_sum_occlusion(tree, tree->root); - } - - MEM_freeN(tree->co); - tree->co = NULL; - - if (!(re->test_break(re->tbh))) - occ_build_sh_normalize(tree->root); - - for (a = 0; a < num_threads; a++) - tree->stack[a] = MEM_callocN(sizeof(OccNode) * TOTCHILD * (tree->maxdepth + 1), "OccStack"); - - tree->num_threads = num_threads; - - return tree; -} - -static void occ_free_tree(OcclusionTree *tree) -{ - int a; - - if (tree) { - if (tree->arena) BLI_memarena_free(tree->arena); - for (a = 0; a < tree->num_threads; a++) - if (tree->stack[a]) - MEM_freeN(tree->stack[a]); - if (tree->occlusion) MEM_freeN(tree->occlusion); - if (tree->cache) MEM_freeN(tree->cache); - if (tree->face) MEM_freeN(tree->face); - if (tree->rad) MEM_freeN(tree->rad); - MEM_freeN(tree); - } -} - -/* ------------------------- Traversal --------------------------- */ - -static float occ_solid_angle(OccNode *node, const float v[3], float d2, float invd2, const float receivenormal[3]) -{ - float dotreceive, dotemit; - float ev[3]; - - ev[0] = -v[0] * invd2; - ev[1] = -v[1] * invd2; - ev[2] = -v[2] * invd2; - dotemit = sh_eval(node->sh, ev); - dotreceive = dot_v3v3(receivenormal, v) * invd2; - - CLAMP(dotemit, 0.0f, 1.0f); - CLAMP(dotreceive, 0.0f, 1.0f); - - return ((node->area * dotemit * dotreceive) / (d2 + node->area * INVPI)) * INVPI; -} - -static float occ_form_factor(OccFace *face, float *p, float *n) -{ - ObjectInstanceRen *obi; - VlakRen *vlr; - float v1[3], v2[3], v3[3], v4[3], q0[3], q1[3], q2[3], q3[3], contrib = 0.0f; - - obi = &R.objectinstance[face->obi]; - vlr = RE_findOrAddVlak(obi->obr, face->facenr); - - copy_v3_v3(v1, vlr->v1->co); - copy_v3_v3(v2, vlr->v2->co); - copy_v3_v3(v3, vlr->v3->co); - - if (obi->flag & R_TRANSFORMED) { - mul_m4_v3(obi->mat, v1); - mul_m4_v3(obi->mat, v2); - mul_m4_v3(obi->mat, v3); - } - - if (form_factor_visible_quad(p, n, v1, v2, v3, q0, q1, q2, q3)) - contrib += form_factor_quad(p, n, q0, q1, q2, q3); - - if (vlr->v4) { - copy_v3_v3(v4, vlr->v4->co); - if (obi->flag & R_TRANSFORMED) - mul_m4_v3(obi->mat, v4); - - if (form_factor_visible_quad(p, n, v1, v3, v4, q0, q1, q2, q3)) - contrib += form_factor_quad(p, n, q0, q1, q2, q3); - } - - return contrib; -} - -static void occ_lookup(OcclusionTree *tree, int thread, OccFace *exclude, - const float pp[3], const float pn[3], float *occ, float rad[3], float bentn[3]) -{ - OccNode *node, **stack; - OccFace *face; - float resultocc, resultrad[3], v[3], p[3], n[3], co[3], invd2; - float distfac, fac, error, d2, weight, emitarea; - int b, f, totstack; - - /* init variables */ - copy_v3_v3(p, pp); - copy_v3_v3(n, pn); - madd_v3_v3fl(p, n, 1e-4f); - - if (bentn) - copy_v3_v3(bentn, n); - - error = tree->error; - distfac = tree->distfac; - - resultocc = 0.0f; - zero_v3(resultrad); - - /* init stack */ - stack = tree->stack[thread]; - stack[0] = tree->root; - totstack = 1; - - while (totstack) { - /* pop point off the stack */ - node = stack[--totstack]; - - sub_v3_v3v3(v, node->co, p); - d2 = dot_v3v3(v, v) + 1e-16f; - emitarea = MAX2(node->area, node->dco); - - if (d2 * error > emitarea) { - if (distfac != 0.0f) { - fac = 1.0f / (1.0f + distfac * d2); - if (fac < 0.01f) - continue; - } - else - fac = 1.0f; - - /* accumulate occlusion from spherical harmonics */ - invd2 = 1.0f / sqrtf(d2); - weight = occ_solid_angle(node, v, d2, invd2, n); - - if (rad) - madd_v3_v3fl(resultrad, node->rad, weight * fac); - - weight *= node->occlusion; - - if (bentn) { - bentn[0] -= weight * invd2 * v[0]; - bentn[1] -= weight * invd2 * v[1]; - bentn[2] -= weight * invd2 * v[2]; - } - - resultocc += weight * fac; - } - else { - /* traverse into children */ - for (b = 0; b < TOTCHILD; b++) { - if (node->childflag & (1 << b)) { - f = node->child[b].face; - face = &tree->face[f]; - - /* accumulate occlusion with face form factor */ - if (!exclude || !(face->obi == exclude->obi && face->facenr == exclude->facenr)) { - if (bentn || distfac != 0.0f) { - occ_face(face, co, NULL, NULL); - sub_v3_v3v3(v, co, p); - d2 = dot_v3v3(v, v) + 1e-16f; - - fac = (distfac == 0.0f) ? 1.0f : 1.0f / (1.0f + distfac * d2); - if (fac < 0.01f) - continue; - } - else - fac = 1.0f; - - weight = occ_form_factor(face, p, n); - - if (rad) - madd_v3_v3fl(resultrad, tree->rad[f], weight * fac); - - weight *= tree->occlusion[f]; - - if (bentn) { - invd2 = 1.0f / sqrtf(d2); - bentn[0] -= weight * invd2 * v[0]; - bentn[1] -= weight * invd2 * v[1]; - bentn[2] -= weight * invd2 * v[2]; - } - - resultocc += weight * fac; - } - } - else if (node->child[b].node) { - /* push child on the stack */ - stack[totstack++] = node->child[b].node; - } - } - } - } - - if (occ) *occ = resultocc; - if (rad) copy_v3_v3(rad, resultrad); -#if 0 - if (rad && exclude) { - int a; - for (a = 0; a < tree->totface; a++) - if ((tree->face[a].obi == exclude->obi && tree->face[a].facenr == exclude->facenr)) - copy_v3_v3(rad, tree->rad[a]); - } -#endif - if (bentn) normalize_v3(bentn); -} - -static void occ_compute_bounces(Render *re, OcclusionTree *tree, int totbounce) -{ - float (*rad)[3], (*sum)[3], (*tmp)[3], co[3], n[3], occ; - int bounce, i; - - rad = MEM_callocN(sizeof(float) * 3 * tree->totface, "OcclusionBounceRad"); - sum = MEM_dupallocN(tree->rad); - - for (bounce = 1; bounce < totbounce; bounce++) { - for (i = 0; i < tree->totface; i++) { - occ_face(&tree->face[i], co, n, NULL); - madd_v3_v3fl(co, n, 1e-8f); - - occ_lookup(tree, 0, &tree->face[i], co, n, &occ, rad[i], NULL); - rad[i][0] = MAX2(rad[i][0], 0.0f); - rad[i][1] = MAX2(rad[i][1], 0.0f); - rad[i][2] = MAX2(rad[i][2], 0.0f); - add_v3_v3(sum[i], rad[i]); - - if (re->test_break(re->tbh)) - break; - } - - if (re->test_break(re->tbh)) - break; - - tmp = tree->rad; - tree->rad = rad; - rad = tmp; - - occ_sum_occlusion(tree, tree->root); - } - - MEM_freeN(rad); - MEM_freeN(tree->rad); - tree->rad = sum; - - if (!re->test_break(re->tbh)) - occ_sum_occlusion(tree, tree->root); -} - -static void occ_compute_passes(Render *re, OcclusionTree *tree, int totpass) -{ - float *occ, co[3], n[3]; - int pass, i; - - occ = MEM_callocN(sizeof(float) * tree->totface, "OcclusionPassOcc"); - - for (pass = 0; pass < totpass; pass++) { - for (i = 0; i < tree->totface; i++) { - occ_face(&tree->face[i], co, n, NULL); - negate_v3(n); - madd_v3_v3fl(co, n, 1e-8f); - - occ_lookup(tree, 0, &tree->face[i], co, n, &occ[i], NULL, NULL); - if (re->test_break(re->tbh)) - break; - } - - if (re->test_break(re->tbh)) - break; - - for (i = 0; i < tree->totface; i++) { - tree->occlusion[i] -= occ[i]; //MAX2(1.0f-occ[i], 0.0f); - if (tree->occlusion[i] < 0.0f) - tree->occlusion[i] = 0.0f; - } - - occ_sum_occlusion(tree, tree->root); - } - - MEM_freeN(occ); -} - -static void sample_occ_tree(Render *re, OcclusionTree *tree, OccFace *exclude, - const float co[3], const float n[3], int thread, int onlyshadow, - float *ao, float *env, float *indirect) -{ - float nn[3], bn[3], fac, occ, occlusion, correction, rad[3]; - int envcolor; - - envcolor = re->wrld.aocolor; - if (onlyshadow) - envcolor = WO_AOPLAIN; - - negate_v3_v3(nn, n); - - occ_lookup(tree, thread, exclude, co, nn, &occ, (tree->doindirect) ? rad : NULL, (env && envcolor) ? bn : NULL); - - correction = re->wrld.ao_approx_correction; - - occlusion = (1.0f - correction) * (1.0f - occ); - CLAMP(occlusion, 0.0f, 1.0f); - if (correction != 0.0f) - occlusion += correction * expf(-occ); - - if (env) { - /* sky shading using bent normal */ - if (ELEM(envcolor, WO_AOSKYCOL, WO_AOSKYTEX)) { - fac = 0.5f * (1.0f + dot_v3v3(bn, re->grvec)); - env[0] = (1.0f - fac) * re->wrld.horr + fac * re->wrld.zenr; - env[1] = (1.0f - fac) * re->wrld.horg + fac * re->wrld.zeng; - env[2] = (1.0f - fac) * re->wrld.horb + fac * re->wrld.zenb; - - mul_v3_fl(env, occlusion); - } - else { - env[0] = occlusion; - env[1] = occlusion; - env[2] = occlusion; - } -#if 0 - else { /* WO_AOSKYTEX */ - float dxyview[3]; - bn[0] = -bn[0]; - bn[1] = -bn[1]; - bn[2] = -bn[2]; - dxyview[0] = 1.0f; - dxyview[1] = 1.0f; - dxyview[2] = 0.0f; - shadeSkyView(ao, co, bn, dxyview); - } -#endif - } - - if (ao) { - ao[0] = occlusion; - ao[1] = occlusion; - ao[2] = occlusion; - } - - if (tree->doindirect) copy_v3_v3(indirect, rad); - else zero_v3(indirect); -} - -/* ---------------------------- Caching ------------------------------- */ - -static OcclusionCacheSample *find_occ_sample(OcclusionCache *cache, int x, int y) -{ - x -= cache->x; - y -= cache->y; - - x /= cache->step; - y /= cache->step; - x *= cache->step; - y *= cache->step; - - if (x < 0 || x >= cache->w || y < 0 || y >= cache->h) - return NULL; - else - return &cache->sample[y * cache->w + x]; -} - -static int sample_occ_cache(OcclusionTree *tree, float *co, float *n, int x, int y, int thread, float *ao, float *env, float *indirect) -{ - OcclusionCache *cache; - OcclusionCacheSample *samples[4], *sample; - float wn[4], wz[4], wb[4], tx, ty, w, totw, mino, maxo; - float d[3], dist2; - int i, x1, y1, x2, y2; - - if (!tree->cache) - return 0; - - /* first try to find a sample in the same pixel */ - cache = &tree->cache[thread]; - - if (cache->sample && cache->step) { - sample = &cache->sample[(y - cache->y) * cache->w + (x - cache->x)]; - if (sample->filled) { - sub_v3_v3v3(d, sample->co, co); - dist2 = dot_v3v3(d, d); - if (dist2 < 0.5f * sample->dist2 && dot_v3v3(sample->n, n) > 0.98f) { - copy_v3_v3(ao, sample->ao); - copy_v3_v3(env, sample->env); - copy_v3_v3(indirect, sample->indirect); - return 1; - } - } - } - else - return 0; - - /* try to interpolate between 4 neighboring pixels */ - samples[0] = find_occ_sample(cache, x, y); - samples[1] = find_occ_sample(cache, x + cache->step, y); - samples[2] = find_occ_sample(cache, x, y + cache->step); - samples[3] = find_occ_sample(cache, x + cache->step, y + cache->step); - - for (i = 0; i < 4; i++) - if (!samples[i] || !samples[i]->filled) - return 0; - - /* require intensities not being too different */ - mino = min_ffff(samples[0]->intensity, samples[1]->intensity, samples[2]->intensity, samples[3]->intensity); - maxo = max_ffff(samples[0]->intensity, samples[1]->intensity, samples[2]->intensity, samples[3]->intensity); - - if (maxo - mino > 0.05f) - return 0; - - /* compute weighted interpolation between samples */ - zero_v3(ao); - zero_v3(env); - zero_v3(indirect); - totw = 0.0f; - - x1 = samples[0]->x; - y1 = samples[0]->y; - x2 = samples[3]->x; - y2 = samples[3]->y; - - tx = (float)(x2 - x) / (float)(x2 - x1); - ty = (float)(y2 - y) / (float)(y2 - y1); - - wb[3] = (1.0f - tx) * (1.0f - ty); - wb[2] = (tx) * (1.0f - ty); - wb[1] = (1.0f - tx) * (ty); - wb[0] = tx * ty; - - for (i = 0; i < 4; i++) { - sub_v3_v3v3(d, samples[i]->co, co); - //dist2 = dot_v3v3(d, d); - - wz[i] = 1.0f; //(samples[i]->dist2/(1e-4f + dist2)); - wn[i] = pow(dot_v3v3(samples[i]->n, n), 32.0f); - - w = wb[i] * wn[i] * wz[i]; - - totw += w; - madd_v3_v3fl(ao, samples[i]->ao, w); - madd_v3_v3fl(env, samples[i]->env, w); - madd_v3_v3fl(indirect, samples[i]->indirect, w); - } - - if (totw >= 0.9f) { - totw = 1.0f / totw; - mul_v3_fl(ao, totw); - mul_v3_fl(env, totw); - mul_v3_fl(indirect, totw); - return 1; - } - - return 0; -} - -static void sample_occ_surface(ShadeInput *shi) -{ - StrandRen *strand = shi->strand; - StrandSurface *mesh = strand->buffer->surface; - const int *face, *index = RE_strandren_get_face(shi->obr, strand, 0); - float w[4], *co1, *co2, *co3, *co4; - - if (mesh && mesh->face && mesh->co && mesh->ao && index) { - face = mesh->face[*index]; - - co1 = mesh->co[face[0]]; - co2 = mesh->co[face[1]]; - co3 = mesh->co[face[2]]; - - if (face[3]) { - co4 = mesh->co[face[3]]; - interp_weights_quad_v3(w, co1, co2, co3, co4, strand->vert->co); - } - else { - interp_weights_tri_v3(w, co1, co2, co3, strand->vert->co); - } - - zero_v3(shi->ao); - zero_v3(shi->env); - zero_v3(shi->indirect); - - madd_v3_v3fl(shi->ao, mesh->ao[face[0]], w[0]); - madd_v3_v3fl(shi->env, mesh->env[face[0]], w[0]); - madd_v3_v3fl(shi->indirect, mesh->indirect[face[0]], w[0]); - madd_v3_v3fl(shi->ao, mesh->ao[face[1]], w[1]); - madd_v3_v3fl(shi->env, mesh->env[face[1]], w[1]); - madd_v3_v3fl(shi->indirect, mesh->indirect[face[1]], w[1]); - madd_v3_v3fl(shi->ao, mesh->ao[face[2]], w[2]); - madd_v3_v3fl(shi->env, mesh->env[face[2]], w[2]); - madd_v3_v3fl(shi->indirect, mesh->indirect[face[2]], w[2]); - if (face[3]) { - madd_v3_v3fl(shi->ao, mesh->ao[face[3]], w[3]); - madd_v3_v3fl(shi->env, mesh->env[face[3]], w[3]); - madd_v3_v3fl(shi->indirect, mesh->indirect[face[3]], w[3]); - } - } - else { - shi->ao[0] = 1.0f; - shi->ao[1] = 1.0f; - shi->ao[2] = 1.0f; - zero_v3(shi->env); - zero_v3(shi->indirect); - } -} - -/* ------------------------- External Functions --------------------------- */ - -static void *exec_strandsurface_sample(void *data) -{ - OcclusionThread *othread = (OcclusionThread *)data; - Render *re = othread->re; - StrandSurface *mesh = othread->mesh; - float ao[3], env[3], indirect[3], co[3], n[3], *co1, *co2, *co3, *co4; - int a, *face; - - for (a = othread->begin; a < othread->end; a++) { - face = mesh->face[a]; - co1 = mesh->co[face[0]]; - co2 = mesh->co[face[1]]; - co3 = mesh->co[face[2]]; - - if (face[3]) { - co4 = mesh->co[face[3]]; - - mid_v3_v3v3(co, co1, co3); - normal_quad_v3(n, co1, co2, co3, co4); - } - else { - mid_v3_v3v3v3(co, co1, co2, co3); - normal_tri_v3(n, co1, co2, co3); - } - negate_v3(n); - - sample_occ_tree(re, re->occlusiontree, NULL, co, n, othread->thread, 0, ao, env, indirect); - copy_v3_v3(othread->faceao[a], ao); - copy_v3_v3(othread->faceenv[a], env); - copy_v3_v3(othread->faceindirect[a], indirect); - } - - return NULL; -} - -void make_occ_tree(Render *re) -{ - OcclusionThread othreads[BLENDER_MAX_THREADS]; - OcclusionTree *tree; - StrandSurface *mesh; - ListBase threads; - float ao[3], env[3], indirect[3], (*faceao)[3], (*faceenv)[3], (*faceindirect)[3]; - int a, totface, totthread, *face, *count; - - /* ugly, needed for occ_face */ - R = *re; - - re->i.infostr = IFACE_("Occlusion preprocessing"); - re->stats_draw(re->sdh, &re->i); - - re->occlusiontree = tree = occ_tree_build(re); - - if (tree && !re->test_break(re->tbh)) { - if (re->wrld.ao_approx_passes > 0) - occ_compute_passes(re, tree, re->wrld.ao_approx_passes); - if (tree->doindirect && (re->wrld.mode & WO_INDIRECT_LIGHT)) - occ_compute_bounces(re, tree, re->wrld.ao_indirect_bounces); - - for (mesh = re->strandsurface.first; mesh; mesh = mesh->next) { - if (!mesh->face || !mesh->co || !mesh->ao) - continue; - - count = MEM_callocN(sizeof(int) * mesh->totvert, "OcclusionCount"); - faceao = MEM_callocN(sizeof(float) * 3 * mesh->totface, "StrandSurfFaceAO"); - faceenv = MEM_callocN(sizeof(float) * 3 * mesh->totface, "StrandSurfFaceEnv"); - faceindirect = MEM_callocN(sizeof(float) * 3 * mesh->totface, "StrandSurfFaceIndirect"); - - totthread = (mesh->totface > 10000) ? re->r.threads : 1; - totface = mesh->totface / totthread; - for (a = 0; a < totthread; a++) { - othreads[a].re = re; - othreads[a].faceao = faceao; - othreads[a].faceenv = faceenv; - othreads[a].faceindirect = faceindirect; - othreads[a].thread = a; - othreads[a].mesh = mesh; - othreads[a].begin = a * totface; - othreads[a].end = (a == totthread - 1) ? mesh->totface : (a + 1) * totface; - } - - if (totthread == 1) { - exec_strandsurface_sample(&othreads[0]); - } - else { - BLI_threadpool_init(&threads, exec_strandsurface_sample, totthread); - - for (a = 0; a < totthread; a++) - BLI_threadpool_insert(&threads, &othreads[a]); - - BLI_threadpool_end(&threads); - } - - for (a = 0; a < mesh->totface; a++) { - face = mesh->face[a]; - - copy_v3_v3(ao, faceao[a]); - copy_v3_v3(env, faceenv[a]); - copy_v3_v3(indirect, faceindirect[a]); - - add_v3_v3(mesh->ao[face[0]], ao); - add_v3_v3(mesh->env[face[0]], env); - add_v3_v3(mesh->indirect[face[0]], indirect); - count[face[0]]++; - add_v3_v3(mesh->ao[face[1]], ao); - add_v3_v3(mesh->env[face[1]], env); - add_v3_v3(mesh->indirect[face[1]], indirect); - count[face[1]]++; - add_v3_v3(mesh->ao[face[2]], ao); - add_v3_v3(mesh->env[face[2]], env); - add_v3_v3(mesh->indirect[face[2]], indirect); - count[face[2]]++; - - if (face[3]) { - add_v3_v3(mesh->ao[face[3]], ao); - add_v3_v3(mesh->env[face[3]], env); - add_v3_v3(mesh->indirect[face[3]], indirect); - count[face[3]]++; - } - } - - for (a = 0; a < mesh->totvert; a++) { - if (count[a]) { - mul_v3_fl(mesh->ao[a], 1.0f / count[a]); - mul_v3_fl(mesh->env[a], 1.0f / count[a]); - mul_v3_fl(mesh->indirect[a], 1.0f / count[a]); - } - } - - MEM_freeN(count); - MEM_freeN(faceao); - MEM_freeN(faceenv); - MEM_freeN(faceindirect); - } - } -} - -void free_occ(Render *re) -{ - if (re->occlusiontree) { - occ_free_tree(re->occlusiontree); - re->occlusiontree = NULL; - } -} - -void sample_occ(Render *re, ShadeInput *shi) -{ - OcclusionTree *tree = re->occlusiontree; - OcclusionCache *cache; - OcclusionCacheSample *sample; - OccFace exclude; - int onlyshadow; - - if (tree) { - if (shi->strand) { - sample_occ_surface(shi); - } - /* try to get result from the cache if possible */ - else if (shi->depth != 0 || !sample_occ_cache(tree, shi->co, shi->vno, shi->xs, shi->ys, shi->thread, shi->ao, shi->env, shi->indirect)) { - /* no luck, let's sample the occlusion */ - exclude.obi = shi->obi - re->objectinstance; - exclude.facenr = shi->vlr->index; - onlyshadow = (shi->mat->mode & MA_ONLYSHADOW); - sample_occ_tree(re, tree, &exclude, shi->co, shi->vno, shi->thread, onlyshadow, shi->ao, shi->env, shi->indirect); - - /* fill result into sample, each time */ - if (tree->cache) { - cache = &tree->cache[shi->thread]; - - if (cache->sample && cache->step) { - sample = &cache->sample[(shi->ys - cache->y) * cache->w + (shi->xs - cache->x)]; - copy_v3_v3(sample->co, shi->co); - copy_v3_v3(sample->n, shi->vno); - copy_v3_v3(sample->ao, shi->ao); - copy_v3_v3(sample->env, shi->env); - copy_v3_v3(sample->indirect, shi->indirect); - sample->intensity = max_fff(sample->ao[0], sample->ao[1], sample->ao[2]); - sample->intensity = max_ff(sample->intensity, max_fff(sample->env[0], sample->env[1], sample->env[2])); - sample->intensity = max_ff(sample->intensity, max_fff(sample->indirect[0], sample->indirect[1], sample->indirect[2])); - sample->dist2 = dot_v3v3(shi->dxco, shi->dxco) + dot_v3v3(shi->dyco, shi->dyco); - sample->filled = 1; - } - } - } - } - else { - shi->ao[0] = 1.0f; - shi->ao[1] = 1.0f; - shi->ao[2] = 1.0f; - - shi->env[0] = 0.0f; - shi->env[1] = 0.0f; - shi->env[2] = 0.0f; - - shi->indirect[0] = 0.0f; - shi->indirect[1] = 0.0f; - shi->indirect[2] = 0.0f; - } -} - -void cache_occ_samples(Render *re, RenderPart *pa, ShadeSample *ssamp) -{ - OcclusionTree *tree = re->occlusiontree; - PixStr ps; - OcclusionCache *cache; - OcclusionCacheSample *sample; - OccFace exclude; - ShadeInput *shi; - intptr_t *rd = NULL; - int *ro = NULL, *rp = NULL, *rz = NULL, onlyshadow; - int x, y, step = CACHE_STEP; - - if (!tree->cache) - return; - - cache = &tree->cache[pa->thread]; - cache->w = pa->rectx; - cache->h = pa->recty; - cache->x = pa->disprect.xmin; - cache->y = pa->disprect.ymin; - cache->step = step; - cache->sample = MEM_callocN(sizeof(OcclusionCacheSample) * cache->w * cache->h, "OcclusionCacheSample"); - sample = cache->sample; - - if (re->osa) { - rd = pa->rectdaps; - } - else { - /* fake pixel struct for non-osa */ - ps.next = NULL; - ps.mask = 0xFFFF; - - ro = pa->recto; - rp = pa->rectp; - rz = pa->rectz; - } - - /* compute a sample at every step pixels */ - for (y = pa->disprect.ymin; y < pa->disprect.ymax; y++) { - for (x = pa->disprect.xmin; x < pa->disprect.xmax; x++, sample++, rd++, ro++, rp++, rz++) { - if (!(((x - pa->disprect.xmin + step) % step) == 0 || x == pa->disprect.xmax - 1)) - continue; - if (!(((y - pa->disprect.ymin + step) % step) == 0 || y == pa->disprect.ymax - 1)) - continue; - - if (re->osa) { - if (!*rd) continue; - - shade_samples_fill_with_ps(ssamp, (PixStr *)(*rd), x, y); - } - else { - if (!*rp) continue; - - ps.obi = *ro; - ps.facenr = *rp; - ps.z = *rz; - shade_samples_fill_with_ps(ssamp, &ps, x, y); - } - - shi = ssamp->shi; - if (shi->vlr) { - onlyshadow = (shi->mat->mode & MA_ONLYSHADOW); - exclude.obi = shi->obi - re->objectinstance; - exclude.facenr = shi->vlr->index; - sample_occ_tree(re, tree, &exclude, shi->co, shi->vno, shi->thread, onlyshadow, shi->ao, shi->env, shi->indirect); - - copy_v3_v3(sample->co, shi->co); - copy_v3_v3(sample->n, shi->vno); - copy_v3_v3(sample->ao, shi->ao); - copy_v3_v3(sample->env, shi->env); - copy_v3_v3(sample->indirect, shi->indirect); - sample->intensity = max_fff(sample->ao[0], sample->ao[1], sample->ao[2]); - sample->intensity = max_ff(sample->intensity, max_fff(sample->env[0], sample->env[1], sample->env[2])); - sample->intensity = max_ff(sample->intensity, max_fff(sample->indirect[0], sample->indirect[1], sample->indirect[2])); - sample->dist2 = dot_v3v3(shi->dxco, shi->dxco) + dot_v3v3(shi->dyco, shi->dyco); - sample->x = shi->xs; - sample->y = shi->ys; - sample->filled = 1; - } - - if (re->test_break(re->tbh)) - break; - } - } -} - -void free_occ_samples(Render *re, RenderPart *pa) -{ - OcclusionTree *tree = re->occlusiontree; - OcclusionCache *cache; - - if (tree->cache) { - cache = &tree->cache[pa->thread]; - - if (cache->sample) - MEM_freeN(cache->sample); - - cache->w = 0; - cache->h = 0; - cache->step = 0; - } -} - diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index c9f13004836..14160782898 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -94,6 +94,9 @@ #include "RE_pipeline.h" #include "RE_render_ext.h" +#include "../../../windowmanager/WM_api.h" /* XXX */ +#include "../../../intern/gawain/gawain/gwn_context.h" + #ifdef WITH_FREESTYLE # include "FRS_freestyle.h" #endif @@ -327,6 +330,14 @@ RenderResult *RE_AcquireResultWrite(Render *re) return NULL; } +void RE_ClearResult(Render *re) +{ + if (re) { + render_result_free(re->result); + re->result = NULL; + } +} + void RE_SwapResult(Render *re, RenderResult **rr) { /* for keeping render buffers */ @@ -765,7 +776,7 @@ void RE_InitState(Render *re, Render *source, RenderData *rd, /* if preview render, we try to keep old result */ BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); - if (re->r.scemode & (R_BUTS_PREVIEW|R_VIEWPORT_PREVIEW)) { + if (re->r.scemode & R_BUTS_PREVIEW) { if (had_freestyle || (re->r.mode & R_EDGE_FRS)) { /* freestyle manipulates render layers so always have to free */ render_result_free(re->result); @@ -803,10 +814,6 @@ void RE_InitState(Render *re, Render *source, RenderData *rd, render_result_view_new(re->result, ""); } - eEvaluationMode mode = (re->r.scemode & R_VIEWPORT_PREVIEW) ? DAG_EVAL_PREVIEW : DAG_EVAL_RENDER; - /* This mode should have been set in the Depsgraph immediately when it was created. */ - (void)mode; - /* ensure renderdatabase can use part settings correct */ RE_parts_clamp(re); @@ -1020,6 +1027,54 @@ void RE_test_break_cb(Render *re, void *handle, int (*f)(void *handle)) re->tbh = handle; } +/* ********* GL Context ******** */ + +/* Create the gl context of the Render. + * It will be free by the render itself. */ +void RE_gl_context_create(Render *re) +{ + /* Needs to be created in the main ogl thread. */ + re->gl_context = WM_opengl_context_create(); + re->gl_context_ownership = true; +} + +void RE_gl_context_destroy(Render *re) +{ + /* Needs to be called from the thread which used the ogl context for rendering. */ + if (re->gwn_context) { + GWN_context_active_set(re->gwn_context); + GWN_context_discard(re->gwn_context); + re->gwn_context = NULL; + } + if (re->gl_context) { + if (re->gl_context_ownership) { + WM_opengl_context_dispose(re->gl_context); + } + re->gl_context = NULL; + } +} + +/* Manually set the gl context of the Render. + * It won't be free by the render itself. */ +void RE_gl_context_set(Render *re, void *gl_context) +{ + BLI_assert(gl_context); /* Cannot set NULL */ + re->gl_context = gl_context; + re->gl_context_ownership = false; +} + +void *RE_gl_context_get(Render *re) +{ + return re->gl_context; +} + +void *RE_gwn_context_get(Render *re) +{ + if (re->gwn_context == NULL) { + re->gwn_context = GWN_context_create(); + } + return re->gwn_context; +} /* ********* add object data (later) ******** */ @@ -1192,19 +1247,6 @@ static int composite_needs_render(Scene *sce, int this_scene) return 0; } -static bool rlayer_node_uses_alpha(bNodeTree *ntree, bNode *node) -{ - bNodeSocket *sock; - - for (sock = node->outputs.first; sock; sock = sock->next) { - /* Weak! but how to make it better? */ - if (STREQ(sock->name, "Alpha") && nodeCountSocketLinks(ntree, sock) > 0) - return true; - } - - return false; -} - bool RE_allow_render_generic_object(Object *ob) { /* override not showing object when duplis are used with particles */ @@ -1217,189 +1259,6 @@ bool RE_allow_render_generic_object(Object *ob) return true; } -/* Issue here is that it's possible that object which is used by boolean, - * array or shrinkwrap modifiers weren't displayed in the viewport before - * rendering. This leads to situations when apply() of this modifiers - * could not get ob->derivedFinal and modifiers are not being applied. - * - * This was worked around by direct call of get_derived_final() from those - * modifiers, but such approach leads to write conflicts with threaded - * update. - * - * Here we make sure derivedFinal will be calculated by update_for_newframe - * function later in the pipeline and all the modifiers are applied - * properly without hacks from their side. - * - sergey - - */ -#define DEPSGRAPH_WORKAROUND_HACK - -#ifdef DEPSGRAPH_WORKAROUND_HACK -static void tag_dependend_object_for_render(Scene *scene, Object *object); - -static void tag_dependend_group_for_render(Scene *scene, Collection *collection) -{ - if (collection->id.tag & LIB_TAG_DOIT) { - return; - } - collection->id.tag |= LIB_TAG_DOIT; - - for (CollectionObject *cob = collection->gobject.first; cob != NULL; cob = cob->next) { - Object *object = cob->ob; - tag_dependend_object_for_render(scene, object); - } -} - -static void tag_dependend_object_for_render(Scene *scene, Object *object) -{ - if (object->type == OB_MESH) { - if (RE_allow_render_generic_object(object)) { - ModifierData *md; - VirtualModifierData virtualModifierData; - - if (object->particlesystem.first) { - DEG_id_tag_update(&object->id, OB_RECALC_DATA); - } - - for (md = modifiers_getVirtualModifierList(object, &virtualModifierData); - md; - md = md->next) - { - if (!modifier_isEnabled(scene, md, eModifierMode_Render)) { - continue; - } - - if (md->type == eModifierType_Boolean) { - BooleanModifierData *bmd = (BooleanModifierData *)md; - if (bmd->object && bmd->object->type == OB_MESH) { - DEG_id_tag_update(&bmd->object->id, OB_RECALC_DATA); - } - } - else if (md->type == eModifierType_Array) { - ArrayModifierData *amd = (ArrayModifierData *)md; - if (amd->start_cap && amd->start_cap->type == OB_MESH) { - DEG_id_tag_update(&amd->start_cap->id, OB_RECALC_DATA); - } - if (amd->end_cap && amd->end_cap->type == OB_MESH) { - DEG_id_tag_update(&amd->end_cap->id, OB_RECALC_DATA); - } - } - else if (md->type == eModifierType_Shrinkwrap) { - ShrinkwrapModifierData *smd = (ShrinkwrapModifierData *)md; - if (smd->target && smd->target->type == OB_MESH) { - DEG_id_tag_update(&smd->target->id, OB_RECALC_DATA); - } - } - else if (md->type == eModifierType_ParticleSystem) { - ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md; - ParticleSystem *psys = psmd->psys; - ParticleSettings *part = psys->part; - switch (part->ren_as) { - case PART_DRAW_OB: - if (part->dup_ob != NULL) { - DEG_id_tag_update(&part->dup_ob->id, OB_RECALC_DATA); - } - break; - case PART_DRAW_GR: - if (part->dup_group != NULL) { - FOREACH_COLLECTION_BASE_RECURSIVE_BEGIN(part->dup_group, base) - { - Object *ob = base->object; - DEG_id_tag_update(&ob->id, OB_RECALC_DATA); - } - FOREACH_COLLECTION_BASE_RECURSIVE_END - } - break; - } - } - } - } - } - if (object->dup_group != NULL) { - tag_dependend_group_for_render(scene, object->dup_group); - } -} - -static void tag_dependend_objects_for_render(Main *bmain, Scene *scene) -{ - BKE_main_id_tag_idcode(bmain, ID_GR, LIB_TAG_DOIT, false); - FOREACH_OBJECT_RENDERABLE_BEGIN(scene, object) - { - tag_dependend_object_for_render(scene, object); - } - FOREACH_OBJECT_RENDERABLE_END; -} -#endif - -static void tag_scenes_for_render(Render *re) -{ - bNode *node; - Scene *sce; - - for (sce = re->main->scene.first; sce; sce = sce->id.next) { - sce->id.tag &= ~LIB_TAG_DOIT; -#ifdef DEPSGRAPH_WORKAROUND_HACK - tag_dependend_objects_for_render(re->main, sce); -#endif - } - -#ifdef WITH_FREESTYLE - if (re->freestyle_bmain) { - for (sce = re->freestyle_bmain->scene.first; sce; sce = sce->id.next) { - sce->id.tag &= ~LIB_TAG_DOIT; -#ifdef DEPSGRAPH_WORKAROUND_HACK - tag_dependend_objects_for_render(re->freestyle_bmain, sce); -#endif - } - } -#endif - - if (RE_GetCamera(re) && composite_needs_render(re->scene, 1)) { - re->scene->id.tag |= LIB_TAG_DOIT; -#ifdef DEPSGRAPH_WORKAROUND_HACK - tag_dependend_objects_for_render(re->main, re->scene); -#endif - } - - if (re->scene->nodetree == NULL) return; - - /* check for render-layers nodes using other scenes, we tag them LIB_TAG_DOIT */ - for (node = re->scene->nodetree->nodes.first; node; node = node->next) { - node->flag &= ~NODE_TEST; - if (node->type == CMP_NODE_R_LAYERS && (node->flag & NODE_MUTED) == 0) { - if (node->id) { - if (!MAIN_VERSION_ATLEAST(re->main, 265, 5)) { - if (rlayer_node_uses_alpha(re->scene->nodetree, node)) { - Scene *scene = (Scene *)node->id; - - if (scene->r.alphamode != R_ALPHAPREMUL) { - BKE_reportf(re->reports, RPT_WARNING, "Setting scene %s alpha mode to Premul", scene->id.name + 2); - - /* also print, so feedback is immediate */ - printf("2.66 versioning fix: setting scene %s alpha mode to Premul\n", scene->id.name + 2); - - scene->r.alphamode = R_ALPHAPREMUL; - } - } - } - - if (node->id != (ID *)re->scene) { - if ((node->id->tag & LIB_TAG_DOIT) == 0) { - Scene *scene = (Scene *) node->id; - if (render_scene_has_layers_to_render(scene, NULL)) { - node->flag |= NODE_TEST; - node->id->tag |= LIB_TAG_DOIT; -#ifdef DEPSGRAPH_WORKAROUND_HACK - tag_dependend_objects_for_render(re->main, scene); -#endif - } - } - } - } - } - } - -} - static void ntree_render_scenes(Render *re) { bNode *node; @@ -1409,12 +1268,6 @@ static void ntree_render_scenes(Render *re) if (re->scene->nodetree == NULL) return; - tag_scenes_for_render(re); - -#ifdef DEPSGRAPH_WORKAROUND_GROUP_HACK - tag_collections_for_render(re); -#endif - /* now foreach render-result node tagged we do a full render */ /* results are stored in a way compisitor will find it */ for (node = re->scene->nodetree->nodes.first; node; node = node->next) { @@ -1532,9 +1385,6 @@ static void do_render_composite(Render *re) bNodeTree *ntree = re->scene->nodetree; int update_newframe = 0; - /* INIT seeding, compositor can use random texture */ - BLI_srandom(re->r.cfra); - if (composite_needs_render(re->scene, 1)) { /* save memory... free all cached images */ ntreeFreeCache(ntree); @@ -1611,11 +1461,6 @@ static void do_render_composite(Render *re) free_all_freestyle_renders(); #endif -#ifdef DEPSGRAPH_WORKAROUND_GROUP_HACK - /* Restore their visibility based on the viewport visibility flags. */ - tag_collections_for_render(re); -#endif - /* weak... the display callback wants an active renderlayer pointer... */ if (re->result != NULL) { re->result->renlay = render_get_active_layer(re, re->result); @@ -1798,8 +1643,8 @@ static void do_render_all_options(Render *re) re->i.starttime = PIL_check_seconds_timer(); /* ensure no images are in memory from previous animated sequences */ - BKE_image_all_free_anim_ibufs(re->r.cfra); - BKE_sequencer_all_free_anim_ibufs(re->r.cfra); + BKE_image_all_free_anim_ibufs(re->main, re->r.cfra); + BKE_sequencer_all_free_anim_ibufs(re->main, re->r.cfra); if (RE_engine_render(re, 1)) { /* in this case external render overrides all */ @@ -2069,7 +1914,7 @@ static void update_physics_cache(Render *re, Scene *scene, ViewLayer *view_layer PTCacheBaker baker; memset(&baker, 0, sizeof(baker)); - baker.main = re->main; + baker.bmain = re->main; baker.scene = scene; baker.view_layer = view_layer; baker.depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true); @@ -2135,14 +1980,6 @@ static int render_initialize_from_main(Render *re, RenderData *rd, Main *bmain, return 1; } - /* check all scenes involved */ - tag_scenes_for_render(re); - -#ifdef DEPSGRAPH_WORKAROUND_GROUP_HACK - /* Update collection collections visibility. */ - tag_collections_for_render(re); -#endif - /* * Disabled completely for now, * can be later set as render profile option @@ -2224,6 +2061,9 @@ void RE_BlenderFrame(Render *re, Main *bmain, Scene *scene, ViewLayer *single_la BLI_callback_exec(re->main, (ID *)scene, G.is_break ? BLI_CB_EVT_RENDER_CANCEL : BLI_CB_EVT_RENDER_COMPLETE); + /* Destroy the opengl context in the correct thread. */ + RE_gl_context_destroy(re); + /* UGLY WARNING */ G.is_rendering = false; } @@ -2779,6 +2619,9 @@ void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, Object *camera_overri BLI_callback_exec(re->main, (ID *)scene, G.is_break ? BLI_CB_EVT_RENDER_CANCEL : BLI_CB_EVT_RENDER_COMPLETE); BKE_sound_reset_scene_specs(scene); + /* Destroy the opengl context in the correct thread. */ + RE_gl_context_destroy(re); + /* UGLY WARNING */ G.is_rendering = false; } @@ -2801,6 +2644,9 @@ void RE_PreviewRender(Render *re, Main *bmain, Scene *sce) RE_SetCamera(re, camera); do_render_3d(re); + + /* Destroy the opengl context in the correct thread. */ + RE_gl_context_destroy(re); } /* note; repeated win/disprect calc... solve that nicer, also in compo */ diff --git a/source/blender/render/intern/source/pixelblending.c b/source/blender/render/intern/source/pixelblending.c deleted file mode 100644 index c7cfe765f5b..00000000000 --- a/source/blender/render/intern/source/pixelblending.c +++ /dev/null @@ -1,400 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * Contributor(s): Full recode, 2004-2006 Blender Foundation - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/render/intern/source/pixelblending.c - * \ingroup render - * - * Functions to blend pixels with or without alpha, in various formats - * nzc - June 2000 - */ - - -#include <math.h> -#include <string.h> - -/* global includes */ - -/* own includes */ -#include "render_types.h" -#include "pixelblending.h" - -/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -/* defined in pipeline.c, is hardcopy of active dynamic allocated Render */ -/* only to be used here in this file, it's for speed */ -extern struct Render R; -/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ - - -/* ------------------------------------------------------------------------- */ -/* Debug/behavior defines */ -/* if defined: alpha blending with floats clips color, as with shorts */ -/* #define RE_FLOAT_COLOR_CLIPPING */ -/* if defined: alpha values are clipped */ -/* For now, we just keep alpha clipping. We run into thresholding and */ -/* blending difficulties otherwise. Be careful here. */ -#define RE_ALPHA_CLIPPING - - - -/* Threshold for a 'full' pixel: pixels with alpha above this level are */ -/* considered opaque This is the decimal value for 0xFFF0 / 0xFFFF */ -#define RE_FULL_COLOR_FLOAT 0.9998f -/* Threshold for an 'empty' pixel: pixels with alpha above this level are */ -/* considered completely transparent. This is the decimal value */ -/* for 0x000F / 0xFFFF */ -#define RE_EMPTY_COLOR_FLOAT 0.0002f - - -/* ------------------------------------------------------------------------- */ - -void addAlphaOverFloat(float dest[4], const float source[4]) -{ - /* d = s + (1-alpha_s)d*/ - float mul; - - mul = 1.0f - source[3]; - - dest[0] = (mul * dest[0]) + source[0]; - dest[1] = (mul * dest[1]) + source[1]; - dest[2] = (mul * dest[2]) + source[2]; - dest[3] = (mul * dest[3]) + source[3]; - -} - - -/* ------------------------------------------------------------------------- */ - -void addAlphaUnderFloat(float dest[4], const float source[4]) -{ - float mul; - - mul = 1.0f - dest[3]; - - dest[0] += (mul * source[0]); - dest[1] += (mul * source[1]); - dest[2] += (mul * source[2]); - dest[3] += (mul * source[3]); -} - - -/* ------------------------------------------------------------------------- */ -void addalphaAddfacFloat(float dest[4], const float source[4], char addfac) -{ - float m; /* weiging factor of destination */ - float c; /* intermediate color */ - - /* Addfac is a number between 0 and 1: rescale */ - /* final target is to diminish the influence of dest when addfac rises */ - m = 1.0f - (source[3] * ((255 - addfac) / 255.0f)); - - /* blend colors*/ - c = (m * dest[0]) + source[0]; -#ifdef RE_FLOAT_COLOR_CLIPPING - if (c >= RE_FULL_COLOR_FLOAT) dest[0] = RE_FULL_COLOR_FLOAT; - else -#endif - dest[0] = c; - - c = (m * dest[1]) + source[1]; -#ifdef RE_FLOAT_COLOR_CLIPPING - if (c >= RE_FULL_COLOR_FLOAT) dest[1] = RE_FULL_COLOR_FLOAT; - else -#endif - dest[1] = c; - - c = (m * dest[2]) + source[2]; -#ifdef RE_FLOAT_COLOR_CLIPPING - if (c >= RE_FULL_COLOR_FLOAT) dest[2] = RE_FULL_COLOR_FLOAT; - else -#endif - dest[2] = c; - - c = (m * dest[3]) + source[3]; -#ifdef RE_ALPHA_CLIPPING - if (c >= RE_FULL_COLOR_FLOAT) dest[3] = RE_FULL_COLOR_FLOAT; - else -#endif - dest[3] = c; - -} - - -/* ------------------------------------------------------------------------- */ - -/* filtered adding to scanlines */ -void add_filt_fmask(unsigned int mask, const float col[4], float *rowbuf, int row_w) -{ - /* calc the value of mask */ - float **fmask1 = R.samples->fmask1, **fmask2 = R.samples->fmask2; - float *rb1, *rb2, *rb3; - float val, r, g, b, al; - unsigned int a, maskand, maskshift; - int j; - - r = col[0]; - g = col[1]; - b = col[2]; - al = col[3]; - - rb2 = rowbuf - 4; - rb3 = rb2 - 4 * row_w; - rb1 = rb2 + 4 * row_w; - - maskand = (mask & 255); - maskshift = (mask >> 8); - - for (j = 2; j >= 0; j--) { - - a = j; - - val = *(fmask1[a] + maskand) + *(fmask2[a] + maskshift); - if (val != 0.0f) { - rb1[0] += val * r; - rb1[1] += val * g; - rb1[2] += val * b; - rb1[3] += val * al; - } - a += 3; - - val = *(fmask1[a] + maskand) + *(fmask2[a] + maskshift); - if (val != 0.0f) { - rb2[0] += val * r; - rb2[1] += val * g; - rb2[2] += val * b; - rb2[3] += val * al; - } - a += 3; - - val = *(fmask1[a] + maskand) + *(fmask2[a] + maskshift); - if (val != 0.0f) { - rb3[0] += val * r; - rb3[1] += val * g; - rb3[2] += val * b; - rb3[3] += val * al; - } - - rb1 += 4; - rb2 += 4; - rb3 += 4; - } -} - - -void mask_array(unsigned int mask, float filt[3][3]) -{ - float **fmask1 = R.samples->fmask1, **fmask2 = R.samples->fmask2; - unsigned int maskand = (mask & 255); - unsigned int maskshift = (mask >> 8); - int a, j; - - for (j = 2; j >= 0; j--) { - - a = j; - - filt[2][2 - j] = *(fmask1[a] + maskand) + *(fmask2[a] + maskshift); - - a += 3; - - filt[1][2 - j] = *(fmask1[a] + maskand) + *(fmask2[a] + maskshift); - - a += 3; - - filt[0][2 - j] = *(fmask1[a] + maskand) + *(fmask2[a] + maskshift); - } -} - - -/** - * Index ordering, scanline based: - * - * <pre> - * --- --- --- - * | 2,0 | 2,1 | 2,2 | - * --- --- --- - * | 1,0 | 1,1 | 1,2 | - * --- --- --- - * | 0,0 | 0,1 | 0,2 | - * --- --- --- - * </pre> - */ - -void add_filt_fmask_coord(float filt[3][3], const float col[4], float *rowbuf, int row_stride, int x, int y, rcti *mask) -{ - float *fpoin[3][3]; - float val, r, g, b, al, lfilt[3][3]; - - r = col[0]; - g = col[1]; - b = col[2]; - al = col[3]; - - memcpy(lfilt, filt, sizeof(lfilt)); - - fpoin[0][1] = rowbuf - 4 * row_stride; - fpoin[1][1] = rowbuf; - fpoin[2][1] = rowbuf + 4 * row_stride; - - fpoin[0][0] = fpoin[0][1] - 4; - fpoin[1][0] = fpoin[1][1] - 4; - fpoin[2][0] = fpoin[2][1] - 4; - - fpoin[0][2] = fpoin[0][1] + 4; - fpoin[1][2] = fpoin[1][1] + 4; - fpoin[2][2] = fpoin[2][1] + 4; - - /* limit filtering to withing a mask for border rendering, so pixels don't - * leak outside of the border */ - if (y <= mask->ymin) { - fpoin[0][0] = fpoin[1][0]; - fpoin[0][1] = fpoin[1][1]; - fpoin[0][2] = fpoin[1][2]; - /* filter needs the opposite value yes! */ - lfilt[0][0] = filt[2][0]; - lfilt[0][1] = filt[2][1]; - lfilt[0][2] = filt[2][2]; - } - else if (y >= mask->ymax - 1) { - fpoin[2][0] = fpoin[1][0]; - fpoin[2][1] = fpoin[1][1]; - fpoin[2][2] = fpoin[1][2]; - - lfilt[2][0] = filt[0][0]; - lfilt[2][1] = filt[0][1]; - lfilt[2][2] = filt[0][2]; - } - - if (x <= mask->xmin) { - fpoin[2][0] = fpoin[2][1]; - fpoin[1][0] = fpoin[1][1]; - fpoin[0][0] = fpoin[0][1]; - - lfilt[2][0] = filt[2][2]; - lfilt[1][0] = filt[1][2]; - lfilt[0][0] = filt[0][2]; - } - else if (x >= mask->xmax - 1) { - fpoin[2][2] = fpoin[2][1]; - fpoin[1][2] = fpoin[1][1]; - fpoin[0][2] = fpoin[0][1]; - - lfilt[2][2] = filt[2][0]; - lfilt[1][2] = filt[1][0]; - lfilt[0][2] = filt[0][0]; - } - - - /* loop unroll */ -#define MASKFILT(i, j) \ - val = lfilt[i][j]; \ - if (val != 0.0f) { \ - float *fp = fpoin[i][j]; \ - fp[0] += val * r; \ - fp[1] += val * g; \ - fp[2] += val * b; \ - fp[3] += val * al; \ - } (void)0 - - MASKFILT(0, 0); - MASKFILT(0, 1); - MASKFILT(0, 2); - MASKFILT(1, 0); - MASKFILT(1, 1); - MASKFILT(1, 2); - MASKFILT(2, 0); - MASKFILT(2, 1); - MASKFILT(2, 2); - -#undef MASKFILT -} - -void add_filt_fmask_pixsize(unsigned int mask, float *in, float *rowbuf, int row_w, int pixsize) -{ - /* calc the value of mask */ - float **fmask1 = R.samples->fmask1, **fmask2 = R.samples->fmask2; - float *rb1, *rb2, *rb3; - float val; - unsigned int a, maskand, maskshift; - int i, j; - - rb2 = rowbuf - pixsize; - rb3 = rb2 - pixsize * row_w; - rb1 = rb2 + pixsize * row_w; - - maskand = (mask & 255); - maskshift = (mask >> 8); - - for (j = 2; j >= 0; j--) { - - a = j; - - val = *(fmask1[a] + maskand) + *(fmask2[a] + maskshift); - if (val != 0.0f) { - for (i = 0; i < pixsize; i++) - rb1[i] += val * in[i]; - } - a += 3; - - val = *(fmask1[a] + maskand) + *(fmask2[a] + maskshift); - if (val != 0.0f) { - for (i = 0; i < pixsize; i++) - rb2[i] += val * in[i]; - } - a += 3; - - val = *(fmask1[a] + maskand) + *(fmask2[a] + maskshift); - if (val != 0.0f) { - for (i = 0; i < pixsize; i++) - rb3[i] += val * in[i]; - } - - rb1 += pixsize; - rb2 += pixsize; - rb3 += pixsize; - } -} - -/* ------------------------------------------------------------------------- */ -void addalphaAddFloat(float dest[4], const float source[4]) -{ - - /* Makes me wonder whether this is required... */ - if (dest[3] < RE_EMPTY_COLOR_FLOAT) { - dest[0] = source[0]; - dest[1] = source[1]; - dest[2] = source[2]; - dest[3] = source[3]; - return; - } - - /* no clipping! */ - dest[0] = dest[0] + source[0]; - dest[1] = dest[1] + source[1]; - dest[2] = dest[2] + source[2]; - dest[3] = dest[3] + source[3]; - -} - - -/* ---------------------------------------------------------------------------- */ diff --git a/source/blender/render/intern/source/pixelshading.c b/source/blender/render/intern/source/pixelshading.c deleted file mode 100644 index 7f202629ce4..00000000000 --- a/source/blender/render/intern/source/pixelshading.c +++ /dev/null @@ -1,650 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * Contributor(s): 2004-2006, Blender Foundation, full recode - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/render/intern/source/pixelshading.c - * \ingroup render - */ - - -#include <float.h> -#include <math.h> -#include <string.h> - -#include "BLI_math.h" -#include "BLI_utildefines.h" - -/* External modules: */ - -#include "DNA_group_types.h" -#include "DNA_material_types.h" -#include "DNA_object_types.h" -#include "DNA_image_types.h" -#include "DNA_texture_types.h" -#include "DNA_lamp_types.h" - -#include "BKE_material.h" - - -/* own module */ -#include "render_types.h" -#include "renderdatabase.h" -#include "texture.h" -#include "rendercore.h" -#include "shadbuf.h" -#include "pixelshading.h" -#include "sunsky.h" - -/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -/* defined in pipeline.c, is hardcopy of active dynamic allocated Render */ -/* only to be used here in this file, it's for speed */ -extern struct Render R; -/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ - - -extern const float hashvectf[]; - -static void render_lighting_halo(HaloRen *har, float col_r[3]) -{ - GroupObject *go; - LampRen *lar; - float i, inp, inpr, rco[3], dco[3], lv[3], lampdist, ld, t, *vn; - float ir, ig, ib, shadfac, soft, lacol[3]; - - ir= ig= ib= 0.0; - - copy_v3_v3(rco, har->co); - dco[0]=dco[1]=dco[2]= 1.0f/har->rad; - - vn= har->no; - - for (go=R.lights.first; go; go= go->next) { - lar= go->lampren; - - /* test for lamplayer */ - if (lar->mode & LA_LAYER) if ((lar->lay & har->lay)==0) continue; - - /* lampdist cacluation */ - if (lar->type==LA_SUN || lar->type==LA_HEMI) { - copy_v3_v3(lv, lar->vec); - lampdist= 1.0; - } - else { - lv[0]= rco[0]-lar->co[0]; - lv[1]= rco[1]-lar->co[1]; - lv[2]= rco[2]-lar->co[2]; - ld = len_v3(lv); - lv[0]/= ld; - lv[1]/= ld; - lv[2]/= ld; - - /* ld is re-used further on (texco's) */ - - if (lar->mode & LA_QUAD) { - t= 1.0; - if (lar->ld1>0.0f) - t= lar->dist/(lar->dist+lar->ld1*ld); - if (lar->ld2>0.0f) - t*= lar->distkw/(lar->distkw+lar->ld2*ld*ld); - - lampdist= t; - } - else { - lampdist= (lar->dist/(lar->dist+ld)); - } - - if (lar->mode & LA_SPHERE) { - t= lar->dist - ld; - if (t<0.0f) continue; - - t/= lar->dist; - lampdist*= (t); - } - - } - - lacol[0]= lar->r; - lacol[1]= lar->g; - lacol[2]= lar->b; - - if (lar->mode & LA_TEXTURE) { - ShadeInput shi; - - /* Warning, This is not that nice, and possibly a bit slow, - * however some variables were not initialized properly in, unless using shade_input_initialize(...), - * we need to do a memset */ - memset(&shi, 0, sizeof(ShadeInput)); - /* end warning! - Campbell */ - - copy_v3_v3(shi.co, rco); - shi.osatex= 0; - do_lamp_tex(lar, lv, &shi, lacol, LA_TEXTURE); - } - - if (lar->type==LA_SPOT) { - - if (lar->mode & LA_SQUARE) { - if (lv[0]*lar->vec[0]+lv[1]*lar->vec[1]+lv[2]*lar->vec[2]>0.0f) { - float x, lvrot[3]; - - /* rotate view to lampspace */ - copy_v3_v3(lvrot, lv); - mul_m3_v3(lar->imat, lvrot); - - x = max_ff(fabsf(lvrot[0]/lvrot[2]), fabsf(lvrot[1]/lvrot[2])); - /* 1.0/(sqrt(1+x*x)) is equivalent to cos(atan(x)) */ - - inpr = 1.0f / (sqrtf(1.0f + x * x)); - } - else inpr= 0.0; - } - else { - inpr= lv[0]*lar->vec[0]+lv[1]*lar->vec[1]+lv[2]*lar->vec[2]; - } - - t= lar->spotsi; - if (inpr<t) continue; - else { - t= inpr-t; - soft= 1.0; - if (t<lar->spotbl && lar->spotbl!=0.0f) { - /* soft area */ - i= t/lar->spotbl; - t= i*i; - soft= (3.0f*t-2.0f*t*i); - inpr*= soft; - } - if (lar->mode & LA_ONLYSHADOW) { - /* if (ma->mode & MA_SHADOW) { */ - /* dot product positive: front side face! */ - inp= vn[0]*lv[0] + vn[1]*lv[1] + vn[2]*lv[2]; - if (inp>0.0f) { - /* testshadowbuf==0.0 : 100% shadow */ - shadfac = testshadowbuf(&R, lar->shb, rco, dco, dco, inp, 0.0f); - if ( shadfac>0.0f ) { - shadfac*= inp*soft*lar->energy; - ir -= shadfac; - ig -= shadfac; - ib -= shadfac; - - continue; - } - } - /* } */ - } - lampdist*=inpr; - } - if (lar->mode & LA_ONLYSHADOW) continue; - - } - - /* dot product and reflectivity*/ - - inp = 1.0f - fabsf(dot_v3v3(vn, lv)); - - /* inp= cos(0.5*M_PI-acos(inp)); */ - - i= inp; - - if (lar->type==LA_HEMI) { - i= 0.5f*i+0.5f; - } - if (i>0.0f) { - i*= lampdist; - } - - /* shadow */ - if (i> -0.41f) { /* heuristic valua! */ - if (lar->shb) { - shadfac = testshadowbuf(&R, lar->shb, rco, dco, dco, inp, 0.0f); - if (shadfac==0.0f) continue; - i*= shadfac; - } - } - - if (i>0.0f) { - ir+= i*lacol[0]; - ig+= i*lacol[1]; - ib+= i*lacol[2]; - } - } - - if (ir<0.0f) ir= 0.0f; - if (ig<0.0f) ig= 0.0f; - if (ib<0.0f) ib= 0.0f; - - col_r[0]*= ir; - col_r[1]*= ig; - col_r[2]*= ib; - -} - - -/** - * Converts a halo z-buffer value to distance from the camera's near plane - * \param z The z-buffer value to convert - * \return a distance from the camera's near plane in blender units - */ -static float haloZtoDist(int z) -{ - float zco = 0; - - if (z >= 0x7FFFFF) - return 10e10; - else { - zco = (float)z/(float)0x7FFFFF; - if (R.r.mode & R_ORTHO) - return (R.winmat[3][2] - zco*R.winmat[3][3])/(R.winmat[2][2]); - else - return (R.winmat[3][2])/(R.winmat[2][2] - R.winmat[2][3]*zco); - } -} - -/** - * \param col (float[4]) Store the rgb color here (with alpha) - * The alpha is used to blend the color to the background - * color_new = (1-alpha)*color_background + color - * \param zz The current zbuffer value at the place of this pixel - * \param dist Distance of the pixel from the center of the halo squared. Given in pixels - * \param xn The x coordinate of the pixel relaticve to the center of the halo. given in pixels - * \param yn The y coordinate of the pixel relaticve to the center of the halo. given in pixels - */ -int shadeHaloFloat(HaloRen *har, float col[4], int zz, - float dist, float xn, float yn, short flarec) -{ - /* fill in col */ - float t, zn, radist, ringf=0.0f, linef=0.0f, alpha, si, co; - int a; - - if (R.wrld.mode & WO_MIST) { - if (har->type & HA_ONLYSKY) { - alpha= har->alfa; - } - else { - /* a bit patchy... */ - alpha= mistfactor(-har->co[2], har->co)*har->alfa; - } - } - else alpha= har->alfa; - - if (alpha==0.0f) - return 0; - - /* soften the halo if it intersects geometry */ - if (har->mat && har->mat->mode & MA_HALO_SOFT) { - float segment_length, halo_depth, distance_from_z /* , visible_depth */ /* UNUSED */, soften; - - /* calculate halo depth */ - segment_length= har->hasize*sasqrt(1.0f - dist/(har->rad*har->rad)); - halo_depth= 2.0f*segment_length; - - if (halo_depth < FLT_EPSILON) - return 0; - - /* calculate how much of this depth is visible */ - distance_from_z = haloZtoDist(zz) - haloZtoDist(har->zs); - /* visible_depth = halo_depth; */ /* UNUSED */ - if (distance_from_z < segment_length) { - soften= (segment_length + distance_from_z)/halo_depth; - - /* apply softening to alpha */ - if (soften < 1.0f) - alpha *= soften; - if (alpha <= 0.0f) - return 0; - } - } - else { - /* not a soft halo. use the old softening code */ - /* halo being intersected? */ - if (har->zs> zz-har->zd) { - t= ((float)(zz-har->zs))/(float)har->zd; - alpha*= sqrtf(sqrtf(t)); - } - } - - radist = sqrtf(dist); - - /* watch it: not used nicely: flarec is set at zero in pixstruct */ - if (flarec) har->pixels+= (int)(har->rad-radist); - - if (har->ringc) { - const float *rc; - float fac; - int ofs; - - /* per ring an antialised circle */ - ofs= har->seed; - - for (a= har->ringc; a>0; a--, ofs+=2) { - - rc= hashvectf + (ofs % 768); - - fac = fabsf(rc[1] * (har->rad * fabsf(rc[0]) - radist)); - - if (fac< 1.0f) { - ringf+= (1.0f-fac); - } - } - } - - if (har->type & HA_VECT) { - dist= fabsf(har->cos * (yn) - har->sin * (xn)) / har->rad; - if (dist>1.0f) dist= 1.0f; - if (har->tex) { - zn= har->sin*xn - har->cos*yn; - yn= har->cos*xn + har->sin*yn; - xn= zn; - } - } - else dist= dist/har->radsq; - - if (har->type & HA_FLARECIRC) { - dist = 0.5f + fabsf(dist - 0.5f); - } - - if (har->hard>=30) { - dist = sqrtf(dist); - if (har->hard>=40) { - dist = sinf(dist*(float)M_PI_2); - if (har->hard>=50) { - dist = sqrtf(dist); - } - } - } - else if (har->hard<20) dist*=dist; - - if (dist < 1.0f) - dist= (1.0f-dist); - else - dist= 0.0f; - - if (har->linec) { - const float *rc; - float fac; - int ofs; - - /* per starpoint an antialiased line */ - ofs= har->seed; - - for (a= har->linec; a>0; a--, ofs+=3) { - - rc= hashvectf + (ofs % 768); - - fac = fabsf((xn) * rc[0] + (yn) * rc[1]); - - if (fac< 1.0f ) - linef+= (1.0f-fac); - } - - linef*= dist; - } - - if (har->starpoints) { - float ster, angle; - /* rotation */ - angle = atan2f(yn, xn); - angle *= (1.0f+0.25f*har->starpoints); - - co= cosf(angle); - si= sinf(angle); - - angle= (co*xn+si*yn)*(co*yn-si*xn); - - ster = fabsf(angle); - if (ster>1.0f) { - ster= (har->rad)/(ster); - - if (ster<1.0f) dist*= sqrtf(ster); - } - } - - /* disputable optimize... (ton) */ - if (dist<=0.00001f) - return 0; - - dist*= alpha; - ringf*= dist; - linef*= alpha; - - /* The color is either the rgb spec-ed by the user, or extracted from */ - /* the texture */ - if (har->tex) { - col[0]= har->r; - col[1]= har->g; - col[2]= har->b; - col[3]= dist; - - do_halo_tex(har, xn, yn, col); - - col[0]*= col[3]; - col[1]*= col[3]; - col[2]*= col[3]; - - } - else { - col[0]= dist*har->r; - col[1]= dist*har->g; - col[2]= dist*har->b; - if (har->type & HA_XALPHA) col[3]= dist*dist; - else col[3]= dist; - } - - if (har->mat) { - if (har->mat->mode & MA_HALO_SHADE) { - /* we test for lights because of preview... */ - if (R.lights.first) render_lighting_halo(har, col); - } - - /* Next, we do the line and ring factor modifications. */ - if (linef!=0.0f) { - Material *ma= har->mat; - - col[0]+= linef * ma->specr; - col[1]+= linef * ma->specg; - col[2]+= linef * ma->specb; - - if (har->type & HA_XALPHA) col[3]+= linef*linef; - else col[3]+= linef; - } - if (ringf!=0.0f) { - Material *ma= har->mat; - - col[0]+= ringf * ma->mirr; - col[1]+= ringf * ma->mirg; - col[2]+= ringf * ma->mirb; - - if (har->type & HA_XALPHA) col[3]+= ringf*ringf; - else col[3]+= ringf; - } - } - - /* alpha requires clip, gives black dots */ - if (col[3] > 1.0f) - col[3]= 1.0f; - - return 1; -} - -/* ------------------------------------------------------------------------- */ - -/* Only view vector is important here. Result goes to col_r[3] */ -void shadeSkyView(float col_r[3], const float rco[3], const float view[3], const float dxyview[2], short thread) -{ - float zen[3], hor[3], blend, blendm; - int skyflag; - - /* flag indicating if we render the top hemisphere */ - skyflag = WO_ZENUP; - - /* Some view vector stuff. */ - if (R.wrld.skytype & WO_SKYREAL) { - - blend = dot_v3v3(view, R.grvec); - - if (blend<0.0f) skyflag= 0; - - blend = fabsf(blend); - } - else if (R.wrld.skytype & WO_SKYPAPER) { - blend= 0.5f + 0.5f * view[1]; - } - else { - /* the fraction of how far we are above the bottom of the screen */ - blend = fabsf(0.5f + view[1]); - } - - copy_v3_v3(hor, &R.wrld.horr); - copy_v3_v3(zen, &R.wrld.zenr); - - /* Careful: SKYTEX and SKYBLEND are NOT mutually exclusive! If */ - /* SKYBLEND is active, the texture and color blend are added. */ - if (R.wrld.skytype & WO_SKYTEX) { - float lo[3]; - copy_v3_v3(lo, view); - if (R.wrld.skytype & WO_SKYREAL) { - - mul_m3_v3(R.imat, lo); - - SWAP(float, lo[1], lo[2]); - - } - do_sky_tex(rco, view, lo, dxyview, hor, zen, &blend, skyflag, thread); - } - - if (blend>1.0f) blend= 1.0f; - blendm= 1.0f-blend; - - /* No clipping, no conversion! */ - if (R.wrld.skytype & WO_SKYBLEND) { - col_r[0] = (blendm*hor[0] + blend*zen[0]); - col_r[1] = (blendm*hor[1] + blend*zen[1]); - col_r[2] = (blendm*hor[2] + blend*zen[2]); - } - else { - /* Done when a texture was grabbed. */ - col_r[0]= hor[0]; - col_r[1]= hor[1]; - col_r[2]= hor[2]; - } -} - -/* shade sky according to sun lamps, all parameters are like shadeSkyView except sunsky*/ -void shadeSunView(float col_r[3], const float view[3]) -{ - GroupObject *go; - LampRen *lar; - float sview[3]; - bool do_init = true; - - for (go=R.lights.first; go; go= go->next) { - lar= go->lampren; - if (lar->type==LA_SUN && lar->sunsky && (lar->sunsky->effect_type & LA_SUN_EFFECT_SKY)) { - float sun_collector[3]; - float colorxyz[3]; - - if (do_init) { - - normalize_v3_v3(sview, view); - mul_m3_v3(R.imat, sview); - if (sview[2] < 0.0f) - sview[2] = 0.0f; - normalize_v3(sview); - do_init = false; - } - - GetSkyXYZRadiancef(lar->sunsky, sview, colorxyz); - xyz_to_rgb(colorxyz[0], colorxyz[1], colorxyz[2], &sun_collector[0], &sun_collector[1], &sun_collector[2], - lar->sunsky->sky_colorspace); - - ramp_blend(lar->sunsky->skyblendtype, col_r, lar->sunsky->skyblendfac, sun_collector); - } - } -} - - -/* - * Stuff the sky color into the collector. - */ -void shadeSkyPixel(float collector[4], float fx, float fy, short thread) -{ - float view[3], dxyview[2]; - - /* - * The rules for sky: - * 1. Draw an image, if a background image was provided. Stop - * 2. get texture and color blend, and combine these. - */ - - float fac; - - if ((R.wrld.skytype & (WO_SKYBLEND+WO_SKYTEX))==0) { - /* 1. solid color */ - copy_v3_v3(collector, &R.wrld.horr); - - collector[3] = 0.0f; - } - else { - /* 2. */ - - /* This one true because of the context of this routine */ - if (R.wrld.skytype & WO_SKYPAPER) { - view[0]= -1.0f + 2.0f*(fx/(float)R.winx); - view[1]= -1.0f + 2.0f*(fy/(float)R.winy); - view[2]= 0.0; - - dxyview[0]= 1.0f/(float)R.winx; - dxyview[1]= 1.0f/(float)R.winy; - } - else { - calc_view_vector(view, fx, fy); - fac= normalize_v3(view); - - if (R.wrld.skytype & WO_SKYTEX) { - dxyview[0]= -R.viewdx/fac; - dxyview[1]= -R.viewdy/fac; - } - } - - /* get sky color in the collector */ - shadeSkyView(collector, NULL, view, dxyview, thread); - collector[3] = 0.0f; - } - - calc_view_vector(view, fx, fy); - shadeSunView(collector, view); -} - -/* aerial perspective */ -void shadeAtmPixel(struct SunSky *sunsky, float collector[3], float fx, float fy, float distance) -{ - float view[3]; - - calc_view_vector(view, fx, fy); - normalize_v3(view); - /*mul_m3_v3(R.imat, view);*/ - AtmospherePixleShader(sunsky, view, distance, collector); -} - -/* eof */ diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c deleted file mode 100644 index df1cb868230..00000000000 --- a/source/blender/render/intern/source/rayshade.c +++ /dev/null @@ -1,2503 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 1990-1998 NeoGeo BV. - * All rights reserved. - * - * Contributors: 2004/2005 Blender Foundation, full recode - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/render/intern/source/rayshade.c - * \ingroup render - */ - -#include <stdio.h> -#include <math.h> -#include <string.h> -#include <stdlib.h> -#include <float.h> -#include <assert.h> - -#include "MEM_guardedalloc.h" - -#include "DNA_material_types.h" -#include "DNA_lamp_types.h" - -#include "BLI_blenlib.h" -#include "BLI_system.h" -#include "BLI_math.h" -#include "BLI_rand.h" -#include "BLI_utildefines.h" - -#include "BLT_translation.h" - -#include "BKE_node.h" - -#include "render_result.h" -#include "render_types.h" -#include "rendercore.h" -#include "renderdatabase.h" -#include "pixelshading.h" -#include "shading.h" -#include "volumetric.h" - -#include "rayintersection.h" -#include "rayobject.h" -#include "raycounter.h" - -#define RAY_TRA 1 -#define RAY_INSIDE 2 - -#define DEPTH_SHADOW_TRA 10 - -/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -/* defined in pipeline.c, is hardcopy of active dynamic allocated Render */ -/* only to be used here in this file, it's for speed */ -extern struct Render R; -/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -static int test_break(void *data) -{ - Render *re = (Render *)data; - return re->test_break(re->tbh); -} - -static void RE_rayobject_config_control(RayObject *r, Render *re) -{ - if (RE_rayobject_isRayAPI(r)) { - r = RE_rayobject_align(r); - r->control.data = re; - r->control.test_break = test_break; - } -} - -RayObject *RE_rayobject_create(int type, int size, int octree_resolution) -{ - RayObject * res = NULL; - - if (type == R_RAYSTRUCTURE_AUTO) { - /* TODO */ - //if (detect_simd()) -#ifdef __SSE__ - type = BLI_cpu_support_sse2()? R_RAYSTRUCTURE_SIMD_SVBVH: R_RAYSTRUCTURE_VBVH; -#else - type = R_RAYSTRUCTURE_VBVH; -#endif - } - -#ifndef __SSE__ - if (type == R_RAYSTRUCTURE_SIMD_SVBVH || type == R_RAYSTRUCTURE_SIMD_QBVH) { - puts("Warning: Using VBVH (SSE was disabled at compile time)"); - type = R_RAYSTRUCTURE_VBVH; - } -#endif - - - if (type == R_RAYSTRUCTURE_OCTREE) //TODO dynamic ocres - res = RE_rayobject_octree_create(octree_resolution, size); - else if (type == R_RAYSTRUCTURE_VBVH) - res = RE_rayobject_vbvh_create(size); - else if (type == R_RAYSTRUCTURE_SIMD_SVBVH) - res = RE_rayobject_svbvh_create(size); - else if (type == R_RAYSTRUCTURE_SIMD_QBVH) - res = RE_rayobject_qbvh_create(size); - else - res = RE_rayobject_vbvh_create(size); //Fallback - - return res; -} - -static RayObject* rayobject_create(Render *re, int type, int size) -{ - RayObject * res = NULL; - - res = RE_rayobject_create(type, size, re->r.ocres); - - if (res) - RE_rayobject_config_control(res, re); - - return res; -} - -#ifdef RE_RAYCOUNTER -RayCounter re_rc_counter[BLENDER_MAX_THREADS]; -#endif - - -void freeraytree(Render *re) -{ - ObjectInstanceRen *obi; - - if (re->raytree) { - RE_rayobject_free(re->raytree); - re->raytree = NULL; - } - if (re->rayfaces) { - MEM_freeN(re->rayfaces); - re->rayfaces = NULL; - } - if (re->rayprimitives) { - MEM_freeN(re->rayprimitives); - re->rayprimitives = NULL; - } - - for (obi=re->instancetable.first; obi; obi=obi->next) { - ObjectRen *obr = obi->obr; - if (obr->raytree) { - RE_rayobject_free(obr->raytree); - obr->raytree = NULL; - } - if (obr->rayfaces) { - MEM_freeN(obr->rayfaces); - obr->rayfaces = NULL; - } - if (obi->raytree) { - RE_rayobject_free(obi->raytree); - obi->raytree = NULL; - } - } - -#ifdef RE_RAYCOUNTER - { - const int num_threads = re->r.threads; - RayCounter sum; - memset(&sum, 0, sizeof(sum)); - int i; - for (i=0; i<num_threads; i++) - RE_RC_MERGE(&sum, re_rc_counter+i); - RE_RC_INFO(&sum); - } -#endif -} - -static bool is_raytraceable_vlr(Render *re, VlakRen *vlr) -{ - /* note: volumetric must be tracable, wire must not */ - if ((re->flag & R_BAKE_TRACE) || (vlr->flag & R_TRACEBLE) || (vlr->mat->material_type == MA_TYPE_VOLUME)) - if (vlr->mat->material_type != MA_TYPE_WIRE) - return 1; - return 0; -} - -static bool is_raytraceable(Render *re, ObjectInstanceRen *obi) -{ - int v; - ObjectRen *obr = obi->obr; - - if (re->excludeob && obr->ob == re->excludeob) - return 0; - - for (v=0;v<obr->totvlak;v++) { - VlakRen *vlr = obr->vlaknodes[v>>8].vlak + (v&255); - - if (is_raytraceable_vlr(re, vlr)) - return 1; - } - - return 0; -} - - -RayObject* makeraytree_object(Render *re, ObjectInstanceRen *obi) -{ - /*TODO - * out-of-memory safeproof - * break render - * update render stats */ - ObjectRen *obr = obi->obr; - - if (obr->raytree == NULL) { - RayObject *raytree; - RayFace *face = NULL; - VlakPrimitive *vlakprimitive = NULL; - int v; - - //Count faces - int faces = 0; - for (v=0;v<obr->totvlak;v++) { - VlakRen *vlr = obr->vlaknodes[v>>8].vlak + (v&255); - if (is_raytraceable_vlr(re, vlr)) - faces++; - } - - if (faces == 0) - return NULL; - - //Create Ray cast accelaration structure - raytree = rayobject_create( re, re->r.raytrace_structure, faces ); - if ( (re->r.raytrace_options & R_RAYTRACE_USE_LOCAL_COORDS) ) - vlakprimitive = obr->rayprimitives = (VlakPrimitive *)MEM_callocN(faces * sizeof(VlakPrimitive), "ObjectRen primitives"); - else - face = obr->rayfaces = (RayFace *)MEM_callocN(faces * sizeof(RayFace), "ObjectRen faces"); - - obr->rayobi = obi; - - for (v=0;v<obr->totvlak;v++) { - VlakRen *vlr = obr->vlaknodes[v>>8].vlak + (v&255); - if (is_raytraceable_vlr(re, vlr)) { - if ((re->r.raytrace_options & R_RAYTRACE_USE_LOCAL_COORDS)) { - RE_rayobject_add(raytree, RE_vlakprimitive_from_vlak(vlakprimitive, obi, vlr)); - vlakprimitive++; - } - else { - RE_rayface_from_vlak(face, obi, vlr); - RE_rayobject_add(raytree, RE_rayobject_unalignRayFace(face)); - face++; - } - } - } - RE_rayobject_done(raytree); - - /* in case of cancel during build, raytree is not usable */ - if (test_break(re)) - RE_rayobject_free(raytree); - else - obr->raytree= raytree; - } - - if (obr->raytree) { - if ((obi->flag & R_TRANSFORMED) && obi->raytree == NULL) { - obi->transform_primitives = 0; - obi->raytree = RE_rayobject_instance_create( obr->raytree, obi->mat, obi, obi->obr->rayobi ); - } - } - - if (obi->raytree) return obi->raytree; - return obi->obr->raytree; -} - -static bool has_special_rayobject(Render *re, ObjectInstanceRen *obi) -{ - if ( (obi->flag & R_TRANSFORMED) && (re->r.raytrace_options & R_RAYTRACE_USE_INSTANCES) ) { - ObjectRen *obr = obi->obr; - int v, faces = 0; - - for (v=0;v<obr->totvlak;v++) { - VlakRen *vlr = obr->vlaknodes[v>>8].vlak + (v&255); - if (is_raytraceable_vlr(re, vlr)) { - faces++; - if (faces > 4) - return 1; - } - } - } - return 0; -} -/* - * create a single raytrace structure with all faces - */ -static void makeraytree_single(Render *re) -{ - ObjectInstanceRen *obi; - RayObject *raytree; - RayFace *face = NULL; - VlakPrimitive *vlakprimitive = NULL; - int faces = 0, special = 0; - - for (obi = re->instancetable.first; obi; obi = obi->next) { - if (is_raytraceable(re, obi)) { - ObjectRen *obr = obi->obr; - - if (has_special_rayobject(re, obi)) { - special++; - } - else { - int v; - for (v = 0;v < obr->totvlak; v++) { - VlakRen *vlr = obr->vlaknodes[v >> 8].vlak + (v&255); - if (is_raytraceable_vlr(re, vlr)) { - faces++; - } - } - } - } - } - - if (faces + special == 0) { - re->raytree = RE_rayobject_empty_create(); - return; - } - - //Create raytree - raytree = re->raytree = rayobject_create( re, re->r.raytrace_structure, faces+special ); - - if ( (re->r.raytrace_options & R_RAYTRACE_USE_LOCAL_COORDS) ) { - vlakprimitive = re->rayprimitives = (VlakPrimitive *)MEM_callocN(faces * sizeof(VlakPrimitive), "Raytrace vlak-primitives"); - } - else { - face = re->rayfaces = (RayFace *)MEM_callocN(faces * sizeof(RayFace), "Render ray faces"); - } - - for (obi=re->instancetable.first; obi; obi=obi->next) - if (is_raytraceable(re, obi)) { - if (test_break(re)) - break; - - if (has_special_rayobject(re, obi)) { - RayObject *obj = makeraytree_object(re, obi); - - if (test_break(re)) - break; - - if (obj) - RE_rayobject_add(re->raytree, obj); - } - else { - int v; - ObjectRen *obr = obi->obr; - - if (obi->flag & R_TRANSFORMED) { - obi->transform_primitives = 1; - } - - for (v=0;v<obr->totvlak;v++) { - VlakRen *vlr = obr->vlaknodes[v>>8].vlak + (v&255); - if (is_raytraceable_vlr(re, vlr)) { - if ((re->r.raytrace_options & R_RAYTRACE_USE_LOCAL_COORDS)) { - RayObject *obj = RE_vlakprimitive_from_vlak( vlakprimitive, obi, vlr ); - RE_rayobject_add(raytree, obj); - vlakprimitive++; - } - else { - RE_rayface_from_vlak(face, obi, vlr); - if ((obi->flag & R_TRANSFORMED)) { - mul_m4_v3(obi->mat, face->v1); - mul_m4_v3(obi->mat, face->v2); - mul_m4_v3(obi->mat, face->v3); - if (RE_rayface_isQuad(face)) - mul_m4_v3(obi->mat, face->v4); - } - - RE_rayobject_add(raytree, RE_rayobject_unalignRayFace(face)); - face++; - } - } - } - } - } - - if (!test_break(re)) { - re->i.infostr = IFACE_("Raytree.. building"); - re->stats_draw(re->sdh, &re->i); - - RE_rayobject_done(raytree); - } -} - -void makeraytree(Render *re) -{ - float min[3], max[3], sub[3]; - int i; - - re->i.infostr = IFACE_("Raytree.. preparing"); - re->stats_draw(re->sdh, &re->i); - - /* disable options not yet supported by octree, - * they might actually never be supported (unless people really need it) */ - if (re->r.raytrace_structure == R_RAYSTRUCTURE_OCTREE) - re->r.raytrace_options &= ~( R_RAYTRACE_USE_INSTANCES | R_RAYTRACE_USE_LOCAL_COORDS); - - makeraytree_single(re); - - if (test_break(re)) { - freeraytree(re); - - re->i.infostr = IFACE_("Raytree building canceled"); - re->stats_draw(re->sdh, &re->i); - } - else { - /* Calculate raytree max_size - * This is ONLY needed to kept a bogus behavior of SUN and HEMI lights */ - INIT_MINMAX(min, max); - RE_rayobject_merge_bb(re->raytree, min, max); - if (min[0] > max[0]) { /* empty raytree */ - zero_v3(min); - zero_v3(max); - } - for (i=0; i<3; i++) { - /* TODO: explain why add top both min and max??? */ - min[i] += 0.01f; - max[i] += 0.01f; - sub[i] = max[i]-min[i]; - } - - re->maxdist = len_v3(sub); - - re->i.infostr = IFACE_("Raytree finished"); - re->stats_draw(re->sdh, &re->i); - } - -#ifdef RE_RAYCOUNTER - memset(re_rc_counter, 0, sizeof(re_rc_counter)); -#endif -} - -/* if (shi->osatex) */ -static void shade_ray_set_derivative(ShadeInput *shi) -{ - float detsh, t00, t10, t01, t11; - int axis1, axis2; - - /* find most stable axis to project */ - axis_dominant_v3(&axis1, &axis2, shi->facenor); - - /* compute u,v and derivatives */ - if (shi->obi->flag & R_TRANSFORMED) { - float v1[3], v2[3], v3[3]; - - mul_v3_m3v3(v1, shi->obi->nmat, shi->v1->co); - mul_v3_m3v3(v2, shi->obi->nmat, shi->v2->co); - mul_v3_m3v3(v3, shi->obi->nmat, shi->v3->co); - - /* same as below */ - t00= v3[axis1]-v1[axis1]; t01= v3[axis2]-v1[axis2]; - t10= v3[axis1]-v2[axis1]; t11= v3[axis2]-v2[axis2]; - } - else { - const float *v1= shi->v1->co; - const float *v2= shi->v2->co; - const float *v3= shi->v3->co; - - /* same as above */ - t00= v3[axis1]-v1[axis1]; t01= v3[axis2]-v1[axis2]; - t10= v3[axis1]-v2[axis1]; t11= v3[axis2]-v2[axis2]; - } - - detsh= 1.0f/(t00*t11-t10*t01); - t00*= detsh; t01*=detsh; - t10*=detsh; t11*=detsh; - - shi->dx_u= shi->dxco[axis1]*t11- shi->dxco[axis2]*t10; - shi->dx_v= shi->dxco[axis2]*t00- shi->dxco[axis1]*t01; - shi->dy_u= shi->dyco[axis1]*t11- shi->dyco[axis2]*t10; - shi->dy_v= shi->dyco[axis2]*t00- shi->dyco[axis1]*t01; - -} - -/* main ray shader */ -void shade_ray(Isect *is, ShadeInput *shi, ShadeResult *shr) -{ - ObjectInstanceRen *obi = (ObjectInstanceRen *)is->hit.ob; - VlakRen *vlr = (VlakRen *)is->hit.face; - - /* set up view vector */ - copy_v3_v3(shi->view, is->dir); - - /* render co */ - shi->co[0]= is->start[0]+is->dist*(shi->view[0]); - shi->co[1]= is->start[1]+is->dist*(shi->view[1]); - shi->co[2]= is->start[2]+is->dist*(shi->view[2]); - - normalize_v3(shi->view); - - shi->obi= obi; - shi->obr= obi->obr; - shi->vlr= vlr; - shi->mat= vlr->mat; - shade_input_init_material(shi); - - if (is->isect==2) - shade_input_set_triangle_i(shi, obi, vlr, 0, 2, 3); - else - shade_input_set_triangle_i(shi, obi, vlr, 0, 1, 2); - - shi->u= is->u; - shi->v= is->v; - shi->dx_u= shi->dx_v= shi->dy_u= shi->dy_v= 0.0f; - - if (shi->osatex) - shade_ray_set_derivative(shi); - shade_input_set_normals(shi); - - shade_input_set_shade_texco(shi); - if (shi->mat->material_type == MA_TYPE_VOLUME) { - if (ELEM(is->mode, RE_RAY_SHADOW, RE_RAY_SHADOW_TRA)) { - shade_volume_shadow(shi, shr, is); - } - else { - shade_volume_outside(shi, shr); - } - } - else if (is->mode==RE_RAY_SHADOW_TRA) { - /* temp hack to prevent recursion */ - if (shi->nodes==0 && shi->mat->nodetree && shi->mat->use_nodes) { - ntreeShaderExecTree(shi->mat->nodetree, shi, shr); - shi->mat= vlr->mat; /* shi->mat is being set in nodetree */ - } - else - shade_color(shi, shr); - } - else { - if (shi->mat->nodetree && shi->mat->use_nodes) { - ntreeShaderExecTree(shi->mat->nodetree, shi, shr); - shi->mat= vlr->mat; /* shi->mat is being set in nodetree */ - } - else { - shade_material_loop(shi, shr); - } - - /* raytrace likes to separate the spec color */ - sub_v3_v3v3(shr->diff, shr->combined, shr->spec); - copy_v3_v3(shr->diffshad, shr->diff); - } - -} - -static int refraction(float refract[3], const float n[3], const float view[3], float index) -{ - float dot, fac; - - copy_v3_v3(refract, view); - - dot = dot_v3v3(view, n); - - if (dot>0.0f) { - index = 1.0f/index; - fac= 1.0f - (1.0f - dot*dot)*index*index; - if (fac <= 0.0f) return 0; - fac= -dot*index + sqrtf(fac); - } - else { - fac= 1.0f - (1.0f - dot*dot)*index*index; - if (fac <= 0.0f) return 0; - fac= -dot*index - sqrtf(fac); - } - - refract[0]= index*view[0] + fac*n[0]; - refract[1]= index*view[1] + fac*n[1]; - refract[2]= index*view[2] + fac*n[2]; - - return 1; -} - -static void reflection_simple(float ref[3], float n[3], const float view[3]) -{ - const float f1= -2.0f * dot_v3v3(n, view); - madd_v3_v3v3fl(ref, view, n, f1); -} - -/* orn = original face normal */ -static void reflection(float ref[3], float n[3], const float view[3], const float orn[3]) -{ - float f1; - - reflection_simple(ref, n, view); - - /* test phong normals, then we should prevent vector going to the back */ - f1= dot_v3v3(ref, orn); - if (f1>0.0f) { - f1+= 0.01f; - ref[0]-= f1*orn[0]; - ref[1]-= f1*orn[1]; - ref[2]-= f1*orn[2]; - } -} - -#if 0 -static void color_combine(float *result, float fac1, float fac2, float col1[3], float col2[3]) -{ - float col1t[3], col2t[3]; - - col1t[0]= sqrt(col1[0]); - col1t[1]= sqrt(col1[1]); - col1t[2]= sqrt(col1[2]); - col2t[0]= sqrt(col2[0]); - col2t[1]= sqrt(col2[1]); - col2t[2]= sqrt(col2[2]); - - result[0]= (fac1*col1t[0] + fac2*col2t[0]); - result[0]*= result[0]; - result[1]= (fac1*col1t[1] + fac2*col2t[1]); - result[1]*= result[1]; - result[2]= (fac1*col1t[2] + fac2*col2t[2]); - result[2]*= result[2]; -} -#endif - -static float shade_by_transmission(Isect *is, ShadeInput *shi, ShadeResult *shr) -{ - float d; - if (0 == (shi->mat->mode & MA_TRANSP)) - return -1; - - if (shi->mat->tx_limit <= 0.0f) { - d= 1.0f; - } - else { - float p; - - /* shi.co[] calculated by shade_ray() */ - const float dx= shi->co[0] - is->start[0]; - const float dy= shi->co[1] - is->start[1]; - const float dz= shi->co[2] - is->start[2]; - d = sqrtf(dx * dx + dy * dy + dz * dz); - if (d > shi->mat->tx_limit) - d= shi->mat->tx_limit; - - p = shi->mat->tx_falloff; - if (p < 0.0f) p= 0.0f; - else if (p > 10.0f) p= 10.0f; - - shr->alpha *= powf(d, p); - if (shr->alpha > 1.0f) - shr->alpha= 1.0f; - } - - return d; -} - -static void ray_fadeout_endcolor(float col[3], ShadeInput *origshi, ShadeInput *shi, ShadeResult *shr, Isect *isec, const float vec[3]) -{ - /* un-intersected rays get either rendered material color or sky color */ - if (origshi->mat->fadeto_mir == MA_RAYMIR_FADETOMAT) { - copy_v3_v3(col, shr->combined); - } - else if (origshi->mat->fadeto_mir == MA_RAYMIR_FADETOSKY) { - copy_v3_v3(shi->view, vec); - normalize_v3(shi->view); - - shadeSkyView(col, isec->start, shi->view, NULL, shi->thread); - shadeSunView(col, shi->view); - } -} - -static void ray_fadeout(Isect *is, ShadeInput *shi, float col[3], const float blendcol[3], float dist_mir) -{ - /* if fading out, linear blend against fade color */ - float blendfac; - - blendfac = 1.0f - len_v3v3(shi->co, is->start)/dist_mir; - - col[0] = col[0]*blendfac + (1.0f - blendfac)*blendcol[0]; - col[1] = col[1]*blendfac + (1.0f - blendfac)*blendcol[1]; - col[2] = col[2]*blendfac + (1.0f - blendfac)*blendcol[2]; -} - -/* the main recursive tracer itself - * note: 'col' must be initialized */ -static void traceray(ShadeInput *origshi, ShadeResult *origshr, short depth, const float start[3], const float dir[3], float col[4], ObjectInstanceRen *obi, VlakRen *vlr, int traflag) -{ - ShadeInput shi = {NULL}; - Isect isec; - float dist_mir = origshi->mat->dist_mir; - - /* with high depth the number of rays can explode due to the path splitting - * in two each time, giving 2^depth rays. we need to be able to cancel such - * a render to avoid hanging, a better solution would be random picking - * between directions and russian roulette termination */ - if (R.test_break(R.tbh)) { - zero_v4(col); - return; - } - - copy_v3_v3(isec.start, start); - copy_v3_v3(isec.dir, dir); - isec.dist = dist_mir > 0 ? dist_mir : RE_RAYTRACE_MAXDIST; - isec.mode= RE_RAY_MIRROR; - isec.check = RE_CHECK_VLR_RENDER; - isec.skip = RE_SKIP_VLR_NEIGHBOUR; - isec.hint = NULL; - - isec.orig.ob = obi; - isec.orig.face = vlr; - RE_RC_INIT(isec, shi); - - /* database is in original view, obi->imat transforms current position back to original */ - RE_instance_rotate_ray(origshi->obi, &isec); - - if (RE_rayobject_raycast(R.raytree, &isec)) { - ShadeResult shr= {{0}}; - float d= 1.0f; - - RE_instance_rotate_ray_restore(origshi->obi, &isec); - - /* for as long we don't have proper dx/dy transform for rays we copy over original */ - copy_v3_v3(shi.dxco, origshi->dxco); - copy_v3_v3(shi.dyco, origshi->dyco); - - shi.mask= origshi->mask; - shi.osatex= origshi->osatex; - shi.depth= origshi->depth + 1; /* only used to indicate tracing */ - shi.thread= origshi->thread; - //shi.sample= 0; // memset above, so don't need this - shi.xs= origshi->xs; - shi.ys= origshi->ys; - shi.do_manage= origshi->do_manage; - shi.lay= origshi->lay; - shi.passflag= SCE_PASS_COMBINED; /* result of tracing needs no pass info */ - shi.combinedflag= 0xFFFFFF; /* ray trace does all options */ - //shi.do_preview = false; // memset above, so don't need this - shi.light_override= origshi->light_override; - shi.mat_override= origshi->mat_override; - - shade_ray(&isec, &shi, &shr); - /* ray has traveled inside the material, so shade by transmission */ - if (traflag & RAY_INSIDE) - d= shade_by_transmission(&isec, &shi, &shr); - - if (depth>0) { - float fr, fg, fb, f1; - - if ((shi.mat->mode_l & MA_TRANSP) && shr.alpha < 1.0f && (shi.mat->mode_l & (MA_ZTRANSP | MA_RAYTRANSP))) { - float nf, f, refract[3], tracol[4]; - - tracol[0]= shi.r; - tracol[1]= shi.g; - tracol[2]= shi.b; - tracol[3]= col[3]; /* we pass on and accumulate alpha */ - - if ((shi.mat->mode & MA_TRANSP) && (shi.mat->mode & MA_RAYTRANSP)) { - /* don't overwrite traflag, it's value is used in mirror reflection */ - int new_traflag = traflag; - - if (new_traflag & RAY_INSIDE) { - /* inside the material, so use inverse normal */ - float norm[3]; - norm[0]= - shi.vn[0]; - norm[1]= - shi.vn[1]; - norm[2]= - shi.vn[2]; - - if (refraction(refract, norm, shi.view, shi.ang)) { - /* ray comes out from the material into air */ - new_traflag &= ~RAY_INSIDE; - } - else { - /* total internal reflection (ray stays inside the material) */ - reflection(refract, norm, shi.view, shi.vn); - } - } - else { - if (refraction(refract, shi.vn, shi.view, shi.ang)) { - /* ray goes in to the material from air */ - new_traflag |= RAY_INSIDE; - } - else { - /* total external reflection (ray doesn't enter the material) */ - reflection(refract, shi.vn, shi.view, shi.vn); - } - } - traceray(origshi, origshr, depth-1, shi.co, refract, tracol, shi.obi, shi.vlr, new_traflag); - } - else - traceray(origshi, origshr, depth-1, shi.co, shi.view, tracol, shi.obi, shi.vlr, 0); - - f= shr.alpha; f1= 1.0f-f; - nf= (shi.mat->mode & MA_RAYTRANSP) ? d * shi.mat->filter : 0.0f; - fr= 1.0f+ nf*(shi.r-1.0f); - fg= 1.0f+ nf*(shi.g-1.0f); - fb= 1.0f+ nf*(shi.b-1.0f); - shr.diff[0]= f*shr.diff[0] + f1*fr*tracol[0]; - shr.diff[1]= f*shr.diff[1] + f1*fg*tracol[1]; - shr.diff[2]= f*shr.diff[2] + f1*fb*tracol[2]; - - shr.spec[0] *=f; - shr.spec[1] *=f; - shr.spec[2] *=f; - - col[3]= f1*tracol[3] + f; - } - else { - col[3]= 1.0f; - } - - float f; - if (shi.mat->mode_l & MA_RAYMIRROR) { - f= shi.ray_mirror; - if (f!=0.0f) f*= fresnel_fac(shi.view, shi.vn, shi.mat->fresnel_mir_i, shi.mat->fresnel_mir); - } - else f= 0.0f; - - if (f!=0.0f) { - float mircol[4]; - float ref[3]; - - reflection_simple(ref, shi.vn, shi.view); - traceray(origshi, origshr, depth-1, shi.co, ref, mircol, shi.obi, shi.vlr, traflag); - - f1= 1.0f-f; - - /* combine */ - //color_combine(col, f*fr*(1.0f-shr.spec[0]), f1, col, shr.diff); - //col[0]+= shr.spec[0]; - //col[1]+= shr.spec[1]; - //col[2]+= shr.spec[2]; - - fr= shi.mirr; - fg= shi.mirg; - fb= shi.mirb; - - col[0]= f*fr*(1.0f-shr.spec[0])*mircol[0] + f1*shr.diff[0] + shr.spec[0]; - col[1]= f*fg*(1.0f-shr.spec[1])*mircol[1] + f1*shr.diff[1] + shr.spec[1]; - col[2]= f*fb*(1.0f-shr.spec[2])*mircol[2] + f1*shr.diff[2] + shr.spec[2]; - } - else { - col[0]= shr.diff[0] + shr.spec[0]; - col[1]= shr.diff[1] + shr.spec[1]; - col[2]= shr.diff[2] + shr.spec[2]; - } - - if (dist_mir > 0.0f) { - float blendcol[3]; - - /* max ray distance set, but found an intersection, so fade this color - * out towards the sky/material color for a smooth transition */ - ray_fadeout_endcolor(blendcol, origshi, &shi, origshr, &isec, dir); - ray_fadeout(&isec, &shi, col, blendcol, dist_mir); - } - } - else { - col[0]= shr.diff[0] + shr.spec[0]; - col[1]= shr.diff[1] + shr.spec[1]; - col[2]= shr.diff[2] + shr.spec[2]; - } - - } - else { - ray_fadeout_endcolor(col, origshi, &shi, origshr, &isec, dir); - } - RE_RC_MERGE(&origshi->raycounter, &shi.raycounter); -} - -/* **************** jitter blocks ********** */ - -/* calc distributed planar energy */ - -static void DP_energy(float *table, float vec[2], int tot, float xsize, float ysize) -{ - int x, y, a; - float *fp, force[3], result[3]; - float dx, dy, dist, min; - - min= MIN2(xsize, ysize); - min*= min; - result[0]= result[1]= 0.0f; - - for (y= -1; y<2; y++) { - dy= ysize*y; - for (x= -1; x<2; x++) { - dx= xsize*x; - fp= table; - for (a=0; a<tot; a++, fp+= 2) { - force[0]= vec[0] - fp[0]-dx; - force[1]= vec[1] - fp[1]-dy; - dist= force[0]*force[0] + force[1]*force[1]; - if (dist < min && dist>0.0f) { - result[0]+= force[0]/dist; - result[1]+= force[1]/dist; - } - } - } - } - vec[0] += 0.1f*min*result[0]/(float)tot; - vec[1] += 0.1f*min*result[1]/(float)tot; - /* cyclic clamping */ - vec[0]= vec[0] - xsize*floorf(vec[0]/xsize + 0.5f); - vec[1]= vec[1] - ysize*floorf(vec[1]/ysize + 0.5f); -} - -/* random offset of 1 in 2 */ -static void jitter_plane_offset(float *jitter1, float *jitter2, int tot, float sizex, float sizey, float ofsx, float ofsy) -{ - float dsizex= sizex*ofsx; - float dsizey= sizey*ofsy; - float hsizex= 0.5f*sizex, hsizey= 0.5f*sizey; - int x; - - for (x=tot; x>0; x--, jitter1+=2, jitter2+=2) { - jitter2[0]= jitter1[0] + dsizex; - jitter2[1]= jitter1[1] + dsizey; - if (jitter2[0] > hsizex) jitter2[0]-= sizex; - if (jitter2[1] > hsizey) jitter2[1]-= sizey; - } -} - -/* called from convertBlenderScene.c */ -/* we do this in advance to get consistent random, not alter the render seed, and be threadsafe */ -void init_jitter_plane(LampRen *lar) -{ - float *fp; - int x, tot= lar->ray_totsamp; - - /* test if already initialized */ - if (lar->jitter) return; - - /* at least 4, or max threads+1 tables */ - if (BLENDER_MAX_THREADS < 4) x= 4; - else x= BLENDER_MAX_THREADS+1; - fp= lar->jitter= MEM_callocN(x*tot*2*sizeof(float), "lamp jitter tab"); - - /* if 1 sample, we leave table to be zero's */ - if (tot>1) { - /* set per-lamp fixed seed */ - RNG *rng = BLI_rng_new_srandom(tot); - int iter=12; - - /* fill table with random locations, area_size large */ - for (x=0; x<tot; x++, fp+=2) { - fp[0]= (BLI_rng_get_float(rng)-0.5f)*lar->area_size; - fp[1]= (BLI_rng_get_float(rng)-0.5f)*lar->area_sizey; - } - - while (iter--) { - fp= lar->jitter; - for (x=tot; x>0; x--, fp+=2) { - DP_energy(lar->jitter, fp, tot, lar->area_size, lar->area_sizey); - } - } - - BLI_rng_free(rng); - } - /* create the dithered tables (could just check lamp type!) */ - jitter_plane_offset(lar->jitter, lar->jitter+2*tot, tot, lar->area_size, lar->area_sizey, 0.5f, 0.0f); - jitter_plane_offset(lar->jitter, lar->jitter+4*tot, tot, lar->area_size, lar->area_sizey, 0.5f, 0.5f); - jitter_plane_offset(lar->jitter, lar->jitter+6*tot, tot, lar->area_size, lar->area_sizey, 0.0f, 0.5f); -} - -/* table around origin, -0.5*size to 0.5*size */ -static float *give_jitter_plane(LampRen *lar, int thread, int xs, int ys) -{ - int tot; - - tot= lar->ray_totsamp; - - if (lar->ray_samp_type & LA_SAMP_JITTER) { - /* made it threadsafe */ - - if (lar->xold[thread]!=xs || lar->yold[thread]!=ys) { - jitter_plane_offset(lar->jitter, lar->jitter+2*(thread+1)*tot, tot, lar->area_size, lar->area_sizey, BLI_thread_frand(thread), BLI_thread_frand(thread)); - lar->xold[thread]= xs; - lar->yold[thread]= ys; - } - return lar->jitter+2*(thread+1)*tot; - } - if (lar->ray_samp_type & LA_SAMP_DITHER) { - return lar->jitter + 2*tot*((xs & 1)+2*(ys & 1)); - } - - return lar->jitter; -} - - -/* **************** QMC sampling *************** */ - -static void halton_sample(double *ht_invprimes, double *ht_nums, double *v) -{ - /* incremental halton sequence generator, from: - * "Instant Radiosity", Keller A. */ - unsigned int i; - - for (i = 0; i < 2; i++) { - double r = fabs((1.0 - ht_nums[i]) - 1e-10); - - if (ht_invprimes[i] >= r) { - double lasth; - double h = ht_invprimes[i]; - - do { - lasth = h; - h *= ht_invprimes[i]; - } while (h >= r); - - ht_nums[i] += ((lasth + h) - 1.0); - } - else - ht_nums[i] += ht_invprimes[i]; - - v[i] = (float)ht_nums[i]; - } -} - -/* Generate Hammersley points in [0,1)^2 - * From Lucille renderer */ -static void hammersley_create(double *out, int n) -{ - double p, t; - int k, kk; - - for (k = 0; k < n; k++) { - t = 0; - for (p = 0.5, kk = k; kk; p *= 0.5, kk >>= 1) { - if (kk & 1) { /* kk mod 2 = 1 */ - t += p; - } - } - - out[2 * k + 0] = (double)k / (double)n; - out[2 * k + 1] = t; - } -} - -static struct QMCSampler *QMC_initSampler(int type, int tot) -{ - QMCSampler *qsa = MEM_callocN(sizeof(QMCSampler), "qmc sampler"); - qsa->samp2d = MEM_callocN(2*sizeof(double)*tot, "qmc sample table"); - - qsa->tot = tot; - qsa->type = type; - - if (qsa->type==SAMP_TYPE_HAMMERSLEY) - hammersley_create(qsa->samp2d, qsa->tot); - - return qsa; -} - -static void QMC_initPixel(QMCSampler *qsa, int thread) -{ - if (qsa->type==SAMP_TYPE_HAMMERSLEY) { - /* hammersley sequence is fixed, already created in QMCSampler init. - * per pixel, gets a random offset. We create separate offsets per thread, for write-safety */ - qsa->offs[thread][0] = 0.5f * BLI_thread_frand(thread); - qsa->offs[thread][1] = 0.5f * BLI_thread_frand(thread); - } - else { /* SAMP_TYPE_HALTON */ - - /* generate a new randomized halton sequence per pixel - * to alleviate qmc artifacts and make it reproducible - * between threads/frames */ - double ht_invprimes[2], ht_nums[2]; - double r[2]; - int i; - - ht_nums[0] = BLI_thread_frand(thread); - ht_nums[1] = BLI_thread_frand(thread); - ht_invprimes[0] = 0.5; - ht_invprimes[1] = 1.0/3.0; - - for (i=0; i< qsa->tot; i++) { - halton_sample(ht_invprimes, ht_nums, r); - qsa->samp2d[2*i+0] = r[0]; - qsa->samp2d[2*i+1] = r[1]; - } - } -} - -static void QMC_freeSampler(QMCSampler *qsa) -{ - MEM_freeN(qsa->samp2d); - MEM_freeN(qsa); -} - -static void QMC_getSample(double *s, QMCSampler *qsa, int thread, int num) -{ - if (qsa->type == SAMP_TYPE_HAMMERSLEY) { - s[0] = fmod(qsa->samp2d[2*num+0] + qsa->offs[thread][0], 1.0f); - s[1] = fmod(qsa->samp2d[2*num+1] + qsa->offs[thread][1], 1.0f); - } - else { /* SAMP_TYPE_HALTON */ - s[0] = qsa->samp2d[2*num+0]; - s[1] = qsa->samp2d[2*num+1]; - } -} - -/* phong weighted disc using 'blur' for exponent, centred on 0,0 */ -static void QMC_samplePhong(float vec[3], QMCSampler *qsa, int thread, int num, float blur) -{ - double s[2]; - float phi, pz, sqr; - - QMC_getSample(s, qsa, thread, num); - - phi = s[0]*2*M_PI; - pz = pow(s[1], blur); - sqr = sqrtf(1.0f - pz * pz); - - vec[0] = (float)(cosf(phi)*sqr); - vec[1] = (float)(sinf(phi)*sqr); - vec[2] = 0.0f; -} - -/* rect of edge lengths sizex, sizey, centred on 0.0,0.0 i.e. ranging from -sizex/2 to +sizey/2 */ -static void QMC_sampleRect(float vec[3], QMCSampler *qsa, int thread, int num, float sizex, float sizey) -{ - double s[2]; - - QMC_getSample(s, qsa, thread, num); - - vec[0] = (float)(s[0] - 0.5) * sizex; - vec[1] = (float)(s[1] - 0.5) * sizey; - vec[2] = 0.0f; -} - -/* disc of radius 'radius', centred on 0,0 */ -static void QMC_sampleDisc(float vec[3], QMCSampler *qsa, int thread, int num, float radius) -{ - double s[2]; - float phi, sqr; - - QMC_getSample(s, qsa, thread, num); - - phi = s[0]*2*M_PI; - sqr = sqrt(s[1]); - - vec[0] = cosf(phi)*sqr* radius/2.0f; - vec[1] = sinf(phi)*sqr* radius/2.0f; - vec[2] = 0.0f; -} - -/* uniform hemisphere sampling */ -static void QMC_sampleHemi(float vec[3], QMCSampler *qsa, int thread, int num) -{ - double s[2]; - float phi, sqr; - - QMC_getSample(s, qsa, thread, num); - - phi = s[0]*2.0*M_PI; - sqr = sqrt(s[1]); - - vec[0] = cosf(phi)*sqr; - vec[1] = sinf(phi)*sqr; - vec[2] = (float)(1.0 - s[1]*s[1]); -} - -#if 0 /* currently not used */ -/* cosine weighted hemisphere sampling */ -static void QMC_sampleHemiCosine(float vec[3], QMCSampler *qsa, int thread, int num) -{ - double s[2]; - float phi, sqr; - - QMC_getSample(s, qsa, thread, num); - - phi = s[0]*2.f*M_PI; - sqr = s[1]*sqrt(2-s[1]*s[1]); - - vec[0] = cos(phi)*sqr; - vec[1] = sin(phi)*sqr; - vec[2] = 1.f - s[1]*s[1]; - -} -#endif - -/* called from convertBlenderScene.c */ -void init_render_qmcsampler(Render *re) -{ - const int num_threads = re->r.threads; - re->qmcsamplers= MEM_callocN(sizeof(ListBase)*num_threads, "QMCListBase"); - re->num_qmc_samplers = num_threads; -} - -static QMCSampler *get_thread_qmcsampler(Render *re, int thread, int type, int tot) -{ - QMCSampler *qsa; - - /* create qmc samplers as needed, since recursion makes it hard to - * predict how many are needed */ - - for (qsa=re->qmcsamplers[thread].first; qsa; qsa=qsa->next) { - if (qsa->type == type && qsa->tot == tot && !qsa->used) { - qsa->used = true; - return qsa; - } - } - - qsa= QMC_initSampler(type, tot); - qsa->used = true; - BLI_addtail(&re->qmcsamplers[thread], qsa); - - return qsa; -} - -static void release_thread_qmcsampler(Render *UNUSED(re), int UNUSED(thread), QMCSampler *qsa) -{ - qsa->used= 0; -} - -void free_render_qmcsampler(Render *re) -{ - if (re->qmcsamplers) { - QMCSampler *qsa, *next; - int a; - for (a = 0; a < re->num_qmc_samplers; a++) { - for (qsa=re->qmcsamplers[a].first; qsa; qsa=next) { - next= qsa->next; - QMC_freeSampler(qsa); - } - - re->qmcsamplers[a].first= re->qmcsamplers[a].last= NULL; - } - - MEM_freeN(re->qmcsamplers); - re->qmcsamplers= NULL; - } -} - -static int adaptive_sample_variance(int samples, const float col[3], const float colsq[3], float thresh) -{ - float var[3], mean[3]; - - /* scale threshold just to give a bit more precision in input rather than dealing with - * tiny tiny numbers in the UI */ - thresh /= 2; - - mean[0] = col[0] / (float)samples; - mean[1] = col[1] / (float)samples; - mean[2] = col[2] / (float)samples; - - var[0] = (colsq[0] / (float)samples) - (mean[0]*mean[0]); - var[1] = (colsq[1] / (float)samples) - (mean[1]*mean[1]); - var[2] = (colsq[2] / (float)samples) - (mean[2]*mean[2]); - - if ((var[0] * 0.4f < thresh) && (var[1] * 0.3f < thresh) && (var[2] * 0.6f < thresh)) - return 1; - else - return 0; -} - -static int adaptive_sample_contrast_val(int samples, float prev, float val, float thresh) -{ - /* if the last sample's contribution to the total value was below a small threshold - * (i.e. the samples taken are very similar), then taking more samples that are probably - * going to be the same is wasting effort */ - if (fabsf(prev / (float)(samples - 1) - val / (float)samples ) < thresh) { - return 1; - } - else - return 0; -} - -static float get_avg_speed(ShadeInput *shi) -{ - float pre_x, pre_y, post_x, post_y, speedavg; - - pre_x = (shi->winspeed[0] == PASS_VECTOR_MAX)?0.0f:shi->winspeed[0]; - pre_y = (shi->winspeed[1] == PASS_VECTOR_MAX)?0.0f:shi->winspeed[1]; - post_x = (shi->winspeed[2] == PASS_VECTOR_MAX)?0.0f:shi->winspeed[2]; - post_y = (shi->winspeed[3] == PASS_VECTOR_MAX)?0.0f:shi->winspeed[3]; - - speedavg = (sqrtf(pre_x * pre_x + pre_y * pre_y) + sqrtf(post_x * post_x + post_y * post_y)) / 2.0f; - - return speedavg; -} - -/* ***************** main calls ************** */ - - -static void trace_refract(float col[4], ShadeInput *shi, ShadeResult *shr) -{ - QMCSampler *qsa=NULL; - int samp_type; - int traflag=0; - - float samp3d[3], orthx[3], orthy[3]; - float v_refract[3], v_refract_new[3]; - float sampcol[4], colsq[4]; - - float blur = pow3f(1.0f - shi->mat->gloss_tra); - short max_samples = shi->mat->samp_gloss_tra; - float adapt_thresh = shi->mat->adapt_thresh_tra; - - int samples=0; - - colsq[0] = colsq[1] = colsq[2] = 0.0; - col[0] = col[1] = col[2] = 0.0; - col[3]= shr->alpha; - - if (blur > 0.0f) { - if (adapt_thresh != 0.0f) samp_type = SAMP_TYPE_HALTON; - else samp_type = SAMP_TYPE_HAMMERSLEY; - - /* all samples are generated per pixel */ - qsa = get_thread_qmcsampler(&R, shi->thread, samp_type, max_samples); - QMC_initPixel(qsa, shi->thread); - } - else - max_samples = 1; - - - while (samples < max_samples) { - if (refraction(v_refract, shi->vn, shi->view, shi->ang)) { - traflag |= RAY_INSIDE; - } - else { - /* total external reflection can happen for materials with IOR < 1.0 */ - if ((shi->vlr->flag & R_SMOOTH)) - reflection(v_refract, shi->vn, shi->view, shi->facenor); - else - reflection_simple(v_refract, shi->vn, shi->view); - - /* can't blur total external reflection */ - max_samples = 1; - } - - if (max_samples > 1) { - /* get a quasi-random vector from a phong-weighted disc */ - QMC_samplePhong(samp3d, qsa, shi->thread, samples, blur); - - ortho_basis_v3v3_v3(orthx, orthy, v_refract); - mul_v3_fl(orthx, samp3d[0]); - mul_v3_fl(orthy, samp3d[1]); - - /* and perturb the refraction vector in it */ - add_v3_v3v3(v_refract_new, v_refract, orthx); - add_v3_v3(v_refract_new, orthy); - - normalize_v3(v_refract_new); - } - else { - /* no blurriness, use the original normal */ - copy_v3_v3(v_refract_new, v_refract); - } - - sampcol[0]= sampcol[1]= sampcol[2]= sampcol[3]= 0.0f; - - traceray(shi, shr, shi->mat->ray_depth_tra, shi->co, v_refract_new, sampcol, shi->obi, shi->vlr, traflag); - - col[0] += sampcol[0]; - col[1] += sampcol[1]; - col[2] += sampcol[2]; - col[3] += sampcol[3]; - - /* for variance calc */ - colsq[0] += sampcol[0]*sampcol[0]; - colsq[1] += sampcol[1]*sampcol[1]; - colsq[2] += sampcol[2]*sampcol[2]; - - samples++; - - /* adaptive sampling */ - if (adapt_thresh < 1.0f && samples > max_samples/2) { - if (adaptive_sample_variance(samples, col, colsq, adapt_thresh)) - break; - - /* if the pixel so far is very dark, we can get away with less samples */ - if ( (col[0] + col[1] + col[2])/3.0f/(float)samples < 0.01f ) - max_samples--; - } - } - - col[0] /= (float)samples; - col[1] /= (float)samples; - col[2] /= (float)samples; - col[3] /= (float)samples; - - if (qsa) - release_thread_qmcsampler(&R, shi->thread, qsa); -} - -static void trace_reflect(float col[3], ShadeInput *shi, ShadeResult *shr, float fresnelfac) -{ - QMCSampler *qsa=NULL; - int samp_type; - - float samp3d[3], orthx[3], orthy[3]; - float v_nor_new[3], v_reflect[3]; - float sampcol[4], colsq[4]; - - float blur = pow3f(1.0f - shi->mat->gloss_mir); - short max_samples = shi->mat->samp_gloss_mir; - float adapt_thresh = shi->mat->adapt_thresh_mir; - float aniso = 1.0f - shi->mat->aniso_gloss_mir; - - int samples=0; - - col[0] = col[1] = col[2] = 0.0; - colsq[0] = colsq[1] = colsq[2] = 0.0; - - if (blur > 0.0f) { - if (adapt_thresh != 0.0f) samp_type = SAMP_TYPE_HALTON; - else samp_type = SAMP_TYPE_HAMMERSLEY; - - /* all samples are generated per pixel */ - qsa = get_thread_qmcsampler(&R, shi->thread, samp_type, max_samples); - QMC_initPixel(qsa, shi->thread); - } - else - max_samples = 1; - - while (samples < max_samples) { - - if (max_samples > 1) { - /* get a quasi-random vector from a phong-weighted disc */ - QMC_samplePhong(samp3d, qsa, shi->thread, samples, blur); - - /* find the normal's perpendicular plane, blurring along tangents - * if tangent shading enabled */ - if (shi->mat->mode & (MA_TANGENT_V)) { - cross_v3_v3v3(orthx, shi->vn, shi->tang); // bitangent - copy_v3_v3(orthy, shi->tang); - mul_v3_fl(orthx, samp3d[0]); - mul_v3_fl(orthy, samp3d[1]*aniso); - } - else { - ortho_basis_v3v3_v3(orthx, orthy, shi->vn); - mul_v3_fl(orthx, samp3d[0]); - mul_v3_fl(orthy, samp3d[1]); - } - - /* and perturb the normal in it */ - add_v3_v3v3(v_nor_new, shi->vn, orthx); - add_v3_v3(v_nor_new, orthy); - normalize_v3(v_nor_new); - } - else { - /* no blurriness, use the original normal */ - copy_v3_v3(v_nor_new, shi->vn); - } - - if ((shi->vlr->flag & R_SMOOTH)) - reflection(v_reflect, v_nor_new, shi->view, shi->facenor); - else - reflection_simple(v_reflect, v_nor_new, shi->view); - - sampcol[0]= sampcol[1]= sampcol[2]= sampcol[3]= 0.0f; - - traceray(shi, shr, shi->mat->ray_depth, shi->co, v_reflect, sampcol, shi->obi, shi->vlr, 0); - - - col[0] += sampcol[0]; - col[1] += sampcol[1]; - col[2] += sampcol[2]; - - /* for variance calc */ - colsq[0] += sampcol[0]*sampcol[0]; - colsq[1] += sampcol[1]*sampcol[1]; - colsq[2] += sampcol[2]*sampcol[2]; - - samples++; - - /* adaptive sampling */ - if (adapt_thresh > 0.0f && samples > max_samples/3) { - if (adaptive_sample_variance(samples, col, colsq, adapt_thresh)) - break; - - /* if the pixel so far is very dark, we can get away with less samples */ - if ( (col[0] + col[1] + col[2])/3.0f/(float)samples < 0.01f ) - max_samples--; - - /* reduce samples when reflection is dim due to low ray mirror blend value or fresnel factor - * and when reflection is blurry */ - if (fresnelfac < 0.1f * (blur+1)) { - max_samples--; - - /* even more for very dim */ - if (fresnelfac < 0.05f * (blur+1)) - max_samples--; - } - } - } - - col[0] /= (float)samples; - col[1] /= (float)samples; - col[2] /= (float)samples; - - if (qsa) - release_thread_qmcsampler(&R, shi->thread, qsa); -} - -/* extern call from render loop */ -void ray_trace(ShadeInput *shi, ShadeResult *shr) -{ - float f1, fr, fg, fb; - float mircol[4], tracol[4]; - float diff[3]; - int do_tra, do_mir; - - do_tra = ((shi->mode & MA_TRANSP) && (shi->mode & MA_RAYTRANSP) && shr->alpha != 1.0f && (shi->depth <= shi->mat->ray_depth_tra)); - do_mir = ((shi->mat->mode & MA_RAYMIRROR) && shi->ray_mirror != 0.0f && (shi->depth <= shi->mat->ray_depth)); - - /* raytrace mirror and refract like to separate the spec color */ - if (shi->combinedflag & SCE_PASS_SPEC) - sub_v3_v3v3(diff, shr->combined, shr->spec); - else - copy_v3_v3(diff, shr->combined); - - if (do_tra) { - float olddiff[3], f; - - trace_refract(tracol, shi, shr); - - f= shr->alpha; f1= 1.0f-f; - fr= 1.0f+ shi->mat->filter*(shi->r-1.0f); - fg= 1.0f+ shi->mat->filter*(shi->g-1.0f); - fb= 1.0f+ shi->mat->filter*(shi->b-1.0f); - - /* for refract pass */ - copy_v3_v3(olddiff, diff); - - diff[0]= f*diff[0] + f1*fr*tracol[0]; - diff[1]= f*diff[1] + f1*fg*tracol[1]; - diff[2]= f*diff[2] + f1*fb*tracol[2]; - - if (shi->passflag & SCE_PASS_REFRACT) - sub_v3_v3v3(shr->refr, diff, olddiff); - - if (!(shi->combinedflag & SCE_PASS_REFRACT)) - sub_v3_v3v3(diff, diff, shr->refr); - - shr->alpha = min_ff(1.0f, tracol[3]); - } - - if (do_mir) { - const float i= shi->ray_mirror*fresnel_fac(shi->view, shi->vn, shi->mat->fresnel_mir_i, shi->mat->fresnel_mir); - if (i!=0.0f) { - - trace_reflect(mircol, shi, shr, i); - - fr= i*shi->mirr; - fg= i*shi->mirg; - fb= i*shi->mirb; - - if (shi->passflag & SCE_PASS_REFLECT) { - /* mirror pass is not blocked out with spec */ - shr->refl[0]= fr*mircol[0] - fr*diff[0]; - shr->refl[1]= fg*mircol[1] - fg*diff[1]; - shr->refl[2]= fb*mircol[2] - fb*diff[2]; - } - - if (shi->combinedflag & SCE_PASS_REFLECT) { - /* values in shr->spec can be greater than 1.0. - * In this case the mircol uses a zero blending factor, so ignoring it is ok. - * Fixes bug #18837 - when the spec is higher then 1.0, - * diff can become a negative color - Campbell */ - - f1= 1.0f-i; - - diff[0] *= f1; - diff[1] *= f1; - diff[2] *= f1; - - if (shr->spec[0]<1.0f) diff[0] += mircol[0] * (fr*(1.0f-shr->spec[0])); - if (shr->spec[1]<1.0f) diff[1] += mircol[1] * (fg*(1.0f-shr->spec[1])); - if (shr->spec[2]<1.0f) diff[2] += mircol[2] * (fb*(1.0f-shr->spec[2])); - } - } - } - /* put back together */ - if (shi->combinedflag & SCE_PASS_SPEC) - add_v3_v3v3(shr->combined, diff, shr->spec); - else - copy_v3_v3(shr->combined, diff); -} - -/* color 'shadfac' passes through 'col' with alpha and filter */ -/* filter is only applied on alpha defined transparent part */ -static void addAlphaLight(float shadfac[4], const float col[3], float alpha, float filter) -{ - float fr, fg, fb; - - fr= 1.0f+ filter*(col[0]-1.0f); - fg= 1.0f+ filter*(col[1]-1.0f); - fb= 1.0f+ filter*(col[2]-1.0f); - - shadfac[0]= alpha*col[0] + fr*(1.0f-alpha)*shadfac[0]; - shadfac[1]= alpha*col[1] + fg*(1.0f-alpha)*shadfac[1]; - shadfac[2]= alpha*col[2] + fb*(1.0f-alpha)*shadfac[2]; - - shadfac[3]= (1.0f-alpha)*shadfac[3]; -} - -static void ray_trace_shadow_tra(Isect *is, ShadeInput *origshi, int depth, int traflag, float col[4]) -{ - /* ray to lamp, find first face that intersects, check alpha properties, - * if it has col[3]>0.0f continue. so exit when alpha is full */ - const float initial_dist = is->dist; - - if (RE_rayobject_raycast(R.raytree, is)) { - /* Warning regarding initializing to zero's, This is not that nice, - * and possibly a bit slow for every ray, however some variables were - * not initialized properly in, unless using - * shade_input_initialize(...), we need to zero them. */ - ShadeInput shi= {NULL}; - /* end warning! - Campbell */ - - ShadeResult shr; - - /* we got a face */ - - shi.depth= origshi->depth + 1; /* only used to indicate tracing */ - shi.mask= origshi->mask; - shi.thread= origshi->thread; - shi.passflag= SCE_PASS_COMBINED; - shi.combinedflag= 0xFFFFFF; /* ray trace does all options */ - - shi.xs= origshi->xs; - shi.ys= origshi->ys; - shi.do_manage= origshi->do_manage; - shi.lay= origshi->lay; - shi.nodes= origshi->nodes; - - RE_instance_rotate_ray_restore(origshi->obi, is); - - shade_ray(is, &shi, &shr); - if (shi.mat->material_type == MA_TYPE_SURFACE) { - const float d = (shi.mat->mode & MA_RAYTRANSP) ? - ((traflag & RAY_TRA) ? shade_by_transmission(is, &shi, &shr) : 1.0f) : - 0.0f; - /* mix colors based on shadfac (rgb + amount of light factor) */ - addAlphaLight(col, shr.diff, shr.alpha, d*shi.mat->filter); - } - else if (shi.mat->material_type == MA_TYPE_VOLUME) { - const float a = col[3]; - - col[0] = a*col[0] + shr.alpha*shr.combined[0]; - col[1] = a*col[1] + shr.alpha*shr.combined[1]; - col[2] = a*col[2] + shr.alpha*shr.combined[2]; - - col[3] = (1.0f - shr.alpha)*a; - } - - if (depth>0 && col[3]>0.0f) { - - /* adapt isect struct */ - copy_v3_v3(is->start, shi.co); - is->dist = initial_dist-is->dist; - is->orig.ob = shi.obi; - is->orig.face = shi.vlr; - - ray_trace_shadow_tra(is, origshi, depth-1, traflag | RAY_TRA, col); - } - - RE_RC_MERGE(&origshi->raycounter, &shi.raycounter); - } -} - - -/* aolight: function to create random unit sphere vectors for total random sampling */ - -/* calc distributed spherical energy */ -static void DS_energy(float *sphere, int tot, float vec[3]) -{ - float *fp, fac, force[3], res[3]; - int a; - - res[0]= res[1]= res[2]= 0.0f; - - for (a=0, fp=sphere; a<tot; a++, fp+=3) { - sub_v3_v3v3(force, vec, fp); - fac = dot_v3v3(force, force); - if (fac!=0.0f) { - fac= 1.0f/fac; - res[0]+= fac*force[0]; - res[1]+= fac*force[1]; - res[2]+= fac*force[2]; - } - } - - mul_v3_fl(res, 0.5); - add_v3_v3(vec, res); - normalize_v3(vec); - -} - -/* called from convertBlenderScene.c */ -/* creates an equally distributed spherical sample pattern */ -/* and allocates threadsafe memory */ -void init_ao_sphere(Render *re, World *wrld) -{ - /* fixed random */ - const int num_threads = re->r.threads; - RNG *rng; - float *fp; - int a, tot, iter= 16; - - /* we make twice the amount of samples, because only a hemisphere is used */ - tot= 2*wrld->aosamp*wrld->aosamp; - - wrld->aosphere= MEM_mallocN(3*tot*sizeof(float), "AO sphere"); - rng = BLI_rng_new_srandom(tot); - - /* init */ - fp= wrld->aosphere; - for (a=0; a<tot; a++, fp+= 3) { - BLI_rng_get_float_unit_v3(rng, fp); - } - - while (iter--) { - for (a=0, fp= wrld->aosphere; a<tot; a++, fp+= 3) { - DS_energy(wrld->aosphere, tot, fp); - } - } - - /* tables */ - wrld->aotables= MEM_mallocN(num_threads*3*tot*sizeof(float), "AO tables"); - - BLI_rng_free(rng); -} - -/* give per thread a table, we have to compare xs ys because of way OSA works... */ -static float *threadsafe_table_sphere(int test, int thread, int xs, int ys, int tot) -{ - static int xso[BLENDER_MAX_THREADS], yso[BLENDER_MAX_THREADS]; - static int firsttime= 1; - - if (firsttime) { - memset(xso, 255, sizeof(xso)); - memset(yso, 255, sizeof(yso)); - firsttime= 0; - } - - if (xs==xso[thread] && ys==yso[thread]) return R.wrld.aotables+ thread*tot*3; - if (test) return NULL; - xso[thread]= xs; yso[thread]= ys; - return R.wrld.aotables+ thread*tot*3; -} - -static float *sphere_sampler(int type, int resol, int thread, int xs, int ys, int reset) -{ - int tot; - float *vec; - - tot= 2*resol*resol; - - if (type & WO_AORNDSMP) { - /* total random sampling. NOT THREADSAFE! (should be removed, is not useful) */ - RNG *rng = BLI_rng_new(BLI_thread_rand(thread)); - float *sphere; - int a; - - /* always returns table */ - sphere= threadsafe_table_sphere(0, thread, xs, ys, tot); - - vec= sphere; - for (a=0; a<tot; a++, vec+=3) { - BLI_rng_get_float_unit_v3(rng, vec); - } - - BLI_rng_free(rng); - - return sphere; - } - else { - float *sphere; - float *vec1; - - /* returns table if xs and ys were equal to last call, and not resetting */ - sphere= (reset)? NULL: threadsafe_table_sphere(1, thread, xs, ys, tot); - if (sphere==NULL) { - float cosfi, sinfi, cost, sint; - float ang; - int a; - - sphere= threadsafe_table_sphere(0, thread, xs, ys, tot); - - /* random rotation */ - ang = BLI_thread_frand(thread); - sinfi = sinf(ang); cosfi = cosf(ang); - ang = BLI_thread_frand(thread); - sint = sinf(ang); cost = cosf(ang); - - vec= R.wrld.aosphere; - vec1= sphere; - for (a=0; a<tot; a++, vec+=3, vec1+=3) { - vec1[0]= cost*cosfi*vec[0] - sinfi*vec[1] + sint*cosfi*vec[2]; - vec1[1]= cost*sinfi*vec[0] + cosfi*vec[1] + sint*sinfi*vec[2]; - vec1[2]= -sint*vec[0] + cost*vec[2]; - } - } - return sphere; - } -} - -static void ray_ao_qmc(ShadeInput *shi, float ao[3], float env[3]) -{ - Isect isec; - RayHint point_hint; - QMCSampler *qsa=NULL; - float samp3d[3]; - float up[3], side[3], dir[3], nrm[3]; - - float maxdist = R.wrld.aodist; - float fac=0.0f, prev=0.0f; - float adapt_thresh = R.wrld.ao_adapt_thresh; - float adapt_speed_fac = R.wrld.ao_adapt_speed_fac; - - int samples=0; - int max_samples = R.wrld.aosamp*R.wrld.aosamp; - - float dxyview[3], skyadded=0; - int envcolor; - - RE_RC_INIT(isec, *shi); - isec.orig.ob = shi->obi; - isec.orig.face = shi->vlr; - isec.check = RE_CHECK_VLR_NON_SOLID_MATERIAL; - isec.skip = RE_SKIP_VLR_NEIGHBOUR; - isec.hint = NULL; - - isec.hit.ob = NULL; - isec.hit.face = NULL; - - isec.last_hit = NULL; - - isec.mode= (R.wrld.aomode & WO_AODIST)?RE_RAY_SHADOW_TRA:RE_RAY_SHADOW; - isec.lay= -1; - - copy_v3_v3(isec.start, shi->co); - - RE_instance_rotate_ray_start(shi->obi, &isec); - - RE_rayobject_hint_bb(R.raytree, &point_hint, isec.start, isec.start); - isec.hint = &point_hint; - - zero_v3(ao); - zero_v3(env); - - /* prevent sky colors to be added for only shadow (shadow becomes alpha) */ - envcolor= R.wrld.aocolor; - if (shi->mat->mode & MA_ONLYSHADOW) - envcolor= WO_AOPLAIN; - - if (envcolor == WO_AOSKYTEX) { - dxyview[0]= 1.0f/(float)R.wrld.aosamp; - dxyview[1]= 1.0f/(float)R.wrld.aosamp; - dxyview[2]= 0.0f; - } - - if (shi->vlr->flag & R_SMOOTH) { - copy_v3_v3(nrm, shi->vn); - } - else { - copy_v3_v3(nrm, shi->facenor); - } - - ortho_basis_v3v3_v3(up, side, nrm); - - /* sampling init */ - if (R.wrld.ao_samp_method==WO_AOSAMP_HALTON) { - float speedfac; - - speedfac = get_avg_speed(shi) * adapt_speed_fac; - CLAMP(speedfac, 1.0f, 1000.0f); - max_samples /= speedfac; - if (max_samples < 5) max_samples = 5; - - qsa = get_thread_qmcsampler(&R, shi->thread, SAMP_TYPE_HALTON, max_samples); - } - else if (R.wrld.ao_samp_method==WO_AOSAMP_HAMMERSLEY) - qsa = get_thread_qmcsampler(&R, shi->thread, SAMP_TYPE_HAMMERSLEY, max_samples); - - QMC_initPixel(qsa, shi->thread); - - while (samples < max_samples) { - - /* sampling, returns quasi-random vector in unit hemisphere */ - QMC_sampleHemi(samp3d, qsa, shi->thread, samples); - - dir[0] = (samp3d[0]*up[0] + samp3d[1]*side[0] + samp3d[2]*nrm[0]); - dir[1] = (samp3d[0]*up[1] + samp3d[1]*side[1] + samp3d[2]*nrm[1]); - dir[2] = (samp3d[0]*up[2] + samp3d[1]*side[2] + samp3d[2]*nrm[2]); - - normalize_v3(dir); - - isec.dir[0] = -dir[0]; - isec.dir[1] = -dir[1]; - isec.dir[2] = -dir[2]; - isec.dist = maxdist; - - RE_instance_rotate_ray_dir(shi->obi, &isec); - - prev = fac; - - if (RE_rayobject_raycast(R.raytree, &isec)) { - if (R.wrld.aomode & WO_AODIST) fac+= expf(-isec.dist*R.wrld.aodistfac); - else fac+= 1.0f; - } - else if (envcolor!=WO_AOPLAIN) { - float skycol[4]; - float view[3]; - - view[0]= -dir[0]; - view[1]= -dir[1]; - view[2]= -dir[2]; - normalize_v3(view); - - if (envcolor==WO_AOSKYCOL) { - const float skyfac= 0.5f * (1.0f + dot_v3v3(view, R.grvec)); - env[0]+= (1.0f-skyfac)*R.wrld.horr + skyfac*R.wrld.zenr; - env[1]+= (1.0f-skyfac)*R.wrld.horg + skyfac*R.wrld.zeng; - env[2]+= (1.0f-skyfac)*R.wrld.horb + skyfac*R.wrld.zenb; - } - else { /* WO_AOSKYTEX */ - shadeSkyView(skycol, isec.start, view, dxyview, shi->thread); - shadeSunView(skycol, shi->view); - env[0]+= skycol[0]; - env[1]+= skycol[1]; - env[2]+= skycol[2]; - } - skyadded++; - } - - samples++; - - if (qsa && qsa->type == SAMP_TYPE_HALTON) { - /* adaptive sampling - consider samples below threshold as in shadow (or vice versa) and exit early */ - if (adapt_thresh > 0.0f && (samples > max_samples/2) ) { - - if (adaptive_sample_contrast_val(samples, prev, fac, adapt_thresh)) { - break; - } - } - } - } - - /* average color times distances/hits formula */ - ao[0]= ao[1]= ao[2]= 1.0f - fac/(float)samples; - - if (envcolor!=WO_AOPLAIN && skyadded) - mul_v3_fl(env, (1.0f - fac/(float)samples)/((float)skyadded)); - else - copy_v3_v3(env, ao); - - if (qsa) - release_thread_qmcsampler(&R, shi->thread, qsa); -} - -/* extern call from shade_lamp_loop, ambient occlusion calculus */ -static void ray_ao_spheresamp(ShadeInput *shi, float ao[3], float env[3]) -{ - Isect isec; - RayHint point_hint; - float *vec, *nrm, bias, sh=0.0f; - float maxdist = R.wrld.aodist; - float dxyview[3]; - int j= -1, tot, actual=0, skyadded=0, envcolor, resol= R.wrld.aosamp; - - RE_RC_INIT(isec, *shi); - isec.orig.ob = shi->obi; - isec.orig.face = shi->vlr; - isec.check = RE_CHECK_VLR_RENDER; - isec.skip = RE_SKIP_VLR_NEIGHBOUR; - isec.hint = NULL; - - isec.hit.ob = NULL; - isec.hit.face = NULL; - - isec.last_hit = NULL; - - isec.mode= (R.wrld.aomode & WO_AODIST)?RE_RAY_SHADOW_TRA:RE_RAY_SHADOW; - isec.lay= -1; - - copy_v3_v3(isec.start, shi->co); - RE_instance_rotate_ray_start(shi->obi, &isec); - - RE_rayobject_hint_bb(R.raytree, &point_hint, isec.start, isec.start); - isec.hint = &point_hint; - - zero_v3(ao); - zero_v3(env); - - /* bias prevents smoothed faces to appear flat */ - if (shi->vlr->flag & R_SMOOTH) { - bias= R.wrld.aobias; - nrm= shi->vn; - } - else { - bias= 0.0f; - nrm= shi->facenor; - } - - /* prevent sky colors to be added for only shadow (shadow becomes alpha) */ - envcolor= R.wrld.aocolor; - if (shi->mat->mode & MA_ONLYSHADOW) - envcolor= WO_AOPLAIN; - - if (resol>32) resol= 32; - - /* get sphere samples. for faces we get the same samples for sample x/y values, - * for strand render we always require a new sampler because x/y are not set */ - vec= sphere_sampler(R.wrld.aomode, resol, shi->thread, shi->xs, shi->ys, shi->strand != NULL); - - /* warning: since we use full sphere now, and dotproduct is below, we do twice as much */ - tot= 2*resol*resol; - - if (envcolor == WO_AOSKYTEX) { - dxyview[0]= 1.0f/(float)resol; - dxyview[1]= 1.0f/(float)resol; - dxyview[2]= 0.0f; - } - - while (tot--) { - - if (dot_v3v3(vec, nrm) > bias) { - /* only ao samples for mask */ - if (R.r.mode & R_OSA) { - j++; - if (j==R.osa) j= 0; - if (!(shi->mask & (1<<j))) { - vec+=3; - continue; - } - } - - actual++; - - /* always set start/vec/dist */ - isec.dir[0] = -vec[0]; - isec.dir[1] = -vec[1]; - isec.dir[2] = -vec[2]; - isec.dist = maxdist; - - RE_instance_rotate_ray_dir(shi->obi, &isec); - - /* do the trace */ - if (RE_rayobject_raycast(R.raytree, &isec)) { - if (R.wrld.aomode & WO_AODIST) sh+= expf(-isec.dist*R.wrld.aodistfac); - else sh+= 1.0f; - } - else if (envcolor!=WO_AOPLAIN) { - float skycol[4]; - float view[3]; - - view[0]= -vec[0]; - view[1]= -vec[1]; - view[2]= -vec[2]; - normalize_v3(view); - - if (envcolor==WO_AOSKYCOL) { - const float fac = 0.5f * (1.0f + dot_v3v3(view, R.grvec)); - env[0]+= (1.0f-fac)*R.wrld.horr + fac*R.wrld.zenr; - env[1]+= (1.0f-fac)*R.wrld.horg + fac*R.wrld.zeng; - env[2]+= (1.0f-fac)*R.wrld.horb + fac*R.wrld.zenb; - } - else { /* WO_AOSKYTEX */ - shadeSkyView(skycol, isec.start, view, dxyview, shi->thread); - shadeSunView(skycol, shi->view); - env[0]+= skycol[0]; - env[1]+= skycol[1]; - env[2]+= skycol[2]; - } - skyadded++; - } - } - /* samples */ - vec+= 3; - } - - if (actual==0) sh= 1.0f; - else sh = 1.0f - sh/((float)actual); - - /* average color times distances/hits formula */ - ao[0]= ao[1]= ao[2]= sh; - - if (envcolor!=WO_AOPLAIN && skyadded) - mul_v3_fl(env, sh/((float)skyadded)); - else - copy_v3_v3(env, ao); -} - -void ray_ao(ShadeInput *shi, float ao[3], float env[3]) -{ - /* Unfortunately, the unusual way that the sphere sampler calculates roughly twice as many - * samples as are actually traced, and skips them based on bias and OSA settings makes it very difficult - * to reuse code between these two functions. This is the easiest way I can think of to do it - * --broken */ - if (ELEM(R.wrld.ao_samp_method, WO_AOSAMP_HAMMERSLEY, WO_AOSAMP_HALTON)) - ray_ao_qmc(shi, ao, env); - else if (R.wrld.ao_samp_method == WO_AOSAMP_CONSTANT) - ray_ao_spheresamp(shi, ao, env); -} - -static void ray_shadow_jittered_coords(ShadeInput *shi, int max, float jitco[RE_MAX_OSA][3], int *totjitco) -{ - /* magic numbers for reordering sample positions to give better - * results with adaptive sample, when it usually only takes 4 samples */ - int order8[8] = {0, 1, 5, 6, 2, 3, 4, 7}; - int order11[11] = {1, 3, 8, 10, 0, 2, 4, 5, 6, 7, 9}; - int order16[16] = {1, 3, 9, 12, 0, 6, 7, 8, 13, 2, 4, 5, 10, 11, 14, 15}; - int count = count_mask(shi->mask); - - /* for better antialising shadow samples are distributed over the subpixel - * sample coordinates, this only works for raytracing depth 0 though */ - if (!shi->strand && shi->depth == 0 && count > 1 && count <= max) { - float xs, ys, zs, view[3]; - int samp, ordsamp, tot= 0; - - for (samp=0; samp<R.osa; samp++) { - if (R.osa == 8) ordsamp = order8[samp]; - else if (R.osa == 11) ordsamp = order11[samp]; - else if (R.osa == 16) ordsamp = order16[samp]; - else ordsamp = samp; - - if (shi->mask & (1<<ordsamp)) { - /* zbuffer has this inverse corrected, ensures xs,ys are inside pixel */ - xs= (float)shi->scanco[0] + R.jit[ordsamp][0] + 0.5f; - ys= (float)shi->scanco[1] + R.jit[ordsamp][1] + 0.5f; - zs= shi->scanco[2]; - - shade_input_calc_viewco(shi, xs, ys, zs, view, NULL, jitco[tot], NULL, NULL); - tot++; - } - } - - *totjitco= tot; - } - else { - copy_v3_v3(jitco[0], shi->co); - *totjitco= 1; - } -} - -static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, const float lampco[3], float shadfac[4], Isect *isec) -{ - QMCSampler *qsa=NULL; - int samples=0; - float samp3d[3]; - - float fac=0.0f, vec[3], end[3]; - float colsq[4]; - float adapt_thresh = lar->adapt_thresh; - int min_adapt_samples=4, max_samples = lar->ray_totsamp; - float start[3]; - bool do_soft = true, full_osa = false; - int i; - - float min[3], max[3]; - RayHint bb_hint; - - float jitco[RE_MAX_OSA][3]; - int totjitco; - - colsq[0] = colsq[1] = colsq[2] = 0.0; - if (isec->mode==RE_RAY_SHADOW_TRA) { - shadfac[0]= shadfac[1]= shadfac[2]= shadfac[3]= 0.0f; - } - else - shadfac[3]= 1.0f; - - if (lar->ray_totsamp < 2) do_soft = false; - if ((R.r.mode & R_OSA) && (R.osa > 0) && (shi->vlr->flag & R_FULL_OSA)) full_osa = true; - - if (full_osa) { - if (do_soft) max_samples = max_samples/R.osa + 1; - else max_samples = 1; - } - else { - if (do_soft) max_samples = lar->ray_totsamp; - else if (shi->depth == 0) max_samples = (R.osa > 4)?R.osa:5; - else max_samples = 1; - } - - ray_shadow_jittered_coords(shi, max_samples, jitco, &totjitco); - - /* sampling init */ - if (lar->ray_samp_method==LA_SAMP_HALTON) - qsa = get_thread_qmcsampler(&R, shi->thread, SAMP_TYPE_HALTON, max_samples); - else if (lar->ray_samp_method==LA_SAMP_HAMMERSLEY) - qsa = get_thread_qmcsampler(&R, shi->thread, SAMP_TYPE_HAMMERSLEY, max_samples); - - QMC_initPixel(qsa, shi->thread); - - INIT_MINMAX(min, max); - for (i = 0; i < totjitco; i++) { - minmax_v3v3_v3(min, max, jitco[i]); - } - if (shi->obi->flag & R_ENV_TRANSFORMED) { - mul_m4_v3(shi->obi->imat, min); - mul_m4_v3(shi->obi->imat, max); - } - RE_rayobject_hint_bb(R.raytree, &bb_hint, min, max); - - isec->hint = &bb_hint; - isec->check = RE_CHECK_VLR_RENDER; - isec->skip = RE_SKIP_VLR_NEIGHBOUR; - copy_v3_v3(vec, lampco); - - while (samples < max_samples) { - - isec->orig.ob = shi->obi; - isec->orig.face = shi->vlr; - - /* manually jitter the start shading co-ord per sample - * based on the pre-generated OSA texture sampling offsets, - * for anti-aliasing sharp shadow edges. */ - copy_v3_v3(start, jitco[samples % totjitco]); - - if (do_soft) { - /* sphere shadow source */ - if (lar->type == LA_LOCAL) { - float ru[3], rv[3], v[3], s[3]; - - /* calc tangent plane vectors */ - sub_v3_v3v3(v, start, lampco); - normalize_v3(v); - ortho_basis_v3v3_v3(ru, rv, v); - - /* sampling, returns quasi-random vector in area_size disc */ - QMC_sampleDisc(samp3d, qsa, shi->thread, samples, lar->area_size); - - /* distribute disc samples across the tangent plane */ - s[0] = samp3d[0]*ru[0] + samp3d[1]*rv[0]; - s[1] = samp3d[0]*ru[1] + samp3d[1]*rv[1]; - s[2] = samp3d[0]*ru[2] + samp3d[1]*rv[2]; - - copy_v3_v3(samp3d, s); - } - else { - /* sampling, returns quasi-random vector in [sizex,sizey]^2 plane */ - QMC_sampleRect(samp3d, qsa, shi->thread, samples, lar->area_size, lar->area_sizey); - - /* align samples to lamp vector */ - mul_m3_v3(lar->mat, samp3d); - } - end[0] = vec[0]+samp3d[0]; - end[1] = vec[1]+samp3d[1]; - end[2] = vec[2]+samp3d[2]; - } - else { - copy_v3_v3(end, vec); - } - - if (shi->strand) { - /* bias away somewhat to avoid self intersection */ - float jitbias= 0.5f*(len_v3(shi->dxco) + len_v3(shi->dyco)); - float v[3]; - - sub_v3_v3v3(v, start, end); - normalize_v3(v); - - start[0] -= jitbias*v[0]; - start[1] -= jitbias*v[1]; - start[2] -= jitbias*v[2]; - } - - copy_v3_v3(isec->start, start); - sub_v3_v3v3(isec->dir, end, start); - isec->dist = normalize_v3(isec->dir); - - RE_instance_rotate_ray(shi->obi, isec); - - /* trace the ray */ - if (isec->mode==RE_RAY_SHADOW_TRA) { - float col[4] = {1.0f, 1.0f, 1.0f, 1.0f}; - - ray_trace_shadow_tra(isec, shi, DEPTH_SHADOW_TRA, 0, col); - shadfac[0] += col[0]; - shadfac[1] += col[1]; - shadfac[2] += col[2]; - shadfac[3] += col[3]; - - /* for variance calc */ - colsq[0] += col[0]*col[0]; - colsq[1] += col[1]*col[1]; - colsq[2] += col[2]*col[2]; - } - else { - if ( RE_rayobject_raycast(R.raytree, isec) ) fac+= 1.0f; - } - - samples++; - - if (lar->ray_samp_method == LA_SAMP_HALTON) { - - /* adaptive sampling - consider samples below threshold as in shadow (or vice versa) and exit early */ - if ((max_samples > min_adapt_samples) && (adapt_thresh > 0.0f) && (samples > max_samples / 3)) { - if (isec->mode==RE_RAY_SHADOW_TRA) { - if ((shadfac[3] / samples > (1.0f-adapt_thresh)) || (shadfac[3] / samples < adapt_thresh)) - break; - else if (adaptive_sample_variance(samples, shadfac, colsq, adapt_thresh)) - break; - } - else { - if ((fac / samples > (1.0f-adapt_thresh)) || (fac / samples < adapt_thresh)) - break; - } - } - } - } - - if (isec->mode==RE_RAY_SHADOW_TRA) { - shadfac[0] /= samples; - shadfac[1] /= samples; - shadfac[2] /= samples; - shadfac[3] /= samples; - } - else - shadfac[3]= 1.0f-fac/samples; - - if (qsa) - release_thread_qmcsampler(&R, shi->thread, qsa); -} - -static void ray_shadow_jitter(ShadeInput *shi, LampRen *lar, const float lampco[3], float shadfac[4], Isect *isec) -{ - /* area soft shadow */ - const float *jitlamp; - float fac=0.0f, div=0.0f, vec[3]; - int a, j= -1, mask; - RayHint point_hint; - - if (isec->mode==RE_RAY_SHADOW_TRA) { - shadfac[0]= shadfac[1]= shadfac[2]= shadfac[3]= 0.0f; - } - else shadfac[3]= 1.0f; - - fac= 0.0f; - jitlamp= give_jitter_plane(lar, shi->thread, shi->xs, shi->ys); - - a= lar->ray_totsamp; - - /* this correction to make sure we always take at least 1 sample */ - mask= shi->mask; - if (a==4) mask |= (mask>>4)|(mask>>8); - else if (a==9) mask |= (mask>>9); - - copy_v3_v3(isec->start, shi->co); - RE_instance_rotate_ray_start(shi->obi, isec); - - isec->orig.ob = shi->obi; - isec->orig.face = shi->vlr; - RE_rayobject_hint_bb(R.raytree, &point_hint, isec->start, isec->start); - isec->hint = &point_hint; - - while (a--) { - - if (R.r.mode & R_OSA) { - j++; - if (j>=R.osa) j= 0; - if (!(mask & (1<<j))) { - jitlamp+= 2; - continue; - } - } - - vec[0]= jitlamp[0]; - vec[1]= jitlamp[1]; - vec[2]= 0.0f; - mul_m3_v3(lar->mat, vec); - - /* set start and vec */ - isec->dir[0] = vec[0]+lampco[0]-shi->co[0]; - isec->dir[1] = vec[1]+lampco[1]-shi->co[1]; - isec->dir[2] = vec[2]+lampco[2]-shi->co[2]; - - RE_instance_rotate_ray_dir(shi->obi, isec); - - isec->dist = 1.0f; - isec->check = RE_CHECK_VLR_RENDER; - isec->skip = RE_SKIP_VLR_NEIGHBOUR; - - if (isec->mode==RE_RAY_SHADOW_TRA) { - /* isec.col is like shadfac, so defines amount of light (0.0 is full shadow) */ - float col[4] = {1.0f, 1.0f, 1.0f, 1.0f}; - - ray_trace_shadow_tra(isec, shi, DEPTH_SHADOW_TRA, 0, col); - shadfac[0] += col[0]; - shadfac[1] += col[1]; - shadfac[2] += col[2]; - shadfac[3] += col[3]; - } - else if ( RE_rayobject_raycast(R.raytree, isec) ) fac+= 1.0f; - - div+= 1.0f; - jitlamp+= 2; - } - - if (isec->mode==RE_RAY_SHADOW_TRA) { - shadfac[0] /= div; - shadfac[1] /= div; - shadfac[2] /= div; - shadfac[3] /= div; - } - else { - /* sqrt makes nice umbra effect */ - if (lar->ray_samp_type & LA_SAMP_UMBRA) - shadfac[3] = sqrtf(1.0f - fac / div); - else - shadfac[3] = 1.0f - fac / div; - } -} -/* extern call from shade_lamp_loop */ -void ray_shadow(ShadeInput *shi, LampRen *lar, float shadfac[4]) -{ - Isect isec; - float lampco[3]; - - /* setup isec */ - RE_RC_INIT(isec, *shi); - if (shi->mat->mode & MA_SHADOW_TRA) isec.mode= RE_RAY_SHADOW_TRA; - else isec.mode= RE_RAY_SHADOW; - isec.hint = NULL; - - if (lar->mode & (LA_LAYER|LA_LAYER_SHADOW)) - isec.lay= lar->lay; - else - isec.lay= -1; - - /* only when not mir tracing, first hit optimm */ - if (shi->depth==0) { - isec.last_hit = lar->last_hit[shi->thread]; - } - else { - isec.last_hit = NULL; - } - - if (lar->type==LA_SUN || lar->type==LA_HEMI) { - /* jitter and QMC sampling add a displace vector to the lamp position - * that's incorrect because a SUN lamp does not has an exact position - * and the displace should be done at the ray vector instead of the - * lamp position. - * This is easily verified by noticing that shadows of SUN lights change - * with the scene BB. - * - * This was detected during SoC 2009 - Raytrace Optimization, but to keep - * consistency with older render code it wasn't removed. - * - * If the render code goes through some recode/serious bug-fix then this - * is something to consider! - */ - lampco[0]= shi->co[0] - R.maxdist*lar->vec[0]; - lampco[1]= shi->co[1] - R.maxdist*lar->vec[1]; - lampco[2]= shi->co[2] - R.maxdist*lar->vec[2]; - } - else { - copy_v3_v3(lampco, lar->co); - } - - if (ELEM(lar->ray_samp_method, LA_SAMP_HALTON, LA_SAMP_HAMMERSLEY)) { - - ray_shadow_qmc(shi, lar, lampco, shadfac, &isec); - - } - else { - if (lar->ray_totsamp<2) { - - isec.orig.ob = shi->obi; - isec.orig.face = shi->vlr; - - shadfac[3]= 1.0f; /* 1.0=full light */ - - /* set up isec.dir */ - copy_v3_v3(isec.start, shi->co); - sub_v3_v3v3(isec.dir, lampco, isec.start); - isec.dist = normalize_v3(isec.dir); - - RE_instance_rotate_ray(shi->obi, &isec); - - if (isec.mode==RE_RAY_SHADOW_TRA) { - /* isec.col is like shadfac, so defines amount of light (0.0 is full shadow) */ - float col[4] = {1.0f, 1.0f, 1.0f, 1.0f}; - - ray_trace_shadow_tra(&isec, shi, DEPTH_SHADOW_TRA, 0, col); - copy_v4_v4(shadfac, col); - } - else if (RE_rayobject_raycast(R.raytree, &isec)) - shadfac[3]= 0.0f; - } - else { - ray_shadow_jitter(shi, lar, lampco, shadfac, &isec); - } - } - - /* for first hit optim, set last interesected shadow face */ - if (shi->depth==0) { - lar->last_hit[shi->thread] = isec.last_hit; - } - -} - diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c deleted file mode 100644 index 99d2436d4bc..00000000000 --- a/source/blender/render/intern/source/rendercore.c +++ /dev/null @@ -1,2030 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * Contributors: Hos, Robert Wenzlaff. - * Contributors: 2004/2005/2006 Blender Foundation, full recode - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/render/intern/source/rendercore.c - * \ingroup render - */ - - -/* system includes */ -#include <stdio.h> -#include <math.h> -#include <float.h> -#include <string.h> -#include <assert.h> - -/* External modules: */ -#include "MEM_guardedalloc.h" - -#include "BLI_math.h" -#include "BLI_blenlib.h" -#include "BLI_rand.h" -#include "BLI_threads.h" -#include "BLI_utildefines.h" - -#include "DNA_image_types.h" -#include "DNA_lamp_types.h" -#include "DNA_material_types.h" -#include "DNA_group_types.h" - -/* local include */ -#include "renderpipeline.h" -#include "render_result.h" -#include "render_types.h" -#include "renderdatabase.h" -#include "occlusion.h" -#include "pixelblending.h" -#include "pixelshading.h" -#include "shadbuf.h" -#include "shading.h" -#include "sss.h" -#include "zbuf.h" - -/* own include */ -#include "rendercore.h" - - -/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -/* defined in pipeline.c, is hardcopy of active dynamic allocated Render */ -/* only to be used here in this file, it's for speed */ -extern struct Render R; -/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ - -/* x and y are current pixels in rect to be rendered */ -/* do not normalize! */ -void calc_view_vector(float view[3], float x, float y) -{ - - view[2]= -ABS(R.clipsta); - - if (R.r.mode & R_ORTHO) { - view[0]= view[1]= 0.0f; - } - else { - - if (R.r.mode & R_PANORAMA) { - x-= R.panodxp; - } - - /* move x and y to real viewplane coords */ - x = (x / (float)R.winx); - view[0] = R.viewplane.xmin + x * BLI_rctf_size_x(&R.viewplane); - - y = (y / (float)R.winy); - view[1] = R.viewplane.ymin + y * BLI_rctf_size_y(&R.viewplane); - -// if (R.flag & R_SEC_FIELD) { -// if (R.r.mode & R_ODDFIELD) view[1]= (y+R.ystart)*R.ycor; -// else view[1]= (y+R.ystart+1.0)*R.ycor; -// } -// else view[1]= (y+R.ystart+R.bluroffsy+0.5)*R.ycor; - - if (R.r.mode & R_PANORAMA) { - float u= view[0] + R.panodxv; float v= view[2]; - view[0]= R.panoco*u + R.panosi*v; - view[2]= -R.panosi*u + R.panoco*v; - } - } -} - -void calc_renderco_ortho(float co[3], float x, float y, int z) -{ - /* x and y 3d coordinate can be derived from pixel coord and winmat */ - float fx= 2.0f/(R.winx*R.winmat[0][0]); - float fy= 2.0f/(R.winy*R.winmat[1][1]); - float zco; - - co[0]= (x - 0.5f*R.winx)*fx - R.winmat[3][0]/R.winmat[0][0]; - co[1]= (y - 0.5f*R.winy)*fy - R.winmat[3][1]/R.winmat[1][1]; - - zco= ((float)z)/2147483647.0f; - co[2]= R.winmat[3][2]/( R.winmat[2][3]*zco - R.winmat[2][2] ); -} - -void calc_renderco_zbuf(float co[3], const float view[3], int z) -{ - float fac, zco; - - /* inverse of zbuf calc: zbuf = MAXZ*hoco_z/hoco_w */ - zco= ((float)z)/2147483647.0f; - co[2]= R.winmat[3][2]/( R.winmat[2][3]*zco - R.winmat[2][2] ); - - fac= co[2]/view[2]; - co[0]= fac*view[0]; - co[1]= fac*view[1]; -} - -/* also used in zbuf.c and shadbuf.c */ -int count_mask(unsigned short mask) -{ - if (R.samples) - return (R.samples->cmask[mask & 255]+R.samples->cmask[mask>>8]); - return 0; -} - -static int calchalo_z(HaloRen *har, int zz) -{ - - if (har->type & HA_ONLYSKY) { - if (zz < 0x7FFFFFF0) zz= - 0x7FFFFF; /* edge render messes zvalues */ - } - else { - zz= (zz>>8); - } - return zz; -} - - - -static void halo_pixelstruct(HaloRen *har, RenderLayer **rlpp, int totsample, int od, float dist, float xn, float yn, PixStr *ps) -{ - float col[4], accol[4], fac; - int amount, amountm, zz, flarec, sample, fullsample, mask=0; - - fullsample= (totsample > 1); - amount= 0; - accol[0] = accol[1] = accol[2] = accol[3]= 0.0f; - col[0] = col[1] = col[2] = col[3]= 0.0f; - flarec= har->flarec; - - while (ps) { - amountm= count_mask(ps->mask); - amount+= amountm; - - zz= calchalo_z(har, ps->z); - if ((zz> har->zs) || (har->mat && (har->mat->mode & MA_HALO_SOFT))) { - if (shadeHaloFloat(har, col, zz, dist, xn, yn, flarec)) { - flarec= 0; - - if (fullsample) { - for (sample=0; sample<totsample; sample++) { - if (ps->mask & (1 << sample)) { - float *pass = RE_RenderLayerGetPass(rlpp[sample], RE_PASSNAME_COMBINED, R.viewname); - addalphaAddfacFloat(pass + od*4, col, har->add); - } - } - } - else { - fac= ((float)amountm)/(float)R.osa; - accol[0]+= fac*col[0]; - accol[1]+= fac*col[1]; - accol[2]+= fac*col[2]; - accol[3]+= fac*col[3]; - } - } - } - - mask |= ps->mask; - ps= ps->next; - } - - /* now do the sky sub-pixels */ - amount= R.osa-amount; - if (amount) { - if (shadeHaloFloat(har, col, 0x7FFFFF, dist, xn, yn, flarec)) { - if (!fullsample) { - fac= ((float)amount)/(float)R.osa; - accol[0]+= fac*col[0]; - accol[1]+= fac*col[1]; - accol[2]+= fac*col[2]; - accol[3]+= fac*col[3]; - } - } - } - - if (fullsample) { - for (sample=0; sample<totsample; sample++) { - if (!(mask & (1 << sample))) { - float *pass = RE_RenderLayerGetPass(rlpp[sample], RE_PASSNAME_COMBINED, R.viewname); - addalphaAddfacFloat(pass + od*4, col, har->add); - } - } - } - else { - col[0]= accol[0]; - col[1]= accol[1]; - col[2]= accol[2]; - col[3]= accol[3]; - - for (sample=0; sample<totsample; sample++) { - float *pass = RE_RenderLayerGetPass(rlpp[sample], RE_PASSNAME_COMBINED, R.viewname); - addalphaAddfacFloat(pass + od*4, col, har->add); - } - } -} - -static void halo_tile(RenderPart *pa, RenderLayer *rl) -{ - RenderLayer *rlpp[RE_MAX_OSA]; - HaloRen *har; - rcti disprect= pa->disprect, testrect= pa->disprect; - float dist, xsq, ysq, xn, yn; - float col[4]; - intptr_t *rd= NULL; - int a, *rz, zz, y, sample, totsample, od; - short minx, maxx, miny, maxy, x; - unsigned int lay= rl->lay; - - /* we don't render halos in the cropped area, gives errors in flare counter */ - if (pa->crop) { - testrect.xmin+= pa->crop; - testrect.xmax-= pa->crop; - testrect.ymin+= pa->crop; - testrect.ymax-= pa->crop; - } - - totsample= get_sample_layers(pa, rl, rlpp); - - for (a=0; a<R.tothalo; a++) { - har= R.sortedhalos[a]; - - /* layer test, clip halo with y */ - if ((har->lay & lay) == 0) { - /* pass */ - } - else if (testrect.ymin > har->maxy) { - /* pass */ - } - else if (testrect.ymax < har->miny) { - /* pass */ - } - else { - - minx= floor(har->xs-har->rad); - maxx= ceil(har->xs+har->rad); - - if (testrect.xmin > maxx) { - /* pass */ - } - else if (testrect.xmax < minx) { - /* pass */ - } - else { - - minx = max_ii(minx, testrect.xmin); - maxx = min_ii(maxx, testrect.xmax); - - miny = max_ii(har->miny, testrect.ymin); - maxy = min_ii(har->maxy, testrect.ymax); - - for (y=miny; y<maxy; y++) { - int rectofs= (y-disprect.ymin)*pa->rectx + (minx - disprect.xmin); - rz= pa->rectz + rectofs; - od= rectofs; - - if (pa->rectdaps) - rd= pa->rectdaps + rectofs; - - yn= (y-har->ys)*R.ycor; - ysq= yn*yn; - - for (x=minx; x<maxx; x++, rz++, od++) { - xn= x- har->xs; - xsq= xn*xn; - dist= xsq+ysq; - if (dist<har->radsq) { - if (rd && *rd) { - halo_pixelstruct(har, rlpp, totsample, od, dist, xn, yn, (PixStr *)*rd); - } - else { - zz= calchalo_z(har, *rz); - if ((zz> har->zs) || (har->mat && (har->mat->mode & MA_HALO_SOFT))) { - if (shadeHaloFloat(har, col, zz, dist, xn, yn, har->flarec)) { - for (sample=0; sample<totsample; sample++) { - float * rect= RE_RenderLayerGetPass(rlpp[sample], RE_PASSNAME_COMBINED, R.viewname); - addalphaAddfacFloat(rect + od*4, col, har->add); - } - } - } - } - } - if (rd) rd++; - } - } - } - } - if (R.test_break(R.tbh) ) break; - } -} - -static void lamphalo_tile(RenderPart *pa, RenderLayer *rl) -{ - RenderLayer *rlpp[RE_MAX_OSA]; - ShadeInput shi; - float *pass; - float fac, col[4]; - intptr_t *rd= pa->rectdaps; - const int *rz= pa->rectz; - int x, y, sample, totsample, fullsample, od; - - totsample= get_sample_layers(pa, rl, rlpp); - fullsample= (totsample > 1); - - shade_input_initialize(&shi, pa, rl, 0); /* this zero's ShadeInput for us */ - - for (od=0, y=pa->disprect.ymin; y<pa->disprect.ymax; y++) { - for (x=pa->disprect.xmin; x<pa->disprect.xmax; x++, rz++, od++) { - - calc_view_vector(shi.view, x, y); - - if (rd && *rd) { - PixStr *ps= (PixStr *)*rd; - int count, totsamp= 0, mask= 0; - - while (ps) { - if (R.r.mode & R_ORTHO) - calc_renderco_ortho(shi.co, (float)x, (float)y, ps->z); - else - calc_renderco_zbuf(shi.co, shi.view, ps->z); - - totsamp+= count= count_mask(ps->mask); - mask |= ps->mask; - - col[0]= col[1]= col[2]= col[3]= 0.0f; - renderspothalo(&shi, col, 1.0f); - - if (fullsample) { - for (sample=0; sample<totsample; sample++) { - if (ps->mask & (1 << sample)) { - pass = RE_RenderLayerGetPass(rlpp[sample], RE_PASSNAME_COMBINED, R.viewname); - pass += od * 4; - pass[0]+= col[0]; - pass[1]+= col[1]; - pass[2]+= col[2]; - pass[3]+= col[3]; - if (pass[3]>1.0f) pass[3]= 1.0f; - } - } - } - else { - fac= ((float)count)/(float)R.osa; - pass = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, R.viewname); - pass += od * 4; - pass[0]+= fac*col[0]; - pass[1]+= fac*col[1]; - pass[2]+= fac*col[2]; - pass[3]+= fac*col[3]; - if (pass[3]>1.0f) pass[3]= 1.0f; - } - - ps= ps->next; - } - - if (totsamp<R.osa) { - shi.co[2]= 0.0f; - - col[0]= col[1]= col[2]= col[3]= 0.0f; - renderspothalo(&shi, col, 1.0f); - - if (fullsample) { - for (sample=0; sample<totsample; sample++) { - if (!(mask & (1 << sample))) { - - pass = RE_RenderLayerGetPass(rlpp[sample], RE_PASSNAME_COMBINED, R.viewname); - pass += od * 4; - pass[0]+= col[0]; - pass[1]+= col[1]; - pass[2]+= col[2]; - pass[3]+= col[3]; - if (pass[3]>1.0f) pass[3]= 1.0f; - } - } - } - else { - fac= ((float)R.osa-totsamp)/(float)R.osa; - pass = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, R.viewname); - pass += od * 4; - pass[0]+= fac*col[0]; - pass[1]+= fac*col[1]; - pass[2]+= fac*col[2]; - pass[3]+= fac*col[3]; - if (pass[3]>1.0f) pass[3]= 1.0f; - } - } - } - else { - if (R.r.mode & R_ORTHO) - calc_renderco_ortho(shi.co, (float)x, (float)y, *rz); - else - calc_renderco_zbuf(shi.co, shi.view, *rz); - - col[0]= col[1]= col[2]= col[3]= 0.0f; - renderspothalo(&shi, col, 1.0f); - - for (sample=0; sample<totsample; sample++) { - pass = RE_RenderLayerGetPass(rlpp[sample], RE_PASSNAME_COMBINED, R.viewname); - pass += od * 4; - pass[0]+= col[0]; - pass[1]+= col[1]; - pass[2]+= col[2]; - pass[3]+= col[3]; - if (pass[3]>1.0f) pass[3]= 1.0f; - } - } - - if (rd) rd++; - } - if (y&1) - if (R.test_break(R.tbh)) break; - } -} - - -/* ********************* MAINLOOPS ******************** */ - -/* osa version */ -static void add_filt_passes(RenderLayer *rl, int curmask, int rectx, int offset, ShadeInput *shi, ShadeResult *shr) -{ - RenderPass *rpass; - - for (rpass= rl->passes.first; rpass; rpass= rpass->next) { - float *fp, *col= NULL; - int pixsize= 3; - - if (STREQ(rpass->name, RE_PASSNAME_COMBINED)) { - add_filt_fmask(curmask, shr->combined, rpass->rect + 4*offset, rectx); - } - else if (STREQ(rpass->name, RE_PASSNAME_Z)) { - fp = rpass->rect + offset; - *fp = shr->z; - } - else if (STREQ(rpass->name, RE_PASSNAME_RGBA)) { - col = shr->col; - pixsize = 4; - } - else if (STREQ(rpass->name, RE_PASSNAME_EMIT)) { - col = shr->emit; - } - else if (STREQ(rpass->name, RE_PASSNAME_DIFFUSE)) { - col = shr->diff; - } - else if (STREQ(rpass->name, RE_PASSNAME_SPEC)) { - col = shr->spec; - } - else if (STREQ(rpass->name, RE_PASSNAME_SHADOW)) { - col = shr->shad; - } - else if (STREQ(rpass->name, RE_PASSNAME_AO)) { - col = shr->ao; - } - else if (STREQ(rpass->name, RE_PASSNAME_ENVIRONMENT)) { - col = shr->env; - } - else if (STREQ(rpass->name, RE_PASSNAME_INDIRECT)) { - col = shr->indirect; - } - else if (STREQ(rpass->name, RE_PASSNAME_REFLECT)) { - col = shr->refl; - } - else if (STREQ(rpass->name, RE_PASSNAME_REFRACT)) { - col = shr->refr; - } - else if (STREQ(rpass->name, RE_PASSNAME_NORMAL)) { - col = shr->nor; - } - else if (STREQ(rpass->name, RE_PASSNAME_UV)) { - /* box filter only, gauss will screwup UV too much */ - if (shi->totuv) { - float mult = (float)count_mask(curmask)/(float)R.osa; - fp = rpass->rect + 3*offset; - fp[0]+= mult*(0.5f + 0.5f*shi->uv[shi->actuv].uv[0]); - fp[1]+= mult*(0.5f + 0.5f*shi->uv[shi->actuv].uv[1]); - fp[2]+= mult; - } - } - else if (STREQ(rpass->name, RE_PASSNAME_INDEXOB)) { - /* no filter */ - if (shi->vlr) { - fp = rpass->rect + offset; - if (*fp==0.0f) - *fp = (float)shi->obr->ob->index; - } - } - else if (STREQ(rpass->name, RE_PASSNAME_INDEXMA)) { - /* no filter */ - if (shi->vlr) { - fp = rpass->rect + offset; - if (*fp==0.0f) - *fp = (float)shi->mat->index; - } - } - else if (STREQ(rpass->name, RE_PASSNAME_MIST)) { - /* */ - col = &shr->mist; - pixsize = 1; - } - else if (STREQ(rpass->name, RE_PASSNAME_VECTOR)) { - /* add minimum speed in pixel, no filter */ - fp = rpass->rect + 4*offset; - if ( (ABS(shr->winspeed[0]) + ABS(shr->winspeed[1]))< (ABS(fp[0]) + ABS(fp[1])) ) { - fp[0] = shr->winspeed[0]; - fp[1] = shr->winspeed[1]; - } - if ( (ABS(shr->winspeed[2]) + ABS(shr->winspeed[3]))< (ABS(fp[2]) + ABS(fp[3])) ) { - fp[2] = shr->winspeed[2]; - fp[3] = shr->winspeed[3]; - } - } - else if (STREQ(rpass->name, RE_PASSNAME_RAYHITS)) { - /* */ - col = shr->rayhits; - pixsize= 4; - } - - if (col) { - fp= rpass->rect + pixsize*offset; - add_filt_fmask_pixsize(curmask, col, fp, rectx, pixsize); - } - } -} - -/* non-osa version */ -static void add_passes(RenderLayer *rl, int offset, ShadeInput *shi, ShadeResult *shr) -{ - RenderPass *rpass; - float *fp; - - for (rpass= rl->passes.first; rpass; rpass= rpass->next) { - float *col= NULL, uvcol[3]; - int a, pixsize= 3; - - if (STREQ(rpass->name, RE_PASSNAME_COMBINED)) { - /* copy combined to use for preview */ - copy_v4_v4(rpass->rect + 4*offset, shr->combined); - } - else if (STREQ(rpass->name, RE_PASSNAME_Z)) { - fp = rpass->rect + offset; - *fp = shr->z; - } - else if (STREQ(rpass->name, RE_PASSNAME_RGBA)) { - col = shr->col; - pixsize = 4; - } - else if (STREQ(rpass->name, RE_PASSNAME_EMIT)) { - col = shr->emit; - } - else if (STREQ(rpass->name, RE_PASSNAME_DIFFUSE)) { - col = shr->diff; - } - else if (STREQ(rpass->name, RE_PASSNAME_SPEC)) { - col = shr->spec; - } - else if (STREQ(rpass->name, RE_PASSNAME_SHADOW)) { - col = shr->shad; - } - else if (STREQ(rpass->name, RE_PASSNAME_AO)) { - col = shr->ao; - } - else if (STREQ(rpass->name, RE_PASSNAME_ENVIRONMENT)) { - col = shr->env; - } - else if (STREQ(rpass->name, RE_PASSNAME_INDIRECT)) { - col = shr->indirect; - } - else if (STREQ(rpass->name, RE_PASSNAME_REFLECT)) { - col = shr->refl; - } - else if (STREQ(rpass->name, RE_PASSNAME_REFRACT)) { - col = shr->refr; - } - else if (STREQ(rpass->name, RE_PASSNAME_NORMAL)) { - col = shr->nor; - } - else if (STREQ(rpass->name, RE_PASSNAME_UV)) { - if (shi->totuv) { - uvcol[0] = 0.5f + 0.5f*shi->uv[shi->actuv].uv[0]; - uvcol[1] = 0.5f + 0.5f*shi->uv[shi->actuv].uv[1]; - uvcol[2] = 1.0f; - col = uvcol; - } - } - else if (STREQ(rpass->name, RE_PASSNAME_VECTOR)) { - col = shr->winspeed; - pixsize = 4; - } - else if (STREQ(rpass->name, RE_PASSNAME_INDEXOB)) { - if (shi->vlr) { - fp = rpass->rect + offset; - *fp = (float)shi->obr->ob->index; - } - } - else if (STREQ(rpass->name, RE_PASSNAME_INDEXMA)) { - if (shi->vlr) { - fp = rpass->rect + offset; - *fp = (float)shi->mat->index; - } - } - else if (STREQ(rpass->name, RE_PASSNAME_MIST)) { - fp = rpass->rect + offset; - *fp = shr->mist; - } - else if (STREQ(rpass->name, RE_PASSNAME_RAYHITS)) { - col = shr->rayhits; - pixsize = 4; - } - - if (col) { - fp = rpass->rect + pixsize*offset; - for (a=0; a<pixsize; a++) - fp[a] = col[a]; - } - } -} - -int get_sample_layers(RenderPart *pa, RenderLayer *rl, RenderLayer **rlpp) -{ - - if (pa->fullresult.first) { - int sample, nr= BLI_findindex(&pa->result->layers, rl); - - for (sample=0; sample<R.osa; sample++) { - RenderResult *rr= BLI_findlink(&pa->fullresult, sample); - - rlpp[sample]= BLI_findlink(&rr->layers, nr); - } - return R.osa; - } - else { - rlpp[0]= rl; - return 1; - } -} - - -/* only do sky, is default in the solid layer (shade_tile) btw */ -static void sky_tile(RenderPart *pa, RenderLayer *rl) -{ - RenderLayer *rlpp[RE_MAX_OSA]; - int x, y, od=0, totsample; - - if (R.r.alphamode!=R_ADDSKY) - return; - - totsample= get_sample_layers(pa, rl, rlpp); - - for (y=pa->disprect.ymin; y<pa->disprect.ymax; y++) { - for (x=pa->disprect.xmin; x<pa->disprect.xmax; x++, od+=4) { - float col[4]; - int sample; - bool done = false; - - for (sample= 0; sample<totsample; sample++) { - float *pass = RE_RenderLayerGetPass(rlpp[sample], RE_PASSNAME_COMBINED, R.viewname); - pass += od; - - if (pass[3]<1.0f) { - - if (done==0) { - shadeSkyPixel(col, x, y, pa->thread); - done = true; - } - - if (pass[3]==0.0f) { - copy_v4_v4(pass, col); - pass[3] = 1.0f; - } - else { - addAlphaUnderFloat(pass, col); - pass[3] = 1.0f; - } - } - } - } - - if (y&1) - if (R.test_break(R.tbh)) break; - } -} - -static void atm_tile(RenderPart *pa, RenderLayer *rl) -{ - RenderPass *zpass; - GroupObject *go; - LampRen *lar; - RenderLayer *rlpp[RE_MAX_OSA]; - int totsample; - int x, y, od= 0; - - totsample= get_sample_layers(pa, rl, rlpp); - - /* check that z pass is enabled */ - if (pa->rectz==NULL) return; - for (zpass= rl->passes.first; zpass; zpass= zpass->next) - if (STREQ(zpass->name, RE_PASSNAME_Z)) - break; - - if (zpass==NULL) return; - - /* check for at least one sun lamp that its atmosphere flag is enabled */ - for (go=R.lights.first; go; go= go->next) { - lar= go->lampren; - if (lar->type==LA_SUN && lar->sunsky && (lar->sunsky->effect_type & LA_SUN_EFFECT_AP)) - break; - } - /* do nothign and return if there is no sun lamp */ - if (go==NULL) - return; - - /* for each x,y and each sample, and each sun lamp*/ - for (y=pa->disprect.ymin; y<pa->disprect.ymax; y++) { - for (x=pa->disprect.xmin; x<pa->disprect.xmax; x++, od++) { - int sample; - - for (sample=0; sample<totsample; sample++) { - const float *zrect = RE_RenderLayerGetPass(rlpp[sample], RE_PASSNAME_Z, R.viewname) + od; - float *rgbrect = RE_RenderLayerGetPass(rlpp[sample], RE_PASSNAME_COMBINED, R.viewname) + 4*od; - float rgb[3] = {0}; - bool done = false; - - for (go=R.lights.first; go; go= go->next) { - - - lar= go->lampren; - if (lar->type==LA_SUN && lar->sunsky) { - - /* if it's sky continue and don't apply atmosphere effect on it */ - if (*zrect >= 9.9e10f || rgbrect[3]==0.0f) { - continue; - } - - if ((lar->sunsky->effect_type & LA_SUN_EFFECT_AP)) { - float tmp_rgb[3]; - - /* skip if worldspace lamp vector is below horizon */ - if (go->ob->obmat[2][2] < 0.f) { - continue; - } - - copy_v3_v3(tmp_rgb, rgbrect); - if (rgbrect[3]!=1.0f) { /* de-premul */ - mul_v3_fl(tmp_rgb, 1.0f/rgbrect[3]); - } - shadeAtmPixel(lar->sunsky, tmp_rgb, x, y, *zrect); - if (rgbrect[3]!=1.0f) { /* premul */ - mul_v3_fl(tmp_rgb, rgbrect[3]); - } - - if (done==0) { - copy_v3_v3(rgb, tmp_rgb); - done = true; - } - else { - rgb[0] = 0.5f*rgb[0] + 0.5f*tmp_rgb[0]; - rgb[1] = 0.5f*rgb[1] + 0.5f*tmp_rgb[1]; - rgb[2] = 0.5f*rgb[2] + 0.5f*tmp_rgb[2]; - } - } - } - } - - /* if at least for one sun lamp aerial perspective was applied*/ - if (done) { - copy_v3_v3(rgbrect, rgb); - } - } - } - } -} - -static void shadeDA_tile(RenderPart *pa, RenderLayer *rl) -{ - RenderResult *rr= pa->result; - ShadeSample ssamp; - intptr_t *rd, *rectdaps= pa->rectdaps; - int samp; - int x, y, seed, crop=0, offs=0, od; - - if (R.test_break(R.tbh)) return; - - /* irregular shadowb buffer creation */ - if (R.r.mode & R_SHADOW) - ISB_create(pa, NULL); - - /* we set per pixel a fixed seed, for random AO and shadow samples */ - seed= pa->rectx*pa->disprect.ymin; - - /* general shader info, passes */ - shade_sample_initialize(&ssamp, pa, rl); - - /* occlusion caching */ - if (R.occlusiontree) - cache_occ_samples(&R, pa, &ssamp); - - /* filtered render, for now we assume only 1 filter size */ - if (pa->crop) { - crop= 1; - rectdaps+= pa->rectx + 1; - offs= pa->rectx + 1; - } - - /* scanline updates have to be 2 lines behind */ - rr->renrect.ymin = 0; - rr->renrect.ymax = -2*crop; - rr->renlay= rl; - - for (y=pa->disprect.ymin+crop; y<pa->disprect.ymax-crop; y++, rr->renrect.ymax++) { - rd= rectdaps; - od= offs; - - for (x=pa->disprect.xmin+crop; x<pa->disprect.xmax-crop; x++, rd++, od++) { - BLI_thread_srandom(pa->thread, seed++); - - if (*rd) { - if (shade_samples(&ssamp, (PixStr *)(*rd), x, y)) { - - /* multisample buffers or filtered mask filling? */ - if (pa->fullresult.first) { - int a; - for (samp=0; samp<ssamp.tot; samp++) { - int smask= ssamp.shi[samp].mask; - for (a=0; a<R.osa; a++) { - int mask= 1<<a; - if (smask & mask) - add_passes(ssamp.rlpp[a], od, &ssamp.shi[samp], &ssamp.shr[samp]); - } - } - } - else { - for (samp=0; samp<ssamp.tot; samp++) - add_filt_passes(rl, ssamp.shi[samp].mask, pa->rectx, od, &ssamp.shi[samp], &ssamp.shr[samp]); - } - } - } - } - - rectdaps+= pa->rectx; - offs+= pa->rectx; - - if (y&1) if (R.test_break(R.tbh)) break; - } - - /* disable scanline updating */ - rr->renlay= NULL; - - if (R.r.mode & R_SHADOW) - ISB_free(pa); - - if (R.occlusiontree) - free_occ_samples(&R, pa); -} - -/* ************* pixel struct ******** */ - - -static PixStrMain *addpsmain(ListBase *lb) -{ - PixStrMain *psm; - - psm= (PixStrMain *)MEM_mallocN(sizeof(PixStrMain), "pixstrMain"); - BLI_addtail(lb, psm); - - psm->ps= (PixStr *)MEM_mallocN(4096*sizeof(PixStr), "pixstr"); - psm->counter= 0; - - return psm; -} - -static void freeps(ListBase *lb) -{ - PixStrMain *psm, *psmnext; - - for (psm= lb->first; psm; psm= psmnext) { - psmnext= psm->next; - if (psm->ps) - MEM_freeN(psm->ps); - MEM_freeN(psm); - } - BLI_listbase_clear(lb); -} - -static void addps(ListBase *lb, intptr_t *rd, int obi, int facenr, int z, int maskz, unsigned short mask) -{ - PixStrMain *psm; - PixStr *ps, *last= NULL; - - if (*rd) { - ps= (PixStr *)(*rd); - - while (ps) { - if ( ps->obi == obi && ps->facenr == facenr ) { - ps->mask |= mask; - return; - } - last= ps; - ps= ps->next; - } - } - - /* make new PS (pixel struct) */ - psm= lb->last; - - if (psm->counter==4095) - psm= addpsmain(lb); - - ps= psm->ps + psm->counter++; - - if (last) last->next= ps; - else *rd= (intptr_t)ps; - - ps->next= NULL; - ps->obi= obi; - ps->facenr= facenr; - ps->z= z; - ps->maskz= maskz; - ps->mask = mask; - ps->shadfac= 0; -} - -static void edge_enhance_add(RenderPart *pa, float *rectf, float *arect) -{ - float addcol[4]; - int pix; - - if (arect==NULL) - return; - - for (pix= pa->rectx*pa->recty; pix>0; pix--, arect++, rectf+=4) { - if (*arect != 0.0f) { - addcol[0]= *arect * R.r.edgeR; - addcol[1]= *arect * R.r.edgeG; - addcol[2]= *arect * R.r.edgeB; - addcol[3]= *arect; - addAlphaOverFloat(rectf, addcol); - } - } -} - -/* clamp alpha and RGB to 0..1 and 0..inf, can go outside due to filter */ -static void clamp_alpha_rgb_range(RenderPart *pa, RenderLayer *rl) -{ - RenderLayer *rlpp[RE_MAX_OSA]; - int y, sample, totsample; - - totsample= get_sample_layers(pa, rl, rlpp); - - /* not for full sample, there we clamp after compositing */ - if (totsample > 1) - return; - - for (sample= 0; sample<totsample; sample++) { - float *rectf = RE_RenderLayerGetPass(rlpp[sample], RE_PASSNAME_COMBINED, R.viewname); - - for (y= pa->rectx*pa->recty; y>0; y--, rectf+=4) { - rectf[0] = MAX2(rectf[0], 0.0f); - rectf[1] = MAX2(rectf[1], 0.0f); - rectf[2] = MAX2(rectf[2], 0.0f); - CLAMP(rectf[3], 0.0f, 1.0f); - } - } -} - -/* adds only alpha values */ -static void edge_enhance_tile(RenderPart *pa, float *rectf, int *rectz) -{ - /* use zbuffer to define edges, add it to the image */ - int y, x, col, *rz, *rz1, *rz2, *rz3; - int zval1, zval2, zval3; - float *rf; - - /* shift values in zbuffer 4 to the right (anti overflows), for filter we need multiplying with 12 max */ - rz= rectz; - if (rz==NULL) return; - - for (y=0; y<pa->recty; y++) - for (x=0; x<pa->rectx; x++, rz++) (*rz)>>= 4; - - rz1= rectz; - rz2= rz1+pa->rectx; - rz3= rz2+pa->rectx; - - rf= rectf+pa->rectx+1; - - for (y=0; y<pa->recty-2; y++) { - for (x=0; x<pa->rectx-2; x++, rz1++, rz2++, rz3++, rf++) { - - /* prevent overflow with sky z values */ - zval1= rz1[0] + 2*rz1[1] + rz1[2]; - zval2= 2*rz2[0] + 2*rz2[2]; - zval3= rz3[0] + 2*rz3[1] + rz3[2]; - - col= ( 4*rz2[1] - (zval1 + zval2 + zval3)/3 ); - if (col<0) col= -col; - - col >>= 5; - if (col > (1<<16)) col= (1<<16); - else col= (R.r.edgeint*col)>>8; - - if (col>0) { - float fcol; - - if (col>255) fcol= 1.0f; - else fcol= (float)col/255.0f; - - if (R.osa) - *rf+= fcol/(float)R.osa; - else - *rf= fcol; - } - } - rz1+= 2; - rz2+= 2; - rz3+= 2; - rf+= 2; - } - - /* shift back zbuf values, we might need it still */ - rz= rectz; - for (y=0; y<pa->recty; y++) - for (x=0; x<pa->rectx; x++, rz++) (*rz)<<= 4; - -} - -static void reset_sky_speed(RenderPart *pa, RenderLayer *rl) -{ - /* for all pixels with max speed, set to zero */ - RenderLayer *rlpp[RE_MAX_OSA]; - float *fp; - int a, sample, totsample; - - totsample= get_sample_layers(pa, rl, rlpp); - - for (sample= 0; sample<totsample; sample++) { - fp= RE_RenderLayerGetPass(rlpp[sample], RE_PASSNAME_VECTOR, R.viewname); - if (fp==NULL) break; - - for (a= 4*pa->rectx*pa->recty - 1; a>=0; a--) - if (fp[a] == PASS_VECTOR_MAX) fp[a]= 0.0f; - } -} - -static unsigned short *make_solid_mask(RenderPart *pa) -{ - intptr_t *rd= pa->rectdaps; - unsigned short *solidmask, *sp; - int x; - - if (rd==NULL) return NULL; - - sp=solidmask= MEM_mallocN(sizeof(short)*pa->rectx*pa->recty, "solidmask"); - - for (x=pa->rectx*pa->recty; x>0; x--, rd++, sp++) { - if (*rd) { - PixStr *ps= (PixStr *)*rd; - - *sp= ps->mask; - for (ps= ps->next; ps; ps= ps->next) - *sp |= ps->mask; - } - else - *sp= 0; - } - - return solidmask; -} - -static void addAlphaOverFloatMask(float *dest, float *source, unsigned short dmask, unsigned short smask) -{ - unsigned short shared= dmask & smask; - float mul= 1.0f - source[3]; - - if (shared) { /* overlapping masks */ - - /* masks differ, we make a mixture of 'add' and 'over' */ - if (shared!=dmask) { - float shared_bits= (float)count_mask(shared); /* alpha over */ - float tot_bits= (float)count_mask(smask|dmask); /* alpha add */ - - float add= (tot_bits - shared_bits)/tot_bits; /* add level */ - mul= add + (1.0f-add)*mul; - } - } - else if (dmask && smask) { - /* works for premul only, of course */ - dest[0]+= source[0]; - dest[1]+= source[1]; - dest[2]+= source[2]; - dest[3]+= source[3]; - - return; - } - - dest[0]= (mul*dest[0]) + source[0]; - dest[1]= (mul*dest[1]) + source[1]; - dest[2]= (mul*dest[2]) + source[2]; - dest[3]= (mul*dest[3]) + source[3]; -} - -typedef struct ZbufSolidData { - RenderLayer *rl; - ListBase *psmlist; - float *edgerect; -} ZbufSolidData; - -static void make_pixelstructs(RenderPart *pa, ZSpan *zspan, int sample, void *data) -{ - ZbufSolidData *sdata = (ZbufSolidData *)data; - ListBase *lb= sdata->psmlist; - intptr_t *rd= pa->rectdaps; - const int *ro= zspan->recto; - const int *rp= zspan->rectp; - const int *rz= zspan->rectz; - const int *rm= zspan->rectmask; - int x, y; - int mask= 1<<sample; - - for (y=0; y<pa->recty; y++) { - for (x=0; x<pa->rectx; x++, rd++, rp++, ro++, rz++, rm++) { - if (*rp) { - addps(lb, rd, *ro, *rp, *rz, (zspan->rectmask)? *rm: 0, mask); - } - } - } - - if (sdata->rl->layflag & SCE_LAY_EDGE) - if (R.r.mode & R_EDGE) - edge_enhance_tile(pa, sdata->edgerect, zspan->rectz); -} - -/* main call for shading Delta Accum, for OSA */ -/* supposed to be fully threadable! */ -void zbufshadeDA_tile(RenderPart *pa) -{ - RenderResult *rr= pa->result; - RenderLayer *rl; - ListBase psmlist= {NULL, NULL}; - float *edgerect= NULL; - - /* allocate the necessary buffers */ - /* zbuffer inits these rects */ - pa->recto= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "recto"); - pa->rectp= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectp"); - pa->rectz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectz"); - for (rl= rr->layers.first; rl; rl= rl->next) { - float *rect = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, R.viewname); - - if ((rl->layflag & SCE_LAY_ZMASK) && (rl->layflag & SCE_LAY_NEG_ZMASK)) - pa->rectmask= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectmask"); - - /* initialize pixelstructs and edge buffer */ - addpsmain(&psmlist); - pa->rectdaps= MEM_callocN(sizeof(intptr_t)*pa->rectx*pa->recty+4, "zbufDArectd"); - - if (rl->layflag & SCE_LAY_EDGE) - if (R.r.mode & R_EDGE) - edgerect= MEM_callocN(sizeof(float)*pa->rectx*pa->recty, "rectedge"); - - /* always fill visibility */ - for (pa->sample=0; pa->sample<R.osa; pa->sample+=4) { - ZbufSolidData sdata; - - sdata.rl= rl; - sdata.psmlist= &psmlist; - sdata.edgerect= edgerect; - zbuffer_solid(pa, rl, make_pixelstructs, &sdata); - if (R.test_break(R.tbh)) break; - } - - /* shades solid */ - if (rl->layflag & SCE_LAY_SOLID) - shadeDA_tile(pa, rl); - - /* lamphalo after solid, before ztra, looks nicest because ztra does own halo */ - if (R.flag & R_LAMPHALO) - if (rl->layflag & SCE_LAY_HALO) - lamphalo_tile(pa, rl); - - /* halo before ztra, because ztra fills in zbuffer now */ - if (R.flag & R_HALO) - if (rl->layflag & SCE_LAY_HALO) - halo_tile(pa, rl); - - /* transp layer */ - if (R.flag & R_ZTRA || R.totstrand) { - if (rl->layflag & (SCE_LAY_ZTRA|SCE_LAY_STRAND)) { - if (pa->fullresult.first) { - zbuffer_transp_shade(pa, rl, rect, &psmlist); - } - else { - unsigned short *ztramask, *solidmask= NULL; /* 16 bits, MAX_OSA */ - - /* allocate, but not free here, for asynchronous display of this rect in main thread */ - rl->acolrect= MEM_callocN(4*sizeof(float)*pa->rectx*pa->recty, "alpha layer"); - - /* swap for live updates, and it is used in zbuf.c!!! */ - SWAP(float *, rl->acolrect, rect); - ztramask = zbuffer_transp_shade(pa, rl, rect, &psmlist); - SWAP(float *, rl->acolrect, rect); - - /* zbuffer transp only returns ztramask if there's solid rendered */ - if (ztramask) - solidmask= make_solid_mask(pa); - - if (ztramask && solidmask) { - unsigned short *sps= solidmask, *spz= ztramask; - unsigned short fullmask= (1<<R.osa)-1; - float *fcol= rect; - float *acol= rl->acolrect; - int x; - - for (x=pa->rectx*pa->recty; x>0; x--, acol+=4, fcol+=4, sps++, spz++) { - if (*sps == fullmask) - addAlphaOverFloat(fcol, acol); - else - addAlphaOverFloatMask(fcol, acol, *sps, *spz); - } - } - else { - float *fcol= rect; - float *acol= rl->acolrect; - int x; - for (x=pa->rectx*pa->recty; x>0; x--, acol+=4, fcol+=4) { - addAlphaOverFloat(fcol, acol); - } - } - if (solidmask) MEM_freeN(solidmask); - if (ztramask) MEM_freeN(ztramask); - } - } - } - - /* sun/sky */ - if (rl->layflag & SCE_LAY_SKY) - atm_tile(pa, rl); - - /* sky before edge */ - if (rl->layflag & SCE_LAY_SKY) - sky_tile(pa, rl); - - /* extra layers */ - if (rl->layflag & SCE_LAY_EDGE) - if (R.r.mode & R_EDGE) - edge_enhance_add(pa, rect, edgerect); - - if (rl->passflag & SCE_PASS_VECTOR) - reset_sky_speed(pa, rl); - - /* clamp alpha to 0..1 range, can go outside due to filter */ - clamp_alpha_rgb_range(pa, rl); - - /* free stuff within loop! */ - MEM_freeN(pa->rectdaps); pa->rectdaps= NULL; - freeps(&psmlist); - - if (edgerect) MEM_freeN(edgerect); - edgerect= NULL; - - if (pa->rectmask) { - MEM_freeN(pa->rectmask); - pa->rectmask= NULL; - } - } - - /* free all */ - MEM_freeN(pa->recto); pa->recto= NULL; - MEM_freeN(pa->rectp); pa->rectp= NULL; - MEM_freeN(pa->rectz); pa->rectz= NULL; - - /* display active layer */ - rr->renrect.ymin=rr->renrect.ymax = 0; - rr->renlay= render_get_active_layer(&R, rr); -} - - -/* ------------------------------------------------------------------------ */ - -/* non OSA case, full tile render */ -/* supposed to be fully threadable! */ -void zbufshade_tile(RenderPart *pa) -{ - ShadeSample ssamp; - RenderResult *rr= pa->result; - RenderLayer *rl; - PixStr ps; - float *edgerect= NULL; - - /* fake pixel struct, to comply to osa render */ - ps.next= NULL; - ps.mask= 0xFFFF; - - /* zbuffer code clears/inits rects */ - pa->recto= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "recto"); - pa->rectp= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectp"); - pa->rectz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectz"); - - for (rl= rr->layers.first; rl; rl= rl->next) { - float *rect= RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, R.viewname); - if ((rl->layflag & SCE_LAY_ZMASK) && (rl->layflag & SCE_LAY_NEG_ZMASK)) - pa->rectmask= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectmask"); - - /* general shader info, passes */ - shade_sample_initialize(&ssamp, pa, rl); - - zbuffer_solid(pa, rl, NULL, NULL); - - if (!R.test_break(R.tbh)) { /* NOTE: this if () is not consistent */ - - /* edges only for solid part, ztransp doesn't support it yet anti-aliased */ - if (rl->layflag & SCE_LAY_EDGE) { - if (R.r.mode & R_EDGE) { - edgerect= MEM_callocN(sizeof(float)*pa->rectx*pa->recty, "rectedge"); - edge_enhance_tile(pa, edgerect, pa->rectz); - } - } - - /* initialize scanline updates for main thread */ - rr->renrect.ymin = 0; - rr->renlay= rl; - - if (rl->layflag & SCE_LAY_SOLID) { - const float *fcol = rect; - const int *ro= pa->recto, *rp= pa->rectp, *rz= pa->rectz; - int x, y, offs=0, seed; - - /* we set per pixel a fixed seed, for random AO and shadow samples */ - seed= pa->rectx*pa->disprect.ymin; - - /* irregular shadowb buffer creation */ - if (R.r.mode & R_SHADOW) - ISB_create(pa, NULL); - - if (R.occlusiontree) - cache_occ_samples(&R, pa, &ssamp); - - for (y=pa->disprect.ymin; y<pa->disprect.ymax; y++, rr->renrect.ymax++) { - for (x=pa->disprect.xmin; x<pa->disprect.xmax; x++, ro++, rz++, rp++, fcol+=4, offs++) { - /* per pixel fixed seed */ - BLI_thread_srandom(pa->thread, seed++); - - if (*rp) { - ps.obi= *ro; - ps.facenr= *rp; - ps.z= *rz; - if (shade_samples(&ssamp, &ps, x, y)) { - /* combined and passes */ - add_passes(rl, offs, ssamp.shi, ssamp.shr); - } - } - } - if (y&1) - if (R.test_break(R.tbh)) break; - } - - if (R.occlusiontree) - free_occ_samples(&R, pa); - - if (R.r.mode & R_SHADOW) - ISB_free(pa); - } - - /* disable scanline updating */ - rr->renlay= NULL; - } - - /* lamphalo after solid, before ztra, looks nicest because ztra does own halo */ - if (R.flag & R_LAMPHALO) - if (rl->layflag & SCE_LAY_HALO) - lamphalo_tile(pa, rl); - - /* halo before ztra, because ztra fills in zbuffer now */ - if (R.flag & R_HALO) - if (rl->layflag & SCE_LAY_HALO) - halo_tile(pa, rl); - - if (R.flag & R_ZTRA || R.totstrand) { - if (rl->layflag & (SCE_LAY_ZTRA|SCE_LAY_STRAND)) { - float *fcol, *acol; - int x; - - /* allocate, but not free here, for asynchronous display of this rect in main thread */ - rl->acolrect= MEM_callocN(4*sizeof(float)*pa->rectx*pa->recty, "alpha layer"); - - /* swap for live updates */ - SWAP(float *, rl->acolrect, rect); - zbuffer_transp_shade(pa, rl, rect, NULL); - SWAP(float *, rl->acolrect, rect); - - fcol= rect; acol= rl->acolrect; - for (x=pa->rectx*pa->recty; x>0; x--, acol+=4, fcol+=4) { - addAlphaOverFloat(fcol, acol); - } - } - } - - /* sun/sky */ - if (rl->layflag & SCE_LAY_SKY) - atm_tile(pa, rl); - - /* sky before edge */ - if (rl->layflag & SCE_LAY_SKY) - sky_tile(pa, rl); - - if (!R.test_break(R.tbh)) { - if (rl->layflag & SCE_LAY_EDGE) - if (R.r.mode & R_EDGE) - edge_enhance_add(pa, rect, edgerect); - } - - if (rl->passflag & SCE_PASS_VECTOR) - reset_sky_speed(pa, rl); - - if (edgerect) MEM_freeN(edgerect); - edgerect= NULL; - - if (pa->rectmask) { - MEM_freeN(pa->rectmask); - pa->rectmask= NULL; - } - } - - /* display active layer */ - rr->renrect.ymin=rr->renrect.ymax = 0; - rr->renlay= render_get_active_layer(&R, rr); - - MEM_freeN(pa->recto); pa->recto= NULL; - MEM_freeN(pa->rectp); pa->rectp= NULL; - MEM_freeN(pa->rectz); pa->rectz= NULL; -} - -/* SSS preprocess tile render, fully threadable */ -typedef struct ZBufSSSHandle { - RenderPart *pa; - ListBase psmlist; - int totps; -} ZBufSSSHandle; - -static void addps_sss(void *cb_handle, int obi, int facenr, int x, int y, int z) -{ - ZBufSSSHandle *handle = cb_handle; - RenderPart *pa= handle->pa; - - /* extra border for filter gives double samples on part edges, - * don't use those */ - if (x<pa->crop || x>=pa->rectx-pa->crop) - return; - if (y<pa->crop || y>=pa->recty-pa->crop) - return; - - if (pa->rectall) { - intptr_t *rs= pa->rectall + pa->rectx*y + x; - - addps(&handle->psmlist, rs, obi, facenr, z, 0, 0); - handle->totps++; - } - if (pa->rectz) { - int *rz= pa->rectz + pa->rectx*y + x; - int *rp= pa->rectp + pa->rectx*y + x; - int *ro= pa->recto + pa->rectx*y + x; - - if (z < *rz) { - if (*rp == 0) - handle->totps++; - *rz= z; - *rp= facenr; - *ro= obi; - } - } - if (pa->rectbackz) { - int *rz= pa->rectbackz + pa->rectx*y + x; - int *rp= pa->rectbackp + pa->rectx*y + x; - int *ro= pa->rectbacko + pa->rectx*y + x; - - if (z >= *rz) { - if (*rp == 0) - handle->totps++; - *rz= z; - *rp= facenr; - *ro= obi; - } - } -} - -static void shade_sample_sss(ShadeSample *ssamp, Material *mat, ObjectInstanceRen *obi, VlakRen *vlr, int quad, float x, float y, float z, float *co, float color[3], float *area) -{ - ShadeInput *shi= ssamp->shi; - ShadeResult shr; - float /* texfac,*/ /* UNUSED */ orthoarea, nor[3], alpha, sx, sy; - - /* cache for shadow */ - shi->samplenr= R.shadowsamplenr[shi->thread]++; - - if (quad) - shade_input_set_triangle_i(shi, obi, vlr, 0, 2, 3); - else - shade_input_set_triangle_i(shi, obi, vlr, 0, 1, 2); - - /* center pixel */ - sx = x + 0.5f; - sy = y + 0.5f; - - /* we estimate the area here using shi->dxco and shi->dyco. we need to - * enabled shi->osatex these are filled. we compute two areas, one with - * the normal pointed at the camera and one with the original normal, and - * then clamp to avoid a too large contribution from a single pixel */ - shi->osatex= 1; - - copy_v3_v3(nor, shi->facenor); - calc_view_vector(shi->facenor, sx, sy); - normalize_v3(shi->facenor); - shade_input_set_viewco(shi, x, y, sx, sy, z); - orthoarea= len_v3(shi->dxco)*len_v3(shi->dyco); - - copy_v3_v3(shi->facenor, nor); - shade_input_set_viewco(shi, x, y, sx, sy, z); - *area = min_ff(len_v3(shi->dxco) * len_v3(shi->dyco), 2.0f * orthoarea); - - shade_input_set_uv(shi); - shade_input_set_normals(shi); - - /* we don't want flipped normals, they screw up back scattering */ - if (shi->flippednor) - shade_input_flip_normals(shi); - - /* not a pretty solution, but fixes common cases */ - if (shi->obr->ob && shi->obr->ob->transflag & OB_NEG_SCALE) { - negate_v3(shi->vn); - negate_v3(shi->vno); - negate_v3(shi->nmapnorm); - } - - /* if nodetree, use the material that we are currently preprocessing - * instead of the node material */ - if (shi->mat->nodetree && shi->mat->use_nodes) - shi->mat= mat; - - /* init material vars */ - shade_input_init_material(shi); - - /* render */ - shade_input_set_shade_texco(shi); - - shade_samples_do_AO(ssamp); - shade_material_loop(shi, &shr); - - copy_v3_v3(co, shi->co); - copy_v3_v3(color, shr.combined); - - /* texture blending */ - /* texfac= shi->mat->sss_texfac; */ /* UNUSED */ - - alpha= shr.combined[3]; - *area *= alpha; -} - -static void zbufshade_sss_free(RenderPart *pa) -{ -#if 0 - MEM_freeN(pa->rectall); pa->rectall= NULL; - freeps(&handle.psmlist); -#else - MEM_freeN(pa->rectz); pa->rectz= NULL; - MEM_freeN(pa->rectp); pa->rectp= NULL; - MEM_freeN(pa->recto); pa->recto= NULL; - MEM_freeN(pa->rectbackz); pa->rectbackz= NULL; - MEM_freeN(pa->rectbackp); pa->rectbackp= NULL; - MEM_freeN(pa->rectbacko); pa->rectbacko= NULL; -#endif -} - -void zbufshade_sss_tile(RenderPart *pa) -{ - Render *re= &R; - ShadeSample ssamp; - ZBufSSSHandle handle; - RenderResult *rr= pa->result; - RenderLayer *rl; - VlakRen *vlr; - Material *mat= re->sss_mat; - float (*co)[3], (*color)[3], *area, *fcol; - int x, y, seed, quad, totpoint; - const bool display = (re->r.scemode & (R_BUTS_PREVIEW | R_VIEWPORT_PREVIEW)) == 0; - int *ro, *rz, *rp, *rbo, *rbz, *rbp, lay; -#if 0 - PixStr *ps; - intptr_t *rs; - int z; -#endif - - /* setup pixelstr list and buffer for zbuffering */ - handle.pa= pa; - handle.totps= 0; - -#if 0 - handle.psmlist.first= handle.psmlist.last= NULL; - addpsmain(&handle.psmlist); - - pa->rectall= MEM_callocN(sizeof(intptr_t)*pa->rectx*pa->recty+4, "rectall"); -#else - pa->recto= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "recto"); - pa->rectp= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectp"); - pa->rectz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectz"); - pa->rectbacko= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectbacko"); - pa->rectbackp= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectbackp"); - pa->rectbackz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectbackz"); -#endif - - /* setup shade sample with correct passes */ - memset(&ssamp, 0, sizeof(ssamp)); - shade_sample_initialize(&ssamp, pa, rr->layers.first); - ssamp.tot= 1; - - for (rl=rr->layers.first; rl; rl=rl->next) { - ssamp.shi[0].lay |= rl->lay; - ssamp.shi[0].layflag |= rl->layflag; - ssamp.shi[0].passflag |= rl->passflag; - ssamp.shi[0].combinedflag |= ~rl->pass_xor; - } - - rl= rr->layers.first; - ssamp.shi[0].passflag |= SCE_PASS_RGBA|SCE_PASS_COMBINED; - ssamp.shi[0].combinedflag &= ~(SCE_PASS_SPEC); - ssamp.shi[0].mat_override= NULL; - ssamp.shi[0].light_override= NULL; - lay= ssamp.shi[0].lay; - - /* create the pixelstrs to be used later */ - zbuffer_sss(pa, lay, &handle, addps_sss); - - if (handle.totps==0) { - zbufshade_sss_free(pa); - return; - } - - fcol= RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, R.viewname); - - co= MEM_mallocN(sizeof(float)*3*handle.totps, "SSSCo"); - color= MEM_mallocN(sizeof(float)*3*handle.totps, "SSSColor"); - area= MEM_mallocN(sizeof(float)*handle.totps, "SSSArea"); - -#if 0 - /* create ISB (does not work currently!) */ - if (re->r.mode & R_SHADOW) - ISB_create(pa, NULL); -#endif - - if (display) { - /* initialize scanline updates for main thread */ - rr->renrect.ymin = 0; - rr->renlay= rl; - } - - seed= pa->rectx*pa->disprect.ymin; -#if 0 - rs= pa->rectall; -#else - rz= pa->rectz; - rp= pa->rectp; - ro= pa->recto; - rbz= pa->rectbackz; - rbp= pa->rectbackp; - rbo= pa->rectbacko; -#endif - totpoint= 0; - - for (y=pa->disprect.ymin; y<pa->disprect.ymax; y++, rr->renrect.ymax++) { - for (x=pa->disprect.xmin; x<pa->disprect.xmax; x++, fcol+=4) { - /* per pixel fixed seed */ - BLI_thread_srandom(pa->thread, seed++); - -#if 0 - if (rs) { - /* for each sample in this pixel, shade it */ - for (ps = (PixStr *)(*rs); ps; ps=ps->next) { - ObjectInstanceRen *obi= &re->objectinstance[ps->obi]; - ObjectRen *obr= obi->obr; - vlr= RE_findOrAddVlak(obr, (ps->facenr-1) & RE_QUAD_MASK); - quad= (ps->facenr & RE_QUAD_OFFS); - z= ps->z; - - shade_sample_sss(&ssamp, mat, obi, vlr, quad, x, y, z, - co[totpoint], color[totpoint], &area[totpoint]); - - totpoint++; - - add_v3_v3(fcol, color); - fcol[3]= 1.0f; - } - - rs++; - } -#else - if (rp) { - if (*rp != 0) { - ObjectInstanceRen *obi= &re->objectinstance[*ro]; - ObjectRen *obr= obi->obr; - - /* shade front */ - vlr= RE_findOrAddVlak(obr, (*rp-1) & RE_QUAD_MASK); - quad= ((*rp) & RE_QUAD_OFFS); - - shade_sample_sss(&ssamp, mat, obi, vlr, quad, x, y, *rz, - co[totpoint], color[totpoint], &area[totpoint]); - - add_v3_v3(fcol, color[totpoint]); - fcol[3]= 1.0f; - totpoint++; - } - - rp++; rz++; ro++; - } - - if (rbp) { - if (*rbp != 0 && !(*rbp == *(rp-1) && *rbo == *(ro-1))) { - ObjectInstanceRen *obi= &re->objectinstance[*rbo]; - ObjectRen *obr= obi->obr; - - /* shade back */ - vlr= RE_findOrAddVlak(obr, (*rbp-1) & RE_QUAD_MASK); - quad= ((*rbp) & RE_QUAD_OFFS); - - shade_sample_sss(&ssamp, mat, obi, vlr, quad, x, y, *rbz, - co[totpoint], color[totpoint], &area[totpoint]); - - /* to indicate this is a back sample */ - area[totpoint]= -area[totpoint]; - - add_v3_v3(fcol, color[totpoint]); - fcol[3]= 1.0f; - totpoint++; - } - - rbz++; rbp++; rbo++; - } -#endif - } - - if (y&1) - if (re->test_break(re->tbh)) break; - } - - /* note: after adding we do not free these arrays, sss keeps them */ - if (totpoint > 0) { - sss_add_points(re, co, color, area, totpoint); - } - else { - MEM_freeN(co); - MEM_freeN(color); - MEM_freeN(area); - } - -#if 0 - if (re->r.mode & R_SHADOW) - ISB_free(pa); -#endif - - if (display) { - /* display active layer */ - rr->renrect.ymin=rr->renrect.ymax = 0; - rr->renlay= render_get_active_layer(&R, rr); - } - - zbufshade_sss_free(pa); -} - -/* ------------------------------------------------------------------------ */ - -static void renderhalo_post(RenderResult *rr, float *rectf, HaloRen *har) /* postprocess version */ -{ - float dist, xsq, ysq, xn, yn, colf[4], *rectft, *rtf; - float haloxs, haloys; - int minx, maxx, miny, maxy, x, y; - - /* calculate the disprect mapped coordinate for halo. note: rectx is disprect corrected */ - haloxs= har->xs - R.disprect.xmin; - haloys= har->ys - R.disprect.ymin; - - har->miny= miny= haloys - har->rad/R.ycor; - har->maxy= maxy= haloys + har->rad/R.ycor; - - if (maxy < 0) { - /* pass */ - } - else if (rr->recty < miny) { - /* pass */ - } - else { - minx = floor(haloxs - har->rad); - maxx = ceil(haloxs + har->rad); - - if (maxx < 0) { - /* pass */ - } - else if (rr->rectx < minx) { - /* pass */ - } - else { - if (minx<0) minx= 0; - if (maxx>=rr->rectx) maxx= rr->rectx-1; - if (miny<0) miny= 0; - if (maxy>rr->recty) maxy= rr->recty; - - rectft= rectf+ 4*rr->rectx*miny; - - for (y=miny; y<maxy; y++) { - - rtf= rectft+4*minx; - - yn= (y - haloys)*R.ycor; - ysq= yn*yn; - - for (x=minx; x<=maxx; x++) { - xn= x - haloxs; - xsq= xn*xn; - dist= xsq+ysq; - if (dist<har->radsq) { - - if (shadeHaloFloat(har, colf, 0x7FFFFF, dist, xn, yn, har->flarec)) - addalphaAddfacFloat(rtf, colf, har->add); - } - rtf+=4; - } - - rectft+= 4*rr->rectx; - - if (R.test_break(R.tbh)) break; - } - } - } -} -/* ------------------------------------------------------------------------ */ - -static void renderflare(RenderResult *rr, float *rectf, HaloRen *har) -{ - extern const float hashvectf[]; - HaloRen fla; - Material *ma; - const float *rc; - float rad, alfa, visifac, vec[3]; - int b, type; - - fla= *har; - fla.linec= fla.ringc= fla.flarec= 0; - - rad= har->rad; - alfa= har->alfa; - - visifac= R.ycor*(har->pixels); - /* all radials added / r^3 == 1.0f! */ - visifac /= (har->rad*har->rad*har->rad); - visifac*= visifac; - - ma= har->mat; - - /* first halo: just do */ - - har->rad= rad*ma->flaresize*visifac; - har->radsq= har->rad*har->rad; - har->zs= fla.zs= 0; - - har->alfa= alfa*visifac; - - renderhalo_post(rr, rectf, har); - - /* next halo's: the flares */ - rc= hashvectf + ma->seed2; - - for (b=1; b<har->flarec; b++) { - - fla.r = fabsf(rc[0]); - fla.g = fabsf(rc[1]); - fla.b = fabsf(rc[2]); - fla.alfa= ma->flareboost*fabsf(alfa*visifac*rc[3]); - fla.hard= 20.0f + fabsf(70.0f*rc[7]); - fla.tex= 0; - - type= (int)(fabsf(3.9f*rc[6])); - - fla.rad = ma->subsize * sqrtf(fabsf(2.0f * har->rad * rc[4])); - - if (type==3) { - fla.rad*= 3.0f; - fla.rad+= R.rectx/10; - } - - fla.radsq= fla.rad*fla.rad; - - vec[0]= 1.4f*rc[5]*(har->xs-R.winx/2); - vec[1]= 1.4f*rc[5]*(har->ys-R.winy/2); - vec[2]= 32.0f*sqrtf(vec[0]*vec[0] + vec[1]*vec[1] + 1.0f); - - fla.xs= R.winx/2 + vec[0] + (1.2f+rc[8])*R.rectx*vec[0]/vec[2]; - fla.ys= R.winy/2 + vec[1] + (1.2f+rc[8])*R.rectx*vec[1]/vec[2]; - - if (R.flag & R_SEC_FIELD) { - if (R.r.mode & R_ODDFIELD) fla.ys += 0.5f; - else fla.ys -= 0.5f; - } - if (type & 1) fla.type= HA_FLARECIRC; - else fla.type= 0; - renderhalo_post(rr, rectf, &fla); - - fla.alfa*= 0.5f; - if (type & 2) fla.type= HA_FLARECIRC; - else fla.type= 0; - renderhalo_post(rr, rectf, &fla); - - rc+= 7; - } -} - -/* needs recode... integrate this better! */ -void add_halo_flare(Render *re) -{ - RenderResult *rr= re->result; - RenderLayer *rl; - HaloRen *har; - int a, mode; - float *rect; - - /* for now, we get the first renderlayer in list with halos set */ - for (rl= rr->layers.first; rl; rl= rl->next) { - bool do_draw = false; - - if ((rl->layflag & SCE_LAY_HALO) == 0) - continue; - - rect = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, re->viewname); - - if (rect==NULL) - continue; - - mode= R.r.mode; - R.r.mode &= ~R_PANORAMA; - - project_renderdata(&R, projectverto, 0, 0, 0); - - for (a=0; a<R.tothalo; a++) { - har= R.sortedhalos[a]; - - if (har->flarec && (har->lay & rl->lay)) { - do_draw = true; - renderflare(rr, rect, har); - } - } - - if (do_draw) { - /* weak... the display callback wants an active renderlayer pointer... */ - rr->renlay= rl; - re->display_update(re->duh, rr, NULL); - } - - R.r.mode= mode; - } -} - -void render_internal_update_passes(RenderEngine *engine, Scene *scene, SceneRenderLayer *srl) -{ - int type; - - RE_engine_register_pass(engine, scene, srl, RE_PASSNAME_COMBINED, 4, "RGBA", SOCK_RGBA); - -#define CHECK_PASS(name, channels, chanid) \ - if (srl->passflag & (SCE_PASS_ ## name)) { \ - if (channels == 4) type = SOCK_RGBA; \ - else if (channels == 3) type = SOCK_VECTOR; \ - else type = SOCK_FLOAT; \ - RE_engine_register_pass(engine, scene, srl, RE_PASSNAME_ ## name, channels, chanid, type); \ - } - - CHECK_PASS(Z, 1, "Z"); - CHECK_PASS(VECTOR, 4, "XYZW"); - CHECK_PASS(NORMAL, 3, "XYZ"); - CHECK_PASS(UV, 3, "UVA"); - CHECK_PASS(RGBA, 4, "RGBA"); - CHECK_PASS(EMIT, 3, "RGB"); - CHECK_PASS(DIFFUSE, 3, "RGB"); - CHECK_PASS(SPEC, 3, "RGB"); - CHECK_PASS(AO, 3, "RGB"); - CHECK_PASS(ENVIRONMENT, 3, "RGB"); - CHECK_PASS(INDIRECT, 3, "RGB"); - CHECK_PASS(SHADOW, 3, "RGB"); - CHECK_PASS(REFLECT, 3, "RGB"); - CHECK_PASS(REFRACT, 3, "RGB"); - CHECK_PASS(INDEXOB, 1, "X"); - CHECK_PASS(INDEXMA, 1, "X"); - CHECK_PASS(MIST, 1, "Z"); - -#undef CHECK_PASS -} diff --git a/source/blender/render/intern/source/renderdatabase.c b/source/blender/render/intern/source/renderdatabase.c deleted file mode 100644 index 67bfd1bfdc7..00000000000 --- a/source/blender/render/intern/source/renderdatabase.c +++ /dev/null @@ -1,1603 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * Contributor(s): 2004-2006, Blender Foundation, full recode - * - * ***** END GPL/BL DUAL LICENSE BLOCK ***** - */ - -/** \file blender/render/intern/source/renderdatabase.c - * \ingroup render - */ - - -/* - * Storage, retrieval and query of render specific data. - * - * All data from a Blender scene is converted by the renderconverter/ - * into a special format that is used by the render module to make - * images out of. These functions interface to the render-specific - * database. - * - * The blo{ha/ve/vl} arrays store pointers to blocks of 256 data - * entries each. - * - * The index of an entry is >>8 (the highest 24 * bits), to find an - * offset in a 256-entry block. - * - * - If the 256-entry block entry has an entry in the - * vertnodes/vlaknodes/bloha array of the current block, the i-th entry in - * that block is allocated to this entry. - * - * - If the entry has no block allocated for it yet, memory is - * allocated. - * - * The pointer to the correct entry is returned. Memory is guaranteed - * to exist (as long as the malloc does not break). Since guarded - * allocation is used, memory _must_ be available. Otherwise, an - * exit(0) would occur. - * - */ - -#include <limits.h> -#include <math.h> -#include <string.h> - -#include "MEM_guardedalloc.h" - - -#include "BLI_math.h" -#include "BLI_blenlib.h" -#include "BLI_utildefines.h" -#include "BLI_hash.h" - -#include "DNA_material_types.h" -#include "DNA_meshdata_types.h" -#include "DNA_texture_types.h" -#include "DNA_listBase.h" -#include "DNA_particle_types.h" - -#include "BKE_customdata.h" -#include "BKE_DerivedMesh.h" - -#include "RE_render_ext.h" /* externtex */ - -#include "rayintersection.h" -#include "rayobject.h" -#include "render_types.h" -#include "renderdatabase.h" -#include "zbuf.h" - -/* ------------------------------------------------------------------------- */ - -/* More dynamic allocation of options for render vertices and faces, so we don't - * have to reserve this space inside vertices. - * Important; vertices and faces, should have been created already (to get tables - * checked) that's a reason why the calls demand VertRen/VlakRen * as arg, not - * the index */ - -/* NOTE! the hardcoded table size 256 is used still in code for going quickly over vertices/faces */ -#define RE_STRESS_ELEMS 1 -#define RE_RAD_ELEMS 4 -#define RE_STRAND_ELEMS 1 -#define RE_TANGENT_ELEMS 3 -#define RE_WINSPEED_ELEMS 4 -#define RE_MTFACE_ELEMS 1 -#define RE_MCOL_ELEMS 4 -#define RE_UV_ELEMS 2 -#define RE_VLAK_ORIGINDEX_ELEMS 1 -#define RE_VERT_ORIGINDEX_ELEMS 1 -#define RE_SURFNOR_ELEMS 3 -#define RE_RADFACE_ELEMS 1 -#define RE_SIMPLIFY_ELEMS 2 -#define RE_FACE_ELEMS 1 -#define RE_NMAP_TANGENT_ELEMS 16 - -float *RE_vertren_get_stress(ObjectRen *obr, VertRen *ver, int verify) -{ - float *stress; - int nr= ver->index>>8; - - stress= obr->vertnodes[nr].stress; - if (stress==NULL) { - if (verify) - stress= obr->vertnodes[nr].stress= MEM_mallocN(256*RE_STRESS_ELEMS*sizeof(float), "stress table"); - else - return NULL; - } - return stress + (ver->index & 255)*RE_STRESS_ELEMS; -} - -/* this one callocs! */ -float *RE_vertren_get_rad(ObjectRen *obr, VertRen *ver, int verify) -{ - float *rad; - int nr= ver->index>>8; - - rad= obr->vertnodes[nr].rad; - if (rad==NULL) { - if (verify) - rad= obr->vertnodes[nr].rad= MEM_callocN(256*RE_RAD_ELEMS*sizeof(float), "rad table"); - else - return NULL; - } - return rad + (ver->index & 255)*RE_RAD_ELEMS; -} - -float *RE_vertren_get_strand(ObjectRen *obr, VertRen *ver, int verify) -{ - float *strand; - int nr= ver->index>>8; - - strand= obr->vertnodes[nr].strand; - if (strand==NULL) { - if (verify) - strand= obr->vertnodes[nr].strand= MEM_mallocN(256*RE_STRAND_ELEMS*sizeof(float), "strand table"); - else - return NULL; - } - return strand + (ver->index & 255)*RE_STRAND_ELEMS; -} - -/* needs calloc */ -float *RE_vertren_get_tangent(ObjectRen *obr, VertRen *ver, int verify) -{ - float *tangent; - int nr= ver->index>>8; - - tangent= obr->vertnodes[nr].tangent; - if (tangent==NULL) { - if (verify) - tangent= obr->vertnodes[nr].tangent= MEM_callocN(256*RE_TANGENT_ELEMS*sizeof(float), "tangent table"); - else - return NULL; - } - return tangent + (ver->index & 255)*RE_TANGENT_ELEMS; -} - -/* needs calloc! not all renderverts have them */ -/* also winspeed is exception, it is stored per instance */ -float *RE_vertren_get_winspeed(ObjectInstanceRen *obi, VertRen *ver, int verify) -{ - float *winspeed; - int totvector; - - winspeed= obi->vectors; - if (winspeed==NULL) { - if (verify) { - totvector= obi->obr->totvert + obi->obr->totstrand; - winspeed= obi->vectors= MEM_callocN(totvector*RE_WINSPEED_ELEMS*sizeof(float), "winspeed table"); - } - else - return NULL; - } - return winspeed + ver->index*RE_WINSPEED_ELEMS; -} - -int *RE_vertren_get_origindex(ObjectRen *obr, VertRen *ver, int verify) -{ - int *origindex; - int nr= ver->index>>8; - - origindex= obr->vertnodes[nr].origindex; - if (origindex==NULL) { - if (verify) - origindex= obr->vertnodes[nr].origindex= MEM_mallocN(256*RE_VERT_ORIGINDEX_ELEMS*sizeof(int), "origindex table"); - else - return NULL; - } - return origindex + (ver->index & 255)*RE_VERT_ORIGINDEX_ELEMS; -} - -VertRen *RE_vertren_copy(ObjectRen *obr, VertRen *ver) -{ - VertRen *v1= RE_findOrAddVert(obr, obr->totvert++); - float *fp1, *fp2; - int *int1, *int2; - int index= v1->index; - - *v1= *ver; - v1->index= index; - - fp1= RE_vertren_get_stress(obr, ver, 0); - if (fp1) { - fp2= RE_vertren_get_stress(obr, v1, 1); - memcpy(fp2, fp1, RE_STRESS_ELEMS*sizeof(float)); - } - fp1= RE_vertren_get_rad(obr, ver, 0); - if (fp1) { - fp2= RE_vertren_get_rad(obr, v1, 1); - memcpy(fp2, fp1, RE_RAD_ELEMS*sizeof(float)); - } - fp1= RE_vertren_get_strand(obr, ver, 0); - if (fp1) { - fp2= RE_vertren_get_strand(obr, v1, 1); - memcpy(fp2, fp1, RE_STRAND_ELEMS*sizeof(float)); - } - fp1= RE_vertren_get_tangent(obr, ver, 0); - if (fp1) { - fp2= RE_vertren_get_tangent(obr, v1, 1); - memcpy(fp2, fp1, RE_TANGENT_ELEMS*sizeof(float)); - } - int1= RE_vertren_get_origindex(obr, ver, 0); - if (int1) { - int2= RE_vertren_get_origindex(obr, v1, 1); - memcpy(int2, int1, RE_VERT_ORIGINDEX_ELEMS*sizeof(int)); - } - return v1; -} - -VertRen *RE_findOrAddVert(ObjectRen *obr, int nr) -{ - VertTableNode *temp; - VertRen *v; - int a; - - if (nr<0) { - printf("error in findOrAddVert: %d\n", nr); - return NULL; - } - a= nr>>8; - - if (a>=obr->vertnodeslen-1) { /* Need to allocate more columns..., and keep last element NULL for free loop */ - temp= obr->vertnodes; - - obr->vertnodes= MEM_mallocN(sizeof(VertTableNode)*(obr->vertnodeslen+TABLEINITSIZE), "vertnodes"); - if (temp) memcpy(obr->vertnodes, temp, obr->vertnodeslen*sizeof(VertTableNode)); - memset(obr->vertnodes+obr->vertnodeslen, 0, TABLEINITSIZE*sizeof(VertTableNode)); - - obr->vertnodeslen+=TABLEINITSIZE; - if (temp) MEM_freeN(temp); - } - - v= obr->vertnodes[a].vert; - if (v==NULL) { - int i; - - v= (VertRen *)MEM_callocN(256*sizeof(VertRen), "findOrAddVert"); - obr->vertnodes[a].vert= v; - - for (i= (nr & 0xFFFFFF00), a=0; a<256; a++, i++) { - v[a].index= i; - } - } - v+= (nr & 255); - return v; -} - -/* ------------------------------------------------------------------------ */ - -MTFace *RE_vlakren_get_tface(ObjectRen *obr, VlakRen *vlr, int n, char **name, int verify) -{ - VlakTableNode *node; - int nr= vlr->index>>8, vlakindex= (vlr->index&255); - int index= (n<<8) + vlakindex; - - node= &obr->vlaknodes[nr]; - - if (verify) { - if (n>=node->totmtface) { - MTFace *mtface= node->mtface; - int size= (n+1)*256; - - node->mtface= MEM_callocN(size*sizeof(MTFace), "Vlak mtface"); - - if (mtface) { - size= node->totmtface*256; - memcpy(node->mtface, mtface, size*sizeof(MTFace)); - MEM_freeN(mtface); - } - - node->totmtface= n+1; - } - } - else { - if (n>=node->totmtface) - return NULL; - - if (name) *name= obr->mtface[n]; - } - - return node->mtface + index; -} - -MCol *RE_vlakren_get_mcol(ObjectRen *obr, VlakRen *vlr, int n, char **name, int verify) -{ - VlakTableNode *node; - int nr= vlr->index>>8, vlakindex= (vlr->index&255); - int index= (n<<8) + vlakindex; - - node= &obr->vlaknodes[nr]; - - if (verify) { - if (n>=node->totmcol) { - MCol *mcol= node->mcol; - int size= (n+1)*256; - - node->mcol= MEM_callocN(size*sizeof(MCol)*RE_MCOL_ELEMS, "Vlak mcol"); - - if (mcol) { - size= node->totmcol*256; - memcpy(node->mcol, mcol, size*sizeof(MCol)*RE_MCOL_ELEMS); - MEM_freeN(mcol); - } - - node->totmcol= n+1; - } - } - else { - if (n>=node->totmcol) - return NULL; - - if (name) *name= obr->mcol[n]; - } - - return node->mcol + index*RE_MCOL_ELEMS; -} - -int *RE_vlakren_get_origindex(ObjectRen *obr, VlakRen *vlak, int verify) -{ - int *origindex; - int nr= vlak->index>>8; - - origindex= obr->vlaknodes[nr].origindex; - if (origindex==NULL) { - if (verify) - origindex= obr->vlaknodes[nr].origindex= MEM_callocN(256*RE_VLAK_ORIGINDEX_ELEMS*sizeof(int), "origindex table"); - else - return NULL; - } - return origindex + (vlak->index & 255)*RE_VLAK_ORIGINDEX_ELEMS; -} - -float *RE_vlakren_get_surfnor(ObjectRen *obr, VlakRen *vlak, int verify) -{ - float *surfnor; - int nr= vlak->index>>8; - - surfnor= obr->vlaknodes[nr].surfnor; - if (surfnor==NULL) { - if (verify) - surfnor= obr->vlaknodes[nr].surfnor= MEM_callocN(256*RE_SURFNOR_ELEMS*sizeof(float), "surfnor table"); - else - return NULL; - } - return surfnor + (vlak->index & 255)*RE_SURFNOR_ELEMS; -} - -float *RE_vlakren_get_nmap_tangent(ObjectRen *obr, VlakRen *vlak, int index, bool verify) -{ - float **tangents; - int nr= vlak->index>>8; - - tangents = obr->vlaknodes[nr].tangent_arrays; - - if (index + 1 > 8) { - return NULL; - } - - index = index < 0 ? 0: index; - - if (tangents[index] == NULL) { - if (verify) { - tangents[index] = MEM_callocN(256*RE_NMAP_TANGENT_ELEMS*sizeof(float), "tangent table"); - } - else - return NULL; - } - - return tangents[index] + (vlak->index & 255)*RE_NMAP_TANGENT_ELEMS; -} - -RadFace **RE_vlakren_get_radface(ObjectRen *obr, VlakRen *vlak, int verify) -{ - RadFace **radface; - int nr= vlak->index>>8; - - radface= obr->vlaknodes[nr].radface; - if (radface==NULL) { - if (verify) - radface = obr->vlaknodes[nr].radface= MEM_callocN(256 * RE_RADFACE_ELEMS * sizeof(void *), "radface table"); - else - return NULL; - } - return radface + (vlak->index & 255)*RE_RADFACE_ELEMS; -} - -VlakRen *RE_vlakren_copy(ObjectRen *obr, VlakRen *vlr) -{ - VlakRen *vlr1 = RE_findOrAddVlak(obr, obr->totvlak++); - MTFace *mtface, *mtface1; - MCol *mcol, *mcol1; - float *surfnor, *surfnor1; - float *tangent, *tangent1; - int *origindex, *origindex1; - RadFace **radface, **radface1; - int i, index = vlr1->index; - char *name; - - *vlr1= *vlr; - vlr1->index= index; - - for (i=0; (mtface=RE_vlakren_get_tface(obr, vlr, i, &name, 0)) != NULL; i++) { - mtface1= RE_vlakren_get_tface(obr, vlr1, i, &name, 1); - memcpy(mtface1, mtface, sizeof(MTFace)*RE_MTFACE_ELEMS); - } - - for (i=0; (mcol=RE_vlakren_get_mcol(obr, vlr, i, &name, 0)) != NULL; i++) { - mcol1= RE_vlakren_get_mcol(obr, vlr1, i, &name, 1); - memcpy(mcol1, mcol, sizeof(MCol)*RE_MCOL_ELEMS); - } - - origindex= RE_vlakren_get_origindex(obr, vlr, 0); - if (origindex) { - origindex1= RE_vlakren_get_origindex(obr, vlr1, 1); - /* Just an int, but memcpy for consistency. */ - memcpy(origindex1, origindex, sizeof(int)*RE_VLAK_ORIGINDEX_ELEMS); - } - - surfnor= RE_vlakren_get_surfnor(obr, vlr, 0); - if (surfnor) { - surfnor1= RE_vlakren_get_surfnor(obr, vlr1, 1); - copy_v3_v3(surfnor1, surfnor); - } - - for (i=0; i < MAX_MTFACE; i++) { - tangent = RE_vlakren_get_nmap_tangent(obr, vlr, i, false); - if (!tangent) - continue; - tangent1 = RE_vlakren_get_nmap_tangent(obr, vlr1, i, true); - memcpy(tangent1, tangent, sizeof(float)*RE_NMAP_TANGENT_ELEMS); - } - - radface= RE_vlakren_get_radface(obr, vlr, 0); - if (radface) { - radface1= RE_vlakren_get_radface(obr, vlr1, 1); - *radface1= *radface; - } - - return vlr1; -} - -void RE_vlakren_get_normal(Render *UNUSED(re), ObjectInstanceRen *obi, VlakRen *vlr, float r_nor[3]) -{ - float (*nmat)[3]= obi->nmat; - - if (obi->flag & R_TRANSFORMED) { - mul_v3_m3v3(r_nor, nmat, vlr->n); - normalize_v3(r_nor); - } - else { - copy_v3_v3(r_nor, vlr->n); - } -} - -void RE_set_customdata_names(ObjectRen *obr, CustomData *data) -{ - /* CustomData layer names are stored per object here, because the - * DerivedMesh which stores the layers is freed */ - - CustomDataLayer *layer; - int numtf = 0, numcol = 0, i, mtfn, mcn; - - if (CustomData_has_layer(data, CD_MTFACE)) { - numtf= CustomData_number_of_layers(data, CD_MTFACE); - obr->mtface= MEM_callocN(sizeof(*obr->mtface)*numtf, "mtfacenames"); - } - - if (CustomData_has_layer(data, CD_MCOL)) { - numcol= CustomData_number_of_layers(data, CD_MCOL); - obr->mcol= MEM_callocN(sizeof(*obr->mcol)*numcol, "mcolnames"); - } - - for (i=0, mtfn=0, mcn=0; i < data->totlayer; i++) { - layer= &data->layers[i]; - - if (layer->type == CD_MTFACE) { - BLI_strncpy(obr->mtface[mtfn++], layer->name, sizeof(layer->name)); - obr->actmtface= CLAMPIS(layer->active_rnd, 0, numtf); - obr->bakemtface= layer->active; - } - else if (layer->type == CD_MCOL) { - BLI_strncpy(obr->mcol[mcn++], layer->name, sizeof(layer->name)); - obr->actmcol= CLAMPIS(layer->active_rnd, 0, numcol); - } - } -} - -VlakRen *RE_findOrAddVlak(ObjectRen *obr, int nr) -{ - VlakTableNode *temp; - VlakRen *v; - int a; - - if (nr<0) { - printf("error in findOrAddVlak: %d\n", nr); - return obr->vlaknodes[0].vlak; - } - a= nr>>8; - - if (a>=obr->vlaknodeslen-1) { /* Need to allocate more columns..., and keep last element NULL for free loop */ - temp= obr->vlaknodes; - - obr->vlaknodes= MEM_mallocN(sizeof(VlakTableNode)*(obr->vlaknodeslen+TABLEINITSIZE), "vlaknodes"); - if (temp) memcpy(obr->vlaknodes, temp, obr->vlaknodeslen*sizeof(VlakTableNode)); - memset(obr->vlaknodes+obr->vlaknodeslen, 0, TABLEINITSIZE*sizeof(VlakTableNode)); - - obr->vlaknodeslen+=TABLEINITSIZE; /*Does this really need to be power of 2?*/ - if (temp) MEM_freeN(temp); - } - - v= obr->vlaknodes[a].vlak; - - if (v==NULL) { - int i; - - v= (VlakRen *)MEM_callocN(256*sizeof(VlakRen), "findOrAddVlak"); - obr->vlaknodes[a].vlak= v; - - for (i= (nr & 0xFFFFFF00), a=0; a<256; a++, i++) - v[a].index= i; - } - v+= (nr & 255); - return v; -} - -/* ------------------------------------------------------------------------ */ - -float *RE_strandren_get_surfnor(ObjectRen *obr, StrandRen *strand, int verify) -{ - float *surfnor; - int nr= strand->index>>8; - - surfnor= obr->strandnodes[nr].surfnor; - if (surfnor==NULL) { - if (verify) - surfnor= obr->strandnodes[nr].surfnor= MEM_callocN(256*RE_SURFNOR_ELEMS*sizeof(float), "surfnor strand table"); - else - return NULL; - } - return surfnor + (strand->index & 255)*RE_SURFNOR_ELEMS; -} - -float *RE_strandren_get_uv(ObjectRen *obr, StrandRen *strand, int n, char **name, int verify) -{ - StrandTableNode *node; - int nr= strand->index>>8, strandindex= (strand->index&255); - int index= (n<<8) + strandindex; - - node= &obr->strandnodes[nr]; - - if (verify) { - if (n>=node->totuv) { - float *uv= node->uv; - int size= (n+1)*256; - - node->uv= MEM_callocN(size*sizeof(float)*RE_UV_ELEMS, "strand uv table"); - - if (uv) { - size= node->totuv*256; - memcpy(node->uv, uv, size*sizeof(float)*RE_UV_ELEMS); - MEM_freeN(uv); - } - - node->totuv= n+1; - } - } - else { - if (n>=node->totuv) - return NULL; - - if (name) *name= obr->mtface[n]; - } - - return node->uv + index*RE_UV_ELEMS; -} - -MCol *RE_strandren_get_mcol(ObjectRen *obr, StrandRen *strand, int n, char **name, int verify) -{ - StrandTableNode *node; - int nr= strand->index>>8, strandindex= (strand->index&255); - int index= (n<<8) + strandindex; - - node= &obr->strandnodes[nr]; - - if (verify) { - if (n>=node->totmcol) { - MCol *mcol= node->mcol; - int size= (n+1)*256; - - node->mcol= MEM_callocN(size*sizeof(MCol)*RE_MCOL_ELEMS, "strand mcol table"); - - if (mcol) { - size= node->totmcol*256; - memcpy(node->mcol, mcol, size*sizeof(MCol)*RE_MCOL_ELEMS); - MEM_freeN(mcol); - } - - node->totmcol= n+1; - } - } - else { - if (n>=node->totmcol) - return NULL; - - if (name) *name= obr->mcol[n]; - } - - return node->mcol + index*RE_MCOL_ELEMS; -} - -float *RE_strandren_get_simplify(struct ObjectRen *obr, struct StrandRen *strand, int verify) -{ - float *simplify; - int nr= strand->index>>8; - - simplify= obr->strandnodes[nr].simplify; - if (simplify==NULL) { - if (verify) - simplify= obr->strandnodes[nr].simplify= MEM_callocN(256*RE_SIMPLIFY_ELEMS*sizeof(float), "simplify strand table"); - else - return NULL; - } - return simplify + (strand->index & 255)*RE_SIMPLIFY_ELEMS; -} - -int *RE_strandren_get_face(ObjectRen *obr, StrandRen *strand, int verify) -{ - int *face; - int nr= strand->index>>8; - - face= obr->strandnodes[nr].face; - if (face==NULL) { - if (verify) - face= obr->strandnodes[nr].face= MEM_callocN(256*RE_FACE_ELEMS*sizeof(int), "face strand table"); - else - return NULL; - } - return face + (strand->index & 255)*RE_FACE_ELEMS; -} - -/* winspeed is exception, it is stored per instance */ -float *RE_strandren_get_winspeed(ObjectInstanceRen *obi, StrandRen *strand, int verify) -{ - float *winspeed; - int totvector; - - winspeed= obi->vectors; - if (winspeed==NULL) { - if (verify) { - totvector= obi->obr->totvert + obi->obr->totstrand; - winspeed= obi->vectors= MEM_callocN(totvector*RE_WINSPEED_ELEMS*sizeof(float), "winspeed strand table"); - } - else - return NULL; - } - return winspeed + (obi->obr->totvert + strand->index)*RE_WINSPEED_ELEMS; -} - -StrandRen *RE_findOrAddStrand(ObjectRen *obr, int nr) -{ - StrandTableNode *temp; - StrandRen *v; - int a; - - if (nr<0) { - printf("error in findOrAddStrand: %d\n", nr); - return obr->strandnodes[0].strand; - } - a= nr>>8; - - if (a>=obr->strandnodeslen-1) { /* Need to allocate more columns..., and keep last element NULL for free loop */ - temp= obr->strandnodes; - - obr->strandnodes= MEM_mallocN(sizeof(StrandTableNode)*(obr->strandnodeslen+TABLEINITSIZE), "strandnodes"); - if (temp) memcpy(obr->strandnodes, temp, obr->strandnodeslen*sizeof(StrandTableNode)); - memset(obr->strandnodes+obr->strandnodeslen, 0, TABLEINITSIZE*sizeof(StrandTableNode)); - - obr->strandnodeslen+=TABLEINITSIZE; /*Does this really need to be power of 2?*/ - if (temp) MEM_freeN(temp); - } - - v= obr->strandnodes[a].strand; - - if (v==NULL) { - int i; - - v= (StrandRen *)MEM_callocN(256*sizeof(StrandRen), "findOrAddStrand"); - obr->strandnodes[a].strand= v; - - for (i= (nr & 0xFFFFFF00), a=0; a<256; a++, i++) - v[a].index= i; - } - v+= (nr & 255); - return v; -} - -StrandBuffer *RE_addStrandBuffer(ObjectRen *obr, int totvert) -{ - StrandBuffer *strandbuf; - - strandbuf= MEM_callocN(sizeof(StrandBuffer), "StrandBuffer"); - strandbuf->vert= MEM_callocN(sizeof(StrandVert)*totvert, "StrandVert"); - strandbuf->totvert= totvert; - strandbuf->obr= obr; - - obr->strandbuf= strandbuf; - - return strandbuf; -} - -/* ------------------------------------------------------------------------ */ - -ObjectRen *RE_addRenderObject(Render *re, Object *ob, Object *par, int index, int psysindex, int lay) -{ - ObjectRen *obr= MEM_callocN(sizeof(ObjectRen), "object render struct"); - - BLI_addtail(&re->objecttable, obr); - obr->ob= ob; - obr->par= par; - obr->index= index; - obr->psysindex= psysindex; - obr->lay= lay; - - return obr; -} - -void free_renderdata_vertnodes(VertTableNode *vertnodes) -{ - int a; - - if (vertnodes==NULL) return; - - for (a=0; vertnodes[a].vert; a++) { - MEM_freeN(vertnodes[a].vert); - - if (vertnodes[a].rad) - MEM_freeN(vertnodes[a].rad); - if (vertnodes[a].strand) - MEM_freeN(vertnodes[a].strand); - if (vertnodes[a].tangent) - MEM_freeN(vertnodes[a].tangent); - if (vertnodes[a].stress) - MEM_freeN(vertnodes[a].stress); - if (vertnodes[a].winspeed) - MEM_freeN(vertnodes[a].winspeed); - if (vertnodes[a].origindex) - MEM_freeN(vertnodes[a].origindex); - } - - MEM_freeN(vertnodes); -} - -void free_renderdata_vlaknodes(VlakTableNode *vlaknodes) -{ - int a; - - if (vlaknodes==NULL) return; - - for (a=0; vlaknodes[a].vlak; a++) { - MEM_freeN(vlaknodes[a].vlak); - - if (vlaknodes[a].mtface) - MEM_freeN(vlaknodes[a].mtface); - if (vlaknodes[a].mcol) - MEM_freeN(vlaknodes[a].mcol); - if (vlaknodes[a].origindex) - MEM_freeN(vlaknodes[a].origindex); - if (vlaknodes[a].surfnor) - MEM_freeN(vlaknodes[a].surfnor); - for (int b = 0; b < MAX_MTFACE; b++) { - if (vlaknodes[a].tangent_arrays[b]) - MEM_freeN(vlaknodes[a].tangent_arrays[b]); - } - if (vlaknodes[a].radface) - MEM_freeN(vlaknodes[a].radface); - } - - MEM_freeN(vlaknodes); -} - -static void free_renderdata_strandnodes(StrandTableNode *strandnodes) -{ - int a; - - if (strandnodes==NULL) return; - - for (a=0; strandnodes[a].strand; a++) { - MEM_freeN(strandnodes[a].strand); - - if (strandnodes[a].uv) - MEM_freeN(strandnodes[a].uv); - if (strandnodes[a].mcol) - MEM_freeN(strandnodes[a].mcol); - if (strandnodes[a].winspeed) - MEM_freeN(strandnodes[a].winspeed); - if (strandnodes[a].surfnor) - MEM_freeN(strandnodes[a].surfnor); - if (strandnodes[a].simplify) - MEM_freeN(strandnodes[a].simplify); - if (strandnodes[a].face) - MEM_freeN(strandnodes[a].face); - } - - MEM_freeN(strandnodes); -} - -void free_renderdata_tables(Render *re) -{ - ObjectInstanceRen *obi; - ObjectRen *obr; - StrandBuffer *strandbuf; - int a=0; - - for (obr=re->objecttable.first; obr; obr=obr->next) { - if (obr->vertnodes) { - free_renderdata_vertnodes(obr->vertnodes); - obr->vertnodes= NULL; - obr->vertnodeslen= 0; - } - - if (obr->vlaknodes) { - free_renderdata_vlaknodes(obr->vlaknodes); - obr->vlaknodes= NULL; - obr->vlaknodeslen= 0; - obr->totvlak= 0; - } - - if (obr->bloha) { - for (a=0; obr->bloha[a]; a++) - MEM_freeN(obr->bloha[a]); - - MEM_freeN(obr->bloha); - obr->bloha= NULL; - obr->blohalen= 0; - } - - if (obr->strandnodes) { - free_renderdata_strandnodes(obr->strandnodes); - obr->strandnodes= NULL; - obr->strandnodeslen= 0; - } - - strandbuf= obr->strandbuf; - if (strandbuf) { - if (strandbuf->vert) MEM_freeN(strandbuf->vert); - if (strandbuf->bound) MEM_freeN(strandbuf->bound); - MEM_freeN(strandbuf); - } - - if (obr->mtface) - MEM_freeN(obr->mtface); - - if (obr->mcol) - MEM_freeN(obr->mcol); - - if (obr->rayfaces) { - MEM_freeN(obr->rayfaces); - obr->rayfaces = NULL; - } - - if (obr->rayprimitives) { - MEM_freeN(obr->rayprimitives); - obr->rayprimitives = NULL; - } - - if (obr->raytree) { - RE_rayobject_free(obr->raytree); - obr->raytree = NULL; - } - } - - if (re->objectinstance) { - for (obi=re->instancetable.first; obi; obi=obi->next) { - if (obi->vectors) - MEM_freeN(obi->vectors); - - if (obi->raytree) - RE_rayobject_free(obi->raytree); - } - - MEM_freeN(re->objectinstance); - re->objectinstance= NULL; - re->totinstance= 0; - re->instancetable.first= re->instancetable.last= NULL; - } - - if (re->sortedhalos) { - MEM_freeN(re->sortedhalos); - re->sortedhalos= NULL; - } - - BLI_freelistN(&re->customdata_names); - BLI_freelistN(&re->objecttable); - BLI_freelistN(&re->instancetable); -} - -/* ------------------------------------------------------------------------ */ - -HaloRen *RE_findOrAddHalo(ObjectRen *obr, int nr) -{ - HaloRen *h, **temp; - int a; - - if (nr<0) { - printf("error in findOrAddHalo: %d\n", nr); - return NULL; - } - a= nr>>8; - - if (a>=obr->blohalen-1) { /* Need to allocate more columns..., and keep last element NULL for free loop */ - //printf("Allocating %i more halo groups. %i total.\n", - // TABLEINITSIZE, obr->blohalen+TABLEINITSIZE ); - temp=obr->bloha; - - obr->bloha = (HaloRen **)MEM_callocN(sizeof(void *) * (obr->blohalen + TABLEINITSIZE), "Bloha"); - if (temp) memcpy(obr->bloha, temp, obr->blohalen*sizeof(void *)); - memset(&(obr->bloha[obr->blohalen]), 0, TABLEINITSIZE * sizeof(void *)); - obr->blohalen+=TABLEINITSIZE; /*Does this really need to be power of 2?*/ - if (temp) MEM_freeN(temp); - } - - h= obr->bloha[a]; - if (h==NULL) { - h= (HaloRen *)MEM_callocN(256*sizeof(HaloRen), "findOrAdHalo"); - obr->bloha[a]= h; - } - h+= (nr & 255); - return h; -} - -/* ------------------------------------------------------------------------- */ - -HaloRen *RE_inithalo(Render *re, ObjectRen *obr, Material *ma, - const float vec[3], const float vec1[3], - const float *orco, float hasize, float vectsize, int seed) -{ - const bool skip_load_image = (re->r.scemode & R_NO_IMAGE_LOAD) != 0; - const bool texnode_preview = (re->r.scemode & R_TEXNODE_PREVIEW) != 0; - HaloRen *har; - MTex *mtex; - float tin, tr, tg, tb, ta; - float xn, yn, zn, texvec[3], hoco[4], hoco1[4]; - - if (hasize==0.0f) return NULL; - - projectverto(vec, re->winmat, hoco); - if (hoco[3]==0.0f) return NULL; - if (vec1) { - projectverto(vec1, re->winmat, hoco1); - if (hoco1[3]==0.0f) return NULL; - } - - har= RE_findOrAddHalo(obr, obr->tothalo++); - copy_v3_v3(har->co, vec); - har->hasize= hasize; - - /* actual projectvert is done in function project_renderdata() because of parts/border/pano */ - /* we do it here for sorting of halos */ - zn= hoco[3]; - har->xs= 0.5f*re->winx*(hoco[0]/zn); - har->ys= 0.5f*re->winy*(hoco[1]/zn); - har->zs= 0x7FFFFF*(hoco[2]/zn); - - har->zBufDist = 0x7FFFFFFF*(hoco[2]/zn); - - /* halovect */ - if (vec1) { - - har->type |= HA_VECT; - - xn= har->xs - 0.5f*re->winx*(hoco1[0]/hoco1[3]); - yn= har->ys - 0.5f*re->winy*(hoco1[1]/hoco1[3]); - if (yn == 0.0f && xn >= 0.0f) zn = 0.0f; - else zn = atan2f(yn, xn); - - har->sin = sinf(zn); - har->cos = cosf(zn); - zn= len_v3v3(vec1, vec); - - har->hasize= vectsize*zn + (1.0f-vectsize)*hasize; - - sub_v3_v3v3(har->no, vec, vec1); - normalize_v3(har->no); - } - - if (ma->mode & MA_HALO_XALPHA) har->type |= HA_XALPHA; - - har->alfa= ma->alpha; - har->r= ma->r; - har->g= ma->g; - har->b= ma->b; - har->add= (255.0f*ma->add); - har->mat= ma; - har->hard= ma->har; - har->seed= seed % 256; - - if (ma->mode & MA_STAR) har->starpoints= ma->starc; - if (ma->mode & MA_HALO_LINES) har->linec= ma->linec; - if (ma->mode & MA_HALO_RINGS) har->ringc= ma->ringc; - if (ma->mode & MA_HALO_FLARE) har->flarec= ma->flarec; - - - if (ma->mtex[0]) { - - if (ma->mode & MA_HALOTEX) { - har->tex = 1; - } - else if (har->mat->septex & (1 << 0)) { - /* only 1 level textures */ - } - else { - mtex= ma->mtex[0]; - copy_v3_v3(texvec, vec); - - if (mtex->texco & TEXCO_NORM) { - ; - } - else if (mtex->texco & TEXCO_OBJECT) { - /* texvec[0]+= imatbase->ivec[0]; */ - /* texvec[1]+= imatbase->ivec[1]; */ - /* texvec[2]+= imatbase->ivec[2]; */ - /* mul_m3_v3(imatbase->imat, texvec); */ - } - else { - if (orco) { - copy_v3_v3(texvec, orco); - } - } - - externtex(mtex, - texvec, - &tin, &tr, &tg, &tb, &ta, - 0, - re->pool, - skip_load_image, - texnode_preview); - - yn= tin*mtex->colfac; - //zn= tin*mtex->alphafac; - - if (mtex->mapto & MAP_COL) { - zn= 1.0f-yn; - har->r= (yn*tr+ zn*ma->r); - har->g= (yn*tg+ zn*ma->g); - har->b= (yn*tb+ zn*ma->b); - } - if (mtex->texco & TEXCO_UV) { - har->alfa= tin; - } - if (mtex->mapto & MAP_ALPHA) - har->alfa= tin; - } - } - - har->pool = re->pool; - har->skip_load_image = skip_load_image; - har->texnode_preview = texnode_preview; - - return har; -} - -HaloRen *RE_inithalo_particle(Render *re, ObjectRen *obr, DerivedMesh *dm, Material *ma, - const float vec[3], const float vec1[3], - const float *orco, const float *uvco, float hasize, float vectsize, int seed, const float pa_co[3]) -{ - const bool skip_load_image = (re->r.scemode & R_NO_IMAGE_LOAD) != 0; - const bool texnode_preview = (re->r.scemode & R_TEXNODE_PREVIEW) != 0; - HaloRen *har; - MTex *mtex; - float tin, tr, tg, tb, ta; - float xn, yn, zn, texvec[3], hoco[4], hoco1[4], in[3], tex[3], out[3]; - int i, hasrgb; - - if (hasize==0.0f) return NULL; - - projectverto(vec, re->winmat, hoco); - if (hoco[3]==0.0f) return NULL; - if (vec1) { - projectverto(vec1, re->winmat, hoco1); - if (hoco1[3]==0.0f) return NULL; - } - - har= RE_findOrAddHalo(obr, obr->tothalo++); - copy_v3_v3(har->co, vec); - har->hasize= hasize; - - /* actual projectvert is done in function project_renderdata() because of parts/border/pano */ - /* we do it here for sorting of halos */ - zn= hoco[3]; - har->xs= 0.5f*re->winx*(hoco[0]/zn); - har->ys= 0.5f*re->winy*(hoco[1]/zn); - har->zs= 0x7FFFFF*(hoco[2]/zn); - - har->zBufDist = 0x7FFFFFFF*(hoco[2]/zn); - - /* halovect */ - if (vec1) { - - har->type |= HA_VECT; - - xn= har->xs - 0.5f*re->winx*(hoco1[0]/hoco1[3]); - yn= har->ys - 0.5f*re->winy*(hoco1[1]/hoco1[3]); - if (yn == 0.0f && xn >= 0.0f) zn = 0.0f; - else zn = atan2f(yn, xn); - - har->sin = sinf(zn); - har->cos = cosf(zn); - zn= len_v3v3(vec1, vec)*0.5f; - - har->hasize= vectsize*zn + (1.0f-vectsize)*hasize; - - sub_v3_v3v3(har->no, vec, vec1); - normalize_v3(har->no); - } - - if (ma->mode & MA_HALO_XALPHA) har->type |= HA_XALPHA; - - har->alfa= ma->alpha; - har->r= ma->r; - har->g= ma->g; - har->b= ma->b; - har->add= (255.0f*ma->add); - har->mat= ma; - har->hard= ma->har; - har->seed= seed % 256; - - if (ma->mode & MA_STAR) har->starpoints= ma->starc; - if (ma->mode & MA_HALO_LINES) har->linec= ma->linec; - if (ma->mode & MA_HALO_RINGS) har->ringc= ma->ringc; - if (ma->mode & MA_HALO_FLARE) har->flarec= ma->flarec; - - if ((ma->mode & MA_HALOTEX) && ma->mtex[0]) - har->tex= 1; - - for (i=0; i<MAX_MTEX; i++) - if (ma->mtex[i] && (ma->septex & (1<<i))==0) { - mtex= ma->mtex[i]; - copy_v3_v3(texvec, vec); - - if (mtex->texco & TEXCO_NORM) { - ; - } - else if (mtex->texco & TEXCO_OBJECT) { - if (mtex->object) - mul_m4_v3(mtex->object->imat_ren, texvec); - } - else if (mtex->texco & TEXCO_GLOB) { - copy_v3_v3(texvec, vec); - } - else if (mtex->texco & TEXCO_UV && uvco) { - int uv_index=CustomData_get_named_layer_index(&dm->faceData, CD_MTFACE, mtex->uvname); - if (uv_index<0) - uv_index=CustomData_get_active_layer_index(&dm->faceData, CD_MTFACE); - - uv_index-=CustomData_get_layer_index(&dm->faceData, CD_MTFACE); - - texvec[0]=2.0f*uvco[2*uv_index]-1.0f; - texvec[1]=2.0f*uvco[2*uv_index+1]-1.0f; - texvec[2]=0.0f; - } - else if (mtex->texco & TEXCO_PARTICLE) { - /* particle coordinates in range [0, 1] */ - texvec[0] = 2.f * pa_co[0] - 1.f; - texvec[1] = 2.f * pa_co[1] - 1.f; - texvec[2] = pa_co[2]; - } - else if (orco) { - copy_v3_v3(texvec, orco); - } - - hasrgb = externtex(mtex, - texvec, - &tin, &tr, &tg, &tb, &ta, - 0, - re->pool, - skip_load_image, - texnode_preview); - - //yn= tin*mtex->colfac; - //zn= tin*mtex->alphafac; - if (mtex->mapto & MAP_COL) { - tex[0]=tr; - tex[1]=tg; - tex[2]=tb; - out[0]=har->r; - out[1]=har->g; - out[2]=har->b; - - texture_rgb_blend(in, tex, out, tin, mtex->colfac, mtex->blendtype); - // zn= 1.0-yn; - //har->r= (yn*tr+ zn*ma->r); - //har->g= (yn*tg+ zn*ma->g); - //har->b= (yn*tb+ zn*ma->b); - har->r= in[0]; - har->g= in[1]; - har->b= in[2]; - } - - /* alpha returned, so let's use it instead of intensity */ - if (hasrgb) - tin = ta; - - if (mtex->mapto & MAP_ALPHA) - har->alfa = texture_value_blend(mtex->def_var, har->alfa, tin, mtex->alphafac, mtex->blendtype); - if (mtex->mapto & MAP_HAR) - har->hard = 1.0f+126.0f*texture_value_blend(mtex->def_var, ((float)har->hard)/127.0f, tin, mtex->hardfac, mtex->blendtype); - if (mtex->mapto & MAP_RAYMIRR) - har->hasize = 100.0f*texture_value_blend(mtex->def_var, har->hasize/100.0f, tin, mtex->raymirrfac, mtex->blendtype); - if (mtex->mapto & MAP_TRANSLU) { - float add = texture_value_blend(mtex->def_var, (float)har->add/255.0f, tin, mtex->translfac, mtex->blendtype); - CLAMP(add, 0.f, 1.f); - har->add = 255.0f*add; - } - /* now what on earth is this good for?? */ - //if (mtex->texco & 16) { - // har->alfa= tin; - //} - } - - har->pool = re->pool; - har->skip_load_image = (re->r.scemode & R_NO_IMAGE_LOAD) != 0; - har->texnode_preview = (re->r.scemode & R_TEXNODE_PREVIEW) != 0; - - return har; -} - -/* -------------------------- operations on entire database ----------------------- */ - -/* ugly function for halos in panorama */ -static int panotestclip(Render *re, bool do_pano, float v[4]) -{ - /* part size (ensure we run RE_parts_clamp first) */ - BLI_assert(re->partx == min_ii(re->r.tilex, re->rectx)); - BLI_assert(re->party == min_ii(re->r.tiley, re->recty)); - - if (do_pano == false) { - return testclip(v); - } - else { - /* to be used for halos en infos */ - float abs4; - short c = 0; - - int xparts = (re->rectx + re->partx - 1) / re->partx; - - abs4= fabsf(v[3]); - - if (v[2]< -abs4) c=16; /* this used to be " if (v[2]<0) ", see clippz() */ - else if (v[2]> abs4) c+= 32; - - if ( v[1]>abs4) c+=4; - else if ( v[1]< -abs4) c+=8; - - abs4*= xparts; - if ( v[0]>abs4) c+=2; - else if ( v[0]< -abs4) c+=1; - - return c; - } -} - -/** - * This adds the hcs coordinates to vertices. It iterates over all - * vertices, halos and faces. After the conversion, we clip in hcs. - * - * Elsewhere, all primites are converted to vertices. - * Called in - * - envmapping (envmap.c) - * - shadow buffering (shadbuf.c) - */ - -void project_renderdata(Render *re, - void (*projectfunc)(const float *, float mat[4][4], float *), - bool do_pano, float xoffs, bool UNUSED(do_buckets)) -{ - ObjectRen *obr; - HaloRen *har = NULL; - float zn, vec[3], hoco[4]; - int a; - - if (do_pano) { - float panophi= xoffs; - - re->panosi = sinf(panophi); - re->panoco = cosf(panophi); - } - - for (obr=re->objecttable.first; obr; obr=obr->next) { - /* calculate view coordinates (and zbuffer value) */ - for (a=0; a<obr->tothalo; a++) { - if ((a & 255)==0) har= obr->bloha[a>>8]; - else har++; - - if (do_pano) { - vec[0]= re->panoco*har->co[0] + re->panosi*har->co[2]; - vec[1]= har->co[1]; - vec[2]= -re->panosi*har->co[0] + re->panoco*har->co[2]; - } - else { - copy_v3_v3(vec, har->co); - } - - projectfunc(vec, re->winmat, hoco); - - /* we clip halos less critical, but not for the Z */ - hoco[0]*= 0.5f; - hoco[1]*= 0.5f; - - if ( panotestclip(re, do_pano, hoco) ) { - har->miny= har->maxy= -10000; /* that way render clips it */ - } - else if (hoco[3]<0.0f) { - har->miny= har->maxy= -10000; /* render clips it */ - } - else { /* do the projection...*/ - /* bring back hocos */ - hoco[0]*= 2.0f; - hoco[1]*= 2.0f; - - zn= hoco[3]; - har->xs= 0.5f*re->winx*(1.0f+hoco[0]/zn); /* the 0.5 negates the previous 2...*/ - har->ys= 0.5f*re->winy*(1.0f+hoco[1]/zn); - - /* this should be the zbuffer coordinate */ - har->zs= 0x7FFFFF*(hoco[2]/zn); - /* taking this from the face clip functions? seems ok... */ - har->zBufDist = 0x7FFFFFFF*(hoco[2]/zn); - - vec[0]+= har->hasize; - projectfunc(vec, re->winmat, hoco); - vec[0]-= har->hasize; - zn= hoco[3]; - har->rad= fabsf(har->xs- 0.5f*re->winx*(1.0f+hoco[0]/zn)); - - /* this clip is not really OK, to prevent stars to become too large */ - if (har->type & HA_ONLYSKY) { - if (har->rad>3.0f) har->rad= 3.0f; - } - - har->radsq= har->rad*har->rad; - - har->miny= har->ys - har->rad/re->ycor; - har->maxy= har->ys + har->rad/re->ycor; - - /* the Zd value is still not really correct for pano */ - - vec[2] -= har->hasize; /* z negative, otherwise it's clipped */ - projectfunc(vec, re->winmat, hoco); - zn = hoco[3]; - zn = fabsf((float)har->zs - 0x7FFFFF * (hoco[2] / zn)); - har->zd = CLAMPIS(zn, 0, INT_MAX); - - } - - } - } -} - -/* ------------------------------------------------------------------------- */ - -void RE_updateRenderInstance(Render *re, ObjectInstanceRen *obi, int flag) -{ - /* flag specifies what things have changed. */ - if (flag & RE_OBJECT_INSTANCES_UPDATE_OBMAT) { - copy_m4_m4(obi->obmat, obi->ob->obmat); - invert_m4_m4(obi->obinvmat, obi->obmat); - } - if (flag & RE_OBJECT_INSTANCES_UPDATE_VIEW) { - mul_m4_m4m4(obi->localtoviewmat, re->viewmat, obi->obmat); - mul_m4_m4m4(obi->localtoviewinvmat, obi->obinvmat, re->viewinv); - } -} - -void RE_updateRenderInstances(Render *re, int flag) -{ - int i = 0; - for (i = 0; i < re->totinstance; i++) - RE_updateRenderInstance(re, &re->objectinstance[i], flag); -} - -ObjectInstanceRen *RE_addRenderInstance( - Render *re, ObjectRen *obr, Object *ob, Object *par, - int index, int psysindex, float mat[4][4], int lay, const DupliObject *dob) -{ - ObjectInstanceRen *obi; - float mat3[3][3]; - - obi= MEM_callocN(sizeof(ObjectInstanceRen), "ObjectInstanceRen"); - obi->obr= obr; - obi->ob= ob; - obi->par= par; - obi->index= index; - obi->psysindex= psysindex; - obi->lay= lay; - - /* Fill particle info */ - if (par && dob) { - const ParticleSystem *psys = dob->particle_system; - if (psys) { - int part_index; - if (obi->index < psys->totpart) { - part_index = obi->index; - } - else if (psys->child) { - part_index = psys->child[obi->index - psys->totpart].parent; - } - else { - part_index = -1; - } - - if (part_index >= 0) { - const ParticleData *p = &psys->particles[part_index]; - obi->part_index = part_index; - obi->part_size = p->size; - obi->part_age = RE_GetStats(re)->cfra - p->time; - obi->part_lifetime = p->lifetime; - - copy_v3_v3(obi->part_co, p->state.co); - copy_v3_v3(obi->part_vel, p->state.vel); - copy_v3_v3(obi->part_avel, p->state.ave); - } - } - } - - /* Fill object info */ - if (dob) { - obi->random_id = dob->random_id; - } - else { - obi->random_id = BLI_hash_int_2d(BLI_hash_string(obi->ob->id.name + 2), 0); - } - - RE_updateRenderInstance(re, obi, RE_OBJECT_INSTANCES_UPDATE_OBMAT | RE_OBJECT_INSTANCES_UPDATE_VIEW); - - if (mat) { - copy_m4_m4(obi->mat, mat); - copy_m3_m4(mat3, mat); - invert_m3_m3(obi->nmat, mat3); - transpose_m3(obi->nmat); - obi->flag |= R_DUPLI_TRANSFORMED; - } - - BLI_addtail(&re->instancetable, obi); - - return obi; -} - -void RE_instance_get_particle_info(struct ObjectInstanceRen *obi, float *index, float *random, float *age, float *lifetime, float co[3], float *size, float vel[3], float angvel[3]) -{ - *index = obi->part_index; - *random = BLI_hash_int_01(obi->part_index); - *age = obi->part_age; - *lifetime = obi->part_lifetime; - copy_v3_v3(co, obi->part_co); - *size = obi->part_size; - copy_v3_v3(vel, obi->part_vel); - copy_v3_v3(angvel, obi->part_avel); -} - - -void RE_makeRenderInstances(Render *re) -{ - ObjectInstanceRen *obi, *oldobi; - ListBase newlist; - int tot; - - /* convert list of object instances to an array for index based lookup */ - tot= BLI_listbase_count(&re->instancetable); - re->objectinstance= MEM_callocN(sizeof(ObjectInstanceRen)*tot, "ObjectInstance"); - re->totinstance= tot; - newlist.first= newlist.last= NULL; - - obi= re->objectinstance; - for (oldobi=re->instancetable.first; oldobi; oldobi=oldobi->next) { - *obi= *oldobi; - - if (obi->obr) { - obi->prev= obi->next= NULL; - BLI_addtail(&newlist, obi); - obi++; - } - else - re->totinstance--; - } - - BLI_freelistN(&re->instancetable); - re->instancetable= newlist; -} - -/* four functions to facilitate envmap rotation for raytrace */ -void RE_instance_rotate_ray_start(ObjectInstanceRen *obi, Isect *is) -{ - if (obi && (obi->flag & R_ENV_TRANSFORMED)) { - copy_v3_v3(is->origstart, is->start); - mul_m4_v3(obi->imat, is->start); - } -} - -void RE_instance_rotate_ray_dir(ObjectInstanceRen *obi, Isect *is) -{ - if (obi && (obi->flag & R_ENV_TRANSFORMED)) { - float end[3]; - - copy_v3_v3(is->origdir, is->dir); - add_v3_v3v3(end, is->origstart, is->dir); - - mul_m4_v3(obi->imat, end); - sub_v3_v3v3(is->dir, end, is->start); - } -} - -void RE_instance_rotate_ray(ObjectInstanceRen *obi, Isect *is) -{ - RE_instance_rotate_ray_start(obi, is); - RE_instance_rotate_ray_dir(obi, is); -} - -void RE_instance_rotate_ray_restore(ObjectInstanceRen *obi, Isect *is) -{ - if (obi && (obi->flag & R_ENV_TRANSFORMED)) { - copy_v3_v3(is->start, is->origstart); - copy_v3_v3(is->dir, is->origdir); - } -} - -int clip_render_object(float boundbox[2][3], float bounds[4], float winmat[4][4]) -{ - float mat[4][4], vec[4]; - int a, fl, flag = -1; - - copy_m4_m4(mat, winmat); - - for (a=0; a < 8; a++) { - vec[0]= (a & 1)? boundbox[0][0]: boundbox[1][0]; - vec[1]= (a & 2)? boundbox[0][1]: boundbox[1][1]; - vec[2]= (a & 4)? boundbox[0][2]: boundbox[1][2]; - vec[3]= 1.0; - mul_m4_v4(mat, vec); - - fl = 0; - if (bounds) { - if (vec[0] < bounds[0] * vec[3]) fl |= 1; - else if (vec[0] > bounds[1] * vec[3]) fl |= 2; - - if (vec[1] > bounds[3] * vec[3]) fl |= 4; - else if (vec[1] < bounds[2] * vec[3]) fl |= 8; - } - else { - if (vec[0] < -vec[3]) fl |= 1; - else if (vec[0] > vec[3]) fl |= 2; - - if (vec[1] > vec[3]) fl |= 4; - else if (vec[1] < -vec[3]) fl |= 8; - } - if (vec[2] < -vec[3]) fl |= 16; - else if (vec[2] > vec[3]) fl |= 32; - - flag &= fl; - if (flag == 0) { - return 0; - } - } - - return flag; -} - diff --git a/source/blender/render/intern/source/shadbuf.c b/source/blender/render/intern/source/shadbuf.c deleted file mode 100644 index 04e9177241b..00000000000 --- a/source/blender/render/intern/source/shadbuf.c +++ /dev/null @@ -1,2647 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * Contributor(s): 2004-2006, Blender Foundation - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/render/intern/source/shadbuf.c - * \ingroup render - */ - - -#include <math.h> -#include <string.h> - - -#include "MEM_guardedalloc.h" - -#include "DNA_group_types.h" -#include "DNA_lamp_types.h" -#include "DNA_material_types.h" - -#include "BLI_math.h" -#include "BLI_blenlib.h" -#include "BLI_jitter_2d.h" -#include "BLI_memarena.h" -#include "BLI_rand.h" -#include "BLI_utildefines.h" - -#include "BKE_global.h" -#include "BKE_scene.h" - -#include "PIL_time.h" - -#include "render_types.h" -#include "renderdatabase.h" -#include "rendercore.h" -#include "shadbuf.h" -#include "shading.h" -#include "zbuf.h" - -/* XXX, could be better implemented... this is for endian issues */ -#ifdef __BIG_ENDIAN__ -//# define RCOMP 3 -# define GCOMP 2 -# define BCOMP 1 -# define ACOMP 0 -#else -//# define RCOMP 0 -# define GCOMP 1 -# define BCOMP 2 -# define ACOMP 3 -#endif - -#define RCT_SIZE_X(rct) ((rct)->xmax - (rct)->xmin) -#define RCT_SIZE_Y(rct) ((rct)->ymax - (rct)->ymin) - -/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -/* defined in pipeline.c, is hardcopy of active dynamic allocated Render */ -/* only to be used here in this file, it's for speed */ -extern struct Render R; -/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ - -/* ------------------------------------------------------------------------- */ - -/* initshadowbuf() in convertBlenderScene.c */ - -/* ------------------------------------------------------------------------- */ - -static void copy_to_ztile(int *rectz, int size, int x1, int y1, int tile, char *r1) -{ - int len4, *rz; - int x2, y2; - - x2= x1+tile; - y2= y1+tile; - if (x2>=size) x2= size-1; - if (y2>=size) y2= size-1; - - if (x1>=x2 || y1>=y2) return; - - len4= 4*(x2- x1); - rz= rectz + size*y1 + x1; - for (; y1<y2; y1++) { - memcpy(r1, rz, len4); - rz+= size; - r1+= len4; - } -} - -#if 0 -static int sizeoflampbuf(ShadBuf *shb) -{ - int num, count=0; - char *cp; - - cp= shb->cbuf; - num= (shb->size*shb->size)/256; - - while (num--) count+= *(cp++); - - return 256*count; -} -#endif - -/* not threadsafe... */ -static float *give_jitter_tab(int samp) -{ - /* these are all possible jitter tables, takes up some - * 12k, not really bad! - * For soft shadows, it saves memory and render time - */ - static int tab[17]={1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256}; - static float jit[1496][2]; - static char ctab[17]= {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - int a, offset=0; - - if (samp<2) samp= 2; - else if (samp>16) samp= 16; - - for (a=0; a<samp-1; a++) offset+= tab[a]; - - if (ctab[samp]==0) { - ctab[samp]= 1; - BLI_jitter_init((float (*)[2])jit[offset], samp*samp); - } - - return jit[offset]; - -} - -static void make_jitter_weight_tab(Render *re, ShadBuf *shb, short filtertype) -{ - float *jit, totw= 0.0f; - int samp= get_render_shadow_samples(&re->r, shb->samp); - int a, tot=samp*samp; - - shb->weight= MEM_mallocN(sizeof(float)*tot, "weight tab lamp"); - - for (jit= shb->jit, a=0; a<tot; a++, jit+=2) { - if (filtertype==LA_SHADBUF_TENT) - shb->weight[a] = 0.71f - sqrtf(jit[0] * jit[0] + jit[1] * jit[1]); - else if (filtertype==LA_SHADBUF_GAUSS) - shb->weight[a] = RE_filter_value(R_FILTER_GAUSS, 1.8f * sqrtf(jit[0] * jit[0] + jit[1] * jit[1])); - else - shb->weight[a]= 1.0f; - - totw+= shb->weight[a]; - } - - totw= 1.0f/totw; - for (a=0; a<tot; a++) { - shb->weight[a]*= totw; - } -} - -static int verg_deepsample(const void *poin1, const void *poin2) -{ - const DeepSample *ds1= (const DeepSample*)poin1; - const DeepSample *ds2= (const DeepSample*)poin2; - - if (ds1->z < ds2->z) return -1; - else if (ds1->z == ds2->z) return 0; - else return 1; -} - -static int compress_deepsamples(DeepSample *dsample, int tot, float epsilon) -{ - /* uses doubles to avoid overflows and other numerical issues, - * could be improved */ - DeepSample *ds, *newds; - float v; - double slope, slopemin, slopemax, min, max, div, newmin, newmax; - int a, first, z, newtot= 0; - -#if 0 - if (print) { - for (a=0, ds=dsample; a<tot; a++, ds++) - printf("%lf, %f ", ds->z/(double)0x7FFFFFFF, ds->v); - printf("\n"); - } -#endif - - /* read from and write into same array */ - ds= dsample; - newds= dsample; - a= 0; - - /* as long as we are not at the end of the array */ - for (a++, ds++; a<tot; a++, ds++) { - slopemin= 0.0f; - slopemax= 0.0f; - first= 1; - - for (; a<tot; a++, ds++) { - //dz= ds->z - newds->z; - if (ds->z == newds->z) { - /* still in same z position, simply check - * visibility difference against epsilon */ - if (!(fabsf(newds->v - ds->v) <= epsilon)) { - break; - } - } - else { - /* compute slopes */ - div= (double)0x7FFFFFFF / ((double)ds->z - (double)newds->z); - min= (double)((ds->v - epsilon) - newds->v) * div; - max= (double)((ds->v + epsilon) - newds->v) * div; - - /* adapt existing slopes */ - if (first) { - newmin= min; - newmax= max; - first= 0; - } - else { - newmin= MAX2(slopemin, min); - newmax= MIN2(slopemax, max); - - /* verify if there is still space between the slopes */ - if (newmin > newmax) { - ds--; - a--; - break; - } - } - - slopemin= newmin; - slopemax= newmax; - } - } - - if (a == tot) { - ds--; - a--; - } - - /* always previous z */ - z= ds->z; - - if (first || a==tot-1) { - /* if slopes were not initialized, use last visibility */ - v= ds->v; - } - else { - /* compute visibility at center between slopes at z */ - slope = (slopemin + slopemax) * 0.5; - v = (double)newds->v + slope * ((double)(z - newds->z) / (double)0x7FFFFFFF); - } - - newds++; - newtot++; - - newds->z= z; - newds->v= v; - } - - if (newtot == 0 || (newds->v != (newds-1)->v)) - newtot++; - -#if 0 - if (print) { - for (a=0, ds=dsample; a<newtot; a++, ds++) - printf("%lf, %f ", ds->z/(double)0x7FFFFFFF, ds->v); - printf("\n"); - } -#endif - - return newtot; -} - -static float deep_alpha(Render *re, int obinr, int facenr, bool use_strand) -{ - ObjectInstanceRen *obi= &re->objectinstance[obinr]; - Material *ma; - - if (use_strand) { - StrandRen *strand= RE_findOrAddStrand(obi->obr, facenr-1); - ma= strand->buffer->ma; - } - else { - VlakRen *vlr= RE_findOrAddVlak(obi->obr, (facenr-1) & RE_QUAD_MASK); - ma= vlr->mat; - } - - return ma->shad_alpha; -} - -static void compress_deepshadowbuf(Render *re, ShadBuf *shb, APixstr *apixbuf, APixstrand *apixbufstrand) -{ - ShadSampleBuf *shsample; - DeepSample *ds[RE_MAX_OSA], *sampleds[RE_MAX_OSA], *dsb, *newbuf; - APixstr *ap, *apn; - APixstrand *aps, *apns; - float visibility; - - const int totbuf= shb->totbuf; - const float totbuf_f= (float)shb->totbuf; - const float totbuf_f_inv= 1.0f/totbuf_f; - const int size= shb->size; - - int a, b, c, tot, minz, found, prevtot, newtot; - int sampletot[RE_MAX_OSA], totsample = 0, totsamplec = 0; - - shsample= MEM_callocN(sizeof(ShadSampleBuf), "shad sample buf"); - BLI_addtail(&shb->buffers, shsample); - - shsample->totbuf = MEM_callocN(sizeof(int) * size * size, "deeptotbuf"); - shsample->deepbuf = MEM_callocN(sizeof(DeepSample *) * size * size, "deepbuf"); - - ap= apixbuf; - aps= apixbufstrand; - for (a=0; a<size*size; a++, ap++, aps++) { - /* count number of samples */ - for (c=0; c<totbuf; c++) - sampletot[c]= 0; - - tot= 0; - for (apn=ap; apn; apn=apn->next) - for (b=0; b<4; b++) - if (apn->p[b]) - for (c=0; c<totbuf; c++) - if (apn->mask[b] & (1<<c)) - sampletot[c]++; - - if (apixbufstrand) { - for (apns=aps; apns; apns=apns->next) - for (b=0; b<4; b++) - if (apns->p[b]) - for (c=0; c<totbuf; c++) - if (apns->mask[b] & (1<<c)) - sampletot[c]++; - } - - for (c=0; c<totbuf; c++) - tot += sampletot[c]; - - if (tot == 0) { - shsample->deepbuf[a]= NULL; - shsample->totbuf[a]= 0; - continue; - } - - /* fill samples */ - ds[0]= sampleds[0]= MEM_callocN(sizeof(DeepSample)*tot*2, "deepsample"); - for (c=1; c<totbuf; c++) - ds[c]= sampleds[c]= sampleds[c-1] + sampletot[c-1]*2; - - for (apn=ap; apn; apn=apn->next) { - for (b=0; b<4; b++) { - if (apn->p[b]) { - for (c=0; c<totbuf; c++) { - if (apn->mask[b] & (1<<c)) { - /* two entries to create step profile */ - ds[c]->z= apn->z[b]; - ds[c]->v= 1.0f; /* not used */ - ds[c]++; - ds[c]->z= apn->z[b]; - ds[c]->v= deep_alpha(re, apn->obi[b], apn->p[b], 0); - ds[c]++; - } - } - } - } - } - - if (apixbufstrand) { - for (apns=aps; apns; apns=apns->next) { - for (b=0; b<4; b++) { - if (apns->p[b]) { - for (c=0; c<totbuf; c++) { - if (apns->mask[b] & (1<<c)) { - /* two entries to create step profile */ - ds[c]->z= apns->z[b]; - ds[c]->v= 1.0f; /* not used */ - ds[c]++; - ds[c]->z= apns->z[b]; - ds[c]->v= deep_alpha(re, apns->obi[b], apns->p[b], 1); - ds[c]++; - } - } - } - } - } - } - - for (c=0; c<totbuf; c++) { - /* sort by increasing z */ - qsort(sampleds[c], sampletot[c], sizeof(DeepSample)*2, verg_deepsample); - - /* sum visibility, replacing alpha values */ - visibility= 1.0f; - ds[c]= sampleds[c]; - - for (b=0; b<sampletot[c]; b++) { - /* two entries creating step profile */ - ds[c]->v= visibility; - ds[c]++; - - visibility *= 1.0f-ds[c]->v; - ds[c]->v= visibility; - ds[c]++; - } - - /* halfway trick, probably won't work well for volumes? */ - ds[c]= sampleds[c]; - for (b=0; b<sampletot[c]; b++) { - if (b+1 < sampletot[c]) { - ds[c]->z= (ds[c]->z>>1) + ((ds[c]+2)->z>>1); - ds[c]++; - ds[c]->z= (ds[c]->z>>1) + ((ds[c]+2)->z>>1); - ds[c]++; - } - else { - ds[c]->z= (ds[c]->z>>1) + (0x7FFFFFFF>>1); - ds[c]++; - ds[c]->z= (ds[c]->z>>1) + (0x7FFFFFFF>>1); - ds[c]++; - } - } - - /* init for merge loop */ - ds[c]= sampleds[c]; - sampletot[c] *= 2; - } - - shsample->deepbuf[a]= MEM_callocN(sizeof(DeepSample)*tot*2, "deepsample"); - shsample->totbuf[a]= 0; - - /* merge buffers */ - dsb= shsample->deepbuf[a]; - while (1) { - minz= 0; - found= 0; - - for (c=0; c<totbuf; c++) { - if (sampletot[c] && (!found || ds[c]->z < minz)) { - minz= ds[c]->z; - found= 1; - } - } - - if (!found) - break; - - dsb->z= minz; - dsb->v= 0.0f; - - visibility= 0.0f; - for (c=0; c<totbuf; c++) { - if (sampletot[c] && ds[c]->z == minz) { - ds[c]++; - sampletot[c]--; - } - - if (sampleds[c] == ds[c]) - visibility += totbuf_f_inv; - else - visibility += (ds[c]-1)->v / totbuf_f; - } - - dsb->v= visibility; - dsb++; - shsample->totbuf[a]++; - } - - prevtot= shsample->totbuf[a]; - totsample += prevtot; - - newtot= compress_deepsamples(shsample->deepbuf[a], prevtot, shb->compressthresh); - shsample->totbuf[a]= newtot; - totsamplec += newtot; - - if (newtot < prevtot) { - newbuf= MEM_mallocN(sizeof(DeepSample)*newtot, "cdeepsample"); - memcpy(newbuf, shsample->deepbuf[a], sizeof(DeepSample)*newtot); - MEM_freeN(shsample->deepbuf[a]); - shsample->deepbuf[a]= newbuf; - } - - MEM_freeN(sampleds[0]); - } - - //printf("%d -> %d, ratio %f\n", totsample, totsamplec, (float)totsamplec/(float)totsample); -} - -/* create Z tiles (for compression): this system is 24 bits!!! */ -static void compress_shadowbuf(ShadBuf *shb, int *rectz, int square) -{ - ShadSampleBuf *shsample; - float dist; - uintptr_t *ztile; - int *rz, *rz1, verg, verg1, size= shb->size; - int a, x, y, minx, miny, byt1, byt2; - char *rc, *rcline, *ctile, *zt; - - shsample= MEM_callocN(sizeof(ShadSampleBuf), "shad sample buf"); - BLI_addtail(&shb->buffers, shsample); - - shsample->zbuf= MEM_mallocN(sizeof(uintptr_t)*(size*size)/256, "initshadbuf2"); - shsample->cbuf= MEM_callocN((size*size)/256, "initshadbuf3"); - - ztile= (uintptr_t *)shsample->zbuf; - ctile= shsample->cbuf; - - /* help buffer */ - rcline= MEM_mallocN(256*4+sizeof(int), "makeshadbuf2"); - - for (y=0; y<size; y+=16) { - if (y< size/2) miny= y+15-size/2; - else miny= y-size/2; - - for (x=0; x<size; x+=16) { - - /* is tile within spotbundle? */ - a= size/2; - if (x< a) minx= x+15-a; - else minx= x-a; - - dist = sqrtf((float)(minx * minx + miny * miny)); - - if (square==0 && dist>(float)(a+12)) { /* 12, tested with a onlyshadow lamp */ - a= 256; verg= 0; /* 0x80000000; */ /* 0x7FFFFFFF; */ - rz1= (&verg)+1; - } - else { - copy_to_ztile(rectz, size, x, y, 16, rcline); - rz1= (int *)rcline; - - verg= (*rz1 & 0xFFFFFF00); - - for (a=0;a<256;a++, rz1++) { - if ( (*rz1 & 0xFFFFFF00) !=verg) break; - } - } - if (a==256) { /* complete empty tile */ - *ctile= 0; - *ztile= *(rz1-1); - } - else { - - /* ACOMP etc. are defined to work L/B endian */ - - rc= rcline; - rz1= (int *)rcline; - verg= rc[ACOMP]; - verg1= rc[BCOMP]; - rc+= 4; - byt1= 1; byt2= 1; - for (a=1;a<256;a++, rc+=4) { - byt1 &= (verg==rc[ACOMP]); - byt2 &= (verg1==rc[BCOMP]); - - if (byt1==0) break; - } - if (byt1 && byt2) { /* only store byte */ - *ctile= 1; - *ztile= (uintptr_t)MEM_mallocN(256+4, "tile1"); - rz= (int *)*ztile; - *rz= *rz1; - - zt= (char *)(rz+1); - rc= rcline; - for (a=0; a<256; a++, zt++, rc+=4) *zt= rc[GCOMP]; - } - else if (byt1) { /* only store short */ - *ctile= 2; - *ztile= (uintptr_t)MEM_mallocN(2*256+4, "Tile2"); - rz= (int *)*ztile; - *rz= *rz1; - - zt= (char *)(rz+1); - rc= rcline; - for (a=0; a<256; a++, zt+=2, rc+=4) { - zt[0]= rc[BCOMP]; - zt[1]= rc[GCOMP]; - } - } - else { /* store triple */ - *ctile= 3; - *ztile= (uintptr_t)MEM_mallocN(3*256, "Tile3"); - - zt= (char *)*ztile; - rc= rcline; - for (a=0; a<256; a++, zt+=3, rc+=4) { - zt[0]= rc[ACOMP]; - zt[1]= rc[BCOMP]; - zt[2]= rc[GCOMP]; - } - } - } - ztile++; - ctile++; - } - } - - MEM_freeN(rcline); -} - -/* sets start/end clipping. lar->shb should be initialized */ -static void shadowbuf_autoclip(Render *re, LampRen *lar) -{ - ObjectInstanceRen *obi; - ObjectRen *obr; - VlakRen *vlr= NULL; - VertRen *ver= NULL; - Material *ma= NULL; - float minz, maxz, vec[3], viewmat[4][4], obviewmat[4][4]; - unsigned int lay = -1; - int i, a, maxtotvert, ok= 1; - char *clipflag; - - minz= 1.0e30f; maxz= -1.0e30f; - copy_m4_m4(viewmat, lar->shb->viewmat); - - if (lar->mode & (LA_LAYER|LA_LAYER_SHADOW)) lay= lar->lay; - - maxtotvert= 0; - for (obr=re->objecttable.first; obr; obr=obr->next) - maxtotvert = max_ii(obr->totvert, maxtotvert); - - clipflag= MEM_callocN(sizeof(char)*maxtotvert, "autoclipflag"); - - /* set clip in vertices when face visible */ - for (i=0, obi=re->instancetable.first; obi; i++, obi=obi->next) { - obr= obi->obr; - - if (obi->flag & R_TRANSFORMED) - mul_m4_m4m4(obviewmat, viewmat, obi->mat); - else - copy_m4_m4(obviewmat, viewmat); - - memset(clipflag, 0, sizeof(char)*obr->totvert); - - /* clear clip, is being set if face is visible (clip is calculated for real later) */ - for (a=0; a<obr->totvlak; a++) { - if ((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; - else vlr++; - - /* note; these conditions are copied from zbuffer_shadow() */ - if (vlr->mat!= ma) { - ma= vlr->mat; - ok= 1; - if ((ma->mode2 & MA_CASTSHADOW)==0 || (ma->mode & MA_SHADBUF)==0) ok= 0; - } - - if (ok && (obi->lay & lay)) { - clipflag[vlr->v1->index]= 1; - clipflag[vlr->v2->index]= 1; - clipflag[vlr->v3->index]= 1; - if (vlr->v4) clipflag[vlr->v4->index]= 1; - } - } - - /* calculate min and max */ - for (a=0; a< obr->totvert;a++) { - if ((a & 255)==0) ver= RE_findOrAddVert(obr, a); - else ver++; - - if (clipflag[a]) { - copy_v3_v3(vec, ver->co); - mul_m4_v3(obviewmat, vec); - /* Z on visible side of lamp space */ - if (vec[2] < 0.0f) { - float inpr, z= -vec[2]; - - /* since vec is rotated in lampspace, this is how to get the cosine of angle */ - /* precision is set 20% larger */ - vec[2]*= 1.2f; - normalize_v3(vec); - inpr= - vec[2]; - - if (inpr>=lar->spotsi) { - if (z<minz) minz= z; - if (z>maxz) maxz= z; - } - } - } - } - } - - MEM_freeN(clipflag); - - /* set clipping min and max */ - if (minz < maxz) { - float delta= (maxz - minz); /* threshold to prevent precision issues */ - - //printf("minz %f maxz %f delta %f\n", minz, maxz, delta); - if (lar->bufflag & LA_SHADBUF_AUTO_START) - lar->shb->d= minz - delta*0.02f; /* 0.02 is arbitrary... needs more thinking! */ - if (lar->bufflag & LA_SHADBUF_AUTO_END) - lar->shb->clipend= maxz + delta*0.1f; - - /* bias was calculated as percentage, we scale it to prevent animation issues */ - delta= (lar->clipend-lar->clipsta)/(lar->shb->clipend-lar->shb->d); - //printf("bias delta %f\n", delta); - lar->shb->bias= (int) (delta*(float)lar->shb->bias); - } -} - -static void makeflatshadowbuf(Render *re, LampRen *lar, float *jitbuf) -{ - ShadBuf *shb= lar->shb; - int *rectz, samples; - - /* zbuffering */ - rectz= MEM_mapallocN(sizeof(int)*shb->size*shb->size, "makeshadbuf"); - - for (samples=0; samples<shb->totbuf; samples++) { - zbuffer_shadow(re, shb->persmat, lar, rectz, shb->size, jitbuf[2*samples], jitbuf[2*samples+1]); - /* create Z tiles (for compression): this system is 24 bits!!! */ - compress_shadowbuf(shb, rectz, lar->mode & LA_SQUARE); - - if (re->test_break(re->tbh)) - break; - } - - MEM_freeN(rectz); -} - -static void makedeepshadowbuf(Render *re, LampRen *lar, float *jitbuf) -{ - ShadBuf *shb= lar->shb; - APixstr *apixbuf; - APixstrand *apixbufstrand= NULL; - ListBase apsmbase= {NULL, NULL}; - - /* zbuffering */ - apixbuf= MEM_callocN(sizeof(APixstr)*shb->size*shb->size, "APixbuf"); - if (re->totstrand) - apixbufstrand= MEM_callocN(sizeof(APixstrand)*shb->size*shb->size, "APixbufstrand"); - - zbuffer_abuf_shadow(re, lar, shb->persmat, apixbuf, apixbufstrand, &apsmbase, shb->size, - shb->totbuf, (float(*)[2])jitbuf); - - /* create Z tiles (for compression): this system is 24 bits!!! */ - compress_deepshadowbuf(re, shb, apixbuf, apixbufstrand); - - MEM_freeN(apixbuf); - if (apixbufstrand) - MEM_freeN(apixbufstrand); - freepsA(&apsmbase); -} - -void makeshadowbuf(Render *re, LampRen *lar) -{ - ShadBuf *shb= lar->shb; - float wsize, *jitbuf, twozero[2]= {0.0f, 0.0f}, angle, temp; - - if (lar->bufflag & (LA_SHADBUF_AUTO_START|LA_SHADBUF_AUTO_END)) - shadowbuf_autoclip(re, lar); - - /* just to enforce identical behavior of all irregular buffers */ - if (lar->buftype==LA_SHADBUF_IRREGULAR) - shb->size= 1024; - - /* matrices and window: in winmat the transformation is being put, - * transforming from observer view to lamp view, including lamp window matrix */ - - angle= saacos(lar->spotsi); - temp = 0.5f * shb->size * cosf(angle) / sinf(angle); - shb->pixsize= (shb->d)/temp; - wsize= shb->pixsize*(shb->size/2.0f); - - perspective_m4(shb->winmat, -wsize, wsize, -wsize, wsize, shb->d, shb->clipend); - mul_m4_m4m4(shb->persmat, shb->winmat, shb->viewmat); - - if (ELEM(lar->buftype, LA_SHADBUF_REGULAR, LA_SHADBUF_HALFWAY, LA_SHADBUF_DEEP)) { - shb->totbuf= lar->buffers; - - /* jitter, weights - not threadsafe! */ - BLI_thread_lock(LOCK_CUSTOM1); - shb->jit= give_jitter_tab(get_render_shadow_samples(&re->r, shb->samp)); - make_jitter_weight_tab(re, shb, lar->filtertype); - BLI_thread_unlock(LOCK_CUSTOM1); - - if (shb->totbuf==4) jitbuf= give_jitter_tab(2); - else if (shb->totbuf==9) jitbuf= give_jitter_tab(3); - else jitbuf= twozero; - - /* zbuffering */ - if (lar->buftype == LA_SHADBUF_DEEP) { - makedeepshadowbuf(re, lar, jitbuf); - shb->totbuf= 1; - } - else - makeflatshadowbuf(re, lar, jitbuf); - - /* printf("lampbuf %d\n", sizeoflampbuf(shb)); */ - } -} - -static void *do_shadow_thread(void *re_v) -{ - Render *re = (Render *)re_v; - LampRen *lar; - - do { - BLI_thread_lock(LOCK_CUSTOM1); - for (lar=re->lampren.first; lar; lar=lar->next) { - if (lar->shb && !lar->thread_assigned) { - lar->thread_assigned= 1; - break; - } - } - BLI_thread_unlock(LOCK_CUSTOM1); - - /* if type is irregular, this only sets the perspective matrix and autoclips */ - if (lar) { - makeshadowbuf(re, lar); - BLI_thread_lock(LOCK_CUSTOM1); - lar->thread_ready= 1; - BLI_thread_unlock(LOCK_CUSTOM1); - } - } while (lar && !re->test_break(re->tbh)); - - return NULL; -} - -static volatile int g_break= 0; -static int thread_break(void *UNUSED(arg)) -{ - return g_break; -} - -void threaded_makeshadowbufs(Render *re) -{ - ListBase threads; - LampRen *lar; - int a, totthread= 0; - int (*test_break)(void *); - - /* count number of threads to use */ - if (G.is_rendering) { - for (lar=re->lampren.first; lar; lar= lar->next) - if (lar->shb) - totthread++; - - totthread = min_ii(totthread, re->r.threads); - } - else - totthread = 1; /* preview render */ - - if (totthread <= 1) { - for (lar=re->lampren.first; lar; lar= lar->next) { - if (re->test_break(re->tbh)) break; - if (lar->shb) { - /* if type is irregular, this only sets the perspective matrix and autoclips */ - makeshadowbuf(re, lar); - } - } - } - else { - /* swap test break function */ - test_break= re->test_break; - re->test_break= thread_break; - - for (lar=re->lampren.first; lar; lar= lar->next) { - lar->thread_assigned= 0; - lar->thread_ready= 0; - } - - BLI_threadpool_init(&threads, do_shadow_thread, totthread); - - for (a=0; a<totthread; a++) - BLI_threadpool_insert(&threads, re); - - /* keep rendering as long as there are shadow buffers not ready */ - do { - if ((g_break=test_break(re->tbh))) - break; - - PIL_sleep_ms(50); - - BLI_thread_lock(LOCK_CUSTOM1); - for (lar=re->lampren.first; lar; lar= lar->next) - if (lar->shb && !lar->thread_ready) - break; - BLI_thread_unlock(LOCK_CUSTOM1); - } while (lar); - - BLI_threadpool_end(&threads); - - /* unset threadsafety */ - re->test_break= test_break; - g_break= 0; - } -} - -void freeshadowbuf(LampRen *lar) -{ - if (lar->shb) { - ShadBuf *shb= lar->shb; - ShadSampleBuf *shsample; - int b, v; - - for (shsample= shb->buffers.first; shsample; shsample= shsample->next) { - if (shsample->deepbuf) { - v= shb->size*shb->size; - for (b=0; b<v; b++) - if (shsample->deepbuf[b]) - MEM_freeN(shsample->deepbuf[b]); - - MEM_freeN(shsample->deepbuf); - MEM_freeN(shsample->totbuf); - } - else { - intptr_t *ztile= shsample->zbuf; - const char *ctile= shsample->cbuf; - - v= (shb->size*shb->size)/256; - for (b=0; b<v; b++, ztile++, ctile++) - if (*ctile) MEM_freeN((void *) *ztile); - - MEM_freeN(shsample->zbuf); - MEM_freeN(shsample->cbuf); - } - } - BLI_freelistN(&shb->buffers); - - if (shb->weight) MEM_freeN(shb->weight); - MEM_freeN(lar->shb); - - lar->shb= NULL; - } -} - - -static int firstreadshadbuf(ShadBuf *shb, ShadSampleBuf *shsample, int **rz, int xs, int ys, int nr) -{ - /* return a 1 if fully compressed shadbuf-tile && z==const */ - int ofs; - const char *ct; - - if (shsample->deepbuf) - return 0; - - /* always test borders of shadowbuffer */ - if (xs<0) xs= 0; else if (xs>=shb->size) xs= shb->size-1; - if (ys<0) ys= 0; else if (ys>=shb->size) ys= shb->size-1; - - /* calc z */ - ofs= (ys>>4)*(shb->size>>4) + (xs>>4); - ct= shsample->cbuf+ofs; - if (*ct==0) { - if (nr==0) { - *rz= *( (int **)(shsample->zbuf+ofs) ); - return 1; - } - else if (*rz!= *( (int **)(shsample->zbuf+ofs) )) return 0; - - return 1; - } - - return 0; -} - -static float readdeepvisibility(DeepSample *dsample, int tot, int z, int bias, float *biast) -{ - DeepSample *ds, *prevds; - float t; - int a; - - /* tricky stuff here; we use ints which can overflow easily with bias values */ - - ds= dsample; - for (a=0; a<tot && (z-bias > ds->z); a++, ds++) {} - - if (a == tot) { - if (biast) - *biast= 0.0f; - return (ds-1)->v; /* completely behind all samples */ - } - - /* check if this read needs bias blending */ - if (biast) { - if (z > ds->z) - *biast= (float)(z - ds->z)/(float)bias; - else - *biast= 0.0f; - } - - if (a == 0) - return 1.0f; /* completely in front of all samples */ - - /* converting to float early here because ds->z - prevds->z can overflow */ - prevds= ds-1; - t= ((float)(z-bias) - (float)prevds->z)/((float)ds->z - (float)prevds->z); - return t*ds->v + (1.0f-t)*prevds->v; -} - -static float readdeepshadowbuf(ShadBuf *shb, ShadSampleBuf *shsample, int bias, int xs, int ys, int zs) -{ - float v, biasv, biast; - int ofs, tot; - - if (zs < - 0x7FFFFE00 + bias) - return 1.0; /* extreme close to clipstart */ - - /* calc z */ - ofs= ys*shb->size + xs; - tot= shsample->totbuf[ofs]; - if (tot == 0) - return 1.0f; - - v= readdeepvisibility(shsample->deepbuf[ofs], tot, zs, bias, &biast); - - if (biast != 0.0f) { - /* in soft bias area */ - biasv = readdeepvisibility(shsample->deepbuf[ofs], tot, zs, 0, NULL); - - biast= biast*biast; - return (1.0f-biast)*v + biast*biasv; - } - - return v; -} - -/* return 1.0 : fully in light */ -static float readshadowbuf(ShadBuf *shb, ShadSampleBuf *shsample, int bias, int xs, int ys, int zs) -{ - float temp; - int *rz, ofs; - int zsamp=0; - char *ct, *cz; - - /* simpleclip */ - /* if (xs<0 || ys<0) return 1.0; */ - /* if (xs>=shb->size || ys>=shb->size) return 1.0; */ - - /* always test borders of shadowbuffer */ - if (xs<0) xs= 0; else if (xs>=shb->size) xs= shb->size-1; - if (ys<0) ys= 0; else if (ys>=shb->size) ys= shb->size-1; - - if (shsample->deepbuf) - return readdeepshadowbuf(shb, shsample, bias, xs, ys, zs); - - /* calc z */ - ofs= (ys>>4)*(shb->size>>4) + (xs>>4); - ct= shsample->cbuf+ofs; - rz= *( (int **)(shsample->zbuf+ofs) ); - - if (*ct==3) { - ct= ((char *)rz)+3*16*(ys & 15)+3*(xs & 15); - cz= (char *)&zsamp; - cz[ACOMP]= ct[0]; - cz[BCOMP]= ct[1]; - cz[GCOMP]= ct[2]; - } - else if (*ct==2) { - ct= ((char *)rz); - ct+= 4+2*16*(ys & 15)+2*(xs & 15); - zsamp= *rz; - - cz= (char *)&zsamp; - cz[BCOMP]= ct[0]; - cz[GCOMP]= ct[1]; - } - else if (*ct==1) { - ct= ((char *)rz); - ct+= 4+16*(ys & 15)+(xs & 15); - zsamp= *rz; - - cz= (char *)&zsamp; - cz[GCOMP]= ct[0]; - - } - else { - /* got warning on this for 64 bits.... */ - /* but it's working code! in this case rz is not a pointer but zvalue (ton) */ - zsamp= GET_INT_FROM_POINTER(rz); - } - - /* tricky stuff here; we use ints which can overflow easily with bias values */ - - if (zsamp > zs) return 1.0; /* absolute no shadow */ - else if (zs < - 0x7FFFFE00 + bias) return 1.0; /* extreme close to clipstart */ - else if (zsamp < zs-bias) return 0.0; /* absolute in shadow */ - else { /* soft area */ - - temp= ( (float)(zs- zsamp) )/(float)bias; - return 1.0f - temp*temp; - - } -} - -static void shadowbuf_project_co(float *x, float *y, float *z, ShadBuf *shb, const float co[3]) -{ - float hco[4], size= 0.5f*(float)shb->size; - - copy_v3_v3(hco, co); - hco[3]= 1.0f; - - mul_m4_v4(shb->persmat, hco); - - *x= size*(1.0f+hco[0]/hco[3]); - *y= size*(1.0f+hco[1]/hco[3]); - if (z) *z= (hco[2]/hco[3]); -} - -/* the externally called shadow testing (reading) function */ -/* return 1.0: no shadow at all */ -float testshadowbuf(Render *re, ShadBuf *shb, const float co[3], const float dxco[3], const float dyco[3], float inp, float mat_bias) -{ - ShadSampleBuf *shsample; - float fac, dco[3], dx[3], dy[3], shadfac=0.0f; - float xs1, ys1, zs1, *jit, *weight, xres, yres, biasf; - int xs, ys, zs, bias, *rz; - short a, num; - - /* crash preventer */ - if (shb->buffers.first==NULL) - return 1.0f; - - /* when facing away, assume fully in shadow */ - if (inp <= 0.0f) - return 0.0f; - - /* project coordinate to pixel space */ - shadowbuf_project_co(&xs1, &ys1, &zs1, shb, co); - - /* clip z coordinate, z is projected so that (-1.0, 1.0) matches - * (clipstart, clipend), so we can do this simple test */ - if (zs1>=1.0f) - return 0.0f; - else if (zs1<= -1.0f) - return 1.0f; - - zs= ((float)0x7FFFFFFF)*zs1; - - /* take num*num samples, increase area with fac */ - num= get_render_shadow_samples(&re->r, shb->samp); - num= num*num; - fac= shb->soft; - - /* compute z bias */ - if (mat_bias!=0.0f) biasf= shb->bias*mat_bias; - else biasf= shb->bias; - /* with inp==1.0, bias is half the size. correction value was 1.1, giving errors - * on cube edges, with one side being almost frontal lighted (ton) */ - bias= (1.5f-inp*inp)*biasf; - - /* in case of no filtering we can do things simpler */ - if (num==1) { - for (shsample= shb->buffers.first; shsample; shsample= shsample->next) - shadfac += readshadowbuf(shb, shsample, bias, (int)xs1, (int)ys1, zs); - - return shadfac/(float)shb->totbuf; - } - - /* calculate filter size */ - add_v3_v3v3(dco, co, dxco); - shadowbuf_project_co(&dx[0], &dx[1], NULL, shb, dco); - dx[0]= xs1 - dx[0]; - dx[1]= ys1 - dx[1]; - - add_v3_v3v3(dco, co, dyco); - shadowbuf_project_co(&dy[0], &dy[1], NULL, shb, dco); - dy[0]= xs1 - dy[0]; - dy[1]= ys1 - dy[1]; - - xres = fac * (fabsf(dx[0]) + fabsf(dy[0])); - yres = fac * (fabsf(dx[1]) + fabsf(dy[1])); - if (xres<1.0f) xres= 1.0f; - if (yres<1.0f) yres= 1.0f; - - /* make xs1/xs1 corner of sample area */ - xs1 -= xres*0.5f; - ys1 -= yres*0.5f; - - /* in case we have a constant value in a tile, we can do quicker lookup */ - if (xres<16.0f && yres<16.0f) { - shsample= shb->buffers.first; - if (firstreadshadbuf(shb, shsample, &rz, (int)xs1, (int)ys1, 0)) { - if (firstreadshadbuf(shb, shsample, &rz, (int)(xs1+xres), (int)ys1, 1)) { - if (firstreadshadbuf(shb, shsample, &rz, (int)xs1, (int)(ys1+yres), 1)) { - if (firstreadshadbuf(shb, shsample, &rz, (int)(xs1+xres), (int)(ys1+yres), 1)) { - return readshadowbuf(shb, shsample, bias, (int)xs1, (int)ys1, zs); - } - } - } - } - } - - /* full jittered shadow buffer lookup */ - for (shsample= shb->buffers.first; shsample; shsample= shsample->next) { - jit= shb->jit; - weight= shb->weight; - - for (a=num; a>0; a--, jit+=2, weight++) { - /* instead of jit i tried random: ugly! */ - /* note: the plus 0.5 gives best sampling results, jit goes from -0.5 to 0.5 */ - /* xs1 and ys1 are already corrected to be corner of sample area */ - xs= xs1 + xres*(jit[0] + 0.5f); - ys= ys1 + yres*(jit[1] + 0.5f); - - shadfac+= *weight * readshadowbuf(shb, shsample, bias, xs, ys, zs); - } - } - - /* Renormalizes for the sample number: */ - return shadfac/(float)shb->totbuf; -} - -/* different function... sampling behind clipend can be LIGHT, bias is negative! */ -/* return: light */ -static float readshadowbuf_halo(ShadBuf *shb, ShadSampleBuf *shsample, int xs, int ys, int zs) -{ - float temp; - int *rz, ofs; - int bias, zbias, zsamp; - char *ct, *cz; - - /* negative! The other side is more important */ - bias= -shb->bias; - - /* simpleclip */ - if (xs<0 || ys<0) return 0.0; - if (xs>=shb->size || ys>=shb->size) return 0.0; - - /* calc z */ - ofs= (ys>>4)*(shb->size>>4) + (xs>>4); - ct= shsample->cbuf+ofs; - rz= *( (int **)(shsample->zbuf+ofs) ); - - if (*ct==3) { - ct= ((char *)rz)+3*16*(ys & 15)+3*(xs & 15); - cz= (char *)&zsamp; - zsamp= 0; - cz[ACOMP]= ct[0]; - cz[BCOMP]= ct[1]; - cz[GCOMP]= ct[2]; - } - else if (*ct==2) { - ct= ((char *)rz); - ct+= 4+2*16*(ys & 15)+2*(xs & 15); - zsamp= *rz; - - cz= (char *)&zsamp; - cz[BCOMP]= ct[0]; - cz[GCOMP]= ct[1]; - } - else if (*ct==1) { - ct= ((char *)rz); - ct+= 4+16*(ys & 15)+(xs & 15); - zsamp= *rz; - - cz= (char *)&zsamp; - cz[GCOMP]= ct[0]; - - } - else { - /* same as before */ - /* still working code! (ton) */ - zsamp= GET_INT_FROM_POINTER(rz); - } - - /* NO schadow when sampled at 'eternal' distance */ - - if (zsamp >= 0x7FFFFE00) return 1.0; - - if (zsamp > zs) return 1.0; /* absolute no shadww */ - else { - /* bias is negative, so the (zs-bias) can be beyond 0x7fffffff */ - zbias= 0x7fffffff - zs; - if (zbias > -bias) { - if ( zsamp < zs-bias) return 0.0; /* absolute in shadow */ - } - else return 0.0; /* absolute shadow */ - } - - /* soft area */ - - temp= ( (float)(zs- zsamp) )/(float)bias; - return 1.0f - temp*temp; -} - - -float shadow_halo(LampRen *lar, const float p1[3], const float p2[3]) -{ - /* p1 p2 already are rotated in spot-space */ - ShadBuf *shb= lar->shb; - ShadSampleBuf *shsample; - float co[4], siz; - float lambda, lambda_o, lambda_x, lambda_y, ldx, ldy; - float zf, xf1, yf1, zf1, xf2, yf2, zf2; - float count, lightcount; - int x, y, z, xs1, ys1; - int dx = 0, dy = 0; - - siz= 0.5f*(float)shb->size; - - co[0]= p1[0]; - co[1]= p1[1]; - co[2]= p1[2]/lar->sh_zfac; - co[3]= 1.0; - mul_m4_v4(shb->winmat, co); /* rational hom co */ - xf1= siz*(1.0f+co[0]/co[3]); - yf1= siz*(1.0f+co[1]/co[3]); - zf1= (co[2]/co[3]); - - - co[0]= p2[0]; - co[1]= p2[1]; - co[2]= p2[2]/lar->sh_zfac; - co[3]= 1.0; - mul_m4_v4(shb->winmat, co); /* rational hom co */ - xf2= siz*(1.0f+co[0]/co[3]); - yf2= siz*(1.0f+co[1]/co[3]); - zf2= (co[2]/co[3]); - - /* the 2dda (a pixel line formula) */ - - xs1= (int)xf1; - ys1= (int)yf1; - - if (xf1 != xf2) { - if (xf2-xf1 > 0.0f) { - lambda_x= (xf1-xs1-1.0f)/(xf1-xf2); - ldx= -shb->shadhalostep/(xf1-xf2); - dx= shb->shadhalostep; - } - else { - lambda_x= (xf1-xs1)/(xf1-xf2); - ldx= shb->shadhalostep/(xf1-xf2); - dx= -shb->shadhalostep; - } - } - else { - lambda_x= 1.0; - ldx= 0.0; - } - - if (yf1 != yf2) { - if (yf2-yf1 > 0.0f) { - lambda_y= (yf1-ys1-1.0f)/(yf1-yf2); - ldy= -shb->shadhalostep/(yf1-yf2); - dy= shb->shadhalostep; - } - else { - lambda_y= (yf1-ys1)/(yf1-yf2); - ldy= shb->shadhalostep/(yf1-yf2); - dy= -shb->shadhalostep; - } - } - else { - lambda_y= 1.0; - ldy= 0.0; - } - - x= xs1; - y= ys1; - lambda= count= lightcount= 0.0; - -/* printf("start %x %x \n", (int)(0x7FFFFFFF*zf1), (int)(0x7FFFFFFF*zf2)); */ - - do { - lambda_o= lambda; - - if (lambda_x==lambda_y) { - lambda_x+= ldx; - x+= dx; - lambda_y+= ldy; - y+= dy; - } - else { - if (lambda_x<lambda_y) { - lambda_x+= ldx; - x+= dx; - } - else { - lambda_y+= ldy; - y+= dy; - } - } - - lambda = min_ff(lambda_x, lambda_y); - - /* not making any progress? */ - if (lambda==lambda_o) break; - - /* clip to end of volume */ - lambda = min_ff(lambda, 1.0f); - - zf= zf1 + lambda*(zf2-zf1); - count+= (float)shb->totbuf; - - if (zf<= -1.0f) lightcount += 1.0f; /* close to the spot */ - else { - - /* make sure, behind the clipend we extend halolines. */ - if (zf>=1.0f) z= 0x7FFFF000; - else z= (int)(0x7FFFF000*zf); - - for (shsample= shb->buffers.first; shsample; shsample= shsample->next) - lightcount+= readshadowbuf_halo(shb, shsample, x, y, z); - - } - } - while (lambda < 1.0f); - - if (count!=0.0f) return (lightcount/count); - return 0.0f; - -} - - -/* ********************* Irregular Shadow Buffer (ISB) ************* */ -/* ********** storage of all view samples in a raster of lists ***** */ - -/* based on several articles describing this method, like: - * The Irregular Z-Buffer and its Application to Shadow Mapping - * Gregory S. Johnson - William R. Mark - Christopher A. Burns - * and - * Alias-Free Shadow Maps - * Timo Aila and Samuli Laine - */ - -/* bsp structure (actually kd tree) */ - -#define BSPMAX_SAMPLE 128 -#define BSPMAX_DEPTH 32 - -/* aligned with struct rctf */ -typedef struct Boxf { - float xmin, xmax; - float ymin, ymax; - float zmin, zmax; -} Boxf; - -typedef struct ISBBranch { - struct ISBBranch *left, *right; - float divider[2]; - Boxf box; - short totsamp, index, full, unused; - ISBSample **samples; -} ISBBranch; - -typedef struct BSPFace { - Boxf box; - const float *v1, *v2, *v3, *v4; - int obi; /* object for face lookup */ - int facenr; /* index to retrieve VlakRen */ - int type; /* only for strand now */ - short shad_alpha, is_full; - - /* strand caching data, optimize for point_behind_strand() */ - float radline, radline_end, len; - float vec1[3], vec2[3], rc[3]; -} BSPFace; - -/* boxes are in lamp projection */ -static void init_box(Boxf *box) -{ - box->xmin = 1000000.0f; - box->xmax = 0; - box->ymin = 1000000.0f; - box->ymax = 0; - box->zmin= 0x7FFFFFFF; - box->zmax= - 0x7FFFFFFF; -} - -/* use v1 to calculate boundbox */ -static void bound_boxf(Boxf *box, const float v1[3]) -{ - if (v1[0] < box->xmin) box->xmin = v1[0]; - if (v1[0] > box->xmax) box->xmax = v1[0]; - if (v1[1] < box->ymin) box->ymin = v1[1]; - if (v1[1] > box->ymax) box->ymax = v1[1]; - if (v1[2] < box->zmin) box->zmin= v1[2]; - if (v1[2] > box->zmax) box->zmax= v1[2]; -} - -/* use v1 to calculate boundbox */ -static void bound_rectf(rctf *box, const float v1[2]) -{ - if (v1[0] < box->xmin) box->xmin = v1[0]; - if (v1[0] > box->xmax) box->xmax = v1[0]; - if (v1[1] < box->ymin) box->ymin = v1[1]; - if (v1[1] > box->ymax) box->ymax = v1[1]; -} - - -/* halfway splitting, for initializing a more regular tree */ -static void isb_bsp_split_init(ISBBranch *root, MemArena *mem, int level) -{ - - /* if level > 0 we create new branches and go deeper */ - if (level > 0) { - ISBBranch *left, *right; - int i; - - /* splitpoint */ - root->divider[0]= 0.5f*(root->box.xmin+root->box.xmax); - root->divider[1]= 0.5f*(root->box.ymin+root->box.ymax); - - /* find best splitpoint */ - if (RCT_SIZE_X(&root->box) > RCT_SIZE_Y(&root->box)) - i = root->index = 0; - else - i = root->index = 1; - - left= root->left= BLI_memarena_alloc(mem, sizeof(ISBBranch)); - right= root->right= BLI_memarena_alloc(mem, sizeof(ISBBranch)); - - /* box info */ - left->box= root->box; - right->box= root->box; - if (i==0) { - left->box.xmax = root->divider[0]; - right->box.xmin = root->divider[0]; - } - else { - left->box.ymax = root->divider[1]; - right->box.ymin = root->divider[1]; - } - isb_bsp_split_init(left, mem, level-1); - isb_bsp_split_init(right, mem, level-1); - } - else { - /* we add sample array */ - root->samples= BLI_memarena_alloc(mem, BSPMAX_SAMPLE*sizeof(void *)); - } -} - -/* note; if all samples on same location we just spread them over 2 new branches */ -static void isb_bsp_split(ISBBranch *root, MemArena *mem) -{ - ISBBranch *left, *right; - ISBSample *samples[BSPMAX_SAMPLE]; - int a, i; - - /* splitpoint */ - root->divider[0]= root->divider[1]= 0.0f; - for (a=BSPMAX_SAMPLE-1; a>=0; a--) { - root->divider[0]+= root->samples[a]->zco[0]; - root->divider[1]+= root->samples[a]->zco[1]; - } - root->divider[0]/= BSPMAX_SAMPLE; - root->divider[1]/= BSPMAX_SAMPLE; - - /* find best splitpoint */ - if (RCT_SIZE_X(&root->box) > RCT_SIZE_Y(&root->box)) - i = root->index = 0; - else - i = root->index = 1; - - /* new branches */ - left= root->left= BLI_memarena_alloc(mem, sizeof(ISBBranch)); - right= root->right= BLI_memarena_alloc(mem, sizeof(ISBBranch)); - - /* new sample array */ - left->samples = BLI_memarena_alloc(mem, BSPMAX_SAMPLE*sizeof(void *)); - right->samples = samples; /* tmp */ - - /* split samples */ - for (a=BSPMAX_SAMPLE-1; a>=0; a--) { - int comp= 0; - /* this prevents adding samples all to 1 branch when divider is equal to samples */ - if (root->samples[a]->zco[i] == root->divider[i]) - comp= a & 1; - else if (root->samples[a]->zco[i] < root->divider[i]) - comp= 1; - - if (comp==1) { - left->samples[left->totsamp]= root->samples[a]; - left->totsamp++; - } - else { - right->samples[right->totsamp]= root->samples[a]; - right->totsamp++; - } - } - - /* copy samples from tmp */ - memcpy(root->samples, samples, right->totsamp*(sizeof(void *))); - right->samples= root->samples; - root->samples= NULL; - - /* box info */ - left->box= root->box; - right->box= root->box; - if (i==0) { - left->box.xmax = root->divider[0]; - right->box.xmin = root->divider[0]; - } - else { - left->box.ymax = root->divider[1]; - right->box.ymin = root->divider[1]; - } -} - -/* inserts sample in main tree, also splits on threshold */ -/* returns 1 if error */ -static int isb_bsp_insert(ISBBranch *root, MemArena *memarena, ISBSample *sample) -{ - ISBBranch *bspn= root; - const float *zco= sample->zco; - int i= 0; - - /* debug counter, also used to check if something was filled in ever */ - root->totsamp++; - - /* going over branches until last one found */ - while (bspn->left) { - if (zco[bspn->index] <= bspn->divider[bspn->index]) - bspn= bspn->left; - else - bspn= bspn->right; - i++; - } - /* bspn now is the last branch */ - - if (bspn->totsamp==BSPMAX_SAMPLE) { - printf("error in bsp branch\n"); /* only for debug, cannot happen */ - return 1; - } - - /* insert */ - bspn->samples[bspn->totsamp]= sample; - bspn->totsamp++; - - /* split if allowed and needed */ - if (bspn->totsamp==BSPMAX_SAMPLE) { - if (i==BSPMAX_DEPTH) { - bspn->totsamp--; /* stop filling in... will give errors */ - return 1; - } - isb_bsp_split(bspn, memarena); - } - return 0; -} - -/* initialize vars in face, for optimal point-in-face test */ -static void bspface_init_strand(BSPFace *face) -{ - - face->radline= 0.5f* len_v2v2(face->v1, face->v2); - - mid_v3_v3v3(face->vec1, face->v1, face->v2); - if (face->v4) - mid_v3_v3v3(face->vec2, face->v3, face->v4); - else - copy_v3_v3(face->vec2, face->v3); - - face->rc[0]= face->vec2[0]-face->vec1[0]; - face->rc[1]= face->vec2[1]-face->vec1[1]; - face->rc[2]= face->vec2[2]-face->vec1[2]; - - face->len= face->rc[0]*face->rc[0]+ face->rc[1]*face->rc[1]; - - if (face->len != 0.0f) { - face->radline_end = face->radline / sqrtf(face->len); - face->len = 1.0f / face->len; - } -} - -/* brought back to a simple 2d case */ -static int point_behind_strand(const float p[3], BSPFace *face) -{ - /* v1 - v2 is radius, v1 - v3 length */ - float dist, rc[2], pt[2]; - - /* using code from dist_to_line_segment_v2(), distance vec to line-piece */ - - if (face->len==0.0f) { - rc[0]= p[0]-face->vec1[0]; - rc[1]= p[1]-face->vec1[1]; - dist = len_v2(rc); - - if (dist < face->radline) - return 1; - } - else { - float lambda= ( face->rc[0]*(p[0]-face->vec1[0]) + face->rc[1]*(p[1]-face->vec1[1]) )*face->len; - - if (lambda > -face->radline_end && lambda < 1.0f+face->radline_end) { - /* hesse for dist: */ - //dist= (float)(fabs( (p[0]-vec2[0])*rc[1] + (p[1]-vec2[1])*rc[0])/len); - - pt[0]= lambda*face->rc[0]+face->vec1[0]; - pt[1]= lambda*face->rc[1]+face->vec1[1]; - - rc[0]= pt[0]-p[0]; - rc[1]= pt[1]-p[1]; - dist = len_v2(rc); - - if (dist < face->radline) { - float zval= face->vec1[2] + lambda*face->rc[2]; - if (p[2] > zval) - return 1; - } - } - } - return 0; -} - - -/* return 1 if inside. code derived from src/parametrizer.c */ -static int point_behind_tria2d(const float p[3], const float v1[3], const float v2[3], const float v3[3]) -{ - float a[2], c[2], h[2], div; - float u, v; - - a[0] = v2[0] - v1[0]; - a[1] = v2[1] - v1[1]; - c[0] = v3[0] - v1[0]; - c[1] = v3[1] - v1[1]; - - div = a[0]*c[1] - a[1]*c[0]; - if (div==0.0f) - return 0; - - h[0] = p[0] - v1[0]; - h[1] = p[1] - v1[1]; - - div = 1.0f/div; - - u = (h[0]*c[1] - h[1]*c[0])*div; - if (u >= 0.0f) { - v = (a[0]*h[1] - a[1]*h[0])*div; - if (v >= 0.0f) { - if ( u + v <= 1.0f) { - /* inside, now check if point p is behind */ - float z= (1.0f-u-v)*v1[2] + u*v2[2] + v*v3[2]; - if (z <= p[2]) - return 1; - } - } - } - - return 0; -} - -#if 0 -/* tested these calls, but it gives inaccuracy, 'side' cannot be found reliably using v3 */ - -/* check if line v1-v2 has all rect points on other side of point v3 */ -static int rect_outside_line(rctf *rect, const float v1[3], const float v2[3], const float v3[3]) -{ - float a, b, c; - int side; - - /* line formula for v1-v2 */ - a= v2[1]-v1[1]; - b= v1[0]-v2[0]; - c= -a*v1[0] - b*v1[1]; - side= a*v3[0] + b*v3[1] + c < 0.0f; - - /* the four quad points */ - if ( side==(rect->xmin*a + rect->ymin*b + c >= 0.0f) ) - if ( side==(rect->xmax*a + rect->ymin*b + c >= 0.0f) ) - if ( side==(rect->xmax*a + rect->ymax*b + c >= 0.0f) ) - if ( side==(rect->xmin*a + rect->ymax*b + c >= 0.0f) ) - return 1; - return 0; -} - -/* check if one of the triangle edges separates all rect points on 1 side */ -static int rect_isect_tria(rctf *rect, const float v1[3], const float v2[3], const float v3[3]) -{ - if (rect_outside_line(rect, v1, v2, v3)) - return 0; - if (rect_outside_line(rect, v2, v3, v1)) - return 0; - if (rect_outside_line(rect, v3, v1, v2)) - return 0; - return 1; -} -#endif - -/* if face overlaps a branch, it executes func. recursive */ -static void isb_bsp_face_inside(ISBBranch *bspn, BSPFace *face) -{ - - /* are we descending? */ - if (bspn->left) { - /* hrmf, the box struct cannot be addressed with index */ - if (bspn->index==0) { - if (face->box.xmin <= bspn->divider[0]) - isb_bsp_face_inside(bspn->left, face); - if (face->box.xmax > bspn->divider[0]) - isb_bsp_face_inside(bspn->right, face); - } - else { - if (face->box.ymin <= bspn->divider[1]) - isb_bsp_face_inside(bspn->left, face); - if (face->box.ymax > bspn->divider[1]) - isb_bsp_face_inside(bspn->right, face); - } - } - else { - /* else: end branch reached */ - int a; - - if (bspn->totsamp==0) return; - - /* check for nodes entirely in shadow, can be skipped */ - if (bspn->totsamp==bspn->full) - return; - - /* if bsp node is entirely in front of face, give up */ - if (bspn->box.zmax < face->box.zmin) - return; - - /* if face boundbox is outside of branch rect, give up */ - if (0==BLI_rctf_isect((rctf *)&face->box, (rctf *)&bspn->box, NULL)) - return; - - /* test all points inside branch */ - for (a=bspn->totsamp-1; a>=0; a--) { - ISBSample *samp= bspn->samples[a]; - - if ((samp->facenr!=face->facenr || samp->obi!=face->obi) && samp->shadfac) { - if (face->box.zmin < samp->zco[2]) { - if (BLI_rctf_isect_pt_v((rctf *)&face->box, samp->zco)) { - int inshadow= 0; - - if (face->type) { - if (point_behind_strand(samp->zco, face)) - inshadow= 1; - } - else if ( point_behind_tria2d(samp->zco, face->v1, face->v2, face->v3)) - inshadow= 1; - else if (face->v4 && point_behind_tria2d(samp->zco, face->v1, face->v3, face->v4)) - inshadow= 1; - - if (inshadow) { - *(samp->shadfac) += face->shad_alpha; - /* optimize; is_full means shad_alpha==4096 */ - if (*(samp->shadfac) >= 4096 || face->is_full) { - bspn->full++; - samp->shadfac= NULL; - } - } - } - } - } - } - } -} - -/* based on available samples, recalculate the bounding box for bsp nodes, recursive */ -static void isb_bsp_recalc_box(ISBBranch *root) -{ - if (root->left) { - isb_bsp_recalc_box(root->left); - isb_bsp_recalc_box(root->right); - } - else if (root->totsamp) { - int a; - - init_box(&root->box); - for (a=root->totsamp-1; a>=0; a--) - bound_boxf(&root->box, root->samples[a]->zco); - } -} - -/* callback function for zbuf clip */ -static void isb_bsp_test_strand(ZSpan *zspan, int obi, int zvlnr, - const float *v1, const float *v2, const float *v3, const float *v4) -{ - BSPFace face; - - face.v1= v1; - face.v2= v2; - face.v3= v3; - face.v4= v4; - face.obi= obi; - face.facenr= zvlnr & ~RE_QUAD_OFFS; - face.type= R_STRAND; - if (R.osa) - face.shad_alpha= (short)ceil(4096.0f*zspan->shad_alpha/(float)R.osa); - else - face.shad_alpha= (short)ceil(4096.0f*zspan->shad_alpha); - - face.is_full= (zspan->shad_alpha==1.0f); - - /* setup boundbox */ - init_box(&face.box); - bound_boxf(&face.box, v1); - bound_boxf(&face.box, v2); - bound_boxf(&face.box, v3); - if (v4) - bound_boxf(&face.box, v4); - - /* optimize values */ - bspface_init_strand(&face); - - isb_bsp_face_inside((ISBBranch *)zspan->rectz, &face); - -} - -/* callback function for zbuf clip */ -static void isb_bsp_test_face(ZSpan *zspan, int obi, int zvlnr, - const float *v1, const float *v2, const float *v3, const float *v4) -{ - BSPFace face; - - face.v1= v1; - face.v2= v2; - face.v3= v3; - face.v4= v4; - face.obi= obi; - face.facenr= zvlnr & ~RE_QUAD_OFFS; - face.type= 0; - if (R.osa) - face.shad_alpha= (short)ceil(4096.0f*zspan->shad_alpha/(float)R.osa); - else - face.shad_alpha= (short)ceil(4096.0f*zspan->shad_alpha); - - face.is_full= (zspan->shad_alpha==1.0f); - - /* setup boundbox */ - init_box(&face.box); - bound_boxf(&face.box, v1); - bound_boxf(&face.box, v2); - bound_boxf(&face.box, v3); - if (v4) - bound_boxf(&face.box, v4); - - isb_bsp_face_inside((ISBBranch *)zspan->rectz, &face); -} - -static int testclip_minmax(const float ho[4], const float minmax[4]) -{ - float wco= ho[3]; - int flag= 0; - - if ( ho[0] > minmax[1]*wco) flag = 1; - else if ( ho[0]< minmax[0]*wco) flag = 2; - - if ( ho[1] > minmax[3]*wco) flag |= 4; - else if ( ho[1]< minmax[2]*wco) flag |= 8; - - return flag; -} - -/* main loop going over all faces and check in bsp overlaps, fill in shadfac values */ -static void isb_bsp_fillfaces(Render *re, LampRen *lar, ISBBranch *root) -{ - ObjectInstanceRen *obi; - ObjectRen *obr; - ShadBuf *shb= lar->shb; - ZSpan zspan, zspanstrand; - VlakRen *vlr= NULL; - Material *ma= NULL; - float minmaxf[4], winmat[4][4]; - int size= shb->size; - int i, a, ok=1, lay= -1; - - /* further optimize, also sets minz maxz */ - isb_bsp_recalc_box(root); - - /* extra clipping for minmax */ - minmaxf[0]= (2.0f*root->box.xmin - size-2.0f)/size; - minmaxf[1]= (2.0f*root->box.xmax - size+2.0f)/size; - minmaxf[2]= (2.0f*root->box.ymin - size-2.0f)/size; - minmaxf[3]= (2.0f*root->box.ymax - size+2.0f)/size; - - if (lar->mode & (LA_LAYER|LA_LAYER_SHADOW)) lay= lar->lay; - - /* (ab)use zspan, since we use zbuffer clipping code */ - zbuf_alloc_span(&zspan, size, size, re->clipcrop); - - zspan.zmulx= ((float)size)/2.0f; - zspan.zmuly= ((float)size)/2.0f; - zspan.zofsx= -0.5f; - zspan.zofsy= -0.5f; - - /* pass on bsp root to zspan */ - zspan.rectz= (int *)root; - - /* filling methods */ - zspanstrand= zspan; - // zspan.zbuflinefunc= zbufline_onlyZ; - zspan.zbuffunc= isb_bsp_test_face; - zspanstrand.zbuffunc= isb_bsp_test_strand; - - for (i=0, obi=re->instancetable.first; obi; i++, obi=obi->next) { - obr= obi->obr; - - if (obi->flag & R_TRANSFORMED) - mul_m4_m4m4(winmat, shb->persmat, obi->mat); - else - copy_m4_m4(winmat, shb->persmat); - - for (a=0; a<obr->totvlak; a++) { - - if ((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; - else vlr++; - - /* note, these conditions are copied in shadowbuf_autoclip() */ - if (vlr->mat!= ma) { - ma= vlr->mat; - ok= 1; - if ((ma->mode2 & MA_CASTSHADOW)==0 || (ma->mode & MA_SHADBUF)==0) ok= 0; - if (ma->material_type == MA_TYPE_WIRE) ok= 0; - zspanstrand.shad_alpha= zspan.shad_alpha= ma->shad_alpha; - } - - if (ok && (obi->lay & lay)) { - float hoco[4][4]; - int c1, c2, c3, c4=0; - int d1, d2, d3, d4=0; - int partclip; - - /* create hocos per face, it is while render */ - projectvert(vlr->v1->co, winmat, hoco[0]); d1= testclip_minmax(hoco[0], minmaxf); - projectvert(vlr->v2->co, winmat, hoco[1]); d2= testclip_minmax(hoco[1], minmaxf); - projectvert(vlr->v3->co, winmat, hoco[2]); d3= testclip_minmax(hoco[2], minmaxf); - if (vlr->v4) { - projectvert(vlr->v4->co, winmat, hoco[3]); d4= testclip_minmax(hoco[3], minmaxf); - } - - /* minmax clipping */ - if (vlr->v4) partclip= d1 & d2 & d3 & d4; - else partclip= d1 & d2 & d3; - - if (partclip==0) { - - /* window clipping */ - c1= testclip(hoco[0]); - c2= testclip(hoco[1]); - c3= testclip(hoco[2]); - if (vlr->v4) - c4= testclip(hoco[3]); - - /* ***** NO WIRE YET */ - if (ma->material_type == MA_TYPE_WIRE) { - if (vlr->v4) - zbufclipwire(&zspan, i, a+1, vlr->ec, hoco[0], hoco[1], hoco[2], hoco[3], c1, c2, c3, c4); - else - zbufclipwire(&zspan, i, a+1, vlr->ec, hoco[0], hoco[1], hoco[2], NULL, c1, c2, c3, 0); - } - else if (vlr->v4) { - if (vlr->flag & R_STRAND) - zbufclip4(&zspanstrand, i, a+1, hoco[0], hoco[1], hoco[2], hoco[3], c1, c2, c3, c4); - else - zbufclip4(&zspan, i, a+1, hoco[0], hoco[1], hoco[2], hoco[3], c1, c2, c3, c4); - } - else - zbufclip(&zspan, i, a+1, hoco[0], hoco[1], hoco[2], c1, c2, c3); - - } - } - } - } - - zbuf_free_span(&zspan); -} - -/* returns 1 when the viewpixel is visible in lampbuffer */ -static int viewpixel_to_lampbuf(ShadBuf *shb, ObjectInstanceRen *obi, VlakRen *vlr, float x, float y, float co_r[3]) -{ - float hoco[4], v1[3], nor[3]; - float dface, fac, siz; - - RE_vlakren_get_normal(&R, obi, vlr, nor); - copy_v3_v3(v1, vlr->v1->co); - if (obi->flag & R_TRANSFORMED) - mul_m4_v3(obi->mat, v1); - - /* from shadepixel() */ - dface = dot_v3v3(v1, nor); - hoco[3]= 1.0f; - - /* ortho viewplane cannot intersect using view vector originating in (0, 0, 0) */ - if (R.r.mode & R_ORTHO) { - /* x and y 3d coordinate can be derived from pixel coord and winmat */ - float fx= 2.0f/(R.winx*R.winmat[0][0]); - float fy= 2.0f/(R.winy*R.winmat[1][1]); - - hoco[0]= (x - 0.5f*R.winx)*fx - R.winmat[3][0]/R.winmat[0][0]; - hoco[1]= (y - 0.5f*R.winy)*fy - R.winmat[3][1]/R.winmat[1][1]; - - /* using a*x + b*y + c*z = d equation, (a b c) is normal */ - if (nor[2]!=0.0f) - hoco[2]= (dface - nor[0]*hoco[0] - nor[1]*hoco[1])/nor[2]; - else - hoco[2]= 0.0f; - } - else { - float div, view[3]; - - calc_view_vector(view, x, y); - - div = dot_v3v3(nor, view); - if (div==0.0f) - return 0; - - fac= dface/div; - - hoco[0]= fac*view[0]; - hoco[1]= fac*view[1]; - hoco[2]= fac*view[2]; - } - - /* move 3d vector to lampbuf */ - mul_m4_v4(shb->persmat, hoco); /* rational hom co */ - - /* clip We can test for -1.0/1.0 because of the properties of the - * coordinate transformations. */ - fac = fabsf(hoco[3]); - if (hoco[0]<-fac || hoco[0]>fac) - return 0; - if (hoco[1]<-fac || hoco[1]>fac) - return 0; - if (hoco[2]<-fac || hoco[2]>fac) - return 0; - - siz= 0.5f*(float)shb->size; - co_r[0]= siz*(1.0f+hoco[0]/hoco[3]) -0.5f; - co_r[1]= siz*(1.0f+hoco[1]/hoco[3]) -0.5f; - co_r[2]= ((float)0x7FFFFFFF)*(hoco[2]/hoco[3]); - - /* XXXX bias, much less than normal shadbuf, or do we need a constant? */ - co_r[2] -= 0.05f*shb->bias; - - return 1; -} - -/* storage of shadow results, solid osa and transp case */ -static void isb_add_shadfac(ISBShadfacA **isbsapp, MemArena *mem, int obi, int facenr, short shadfac, short samples) -{ - ISBShadfacA *new; - float shadfacf; - - /* in osa case, the samples were filled in with factor 1.0/R.osa. if fewer samples we have to correct */ - if (R.osa) - shadfacf= ((float)shadfac*R.osa)/(4096.0f*samples); - else - shadfacf= ((float)shadfac)/(4096.0f); - - new= BLI_memarena_alloc(mem, sizeof(ISBShadfacA)); - new->obi= obi; - new->facenr= facenr & ~RE_QUAD_OFFS; - new->shadfac= shadfacf; - if (*isbsapp) - new->next= (*isbsapp); - else - new->next= NULL; - - *isbsapp= new; -} - -/* adding samples, solid case */ -static int isb_add_samples(RenderPart *pa, ISBBranch *root, MemArena *memarena, ISBSample **samplebuf) -{ - int xi, yi, *xcos, *ycos; - int sample, bsp_err= 0; - - /* bsp split doesn't like to handle regular sequences */ - xcos= MEM_mallocN(pa->rectx*sizeof(int), "xcos"); - ycos= MEM_mallocN(pa->recty*sizeof(int), "ycos"); - for (xi=0; xi<pa->rectx; xi++) - xcos[xi]= xi; - for (yi=0; yi<pa->recty; yi++) - ycos[yi]= yi; - BLI_array_randomize(xcos, sizeof(int), pa->rectx, 12345); - BLI_array_randomize(ycos, sizeof(int), pa->recty, 54321); - - for (sample=0; sample<(R.osa?R.osa:1); sample++) { - ISBSample *samp= samplebuf[sample], *samp1; - - for (yi=0; yi<pa->recty; yi++) { - int y= ycos[yi]; - for (xi=0; xi<pa->rectx; xi++) { - int x= xcos[xi]; - samp1= samp + y*pa->rectx + x; - if (samp1->facenr) - bsp_err |= isb_bsp_insert(root, memarena, samp1); - } - if (bsp_err) break; - } - } - - MEM_freeN(xcos); - MEM_freeN(ycos); - - return bsp_err; -} - -/* solid version */ -/* lar->shb, pa->rectz and pa->rectp should exist */ -static void isb_make_buffer(RenderPart *pa, LampRen *lar) -{ - ShadBuf *shb= lar->shb; - ISBData *isbdata; - ISBSample *samp, *samplebuf[16]; /* should be RE_MAX_OSA */ - ISBBranch root; - MemArena *memarena; - intptr_t *rd; - int *recto, *rectp, x, y, sindex, sample, bsp_err=0; - - /* storage for shadow, per thread */ - isbdata= shb->isb_result[pa->thread]; - - /* to map the shi->xs and ys coordinate */ - isbdata->minx= pa->disprect.xmin; - isbdata->miny= pa->disprect.ymin; - isbdata->rectx= pa->rectx; - isbdata->recty= pa->recty; - - /* branches are added using memarena (32k branches) */ - memarena = BLI_memarena_new(0x8000 * sizeof(ISBBranch), "isb arena"); - BLI_memarena_use_calloc(memarena); - - /* samplebuf is in camera view space (pixels) */ - for (sample=0; sample<(R.osa?R.osa:1); sample++) - samplebuf[sample]= MEM_callocN(sizeof(ISBSample)*pa->rectx*pa->recty, "isb samplebuf"); - - /* for end result, ISBSamples point to this in non OSA case, otherwise to pixstruct->shadfac */ - if (R.osa==0) - isbdata->shadfacs= MEM_callocN(pa->rectx*pa->recty*sizeof(short), "isb shadfacs"); - - /* setup bsp root */ - memset(&root, 0, sizeof(ISBBranch)); - root.box.xmin = (float)shb->size; - root.box.ymin = (float)shb->size; - - /* create the sample buffers */ - for (sindex=0, y=0; y<pa->recty; y++) { - for (x=0; x<pa->rectx; x++, sindex++) { - - /* this makes it a long function, but splitting it out would mean 10+ arguments */ - /* first check OSA case */ - if (R.osa) { - rd= pa->rectdaps + sindex; - if (*rd) { - float xs= (float)(x + pa->disprect.xmin); - float ys= (float)(y + pa->disprect.ymin); - - for (sample=0; sample<R.osa; sample++) { - PixStr *ps= (PixStr *)(*rd); - int mask= (1<<sample); - - while (ps) { - if (ps->mask & mask) - break; - ps= ps->next; - } - if (ps && ps->facenr>0) { - ObjectInstanceRen *obi= &R.objectinstance[ps->obi]; - ObjectRen *obr= obi->obr; - VlakRen *vlr= RE_findOrAddVlak(obr, (ps->facenr-1) & RE_QUAD_MASK); - - samp= samplebuf[sample] + sindex; - /* convert image plane pixel location to lamp buffer space */ - if (viewpixel_to_lampbuf(shb, obi, vlr, xs + R.jit[sample][0], ys + R.jit[sample][1], samp->zco)) { - samp->obi= ps->obi; - samp->facenr= ps->facenr & ~RE_QUAD_OFFS; - ps->shadfac= 0; - samp->shadfac= &ps->shadfac; - bound_rectf((rctf *)&root.box, samp->zco); - } - } - } - } - } - else { - rectp= pa->rectp + sindex; - recto= pa->recto + sindex; - if (*rectp>0) { - ObjectInstanceRen *obi= &R.objectinstance[*recto]; - ObjectRen *obr= obi->obr; - VlakRen *vlr= RE_findOrAddVlak(obr, (*rectp-1) & RE_QUAD_MASK); - float xs= (float)(x + pa->disprect.xmin); - float ys= (float)(y + pa->disprect.ymin); - - samp= samplebuf[0] + sindex; - /* convert image plane pixel location to lamp buffer space */ - if (viewpixel_to_lampbuf(shb, obi, vlr, xs, ys, samp->zco)) { - samp->obi= *recto; - samp->facenr= *rectp & ~RE_QUAD_OFFS; - samp->shadfac= isbdata->shadfacs + sindex; - bound_rectf((rctf *)&root.box, samp->zco); - } - } - } - } - } - - /* simple method to see if we have samples */ - if (root.box.xmin != (float)shb->size) { - /* now create a regular split, root.box has the initial bounding box of all pixels */ - /* split bsp 8 levels deep, in regular grid (16 x 16) */ - isb_bsp_split_init(&root, memarena, 8); - - /* insert all samples in BSP now */ - bsp_err= isb_add_samples(pa, &root, memarena, samplebuf); - - if (bsp_err==0) { - /* go over all faces and fill in shadow values */ - - isb_bsp_fillfaces(&R, lar, &root); /* shb->persmat should have been calculated */ - - /* copy shadow samples to persistent buffer, reduce memory overhead */ - if (R.osa) { - ISBShadfacA **isbsa= isbdata->shadfaca= MEM_callocN(pa->rectx*pa->recty*sizeof(void *), "isb shadfacs"); - - isbdata->memarena = BLI_memarena_new(0x8000 * sizeof(ISBSampleA), "isb arena"); - BLI_memarena_use_calloc(isbdata->memarena); - - for (rd= pa->rectdaps, x=pa->rectx*pa->recty; x>0; x--, rd++, isbsa++) { - - if (*rd) { - PixStr *ps= (PixStr *)(*rd); - while (ps) { - if (ps->shadfac) - isb_add_shadfac(isbsa, isbdata->memarena, ps->obi, ps->facenr, ps->shadfac, count_mask(ps->mask)); - ps= ps->next; - } - } - } - } - } - } - else { - if (isbdata->shadfacs) { - MEM_freeN(isbdata->shadfacs); - isbdata->shadfacs= NULL; - } - } - - /* free BSP */ - BLI_memarena_free(memarena); - - /* free samples */ - for (x=0; x<(R.osa?R.osa:1); x++) - MEM_freeN(samplebuf[x]); - - if (bsp_err) printf("error in filling bsp\n"); -} - -/* add sample to buffer, isbsa is the root sample in a buffer */ -static ISBSampleA *isb_alloc_sample_transp(ISBSampleA **isbsa, MemArena *mem) -{ - ISBSampleA *new; - - new= BLI_memarena_alloc(mem, sizeof(ISBSampleA)); - if (*isbsa) - new->next= (*isbsa); - else - new->next= NULL; - - *isbsa= new; - return new; -} - -/* adding samples in BSP, transparent case */ -static int isb_add_samples_transp(RenderPart *pa, ISBBranch *root, MemArena *memarena, ISBSampleA ***samplebuf) -{ - int xi, yi, *xcos, *ycos; - int sample, bsp_err= 0; - - /* bsp split doesn't like to handle regular sequences */ - xcos= MEM_mallocN(pa->rectx*sizeof(int), "xcos"); - ycos= MEM_mallocN(pa->recty*sizeof(int), "ycos"); - for (xi=0; xi<pa->rectx; xi++) - xcos[xi]= xi; - for (yi=0; yi<pa->recty; yi++) - ycos[yi]= yi; - BLI_array_randomize(xcos, sizeof(int), pa->rectx, 12345); - BLI_array_randomize(ycos, sizeof(int), pa->recty, 54321); - - for (sample=0; sample<(R.osa?R.osa:1); sample++) { - ISBSampleA **samp= samplebuf[sample], *samp1; - - for (yi=0; yi<pa->recty; yi++) { - int y= ycos[yi]; - for (xi=0; xi<pa->rectx; xi++) { - int x= xcos[xi]; - - samp1= *(samp + y*pa->rectx + x); - while (samp1) { - bsp_err |= isb_bsp_insert(root, memarena, (ISBSample *)samp1); - samp1= samp1->next; - } - } - if (bsp_err) break; - } - } - - MEM_freeN(xcos); - MEM_freeN(ycos); - - return bsp_err; -} - - -/* Ztransp version */ -/* lar->shb, pa->rectz and pa->rectp should exist */ -static void isb_make_buffer_transp(RenderPart *pa, APixstr *apixbuf, LampRen *lar) -{ - ShadBuf *shb= lar->shb; - ISBData *isbdata; - ISBSampleA *samp, **samplebuf[16]; /* MAX_OSA */ - ISBBranch root; - MemArena *memarena; - APixstr *ap; - int x, y, sindex, sample, bsp_err=0; - - /* storage for shadow, per thread */ - isbdata= shb->isb_result[pa->thread]; - - /* to map the shi->xs and ys coordinate */ - isbdata->minx= pa->disprect.xmin; - isbdata->miny= pa->disprect.ymin; - isbdata->rectx= pa->rectx; - isbdata->recty= pa->recty; - - /* branches are added using memarena (32k branches) */ - memarena = BLI_memarena_new(0x8000 * sizeof(ISBBranch), "isb arena"); - BLI_memarena_use_calloc(memarena); - - /* samplebuf is in camera view space (pixels) */ - for (sample=0; sample<(R.osa?R.osa:1); sample++) - samplebuf[sample]= MEM_callocN(sizeof(void *)*pa->rectx*pa->recty, "isb alpha samplebuf"); - - /* setup bsp root */ - memset(&root, 0, sizeof(ISBBranch)); - root.box.xmin = (float)shb->size; - root.box.ymin = (float)shb->size; - - /* create the sample buffers */ - for (ap= apixbuf, sindex=0, y=0; y<pa->recty; y++) { - for (x=0; x<pa->rectx; x++, sindex++, ap++) { - - if (ap->p[0]) { - APixstr *apn; - float xs= (float)(x + pa->disprect.xmin); - float ys= (float)(y + pa->disprect.ymin); - - for (apn=ap; apn; apn= apn->next) { - int a; - for (a=0; a<4; a++) { - if (apn->p[a]) { - ObjectInstanceRen *obi= &R.objectinstance[apn->obi[a]]; - ObjectRen *obr= obi->obr; - VlakRen *vlr= RE_findOrAddVlak(obr, (apn->p[a]-1) & RE_QUAD_MASK); - float zco[3]; - - /* here we store shadfac, easier to create the end storage buffer. needs zero'ed, multiple shadowbufs use it */ - apn->shadfac[a]= 0; - - if (R.osa) { - for (sample=0; sample<R.osa; sample++) { - int mask= (1<<sample); - - if (apn->mask[a] & mask) { - - /* convert image plane pixel location to lamp buffer space */ - if (viewpixel_to_lampbuf(shb, obi, vlr, xs + R.jit[sample][0], ys + R.jit[sample][1], zco)) { - samp= isb_alloc_sample_transp(samplebuf[sample] + sindex, memarena); - samp->obi= apn->obi[a]; - samp->facenr= apn->p[a] & ~RE_QUAD_OFFS; - samp->shadfac= &apn->shadfac[a]; - - copy_v3_v3(samp->zco, zco); - bound_rectf((rctf *)&root.box, samp->zco); - } - } - } - } - else { - - /* convert image plane pixel location to lamp buffer space */ - if (viewpixel_to_lampbuf(shb, obi, vlr, xs, ys, zco)) { - - samp= isb_alloc_sample_transp(samplebuf[0] + sindex, memarena); - samp->obi= apn->obi[a]; - samp->facenr= apn->p[a] & ~RE_QUAD_OFFS; - samp->shadfac= &apn->shadfac[a]; - - copy_v3_v3(samp->zco, zco); - bound_rectf((rctf *)&root.box, samp->zco); - } - } - } - } - } - } - } - } - - /* simple method to see if we have samples */ - if (root.box.xmin != (float)shb->size) { - /* now create a regular split, root.box has the initial bounding box of all pixels */ - /* split bsp 8 levels deep, in regular grid (16 x 16) */ - isb_bsp_split_init(&root, memarena, 8); - - /* insert all samples in BSP now */ - bsp_err= isb_add_samples_transp(pa, &root, memarena, samplebuf); - - if (bsp_err==0) { - ISBShadfacA **isbsa; - - /* go over all faces and fill in shadow values */ - isb_bsp_fillfaces(&R, lar, &root); /* shb->persmat should have been calculated */ - - /* copy shadow samples to persistent buffer, reduce memory overhead */ - isbsa= isbdata->shadfaca= MEM_callocN(pa->rectx*pa->recty*sizeof(void *), "isb shadfacs"); - - isbdata->memarena = BLI_memarena_new(0x8000 * sizeof(ISBSampleA), "isb arena"); - - for (ap= apixbuf, x=pa->rectx*pa->recty; x>0; x--, ap++, isbsa++) { - - if (ap->p[0]) { - APixstr *apn; - for (apn=ap; apn; apn= apn->next) { - int a; - for (a=0; a<4; a++) { - if (apn->p[a] && apn->shadfac[a]) { - if (R.osa) - isb_add_shadfac(isbsa, isbdata->memarena, apn->obi[a], apn->p[a], apn->shadfac[a], count_mask(apn->mask[a])); - else - isb_add_shadfac(isbsa, isbdata->memarena, apn->obi[a], apn->p[a], apn->shadfac[a], 0); - } - } - } - } - } - } - } - - /* free BSP */ - BLI_memarena_free(memarena); - - /* free samples */ - for (x=0; x<(R.osa?R.osa:1); x++) - MEM_freeN(samplebuf[x]); - - if (bsp_err) printf("error in filling bsp\n"); -} - - - -/* exported */ - -/* returns amount of light (1.0 = no shadow) */ -/* note, shadepixel() rounds the coordinate, not the real sample info */ -float ISB_getshadow(ShadeInput *shi, ShadBuf *shb) -{ - /* if raytracing, we can't accept irregular shadow */ - if (shi->depth==0) { - ISBData *isbdata= shb->isb_result[shi->thread]; - - if (isbdata) { - if (isbdata->shadfacs || isbdata->shadfaca) { - int x= shi->xs - isbdata->minx; - - if (x >= 0 && x < isbdata->rectx) { - int y= shi->ys - isbdata->miny; - - if (y >= 0 && y < isbdata->recty) { - if (isbdata->shadfacs) { - const short *sp= isbdata->shadfacs + y*isbdata->rectx + x; - return *sp>=4096?0.0f:1.0f - ((float)*sp)/4096.0f; - } - else { - int sindex= y*isbdata->rectx + x; - int obi= shi->obi - R.objectinstance; - ISBShadfacA *isbsa= *(isbdata->shadfaca + sindex); - - while (isbsa) { - if (isbsa->facenr==shi->facenr+1 && isbsa->obi==obi) - return isbsa->shadfac>=1.0f?0.0f:1.0f - isbsa->shadfac; - isbsa= isbsa->next; - } - } - } - } - } - } - } - return 1.0f; -} - -/* part is supposed to be solid zbuffered (apixbuf==NULL) or transparent zbuffered */ -void ISB_create(RenderPart *pa, APixstr *apixbuf) -{ - GroupObject *go; - - /* go over all lamps, and make the irregular buffers */ - for (go=R.lights.first; go; go= go->next) { - LampRen *lar= go->lampren; - - if (lar->type==LA_SPOT && lar->shb && lar->buftype==LA_SHADBUF_IRREGULAR) { - - /* create storage for shadow, per thread */ - lar->shb->isb_result[pa->thread]= MEM_callocN(sizeof(ISBData), "isb data"); - - if (apixbuf) - isb_make_buffer_transp(pa, apixbuf, lar); - else - isb_make_buffer(pa, lar); - } - } -} - - -/* end of part rendering, free stored shadow data for this thread from all lamps */ -void ISB_free(RenderPart *pa) -{ - GroupObject *go; - - /* go over all lamps, and free the irregular buffers */ - for (go=R.lights.first; go; go= go->next) { - LampRen *lar= go->lampren; - - if (lar->type==LA_SPOT && lar->shb && lar->buftype==LA_SHADBUF_IRREGULAR) { - ISBData *isbdata= lar->shb->isb_result[pa->thread]; - - if (isbdata) { - if (isbdata->shadfacs) - MEM_freeN(isbdata->shadfacs); - if (isbdata->shadfaca) - MEM_freeN(isbdata->shadfaca); - - if (isbdata->memarena) - BLI_memarena_free(isbdata->memarena); - - MEM_freeN(isbdata); - lar->shb->isb_result[pa->thread]= NULL; - } - } - } -} diff --git a/source/blender/render/intern/source/shadeinput.c b/source/blender/render/intern/source/shadeinput.c deleted file mode 100644 index d79749871c3..00000000000 --- a/source/blender/render/intern/source/shadeinput.c +++ /dev/null @@ -1,1490 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2006 Blender Foundation - * All rights reserved. - * - * Contributors: Hos, Robert Wenzlaff. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/render/intern/source/shadeinput.c - * \ingroup render - */ - - -#include <stdio.h> -#include <math.h> -#include <string.h> - - -#include "BLI_math.h" -#include "BLI_utildefines.h" - -#include "DNA_lamp_types.h" -#include "DNA_meshdata_types.h" -#include "DNA_material_types.h" -#include "DNA_particle_types.h" - -#include "BKE_scene.h" - -#include "BKE_node.h" - -/* local include */ -#include "raycounter.h" -#include "render_types.h" -#include "renderdatabase.h" -#include "rendercore.h" -#include "shading.h" -#include "strand.h" -#include "texture.h" -#include "volumetric.h" -#include "zbuf.h" - -/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -/* defined in pipeline.c, is hardcopy of active dynamic allocated Render */ -/* only to be used here in this file, it's for speed */ -extern struct Render R; -/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ - -/* Shade Sample order: - * - * - shade_samples_fill_with_ps() - * - for each sample - * - shade_input_set_triangle() <- if prev sample-face is same, use shade_input_copy_triangle() - * - if vlr - * - shade_input_set_viewco() <- not for ray or bake - * - shade_input_set_uv() <- not for ray or bake - * - shade_input_set_normals() - * - shade_samples() - * - if AO - * - shade_samples_do_AO() - * - if shading happens - * - for each sample - * - shade_input_set_shade_texco() - * - shade_samples_do_shade() - * - OSA: distribute sample result with filter masking - * - */ - -/* initialize material variables in shadeinput, - * doing inverse gamma correction where applicable */ -void shade_input_init_material(ShadeInput *shi) -{ - /* note, keep this synced with render_types.h */ - memcpy(&shi->r, &shi->mat->r, 23 * sizeof(float)); - shi->har = shi->mat->har; -} - -/* also used as callback for nodes */ -/* delivers a fully filled in ShadeResult, for all passes */ -void shade_material_loop(ShadeInput *shi, ShadeResult *shr) -{ - - shade_lamp_loop(shi, shr); /* clears shr */ - - if (shi->translucency != 0.0f) { - ShadeResult shr_t; - float fac = shi->translucency; - - shade_input_init_material(shi); - negate_v3_v3(shi->vn, shi->vno); - negate_v3(shi->facenor); - shi->depth++; /* hack to get real shadow now */ - shade_lamp_loop(shi, &shr_t); - shi->depth--; - - /* a couple of passes */ - madd_v3_v3fl(shr->combined, shr_t.combined, fac); - if (shi->passflag & SCE_PASS_SPEC) - madd_v3_v3fl(shr->spec, shr_t.spec, fac); - if (shi->passflag & SCE_PASS_DIFFUSE) { - madd_v3_v3fl(shr->diff, shr_t.diff, fac); - madd_v3_v3fl(shr->diffshad, shr_t.diffshad, fac); - } - if (shi->passflag & SCE_PASS_SHADOW) - madd_v3_v3fl(shr->shad, shr_t.shad, fac); - - negate_v3(shi->vn); - negate_v3(shi->facenor); - } - - /* depth >= 1 when ray-shading */ - if (shi->depth == 0 || shi->volume_depth > 0) { - if (R.r.mode & R_RAYTRACE) { - if (shi->ray_mirror != 0.0f || ((shi->mode & MA_TRANSP) && (shi->mode & MA_RAYTRANSP) && shr->alpha != 1.0f)) { - /* ray trace works on combined, but gives pass info */ - ray_trace(shi, shr); - } - } - /* disable adding of sky for raytransp */ - if ((shi->mode & MA_TRANSP) && (shi->mode & MA_RAYTRANSP)) - if ((shi->layflag & SCE_LAY_SKY) && (R.r.alphamode == R_ADDSKY)) - shr->alpha = 1.0f; - } - - if (R.r.mode & R_RAYTRACE) { - if (R.render_volumes_inside.first) - shade_volume_inside(shi, shr); - } -} - - -/* do a shade, finish up some passes, apply mist */ -void shade_input_do_shade(ShadeInput *shi, ShadeResult *shr) -{ - bool compat = false; - float alpha; - - /* ------ main shading loop -------- */ -#ifdef RE_RAYCOUNTER - memset(&shi->raycounter, 0, sizeof(shi->raycounter)); -#endif - - if (shi->mat->nodetree && shi->mat->use_nodes) { - compat = ntreeShaderExecTree(shi->mat->nodetree, shi, shr); - } - - /* also run this when node shaders fail, due to incompatible shader nodes */ - if (compat == false) { - /* copy all relevant material vars, note, keep this synced with render_types.h */ - shade_input_init_material(shi); - - if (shi->mat->material_type == MA_TYPE_VOLUME) { - if (R.r.mode & R_RAYTRACE) { - shade_volume_outside(shi, shr); - } - } - else { /* MA_TYPE_SURFACE, MA_TYPE_WIRE */ - shade_material_loop(shi, shr); - } - } - - /* copy additional passes */ - if (shi->passflag & (SCE_PASS_VECTOR | SCE_PASS_NORMAL)) { - copy_v4_v4(shr->winspeed, shi->winspeed); - copy_v3_v3(shr->nor, shi->vn); - } - - /* MIST */ - if ((shi->passflag & SCE_PASS_MIST) || ((R.wrld.mode & WO_MIST) && (shi->mat->mode & MA_NOMIST) == 0)) { - if (R.r.mode & R_ORTHO) - shr->mist = mistfactor(-shi->co[2], shi->co); - else - shr->mist = mistfactor(len_v3(shi->co), shi->co); - } - else shr->mist = 0.0f; - - if ((R.wrld.mode & WO_MIST) && (shi->mat->mode & MA_NOMIST) == 0) { - alpha = shr->mist; - } - else alpha = 1.0f; - - /* add mist and premul color */ - if (shr->alpha != 1.0f || alpha != 1.0f) { - float fac = alpha * (shr->alpha); - shr->combined[3] = fac; - - if (shi->mat->material_type != MA_TYPE_VOLUME) - mul_v3_fl(shr->combined, fac); - } - else - shr->combined[3] = 1.0f; - - /* add z */ - shr->z = -shi->co[2]; - - /* RAYHITS */ -#if 0 - if (1 || shi->passflag & SCE_PASS_RAYHITS) { - shr->rayhits[0] = (float)shi->raycounter.faces.test; - shr->rayhits[1] = (float)shi->raycounter.bb.hit; - shr->rayhits[2] = 0.0; - shr->rayhits[3] = 1.0; - } -#endif - - RE_RC_MERGE(&re_rc_counter[shi->thread], &shi->raycounter); -} - -/* **************************************************************************** */ -/* ShadeInput */ -/* **************************************************************************** */ - - -void vlr_set_uv_indices(VlakRen *vlr, int *i1, int *i2, int *i3) -{ - /* to prevent storing new tfaces or vcols, we check a split runtime */ - /* 4---3 4---3 */ - /* |\ 1| or |1 /| */ - /* |0\ | |/ 0| */ - /* 1---2 1---2 0 = orig face, 1 = new face */ - - /* Update vert nums to point to correct verts of original face */ - if (vlr->flag & R_DIVIDE_24) { - if (vlr->flag & R_FACE_SPLIT) { - (*i1)++; (*i2)++; (*i3)++; - } - else { - (*i3)++; - } - } - else if (vlr->flag & R_FACE_SPLIT) { - (*i2)++; (*i3)++; - } -} - -/* copy data from face to ShadeInput, general case */ -/* indices 0 1 2 3 only */ -void shade_input_set_triangle_i(ShadeInput *shi, ObjectInstanceRen *obi, VlakRen *vlr, short i1, short i2, short i3) -{ - VertRen **vpp = &vlr->v1; - - shi->vlr = vlr; - shi->obi = obi; - shi->obr = obi->obr; - - shi->v1 = vpp[i1]; - shi->v2 = vpp[i2]; - shi->v3 = vpp[i3]; - - shi->i1 = i1; - shi->i2 = i2; - shi->i3 = i3; - - /* note, shi->mat is set in node shaders */ - shi->mat = shi->mat_override ? shi->mat_override : vlr->mat; - - shi->osatex = (shi->mat->texco & TEXCO_OSA); - shi->mode = shi->mat->mode_l; /* or-ed result for all nodes */ - shi->mode2 = shi->mat->mode2_l; - - /* facenormal copy, can get flipped */ - shi->flippednor = 0; - RE_vlakren_get_normal(&R, obi, vlr, shi->facenor); - - /* calculate vertexnormals */ - if (vlr->flag & R_SMOOTH) { - copy_v3_v3(shi->n1, shi->v1->n); - copy_v3_v3(shi->n2, shi->v2->n); - copy_v3_v3(shi->n3, shi->v3->n); - - if (obi->flag & R_TRANSFORMED) { - mul_m3_v3(obi->nmat, shi->n1); normalize_v3(shi->n1); - mul_m3_v3(obi->nmat, shi->n2); normalize_v3(shi->n2); - mul_m3_v3(obi->nmat, shi->n3); normalize_v3(shi->n3); - } - } -} - -/* copy data from face to ShadeInput, scanline case */ -void shade_input_set_triangle(ShadeInput *shi, int obi, int facenr, int UNUSED(normal_flip)) -{ - if (facenr > 0) { - shi->obi = &R.objectinstance[obi]; - shi->obr = shi->obi->obr; - shi->facenr = (facenr - 1) & RE_QUAD_MASK; - if (shi->facenr < shi->obr->totvlak) { - VlakRen *vlr = RE_findOrAddVlak(shi->obr, shi->facenr); - - if (facenr & RE_QUAD_OFFS) - shade_input_set_triangle_i(shi, shi->obi, vlr, 0, 2, 3); - else - shade_input_set_triangle_i(shi, shi->obi, vlr, 0, 1, 2); - } - else - shi->vlr = NULL; /* general signal we got sky */ - } - else - shi->vlr = NULL; /* general signal we got sky */ -} - -/* full osa case: copy static info */ -void shade_input_copy_triangle(ShadeInput *shi, ShadeInput *from) -{ - /* not so nice, but works... warning is in RE_shader_ext.h */ - memcpy(shi, from, sizeof(struct ShadeInputCopy)); -} - -/* copy data from strand to shadeinput */ -void shade_input_set_strand(ShadeInput *shi, StrandRen *strand, StrandPoint *spoint) -{ - /* note, shi->mat is set in node shaders */ - shi->mat = shi->mat_override ? shi->mat_override : strand->buffer->ma; - - shi->osatex = (shi->mat->texco & TEXCO_OSA); - shi->mode = shi->mat->mode_l; /* or-ed result for all nodes */ - - /* shade_input_set_viewco equivalent */ - copy_v3_v3(shi->co, spoint->co); - copy_v3_v3(shi->view, shi->co); - normalize_v3(shi->view); - - shi->xs = (int)spoint->x; - shi->ys = (int)spoint->y; - - if (shi->osatex || (R.r.mode & R_SHADOW)) { - copy_v3_v3(shi->dxco, spoint->dtco); - copy_v3_v3(shi->dyco, spoint->dsco); - } - - /* dxview, dyview, not supported */ - - /* facenormal, simply viewco flipped */ - copy_v3_v3(shi->facenor, spoint->nor); - - /* shade_input_set_normals equivalent */ - if (shi->mat->mode & MA_TANGENT_STR) { - copy_v3_v3(shi->vn, spoint->tan); - } - else { - float cross[3]; - - cross_v3_v3v3(cross, spoint->co, spoint->tan); - cross_v3_v3v3(shi->vn, cross, spoint->tan); - normalize_v3(shi->vn); - - if (dot_v3v3(shi->vn, shi->view) < 0.0f) - negate_v3(shi->vn); - } - - copy_v3_v3(shi->vno, shi->vn); -} - -void shade_input_set_strand_texco(ShadeInput *shi, StrandRen *strand, StrandVert *svert, StrandPoint *spoint) -{ - StrandBuffer *strandbuf = strand->buffer; - ObjectRen *obr = strandbuf->obr; - StrandVert *sv; - int mode = shi->mode; /* or-ed result for all nodes */ - short texco = shi->mat->texco; - - if ((shi->mat->texco & TEXCO_REFL)) { - /* shi->dxview, shi->dyview, not supported */ - } - - if (shi->osatex && (texco & (TEXCO_NORM | TEXCO_REFL))) { - /* not supported */ - } - - if (mode & (MA_TANGENT_V | MA_NORMAP_TANG)) { - copy_v3_v3(shi->tang, spoint->tan); - copy_v3_v3(shi->nmaptang, spoint->tan); - } - - if (mode & MA_STR_SURFDIFF) { - const float *surfnor = RE_strandren_get_surfnor(obr, strand, 0); - - if (surfnor) - copy_v3_v3(shi->surfnor, surfnor); - else - copy_v3_v3(shi->surfnor, shi->vn); - - if (shi->mat->strand_surfnor > 0.0f) { - shi->surfdist = 0.0f; - for (sv = strand->vert; sv != svert; sv++) - shi->surfdist += len_v3v3(sv->co, (sv + 1)->co); - shi->surfdist += spoint->t * len_v3v3(sv->co, (sv + 1)->co); - } - } - - if (R.r.mode & R_SPEED) { - const float *speed; - - speed = RE_strandren_get_winspeed(shi->obi, strand, 0); - if (speed) - copy_v4_v4(shi->winspeed, speed); - else - shi->winspeed[0] = shi->winspeed[1] = shi->winspeed[2] = shi->winspeed[3] = 0.0f; - } - - /* shade_input_set_shade_texco equivalent */ - if (texco & NEED_UV) { - if (texco & TEXCO_ORCO) { - copy_v3_v3(shi->lo, strand->orco); - /* no shi->osatex, orco derivatives are zero */ - } - - if (texco & TEXCO_GLOB) { - mul_v3_m4v3(shi->gl, R.viewinv, shi->co); - - if (shi->osatex) { - mul_v3_mat3_m4v3(shi->dxgl, R.viewinv, shi->dxco); - mul_v3_mat3_m4v3(shi->dygl, R.viewinv, shi->dyco); - } - } - - if (texco & TEXCO_STRAND) { - shi->strandco = spoint->strandco; - - if (shi->osatex) { - shi->dxstrand = spoint->dtstrandco; - shi->dystrand = 0.0f; - } - } - - if ((texco & TEXCO_UV) || (mode & (MA_VERTEXCOL | MA_VERTEXCOLP | MA_FACETEXTURE))) { - MCol *mcol; - const float *uv; - char *name; - int i; - - shi->totuv = 0; - shi->totcol = 0; - shi->actuv = obr->actmtface; - shi->actcol = obr->actmcol; - - if (mode & (MA_VERTEXCOL | MA_VERTEXCOLP)) { - for (i = 0; (mcol = RE_strandren_get_mcol(obr, strand, i, &name, 0)); i++) { - ShadeInputCol *scol = &shi->col[i]; - const char *cp = (char *)mcol; - - shi->totcol++; - scol->name = name; - - scol->col[0] = cp[3] / 255.0f; - scol->col[1] = cp[2] / 255.0f; - scol->col[2] = cp[1] / 255.0f; - scol->col[3] = cp[0] / 255.0f; - } - - if (shi->totcol) { - shi->vcol[0] = shi->col[shi->actcol].col[0]; - shi->vcol[1] = shi->col[shi->actcol].col[1]; - shi->vcol[2] = shi->col[shi->actcol].col[2]; - shi->vcol[3] = shi->col[shi->actcol].col[3]; - } - else { - shi->vcol[0] = 0.0f; - shi->vcol[1] = 0.0f; - shi->vcol[2] = 0.0f; - shi->vcol[3] = 0.0f; - } - } - - for (i = 0; (uv = RE_strandren_get_uv(obr, strand, i, &name, 0)); i++) { - ShadeInputUV *suv = &shi->uv[i]; - - shi->totuv++; - suv->name = name; - - if (strandbuf->overrideuv == i) { - suv->uv[0] = -1.0f; - suv->uv[1] = spoint->strandco; - suv->uv[2] = 0.0f; - } - else { - suv->uv[0] = -1.0f + 2.0f * uv[0]; - suv->uv[1] = -1.0f + 2.0f * uv[1]; - suv->uv[2] = 0.0f; /* texture.c assumes there are 3 coords */ - } - - if (shi->osatex) { - suv->dxuv[0] = 0.0f; - suv->dxuv[1] = 0.0f; - suv->dyuv[0] = 0.0f; - suv->dyuv[1] = 0.0f; - } - - if ((mode & MA_FACETEXTURE) && i == obr->actmtface) { - if ((mode & (MA_VERTEXCOL | MA_VERTEXCOLP)) == 0) { - shi->vcol[0] = 1.0f; - shi->vcol[1] = 1.0f; - shi->vcol[2] = 1.0f; - shi->vcol[3] = 1.0f; - } - } - } - - if (shi->totuv == 0) { - ShadeInputUV *suv = &shi->uv[0]; - - suv->uv[0] = 0.0f; - suv->uv[1] = spoint->strandco; - suv->uv[2] = 0.0f; /* texture.c assumes there are 3 coords */ - - if (mode & MA_FACETEXTURE) { - /* no tface? set at 1.0f */ - shi->vcol[0] = 1.0f; - shi->vcol[1] = 1.0f; - shi->vcol[2] = 1.0f; - shi->vcol[3] = 1.0f; - } - } - - } - - if (texco & TEXCO_NORM) { - shi->orn[0] = -shi->vn[0]; - shi->orn[1] = -shi->vn[1]; - shi->orn[2] = -shi->vn[2]; - } - - if (texco & TEXCO_STRESS) { - /* not supported */ - } - - if (texco & TEXCO_TANGENT) { - if ((mode & MA_TANGENT_V) == 0) { - /* just prevent surprises */ - shi->tang[0] = shi->tang[1] = shi->tang[2] = 0.0f; - shi->nmaptang[0] = shi->nmaptang[1] = shi->nmaptang[2] = 0.0f; - } - } - } - - /* this only avalailable for scanline renders */ - if (shi->depth == 0) { - if (texco & TEXCO_WINDOW) { - shi->winco[0] = -1.0f + 2.0f * spoint->x / (float)R.winx; - shi->winco[1] = -1.0f + 2.0f * spoint->y / (float)R.winy; - shi->winco[2] = 0.0f; - - /* not supported */ - if (shi->osatex) { - shi->dxwin[0] = 0.0f; - shi->dywin[1] = 0.0f; - shi->dxwin[0] = 0.0f; - shi->dywin[1] = 0.0f; - } - } - } - - if (shi->do_manage) { - if (mode & (MA_VERTEXCOL | MA_VERTEXCOLP | MA_FACETEXTURE)) { - srgb_to_linearrgb_v3_v3(shi->vcol, shi->vcol); - } - } - -} - -/* from scanline pixel coordinates to 3d coordinates, requires set_triangle */ -void shade_input_calc_viewco(ShadeInput *shi, float x, float y, float z, float view[3], float dxyview[2], float co[3], float dxco[3], float dyco[3]) -{ - /* returns not normalized, so is in viewplane coords */ - calc_view_vector(view, x, y); - - if (shi->mat->material_type == MA_TYPE_WIRE) { - /* wire cannot use normal for calculating shi->co, so - * we reconstruct the coordinate less accurate */ - if (R.r.mode & R_ORTHO) - calc_renderco_ortho(co, x, y, z); - else - calc_renderco_zbuf(co, view, z); - } - else { - /* for non-wire, intersect with the triangle to get the exact coord */ - float fac, dface, v1[3]; - - copy_v3_v3(v1, shi->v1->co); - if (shi->obi->flag & R_TRANSFORMED) - mul_m4_v3(shi->obi->mat, v1); - - dface = dot_v3v3(v1, shi->facenor); - - /* ortho viewplane cannot intersect using view vector originating in (0,0,0) */ - if (R.r.mode & R_ORTHO) { - /* x and y 3d coordinate can be derived from pixel coord and winmat */ - float fx = 2.0f / (R.winx * R.winmat[0][0]); - float fy = 2.0f / (R.winy * R.winmat[1][1]); - - co[0] = (x - 0.5f * R.winx) * fx - R.winmat[3][0] / R.winmat[0][0]; - co[1] = (y - 0.5f * R.winy) * fy - R.winmat[3][1] / R.winmat[1][1]; - - /* using a*x + b*y + c*z = d equation, (a b c) is normal */ - if (shi->facenor[2] != 0.0f) - co[2] = (dface - shi->facenor[0] * co[0] - shi->facenor[1] * co[1]) / shi->facenor[2]; - else - co[2] = 0.0f; - - if (dxco && dyco) { - dxco[0] = fx; - dxco[1] = 0.0f; - if (shi->facenor[2] != 0.0f) - dxco[2] = -(shi->facenor[0] * fx) / shi->facenor[2]; - else - dxco[2] = 0.0f; - - dyco[0] = 0.0f; - dyco[1] = fy; - if (shi->facenor[2] != 0.0f) - dyco[2] = -(shi->facenor[1] * fy) / shi->facenor[2]; - else - dyco[2] = 0.0f; - - if (dxyview) { - fac = (co[2] != 0.0f) ? (1.0f / co[2]) : 0.0f; - dxyview[0] = -R.viewdx * fac; - dxyview[1] = -R.viewdy * fac; - } - } - } - else { - float div; - - div = dot_v3v3(shi->facenor, view); - if (div != 0.0f) fac = dface / div; - else fac = 0.0f; - - co[0] = fac * view[0]; - co[1] = fac * view[1]; - co[2] = fac * view[2]; - - /* pixel dx/dy for render coord */ - if (dxco && dyco) { - float u = dface / (div - R.viewdx * shi->facenor[0]); - float v = dface / (div - R.viewdy * shi->facenor[1]); - - dxco[0] = co[0] - (view[0] - R.viewdx) * u; - dxco[1] = co[1] - (view[1]) * u; - dxco[2] = co[2] - (view[2]) * u; - - dyco[0] = co[0] - (view[0]) * v; - dyco[1] = co[1] - (view[1] - R.viewdy) * v; - dyco[2] = co[2] - (view[2]) * v; - - if (dxyview) { - if (fac != 0.0f) fac = 1.0f / fac; - dxyview[0] = -R.viewdx * fac; - dxyview[1] = -R.viewdy * fac; - } - } - } - } - - /* set camera coords - for scanline, it's always 0.0,0.0,0.0 (render is in camera space) - * however for raytrace it can be different - the position of the last intersection */ - shi->camera_co[0] = shi->camera_co[1] = shi->camera_co[2] = 0.0f; - - /* cannot normalize earlier, code above needs it at viewplane level */ - normalize_v3(view); -} - -/* from scanline pixel coordinates to 3d coordinates, requires set_triangle */ -void shade_input_set_viewco(ShadeInput *shi, float x, float y, float xs, float ys, float z) -{ - float *dxyview = NULL, *dxco = NULL, *dyco = NULL; - - /* currently in use for dithering (soft shadow), node preview, irregular shad */ - shi->xs = (int)xs; - shi->ys = (int)ys; - - /* original scanline coordinate without jitter */ - shi->scanco[0] = x; - shi->scanco[1] = y; - shi->scanco[2] = z; - - /* check if we need derivatives */ - if (shi->osatex || (R.r.mode & R_SHADOW)) { - dxco = shi->dxco; - dyco = shi->dyco; - - if ((shi->mat->texco & TEXCO_REFL)) - dxyview = &shi->dxview; - } - - shade_input_calc_viewco(shi, xs, ys, z, shi->view, dxyview, shi->co, dxco, dyco); -} - -void barycentric_differentials_from_position( - const float co[3], const float v1[3], const float v2[3], const float v3[3], - const float dxco[3], const float dyco[3], const float facenor[3], const bool differentials, - float *u, float *v, float *dx_u, float *dx_v, float *dy_u, float *dy_v) -{ - /* find most stable axis to project */ - int axis1, axis2; - axis_dominant_v3(&axis1, &axis2, facenor); - - /* compute u,v and derivatives */ - float t00 = v3[axis1] - v1[axis1]; - float t01 = v3[axis2] - v1[axis2]; - float t10 = v3[axis1] - v2[axis1]; - float t11 = v3[axis2] - v2[axis2]; - - float detsh = (t00 * t11 - t10 * t01); - detsh = (detsh != 0.0f) ? 1.0f / detsh : 0.0f; - t00 *= detsh; t01 *= detsh; - t10 *= detsh; t11 *= detsh; - - *u = (v3[axis1] - co[axis1]) * t11 - (v3[axis2] - co[axis2]) * t10; - *v = (v3[axis2] - co[axis2]) * t00 - (v3[axis1] - co[axis1]) * t01; - if (differentials) { - *dx_u = dxco[axis1] * t11 - dxco[axis2] * t10; - *dx_v = dxco[axis2] * t00 - dxco[axis1] * t01; - *dy_u = dyco[axis1] * t11 - dyco[axis2] * t10; - *dy_v = dyco[axis2] * t00 - dyco[axis1] * t01; - } -} -/* calculate U and V, for scanline (silly render face u and v are in range -1 to 0) */ -void shade_input_set_uv(ShadeInput *shi) -{ - VlakRen *vlr = shi->vlr; - - if ((vlr->flag & R_SMOOTH) || (shi->mat->texco & NEED_UV) || (shi->passflag & SCE_PASS_UV)) { - float v1[3], v2[3], v3[3]; - - copy_v3_v3(v1, shi->v1->co); - copy_v3_v3(v2, shi->v2->co); - copy_v3_v3(v3, shi->v3->co); - - if (shi->obi->flag & R_TRANSFORMED) { - mul_m4_v3(shi->obi->mat, v1); - mul_m4_v3(shi->obi->mat, v2); - mul_m4_v3(shi->obi->mat, v3); - } - - /* exception case for wire render of edge */ - if (vlr->v2 == vlr->v3) { - float lend, lenc; - - lend = len_v3v3(v2, v1); - lenc = len_v3v3(shi->co, v1); - - if (lend == 0.0f) { - shi->u = shi->v = 0.0f; - } - else { - shi->u = -(1.0f - lenc / lend); - shi->v = 0.0f; - } - - if (shi->osatex) { - shi->dx_u = 0.0f; - shi->dx_v = 0.0f; - shi->dy_u = 0.0f; - shi->dy_v = 0.0f; - } - } - else { - barycentric_differentials_from_position( - shi->co, v1, v2, v3, shi->dxco, shi->dyco, shi->facenor, shi->osatex, - &shi->u, &shi->v, &shi->dx_u, &shi->dx_v, &shi->dy_u, &shi->dy_v); - - shi->u = -shi->u; - shi->v = -shi->v; - - /* u and v are in range -1 to 0, we allow a little bit extra but not too much, screws up speedvectors */ - CLAMP(shi->u, -2.0f, 1.0f); - CLAMP(shi->v, -2.0f, 1.0f); - } - } -} - -void shade_input_set_normals(ShadeInput *shi) -{ - float u = shi->u, v = shi->v; - float l = 1.0f + u + v; - - shi->flippednor = 0; - - /* test flip normals to viewing direction */ - if (!(shi->vlr->flag & R_TANGENT)) { - if (dot_v3v3(shi->facenor, shi->view) < 0.0f) { - negate_v3(shi->facenor); - shi->flippednor = 1; - } - } - - /* calculate vertexnormals */ - if (shi->vlr->flag & R_SMOOTH) { - float *n1 = shi->n1, *n2 = shi->n2, *n3 = shi->n3; - - if (shi->flippednor) { - negate_v3(n1); - negate_v3(n2); - negate_v3(n3); - } - - shi->vn[0] = l * n3[0] - u * n1[0] - v * n2[0]; - shi->vn[1] = l * n3[1] - u * n1[1] - v * n2[1]; - shi->vn[2] = l * n3[2] - u * n1[2] - v * n2[2]; - - /* use unnormalized normal (closer to games) */ - copy_v3_v3(shi->nmapnorm, shi->vn); - - normalize_v3(shi->vn); - } - else { - copy_v3_v3(shi->vn, shi->facenor); - copy_v3_v3(shi->nmapnorm, shi->vn); - } - - /* used in nodes */ - copy_v3_v3(shi->vno, shi->vn); - - /* flip normals to viewing direction */ - if (!(shi->vlr->flag & R_TANGENT)) - if (dot_v3v3(shi->facenor, shi->view) < 0.0f) - shade_input_flip_normals(shi); -} - -/* XXX shi->flippednor messes up otherwise */ -void shade_input_set_vertex_normals(ShadeInput *shi) -{ - float u = shi->u, v = shi->v; - float l = 1.0f + u + v; - - /* calculate vertexnormals */ - if (shi->vlr->flag & R_SMOOTH) { - const float *n1 = shi->n1, *n2 = shi->n2, *n3 = shi->n3; - - shi->vn[0] = l * n3[0] - u * n1[0] - v * n2[0]; - shi->vn[1] = l * n3[1] - u * n1[1] - v * n2[1]; - shi->vn[2] = l * n3[2] - u * n1[2] - v * n2[2]; - - /* use unnormalized normal (closer to games) */ - copy_v3_v3(shi->nmapnorm, shi->vn); - - normalize_v3(shi->vn); - } - else { - copy_v3_v3(shi->vn, shi->facenor); - copy_v3_v3(shi->nmapnorm, shi->vn); - } - - /* used in nodes */ - copy_v3_v3(shi->vno, shi->vn); -} - - -/* use by raytrace, sss, bake to flip into the right direction */ -void shade_input_flip_normals(ShadeInput *shi) -{ - negate_v3(shi->facenor); - negate_v3(shi->vn); - negate_v3(shi->vno); - negate_v3(shi->nmapnorm); - shi->flippednor = !shi->flippednor; -} - -void shade_input_set_shade_texco(ShadeInput *shi) -{ - ObjectInstanceRen *obi = shi->obi; - ObjectRen *obr = shi->obr; - VertRen *v1 = shi->v1, *v2 = shi->v2, *v3 = shi->v3; - float u = shi->u, v = shi->v; - float l = 1.0f + u + v, dl; - int mode = shi->mode; /* or-ed result for all nodes */ - int mode2 = shi->mode2; - short texco = shi->mat->texco; - const bool need_mikk_tangent = (mode & MA_NORMAP_TANG || R.flag & R_NEED_TANGENT); - const bool need_mikk_tangent_concrete = (mode2 & MA_TANGENT_CONCRETE) != 0; - - /* calculate dxno */ - if (shi->vlr->flag & R_SMOOTH) { - - if (shi->osatex && (texco & (TEXCO_NORM | TEXCO_REFL)) ) { - const float *n1 = shi->n1, *n2 = shi->n2, *n3 = shi->n3; - - dl = shi->dx_u + shi->dx_v; - shi->dxno[0] = dl * n3[0] - shi->dx_u * n1[0] - shi->dx_v * n2[0]; - shi->dxno[1] = dl * n3[1] - shi->dx_u * n1[1] - shi->dx_v * n2[1]; - shi->dxno[2] = dl * n3[2] - shi->dx_u * n1[2] - shi->dx_v * n2[2]; - dl = shi->dy_u + shi->dy_v; - shi->dyno[0] = dl * n3[0] - shi->dy_u * n1[0] - shi->dy_v * n2[0]; - shi->dyno[1] = dl * n3[1] - shi->dy_u * n1[1] - shi->dy_v * n2[1]; - shi->dyno[2] = dl * n3[2] - shi->dy_u * n1[2] - shi->dy_v * n2[2]; - - } - } - - /* calc tangents */ - if (mode & (MA_TANGENT_V | MA_NORMAP_TANG) || mode2 & MA_TANGENT_CONCRETE || R.flag & R_NEED_TANGENT) { - const float *s1, *s2, *s3; - float tl, tu, tv; - - if (shi->vlr->flag & R_SMOOTH) { - tl = l; - tu = u; - tv = v; - } - else { - /* qdn: flat faces have tangents too, - * could pick either one, using average here */ - tl = 1.0f / 3.0f; - tu = -1.0f / 3.0f; - tv = -1.0f / 3.0f; - } - - shi->tang[0] = shi->tang[1] = shi->tang[2] = 0.0f; - shi->nmaptang[0] = shi->nmaptang[1] = shi->nmaptang[2] = 0.0f; - - if (mode & MA_TANGENT_V) { - s1 = RE_vertren_get_tangent(obr, v1, 0); - s2 = RE_vertren_get_tangent(obr, v2, 0); - s3 = RE_vertren_get_tangent(obr, v3, 0); - - if (s1 && s2 && s3) { - shi->tang[0] = (tl * s3[0] - tu * s1[0] - tv * s2[0]); - shi->tang[1] = (tl * s3[1] - tu * s1[1] - tv * s2[1]); - shi->tang[2] = (tl * s3[2] - tu * s1[2] - tv * s2[2]); - - if (obi->flag & R_TRANSFORMED) - mul_m3_v3(obi->nmat, shi->tang); - - normalize_v3(shi->tang); - copy_v3_v3(shi->nmaptang, shi->tang); - } - } - - if (need_mikk_tangent || need_mikk_tangent_concrete) { - int j1 = shi->i1, j2 = shi->i2, j3 = shi->i3; - float c0[3], c1[3], c2[3]; - int acttang = obr->actmtface; - - vlr_set_uv_indices(shi->vlr, &j1, &j2, &j3); - - /* cycle through all tangent in vlakren */ - for (int i = 0; i < MAX_MTFACE; i++) { - const float *tangent = RE_vlakren_get_nmap_tangent(obr, shi->vlr, i, false); - if (!tangent) - continue; - - copy_v3_v3(c0, &tangent[j1 * 4]); - copy_v3_v3(c1, &tangent[j2 * 4]); - copy_v3_v3(c2, &tangent[j3 * 4]); - - /* keeping tangents normalized at vertex level - * corresponds better to how it's done in game engines */ - if (obi->flag & R_TRANSFORMED) { - mul_mat3_m4_v3(obi->mat, c0); normalize_v3(c0); - mul_mat3_m4_v3(obi->mat, c1); normalize_v3(c1); - mul_mat3_m4_v3(obi->mat, c2); normalize_v3(c2); - } - - /* we don't normalize the interpolated TBN tangent - * corresponds better to how it's done in game engines */ - shi->tangents[i][0] = (tl * c2[0] - tu * c0[0] - tv * c1[0]); - shi->tangents[i][1] = (tl * c2[1] - tu * c0[1] - tv * c1[1]); - shi->tangents[i][2] = (tl * c2[2] - tu * c0[2] - tv * c1[2]); - - /* the sign is the same for all 3 vertices of any - * non degenerate triangle. */ - shi->tangents[i][3] = tangent[j1 * 4 + 3]; - - if (acttang == i && need_mikk_tangent) { - for (int m = 0; m < 4; m++) { - shi->nmaptang[m] = shi->tangents[i][m]; - } - } - } - } - } - - if (mode & MA_STR_SURFDIFF) { - const float *surfnor = RE_vlakren_get_surfnor(obr, shi->vlr, 0); - - if (surfnor) { - copy_v3_v3(shi->surfnor, surfnor); - if (obi->flag & R_TRANSFORMED) - mul_m3_v3(obi->nmat, shi->surfnor); - } - else - copy_v3_v3(shi->surfnor, shi->vn); - - shi->surfdist = 0.0f; - } - - if (R.r.mode & R_SPEED) { - const float *s1, *s2, *s3; - - s1 = RE_vertren_get_winspeed(obi, v1, 0); - s2 = RE_vertren_get_winspeed(obi, v2, 0); - s3 = RE_vertren_get_winspeed(obi, v3, 0); - if (s1 && s2 && s3) { - shi->winspeed[0] = (l * s3[0] - u * s1[0] - v * s2[0]); - shi->winspeed[1] = (l * s3[1] - u * s1[1] - v * s2[1]); - shi->winspeed[2] = (l * s3[2] - u * s1[2] - v * s2[2]); - shi->winspeed[3] = (l * s3[3] - u * s1[3] - v * s2[3]); - } - else { - shi->winspeed[0] = shi->winspeed[1] = shi->winspeed[2] = shi->winspeed[3] = 0.0f; - } - } - - /* pass option forces UV calc */ - if ((shi->passflag & SCE_PASS_UV) || (R.flag & R_NEED_VCOL)) - texco |= (NEED_UV | TEXCO_UV); - - /* texture coordinates. shi->dxuv shi->dyuv have been set */ - if (texco & NEED_UV) { - - if (texco & TEXCO_ORCO) { - if (v1->orco) { - const float *o1, *o2, *o3; - - o1 = v1->orco; - o2 = v2->orco; - o3 = v3->orco; - - shi->lo[0] = l * o3[0] - u * o1[0] - v * o2[0]; - shi->lo[1] = l * o3[1] - u * o1[1] - v * o2[1]; - shi->lo[2] = l * o3[2] - u * o1[2] - v * o2[2]; - - if (shi->osatex) { - dl = shi->dx_u + shi->dx_v; - shi->dxlo[0] = dl * o3[0] - shi->dx_u * o1[0] - shi->dx_v * o2[0]; - shi->dxlo[1] = dl * o3[1] - shi->dx_u * o1[1] - shi->dx_v * o2[1]; - shi->dxlo[2] = dl * o3[2] - shi->dx_u * o1[2] - shi->dx_v * o2[2]; - dl = shi->dy_u + shi->dy_v; - shi->dylo[0] = dl * o3[0] - shi->dy_u * o1[0] - shi->dy_v * o2[0]; - shi->dylo[1] = dl * o3[1] - shi->dy_u * o1[1] - shi->dy_v * o2[1]; - shi->dylo[2] = dl * o3[2] - shi->dy_u * o1[2] - shi->dy_v * o2[2]; - } - } - - copy_v3_v3(shi->duplilo, obi->dupliorco); - } - - if (texco & TEXCO_GLOB) { - copy_v3_v3(shi->gl, shi->co); - mul_m4_v3(R.viewinv, shi->gl); - if (shi->osatex) { - copy_v3_v3(shi->dxgl, shi->dxco); - mul_mat3_m4_v3(R.viewinv, shi->dxgl); - copy_v3_v3(shi->dygl, shi->dyco); - mul_mat3_m4_v3(R.viewinv, shi->dygl); - } - } - - if (texco & TEXCO_STRAND) { - shi->strandco = (l * v3->accum - u * v1->accum - v * v2->accum); - if (shi->osatex) { - dl = shi->dx_u + shi->dx_v; - shi->dxstrand = dl * v3->accum - shi->dx_u * v1->accum - shi->dx_v * v2->accum; - dl = shi->dy_u + shi->dy_v; - shi->dystrand = dl * v3->accum - shi->dy_u * v1->accum - shi->dy_v * v2->accum; - } - } - - if ((texco & TEXCO_UV) || (mode & (MA_VERTEXCOL | MA_VERTEXCOLP | MA_FACETEXTURE)) || (R.flag & R_NEED_VCOL)) { - VlakRen *vlr = shi->vlr; - MTFace *tface; - MCol *mcol; - char *name; - int i, j1 = shi->i1, j2 = shi->i2, j3 = shi->i3; - - /* uv and vcols are not copied on split, so set them according vlr divide flag */ - vlr_set_uv_indices(vlr, &j1, &j2, &j3); - - shi->totuv = 0; - shi->totcol = 0; - shi->actuv = obr->actmtface; - shi->actcol = obr->actmcol; - - if ((mode & (MA_VERTEXCOL | MA_VERTEXCOLP)) || (R.flag & R_NEED_VCOL)) { - for (i = 0; (mcol = RE_vlakren_get_mcol(obr, vlr, i, &name, 0)); i++) { - ShadeInputCol *scol = &shi->col[i]; - const char *cp1, *cp2, *cp3; - float a[3]; - - shi->totcol++; - scol->name = name; - - cp1 = (char *)(mcol + j1); - cp2 = (char *)(mcol + j2); - cp3 = (char *)(mcol + j3); - - /* alpha values */ - a[0] = ((float)cp1[0]) / 255.f; - a[1] = ((float)cp2[0]) / 255.f; - a[2] = ((float)cp3[0]) / 255.f; - scol->col[3] = l * a[2] - u * a[0] - v * a[1]; - - /* sample premultiplied color value */ - scol->col[0] = (l * ((float)cp3[3]) * a[2] - u * ((float)cp1[3]) * a[0] - v * ((float)cp2[3]) * a[1]) / 255.f; - scol->col[1] = (l * ((float)cp3[2]) * a[2] - u * ((float)cp1[2]) * a[0] - v * ((float)cp2[2]) * a[1]) / 255.f; - scol->col[2] = (l * ((float)cp3[1]) * a[2] - u * ((float)cp1[1]) * a[0] - v * ((float)cp2[1]) * a[1]) / 255.f; - - /* if not zero alpha, restore non-multiplied color */ - if (scol->col[3]) { - mul_v3_fl(scol->col, 1.0f / scol->col[3]); - } - } - - if (shi->totcol) { - shi->vcol[0] = shi->col[shi->actcol].col[0]; - shi->vcol[1] = shi->col[shi->actcol].col[1]; - shi->vcol[2] = shi->col[shi->actcol].col[2]; - shi->vcol[3] = shi->col[shi->actcol].col[3]; - } - else { - shi->vcol[0] = 0.0f; - shi->vcol[1] = 0.0f; - shi->vcol[2] = 0.0f; - shi->vcol[3] = 1.0f; - } - } - - for (i = 0; (tface = RE_vlakren_get_tface(obr, vlr, i, &name, 0)); i++) { - ShadeInputUV *suv = &shi->uv[i]; - const float *uv1 = tface->uv[j1]; - const float *uv2 = tface->uv[j2]; - const float *uv3 = tface->uv[j3]; - - shi->totuv++; - suv->name = name; - - if ((shi->mat->mapflag & MA_MAPFLAG_UVPROJECT) && (shi->depth == 0)) { - float x = shi->xs; - float y = shi->ys; - - float s1[2] = {-1.0f + 2.0f * uv1[0], -1.0f + 2.0f * uv1[1]}; - float s2[2] = {-1.0f + 2.0f * uv2[0], -1.0f + 2.0f * uv2[1]}; - float s3[2] = {-1.0f + 2.0f * uv3[0], -1.0f + 2.0f * uv3[1]}; - - - float obwinmat[4][4], winmat[4][4], ho1[4], ho2[4], ho3[4]; - float Zmulx, Zmuly; - float hox, hoy, l_proj, dl_proj, u_proj, v_proj; - float s00, s01, s10, s11, detsh; - - /* old globals, localized now */ - Zmulx = ((float)R.winx) / 2.0f; - Zmuly = ((float)R.winy) / 2.0f; - - zbuf_make_winmat(&R, winmat); - if (shi->obi->flag & R_TRANSFORMED) - mul_m4_m4m4(obwinmat, winmat, obi->mat); - else - copy_m4_m4(obwinmat, winmat); - - zbuf_render_project(obwinmat, v1->co, ho1); - zbuf_render_project(obwinmat, v2->co, ho2); - zbuf_render_project(obwinmat, v3->co, ho3); - - s00 = ho3[0] / ho3[3] - ho1[0] / ho1[3]; - s01 = ho3[1] / ho3[3] - ho1[1] / ho1[3]; - s10 = ho3[0] / ho3[3] - ho2[0] / ho2[3]; - s11 = ho3[1] / ho3[3] - ho2[1] / ho2[3]; - - detsh = s00 * s11 - s10 * s01; - detsh = (detsh != 0.0f) ? 1.0f / detsh : 0.0f; - s00 *= detsh; s01 *= detsh; - s10 *= detsh; s11 *= detsh; - - /* recalc u and v again */ - hox = x / Zmulx - 1.0f; - hoy = y / Zmuly - 1.0f; - u_proj = (hox - ho3[0] / ho3[3]) * s11 - (hoy - ho3[1] / ho3[3]) * s10; - v_proj = (hoy - ho3[1] / ho3[3]) * s00 - (hox - ho3[0] / ho3[3]) * s01; - l_proj = 1.0f + u_proj + v_proj; - - suv->uv[0] = l_proj * s3[0] - u_proj * s1[0] - v_proj * s2[0]; - suv->uv[1] = l_proj * s3[1] - u_proj * s1[1] - v_proj * s2[1]; - suv->uv[2] = 0.0f; - - if (shi->osatex) { - float dxuv[2], dyuv[2]; - dxuv[0] = s11 / Zmulx; - dxuv[1] = -s01 / Zmulx; - dyuv[0] = -s10 / Zmuly; - dyuv[1] = s00 / Zmuly; - - dl_proj = dxuv[0] + dxuv[1]; - suv->dxuv[0] = dl_proj * s3[0] - dxuv[0] * s1[0] - dxuv[1] * s2[0]; - suv->dxuv[1] = dl_proj * s3[1] - dxuv[0] * s1[1] - dxuv[1] * s2[1]; - dl_proj = dyuv[0] + dyuv[1]; - suv->dyuv[0] = dl_proj * s3[0] - dyuv[0] * s1[0] - dyuv[1] * s2[0]; - suv->dyuv[1] = dl_proj * s3[1] - dyuv[0] * s1[1] - dyuv[1] * s2[1]; - } - } - else { - - suv->uv[0] = -1.0f + 2.0f * (l * uv3[0] - u * uv1[0] - v * uv2[0]); - suv->uv[1] = -1.0f + 2.0f * (l * uv3[1] - u * uv1[1] - v * uv2[1]); - suv->uv[2] = 0.0f; /* texture.c assumes there are 3 coords */ - - if (shi->osatex) { - float duv[2]; - - dl = shi->dx_u + shi->dx_v; - duv[0] = shi->dx_u; - duv[1] = shi->dx_v; - - suv->dxuv[0] = 2.0f * (dl * uv3[0] - duv[0] * uv1[0] - duv[1] * uv2[0]); - suv->dxuv[1] = 2.0f * (dl * uv3[1] - duv[0] * uv1[1] - duv[1] * uv2[1]); - - dl = shi->dy_u + shi->dy_v; - duv[0] = shi->dy_u; - duv[1] = shi->dy_v; - - suv->dyuv[0] = 2.0f * (dl * uv3[0] - duv[0] * uv1[0] - duv[1] * uv2[0]); - suv->dyuv[1] = 2.0f * (dl * uv3[1] - duv[0] * uv1[1] - duv[1] * uv2[1]); - } - - if ((mode & MA_FACETEXTURE) && i == obr->actmtface) { - if (((mode & (MA_VERTEXCOL | MA_VERTEXCOLP)) == 0) && ((R.flag & R_NEED_VCOL) == 0)) { - shi->vcol[0] = 1.0f; - shi->vcol[1] = 1.0f; - shi->vcol[2] = 1.0f; - shi->vcol[3] = 1.0f; - } - if (tface->tpage) { - render_realtime_texture(shi, tface->tpage); - } - } - } - } - - shi->dupliuv[0] = -1.0f + 2.0f * obi->dupliuv[0]; - shi->dupliuv[1] = -1.0f + 2.0f * obi->dupliuv[1]; - shi->dupliuv[2] = 0.0f; - - if (shi->totuv == 0) { - ShadeInputUV *suv = &shi->uv[0]; - - suv->uv[0] = 2.0f * (u + .5f); - suv->uv[1] = 2.0f * (v + .5f); - suv->uv[2] = 0.0f; /* texture.c assumes there are 3 coords */ - - if (mode & MA_FACETEXTURE) { - /* no tface? set at 1.0f */ - shi->vcol[0] = 1.0f; - shi->vcol[1] = 1.0f; - shi->vcol[2] = 1.0f; - shi->vcol[3] = 1.0f; - } - } - } - - if (texco & TEXCO_NORM) { - shi->orn[0] = -shi->vn[0]; - shi->orn[1] = -shi->vn[1]; - shi->orn[2] = -shi->vn[2]; - } - - if (texco & TEXCO_STRESS) { - const float *s1, *s2, *s3; - - s1 = RE_vertren_get_stress(obr, v1, 0); - s2 = RE_vertren_get_stress(obr, v2, 0); - s3 = RE_vertren_get_stress(obr, v3, 0); - if (s1 && s2 && s3) { - shi->stress = l * s3[0] - u * s1[0] - v * s2[0]; - if (shi->stress < 1.0f) shi->stress -= 1.0f; - else shi->stress = (shi->stress - 1.0f) / shi->stress; - } - else shi->stress = 0.0f; - } - - if (texco & TEXCO_TANGENT) { - if ((mode & MA_TANGENT_V) == 0) { - /* just prevent surprises */ - shi->tang[0] = shi->tang[1] = shi->tang[2] = 0.0f; - shi->nmaptang[0] = shi->nmaptang[1] = shi->nmaptang[2] = 0.0f; - } - } - } - - /* this only avalailable for scanline renders */ - if (shi->depth == 0) { - float x = shi->xs; - float y = shi->ys; - - if (texco & TEXCO_WINDOW) { - shi->winco[0] = -1.0f + 2.0f * x / (float)R.winx; - shi->winco[1] = -1.0f + 2.0f * y / (float)R.winy; - shi->winco[2] = 0.0f; - if (shi->osatex) { - shi->dxwin[0] = 2.0f / (float)R.winx; - shi->dywin[1] = 2.0f / (float)R.winy; - shi->dxwin[1] = shi->dxwin[2] = 0.0f; - shi->dywin[0] = shi->dywin[2] = 0.0f; - } - } - } - /* else { - * Note! For raytracing winco is not set, - * important because thus means all shader input's need to have their variables set to zero - * else un-initialized values are used - */ - if (shi->do_manage) { - if ((mode & (MA_VERTEXCOL | MA_VERTEXCOLP | MA_FACETEXTURE)) || (R.flag & R_NEED_VCOL)) { - srgb_to_linearrgb_v3_v3(shi->vcol, shi->vcol); - } - } - -} - -/* ****************** ShadeSample ************************************** */ - -/* initialize per part, not per pixel! */ -void shade_input_initialize(ShadeInput *shi, RenderPart *pa, RenderLayer *rl, int sample) -{ - - memset(shi, 0, sizeof(ShadeInput)); - - shi->sample = sample; - shi->thread = pa->thread; - shi->do_preview = (R.r.scemode & R_MATNODE_PREVIEW) != 0; - - shi->do_manage = BKE_scene_check_color_management_enabled(R.scene); - shi->use_world_space_shading = BKE_scene_use_world_space_shading(R.scene); - - shi->lay = rl->lay; - shi->layflag = rl->layflag; - shi->passflag = rl->passflag; - shi->combinedflag = ~rl->pass_xor; - shi->mat_override = rl->mat_override; - shi->light_override = rl->light_override; -// shi->rl= rl; - /* note shi.depth==0 means first hit, not raytracing */ - -} - -/* initialize per part, not per pixel! */ -void shade_sample_initialize(ShadeSample *ssamp, RenderPart *pa, RenderLayer *rl) -{ - int a, tot; - - tot = R.osa == 0 ? 1 : R.osa; - - for (a = 0; a < tot; a++) { - shade_input_initialize(&ssamp->shi[a], pa, rl, a); - memset(&ssamp->shr[a], 0, sizeof(ShadeResult)); - } - - get_sample_layers(pa, rl, ssamp->rlpp); -} - -/* Do AO or (future) GI */ -void shade_samples_do_AO(ShadeSample *ssamp) -{ - if (!(R.r.mode & R_SHADOW)) - return; - if (!(R.r.mode & R_RAYTRACE) && !(R.wrld.ao_gather_method == WO_AOGATHER_APPROX)) - return; - - if (R.wrld.mode & (WO_AMB_OCC | WO_ENV_LIGHT | WO_INDIRECT_LIGHT)) { - ShadeInput *shi = &ssamp->shi[0]; - int sample; - - if (((shi->passflag & SCE_PASS_COMBINED) && (shi->combinedflag & (SCE_PASS_AO | SCE_PASS_ENVIRONMENT | SCE_PASS_INDIRECT))) || - (shi->passflag & (SCE_PASS_AO | SCE_PASS_ENVIRONMENT | SCE_PASS_INDIRECT))) - { - for (sample = 0; sample < ssamp->tot; shi++, sample++) - if (!(shi->mode & MA_SHLESS)) - ambient_occlusion(shi); /* stores in shi->ao[] */ - } - } -} - - -void shade_samples_fill_with_ps(ShadeSample *ssamp, PixStr *ps, int x, int y) -{ - ShadeInput *shi; - float xs, ys; - - ssamp->tot = 0; - - for (shi = ssamp->shi; ps; ps = ps->next) { - shade_input_set_triangle(shi, ps->obi, ps->facenr, 1); - - if (shi->vlr) { /* NULL happens for env material or for 'all z' */ - unsigned short curmask = ps->mask; - - /* full osa is only set for OSA renders */ - if (shi->vlr->flag & R_FULL_OSA) { - short shi_cp = 0, samp; - - for (samp = 0; samp < R.osa; samp++) { - if (curmask & (1 << samp)) { - /* zbuffer has this inverse corrected, ensures xs,ys are inside pixel */ - xs = (float)x + R.jit[samp][0] + 0.5f; - ys = (float)y + R.jit[samp][1] + 0.5f; - - if (shi_cp) - shade_input_copy_triangle(shi, shi - 1); - - shi->mask = (1 << samp); -// shi->rl= ssamp->rlpp[samp]; - shi->samplenr = R.shadowsamplenr[shi->thread]++; /* this counter is not being reset per pixel */ - shade_input_set_viewco(shi, x, y, xs, ys, (float)ps->z); - shade_input_set_uv(shi); - if (shi_cp == 0) - shade_input_set_normals(shi); - else /* XXX shi->flippednor messes up otherwise */ - shade_input_set_vertex_normals(shi); - - shi_cp = 1; - shi++; - } - } - } - else { - if (R.osa) { - short b = R.samples->centmask[curmask]; - xs = (float)x + R.samples->centLut[b & 15] + 0.5f; - ys = (float)y + R.samples->centLut[b >> 4] + 0.5f; - } - else if (R.i.curblur) { - xs= (float)x + R.mblur_jit[R.i.curblur-1][0] + 0.5f; - ys= (float)y + R.mblur_jit[R.i.curblur-1][1] + 0.5f; - } - else { - xs = (float)x + 0.5f; - ys = (float)y + 0.5f; - } - - shi->mask = curmask; - shi->samplenr = R.shadowsamplenr[shi->thread]++; - shade_input_set_viewco(shi, x, y, xs, ys, (float)ps->z); - shade_input_set_uv(shi); - shade_input_set_normals(shi); - shi++; - } - - /* total sample amount, shi->sample is static set in initialize */ - if (shi != ssamp->shi) - ssamp->tot = (shi - 1)->sample + 1; - } - } -} - -/* shades samples, returns true if anything happened */ -int shade_samples(ShadeSample *ssamp, PixStr *ps, int x, int y) -{ - shade_samples_fill_with_ps(ssamp, ps, x, y); - - if (ssamp->tot) { - ShadeInput *shi = ssamp->shi; - ShadeResult *shr = ssamp->shr; - int samp; - - /* if shadow or AO? */ - shade_samples_do_AO(ssamp); - - /* if shade (all shadepinputs have same passflag) */ - if (ssamp->shi[0].passflag & ~(SCE_PASS_Z | SCE_PASS_INDEXOB | SCE_PASS_INDEXMA)) { - - for (samp = 0; samp < ssamp->tot; samp++, shi++, shr++) { - shade_input_set_shade_texco(shi); - shade_input_do_shade(shi, shr); - } - } - else if (shi->passflag & SCE_PASS_Z) { - for (samp = 0; samp < ssamp->tot; samp++, shi++, shr++) - shr->z = -shi->co[2]; - } - - return 1; - } - return 0; -} - diff --git a/source/blender/render/intern/source/shadeoutput.c b/source/blender/render/intern/source/shadeoutput.c deleted file mode 100644 index 090c249defb..00000000000 --- a/source/blender/render/intern/source/shadeoutput.c +++ /dev/null @@ -1,2182 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2006 Blender Foundation - * All rights reserved. - * - * Contributors: Hos, Robert Wenzlaff. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/render/intern/source/shadeoutput.c - * \ingroup render - */ - -#include <stdio.h> -#include <float.h> -#include <math.h> -#include <string.h> - -#include "BLI_math.h" -#include "BLI_utildefines.h" - -#include "BKE_colorband.h" -#include "BKE_colortools.h" -#include "BKE_material.h" - -#include "DNA_group_types.h" -#include "DNA_lamp_types.h" -#include "DNA_material_types.h" - -/* local include */ -#include "occlusion.h" -#include "render_types.h" -#include "rendercore.h" -#include "shadbuf.h" -#include "sss.h" -#include "texture.h" - -#include "shading.h" /* own include */ - -#include "IMB_colormanagement.h" - -/* could enable at some point but for now there are far too many conversions */ -#ifdef __GNUC__ -# pragma GCC diagnostic ignored "-Wdouble-promotion" -#endif - -/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -/* defined in pipeline.c, is hardcopy of active dynamic allocated Render */ -/* only to be used here in this file, it's for speed */ -extern struct Render R; -/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ - -ListBase *get_lights(ShadeInput *shi) -{ - - if (R.r.scemode & R_BUTS_PREVIEW) - return &R.lights; - if (shi->light_override) - return &shi->light_override->gobject; - if (shi->mat && shi->mat->group) - return &shi->mat->group->gobject; - - return &R.lights; -} - -#if 0 -static void fogcolor(const float colf[3], float *rco, float *view) -{ - float alpha, stepsize, startdist, dist, hor[4], zen[3], vec[3], dview[3]; - float div=0.0f, distfac; - - hor[0]= R.wrld.horr; hor[1]= R.wrld.horg; hor[2]= R.wrld.horb; - zen[0]= R.wrld.zenr; zen[1]= R.wrld.zeng; zen[2]= R.wrld.zenb; - - copy_v3_v3(vec, rco); - - /* we loop from cur coord to mist start in steps */ - stepsize= 1.0f; - - div= ABS(view[2]); - dview[0]= view[0]/(stepsize*div); - dview[1]= view[1]/(stepsize*div); - dview[2]= -stepsize; - - startdist= -rco[2] + BLI_frand(); - for (dist= startdist; dist>R.wrld.miststa; dist-= stepsize) { - - hor[0]= R.wrld.horr; hor[1]= R.wrld.horg; hor[2]= R.wrld.horb; - alpha= 1.0f; - do_sky_tex(vec, vec, NULL, hor, zen, &alpha); - - distfac= (dist-R.wrld.miststa)/R.wrld.mistdist; - - hor[3]= hor[0]*distfac*distfac; - - /* premul! */ - alpha= hor[3]; - hor[0]= hor[0]*alpha; - hor[1]= hor[1]*alpha; - hor[2]= hor[2]*alpha; - addAlphaOverFloat(colf, hor); - - sub_v3_v3(vec, dview); - } -} -#endif - -/* zcor is distance, co the 3d coordinate in eye space, return alpha */ -float mistfactor(float zcor, float const co[3]) -{ - float fac, hi; - - fac = zcor - R.wrld.miststa; /* zcor is calculated per pixel */ - - /* fac= -co[2]-R.wrld.miststa; */ - - if (fac > 0.0f) { - if (fac < R.wrld.mistdist) { - - fac = (fac / R.wrld.mistdist); - - if (R.wrld.mistype == 0) { - fac *= fac; - } - else if (R.wrld.mistype == 1) { - /* pass */ - } - else { - fac = sqrtf(fac); - } - } - else { - fac = 1.0f; - } - } - else { - fac = 0.0f; - } - - /* height switched off mist */ - if (R.wrld.misthi!=0.0f && fac!=0.0f) { - /* at height misthi the mist is completely gone */ - - hi = R.viewinv[0][2] * co[0] + - R.viewinv[1][2] * co[1] + - R.viewinv[2][2] * co[2] + - R.viewinv[3][2]; - - if (hi > R.wrld.misthi) { - fac = 0.0f; - } - else if (hi>0.0f) { - hi= (R.wrld.misthi-hi)/R.wrld.misthi; - fac*= hi*hi; - } - } - - return (1.0f-fac)* (1.0f-R.wrld.misi); -} - -static void spothalo(struct LampRen *lar, ShadeInput *shi, float *intens) -{ - double a, b, c, disc, nray[3], npos[3]; - double t0, t1 = 0.0f, t2= 0.0f, t3; - float p1[3], p2[3], ladist, maxz = 0.0f, maxy = 0.0f, haint; - int cuts; - bool do_clip = true, use_yco = false; - - *intens= 0.0f; - haint= lar->haint; - - if (R.r.mode & R_ORTHO) { - /* camera pos (view vector) cannot be used... */ - /* camera position (cox,coy,0) rotate around lamp */ - p1[0]= shi->co[0]-lar->co[0]; - p1[1]= shi->co[1]-lar->co[1]; - p1[2]= -lar->co[2]; - mul_m3_v3(lar->imat, p1); - copy_v3db_v3fl(npos, p1); /* npos is double! */ - - /* pre-scale */ - npos[2] *= (double)lar->sh_zfac; - } - else { - copy_v3db_v3fl(npos, lar->sh_invcampos); /* in initlamp calculated */ - } - - /* rotate view */ - copy_v3db_v3fl(nray, shi->view); - mul_m3_v3_double(lar->imat, nray); - - if (R.wrld.mode & WO_MIST) { - /* patchy... */ - haint *= mistfactor(-lar->co[2], lar->co); - if (haint==0.0f) { - return; - } - } - - - /* rotate maxz */ - if (shi->co[2]==0.0f) { - do_clip = false; /* for when halo at sky */ - } - else { - p1[0]= shi->co[0]-lar->co[0]; - p1[1]= shi->co[1]-lar->co[1]; - p1[2]= shi->co[2]-lar->co[2]; - - maxz= lar->imat[0][2]*p1[0]+lar->imat[1][2]*p1[1]+lar->imat[2][2]*p1[2]; - maxz*= lar->sh_zfac; - maxy= lar->imat[0][1]*p1[0]+lar->imat[1][1]*p1[1]+lar->imat[2][1]*p1[2]; - - if (fabs(nray[2]) < FLT_EPSILON) { - use_yco = true; - } - } - - /* scale z to make sure volume is normalized */ - nray[2] *= (double)lar->sh_zfac; - /* nray does not need normalization */ - - ladist= lar->sh_zfac*lar->dist; - - /* solve */ - a = nray[0] * nray[0] + nray[1] * nray[1] - nray[2]*nray[2]; - b = nray[0] * npos[0] + nray[1] * npos[1] - nray[2]*npos[2]; - c = npos[0] * npos[0] + npos[1] * npos[1] - npos[2]*npos[2]; - - cuts= 0; - if (fabs(a) < DBL_EPSILON) { - /* - * Only one intersection point... - */ - return; - } - else { - disc = b*b - a*c; - - if (disc==0.0) { - t1=t2= (-b)/ a; - cuts= 2; - } - else if (disc > 0.0) { - disc = sqrt(disc); - t1 = (-b + disc) / a; - t2 = (-b - disc) / a; - cuts= 2; - } - } - if (cuts==2) { - int ok1=0, ok2=0; - - /* sort */ - if (t1>t2) { - a= t1; t1= t2; t2= a; - } - - /* z of intersection points with diabolo */ - p1[2]= npos[2] + t1*nray[2]; - p2[2]= npos[2] + t2*nray[2]; - - /* evaluate both points */ - if (p1[2]<=0.0f) ok1= 1; - if (p2[2]<=0.0f && t1!=t2) ok2= 1; - - /* at least 1 point with negative z */ - if (ok1==0 && ok2==0) return; - - /* intersction point with -ladist, the bottom of the cone */ - if (use_yco == false) { - t3= ((double)(-ladist)-npos[2])/nray[2]; - - /* de we have to replace one of the intersection points? */ - if (ok1) { - if (p1[2]<-ladist) t1= t3; - } - else { - t1= t3; - } - if (ok2) { - if (p2[2]<-ladist) t2= t3; - } - else { - t2= t3; - } - } - else if (ok1==0 || ok2==0) return; - - /* at least 1 visible interesction point */ - if (t1<0.0 && t2<0.0) return; - - if (t1<0.0) t1= 0.0; - if (t2<0.0) t2= 0.0; - - if (t1==t2) return; - - /* sort again to be sure */ - if (t1>t2) { - a= t1; t1= t2; t2= a; - } - - /* calculate t0: is the maximum visible z (when halo is intersected by face) */ - if (do_clip) { - if (use_yco == false) t0 = ((double)maxz - npos[2]) / nray[2]; - else t0 = ((double)maxy - npos[1]) / nray[1]; - - if (t0 < t1) return; - if (t0 < t2) t2= t0; - } - - /* calc points */ - p1[0]= npos[0] + t1*nray[0]; - p1[1]= npos[1] + t1*nray[1]; - p1[2]= npos[2] + t1*nray[2]; - p2[0]= npos[0] + t2*nray[0]; - p2[1]= npos[1] + t2*nray[1]; - p2[2]= npos[2] + t2*nray[2]; - - - /* now we have 2 points, make three lengths with it */ - - a = len_v3(p1); - b = len_v3(p2); - c = len_v3v3(p1, p2); - - a/= ladist; - a= sqrt(a); - b/= ladist; - b= sqrt(b); - c/= ladist; - - *intens= c*( (1.0-a)+(1.0-b) ); - - /* WATCH IT: do not clip a,b en c at 1.0, this gives nasty little overflows - * at the edges (especially with narrow halos) */ - if (*intens<=0.0f) return; - - /* soft area */ - /* not needed because t0 has been used for p1/p2 as well */ - /* if (doclip && t0<t2) { */ - /* *intens *= (t0-t1)/(t2-t1); */ - /* } */ - - *intens *= haint; - - if (lar->shb && lar->shb->shadhalostep) { - *intens *= shadow_halo(lar, p1, p2); - } - - } -} - -void renderspothalo(ShadeInput *shi, float col[4], float alpha) -{ - ListBase *lights; - GroupObject *go; - LampRen *lar; - float i; - - if (alpha==0.0f) return; - - lights= get_lights(shi); - for (go=lights->first; go; go= go->next) { - lar= go->lampren; - if (lar==NULL) continue; - - if (lar->type==LA_SPOT && (lar->mode & LA_HALO) && (lar->buftype != LA_SHADBUF_DEEP) && lar->haint>0) { - - if (lar->mode & LA_LAYER) - if (shi->vlr && (lar->lay & shi->obi->lay)==0) - continue; - if ((lar->lay & shi->lay)==0) - continue; - - spothalo(lar, shi, &i); - if (i > 0.0f) { - const float i_alpha = i * alpha; - col[0] += i_alpha * lar->r; - col[1] += i_alpha * lar->g; - col[2] += i_alpha * lar->b; - col[3] += i_alpha; /* all premul */ - } - } - } - /* clip alpha, is needed for unified 'alpha threshold' (vanillaRenderPipe.c) */ - if (col[3]>1.0f) col[3]= 1.0f; -} - - - -/* ---------------- shaders ----------------------- */ - -static double Normalize_d(double *n) -{ - double d; - - d= n[0]*n[0]+n[1]*n[1]+n[2]*n[2]; - - if (d>0.00000000000000001) { - d= sqrt(d); - - n[0]/=d; - n[1]/=d; - n[2]/=d; - } - else { - n[0]=n[1]=n[2]= 0.0; - d= 0.0; - } - return d; -} - -/* mix of 'real' fresnel and allowing control. grad defines blending gradient */ -float fresnel_fac(const float view[3], const float vn[3], float grad, float fac) -{ - float t1, t2; - - if (fac==0.0f) return 1.0f; - - t1 = dot_v3v3(view, vn); - if (t1>0.0f) t2= 1.0f+t1; - else t2= 1.0f-t1; - - t2= grad + (1.0f-grad)*powf(t2, fac); - - if (t2<0.0f) return 0.0f; - else if (t2>1.0f) return 1.0f; - return t2; -} - -static double saacos_d(double fac) -{ - if (fac<= -1.0) return M_PI; - else if (fac>=1.0) return 0.0; - else return acos(fac); -} - -/* Stoke's form factor. Need doubles here for extreme small area sizes */ -static float area_lamp_energy(float (*area)[3], const float co[3], const float vn[3]) -{ - double fac; - double vec[4][3]; /* vectors of rendered co to vertices lamp */ - double cross[4][3]; /* cross products of this */ - double rad[4]; /* angles between vecs */ - - VECSUB(vec[0], co, area[0]); - VECSUB(vec[1], co, area[1]); - VECSUB(vec[2], co, area[2]); - VECSUB(vec[3], co, area[3]); - - Normalize_d(vec[0]); - Normalize_d(vec[1]); - Normalize_d(vec[2]); - Normalize_d(vec[3]); - - /* cross product */ -#define CROSS(dest, a, b) \ - { \ - dest[0]= a[1] * b[2] - a[2] * b[1]; \ - dest[1]= a[2] * b[0] - a[0] * b[2]; \ - dest[2]= a[0] * b[1] - a[1] * b[0]; \ - } (void)0 - - CROSS(cross[0], vec[0], vec[1]); - CROSS(cross[1], vec[1], vec[2]); - CROSS(cross[2], vec[2], vec[3]); - CROSS(cross[3], vec[3], vec[0]); - -#undef CROSS - - Normalize_d(cross[0]); - Normalize_d(cross[1]); - Normalize_d(cross[2]); - Normalize_d(cross[3]); - - /* angles */ - rad[0]= vec[0][0]*vec[1][0]+ vec[0][1]*vec[1][1]+ vec[0][2]*vec[1][2]; - rad[1]= vec[1][0]*vec[2][0]+ vec[1][1]*vec[2][1]+ vec[1][2]*vec[2][2]; - rad[2]= vec[2][0]*vec[3][0]+ vec[2][1]*vec[3][1]+ vec[2][2]*vec[3][2]; - rad[3]= vec[3][0]*vec[0][0]+ vec[3][1]*vec[0][1]+ vec[3][2]*vec[0][2]; - - rad[0]= saacos_d(rad[0]); - rad[1]= saacos_d(rad[1]); - rad[2]= saacos_d(rad[2]); - rad[3]= saacos_d(rad[3]); - - /* Stoke formula */ - fac= rad[0]*(vn[0]*cross[0][0]+ vn[1]*cross[0][1]+ vn[2]*cross[0][2]); - fac+= rad[1]*(vn[0]*cross[1][0]+ vn[1]*cross[1][1]+ vn[2]*cross[1][2]); - fac+= rad[2]*(vn[0]*cross[2][0]+ vn[1]*cross[2][1]+ vn[2]*cross[2][2]); - fac+= rad[3]*(vn[0]*cross[3][0]+ vn[1]*cross[3][1]+ vn[2]*cross[3][2]); - - if (fac<=0.0) return 0.0; - return fac; -} - -static float area_lamp_energy_multisample(LampRen *lar, const float co[3], float *vn) -{ - /* corner vectors are moved around according lamp jitter */ - float *jitlamp= lar->jitter, vec[3]; - float area[4][3], intens= 0.0f; - int a= lar->ray_totsamp; - - /* test if co is behind lamp */ - sub_v3_v3v3(vec, co, lar->co); - if (dot_v3v3(vec, lar->vec) < 0.0f) - return 0.0f; - - while (a--) { - vec[0]= jitlamp[0]; - vec[1]= jitlamp[1]; - vec[2]= 0.0f; - mul_m3_v3(lar->mat, vec); - - add_v3_v3v3(area[0], lar->area[0], vec); - add_v3_v3v3(area[1], lar->area[1], vec); - add_v3_v3v3(area[2], lar->area[2], vec); - add_v3_v3v3(area[3], lar->area[3], vec); - - intens+= area_lamp_energy(area, co, vn); - - jitlamp+= 2; - } - intens /= (float)lar->ray_totsamp; - - return pow(intens * lar->areasize, lar->k); /* corrected for buttons size and lar->dist^2 */ -} - -static float spec(float inp, int hard) -{ - float b1; - - if (inp>=1.0f) return 1.0f; - else if (inp<=0.0f) return 0.0f; - - b1= inp*inp; - /* avoid FPE */ - if (b1<0.01f) b1= 0.01f; - - if ((hard & 1)==0) inp= 1.0f; - if (hard & 2) inp*= b1; - b1*= b1; - if (hard & 4) inp*= b1; - b1*= b1; - if (hard & 8) inp*= b1; - b1*= b1; - if (hard & 16) inp*= b1; - b1*= b1; - - /* avoid FPE */ - if (b1<0.001f) b1= 0.0f; - - if (hard & 32) inp*= b1; - b1*= b1; - if (hard & 64) inp*=b1; - b1*= b1; - if (hard & 128) inp*=b1; - - if (b1<0.001f) b1= 0.0f; - - if (hard & 256) { - b1*= b1; - inp*=b1; - } - - return inp; -} - -static float Phong_Spec(const float n[3], const float l[3], const float v[3], int hard, int tangent ) -{ - float h[3]; - float rslt; - - h[0] = l[0] + v[0]; - h[1] = l[1] + v[1]; - h[2] = l[2] + v[2]; - normalize_v3(h); - - rslt = h[0]*n[0] + h[1]*n[1] + h[2]*n[2]; - if (tangent) rslt= sasqrt(1.0f - rslt*rslt); - - if ( rslt > 0.0f ) rslt= spec(rslt, hard); - else rslt = 0.0f; - - return rslt; -} - - -/* reduced cook torrance spec (for off-specular peak) */ -static float CookTorr_Spec(const float n[3], const float l[3], const float v[3], int hard, int tangent) -{ - float i, nh, nv, h[3]; - - h[0]= v[0]+l[0]; - h[1]= v[1]+l[1]; - h[2]= v[2]+l[2]; - normalize_v3(h); - - nh= n[0]*h[0]+n[1]*h[1]+n[2]*h[2]; - if (tangent) nh= sasqrt(1.0f - nh*nh); - else if (nh<0.0f) return 0.0f; - - nv= n[0]*v[0]+n[1]*v[1]+n[2]*v[2]; - if (tangent) nv= sasqrt(1.0f - nv*nv); - else if (nv<0.0f) nv= 0.0f; - - i= spec(nh, hard); - - i= i/(0.1f+nv); - return i; -} - -/* Blinn spec */ -static float Blinn_Spec(const float n[3], const float l[3], const float v[3], float refrac, float spec_power, int tangent) -{ - float i, nh, nv, nl, vh, h[3]; - float a, b, c, g=0.0f, p, f, ang; - - if (refrac < 1.0f) return 0.0f; - if (spec_power == 0.0f) return 0.0f; - - /* conversion from 'hardness' (1-255) to 'spec_power' (50 maps at 0.1) */ - if (spec_power<100.0f) - spec_power = sqrtf(1.0f / spec_power); - else spec_power= 10.0f/spec_power; - - h[0]= v[0]+l[0]; - h[1]= v[1]+l[1]; - h[2]= v[2]+l[2]; - normalize_v3(h); - - nh= n[0]*h[0]+n[1]*h[1]+n[2]*h[2]; /* Dot product between surface normal and half-way vector */ - if (tangent) nh= sasqrt(1.0f - nh*nh); - else if (nh<0.0f) return 0.0f; - - nv= n[0]*v[0]+n[1]*v[1]+n[2]*v[2]; /* Dot product between surface normal and view vector */ - if (tangent) nv= sasqrt(1.0f - nv*nv); - if (nv<=0.01f) nv= 0.01f; /* hrms... */ - - nl= n[0]*l[0]+n[1]*l[1]+n[2]*l[2]; /* Dot product between surface normal and light vector */ - if (tangent) nl= sasqrt(1.0f - nl*nl); - if (nl<=0.01f) { - return 0.0f; - } - - vh= v[0]*h[0]+v[1]*h[1]+v[2]*h[2]; /* Dot product between view vector and half-way vector */ - if (vh<=0.0f) vh= 0.01f; - - a = 1.0f; - b = (2.0f*nh*nv)/vh; - c = (2.0f*nh*nl)/vh; - - if ( a < b && a < c ) g = a; - else if ( b < a && b < c ) g = b; - else if ( c < a && c < b ) g = c; - - p = sqrt((double)((refrac * refrac)+(vh * vh) - 1.0f)); - f = (((p-vh)*(p-vh))/((p+vh)*(p+vh)))*(1+((((vh*(p+vh))-1.0f)*((vh*(p+vh))-1.0f))/(((vh*(p-vh))+1.0f)*((vh*(p-vh))+1.0f)))); - ang = saacos(nh); - - i= f * g * exp((double)(-(ang*ang) / (2.0f*spec_power*spec_power))); - if (i<0.0f) i= 0.0f; - - return i; -} - -/* cartoon render spec */ -static float Toon_Spec(const float n[3], const float l[3], const float v[3], float size, float smooth, int tangent) -{ - float h[3]; - float ang; - float rslt; - - h[0] = l[0] + v[0]; - h[1] = l[1] + v[1]; - h[2] = l[2] + v[2]; - normalize_v3(h); - - rslt = h[0]*n[0] + h[1]*n[1] + h[2]*n[2]; - if (tangent) rslt = sasqrt(1.0f - rslt*rslt); - - ang = saacos( rslt ); - - if ( ang < size ) rslt = 1.0f; - else if ( ang >= (size + smooth) || smooth == 0.0f ) rslt = 0.0f; - else rslt = 1.0f - ((ang - size) / smooth); - - return rslt; -} - -/* Ward isotropic gaussian spec */ -static float WardIso_Spec(const float n[3], const float l[3], const float v[3], float rms, int tangent) -{ - float i, nh, nv, nl, h[3], angle, alpha; - - - /* half-way vector */ - h[0] = l[0] + v[0]; - h[1] = l[1] + v[1]; - h[2] = l[2] + v[2]; - normalize_v3(h); - - nh = n[0]*h[0]+n[1]*h[1]+n[2]*h[2]; /* Dot product between surface normal and half-way vector */ - if (tangent) nh = sasqrt(1.0f - nh*nh); - if (nh<=0.0f) nh = 0.001f; - - nv = n[0]*v[0]+n[1]*v[1]+n[2]*v[2]; /* Dot product between surface normal and view vector */ - if (tangent) nv = sasqrt(1.0f - nv*nv); - if (nv<=0.0f) nv = 0.001f; - - nl = n[0]*l[0]+n[1]*l[1]+n[2]*l[2]; /* Dot product between surface normal and light vector */ - if (tangent) nl = sasqrt(1.0f - nl*nl); - if (nl<=0.0f) nl = 0.001f; - - angle = tanf(saacos(nh)); - alpha = MAX2(rms, 0.001f); - - i= nl * (1.0f/(4.0f*(float)M_PI*alpha*alpha)) * (expf( -(angle*angle)/(alpha*alpha))/(sqrtf(nv*nl))); - - return i; -} - -/* cartoon render diffuse */ -static float Toon_Diff(const float n[3], const float l[3], const float UNUSED(v[3]), float size, float smooth) -{ - float rslt, ang; - - rslt = n[0]*l[0] + n[1]*l[1] + n[2]*l[2]; - - ang = saacos(rslt); - - if ( ang < size ) rslt = 1.0f; - else if ( ang >= (size + smooth) || smooth == 0.0f ) rslt = 0.0f; - else rslt = 1.0f - ((ang - size) / smooth); - - return rslt; -} - -/* Oren Nayar diffuse */ - -/* 'nl' is either dot product, or return value of area light */ -/* in latter case, only last multiplication uses 'nl' */ -static float OrenNayar_Diff(float nl, const float n[3], const float l[3], const float v[3], float rough ) -{ - float i/*, nh*/, nv /*, vh */, realnl, h[3]; - float a, b, t, A, B; - float Lit_A, View_A, Lit_B[3], View_B[3]; - - h[0]= v[0]+l[0]; - h[1]= v[1]+l[1]; - h[2]= v[2]+l[2]; - normalize_v3(h); - - /* nh= n[0]*h[0]+n[1]*h[1]+n[2]*h[2]; */ /* Dot product between surface normal and half-way vector */ - /* if (nh<0.0f) nh = 0.0f; */ - - nv= n[0]*v[0]+n[1]*v[1]+n[2]*v[2]; /* Dot product between surface normal and view vector */ - if (nv<=0.0f) nv= 0.0f; - - realnl= n[0]*l[0]+n[1]*l[1]+n[2]*l[2]; /* Dot product between surface normal and light vector */ - if (realnl<=0.0f) return 0.0f; - if (nl<0.0f) return 0.0f; /* value from area light */ - - /* vh= v[0]*h[0]+v[1]*h[1]+v[2]*h[2]; */ /* Dot product between view vector and halfway vector */ - /* if (vh<=0.0f) vh= 0.0f; */ - - Lit_A = saacos(realnl); - View_A = saacos( nv ); - - Lit_B[0] = l[0] - (realnl * n[0]); - Lit_B[1] = l[1] - (realnl * n[1]); - Lit_B[2] = l[2] - (realnl * n[2]); - normalize_v3(Lit_B); - - View_B[0] = v[0] - (nv * n[0]); - View_B[1] = v[1] - (nv * n[1]); - View_B[2] = v[2] - (nv * n[2]); - normalize_v3(View_B); - - t = Lit_B[0]*View_B[0] + Lit_B[1]*View_B[1] + Lit_B[2]*View_B[2]; - if ( t < 0 ) t = 0; - - if ( Lit_A > View_A ) { - a = Lit_A; - b = View_A; - } - else { - a = View_A; - b = Lit_A; - } - - A = 1.0f - (0.5f * ((rough * rough) / ((rough * rough) + 0.33f))); - B = 0.45f * ((rough * rough) / ((rough * rough) + 0.09f)); - - b*= 0.95f; /* prevent tangens from shooting to inf, 'nl' can be not a dot product here. */ - /* overflow only happens with extreme size area light, and higher roughness */ - i = nl * ( A + ( B * t * sinf(a) * tanf(b) ) ); - - return i; -} - -/* Minnaert diffuse */ -static float Minnaert_Diff(float nl, const float n[3], const float v[3], float darkness) -{ - float i, nv; - - /* nl = dot product between surface normal and light vector */ - if (nl <= 0.0f) - return 0.0f; - - /* nv = dot product between surface normal and view vector */ - nv = dot_v3v3(n, v); - if (nv < 0.0f) - nv = 0.0f; - - if (darkness <= 1.0f) - i = nl * pow(max_ff(nv * nl, 0.1f), (darkness - 1.0f) ); /*The Real model*/ - else - i = nl * pow( (1.001f - nv), (darkness - 1.0f) ); /*Nvidia model*/ - - return i; -} - -static float Fresnel_Diff(float *vn, float *lv, float *UNUSED(view), float fac_i, float fac) -{ - return fresnel_fac(lv, vn, fac_i, fac); -} - -/* --------------------------------------------- */ -/* also called from texture.c */ -void calc_R_ref(ShadeInput *shi) -{ - float i; - - /* shi->vn dot shi->view */ - i= -2*(shi->vn[0]*shi->view[0]+shi->vn[1]*shi->view[1]+shi->vn[2]*shi->view[2]); - - shi->ref[0]= (shi->view[0]+i*shi->vn[0]); - shi->ref[1]= (shi->view[1]+i*shi->vn[1]); - shi->ref[2]= (shi->view[2]+i*shi->vn[2]); - if (shi->osatex) { - if (shi->vlr->flag & R_SMOOTH) { - i= -2*( (shi->vn[0]+shi->dxno[0])*(shi->view[0]+shi->dxview) + - (shi->vn[1]+shi->dxno[1])*shi->view[1]+ (shi->vn[2]+shi->dxno[2])*shi->view[2] ); - - shi->dxref[0]= shi->ref[0]- ( shi->view[0]+shi->dxview+i*(shi->vn[0]+shi->dxno[0])); - shi->dxref[1]= shi->ref[1]- (shi->view[1]+ i*(shi->vn[1]+shi->dxno[1])); - shi->dxref[2]= shi->ref[2]- (shi->view[2]+ i*(shi->vn[2]+shi->dxno[2])); - - i= -2*( (shi->vn[0]+shi->dyno[0])*shi->view[0]+ - (shi->vn[1]+shi->dyno[1])*(shi->view[1]+shi->dyview)+ (shi->vn[2]+shi->dyno[2])*shi->view[2] ); - - shi->dyref[0]= shi->ref[0]- (shi->view[0]+ i*(shi->vn[0]+shi->dyno[0])); - shi->dyref[1]= shi->ref[1]- (shi->view[1]+shi->dyview+i*(shi->vn[1]+shi->dyno[1])); - shi->dyref[2]= shi->ref[2]- (shi->view[2]+ i*(shi->vn[2]+shi->dyno[2])); - - } - else { - - i= -2*( shi->vn[0]*(shi->view[0]+shi->dxview) + - shi->vn[1]*shi->view[1]+ shi->vn[2]*shi->view[2] ); - - shi->dxref[0]= shi->ref[0]- (shi->view[0]+shi->dxview+i*shi->vn[0]); - shi->dxref[1]= shi->ref[1]- (shi->view[1]+ i*shi->vn[1]); - shi->dxref[2]= shi->ref[2]- (shi->view[2]+ i*shi->vn[2]); - - i= -2*( shi->vn[0]*shi->view[0]+ - shi->vn[1]*(shi->view[1]+shi->dyview)+ shi->vn[2]*shi->view[2] ); - - shi->dyref[0]= shi->ref[0]- (shi->view[0]+ i*shi->vn[0]); - shi->dyref[1]= shi->ref[1]- (shi->view[1]+shi->dyview+i*shi->vn[1]); - shi->dyref[2]= shi->ref[2]- (shi->view[2]+ i*shi->vn[2]); - } - } - -} - -/* called from rayshade.c */ -void shade_color(ShadeInput *shi, ShadeResult *shr) -{ - Material *ma= shi->mat; - - if (ma->mode & (MA_FACETEXTURE)) { - shi->r= shi->vcol[0]; - shi->g= shi->vcol[1]; - shi->b= shi->vcol[2]; - if (ma->mode & (MA_FACETEXTURE_ALPHA)) - shi->alpha= shi->vcol[3]; - } - else if (ma->mode & (MA_VERTEXCOLP)) { - float neg_alpha = 1.0f - shi->vcol[3]; - shi->r= shi->r*neg_alpha + shi->vcol[0]*shi->vcol[3]; - shi->g= shi->g*neg_alpha + shi->vcol[1]*shi->vcol[3]; - shi->b= shi->b*neg_alpha + shi->vcol[2]*shi->vcol[3]; - } - - if (ma->texco) - do_material_tex(shi, &R); - - if (ma->fresnel_tra!=0.0f) - shi->alpha*= fresnel_fac(shi->view, shi->vn, ma->fresnel_tra_i, ma->fresnel_tra); - - if (!(shi->mode & MA_TRANSP)) shi->alpha= 1.0f; - - shr->diff[0]= shi->r; - shr->diff[1]= shi->g; - shr->diff[2]= shi->b; - shr->alpha= shi->alpha; - - /* modulate by the object color */ - if ((ma->shade_flag & MA_OBCOLOR) && shi->obr->ob) { - float obcol[4]; - - copy_v4_v4(obcol, shi->obr->ob->col); - CLAMP(obcol[3], 0.0f, 1.0f); - - shr->diff[0] *= obcol[0]; - shr->diff[1] *= obcol[1]; - shr->diff[2] *= obcol[2]; - if (shi->mode & MA_TRANSP) shr->alpha *= obcol[3]; - } - - copy_v3_v3(shr->diffshad, shr->diff); -} - -/* ramp for at end of shade */ -static void ramp_diffuse_result(float *diff, ShadeInput *shi) -{ - Material *ma= shi->mat; - float col[4]; - - if (ma->ramp_col) { - if (ma->rampin_col==MA_RAMP_IN_RESULT) { - float fac = IMB_colormanagement_get_luminance(diff); - BKE_colorband_evaluate(ma->ramp_col, fac, col); - - /* blending method */ - fac= col[3]*ma->rampfac_col; - - ramp_blend(ma->rampblend_col, diff, fac, col); - } - } -} - -/* r,g,b denote energy, ramp is used with different values to make new material color */ -static void add_to_diffuse(float diff[3], const ShadeInput *shi, const float is, const float rgb[3]) -{ - Material *ma= shi->mat; - - if (ma->ramp_col && (ma->mode & MA_RAMP_COL)) { - - /* MA_RAMP_IN_RESULT is exceptional */ - if (ma->rampin_col==MA_RAMP_IN_RESULT) { - /* normal add */ - diff[0] += rgb[0] * shi->r; - diff[1] += rgb[1] * shi->g; - diff[2] += rgb[2] * shi->b; - } - else { - float colt[3], col[4]; - float fac; - - /* input */ - switch (ma->rampin_col) { - case MA_RAMP_IN_ENERGY: - fac = IMB_colormanagement_get_luminance(rgb); - break; - case MA_RAMP_IN_SHADER: - fac = is; - break; - case MA_RAMP_IN_NOR: - fac = dot_v3v3(shi->view, shi->vn); - break; - default: - fac = 0.0f; - break; - } - - BKE_colorband_evaluate(ma->ramp_col, fac, col); - - /* blending method */ - fac = col[3] * ma->rampfac_col; - copy_v3_v3(colt, &shi->r); - - ramp_blend(ma->rampblend_col, colt, fac, col); - - /* output to */ - diff[0] += rgb[0] * colt[0]; - diff[1] += rgb[1] * colt[1]; - diff[2] += rgb[2] * colt[2]; - } - } - else { - diff[0] += rgb[0] * shi->r; - diff[1] += rgb[1] * shi->g; - diff[2] += rgb[2] * shi->b; - } -} - -static void ramp_spec_result(float spec_col[3], ShadeInput *shi) -{ - Material *ma= shi->mat; - - if (ma->ramp_spec && (ma->rampin_spec==MA_RAMP_IN_RESULT)) { - float col[4]; - float fac = IMB_colormanagement_get_luminance(spec_col); - - BKE_colorband_evaluate(ma->ramp_spec, fac, col); - - /* blending method */ - fac= col[3]*ma->rampfac_spec; - - ramp_blend(ma->rampblend_spec, spec_col, fac, col); - - } -} - -/* is = dot product shade, t = spec energy */ -static void do_specular_ramp(ShadeInput *shi, float is, float t, float spec[3]) -{ - Material *ma= shi->mat; - - spec[0]= shi->specr; - spec[1]= shi->specg; - spec[2]= shi->specb; - - /* MA_RAMP_IN_RESULT is exception */ - if (ma->ramp_spec && (ma->rampin_spec!=MA_RAMP_IN_RESULT)) { - float fac; - float col[4]; - - /* input */ - switch (ma->rampin_spec) { - case MA_RAMP_IN_ENERGY: - fac= t; - break; - case MA_RAMP_IN_SHADER: - fac= is; - break; - case MA_RAMP_IN_NOR: - fac= shi->view[0]*shi->vn[0] + shi->view[1]*shi->vn[1] + shi->view[2]*shi->vn[2]; - break; - default: - fac= 0.0f; - break; - } - - BKE_colorband_evaluate(ma->ramp_spec, fac, col); - - /* blending method */ - fac= col[3]*ma->rampfac_spec; - - ramp_blend(ma->rampblend_spec, spec, fac, col); - } -} - -/* pure AO, check for raytrace and world should have been done */ -/* preprocess, textures were not done, don't use shi->amb for that reason */ -void ambient_occlusion(ShadeInput *shi) -{ - if ((R.wrld.ao_gather_method == WO_AOGATHER_APPROX) && shi->mat->amb!=0.0f) { - sample_occ(&R, shi); - } - else if ((R.r.mode & R_RAYTRACE) && shi->mat->amb!=0.0f) { - ray_ao(shi, shi->ao, shi->env); - } - else { - shi->ao[0]= shi->ao[1]= shi->ao[2]= 1.0f; - zero_v3(shi->env); - zero_v3(shi->indirect); - } -} - - -/* wrld mode was checked for */ -static void ambient_occlusion_apply(ShadeInput *shi, ShadeResult *shr) -{ - float f= R.wrld.aoenergy; - float tmp[3], tmpspec[3]; - - if (!((R.r.mode & R_RAYTRACE) || R.wrld.ao_gather_method == WO_AOGATHER_APPROX)) - return; - if (f == 0.0f) - return; - - if (R.wrld.aomix==WO_AOADD) { - shr->combined[0] += shi->ao[0]*shi->r*shi->refl*f; - shr->combined[1] += shi->ao[1]*shi->g*shi->refl*f; - shr->combined[2] += shi->ao[2]*shi->b*shi->refl*f; - } - else if (R.wrld.aomix==WO_AOMUL) { - mul_v3_v3v3(tmp, shr->combined, shi->ao); - mul_v3_v3v3(tmpspec, shr->spec, shi->ao); - - if (f == 1.0f) { - copy_v3_v3(shr->combined, tmp); - copy_v3_v3(shr->spec, tmpspec); - } - else { - interp_v3_v3v3(shr->combined, shr->combined, tmp, f); - interp_v3_v3v3(shr->spec, shr->spec, tmpspec, f); - } - } -} - -void environment_lighting_apply(ShadeInput *shi, ShadeResult *shr) -{ - float f= R.wrld.ao_env_energy*shi->amb; - - if (!((R.r.mode & R_RAYTRACE) || R.wrld.ao_gather_method == WO_AOGATHER_APPROX)) - return; - if (f == 0.0f) - return; - - shr->combined[0] += shi->env[0]*shi->r*shi->refl*f; - shr->combined[1] += shi->env[1]*shi->g*shi->refl*f; - shr->combined[2] += shi->env[2]*shi->b*shi->refl*f; -} - -static void indirect_lighting_apply(ShadeInput *shi, ShadeResult *shr) -{ - float f= R.wrld.ao_indirect_energy; - - if (!((R.r.mode & R_RAYTRACE) || R.wrld.ao_gather_method == WO_AOGATHER_APPROX)) - return; - if (f == 0.0f) - return; - - shr->combined[0] += shi->indirect[0]*shi->r*shi->refl*f; - shr->combined[1] += shi->indirect[1]*shi->g*shi->refl*f; - shr->combined[2] += shi->indirect[2]*shi->b*shi->refl*f; -} - -/* result written in shadfac */ -void lamp_get_shadow(LampRen *lar, ShadeInput *shi, float inp, float shadfac[4], int do_real) -{ - LampShadowSubSample *lss= &(lar->shadsamp[shi->thread].s[shi->sample]); - - if (do_real || lss->samplenr!=shi->samplenr) { - - shadfac[0]= shadfac[1]= shadfac[2]= shadfac[3]= 1.0f; - - if (lar->shb) { - if (lar->buftype==LA_SHADBUF_IRREGULAR) - shadfac[3]= ISB_getshadow(shi, lar->shb); - else - shadfac[3] = testshadowbuf(&R, lar->shb, shi->co, shi->dxco, shi->dyco, inp, shi->mat->lbias); - } - else if (lar->mode & LA_SHAD_RAY) { - ray_shadow(shi, lar, shadfac); - } - - if (shi->depth==0) { - copy_v4_v4(lss->shadfac, shadfac); - lss->samplenr= shi->samplenr; - } - } - else { - copy_v4_v4(shadfac, lss->shadfac); - } -} - -/* lampdistance and spot angle, writes in lv and dist */ -float lamp_get_visibility(LampRen *lar, const float co[3], float lv[3], float *dist) -{ - if (lar->type==LA_SUN || lar->type==LA_HEMI) { - *dist= 1.0f; - copy_v3_v3(lv, lar->vec); - return 1.0f; - } - else { - float visifac= 1.0f, visifac_r; - - sub_v3_v3v3(lv, co, lar->co); - mul_v3_fl(lv, 1.0f / (*dist = len_v3(lv))); - - /* area type has no quad or sphere option */ - if (lar->type==LA_AREA) { - /* area is single sided */ - //if (dot_v3v3(lv, lar->vec) > 0.0f) - // visifac= 1.0f; - //else - // visifac= 0.0f; - } - else { - switch (lar->falloff_type) { - case LA_FALLOFF_CONSTANT: - visifac = 1.0f; - break; - case LA_FALLOFF_INVLINEAR: - visifac = lar->dist/(lar->dist + dist[0]); - break; - case LA_FALLOFF_INVSQUARE: - /* NOTE: This seems to be a hack since commit r12045 says this - * option is similar to old Quad, but with slight changes. - * Correct inv square would be (which would be old Quad): - * visifac = lar->distkw / (lar->distkw + dist[0]*dist[0]); - */ - visifac = lar->dist / (lar->dist + dist[0]*dist[0]); - break; - case LA_FALLOFF_SLIDERS: - if (lar->ld1>0.0f) - visifac= lar->dist/(lar->dist+lar->ld1*dist[0]); - if (lar->ld2>0.0f) - visifac*= lar->distkw/(lar->distkw+lar->ld2*dist[0]*dist[0]); - break; - case LA_FALLOFF_INVCOEFFICIENTS: - visifac_r = lar->coeff_const + - lar->coeff_lin * dist[0] + - lar->coeff_quad * dist[0] * dist[0]; - if (visifac_r > 0.0) - visifac = 1.0 / visifac_r; - else - visifac = 0.0; - break; - case LA_FALLOFF_CURVE: - /* curvemapping_initialize is called from #add_render_lamp */ - visifac = curvemapping_evaluateF(lar->curfalloff, 0, dist[0]/lar->dist); - break; - } - - if (lar->mode & LA_SPHERE) { - float t= lar->dist - dist[0]; - if (t<=0.0f) - visifac= 0.0f; - else - visifac*= t/lar->dist; - } - - if (visifac > 0.0f) { - if (lar->type==LA_SPOT) { - float inpr, t; - - if (lar->mode & LA_SQUARE) { - if (dot_v3v3(lv, lar->vec) > 0.0f) { - float lvrot[3], x; - - /* rotate view to lampspace */ - copy_v3_v3(lvrot, lv); - mul_m3_v3(lar->imat, lvrot); - - x = max_ff(fabsf(lvrot[0]/lvrot[2]), fabsf(lvrot[1]/lvrot[2])); - /* 1.0f/(sqrt(1+x*x)) is equivalent to cos(atan(x)) */ - - inpr = 1.0f / (sqrtf(1.0f + x * x)); - } - else inpr= 0.0f; - } - else { - inpr= lv[0]*lar->vec[0]+lv[1]*lar->vec[1]+lv[2]*lar->vec[2]; - } - - t= lar->spotsi; - if (inpr<=t) - visifac= 0.0f; - else { - t= inpr-t; - if (t<lar->spotbl && lar->spotbl!=0.0f) { - /* soft area */ - float i= t/lar->spotbl; - t= i*i; - inpr*= (3.0f*t-2.0f*t*i); - } - visifac*= inpr; - } - } - } - } - if (visifac <= 0.001f) visifac = 0.0f; - return visifac; - } -} - -/* function returns raw diff, spec and full shadowed diff in the 'shad' pass */ -static void shade_one_light(LampRen *lar, ShadeInput *shi, ShadeResult *shr, int passflag) -{ - Material *ma= shi->mat; - VlakRen *vlr= shi->vlr; - float lv[3], lampdist, lacol[3], shadfac[4], lashdw[3]; - float i, is, i_noshad, inp, *vn, *view, vnor[3], phongcorr=1.0f; - float visifac; - - vn= shi->vn; - view= shi->view; - - - if (lar->energy == 0.0f) return; - /* only shadow lamps shouldn't affect shadow-less materials at all */ - if ((lar->mode & LA_ONLYSHADOW) && (!(ma->mode & MA_SHADOW) || !(R.r.mode & R_SHADOW))) - return; - /* optimization, don't render fully black lamps */ - if (!(lar->mode & LA_TEXTURE) && (lar->r + lar->g + lar->b == 0.0f)) - return; - - /* lampdist, spot angle, area side, ... */ - visifac= lamp_get_visibility(lar, shi->co, lv, &lampdist); - if (visifac==0.0f) - return; - - if (lar->type==LA_SPOT) { - if (lar->mode & LA_OSATEX) { - shi->osatex= 1; /* signal for multitex() */ - - shi->dxlv[0]= lv[0] - (shi->co[0]-lar->co[0]+shi->dxco[0])/lampdist; - shi->dxlv[1]= lv[1] - (shi->co[1]-lar->co[1]+shi->dxco[1])/lampdist; - shi->dxlv[2]= lv[2] - (shi->co[2]-lar->co[2]+shi->dxco[2])/lampdist; - - shi->dylv[0]= lv[0] - (shi->co[0]-lar->co[0]+shi->dyco[0])/lampdist; - shi->dylv[1]= lv[1] - (shi->co[1]-lar->co[1]+shi->dyco[1])/lampdist; - shi->dylv[2]= lv[2] - (shi->co[2]-lar->co[2]+shi->dyco[2])/lampdist; - } - } - - /* lamp color texture */ - lacol[0]= lar->r; - lacol[1]= lar->g; - lacol[2]= lar->b; - - lashdw[0]= lar->shdwr; - lashdw[1]= lar->shdwg; - lashdw[2]= lar->shdwb; - - if (lar->mode & LA_TEXTURE) do_lamp_tex(lar, lv, shi, lacol, LA_TEXTURE); - if (lar->mode & LA_SHAD_TEX) do_lamp_tex(lar, lv, shi, lashdw, LA_SHAD_TEX); - - /* tangent case; calculate fake face normal, aligned with lampvector */ - /* note, vnor==vn is used as tangent trigger for buffer shadow */ - if (vlr->flag & R_TANGENT) { - float cross[3], nstrand[3], blend; - - if (ma->mode & MA_STR_SURFDIFF) { - cross_v3_v3v3(cross, shi->surfnor, vn); - cross_v3_v3v3(nstrand, vn, cross); - - blend= dot_v3v3(nstrand, shi->surfnor); - blend= 1.0f - blend; - CLAMP(blend, 0.0f, 1.0f); - - interp_v3_v3v3(vnor, nstrand, shi->surfnor, blend); - normalize_v3(vnor); - } - else { - cross_v3_v3v3(cross, lv, vn); - cross_v3_v3v3(vnor, cross, vn); - normalize_v3(vnor); - } - - if (ma->strand_surfnor > 0.0f) { - if (ma->strand_surfnor > shi->surfdist) { - blend= (ma->strand_surfnor - shi->surfdist)/ma->strand_surfnor; - interp_v3_v3v3(vnor, vnor, shi->surfnor, blend); - normalize_v3(vnor); - } - } - - vnor[0]= -vnor[0];vnor[1]= -vnor[1];vnor[2]= -vnor[2]; - vn= vnor; - } - else if (ma->mode & MA_TANGENT_V) { - float cross[3]; - cross_v3_v3v3(cross, lv, shi->tang); - cross_v3_v3v3(vnor, cross, shi->tang); - normalize_v3(vnor); - vnor[0]= -vnor[0];vnor[1]= -vnor[1];vnor[2]= -vnor[2]; - vn= vnor; - } - - /* dot product and reflectivity */ - /* inp = dotproduct, is = shader result, i = lamp energy (with shadow), i_noshad = i without shadow */ - inp= dot_v3v3(vn, lv); - - /* phong threshold to prevent backfacing faces having artifacts on ray shadow (terminator problem) */ - /* this complex construction screams for a nicer implementation! (ton) */ - if (R.r.mode & R_SHADOW) { - if (ma->mode & MA_SHADOW) { - if (lar->type == LA_HEMI || lar->type == LA_AREA) { - /* pass */ - } - else if ((ma->mode & MA_RAYBIAS) && (lar->mode & LA_SHAD_RAY) && (vlr->flag & R_SMOOTH)) { - float thresh= shi->obr->ob->smoothresh; - if (inp>thresh) - phongcorr= (inp-thresh)/(inp*(1.0f-thresh)); - else - phongcorr= 0.0f; - } - else if (ma->sbias!=0.0f && ((lar->mode & LA_SHAD_RAY) || lar->shb)) { - if (inp>ma->sbias) - phongcorr= (inp-ma->sbias)/(inp*(1.0f-ma->sbias)); - else - phongcorr= 0.0f; - } - } - } - - /* diffuse shaders */ - if (lar->mode & LA_NO_DIFF) { - is = 0.0f; /* skip shaders */ - } - else if (lar->type==LA_HEMI) { - is = 0.5f * inp + 0.5f; - } - else { - - if (lar->type==LA_AREA) - inp= area_lamp_energy_multisample(lar, shi->co, vn); - - /* diffuse shaders (oren nayer gets inp from area light) */ - if (ma->diff_shader==MA_DIFF_ORENNAYAR) is= OrenNayar_Diff(inp, vn, lv, view, ma->roughness); - else if (ma->diff_shader==MA_DIFF_TOON) is= Toon_Diff(vn, lv, view, ma->param[0], ma->param[1]); - else if (ma->diff_shader==MA_DIFF_MINNAERT) is= Minnaert_Diff(inp, vn, view, ma->darkness); - else if (ma->diff_shader==MA_DIFF_FRESNEL) is= Fresnel_Diff(vn, lv, view, ma->param[0], ma->param[1]); - else is= inp; /* Lambert */ - } - - /* 'is' is diffuse */ - if ((ma->shade_flag & MA_CUBIC) && is > 0.0f && is < 1.0f) { - is= 3.0f * is * is - 2.0f * is * is * is; /* nicer termination of shades */ - } - - i= is*phongcorr; - - if (i>0.0f) { - i*= visifac*shi->refl; - } - i_noshad= i; - - vn = shi->vn; /* bring back original vector, we use special specular shaders for tangent */ - if (ma->mode & MA_TANGENT_V) - vn= shi->tang; - - /* init transp shadow */ - shadfac[0]= shadfac[1]= shadfac[2]= shadfac[3]= 1.0f; - - /* shadow and spec, (visifac==0 outside spot) */ - if (visifac> 0.0f) { - - if ((R.r.mode & R_SHADOW)) { - if (ma->mode & MA_SHADOW) { - if (lar->shb || (lar->mode & LA_SHAD_RAY)) { - - if (vn==vnor) /* tangent trigger */ - lamp_get_shadow(lar, shi, dot_v3v3(shi->vn, lv), shadfac, shi->depth); - else - lamp_get_shadow(lar, shi, inp, shadfac, shi->depth); - - /* warning, here it skips the loop */ - if ((lar->mode & LA_ONLYSHADOW) && i>0.0f) { - - shadfac[3]= i*lar->energy*(1.0f-shadfac[3]); - shr->shad[0] -= shadfac[3]*shi->r*(1.0f-lashdw[0]); - shr->shad[1] -= shadfac[3]*shi->g*(1.0f-lashdw[1]); - shr->shad[2] -= shadfac[3]*shi->b*(1.0f-lashdw[2]); - - if (!(lar->mode & LA_NO_SPEC)) { - shr->spec[0] -= shadfac[3]*shi->specr*(1.0f-lashdw[0]); - shr->spec[1] -= shadfac[3]*shi->specg*(1.0f-lashdw[1]); - shr->spec[2] -= shadfac[3]*shi->specb*(1.0f-lashdw[2]); - } - - return; - } - - i*= shadfac[3]; - shr->shad[3] = shadfac[3]; /* store this for possible check in troublesome cases */ - } - else { - shr->shad[3] = 1.0f; /* No shadow at all! */ - } - } - } - - /* in case 'no diffuse' we still do most calculus, spec can be in shadow.*/ - if (!(lar->mode & LA_NO_DIFF)) { - if (i>0.0f) { - if (ma->mode & MA_SHADOW_TRA) { - const float tcol[3] = { - i * shadfac[0] * lacol[0], - i * shadfac[1] * lacol[1], - i * shadfac[2] * lacol[2], - }; - add_to_diffuse(shr->shad, shi, is, tcol); - } - else { - const float tcol[3] = { - i * lacol[0], - i * lacol[1], - i * lacol[2], - }; - add_to_diffuse(shr->shad, shi, is, tcol); - } - } - /* add light for colored shadow */ - if (i_noshad>i && !(lashdw[0]==0 && lashdw[1]==0 && lashdw[2]==0)) { - const float tcol[3] = { - lashdw[0] * (i_noshad - i) * lacol[0], - lashdw[1] * (i_noshad - i) * lacol[1], - lashdw[2] * (i_noshad - i) * lacol[2], - }; - add_to_diffuse(shr->shad, shi, is, tcol); - } - if (i_noshad>0.0f) { - if (passflag & (SCE_PASS_DIFFUSE|SCE_PASS_SHADOW) || - ((passflag & SCE_PASS_COMBINED) && !(shi->combinedflag & SCE_PASS_SHADOW))) - { - const float tcol[3] = { - i_noshad * lacol[0], - i_noshad * lacol[1], - i_noshad * lacol[2] - }; - add_to_diffuse(shr->diff, shi, is, tcol); - } - else { - copy_v3_v3(shr->diff, shr->shad); - } - } - } - - /* specularity */ - shadfac[3]*= phongcorr; /* note, shadfac not allowed to be stored nonlocal */ - - if (shadfac[3]>0.0f && shi->spec!=0.0f && !(lar->mode & LA_NO_SPEC) && !(lar->mode & LA_ONLYSHADOW)) { - - if (!(passflag & (SCE_PASS_COMBINED | SCE_PASS_SPEC))) { - /* pass */ - } - else if (lar->type == LA_HEMI) { - float t; - /* hemi uses no spec shaders (yet) */ - - lv[0]+= view[0]; - lv[1]+= view[1]; - lv[2]+= view[2]; - - normalize_v3(lv); - - t= vn[0]*lv[0]+vn[1]*lv[1]+vn[2]*lv[2]; - - if (lar->type==LA_HEMI) { - t= 0.5f*t+0.5f; - } - - t= shadfac[3]*shi->spec*spec(t, shi->har); - - shr->spec[0]+= t*(lacol[0] * shi->specr); - shr->spec[1]+= t*(lacol[1] * shi->specg); - shr->spec[2]+= t*(lacol[2] * shi->specb); - } - else { - /* specular shaders */ - float specfac, t; - - if (ma->spec_shader==MA_SPEC_PHONG) - specfac= Phong_Spec(vn, lv, view, shi->har, (vlr->flag & R_TANGENT) || (ma->mode & MA_TANGENT_V)); - else if (ma->spec_shader==MA_SPEC_COOKTORR) - specfac= CookTorr_Spec(vn, lv, view, shi->har, (vlr->flag & R_TANGENT) || (ma->mode & MA_TANGENT_V)); - else if (ma->spec_shader==MA_SPEC_BLINN) - specfac= Blinn_Spec(vn, lv, view, ma->refrac, (float)shi->har, (vlr->flag & R_TANGENT) || (ma->mode & MA_TANGENT_V)); - else if (ma->spec_shader==MA_SPEC_WARDISO) - specfac= WardIso_Spec( vn, lv, view, ma->rms, (vlr->flag & R_TANGENT) || (ma->mode & MA_TANGENT_V)); - else - specfac= Toon_Spec(vn, lv, view, ma->param[2], ma->param[3], (vlr->flag & R_TANGENT) || (ma->mode & MA_TANGENT_V)); - - /* area lamp correction */ - if (lar->type==LA_AREA) specfac*= inp; - - t= shadfac[3]*shi->spec*visifac*specfac; - - if (ma->mode & MA_RAMP_SPEC) { - float spec[3]; - do_specular_ramp(shi, specfac, t, spec); - shr->spec[0]+= t*(lacol[0] * spec[0]); - shr->spec[1]+= t*(lacol[1] * spec[1]); - shr->spec[2]+= t*(lacol[2] * spec[2]); - } - else { - shr->spec[0]+= t*(lacol[0] * shi->specr); - shr->spec[1]+= t*(lacol[1] * shi->specg); - shr->spec[2]+= t*(lacol[2] * shi->specb); - } - } - } - } -} - -static void shade_lamp_loop_only_shadow(ShadeInput *shi, ShadeResult *shr) -{ - - if (R.r.mode & R_SHADOW) { - ListBase *lights; - LampRen *lar; - GroupObject *go; - float inpr, lv[3]; - float /* *view, */ shadfac[4]; - float ir, accum, visifac, lampdist; - float shaded = 0.0f, lightness = 0.0f; - - - /* view= shi->view; */ /* UNUSED */ - accum= ir= 0.0f; - - lights= get_lights(shi); - for (go=lights->first; go; go= go->next) { - lar= go->lampren; - if (lar==NULL) continue; - - if (lar->mode & LA_LAYER) if ((lar->lay & shi->obi->lay)==0) continue; - if ((lar->lay & shi->lay)==0) continue; - - if (lar->shb || (lar->mode & LA_SHAD_RAY)) { - visifac= lamp_get_visibility(lar, shi->co, lv, &lampdist); - ir+= 1.0f; - - if (visifac <= 0.0f) { - if (shi->mat->shadowonly_flag == MA_SO_OLD) - accum+= 1.0f; - - continue; - } - inpr= dot_v3v3(shi->vn, lv); - if (inpr <= 0.0f) { - if (shi->mat->shadowonly_flag == MA_SO_OLD) - accum+= 1.0f; - - continue; - } - - lamp_get_shadow(lar, shi, inpr, shadfac, shi->depth); - - if (shi->mat->shadowonly_flag == MA_SO_OLD) { - /* Old "Shadows Only" */ - accum+= (1.0f-visifac) + (visifac)*IMB_colormanagement_get_luminance(shadfac)*shadfac[3]; - } - else { - shaded += IMB_colormanagement_get_luminance(shadfac)*shadfac[3] * visifac * lar->energy; - - if (shi->mat->shadowonly_flag == MA_SO_SHADOW) { - lightness += visifac * lar->energy; - } - } - } - } - - /* Apply shadows as alpha */ - if (ir>0.0f) { - if (shi->mat->shadowonly_flag == MA_SO_OLD) { - accum = 1.0f - accum/ir; - } - else { - if (shi->mat->shadowonly_flag == MA_SO_SHADOW) { - if (lightness > 0.0f) { - /* Get shadow value from between 0.0f and non-shadowed lightness */ - accum = (lightness - shaded) / (lightness); - } - else { - accum = 0.0f; - } - } - else { /* shadowonly_flag == MA_SO_SHADED */ - /* Use shaded value */ - accum = 1.0f - shaded; - } - } - - shr->alpha= (shi->alpha)*(accum); - if (shr->alpha<0.0f) shr->alpha=0.0f; - } - else { - /* If "fully shaded", use full alpha even on areas that have no lights */ - if (shi->mat->shadowonly_flag == MA_SO_SHADED) shr->alpha=shi->alpha; - else shr->alpha= 0.f; - } - } - - /* quite disputable this... also note it doesn't mirror-raytrace */ - if ((R.wrld.mode & (WO_AMB_OCC|WO_ENV_LIGHT)) && shi->amb!=0.0f) { - float f; - - if (R.wrld.mode & WO_AMB_OCC) { - f= R.wrld.aoenergy*shi->amb; - - if (R.wrld.aomix==WO_AOADD) { - if (shi->mat->shadowonly_flag == MA_SO_OLD) { - f= f*(1.0f - IMB_colormanagement_get_luminance(shi->ao)); - shr->alpha= (shr->alpha + f)*f; - } - else { - shr->alpha -= f*IMB_colormanagement_get_luminance(shi->ao); - if (shr->alpha<0.0f) shr->alpha=0.0f; - } - } - else /* AO Multiply */ - shr->alpha= (1.0f - f)*shr->alpha + f*(1.0f - (1.0f - shr->alpha)*IMB_colormanagement_get_luminance(shi->ao)); - } - - if (R.wrld.mode & WO_ENV_LIGHT) { - if (shi->mat->shadowonly_flag == MA_SO_OLD) { - f= R.wrld.ao_env_energy*shi->amb*(1.0f - IMB_colormanagement_get_luminance(shi->env)); - shr->alpha= (shr->alpha + f)*f; - } - else { - f= R.wrld.ao_env_energy*shi->amb; - shr->alpha -= f*IMB_colormanagement_get_luminance(shi->env); - if (shr->alpha<0.0f) shr->alpha=0.0f; - } - } - } -} - -/* let's map negative light as if it mirrors positive light, otherwise negative values disappear */ -static void wrld_exposure_correct(float diff[3]) -{ - - diff[0]= R.wrld.linfac*(1.0f-expf( diff[0]*R.wrld.logfac) ); - diff[1]= R.wrld.linfac*(1.0f-expf( diff[1]*R.wrld.logfac) ); - diff[2]= R.wrld.linfac*(1.0f-expf( diff[2]*R.wrld.logfac) ); -} - -void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr) -{ - /* Passes which might need to know material color. - * - * It seems to be faster to just calculate material color - * even if the pass doesn't really need it than trying to - * figure out whether color is really needed or not. - */ - const int color_passes = - SCE_PASS_COMBINED | SCE_PASS_RGBA | SCE_PASS_DIFFUSE | SCE_PASS_SPEC | - SCE_PASS_REFLECT | SCE_PASS_NORMAL | SCE_PASS_REFRACT | SCE_PASS_EMIT | SCE_PASS_SHADOW; - - Material *ma= shi->mat; - int passflag= shi->passflag; - - memset(shr, 0, sizeof(ShadeResult)); - - if (!(shi->mode & MA_TRANSP)) shi->alpha = 1.0f; - - /* separate loop */ - if (ma->mode & MA_ONLYSHADOW) { - shade_lamp_loop_only_shadow(shi, shr); - return; - } - - /* envmap hack, always reset */ - shi->refcol[0]= shi->refcol[1]= shi->refcol[2]= shi->refcol[3]= 0.0f; - - /* material color itself */ - if (passflag & color_passes) { - if (ma->mode & (MA_FACETEXTURE)) { - shi->r= shi->vcol[0]; - shi->g= shi->vcol[1]; - shi->b= shi->vcol[2]; - if (ma->mode & (MA_FACETEXTURE_ALPHA)) - shi->alpha= shi->vcol[3]; - } -#ifdef WITH_FREESTYLE - else if (ma->vcol_alpha) { - shi->r= shi->vcol[0]; - shi->g= shi->vcol[1]; - shi->b= shi->vcol[2]; - shi->alpha= shi->vcol[3]; - } -#endif - else if (ma->mode & (MA_VERTEXCOLP)) { - float neg_alpha = 1.0f - shi->vcol[3]; - shi->r= shi->r*neg_alpha + shi->vcol[0]*shi->vcol[3]; - shi->g= shi->g*neg_alpha + shi->vcol[1]*shi->vcol[3]; - shi->b= shi->b*neg_alpha + shi->vcol[2]*shi->vcol[3]; - } - if (ma->texco) { - do_material_tex(shi, &R); - if (!(shi->mode & MA_TRANSP)) shi->alpha = 1.0f; - } - - shr->col[0]= shi->r*shi->alpha; - shr->col[1]= shi->g*shi->alpha; - shr->col[2]= shi->b*shi->alpha; - shr->col[3]= shi->alpha; - - if ((ma->sss_flag & MA_DIFF_SSS) && !sss_pass_done(&R, ma)) { - if (ma->sss_texfac == 0.0f) { - shi->r= shi->g= shi->b= shi->alpha= 1.0f; - shr->col[0]= shr->col[1]= shr->col[2]= shr->col[3]= 1.0f; - } - else { - shi->r= pow(max_ff(shi->r, 0.0f), ma->sss_texfac); - shi->g= pow(max_ff(shi->g, 0.0f), ma->sss_texfac); - shi->b= pow(max_ff(shi->b, 0.0f), ma->sss_texfac); - shi->alpha= pow(max_ff(shi->alpha, 0.0f), ma->sss_texfac); - - shr->col[0]= pow(max_ff(shr->col[0], 0.0f), ma->sss_texfac); - shr->col[1]= pow(max_ff(shr->col[1], 0.0f), ma->sss_texfac); - shr->col[2]= pow(max_ff(shr->col[2], 0.0f), ma->sss_texfac); - shr->col[3]= pow(max_ff(shr->col[3], 0.0f), ma->sss_texfac); - } - } - } - - if (ma->mode & MA_SHLESS) { - shr->combined[0]= shi->r; - shr->combined[1]= shi->g; - shr->combined[2]= shi->b; - shr->alpha= shi->alpha; - goto finally_shadeless; - } - - if ( (ma->mode & (MA_VERTEXCOL|MA_VERTEXCOLP))== MA_VERTEXCOL ) { /* vertexcolor light */ - shr->emit[0]= shi->r*(shi->emit+shi->vcol[0]*shi->vcol[3]); - shr->emit[1]= shi->g*(shi->emit+shi->vcol[1]*shi->vcol[3]); - shr->emit[2]= shi->b*(shi->emit+shi->vcol[2]*shi->vcol[3]); - } - else { - shr->emit[0]= shi->r*shi->emit; - shr->emit[1]= shi->g*shi->emit; - shr->emit[2]= shi->b*shi->emit; - } - - /* AO pass */ - if (((passflag & SCE_PASS_COMBINED) && (shi->combinedflag & (SCE_PASS_AO|SCE_PASS_ENVIRONMENT|SCE_PASS_INDIRECT))) || - (passflag & (SCE_PASS_AO|SCE_PASS_ENVIRONMENT|SCE_PASS_INDIRECT))) { - if ((R.wrld.mode & (WO_AMB_OCC|WO_ENV_LIGHT|WO_INDIRECT_LIGHT)) && (R.r.mode & R_SHADOW)) { - /* AO was calculated for scanline already */ - if (shi->depth || shi->volume_depth) - ambient_occlusion(shi); - copy_v3_v3(shr->ao, shi->ao); - copy_v3_v3(shr->env, shi->env); /* XXX multiply */ - copy_v3_v3(shr->indirect, shi->indirect); /* XXX multiply */ - } - else { - shr->ao[0]= shr->ao[1]= shr->ao[2]= 1.0f; - zero_v3(shr->env); - zero_v3(shr->indirect); - } - } - - /* lighting pass */ - if (passflag & (SCE_PASS_COMBINED|SCE_PASS_DIFFUSE|SCE_PASS_SPEC|SCE_PASS_SHADOW)) { - GroupObject *go; - ListBase *lights; - LampRen *lar; - - lights= get_lights(shi); - for (go=lights->first; go; go= go->next) { - lar= go->lampren; - if (lar==NULL) continue; - - /* test for lamp layer */ - if (lar->mode & LA_LAYER) if ((lar->lay & shi->obi->lay)==0) continue; - if ((lar->lay & shi->lay)==0) continue; - - /* accumulates in shr->diff and shr->spec and shr->shad (diffuse with shadow!) */ - shade_one_light(lar, shi, shr, passflag); - } - - /* this check is to prevent only shadow lamps from producing negative - * colors.*/ - if (shr->spec[0] < 0) shr->spec[0] = 0; - if (shr->spec[1] < 0) shr->spec[1] = 0; - if (shr->spec[2] < 0) shr->spec[2] = 0; - - if (shr->shad[0] < 0) shr->shad[0] = 0; - if (shr->shad[1] < 0) shr->shad[1] = 0; - if (shr->shad[2] < 0) shr->shad[2] = 0; - - if (ma->sss_flag & MA_DIFF_SSS) { - float sss[3], col[3], invalpha, texfac= ma->sss_texfac; - - /* this will return false in the preprocess stage */ - if (sample_sss(&R, ma, shi->co, sss)) { - invalpha= (shr->col[3] > FLT_EPSILON)? 1.0f/shr->col[3]: 1.0f; - - if (texfac==0.0f) { - copy_v3_v3(col, shr->col); - mul_v3_fl(col, invalpha); - } - else if (texfac==1.0f) { - col[0]= col[1]= col[2]= 1.0f; - mul_v3_fl(col, invalpha); - } - else { - copy_v3_v3(col, shr->col); - mul_v3_fl(col, invalpha); - col[0]= pow(max_ff(col[0], 0.0f), 1.0f-texfac); - col[1]= pow(max_ff(col[1], 0.0f), 1.0f-texfac); - col[2]= pow(max_ff(col[2], 0.0f), 1.0f-texfac); - } - - shr->diff[0]= sss[0]*col[0]; - shr->diff[1]= sss[1]*col[1]; - shr->diff[2]= sss[2]*col[2]; - - if (shi->combinedflag & SCE_PASS_SHADOW) { - shr->shad[0]= shr->diff[0]; - shr->shad[1]= shr->diff[1]; - shr->shad[2]= shr->diff[2]; - } - } - } - - if (shi->combinedflag & SCE_PASS_SHADOW) - copy_v3_v3(shr->diffshad, shr->shad); - else - copy_v3_v3(shr->diffshad, shr->diff); - - copy_v3_v3(shr->combined, shr->diffshad); - - /* calculate shadow pass, we use a multiplication mask */ - /* Even if diff = 0,0,0, it does matter what the shadow pass is, since we may want it 'for itself'! */ - if (passflag & SCE_PASS_SHADOW) { - if (shr->diff[0]!=0.0f) shr->shad[0]= shr->shad[0]/shr->diff[0]; - /* can't determine proper shadow from shad/diff (0/0), so use shadow intensity */ - else if (shr->shad[0]==0.0f) shr->shad[0]= shr->shad[3]; - - if (shr->diff[1]!=0.0f) shr->shad[1]= shr->shad[1]/shr->diff[1]; - else if (shr->shad[1]==0.0f) shr->shad[1]= shr->shad[3]; - - if (shr->diff[2]!=0.0f) shr->shad[2]= shr->shad[2]/shr->diff[2]; - else if (shr->shad[2]==0.0f) shr->shad[2]= shr->shad[3]; - } - - /* exposure correction */ - if ((R.wrld.exp!=0.0f || R.wrld.range!=1.0f) && !R.sss_points) { - wrld_exposure_correct(shr->combined); /* has no spec! */ - wrld_exposure_correct(shr->spec); - } - } - - /* alpha in end, spec can influence it */ - if (passflag & (SCE_PASS_COMBINED)) { - if ((ma->fresnel_tra!=0.0f) && (shi->mode & MA_TRANSP)) - shi->alpha*= fresnel_fac(shi->view, shi->vn, ma->fresnel_tra_i, ma->fresnel_tra); - - /* note: shi->mode! */ - if (shi->mode & MA_TRANSP && (shi->mode & (MA_ZTRANSP|MA_RAYTRANSP))) { - if (shi->spectra!=0.0f) { - float t = max_fff(shr->spec[0], shr->spec[1], shr->spec[2]); - t *= shi->spectra; - if (t>1.0f) t= 1.0f; - shi->alpha= (1.0f-t)*shi->alpha+t; - } - } - } - shr->alpha= shi->alpha; - - /* from now stuff everything in shr->combined: ambient, AO, ramps, exposure */ - if (!(ma->sss_flag & MA_DIFF_SSS) || !sss_pass_done(&R, ma)) { - if (R.r.mode & R_SHADOW) { - /* add AO in combined? */ - if (R.wrld.mode & WO_AMB_OCC) - if (shi->combinedflag & SCE_PASS_AO) - ambient_occlusion_apply(shi, shr); - - if (R.wrld.mode & WO_ENV_LIGHT) - if (shi->combinedflag & SCE_PASS_ENVIRONMENT) - environment_lighting_apply(shi, shr); - - if (R.wrld.mode & WO_INDIRECT_LIGHT) - if (shi->combinedflag & SCE_PASS_INDIRECT) - indirect_lighting_apply(shi, shr); - } - - shr->combined[0]+= shi->ambr; - shr->combined[1]+= shi->ambg; - shr->combined[2]+= shi->ambb; - - if (ma->mode & MA_RAMP_COL) ramp_diffuse_result(shr->combined, shi); - } - - if (ma->mode & MA_RAMP_SPEC) ramp_spec_result(shr->spec, shi); - - /* refcol is for envmap only */ - if (shi->refcol[0]!=0.0f) { - float result[3]; - - result[0]= shi->mirr*shi->refcol[1] + (1.0f - shi->mirr*shi->refcol[0])*shr->combined[0]; - result[1]= shi->mirg*shi->refcol[2] + (1.0f - shi->mirg*shi->refcol[0])*shr->combined[1]; - result[2]= shi->mirb*shi->refcol[3] + (1.0f - shi->mirb*shi->refcol[0])*shr->combined[2]; - - if (passflag & SCE_PASS_REFLECT) - sub_v3_v3v3(shr->refl, result, shr->combined); - - if (shi->combinedflag & SCE_PASS_REFLECT) - copy_v3_v3(shr->combined, result); - - } - - /* and add emit and spec */ - if (shi->combinedflag & SCE_PASS_EMIT) - add_v3_v3(shr->combined, shr->emit); - if (shi->combinedflag & SCE_PASS_SPEC) - add_v3_v3(shr->combined, shr->spec); - - - /* Last section of this function applies to shadeless colors too */ -finally_shadeless: - - /* modulate by the object color */ - if ((ma->shade_flag & MA_OBCOLOR) && shi->obr->ob) { - if (!(ma->sss_flag & MA_DIFF_SSS) || !sss_pass_done(&R, ma)) { - float obcol[4]; - - copy_v4_v4(obcol, shi->obr->ob->col); - CLAMP(obcol[3], 0.0f, 1.0f); - - shr->combined[0] *= obcol[0]; - shr->combined[1] *= obcol[1]; - shr->combined[2] *= obcol[2]; - if (shi->mode & MA_TRANSP) shr->alpha *= obcol[3]; - } - } - - shr->combined[3]= shr->alpha; -} - -/* used for "Lamp Data" shader node */ -static float lamp_get_data_internal(ShadeInput *shi, GroupObject *go, float col[4], float lv[3], float *dist, float shadow[4]) -{ - LampRen *lar = go->lampren; - float visifac, inp; - - if (!lar - || ((lar->mode & LA_LAYER) && (lar->lay & shi->obi->lay) == 0) - || (lar->lay & shi->lay) == 0) - return 0.0f; - - if (lar->mode & LA_TEXTURE) - do_lamp_tex(lar, lv, shi, col, LA_TEXTURE); - - visifac = lamp_get_visibility(lar, shi->co, lv, dist); - - if (visifac == 0.0f - || lar->type == LA_HEMI - || (lar->type != LA_SPOT && !(lar->mode & LA_SHAD_RAY)) - || (R.r.scemode & R_BUTS_PREVIEW)) - return visifac; - - inp = dot_v3v3(shi->vn, lv); - - if (inp > 0.0f) { - float shadfac[4]; - - shadow[0] = lar->shdwr; - shadow[1] = lar->shdwg; - shadow[2] = lar->shdwb; - - if (lar->mode & LA_SHAD_TEX) - do_lamp_tex(lar, lv, shi, shadow, LA_SHAD_TEX); - - if (R.r.mode & R_SHADOW) { - lamp_get_shadow(lar, shi, inp, shadfac, shi->depth); - - shadow[0] = 1.0f - ((1.0f - shadfac[0] * shadfac[3]) * (1.0f - shadow[0])); - shadow[1] = 1.0f - ((1.0f - shadfac[1] * shadfac[3]) * (1.0f - shadow[1])); - shadow[2] = 1.0f - ((1.0f - shadfac[2] * shadfac[3]) * (1.0f - shadow[2])); - } - } - - return visifac; -} - -float RE_lamp_get_data(ShadeInput *shi, Object *lamp_obj, float col[4], float lv[3], float *dist, float shadow[4]) -{ - col[0] = col[1] = col[2] = 0.0f; - col[3] = 1.0f; - copy_v3_v3(lv, shi->vn); - *dist = 1.0f; - shadow[0] = shadow[1] = shadow[2] = shadow[3] = 1.0f; - - if (lamp_obj->type == OB_LAMP) { - GroupObject *go; - Lamp *lamp = (Lamp *)lamp_obj->data; - - col[0] = lamp->r * lamp->energy; - col[1] = lamp->g * lamp->energy; - col[2] = lamp->b * lamp->energy; - - if (R.r.scemode & R_BUTS_PREVIEW) { - for (go = R.lights.first; go; go = go->next) { - /* "Lamp.002" is main key light of material preview */ - if (STREQ(go->ob->id.name + 2, "Lamp.002")) - return lamp_get_data_internal(shi, go, col, lv, dist, shadow); - } - return 0.0f; - } - - if (shi->light_override) { - for (go = shi->light_override->gobject.first; go; go = go->next) { - if (go->ob == lamp_obj) - return lamp_get_data_internal(shi, go, col, lv, dist, shadow); - } - } - - if (shi->mat && shi->mat->group) { - for (go = shi->mat->group->gobject.first; go; go = go->next) { - if (go->ob == lamp_obj) - return lamp_get_data_internal(shi, go, col, lv, dist, shadow); - } - } - - for (go = R.lights.first; go; go = go->next) { - if (go->ob == lamp_obj) - return lamp_get_data_internal(shi, go, col, lv, dist, shadow); - } - } - - return 0.0f; -} - -const float (*RE_object_instance_get_matrix(struct ObjectInstanceRen *obi, int matrix_id))[4] -{ - if (obi) { - switch (matrix_id) { - case RE_OBJECT_INSTANCE_MATRIX_OB: - return (const float(*)[4])obi->obmat; - case RE_OBJECT_INSTANCE_MATRIX_OBINV: - return (const float(*)[4])obi->obinvmat; - case RE_OBJECT_INSTANCE_MATRIX_LOCALTOVIEW: - return (const float(*)[4])obi->localtoviewmat; - case RE_OBJECT_INSTANCE_MATRIX_LOCALTOVIEWINV: - return (const float(*)[4])obi->localtoviewinvmat; - } - } - return NULL; -} - -float RE_object_instance_get_object_pass_index(struct ObjectInstanceRen *obi) -{ - return obi->ob->index; -} - -float RE_object_instance_get_random_id(struct ObjectInstanceRen *obi) -{ - return obi->random_id; -} - -const float (*RE_render_current_get_matrix(int matrix_id))[4] -{ - switch (matrix_id) { - case RE_VIEW_MATRIX: - return (const float(*)[4])R.viewmat; - case RE_VIEWINV_MATRIX: - return (const float(*)[4])R.viewinv; - } - return NULL; -} - -float RE_fresnel_dielectric(float incoming[3], float normal[3], float eta) -{ - /* compute fresnel reflectance without explicitly computing - * the refracted direction */ - float c = fabs(dot_v3v3(incoming, normal)); - float g = eta * eta - 1.0 + c * c; - float result; - - if (g > 0.0) { - g = sqrtf(g); - float A = (g - c) / (g + c); - float B = (c * (g + c) - 1.0) / (c * (g - c) + 1.0); - result = 0.5 * A * A * (1.0 + B * B); - } - else { - result = 1.0; /* TIR (no refracted component) */ - } - - return result; -} diff --git a/source/blender/render/intern/source/sss.c b/source/blender/render/intern/source/sss.c deleted file mode 100644 index 5919b8130d7..00000000000 --- a/source/blender/render/intern/source/sss.c +++ /dev/null @@ -1,1074 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2007 Blender Foundation. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/render/intern/source/sss.c - * \ingroup render - */ - -/* Possible Improvements: - * - add fresnel terms - * - adapt Rd table to scale, now with small scale there are a lot of misses? - * - possible interesting method: perform sss on all samples in the tree, - * and then use those values interpolated somehow later. can also do this - * filtering on demand for speed. since we are doing things in screen - * space now there is an exact correspondence - * - avoid duplicate shading (filtering points in advance, irradiance cache - * like lookup?) - * - lower resolution samples - */ - -#include <math.h> -#include <string.h> -#include <stdio.h> -#include <string.h> - -/* external modules: */ -#include "MEM_guardedalloc.h" - -#include "BLI_math.h" -#include "BLI_blenlib.h" -#include "BLI_utildefines.h" -#include "BLI_ghash.h" -#include "BLI_memarena.h" - -#include "BLT_translation.h" - - -#include "DNA_material_types.h" - -#include "BKE_global.h" -#include "BKE_main.h" -#include "BKE_scene.h" - - -/* this module */ -#include "render_types.h" -#include "sss.h" - -/* Generic Multiple Scattering API */ - -/* Relevant papers: - * [1] A Practical Model for Subsurface Light Transport - * [2] A Rapid Hierarchical Rendering Technique for Translucent Materials - * [3] Efficient Rendering of Local Subsurface Scattering - * [4] Implementing a skin BSSRDF (or several...) - */ - -/* Defines */ - -#define RD_TABLE_RANGE 100.0f -#define RD_TABLE_RANGE_2 10000.0f -#define RD_TABLE_SIZE 10000 - -#define MAX_OCTREE_NODE_POINTS 8 -#define MAX_OCTREE_DEPTH 15 - -/* Struct Definitions */ - -struct ScatterSettings { - float eta; /* index of refraction */ - float sigma_a; /* absorption coefficient */ - float sigma_s_; /* reduced scattering coefficient */ - float sigma_t_; /* reduced extinction coefficient */ - float sigma; /* effective extinction coefficient */ - float Fdr; /* diffuse fresnel reflectance */ - float D; /* diffusion constant */ - float A; - float alpha_; /* reduced albedo */ - float zr; /* distance of virtual lightsource above surface */ - float zv; /* distance of virtual lightsource below surface */ - float ld; /* mean free path */ - float ro; /* diffuse reflectance */ - float color; - float invsigma_t_; - float frontweight; - float backweight; - - float *tableRd; /* lookup table to avoid computing Rd */ - float *tableRd2; /* lookup table to avoid computing Rd for bigger values */ -}; - -typedef struct ScatterPoint { - float co[3]; - float rad[3]; - float area; - int back; -} ScatterPoint; - -typedef struct ScatterNode { - float co[3]; - float rad[3]; - float backrad[3]; - float area, backarea; - - int totpoint; - ScatterPoint *points; - - float split[3]; - struct ScatterNode *child[8]; -} ScatterNode; - -struct ScatterTree { - MemArena *arena; - - ScatterSettings *ss[3]; - float error, scale; - - ScatterNode *root; - ScatterPoint *points; - ScatterPoint **refpoints; - ScatterPoint **tmppoints; - int totpoint; - float min[3], max[3]; -}; - -typedef struct ScatterResult { - float rad[3]; - float backrad[3]; - float rdsum[3]; - float backrdsum[3]; -} ScatterResult; - -/* Functions for BSSRDF reparametrization in to more intuitive parameters, - * see [2] section 4 for more info. */ - -static float f_Rd(float alpha_, float A, float ro) -{ - float sq; - - sq = sqrtf(3.0f * (1.0f - alpha_)); - return (alpha_/2.0f)*(1.0f + expf((-4.0f/3.0f)*A*sq))*expf(-sq) - ro; -} - -static float compute_reduced_albedo(ScatterSettings *ss) -{ - const float tolerance= 1e-8; - const int max_iteration_count= 20; - float d, fsub, xn_1= 0.0f, xn= 1.0f, fxn, fxn_1; - int i; - - /* use secant method to compute reduced albedo using Rd function inverse - * with a given reflectance */ - fxn= f_Rd(xn, ss->A, ss->ro); - fxn_1= f_Rd(xn_1, ss->A, ss->ro); - - for (i= 0; i < max_iteration_count; i++) { - fsub= (fxn - fxn_1); - if (fabsf(fsub) < tolerance) - break; - d= ((xn - xn_1)/fsub)*fxn; - if (fabsf(d) < tolerance) - break; - - xn_1= xn; - fxn_1= fxn; - xn= xn - d; - - if (xn > 1.0f) xn= 1.0f; - if (xn_1 > 1.0f) xn_1= 1.0f; - - fxn= f_Rd(xn, ss->A, ss->ro); - } - - /* avoid division by zero later */ - if (xn <= 0.0f) - xn= 0.00001f; - - return xn; -} - -/* Exponential falloff functions */ - -static float Rd_rsquare(ScatterSettings *ss, float rr) -{ - float sr, sv, Rdr, Rdv; - - sr = sqrtf(rr + ss->zr * ss->zr); - sv = sqrtf(rr + ss->zv * ss->zv); - - Rdr= ss->zr*(1.0f + ss->sigma*sr)*expf(-ss->sigma*sr)/(sr*sr*sr); - Rdv= ss->zv*(1.0f + ss->sigma*sv)*expf(-ss->sigma*sv)/(sv*sv*sv); - - return /*ss->alpha_*/(1.0f/(4.0f*(float)M_PI))*(Rdr + Rdv); -} - -static float Rd(ScatterSettings *ss, float r) -{ - return Rd_rsquare(ss, r*r); -} - -/* table lookups for Rd. this avoids expensive exp calls. we use two - * separate tables as well for lower and higher numbers to improve - * precision, since the number are poorly distributed because we do - * a lookup with the squared distance for smaller distances, saving - * another sqrt. */ - -static void approximate_Rd_rgb(ScatterSettings **ss, float rr, float *rd) -{ - float indexf, t, idxf; - int index; - - if (rr > (RD_TABLE_RANGE_2 * RD_TABLE_RANGE_2)) { - /* pass */ - } - else if (rr > RD_TABLE_RANGE) { - rr = sqrtf(rr); - indexf= rr*(RD_TABLE_SIZE/RD_TABLE_RANGE_2); - index= (int)indexf; - idxf= (float)index; - t= indexf - idxf; - - if (index >= 0 && index < RD_TABLE_SIZE) { - rd[0]= (ss[0]->tableRd2[index]*(1-t) + ss[0]->tableRd2[index+1]*t); - rd[1]= (ss[1]->tableRd2[index]*(1-t) + ss[1]->tableRd2[index+1]*t); - rd[2]= (ss[2]->tableRd2[index]*(1-t) + ss[2]->tableRd2[index+1]*t); - return; - } - } - else { - indexf= rr*(RD_TABLE_SIZE/RD_TABLE_RANGE); - index= (int)indexf; - idxf= (float)index; - t= indexf - idxf; - - if (index >= 0 && index < RD_TABLE_SIZE) { - rd[0]= (ss[0]->tableRd[index]*(1-t) + ss[0]->tableRd[index+1]*t); - rd[1]= (ss[1]->tableRd[index]*(1-t) + ss[1]->tableRd[index+1]*t); - rd[2]= (ss[2]->tableRd[index]*(1-t) + ss[2]->tableRd[index+1]*t); - return; - } - } - - /* fallback to slow Rd computation */ - rd[0]= Rd_rsquare(ss[0], rr); - rd[1]= Rd_rsquare(ss[1], rr); - rd[2]= Rd_rsquare(ss[2], rr); -} - -static void build_Rd_table(ScatterSettings *ss) -{ - float r; - int i, size = RD_TABLE_SIZE+1; - - ss->tableRd= MEM_mallocN(sizeof(float)*size, "scatterTableRd"); - ss->tableRd2= MEM_mallocN(sizeof(float)*size, "scatterTableRd"); - - for (i= 0; i < size; i++) { - r= i*(RD_TABLE_RANGE/RD_TABLE_SIZE); -#if 0 - if (r < ss->invsigma_t_*ss->invsigma_t_) { - r= ss->invsigma_t_*ss->invsigma_t_; - } -#endif - ss->tableRd[i]= Rd(ss, sqrtf(r)); - - r= i*(RD_TABLE_RANGE_2/RD_TABLE_SIZE); -#if 0 - if (r < ss->invsigma_t_) { - r= ss->invsigma_t_; - } -#endif - ss->tableRd2[i]= Rd(ss, r); - } -} - -ScatterSettings *scatter_settings_new(float refl, float radius, float ior, float reflfac, float frontweight, float backweight) -{ - ScatterSettings *ss; - - ss= MEM_callocN(sizeof(ScatterSettings), "ScatterSettings"); - - /* see [1] and [3] for these formulas */ - ss->eta= ior; - ss->Fdr= -1.440f/ior*ior + 0.710f/ior + 0.668f + 0.0636f*ior; - ss->A= (1.0f + ss->Fdr)/(1.0f - ss->Fdr); - ss->ld= radius; - ss->ro= min_ff(refl, 0.99f); - ss->color= ss->ro*reflfac + (1.0f-reflfac); - - ss->alpha_= compute_reduced_albedo(ss); - - ss->sigma= 1.0f/ss->ld; - ss->sigma_t_= ss->sigma/sqrtf(3.0f*(1.0f - ss->alpha_)); - ss->sigma_s_= ss->alpha_*ss->sigma_t_; - ss->sigma_a= ss->sigma_t_ - ss->sigma_s_; - - ss->D= 1.0f/(3.0f*ss->sigma_t_); - - ss->zr= 1.0f/ss->sigma_t_; - ss->zv= ss->zr + 4.0f*ss->A*ss->D; - - ss->invsigma_t_= 1.0f/ss->sigma_t_; - - ss->frontweight= frontweight; - ss->backweight= backweight; - - /* precompute a table of Rd values for quick lookup */ - build_Rd_table(ss); - - return ss; -} - -void scatter_settings_free(ScatterSettings *ss) -{ - MEM_freeN(ss->tableRd); - MEM_freeN(ss->tableRd2); - MEM_freeN(ss); -} - -/* Hierarchical method as in [2]. */ - -/* traversal */ - -#define SUBNODE_INDEX(co, split) \ - ((co[0]>=split[0]) + (co[1]>=split[1])*2 + (co[2]>=split[2])*4) - -static void add_radiance(ScatterTree *tree, float *frontrad, float *backrad, float area, float backarea, float rr, ScatterResult *result) -{ - float rd[3], frontrd[3], backrd[3]; - - approximate_Rd_rgb(tree->ss, rr, rd); - - if (frontrad && area) { - frontrd[0] = rd[0]*area; - frontrd[1] = rd[1]*area; - frontrd[2] = rd[2]*area; - - result->rad[0] += frontrad[0]*frontrd[0]; - result->rad[1] += frontrad[1]*frontrd[1]; - result->rad[2] += frontrad[2]*frontrd[2]; - - result->rdsum[0] += frontrd[0]; - result->rdsum[1] += frontrd[1]; - result->rdsum[2] += frontrd[2]; - } - if (backrad && backarea) { - backrd[0] = rd[0]*backarea; - backrd[1] = rd[1]*backarea; - backrd[2] = rd[2]*backarea; - - result->backrad[0] += backrad[0]*backrd[0]; - result->backrad[1] += backrad[1]*backrd[1]; - result->backrad[2] += backrad[2]*backrd[2]; - - result->backrdsum[0] += backrd[0]; - result->backrdsum[1] += backrd[1]; - result->backrdsum[2] += backrd[2]; - } -} - -static void traverse_octree(ScatterTree *tree, ScatterNode *node, const float co[3], int self, ScatterResult *result) -{ - float sub[3], dist; - int i, index = 0; - - if (node->totpoint > 0) { - /* leaf - add radiance from all samples */ - for (i=0; i<node->totpoint; i++) { - ScatterPoint *p= &node->points[i]; - - sub_v3_v3v3(sub, co, p->co); - dist= dot_v3v3(sub, sub); - - if (p->back) - add_radiance(tree, NULL, p->rad, 0.0f, p->area, dist, result); - else - add_radiance(tree, p->rad, NULL, p->area, 0.0f, dist, result); - } - } - else { - /* branch */ - if (self) - index = SUBNODE_INDEX(co, node->split); - - for (i=0; i<8; i++) { - if (node->child[i]) { - ScatterNode *subnode= node->child[i]; - - if (self && index == i) { - /* always traverse node containing the point */ - traverse_octree(tree, subnode, co, 1, result); - } - else { - /* decide subnode traversal based on maximum solid angle */ - sub_v3_v3v3(sub, co, subnode->co); - dist= dot_v3v3(sub, sub); - - /* actually area/dist > error, but this avoids division */ - if (subnode->area+subnode->backarea>tree->error*dist) { - traverse_octree(tree, subnode, co, 0, result); - } - else { - add_radiance(tree, subnode->rad, subnode->backrad, - subnode->area, subnode->backarea, dist, result); - } - } - } - } - } -} - -static void compute_radiance(ScatterTree *tree, const float co[3], float *rad) -{ - ScatterResult result; - float rdsum[3], backrad[3], backrdsum[3]; - - memset(&result, 0, sizeof(result)); - - traverse_octree(tree, tree->root, co, 1, &result); - - /* the original paper doesn't do this, but we normalize over the - * sampled area and multiply with the reflectance. this is because - * our point samples are incomplete, there are no samples on parts - * of the mesh not visible from the camera. this can not only make - * it darker, but also lead to ugly color shifts */ - - mul_v3_fl(result.rad, tree->ss[0]->frontweight); - mul_v3_fl(result.backrad, tree->ss[0]->backweight); - - copy_v3_v3(rad, result.rad); - add_v3_v3v3(backrad, result.rad, result.backrad); - - copy_v3_v3(rdsum, result.rdsum); - add_v3_v3v3(backrdsum, result.rdsum, result.backrdsum); - - if (rdsum[0] > 1e-16f) rad[0]= tree->ss[0]->color*rad[0]/rdsum[0]; - if (rdsum[1] > 1e-16f) rad[1]= tree->ss[1]->color*rad[1]/rdsum[1]; - if (rdsum[2] > 1e-16f) rad[2]= tree->ss[2]->color*rad[2]/rdsum[2]; - - if (backrdsum[0] > 1e-16f) backrad[0]= tree->ss[0]->color*backrad[0]/backrdsum[0]; - if (backrdsum[1] > 1e-16f) backrad[1]= tree->ss[1]->color*backrad[1]/backrdsum[1]; - if (backrdsum[2] > 1e-16f) backrad[2]= tree->ss[2]->color*backrad[2]/backrdsum[2]; - - rad[0]= MAX2(rad[0], backrad[0]); - rad[1]= MAX2(rad[1], backrad[1]); - rad[2]= MAX2(rad[2], backrad[2]); -} - -/* building */ - -static void sum_leaf_radiance(ScatterTree *UNUSED(tree), ScatterNode *node) -{ - ScatterPoint *p; - float rad, totrad= 0.0f, inv; - int i; - - node->co[0]= node->co[1]= node->co[2]= 0.0; - node->rad[0]= node->rad[1]= node->rad[2]= 0.0; - node->backrad[0]= node->backrad[1]= node->backrad[2]= 0.0; - - /* compute total rad, rad weighted average position, - * and total area */ - for (i=0; i<node->totpoint; i++) { - p= &node->points[i]; - - rad= p->area*fabsf(p->rad[0] + p->rad[1] + p->rad[2]); - totrad += rad; - - node->co[0] += rad*p->co[0]; - node->co[1] += rad*p->co[1]; - node->co[2] += rad*p->co[2]; - - if (p->back) { - node->backrad[0] += p->rad[0]*p->area; - node->backrad[1] += p->rad[1]*p->area; - node->backrad[2] += p->rad[2]*p->area; - - node->backarea += p->area; - } - else { - node->rad[0] += p->rad[0]*p->area; - node->rad[1] += p->rad[1]*p->area; - node->rad[2] += p->rad[2]*p->area; - - node->area += p->area; - } - } - - if (node->area > 1e-16f) { - inv= 1.0f/node->area; - node->rad[0] *= inv; - node->rad[1] *= inv; - node->rad[2] *= inv; - } - if (node->backarea > 1e-16f) { - inv= 1.0f/node->backarea; - node->backrad[0] *= inv; - node->backrad[1] *= inv; - node->backrad[2] *= inv; - } - - if (totrad > 1e-16f) { - inv= 1.0f/totrad; - node->co[0] *= inv; - node->co[1] *= inv; - node->co[2] *= inv; - } - else { - /* make sure that if radiance is 0.0f, we still have these points in - * the tree at a good position, they count for rdsum too */ - for (i=0; i<node->totpoint; i++) { - p= &node->points[i]; - - node->co[0] += p->co[0]; - node->co[1] += p->co[1]; - node->co[2] += p->co[2]; - } - - node->co[0] /= node->totpoint; - node->co[1] /= node->totpoint; - node->co[2] /= node->totpoint; - } -} - -static void sum_branch_radiance(ScatterTree *UNUSED(tree), ScatterNode *node) -{ - ScatterNode *subnode; - float rad, totrad= 0.0f, inv; - int i, totnode; - - node->co[0]= node->co[1]= node->co[2]= 0.0; - node->rad[0]= node->rad[1]= node->rad[2]= 0.0; - node->backrad[0]= node->backrad[1]= node->backrad[2]= 0.0; - - /* compute total rad, rad weighted average position, - * and total area */ - for (i=0; i<8; i++) { - if (node->child[i] == NULL) - continue; - - subnode= node->child[i]; - - rad= subnode->area*fabsf(subnode->rad[0] + subnode->rad[1] + subnode->rad[2]); - rad += subnode->backarea*fabsf(subnode->backrad[0] + subnode->backrad[1] + subnode->backrad[2]); - totrad += rad; - - node->co[0] += rad*subnode->co[0]; - node->co[1] += rad*subnode->co[1]; - node->co[2] += rad*subnode->co[2]; - - node->rad[0] += subnode->rad[0]*subnode->area; - node->rad[1] += subnode->rad[1]*subnode->area; - node->rad[2] += subnode->rad[2]*subnode->area; - - node->backrad[0] += subnode->backrad[0]*subnode->backarea; - node->backrad[1] += subnode->backrad[1]*subnode->backarea; - node->backrad[2] += subnode->backrad[2]*subnode->backarea; - - node->area += subnode->area; - node->backarea += subnode->backarea; - } - - if (node->area > 1e-16f) { - inv= 1.0f/node->area; - node->rad[0] *= inv; - node->rad[1] *= inv; - node->rad[2] *= inv; - } - if (node->backarea > 1e-16f) { - inv= 1.0f/node->backarea; - node->backrad[0] *= inv; - node->backrad[1] *= inv; - node->backrad[2] *= inv; - } - - if (totrad > 1e-16f) { - inv= 1.0f/totrad; - node->co[0] *= inv; - node->co[1] *= inv; - node->co[2] *= inv; - } - else { - /* make sure that if radiance is 0.0f, we still have these points in - * the tree at a good position, they count for rdsum too */ - totnode= 0; - - for (i=0; i<8; i++) { - if (node->child[i]) { - subnode= node->child[i]; - - node->co[0] += subnode->co[0]; - node->co[1] += subnode->co[1]; - node->co[2] += subnode->co[2]; - - totnode++; - } - } - - node->co[0] /= totnode; - node->co[1] /= totnode; - node->co[2] /= totnode; - } -} - -static void sum_radiance(ScatterTree *tree, ScatterNode *node) -{ - if (node->totpoint > 0) { - sum_leaf_radiance(tree, node); - } - else { - int i; - - for (i=0; i<8; i++) - if (node->child[i]) - sum_radiance(tree, node->child[i]); - - sum_branch_radiance(tree, node); - } -} - -static void subnode_middle(int i, float *mid, float *subsize, float *submid) -{ - int x= i & 1, y= i & 2, z= i & 4; - - submid[0]= mid[0] + ((x)? subsize[0]: -subsize[0]); - submid[1]= mid[1] + ((y)? subsize[1]: -subsize[1]); - submid[2]= mid[2] + ((z)? subsize[2]: -subsize[2]); -} - -static void create_octree_node(ScatterTree *tree, ScatterNode *node, float *mid, float *size, ScatterPoint **refpoints, int depth) -{ - ScatterNode *subnode; - ScatterPoint **subrefpoints, **tmppoints= tree->tmppoints; - int index, nsize[8], noffset[8], i, subco, used_nodes, usedi; - float submid[3], subsize[3]; - - /* stopping condition */ - if (node->totpoint <= MAX_OCTREE_NODE_POINTS || depth == MAX_OCTREE_DEPTH) { - for (i=0; i<node->totpoint; i++) - node->points[i]= *(refpoints[i]); - - return; - } - - subsize[0]= size[0]*0.5f; - subsize[1]= size[1]*0.5f; - subsize[2]= size[2]*0.5f; - - node->split[0]= mid[0]; - node->split[1]= mid[1]; - node->split[2]= mid[2]; - - memset(nsize, 0, sizeof(nsize)); - memset(noffset, 0, sizeof(noffset)); - - /* count points in subnodes */ - for (i=0; i<node->totpoint; i++) { - index= SUBNODE_INDEX(refpoints[i]->co, node->split); - tmppoints[i]= refpoints[i]; - nsize[index]++; - } - - /* here we check if only one subnode is used. if this is the case, we don't - * create a new node, but rather call this function again, with different - * size and middle position for the same node. */ - for (usedi=0, used_nodes=0, i=0; i<8; i++) { - if (nsize[i]) { - used_nodes++; - usedi = i; - } - if (i != 0) - noffset[i]= noffset[i-1]+nsize[i-1]; - } - - if (used_nodes <= 1) { - subnode_middle(usedi, mid, subsize, submid); - create_octree_node(tree, node, submid, subsize, refpoints, depth+1); - return; - } - - /* reorder refpoints by subnode */ - for (i=0; i<node->totpoint; i++) { - index= SUBNODE_INDEX(tmppoints[i]->co, node->split); - refpoints[noffset[index]]= tmppoints[i]; - noffset[index]++; - } - - /* create subnodes */ - for (subco=0, i=0; i<8; subco+=nsize[i], i++) { - if (nsize[i] > 0) { - subnode= BLI_memarena_alloc(tree->arena, sizeof(ScatterNode)); - node->child[i]= subnode; - subnode->points= node->points + subco; - subnode->totpoint= nsize[i]; - subrefpoints= refpoints + subco; - - subnode_middle(i, mid, subsize, submid); - - create_octree_node(tree, subnode, submid, subsize, subrefpoints, - depth+1); - } - else - node->child[i]= NULL; - } - - node->points= NULL; - node->totpoint= 0; -} - -/* public functions */ - -ScatterTree *scatter_tree_new(ScatterSettings *ss[3], float scale, float error, - float (*co)[3], float (*color)[3], float *area, int totpoint) -{ - ScatterTree *tree; - ScatterPoint *points, **refpoints; - int i; - - /* allocate tree */ - tree= MEM_callocN(sizeof(ScatterTree), "ScatterTree"); - tree->scale= scale; - tree->error= error; - tree->totpoint= totpoint; - - tree->ss[0]= ss[0]; - tree->ss[1]= ss[1]; - tree->ss[2]= ss[2]; - - points = MEM_callocN(sizeof(ScatterPoint) * totpoint, "ScatterPoints"); - refpoints = MEM_callocN(sizeof(ScatterPoint *) * totpoint, "ScatterRefPoints"); - - tree->points= points; - tree->refpoints= refpoints; - - /* build points */ - INIT_MINMAX(tree->min, tree->max); - - for (i=0; i<totpoint; i++) { - copy_v3_v3(points[i].co, co[i]); - copy_v3_v3(points[i].rad, color[i]); - points[i].area= fabsf(area[i])/(tree->scale*tree->scale); - points[i].back= (area[i] < 0.0f); - - mul_v3_fl(points[i].co, 1.0f / tree->scale); - minmax_v3v3_v3(tree->min, tree->max, points[i].co); - - refpoints[i]= points + i; - } - - return tree; -} - -void scatter_tree_build(ScatterTree *tree) -{ - ScatterPoint *newpoints, **tmppoints; - float mid[3], size[3]; - int totpoint= tree->totpoint; - - newpoints = MEM_callocN(sizeof(ScatterPoint) * totpoint, "ScatterPoints"); - tmppoints = MEM_callocN(sizeof(ScatterPoint *) * totpoint, "ScatterTmpPoints"); - tree->tmppoints= tmppoints; - - tree->arena= BLI_memarena_new(0x8000 * sizeof(ScatterNode), "sss tree arena"); - BLI_memarena_use_calloc(tree->arena); - - /* build tree */ - tree->root= BLI_memarena_alloc(tree->arena, sizeof(ScatterNode)); - tree->root->points= newpoints; - tree->root->totpoint= totpoint; - - mid[0]= (tree->min[0]+tree->max[0])*0.5f; - mid[1]= (tree->min[1]+tree->max[1])*0.5f; - mid[2]= (tree->min[2]+tree->max[2])*0.5f; - - size[0]= (tree->max[0]-tree->min[0])*0.5f; - size[1]= (tree->max[1]-tree->min[1])*0.5f; - size[2]= (tree->max[2]-tree->min[2])*0.5f; - - create_octree_node(tree, tree->root, mid, size, tree->refpoints, 0); - - MEM_freeN(tree->points); - MEM_freeN(tree->refpoints); - MEM_freeN(tree->tmppoints); - tree->refpoints= NULL; - tree->tmppoints= NULL; - tree->points= newpoints; - - /* sum radiance at nodes */ - sum_radiance(tree, tree->root); -} - -void scatter_tree_sample(ScatterTree *tree, const float co[3], float color[3]) -{ - float sco[3]; - - copy_v3_v3(sco, co); - mul_v3_fl(sco, 1.0f / tree->scale); - - compute_radiance(tree, sco, color); -} - -void scatter_tree_free(ScatterTree *tree) -{ - if (tree->arena) BLI_memarena_free(tree->arena); - if (tree->points) MEM_freeN(tree->points); - if (tree->refpoints) MEM_freeN(tree->refpoints); - - MEM_freeN(tree); -} - -/* Internal Renderer API */ - -/* sss tree building */ - -typedef struct SSSData { - ScatterTree *tree; - ScatterSettings *ss[3]; -} SSSData; - -typedef struct SSSPoints { - struct SSSPoints *next, *prev; - - float (*co)[3]; - float (*color)[3]; - float *area; - int totpoint; -} SSSPoints; - -static void sss_create_tree_mat(Render *re, Material *mat) -{ - SSSPoints *p; - RenderResult *rr; - ListBase points; - float (*co)[3] = NULL, (*color)[3] = NULL, *area = NULL; - int totpoint = 0, osa, osaflag, frsflag, partsdone; - - if (re->test_break(re->tbh)) - return; - - points.first= points.last= NULL; - - /* TODO: this is getting a bit ugly, copying all those variables and - * setting them back, maybe we need to create our own Render? */ - - /* do SSS preprocessing render */ - BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); - rr= re->result; - osa= re->osa; - osaflag= re->r.mode & R_OSA; - frsflag= re->r.mode & R_EDGE_FRS; - partsdone= re->i.partsdone; - - re->osa= 0; - re->r.mode &= ~(R_OSA | R_EDGE_FRS); - re->sss_points= &points; - re->sss_mat= mat; - re->i.partsdone = 0; - - if (!(re->r.scemode & (R_BUTS_PREVIEW|R_VIEWPORT_PREVIEW))) - re->result= NULL; - BLI_rw_mutex_unlock(&re->resultmutex); - - RE_TileProcessor(re); - - BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); - if (!(re->r.scemode & (R_BUTS_PREVIEW|R_VIEWPORT_PREVIEW))) { - RE_FreeRenderResult(re->result); - re->result= rr; - } - BLI_rw_mutex_unlock(&re->resultmutex); - - re->i.partsdone= partsdone; - re->sss_mat= NULL; - re->sss_points= NULL; - re->osa= osa; - if (osaflag) re->r.mode |= R_OSA; - if (frsflag) re->r.mode |= R_EDGE_FRS; - - /* no points? no tree */ - if (!points.first) - return; - - /* merge points together into a single buffer */ - if (!re->test_break(re->tbh)) { - for (totpoint=0, p=points.first; p; p=p->next) - totpoint += p->totpoint; - - co= MEM_mallocN(sizeof(*co)*totpoint, "SSSCo"); - color= MEM_mallocN(sizeof(*color)*totpoint, "SSSColor"); - area= MEM_mallocN(sizeof(*area)*totpoint, "SSSArea"); - - for (totpoint=0, p=points.first; p; p=p->next) { - memcpy(co+totpoint, p->co, sizeof(*co)*p->totpoint); - memcpy(color+totpoint, p->color, sizeof(*color)*p->totpoint); - memcpy(area+totpoint, p->area, sizeof(*area)*p->totpoint); - totpoint += p->totpoint; - } - } - - /* free points */ - for (p=points.first; p; p=p->next) { - MEM_freeN(p->co); - MEM_freeN(p->color); - MEM_freeN(p->area); - } - BLI_freelistN(&points); - - /* build tree */ - if (!re->test_break(re->tbh)) { - SSSData *sss= MEM_callocN(sizeof(*sss), "SSSData"); - float ior= mat->sss_ior, cfac= mat->sss_colfac; - const float *radius = mat->sss_radius; - float fw= mat->sss_front, bw= mat->sss_back; - float error = mat->sss_error; - - error= get_render_aosss_error(&re->r, error); - if ((re->r.scemode & (R_BUTS_PREVIEW|R_VIEWPORT_PREVIEW)) && error < 0.5f) - error= 0.5f; - - sss->ss[0]= scatter_settings_new(mat->sss_col[0], radius[0], ior, cfac, fw, bw); - sss->ss[1]= scatter_settings_new(mat->sss_col[1], radius[1], ior, cfac, fw, bw); - sss->ss[2]= scatter_settings_new(mat->sss_col[2], radius[2], ior, cfac, fw, bw); - sss->tree= scatter_tree_new(sss->ss, mat->sss_scale, error, - co, color, area, totpoint); - - MEM_freeN(co); - MEM_freeN(color); - MEM_freeN(area); - - scatter_tree_build(sss->tree); - - BLI_ghash_insert(re->sss_hash, mat, sss); - } - else { - if (co) MEM_freeN(co); - if (color) MEM_freeN(color); - if (area) MEM_freeN(area); - } -} - -void sss_add_points(Render *re, float (*co)[3], float (*color)[3], float *area, int totpoint) -{ - SSSPoints *p; - - if (totpoint > 0) { - p= MEM_callocN(sizeof(SSSPoints), "SSSPoints"); - - p->co= co; - p->color= color; - p->area= area; - p->totpoint= totpoint; - - BLI_thread_lock(LOCK_CUSTOM1); - BLI_addtail(re->sss_points, p); - BLI_thread_unlock(LOCK_CUSTOM1); - } -} - -static void sss_free_tree(SSSData *sss) -{ - scatter_tree_free(sss->tree); - scatter_settings_free(sss->ss[0]); - scatter_settings_free(sss->ss[1]); - scatter_settings_free(sss->ss[2]); - MEM_freeN(sss); -} - -/* public functions */ - -void make_sss_tree(Render *re) -{ - Material *mat; - bool infostr_set = false; - const char *prevstr = NULL; - - free_sss(re); - - re->sss_hash= BLI_ghash_ptr_new("make_sss_tree gh"); - - re->stats_draw(re->sdh, &re->i); - - for (mat= re->main->mat.first; mat; mat= mat->id.next) { - if (mat->id.us && (mat->flag & MA_IS_USED) && (mat->sss_flag & MA_DIFF_SSS)) { - if (!infostr_set) { - prevstr = re->i.infostr; - re->i.infostr = IFACE_("SSS preprocessing"); - infostr_set = true; - } - - sss_create_tree_mat(re, mat); - } - } - - /* XXX preview exception */ - /* localizing preview render data is not fun for node trees :( */ - if (re->main!=G.main) { - for (mat= G.main->mat.first; mat; mat= mat->id.next) { - if (mat->id.us && (mat->flag & MA_IS_USED) && (mat->sss_flag & MA_DIFF_SSS)) { - if (!infostr_set) { - prevstr = re->i.infostr; - re->i.infostr = IFACE_("SSS preprocessing"); - infostr_set = true; - } - - sss_create_tree_mat(re, mat); - } - } - } - - if (infostr_set) - re->i.infostr = prevstr; -} - -void free_sss(Render *re) -{ - if (re->sss_hash) { - GHashIterator gh_iter; - - GHASH_ITER (gh_iter, re->sss_hash) { - sss_free_tree(BLI_ghashIterator_getValue(&gh_iter)); - } - - BLI_ghash_free(re->sss_hash, NULL, NULL); - re->sss_hash= NULL; - } -} - -int sample_sss(Render *re, Material *mat, const float co[3], float color[3]) -{ - if (re->sss_hash) { - SSSData *sss= BLI_ghash_lookup(re->sss_hash, mat); - - if (sss) { - scatter_tree_sample(sss->tree, co, color); - return 1; - } - else { - color[0]= 0.0f; - color[1]= 0.0f; - color[2]= 0.0f; - } - } - - return 0; -} - -int sss_pass_done(struct Render *re, struct Material *mat) -{ - return ((re->flag & R_BAKING) || !(re->r.mode & R_SSS) || (re->sss_hash && BLI_ghash_lookup(re->sss_hash, mat))); -} - diff --git a/source/blender/render/intern/source/strand.c b/source/blender/render/intern/source/strand.c deleted file mode 100644 index 5fde688481a..00000000000 --- a/source/blender/render/intern/source/strand.c +++ /dev/null @@ -1,1069 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * Contributors: Brecht Van Lommel. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/render/intern/source/strand.c - * \ingroup render - */ - - -#include <math.h> -#include <string.h> -#include <stdlib.h> - -#include "MEM_guardedalloc.h" - -#include "DNA_key_types.h" -#include "DNA_material_types.h" -#include "DNA_meshdata_types.h" - -#include "BLI_math.h" -#include "BLI_blenlib.h" -#include "BLI_utildefines.h" -#include "BLI_ghash.h" -#include "BLI_memarena.h" -#include "BLI_rand.h" - -#include "BKE_DerivedMesh.h" -#include "BKE_key.h" - - -#include "render_types.h" -#include "rendercore.h" -#include "renderdatabase.h" -#include "shading.h" -#include "strand.h" -#include "zbuf.h" - -/* *************** */ - -static float strand_eval_width(Material *ma, float strandco) -{ - float fac; - - strandco= 0.5f*(strandco + 1.0f); - - if (ma->strand_ease!=0.0f) { - if (ma->strand_ease<0.0f) - fac= pow(strandco, 1.0f+ma->strand_ease); - else - fac= pow(strandco, 1.0f/(1.0f-ma->strand_ease)); - } - else fac= strandco; - - return ((1.0f-fac)*ma->strand_sta + (fac)*ma->strand_end); -} - -void strand_eval_point(StrandSegment *sseg, StrandPoint *spoint) -{ - Material *ma; - StrandBuffer *strandbuf; - const float *simplify; - float p[4][3], data[4], cross[3], w, dx, dy, t; - int type; - - strandbuf= sseg->buffer; - ma= sseg->buffer->ma; - t= spoint->t; - type= (strandbuf->flag & R_STRAND_BSPLINE)? KEY_BSPLINE: KEY_CARDINAL; - - copy_v3_v3(p[0], sseg->v[0]->co); - copy_v3_v3(p[1], sseg->v[1]->co); - copy_v3_v3(p[2], sseg->v[2]->co); - copy_v3_v3(p[3], sseg->v[3]->co); - - if (sseg->obi->flag & R_TRANSFORMED) { - mul_m4_v3(sseg->obi->mat, p[0]); - mul_m4_v3(sseg->obi->mat, p[1]); - mul_m4_v3(sseg->obi->mat, p[2]); - mul_m4_v3(sseg->obi->mat, p[3]); - } - - if (t == 0.0f) { - copy_v3_v3(spoint->co, p[1]); - spoint->strandco= sseg->v[1]->strandco; - - spoint->dtstrandco= (sseg->v[2]->strandco - sseg->v[0]->strandco); - if (sseg->v[0] != sseg->v[1]) - spoint->dtstrandco *= 0.5f; - } - else if (t == 1.0f) { - copy_v3_v3(spoint->co, p[2]); - spoint->strandco= sseg->v[2]->strandco; - - spoint->dtstrandco= (sseg->v[3]->strandco - sseg->v[1]->strandco); - if (sseg->v[3] != sseg->v[2]) - spoint->dtstrandco *= 0.5f; - } - else { - key_curve_position_weights(t, data, type); - spoint->co[0]= data[0]*p[0][0] + data[1]*p[1][0] + data[2]*p[2][0] + data[3]*p[3][0]; - spoint->co[1]= data[0]*p[0][1] + data[1]*p[1][1] + data[2]*p[2][1] + data[3]*p[3][1]; - spoint->co[2]= data[0]*p[0][2] + data[1]*p[1][2] + data[2]*p[2][2] + data[3]*p[3][2]; - spoint->strandco= (1.0f-t)*sseg->v[1]->strandco + t*sseg->v[2]->strandco; - } - - key_curve_tangent_weights(t, data, type); - spoint->dtco[0]= data[0]*p[0][0] + data[1]*p[1][0] + data[2]*p[2][0] + data[3]*p[3][0]; - spoint->dtco[1]= data[0]*p[0][1] + data[1]*p[1][1] + data[2]*p[2][1] + data[3]*p[3][1]; - spoint->dtco[2]= data[0]*p[0][2] + data[1]*p[1][2] + data[2]*p[2][2] + data[3]*p[3][2]; - - normalize_v3_v3(spoint->tan, spoint->dtco); - normalize_v3_v3(spoint->nor, spoint->co); - negate_v3(spoint->nor); - - spoint->width= strand_eval_width(ma, spoint->strandco); - - /* simplification */ - simplify= RE_strandren_get_simplify(strandbuf->obr, sseg->strand, 0); - spoint->alpha= (simplify)? simplify[1]: 1.0f; - - /* outer points */ - cross_v3_v3v3(cross, spoint->co, spoint->tan); - - w= spoint->co[2]*strandbuf->winmat[2][3] + strandbuf->winmat[3][3]; - dx= strandbuf->winx*cross[0]*strandbuf->winmat[0][0]/w; - dy= strandbuf->winy*cross[1]*strandbuf->winmat[1][1]/w; - w = sqrtf(dx * dx + dy * dy); - - if (w > 0.0f) { - if (strandbuf->flag & R_STRAND_B_UNITS) { - const float crosslen= len_v3(cross); - w= 2.0f*crosslen*strandbuf->minwidth/w; - - if (spoint->width < w) { - spoint->alpha= spoint->width/w; - spoint->width= w; - } - - if (simplify) - /* squared because we only change width, not length */ - spoint->width *= simplify[0]*simplify[0]; - - mul_v3_fl(cross, spoint->width*0.5f/crosslen); - } - else - mul_v3_fl(cross, spoint->width/w); - } - - sub_v3_v3v3(spoint->co1, spoint->co, cross); - add_v3_v3v3(spoint->co2, spoint->co, cross); - - copy_v3_v3(spoint->dsco, cross); -} - -/* *************** */ - -static void interpolate_vec1(float *v1, float *v2, float t, float negt, float *v) -{ - v[0]= negt*v1[0] + t*v2[0]; -} - -static void interpolate_vec3(float *v1, float *v2, float t, float negt, float *v) -{ - v[0]= negt*v1[0] + t*v2[0]; - v[1]= negt*v1[1] + t*v2[1]; - v[2]= negt*v1[2] + t*v2[2]; -} - -static void interpolate_vec4(float *v1, float *v2, float t, float negt, float *v) -{ - v[0]= negt*v1[0] + t*v2[0]; - v[1]= negt*v1[1] + t*v2[1]; - v[2]= negt*v1[2] + t*v2[2]; - v[3]= negt*v1[3] + t*v2[3]; -} - -static void interpolate_shade_result(ShadeResult *shr1, ShadeResult *shr2, float t, ShadeResult *shr, int addpassflag) -{ - float negt= 1.0f - t; - - interpolate_vec4(shr1->combined, shr2->combined, t, negt, shr->combined); - - if (addpassflag & SCE_PASS_VECTOR) { - interpolate_vec4(shr1->winspeed, shr2->winspeed, t, negt, shr->winspeed); - } - /* optim... */ - if (addpassflag & ~(SCE_PASS_VECTOR)) { - if (addpassflag & SCE_PASS_Z) - interpolate_vec1(&shr1->z, &shr2->z, t, negt, &shr->z); - if (addpassflag & SCE_PASS_RGBA) - interpolate_vec4(shr1->col, shr2->col, t, negt, shr->col); - if (addpassflag & SCE_PASS_NORMAL) { - interpolate_vec3(shr1->nor, shr2->nor, t, negt, shr->nor); - normalize_v3(shr->nor); - } - if (addpassflag & SCE_PASS_EMIT) - interpolate_vec3(shr1->emit, shr2->emit, t, negt, shr->emit); - if (addpassflag & SCE_PASS_DIFFUSE) { - interpolate_vec3(shr1->diff, shr2->diff, t, negt, shr->diff); - interpolate_vec3(shr1->diffshad, shr2->diffshad, t, negt, shr->diffshad); - } - if (addpassflag & SCE_PASS_SPEC) - interpolate_vec3(shr1->spec, shr2->spec, t, negt, shr->spec); - if (addpassflag & SCE_PASS_SHADOW) - interpolate_vec3(shr1->shad, shr2->shad, t, negt, shr->shad); - if (addpassflag & SCE_PASS_AO) - interpolate_vec3(shr1->ao, shr2->ao, t, negt, shr->ao); - if (addpassflag & SCE_PASS_ENVIRONMENT) - interpolate_vec3(shr1->env, shr2->env, t, negt, shr->env); - if (addpassflag & SCE_PASS_INDIRECT) - interpolate_vec3(shr1->indirect, shr2->indirect, t, negt, shr->indirect); - if (addpassflag & SCE_PASS_REFLECT) - interpolate_vec3(shr1->refl, shr2->refl, t, negt, shr->refl); - if (addpassflag & SCE_PASS_REFRACT) - interpolate_vec3(shr1->refr, shr2->refr, t, negt, shr->refr); - if (addpassflag & SCE_PASS_MIST) - interpolate_vec1(&shr1->mist, &shr2->mist, t, negt, &shr->mist); - } -} - -static void strand_apply_shaderesult_alpha(ShadeResult *shr, float alpha) -{ - if (alpha < 1.0f) { - shr->combined[0] *= alpha; - shr->combined[1] *= alpha; - shr->combined[2] *= alpha; - shr->combined[3] *= alpha; - - shr->col[0] *= alpha; - shr->col[1] *= alpha; - shr->col[2] *= alpha; - shr->col[3] *= alpha; - - shr->alpha *= alpha; - } -} - -static void strand_shade_point(Render *re, ShadeSample *ssamp, StrandSegment *sseg, StrandVert *svert, StrandPoint *spoint) -{ - ShadeInput *shi= ssamp->shi; - ShadeResult *shr= ssamp->shr; - VlakRen vlr; - int seed; - - memset(&vlr, 0, sizeof(vlr)); - vlr.flag= R_SMOOTH; - if (sseg->buffer->ma->mode & MA_TANGENT_STR) - vlr.flag |= R_TANGENT; - - shi->vlr= &vlr; - shi->v1= NULL; - shi->v2= NULL; - shi->v3= NULL; - shi->strand= sseg->strand; - shi->obi= sseg->obi; - shi->obr= sseg->obi->obr; - - /* cache for shadow */ - shi->samplenr= re->shadowsamplenr[shi->thread]++; - - /* all samples */ - shi->mask= 0xFFFF; - - /* seed RNG for consistent results across tiles */ - seed = shi->strand->index + (svert - shi->strand->vert); - BLI_thread_srandom(shi->thread, seed); - - shade_input_set_strand(shi, sseg->strand, spoint); - shade_input_set_strand_texco(shi, sseg->strand, sseg->v[1], spoint); - - /* init material vars */ - shade_input_init_material(shi); - - /* shade */ - shade_samples_do_AO(ssamp); - shade_input_do_shade(shi, shr); - - /* apply simplification */ - strand_apply_shaderesult_alpha(shr, spoint->alpha); - - /* include lamphalos for strand, since halo layer was added already */ - if (re->flag & R_LAMPHALO) - if (shi->layflag & SCE_LAY_HALO) - renderspothalo(shi, shr->combined, shr->combined[3]); - - shi->strand= NULL; -} - -/* *************** */ - -struct StrandShadeCache { - GHash *resulthash; - GHash *refcounthash; - MemArena *memarena; -}; - -typedef struct StrandCacheEntry { - GHashPair pair; - ShadeResult shr; -} StrandCacheEntry; - -StrandShadeCache *strand_shade_cache_create(void) -{ - StrandShadeCache *cache; - - cache= MEM_callocN(sizeof(StrandShadeCache), "StrandShadeCache"); - cache->resulthash= BLI_ghash_pair_new("strand_shade_cache_create1 gh"); - cache->refcounthash= BLI_ghash_pair_new("strand_shade_cache_create2 gh"); - cache->memarena= BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "strand shade cache arena"); - - return cache; -} - -void strand_shade_cache_free(StrandShadeCache *cache) -{ - BLI_ghash_free(cache->refcounthash, NULL, NULL); - BLI_ghash_free(cache->resulthash, MEM_freeN, NULL); - BLI_memarena_free(cache->memarena); - MEM_freeN(cache); -} - -static GHashPair strand_shade_hash_pair(ObjectInstanceRen *obi, StrandVert *svert) -{ - GHashPair pair = {obi, svert}; - return pair; -} - -static void strand_shade_get(Render *re, StrandShadeCache *cache, ShadeSample *ssamp, StrandSegment *sseg, StrandVert *svert) -{ - StrandCacheEntry *entry; - StrandPoint p; - int *refcount; - GHashPair pair = strand_shade_hash_pair(sseg->obi, svert); - - entry= BLI_ghash_lookup(cache->resulthash, &pair); - refcount= BLI_ghash_lookup(cache->refcounthash, &pair); - - if (!entry) { - /* not shaded yet, shade and insert into hash */ - p.t= (sseg->v[1] == svert)? 0.0f: 1.0f; - strand_eval_point(sseg, &p); - strand_shade_point(re, ssamp, sseg, svert, &p); - - entry= MEM_callocN(sizeof(StrandCacheEntry), "StrandCacheEntry"); - entry->pair = pair; - entry->shr = ssamp->shr[0]; - BLI_ghash_insert(cache->resulthash, entry, entry); - } - else - /* already shaded, just copy previous result from hash */ - ssamp->shr[0]= entry->shr; - - /* lower reference count and remove if not needed anymore by any samples */ - (*refcount)--; - if (*refcount == 0) { - BLI_ghash_remove(cache->resulthash, &pair, MEM_freeN, NULL); - BLI_ghash_remove(cache->refcounthash, &pair, NULL, NULL); - } -} - -void strand_shade_segment(Render *re, StrandShadeCache *cache, StrandSegment *sseg, ShadeSample *ssamp, float t, float s, int addpassflag) -{ - ShadeResult shr1, shr2; - - /* get shading for two endpoints and interpolate */ - strand_shade_get(re, cache, ssamp, sseg, sseg->v[1]); - shr1= ssamp->shr[0]; - strand_shade_get(re, cache, ssamp, sseg, sseg->v[2]); - shr2= ssamp->shr[0]; - - interpolate_shade_result(&shr1, &shr2, t, ssamp->shr, addpassflag); - - /* apply alpha along width */ - if (sseg->buffer->widthfade != -1.0f) { - s = 1.0f - powf(fabsf(s), sseg->buffer->widthfade); - - strand_apply_shaderesult_alpha(ssamp->shr, s); - } -} - -void strand_shade_unref(StrandShadeCache *cache, ObjectInstanceRen *obi, StrandVert *svert) -{ - GHashPair pair = strand_shade_hash_pair(obi, svert); - int *refcount; - - /* lower reference count and remove if not needed anymore by any samples */ - refcount= BLI_ghash_lookup(cache->refcounthash, &pair); - - (*refcount)--; - if (*refcount == 0) { - BLI_ghash_remove(cache->resulthash, &pair, MEM_freeN, NULL); - BLI_ghash_remove(cache->refcounthash, &pair, NULL, NULL); - } -} - -static void strand_shade_refcount(StrandShadeCache *cache, StrandSegment *sseg, StrandVert *svert) -{ - GHashPair pair = strand_shade_hash_pair(sseg->obi, svert); - GHashPair *key; - int *refcount= BLI_ghash_lookup(cache->refcounthash, &pair); - - if (!refcount) { - key= BLI_memarena_alloc(cache->memarena, sizeof(GHashPair)); - *key = pair; - refcount= BLI_memarena_alloc(cache->memarena, sizeof(int)); - *refcount= 1; - BLI_ghash_insert(cache->refcounthash, key, refcount); - } - else - (*refcount)++; -} - -/* *************** */ - -typedef struct StrandPart { - Render *re; - ZSpan *zspan; - - APixstrand *apixbuf; - int *totapixbuf; - int *rectz; - int *rectmask; - intptr_t *rectdaps; - int rectx, recty; - int sample; - int shadow; - float (*jit)[2]; - int samples; - - StrandSegment *segment; - float t[3], s[3]; - - StrandShadeCache *cache; -} StrandPart; - -typedef struct StrandSortSegment { - struct StrandSortSegment *next; - int obi, strand, segment; - float z; -} StrandSortSegment; - -static int compare_strand_segment(const void *poin1, const void *poin2) -{ - const StrandSortSegment *seg1= (const StrandSortSegment*)poin1; - const StrandSortSegment *seg2= (const StrandSortSegment*)poin2; - - if (seg1->z < seg2->z) - return -1; - else if (seg1->z == seg2->z) - return 0; - else - return 1; -} - -static void do_strand_point_project(float winmat[4][4], ZSpan *zspan, float *co, float *hoco, float *zco) -{ - projectvert(co, winmat, hoco); - hoco_to_zco(zspan, zco, hoco); -} - -static void strand_project_point(float winmat[4][4], float winx, float winy, StrandPoint *spoint) -{ - float div; - - projectvert(spoint->co, winmat, spoint->hoco); - - div= 1.0f/spoint->hoco[3]; - spoint->x= spoint->hoco[0]*div*winx*0.5f; - spoint->y= spoint->hoco[1]*div*winy*0.5f; -} - -static APixstrand *addpsmainAstrand(ListBase *lb) -{ - APixstrMain *psm; - - psm= MEM_mallocN(sizeof(APixstrMain), "addpsmainA"); - BLI_addtail(lb, psm); - psm->ps = MEM_callocN(4096 * sizeof(APixstrand), "pixstr"); - - return psm->ps; -} - -static APixstrand *addpsAstrand(ZSpan *zspan) -{ - /* make new PS */ - if (zspan->apstrandmcounter==0) { - zspan->curpstrand= addpsmainAstrand(zspan->apsmbase); - zspan->apstrandmcounter= 4095; - } - else { - zspan->curpstrand++; - zspan->apstrandmcounter--; - } - return zspan->curpstrand; -} - -#define MAX_ZROW 2000 - -static void do_strand_fillac(void *handle, int x, int y, float u, float v, float z) -{ - StrandPart *spart= (StrandPart *)handle; - StrandShadeCache *cache= spart->cache; - StrandSegment *sseg= spart->segment; - APixstrand *apn, *apnew; - float t, s; - int offset, mask, obi, strnr, seg, zverg, bufferz, maskz=0; - - offset = y*spart->rectx + x; - obi= sseg->obi - spart->re->objectinstance; - strnr= sseg->strand->index + 1; - seg= sseg->v[1] - sseg->strand->vert; - mask= (1<<spart->sample); - - /* check against solid z-buffer */ - zverg= (int)z; - - if (spart->rectdaps) { - /* find the z of the sample */ - PixStr *ps; - intptr_t *rd= spart->rectdaps + offset; - - bufferz= 0x7FFFFFFF; - if (spart->rectmask) maskz= 0x7FFFFFFF; - - if (*rd) { - for (ps= (PixStr *)(*rd); ps; ps= ps->next) { - if (mask & ps->mask) { - bufferz= ps->z; - if (spart->rectmask) - maskz= ps->maskz; - break; - } - } - } - } - else { - bufferz= (spart->rectz)? spart->rectz[offset]: 0x7FFFFFFF; - if (spart->rectmask) - maskz= spart->rectmask[offset]; - } - -#define CHECK_ADD(n) \ - if (apn->p[n]==strnr && apn->obi[n]==obi && apn->seg[n]==seg) \ - { if (!(apn->mask[n] & mask)) { apn->mask[n] |= mask; apn->v[n] += t; apn->u[n] += s; } break; } (void)0 -#define CHECK_ASSIGN(n) \ - if (apn->p[n]==0) \ - {apn->obi[n]= obi; apn->p[n]= strnr; apn->z[n]= zverg; apn->mask[n]= mask; apn->v[n]= t; apn->u[n]= s; apn->seg[n]= seg; break; } (void)0 - - /* add to pixel list */ - if (zverg < bufferz && (spart->totapixbuf[offset] < MAX_ZROW)) { - if (!spart->rectmask || zverg > maskz) { - t = u * spart->t[0] + v * spart->t[1] + (1.0f - u - v) * spart->t[2]; - s = fabsf(u * spart->s[0] + v * spart->s[1] + (1.0f - u - v) * spart->s[2]); - - apn= spart->apixbuf + offset; - while (apn) { - CHECK_ADD(0); - CHECK_ADD(1); - CHECK_ADD(2); - CHECK_ADD(3); - CHECK_ASSIGN(0); - CHECK_ASSIGN(1); - CHECK_ASSIGN(2); - CHECK_ASSIGN(3); - - apnew= addpsAstrand(spart->zspan); - SWAP(APixstrand, *apnew, *apn); - apn->next= apnew; - CHECK_ASSIGN(0); - } - - if (cache) { - strand_shade_refcount(cache, sseg, sseg->v[1]); - strand_shade_refcount(cache, sseg, sseg->v[2]); - } - spart->totapixbuf[offset]++; - } - } -} - -/* width is calculated in hoco space, to ensure strands are visible */ -static int strand_test_clip(float winmat[4][4], ZSpan *UNUSED(zspan), float *bounds, float *co, float *zcomp, float widthx, float widthy) -{ - float hoco[4]; - int clipflag= 0; - - projectvert(co, winmat, hoco); - - /* we compare z without perspective division for segment sorting */ - *zcomp= hoco[2]; - - if (hoco[0]+widthx < bounds[0]*hoco[3]) clipflag |= 1; - else if (hoco[0]-widthx > bounds[1]*hoco[3]) clipflag |= 2; - - if (hoco[1]-widthy > bounds[3]*hoco[3]) clipflag |= 4; - else if (hoco[1]+widthy < bounds[2]*hoco[3]) clipflag |= 8; - - clipflag |= testclip(hoco); - - return clipflag; -} - -static void do_scanconvert_strand(Render *UNUSED(re), StrandPart *spart, ZSpan *zspan, float t, float dt, float *co1, float *co2, float *co3, float *co4, int sample) -{ - float jco1[3], jco2[3], jco3[3], jco4[3], jx, jy; - - copy_v3_v3(jco1, co1); - copy_v3_v3(jco2, co2); - copy_v3_v3(jco3, co3); - copy_v3_v3(jco4, co4); - - if (spart->jit) { - jx= -spart->jit[sample][0]; - jy= -spart->jit[sample][1]; - - jco1[0] += jx; jco1[1] += jy; - jco2[0] += jx; jco2[1] += jy; - jco3[0] += jx; jco3[1] += jy; - jco4[0] += jx; jco4[1] += jy; - - /* XXX mblur? */ - } - - spart->sample= sample; - - spart->t[0]= t-dt; - spart->s[0]= -1.0f; - spart->t[1]= t-dt; - spart->s[1]= 1.0f; - spart->t[2]= t; - spart->s[2]= 1.0f; - zspan_scanconvert_strand(zspan, spart, jco1, jco2, jco3, do_strand_fillac); - spart->t[0]= t-dt; - spart->s[0]= -1.0f; - spart->t[1]= t; - spart->s[1]= 1.0f; - spart->t[2]= t; - spart->s[2]= -1.0f; - zspan_scanconvert_strand(zspan, spart, jco1, jco3, jco4, do_strand_fillac); -} - -static void strand_render(Render *re, StrandSegment *sseg, float winmat[4][4], StrandPart *spart, ZSpan *zspan, int totzspan, StrandPoint *p1, StrandPoint *p2) -{ - if (spart) { - float t= p2->t; - float dt= p2->t - p1->t; - int a; - - for (a=0; a<spart->samples; a++) - do_scanconvert_strand(re, spart, zspan, t, dt, p1->zco2, p1->zco1, p2->zco1, p2->zco2, a); - } - else { - float hoco1[4], hoco2[4]; - int a, obi, index; - - obi= sseg->obi - re->objectinstance; - index= sseg->strand->index; - - projectvert(p1->co, winmat, hoco1); - projectvert(p2->co, winmat, hoco2); - - - for (a=0; a<totzspan; a++) { -#if 0 - /* render both strand and single pixel wire to counter aliasing */ - zbufclip4(re, &zspan[a], obi, index, p1->hoco2, p1->hoco1, p2->hoco1, p2->hoco2, p1->clip2, p1->clip1, p2->clip1, p2->clip2); -#endif - /* only render a line for now, which makes the shadow map more - * similar across frames, and so reduces flicker */ - zbufsinglewire(&zspan[a], obi, index, hoco1, hoco2); - } - } -} - -static int strand_segment_recursive(Render *re, float winmat[4][4], StrandPart *spart, ZSpan *zspan, int totzspan, StrandSegment *sseg, StrandPoint *p1, StrandPoint *p2, int depth) -{ - StrandPoint p; - StrandBuffer *buffer= sseg->buffer; - float dot, d1[2], d2[2], len1, len2; - - if (depth == buffer->maxdepth) - return 0; - - p.t= (p1->t + p2->t)*0.5f; - strand_eval_point(sseg, &p); - strand_project_point(buffer->winmat, buffer->winx, buffer->winy, &p); - - d1[0]= (p.x - p1->x); - d1[1]= (p.y - p1->y); - len1= d1[0]*d1[0] + d1[1]*d1[1]; - - d2[0]= (p2->x - p.x); - d2[1]= (p2->y - p.y); - len2= d2[0]*d2[0] + d2[1]*d2[1]; - - if (len1 == 0.0f || len2 == 0.0f) - return 0; - - dot= d1[0]*d2[0] + d1[1]*d2[1]; - if (dot*dot > sseg->sqadaptcos*len1*len2) - return 0; - - if (spart) { - do_strand_point_project(winmat, zspan, p.co1, p.hoco1, p.zco1); - do_strand_point_project(winmat, zspan, p.co2, p.hoco2, p.zco2); - } - else { -#if 0 - projectvert(p.co1, winmat, p.hoco1); - projectvert(p.co2, winmat, p.hoco2); - p.clip1= testclip(p.hoco1); - p.clip2= testclip(p.hoco2); -#endif - } - - if (!strand_segment_recursive(re, winmat, spart, zspan, totzspan, sseg, p1, &p, depth+1)) - strand_render(re, sseg, winmat, spart, zspan, totzspan, p1, &p); - if (!strand_segment_recursive(re, winmat, spart, zspan, totzspan, sseg, &p, p2, depth+1)) - strand_render(re, sseg, winmat, spart, zspan, totzspan, &p, p2); - - return 1; -} - -void render_strand_segment(Render *re, float winmat[4][4], StrandPart *spart, ZSpan *zspan, int totzspan, StrandSegment *sseg) -{ - StrandBuffer *buffer= sseg->buffer; - StrandPoint *p1= &sseg->point1; - StrandPoint *p2= &sseg->point2; - - p1->t= 0.0f; - p2->t= 1.0f; - - strand_eval_point(sseg, p1); - strand_project_point(buffer->winmat, buffer->winx, buffer->winy, p1); - strand_eval_point(sseg, p2); - strand_project_point(buffer->winmat, buffer->winx, buffer->winy, p2); - - if (spart) { - do_strand_point_project(winmat, zspan, p1->co1, p1->hoco1, p1->zco1); - do_strand_point_project(winmat, zspan, p1->co2, p1->hoco2, p1->zco2); - do_strand_point_project(winmat, zspan, p2->co1, p2->hoco1, p2->zco1); - do_strand_point_project(winmat, zspan, p2->co2, p2->hoco2, p2->zco2); - } - else { -#if 0 - projectvert(p1->co1, winmat, p1->hoco1); - projectvert(p1->co2, winmat, p1->hoco2); - projectvert(p2->co1, winmat, p2->hoco1); - projectvert(p2->co2, winmat, p2->hoco2); - p1->clip1= testclip(p1->hoco1); - p1->clip2= testclip(p1->hoco2); - p2->clip1= testclip(p2->hoco1); - p2->clip2= testclip(p2->hoco2); -#endif - } - - if (!strand_segment_recursive(re, winmat, spart, zspan, totzspan, sseg, p1, p2, 0)) - strand_render(re, sseg, winmat, spart, zspan, totzspan, p1, p2); -} - -/* render call to fill in strands */ -int zbuffer_strands_abuf(Render *re, RenderPart *pa, APixstrand *apixbuf, ListBase *apsmbase, unsigned int lay, int UNUSED(negzmask), float winmat[4][4], int winx, int winy, int samples, float (*jit)[2], float clipcrop, int shadow, StrandShadeCache *cache) -{ - ObjectRen *obr; - ObjectInstanceRen *obi; - ZSpan zspan; - StrandRen *strand = NULL; - StrandVert *svert; - StrandBound *sbound; - StrandPart spart; - StrandSegment sseg; - StrandSortSegment *sortsegments = NULL, *sortseg, *firstseg; - MemArena *memarena; - float z[4], bounds[4], obwinmat[4][4]; - int a, b, c, i, totsegment, clip[4]; - - if (re->test_break(re->tbh)) - return 0; - if (re->totstrand == 0) - return 0; - - /* setup StrandPart */ - memset(&spart, 0, sizeof(spart)); - - spart.re= re; - spart.rectx= pa->rectx; - spart.recty= pa->recty; - spart.apixbuf= apixbuf; - spart.zspan= &zspan; - spart.rectdaps= pa->rectdaps; - spart.rectz= pa->rectz; - spart.rectmask= pa->rectmask; - spart.cache= cache; - spart.shadow= shadow; - spart.jit= jit; - spart.samples= samples; - - zbuf_alloc_span(&zspan, pa->rectx, pa->recty, clipcrop); - - /* needed for transform from hoco to zbuffer co */ - zspan.zmulx= ((float)winx)/2.0f; - zspan.zmuly= ((float)winy)/2.0f; - - zspan.zofsx= -pa->disprect.xmin; - zspan.zofsy= -pa->disprect.ymin; - - /* to center the sample position */ - if (!shadow) { - zspan.zofsx -= 0.5f; - zspan.zofsy -= 0.5f; - } - - zspan.apsmbase= apsmbase; - - /* clipping setup */ - bounds[0]= (2*pa->disprect.xmin - winx-1)/(float)winx; - bounds[1]= (2*pa->disprect.xmax - winx+1)/(float)winx; - bounds[2]= (2*pa->disprect.ymin - winy-1)/(float)winy; - bounds[3]= (2*pa->disprect.ymax - winy+1)/(float)winy; - - memarena= BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "strand sort arena"); - firstseg= NULL; - totsegment= 0; - - /* for all object instances */ - for (obi=re->instancetable.first, i=0; obi; obi=obi->next, i++) { - Material *ma; - float widthx, widthy; - - obr= obi->obr; - - if (!obr->strandbuf || !(obr->strandbuf->lay & lay)) - continue; - - /* compute matrix and try clipping whole object */ - if (obi->flag & R_TRANSFORMED) - mul_m4_m4m4(obwinmat, winmat, obi->mat); - else - copy_m4_m4(obwinmat, winmat); - - /* test if we should skip it */ - ma = obr->strandbuf->ma; - - if (shadow && (!(ma->mode2 & MA_CASTSHADOW) || !(ma->mode & MA_SHADBUF))) - continue; - else if (!shadow && (ma->mode & MA_ONLYCAST)) - continue; - - if (clip_render_object(obi->obr->boundbox, bounds, obwinmat)) - continue; - - widthx= obr->strandbuf->maxwidth*obwinmat[0][0]; - widthy= obr->strandbuf->maxwidth*obwinmat[1][1]; - - /* for each bounding box containing a number of strands */ - sbound= obr->strandbuf->bound; - for (c=0; c<obr->strandbuf->totbound; c++, sbound++) { - if (clip_render_object(sbound->boundbox, bounds, obwinmat)) - continue; - - /* for each strand in this bounding box */ - for (a=sbound->start; a<sbound->end; a++) { - strand= RE_findOrAddStrand(obr, a); - svert= strand->vert; - - /* keep clipping and z depth for 4 control points */ - clip[1]= strand_test_clip(obwinmat, &zspan, bounds, svert->co, &z[1], widthx, widthy); - clip[2]= strand_test_clip(obwinmat, &zspan, bounds, (svert+1)->co, &z[2], widthx, widthy); - clip[0]= clip[1]; z[0]= z[1]; - - for (b=0; b<strand->totvert-1; b++, svert++) { - /* compute 4th point clipping and z depth */ - if (b < strand->totvert-2) { - clip[3]= strand_test_clip(obwinmat, &zspan, bounds, (svert+2)->co, &z[3], widthx, widthy); - } - else { - clip[3]= clip[2]; z[3]= z[2]; - } - - /* check clipping and add to sortsegments buffer */ - if (!(clip[0] & clip[1] & clip[2] & clip[3])) { - sortseg= BLI_memarena_alloc(memarena, sizeof(StrandSortSegment)); - sortseg->obi= i; - sortseg->strand= strand->index; - sortseg->segment= b; - - sortseg->z= 0.5f*(z[1] + z[2]); - - sortseg->next= firstseg; - firstseg= sortseg; - totsegment++; - } - - /* shift clipping and z depth */ - clip[0]= clip[1]; z[0]= z[1]; - clip[1]= clip[2]; z[1]= z[2]; - clip[2]= clip[3]; z[2]= z[3]; - } - } - } - } - - if (!re->test_break(re->tbh)) { - /* convert list to array and sort */ - sortsegments= MEM_mallocN(sizeof(StrandSortSegment)*totsegment, "StrandSortSegment"); - for (a=0, sortseg=firstseg; a<totsegment; a++, sortseg=sortseg->next) - sortsegments[a]= *sortseg; - qsort(sortsegments, totsegment, sizeof(StrandSortSegment), compare_strand_segment); - } - - BLI_memarena_free(memarena); - - spart.totapixbuf= MEM_callocN(sizeof(int)*pa->rectx*pa->recty, "totapixbuf"); - - if (!re->test_break(re->tbh)) { - /* render segments in sorted order */ - sortseg= sortsegments; - for (a=0; a<totsegment; a++, sortseg++) { - if (re->test_break(re->tbh)) - break; - - obi= &re->objectinstance[sortseg->obi]; - obr= obi->obr; - - sseg.obi= obi; - sseg.strand= RE_findOrAddStrand(obr, sortseg->strand); - sseg.buffer= sseg.strand->buffer; - sseg.sqadaptcos= sseg.buffer->adaptcos; - sseg.sqadaptcos *= sseg.sqadaptcos; - - svert= sseg.strand->vert + sortseg->segment; - sseg.v[0]= (sortseg->segment > 0)? (svert-1): svert; - sseg.v[1]= svert; - sseg.v[2]= svert+1; - sseg.v[3]= (sortseg->segment < sseg.strand->totvert-2)? svert+2: svert+1; - sseg.shaded= 0; - - spart.segment= &sseg; - - render_strand_segment(re, winmat, &spart, &zspan, 1, &sseg); - } - } - - if (sortsegments) - MEM_freeN(sortsegments); - MEM_freeN(spart.totapixbuf); - - zbuf_free_span(&zspan); - - return totsegment; -} - -/* *************** */ - -StrandSurface *cache_strand_surface(Render *re, ObjectRen *obr, DerivedMesh *dm, float mat[4][4], int timeoffset) -{ - StrandSurface *mesh; - MFace *mface; - MVert *mvert; - float (*co)[3]; - int a, totvert, totface; - - totvert= dm->getNumVerts(dm); - totface= dm->getNumTessFaces(dm); - - for (mesh = re->strandsurface.first; mesh; mesh = mesh->next) { - if ((mesh->obr.ob == obr->ob) && - (mesh->obr.par == obr->par) && - (mesh->obr.index == obr->index) && - (mesh->totvert == totvert) && - (mesh->totface == totface)) - { - break; - } - } - - if (!mesh) { - mesh= MEM_callocN(sizeof(StrandSurface), "StrandSurface"); - mesh->obr= *obr; - mesh->totvert= totvert; - mesh->totface= totface; - mesh->face= MEM_callocN(sizeof(int)*4*mesh->totface, "StrandSurfFaces"); - mesh->ao= MEM_callocN(sizeof(float)*3*mesh->totvert, "StrandSurfAO"); - mesh->env= MEM_callocN(sizeof(float)*3*mesh->totvert, "StrandSurfEnv"); - mesh->indirect= MEM_callocN(sizeof(float)*3*mesh->totvert, "StrandSurfIndirect"); - BLI_addtail(&re->strandsurface, mesh); - } - - if (timeoffset == -1 && !mesh->prevco) - mesh->prevco= co= MEM_callocN(sizeof(float)*3*mesh->totvert, "StrandSurfCo"); - else if (timeoffset == 0 && !mesh->co) - mesh->co= co= MEM_callocN(sizeof(float)*3*mesh->totvert, "StrandSurfCo"); - else if (timeoffset == 1 && !mesh->nextco) - mesh->nextco= co= MEM_callocN(sizeof(float)*3*mesh->totvert, "StrandSurfCo"); - else - return mesh; - - mvert= dm->getVertArray(dm); - for (a=0; a<mesh->totvert; a++, mvert++) { - copy_v3_v3(co[a], mvert->co); - mul_m4_v3(mat, co[a]); - } - - mface= dm->getTessFaceArray(dm); - for (a=0; a<mesh->totface; a++, mface++) { - mesh->face[a][0]= mface->v1; - mesh->face[a][1]= mface->v2; - mesh->face[a][2]= mface->v3; - mesh->face[a][3]= mface->v4; - } - - return mesh; -} - -void free_strand_surface(Render *re) -{ - StrandSurface *mesh; - - for (mesh=re->strandsurface.first; mesh; mesh=mesh->next) { - if (mesh->co) MEM_freeN(mesh->co); - if (mesh->prevco) MEM_freeN(mesh->prevco); - if (mesh->nextco) MEM_freeN(mesh->nextco); - if (mesh->ao) MEM_freeN(mesh->ao); - if (mesh->env) MEM_freeN(mesh->env); - if (mesh->indirect) MEM_freeN(mesh->indirect); - if (mesh->face) MEM_freeN(mesh->face); - } - - BLI_freelistN(&re->strandsurface); -} - -void strand_minmax(StrandRen *strand, float min[3], float max[3], const float width) -{ - StrandVert *svert; - const float width2 = width * 2.0f; - float vec[3]; - int a; - - for (a=0, svert=strand->vert; a<strand->totvert; a++, svert++) { - copy_v3_v3(vec, svert->co); - minmax_v3v3_v3(min, max, vec); - - if (width!=0.0f) { - add_v3_fl(vec, width); - minmax_v3v3_v3(min, max, vec); - add_v3_fl(vec, -width2); - minmax_v3v3_v3(min, max, vec); - } - } -} - diff --git a/source/blender/render/intern/source/sunsky.c b/source/blender/render/intern/source/sunsky.c deleted file mode 100644 index 80dd52c220c..00000000000 --- a/source/blender/render/intern/source/sunsky.c +++ /dev/null @@ -1,506 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/render/intern/source/sunsky.c - * \ingroup render - * - * This feature comes from Preetham paper on "A Practical Analytic Model for Daylight" - * and example code from Brian Smits, another author of that paper in - * http://www.cs.utah.edu/vissim/papers/sunsky/code/ - */ - -#include "sunsky.h" -#include "BLI_math.h" - -/** - * These macros are defined for vector operations - * */ - -/** - * compute v1 = v2 op v3 - * v1, v2 and v3 are vectors contains 3 float - * */ -#define VEC3OPV(v1, v2, op, v3) \ - { \ - v1[0] = (v2[0] op v3[0]); \ - v1[1] = (v2[1] op v3[1]); \ - v1[2] = (v2[2] op v3[2]); \ - } (void)0 - -/** - * compute v1 = v2 op f1 - * v1, v2 are vectors contains 3 float - * and f1 is a float - * */ -#define VEC3OPF(v1, v2, op, f1) \ - { \ - v1[0] = (v2[0] op(f1)); \ - v1[1] = (v2[1] op(f1)); \ - v1[2] = (v2[2] op(f1)); \ - } (void)0 - -/** - * compute v1 = f1 op v2 - * v1, v2 are vectors contains 3 float - * and f1 is a float - * */ -#define FOPVEC3(v1, f1, op, v2) \ - { \ - v1[0] = ((f1) op v2[0]); \ - v1[1] = ((f1) op v2[1]); \ - v1[2] = ((f1) op v2[2]); \ - } (void)0 - -/** - * ClipColor: - * clip a color to range [0, 1]; - * */ -void ClipColor(float c[3]) -{ - if (c[0] > 1.0f) c[0] = 1.0f; - if (c[0] < 0.0f) c[0] = 0.0f; - if (c[1] > 1.0f) c[1] = 1.0f; - if (c[1] < 0.0f) c[1] = 0.0f; - if (c[2] > 1.0f) c[2] = 1.0f; - if (c[2] < 0.0f) c[2] = 0.0f; -} - -/** - * AngleBetween: - * compute angle between to direction - * all angles are in radians - * */ -static float AngleBetween(float thetav, float phiv, float theta, float phi) -{ - float cospsi = sinf(thetav) * sinf(theta) * cosf(phi - phiv) + cosf(thetav) * cosf(theta); - - if (cospsi > 1.0f) - return 0; - if (cospsi < -1.0f) - return M_PI; - - return acosf(cospsi); -} - -/** - * DirectionToThetaPhi: - * this function convert a direction to it's theta and phi value - * parameters: - * toSun: contains direction information - * theta, phi, are return values from this conversion - * */ -static void DirectionToThetaPhi(float *toSun, float *theta, float *phi) -{ - *theta = acosf(toSun[2]); - if (fabsf(*theta) < 1e-5f) - *phi = 0; - else - *phi = atan2f(toSun[1], toSun[0]); -} - -/** - * PerezFunction: - * compute perez function value based on input parameters - */ -static float PerezFunction(struct SunSky *sunsky, const float *lam, float theta, float gamma, float lvz) -{ - float den, num; - - den = ((1 + lam[0] * expf(lam[1])) * - (1 + lam[2] * expf(lam[3] * sunsky->theta) + lam[4] * cosf(sunsky->theta) * cosf(sunsky->theta))); - - num = ((1 + lam[0] * expf(lam[1] / cosf(theta))) * - (1 + lam[2] * expf(lam[3] * gamma) + lam[4] * cosf(gamma) * cosf(gamma))); - - return(lvz * num / den); -} - -/** - * InitSunSky: - * this function compute some sun,sky parameters according to input parameters and also initiate some other sun, sky parameters - * parameters: - * sunSky, is a structure that contains information about sun, sky and atmosphere, in this function, most of its values initiated - * turb, is atmosphere turbidity - * toSun, contains sun direction - * horizon_brighness, controls the brightness of the horizon colors - * spread, controls colors spreed at horizon - * sun_brightness, controls sun's brightness - * sun_size, controls sun's size - * back_scatter, controls back scatter light - * */ -void InitSunSky(struct SunSky *sunsky, float turb, const float toSun[3], float horizon_brightness, - float spread, float sun_brightness, float sun_size, float back_scatter, - float skyblendfac, short skyblendtype, float sky_exposure, float sky_colorspace) -{ - float theta2; - float theta3; - float T; - float T2; - float chi; - - sunsky->turbidity = turb; - - sunsky->horizon_brightness = horizon_brightness; - sunsky->spread = spread; - sunsky->sun_brightness = sun_brightness; - sunsky->sun_size = sun_size; - sunsky->backscattered_light = back_scatter; - sunsky->skyblendfac = skyblendfac; - sunsky->skyblendtype = skyblendtype; - sunsky->sky_exposure = -sky_exposure; - sunsky->sky_colorspace = sky_colorspace; - - sunsky->toSun[0] = toSun[0]; - sunsky->toSun[1] = toSun[1]; - sunsky->toSun[2] = toSun[2]; - - DirectionToThetaPhi(sunsky->toSun, &sunsky->theta, &sunsky->phi); - - sunsky->sunSolidAngle = 0.25 * M_PI * 1.39 * 1.39 / (150 * 150); /* = 6.7443e-05 */ - - theta2 = sunsky->theta * sunsky->theta; - theta3 = theta2 * sunsky->theta; - T = turb; - T2 = turb * turb; - - chi = (4.0f / 9.0f - T / 120.0f) * ((float)M_PI - 2.0f * sunsky->theta); - sunsky->zenith_Y = (4.0453f * T - 4.9710f) * tanf(chi) - 0.2155f * T + 2.4192f; - sunsky->zenith_Y *= 1000; /* conversion from kcd/m^2 to cd/m^2 */ - - if (sunsky->zenith_Y <= 0) - sunsky->zenith_Y = 1e-6; - - sunsky->zenith_x = - (+0.00165f * theta3 - 0.00374f * theta2 + 0.00208f * sunsky->theta + 0.0f) * T2 + - (-0.02902f * theta3 + 0.06377f * theta2 - 0.03202f * sunsky->theta + 0.00394f) * T + - (+0.11693f * theta3 - 0.21196f * theta2 + 0.06052f * sunsky->theta + 0.25885f); - - sunsky->zenith_y = - (+0.00275f * theta3 - 0.00610f * theta2 + 0.00316f * sunsky->theta + 0.0f) * T2 + - (-0.04214f * theta3 + 0.08970f * theta2 - 0.04153f * sunsky->theta + 0.00515f) * T + - (+0.15346f * theta3 - 0.26756f * theta2 + 0.06669f * sunsky->theta + 0.26688f); - - - sunsky->perez_Y[0] = 0.17872f * T - 1.46303f; - sunsky->perez_Y[1] = -0.35540f * T + 0.42749f; - sunsky->perez_Y[2] = -0.02266f * T + 5.32505f; - sunsky->perez_Y[3] = 0.12064f * T - 2.57705f; - sunsky->perez_Y[4] = -0.06696f * T + 0.37027f; - - sunsky->perez_x[0] = -0.01925f * T - 0.25922f; - sunsky->perez_x[1] = -0.06651f * T + 0.00081f; - sunsky->perez_x[2] = -0.00041f * T + 0.21247f; - sunsky->perez_x[3] = -0.06409f * T - 0.89887f; - sunsky->perez_x[4] = -0.00325f * T + 0.04517f; - - sunsky->perez_y[0] = -0.01669f * T - 0.26078f; - sunsky->perez_y[1] = -0.09495f * T + 0.00921f; - sunsky->perez_y[2] = -0.00792f * T + 0.21023f; - sunsky->perez_y[3] = -0.04405f * T - 1.65369f; - sunsky->perez_y[4] = -0.01092f * T + 0.05291f; - - /* suggested by glome in patch [#8063] */ - sunsky->perez_Y[0] *= sunsky->horizon_brightness; - sunsky->perez_x[0] *= sunsky->horizon_brightness; - sunsky->perez_y[0] *= sunsky->horizon_brightness; - - sunsky->perez_Y[1] *= sunsky->spread; - sunsky->perez_x[1] *= sunsky->spread; - sunsky->perez_y[1] *= sunsky->spread; - - sunsky->perez_Y[2] *= sunsky->sun_brightness; - sunsky->perez_x[2] *= sunsky->sun_brightness; - sunsky->perez_y[2] *= sunsky->sun_brightness; - - sunsky->perez_Y[3] *= sunsky->sun_size; - sunsky->perez_x[3] *= sunsky->sun_size; - sunsky->perez_y[3] *= sunsky->sun_size; - - sunsky->perez_Y[4] *= sunsky->backscattered_light; - sunsky->perez_x[4] *= sunsky->backscattered_light; - sunsky->perez_y[4] *= sunsky->backscattered_light; -} - -/** - * GetSkyXYZRadiance: - * this function compute sky radiance according to a view parameters `theta' and `phi'and sunSky values - * parameters: - * sunSky, sontains sun and sky parameters - * theta, is sun's theta - * phi, is sun's phi - * color_out, is computed color that shows sky radiance in XYZ color format - * */ -void GetSkyXYZRadiance(struct SunSky *sunsky, float theta, float phi, float color_out[3]) -{ - float gamma; - float x, y, Y, X, Z; - float hfade = 1, nfade = 1; - - - if (theta > (float)M_PI_2) { - hfade = 1.0f - (theta * (float)M_1_PI - 0.5f) * 2.0f; - hfade = hfade * hfade * (3.0f - 2.0f * hfade); - theta = M_PI_2; - } - - if (sunsky->theta > (float)M_PI_2) { - if (theta <= (float)M_PI_2) { - nfade = 1.0f - (0.5f - theta * (float)M_1_PI) * 2.0f; - nfade *= 1.0f - (sunsky->theta * (float)M_1_PI - 0.5f) * 2.0f; - nfade = nfade * nfade * (3.0f - 2.0f * nfade); - } - } - - gamma = AngleBetween(theta, phi, sunsky->theta, sunsky->phi); - - /* Compute xyY values */ - x = PerezFunction(sunsky, sunsky->perez_x, theta, gamma, sunsky->zenith_x); - y = PerezFunction(sunsky, sunsky->perez_y, theta, gamma, sunsky->zenith_y); - Y = 6.666666667e-5f * nfade * hfade * PerezFunction(sunsky, sunsky->perez_Y, theta, gamma, sunsky->zenith_Y); - - if (sunsky->sky_exposure != 0.0f) - Y = 1.0 - exp(Y * sunsky->sky_exposure); - - X = (x / y) * Y; - Z = ((1 - x - y) / y) * Y; - - color_out[0] = X; - color_out[1] = Y; - color_out[2] = Z; -} - -/** - * GetSkyXYZRadiancef: - * this function compute sky radiance according to a view direction `varg' and sunSky values - * parameters: - * sunSky, sontains sun and sky parameters - * varg, shows direction - * color_out, is computed color that shows sky radiance in XYZ color format - * */ -void GetSkyXYZRadiancef(struct SunSky *sunsky, const float varg[3], float color_out[3]) -{ - float theta, phi; - float v[3]; - - normalize_v3_v3(v, varg); - - if (v[2] < 0.001f) { - v[2] = 0.001f; - normalize_v3(v); - } - - DirectionToThetaPhi(v, &theta, &phi); - GetSkyXYZRadiance(sunsky, theta, phi, color_out); -} - -/** - * ComputeAttenuatedSunlight: - * this function compute attenuated sun light based on sun's theta and atmosphere turbidity - * parameters: - * theta, is sun's theta - * turbidity: is atmosphere turbidity - * fTau: contains computed attenuated sun light - * */ -static void ComputeAttenuatedSunlight(float theta, int turbidity, float fTau[3]) -{ - float fBeta; - float fTauR, fTauA; - float m; - float fAlpha; - - int i; - float fLambda[3]; - fLambda[0] = 0.65f; - fLambda[1] = 0.57f; - fLambda[2] = 0.475f; - - fAlpha = 1.3f; - fBeta = 0.04608365822050f * turbidity - 0.04586025928522f; - - m = 1.0f / (cosf(theta) + 0.15f * powf(93.885f - theta / (float)M_PI * 180.0f, -1.253f)); - - for (i = 0; i < 3; i++) { - /* Rayleigh Scattering */ - fTauR = expf(-m * 0.008735f * powf(fLambda[i], (float)(-4.08f))); - - /* Aerosal (water + dust) attenuation */ - fTauA = exp(-m * fBeta * powf(fLambda[i], -fAlpha)); - - fTau[i] = fTauR * fTauA; - } -} - -/** - * InitAtmosphere: - * this function initiate sunSky structure with user input parameters. - * parameters: - * sunSky, contains information about sun, and in this function some atmosphere parameters will initiated - * sun_intens, shows sun intensity value - * mief, Mie scattering factor this factor currently call with 1.0 - * rayf, Rayleigh scattering factor, this factor currently call with 1.0 - * inscattf, inscatter light factor that range from 0.0 to 1.0, 0.0 means no inscatter light and 1.0 means full inscatter light - * extincf, extinction light factor that range from 0.0 to 1.0, 0.0 means no extinction and 1.0 means full extinction - * disf, is distance factor, multiplied to pixle's z value to compute each pixle's distance to camera, - * */ -void InitAtmosphere(struct SunSky *sunSky, float sun_intens, float mief, float rayf, - float inscattf, float extincf, float disf) -{ - const float pi = M_PI; - const float n = 1.003f; /* refractive index */ - const float N = 2.545e25; - const float pn = 0.035f; - const float T = 2.0f; - float fTemp, fTemp2, fTemp3, fBeta, fBetaDash; - float c = (6.544f * T - 6.51f) * 1e-17f; - float K[3] = {0.685f, 0.679f, 0.670f}; - float vBetaMieTemp[3]; - - float fLambda[3], fLambda2[3], fLambda4[3]; - float vLambda2[3]; - float vLambda4[3]; - - int i; - - sunSky->atm_SunIntensity = sun_intens; - sunSky->atm_BetaMieMultiplier = mief; - sunSky->atm_BetaRayMultiplier = rayf; - sunSky->atm_InscatteringMultiplier = inscattf; - sunSky->atm_ExtinctionMultiplier = extincf; - sunSky->atm_DistanceMultiplier = disf; - - sunSky->atm_HGg = 0.8; - - fLambda[0] = 1 / 650e-9f; - fLambda[1] = 1 / 570e-9f; - fLambda[2] = 1 / 475e-9f; - for (i = 0; i < 3; i++) { - fLambda2[i] = fLambda[i] * fLambda[i]; - fLambda4[i] = fLambda2[i] * fLambda2[i]; - } - - vLambda2[0] = fLambda2[0]; - vLambda2[1] = fLambda2[1]; - vLambda2[2] = fLambda2[2]; - - vLambda4[0] = fLambda4[0]; - vLambda4[1] = fLambda4[1]; - vLambda4[2] = fLambda4[2]; - - /* Rayleigh scattering constants. */ - fTemp = pi * pi * (n * n - 1) * (n * n - 1) * (6 + 3 * pn) / (6 - 7 * pn) / N; - fBeta = 8 * fTemp * pi / 3; - - VEC3OPF(sunSky->atm_BetaRay, vLambda4, *, fBeta); - fBetaDash = fTemp / 2; - VEC3OPF(sunSky->atm_BetaDashRay, vLambda4, *, fBetaDash); - - - /* Mie scattering constants. */ - fTemp2 = 0.434f * c * (2 * pi) * (2 * pi) * 0.5f; - VEC3OPF(sunSky->atm_BetaDashMie, vLambda2, *, fTemp2); - - fTemp3 = 0.434f * c * pi * (2 * pi) * (2 * pi); - - VEC3OPV(vBetaMieTemp, K, *, fLambda); - VEC3OPF(sunSky->atm_BetaMie, vBetaMieTemp, *, fTemp3); - -} - -/** - * AtmospherePixleShader: - * this function apply atmosphere effect on a pixle color `rgb' at distance `s' - * parameters: - * sunSky, contains information about sun parameters and user values - * view, is camera view vector - * s, is distance - * rgb, contains rendered color value for a pixle - * */ -void AtmospherePixleShader(struct SunSky *sunSky, float view[3], float s, float rgb[3]) -{ - float costheta; - float Phase_1; - float Phase_2; - float sunColor[3]; - - float E[3]; - float E1[3]; - - - float I[3]; - float fTemp; - float vTemp1[3], vTemp2[3]; - - float sunDirection[3]; - - s *= sunSky->atm_DistanceMultiplier; - - sunDirection[0] = sunSky->toSun[0]; - sunDirection[1] = sunSky->toSun[1]; - sunDirection[2] = sunSky->toSun[2]; - - costheta = dot_v3v3(view, sunDirection); /* cos(theta) */ - Phase_1 = 1 + (costheta * costheta); /* Phase_1 */ - - VEC3OPF(sunSky->atm_BetaRay, sunSky->atm_BetaRay, *, sunSky->atm_BetaRayMultiplier); - VEC3OPF(sunSky->atm_BetaMie, sunSky->atm_BetaMie, *, sunSky->atm_BetaMieMultiplier); - VEC3OPV(sunSky->atm_BetaRM, sunSky->atm_BetaRay, +, sunSky->atm_BetaMie); - - /* e^(-(beta_1 + beta_2) * s) = E1 */ - VEC3OPF(E1, sunSky->atm_BetaRM, *, -s / (float)M_LN2); - E1[0] = exp(E1[0]); - E1[1] = exp(E1[1]); - E1[2] = exp(E1[2]); - - copy_v3_v3(E, E1); - - /* Phase2(theta) = (1-g^2)/(1+g-2g*cos(theta))^(3/2) */ - fTemp = 1 + sunSky->atm_HGg - 2 * sunSky->atm_HGg * costheta; - fTemp = fTemp * sqrtf(fTemp); - Phase_2 = (1 - sunSky->atm_HGg * sunSky->atm_HGg) / fTemp; - - VEC3OPF(vTemp1, sunSky->atm_BetaDashRay, *, Phase_1); - VEC3OPF(vTemp2, sunSky->atm_BetaDashMie, *, Phase_2); - - VEC3OPV(vTemp1, vTemp1, +, vTemp2); - FOPVEC3(vTemp2, 1.0f, -, E1); - VEC3OPV(vTemp1, vTemp1, *, vTemp2); - - FOPVEC3(vTemp2, 1.0f, /, sunSky->atm_BetaRM); - - VEC3OPV(I, vTemp1, *, vTemp2); - - VEC3OPF(I, I, *, sunSky->atm_InscatteringMultiplier); - VEC3OPF(E, E, *, sunSky->atm_ExtinctionMultiplier); - - /* scale to color sun */ - ComputeAttenuatedSunlight(sunSky->theta, sunSky->turbidity, sunColor); - VEC3OPV(E, E, *, sunColor); - - VEC3OPF(I, I, *, sunSky->atm_SunIntensity); - - VEC3OPV(rgb, rgb, *, E); - VEC3OPV(rgb, rgb, +, I); -} - -#undef VEC3OPV -#undef VEC3OPF -#undef FOPVEC3 - -/* EOF */ diff --git a/source/blender/render/intern/source/volume_precache.c b/source/blender/render/intern/source/volume_precache.c deleted file mode 100644 index 8e79f309814..00000000000 --- a/source/blender/render/intern/source/volume_precache.c +++ /dev/null @@ -1,855 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): Matt Ebb, Ra˙l Fern·ndez Hern·ndez (Farsthary). - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/render/intern/source/volume_precache.c - * \ingroup render - */ - - -#include <math.h> -#include <stdlib.h> -#include <string.h> -#include <float.h> - -#include "MEM_guardedalloc.h" - -#include "BLI_blenlib.h" -#include "BLI_math.h" -#include "BLI_task.h" -#include "BLI_threads.h" -#include "BLI_voxel.h" -#include "BLI_utildefines.h" - -#include "BLT_translation.h" - -#include "PIL_time.h" - -#include "RE_shader_ext.h" - -#include "DNA_material_types.h" - -#include "rayintersection.h" -#include "rayobject.h" -#include "render_types.h" -#include "rendercore.h" -#include "renderdatabase.h" -#include "volumetric.h" -#include "volume_precache.h" - -#include "atomic_ops.h" - - -/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -/* defined in pipeline.c, is hardcopy of active dynamic allocated Render */ -/* only to be used here in this file, it's for speed */ -extern struct Render R; -/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ - -/* *** utility code to set up an individual raytree for objectinstance, for checking inside/outside *** */ - -/* Recursive test for intersections, from a point inside the mesh, to outside - * Number of intersections (depth) determine if a point is inside or outside the mesh */ -static int intersect_outside_volume(RayObject *tree, Isect *isect, float *offset, int limit, int depth) -{ - if (limit == 0) return depth; - - if (RE_rayobject_raycast(tree, isect)) { - - isect->start[0] = isect->start[0] + isect->dist*isect->dir[0]; - isect->start[1] = isect->start[1] + isect->dist*isect->dir[1]; - isect->start[2] = isect->start[2] + isect->dist*isect->dir[2]; - - isect->dist = FLT_MAX; - isect->skip = RE_SKIP_VLR_NEIGHBOUR; - isect->orig.face= isect->hit.face; - isect->orig.ob= isect->hit.ob; - - return intersect_outside_volume(tree, isect, offset, limit-1, depth+1); - } - else { - return depth; - } -} - -/* Uses ray tracing to check if a point is inside or outside an ObjectInstanceRen */ -static int point_inside_obi(RayObject *tree, ObjectInstanceRen *obi, const float co[3]) -{ - Isect isect= {{0}}; - float dir[3] = {0.0f, 0.0f, 1.0f}; - int final_depth=0, depth=0, limit=20; - - /* set up the isect */ - copy_v3_v3(isect.start, co); - copy_v3_v3(isect.dir, dir); - isect.mode= RE_RAY_MIRROR; - isect.last_hit= NULL; - isect.lay= -1; - - isect.dist = FLT_MAX; - isect.orig.face= NULL; - isect.orig.ob = NULL; - - RE_instance_rotate_ray(obi, &isect); - final_depth = intersect_outside_volume(tree, &isect, dir, limit, depth); - RE_instance_rotate_ray_restore(obi, &isect); - - /* even number of intersections: point is outside - * odd number: point is inside */ - if (final_depth % 2 == 0) return 0; - else return 1; -} - -/* find the bounding box of an objectinstance in global space */ -void global_bounds_obi(Render *re, ObjectInstanceRen *obi, float bbmin[3], float bbmax[3]) -{ - ObjectRen *obr = obi->obr; - VolumePrecache *vp = obi->volume_precache; - VertRen *ver= NULL; - float co[3]; - int a; - - if (vp->bbmin != NULL && vp->bbmax != NULL) { - copy_v3_v3(bbmin, vp->bbmin); - copy_v3_v3(bbmax, vp->bbmax); - return; - } - - vp->bbmin = MEM_callocN(sizeof(float)*3, "volume precache min boundbox corner"); - vp->bbmax = MEM_callocN(sizeof(float)*3, "volume precache max boundbox corner"); - - INIT_MINMAX(bbmin, bbmax); - - for (a=0; a<obr->totvert; a++) { - if ((a & 255)==0) ver= obr->vertnodes[a>>8].vert; - else ver++; - - copy_v3_v3(co, ver->co); - - /* transformed object instance in camera space */ - if (obi->flag & R_TRANSFORMED) - mul_m4_v3(obi->mat, co); - - /* convert to global space */ - mul_m4_v3(re->viewinv, co); - - minmax_v3v3_v3(vp->bbmin, vp->bbmax, co); - } - - copy_v3_v3(bbmin, vp->bbmin); - copy_v3_v3(bbmax, vp->bbmax); - -} - -/* *** light cache filtering *** */ - -static float get_avg_surrounds(float *cache, int *res, int xx, int yy, int zz) -{ - int x, y, z, x_, y_, z_; - int added=0; - float tot=0.0f; - - for (z=-1; z <= 1; z++) { - z_ = zz+z; - if (z_ >= 0 && z_ <= res[2]-1) { - - for (y=-1; y <= 1; y++) { - y_ = yy+y; - if (y_ >= 0 && y_ <= res[1]-1) { - - for (x=-1; x <= 1; x++) { - x_ = xx+x; - if (x_ >= 0 && x_ <= res[0]-1) { - const int64_t i = BLI_VOXEL_INDEX(x_, y_, z_, res); - - if (cache[i] > 0.0f) { - tot += cache[i]; - added++; - } - - } - } - } - } - } - } - - if (added > 0) tot /= added; - - return tot; -} - -/* function to filter the edges of the light cache, where there was no volume originally. - * For each voxel which was originally external to the mesh, it finds the average values of - * the surrounding internal voxels and sets the original external voxel to that average amount. - * Works almost a bit like a 'dilate' filter */ -static void lightcache_filter(VolumePrecache *vp) -{ - int x, y, z; - - for (z=0; z < vp->res[2]; z++) { - for (y=0; y < vp->res[1]; y++) { - for (x=0; x < vp->res[0]; x++) { - /* trigger for outside mesh */ - const int64_t i = BLI_VOXEL_INDEX(x, y, z, vp->res); - - if (vp->data_r[i] < -0.f) - vp->data_r[i] = get_avg_surrounds(vp->data_r, vp->res, x, y, z); - if (vp->data_g[i] < -0.f) - vp->data_g[i] = get_avg_surrounds(vp->data_g, vp->res, x, y, z); - if (vp->data_b[i] < -0.f) - vp->data_b[i] = get_avg_surrounds(vp->data_b, vp->res, x, y, z); - } - } - } -} - -#if 0 -static void lightcache_filter2(VolumePrecache *vp) -{ - int x, y, z; - float *new_r, *new_g, *new_b; - int field_size = vp->res[0]*vp->res[1]*vp->res[2]*sizeof(float); - - new_r = MEM_mallocN(field_size, "temp buffer for light cache filter r channel"); - new_g = MEM_mallocN(field_size, "temp buffer for light cache filter g channel"); - new_b = MEM_mallocN(field_size, "temp buffer for light cache filter b channel"); - - memcpy(new_r, vp->data_r, field_size); - memcpy(new_g, vp->data_g, field_size); - memcpy(new_b, vp->data_b, field_size); - - for (z=0; z < vp->res[2]; z++) { - for (y=0; y < vp->res[1]; y++) { - for (x=0; x < vp->res[0]; x++) { - /* trigger for outside mesh */ - const int64_t i = BLI_VOXEL_INDEX(x, y, z, vp->res); - if (vp->data_r[i] < -0.f) - new_r[i] = get_avg_surrounds(vp->data_r, vp->res, x, y, z); - if (vp->data_g[i] < -0.f) - new_g[i] = get_avg_surrounds(vp->data_g, vp->res, x, y, z); - if (vp->data_b[i] < -0.f) - new_b[i] = get_avg_surrounds(vp->data_b, vp->res, x, y, z); - } - } - } - - SWAP(float *, vp->data_r, new_r); - SWAP(float *, vp->data_g, new_g); - SWAP(float *, vp->data_b, new_b); - - if (new_r) { MEM_freeN(new_r); new_r=NULL; } - if (new_g) { MEM_freeN(new_g); new_g=NULL; } - if (new_b) { MEM_freeN(new_b); new_b=NULL; } -} -#endif - -/* has a pad of 1 voxel surrounding the core for boundary simulation */ -BLI_INLINE int64_t ms_I(int x, int y, int z, const int *n) -{ - /* different ordering to light cache */ - return ((int64_t)x * (int64_t)(n[1] + 2) * (int64_t)(n[2] + 2) + - (int64_t)y * (int64_t)(n[2] + 2) + - (int64_t)z); -} - -/* has a pad of 1 voxel surrounding the core for boundary simulation */ -BLI_INLINE int64_t v_I_pad(int x, int y, int z, const int *n) -{ - /* same ordering to light cache, with padding */ - return ((int64_t)z * (int64_t)(n[1] + 2) * (int64_t)(n[0] + 2) + - (int64_t)y * (int64_t)(n[0] + 2) + - (int64_t)x); -} - -BLI_INLINE int64_t lc_to_ms_I(int x, int y, int z, const int *n) -{ - /* converting light cache index to multiple scattering index */ - return ((int64_t)(x - 1) * ((int64_t)n[1] * (int64_t)n[2]) + - (int64_t)(y - 1) * ((int64_t)n[2]) + - (int64_t)(z - 1)); -} - -/* *** multiple scattering approximation *** */ - -/* get the total amount of light energy in the light cache. used to normalize after multiple scattering */ -static float total_ss_energy(Render *re, int do_test_break, VolumePrecache *vp) -{ - int x, y, z; - const int *res = vp->res; - float energy=0.f; - - for (z=0; z < res[2]; z++) { - for (y=0; y < res[1]; y++) { - for (x=0; x < res[0]; x++) { - const int64_t i = BLI_VOXEL_INDEX(x, y, z, res); - - if (vp->data_r[i] > 0.f) energy += vp->data_r[i]; - if (vp->data_g[i] > 0.f) energy += vp->data_g[i]; - if (vp->data_b[i] > 0.f) energy += vp->data_b[i]; - } - } - - if (do_test_break && re->test_break(re->tbh)) break; - } - - return energy; -} - -static float total_ms_energy(Render *re, int do_test_break, float *sr, float *sg, float *sb, const int res[3]) -{ - int x, y, z; - float energy=0.f; - - for (z=1;z<=res[2];z++) { - for (y=1;y<=res[1];y++) { - for (x=1;x<=res[0];x++) { - const int64_t i = ms_I(x, y, z, res); - - if (sr[i] > 0.f) energy += sr[i]; - if (sg[i] > 0.f) energy += sg[i]; - if (sb[i] > 0.f) energy += sb[i]; - } - } - - if (do_test_break && re->test_break(re->tbh)) break; - } - - return energy; -} - -/** - * \param n: the unpadded resolution - */ -static void ms_diffuse(Render *re, int do_test_break, const float *x0, float *x, float diff, const int n[3]) -{ - int i, j, k, l; - const float dt = VOL_MS_TIMESTEP; - int64_t size = (int64_t)n[0] * (int64_t)n[1] * (int64_t)n[2]; - const float a = dt * diff * size; - - for (l=0; l<20; l++) { - for (k=1; k<=n[2]; k++) { - for (j=1; j<=n[1]; j++) { - for (i=1; i<=n[0]; i++) { - x[v_I_pad(i, j, k, n)] = - ((x0[v_I_pad(i, j, k, n)]) + ( - (x0[v_I_pad(i - 1, j, k, n)] + - x0[v_I_pad(i + 1, j, k, n)] + - x0[v_I_pad(i, j - 1, k, n)] + - x0[v_I_pad(i, j + 1, k, n)] + - x0[v_I_pad(i, j, k - 1, n)] + - x0[v_I_pad(i, j, k + 1, n)]) * a) / (1 + 6 * a)); - } - } - - if (do_test_break && re->test_break(re->tbh)) break; - } - - if (re->test_break(re->tbh)) break; - } -} - -static void multiple_scattering_diffusion(Render *re, VolumePrecache *vp, Material *ma) -{ - const float diff = ma->vol.ms_diff * 0.001f; /* compensate for scaling for a nicer UI range */ - const int simframes = (int)(ma->vol.ms_spread * (float)max_iii(vp->res[0], vp->res[1], vp->res[2])); - const int shade_type = ma->vol.shade_type; - float fac = ma->vol.ms_intensity; - - int x, y, z, m; - const int *n = vp->res; - const int size = (n[0]+2)*(n[1]+2)*(n[2]+2); - const int do_test_break = (size > 100000); - double time, lasttime= PIL_check_seconds_timer(); - float total; - float c=1.0f; - float origf; /* factor for blending in original light cache */ - float energy_ss, energy_ms; - - float *sr0=(float *)MEM_callocN(size*sizeof(float), "temporary multiple scattering buffer"); - float *sr=(float *)MEM_callocN(size*sizeof(float), "temporary multiple scattering buffer"); - float *sg0=(float *)MEM_callocN(size*sizeof(float), "temporary multiple scattering buffer"); - float *sg=(float *)MEM_callocN(size*sizeof(float), "temporary multiple scattering buffer"); - float *sb0=(float *)MEM_callocN(size*sizeof(float), "temporary multiple scattering buffer"); - float *sb=(float *)MEM_callocN(size*sizeof(float), "temporary multiple scattering buffer"); - - total = (float)(n[0]*n[1]*n[2]*simframes); - - energy_ss = total_ss_energy(re, do_test_break, vp); - - /* Scattering as diffusion pass */ - for (m=0; m<simframes; m++) { - /* add sources */ - for (z=1; z<=n[2]; z++) { - for (y=1; y<=n[1]; y++) { - for (x=1; x<=n[0]; x++) { - const int64_t i = lc_to_ms_I(x, y, z, n); //lc index - const int64_t j = ms_I(x, y, z, n); //ms index - - time= PIL_check_seconds_timer(); - c++; - if (vp->data_r[i] > 0.0f) - sr[j] += vp->data_r[i]; - if (vp->data_g[i] > 0.0f) - sg[j] += vp->data_g[i]; - if (vp->data_b[i] > 0.0f) - sb[j] += vp->data_b[i]; - - /* Displays progress every second */ - if (time-lasttime>1.0) { - char str[64]; - BLI_snprintf(str, sizeof(str), IFACE_("Simulating multiple scattering: %d%%"), - (int)(100.0f * (c / total))); - re->i.infostr = str; - re->stats_draw(re->sdh, &re->i); - re->i.infostr = NULL; - lasttime= time; - } - } - } - - if (do_test_break && re->test_break(re->tbh)) break; - } - - if (re->test_break(re->tbh)) break; - - SWAP(float *, sr, sr0); - SWAP(float *, sg, sg0); - SWAP(float *, sb, sb0); - - /* main diffusion simulation */ - ms_diffuse(re, do_test_break, sr0, sr, diff, n); - ms_diffuse(re, do_test_break, sg0, sg, diff, n); - ms_diffuse(re, do_test_break, sb0, sb, diff, n); - - if (re->test_break(re->tbh)) break; - } - - /* normalization factor to conserve energy */ - energy_ms = total_ms_energy(re, do_test_break, sr, sg, sb, n); - fac *= (energy_ss / energy_ms); - - /* blend multiple scattering back in the light cache */ - if (shade_type == MA_VOL_SHADE_SHADEDPLUSMULTIPLE) { - /* conserve energy - half single, half multiple */ - origf = 0.5f; - fac *= 0.5f; - } - else { - origf = 0.0f; - } - - for (z=1;z<=n[2];z++) { - for (y=1;y<=n[1];y++) { - for (x=1;x<=n[0];x++) { - const int64_t i = lc_to_ms_I(x, y, z, n); //lc index - const int64_t j = ms_I(x, y, z, n); //ms index - - vp->data_r[i] = origf * vp->data_r[i] + fac * sr[j]; - vp->data_g[i] = origf * vp->data_g[i] + fac * sg[j]; - vp->data_b[i] = origf * vp->data_b[i] + fac * sb[j]; - } - } - - if (do_test_break && re->test_break(re->tbh)) break; - } - - MEM_freeN(sr0); - MEM_freeN(sr); - MEM_freeN(sg0); - MEM_freeN(sg); - MEM_freeN(sb0); - MEM_freeN(sb); -} - - - -#if 0 /* debug stuff */ -static void *vol_precache_part_test(void *data) -{ - VolPrecachePart *pa = data; - - printf("part number: %d\n", pa->num); - printf("done: %d\n", pa->done); - printf("x min: %d x max: %d\n", pa->minx, pa->maxx); - printf("y min: %d y max: %d\n", pa->miny, pa->maxy); - printf("z min: %d z max: %d\n", pa->minz, pa->maxz); - - return NULL; -} -#endif - -/* Iterate over the 3d voxel grid, and fill the voxels with scattering information - * - * It's stored in memory as 3 big float grids next to each other, one for each RGB channel. - * I'm guessing the memory alignment may work out better this way for the purposes - * of doing linear interpolation, but I haven't actually tested this theory! :) - */ -typedef struct VolPrecacheState { - double lasttime; - unsigned int doneparts; - unsigned int totparts; -} VolPrecacheState; - -static void vol_precache_part(TaskPool * __restrict pool, void *taskdata, int UNUSED(threadid)) -{ - VolPrecacheState *state = (VolPrecacheState *)BLI_task_pool_userdata(pool); - VolPrecachePart *pa = (VolPrecachePart *)taskdata; - Render *re = pa->re; - - ObjectInstanceRen *obi = pa->obi; - RayObject *tree = pa->tree; - ShadeInput *shi = pa->shi; - float scatter_col[3] = {0.f, 0.f, 0.f}; - float co[3], cco[3], view[3]; - int x, y, z; - int res[3]; - double time; - - if (re->test_break && re->test_break(re->tbh)) - return; - - //printf("thread id %d\n", threadid); - - res[0]= pa->res[0]; - res[1]= pa->res[1]; - res[2]= pa->res[2]; - - for (z= pa->minz; z < pa->maxz; z++) { - co[2] = pa->bbmin[2] + (pa->voxel[2] * (z + 0.5f)); - - for (y= pa->miny; y < pa->maxy; y++) { - co[1] = pa->bbmin[1] + (pa->voxel[1] * (y + 0.5f)); - - for (x=pa->minx; x < pa->maxx; x++) { - int64_t i; - co[0] = pa->bbmin[0] + (pa->voxel[0] * (x + 0.5f)); - - if (re->test_break && re->test_break(re->tbh)) - break; - - /* convert from world->camera space for shading */ - mul_v3_m4v3(cco, pa->viewmat, co); - - i = BLI_VOXEL_INDEX(x, y, z, res); - - /* don't bother if the point is not inside the volume mesh */ - if (!point_inside_obi(tree, obi, cco)) { - obi->volume_precache->data_r[i] = -1.0f; - obi->volume_precache->data_g[i] = -1.0f; - obi->volume_precache->data_b[i] = -1.0f; - continue; - } - - copy_v3_v3(view, cco); - normalize_v3(view); - vol_get_scattering(shi, scatter_col, cco, view); - - obi->volume_precache->data_r[i] = scatter_col[0]; - obi->volume_precache->data_g[i] = scatter_col[1]; - obi->volume_precache->data_b[i] = scatter_col[2]; - - } - } - } - - unsigned int doneparts = atomic_add_and_fetch_u(&state->doneparts, 1); - - time = PIL_check_seconds_timer(); - if (time - state->lasttime > 1.0) { - ThreadMutex *mutex = BLI_task_pool_user_mutex(pool); - - if (BLI_mutex_trylock(mutex)) { - char str[64]; - float ratio = (float)doneparts/(float)state->totparts; - BLI_snprintf(str, sizeof(str), IFACE_("Precaching volume: %d%%"), (int)(100.0f * ratio)); - re->i.infostr = str; - re->stats_draw(re->sdh, &re->i); - re->i.infostr = NULL; - state->lasttime = time; - - BLI_mutex_unlock(mutex); - } - } -} - -static void precache_setup_shadeinput(Render *re, ObjectInstanceRen *obi, Material *ma, ShadeInput *shi) -{ - memset(shi, 0, sizeof(ShadeInput)); - shi->depth= 1; - shi->mask= 1; - shi->mat = ma; - shi->vlr = NULL; - memcpy(&shi->r, &shi->mat->r, 23*sizeof(float)); /* note, keep this synced with render_types.h */ - shi->har= shi->mat->har; - shi->obi= obi; - shi->obr= obi->obr; - shi->lay = re->lay; -} - -static void precache_launch_parts(Render *re, RayObject *tree, ShadeInput *shi, ObjectInstanceRen *obi) -{ - TaskScheduler *task_scheduler; - TaskPool *task_pool; - VolumePrecache *vp = obi->volume_precache; - VolPrecacheState state; - int i=0, x, y, z; - float voxel[3]; - int sizex, sizey, sizez; - float bbmin[3], bbmax[3]; - const int *res; - int minx, maxx; - int miny, maxy; - int minz, maxz; - int totthread = re->r.threads; - int parts[3]; - - if (!vp) return; - - /* currently we just subdivide the box, number of threads per side */ - parts[0] = parts[1] = parts[2] = totthread; - res = vp->res; - - /* setup task scheduler */ - memset(&state, 0, sizeof(state)); - state.doneparts = 0; - state.totparts = parts[0]*parts[1]*parts[2]; - state.lasttime = PIL_check_seconds_timer(); - - task_scheduler = BLI_task_scheduler_create(totthread); - task_pool = BLI_task_pool_create(task_scheduler, &state); - - /* using boundbox in worldspace */ - global_bounds_obi(re, obi, bbmin, bbmax); - sub_v3_v3v3(voxel, bbmax, bbmin); - - voxel[0] /= (float)res[0]; - voxel[1] /= (float)res[1]; - voxel[2] /= (float)res[2]; - - for (x=0; x < parts[0]; x++) { - sizex = ceil(res[0] / (float)parts[0]); - minx = x * sizex; - maxx = minx + sizex; - maxx = (maxx>res[0])?res[0]:maxx; - - for (y=0; y < parts[1]; y++) { - sizey = ceil(res[1] / (float)parts[1]); - miny = y * sizey; - maxy = miny + sizey; - maxy = (maxy>res[1])?res[1]:maxy; - - for (z=0; z < parts[2]; z++) { - VolPrecachePart *pa= MEM_callocN(sizeof(VolPrecachePart), "new precache part"); - - sizez = ceil(res[2] / (float)parts[2]); - minz = z * sizez; - maxz = minz + sizez; - maxz = (maxz>res[2])?res[2]:maxz; - - pa->re = re; - pa->num = i; - pa->tree = tree; - pa->shi = shi; - pa->obi = obi; - copy_m4_m4(pa->viewmat, re->viewmat); - - copy_v3_v3(pa->bbmin, bbmin); - copy_v3_v3(pa->voxel, voxel); - copy_v3_v3_int(pa->res, res); - - pa->minx = minx; pa->maxx = maxx; - pa->miny = miny; pa->maxy = maxy; - pa->minz = minz; pa->maxz = maxz; - - BLI_task_pool_push(task_pool, vol_precache_part, pa, true, TASK_PRIORITY_HIGH); - - i++; - } - } - } - - /* work and wait until tasks are done */ - BLI_task_pool_work_and_wait(task_pool); - - /* free */ - BLI_task_pool_free(task_pool); - BLI_task_scheduler_free(task_scheduler); -} - -/* calculate resolution from bounding box in world space */ -static int precache_resolution(Render *re, VolumePrecache *vp, ObjectInstanceRen *obi, int res) -{ - float dim[3], div; - float bbmin[3], bbmax[3]; - - /* bound box in global space */ - global_bounds_obi(re, obi, bbmin, bbmax); - sub_v3_v3v3(dim, bbmax, bbmin); - - div = max_fff(dim[0], dim[1], dim[2]); - dim[0] /= div; - dim[1] /= div; - dim[2] /= div; - - vp->res[0] = ceil(dim[0] * res); - vp->res[1] = ceil(dim[1] * res); - vp->res[2] = ceil(dim[2] * res); - - if ((vp->res[0] < 1) || (vp->res[1] < 1) || (vp->res[2] < 1)) - return 0; - - return 1; -} - -/* Precache a volume into a 3D voxel grid. - * The voxel grid is stored in the ObjectInstanceRen, - * in camera space, aligned with the ObjectRen's bounding box. - * Resolution is defined by the user. - */ -static void vol_precache_objectinstance_threads(Render *re, ObjectInstanceRen *obi, Material *ma) -{ - VolumePrecache *vp; - RayObject *tree; - ShadeInput shi; - - R = *re; - - /* create a raytree with just the faces of the instanced ObjectRen, - * used for checking if the cached point is inside or outside. */ - tree = makeraytree_object(&R, obi); - if (!tree) return; - - vp = MEM_callocN(sizeof(VolumePrecache), "volume light cache"); - obi->volume_precache = vp; - - if (!precache_resolution(re, vp, obi, ma->vol.precache_resolution)) { - MEM_freeN(vp); - vp = NULL; - return; - } - - vp->data_r = MEM_callocN(sizeof(float)*vp->res[0]*vp->res[1]*vp->res[2], "volume light cache data red channel"); - vp->data_g = MEM_callocN(sizeof(float)*vp->res[0]*vp->res[1]*vp->res[2], "volume light cache data green channel"); - vp->data_b = MEM_callocN(sizeof(float)*vp->res[0]*vp->res[1]*vp->res[2], "volume light cache data blue channel"); - if (vp->data_r==NULL || vp->data_g==NULL || vp->data_b==NULL) { - MEM_freeN(vp); - return; - } - - /* Need a shadeinput to calculate scattering */ - precache_setup_shadeinput(re, obi, ma, &shi); - - precache_launch_parts(re, tree, &shi, obi); - - if (tree) { - /* TODO: makeraytree_object creates a tree and saves it on OBI, - * if we free this tree we should also clear other pointers to it */ - //RE_rayobject_free(tree); - //tree= NULL; - } - - if (ELEM(ma->vol.shade_type, MA_VOL_SHADE_MULTIPLE, MA_VOL_SHADE_SHADEDPLUSMULTIPLE)) { - /* this should be before the filtering */ - multiple_scattering_diffusion(re, obi->volume_precache, ma); - } - - lightcache_filter(obi->volume_precache); -} - -static int using_lightcache(Material *ma) -{ - return (((ma->vol.shadeflag & MA_VOL_PRECACHESHADING) && (ma->vol.shade_type == MA_VOL_SHADE_SHADED)) || - (ELEM(ma->vol.shade_type, MA_VOL_SHADE_MULTIPLE, MA_VOL_SHADE_SHADEDPLUSMULTIPLE))); -} - -/* loop through all objects (and their associated materials) - * marked for pre-caching in convertblender.c, and pre-cache them */ -void volume_precache(Render *re) -{ - ObjectInstanceRen *obi; - VolumeOb *vo; - - re->i.infostr = IFACE_("Volume preprocessing"); - re->stats_draw(re->sdh, &re->i); - - for (vo= re->volumes.first; vo; vo= vo->next) { - if (using_lightcache(vo->ma)) { - for (obi= re->instancetable.first; obi; obi= obi->next) { - if (obi->obr == vo->obr) { - vol_precache_objectinstance_threads(re, obi, vo->ma); - - if (re->test_break && re->test_break(re->tbh)) - break; - } - } - - if (re->test_break && re->test_break(re->tbh)) - break; - } - } - - re->i.infostr = NULL; - re->stats_draw(re->sdh, &re->i); -} - -void free_volume_precache(Render *re) -{ - ObjectInstanceRen *obi; - - for (obi= re->instancetable.first; obi; obi= obi->next) { - if (obi->volume_precache != NULL) { - MEM_freeN(obi->volume_precache->data_r); - MEM_freeN(obi->volume_precache->data_g); - MEM_freeN(obi->volume_precache->data_b); - MEM_freeN(obi->volume_precache->bbmin); - MEM_freeN(obi->volume_precache->bbmax); - MEM_freeN(obi->volume_precache); - obi->volume_precache = NULL; - } - } - - BLI_freelistN(&re->volumes); -} - -int point_inside_volume_objectinstance(Render *re, ObjectInstanceRen *obi, const float co[3]) -{ - RayObject *tree; - int inside=0; - - tree = makeraytree_object(re, obi); - if (!tree) return 0; - - inside = point_inside_obi(tree, obi, co); - - //TODO: makeraytree_object creates a tree and saves it on OBI, if we free this tree we should also clear other pointers to it - //RE_rayobject_free(tree); - //tree= NULL; - - return inside; -} - diff --git a/source/blender/render/intern/source/volumetric.c b/source/blender/render/intern/source/volumetric.c deleted file mode 100644 index 583353ed8cf..00000000000 --- a/source/blender/render/intern/source/volumetric.c +++ /dev/null @@ -1,836 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): Matt Ebb, Raul Fernandez Hernandez (Farsthary) - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/render/intern/source/volumetric.c - * \ingroup render - */ - -#include <math.h> -#include <stdlib.h> -#include <string.h> -#include <float.h> - -#include "BLI_math.h" -#include "BLI_rand.h" -#include "BLI_voxel.h" -#include "BLI_utildefines.h" - -#include "RE_shader_ext.h" - -#include "IMB_colormanagement.h" - -#include "DNA_material_types.h" -#include "DNA_group_types.h" -#include "DNA_lamp_types.h" -#include "DNA_meta_types.h" - - -#include "render_types.h" -#include "pixelshading.h" -#include "rayintersection.h" -#include "rayobject.h" -#include "renderdatabase.h" -#include "shading.h" -#include "shadbuf.h" -#include "texture.h" -#include "volumetric.h" -#include "volume_precache.h" - -/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -/* defined in pipeline.c, is hardcopy of active dynamic allocated Render */ -/* only to be used here in this file, it's for speed */ -extern struct Render R; -/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ - -/* tracing */ -static float vol_get_shadow(ShadeInput *shi, LampRen *lar, const float co[3]) -{ - float visibility = 1.f; - - if (lar->shb) { - float dxco[3] = {0.f, 0.f, 0.f}, dyco[3] = {0.f, 0.f, 0.f}; - - visibility = testshadowbuf(&R, lar->shb, co, dxco, dyco, 1.0, 0.0); - } - else if (lar->mode & LA_SHAD_RAY) { - /* trace shadow manually, no good lamp api atm */ - Isect is; - - copy_v3_v3(is.start, co); - if (lar->type == LA_SUN || lar->type == LA_HEMI) { - is.dir[0] = -lar->vec[0]; - is.dir[1] = -lar->vec[1]; - is.dir[2] = -lar->vec[2]; - is.dist = R.maxdist; - } - else { - sub_v3_v3v3(is.dir, lar->co, is.start); - is.dist = normalize_v3(is.dir); - } - - is.mode = RE_RAY_MIRROR; - is.check = RE_CHECK_VLR_NON_SOLID_MATERIAL; - is.skip = 0; - - if (lar->mode & (LA_LAYER | LA_LAYER_SHADOW)) - is.lay = lar->lay; - else - is.lay = -1; - - is.orig.ob = NULL; - is.orig.face = NULL; - is.last_hit = lar->last_hit[shi->thread]; - - RE_instance_rotate_ray(shi->obi, &is); - - if (RE_rayobject_raycast(R.raytree, &is)) { - RE_instance_rotate_ray_restore(shi->obi, &is); - - visibility = 0.f; - } - - lar->last_hit[shi->thread] = is.last_hit; - } - return visibility; -} - -static int vol_get_bounds(ShadeInput *shi, const float co[3], const float vec[3], float hitco[3], Isect *isect, int intersect_type) -{ - - copy_v3_v3(isect->start, co); - copy_v3_v3(isect->dir, vec); - isect->dist = FLT_MAX; - isect->mode = RE_RAY_MIRROR; - isect->last_hit = NULL; - isect->lay = -1; - isect->check = RE_CHECK_VLR_NONE; - - if (intersect_type == VOL_BOUNDS_DEPTH) { - isect->skip = RE_SKIP_VLR_NEIGHBOUR; - isect->orig.face = (void *)shi->vlr; - isect->orig.ob = (void *)shi->obi; - } - else { // if (intersect_type == VOL_BOUNDS_SS) { - isect->skip = 0; - isect->orig.face = NULL; - isect->orig.ob = NULL; - } - - RE_instance_rotate_ray(shi->obi, isect); - - if (RE_rayobject_raycast(R.raytree, isect)) { - RE_instance_rotate_ray_restore(shi->obi, isect); - - hitco[0] = isect->start[0] + isect->dist * isect->dir[0]; - hitco[1] = isect->start[1] + isect->dist * isect->dir[1]; - hitco[2] = isect->start[2] + isect->dist * isect->dir[2]; - return 1; - } - else { - return 0; - } -} - -static void shade_intersection(ShadeInput *shi, float col_r[4], Isect *is) -{ - ShadeInput shi_new; - ShadeResult shr_new; - - memset(&shi_new, 0, sizeof(ShadeInput)); - - shi_new.mask = shi->mask; - shi_new.osatex = shi->osatex; - shi_new.thread = shi->thread; - shi_new.depth = shi->depth + 1; - shi_new.volume_depth = shi->volume_depth + 1; - shi_new.xs = shi->xs; - shi_new.ys = shi->ys; - shi_new.lay = shi->lay; - shi_new.passflag = SCE_PASS_COMBINED; /* result of tracing needs no pass info */ - shi_new.combinedflag = 0xFFFFFF; /* ray trace does all options */ - shi_new.light_override = shi->light_override; - shi_new.mat_override = shi->mat_override; - - copy_v3_v3(shi_new.camera_co, is->start); - - memset(&shr_new, 0, sizeof(ShadeResult)); - - /* hardcoded limit of 100 for now - prevents problems in weird geometry */ - if (shi->volume_depth < 100) { - shade_ray(is, &shi_new, &shr_new); - } - - copy_v3_v3(col_r, shr_new.combined); - col_r[3] = shr_new.alpha; -} - -static void vol_trace_behind(ShadeInput *shi, VlakRen *vlr, const float co[3], float col_r[4]) -{ - Isect isect; - - copy_v3_v3(isect.start, co); - copy_v3_v3(isect.dir, shi->view); - isect.dist = FLT_MAX; - - isect.mode = RE_RAY_MIRROR; - isect.check = RE_CHECK_VLR_NONE; - isect.skip = RE_SKIP_VLR_NEIGHBOUR; - isect.orig.ob = (void *) shi->obi; - isect.orig.face = (void *)vlr; - isect.last_hit = NULL; - isect.lay = -1; - - /* check to see if there's anything behind the volume, otherwise shade the sky */ - RE_instance_rotate_ray(shi->obi, &isect); - - if (RE_rayobject_raycast(R.raytree, &isect)) { - RE_instance_rotate_ray_restore(shi->obi, &isect); - - shade_intersection(shi, col_r, &isect); - } - else { - shadeSkyView(col_r, co, shi->view, NULL, shi->thread); - shadeSunView(col_r, shi->view); - } -} - - -/* trilinear interpolation */ -static void vol_get_precached_scattering(Render *re, ShadeInput *shi, float scatter_col[3], const float co[3]) -{ - VolumePrecache *vp = shi->obi->volume_precache; - float bbmin[3], bbmax[3], dim[3]; - float world_co[3], sample_co[3]; - - if (!vp) return; - - /* find sample point in global space bounding box 0.0-1.0 */ - global_bounds_obi(re, shi->obi, bbmin, bbmax); - sub_v3_v3v3(dim, bbmax, bbmin); - mul_v3_m4v3(world_co, re->viewinv, co); - - /* sample_co in 0.0-1.0 */ - sample_co[0] = (world_co[0] - bbmin[0]) / dim[0]; - sample_co[1] = (world_co[1] - bbmin[1]) / dim[1]; - sample_co[2] = (world_co[2] - bbmin[2]) / dim[2]; - - scatter_col[0] = BLI_voxel_sample_triquadratic(vp->data_r, vp->res, sample_co); - scatter_col[1] = BLI_voxel_sample_triquadratic(vp->data_g, vp->res, sample_co); - scatter_col[2] = BLI_voxel_sample_triquadratic(vp->data_b, vp->res, sample_co); -} - -/* Meta object density, brute force for now - * (might be good enough anyway, don't need huge number of metaobs to model volumetric objects */ -static float metadensity(Object *ob, const float co[3]) -{ - float mat[4][4], imat[4][4], dens = 0.f; - MetaBall *mb = (MetaBall *)ob->data; - MetaElem *ml; - - /* transform co to meta-element */ - float tco[3] = {co[0], co[1], co[2]}; - mul_m4_m4m4(mat, R.viewmat, ob->obmat); - invert_m4_m4(imat, mat); - mul_m4_v3(imat, tco); - - for (ml = mb->elems.first; ml; ml = ml->next) { - float bmat[3][3], dist2; - - /* element rotation transform */ - float tp[3] = {ml->x - tco[0], ml->y - tco[1], ml->z - tco[2]}; - quat_to_mat3(bmat, ml->quat); - transpose_m3(bmat); /* rot.only, so inverse == transpose */ - mul_m3_v3(bmat, tp); - - /* MB_BALL default */ - switch (ml->type) { - case MB_ELIPSOID: - tp[0] /= ml->expx; - tp[1] /= ml->expy; - tp[2] /= ml->expz; - break; - case MB_CUBE: - tp[2] = (tp[2] > ml->expz) ? (tp[2] - ml->expz) : ((tp[2] < -ml->expz) ? (tp[2] + ml->expz) : 0.f); - /* no break, xy as plane */ - ATTR_FALLTHROUGH; - case MB_PLANE: - tp[1] = (tp[1] > ml->expy) ? (tp[1] - ml->expy) : ((tp[1] < -ml->expy) ? (tp[1] + ml->expy) : 0.f); - /* no break, x as tube */ - ATTR_FALLTHROUGH; - case MB_TUBE: - tp[0] = (tp[0] > ml->expx) ? (tp[0] - ml->expx) : ((tp[0] < -ml->expx) ? (tp[0] + ml->expx) : 0.f); - } - - /* ml->rad2 is not set */ - dist2 = 1.0f - (dot_v3v3(tp, tp) / (ml->rad * ml->rad)); - if (dist2 > 0.f) - dens += (ml->flag & MB_NEGATIVE) ? -ml->s * dist2 * dist2 * dist2 : ml->s * dist2 * dist2 * dist2; - } - - dens -= mb->thresh; - return (dens < 0.f) ? 0.f : dens; -} - -float vol_get_density(struct ShadeInput *shi, const float co[3]) -{ - float density = shi->mat->vol.density; - float density_scale = shi->mat->vol.density_scale; - - if (shi->mat->mapto_textured & MAP_DENSITY) - do_volume_tex(shi, co, MAP_DENSITY, NULL, &density, &R); - - /* if meta-object, modulate by metadensity without increasing it */ - if (shi->obi->obr->ob->type == OB_MBALL) { - const float md = metadensity(shi->obi->obr->ob, co); - if (md < 1.f) density *= md; - } - - return density * density_scale; -} - - -/* Color of light that gets scattered out by the volume */ -/* Uses same physically based scattering parameter as in transmission calculations, - * along with artificial reflection scale/reflection color tint */ -static void vol_get_reflection_color(ShadeInput *shi, float ref_col[3], const float co[3]) -{ - float scatter = shi->mat->vol.scattering; - float reflection = shi->mat->vol.reflection; - copy_v3_v3(ref_col, shi->mat->vol.reflection_col); - - if (shi->mat->mapto_textured & (MAP_SCATTERING + MAP_REFLECTION_COL)) - do_volume_tex(shi, co, MAP_SCATTERING + MAP_REFLECTION_COL, ref_col, &scatter, &R); - - /* only one single float parameter at a time... :s */ - if (shi->mat->mapto_textured & (MAP_REFLECTION)) - do_volume_tex(shi, co, MAP_REFLECTION, NULL, &reflection, &R); - - ref_col[0] = reflection * ref_col[0] * scatter; - ref_col[1] = reflection * ref_col[1] * scatter; - ref_col[2] = reflection * ref_col[2] * scatter; -} - -/* compute emission component, amount of radiance to add per segment - * can be textured with 'emit' */ -static void vol_get_emission(ShadeInput *shi, float emission_col[3], const float co[3]) -{ - float emission = shi->mat->vol.emission; - copy_v3_v3(emission_col, shi->mat->vol.emission_col); - - if (shi->mat->mapto_textured & (MAP_EMISSION + MAP_EMISSION_COL)) - do_volume_tex(shi, co, MAP_EMISSION + MAP_EMISSION_COL, emission_col, &emission, &R); - - emission_col[0] = emission_col[0] * emission; - emission_col[1] = emission_col[1] * emission; - emission_col[2] = emission_col[2] * emission; -} - - -/* A combination of scattering and absorption -> known as sigma T. - * This can possibly use a specific scattering color, - * and absorption multiplier factor too, but these parameters are left out for simplicity. - * It's easy enough to get a good wide range of results with just these two parameters. */ -static void vol_get_sigma_t(ShadeInput *shi, float sigma_t[3], const float co[3]) -{ - /* technically absorption, but named transmission color - * since it describes the effect of the coloring *after* absorption */ - float transmission_col[3] = {shi->mat->vol.transmission_col[0], shi->mat->vol.transmission_col[1], shi->mat->vol.transmission_col[2]}; - float scattering = shi->mat->vol.scattering; - - if (shi->mat->mapto_textured & (MAP_SCATTERING + MAP_TRANSMISSION_COL)) - do_volume_tex(shi, co, MAP_SCATTERING + MAP_TRANSMISSION_COL, transmission_col, &scattering, &R); - - sigma_t[0] = (1.0f - transmission_col[0]) + scattering; - sigma_t[1] = (1.0f - transmission_col[1]) + scattering; - sigma_t[2] = (1.0f - transmission_col[2]) + scattering; -} - -/* phase function - determines in which directions the light - * is scattered in the volume relative to incoming direction - * and view direction */ -static float vol_get_phasefunc(ShadeInput *UNUSED(shi), float g, const float w[3], const float wp[3]) -{ - const float normalize = 0.25f; // = 1.f/4.f = M_PI/(4.f*M_PI) - - /* normalization constant is 1/4 rather than 1/4pi, since - * Blender's shading system doesn't normalize for - * energy conservation - eg. multiplying by pdf ( 1/pi for a lambert brdf ). - * This means that lambert surfaces in Blender are pi times brighter than they 'should be' - * and therefore, with correct energy conservation, volumes will darker than other solid objects, - * for the same lighting intensity. - * To correct this, scale up the phase function values by pi - * until Blender's shading system supports this better. --matt - */ - - if (g == 0.f) { /* isotropic */ - return normalize * 1.f; - } - else { /* schlick */ - const float k = 1.55f * g - 0.55f * g * g * g; - const float kcostheta = k * dot_v3v3(w, wp); - return normalize * (1.f - k * k) / ((1.f - kcostheta) * (1.f - kcostheta)); - } - - /* not used, but here for reference: */ -#if 0 - switch (phasefunc_type) { - case MA_VOL_PH_MIEHAZY: - return normalize * (0.5f + 4.5f * powf(0.5 * (1.f + costheta), 8.f)); - case MA_VOL_PH_MIEMURKY: - return normalize * (0.5f + 16.5f * powf(0.5 * (1.f + costheta), 32.f)); - case MA_VOL_PH_RAYLEIGH: - return normalize * 3.f / 4.f * (1 + costheta * costheta); - case MA_VOL_PH_HG: - return normalize * (1.f - g * g) / powf(1.f + g * g - 2.f * g * costheta, 1.5f); - case MA_VOL_PH_SCHLICK: - { - const float k = 1.55f * g - 0.55f * g * g * g; - const float kcostheta = k * costheta; - return normalize * (1.f - k * k) / ((1.f - kcostheta) * (1.f - kcostheta)); - } - case MA_VOL_PH_ISOTROPIC: - default: - return normalize * 1.f; - } -#endif -} - -/* Compute transmittance = e^(-attenuation) */ -static void vol_get_transmittance_seg(ShadeInput *shi, float tr[3], float stepsize, const float co[3], float density) -{ - /* input density = density at co */ - float tau[3] = {0.f, 0.f, 0.f}; - const float stepd = density * stepsize; - float sigma_t[3]; - - vol_get_sigma_t(shi, sigma_t, co); - - /* homogeneous volume within the sampled distance */ - tau[0] += stepd * sigma_t[0]; - tau[1] += stepd * sigma_t[1]; - tau[2] += stepd * sigma_t[2]; - - tr[0] *= expf(-tau[0]); - tr[1] *= expf(-tau[1]); - tr[2] *= expf(-tau[2]); -} - -/* Compute transmittance = e^(-attenuation) */ -static void vol_get_transmittance(ShadeInput *shi, float tr[3], const float co[3], const float endco[3]) -{ - float p[3] = {co[0], co[1], co[2]}; - float step_vec[3] = {endco[0] - co[0], endco[1] - co[1], endco[2] - co[2]}; - float tau[3] = {0.f, 0.f, 0.f}; - - float t0 = 0.f; - float t1 = normalize_v3(step_vec); - float pt0 = t0; - - t0 += shi->mat->vol.stepsize * ((shi->mat->vol.stepsize_type == MA_VOL_STEP_CONSTANT) ? 0.5f : BLI_thread_frand(shi->thread)); - p[0] += t0 * step_vec[0]; - p[1] += t0 * step_vec[1]; - p[2] += t0 * step_vec[2]; - mul_v3_fl(step_vec, shi->mat->vol.stepsize); - - for (; t0 < t1; pt0 = t0, t0 += shi->mat->vol.stepsize) { - const float d = vol_get_density(shi, p); - const float stepd = (t0 - pt0) * d; - float sigma_t[3]; - - vol_get_sigma_t(shi, sigma_t, p); - - tau[0] += stepd * sigma_t[0]; - tau[1] += stepd * sigma_t[1]; - tau[2] += stepd * sigma_t[2]; - - add_v3_v3(p, step_vec); - } - - /* return transmittance */ - tr[0] = expf(-tau[0]); - tr[1] = expf(-tau[1]); - tr[2] = expf(-tau[2]); -} - -static void vol_shade_one_lamp(struct ShadeInput *shi, const float co[3], const float view[3], LampRen *lar, float lacol[3]) -{ - float visifac, lv[3], lampdist; - float tr[3] = {1.0, 1.0, 1.0}; - float hitco[3], *atten_co; - float p, ref_col[3]; - - if (lar->mode & LA_LAYER) if ((lar->lay & shi->obi->lay) == 0) return; - if ((lar->lay & shi->lay) == 0) return; - if (lar->energy == 0.0f) return; - - if ((visifac = lamp_get_visibility(lar, co, lv, &lampdist)) == 0.f) return; - - copy_v3_v3(lacol, &lar->r); - - if (lar->mode & LA_TEXTURE) { - shi->osatex = 0; - do_lamp_tex(lar, lv, shi, lacol, LA_TEXTURE); - } - - mul_v3_fl(lacol, visifac); - - if (ELEM(lar->type, LA_SUN, LA_HEMI)) - copy_v3_v3(lv, lar->vec); - negate_v3(lv); - - if (shi->mat->vol.shade_type == MA_VOL_SHADE_SHADOWED) { - mul_v3_fl(lacol, vol_get_shadow(shi, lar, co)); - } - else if (ELEM(shi->mat->vol.shade_type, MA_VOL_SHADE_SHADED, MA_VOL_SHADE_MULTIPLE, MA_VOL_SHADE_SHADEDPLUSMULTIPLE)) { - Isect is; - - if (shi->mat->vol.shadeflag & MA_VOL_RECV_EXT_SHADOW) { - mul_v3_fl(lacol, vol_get_shadow(shi, lar, co)); - if (IMB_colormanagement_get_luminance(lacol) < 0.001f) return; - } - - /* find minimum of volume bounds, or lamp coord */ - if (vol_get_bounds(shi, co, lv, hitco, &is, VOL_BOUNDS_SS)) { - float dist = len_v3v3(co, hitco); - VlakRen *vlr = (VlakRen *)is.hit.face; - - /* simple internal shadowing */ - if (vlr->mat->material_type == MA_TYPE_SURFACE) { - lacol[0] = lacol[1] = lacol[2] = 0.0f; - return; - } - - if (ELEM(lar->type, LA_SUN, LA_HEMI)) - /* infinite lights, can never be inside volume */ - atten_co = hitco; - else if (lampdist < dist) { - atten_co = lar->co; - } - else - atten_co = hitco; - - vol_get_transmittance(shi, tr, co, atten_co); - - mul_v3_v3v3(lacol, lacol, tr); - } - else { - /* Point is on the outside edge of the volume, - * therefore no attenuation, full transmission. - * Radiance from lamp remains unchanged */ - } - } - - if (IMB_colormanagement_get_luminance(lacol) < 0.001f) return; - - normalize_v3(lv); - p = vol_get_phasefunc(shi, shi->mat->vol.asymmetry, view, lv); - - /* physically based scattering with non-physically based RGB gain */ - vol_get_reflection_color(shi, ref_col, co); - - lacol[0] *= p * ref_col[0]; - lacol[1] *= p * ref_col[1]; - lacol[2] *= p * ref_col[2]; -} - -/* single scattering only for now */ -void vol_get_scattering(ShadeInput *shi, float scatter_col[3], const float co[3], const float view[3]) -{ - ListBase *lights; - GroupObject *go; - LampRen *lar; - - zero_v3(scatter_col); - - lights = get_lights(shi); - for (go = lights->first; go; go = go->next) { - float lacol[3] = {0.f, 0.f, 0.f}; - lar = go->lampren; - - if (lar) { - vol_shade_one_lamp(shi, co, view, lar, lacol); - add_v3_v3(scatter_col, lacol); - } - } -} - - -/* - * The main volumetric integrator, using an emission/absorption/scattering model. - * - * Incoming radiance = - * - * outgoing radiance from behind surface * beam transmittance/attenuation - * + added radiance from all points along the ray due to participating media - * --> radiance for each segment = - * (radiance added by scattering + radiance added by emission) * beam transmittance/attenuation - */ - -/* For ease of use, I've also introduced a 'reflection' and 'reflection color' parameter, which isn't - * physically correct. This works as an RGB tint/gain on out-scattered light, but doesn't affect the light - * that is transmitted through the volume. While having wavelength dependent absorption/scattering is more correct, - * it also makes it harder to control the overall look of the volume since coloring the outscattered light results - * in the inverse color being transmitted through the rest of the volume. - */ -static void volumeintegrate(struct ShadeInput *shi, float col[4], const float co[3], const float endco[3]) -{ - float radiance[3] = {0.f, 0.f, 0.f}; - float tr[3] = {1.f, 1.f, 1.f}; - float p[3] = {co[0], co[1], co[2]}; - float step_vec[3] = {endco[0] - co[0], endco[1] - co[1], endco[2] - co[2]}; - const float stepsize = shi->mat->vol.stepsize; - - float t0 = 0.f; - float pt0 = t0; - float t1 = normalize_v3(step_vec); /* returns vector length */ - - t0 += stepsize * ((shi->mat->vol.stepsize_type == MA_VOL_STEP_CONSTANT) ? 0.5f : BLI_thread_frand(shi->thread)); - p[0] += t0 * step_vec[0]; - p[1] += t0 * step_vec[1]; - p[2] += t0 * step_vec[2]; - mul_v3_fl(step_vec, stepsize); - - for (; t0 < t1; pt0 = t0, t0 += stepsize) { - const float density = vol_get_density(shi, p); - - if (density > 0.00001f) { - float scatter_col[3] = {0.f, 0.f, 0.f}, emit_col[3]; - const float stepd = (t0 - pt0) * density; - - /* transmittance component (alpha) */ - vol_get_transmittance_seg(shi, tr, stepsize, co, density); - - if (t0 > t1 * 0.25f) { - /* only use depth cutoff after we've traced a little way into the volume */ - if (IMB_colormanagement_get_luminance(tr) < shi->mat->vol.depth_cutoff) break; - } - - vol_get_emission(shi, emit_col, p); - - if (shi->obi->volume_precache) { - float p2[3]; - - p2[0] = p[0] + (step_vec[0] * 0.5f); - p2[1] = p[1] + (step_vec[1] * 0.5f); - p2[2] = p[2] + (step_vec[2] * 0.5f); - - vol_get_precached_scattering(&R, shi, scatter_col, p2); - } - else - vol_get_scattering(shi, scatter_col, p, shi->view); - - radiance[0] += stepd * tr[0] * (emit_col[0] + scatter_col[0]); - radiance[1] += stepd * tr[1] * (emit_col[1] + scatter_col[1]); - radiance[2] += stepd * tr[2] * (emit_col[2] + scatter_col[2]); - } - add_v3_v3(p, step_vec); - } - - /* multiply original color (from behind volume) with transmittance over entire distance */ - mul_v3_v3v3(col, tr, col); - add_v3_v3(col, radiance); - - /* alpha <-- transmission luminance */ - col[3] = 1.0f - IMB_colormanagement_get_luminance(tr); -} - -/* the main entry point for volume shading */ -static void volume_trace(struct ShadeInput *shi, struct ShadeResult *shr, int inside_volume) -{ - float hitco[3], col[4] = {0.f, 0.f, 0.f, 0.f}; - const float *startco, *endco; - int trace_behind = 1; - const int ztransp = ((shi->depth == 0) && (shi->mat->mode & MA_TRANSP) && (shi->mat->mode & MA_ZTRANSP)); - Isect is; - - /* check for shading an internal face a volume object directly */ - if (inside_volume == VOL_SHADE_INSIDE) - trace_behind = 0; - else if (inside_volume == VOL_SHADE_OUTSIDE) { - if (shi->flippednor) - inside_volume = VOL_SHADE_INSIDE; - } - - if (ztransp && inside_volume == VOL_SHADE_INSIDE) { - MatInside *mi; - int render_this = 0; - - /* don't render the backfaces of ztransp volume materials. - * - * volume shading renders the internal volume from between the - * ' view intersection of the solid volume to the - * intersection on the other side, as part of the shading of - * the front face. - * - * Because ztransp renders both front and back faces independently - * this will double up, so here we prevent rendering the backface as well, - * which would otherwise render the volume in between the camera and the backface - * --matt */ - - for (mi = R.render_volumes_inside.first; mi; mi = mi->next) { - /* weak... */ - if (mi->ma == shi->mat) render_this = 1; - } - if (!render_this) return; - } - - - if (inside_volume == VOL_SHADE_INSIDE) { - startco = shi->camera_co; - endco = shi->co; - - if (trace_behind) { - if (!ztransp) - /* trace behind the volume object */ - vol_trace_behind(shi, shi->vlr, endco, col); - } - else { - /* we're tracing through the volume between the camera - * and a solid surface, so use that pre-shaded radiance */ - copy_v4_v4(col, shr->combined); - } - - /* shade volume from 'camera' to 1st hit point */ - volumeintegrate(shi, col, startco, endco); - } - /* trace to find a backface, the other side bounds of the volume */ - /* (ray intersect ignores front faces here) */ - else if (vol_get_bounds(shi, shi->co, shi->view, hitco, &is, VOL_BOUNDS_DEPTH)) { - VlakRen *vlr = (VlakRen *)is.hit.face; - - startco = shi->co; - endco = hitco; - - if (!ztransp) { - /* if it's another face in the same material */ - if (vlr->mat == shi->mat) { - /* trace behind the 2nd (raytrace) hit point */ - vol_trace_behind(shi, (VlakRen *)is.hit.face, endco, col); - } - else { - shade_intersection(shi, col, &is); - } - } - - /* shade volume from 1st hit point to 2nd hit point */ - volumeintegrate(shi, col, startco, endco); - } - - if (ztransp) - col[3] = col[3] > 1.f ? 1.f : col[3]; - else - col[3] = 1.f; - - copy_v3_v3(shr->combined, col); - shr->alpha = col[3]; - - copy_v3_v3(shr->diff, shr->combined); - copy_v3_v3(shr->diffshad, shr->diff); -} - -/* Traces a shadow through the object, - * pretty much gets the transmission over a ray path */ -void shade_volume_shadow(struct ShadeInput *shi, struct ShadeResult *shr, struct Isect *last_is) -{ - float hitco[3]; - float tr[3] = {1.0, 1.0, 1.0}; - Isect is = {{0}}; - const float *startco, *endco; - - memset(shr, 0, sizeof(ShadeResult)); - - /* if 1st hit normal is facing away from the camera, - * then we're inside the volume already. */ - if (shi->flippednor) { - startco = last_is->start; - endco = shi->co; - } - - /* trace to find a backface, the other side bounds of the volume */ - /* (ray intersect ignores front faces here) */ - else if (vol_get_bounds(shi, shi->co, shi->view, hitco, &is, VOL_BOUNDS_DEPTH)) { - startco = shi->co; - endco = hitco; - } - else { - shr->combined[0] = shr->combined[1] = shr->combined[2] = 0.f; - shr->alpha = shr->combined[3] = 1.f; - return; - } - - vol_get_transmittance(shi, tr, startco, endco); - - - /* if we hit another face in the same volume bounds */ - /* shift raytrace coordinates to the hit point, to avoid shading volume twice */ - /* due to idiosyncracy in ray_trace_shadow_tra() */ - if (is.hit.ob == shi->obi) { - copy_v3_v3(shi->co, hitco); - last_is->dist += is.dist; - shi->vlr = (VlakRen *)is.hit.face; - } - - - copy_v3_v3(shr->combined, tr); - shr->combined[3] = 1.0f - IMB_colormanagement_get_luminance(tr); - shr->alpha = shr->combined[3]; -} - - -/* delivers a fully filled in ShadeResult, for all passes */ -void shade_volume_outside(ShadeInput *shi, ShadeResult *shr) -{ - memset(shr, 0, sizeof(ShadeResult)); - volume_trace(shi, shr, VOL_SHADE_OUTSIDE); -} - - -void shade_volume_inside(ShadeInput *shi, ShadeResult *shr) -{ - MatInside *m; - Material *mat_backup; - ObjectInstanceRen *obi_backup; - float prev_alpha = shr->alpha; - - /* XXX: extend to multiple volumes perhaps later */ - mat_backup = shi->mat; - obi_backup = shi->obi; - - m = R.render_volumes_inside.first; - shi->mat = m->ma; - shi->obi = m->obi; - shi->obr = m->obi->obr; - - volume_trace(shi, shr, VOL_SHADE_INSIDE); - - shr->alpha = shr->alpha + prev_alpha; - CLAMP(shr->alpha, 0.0f, 1.0f); - - shi->mat = mat_backup; - shi->obi = obi_backup; - shi->obr = obi_backup->obr; -} diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c index 6a42bf26a97..7eeea0f64ee 100644 --- a/source/blender/windowmanager/intern/wm.c +++ b/source/blender/windowmanager/intern/wm.c @@ -165,9 +165,6 @@ void wm_operator_register(bContext *C, wmOperator *op) wmWindowManager *wm = CTX_wm_manager(C); int tot = 0; - op->execution_area = CTX_wm_area(C); - op->execution_region = CTX_wm_region(C); - BLI_addtail(&wm->operators, op); /* only count registered operators */ diff --git a/source/blender/windowmanager/intern/wm_cursors.c b/source/blender/windowmanager/intern/wm_cursors.c index f13dac9cb4c..eaeaac45f89 100644 --- a/source/blender/windowmanager/intern/wm_cursors.c +++ b/source/blender/windowmanager/intern/wm_cursors.c @@ -194,7 +194,7 @@ void WM_cursor_modal_restore(wmWindow *win) void WM_cursor_wait(bool val) { if (!G.background) { - wmWindowManager *wm = G.main->wm.first; + wmWindowManager *wm = G_MAIN->wm.first; wmWindow *win = wm ? wm->windows.first : NULL; for (; win; win = win->next) { diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c index df958f35e91..5efe9330f52 100644 --- a/source/blender/windowmanager/intern/wm_draw.c +++ b/source/blender/windowmanager/intern/wm_draw.c @@ -50,6 +50,7 @@ #include "BKE_context.h" #include "BKE_image.h" +#include "BKE_main.h" #include "BKE_screen.h" #include "BKE_scene.h" #include "BKE_workspace.h" @@ -118,7 +119,7 @@ static void wm_paintcursor_draw(bContext *C, ARegion *ar) } -static bool wm_draw_region_stereo_set(ScrArea *sa, ARegion *ar, eStereoViews sview) +static bool wm_draw_region_stereo_set(Main *bmain, ScrArea *sa, ARegion *ar, eStereoViews sview) { /* We could detect better when stereo is actually needed, by inspecting the * image in the image editor and sequencer. */ @@ -149,7 +150,7 @@ static bool wm_draw_region_stereo_set(ScrArea *sa, ARegion *ar, eStereoViews svi { SpaceNode *snode = sa->spacedata.first; if ((snode->flag & SNODE_BACKDRAW) && ED_node_is_compositor(snode)) { - Image *ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node"); + Image *ima = BKE_image_verify_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node"); ima->eye = sview; return true; } @@ -488,6 +489,7 @@ GPUViewport *WM_draw_region_get_bound_viewport(ARegion *ar) static void wm_draw_window_offscreen(bContext *C, wmWindow *win, bool stereo) { + Main *bmain = CTX_data_main(C); wmWindowManager *wm = CTX_wm_manager(C); bScreen *screen = WM_window_get_active_screen(win); @@ -512,7 +514,7 @@ static void wm_draw_window_offscreen(bContext *C, wmWindow *win, bool stereo) CTX_wm_region_set(C, ar); bool use_viewport = wm_region_use_viewport(sa, ar); - if (stereo && wm_draw_region_stereo_set(sa, ar, STEREO_LEFT_ID)) { + if (stereo && wm_draw_region_stereo_set(bmain, sa, ar, STEREO_LEFT_ID)) { wm_draw_region_buffer_create(ar, true, use_viewport); for (int view = 0; view < 2; view++) { @@ -522,7 +524,7 @@ static void wm_draw_window_offscreen(bContext *C, wmWindow *win, bool stereo) } else { sview = STEREO_RIGHT_ID; - wm_draw_region_stereo_set(sa, ar, sview); + wm_draw_region_stereo_set(bmain, sa, ar, sview); } wm_draw_region_bind(ar, view); diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 1e3a08bdcbc..cd56eac84d1 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -210,7 +210,7 @@ void WM_event_add_notifier(const bContext *C, unsigned int type, void *reference void WM_main_add_notifier(unsigned int type, void *reference) { - Main *bmain = G.main; + Main *bmain = G_MAIN; wmWindowManager *wm = bmain->wm.first; wmNotifier *note; @@ -235,7 +235,7 @@ void WM_main_add_notifier(unsigned int type, void *reference) */ void WM_main_remove_notifier_reference(const void *reference) { - Main *bmain = G.main; + Main *bmain = G_MAIN; wmWindowManager *wm = bmain->wm.first; if (wm) { @@ -263,7 +263,7 @@ void WM_main_remove_notifier_reference(const void *reference) void WM_main_remap_editor_id_reference(ID *old_id, ID *new_id) { - Main *bmain = G.main; + Main *bmain = G_MAIN; bScreen *sc; for (sc = bmain->screen.first; sc; sc = sc->id.next) { @@ -714,7 +714,7 @@ void WM_event_print(const wmEvent *event) */ void WM_report_banner_show(void) { - wmWindowManager *wm = G.main->wm.first; + wmWindowManager *wm = G_MAIN->wm.first; ReportList *wm_reports = &wm->reports; ReportTimerInfo *rti; @@ -749,7 +749,7 @@ static void wm_add_reports(ReportList *reports) { /* if the caller owns them, handle this */ if (reports->list.first && (reports->flag & RPT_OP_HOLD) == 0) { - wmWindowManager *wm = G.main->wm.first; + wmWindowManager *wm = G_MAIN->wm.first; /* add reports to the global list, otherwise they are not seen */ BLI_movelisttolist(&wm->reports.list, &reports->list); @@ -843,6 +843,7 @@ static bool wm_operator_register_check(wmWindowManager *wm, wmOperatorType *ot) static void wm_operator_finished(bContext *C, wmOperator *op, const bool repeat, const bool store) { wmWindowManager *wm = CTX_wm_manager(C); + enum { NOP, SET, CLEAR, } hud_status = NOP; op->customdata = NULL; @@ -854,10 +855,19 @@ static void wm_operator_finished(bContext *C, wmOperator *op, const bool repeat, * called from operators that already do an undo push. usually * this will happen for python operators that call C operators */ if (wm->op_undo_depth == 0) { - if (op->type->flag & OPTYPE_UNDO) + if (op->type->flag & OPTYPE_UNDO) { ED_undo_push_op(C, op); - else if (op->type->flag & OPTYPE_UNDO_GROUPED) + if (repeat == 0) { + hud_status = CLEAR; + } + } + else if (op->type->flag & OPTYPE_UNDO_GROUPED) { ED_undo_grouped_push_op(C, op); + if (repeat == 0) { + hud_status = CLEAR; + } + } + } if (repeat == 0) { @@ -873,11 +883,29 @@ static void wm_operator_finished(bContext *C, wmOperator *op, const bool repeat, wm_operator_register(C, op); WM_operator_region_active_win_set(C); + + /* Show the redo panel. */ + hud_status = SET; } else { WM_operator_free(op); } } + + if (hud_status != NOP) { + if (hud_status == SET) { + ScrArea *sa = CTX_wm_area(C); + if (sa) { + ED_area_type_hud_ensure(C, sa); + } + } + else if (hud_status == CLEAR) { + ED_area_type_hud_clear(wm, NULL); + } + else { + BLI_assert(0); + } + } } /* if repeat is true, it doesn't register again, nor does it free */ @@ -979,14 +1007,7 @@ int WM_operator_call_notest(bContext *C, wmOperator *op) */ int WM_operator_repeat(bContext *C, wmOperator *op) { - const OperatorRepeatContextHandle *context_info; - int retval; - - context_info = ED_operator_repeat_prepare_context(C, op); - retval = wm_operator_exec(C, op, true, true); - ED_operator_repeat_reset_context(C, context_info); - - return retval; + return wm_operator_exec(C, op, true, true); } /** * \return true if #WM_operator_repeat can run @@ -2358,8 +2379,7 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers if (event->type == MOUSEMOVE && !wm_manipulatormap_modal_get(mmap)) { int part; mpr = wm_manipulatormap_highlight_find(mmap, C, event, &part); - wm_manipulatormap_highlight_set(mmap, C, mpr, part); - if (mpr != NULL) { + if (wm_manipulatormap_highlight_set(mmap, C, mpr, part) && mpr != NULL) { WM_tooltip_timer_init(C, CTX_wm_window(C), region, WM_manipulatormap_tooltip_init); } } @@ -2549,7 +2569,7 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers) } } } - else if (ISMOUSE(event->type) || ISKEYBOARD(event->type)) { + else if (ISMOUSE_BUTTON(event->type) || ISKEYBOARD(event->type)) { /* All events that don't set wmEvent.prevtype must be ignored. */ /* test for CLICK events */ diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index 3aaec875627..81618468a04 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -153,8 +153,8 @@ static void wm_window_match_init(bContext *C, ListBase *wmlist) wmWindowManager *wm; wmWindow *win, *active_win; - *wmlist = G.main->wm; - BLI_listbase_clear(&G.main->wm); + *wmlist = G_MAIN->wm; + BLI_listbase_clear(&G_MAIN->wm); active_win = CTX_wm_window(C); @@ -227,7 +227,7 @@ static void wm_window_match_keep_current_wm( for (wmWindow *win = wm->windows.first; win; win = win->next) { WorkSpace *workspace; - BKE_workspace_layout_find_global(G.main, screen, &workspace); + BKE_workspace_layout_find_global(bmain, screen, &workspace); BKE_workspace_active_set(win->workspace_hook, workspace); win->scene = CTX_data_scene(C); @@ -440,12 +440,12 @@ void WM_file_autoexec_init(const char *filepath) } } -void wm_file_read_report(bContext *C) +void wm_file_read_report(bContext *C, Main *bmain) { ReportList *reports = NULL; Scene *sce; - for (sce = G.main->scene.first; sce; sce = sce->id.next) { + for (sce = bmain->scene.first; sce; sce = sce->id.next) { if (sce->r.engine[0] && BLI_findstring(&R_engines, sce->r.engine, offsetof(RenderEngineType, idname)) == NULL) { @@ -483,7 +483,9 @@ static void wm_file_read_post(bContext *C, const bool is_startup_file, const boo CTX_wm_window_set(C, wm->windows.first); ED_editors_init(C); - DEG_on_visible_update(CTX_data_main(C), true); + + Main *bmain = CTX_data_main(C); + DEG_on_visible_update(bmain, true); #ifdef WITH_PYTHON if (is_startup_file) { @@ -513,8 +515,8 @@ static void wm_file_read_post(bContext *C, const bool is_startup_file, const boo WM_operatortype_last_properties_clear_all(); /* important to do before NULL'ing the context */ - BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_VERSION_UPDATE); - BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_POST); + BLI_callback_exec(bmain, NULL, BLI_CB_EVT_VERSION_UPDATE); + BLI_callback_exec(bmain, NULL, BLI_CB_EVT_LOAD_POST); #if 1 WM_event_add_notifier(C, NC_WM | ND_FILEREAD, NULL); @@ -525,7 +527,7 @@ static void wm_file_read_post(bContext *C, const bool is_startup_file, const boo /* report any errors. * currently disabled if addons aren't yet loaded */ if (addons_loaded) { - wm_file_read_report(C); + wm_file_read_report(C, bmain); } if (!G.background) { @@ -535,7 +537,7 @@ static void wm_file_read_post(bContext *C, const bool is_startup_file, const boo else { BKE_undosys_stack_clear(wm->undo_stack); } - BKE_undosys_stack_init_from_main(wm->undo_stack, CTX_data_main(C)); + BKE_undosys_stack_init_from_main(wm->undo_stack, bmain); BKE_undosys_stack_init_from_context(wm->undo_stack, C); } @@ -677,7 +679,7 @@ int wm_homefile_read( bool use_factory_settings, bool use_empty_data, bool use_userdef, const char *filepath_startup_override, const char *app_template_override) { - Main *bmain = G.main; /* Context does not always have valid main pointer here... */ + Main *bmain = G_MAIN; /* Context does not always have valid main pointer here... */ ListBase wmbase; bool success = false; @@ -1099,7 +1101,7 @@ bool write_crash_blend(void) BLI_strncpy(path, BKE_main_blendfile_path_from_global(), sizeof(path)); BLI_replace_extension(path, sizeof(path), "_crash.blend"); - if (BLO_write_file(G.main, path, fileflags, NULL, NULL)) { + if (BLO_write_file(G_MAIN, path, fileflags, NULL, NULL)) { printf("written: %s\n", path); return 1; } @@ -1234,7 +1236,7 @@ void wm_autosave_location(char *filepath) const char *savedir; #endif - if (G.main && G.relbase_valid) { + if (G_MAIN && G.relbase_valid) { const char *basename = BLI_path_basename(BKE_main_blendfile_path_from_global()); int len = strlen(basename) - 6; BLI_snprintf(path, sizeof(path), "%.*s.blend", len, basename); @@ -1384,7 +1386,7 @@ void wm_open_init_use_scripts(wmOperator *op, bool use_prefs) void WM_file_tag_modified(void) { - wmWindowManager *wm = G.main->wm.first; + wmWindowManager *wm = G_MAIN->wm.first; if (wm->file_saved) { wm->file_saved = 0; /* notifier that data changed, for save-over warning or header */ @@ -1401,6 +1403,7 @@ void WM_file_tag_modified(void) */ static int wm_homefile_write_exec(bContext *C, wmOperator *op) { + Main *bmain = CTX_data_main(C); wmWindowManager *wm = CTX_wm_manager(C); wmWindow *win = CTX_wm_window(C); char filepath[FILE_MAX]; @@ -1413,7 +1416,7 @@ static int wm_homefile_write_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - BLI_callback_exec(G.main, NULL, BLI_CB_EVT_SAVE_PRE); + BLI_callback_exec(bmain, NULL, BLI_CB_EVT_SAVE_PRE); /* check current window and close it if temp */ if (win && WM_window_is_temp_screen(win)) @@ -1431,7 +1434,7 @@ static int wm_homefile_write_exec(bContext *C, wmOperator *op) /* force save as regular blend file */ fileflags = G.fileflags & ~(G_FILE_COMPRESS | G_FILE_HISTORY); - if (BLO_write_file(CTX_data_main(C), filepath, fileflags | G_FILE_USERPREFS, op->reports, NULL) == 0) { + if (BLO_write_file(bmain, filepath, fileflags | G_FILE_USERPREFS, op->reports, NULL) == 0) { printf("fail\n"); return OPERATOR_CANCELLED; } @@ -1440,7 +1443,7 @@ static int wm_homefile_write_exec(bContext *C, wmOperator *op) G.save_over = 0; - BLI_callback_exec(G.main, NULL, BLI_CB_EVT_SAVE_POST); + BLI_callback_exec(bmain, NULL, BLI_CB_EVT_SAVE_POST); return OPERATOR_FINISHED; } diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index c5a57147dd6..ebaa51e7906 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -296,7 +296,7 @@ void WM_init(bContext *C, int argc, const char **argv) /* allow a path of "", this is what happens when making a new file */ #if 0 if (BKE_main_blendfile_path_from_global()[0] == '\0') - BLI_make_file_string("/", G.main->name, BKE_appdir_folder_default(), "untitled.blend"); + BLI_make_file_string("/", G_MAIN->name, BKE_appdir_folder_default(), "untitled.blend"); #endif BLI_strncpy(G.lib, BKE_main_blendfile_path_from_global(), sizeof(G.lib)); @@ -314,6 +314,7 @@ void WM_init(bContext *C, int argc, const char **argv) /* that prevents loading both the kept session, and the file on the command line */ } else { + Main *bmain = CTX_data_main(C); /* note, logic here is from wm_file_read_post, * call functions that depend on Python being initialized. */ @@ -324,10 +325,10 @@ void WM_init(bContext *C, int argc, const char **argv) * note that recovering the last session does its own callbacks. */ CTX_wm_window_set(C, CTX_wm_manager(C)->windows.first); - BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_VERSION_UPDATE); - BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_POST); + BLI_callback_exec(bmain, NULL, BLI_CB_EVT_VERSION_UPDATE); + BLI_callback_exec(bmain, NULL, BLI_CB_EVT_LOAD_POST); - wm_file_read_report(C); + wm_file_read_report(C, bmain); if (!G.background) { CTX_wm_window_set(C, NULL); diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c index 67493454e8f..bbc7e6fbb69 100644 --- a/source/blender/windowmanager/intern/wm_keymap.c +++ b/source/blender/windowmanager/intern/wm_keymap.c @@ -828,7 +828,7 @@ wmKeyMap *WM_modalkeymap_add(wmKeyConfig *keyconf, const char *idname, const Enu if (!items) { /* init modal items from default config */ - wmWindowManager *wm = G.main->wm.first; + wmWindowManager *wm = G_MAIN->wm.first; if (wm->defaultconf) { wmKeyMap *defaultkm = WM_keymap_list_find(&wm->defaultconf->keymaps, km->idname, 0, 0); diff --git a/source/blender/windowmanager/intern/wm_operator_props.c b/source/blender/windowmanager/intern/wm_operator_props.c index 8e2f41c49e0..fa7ff85c874 100644 --- a/source/blender/windowmanager/intern/wm_operator_props.c +++ b/source/blender/windowmanager/intern/wm_operator_props.c @@ -130,7 +130,9 @@ void WM_operator_properties_filesel( static void wm_operator_properties_select_action_ex(wmOperatorType *ot, int default_action, const EnumPropertyItem *select_actions) { - RNA_def_enum(ot->srna, "action", select_actions, default_action, "Action", "Selection action to execute"); + PropertyRNA *prop; + prop = RNA_def_enum(ot->srna, "action", select_actions, default_action, "Action", "Selection action to execute"); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } void WM_operator_properties_select_action(wmOperatorType *ot, int default_action) diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 926e87cc3b4..20c4d2700aa 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -1421,7 +1421,7 @@ ID *WM_operator_drop_load_path(struct bContext *C, wmOperator *op, const short i errno = 0; if (idcode == ID_IM) { - id = (ID *)BKE_image_load_exists_ex(path, &exists); + id = (ID *)BKE_image_load_exists_ex(bmain, path, &exists); } else { BLI_assert(0); diff --git a/source/blender/windowmanager/intern/wm_tooltip.c b/source/blender/windowmanager/intern/wm_tooltip.c index 6096317b582..94a44a97afd 100644 --- a/source/blender/windowmanager/intern/wm_tooltip.c +++ b/source/blender/windowmanager/intern/wm_tooltip.c @@ -41,6 +41,8 @@ void WM_tooltip_timer_init( bContext *C, wmWindow *win, ARegion *ar, wmTooltipInitFn init) { + WM_tooltip_timer_clear(C, win); + bScreen *screen = WM_window_get_active_screen(win); wmWindowManager *wm = CTX_wm_manager(C); if (screen->tool_tip == NULL) { diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index e1528551c12..076514cd73f 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -232,7 +232,7 @@ void wm_window_free(bContext *C, wmWindowManager *wm, wmWindow *win) wm_ghostwindow_destroy(wm, win); - BKE_workspace_instance_hook_free(G.main, win->workspace_hook); + BKE_workspace_instance_hook_free(G_MAIN, win->workspace_hook); MEM_freeN(win->stereo3d_format); MEM_freeN(win); @@ -553,7 +553,7 @@ void wm_window_title(wmWindowManager *wm, wmWindow *win) char str[sizeof(((Main *)NULL)->name) + 24]; BLI_snprintf(str, sizeof(str), "Blender%s [%s%s]", wm->file_saved ? "" : "*", BKE_main_blendfile_path_from_global(), - G.main->recovered ? " (Recovered)" : ""); + G_MAIN->recovered ? " (Recovered)" : ""); GHOST_SetTitle(win->ghostwin, str); } else @@ -1236,7 +1236,7 @@ void wm_window_reset_drawable(void) { BLI_assert(BLI_thread_is_main()); BLI_assert(GPU_framebuffer_current_get() == 0); - wmWindowManager *wm = G.main->wm.first; + wmWindowManager *wm = G_MAIN->wm.first; if (wm == NULL) return; @@ -2318,13 +2318,14 @@ void *WM_opengl_context_create(void) * So we should call this function only on the main thread. */ BLI_assert(BLI_thread_is_main()); - BLI_assert(GPU_framebuffer_current_get() == 0); + // BLI_assert(GPU_framebuffer_current_get() == 0); return GHOST_CreateOpenGLContext(g_system); } void WM_opengl_context_dispose(void *context) { - BLI_assert(GPU_framebuffer_current_get() == 0); + // BLI_assert(BLI_thread_is_main()); + // BLI_assert(GPU_framebuffer_current_get() == 0); GHOST_DisposeOpenGLContext(g_system, (GHOST_ContextHandle)context); } diff --git a/source/blender/windowmanager/manipulators/intern/wm_manipulator.c b/source/blender/windowmanager/manipulators/intern/wm_manipulator.c index 5634a1a3ee7..d6eb110dca0 100644 --- a/source/blender/windowmanager/manipulators/intern/wm_manipulator.c +++ b/source/blender/windowmanager/manipulators/intern/wm_manipulator.c @@ -92,7 +92,7 @@ static wmManipulator *wm_manipulator_create( IDPropertyTemplate val = {0}; mpr->properties = IDP_New(IDP_GROUP, &val, "wmManipulatorProperties"); } - RNA_pointer_create(G.main->wm.first, wt->srna, mpr->properties, mpr->ptr); + RNA_pointer_create(G_MAIN->wm.first, wt->srna, mpr->properties, mpr->ptr); WM_manipulator_properties_sanitize(mpr->ptr, 0); diff --git a/source/blender/windowmanager/manipulators/intern/wm_manipulator_map.c b/source/blender/windowmanager/manipulators/intern/wm_manipulator_map.c index ab8c797df69..7b06382b029 100644 --- a/source/blender/windowmanager/manipulators/intern/wm_manipulator_map.c +++ b/source/blender/windowmanager/manipulators/intern/wm_manipulator_map.c @@ -542,9 +542,8 @@ static wmManipulator *manipulator_find_intersected_3d( int hotspot_radii[] = { 3 * U.pixelsize, -#if 0 /* We may want to enable when selection doesn't run on mousemove! */ - 7 * U.pixelsize, -#endif + /* This runs on mouse move, careful doing too many tests! */ + 10 * U.pixelsize, }; *r_part = 0; @@ -846,7 +845,7 @@ bool WM_manipulatormap_cursor_set(const wmManipulatorMap *mmap, wmWindow *win) return false; } -void wm_manipulatormap_highlight_set( +bool wm_manipulatormap_highlight_set( wmManipulatorMap *mmap, const bContext *C, wmManipulator *mpr, int part) { if ((mpr != mmap->mmap_context.highlight) || @@ -881,7 +880,11 @@ void wm_manipulatormap_highlight_set( ARegion *ar = CTX_wm_region(C); ED_region_tag_redraw(ar); } + + return true; } + + return false; } wmManipulator *wm_manipulatormap_highlight_get(wmManipulatorMap *mmap) diff --git a/source/blender/windowmanager/manipulators/wm_manipulator_wmapi.h b/source/blender/windowmanager/manipulators/wm_manipulator_wmapi.h index 87cf711a60b..7b294b9320f 100644 --- a/source/blender/windowmanager/manipulators/wm_manipulator_wmapi.h +++ b/source/blender/windowmanager/manipulators/wm_manipulator_wmapi.h @@ -77,7 +77,7 @@ void wm_manipulatormap_handler_context(bContext *C, struct wmEventHandler *handl struct wmManipulator *wm_manipulatormap_highlight_find( struct wmManipulatorMap *mmap, bContext *C, const struct wmEvent *event, int *r_part); -void wm_manipulatormap_highlight_set( +bool wm_manipulatormap_highlight_set( struct wmManipulatorMap *mmap, const bContext *C, struct wmManipulator *mpr, int part); struct wmManipulator *wm_manipulatormap_highlight_get(struct wmManipulatorMap *mmap); diff --git a/source/blender/windowmanager/wm_event_types.h b/source/blender/windowmanager/wm_event_types.h index db2fd5ce7f2..be648628079 100644 --- a/source/blender/windowmanager/wm_event_types.h +++ b/source/blender/windowmanager/wm_event_types.h @@ -368,6 +368,13 @@ enum { /* test whether the event is a mouse button */ #define ISMOUSE(event_type) ((event_type) >= LEFTMOUSE && (event_type) <= BUTTON7MOUSE) +#define ISMOUSE_WHEEL(event_type) ((event_type) >= WHEELUPMOUSE && (event_type) <= WHEELOUTMOUSE) +#define ISMOUSE_GESTURE(event_type) ((event_type) >= MOUSEPAN && (event_type) <= MOUSEROTATE) +#define ISMOUSE_BUTTON(event_type) \ + (ELEM(event_type, \ + LEFTMOUSE, MIDDLEMOUSE, RIGHTMOUSE, ACTIONMOUSE, SELECTMOUSE, \ + BUTTON4MOUSE, BUTTON5MOUSE, BUTTON6MOUSE, BUTTON7MOUSE)) + /* test whether the event is tweak event */ #define ISTWEAK(event_type) ((event_type) >= EVT_TWEAK_L && (event_type) <= EVT_GESTURE) diff --git a/source/blender/windowmanager/wm_files.h b/source/blender/windowmanager/wm_files.h index 4e87202ef5f..5b6022658db 100644 --- a/source/blender/windowmanager/wm_files.h +++ b/source/blender/windowmanager/wm_files.h @@ -31,6 +31,7 @@ #ifndef __WM_FILES_H__ #define __WM_FILES_H__ +struct Main; struct wmOperatorType; /* wm_files.c */ @@ -39,7 +40,7 @@ int wm_homefile_read( struct bContext *C, struct ReportList *reports, bool use_factory_settings, bool use_empty_data, bool use_userdef, const char *filepath_startup_override, const char *app_template_override); -void wm_file_read_report(bContext *C); +void wm_file_read_report(bContext *C, struct Main *bmain); void WM_OT_save_homefile(struct wmOperatorType *ot); void WM_OT_userpref_autoexec_path_add(struct wmOperatorType *ot); diff --git a/source/tools b/source/tools -Subproject fca325137b6ee2dfd0930ca87684ccf30703554 +Subproject f35d8e55afffb9da50cc13b14615ed280f9e558 |