2022-02-11 09:07:11 +11:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
|
* Copyright 2001-2002 NaN Holding BV. All rights reserved. */
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2019-02-18 08:08:12 +11:00
|
|
|
/** \file
|
|
|
|
|
* \ingroup bke
|
2011-02-27 20:40:57 +00:00
|
|
|
*/
|
|
|
|
|
|
2020-11-06 18:25:44 +01:00
|
|
|
/* Allow using deprecated functionality for .blend file I/O. */
|
|
|
|
|
#define DNA_DEPRECATED_ALLOW
|
|
|
|
|
|
2021-11-04 16:51:37 -03:00
|
|
|
#include <cmath>
|
|
|
|
|
#include <cstdio>
|
|
|
|
|
#include <cstring>
|
2002-11-25 12:02:15 +00:00
|
|
|
|
2019-02-01 12:44:19 +11:00
|
|
|
#include "CLG_log.h"
|
|
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
|
2.5: Blender "Animato" - New Animation System
Finally, here is the basic (functional) prototype of the new animation system which will allow for the infamous "everything is animatable", and which also addresses several of the more serious shortcomings of the old system. Unfortunately, this will break old animation files (especially right now, as I haven't written the version patching code yet), however, this is for the future.
Highlights of the new system:
* Scrapped IPO-Curves/IPO/(Action+Constraint-Channels)/Action system, and replaced it with F-Curve/Action.
- F-Curves (animators from other packages will feel at home with this name) replace IPO-Curves.
- The 'new' Actions, act as the containers for F-Curves, so that they can be reused. They are therefore more akin to the old 'IPO' blocks, except they do not have the blocktype restriction, so you can store materials/texture/geometry F-Curves in the same Action as Object transforms, etc.
* F-Curves use RNA-paths for Data Access, hence allowing "every" (where sensible/editable that is) user-accessible setting from RNA to be animated.
* Drivers are no longer mixed with Animation Data, so rigs will not be that easily broken and several dependency problems can be eliminated. (NOTE: drivers haven't been hooked up yet, but the code is in place)
* F-Curve modifier system allows useful 'large-scale' manipulation of F-Curve values, including (I've only included implemented ones here): envelope deform (similar to lattices to allow broad-scale reshaping of curves), curve generator (polynomial or py-expression), cycles (replacing the old cyclic extrapolation modes, giving more control over this). (NOTE: currently this cannot be tested, as there's not access to them, but the code is all in place)
* NLA system with 'tracks' (i.e. layers), and multiple strips per track. (NOTE: NLA system is not yet functional, as it's only partially coded still)
There are more nice things that I will be preparing some nice docs for soon, but for now, check for more details:
http://lists.blender.org/pipermail/bf-taskforce25/2009-January/000260.html
So, what currently works:
* I've implemented two basic operators for the 3D-view only to Insert and Delete Keyframes. These are tempolary ones only that will be replaced in due course with 'proper' code.
* Object Loc/Rot/Scale can be keyframed. Also, the colour of the 'active' material (Note: this should really be for nth material instead, but that doesn't work yet in RNA) can also be keyframed into the same datablock.
* Standard animation refresh (i.e. animation resulting from NLA and Action evaluation) is now done completely separate from drivers before anything else is done after a frame change. Drivers are handled after this in a separate pass, as dictated by depsgraph flags, etc.
Notes:
* Drivers haven't been hooked up yet
* Only objects and data directly linked to objects can be animated.
* Depsgraph will need further tweaks. Currently, I've only made sure that it will update some things in the most basic cases (i.e. frame change).
* Animation Editors are currently broken (in terms of editing stuff). This will be my next target (priority to get Dopesheet working first, then F-Curve editor - i.e. old IPO Editor)
* I've had to put in large chunks of XXX sandboxing for old animation system code all around the place. This will be cleaned up in due course, as some places need special review.
In particular, the particles and sequencer code have far too many manual calls to calculate + flush animation info, which is really bad (this is a 'please explain yourselves' call to Physics coders!).
2009-01-17 03:12:50 +00:00
|
|
|
#include "DNA_anim_types.h"
|
2002-10-12 11:37:38 +00:00
|
|
|
#include "DNA_armature_types.h"
|
|
|
|
|
#include "DNA_camera_types.h"
|
2018-08-29 15:32:50 +02:00
|
|
|
#include "DNA_collection_types.h"
|
2002-10-12 11:37:38 +00:00
|
|
|
#include "DNA_constraint_types.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "DNA_defaults.h"
|
2020-12-15 10:47:58 +11:00
|
|
|
#include "DNA_dynamicpaint_types.h"
|
2020-11-06 18:25:44 +01:00
|
|
|
#include "DNA_effect_types.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "DNA_fluid_types.h"
|
2018-07-31 10:22:19 +02:00
|
|
|
#include "DNA_gpencil_modifier_types.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "DNA_gpencil_types.h"
|
2009-12-28 15:26:36 +00:00
|
|
|
#include "DNA_key_types.h"
|
2002-10-12 11:37:38 +00:00
|
|
|
#include "DNA_lattice_types.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "DNA_light_types.h"
|
|
|
|
|
#include "DNA_lightprobe_types.h"
|
2002-10-12 11:37:38 +00:00
|
|
|
#include "DNA_material_types.h"
|
2012-02-19 22:17:30 +00:00
|
|
|
#include "DNA_mesh_types.h"
|
2004-03-20 22:55:42 +00:00
|
|
|
#include "DNA_meshdata_types.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "DNA_meta_types.h"
|
2011-11-07 12:55:18 +00:00
|
|
|
#include "DNA_movieclip_types.h"
|
2020-11-06 18:25:44 +01:00
|
|
|
#include "DNA_nla_types.h"
|
|
|
|
|
#include "DNA_object_fluidsim_types.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "DNA_object_types.h"
|
2020-04-09 18:49:40 +02:00
|
|
|
#include "DNA_pointcloud_types.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "DNA_rigidbody_types.h"
|
2002-10-12 11:37:38 +00:00
|
|
|
#include "DNA_scene_types.h"
|
|
|
|
|
#include "DNA_screen_types.h"
|
2010-03-09 13:52:52 +00:00
|
|
|
#include "DNA_sequence_types.h"
|
2018-07-31 10:22:19 +02:00
|
|
|
#include "DNA_shader_fx_types.h"
|
2002-10-12 11:37:38 +00:00
|
|
|
#include "DNA_space_types.h"
|
|
|
|
|
#include "DNA_view3d_types.h"
|
|
|
|
|
#include "DNA_world_types.h"
|
|
|
|
|
|
|
|
|
|
#include "BLI_blenlib.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "BLI_kdtree.h"
|
|
|
|
|
#include "BLI_linklist.h"
|
2020-09-15 15:41:06 +10:00
|
|
|
#include "BLI_listbase.h"
|
2010-03-22 11:59:36 +00:00
|
|
|
#include "BLI_math.h"
|
2022-04-01 14:48:48 -05:00
|
|
|
#include "BLI_math_vec_types.hh"
|
2014-01-09 16:19:51 +06:00
|
|
|
#include "BLI_threads.h"
|
2011-01-07 18:36:47 +00:00
|
|
|
#include "BLI_utildefines.h"
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2015-08-16 17:32:01 +10:00
|
|
|
#include "BLT_translation.h"
|
2013-03-24 12:13:13 +00:00
|
|
|
|
2.5: Blender "Animato" - New Animation System
Finally, here is the basic (functional) prototype of the new animation system which will allow for the infamous "everything is animatable", and which also addresses several of the more serious shortcomings of the old system. Unfortunately, this will break old animation files (especially right now, as I haven't written the version patching code yet), however, this is for the future.
Highlights of the new system:
* Scrapped IPO-Curves/IPO/(Action+Constraint-Channels)/Action system, and replaced it with F-Curve/Action.
- F-Curves (animators from other packages will feel at home with this name) replace IPO-Curves.
- The 'new' Actions, act as the containers for F-Curves, so that they can be reused. They are therefore more akin to the old 'IPO' blocks, except they do not have the blocktype restriction, so you can store materials/texture/geometry F-Curves in the same Action as Object transforms, etc.
* F-Curves use RNA-paths for Data Access, hence allowing "every" (where sensible/editable that is) user-accessible setting from RNA to be animated.
* Drivers are no longer mixed with Animation Data, so rigs will not be that easily broken and several dependency problems can be eliminated. (NOTE: drivers haven't been hooked up yet, but the code is in place)
* F-Curve modifier system allows useful 'large-scale' manipulation of F-Curve values, including (I've only included implemented ones here): envelope deform (similar to lattices to allow broad-scale reshaping of curves), curve generator (polynomial or py-expression), cycles (replacing the old cyclic extrapolation modes, giving more control over this). (NOTE: currently this cannot be tested, as there's not access to them, but the code is all in place)
* NLA system with 'tracks' (i.e. layers), and multiple strips per track. (NOTE: NLA system is not yet functional, as it's only partially coded still)
There are more nice things that I will be preparing some nice docs for soon, but for now, check for more details:
http://lists.blender.org/pipermail/bf-taskforce25/2009-January/000260.html
So, what currently works:
* I've implemented two basic operators for the 3D-view only to Insert and Delete Keyframes. These are tempolary ones only that will be replaced in due course with 'proper' code.
* Object Loc/Rot/Scale can be keyframed. Also, the colour of the 'active' material (Note: this should really be for nth material instead, but that doesn't work yet in RNA) can also be keyframed into the same datablock.
* Standard animation refresh (i.e. animation resulting from NLA and Action evaluation) is now done completely separate from drivers before anything else is done after a frame change. Drivers are handled after this in a separate pass, as dictated by depsgraph flags, etc.
Notes:
* Drivers haven't been hooked up yet
* Only objects and data directly linked to objects can be animated.
* Depsgraph will need further tweaks. Currently, I've only made sure that it will update some things in the most basic cases (i.e. frame change).
* Animation Editors are currently broken (in terms of editing stuff). This will be my next target (priority to get Dopesheet working first, then F-Curve editor - i.e. old IPO Editor)
* I've had to put in large chunks of XXX sandboxing for old animation system code all around the place. This will be cleaned up in due course, as some places need special review.
In particular, the particles and sequencer code have far too many manual calls to calculate + flush animation info, which is really bad (this is a 'please explain yourselves' call to Physics coders!).
2009-01-17 03:12:50 +00:00
|
|
|
#include "BKE_DerivedMesh.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "BKE_action.h"
|
2020-04-03 13:07:36 +02:00
|
|
|
#include "BKE_anim_data.h"
|
2020-04-03 11:35:04 +02:00
|
|
|
#include "BKE_anim_path.h"
|
|
|
|
|
#include "BKE_anim_visualization.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "BKE_animsys.h"
|
|
|
|
|
#include "BKE_armature.h"
|
2021-10-25 08:02:08 -03:00
|
|
|
#include "BKE_asset.h"
|
Refactor BKE_bpath module.
The main goal of this refactor is to make BPath module use `IDTypeInfo`,
and move each ID-specific part of the `foreach_path` looper into their
own IDTypeInfo struct, using a new `foreach_path` callback.
Additionally, following improvements/cleanups are included:
* Attempt to get better, more consistent namings.
** In particular, move from `path_visitor` to more standard `foreach_path`.
* Update and extend documentation.
** API doc was moved to header, according to recent discussions on this
topic.
* Remove `BKE_bpath_relocate_visitor` from API, this is specific
callback that belongs in `lib_id.c` user code.
NOTE: This commit is expected to be 100% non-behavioral-change. This
implies that several potential further changes were only noted as
comments (like using a more generic solution for
`lib_id_library_local_paths`, addressing inconsistencies like path of
packed libraries always being skipped, regardless of the
`BKE_BPATH_FOREACH_PATH_SKIP_PACKED` `eBPathForeachFlag` flag value,
etc.).
NOTE: basic unittests were added to master already in
rBdcc500e5a265093bc9cc.
Reviewed By: brecht
Differential Revision: https://developer.blender.org/D13381
2021-11-29 14:20:58 +01:00
|
|
|
#include "BKE_bpath.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "BKE_camera.h"
|
Collections and groups unification
OVERVIEW
* In 2.7 terminology, all layers and groups are now collection datablocks.
* These collections are nestable, linkable, instanceable, overrideable, ..
which opens up new ways to set up scenes and link + override data.
* Viewport/render visibility and selectability are now a part of the collection
and shared across all view layers and linkable.
* View layers define which subset of the scene collection hierarchy is excluded
for each. For many workflows one view layer can be used, these are more of an
advanced feature now.
OUTLINER
* The outliner now has a "View Layer" display mode instead of "Collections",
which can display the collections and/or objects in the view layer.
* In this display mode, collections can be excluded with the right click menu.
These will then be greyed out and their objects will be excluded.
* To view collections not linked to any scene, the "Blender File" display mode
can be used, with the new filtering option to just see Colleciton datablocks.
* The outliner right click menus for collections and objects were reorganized.
* Drag and drop still needs to be improved. Like before, dragging the icon or
text gives different results, we'll unify this later.
LINKING AND OVERRIDES
* Collections can now be linked into the scene without creating an instance,
with the link/append operator or from the collections view in the outliner.
* Collections can get static overrides with the right click menu in the outliner,
but this is rather unreliable and not clearly communicated at the moment.
* We still need to improve the make override operator to turn collection instances
into collections with overrides directly in the scene.
PERFORMANCE
* We tried to make performance not worse than before and improve it in some
cases. The main thing that's still a bit slower is multiple scenes, we have to
change the layer syncing to only updated affected scenes.
* Collections keep a list of their parent collections for faster incremental
updates in syncing and caching.
* View layer bases are now in a object -> base hash to avoid quadratic time
lookups internally and in API functions like visible_get().
VERSIONING
* Compatibility with 2.7 files should be improved due to the new visibility
controls. Of course users may not want to set up their scenes differently
now to avoid having separate layers and groups.
* Compatibility with 2.8 is mostly there, and was tested on Eevee demo and Hero
files. There's a few things which are know to be not quite compatible, like
nested layer collections inside groups.
* The versioning code for 2.8 files is quite complicated, and isolated behind
#ifdef so it can be removed at the end of the release cycle.
KNOWN ISSUES
* The G-key group operators in the 3D viewport were left mostly as is, they
need to be modified still to fit better.
* Same for the groups panel in the object properties. This needs to be updated
still, or perhaps replaced by something better.
* Collections must all have a unique name. Less restrictive namespacing is to
be done later, we'll have to see how important this is as all objects within
the collections must also have a unique name anyway.
* Full scene copy and delete scene are exactly doing the right thing yet.
Differential Revision: https://developer.blender.org/D3383
https://code.blender.org/2018/05/collections-and-groups/
2018-04-30 15:57:22 +02:00
|
|
|
#include "BKE_collection.h"
|
Result of 2 weeks of quiet coding work in Greece :)
Aim was to get a total refresh of the animation system. This
is needed because;
- we need to upgrade it with 21st century features
- current code is spaghetti/hack combo, and hides good design
- it should become lag-free with using dependency graphs
A full log, with complete code API/structure/design explanation
will follow, that's a load of work... so here below the list with
hot changes;
- The entire object update system (matrices, geometry) is now
centralized. Calls to where_is_object and makeDispList are
forbidden, instead we tag objects 'changed' and let the
depgraph code sort it out
- Removed all old "Ika" code
- Depgraph is aware of all relationships, including meta balls,
constraints, bevelcurve, and so on.
- Made depgraph aware of relation types and layers, to do smart
flushing of 'changed' events. Nothing gets calculated too often!
- Transform uses depgraph to detect changes
- On frame-advance, depgraph flushes animated changes
Armatures;
Almost all armature related code has been fully built from scratch.
It now reveils the original design much better, with a very clean
implementation, lag free without even calculating each Bone more than
once. Result is quite a speedup yes!
Important to note is;
1) Armature is data containing the 'rest position'
2) Pose is the changes of rest position, and always on object level.
That way more Objects can use same Pose. Also constraints are in Pose
3) Actions only contain the Ipos to change values in Poses.
- Bones draw unrotated now
- Drawing bones speedup enormously (10-20 times)
- Bone selecting in EditMode, selection state is saved for PoseMode,
and vice-versa
- Undo in editmode
- Bone renaming does vertexgroups, constraints, posechannels, actions,
for all users of Armature in entire file
- Added Bone renaming in NKey panel
- Nkey PoseMode shows eulers now
- EditMode and PoseMode now have 'active' bone too (last clicked)
- Parenting in EditMode' CTRL+P, ALT+P, with nice options!
- Pose is added in Outliner now, with showing that constraints are in
the Pose, not Armature
- Disconnected IK solving from constraints. It's a separate phase now,
on top of the full Pose calculations
- Pose itself has a dependency graph too, so evaluation order is lag free.
TODO NOW;
- Rotating in Posemode has incorrect inverse transform (Martin will fix)
- Python Bone/Armature/Pose API disabled... needs full recode too
(wait for my doc!)
- Game engine will need upgrade too
- Depgraph code needs revision, cleanup, can be much faster!
(But, compliments for Jean-Luc, it works like a charm!)
- IK changed, it now doesnt use previous position to advance to next
position anymore. That system looks nice (no flips) but is not well
suited for NLA and background render.
TODO LATER;
We now can do loadsa new nifty features as well; like:
- Kill PoseMode (can be option for armatures itself)
- Make B-Bones (Bezier, Bspline, like for spines)
- Move all silly button level edit to 3d window (like CTRL+I = add
IK)
- Much better & informative drawing
- Fix action/nla editors
- Put all ipos in Actions (object, mesh key, lamp color)
- Add hooks
- Null bones
- Much more advanced constraints...
Bugfixes;
- OGL render (view3d header) had wrong first frame on anim render
- Ipo 'recording' mode had wrong playback speed
- Vertex-key mode now sticks to show 'active key', until frame change
-Ton-
2005-07-03 17:35:38 +00:00
|
|
|
#include "BKE_constraint.h"
|
2022-01-05 09:53:48 +01:00
|
|
|
#include "BKE_crazyspace.h"
|
Result of 2 weeks of quiet coding work in Greece :)
Aim was to get a total refresh of the animation system. This
is needed because;
- we need to upgrade it with 21st century features
- current code is spaghetti/hack combo, and hides good design
- it should become lag-free with using dependency graphs
A full log, with complete code API/structure/design explanation
will follow, that's a load of work... so here below the list with
hot changes;
- The entire object update system (matrices, geometry) is now
centralized. Calls to where_is_object and makeDispList are
forbidden, instead we tag objects 'changed' and let the
depgraph code sort it out
- Removed all old "Ika" code
- Depgraph is aware of all relationships, including meta balls,
constraints, bevelcurve, and so on.
- Made depgraph aware of relation types and layers, to do smart
flushing of 'changed' events. Nothing gets calculated too often!
- Transform uses depgraph to detect changes
- On frame-advance, depgraph flushes animated changes
Armatures;
Almost all armature related code has been fully built from scratch.
It now reveils the original design much better, with a very clean
implementation, lag free without even calculating each Bone more than
once. Result is quite a speedup yes!
Important to note is;
1) Armature is data containing the 'rest position'
2) Pose is the changes of rest position, and always on object level.
That way more Objects can use same Pose. Also constraints are in Pose
3) Actions only contain the Ipos to change values in Poses.
- Bones draw unrotated now
- Drawing bones speedup enormously (10-20 times)
- Bone selecting in EditMode, selection state is saved for PoseMode,
and vice-versa
- Undo in editmode
- Bone renaming does vertexgroups, constraints, posechannels, actions,
for all users of Armature in entire file
- Added Bone renaming in NKey panel
- Nkey PoseMode shows eulers now
- EditMode and PoseMode now have 'active' bone too (last clicked)
- Parenting in EditMode' CTRL+P, ALT+P, with nice options!
- Pose is added in Outliner now, with showing that constraints are in
the Pose, not Armature
- Disconnected IK solving from constraints. It's a separate phase now,
on top of the full Pose calculations
- Pose itself has a dependency graph too, so evaluation order is lag free.
TODO NOW;
- Rotating in Posemode has incorrect inverse transform (Martin will fix)
- Python Bone/Armature/Pose API disabled... needs full recode too
(wait for my doc!)
- Game engine will need upgrade too
- Depgraph code needs revision, cleanup, can be much faster!
(But, compliments for Jean-Luc, it works like a charm!)
- IK changed, it now doesnt use previous position to advance to next
position anymore. That system looks nice (no flips) but is not well
suited for NLA and background render.
TODO LATER;
We now can do loadsa new nifty features as well; like:
- Kill PoseMode (can be option for armatures itself)
- Make B-Bones (Bezier, Bspline, like for spines)
- Move all silly button level edit to 3d window (like CTRL+I = add
IK)
- Much better & informative drawing
- Fix action/nla editors
- Put all ipos in Actions (object, mesh key, lamp color)
- Add hooks
- Null bones
- Much more advanced constraints...
Bugfixes;
- OGL render (view3d header) had wrong first frame on anim render
- Ipo 'recording' mode had wrong playback speed
- Vertex-key mode now sticks to show 'active key', until frame change
-Ton-
2005-07-03 17:35:38 +00:00
|
|
|
#include "BKE_curve.h"
|
2022-02-16 11:32:37 -06:00
|
|
|
#include "BKE_curves.hh"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "BKE_deform.h"
|
Result of 2 weeks of quiet coding work in Greece :)
Aim was to get a total refresh of the animation system. This
is needed because;
- we need to upgrade it with 21st century features
- current code is spaghetti/hack combo, and hides good design
- it should become lag-free with using dependency graphs
A full log, with complete code API/structure/design explanation
will follow, that's a load of work... so here below the list with
hot changes;
- The entire object update system (matrices, geometry) is now
centralized. Calls to where_is_object and makeDispList are
forbidden, instead we tag objects 'changed' and let the
depgraph code sort it out
- Removed all old "Ika" code
- Depgraph is aware of all relationships, including meta balls,
constraints, bevelcurve, and so on.
- Made depgraph aware of relation types and layers, to do smart
flushing of 'changed' events. Nothing gets calculated too often!
- Transform uses depgraph to detect changes
- On frame-advance, depgraph flushes animated changes
Armatures;
Almost all armature related code has been fully built from scratch.
It now reveils the original design much better, with a very clean
implementation, lag free without even calculating each Bone more than
once. Result is quite a speedup yes!
Important to note is;
1) Armature is data containing the 'rest position'
2) Pose is the changes of rest position, and always on object level.
That way more Objects can use same Pose. Also constraints are in Pose
3) Actions only contain the Ipos to change values in Poses.
- Bones draw unrotated now
- Drawing bones speedup enormously (10-20 times)
- Bone selecting in EditMode, selection state is saved for PoseMode,
and vice-versa
- Undo in editmode
- Bone renaming does vertexgroups, constraints, posechannels, actions,
for all users of Armature in entire file
- Added Bone renaming in NKey panel
- Nkey PoseMode shows eulers now
- EditMode and PoseMode now have 'active' bone too (last clicked)
- Parenting in EditMode' CTRL+P, ALT+P, with nice options!
- Pose is added in Outliner now, with showing that constraints are in
the Pose, not Armature
- Disconnected IK solving from constraints. It's a separate phase now,
on top of the full Pose calculations
- Pose itself has a dependency graph too, so evaluation order is lag free.
TODO NOW;
- Rotating in Posemode has incorrect inverse transform (Martin will fix)
- Python Bone/Armature/Pose API disabled... needs full recode too
(wait for my doc!)
- Game engine will need upgrade too
- Depgraph code needs revision, cleanup, can be much faster!
(But, compliments for Jean-Luc, it works like a charm!)
- IK changed, it now doesnt use previous position to advance to next
position anymore. That system looks nice (no flips) but is not well
suited for NLA and background render.
TODO LATER;
We now can do loadsa new nifty features as well; like:
- Kill PoseMode (can be option for armatures itself)
- Make B-Bones (Bezier, Bspline, like for spines)
- Move all silly button level edit to 3d window (like CTRL+I = add
IK)
- Much better & informative drawing
- Fix action/nla editors
- Put all ipos in Actions (object, mesh key, lamp color)
- Add hooks
- Null bones
- Much more advanced constraints...
Bugfixes;
- OGL render (view3d header) had wrong first frame on anim render
- Ipo 'recording' mode had wrong playback speed
- Vertex-key mode now sticks to show 'active key', until frame change
-Ton-
2005-07-03 17:35:38 +00:00
|
|
|
#include "BKE_displist.h"
|
2020-04-03 11:35:04 +02:00
|
|
|
#include "BKE_duplilist.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "BKE_editmesh.h"
|
2020-05-25 20:16:42 +10:00
|
|
|
#include "BKE_editmesh_cache.h"
|
Unified effector functionality for particles, cloth and softbody
* Unified scene wide gravity (currently in scene buttons)
instead of each simulation having it's own gravity.
* Weight parameters for all effectors and an effector group
setting.
* Every effector can use noise.
* Most effectors have "shapes" point, plane, surface, every point.
- "Point" is most like the old effectors and uses the
effector location as the effector point.
- "Plane" uses the closest point on effectors local xy-plane
as the effector point.
- "Surface" uses the closest point on an effector object's
surface as the effector point.
- "Every Point" uses every point in a mesh effector object
as an effector point.
- The falloff is calculated from this point, so for example
with "surface" shape and "use only negative z axis" it's
possible to apply force only "inside" the effector object.
* Spherical effector is now renamed as "force" as it's no longer
just spherical.
* New effector parameter "flow", which makes the effector act as
surrounding air velocity, so the resulting force is
proportional to the velocity difference of the point and "air
velocity". For example a wind field with flow=1.0 results in
proper non-accelerating wind.
* New effector fields "turbulence", which creates nice random
flow paths, and "drag", which slows the points down.
* Much improved vortex field.
* Effectors can now effect particle rotation as well as location.
* Use full, or only positive/negative z-axis to apply force
(note. the z-axis is the surface normal in the case of
effector shape "surface")
* New "force field" submenu in add menu, which adds an empty
with the chosen effector (curve object for corve guides).
* Other dynamics should be quite easy to add to the effector
system too if wanted.
* "Unified" doesn't mean that force fields give the exact same results for
particles, softbody & cloth, since their final effect depends on many external
factors, like for example the surface area of the effected faces.
Code changes
* Subversion bump for correct handling of global gravity.
* Separate ui py file for common dynamics stuff.
* Particle settings updating is flushed with it's id through
DAG_id_flush_update(..).
Known issues
* Curve guides don't yet have all ui buttons in place, but they
should work none the less.
* Hair dynamics don't yet respect force fields.
Other changes
* Particle emission defaults now to frames 1-200 with life of 50
frames to fill the whole default timeline.
* Many particles drawing related crashes fixed.
* Sometimes particles didn't update on first frame properly.
* Hair with object/group visualization didn't work properly.
* Memory leaks with PointCacheID lists (Genscher, remember to
free pidlists after use :).
2009-09-30 22:10:14 +00:00
|
|
|
#include "BKE_effect.h"
|
2009-08-03 12:11:50 +00:00
|
|
|
#include "BKE_fcurve.h"
|
2020-05-01 12:43:12 +02:00
|
|
|
#include "BKE_fcurve_driver.h"
|
2020-12-02 13:25:25 +01:00
|
|
|
#include "BKE_geometry_set.h"
|
2021-11-05 11:51:34 -05:00
|
|
|
#include "BKE_geometry_set.hh"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "BKE_global.h"
|
|
|
|
|
#include "BKE_gpencil.h"
|
2020-03-19 11:35:17 +01:00
|
|
|
#include "BKE_gpencil_geom.h"
|
2018-07-31 10:22:19 +02:00
|
|
|
#include "BKE_gpencil_modifier.h"
|
2015-08-10 15:41:28 +02:00
|
|
|
#include "BKE_icons.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "BKE_idprop.h"
|
2020-03-05 10:54:00 +01:00
|
|
|
#include "BKE_idtype.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "BKE_image.h"
|
Result of 2 weeks of quiet coding work in Greece :)
Aim was to get a total refresh of the animation system. This
is needed because;
- we need to upgrade it with 21st century features
- current code is spaghetti/hack combo, and hides good design
- it should become lag-free with using dependency graphs
A full log, with complete code API/structure/design explanation
will follow, that's a load of work... so here below the list with
hot changes;
- The entire object update system (matrices, geometry) is now
centralized. Calls to where_is_object and makeDispList are
forbidden, instead we tag objects 'changed' and let the
depgraph code sort it out
- Removed all old "Ika" code
- Depgraph is aware of all relationships, including meta balls,
constraints, bevelcurve, and so on.
- Made depgraph aware of relation types and layers, to do smart
flushing of 'changed' events. Nothing gets calculated too often!
- Transform uses depgraph to detect changes
- On frame-advance, depgraph flushes animated changes
Armatures;
Almost all armature related code has been fully built from scratch.
It now reveils the original design much better, with a very clean
implementation, lag free without even calculating each Bone more than
once. Result is quite a speedup yes!
Important to note is;
1) Armature is data containing the 'rest position'
2) Pose is the changes of rest position, and always on object level.
That way more Objects can use same Pose. Also constraints are in Pose
3) Actions only contain the Ipos to change values in Poses.
- Bones draw unrotated now
- Drawing bones speedup enormously (10-20 times)
- Bone selecting in EditMode, selection state is saved for PoseMode,
and vice-versa
- Undo in editmode
- Bone renaming does vertexgroups, constraints, posechannels, actions,
for all users of Armature in entire file
- Added Bone renaming in NKey panel
- Nkey PoseMode shows eulers now
- EditMode and PoseMode now have 'active' bone too (last clicked)
- Parenting in EditMode' CTRL+P, ALT+P, with nice options!
- Pose is added in Outliner now, with showing that constraints are in
the Pose, not Armature
- Disconnected IK solving from constraints. It's a separate phase now,
on top of the full Pose calculations
- Pose itself has a dependency graph too, so evaluation order is lag free.
TODO NOW;
- Rotating in Posemode has incorrect inverse transform (Martin will fix)
- Python Bone/Armature/Pose API disabled... needs full recode too
(wait for my doc!)
- Game engine will need upgrade too
- Depgraph code needs revision, cleanup, can be much faster!
(But, compliments for Jean-Luc, it works like a charm!)
- IK changed, it now doesnt use previous position to advance to next
position anymore. That system looks nice (no flips) but is not well
suited for NLA and background render.
TODO LATER;
We now can do loadsa new nifty features as well; like:
- Kill PoseMode (can be option for armatures itself)
- Make B-Bones (Bezier, Bspline, like for spines)
- Move all silly button level edit to 3d window (like CTRL+I = add
IK)
- Much better & informative drawing
- Fix action/nla editors
- Put all ipos in Actions (object, mesh key, lamp color)
- Add hooks
- Null bones
- Much more advanced constraints...
Bugfixes;
- OGL render (view3d header) had wrong first frame on anim render
- Ipo 'recording' mode had wrong playback speed
- Vertex-key mode now sticks to show 'active key', until frame change
-Ton-
2005-07-03 17:35:38 +00:00
|
|
|
#include "BKE_key.h"
|
|
|
|
|
#include "BKE_lattice.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "BKE_layer.h"
|
2020-02-10 12:58:59 +01:00
|
|
|
#include "BKE_lib_id.h"
|
|
|
|
|
#include "BKE_lib_query.h"
|
|
|
|
|
#include "BKE_lib_remap.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "BKE_light.h"
|
|
|
|
|
#include "BKE_lightprobe.h"
|
2013-03-23 03:00:37 +00:00
|
|
|
#include "BKE_linestyle.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "BKE_main.h"
|
|
|
|
|
#include "BKE_material.h"
|
2002-10-12 11:37:38 +00:00
|
|
|
#include "BKE_mball.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "BKE_mesh.h"
|
2020-06-10 22:32:06 +10:00
|
|
|
#include "BKE_mesh_wrapper.h"
|
- shuffled editmesh derived function name/function
- added ModifierTypeInfo.freeData function
- added modifier_{new,free] utility function
- added ccgSubSurf_getUseAgeCounts to query info
- removed subsurf modifier faking (ME_SUBSURF flag is no
longer valid). subsurf modifier gets converted on file load
although there is obscure linked mesh situation where this
can go wrong, will fix shortly. this also means that some
places in the code that test/copy subsurf settings are broken
for the time being.
- shuffled modifier calculation to be simpler. note that
all modifiers are currently disabled in editmode (including
subsurf). don't worry, will return shortly.
- bug fix, build modifier didn't randomize meshes with only verts
- cleaned up subsurf_ccg and adapted for future editmode modifier
work
- added editmesh.derived{Cage,Final}, not used yet
- added SubsurfModifierData.{mCache,emCache}, will be used to cache
subsurf instead of caching in derivedmesh itself
- removed old subsurf buttons
- added do_modifiers_buttons to handle modifier events
- removed count_object counting of modifier (subsurfed) objects...
this would be nice to add back at some point but requires care.
probably requires rewrite of counting system.
New feature: Incremental Subsurf in Object Mode
The previous release introduce incremental subsurf calculation during
editmode but it was not turned on during object mode. In general it
does not make sense to have it always enabled during object mode because
it requires caching a fair amount of information about the mesh which
is a waste of memory unless the mesh is often recalculated.
However, for mesh's that have subsurfed armatures for example, or that
have other modifiers so that the mesh is essentially changing on every
frame, it makes a lot of sense to keep the subsurf'd object around and
that is what the new incremental subsurf modifier toggle is for. The
intent is that the user will enable this option for (a) a mesh that is
currently under active editing or (b) a mesh that is heavily updated
in the scene, such as a character.
I will try to write more about this feature for release, because it
has advantages and disadvantages that are not immediately obvious (the
first user reaction will be to turn it on for ever object, which is
probably not correct).
2005-07-21 20:30:33 +00:00
|
|
|
#include "BKE_modifier.h"
|
2015-05-07 15:16:10 +02:00
|
|
|
#include "BKE_multires.h"
|
2014-11-06 17:55:55 +01:00
|
|
|
#include "BKE_node.h"
|
Result of 2 weeks of quiet coding work in Greece :)
Aim was to get a total refresh of the animation system. This
is needed because;
- we need to upgrade it with 21st century features
- current code is spaghetti/hack combo, and hides good design
- it should become lag-free with using dependency graphs
A full log, with complete code API/structure/design explanation
will follow, that's a load of work... so here below the list with
hot changes;
- The entire object update system (matrices, geometry) is now
centralized. Calls to where_is_object and makeDispList are
forbidden, instead we tag objects 'changed' and let the
depgraph code sort it out
- Removed all old "Ika" code
- Depgraph is aware of all relationships, including meta balls,
constraints, bevelcurve, and so on.
- Made depgraph aware of relation types and layers, to do smart
flushing of 'changed' events. Nothing gets calculated too often!
- Transform uses depgraph to detect changes
- On frame-advance, depgraph flushes animated changes
Armatures;
Almost all armature related code has been fully built from scratch.
It now reveils the original design much better, with a very clean
implementation, lag free without even calculating each Bone more than
once. Result is quite a speedup yes!
Important to note is;
1) Armature is data containing the 'rest position'
2) Pose is the changes of rest position, and always on object level.
That way more Objects can use same Pose. Also constraints are in Pose
3) Actions only contain the Ipos to change values in Poses.
- Bones draw unrotated now
- Drawing bones speedup enormously (10-20 times)
- Bone selecting in EditMode, selection state is saved for PoseMode,
and vice-versa
- Undo in editmode
- Bone renaming does vertexgroups, constraints, posechannels, actions,
for all users of Armature in entire file
- Added Bone renaming in NKey panel
- Nkey PoseMode shows eulers now
- EditMode and PoseMode now have 'active' bone too (last clicked)
- Parenting in EditMode' CTRL+P, ALT+P, with nice options!
- Pose is added in Outliner now, with showing that constraints are in
the Pose, not Armature
- Disconnected IK solving from constraints. It's a separate phase now,
on top of the full Pose calculations
- Pose itself has a dependency graph too, so evaluation order is lag free.
TODO NOW;
- Rotating in Posemode has incorrect inverse transform (Martin will fix)
- Python Bone/Armature/Pose API disabled... needs full recode too
(wait for my doc!)
- Game engine will need upgrade too
- Depgraph code needs revision, cleanup, can be much faster!
(But, compliments for Jean-Luc, it works like a charm!)
- IK changed, it now doesnt use previous position to advance to next
position anymore. That system looks nice (no flips) but is not well
suited for NLA and background render.
TODO LATER;
We now can do loadsa new nifty features as well; like:
- Kill PoseMode (can be option for armatures itself)
- Make B-Bones (Bezier, Bspline, like for spines)
- Move all silly button level edit to 3d window (like CTRL+I = add
IK)
- Much better & informative drawing
- Fix action/nla editors
- Put all ipos in Actions (object, mesh key, lamp color)
- Add hooks
- Null bones
- Much more advanced constraints...
Bugfixes;
- OGL render (view3d header) had wrong first frame on anim render
- Ipo 'recording' mode had wrong playback speed
- Vertex-key mode now sticks to show 'active key', until frame change
-Ton-
2005-07-03 17:35:38 +00:00
|
|
|
#include "BKE_object.h"
|
2017-05-30 17:58:24 +10:00
|
|
|
#include "BKE_object_facemap.h"
|
2009-08-28 21:47:11 +00:00
|
|
|
#include "BKE_paint.h"
|
Particles
=========
Merge of the famous particle patch by Janne Karhu, a full rewrite
of the Blender particle system. This includes:
- Emitter, Hair and Reactor particle types.
- Newtonian, Keyed and Boids physics.
- Various particle visualisation and rendering types.
- Vertex group and texture control for various properties.
- Interpolated child particles from parents.
- Hair editing with combing, growing, cutting, .. .
- Explode modifier.
- Harmonic, Magnetic fields, and multiple falloff types.
.. and lots of other things, some more info is here:
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite_Doc
The new particle system cannot be backwards compatible. Old particle
systems are being converted to the new system, but will require
tweaking to get them looking the same as before.
Point Cache
===========
The new system to replace manual baking, based on automatic caching
on disk. This is currently used by softbodies and the particle system.
See the Cache API section on:
http://wiki.blender.org/index.php/BlenderDev/PhysicsSprint
Documentation
=============
These new features still need good docs for the release logs, help
for this is appreciated.
2007-11-26 22:09:57 +00:00
|
|
|
#include "BKE_particle.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "BKE_pbvh.h"
|
Point Cache Refactoring
=======================
Caching and Baking:
- The point cache is now cleared on DAG_object_flush_update(), and not cleared for time dependency graph updates.
- There is now a Bake button instead of Protect. Also cache start and end frames were added to softbody and particles.
- The cloth autoprotect feature was removed.
- The Ctrl+B menu now also bakes cloth and particles next to softbody and fluids. Additionally there are now frree bake and free cache menu entries.
- The point cache api has been changed. There is now a PTCacheID struct for each point cache type that can be filled and then used to call the point cache functions.
- PointCache struct was added to DNA and is automatically allocated for each physics type.
- Soft body now supports Bake Editing just like cloth.
- Tried to make the systems deal consistently with time ipo's and offsets. Still not sure it all works correct, but too complicated to solve completely now.
Library Linking:
- Added some more warnings to prevent editing settings on library linked objects.
- Linked objects now read from the cache located next to the original library file, and never write to it. This restores old behavior for softbodies. For local simulation the mesh and not the object should be linked.
- Dupligroups and proxies can't create local point caches at the moment, how to implement that I'm not sure. We probably need a proxy point cache for that to work (ugh).
Physics UI:
- Renamed deflection panel to collision for consistency and reorganized the buttons. Also removed some softbody collision buttons from the softbody panel that were duplicated in this panel for cloth.
- Tweaked field panel buttons to not jump around when changing options.
- Tabbing e.g. Soft Body Collision into the Soft Body panel, it now only shows Collision to make the panel names readable.
- I tried to make enabled/disabling physics more consistent, since all three system did things different. Now the two modifier buttons to enable the modifier for the viewport and rendering are also duplicated in the physics panels. Toggling the Soft Body and Cloth buttons now both remove their modifiers.
- Fixed modifier error drawing glitch.
Particles:
- Particles are now recalculated more often than before. Previously it did partial updates based on the changes, but that doesn't work well with DAG_object_flush_update() ..
- Fixed memory leak loading keyed particle system. Now keys are not written to file anymore but always created after loading.
- Make particle threads work with autothreads.
Continue Physics:
- The timeline play now has a Continue Physics option in the playback menu, which keeps the simulations going without writing them to the cache.
- This doesn't always work that well, some changes are not immediately updated, but this can be improved later. Still it's fun to get a feel for the physics.
Todo:
- Point cache can get out of sync with and undo and changing a file without saving it.
- Change the point cache file format to store a version (so old point cache files can be either converted or at least ignored), and to do correct endian conversion.
- Menu item and/or buttons for Ctrl+B.
- A system("rm ..") was changed to remove() since the former is very slow for clearing point caches. These system() calls were already giving trouble in a bug in the tracker, but really most use of this system("") should be changed and tested.
- The Soft Body Collision and Clot Collision panel titles don't mention there's point cache settings there too, doing that makes them unreadable with the default panel setup.. but may need to make the names longer anyway.
2008-04-10 11:39:20 +00:00
|
|
|
#include "BKE_pointcache.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "BKE_pointcloud.h"
|
2013-01-23 05:56:22 +00:00
|
|
|
#include "BKE_rigidbody.h"
|
2002-10-12 11:37:38 +00:00
|
|
|
#include "BKE_scene.h"
|
2018-07-31 10:22:19 +02:00
|
|
|
#include "BKE_shader_fx.h"
|
2004-10-01 14:04:17 +00:00
|
|
|
#include "BKE_softbody.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "BKE_speaker.h"
|
2018-09-25 12:31:01 +02:00
|
|
|
#include "BKE_subdiv_ccg.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "BKE_subsurf.h"
|
2021-10-06 11:15:53 +11:00
|
|
|
#include "BKE_vfont.h"
|
2020-03-17 14:41:48 +01:00
|
|
|
#include "BKE_volume.h"
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2017-04-06 15:37:46 +02:00
|
|
|
#include "DEG_depsgraph.h"
|
2018-05-25 12:27:54 +02:00
|
|
|
#include "DEG_depsgraph_query.h"
|
2017-04-06 15:37:46 +02:00
|
|
|
|
2017-04-03 19:01:10 +02:00
|
|
|
#include "DRW_engine.h"
|
|
|
|
|
|
2020-11-06 16:42:37 +01:00
|
|
|
#include "BLO_read_write.h"
|
2021-08-03 12:54:05 +02:00
|
|
|
#include "BLO_readfile.h"
|
2020-11-06 16:42:37 +01:00
|
|
|
|
2020-11-01 21:03:31 +01:00
|
|
|
#include "SEQ_sequencer.h"
|
|
|
|
|
|
2010-10-31 04:11:39 +00:00
|
|
|
#ifdef WITH_PYTHON
|
2003-11-23 14:28:46 +00:00
|
|
|
# include "BPY_extern.h"
|
2008-10-28 18:47:13 +00:00
|
|
|
#endif
|
2003-11-23 14:28:46 +00:00
|
|
|
|
2014-10-31 20:06:19 +01:00
|
|
|
#include "CCGSubSurf.h"
|
2017-04-26 15:40:32 +02:00
|
|
|
#include "atomic_ops.h"
|
2014-10-31 20:06:19 +01:00
|
|
|
|
2022-04-01 14:48:48 -05:00
|
|
|
using blender::float3;
|
|
|
|
|
|
2019-02-01 12:44:19 +11:00
|
|
|
static CLG_LogRef LOG = {"bke.object"};
|
|
|
|
|
|
2020-09-07 14:33:24 +10:00
|
|
|
/**
|
2021-11-05 10:19:44 +11:00
|
|
|
* NOTE(@sergey): Vertex parent modifies original #BMesh which is not safe for threading.
|
2014-01-09 16:19:51 +06:00
|
|
|
* Ideally such a modification should be handled as a separate DAG update
|
2021-11-05 10:19:44 +11:00
|
|
|
* callback for mesh data-block, but for until it is actually supported use
|
2014-01-09 16:19:51 +06:00
|
|
|
* simpler solution with a mutex lock.
|
|
|
|
|
*/
|
|
|
|
|
#define VPARENT_THREADING_HACK
|
|
|
|
|
|
|
|
|
|
#ifdef VPARENT_THREADING_HACK
|
|
|
|
|
static ThreadMutex vparent_lock = BLI_MUTEX_INITIALIZER;
|
|
|
|
|
#endif
|
|
|
|
|
|
2020-03-05 10:54:00 +01:00
|
|
|
static void copy_object_pose(Object *obn, const Object *ob, const int flag);
|
|
|
|
|
|
|
|
|
|
static void object_init_data(ID *id)
|
|
|
|
|
{
|
|
|
|
|
Object *ob = (Object *)id;
|
|
|
|
|
BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(ob, id));
|
|
|
|
|
|
|
|
|
|
MEMCPY_STRUCT_AFTER(ob, DNA_struct_default_get(Object), id);
|
|
|
|
|
|
|
|
|
|
ob->type = OB_EMPTY;
|
|
|
|
|
|
|
|
|
|
ob->trackflag = OB_POSY;
|
|
|
|
|
ob->upflag = OB_POSZ;
|
|
|
|
|
|
|
|
|
|
/* Animation Visualization defaults */
|
|
|
|
|
animviz_settings_init(&ob->avs);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void object_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int flag)
|
|
|
|
|
{
|
|
|
|
|
Object *ob_dst = (Object *)id_dst;
|
|
|
|
|
const Object *ob_src = (const Object *)id_src;
|
|
|
|
|
|
|
|
|
|
/* Do not copy runtime data. */
|
|
|
|
|
BKE_object_runtime_reset_on_copy(ob_dst, flag);
|
|
|
|
|
|
|
|
|
|
/* We never handle usercount here for own data. */
|
|
|
|
|
const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT;
|
|
|
|
|
|
|
|
|
|
if (ob_src->totcol) {
|
2021-11-04 16:51:37 -03:00
|
|
|
ob_dst->mat = (Material **)MEM_dupallocN(ob_src->mat);
|
|
|
|
|
ob_dst->matbits = (char *)MEM_dupallocN(ob_src->matbits);
|
2020-03-05 10:54:00 +01:00
|
|
|
ob_dst->totcol = ob_src->totcol;
|
|
|
|
|
}
|
2021-11-04 16:51:37 -03:00
|
|
|
else if (ob_dst->mat != nullptr || ob_dst->matbits != nullptr) {
|
2020-03-05 10:54:00 +01:00
|
|
|
/* This shall not be needed, but better be safe than sorry. */
|
2021-07-15 18:23:28 +10:00
|
|
|
BLI_assert_msg(
|
2021-11-04 16:51:37 -03:00
|
|
|
0, "Object copy: non-nullptr material pointers with zero counter, should not happen.");
|
|
|
|
|
ob_dst->mat = nullptr;
|
|
|
|
|
ob_dst->matbits = nullptr;
|
2020-03-05 10:54:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ob_src->iuser) {
|
2021-11-04 16:51:37 -03:00
|
|
|
ob_dst->iuser = (ImageUser *)MEM_dupallocN(ob_src->iuser);
|
2020-03-05 10:54:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ob_src->runtime.bb) {
|
2021-11-04 16:51:37 -03:00
|
|
|
ob_dst->runtime.bb = (BoundBox *)MEM_dupallocN(ob_src->runtime.bb);
|
2020-03-05 10:54:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BLI_listbase_clear(&ob_dst->shader_fx);
|
2020-05-07 10:11:40 +02:00
|
|
|
LISTBASE_FOREACH (ShaderFxData *, fx, &ob_src->shader_fx) {
|
2020-03-05 10:54:00 +01:00
|
|
|
ShaderFxData *nfx = BKE_shaderfx_new(fx->type);
|
|
|
|
|
BLI_strncpy(nfx->name, fx->name, sizeof(nfx->name));
|
2020-05-08 10:32:30 +02:00
|
|
|
BKE_shaderfx_copydata_ex(fx, nfx, flag_subdata);
|
2020-03-05 10:54:00 +01:00
|
|
|
BLI_addtail(&ob_dst->shader_fx, nfx);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ob_src->pose) {
|
|
|
|
|
copy_object_pose(ob_dst, ob_src, flag_subdata);
|
|
|
|
|
/* backwards compat... non-armatures can get poses in older files? */
|
|
|
|
|
if (ob_src->type == OB_ARMATURE) {
|
|
|
|
|
const bool do_pose_id_user = (flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0;
|
2021-11-04 16:51:37 -03:00
|
|
|
BKE_pose_rebuild(bmain, ob_dst, (bArmature *)ob_dst->data, do_pose_id_user);
|
2020-03-05 10:54:00 +01:00
|
|
|
}
|
|
|
|
|
}
|
2021-07-13 12:10:34 -04:00
|
|
|
|
2020-03-05 10:54:00 +01:00
|
|
|
BKE_object_facemap_copy_list(&ob_dst->fmaps, &ob_src->fmaps);
|
|
|
|
|
BKE_constraints_copy_ex(&ob_dst->constraints, &ob_src->constraints, flag_subdata, true);
|
|
|
|
|
|
|
|
|
|
ob_dst->mode = ob_dst->type != OB_GPENCIL ? OB_MODE_OBJECT : ob_dst->mode;
|
2021-11-04 16:51:37 -03:00
|
|
|
ob_dst->sculpt = nullptr;
|
2020-03-05 10:54:00 +01:00
|
|
|
|
|
|
|
|
if (ob_src->pd) {
|
2021-11-04 16:51:37 -03:00
|
|
|
ob_dst->pd = (PartDeflect *)MEM_dupallocN(ob_src->pd);
|
2020-03-05 10:54:00 +01:00
|
|
|
if (ob_dst->pd->rng) {
|
2021-11-04 16:51:37 -03:00
|
|
|
ob_dst->pd->rng = (RNG *)MEM_dupallocN(ob_src->pd->rng);
|
2020-03-05 10:54:00 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
BKE_rigidbody_object_copy(bmain, ob_dst, ob_src, flag_subdata);
|
|
|
|
|
|
2021-01-19 16:02:25 +01:00
|
|
|
BLI_listbase_clear(&ob_dst->modifiers);
|
|
|
|
|
BLI_listbase_clear(&ob_dst->greasepencil_modifiers);
|
2021-07-03 23:08:40 +10:00
|
|
|
/* NOTE: Also takes care of softbody and particle systems copying. */
|
2021-01-19 16:02:25 +01:00
|
|
|
BKE_object_modifier_stack_copy(ob_dst, ob_src, true, flag_subdata);
|
2020-03-05 10:54:00 +01:00
|
|
|
|
|
|
|
|
BLI_listbase_clear((ListBase *)&ob_dst->drawdata);
|
|
|
|
|
BLI_listbase_clear(&ob_dst->pc_ids);
|
|
|
|
|
|
|
|
|
|
ob_dst->avs = ob_src->avs;
|
|
|
|
|
ob_dst->mpath = animviz_copy_motionpath(ob_src->mpath);
|
|
|
|
|
|
|
|
|
|
/* Do not copy object's preview
|
|
|
|
|
* (mostly due to the fact renderers create temp copy of objects). */
|
2021-07-03 23:08:40 +10:00
|
|
|
if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0 && false) { /* XXX TODO: temp hack. */
|
2020-03-05 10:54:00 +01:00
|
|
|
BKE_previewimg_id_copy(&ob_dst->id, &ob_src->id);
|
|
|
|
|
}
|
|
|
|
|
else {
|
2021-11-04 16:51:37 -03:00
|
|
|
ob_dst->preview = nullptr;
|
2020-03-05 10:54:00 +01:00
|
|
|
}
|
2022-04-02 00:11:11 +02:00
|
|
|
|
|
|
|
|
if (ob_src->lightgroup) {
|
|
|
|
|
ob_dst->lightgroup = (LightgroupMembership *)MEM_dupallocN(ob_src->lightgroup);
|
|
|
|
|
}
|
2020-03-05 10:54:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void object_free_data(ID *id)
|
|
|
|
|
{
|
|
|
|
|
Object *ob = (Object *)id;
|
|
|
|
|
|
|
|
|
|
DRW_drawdata_free((ID *)ob);
|
|
|
|
|
|
|
|
|
|
/* BKE_<id>_free shall never touch to ID->us. Never ever. */
|
|
|
|
|
BKE_object_free_modifiers(ob, LIB_ID_CREATE_NO_USER_REFCOUNT);
|
|
|
|
|
BKE_object_free_shaderfx(ob, LIB_ID_CREATE_NO_USER_REFCOUNT);
|
|
|
|
|
|
|
|
|
|
MEM_SAFE_FREE(ob->mat);
|
|
|
|
|
MEM_SAFE_FREE(ob->matbits);
|
|
|
|
|
MEM_SAFE_FREE(ob->iuser);
|
|
|
|
|
MEM_SAFE_FREE(ob->runtime.bb);
|
|
|
|
|
|
|
|
|
|
BLI_freelistN(&ob->fmaps);
|
|
|
|
|
if (ob->pose) {
|
|
|
|
|
BKE_pose_free_ex(ob->pose, false);
|
2021-11-04 16:51:37 -03:00
|
|
|
ob->pose = nullptr;
|
2020-03-05 10:54:00 +01:00
|
|
|
}
|
|
|
|
|
if (ob->mpath) {
|
|
|
|
|
animviz_free_motionpath(ob->mpath);
|
2021-11-04 16:51:37 -03:00
|
|
|
ob->mpath = nullptr;
|
2020-03-05 10:54:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BKE_constraints_free_ex(&ob->constraints, false);
|
|
|
|
|
|
|
|
|
|
BKE_partdeflect_free(ob->pd);
|
2021-11-04 16:51:37 -03:00
|
|
|
BKE_rigidbody_free_object(ob, nullptr);
|
2020-03-05 10:54:00 +01:00
|
|
|
BKE_rigidbody_free_constraint(ob);
|
|
|
|
|
|
|
|
|
|
sbFree(ob);
|
|
|
|
|
|
|
|
|
|
BKE_sculptsession_free(ob);
|
|
|
|
|
|
|
|
|
|
BLI_freelistN(&ob->pc_ids);
|
|
|
|
|
|
|
|
|
|
/* Free runtime curves data. */
|
|
|
|
|
if (ob->runtime.curve_cache) {
|
|
|
|
|
BKE_curve_bevelList_free(&ob->runtime.curve_cache->bev);
|
2021-04-08 15:51:08 +02:00
|
|
|
if (ob->runtime.curve_cache->anim_path_accum_length) {
|
2021-04-09 14:55:31 +10:00
|
|
|
MEM_freeN((void *)ob->runtime.curve_cache->anim_path_accum_length);
|
2020-03-05 10:54:00 +01:00
|
|
|
}
|
|
|
|
|
MEM_freeN(ob->runtime.curve_cache);
|
2021-11-04 16:51:37 -03:00
|
|
|
ob->runtime.curve_cache = nullptr;
|
2020-03-05 10:54:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BKE_previewimg_free(&ob->preview);
|
2022-04-02 00:11:11 +02:00
|
|
|
|
|
|
|
|
MEM_SAFE_FREE(ob->lightgroup);
|
2020-03-05 10:54:00 +01:00
|
|
|
}
|
|
|
|
|
|
2020-05-21 19:09:48 +02:00
|
|
|
static void library_foreach_modifiersForeachIDLink(void *user_data,
|
|
|
|
|
Object *UNUSED(object),
|
|
|
|
|
ID **id_pointer,
|
|
|
|
|
int cb_flag)
|
|
|
|
|
{
|
|
|
|
|
LibraryForeachIDData *data = (LibraryForeachIDData *)user_data;
|
2021-10-27 11:30:43 +02:00
|
|
|
BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
|
|
|
|
|
data, BKE_lib_query_foreachid_process(data, id_pointer, cb_flag));
|
2020-05-21 19:09:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void library_foreach_gpencil_modifiersForeachIDLink(void *user_data,
|
|
|
|
|
Object *UNUSED(object),
|
|
|
|
|
ID **id_pointer,
|
|
|
|
|
int cb_flag)
|
|
|
|
|
{
|
|
|
|
|
LibraryForeachIDData *data = (LibraryForeachIDData *)user_data;
|
2021-10-27 11:30:43 +02:00
|
|
|
BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
|
|
|
|
|
data, BKE_lib_query_foreachid_process(data, id_pointer, cb_flag));
|
2020-05-21 19:09:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void library_foreach_shaderfxForeachIDLink(void *user_data,
|
|
|
|
|
Object *UNUSED(object),
|
|
|
|
|
ID **id_pointer,
|
|
|
|
|
int cb_flag)
|
|
|
|
|
{
|
|
|
|
|
LibraryForeachIDData *data = (LibraryForeachIDData *)user_data;
|
2021-10-27 11:30:43 +02:00
|
|
|
BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
|
|
|
|
|
data, BKE_lib_query_foreachid_process(data, id_pointer, cb_flag));
|
2020-05-21 19:09:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void library_foreach_constraintObjectLooper(bConstraint *UNUSED(con),
|
|
|
|
|
ID **id_pointer,
|
|
|
|
|
bool is_reference,
|
|
|
|
|
void *user_data)
|
|
|
|
|
{
|
|
|
|
|
LibraryForeachIDData *data = (LibraryForeachIDData *)user_data;
|
|
|
|
|
const int cb_flag = is_reference ? IDWALK_CB_USER : IDWALK_CB_NOP;
|
2021-10-27 11:30:43 +02:00
|
|
|
BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
|
|
|
|
|
data, BKE_lib_query_foreachid_process(data, id_pointer, cb_flag));
|
2020-05-21 19:09:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void library_foreach_particlesystemsObjectLooper(ParticleSystem *UNUSED(psys),
|
|
|
|
|
ID **id_pointer,
|
|
|
|
|
void *user_data,
|
|
|
|
|
int cb_flag)
|
|
|
|
|
{
|
|
|
|
|
LibraryForeachIDData *data = (LibraryForeachIDData *)user_data;
|
2021-10-27 11:30:43 +02:00
|
|
|
BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
|
|
|
|
|
data, BKE_lib_query_foreachid_process(data, id_pointer, cb_flag));
|
2020-05-21 19:09:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void object_foreach_id(ID *id, LibraryForeachIDData *data)
|
|
|
|
|
{
|
|
|
|
|
Object *object = (Object *)id;
|
|
|
|
|
|
|
|
|
|
/* object data special case */
|
|
|
|
|
if (object->type == OB_EMPTY) {
|
2021-11-04 16:51:37 -03:00
|
|
|
/* empty can have nullptr or Image */
|
2022-02-03 17:57:40 +01:00
|
|
|
BKE_LIB_FOREACHID_PROCESS_ID(data, object->data, IDWALK_CB_USER);
|
2020-05-21 19:09:48 +02:00
|
|
|
}
|
|
|
|
|
else {
|
2021-11-04 16:51:37 -03:00
|
|
|
/* when set, this can't be nullptr */
|
2020-05-21 19:09:48 +02:00
|
|
|
if (object->data) {
|
2022-02-03 17:57:40 +01:00
|
|
|
BKE_LIB_FOREACHID_PROCESS_ID(data, object->data, IDWALK_CB_USER | IDWALK_CB_NEVER_NULL);
|
2020-05-21 19:09:48 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-26 10:40:36 +02:00
|
|
|
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, object->parent, IDWALK_CB_NEVER_SELF);
|
|
|
|
|
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, object->track, IDWALK_CB_NEVER_SELF);
|
2020-05-21 19:09:48 +02:00
|
|
|
|
2021-10-26 10:40:36 +02:00
|
|
|
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, object->poselib, IDWALK_CB_USER);
|
2020-05-21 19:09:48 +02:00
|
|
|
|
|
|
|
|
for (int i = 0; i < object->totcol; i++) {
|
2022-02-03 17:57:40 +01:00
|
|
|
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, object->mat[i], IDWALK_CB_USER);
|
2020-05-21 19:09:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Note that ob->gpd is deprecated, so no need to handle it here. */
|
2021-10-26 10:40:36 +02:00
|
|
|
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, object->instance_collection, IDWALK_CB_USER);
|
2020-05-21 19:09:48 +02:00
|
|
|
|
|
|
|
|
if (object->pd) {
|
2021-10-26 10:40:36 +02:00
|
|
|
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, object->pd->tex, IDWALK_CB_USER);
|
|
|
|
|
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, object->pd->f_source, IDWALK_CB_NOP);
|
2020-05-21 19:09:48 +02:00
|
|
|
}
|
|
|
|
|
/* Note that ob->effect is deprecated, so no need to handle it here. */
|
|
|
|
|
|
|
|
|
|
if (object->pose) {
|
|
|
|
|
LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
|
2021-10-27 11:30:43 +02:00
|
|
|
BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
|
|
|
|
|
data,
|
|
|
|
|
IDP_foreach_property(pchan->prop,
|
|
|
|
|
IDP_TYPE_FILTER_ID,
|
|
|
|
|
BKE_lib_query_idpropertiesForeachIDLink_callback,
|
|
|
|
|
data));
|
|
|
|
|
|
2021-10-26 10:40:36 +02:00
|
|
|
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, pchan->custom, IDWALK_CB_USER);
|
2021-10-27 11:30:43 +02:00
|
|
|
BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
|
|
|
|
|
data,
|
|
|
|
|
BKE_constraints_id_loop(
|
|
|
|
|
&pchan->constraints, library_foreach_constraintObjectLooper, data));
|
2020-05-21 19:09:48 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (object->rigidbody_constraint) {
|
2021-10-26 10:40:36 +02:00
|
|
|
BKE_LIB_FOREACHID_PROCESS_IDSUPER(
|
|
|
|
|
data, object->rigidbody_constraint->ob1, IDWALK_CB_NEVER_SELF);
|
|
|
|
|
BKE_LIB_FOREACHID_PROCESS_IDSUPER(
|
|
|
|
|
data, object->rigidbody_constraint->ob2, IDWALK_CB_NEVER_SELF);
|
2020-05-21 19:09:48 +02:00
|
|
|
}
|
|
|
|
|
|
2021-10-27 11:30:43 +02:00
|
|
|
BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
|
|
|
|
|
data, BKE_modifiers_foreach_ID_link(object, library_foreach_modifiersForeachIDLink, data));
|
|
|
|
|
BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
|
|
|
|
|
data,
|
|
|
|
|
BKE_gpencil_modifiers_foreach_ID_link(
|
|
|
|
|
object, library_foreach_gpencil_modifiersForeachIDLink, data));
|
|
|
|
|
BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
|
|
|
|
|
data,
|
|
|
|
|
BKE_constraints_id_loop(&object->constraints, library_foreach_constraintObjectLooper, data));
|
|
|
|
|
BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
|
|
|
|
|
data, BKE_shaderfx_foreach_ID_link(object, library_foreach_shaderfxForeachIDLink, data));
|
2020-05-21 19:09:48 +02:00
|
|
|
|
|
|
|
|
LISTBASE_FOREACH (ParticleSystem *, psys, &object->particlesystem) {
|
2021-10-27 11:30:43 +02:00
|
|
|
BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
|
|
|
|
|
data, BKE_particlesystem_id_loop(psys, library_foreach_particlesystemsObjectLooper, data));
|
2020-05-21 19:09:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (object->soft) {
|
2021-10-26 10:40:36 +02:00
|
|
|
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, object->soft->collision_group, IDWALK_CB_NOP);
|
2020-05-21 19:09:48 +02:00
|
|
|
|
|
|
|
|
if (object->soft->effector_weights) {
|
2021-10-26 10:40:36 +02:00
|
|
|
BKE_LIB_FOREACHID_PROCESS_IDSUPER(
|
2022-08-25 17:21:39 +02:00
|
|
|
data, object->soft->effector_weights->group, IDWALK_CB_USER);
|
2020-05-21 19:09:48 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-30 09:18:41 +11:00
|
|
|
static void object_foreach_path_pointcache(ListBase *ptcache_list,
|
|
|
|
|
BPathForeachPathData *bpath_data)
|
Refactor BKE_bpath module.
The main goal of this refactor is to make BPath module use `IDTypeInfo`,
and move each ID-specific part of the `foreach_path` looper into their
own IDTypeInfo struct, using a new `foreach_path` callback.
Additionally, following improvements/cleanups are included:
* Attempt to get better, more consistent namings.
** In particular, move from `path_visitor` to more standard `foreach_path`.
* Update and extend documentation.
** API doc was moved to header, according to recent discussions on this
topic.
* Remove `BKE_bpath_relocate_visitor` from API, this is specific
callback that belongs in `lib_id.c` user code.
NOTE: This commit is expected to be 100% non-behavioral-change. This
implies that several potential further changes were only noted as
comments (like using a more generic solution for
`lib_id_library_local_paths`, addressing inconsistencies like path of
packed libraries always being skipped, regardless of the
`BKE_BPATH_FOREACH_PATH_SKIP_PACKED` `eBPathForeachFlag` flag value,
etc.).
NOTE: basic unittests were added to master already in
rBdcc500e5a265093bc9cc.
Reviewed By: brecht
Differential Revision: https://developer.blender.org/D13381
2021-11-29 14:20:58 +01:00
|
|
|
{
|
|
|
|
|
for (PointCache *cache = (PointCache *)ptcache_list->first; cache != nullptr;
|
|
|
|
|
cache = cache->next) {
|
|
|
|
|
if (cache->flag & PTCACHE_DISK_CACHE) {
|
|
|
|
|
BKE_bpath_foreach_path_fixed_process(bpath_data, cache->path);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void object_foreach_path(ID *id, BPathForeachPathData *bpath_data)
|
|
|
|
|
{
|
|
|
|
|
Object *ob = reinterpret_cast<Object *>(id);
|
|
|
|
|
|
|
|
|
|
LISTBASE_FOREACH (ModifierData *, md, &ob->modifiers) {
|
|
|
|
|
/* TODO: Move that to #ModifierTypeInfo. */
|
|
|
|
|
switch (md->type) {
|
|
|
|
|
case eModifierType_Fluidsim: {
|
|
|
|
|
FluidsimModifierData *fluidmd = reinterpret_cast<FluidsimModifierData *>(md);
|
|
|
|
|
if (fluidmd->fss) {
|
|
|
|
|
BKE_bpath_foreach_path_fixed_process(bpath_data, fluidmd->fss->surfdataPath);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case eModifierType_Fluid: {
|
|
|
|
|
FluidModifierData *fmd = reinterpret_cast<FluidModifierData *>(md);
|
|
|
|
|
if (fmd->type & MOD_FLUID_TYPE_DOMAIN && fmd->domain) {
|
|
|
|
|
BKE_bpath_foreach_path_fixed_process(bpath_data, fmd->domain->cache_directory);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case eModifierType_Cloth: {
|
|
|
|
|
ClothModifierData *clmd = reinterpret_cast<ClothModifierData *>(md);
|
|
|
|
|
object_foreach_path_pointcache(&clmd->ptcaches, bpath_data);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case eModifierType_Ocean: {
|
|
|
|
|
OceanModifierData *omd = reinterpret_cast<OceanModifierData *>(md);
|
|
|
|
|
BKE_bpath_foreach_path_fixed_process(bpath_data, omd->cachepath);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case eModifierType_MeshCache: {
|
|
|
|
|
MeshCacheModifierData *mcmd = reinterpret_cast<MeshCacheModifierData *>(md);
|
|
|
|
|
BKE_bpath_foreach_path_fixed_process(bpath_data, mcmd->filepath);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ob->soft != nullptr) {
|
|
|
|
|
object_foreach_path_pointcache(&ob->soft->shared->ptcaches, bpath_data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LISTBASE_FOREACH (ParticleSystem *, psys, &ob->particlesystem) {
|
|
|
|
|
object_foreach_path_pointcache(&psys->ptcaches, bpath_data);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-06 18:25:44 +01:00
|
|
|
static void write_fmaps(BlendWriter *writer, ListBase *fbase)
|
|
|
|
|
{
|
|
|
|
|
LISTBASE_FOREACH (bFaceMap *, fmap, fbase) {
|
|
|
|
|
BLO_write_struct(writer, bFaceMap, fmap);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void object_blend_write(BlendWriter *writer, ID *id, const void *id_address)
|
|
|
|
|
{
|
|
|
|
|
Object *ob = (Object *)id;
|
|
|
|
|
|
|
|
|
|
const bool is_undo = BLO_write_is_undo(writer);
|
|
|
|
|
|
2021-08-19 11:13:55 +02:00
|
|
|
/* Clean up, important in undo case to reduce false detection of changed data-blocks. */
|
|
|
|
|
BKE_object_runtime_reset(ob);
|
2020-11-06 18:25:44 +01:00
|
|
|
|
2021-08-19 11:13:55 +02:00
|
|
|
if (is_undo) {
|
|
|
|
|
/* For undo we stay in object mode during undo presses, so keep edit-mode disabled on save as
|
|
|
|
|
* well, can help reducing false detection of changed data-blocks. */
|
|
|
|
|
ob->mode &= ~OB_MODE_EDIT;
|
|
|
|
|
}
|
2020-11-06 18:25:44 +01:00
|
|
|
|
2021-08-19 11:13:55 +02:00
|
|
|
/* write LibData */
|
|
|
|
|
BLO_write_id_struct(writer, Object, id_address, &ob->id);
|
|
|
|
|
BKE_id_blend_write(writer, &ob->id);
|
2020-11-06 18:25:44 +01:00
|
|
|
|
2021-08-19 11:13:55 +02:00
|
|
|
if (ob->adt) {
|
|
|
|
|
BKE_animdata_blend_write(writer, ob->adt);
|
|
|
|
|
}
|
2020-11-06 18:25:44 +01:00
|
|
|
|
2021-08-19 11:13:55 +02:00
|
|
|
/* direct data */
|
|
|
|
|
BLO_write_pointer_array(writer, ob->totcol, ob->mat);
|
|
|
|
|
BLO_write_raw(writer, sizeof(char) * ob->totcol, ob->matbits);
|
2020-11-06 18:25:44 +01:00
|
|
|
|
2021-11-04 16:51:37 -03:00
|
|
|
bArmature *arm = nullptr;
|
2021-08-19 11:13:55 +02:00
|
|
|
if (ob->type == OB_ARMATURE) {
|
2021-11-04 16:51:37 -03:00
|
|
|
arm = (bArmature *)ob->data;
|
2021-08-19 11:13:55 +02:00
|
|
|
}
|
2020-11-06 18:25:44 +01:00
|
|
|
|
2021-08-19 11:13:55 +02:00
|
|
|
BKE_pose_blend_write(writer, ob->pose, arm);
|
|
|
|
|
write_fmaps(writer, &ob->fmaps);
|
|
|
|
|
BKE_constraint_blend_write(writer, &ob->constraints);
|
|
|
|
|
animviz_motionpath_blend_write(writer, ob->mpath);
|
|
|
|
|
|
|
|
|
|
BLO_write_struct(writer, PartDeflect, ob->pd);
|
|
|
|
|
if (ob->soft) {
|
|
|
|
|
/* Set deprecated pointers to prevent crashes of older Blenders */
|
|
|
|
|
ob->soft->pointcache = ob->soft->shared->pointcache;
|
|
|
|
|
ob->soft->ptcaches = ob->soft->shared->ptcaches;
|
|
|
|
|
BLO_write_struct(writer, SoftBody, ob->soft);
|
|
|
|
|
BLO_write_struct(writer, SoftBody_Shared, ob->soft->shared);
|
|
|
|
|
BKE_ptcache_blend_write(writer, &(ob->soft->shared->ptcaches));
|
|
|
|
|
BLO_write_struct(writer, EffectorWeights, ob->soft->effector_weights);
|
|
|
|
|
}
|
2020-11-06 18:25:44 +01:00
|
|
|
|
2021-08-19 11:13:55 +02:00
|
|
|
if (ob->rigidbody_object) {
|
|
|
|
|
/* TODO: if any extra data is added to handle duplis, will need separate function then */
|
|
|
|
|
BLO_write_struct(writer, RigidBodyOb, ob->rigidbody_object);
|
|
|
|
|
}
|
|
|
|
|
if (ob->rigidbody_constraint) {
|
|
|
|
|
BLO_write_struct(writer, RigidBodyCon, ob->rigidbody_constraint);
|
|
|
|
|
}
|
2020-11-06 18:25:44 +01:00
|
|
|
|
2021-08-19 11:13:55 +02:00
|
|
|
if (ob->type == OB_EMPTY && ob->empty_drawtype == OB_EMPTY_IMAGE) {
|
|
|
|
|
BLO_write_struct(writer, ImageUser, ob->iuser);
|
2020-11-06 18:25:44 +01:00
|
|
|
}
|
2021-08-19 11:13:55 +02:00
|
|
|
|
|
|
|
|
BKE_particle_system_blend_write(writer, &ob->particlesystem);
|
2022-05-16 16:00:00 +02:00
|
|
|
BKE_modifier_blend_write(writer, &ob->id, &ob->modifiers);
|
2021-08-19 11:13:55 +02:00
|
|
|
BKE_gpencil_modifier_blend_write(writer, &ob->greasepencil_modifiers);
|
|
|
|
|
BKE_shaderfx_blend_write(writer, &ob->shader_fx);
|
|
|
|
|
|
|
|
|
|
BLO_write_struct_list(writer, LinkData, &ob->pc_ids);
|
|
|
|
|
|
|
|
|
|
BKE_previewimg_blend_write(writer, ob->preview);
|
2022-04-02 00:11:11 +02:00
|
|
|
|
|
|
|
|
if (ob->lightgroup) {
|
|
|
|
|
BLO_write_struct(writer, LightgroupMembership, ob->lightgroup);
|
|
|
|
|
}
|
2020-11-06 18:25:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* XXX deprecated - old animation system */
|
|
|
|
|
static void direct_link_nlastrips(BlendDataReader *reader, ListBase *strips)
|
|
|
|
|
{
|
|
|
|
|
BLO_read_list(reader, strips);
|
|
|
|
|
|
|
|
|
|
LISTBASE_FOREACH (bActionStrip *, strip, strips) {
|
|
|
|
|
BLO_read_list(reader, &strip->modifiers);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void object_blend_read_data(BlendDataReader *reader, ID *id)
|
|
|
|
|
{
|
|
|
|
|
Object *ob = (Object *)id;
|
|
|
|
|
|
|
|
|
|
PartEff *paf;
|
|
|
|
|
|
|
|
|
|
/* XXX This should not be needed - but seems like it can happen in some cases,
|
|
|
|
|
* so for now play safe. */
|
2021-11-04 16:51:37 -03:00
|
|
|
ob->proxy_from = nullptr;
|
2020-11-06 18:25:44 +01:00
|
|
|
|
|
|
|
|
const bool is_undo = BLO_read_data_is_undo(reader);
|
|
|
|
|
if (ob->id.tag & (LIB_TAG_EXTERN | LIB_TAG_INDIRECT)) {
|
|
|
|
|
/* Do not allow any non-object mode for linked data.
|
|
|
|
|
* See T34776, T42780, T81027 for more information. */
|
|
|
|
|
ob->mode &= ~OB_MODE_ALL_MODE_DATA;
|
|
|
|
|
}
|
|
|
|
|
else if (is_undo) {
|
|
|
|
|
/* For undo we want to stay in object mode during undo presses, so keep some edit modes
|
|
|
|
|
* disabled.
|
|
|
|
|
* TODO: Check if we should not disable more edit modes here? */
|
|
|
|
|
ob->mode &= ~(OB_MODE_EDIT | OB_MODE_PARTICLE_EDIT);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BLO_read_data_address(reader, &ob->adt);
|
|
|
|
|
BKE_animdata_blend_read_data(reader, ob->adt);
|
|
|
|
|
|
|
|
|
|
BLO_read_data_address(reader, &ob->pose);
|
|
|
|
|
BKE_pose_blend_read_data(reader, ob->pose);
|
|
|
|
|
|
|
|
|
|
BLO_read_data_address(reader, &ob->mpath);
|
|
|
|
|
if (ob->mpath) {
|
|
|
|
|
animviz_motionpath_blend_read_data(reader, ob->mpath);
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-13 12:10:34 -04:00
|
|
|
/* Only for versioning, vertex group names are now stored on object data. */
|
2020-11-06 18:25:44 +01:00
|
|
|
BLO_read_list(reader, &ob->defbase);
|
2021-07-13 12:10:34 -04:00
|
|
|
|
2020-11-06 18:25:44 +01:00
|
|
|
BLO_read_list(reader, &ob->fmaps);
|
|
|
|
|
/* XXX deprecated - old animation system <<< */
|
|
|
|
|
direct_link_nlastrips(reader, &ob->nlastrips);
|
|
|
|
|
BLO_read_list(reader, &ob->constraintChannels);
|
|
|
|
|
/* >>> XXX deprecated - old animation system */
|
|
|
|
|
|
|
|
|
|
BLO_read_pointer_array(reader, (void **)&ob->mat);
|
|
|
|
|
BLO_read_data_address(reader, &ob->matbits);
|
|
|
|
|
|
|
|
|
|
/* do it here, below old data gets converted */
|
|
|
|
|
BKE_modifier_blend_read_data(reader, &ob->modifiers, ob);
|
|
|
|
|
BKE_gpencil_modifier_blend_read_data(reader, &ob->greasepencil_modifiers);
|
|
|
|
|
BKE_shaderfx_blend_read_data(reader, &ob->shader_fx);
|
|
|
|
|
|
|
|
|
|
BLO_read_list(reader, &ob->effect);
|
2021-11-04 16:51:37 -03:00
|
|
|
paf = (PartEff *)ob->effect.first;
|
2020-11-06 18:25:44 +01:00
|
|
|
while (paf) {
|
|
|
|
|
if (paf->type == EFF_PARTICLE) {
|
2021-11-04 16:51:37 -03:00
|
|
|
paf->keys = nullptr;
|
2020-11-06 18:25:44 +01:00
|
|
|
}
|
|
|
|
|
if (paf->type == EFF_WAVE) {
|
|
|
|
|
WaveEff *wav = (WaveEff *)paf;
|
|
|
|
|
PartEff *next = paf->next;
|
|
|
|
|
WaveModifierData *wmd = (WaveModifierData *)BKE_modifier_new(eModifierType_Wave);
|
|
|
|
|
|
|
|
|
|
wmd->damp = wav->damp;
|
|
|
|
|
wmd->flag = wav->flag;
|
|
|
|
|
wmd->height = wav->height;
|
|
|
|
|
wmd->lifetime = wav->lifetime;
|
|
|
|
|
wmd->narrow = wav->narrow;
|
|
|
|
|
wmd->speed = wav->speed;
|
|
|
|
|
wmd->startx = wav->startx;
|
|
|
|
|
wmd->starty = wav->startx;
|
|
|
|
|
wmd->timeoffs = wav->timeoffs;
|
|
|
|
|
wmd->width = wav->width;
|
|
|
|
|
|
|
|
|
|
BLI_addtail(&ob->modifiers, wmd);
|
|
|
|
|
|
|
|
|
|
BLI_remlink(&ob->effect, paf);
|
|
|
|
|
MEM_freeN(paf);
|
|
|
|
|
|
|
|
|
|
paf = next;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (paf->type == EFF_BUILD) {
|
|
|
|
|
BuildEff *baf = (BuildEff *)paf;
|
|
|
|
|
PartEff *next = paf->next;
|
|
|
|
|
BuildModifierData *bmd = (BuildModifierData *)BKE_modifier_new(eModifierType_Build);
|
|
|
|
|
|
|
|
|
|
bmd->start = baf->sfra;
|
|
|
|
|
bmd->length = baf->len;
|
|
|
|
|
bmd->randomize = 0;
|
|
|
|
|
bmd->seed = 1;
|
|
|
|
|
|
|
|
|
|
BLI_addtail(&ob->modifiers, bmd);
|
|
|
|
|
|
|
|
|
|
BLI_remlink(&ob->effect, paf);
|
|
|
|
|
MEM_freeN(paf);
|
|
|
|
|
|
|
|
|
|
paf = next;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
paf = paf->next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BLO_read_data_address(reader, &ob->pd);
|
|
|
|
|
BKE_particle_partdeflect_blend_read_data(reader, ob->pd);
|
|
|
|
|
BLO_read_data_address(reader, &ob->soft);
|
|
|
|
|
if (ob->soft) {
|
|
|
|
|
SoftBody *sb = ob->soft;
|
|
|
|
|
|
2021-11-04 16:51:37 -03:00
|
|
|
sb->bpoint = nullptr; /* init pointers so it gets rebuilt nicely */
|
|
|
|
|
sb->bspring = nullptr;
|
|
|
|
|
sb->scratch = nullptr;
|
2020-11-06 18:25:44 +01:00
|
|
|
/* although not used anymore */
|
|
|
|
|
/* still have to be loaded to be compatible with old files */
|
|
|
|
|
BLO_read_pointer_array(reader, (void **)&sb->keys);
|
|
|
|
|
if (sb->keys) {
|
|
|
|
|
for (int a = 0; a < sb->totkey; a++) {
|
|
|
|
|
BLO_read_data_address(reader, &sb->keys[a]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BLO_read_data_address(reader, &sb->effector_weights);
|
|
|
|
|
if (!sb->effector_weights) {
|
2021-11-04 16:51:37 -03:00
|
|
|
sb->effector_weights = BKE_effector_add_weights(nullptr);
|
2020-11-06 18:25:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BLO_read_data_address(reader, &sb->shared);
|
2021-11-04 16:51:37 -03:00
|
|
|
if (sb->shared == nullptr) {
|
2020-11-06 18:25:44 +01:00
|
|
|
/* Link deprecated caches if they exist, so we can use them for versioning.
|
2021-11-04 16:51:37 -03:00
|
|
|
* We should only do this when sb->shared == nullptr, because those pointers
|
2020-11-06 18:25:44 +01:00
|
|
|
* are always set (for compatibility with older Blenders). We mustn't link
|
|
|
|
|
* the same pointcache twice. */
|
|
|
|
|
BKE_ptcache_blend_read_data(reader, &sb->ptcaches, &sb->pointcache, false);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* link caches */
|
|
|
|
|
BKE_ptcache_blend_read_data(reader, &sb->shared->ptcaches, &sb->shared->pointcache, false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
BLO_read_data_address(reader, &ob->fluidsimSettings); /* NT */
|
|
|
|
|
|
|
|
|
|
BLO_read_data_address(reader, &ob->rigidbody_object);
|
|
|
|
|
if (ob->rigidbody_object) {
|
|
|
|
|
RigidBodyOb *rbo = ob->rigidbody_object;
|
|
|
|
|
/* Allocate runtime-only struct */
|
2021-11-04 16:51:37 -03:00
|
|
|
rbo->shared = (RigidBodyOb_Shared *)MEM_callocN(sizeof(*rbo->shared), "RigidBodyObShared");
|
2020-11-06 18:25:44 +01:00
|
|
|
}
|
|
|
|
|
BLO_read_data_address(reader, &ob->rigidbody_constraint);
|
|
|
|
|
if (ob->rigidbody_constraint) {
|
2021-11-04 16:51:37 -03:00
|
|
|
ob->rigidbody_constraint->physics_constraint = nullptr;
|
2020-11-06 18:25:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BLO_read_list(reader, &ob->particlesystem);
|
|
|
|
|
BKE_particle_system_blend_read_data(reader, &ob->particlesystem);
|
|
|
|
|
|
|
|
|
|
BKE_constraint_blend_read_data(reader, &ob->constraints);
|
|
|
|
|
|
|
|
|
|
BLO_read_list(reader, &ob->hooks);
|
|
|
|
|
while (ob->hooks.first) {
|
2021-11-04 16:51:37 -03:00
|
|
|
ObHook *hook = (ObHook *)ob->hooks.first;
|
2020-11-06 18:25:44 +01:00
|
|
|
HookModifierData *hmd = (HookModifierData *)BKE_modifier_new(eModifierType_Hook);
|
|
|
|
|
|
|
|
|
|
BLO_read_int32_array(reader, hook->totindex, &hook->indexar);
|
|
|
|
|
|
|
|
|
|
/* Do conversion here because if we have loaded
|
|
|
|
|
* a hook we need to make sure it gets converted
|
|
|
|
|
* and freed, regardless of version.
|
|
|
|
|
*/
|
|
|
|
|
copy_v3_v3(hmd->cent, hook->cent);
|
|
|
|
|
hmd->falloff = hook->falloff;
|
|
|
|
|
hmd->force = hook->force;
|
|
|
|
|
hmd->indexar = hook->indexar;
|
|
|
|
|
hmd->object = hook->parent;
|
|
|
|
|
memcpy(hmd->parentinv, hook->parentinv, sizeof(hmd->parentinv));
|
2022-03-28 12:29:47 +11:00
|
|
|
hmd->indexar_num = hook->totindex;
|
2020-11-06 18:25:44 +01:00
|
|
|
|
|
|
|
|
BLI_addhead(&ob->modifiers, hmd);
|
|
|
|
|
BLI_remlink(&ob->hooks, hook);
|
|
|
|
|
|
|
|
|
|
BKE_modifier_unique_name(&ob->modifiers, (ModifierData *)hmd);
|
|
|
|
|
|
|
|
|
|
MEM_freeN(hook);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BLO_read_data_address(reader, &ob->iuser);
|
|
|
|
|
if (ob->type == OB_EMPTY && ob->empty_drawtype == OB_EMPTY_IMAGE && !ob->iuser) {
|
|
|
|
|
BKE_object_empty_draw_type_set(ob, ob->empty_drawtype);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BKE_object_runtime_reset(ob);
|
|
|
|
|
BLO_read_list(reader, &ob->pc_ids);
|
|
|
|
|
|
|
|
|
|
/* in case this value changes in future, clamp else we get undefined behavior */
|
|
|
|
|
CLAMP(ob->rotmode, ROT_MODE_MIN, ROT_MODE_MAX);
|
|
|
|
|
|
|
|
|
|
if (ob->sculpt) {
|
2021-11-04 16:51:37 -03:00
|
|
|
ob->sculpt = nullptr;
|
2020-11-06 18:25:44 +01:00
|
|
|
/* Only create data on undo, otherwise rely on editor mode switching. */
|
|
|
|
|
if (BLO_read_data_is_undo(reader) && (ob->mode & OB_MODE_ALL_SCULPT)) {
|
|
|
|
|
BKE_object_sculpt_data_create(ob);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BLO_read_data_address(reader, &ob->preview);
|
|
|
|
|
BKE_previewimg_blend_read(reader, ob->preview);
|
2022-04-02 00:11:11 +02:00
|
|
|
|
|
|
|
|
BLO_read_data_address(reader, &ob->lightgroup);
|
2020-11-06 18:25:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* XXX deprecated - old animation system */
|
|
|
|
|
static void lib_link_nlastrips(BlendLibReader *reader, ID *id, ListBase *striplist)
|
|
|
|
|
{
|
|
|
|
|
LISTBASE_FOREACH (bActionStrip *, strip, striplist) {
|
|
|
|
|
BLO_read_id_address(reader, id->lib, &strip->object);
|
|
|
|
|
BLO_read_id_address(reader, id->lib, &strip->act);
|
|
|
|
|
BLO_read_id_address(reader, id->lib, &strip->ipo);
|
|
|
|
|
LISTBASE_FOREACH (bActionModifier *, amod, &strip->modifiers) {
|
|
|
|
|
BLO_read_id_address(reader, id->lib, &amod->ob);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* XXX deprecated - old animation system */
|
|
|
|
|
static void lib_link_constraint_channels(BlendLibReader *reader, ID *id, ListBase *chanbase)
|
|
|
|
|
{
|
|
|
|
|
LISTBASE_FOREACH (bConstraintChannel *, chan, chanbase) {
|
|
|
|
|
BLO_read_id_address(reader, id->lib, &chan->ipo);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void object_blend_read_lib(BlendLibReader *reader, ID *id)
|
|
|
|
|
{
|
|
|
|
|
Object *ob = (Object *)id;
|
|
|
|
|
|
2021-11-03 17:56:25 +01:00
|
|
|
Main *bmain = BLO_read_lib_get_main(reader);
|
2021-08-03 12:54:05 +02:00
|
|
|
BlendFileReadReport *reports = BLO_read_lib_reports(reader);
|
2020-11-06 18:25:44 +01:00
|
|
|
|
|
|
|
|
/* XXX deprecated - old animation system <<< */
|
|
|
|
|
BLO_read_id_address(reader, ob->id.lib, &ob->ipo);
|
|
|
|
|
BLO_read_id_address(reader, ob->id.lib, &ob->action);
|
|
|
|
|
/* >>> XXX deprecated - old animation system */
|
|
|
|
|
|
|
|
|
|
BLO_read_id_address(reader, ob->id.lib, &ob->parent);
|
|
|
|
|
BLO_read_id_address(reader, ob->id.lib, &ob->track);
|
|
|
|
|
BLO_read_id_address(reader, ob->id.lib, &ob->poselib);
|
|
|
|
|
|
|
|
|
|
/* 2.8x drops support for non-empty dupli instances. */
|
|
|
|
|
if (ob->type == OB_EMPTY) {
|
|
|
|
|
BLO_read_id_address(reader, ob->id.lib, &ob->instance_collection);
|
|
|
|
|
}
|
|
|
|
|
else {
|
2021-11-04 16:51:37 -03:00
|
|
|
if (ob->instance_collection != nullptr) {
|
2020-11-06 18:25:44 +01:00
|
|
|
ID *new_id = BLO_read_get_new_id_address(reader, ob->id.lib, &ob->instance_collection->id);
|
2021-08-03 12:54:05 +02:00
|
|
|
BLO_reportf_wrap(reports,
|
|
|
|
|
RPT_INFO,
|
2020-11-06 18:25:44 +01:00
|
|
|
TIP_("Non-Empty object '%s' cannot duplicate collection '%s' "
|
|
|
|
|
"anymore in Blender 2.80, removed instancing"),
|
|
|
|
|
ob->id.name + 2,
|
|
|
|
|
new_id->name + 2);
|
|
|
|
|
}
|
2021-11-04 16:51:37 -03:00
|
|
|
ob->instance_collection = nullptr;
|
2020-11-06 18:25:44 +01:00
|
|
|
ob->transflag &= ~OB_DUPLICOLLECTION;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BLO_read_id_address(reader, ob->id.lib, &ob->proxy);
|
|
|
|
|
if (ob->proxy) {
|
|
|
|
|
/* paranoia check, actually a proxy_from pointer should never be written... */
|
2021-08-26 15:01:14 +02:00
|
|
|
if (!ID_IS_LINKED(ob->proxy)) {
|
2021-11-04 16:51:37 -03:00
|
|
|
ob->proxy->proxy_from = nullptr;
|
|
|
|
|
ob->proxy = nullptr;
|
2020-11-06 18:25:44 +01:00
|
|
|
|
|
|
|
|
if (ob->id.lib) {
|
2021-08-03 12:54:05 +02:00
|
|
|
BLO_reportf_wrap(reports,
|
|
|
|
|
RPT_INFO,
|
|
|
|
|
TIP_("Proxy lost from object %s lib %s\n"),
|
|
|
|
|
ob->id.name + 2,
|
|
|
|
|
ob->id.lib->filepath);
|
2020-11-06 18:25:44 +01:00
|
|
|
}
|
|
|
|
|
else {
|
2021-08-03 12:54:05 +02:00
|
|
|
BLO_reportf_wrap(
|
|
|
|
|
reports, RPT_INFO, TIP_("Proxy lost from object %s lib <NONE>\n"), ob->id.name + 2);
|
2020-11-06 18:25:44 +01:00
|
|
|
}
|
2021-08-03 12:54:05 +02:00
|
|
|
reports->count.missing_obproxies++;
|
2020-11-06 18:25:44 +01:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* this triggers object_update to always use a copy */
|
|
|
|
|
ob->proxy->proxy_from = ob;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
BLO_read_id_address(reader, ob->id.lib, &ob->proxy_group);
|
|
|
|
|
|
|
|
|
|
void *poin = ob->data;
|
|
|
|
|
BLO_read_id_address(reader, ob->id.lib, &ob->data);
|
|
|
|
|
|
2021-11-04 16:51:37 -03:00
|
|
|
if (ob->data == nullptr && poin != nullptr) {
|
2020-11-06 18:25:44 +01:00
|
|
|
ob->type = OB_EMPTY;
|
|
|
|
|
|
|
|
|
|
if (ob->pose) {
|
|
|
|
|
/* we can't call #BKE_pose_free() here because of library linking
|
|
|
|
|
* freeing will recurse down into every pose constraints ID pointers
|
|
|
|
|
* which are not always valid, so for now free directly and suffer
|
|
|
|
|
* some leaked memory rather than crashing immediately
|
|
|
|
|
* while bad this _is_ an exceptional case - campbell */
|
|
|
|
|
#if 0
|
|
|
|
|
BKE_pose_free(ob->pose);
|
|
|
|
|
#else
|
|
|
|
|
MEM_freeN(ob->pose);
|
|
|
|
|
#endif
|
2021-11-04 16:51:37 -03:00
|
|
|
ob->pose = nullptr;
|
2020-11-06 18:25:44 +01:00
|
|
|
ob->mode &= ~OB_MODE_POSE;
|
|
|
|
|
}
|
2021-08-03 12:54:05 +02:00
|
|
|
|
|
|
|
|
if (ob->id.lib) {
|
|
|
|
|
BLO_reportf_wrap(reports,
|
|
|
|
|
RPT_INFO,
|
2021-08-09 14:41:30 +02:00
|
|
|
TIP_("Can't find object data of %s lib %s\n"),
|
2021-08-03 12:54:05 +02:00
|
|
|
ob->id.name + 2,
|
|
|
|
|
ob->id.lib->filepath);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
BLO_reportf_wrap(reports, RPT_INFO, TIP_("Object %s lost data\n"), ob->id.name + 2);
|
|
|
|
|
}
|
|
|
|
|
reports->count.missing_obdata++;
|
2020-11-06 18:25:44 +01:00
|
|
|
}
|
|
|
|
|
for (int a = 0; a < ob->totcol; a++) {
|
|
|
|
|
BLO_read_id_address(reader, ob->id.lib, &ob->mat[a]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* When the object is local and the data is library its possible
|
|
|
|
|
* the material list size gets out of sync. T22663. */
|
|
|
|
|
if (ob->data && ob->id.lib != ((ID *)ob->data)->lib) {
|
2021-11-04 16:51:37 -03:00
|
|
|
BKE_object_materials_test(bmain, ob, (ID *)ob->data);
|
2020-11-06 18:25:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BLO_read_id_address(reader, ob->id.lib, &ob->gpd);
|
|
|
|
|
|
|
|
|
|
/* if id.us==0 a new base will be created later on */
|
|
|
|
|
|
|
|
|
|
/* WARNING! Also check expand_object(), should reflect the stuff below. */
|
|
|
|
|
BKE_pose_blend_read_lib(reader, ob, ob->pose);
|
|
|
|
|
BKE_constraint_blend_read_lib(reader, &ob->id, &ob->constraints);
|
|
|
|
|
|
|
|
|
|
/* XXX deprecated - old animation system <<< */
|
|
|
|
|
lib_link_constraint_channels(reader, &ob->id, &ob->constraintChannels);
|
|
|
|
|
lib_link_nlastrips(reader, &ob->id, &ob->nlastrips);
|
|
|
|
|
/* >>> XXX deprecated - old animation system */
|
|
|
|
|
|
|
|
|
|
LISTBASE_FOREACH (PartEff *, paf, &ob->effect) {
|
|
|
|
|
if (paf->type == EFF_PARTICLE) {
|
|
|
|
|
BLO_read_id_address(reader, ob->id.lib, &paf->group);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
FluidsimModifierData *fluidmd = (FluidsimModifierData *)BKE_modifiers_findby_type(
|
|
|
|
|
ob, eModifierType_Fluidsim);
|
|
|
|
|
|
|
|
|
|
if (fluidmd && fluidmd->fss) {
|
2021-06-23 12:05:40 +10:00
|
|
|
/* XXX: deprecated - old animation system. */
|
|
|
|
|
BLO_read_id_address(reader, ob->id.lib, &fluidmd->fss->ipo);
|
2020-11-06 18:25:44 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
FluidModifierData *fmd = (FluidModifierData *)BKE_modifiers_findby_type(ob,
|
|
|
|
|
eModifierType_Fluid);
|
|
|
|
|
|
|
|
|
|
if (fmd && (fmd->type == MOD_FLUID_TYPE_DOMAIN) && fmd->domain) {
|
|
|
|
|
/* Flag for refreshing the simulation after loading */
|
|
|
|
|
fmd->domain->flags |= FLUID_DOMAIN_FILE_LOAD;
|
|
|
|
|
}
|
|
|
|
|
else if (fmd && (fmd->type == MOD_FLUID_TYPE_FLOW) && fmd->flow) {
|
|
|
|
|
fmd->flow->flags &= ~FLUID_FLOW_NEEDS_UPDATE;
|
|
|
|
|
}
|
|
|
|
|
else if (fmd && (fmd->type == MOD_FLUID_TYPE_EFFEC) && fmd->effector) {
|
|
|
|
|
fmd->effector->flags &= ~FLUID_EFFECTOR_NEEDS_UPDATE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* texture field */
|
|
|
|
|
if (ob->pd) {
|
|
|
|
|
BKE_particle_partdeflect_blend_read_lib(reader, &ob->id, ob->pd);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ob->soft) {
|
|
|
|
|
BLO_read_id_address(reader, ob->id.lib, &ob->soft->collision_group);
|
|
|
|
|
|
|
|
|
|
BLO_read_id_address(reader, ob->id.lib, &ob->soft->effector_weights->group);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BKE_particle_system_blend_read_lib(reader, ob, &ob->id, &ob->particlesystem);
|
|
|
|
|
BKE_modifier_blend_read_lib(reader, ob);
|
|
|
|
|
BKE_gpencil_modifier_blend_read_lib(reader, ob);
|
|
|
|
|
BKE_shaderfx_blend_read_lib(reader, ob);
|
|
|
|
|
|
|
|
|
|
if (ob->rigidbody_constraint) {
|
|
|
|
|
BLO_read_id_address(reader, ob->id.lib, &ob->rigidbody_constraint->ob1);
|
|
|
|
|
BLO_read_id_address(reader, ob->id.lib, &ob->rigidbody_constraint->ob2);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* XXX deprecated - old animation system */
|
|
|
|
|
static void expand_constraint_channels(BlendExpander *expander, ListBase *chanbase)
|
|
|
|
|
{
|
|
|
|
|
LISTBASE_FOREACH (bConstraintChannel *, chan, chanbase) {
|
|
|
|
|
BLO_expand(expander, chan->ipo);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void expand_object_expandModifiers(void *userData,
|
|
|
|
|
Object *UNUSED(ob),
|
|
|
|
|
ID **idpoin,
|
|
|
|
|
int UNUSED(cb_flag))
|
|
|
|
|
{
|
2021-11-04 16:51:37 -03:00
|
|
|
BlendExpander *expander = (BlendExpander *)userData;
|
2020-11-06 18:25:44 +01:00
|
|
|
BLO_expand(expander, *idpoin);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PartEff *BKE_object_do_version_give_parteff_245(Object *ob)
|
|
|
|
|
{
|
|
|
|
|
PartEff *paf;
|
|
|
|
|
|
2021-11-04 16:51:37 -03:00
|
|
|
paf = (PartEff *)ob->effect.first;
|
2020-11-06 18:25:44 +01:00
|
|
|
while (paf) {
|
|
|
|
|
if (paf->type == EFF_PARTICLE) {
|
|
|
|
|
return paf;
|
|
|
|
|
}
|
|
|
|
|
paf = paf->next;
|
|
|
|
|
}
|
2021-11-04 16:51:37 -03:00
|
|
|
return nullptr;
|
2020-11-06 18:25:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void object_blend_read_expand(BlendExpander *expander, ID *id)
|
|
|
|
|
{
|
|
|
|
|
Object *ob = (Object *)id;
|
|
|
|
|
|
|
|
|
|
BLO_expand(expander, ob->data);
|
|
|
|
|
|
2021-07-05 18:03:57 +02:00
|
|
|
BLO_expand(expander, ob->parent);
|
|
|
|
|
|
2020-11-06 18:25:44 +01:00
|
|
|
/* expand_object_expandModifier() */
|
|
|
|
|
if (ob->modifiers.first) {
|
|
|
|
|
BKE_modifiers_foreach_ID_link(ob, expand_object_expandModifiers, expander);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* expand_object_expandModifier() */
|
|
|
|
|
if (ob->greasepencil_modifiers.first) {
|
|
|
|
|
BKE_gpencil_modifiers_foreach_ID_link(ob, expand_object_expandModifiers, expander);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* expand_object_expandShaderFx() */
|
|
|
|
|
if (ob->shader_fx.first) {
|
|
|
|
|
BKE_shaderfx_foreach_ID_link(ob, expand_object_expandModifiers, expander);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BKE_pose_blend_read_expand(expander, ob->pose);
|
|
|
|
|
BLO_expand(expander, ob->poselib);
|
|
|
|
|
BKE_constraint_blend_read_expand(expander, &ob->constraints);
|
|
|
|
|
|
|
|
|
|
BLO_expand(expander, ob->gpd);
|
|
|
|
|
|
|
|
|
|
/* XXX deprecated - old animation system (for version patching only) */
|
|
|
|
|
BLO_expand(expander, ob->ipo);
|
|
|
|
|
BLO_expand(expander, ob->action);
|
|
|
|
|
|
|
|
|
|
expand_constraint_channels(expander, &ob->constraintChannels);
|
|
|
|
|
|
|
|
|
|
LISTBASE_FOREACH (bActionStrip *, strip, &ob->nlastrips) {
|
|
|
|
|
BLO_expand(expander, strip->object);
|
|
|
|
|
BLO_expand(expander, strip->act);
|
|
|
|
|
BLO_expand(expander, strip->ipo);
|
|
|
|
|
}
|
|
|
|
|
/* XXX deprecated - old animation system (for version patching only) */
|
|
|
|
|
|
|
|
|
|
for (int a = 0; a < ob->totcol; a++) {
|
|
|
|
|
BLO_expand(expander, ob->mat[a]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PartEff *paf = BKE_object_do_version_give_parteff_245(ob);
|
|
|
|
|
if (paf && paf->group) {
|
|
|
|
|
BLO_expand(expander, paf->group);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ob->instance_collection) {
|
|
|
|
|
BLO_expand(expander, ob->instance_collection);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ob->proxy) {
|
|
|
|
|
BLO_expand(expander, ob->proxy);
|
|
|
|
|
}
|
|
|
|
|
if (ob->proxy_group) {
|
|
|
|
|
BLO_expand(expander, ob->proxy_group);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LISTBASE_FOREACH (ParticleSystem *, psys, &ob->particlesystem) {
|
|
|
|
|
BLO_expand(expander, psys->part);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ob->pd) {
|
|
|
|
|
BLO_expand(expander, ob->pd->tex);
|
|
|
|
|
BLO_expand(expander, ob->pd->f_source);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ob->soft) {
|
|
|
|
|
BLO_expand(expander, ob->soft->collision_group);
|
|
|
|
|
|
|
|
|
|
if (ob->soft->effector_weights) {
|
|
|
|
|
BLO_expand(expander, ob->soft->effector_weights->group);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ob->rigidbody_constraint) {
|
|
|
|
|
BLO_expand(expander, ob->rigidbody_constraint->ob1);
|
|
|
|
|
BLO_expand(expander, ob->rigidbody_constraint->ob2);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-20 17:21:30 +02:00
|
|
|
static void object_lib_override_apply_post(ID *id_dst, ID *id_src)
|
2021-01-22 14:52:50 +01:00
|
|
|
{
|
2021-10-20 17:21:30 +02:00
|
|
|
/* id_dst is the new local override copy of the linked reference data. id_src is the old override
|
|
|
|
|
* data stored on disk, used as source data for override operations. */
|
|
|
|
|
Object *object_dst = (Object *)id_dst;
|
|
|
|
|
Object *object_src = (Object *)id_src;
|
|
|
|
|
|
|
|
|
|
ListBase pidlist_dst, pidlist_src;
|
2021-11-04 16:51:37 -03:00
|
|
|
BKE_ptcache_ids_from_object(&pidlist_dst, object_dst, nullptr, 0);
|
|
|
|
|
BKE_ptcache_ids_from_object(&pidlist_src, object_src, nullptr, 0);
|
2021-10-20 17:21:30 +02:00
|
|
|
|
|
|
|
|
/* Problem with point caches is that several status flags (like OUTDATED or BAKED) are read-only
|
|
|
|
|
* at RNA level, and therefore not overridable per-se.
|
|
|
|
|
*
|
2021-10-22 10:28:56 +11:00
|
|
|
* This code is a workaround this to check all point-caches from both source and destination
|
2021-10-20 17:21:30 +02:00
|
|
|
* objects in parallel, and transfer those flags when it makes sense.
|
|
|
|
|
*
|
|
|
|
|
* This allows to keep baked caches across liboverrides applies.
|
|
|
|
|
*
|
2021-10-22 10:28:56 +11:00
|
|
|
* NOTE: This is fairly hackish and weak, but so is the point-cache system as its whole. A more
|
2021-10-20 17:21:30 +02:00
|
|
|
* robust solution would be e.g. to have a specific RNA entry point to deal with such cases
|
|
|
|
|
* (maybe a new flag to allow override code to set values of some read-only properties?).
|
|
|
|
|
*/
|
|
|
|
|
PTCacheID *pid_src, *pid_dst;
|
2021-11-04 16:51:37 -03:00
|
|
|
for (pid_dst = (PTCacheID *)pidlist_dst.first, pid_src = (PTCacheID *)pidlist_src.first;
|
|
|
|
|
pid_dst != nullptr;
|
|
|
|
|
pid_dst = pid_dst->next, pid_src = (pid_src != nullptr) ? pid_src->next : nullptr) {
|
2021-10-20 17:21:30 +02:00
|
|
|
/* If pid's do not match, just tag info of caches in dst as dirty and continue. */
|
2021-11-04 16:51:37 -03:00
|
|
|
if (pid_src == nullptr) {
|
2021-10-26 10:13:44 +02:00
|
|
|
continue;
|
|
|
|
|
}
|
2021-10-26 10:28:52 +02:00
|
|
|
if (pid_dst->type != pid_src->type || pid_dst->file_type != pid_src->file_type ||
|
|
|
|
|
pid_dst->default_step != pid_src->default_step || pid_dst->max_step != pid_src->max_step ||
|
|
|
|
|
pid_dst->data_types != pid_src->data_types || pid_dst->info_types != pid_src->info_types) {
|
2021-10-20 17:21:30 +02:00
|
|
|
LISTBASE_FOREACH (PointCache *, point_cache_src, pid_src->ptcaches) {
|
|
|
|
|
point_cache_src->flag |= PTCACHE_FLAG_INFO_DIRTY;
|
|
|
|
|
}
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2021-01-22 14:52:50 +01:00
|
|
|
|
2021-10-20 17:21:30 +02:00
|
|
|
PointCache *point_cache_dst, *point_cache_src;
|
2021-11-04 16:51:37 -03:00
|
|
|
for (point_cache_dst = (PointCache *)pid_dst->ptcaches->first,
|
|
|
|
|
point_cache_src = (PointCache *)pid_src->ptcaches->first;
|
|
|
|
|
point_cache_dst != nullptr;
|
2021-10-20 17:21:30 +02:00
|
|
|
point_cache_dst = point_cache_dst->next,
|
2021-11-04 16:51:37 -03:00
|
|
|
point_cache_src = (point_cache_src != nullptr) ? point_cache_src->next : nullptr) {
|
2021-10-20 17:21:30 +02:00
|
|
|
/* Always force updating info about caches of applied liboverrides. */
|
|
|
|
|
point_cache_dst->flag |= PTCACHE_FLAG_INFO_DIRTY;
|
2021-11-04 16:51:37 -03:00
|
|
|
if (point_cache_src == nullptr || !STREQ(point_cache_dst->name, point_cache_src->name)) {
|
2021-10-20 17:21:30 +02:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if ((point_cache_src->flag & PTCACHE_BAKED) != 0) {
|
|
|
|
|
point_cache_dst->flag |= PTCACHE_BAKED;
|
|
|
|
|
}
|
|
|
|
|
if ((point_cache_src->flag & PTCACHE_OUTDATED) == 0) {
|
|
|
|
|
point_cache_dst->flag &= ~PTCACHE_OUTDATED;
|
|
|
|
|
}
|
2021-01-22 14:52:50 +01:00
|
|
|
}
|
|
|
|
|
}
|
2021-10-20 17:21:30 +02:00
|
|
|
BLI_freelistN(&pidlist_dst);
|
|
|
|
|
BLI_freelistN(&pidlist_src);
|
2021-01-22 14:52:50 +01:00
|
|
|
}
|
|
|
|
|
|
2021-10-25 08:02:08 -03:00
|
|
|
static IDProperty *object_asset_dimensions_property(Object *ob)
|
|
|
|
|
{
|
2022-04-01 14:48:48 -05:00
|
|
|
float3 dimensions;
|
2021-10-25 08:02:08 -03:00
|
|
|
BKE_object_dimensions_get(ob, dimensions);
|
|
|
|
|
if (is_zero_v3(dimensions)) {
|
2021-11-04 16:51:37 -03:00
|
|
|
return nullptr;
|
2021-10-25 08:02:08 -03:00
|
|
|
}
|
|
|
|
|
|
2021-11-08 12:40:08 -03:00
|
|
|
IDPropertyTemplate idprop{};
|
2021-10-25 08:02:08 -03:00
|
|
|
idprop.array.len = ARRAY_SIZE(dimensions);
|
|
|
|
|
idprop.array.type = IDP_FLOAT;
|
|
|
|
|
|
|
|
|
|
IDProperty *property = IDP_New(IDP_ARRAY, &idprop, "dimensions");
|
|
|
|
|
memcpy(IDP_Array(property), dimensions, sizeof(dimensions));
|
|
|
|
|
|
|
|
|
|
return property;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void object_asset_pre_save(void *asset_ptr, struct AssetMetaData *asset_data)
|
|
|
|
|
{
|
2021-11-04 16:51:37 -03:00
|
|
|
Object *ob = (Object *)asset_ptr;
|
2021-10-25 08:02:08 -03:00
|
|
|
BLI_assert(GS(ob->id.name) == ID_OB);
|
|
|
|
|
|
|
|
|
|
/* Update dimensions hint for the asset. */
|
|
|
|
|
IDProperty *dimensions_prop = object_asset_dimensions_property(ob);
|
|
|
|
|
if (dimensions_prop) {
|
|
|
|
|
BKE_asset_metadata_idprop_ensure(asset_data, dimensions_prop);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-29 09:24:25 +10:00
|
|
|
static AssetTypeInfo AssetType_OB = {
|
2021-11-04 16:51:37 -03:00
|
|
|
/* pre_save_fn */ object_asset_pre_save,
|
2021-10-25 08:02:08 -03:00
|
|
|
};
|
|
|
|
|
|
2020-03-05 10:54:00 +01:00
|
|
|
IDTypeInfo IDType_ID_OB = {
|
2021-11-04 16:51:37 -03:00
|
|
|
/* id_code */ ID_OB,
|
|
|
|
|
/* id_filter */ FILTER_ID_OB,
|
|
|
|
|
/* main_listbase_index */ INDEX_ID_OB,
|
|
|
|
|
/* struct_size */ sizeof(Object),
|
|
|
|
|
/* name */ "Object",
|
|
|
|
|
/* name_plural */ "objects",
|
|
|
|
|
/* translation_context */ BLT_I18NCONTEXT_ID_OBJECT,
|
|
|
|
|
/* flags */ 0,
|
2021-11-24 10:32:28 +01:00
|
|
|
/* asset_type_info */ &AssetType_OB,
|
2021-11-04 16:51:37 -03:00
|
|
|
|
|
|
|
|
/* init_data */ object_init_data,
|
|
|
|
|
/* copy_data */ object_copy_data,
|
|
|
|
|
/* free_data */ object_free_data,
|
2022-02-04 15:34:30 +01:00
|
|
|
/* make_local */ nullptr,
|
2021-11-04 16:51:37 -03:00
|
|
|
/* foreach_id */ object_foreach_id,
|
|
|
|
|
/* foreach_cache */ nullptr,
|
Refactor BKE_bpath module.
The main goal of this refactor is to make BPath module use `IDTypeInfo`,
and move each ID-specific part of the `foreach_path` looper into their
own IDTypeInfo struct, using a new `foreach_path` callback.
Additionally, following improvements/cleanups are included:
* Attempt to get better, more consistent namings.
** In particular, move from `path_visitor` to more standard `foreach_path`.
* Update and extend documentation.
** API doc was moved to header, according to recent discussions on this
topic.
* Remove `BKE_bpath_relocate_visitor` from API, this is specific
callback that belongs in `lib_id.c` user code.
NOTE: This commit is expected to be 100% non-behavioral-change. This
implies that several potential further changes were only noted as
comments (like using a more generic solution for
`lib_id_library_local_paths`, addressing inconsistencies like path of
packed libraries always being skipped, regardless of the
`BKE_BPATH_FOREACH_PATH_SKIP_PACKED` `eBPathForeachFlag` flag value,
etc.).
NOTE: basic unittests were added to master already in
rBdcc500e5a265093bc9cc.
Reviewed By: brecht
Differential Revision: https://developer.blender.org/D13381
2021-11-29 14:20:58 +01:00
|
|
|
/* foreach_path */ object_foreach_path,
|
2021-11-04 16:51:37 -03:00
|
|
|
/* owner_get */ nullptr,
|
|
|
|
|
|
|
|
|
|
/* blend_write */ object_blend_write,
|
|
|
|
|
/* blend_read_data */ object_blend_read_data,
|
|
|
|
|
/* blend_read_lib */ object_blend_read_lib,
|
|
|
|
|
/* blend_read_expand */ object_blend_read_expand,
|
|
|
|
|
|
|
|
|
|
/* blend_read_undo_preserve */ nullptr,
|
|
|
|
|
|
|
|
|
|
/* lib_override_apply_post */ object_lib_override_apply_post,
|
2020-03-05 10:54:00 +01:00
|
|
|
};
|
|
|
|
|
|
2012-05-05 14:03:12 +00:00
|
|
|
void BKE_object_workob_clear(Object *workob)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2022-03-31 10:06:33 +02:00
|
|
|
*workob = blender::dna::shallow_zero_initialize();
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2019-02-18 15:43:06 +11:00
|
|
|
workob->scale[0] = workob->scale[1] = workob->scale[2] = 1.0f;
|
2012-05-06 15:15:33 +00:00
|
|
|
workob->dscale[0] = workob->dscale[1] = workob->dscale[2] = 1.0f;
|
|
|
|
|
workob->rotmode = ROT_MODE_EUL;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
2012-05-05 14:03:12 +00:00
|
|
|
void BKE_object_free_particlesystems(Object *ob)
|
2008-02-27 17:04:58 +00:00
|
|
|
{
|
2013-08-26 23:37:08 +00:00
|
|
|
ParticleSystem *psys;
|
|
|
|
|
|
2021-11-04 16:51:37 -03:00
|
|
|
while ((psys = (ParticleSystem *)BLI_pophead(&ob->particlesystem))) {
|
2012-04-29 15:47:02 +00:00
|
|
|
psys_free(ob, psys);
|
2008-02-27 17:04:58 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-05 14:03:12 +00:00
|
|
|
void BKE_object_free_softbody(Object *ob)
|
2008-02-27 17:04:58 +00:00
|
|
|
{
|
2018-07-04 11:21:31 +02:00
|
|
|
sbFree(ob);
|
2008-02-27 17:04:58 +00:00
|
|
|
}
|
|
|
|
|
|
2013-08-19 09:25:24 +00:00
|
|
|
void BKE_object_free_curve_cache(Object *ob)
|
|
|
|
|
{
|
2018-07-30 16:54:40 +02:00
|
|
|
if (ob->runtime.curve_cache) {
|
|
|
|
|
BKE_displist_free(&ob->runtime.curve_cache->disp);
|
|
|
|
|
BKE_curve_bevelList_free(&ob->runtime.curve_cache->bev);
|
2021-04-08 15:51:08 +02:00
|
|
|
if (ob->runtime.curve_cache->anim_path_accum_length) {
|
2021-04-09 14:55:31 +10:00
|
|
|
MEM_freeN((void *)ob->runtime.curve_cache->anim_path_accum_length);
|
2013-08-19 09:25:24 +00:00
|
|
|
}
|
2018-07-30 16:54:40 +02:00
|
|
|
BKE_nurbList_free(&ob->runtime.curve_cache->deformed_nurbs);
|
|
|
|
|
MEM_freeN(ob->runtime.curve_cache);
|
2021-11-04 16:51:37 -03:00
|
|
|
ob->runtime.curve_cache = nullptr;
|
2013-08-19 09:25:24 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-04 14:56:32 +02:00
|
|
|
void BKE_object_free_modifiers(Object *ob, const int flag)
|
2005-07-19 20:14:17 +00:00
|
|
|
{
|
2013-08-26 23:37:08 +00:00
|
|
|
ModifierData *md;
|
2018-07-31 10:22:19 +02:00
|
|
|
GpencilModifierData *gp_md;
|
2013-08-26 23:37:08 +00:00
|
|
|
|
2021-11-04 16:51:37 -03:00
|
|
|
while ((md = (ModifierData *)BLI_pophead(&ob->modifiers))) {
|
2020-05-08 10:14:02 +02:00
|
|
|
BKE_modifier_free_ex(md, flag);
|
2005-07-19 20:14:17 +00:00
|
|
|
}
|
Particles
=========
Merge of the famous particle patch by Janne Karhu, a full rewrite
of the Blender particle system. This includes:
- Emitter, Hair and Reactor particle types.
- Newtonian, Keyed and Boids physics.
- Various particle visualisation and rendering types.
- Vertex group and texture control for various properties.
- Interpolated child particles from parents.
- Hair editing with combing, growing, cutting, .. .
- Explode modifier.
- Harmonic, Magnetic fields, and multiple falloff types.
.. and lots of other things, some more info is here:
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite_Doc
The new particle system cannot be backwards compatible. Old particle
systems are being converted to the new system, but will require
tweaking to get them looking the same as before.
Point Cache
===========
The new system to replace manual baking, based on automatic caching
on disk. This is currently used by softbodies and the particle system.
See the Cache API section on:
http://wiki.blender.org/index.php/BlenderDev/PhysicsSprint
Documentation
=============
These new features still need good docs for the release logs, help
for this is appreciated.
2007-11-26 22:09:57 +00:00
|
|
|
|
2021-11-04 16:51:37 -03:00
|
|
|
while ((gp_md = (GpencilModifierData *)BLI_pophead(&ob->greasepencil_modifiers))) {
|
2018-07-31 10:22:19 +02:00
|
|
|
BKE_gpencil_modifier_free_ex(gp_md, flag);
|
|
|
|
|
}
|
Particles
=========
Merge of the famous particle patch by Janne Karhu, a full rewrite
of the Blender particle system. This includes:
- Emitter, Hair and Reactor particle types.
- Newtonian, Keyed and Boids physics.
- Various particle visualisation and rendering types.
- Vertex group and texture control for various properties.
- Interpolated child particles from parents.
- Hair editing with combing, growing, cutting, .. .
- Explode modifier.
- Harmonic, Magnetic fields, and multiple falloff types.
.. and lots of other things, some more info is here:
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite_Doc
The new particle system cannot be backwards compatible. Old particle
systems are being converted to the new system, but will require
tweaking to get them looking the same as before.
Point Cache
===========
The new system to replace manual baking, based on automatic caching
on disk. This is currently used by softbodies and the particle system.
See the Cache API section on:
http://wiki.blender.org/index.php/BlenderDev/PhysicsSprint
Documentation
=============
These new features still need good docs for the release logs, help
for this is appreciated.
2007-11-26 22:09:57 +00:00
|
|
|
/* particle modifiers were freed, so free the particlesystems as well */
|
2012-05-05 14:03:12 +00:00
|
|
|
BKE_object_free_particlesystems(ob);
|
Particles
=========
Merge of the famous particle patch by Janne Karhu, a full rewrite
of the Blender particle system. This includes:
- Emitter, Hair and Reactor particle types.
- Newtonian, Keyed and Boids physics.
- Various particle visualisation and rendering types.
- Vertex group and texture control for various properties.
- Interpolated child particles from parents.
- Hair editing with combing, growing, cutting, .. .
- Explode modifier.
- Harmonic, Magnetic fields, and multiple falloff types.
.. and lots of other things, some more info is here:
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite_Doc
The new particle system cannot be backwards compatible. Old particle
systems are being converted to the new system, but will require
tweaking to get them looking the same as before.
Point Cache
===========
The new system to replace manual baking, based on automatic caching
on disk. This is currently used by softbodies and the particle system.
See the Cache API section on:
http://wiki.blender.org/index.php/BlenderDev/PhysicsSprint
Documentation
=============
These new features still need good docs for the release logs, help
for this is appreciated.
2007-11-26 22:09:57 +00:00
|
|
|
|
2008-02-27 17:04:58 +00:00
|
|
|
/* same for softbody */
|
2012-05-05 14:03:12 +00:00
|
|
|
BKE_object_free_softbody(ob);
|
2015-11-11 01:56:39 +11:00
|
|
|
|
|
|
|
|
/* modifiers may have stored data in the DM cache */
|
|
|
|
|
BKE_object_free_derived_caches(ob);
|
2005-07-19 20:14:17 +00:00
|
|
|
}
|
|
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
void BKE_object_free_shaderfx(Object *ob, const int flag)
|
|
|
|
|
{
|
|
|
|
|
ShaderFxData *fx;
|
|
|
|
|
|
2021-11-04 16:51:37 -03:00
|
|
|
while ((fx = (ShaderFxData *)BLI_pophead(&ob->shader_fx))) {
|
2018-07-31 10:22:19 +02:00
|
|
|
BKE_shaderfx_free_ex(fx, flag);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-15 20:15:45 +00:00
|
|
|
void BKE_object_modifier_hook_reset(Object *ob, HookModifierData *hmd)
|
|
|
|
|
{
|
|
|
|
|
/* reset functionality */
|
|
|
|
|
if (hmd->object) {
|
|
|
|
|
bPoseChannel *pchan = BKE_pose_channel_find_name(hmd->object->pose, hmd->subtarget);
|
|
|
|
|
|
|
|
|
|
if (hmd->subtarget[0] && pchan) {
|
|
|
|
|
float imat[4][4], mat[4][4];
|
|
|
|
|
|
2019-04-27 12:07:07 +10:00
|
|
|
/* Calculate the world-space matrix for the pose-channel target first,
|
|
|
|
|
* then carry on as usual. */
|
2013-10-15 20:15:45 +00:00
|
|
|
mul_m4_m4m4(mat, hmd->object->obmat, pchan->pose_mat);
|
|
|
|
|
|
|
|
|
|
invert_m4_m4(imat, mat);
|
|
|
|
|
mul_m4_m4m4(hmd->parentinv, imat, ob->obmat);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
invert_m4_m4(hmd->object->imat, hmd->object->obmat);
|
|
|
|
|
mul_m4_m4m4(hmd->parentinv, hmd->object->imat, ob->obmat);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
void BKE_object_modifier_gpencil_hook_reset(Object *ob, HookGpencilModifierData *hmd)
|
|
|
|
|
{
|
2021-11-04 16:51:37 -03:00
|
|
|
if (hmd->object == nullptr) {
|
2018-07-31 10:22:19 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
/* reset functionality */
|
|
|
|
|
bPoseChannel *pchan = BKE_pose_channel_find_name(hmd->object->pose, hmd->subtarget);
|
|
|
|
|
|
|
|
|
|
if (hmd->subtarget[0] && pchan) {
|
|
|
|
|
float imat[4][4], mat[4][4];
|
|
|
|
|
|
2019-04-27 12:07:07 +10:00
|
|
|
/* Calculate the world-space matrix for the pose-channel target first,
|
|
|
|
|
* then carry on as usual. */
|
2018-07-31 10:22:19 +02:00
|
|
|
mul_m4_m4m4(mat, hmd->object->obmat, pchan->pose_mat);
|
|
|
|
|
|
|
|
|
|
invert_m4_m4(imat, mat);
|
|
|
|
|
mul_m4_m4m4(hmd->parentinv, imat, ob->obmat);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
invert_m4_m4(hmd->object->imat, hmd->object->obmat);
|
|
|
|
|
mul_m4_m4m4(hmd->parentinv, hmd->object->imat, ob->obmat);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-02 13:35:07 +01:00
|
|
|
void BKE_object_modifier_set_active(Object *ob, ModifierData *md)
|
|
|
|
|
{
|
|
|
|
|
LISTBASE_FOREACH (ModifierData *, md_iter, &ob->modifiers) {
|
|
|
|
|
md_iter->flag &= ~eModifierFlag_Active;
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-04 16:51:37 -03:00
|
|
|
if (md != nullptr) {
|
2020-12-02 13:35:07 +01:00
|
|
|
BLI_assert(BLI_findindex(&ob->modifiers, md) != -1);
|
|
|
|
|
md->flag |= eModifierFlag_Active;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ModifierData *BKE_object_active_modifier(const Object *ob)
|
|
|
|
|
{
|
|
|
|
|
/* In debug mode, check for only one active modifier. */
|
|
|
|
|
#ifndef NDEBUG
|
|
|
|
|
int active_count = 0;
|
|
|
|
|
LISTBASE_FOREACH (ModifierData *, md, &ob->modifiers) {
|
|
|
|
|
if (md->flag & eModifierFlag_Active) {
|
|
|
|
|
active_count++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
BLI_assert(ELEM(active_count, 0, 1));
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
LISTBASE_FOREACH (ModifierData *, md, &ob->modifiers) {
|
|
|
|
|
if (md->flag & eModifierFlag_Active) {
|
|
|
|
|
return md;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-04 16:51:37 -03:00
|
|
|
return nullptr;
|
2020-12-02 13:35:07 +01:00
|
|
|
}
|
|
|
|
|
|
2020-12-28 11:17:49 -06:00
|
|
|
bool BKE_object_supports_modifiers(const Object *ob)
|
|
|
|
|
{
|
2022-02-18 09:50:29 -06:00
|
|
|
return (ELEM(ob->type,
|
|
|
|
|
OB_MESH,
|
2022-07-12 18:31:33 +02:00
|
|
|
OB_CURVES,
|
2022-02-18 09:50:29 -06:00
|
|
|
OB_CURVES_LEGACY,
|
|
|
|
|
OB_SURF,
|
|
|
|
|
OB_FONT,
|
|
|
|
|
OB_LATTICE,
|
|
|
|
|
OB_POINTCLOUD,
|
|
|
|
|
OB_VOLUME));
|
2020-12-28 11:17:49 -06:00
|
|
|
}
|
|
|
|
|
|
2018-04-14 14:27:38 +02:00
|
|
|
bool BKE_object_support_modifier_type_check(const Object *ob, int modifier_type)
|
2012-03-12 14:35:07 +00:00
|
|
|
{
|
2021-11-04 16:51:37 -03:00
|
|
|
const ModifierTypeInfo *mti = BKE_modifier_get_info((ModifierType)modifier_type);
|
2012-03-12 14:35:07 +00:00
|
|
|
|
Geometry Nodes: Support modifier on curve objects
With this commit, curve objects support the geometry nodes modifier.
Curves objects now evaluate to `CurveEval` unless there was a previous
implicit conversion (tessellating modifiers, mesh modifiers, or the
settings in the curve "Geometry" panel). In the new code, curves are
only considered to be the wire edges-- any generated surface is a mesh
instead, stored in the evaluated geometry set.
The consolidation of concepts mentioned above allows remove a lot of
code that had to do with maintaining the `DispList` type temporarily
for modifiers and rendering. Instead, render engines see a separate
object for the mesh from the mesh geometry component, and when the
curve object evaluates to a curve, the `CurveEval` is always used for
drawing wire edges.
However, currently the `DispList` type is still maintained and used as
an intermediate step in implicit mesh conversion. In the future, more
uses of it could be changed to use `CurveEval` and `Mesh` instead.
This is mostly not changed behavior, it is just a formalization of
existing logic after recent fixes for 2.8 versions last year and two
years ago. Also, in the future more functionality can be converted
to nodes, removing cases of implicit conversions. For more discussion
on that topic, see T89676.
The `use_fill_deform` option is removed. It has not worked properly
since 2.62, and the choice for filling a curve before or after
deformation will work much better and be clearer with a node system.
Applying the geometry nodes modifier to generate a curve is not
implemented with this commit, so applying the modifier won't work
at all. This is a separate technical challenge, and should be solved
in a separate step.
Differential Revision: https://developer.blender.org/D11597
2021-09-11 13:54:40 -05:00
|
|
|
/* Surface and lattice objects don't output geometry sets. */
|
2021-11-04 16:51:37 -03:00
|
|
|
if (mti->modifyGeometrySet != nullptr && ELEM(ob->type, OB_SURF, OB_LATTICE)) {
|
Geometry Nodes: Support modifier on curve objects
With this commit, curve objects support the geometry nodes modifier.
Curves objects now evaluate to `CurveEval` unless there was a previous
implicit conversion (tessellating modifiers, mesh modifiers, or the
settings in the curve "Geometry" panel). In the new code, curves are
only considered to be the wire edges-- any generated surface is a mesh
instead, stored in the evaluated geometry set.
The consolidation of concepts mentioned above allows remove a lot of
code that had to do with maintaining the `DispList` type temporarily
for modifiers and rendering. Instead, render engines see a separate
object for the mesh from the mesh geometry component, and when the
curve object evaluates to a curve, the `CurveEval` is always used for
drawing wire edges.
However, currently the `DispList` type is still maintained and used as
an intermediate step in implicit mesh conversion. In the future, more
uses of it could be changed to use `CurveEval` and `Mesh` instead.
This is mostly not changed behavior, it is just a formalization of
existing logic after recent fixes for 2.8 versions last year and two
years ago. Also, in the future more functionality can be converted
to nodes, removing cases of implicit conversions. For more discussion
on that topic, see T89676.
The `use_fill_deform` option is removed. It has not worked properly
since 2.62, and the choice for filling a curve before or after
deformation will work much better and be clearer with a node system.
Applying the geometry nodes modifier to generate a curve is not
implemented with this commit, so applying the modifier won't work
at all. This is a separate technical challenge, and should be solved
in a separate step.
Differential Revision: https://developer.blender.org/D11597
2021-09-11 13:54:40 -05:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-30 20:09:02 +10:00
|
|
|
/* Only geometry objects should be able to get modifiers T25291. */
|
Curves: Rename "Hair" types, variables, and functions to "Curves"
Based on discussions from T95355 and T94193, the plan is to use
the name "Curves" to describe the data-block container for multiple
curves. Eventually this will replace the existing "Curve" data-block.
However, it will be a while before the curve data-block can be replaced
so in order to distinguish the two curve types in the UI, "Hair Curves"
will be used, but eventually changed back to "Curves".
This patch renames "hair-related" files, functions, types, and variable
names to this convention. A deep rename is preferred to keep code
consistent and to avoid any "hair" terminology from leaking, since the
new data-block is meant for all curve types, not just hair use cases.
The downside of this naming is that the difference between "Curve"
and "Curves" has become important. That was considered during
design discussons and deemed acceptable, especially given the
non-permanent nature of the somewhat common conflict.
Some points of interest:
- All DNA compatibility is lost, just like rBf59767ff9729.
- I renamed `ID_HA` to `ID_CV` so there is no complete mismatch.
- `hair_curves` is used where necessary to distinguish from the
existing "curves" plural.
- I didn't rename any of the cycles/rendering code function names,
since that is also used by the old hair particle system.
Differential Revision: https://developer.blender.org/D14007
2022-02-07 11:55:54 -06:00
|
|
|
if (ELEM(ob->type, OB_POINTCLOUD, OB_VOLUME, OB_CURVES)) {
|
2021-11-04 16:51:37 -03:00
|
|
|
return (mti->modifyGeometrySet != nullptr);
|
2020-04-21 13:09:41 +02:00
|
|
|
}
|
2022-02-18 09:50:29 -06:00
|
|
|
if (ELEM(ob->type, OB_MESH, OB_CURVES_LEGACY, OB_SURF, OB_FONT, OB_LATTICE)) {
|
2020-04-21 13:09:41 +02:00
|
|
|
if (ob->type == OB_LATTICE && (mti->flags & eModifierTypeFlag_AcceptsVertexCosOnly) == 0) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!((mti->flags & eModifierTypeFlag_AcceptsCVs) ||
|
|
|
|
|
(ob->type == OB_MESH && (mti->flags & eModifierTypeFlag_AcceptsMesh)))) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2016-05-18 22:21:46 +10:00
|
|
|
|
2020-04-21 13:09:41 +02:00
|
|
|
return true;
|
2012-03-12 14:35:07 +00:00
|
|
|
}
|
|
|
|
|
|
2020-04-21 13:09:41 +02:00
|
|
|
return false;
|
2012-03-12 14:35:07 +00:00
|
|
|
}
|
|
|
|
|
|
2021-01-19 16:02:25 +01:00
|
|
|
static bool object_modifier_type_copy_check(ModifierType md_type)
|
2020-09-15 14:39:09 -06:00
|
|
|
{
|
2021-01-19 16:02:25 +01:00
|
|
|
return !ELEM(md_type, eModifierType_Hook, eModifierType_Collision);
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-09 18:47:10 +10:00
|
|
|
/**
|
|
|
|
|
* Find a `psys` matching given `psys_src` in `ob_dst` (i.e. sharing the same ParticleSettings ID),
|
|
|
|
|
* or add one, and return valid `psys` from `ob_dst`.
|
2021-01-19 16:02:25 +01:00
|
|
|
*
|
|
|
|
|
* \note Order handling is fairly weak here. This code assumes that it is called **before** the
|
|
|
|
|
* modifier using the psys is actually copied, and that this copied modifier will be added at the
|
|
|
|
|
* end of the stack. That way we can be sure that the particle modifier will be before the one
|
|
|
|
|
* using its particle system in the stack.
|
|
|
|
|
*/
|
|
|
|
|
static ParticleSystem *object_copy_modifier_particle_system_ensure(Main *bmain,
|
|
|
|
|
Scene *scene,
|
|
|
|
|
Object *ob_dst,
|
|
|
|
|
ParticleSystem *psys_src)
|
|
|
|
|
{
|
2021-11-04 16:51:37 -03:00
|
|
|
ParticleSystem *psys_dst = nullptr;
|
2021-01-19 16:02:25 +01:00
|
|
|
|
|
|
|
|
/* Check if a particle system with the same particle settings
|
|
|
|
|
* already exists on the destination object. */
|
|
|
|
|
LISTBASE_FOREACH (ParticleSystem *, psys, &ob_dst->particlesystem) {
|
|
|
|
|
if (psys->part == psys_src->part) {
|
|
|
|
|
psys_dst = psys;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* If it does not exist, copy the particle system to the destination object. */
|
2021-11-04 16:51:37 -03:00
|
|
|
if (psys_dst == nullptr) {
|
2021-01-19 16:02:25 +01:00
|
|
|
ModifierData *md = object_copy_particle_system(bmain, scene, ob_dst, psys_src);
|
|
|
|
|
psys_dst = ((ParticleSystemModifierData *)md)->psys;
|
2020-09-15 14:39:09 -06:00
|
|
|
}
|
|
|
|
|
|
2021-01-19 16:02:25 +01:00
|
|
|
return psys_dst;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool BKE_object_copy_modifier(
|
|
|
|
|
Main *bmain, Scene *scene, Object *ob_dst, const Object *ob_src, ModifierData *md_src)
|
|
|
|
|
{
|
|
|
|
|
BLI_assert(ob_dst->type != OB_GPENCIL);
|
|
|
|
|
|
2021-11-04 16:51:37 -03:00
|
|
|
const ModifierTypeInfo *mti = BKE_modifier_get_info((ModifierType)md_src->type);
|
|
|
|
|
if (!object_modifier_type_copy_check((ModifierType)md_src->type)) {
|
2021-01-19 16:02:25 +01:00
|
|
|
/* We never allow copying those modifiers here. */
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if (!BKE_object_support_modifier_type_check(ob_dst, md_src->type)) {
|
2020-09-15 14:39:09 -06:00
|
|
|
return false;
|
|
|
|
|
}
|
2021-01-19 16:02:25 +01:00
|
|
|
if (mti->flags & eModifierTypeFlag_Single) {
|
2021-11-04 16:51:37 -03:00
|
|
|
if (BKE_modifiers_findby_type(ob_dst, (ModifierType)md_src->type) != nullptr) {
|
2021-01-19 16:02:25 +01:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-09-15 14:39:09 -06:00
|
|
|
|
2021-11-04 16:51:37 -03:00
|
|
|
ParticleSystem *psys_src = nullptr;
|
|
|
|
|
ParticleSystem *psys_dst = nullptr;
|
2021-01-19 16:02:25 +01:00
|
|
|
|
|
|
|
|
switch (md_src->type) {
|
2020-09-15 14:39:09 -06:00
|
|
|
case eModifierType_Softbody:
|
|
|
|
|
BKE_object_copy_softbody(ob_dst, ob_src, 0);
|
|
|
|
|
break;
|
|
|
|
|
case eModifierType_Skin:
|
|
|
|
|
/* ensure skin-node customdata exists */
|
2021-11-04 16:51:37 -03:00
|
|
|
BKE_mesh_ensure_skin_customdata((Mesh *)ob_dst->data);
|
2020-09-15 14:39:09 -06:00
|
|
|
break;
|
2021-01-19 16:02:25 +01:00
|
|
|
case eModifierType_Fluid: {
|
|
|
|
|
FluidModifierData *fmd = (FluidModifierData *)md_src;
|
|
|
|
|
if (fmd->type == MOD_FLUID_TYPE_FLOW) {
|
2021-11-04 16:51:37 -03:00
|
|
|
if (fmd->flow != nullptr && fmd->flow->psys != nullptr) {
|
2021-01-19 16:02:25 +01:00
|
|
|
psys_src = fmd->flow->psys;
|
|
|
|
|
psys_dst = object_copy_modifier_particle_system_ensure(bmain, scene, ob_dst, psys_src);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case eModifierType_DynamicPaint: {
|
|
|
|
|
DynamicPaintModifierData *dpmd = (DynamicPaintModifierData *)md_src;
|
2021-11-04 16:51:37 -03:00
|
|
|
if (dpmd->brush != nullptr && dpmd->brush->psys != nullptr) {
|
2021-01-19 16:02:25 +01:00
|
|
|
psys_src = dpmd->brush->psys;
|
|
|
|
|
psys_dst = object_copy_modifier_particle_system_ensure(bmain, scene, ob_dst, psys_src);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
break;
|
2020-09-15 14:39:09 -06:00
|
|
|
}
|
|
|
|
|
|
2021-01-19 16:02:25 +01:00
|
|
|
ModifierData *md_dst;
|
|
|
|
|
if (md_src->type == eModifierType_ParticleSystem) {
|
|
|
|
|
md_dst = object_copy_particle_system(
|
|
|
|
|
bmain, scene, ob_dst, ((ParticleSystemModifierData *)md_src)->psys);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
md_dst = BKE_modifier_new(md_src->type);
|
|
|
|
|
|
|
|
|
|
BLI_strncpy(md_dst->name, md_src->name, sizeof(md_dst->name));
|
2020-09-15 14:39:09 -06:00
|
|
|
|
2021-01-19 16:02:25 +01:00
|
|
|
if (md_src->type == eModifierType_Multires) {
|
|
|
|
|
/* Has to be done after mod creation, but *before* we actually copy its settings! */
|
|
|
|
|
multiresModifier_sync_levels_ex(
|
|
|
|
|
ob_dst, (MultiresModifierData *)md_src, (MultiresModifierData *)md_dst);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BKE_modifier_copydata(md_src, md_dst);
|
|
|
|
|
|
|
|
|
|
switch (md_dst->type) {
|
|
|
|
|
case eModifierType_Fluid:
|
2021-11-04 16:51:37 -03:00
|
|
|
if (psys_dst != nullptr) {
|
2021-01-19 16:02:25 +01:00
|
|
|
FluidModifierData *fmd_dst = (FluidModifierData *)md_dst;
|
2021-11-04 16:51:37 -03:00
|
|
|
BLI_assert(fmd_dst->type == MOD_FLUID_TYPE_FLOW && fmd_dst->flow != nullptr &&
|
|
|
|
|
fmd_dst->flow->psys != nullptr);
|
2021-01-19 16:02:25 +01:00
|
|
|
fmd_dst->flow->psys = psys_dst;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case eModifierType_DynamicPaint:
|
2021-11-04 16:51:37 -03:00
|
|
|
if (psys_dst != nullptr) {
|
2021-01-19 16:02:25 +01:00
|
|
|
DynamicPaintModifierData *dpmd_dst = (DynamicPaintModifierData *)md_dst;
|
2021-11-04 16:51:37 -03:00
|
|
|
BLI_assert(dpmd_dst->brush != nullptr && dpmd_dst->brush->psys != nullptr);
|
2021-01-19 16:02:25 +01:00
|
|
|
dpmd_dst->brush->psys = psys_dst;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BLI_addtail(&ob_dst->modifiers, md_dst);
|
|
|
|
|
BKE_modifier_unique_name(&ob_dst->modifiers, md_dst);
|
2020-09-15 14:39:09 -06:00
|
|
|
}
|
|
|
|
|
|
2021-01-19 16:02:25 +01:00
|
|
|
BKE_object_modifier_set_active(ob_dst, md_dst);
|
2020-09-15 14:39:09 -06:00
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-19 16:02:25 +01:00
|
|
|
bool BKE_object_copy_gpencil_modifier(struct Object *ob_dst, GpencilModifierData *gmd_src)
|
2020-09-15 14:39:09 -06:00
|
|
|
{
|
2021-01-19 16:02:25 +01:00
|
|
|
BLI_assert(ob_dst->type == OB_GPENCIL);
|
|
|
|
|
|
|
|
|
|
GpencilModifierData *gmd_dst = BKE_gpencil_modifier_new(gmd_src->type);
|
|
|
|
|
BLI_strncpy(gmd_dst->name, gmd_src->name, sizeof(gmd_dst->name));
|
2020-09-15 14:39:09 -06:00
|
|
|
|
2021-11-04 16:51:37 -03:00
|
|
|
const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(
|
|
|
|
|
(GpencilModifierType)gmd_src->type);
|
2021-01-19 16:02:25 +01:00
|
|
|
mti->copyData(gmd_src, gmd_dst);
|
2020-09-15 14:39:09 -06:00
|
|
|
|
2021-01-19 16:02:25 +01:00
|
|
|
BLI_addtail(&ob_dst->greasepencil_modifiers, gmd_dst);
|
|
|
|
|
BKE_gpencil_modifier_unique_name(&ob_dst->greasepencil_modifiers, gmd_dst);
|
2020-09-15 14:39:09 -06:00
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-19 16:02:25 +01:00
|
|
|
bool BKE_object_modifier_stack_copy(Object *ob_dst,
|
|
|
|
|
const Object *ob_src,
|
|
|
|
|
const bool do_copy_all,
|
|
|
|
|
const int flag_subdata)
|
2010-01-04 16:26:07 +00:00
|
|
|
{
|
2021-01-19 16:02:25 +01:00
|
|
|
if ((ob_dst->type == OB_GPENCIL) != (ob_src->type == OB_GPENCIL)) {
|
2021-07-15 18:23:28 +10:00
|
|
|
BLI_assert_msg(0,
|
|
|
|
|
"Trying to copy a modifier stack between a GPencil object and another type.");
|
2021-01-19 16:02:25 +01:00
|
|
|
return false;
|
|
|
|
|
}
|
2010-01-04 16:26:07 +00:00
|
|
|
|
2021-01-19 16:02:25 +01:00
|
|
|
if (!BLI_listbase_is_empty(&ob_dst->modifiers) ||
|
|
|
|
|
!BLI_listbase_is_empty(&ob_dst->greasepencil_modifiers)) {
|
|
|
|
|
BLI_assert(
|
|
|
|
|
!"Trying to copy a modifier stack into an object having a non-empty modifier stack.");
|
|
|
|
|
return false;
|
2012-03-12 14:35:07 +00:00
|
|
|
}
|
|
|
|
|
|
2021-01-19 16:02:25 +01:00
|
|
|
LISTBASE_FOREACH (ModifierData *, md_src, &ob_src->modifiers) {
|
2021-11-04 16:51:37 -03:00
|
|
|
if (!do_copy_all && !object_modifier_type_copy_check((ModifierType)md_src->type)) {
|
2021-01-19 16:02:25 +01:00
|
|
|
continue;
|
2015-05-07 15:16:10 +02:00
|
|
|
}
|
2021-01-19 16:02:25 +01:00
|
|
|
if (!BKE_object_support_modifier_type_check(ob_dst, md_src->type)) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-16 11:56:04 +01:00
|
|
|
ModifierData *md_dst = BKE_modifier_copy_ex(md_src, flag_subdata);
|
2021-01-19 16:02:25 +01:00
|
|
|
BLI_addtail(&ob_dst->modifiers, md_dst);
|
2020-05-07 09:57:28 +02:00
|
|
|
}
|
2015-05-07 15:16:10 +02:00
|
|
|
|
2021-01-19 16:02:25 +01:00
|
|
|
LISTBASE_FOREACH (GpencilModifierData *, gmd_src, &ob_src->greasepencil_modifiers) {
|
|
|
|
|
GpencilModifierData *gmd_dst = BKE_gpencil_modifier_new(gmd_src->type);
|
|
|
|
|
BLI_strncpy(gmd_dst->name, gmd_src->name, sizeof(gmd_dst->name));
|
|
|
|
|
BKE_gpencil_modifier_copydata_ex(gmd_src, gmd_dst, flag_subdata);
|
|
|
|
|
BLI_addtail(&ob_dst->greasepencil_modifiers, gmd_dst);
|
2010-01-04 16:26:07 +00:00
|
|
|
}
|
|
|
|
|
|
2021-01-19 16:02:25 +01:00
|
|
|
/* This could be copied from anywhere, since no other modifier actually use this data. But for
|
|
|
|
|
* consistency do it together with particle systems. */
|
|
|
|
|
BKE_object_copy_softbody(ob_dst, ob_src, flag_subdata);
|
|
|
|
|
|
|
|
|
|
/* It is mandatory that this happens after copying modifiers, as it will update their `psys`
|
|
|
|
|
* pointers accordingly. */
|
|
|
|
|
BKE_object_copy_particlesystems(ob_dst, ob_src, flag_subdata);
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BKE_object_link_modifiers(Object *ob_dst, const Object *ob_src)
|
|
|
|
|
{
|
|
|
|
|
BKE_object_free_modifiers(ob_dst, 0);
|
2010-01-04 16:26:07 +00:00
|
|
|
|
2021-01-19 16:02:25 +01:00
|
|
|
BKE_object_modifier_stack_copy(ob_dst, ob_src, false, 0);
|
2010-01-04 16:26:07 +00:00
|
|
|
}
|
|
|
|
|
|
2020-09-07 14:33:24 +10:00
|
|
|
/**
|
|
|
|
|
* Copy CCG related data. Used to sync copy of mesh with reshaped original mesh.
|
2018-09-25 12:31:01 +02:00
|
|
|
*/
|
|
|
|
|
static void copy_ccg_data(Mesh *mesh_destination, Mesh *mesh_source, int layer_type)
|
|
|
|
|
{
|
|
|
|
|
BLI_assert(mesh_destination->totloop == mesh_source->totloop);
|
|
|
|
|
CustomData *data_destination = &mesh_destination->ldata;
|
|
|
|
|
CustomData *data_source = &mesh_source->ldata;
|
|
|
|
|
const int num_elements = mesh_source->totloop;
|
|
|
|
|
if (!CustomData_has_layer(data_source, layer_type)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
const int layer_index = CustomData_get_layer_index(data_destination, layer_type);
|
|
|
|
|
CustomData_free_layer(data_destination, layer_type, num_elements, layer_index);
|
|
|
|
|
BLI_assert(!CustomData_has_layer(data_destination, layer_type));
|
2021-11-04 16:51:37 -03:00
|
|
|
CustomData_add_layer(data_destination, layer_type, CD_CALLOC, nullptr, num_elements);
|
2018-09-25 12:31:01 +02:00
|
|
|
BLI_assert(CustomData_has_layer(data_destination, layer_type));
|
|
|
|
|
CustomData_copy_layer_type_data(data_source, data_destination, layer_type, 0, 0, num_elements);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void object_update_from_subsurf_ccg(Object *object)
|
|
|
|
|
{
|
|
|
|
|
/* Currently CCG is only created for Mesh objects. */
|
|
|
|
|
if (object->type != OB_MESH) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2019-05-27 11:45:33 +02:00
|
|
|
/* If object does not own evaluated mesh we can not access it since it might be freed already
|
|
|
|
|
* (happens on dependency graph free where order of CoW-ed IDs free is undefined).
|
|
|
|
|
*
|
|
|
|
|
* Good news is: such mesh does not have modifiers applied, so no need to worry about CCG. */
|
2020-02-27 11:23:15 +01:00
|
|
|
if (!object->runtime.is_data_eval_owned) {
|
2019-05-27 11:45:33 +02:00
|
|
|
return;
|
|
|
|
|
}
|
OpenSubDiv: add support for an OpenGL evaluator
This evaluator is used in order to evaluate subdivision at render time, allowing for
faster renders of meshes with a subdivision surface modifier placed at the last
position in the modifier list.
When evaluating the subsurf modifier, we detect whether we can delegate evaluation
to the draw code. If so, the subdivision is first evaluated on the GPU using our own
custom evaluator (only the coarse data needs to be initially sent to the GPU), then,
buffers for the final `MeshBufferCache` are filled on the GPU using a set of
compute shaders. However, some buffers are still filled on the CPU side, if doing so
on the GPU is impractical (e.g. the line adjacency buffer used for x-ray, whose
logic is hardly GPU compatible).
This is done at the mesh buffer extraction level so that the result can be readily used
in the various OpenGL engines, without having to write custom geometry or tesselation
shaders.
We use our own subdivision evaluation shaders, instead of OpenSubDiv's vanilla one, in
order to control the data layout, and interpolation. For example, we store vertex colors
as compressed 16-bit integers, while OpenSubDiv's default evaluator only work for float
types.
In order to still access the modified geometry on the CPU side, for use in modifiers
or transform operators, a dedicated wrapper type is added `MESH_WRAPPER_TYPE_SUBD`.
Subdivision will be lazily evaluated via `BKE_object_get_evaluated_mesh` which will
create such a wrapper if possible. If the final subdivision surface is not needed on
the CPU side, `BKE_object_get_evaluated_mesh_no_subsurf` should be used.
Enabling or disabling GPU subdivision can be done through the user preferences (under
Viewport -> Subdivision).
See patch description for benchmarks.
Reviewed By: campbellbarton, jbakker, fclem, brecht, #eevee_viewport
Differential Revision: https://developer.blender.org/D12406
2021-12-27 16:34:47 +01:00
|
|
|
/* Object was never evaluated, so can not have CCG subdivision surface. If it were evaluated, do
|
|
|
|
|
* not try to compute OpenSubDiv on the CPU as it is not needed here. */
|
|
|
|
|
Mesh *mesh_eval = BKE_object_get_evaluated_mesh_no_subsurf(object);
|
2021-11-04 16:51:37 -03:00
|
|
|
if (mesh_eval == nullptr) {
|
2018-09-25 12:31:01 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
SubdivCCG *subdiv_ccg = mesh_eval->runtime.subdiv_ccg;
|
2021-11-04 16:51:37 -03:00
|
|
|
if (subdiv_ccg == nullptr) {
|
2018-09-25 12:31:01 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
/* Check whether there is anything to be reshaped. */
|
|
|
|
|
if (!subdiv_ccg->dirty.coords && !subdiv_ccg->dirty.hidden) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2018-09-26 15:08:04 +02:00
|
|
|
const int tot_level = mesh_eval->runtime.subdiv_ccg_tot_level;
|
2018-09-25 12:31:01 +02:00
|
|
|
Object *object_orig = DEG_get_original_object(object);
|
|
|
|
|
Mesh *mesh_orig = (Mesh *)object_orig->data;
|
2018-09-26 15:08:04 +02:00
|
|
|
multiresModifier_reshapeFromCCG(tot_level, mesh_orig, subdiv_ccg);
|
2018-09-25 12:31:01 +02:00
|
|
|
/* NOTE: we need to reshape into an original mesh from main database,
|
|
|
|
|
* allowing:
|
|
|
|
|
*
|
2021-11-05 10:19:44 +11:00
|
|
|
* - Update copies of that mesh at any moment.
|
|
|
|
|
* - Save the file without doing extra reshape.
|
|
|
|
|
* - All the users of the mesh have updated displacement.
|
2018-09-25 12:31:01 +02:00
|
|
|
*
|
|
|
|
|
* However, the tricky part here is that we only know about sculpted
|
|
|
|
|
* state of a mesh on an object level, and object is being updated after
|
2021-11-05 10:19:44 +11:00
|
|
|
* mesh data-block is updated. This forces us to:
|
2018-09-25 12:31:01 +02:00
|
|
|
*
|
2021-11-05 10:19:44 +11:00
|
|
|
* - Update mesh data-block from object evaluation, which is technically
|
|
|
|
|
* forbidden, but there is no other place for this yet.
|
|
|
|
|
* - Reshape to the original mesh from main database, and then copy updated
|
|
|
|
|
* layer to copy of that mesh (since copy of the mesh has decoupled
|
|
|
|
|
* custom data layers).
|
2018-09-25 12:31:01 +02:00
|
|
|
*
|
|
|
|
|
* All this is defeating all the designs we need to follow to allow safe
|
|
|
|
|
* threaded evaluation, but this is as good as we can make it within the
|
2021-07-20 15:01:05 +10:00
|
|
|
* current sculpt/evaluated mesh design. This is also how we've survived
|
2021-11-05 10:19:44 +11:00
|
|
|
* with old #DerivedMesh based solutions. So, while this is all wrong and
|
2018-09-25 12:31:01 +02:00
|
|
|
* needs reconsideration, doesn't seem to be a big stopper for real
|
|
|
|
|
* production artists.
|
|
|
|
|
*/
|
|
|
|
|
/* TODO(sergey): Solve this somehow, to be fully stable for threaded
|
|
|
|
|
* evaluation environment.
|
|
|
|
|
*/
|
2020-02-27 11:23:15 +01:00
|
|
|
/* NOTE: runtime.data_orig is what was before assigning mesh_eval,
|
2018-09-25 12:31:01 +02:00
|
|
|
* it is orig as in what was in object_eval->data before evaluating
|
|
|
|
|
* modifier stack.
|
|
|
|
|
*
|
2021-11-05 10:19:44 +11:00
|
|
|
* mesh_cow is a copy-on-written version of `object_orig->data`.
|
2018-09-25 12:31:01 +02:00
|
|
|
*/
|
2020-02-27 11:23:15 +01:00
|
|
|
Mesh *mesh_cow = (Mesh *)object->runtime.data_orig;
|
2018-09-25 12:31:01 +02:00
|
|
|
copy_ccg_data(mesh_cow, mesh_orig, CD_MDISPS);
|
|
|
|
|
copy_ccg_data(mesh_cow, mesh_orig, CD_GRID_PAINT_MASK);
|
2018-12-06 15:20:16 +01:00
|
|
|
/* Everything is now up-to-date. */
|
|
|
|
|
subdiv_ccg->dirty.coords = false;
|
|
|
|
|
subdiv_ccg->dirty.hidden = false;
|
2018-09-25 12:31:01 +02:00
|
|
|
}
|
|
|
|
|
|
2020-02-27 11:23:15 +01:00
|
|
|
void BKE_object_eval_assign_data(Object *object_eval, ID *data_eval, bool is_owned)
|
|
|
|
|
{
|
|
|
|
|
BLI_assert(object_eval->id.tag & LIB_TAG_COPIED_ON_WRITE);
|
2021-11-04 16:51:37 -03:00
|
|
|
BLI_assert(object_eval->runtime.data_eval == nullptr);
|
2020-02-27 11:23:15 +01:00
|
|
|
BLI_assert(data_eval->tag & LIB_TAG_NO_MAIN);
|
|
|
|
|
|
|
|
|
|
if (is_owned) {
|
|
|
|
|
/* Set flag for debugging. */
|
|
|
|
|
data_eval->tag |= LIB_TAG_COPIED_ON_WRITE_EVAL_RESULT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Assigned evaluated data. */
|
|
|
|
|
object_eval->runtime.data_eval = data_eval;
|
|
|
|
|
object_eval->runtime.is_data_eval_owned = is_owned;
|
|
|
|
|
|
2021-11-05 10:19:44 +11:00
|
|
|
/* Overwrite data of evaluated object, if the data-block types match. */
|
2021-11-04 16:51:37 -03:00
|
|
|
ID *data = (ID *)object_eval->data;
|
2020-02-27 11:23:15 +01:00
|
|
|
if (GS(data->name) == GS(data_eval->name)) {
|
|
|
|
|
/* NOTE: we are not supposed to invoke evaluation for original objects,
|
|
|
|
|
* but some areas are still being ported, so we play safe here. */
|
|
|
|
|
if (object_eval->id.tag & LIB_TAG_COPIED_ON_WRITE) {
|
|
|
|
|
object_eval->data = data_eval;
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-12-02 13:25:25 +01:00
|
|
|
|
|
|
|
|
/* Is set separately currently. */
|
2021-11-04 16:51:37 -03:00
|
|
|
object_eval->runtime.geometry_set_eval = nullptr;
|
2020-02-27 11:23:15 +01:00
|
|
|
}
|
|
|
|
|
|
2013-05-18 10:24:34 +00:00
|
|
|
void BKE_object_free_derived_caches(Object *ob)
|
2005-11-27 20:49:25 +00:00
|
|
|
{
|
2019-02-18 17:55:44 +01:00
|
|
|
MEM_SAFE_FREE(ob->runtime.bb);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-09-25 12:31:01 +02:00
|
|
|
object_update_from_subsurf_ccg(ob);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-01-11 15:42:07 +01:00
|
|
|
if (ob->runtime.editmesh_eval_cage &&
|
|
|
|
|
ob->runtime.editmesh_eval_cage != reinterpret_cast<Mesh *>(ob->runtime.data_eval)) {
|
|
|
|
|
BKE_mesh_eval_delete(ob->runtime.editmesh_eval_cage);
|
|
|
|
|
}
|
|
|
|
|
ob->runtime.editmesh_eval_cage = nullptr;
|
|
|
|
|
|
2021-11-04 16:51:37 -03:00
|
|
|
if (ob->runtime.data_eval != nullptr) {
|
2020-02-27 11:23:15 +01:00
|
|
|
if (ob->runtime.is_data_eval_owned) {
|
|
|
|
|
ID *data_eval = ob->runtime.data_eval;
|
|
|
|
|
if (GS(data_eval->name) == ID_ME) {
|
|
|
|
|
BKE_mesh_eval_delete((Mesh *)data_eval);
|
|
|
|
|
}
|
|
|
|
|
else {
|
2022-04-22 10:26:08 -05:00
|
|
|
BKE_libblock_free_data(data_eval, false);
|
2020-02-27 11:23:15 +01:00
|
|
|
BKE_libblock_free_datablock(data_eval, 0);
|
|
|
|
|
MEM_freeN(data_eval);
|
|
|
|
|
}
|
2019-05-31 17:03:40 +02:00
|
|
|
}
|
2021-11-04 16:51:37 -03:00
|
|
|
ob->runtime.data_eval = nullptr;
|
Depsgraph: Initial groundwork for copy-on-write support
< Dependency graph Copy-on-Write >
--------------------------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
This is an initial commit of Copy-on-write support added to dependency graph.
Main priority for now: get playback (Alt-A) and all operators (selection,
transform etc) to work with the new concept of clear separation between
evaluated data coming from dependency graph and original data coming from
.blend file (and stored in bmain).
= How does this work? =
The idea is to support Copy-on-Write on the ID level. This means, we duplicate
the whole ID before we cann it's evaluaiton function. This is currently done
in the following way:
- At the depsgraph construction time we create "shallow" copy of the ID
datablock, just so we know it's pointer in memory and can use for function
bindings.
- At the evaluaiton time, the copy of ID get's "expanded" (needs a better
name internally, so it does not conflict with expanding datablocks during
library linking), which means the content of the datablock is being
copied over and all IDs are getting remapped to the copied ones.
Currently we do the whole copy, in the future we will support some tricks
here to prevent duplicating geometry arrays (verts, edges, loops, faces
and polys) when we don't need that.
- Evaluation functions are operating on copied datablocks and never touching
original datablock.
- There are some cases when we need to know non-ID pointers for function
bindings. This mainly applies to scene collections and armatures. The
idea of dealing with this is to "expand" copy-on-write datablock at
the dependency graph build time. This might introduce some slowdown to the
dependency graph construction time, but allows us to have minimal changes
in the code and avoid any hash look-up from evaluation function (one of
the ideas to avoid using pointers as function bindings is to pass name
of layer or a bone to the evaluation function and look up actual data based
on that name).
Currently there is a special function in depsgraph which does such a
synchronization, in the future we might want to make it more generic.
At some point we need to synchronize copy-on-write version of datablock with
the original version. This happens, i.e., when we change active object or
change selection. We don't want any actual evaluation of update flush happening
for such thins, so now we have a special update tag:
DEG_id_tag_update((id, DEG_TAG_COPY_ON_WRITE)
- For the render engines we now have special call for the dependency graph to
give evaluated datablock for the given original one. This isn't fully ideal
but allows to have Cycles viewport render.
This is definitely a subject for further investigation / improvement.
This call will tag copy-on-write component tagged for update without causing
updates to be flushed to any other objects, causing chain reaction of updates.
This tag is handy when selection in the scene changes.
This basically summarizes ideas underneath this commit. The code should be
reasonably documented.
Here is a demo of dependency graph with all copy-on-write stuff in it:
https://developer.blender.org/F635468
= What to expect to (not) work? =
- Only meshes are properly-ish aware of copy-on-write currently, Non-mesh
geometry will probably crash or will not work at all.
- Armatures will need similar depsgraph built-time expansion of the copied
datablock.
- There are some extra tags / relations added, to keep things demo-able but
which are slowing things down for evaluation.
- Edit mode works for until click selection is used (due to the selection
code using EditDerivedMesh created ad-hoc).
- Lots of tools will lack tagging synchronization of copied datablock for
sync with original ID.
= How to move forward? =
There is some tedious work related on going over all the tools, checking
whether they need to work with original or final evaluated object and make
the required changes.
Additionally, there need synchronization tag done in fair amount of tools
and operators as well. For example, currently it's not possible to change
render engine without re-opening the file or forcing dependency graph for
re-build via python console.
There is also now some thoughts required about copying evaluated properties
between objects or from collection to a new object. Perhaps easiest way
would be to move base flag flush to Object ID node and tag new objects for
update instead of doing manual copy.
here is some WIP patch which moves such evaluaiton / flush:
https://developer.blender.org/F635479
Lots of TODOs in the code, with possible optimization.
= How to test? =
This is a feature under heavy development, so obviously it is disabled by
default. The only reason it goes to 2.8 branch is to avoid possible merge
hell.
In order to enable this feature use WITH_DEPSGRAPH_COPY_ON_WRITE CMake
configuration option.
2017-06-14 10:26:24 +02:00
|
|
|
}
|
2021-11-04 16:51:37 -03:00
|
|
|
if (ob->runtime.mesh_deform_eval != nullptr) {
|
2018-05-30 11:49:45 +02:00
|
|
|
Mesh *mesh_deform_eval = ob->runtime.mesh_deform_eval;
|
2019-07-28 15:12:38 +02:00
|
|
|
BKE_mesh_eval_delete(mesh_deform_eval);
|
2021-11-04 16:51:37 -03:00
|
|
|
ob->runtime.mesh_deform_eval = nullptr;
|
2018-05-30 11:49:45 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-11-05 10:19:44 +11:00
|
|
|
/* Restore initial pointer for copy-on-write data-blocks, object->data
|
|
|
|
|
* might be pointing to an evaluated data-block data was just freed above. */
|
2021-11-04 16:51:37 -03:00
|
|
|
if (ob->runtime.data_orig != nullptr) {
|
2020-02-27 11:23:15 +01:00
|
|
|
ob->data = ob->runtime.data_orig;
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-16 13:49:21 +02:00
|
|
|
BKE_object_to_mesh_clear(ob);
|
2021-02-20 18:05:13 +02:00
|
|
|
BKE_object_to_curve_clear(ob);
|
2014-10-21 14:44:08 +02:00
|
|
|
BKE_object_free_curve_cache(ob);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-01-05 09:53:48 +01:00
|
|
|
BKE_crazyspace_api_eval_clear(ob);
|
|
|
|
|
|
2020-03-09 16:27:24 +01:00
|
|
|
/* Clear grease pencil data. */
|
2021-11-04 16:51:37 -03:00
|
|
|
if (ob->runtime.gpd_eval != nullptr) {
|
2020-03-09 16:27:24 +01:00
|
|
|
BKE_gpencil_eval_delete(ob->runtime.gpd_eval);
|
2021-11-04 16:51:37 -03:00
|
|
|
ob->runtime.gpd_eval = nullptr;
|
2020-03-09 16:27:24 +01:00
|
|
|
}
|
2020-12-02 13:25:25 +01:00
|
|
|
|
2021-11-04 16:51:37 -03:00
|
|
|
if (ob->runtime.geometry_set_eval != nullptr) {
|
2020-12-02 13:25:25 +01:00
|
|
|
BKE_geometry_set_free(ob->runtime.geometry_set_eval);
|
2021-11-04 16:51:37 -03:00
|
|
|
ob->runtime.geometry_set_eval = nullptr;
|
2020-12-02 13:25:25 +01:00
|
|
|
}
|
2022-01-11 15:42:07 +01:00
|
|
|
|
|
|
|
|
MEM_SAFE_FREE(ob->runtime.editmesh_bb_cage);
|
2005-11-27 20:49:25 +00:00
|
|
|
}
|
2011-09-14 00:37:27 +00:00
|
|
|
|
2015-02-17 17:27:15 +05:00
|
|
|
void BKE_object_free_caches(Object *object)
|
|
|
|
|
{
|
|
|
|
|
short update_flag = 0;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-02-17 17:27:15 +05:00
|
|
|
/* Free particle system caches holding paths. */
|
|
|
|
|
if (object->particlesystem.first) {
|
2021-11-04 16:51:37 -03:00
|
|
|
LISTBASE_FOREACH (ParticleSystem *, psys, &object->particlesystem) {
|
2015-02-17 17:27:15 +05:00
|
|
|
psys_free_path_cache(psys, psys->edit);
|
2018-12-06 17:52:37 +01:00
|
|
|
update_flag |= ID_RECALC_PSYS_REDO;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2015-02-17 17:27:15 +05:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-02-17 17:27:15 +05:00
|
|
|
/* Free memory used by cached derived meshes in the particle system modifiers. */
|
2020-12-22 10:35:18 -06:00
|
|
|
LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) {
|
2015-02-17 17:27:15 +05:00
|
|
|
if (md->type == eModifierType_ParticleSystem) {
|
|
|
|
|
ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md;
|
2019-06-21 11:49:43 +02:00
|
|
|
if (psmd->mesh_final) {
|
2021-11-04 16:51:37 -03:00
|
|
|
BKE_id_free(nullptr, psmd->mesh_final);
|
|
|
|
|
psmd->mesh_final = nullptr;
|
2019-06-21 11:49:43 +02:00
|
|
|
if (psmd->mesh_original) {
|
2021-11-04 16:51:37 -03:00
|
|
|
BKE_id_free(nullptr, psmd->mesh_original);
|
|
|
|
|
psmd->mesh_original = nullptr;
|
Fix T47038: Particles in Particle Edit Mode get added in completely wrong location.
It also fixes another issue (crash) related to symmetric editing.
Quite involved, we (try to!) fix complete broken logic of parts of particle code, which would use poly index
as tessface one (or vice-versa). Issue most probably goes back to BMesh integration time...
This patch mostly fixes particle editing mode:
- Adding/removing particles when using generative modifiers (like subsurf) should now work.
- Adding/removing particles with a non-tessellated mesh (i.e. one having ngons) should also mostly work.
- X-axis-mirror-editing particles over ngons does not really work, not sure why currently.
- All this in both 'modes' (with or without using modifier stack for particles).
Tech side:
- Store a deformed-only DM in particle modifier data.
- Rename existing DM to make it clear it's a final one.
- Use deformed-only DM's tessface2poly mapping to 'solve' poly/tessface mismatches.
- Make (part of) mirror-editing code able to use a DM instead of raw mesh, so that we can mirror based on final DM
when editing particles using modifier stack (mandatory, since there is no way currently to find orig tessface
from an final DM tessface index).
Note that this patch is not really nice and clean (current particles are beyond hope on this side anyway),
it's more like some urgency bandage. Whole crap needs complete rewrite anyway,
BMesh's polygons make it really hard to work with current system (and looptri would not help much here).
Also, did not test everything possibly affected by those changes, so it needs some users' testing & validation too.
Reviewers: psy-fi
Subscribers: dfelinto, eyecandy
Maniphest Tasks: T47038
Differential Revision: https://developer.blender.org/D1685
2016-01-04 12:19:45 +01:00
|
|
|
}
|
2015-06-09 18:54:43 +02:00
|
|
|
psmd->flag |= eParticleSystemFlag_file_loaded;
|
2018-12-06 17:52:37 +01:00
|
|
|
update_flag |= ID_RECALC_GEOMETRY;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2015-02-17 17:27:15 +05:00
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-06-26 11:05:59 +02:00
|
|
|
/* NOTE: If object is coming from a duplicator, it might be a temporary
|
2018-06-26 10:47:35 +02:00
|
|
|
* object created by dependency graph, which shares pointers with original
|
2018-06-26 11:05:59 +02:00
|
|
|
* object. In this case we can not free anything.
|
2018-06-26 10:47:35 +02:00
|
|
|
*/
|
2019-01-15 23:27:54 +11:00
|
|
|
if ((object->base_flag & BASE_FROM_DUPLI) == 0) {
|
2018-06-26 10:47:35 +02:00
|
|
|
BKE_object_free_derived_caches(object);
|
2018-12-06 17:52:37 +01:00
|
|
|
update_flag |= ID_RECALC_GEOMETRY;
|
2018-06-26 10:47:35 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-02-17 17:27:15 +05:00
|
|
|
/* Tag object for update, so once memory critical operation is over and
|
|
|
|
|
* scene update routines are back to its business the object will be
|
|
|
|
|
* guaranteed to be in a known state.
|
|
|
|
|
*/
|
|
|
|
|
if (update_flag != 0) {
|
2017-04-06 16:11:50 +02:00
|
|
|
DEG_id_tag_update(&object->id, update_flag);
|
2015-02-17 17:27:15 +05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-14 14:27:38 +02:00
|
|
|
bool BKE_object_is_in_editmode(const Object *ob)
|
2012-12-17 14:51:06 +00:00
|
|
|
{
|
2021-11-04 16:51:37 -03:00
|
|
|
if (ob->data == nullptr) {
|
2013-03-09 05:35:49 +00:00
|
|
|
return false;
|
2012-12-17 14:51:06 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-10-26 13:21:54 -03:00
|
|
|
switch (ob->type) {
|
|
|
|
|
case OB_MESH:
|
2021-11-04 16:51:37 -03:00
|
|
|
return ((Mesh *)ob->data)->edit_mesh != nullptr;
|
2018-10-26 13:21:54 -03:00
|
|
|
case OB_ARMATURE:
|
2021-11-04 16:51:37 -03:00
|
|
|
return ((bArmature *)ob->data)->edbo != nullptr;
|
2018-10-26 13:21:54 -03:00
|
|
|
case OB_FONT:
|
2021-11-04 16:51:37 -03:00
|
|
|
return ((Curve *)ob->data)->editfont != nullptr;
|
2018-10-26 13:21:54 -03:00
|
|
|
case OB_MBALL:
|
2021-11-04 16:51:37 -03:00
|
|
|
return ((MetaBall *)ob->data)->editelems != nullptr;
|
2018-10-26 13:21:54 -03:00
|
|
|
case OB_LATTICE:
|
2021-11-04 16:51:37 -03:00
|
|
|
return ((Lattice *)ob->data)->editlatt != nullptr;
|
2018-10-26 13:21:54 -03:00
|
|
|
case OB_SURF:
|
2022-02-18 09:50:29 -06:00
|
|
|
case OB_CURVES_LEGACY:
|
2021-11-04 16:51:37 -03:00
|
|
|
return ((Curve *)ob->data)->editnurb != nullptr;
|
2020-03-09 16:27:24 +01:00
|
|
|
case OB_GPENCIL:
|
|
|
|
|
/* Grease Pencil object has no edit mode data. */
|
|
|
|
|
return GPENCIL_EDIT_MODE((bGPdata *)ob->data);
|
Curves: fix edit mode detection
This adds missing cases to detect edit mode for Curves objects.
Unlike other object types, Curves do not have specific edit data,
rather we edit the original data directly, and rely on `Object.mode`.
For this, `BKE_object_data_is_in_editmode` had to be modified to
take a pointer to the object. This affects two places: the outliner
and the dependency graph. For the former place, the object pointer
is readily available, and we can use it. For the latter, the object
pointer is not available, however since it is used to update edit
mode pointers, and since Curves do not have such data, we can
safely pass null to the function here.
This also fixes the assertion failure that happens when closing a file
in edit mode.
Differential Revision: https://developer.blender.org/D14330
2022-04-05 19:59:20 +02:00
|
|
|
case OB_CURVES:
|
|
|
|
|
return ob->mode == OB_MODE_EDIT;
|
2018-10-26 13:21:54 -03:00
|
|
|
default:
|
|
|
|
|
return false;
|
2012-12-17 14:51:06 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-14 14:27:38 +02:00
|
|
|
bool BKE_object_is_in_editmode_vgroup(const Object *ob)
|
2013-07-01 20:27:03 +00:00
|
|
|
{
|
|
|
|
|
return (OB_TYPE_SUPPORT_VGROUP(ob->type) && BKE_object_is_in_editmode(ob));
|
|
|
|
|
}
|
|
|
|
|
|
Curves: fix edit mode detection
This adds missing cases to detect edit mode for Curves objects.
Unlike other object types, Curves do not have specific edit data,
rather we edit the original data directly, and rely on `Object.mode`.
For this, `BKE_object_data_is_in_editmode` had to be modified to
take a pointer to the object. This affects two places: the outliner
and the dependency graph. For the former place, the object pointer
is readily available, and we can use it. For the latter, the object
pointer is not available, however since it is used to update edit
mode pointers, and since Curves do not have such data, we can
safely pass null to the function here.
This also fixes the assertion failure that happens when closing a file
in edit mode.
Differential Revision: https://developer.blender.org/D14330
2022-04-05 19:59:20 +02:00
|
|
|
bool BKE_object_data_is_in_editmode(const Object *ob, const ID *id)
|
2018-05-30 10:15:36 +02:00
|
|
|
{
|
|
|
|
|
const short type = GS(id->name);
|
|
|
|
|
BLI_assert(OB_DATA_SUPPORT_EDITMODE(type));
|
|
|
|
|
switch (type) {
|
|
|
|
|
case ID_ME:
|
2021-11-04 16:51:37 -03:00
|
|
|
return ((const Mesh *)id)->edit_mesh != nullptr;
|
2022-02-18 09:50:29 -06:00
|
|
|
case ID_CU_LEGACY:
|
2021-11-04 16:51:37 -03:00
|
|
|
return ((((const Curve *)id)->editnurb != nullptr) ||
|
|
|
|
|
(((const Curve *)id)->editfont != nullptr));
|
2018-05-30 10:15:36 +02:00
|
|
|
case ID_MB:
|
2021-11-04 16:51:37 -03:00
|
|
|
return ((const MetaBall *)id)->editelems != nullptr;
|
2018-05-30 10:15:36 +02:00
|
|
|
case ID_LT:
|
2021-11-04 16:51:37 -03:00
|
|
|
return ((const Lattice *)id)->editlatt != nullptr;
|
2018-05-30 10:15:36 +02:00
|
|
|
case ID_AR:
|
2021-11-04 16:51:37 -03:00
|
|
|
return ((const bArmature *)id)->edbo != nullptr;
|
Curves: fix edit mode detection
This adds missing cases to detect edit mode for Curves objects.
Unlike other object types, Curves do not have specific edit data,
rather we edit the original data directly, and rely on `Object.mode`.
For this, `BKE_object_data_is_in_editmode` had to be modified to
take a pointer to the object. This affects two places: the outliner
and the dependency graph. For the former place, the object pointer
is readily available, and we can use it. For the latter, the object
pointer is not available, however since it is used to update edit
mode pointers, and since Curves do not have such data, we can
safely pass null to the function here.
This also fixes the assertion failure that happens when closing a file
in edit mode.
Differential Revision: https://developer.blender.org/D14330
2022-04-05 19:59:20 +02:00
|
|
|
case ID_CV:
|
|
|
|
|
if (ob) {
|
|
|
|
|
return BKE_object_is_in_editmode(ob);
|
|
|
|
|
}
|
|
|
|
|
return false;
|
2018-05-30 10:15:36 +02:00
|
|
|
default:
|
2021-03-24 12:38:08 +11:00
|
|
|
BLI_assert_unreachable();
|
2018-05-30 10:15:36 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-07 16:52:03 +11:00
|
|
|
char *BKE_object_data_editmode_flush_ptr_get(struct ID *id)
|
|
|
|
|
{
|
|
|
|
|
const short type = GS(id->name);
|
|
|
|
|
switch (type) {
|
|
|
|
|
case ID_ME: {
|
|
|
|
|
BMEditMesh *em = ((Mesh *)id)->edit_mesh;
|
2021-11-04 16:51:37 -03:00
|
|
|
if (em != nullptr) {
|
2019-11-07 16:52:03 +11:00
|
|
|
return &em->needs_flush_to_id;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
2022-02-18 09:50:29 -06:00
|
|
|
case ID_CU_LEGACY: {
|
2021-11-04 16:51:37 -03:00
|
|
|
if (((Curve *)id)->vfont != nullptr) {
|
2019-11-07 16:52:03 +11:00
|
|
|
EditFont *ef = ((Curve *)id)->editfont;
|
2021-11-04 16:51:37 -03:00
|
|
|
if (ef != nullptr) {
|
2019-11-07 16:52:03 +11:00
|
|
|
return &ef->needs_flush_to_id;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
EditNurb *editnurb = ((Curve *)id)->editnurb;
|
|
|
|
|
if (editnurb) {
|
|
|
|
|
return &editnurb->needs_flush_to_id;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case ID_MB: {
|
|
|
|
|
MetaBall *mb = (MetaBall *)id;
|
|
|
|
|
return &mb->needs_flush_to_id;
|
|
|
|
|
}
|
|
|
|
|
case ID_LT: {
|
|
|
|
|
EditLatt *editlatt = ((Lattice *)id)->editlatt;
|
|
|
|
|
if (editlatt) {
|
|
|
|
|
return &editlatt->needs_flush_to_id;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case ID_AR: {
|
|
|
|
|
bArmature *arm = (bArmature *)id;
|
|
|
|
|
return &arm->needs_flush_to_id;
|
|
|
|
|
}
|
Curves: fix edit mode detection
This adds missing cases to detect edit mode for Curves objects.
Unlike other object types, Curves do not have specific edit data,
rather we edit the original data directly, and rely on `Object.mode`.
For this, `BKE_object_data_is_in_editmode` had to be modified to
take a pointer to the object. This affects two places: the outliner
and the dependency graph. For the former place, the object pointer
is readily available, and we can use it. For the latter, the object
pointer is not available, however since it is used to update edit
mode pointers, and since Curves do not have such data, we can
safely pass null to the function here.
This also fixes the assertion failure that happens when closing a file
in edit mode.
Differential Revision: https://developer.blender.org/D14330
2022-04-05 19:59:20 +02:00
|
|
|
case ID_CV: {
|
|
|
|
|
/* Curves have no edit mode data. */
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
2019-11-07 16:52:03 +11:00
|
|
|
default:
|
2021-03-24 12:38:08 +11:00
|
|
|
BLI_assert_unreachable();
|
2021-11-04 16:51:37 -03:00
|
|
|
return nullptr;
|
2019-11-07 16:52:03 +11:00
|
|
|
}
|
2021-11-04 16:51:37 -03:00
|
|
|
return nullptr;
|
2019-11-07 16:52:03 +11:00
|
|
|
}
|
|
|
|
|
|
2018-04-05 18:20:27 +02:00
|
|
|
bool BKE_object_is_in_wpaint_select_vert(const Object *ob)
|
2013-07-01 20:27:03 +00:00
|
|
|
{
|
|
|
|
|
if (ob->type == OB_MESH) {
|
2021-11-04 16:51:37 -03:00
|
|
|
Mesh *me = (Mesh *)ob->data;
|
|
|
|
|
return ((ob->mode & OB_MODE_WEIGHT_PAINT) && (me->edit_mesh == nullptr) &&
|
2014-08-27 09:49:31 +10:00
|
|
|
(ME_EDIT_PAINT_SEL_MODE(me) == SCE_SELECT_VERTEX));
|
2013-07-01 20:27:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-16 16:27:55 +02:00
|
|
|
bool BKE_object_has_mode_data(const struct Object *ob, eObjectMode object_mode)
|
|
|
|
|
{
|
|
|
|
|
if (object_mode & OB_MODE_EDIT) {
|
|
|
|
|
if (BKE_object_is_in_editmode(ob)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (object_mode & OB_MODE_VERTEX_PAINT) {
|
|
|
|
|
if (ob->sculpt && (ob->sculpt->mode_type == OB_MODE_VERTEX_PAINT)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (object_mode & OB_MODE_WEIGHT_PAINT) {
|
|
|
|
|
if (ob->sculpt && (ob->sculpt->mode_type == OB_MODE_WEIGHT_PAINT)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (object_mode & OB_MODE_SCULPT) {
|
|
|
|
|
if (ob->sculpt && (ob->sculpt->mode_type == OB_MODE_SCULPT)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (object_mode & OB_MODE_POSE) {
|
2021-11-04 16:51:37 -03:00
|
|
|
if (ob->pose != nullptr) {
|
2018-04-16 16:27:55 +02:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2018-05-29 15:43:53 +02:00
|
|
|
bool BKE_object_is_mode_compat(const struct Object *ob, eObjectMode object_mode)
|
|
|
|
|
{
|
|
|
|
|
return ((ob->mode == object_mode) || (ob->mode & object_mode) != 0);
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-18 18:18:00 +01:00
|
|
|
int BKE_object_visibility(const Object *ob, const int dag_eval_mode)
|
2017-09-21 12:55:14 +02:00
|
|
|
{
|
2019-10-03 19:22:36 -03:00
|
|
|
if ((ob->base_flag & BASE_VISIBLE_DEPSGRAPH) == 0) {
|
2018-12-18 18:18:00 +01:00
|
|
|
return 0;
|
2017-12-21 13:29:14 -02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-12-18 18:18:00 +01:00
|
|
|
/* Test which components the object has. */
|
|
|
|
|
int visibility = OB_VISIBLE_SELF;
|
|
|
|
|
if (ob->particlesystem.first) {
|
|
|
|
|
visibility |= OB_VISIBLE_INSTANCES | OB_VISIBLE_PARTICLES;
|
2017-12-21 13:29:14 -02:00
|
|
|
}
|
2018-12-18 18:18:00 +01:00
|
|
|
else if (ob->transflag & OB_DUPLI) {
|
|
|
|
|
visibility |= OB_VISIBLE_INSTANCES;
|
2017-12-21 13:29:14 -02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-09-06 18:22:24 +02:00
|
|
|
if (BKE_object_has_geometry_set_instances(ob)) {
|
2020-12-02 13:25:25 +01:00
|
|
|
visibility |= OB_VISIBLE_INSTANCES;
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-18 18:18:00 +01:00
|
|
|
/* Optional hiding of self if there are particles or instancers. */
|
|
|
|
|
if (visibility & (OB_VISIBLE_PARTICLES | OB_VISIBLE_INSTANCES)) {
|
|
|
|
|
switch ((eEvaluationMode)dag_eval_mode) {
|
|
|
|
|
case DAG_EVAL_VIEWPORT:
|
|
|
|
|
if (!(ob->duplicator_visibility_flag & OB_DUPLI_FLAG_VIEWPORT)) {
|
|
|
|
|
visibility &= ~OB_VISIBLE_SELF;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case DAG_EVAL_RENDER:
|
|
|
|
|
if (!(ob->duplicator_visibility_flag & OB_DUPLI_FLAG_RENDER)) {
|
|
|
|
|
visibility &= ~OB_VISIBLE_SELF;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
2017-12-21 13:29:14 -02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-12-18 18:18:00 +01:00
|
|
|
return visibility;
|
2017-09-21 12:55:14 +02:00
|
|
|
}
|
|
|
|
|
|
2018-05-31 12:27:47 +02:00
|
|
|
bool BKE_object_exists_check(Main *bmain, const Object *obtest)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2021-11-04 16:51:37 -03:00
|
|
|
if (obtest == nullptr) {
|
2013-03-09 05:35:49 +00:00
|
|
|
return false;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2020-12-22 10:35:18 -06:00
|
|
|
LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
|
2019-04-22 09:39:35 +10:00
|
|
|
if (ob == obtest) {
|
2013-03-09 05:35:49 +00:00
|
|
|
return true;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2020-12-22 10:35:18 -06:00
|
|
|
|
2013-03-09 05:35:49 +00:00
|
|
|
return false;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* *************************************************** */
|
|
|
|
|
|
2010-12-03 17:05:21 +00:00
|
|
|
static const char *get_obdata_defname(int type)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
|
|
|
|
switch (type) {
|
2013-03-24 12:13:13 +00:00
|
|
|
case OB_MESH:
|
|
|
|
|
return DATA_("Mesh");
|
2022-02-18 09:50:29 -06:00
|
|
|
case OB_CURVES_LEGACY:
|
2013-03-24 12:13:13 +00:00
|
|
|
return DATA_("Curve");
|
|
|
|
|
case OB_SURF:
|
|
|
|
|
return DATA_("Surf");
|
|
|
|
|
case OB_FONT:
|
|
|
|
|
return DATA_("Text");
|
|
|
|
|
case OB_MBALL:
|
|
|
|
|
return DATA_("Mball");
|
|
|
|
|
case OB_CAMERA:
|
|
|
|
|
return DATA_("Camera");
|
2019-02-12 22:13:42 +01:00
|
|
|
case OB_LAMP:
|
|
|
|
|
return CTX_DATA_(BLT_I18NCONTEXT_ID_LIGHT, "Light");
|
2013-03-24 12:13:13 +00:00
|
|
|
case OB_LATTICE:
|
|
|
|
|
return DATA_("Lattice");
|
|
|
|
|
case OB_ARMATURE:
|
|
|
|
|
return DATA_("Armature");
|
|
|
|
|
case OB_SPEAKER:
|
|
|
|
|
return DATA_("Speaker");
|
Curves: Rename "Hair" types, variables, and functions to "Curves"
Based on discussions from T95355 and T94193, the plan is to use
the name "Curves" to describe the data-block container for multiple
curves. Eventually this will replace the existing "Curve" data-block.
However, it will be a while before the curve data-block can be replaced
so in order to distinguish the two curve types in the UI, "Hair Curves"
will be used, but eventually changed back to "Curves".
This patch renames "hair-related" files, functions, types, and variable
names to this convention. A deep rename is preferred to keep code
consistent and to avoid any "hair" terminology from leaking, since the
new data-block is meant for all curve types, not just hair use cases.
The downside of this naming is that the difference between "Curve"
and "Curves" has become important. That was considered during
design discussons and deemed acceptable, especially given the
non-permanent nature of the somewhat common conflict.
Some points of interest:
- All DNA compatibility is lost, just like rBf59767ff9729.
- I renamed `ID_HA` to `ID_CV` so there is no complete mismatch.
- `hair_curves` is used where necessary to distinguish from the
existing "curves" plural.
- I didn't rename any of the cycles/rendering code function names,
since that is also used by the old hair particle system.
Differential Revision: https://developer.blender.org/D14007
2022-02-07 11:55:54 -06:00
|
|
|
case OB_CURVES:
|
2022-05-05 13:01:39 +02:00
|
|
|
return DATA_("Curves");
|
2020-03-17 14:41:48 +01:00
|
|
|
case OB_POINTCLOUD:
|
|
|
|
|
return DATA_("PointCloud");
|
|
|
|
|
case OB_VOLUME:
|
|
|
|
|
return DATA_("Volume");
|
2013-03-24 12:13:13 +00:00
|
|
|
case OB_EMPTY:
|
|
|
|
|
return DATA_("Empty");
|
2018-07-31 10:22:19 +02:00
|
|
|
case OB_GPENCIL:
|
|
|
|
|
return DATA_("GPencil");
|
2020-01-17 19:14:23 +01:00
|
|
|
case OB_LIGHTPROBE:
|
|
|
|
|
return DATA_("LightProbe");
|
2012-05-06 15:15:33 +00:00
|
|
|
default:
|
2019-02-01 12:44:19 +11:00
|
|
|
CLOG_ERROR(&LOG, "Internal error, bad type: %d", type);
|
2013-03-24 12:13:13 +00:00
|
|
|
return DATA_("Empty");
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-06 11:18:14 +01:00
|
|
|
static void object_init(Object *ob, const short ob_type)
|
|
|
|
|
{
|
|
|
|
|
object_init_data(&ob->id);
|
|
|
|
|
|
|
|
|
|
ob->type = ob_type;
|
|
|
|
|
|
|
|
|
|
if (ob->type != OB_EMPTY) {
|
|
|
|
|
zero_v2(ob->ima_ofs);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ELEM(ob->type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
|
|
|
|
|
ob->trackflag = OB_NEGZ;
|
|
|
|
|
ob->upflag = OB_POSY;
|
|
|
|
|
}
|
2020-03-09 16:27:24 +01:00
|
|
|
|
|
|
|
|
if (ob->type == OB_GPENCIL) {
|
|
|
|
|
ob->dtx |= OB_USE_GPENCIL_LIGHTS;
|
|
|
|
|
}
|
2021-08-04 19:43:40 +02:00
|
|
|
|
|
|
|
|
if (ob->type == OB_LAMP) {
|
|
|
|
|
/* Lights are invisible to camera rays and are assumed to be a
|
|
|
|
|
* shadow catcher by default. */
|
|
|
|
|
ob->visibility_flag |= OB_HIDE_CAMERA | OB_SHADOW_CATCHER;
|
|
|
|
|
}
|
2020-03-06 11:18:14 +01:00
|
|
|
}
|
|
|
|
|
|
2015-05-04 12:25:33 +10:00
|
|
|
void *BKE_object_obdata_add_from_type(Main *bmain, int type, const char *name)
|
|
|
|
|
{
|
2021-11-04 16:51:37 -03:00
|
|
|
if (name == nullptr) {
|
2015-05-04 12:25:33 +10:00
|
|
|
name = get_obdata_defname(type);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-05-04 12:25:33 +10:00
|
|
|
switch (type) {
|
|
|
|
|
case OB_MESH:
|
|
|
|
|
return BKE_mesh_add(bmain, name);
|
2022-02-18 09:50:29 -06:00
|
|
|
case OB_CURVES_LEGACY:
|
|
|
|
|
return BKE_curve_add(bmain, name, OB_CURVES_LEGACY);
|
2015-05-04 12:25:33 +10:00
|
|
|
case OB_SURF:
|
|
|
|
|
return BKE_curve_add(bmain, name, OB_SURF);
|
|
|
|
|
case OB_FONT:
|
|
|
|
|
return BKE_curve_add(bmain, name, OB_FONT);
|
|
|
|
|
case OB_MBALL:
|
|
|
|
|
return BKE_mball_add(bmain, name);
|
|
|
|
|
case OB_CAMERA:
|
|
|
|
|
return BKE_camera_add(bmain, name);
|
2019-02-27 10:46:48 +11:00
|
|
|
case OB_LAMP:
|
|
|
|
|
return BKE_light_add(bmain, name);
|
2015-05-04 12:25:33 +10:00
|
|
|
case OB_LATTICE:
|
|
|
|
|
return BKE_lattice_add(bmain, name);
|
|
|
|
|
case OB_ARMATURE:
|
|
|
|
|
return BKE_armature_add(bmain, name);
|
|
|
|
|
case OB_SPEAKER:
|
|
|
|
|
return BKE_speaker_add(bmain, name);
|
2017-06-12 20:59:54 +10:00
|
|
|
case OB_LIGHTPROBE:
|
|
|
|
|
return BKE_lightprobe_add(bmain, name);
|
2018-07-31 10:22:19 +02:00
|
|
|
case OB_GPENCIL:
|
|
|
|
|
return BKE_gpencil_data_addnew(bmain, name);
|
Curves: Rename "Hair" types, variables, and functions to "Curves"
Based on discussions from T95355 and T94193, the plan is to use
the name "Curves" to describe the data-block container for multiple
curves. Eventually this will replace the existing "Curve" data-block.
However, it will be a while before the curve data-block can be replaced
so in order to distinguish the two curve types in the UI, "Hair Curves"
will be used, but eventually changed back to "Curves".
This patch renames "hair-related" files, functions, types, and variable
names to this convention. A deep rename is preferred to keep code
consistent and to avoid any "hair" terminology from leaking, since the
new data-block is meant for all curve types, not just hair use cases.
The downside of this naming is that the difference between "Curve"
and "Curves" has become important. That was considered during
design discussons and deemed acceptable, especially given the
non-permanent nature of the somewhat common conflict.
Some points of interest:
- All DNA compatibility is lost, just like rBf59767ff9729.
- I renamed `ID_HA` to `ID_CV` so there is no complete mismatch.
- `hair_curves` is used where necessary to distinguish from the
existing "curves" plural.
- I didn't rename any of the cycles/rendering code function names,
since that is also used by the old hair particle system.
Differential Revision: https://developer.blender.org/D14007
2022-02-07 11:55:54 -06:00
|
|
|
case OB_CURVES:
|
|
|
|
|
return BKE_curves_add(bmain, name);
|
2020-03-17 14:41:48 +01:00
|
|
|
case OB_POINTCLOUD:
|
2020-04-09 18:49:40 +02:00
|
|
|
return BKE_pointcloud_add_default(bmain, name);
|
2020-03-17 14:41:48 +01:00
|
|
|
case OB_VOLUME:
|
|
|
|
|
return BKE_volume_add(bmain, name);
|
2015-05-04 12:25:33 +10:00
|
|
|
case OB_EMPTY:
|
2021-11-04 16:51:37 -03:00
|
|
|
return nullptr;
|
2015-05-04 12:25:33 +10:00
|
|
|
default:
|
2019-02-01 12:44:19 +11:00
|
|
|
CLOG_ERROR(&LOG, "Internal error, bad type: %d", type);
|
2021-11-04 16:51:37 -03:00
|
|
|
return nullptr;
|
2015-05-04 12:25:33 +10:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-03 16:23:49 +10:00
|
|
|
int BKE_object_obdata_to_type(const ID *id)
|
|
|
|
|
{
|
|
|
|
|
/* Keep in sync with #OB_DATA_SUPPORT_ID macro. */
|
|
|
|
|
switch (GS(id->name)) {
|
|
|
|
|
case ID_ME:
|
|
|
|
|
return OB_MESH;
|
2022-02-18 09:50:29 -06:00
|
|
|
case ID_CU_LEGACY:
|
2020-09-03 16:23:49 +10:00
|
|
|
return BKE_curve_type_get((const Curve *)id);
|
|
|
|
|
case ID_MB:
|
|
|
|
|
return OB_MBALL;
|
|
|
|
|
case ID_LA:
|
|
|
|
|
return OB_LAMP;
|
|
|
|
|
case ID_SPK:
|
|
|
|
|
return OB_SPEAKER;
|
|
|
|
|
case ID_CA:
|
|
|
|
|
return OB_CAMERA;
|
|
|
|
|
case ID_LT:
|
|
|
|
|
return OB_LATTICE;
|
|
|
|
|
case ID_GD:
|
|
|
|
|
return OB_GPENCIL;
|
|
|
|
|
case ID_AR:
|
|
|
|
|
return OB_ARMATURE;
|
|
|
|
|
case ID_LP:
|
|
|
|
|
return OB_LIGHTPROBE;
|
Curves: Rename "Hair" types, variables, and functions to "Curves"
Based on discussions from T95355 and T94193, the plan is to use
the name "Curves" to describe the data-block container for multiple
curves. Eventually this will replace the existing "Curve" data-block.
However, it will be a while before the curve data-block can be replaced
so in order to distinguish the two curve types in the UI, "Hair Curves"
will be used, but eventually changed back to "Curves".
This patch renames "hair-related" files, functions, types, and variable
names to this convention. A deep rename is preferred to keep code
consistent and to avoid any "hair" terminology from leaking, since the
new data-block is meant for all curve types, not just hair use cases.
The downside of this naming is that the difference between "Curve"
and "Curves" has become important. That was considered during
design discussons and deemed acceptable, especially given the
non-permanent nature of the somewhat common conflict.
Some points of interest:
- All DNA compatibility is lost, just like rBf59767ff9729.
- I renamed `ID_HA` to `ID_CV` so there is no complete mismatch.
- `hair_curves` is used where necessary to distinguish from the
existing "curves" plural.
- I didn't rename any of the cycles/rendering code function names,
since that is also used by the old hair particle system.
Differential Revision: https://developer.blender.org/D14007
2022-02-07 11:55:54 -06:00
|
|
|
case ID_CV:
|
|
|
|
|
return OB_CURVES;
|
2020-09-03 16:23:49 +10:00
|
|
|
case ID_PT:
|
|
|
|
|
return OB_POINTCLOUD;
|
|
|
|
|
case ID_VO:
|
|
|
|
|
return OB_VOLUME;
|
|
|
|
|
default:
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
First step to handle missing libs/datablocks when reading a file.
Idea is, instead of ignoring completely missing linked datablocks, to
create void placeholders for them.
That way, you can work on your file, save it, and find again your missing data once
lib becomes available again. Or you can edit missing lib's path (in Outliner),
save and reload the file, and you are done.
Also, Outliner now shows broken libraries (and placeholders) with a 'broken lib' icon.
Future plans are also to be able to relocate missing libs and reload them at runtime.
Code notes:
- Placeholder ID is just a regular datablock of same type as expected linked one,
with 'default' data, and a LIB_MISSING bitflag set.
- To allow creation of such datablocks, creation of datablocks in BKE was split in two step:
+ Allocation of memory itself.
+ Setting of all internal data to default values.
See also the design task (T43351).
Reviewed by @campbellbarton, thanks a bunch!
Differential Revision: https://developer.blender.org/D1394
2015-10-20 14:44:57 +02:00
|
|
|
Object *BKE_object_add_only_object(Main *bmain, int type, const char *name)
|
|
|
|
|
{
|
2019-04-22 09:39:35 +10:00
|
|
|
if (!name) {
|
First step to handle missing libs/datablocks when reading a file.
Idea is, instead of ignoring completely missing linked datablocks, to
create void placeholders for them.
That way, you can work on your file, save it, and find again your missing data once
lib becomes available again. Or you can edit missing lib's path (in Outliner),
save and reload the file, and you are done.
Also, Outliner now shows broken libraries (and placeholders) with a 'broken lib' icon.
Future plans are also to be able to relocate missing libs and reload them at runtime.
Code notes:
- Placeholder ID is just a regular datablock of same type as expected linked one,
with 'default' data, and a LIB_MISSING bitflag set.
- To allow creation of such datablocks, creation of datablocks in BKE was split in two step:
+ Allocation of memory itself.
+ Setting of all internal data to default values.
See also the design task (T43351).
Reviewed by @campbellbarton, thanks a bunch!
Differential Revision: https://developer.blender.org/D1394
2015-10-20 14:44:57 +02:00
|
|
|
name = get_obdata_defname(type);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
First step to handle missing libs/datablocks when reading a file.
Idea is, instead of ignoring completely missing linked datablocks, to
create void placeholders for them.
That way, you can work on your file, save it, and find again your missing data once
lib becomes available again. Or you can edit missing lib's path (in Outliner),
save and reload the file, and you are done.
Also, Outliner now shows broken libraries (and placeholders) with a 'broken lib' icon.
Future plans are also to be able to relocate missing libs and reload them at runtime.
Code notes:
- Placeholder ID is just a regular datablock of same type as expected linked one,
with 'default' data, and a LIB_MISSING bitflag set.
- To allow creation of such datablocks, creation of datablocks in BKE was split in two step:
+ Allocation of memory itself.
+ Setting of all internal data to default values.
See also the design task (T43351).
Reviewed by @campbellbarton, thanks a bunch!
Differential Revision: https://developer.blender.org/D1394
2015-10-20 14:44:57 +02:00
|
|
|
|
2020-10-08 12:50:04 +02:00
|
|
|
/* We cannot use #BKE_id_new here as we need some custom initialization code. */
|
2022-03-29 15:36:02 +02:00
|
|
|
Object *ob = (Object *)BKE_libblock_alloc(bmain, ID_OB, name, bmain ? 0 : LIB_ID_CREATE_NO_MAIN);
|
First step to handle missing libs/datablocks when reading a file.
Idea is, instead of ignoring completely missing linked datablocks, to
create void placeholders for them.
That way, you can work on your file, save it, and find again your missing data once
lib becomes available again. Or you can edit missing lib's path (in Outliner),
save and reload the file, and you are done.
Also, Outliner now shows broken libraries (and placeholders) with a 'broken lib' icon.
Future plans are also to be able to relocate missing libs and reload them at runtime.
Code notes:
- Placeholder ID is just a regular datablock of same type as expected linked one,
with 'default' data, and a LIB_MISSING bitflag set.
- To allow creation of such datablocks, creation of datablocks in BKE was split in two step:
+ Allocation of memory itself.
+ Setting of all internal data to default values.
See also the design task (T43351).
Reviewed by @campbellbarton, thanks a bunch!
Differential Revision: https://developer.blender.org/D1394
2015-10-20 14:44:57 +02:00
|
|
|
|
Collections and groups unification
OVERVIEW
* In 2.7 terminology, all layers and groups are now collection datablocks.
* These collections are nestable, linkable, instanceable, overrideable, ..
which opens up new ways to set up scenes and link + override data.
* Viewport/render visibility and selectability are now a part of the collection
and shared across all view layers and linkable.
* View layers define which subset of the scene collection hierarchy is excluded
for each. For many workflows one view layer can be used, these are more of an
advanced feature now.
OUTLINER
* The outliner now has a "View Layer" display mode instead of "Collections",
which can display the collections and/or objects in the view layer.
* In this display mode, collections can be excluded with the right click menu.
These will then be greyed out and their objects will be excluded.
* To view collections not linked to any scene, the "Blender File" display mode
can be used, with the new filtering option to just see Colleciton datablocks.
* The outliner right click menus for collections and objects were reorganized.
* Drag and drop still needs to be improved. Like before, dragging the icon or
text gives different results, we'll unify this later.
LINKING AND OVERRIDES
* Collections can now be linked into the scene without creating an instance,
with the link/append operator or from the collections view in the outliner.
* Collections can get static overrides with the right click menu in the outliner,
but this is rather unreliable and not clearly communicated at the moment.
* We still need to improve the make override operator to turn collection instances
into collections with overrides directly in the scene.
PERFORMANCE
* We tried to make performance not worse than before and improve it in some
cases. The main thing that's still a bit slower is multiple scenes, we have to
change the layer syncing to only updated affected scenes.
* Collections keep a list of their parent collections for faster incremental
updates in syncing and caching.
* View layer bases are now in a object -> base hash to avoid quadratic time
lookups internally and in API functions like visible_get().
VERSIONING
* Compatibility with 2.7 files should be improved due to the new visibility
controls. Of course users may not want to set up their scenes differently
now to avoid having separate layers and groups.
* Compatibility with 2.8 is mostly there, and was tested on Eevee demo and Hero
files. There's a few things which are know to be not quite compatible, like
nested layer collections inside groups.
* The versioning code for 2.8 files is quite complicated, and isolated behind
#ifdef so it can be removed at the end of the release cycle.
KNOWN ISSUES
* The G-key group operators in the 3D viewport were left mostly as is, they
need to be modified still to fit better.
* Same for the groups panel in the object properties. This needs to be updated
still, or perhaps replaced by something better.
* Collections must all have a unique name. Less restrictive namespacing is to
be done later, we'll have to see how important this is as all objects within
the collections must also have a unique name anyway.
* Full scene copy and delete scene are exactly doing the right thing yet.
Differential Revision: https://developer.blender.org/D3383
https://code.blender.org/2018/05/collections-and-groups/
2018-04-30 15:57:22 +02:00
|
|
|
/* We increase object user count when linking to Collections. */
|
2017-11-27 14:33:31 -02:00
|
|
|
id_us_min(&ob->id);
|
|
|
|
|
|
First step to handle missing libs/datablocks when reading a file.
Idea is, instead of ignoring completely missing linked datablocks, to
create void placeholders for them.
That way, you can work on your file, save it, and find again your missing data once
lib becomes available again. Or you can edit missing lib's path (in Outliner),
save and reload the file, and you are done.
Also, Outliner now shows broken libraries (and placeholders) with a 'broken lib' icon.
Future plans are also to be able to relocate missing libs and reload them at runtime.
Code notes:
- Placeholder ID is just a regular datablock of same type as expected linked one,
with 'default' data, and a LIB_MISSING bitflag set.
- To allow creation of such datablocks, creation of datablocks in BKE was split in two step:
+ Allocation of memory itself.
+ Setting of all internal data to default values.
See also the design task (T43351).
Reviewed by @campbellbarton, thanks a bunch!
Differential Revision: https://developer.blender.org/D1394
2015-10-20 14:44:57 +02:00
|
|
|
/* default object vars */
|
2020-03-06 11:18:14 +01:00
|
|
|
object_init(ob, type);
|
2009-08-25 18:41:36 +00:00
|
|
|
|
2006-09-11 17:55:52 +00:00
|
|
|
return ob;
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-22 10:52:39 -02:00
|
|
|
static Object *object_add_common(Main *bmain, ViewLayer *view_layer, int type, const char *name)
|
2017-10-19 18:01:41 -02:00
|
|
|
{
|
2020-12-22 10:35:18 -06:00
|
|
|
Object *ob = BKE_object_add_only_object(bmain, type, name);
|
2017-10-19 18:01:41 -02:00
|
|
|
ob->data = BKE_object_obdata_add_from_type(bmain, type, name);
|
2017-11-22 10:52:39 -02:00
|
|
|
BKE_view_layer_base_deselect_all(view_layer);
|
2017-10-19 18:01:41 -02:00
|
|
|
|
2018-12-06 17:52:37 +01:00
|
|
|
DEG_id_tag_update_ex(
|
|
|
|
|
bmain, &ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
|
2017-10-19 18:01:41 -02:00
|
|
|
return ob;
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-07 14:09:50 +10:00
|
|
|
Object *BKE_object_add(Main *bmain, ViewLayer *view_layer, int type, const char *name)
|
2006-09-11 17:55:52 +00:00
|
|
|
{
|
2020-12-22 10:35:18 -06:00
|
|
|
Object *ob = object_add_common(bmain, view_layer, type, name);
|
2006-09-11 17:55:52 +00:00
|
|
|
|
2020-12-22 10:35:18 -06:00
|
|
|
LayerCollection *layer_collection = BKE_layer_collection_get_active(view_layer);
|
2022-06-01 12:44:11 +02:00
|
|
|
BKE_collection_viewlayer_object_add(bmain, view_layer, layer_collection->collection, ob);
|
2006-09-11 17:55:52 +00:00
|
|
|
|
2022-06-27 17:29:57 +10:00
|
|
|
/* NOTE: There is no way to be sure that #BKE_collection_viewlayer_object_add will actually
|
2022-06-01 12:44:11 +02:00
|
|
|
* manage to find a valid collection in given `view_layer` to add the new object to. */
|
2020-12-22 10:35:18 -06:00
|
|
|
Base *base = BKE_view_layer_base_find(view_layer, ob);
|
2022-06-01 12:44:11 +02:00
|
|
|
if (base != nullptr) {
|
|
|
|
|
BKE_view_layer_base_select_and_set_active(view_layer, base);
|
|
|
|
|
}
|
2017-10-19 18:01:41 -02:00
|
|
|
|
|
|
|
|
return ob;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Object *BKE_object_add_from(
|
2017-11-22 10:52:39 -02:00
|
|
|
Main *bmain, Scene *scene, ViewLayer *view_layer, int type, const char *name, Object *ob_src)
|
2017-10-19 18:01:41 -02:00
|
|
|
{
|
2020-12-22 10:35:18 -06:00
|
|
|
Object *ob = object_add_common(bmain, view_layer, type, name);
|
Collections and groups unification
OVERVIEW
* In 2.7 terminology, all layers and groups are now collection datablocks.
* These collections are nestable, linkable, instanceable, overrideable, ..
which opens up new ways to set up scenes and link + override data.
* Viewport/render visibility and selectability are now a part of the collection
and shared across all view layers and linkable.
* View layers define which subset of the scene collection hierarchy is excluded
for each. For many workflows one view layer can be used, these are more of an
advanced feature now.
OUTLINER
* The outliner now has a "View Layer" display mode instead of "Collections",
which can display the collections and/or objects in the view layer.
* In this display mode, collections can be excluded with the right click menu.
These will then be greyed out and their objects will be excluded.
* To view collections not linked to any scene, the "Blender File" display mode
can be used, with the new filtering option to just see Colleciton datablocks.
* The outliner right click menus for collections and objects were reorganized.
* Drag and drop still needs to be improved. Like before, dragging the icon or
text gives different results, we'll unify this later.
LINKING AND OVERRIDES
* Collections can now be linked into the scene without creating an instance,
with the link/append operator or from the collections view in the outliner.
* Collections can get static overrides with the right click menu in the outliner,
but this is rather unreliable and not clearly communicated at the moment.
* We still need to improve the make override operator to turn collection instances
into collections with overrides directly in the scene.
PERFORMANCE
* We tried to make performance not worse than before and improve it in some
cases. The main thing that's still a bit slower is multiple scenes, we have to
change the layer syncing to only updated affected scenes.
* Collections keep a list of their parent collections for faster incremental
updates in syncing and caching.
* View layer bases are now in a object -> base hash to avoid quadratic time
lookups internally and in API functions like visible_get().
VERSIONING
* Compatibility with 2.7 files should be improved due to the new visibility
controls. Of course users may not want to set up their scenes differently
now to avoid having separate layers and groups.
* Compatibility with 2.8 is mostly there, and was tested on Eevee demo and Hero
files. There's a few things which are know to be not quite compatible, like
nested layer collections inside groups.
* The versioning code for 2.8 files is quite complicated, and isolated behind
#ifdef so it can be removed at the end of the release cycle.
KNOWN ISSUES
* The G-key group operators in the 3D viewport were left mostly as is, they
need to be modified still to fit better.
* Same for the groups panel in the object properties. This needs to be updated
still, or perhaps replaced by something better.
* Collections must all have a unique name. Less restrictive namespacing is to
be done later, we'll have to see how important this is as all objects within
the collections must also have a unique name anyway.
* Full scene copy and delete scene are exactly doing the right thing yet.
Differential Revision: https://developer.blender.org/D3383
https://code.blender.org/2018/05/collections-and-groups/
2018-04-30 15:57:22 +02:00
|
|
|
BKE_collection_object_add_from(bmain, scene, ob_src, ob);
|
Render Layers and Collections (merge from render-layers)
Design Documents
----------------
* https://wiki.blender.org/index.php/Dev:2.8/Source/Layers
* https://wiki.blender.org/index.php/Dev:2.8/Source/DataDesignRevised
User Commit Log
---------------
* New Layer and Collection system to replace render layers and viewport layers.
* A layer is a set of collections of objects (and their drawing options) required for specific tasks.
* A collection is a set of objects, equivalent of the old layers in Blender. A collection can be shared across multiple layers.
* All Scenes have a master collection that all other collections are children of.
* New collection "context" tab (in Properties Editor)
* New temporary viewport "collections" panel to control per-collection
visibility
Missing User Features
---------------------
* Collection "Filter"
Option to add objects based on their names
* Collection Manager operators
The existing buttons are placeholders
* Collection Manager drawing
The editor main region is empty
* Collection Override
* Per-Collection engine settings
This will come as a separate commit, as part of the clay-engine branch
Dev Commit Log
--------------
* New DNA file (DNA_layer_types.h) with the new structs
We are replacing Base by a new extended Base while keeping it backward
compatible with some legacy settings (i.e., lay, flag_legacy).
Renamed all Base to BaseLegacy to make it clear the areas of code that
still need to be converted
Note: manual changes were required on - deg_builder_nodes.h, rna_object.c, KX_Light.cpp
* Unittesting for main syncronization requirements
- read, write, add/copy/remove objects, copy scene, collection
link/unlinking, context)
* New Editor: Collection Manager
Based on patch by Julian Eisel
This is extracted from the layer-manager branch. With the following changes:
- Renamed references of layer manager to collections manager
- I doesn't include the editors/space_collections/ draw and util files
- The drawing code itself will be implemented separately by Julian
* Base / Object:
A little note about them. Original Blender code would try to keep them
in sync through the code, juggling flags back and forth. This will now
be handled by Depsgraph, keeping Object and Bases more separated
throughout the non-rendering code.
Scene.base is being cleared in doversion, and the old viewport drawing
code was poorly converted to use the new bases while the new viewport
code doesn't get merged and replace the old one.
Python API Changes
------------------
```
- scene.layers
+ # no longer exists
- scene.objects
+ scene.scene_layers.active.objects
- scene.objects.active
+ scene.render_layers.active.objects.active
- bpy.context.scene.objects.link()
+ bpy.context.scene_collection.objects.link()
- bpy_extras.object_utils.object_data_add(context, obdata, operator=None, use_active_layer=True, name=None)
+ bpy_extras.object_utils.object_data_add(context, obdata, operator=None, name=None)
- bpy.context.object.select
+ bpy.context.object.select = True
+ bpy.context.object.select = False
+ bpy.context.object.select_get()
+ bpy.context.object.select_set(action='SELECT')
+ bpy.context.object.select_set(action='DESELECT')
-AddObjectHelper.layers
+ # no longer exists
```
2017-02-07 10:18:38 +01:00
|
|
|
|
2020-12-22 10:35:18 -06:00
|
|
|
Base *base = BKE_view_layer_base_find(view_layer, ob);
|
2018-11-08 08:15:22 +11:00
|
|
|
BKE_view_layer_base_select_and_set_active(view_layer, base);
|
2006-09-11 17:55:52 +00:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
return ob;
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-31 10:22:19 +02:00
|
|
|
Object *BKE_object_add_for_data(
|
|
|
|
|
Main *bmain, ViewLayer *view_layer, int type, const char *name, ID *data, bool do_id_user)
|
|
|
|
|
{
|
|
|
|
|
/* same as object_add_common, except we don't create new ob->data */
|
2020-12-22 10:35:18 -06:00
|
|
|
Object *ob = BKE_object_add_only_object(bmain, type, name);
|
2021-11-04 16:51:37 -03:00
|
|
|
ob->data = (void *)data;
|
2019-04-22 09:39:35 +10:00
|
|
|
if (do_id_user) {
|
2018-07-31 10:22:19 +02:00
|
|
|
id_us_plus(data);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2018-07-31 10:22:19 +02:00
|
|
|
|
|
|
|
|
BKE_view_layer_base_deselect_all(view_layer);
|
2018-12-06 17:52:37 +01:00
|
|
|
DEG_id_tag_update_ex(
|
|
|
|
|
bmain, &ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
|
2018-07-31 10:22:19 +02:00
|
|
|
|
2020-12-22 10:35:18 -06:00
|
|
|
LayerCollection *layer_collection = BKE_layer_collection_get_active(view_layer);
|
2018-07-31 10:22:19 +02:00
|
|
|
BKE_collection_object_add(bmain, layer_collection->collection, ob);
|
|
|
|
|
|
2020-12-22 10:35:18 -06:00
|
|
|
Base *base = BKE_view_layer_base_find(view_layer, ob);
|
2018-11-08 08:15:22 +11:00
|
|
|
BKE_view_layer_base_select_and_set_active(view_layer, base);
|
2018-07-31 10:22:19 +02:00
|
|
|
|
|
|
|
|
return ob;
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-19 16:02:25 +01:00
|
|
|
void BKE_object_copy_softbody(Object *ob_dst, const Object *ob_src, const int flag)
|
2005-04-16 15:06:02 +00:00
|
|
|
{
|
2018-07-03 18:20:44 +02:00
|
|
|
SoftBody *sb = ob_src->soft;
|
2021-05-18 12:53:28 +10:00
|
|
|
const bool is_orig = (flag & LIB_ID_COPY_SET_COPIED_ON_WRITE) == 0;
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2018-07-03 18:20:44 +02:00
|
|
|
ob_dst->softflag = ob_src->softflag;
|
2021-11-04 16:51:37 -03:00
|
|
|
if (sb == nullptr) {
|
|
|
|
|
ob_dst->soft = nullptr;
|
2018-07-03 18:20:44 +02:00
|
|
|
return;
|
|
|
|
|
}
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2021-11-04 16:51:37 -03:00
|
|
|
SoftBody *sbn = (SoftBody *)MEM_dupallocN(sb);
|
2012-09-27 14:37:20 +00:00
|
|
|
|
Refactor ID copying (and to some extent, ID freeing).
This will allow much finer controll over how we copy data-blocks, from
full copy in Main database, to "lighter" ones (out of Main, inside an
already allocated datablock, etc.).
This commit also transfers a llot of what was previously handled by
per-ID-type custom code to generic ID handling code in BKE_library.
Hopefully will avoid in future inconsistencies and missing bits we had
all over the codebase in the past.
It also adds missing copying handling for a few types, most notably
Scene (which where using a fully customized handling previously).
Note that the type of allocation used during copying (regular in Main,
allocated but outside of Main, or not allocated by ID handling code at
all) is stored in ID's, which allows to handle them correctly when
freeing. This needs to be taken care of with caution when doing 'weird'
unusual things with ID copying and/or allocation!
As a final note, while rather noisy, this commit will hopefully not
break too much existing branches, old 'API' has been kept for the main
part, as a wrapper around new code. Cleaning it up will happen later.
Design task : T51804
Phab Diff: D2714
2017-08-07 16:39:55 +02:00
|
|
|
if ((flag & LIB_ID_COPY_CACHES) == 0) {
|
2012-09-27 14:37:20 +00:00
|
|
|
sbn->totspring = sbn->totpoint = 0;
|
2021-11-04 16:51:37 -03:00
|
|
|
sbn->bpoint = nullptr;
|
|
|
|
|
sbn->bspring = nullptr;
|
2012-09-27 14:37:20 +00:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
sbn->totspring = sb->totspring;
|
|
|
|
|
sbn->totpoint = sb->totpoint;
|
|
|
|
|
|
|
|
|
|
if (sbn->bpoint) {
|
|
|
|
|
int i;
|
|
|
|
|
|
2021-11-04 16:51:37 -03:00
|
|
|
sbn->bpoint = (BodyPoint *)MEM_dupallocN(sbn->bpoint);
|
2012-09-27 14:37:20 +00:00
|
|
|
|
|
|
|
|
for (i = 0; i < sbn->totpoint; i++) {
|
2019-04-22 09:39:35 +10:00
|
|
|
if (sbn->bpoint[i].springs) {
|
2021-11-04 16:51:37 -03:00
|
|
|
sbn->bpoint[i].springs = (int *)MEM_dupallocN(sbn->bpoint[i].springs);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2012-09-27 14:37:20 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (sb->bspring) {
|
2021-11-04 16:51:37 -03:00
|
|
|
sbn->bspring = (struct BodySpring *)MEM_dupallocN(sb->bspring);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2012-09-27 14:37:20 +00:00
|
|
|
}
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2021-11-04 16:51:37 -03:00
|
|
|
sbn->keys = nullptr;
|
2012-05-06 15:15:33 +00:00
|
|
|
sbn->totkey = sbn->totpointkey = 0;
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2021-11-04 16:51:37 -03:00
|
|
|
sbn->scratch = nullptr;
|
Point Cache Refactoring
=======================
Caching and Baking:
- The point cache is now cleared on DAG_object_flush_update(), and not cleared for time dependency graph updates.
- There is now a Bake button instead of Protect. Also cache start and end frames were added to softbody and particles.
- The cloth autoprotect feature was removed.
- The Ctrl+B menu now also bakes cloth and particles next to softbody and fluids. Additionally there are now frree bake and free cache menu entries.
- The point cache api has been changed. There is now a PTCacheID struct for each point cache type that can be filled and then used to call the point cache functions.
- PointCache struct was added to DNA and is automatically allocated for each physics type.
- Soft body now supports Bake Editing just like cloth.
- Tried to make the systems deal consistently with time ipo's and offsets. Still not sure it all works correct, but too complicated to solve completely now.
Library Linking:
- Added some more warnings to prevent editing settings on library linked objects.
- Linked objects now read from the cache located next to the original library file, and never write to it. This restores old behavior for softbodies. For local simulation the mesh and not the object should be linked.
- Dupligroups and proxies can't create local point caches at the moment, how to implement that I'm not sure. We probably need a proxy point cache for that to work (ugh).
Physics UI:
- Renamed deflection panel to collision for consistency and reorganized the buttons. Also removed some softbody collision buttons from the softbody panel that were duplicated in this panel for cloth.
- Tweaked field panel buttons to not jump around when changing options.
- Tabbing e.g. Soft Body Collision into the Soft Body panel, it now only shows Collision to make the panel names readable.
- I tried to make enabled/disabling physics more consistent, since all three system did things different. Now the two modifier buttons to enable the modifier for the viewport and rendering are also duplicated in the physics panels. Toggling the Soft Body and Cloth buttons now both remove their modifiers.
- Fixed modifier error drawing glitch.
Particles:
- Particles are now recalculated more often than before. Previously it did partial updates based on the changes, but that doesn't work well with DAG_object_flush_update() ..
- Fixed memory leak loading keyed particle system. Now keys are not written to file anymore but always created after loading.
- Make particle threads work with autothreads.
Continue Physics:
- The timeline play now has a Continue Physics option in the playback menu, which keeps the simulations going without writing them to the cache.
- This doesn't always work that well, some changes are not immediately updated, but this can be improved later. Still it's fun to get a feel for the physics.
Todo:
- Point cache can get out of sync with and undo and changing a file without saving it.
- Change the point cache file format to store a version (so old point cache files can be either converted or at least ignored), and to do correct endian conversion.
- Menu item and/or buttons for Ctrl+B.
- A system("rm ..") was changed to remove() since the former is very slow for clearing point caches. These system() calls were already giving trouble in a bug in the tracker, but really most use of this system("") should be changed and tested.
- The Soft Body Collision and Clot Collision panel titles don't mention there's point cache settings there too, doing that makes them unreadable with the default panel setup.. but may need to make the names longer anyway.
2008-04-10 11:39:20 +00:00
|
|
|
|
2021-05-18 12:53:28 +10:00
|
|
|
if (is_orig) {
|
2021-11-04 16:51:37 -03:00
|
|
|
sbn->shared = (SoftBody_Shared *)MEM_dupallocN(sb->shared);
|
2018-07-04 11:22:15 +02:00
|
|
|
sbn->shared->pointcache = BKE_ptcache_copy_list(
|
|
|
|
|
&sbn->shared->ptcaches, &sb->shared->ptcaches, flag);
|
|
|
|
|
}
|
Point Cache Refactoring
=======================
Caching and Baking:
- The point cache is now cleared on DAG_object_flush_update(), and not cleared for time dependency graph updates.
- There is now a Bake button instead of Protect. Also cache start and end frames were added to softbody and particles.
- The cloth autoprotect feature was removed.
- The Ctrl+B menu now also bakes cloth and particles next to softbody and fluids. Additionally there are now frree bake and free cache menu entries.
- The point cache api has been changed. There is now a PTCacheID struct for each point cache type that can be filled and then used to call the point cache functions.
- PointCache struct was added to DNA and is automatically allocated for each physics type.
- Soft body now supports Bake Editing just like cloth.
- Tried to make the systems deal consistently with time ipo's and offsets. Still not sure it all works correct, but too complicated to solve completely now.
Library Linking:
- Added some more warnings to prevent editing settings on library linked objects.
- Linked objects now read from the cache located next to the original library file, and never write to it. This restores old behavior for softbodies. For local simulation the mesh and not the object should be linked.
- Dupligroups and proxies can't create local point caches at the moment, how to implement that I'm not sure. We probably need a proxy point cache for that to work (ugh).
Physics UI:
- Renamed deflection panel to collision for consistency and reorganized the buttons. Also removed some softbody collision buttons from the softbody panel that were duplicated in this panel for cloth.
- Tweaked field panel buttons to not jump around when changing options.
- Tabbing e.g. Soft Body Collision into the Soft Body panel, it now only shows Collision to make the panel names readable.
- I tried to make enabled/disabling physics more consistent, since all three system did things different. Now the two modifier buttons to enable the modifier for the viewport and rendering are also duplicated in the physics panels. Toggling the Soft Body and Cloth buttons now both remove their modifiers.
- Fixed modifier error drawing glitch.
Particles:
- Particles are now recalculated more often than before. Previously it did partial updates based on the changes, but that doesn't work well with DAG_object_flush_update() ..
- Fixed memory leak loading keyed particle system. Now keys are not written to file anymore but always created after loading.
- Make particle threads work with autothreads.
Continue Physics:
- The timeline play now has a Continue Physics option in the playback menu, which keeps the simulations going without writing them to the cache.
- This doesn't always work that well, some changes are not immediately updated, but this can be improved later. Still it's fun to get a feel for the physics.
Todo:
- Point cache can get out of sync with and undo and changing a file without saving it.
- Change the point cache file format to store a version (so old point cache files can be either converted or at least ignored), and to do correct endian conversion.
- Menu item and/or buttons for Ctrl+B.
- A system("rm ..") was changed to remove() since the former is very slow for clearing point caches. These system() calls were already giving trouble in a bug in the tracker, but really most use of this system("") should be changed and tested.
- The Soft Body Collision and Clot Collision panel titles don't mention there's point cache settings there too, doing that makes them unreadable with the default panel setup.. but may need to make the names longer anyway.
2008-04-10 11:39:20 +00:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (sb->effector_weights) {
|
2021-11-04 16:51:37 -03:00
|
|
|
sbn->effector_weights = (EffectorWeights *)MEM_dupallocN(sb->effector_weights);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
Unified effector functionality for particles, cloth and softbody
* Unified scene wide gravity (currently in scene buttons)
instead of each simulation having it's own gravity.
* Weight parameters for all effectors and an effector group
setting.
* Every effector can use noise.
* Most effectors have "shapes" point, plane, surface, every point.
- "Point" is most like the old effectors and uses the
effector location as the effector point.
- "Plane" uses the closest point on effectors local xy-plane
as the effector point.
- "Surface" uses the closest point on an effector object's
surface as the effector point.
- "Every Point" uses every point in a mesh effector object
as an effector point.
- The falloff is calculated from this point, so for example
with "surface" shape and "use only negative z axis" it's
possible to apply force only "inside" the effector object.
* Spherical effector is now renamed as "force" as it's no longer
just spherical.
* New effector parameter "flow", which makes the effector act as
surrounding air velocity, so the resulting force is
proportional to the velocity difference of the point and "air
velocity". For example a wind field with flow=1.0 results in
proper non-accelerating wind.
* New effector fields "turbulence", which creates nice random
flow paths, and "drag", which slows the points down.
* Much improved vortex field.
* Effectors can now effect particle rotation as well as location.
* Use full, or only positive/negative z-axis to apply force
(note. the z-axis is the surface normal in the case of
effector shape "surface")
* New "force field" submenu in add menu, which adds an empty
with the chosen effector (curve object for corve guides).
* Other dynamics should be quite easy to add to the effector
system too if wanted.
* "Unified" doesn't mean that force fields give the exact same results for
particles, softbody & cloth, since their final effect depends on many external
factors, like for example the surface area of the effected faces.
Code changes
* Subversion bump for correct handling of global gravity.
* Separate ui py file for common dynamics stuff.
* Particle settings updating is flushed with it's id through
DAG_id_flush_update(..).
Known issues
* Curve guides don't yet have all ui buttons in place, but they
should work none the less.
* Hair dynamics don't yet respect force fields.
Other changes
* Particle emission defaults now to frames 1-200 with life of 50
frames to fill the whole default timeline.
* Many particles drawing related crashes fixed.
* Sometimes particles didn't update on first frame properly.
* Hair with object/group visualization didn't work properly.
* Memory leaks with PointCacheID lists (Genscher, remember to
free pidlists after use :).
2009-09-30 22:10:14 +00:00
|
|
|
|
2018-07-03 18:20:44 +02:00
|
|
|
ob_dst->soft = sbn;
|
2005-04-16 15:06:02 +00:00
|
|
|
}
|
2004-10-14 08:52:12 +00:00
|
|
|
|
Refactor ID copying (and to some extent, ID freeing).
This will allow much finer controll over how we copy data-blocks, from
full copy in Main database, to "lighter" ones (out of Main, inside an
already allocated datablock, etc.).
This commit also transfers a llot of what was previously handled by
per-ID-type custom code to generic ID handling code in BKE_library.
Hopefully will avoid in future inconsistencies and missing bits we had
all over the codebase in the past.
It also adds missing copying handling for a few types, most notably
Scene (which where using a fully customized handling previously).
Note that the type of allocation used during copying (regular in Main,
allocated but outside of Main, or not allocated by ID handling code at
all) is stored in ID's, which allows to handle them correctly when
freeing. This needs to be taken care of with caution when doing 'weird'
unusual things with ID copying and/or allocation!
As a final note, while rather noisy, this commit will hopefully not
break too much existing branches, old 'API' has been kept for the main
part, as a wrapper around new code. Cleaning it up will happen later.
Design task : T51804
Phab Diff: D2714
2017-08-07 16:39:55 +02:00
|
|
|
ParticleSystem *BKE_object_copy_particlesystem(ParticleSystem *psys, const int flag)
|
Particles
=========
Merge of the famous particle patch by Janne Karhu, a full rewrite
of the Blender particle system. This includes:
- Emitter, Hair and Reactor particle types.
- Newtonian, Keyed and Boids physics.
- Various particle visualisation and rendering types.
- Vertex group and texture control for various properties.
- Interpolated child particles from parents.
- Hair editing with combing, growing, cutting, .. .
- Explode modifier.
- Harmonic, Magnetic fields, and multiple falloff types.
.. and lots of other things, some more info is here:
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite_Doc
The new particle system cannot be backwards compatible. Old particle
systems are being converted to the new system, but will require
tweaking to get them looking the same as before.
Point Cache
===========
The new system to replace manual baking, based on automatic caching
on disk. This is currently used by softbodies and the particle system.
See the Cache API section on:
http://wiki.blender.org/index.php/BlenderDev/PhysicsSprint
Documentation
=============
These new features still need good docs for the release logs, help
for this is appreciated.
2007-11-26 22:09:57 +00:00
|
|
|
{
|
2021-11-04 16:51:37 -03:00
|
|
|
ParticleSystem *psysn = (ParticleSystem *)MEM_dupallocN(psys);
|
Particles
=========
Merge of the famous particle patch by Janne Karhu, a full rewrite
of the Blender particle system. This includes:
- Emitter, Hair and Reactor particle types.
- Newtonian, Keyed and Boids physics.
- Various particle visualisation and rendering types.
- Vertex group and texture control for various properties.
- Interpolated child particles from parents.
- Hair editing with combing, growing, cutting, .. .
- Explode modifier.
- Harmonic, Magnetic fields, and multiple falloff types.
.. and lots of other things, some more info is here:
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite_Doc
The new particle system cannot be backwards compatible. Old particle
systems are being converted to the new system, but will require
tweaking to get them looking the same as before.
Point Cache
===========
The new system to replace manual baking, based on automatic caching
on disk. This is currently used by softbodies and the particle system.
See the Cache API section on:
http://wiki.blender.org/index.php/BlenderDev/PhysicsSprint
Documentation
=============
These new features still need good docs for the release logs, help
for this is appreciated.
2007-11-26 22:09:57 +00:00
|
|
|
|
2018-06-19 11:46:39 +02:00
|
|
|
psys_copy_particles(psysn, psys);
|
2007-12-01 20:08:31 +00:00
|
|
|
|
2012-02-23 02:17:50 +00:00
|
|
|
if (psys->clmd) {
|
2020-05-08 10:14:02 +02:00
|
|
|
psysn->clmd = (ClothModifierData *)BKE_modifier_new(eModifierType_Cloth);
|
|
|
|
|
BKE_modifier_copydata_ex((ModifierData *)psys->clmd, (ModifierData *)psysn->clmd, flag);
|
2021-11-04 16:51:37 -03:00
|
|
|
psys->hair_in_mesh = psys->hair_out_mesh = nullptr;
|
2008-02-17 12:46:09 +00:00
|
|
|
}
|
2009-07-12 23:38:47 +00:00
|
|
|
|
2009-09-04 23:06:15 +00:00
|
|
|
BLI_duplicatelist(&psysn->targets, &psys->targets);
|
2010-05-06 21:31:16 +00:00
|
|
|
|
2021-11-04 16:51:37 -03:00
|
|
|
psysn->pathcache = nullptr;
|
|
|
|
|
psysn->childcache = nullptr;
|
|
|
|
|
psysn->edit = nullptr;
|
|
|
|
|
psysn->pdd = nullptr;
|
|
|
|
|
psysn->effectors = nullptr;
|
|
|
|
|
psysn->tree = nullptr;
|
|
|
|
|
psysn->bvhtree = nullptr;
|
|
|
|
|
psysn->batch_cache = nullptr;
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2014-02-08 06:07:10 +11:00
|
|
|
BLI_listbase_clear(&psysn->pathcachebufs);
|
|
|
|
|
BLI_listbase_clear(&psysn->childcachebufs);
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2021-05-25 19:10:34 +02:00
|
|
|
if (flag & LIB_ID_COPY_SET_COPIED_ON_WRITE) {
|
2020-12-14 12:48:16 +01:00
|
|
|
/* XXX Disabled, fails when evaluating depsgraph after copying ID with no main for preview
|
|
|
|
|
* creation. */
|
|
|
|
|
// BLI_assert((psys->flag & PSYS_SHARED_CACHES) == 0);
|
2018-11-12 16:24:53 +01:00
|
|
|
psysn->flag |= PSYS_SHARED_CACHES;
|
2021-11-04 16:51:37 -03:00
|
|
|
BLI_assert(psysn->pointcache != nullptr);
|
2018-11-12 16:24:53 +01:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
psysn->pointcache = BKE_ptcache_copy_list(&psysn->ptcaches, &psys->ptcaches, flag);
|
|
|
|
|
}
|
Particles
=========
Merge of the famous particle patch by Janne Karhu, a full rewrite
of the Blender particle system. This includes:
- Emitter, Hair and Reactor particle types.
- Newtonian, Keyed and Boids physics.
- Various particle visualisation and rendering types.
- Vertex group and texture control for various properties.
- Interpolated child particles from parents.
- Hair editing with combing, growing, cutting, .. .
- Explode modifier.
- Harmonic, Magnetic fields, and multiple falloff types.
.. and lots of other things, some more info is here:
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite_Doc
The new particle system cannot be backwards compatible. Old particle
systems are being converted to the new system, but will require
tweaking to get them looking the same as before.
Point Cache
===========
The new system to replace manual baking, based on automatic caching
on disk. This is currently used by softbodies and the particle system.
See the Cache API section on:
http://wiki.blender.org/index.php/BlenderDev/PhysicsSprint
Documentation
=============
These new features still need good docs for the release logs, help
for this is appreciated.
2007-11-26 22:09:57 +00:00
|
|
|
|
2021-10-22 10:28:56 +11:00
|
|
|
/* XXX(@campbellbarton): from reading existing code this seems correct but intended usage of
|
|
|
|
|
* point-cache should /w cloth should be added in 'ParticleSystem'. */
|
2012-02-23 02:17:50 +00:00
|
|
|
if (psysn->clmd) {
|
2012-05-06 15:15:33 +00:00
|
|
|
psysn->clmd->point_cache = psysn->pointcache;
|
2010-02-04 16:54:25 +00:00
|
|
|
}
|
|
|
|
|
|
Refactor ID copying (and to some extent, ID freeing).
This will allow much finer controll over how we copy data-blocks, from
full copy in Main database, to "lighter" ones (out of Main, inside an
already allocated datablock, etc.).
This commit also transfers a llot of what was previously handled by
per-ID-type custom code to generic ID handling code in BKE_library.
Hopefully will avoid in future inconsistencies and missing bits we had
all over the codebase in the past.
It also adds missing copying handling for a few types, most notably
Scene (which where using a fully customized handling previously).
Note that the type of allocation used during copying (regular in Main,
allocated but outside of Main, or not allocated by ID handling code at
all) is stored in ID's, which allows to handle them correctly when
freeing. This needs to be taken care of with caution when doing 'weird'
unusual things with ID copying and/or allocation!
As a final note, while rather noisy, this commit will hopefully not
break too much existing branches, old 'API' has been kept for the main
part, as a wrapper around new code. Cleaning it up will happen later.
Design task : T51804
Phab Diff: D2714
2017-08-07 16:39:55 +02:00
|
|
|
if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
|
|
|
|
|
id_us_plus((ID *)psysn->part);
|
|
|
|
|
}
|
Particles
=========
Merge of the famous particle patch by Janne Karhu, a full rewrite
of the Blender particle system. This includes:
- Emitter, Hair and Reactor particle types.
- Newtonian, Keyed and Boids physics.
- Various particle visualisation and rendering types.
- Vertex group and texture control for various properties.
- Interpolated child particles from parents.
- Hair editing with combing, growing, cutting, .. .
- Explode modifier.
- Harmonic, Magnetic fields, and multiple falloff types.
.. and lots of other things, some more info is here:
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite_Doc
The new particle system cannot be backwards compatible. Old particle
systems are being converted to the new system, but will require
tweaking to get them looking the same as before.
Point Cache
===========
The new system to replace manual baking, based on automatic caching
on disk. This is currently used by softbodies and the particle system.
See the Cache API section on:
http://wiki.blender.org/index.php/BlenderDev/PhysicsSprint
Documentation
=============
These new features still need good docs for the release logs, help
for this is appreciated.
2007-11-26 22:09:57 +00:00
|
|
|
|
|
|
|
|
return psysn;
|
|
|
|
|
}
|
|
|
|
|
|
Refactor ID copying (and to some extent, ID freeing).
This will allow much finer controll over how we copy data-blocks, from
full copy in Main database, to "lighter" ones (out of Main, inside an
already allocated datablock, etc.).
This commit also transfers a llot of what was previously handled by
per-ID-type custom code to generic ID handling code in BKE_library.
Hopefully will avoid in future inconsistencies and missing bits we had
all over the codebase in the past.
It also adds missing copying handling for a few types, most notably
Scene (which where using a fully customized handling previously).
Note that the type of allocation used during copying (regular in Main,
allocated but outside of Main, or not allocated by ID handling code at
all) is stored in ID's, which allows to handle them correctly when
freeing. This needs to be taken care of with caution when doing 'weird'
unusual things with ID copying and/or allocation!
As a final note, while rather noisy, this commit will hopefully not
break too much existing branches, old 'API' has been kept for the main
part, as a wrapper around new code. Cleaning it up will happen later.
Design task : T51804
Phab Diff: D2714
2017-08-07 16:39:55 +02:00
|
|
|
void BKE_object_copy_particlesystems(Object *ob_dst, const Object *ob_src, const int flag)
|
2008-02-27 17:04:58 +00:00
|
|
|
{
|
2015-06-02 20:21:45 +10:00
|
|
|
if (ob_dst->type != OB_MESH) {
|
2012-03-12 14:35:07 +00:00
|
|
|
/* currently only mesh objects can have soft body */
|
|
|
|
|
return;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-06-02 20:21:45 +10:00
|
|
|
BLI_listbase_clear(&ob_dst->particlesystem);
|
2020-12-22 10:35:18 -06:00
|
|
|
LISTBASE_FOREACH (ParticleSystem *, psys, &ob_src->particlesystem) {
|
|
|
|
|
ParticleSystem *npsys = BKE_object_copy_particlesystem(psys, flag);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-06-02 20:21:45 +10:00
|
|
|
BLI_addtail(&ob_dst->particlesystem, npsys);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-02-27 17:04:58 +00:00
|
|
|
/* need to update particle modifiers too */
|
2020-12-22 10:35:18 -06:00
|
|
|
LISTBASE_FOREACH (ModifierData *, md, &ob_dst->modifiers) {
|
2012-05-06 15:15:33 +00:00
|
|
|
if (md->type == eModifierType_ParticleSystem) {
|
|
|
|
|
ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md;
|
2019-04-22 09:39:35 +10:00
|
|
|
if (psmd->psys == psys) {
|
2012-05-06 15:15:33 +00:00
|
|
|
psmd->psys = npsys;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2008-02-27 17:04:58 +00:00
|
|
|
}
|
2012-05-06 15:15:33 +00:00
|
|
|
else if (md->type == eModifierType_DynamicPaint) {
|
|
|
|
|
DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)md;
|
2011-11-15 13:45:24 +00:00
|
|
|
if (pmd->brush) {
|
2012-05-06 15:15:33 +00:00
|
|
|
if (pmd->brush->psys == psys) {
|
|
|
|
|
pmd->brush->psys = npsys;
|
2011-11-15 13:45:24 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-12-16 15:50:14 +01:00
|
|
|
else if (md->type == eModifierType_Fluid) {
|
2020-07-03 11:51:15 +02:00
|
|
|
FluidModifierData *fmd = (FluidModifierData *)md;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-07-03 11:51:15 +02:00
|
|
|
if (fmd->type == MOD_FLUID_TYPE_FLOW) {
|
|
|
|
|
if (fmd->flow) {
|
|
|
|
|
if (fmd->flow->psys == psys) {
|
|
|
|
|
fmd->flow->psys = npsys;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2011-11-15 13:45:24 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2008-02-27 17:04:58 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
Refactor ID copying (and to some extent, ID freeing).
This will allow much finer controll over how we copy data-blocks, from
full copy in Main database, to "lighter" ones (out of Main, inside an
already allocated datablock, etc.).
This commit also transfers a llot of what was previously handled by
per-ID-type custom code to generic ID handling code in BKE_library.
Hopefully will avoid in future inconsistencies and missing bits we had
all over the codebase in the past.
It also adds missing copying handling for a few types, most notably
Scene (which where using a fully customized handling previously).
Note that the type of allocation used during copying (regular in Main,
allocated but outside of Main, or not allocated by ID handling code at
all) is stored in ID's, which allows to handle them correctly when
freeing. This needs to be taken care of with caution when doing 'weird'
unusual things with ID copying and/or allocation!
As a final note, while rather noisy, this commit will hopefully not
break too much existing branches, old 'API' has been kept for the main
part, as a wrapper around new code. Cleaning it up will happen later.
Design task : T51804
Phab Diff: D2714
2017-08-07 16:39:55 +02:00
|
|
|
static void copy_object_pose(Object *obn, const Object *ob, const int flag)
|
2006-11-11 16:45:17 +00:00
|
|
|
{
|
2021-07-03 23:08:40 +10:00
|
|
|
/* NOTE: need to clear obn->pose pointer first,
|
2019-01-08 10:28:20 +11:00
|
|
|
* so that BKE_pose_copy_data works (otherwise there's a crash) */
|
2021-11-04 16:51:37 -03:00
|
|
|
obn->pose = nullptr;
|
Refactor ID copying (and to some extent, ID freeing).
This will allow much finer controll over how we copy data-blocks, from
full copy in Main database, to "lighter" ones (out of Main, inside an
already allocated datablock, etc.).
This commit also transfers a llot of what was previously handled by
per-ID-type custom code to generic ID handling code in BKE_library.
Hopefully will avoid in future inconsistencies and missing bits we had
all over the codebase in the past.
It also adds missing copying handling for a few types, most notably
Scene (which where using a fully customized handling previously).
Note that the type of allocation used during copying (regular in Main,
allocated but outside of Main, or not allocated by ID handling code at
all) is stored in ID's, which allows to handle them correctly when
freeing. This needs to be taken care of with caution when doing 'weird'
unusual things with ID copying and/or allocation!
As a final note, while rather noisy, this commit will hopefully not
break too much existing branches, old 'API' has been kept for the main
part, as a wrapper around new code. Cleaning it up will happen later.
Design task : T51804
Phab Diff: D2714
2017-08-07 16:39:55 +02:00
|
|
|
BKE_pose_copy_data_ex(&obn->pose, ob->pose, flag, true); /* true = copy constraints */
|
2006-11-11 16:45:17 +00:00
|
|
|
|
2020-12-22 10:35:18 -06:00
|
|
|
LISTBASE_FOREACH (bPoseChannel *, chan, &obn->pose->chanbase) {
|
2012-05-06 15:15:33 +00:00
|
|
|
chan->flag &= ~(POSE_LOC | POSE_ROT | POSE_SIZE);
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2019-04-27 12:07:07 +10:00
|
|
|
/* XXX Remapping object pointing onto itself should be handled by generic
|
|
|
|
|
* BKE_library_remap stuff, but...
|
Refactor ID copying (and to some extent, ID freeing).
This will allow much finer controll over how we copy data-blocks, from
full copy in Main database, to "lighter" ones (out of Main, inside an
already allocated datablock, etc.).
This commit also transfers a llot of what was previously handled by
per-ID-type custom code to generic ID handling code in BKE_library.
Hopefully will avoid in future inconsistencies and missing bits we had
all over the codebase in the past.
It also adds missing copying handling for a few types, most notably
Scene (which where using a fully customized handling previously).
Note that the type of allocation used during copying (regular in Main,
allocated but outside of Main, or not allocated by ID handling code at
all) is stored in ID's, which allows to handle them correctly when
freeing. This needs to be taken care of with caution when doing 'weird'
unusual things with ID copying and/or allocation!
As a final note, while rather noisy, this commit will hopefully not
break too much existing branches, old 'API' has been kept for the main
part, as a wrapper around new code. Cleaning it up will happen later.
Design task : T51804
Phab Diff: D2714
2017-08-07 16:39:55 +02:00
|
|
|
* the flush_constraint_targets callback am not sure about, so will delay that for now. */
|
2020-12-22 10:35:18 -06:00
|
|
|
LISTBASE_FOREACH (bConstraint *, con, &chan->constraints) {
|
2021-11-04 16:51:37 -03:00
|
|
|
ListBase targets = {nullptr, nullptr};
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2020-11-23 23:42:05 +03:00
|
|
|
if (BKE_constraint_targets_get(con, &targets)) {
|
2021-11-04 16:51:37 -03:00
|
|
|
LISTBASE_FOREACH (bConstraintTarget *, ct, &targets) {
|
2019-04-22 09:39:35 +10:00
|
|
|
if (ct->tar == ob) {
|
== Constraints System - Recode 2 ==
Once again, I've recoded the constraints system. This time, the goals were:
* To make it more future-proof by 'modernising' the coding style. The long functions filled with switch statements, have given way to function-pointers with smaller functions for specific purposes.
* To make it support constraints which use multiple targets more readily that it did. In the past, it was assumed that constraints could only have at most one target.
As a result, a lot of code has been shuffled around, and modified. Also, the subversion number has been bumped up.
Known issues:
* PyConstraints, which were the main motivation for supporting multiple-targets, are currently broken. There are some bimport() error that keeps causing problems. I've also temporarily removed the doDriver support, although it may return in another form soon.
* Constraints BPy-API is currently has a few features which currently don't work yet
* Outliner currently only displays the names of the constraints instead of the fancy subtarget/target/constraint-name display it used to do. What gets displayed here needs further investigation, as the old way was certainly not that great (and is not compatible with the new system too)
2007-10-21 23:00:29 +00:00
|
|
|
ct->tar = obn;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
== Constraints System - Recode 2 ==
Once again, I've recoded the constraints system. This time, the goals were:
* To make it more future-proof by 'modernising' the coding style. The long functions filled with switch statements, have given way to function-pointers with smaller functions for specific purposes.
* To make it support constraints which use multiple targets more readily that it did. In the past, it was assumed that constraints could only have at most one target.
As a result, a lot of code has been shuffled around, and modified. Also, the subversion number has been bumped up.
Known issues:
* PyConstraints, which were the main motivation for supporting multiple-targets, are currently broken. There are some bimport() error that keeps causing problems. I've also temporarily removed the doDriver support, although it may return in another form soon.
* Constraints BPy-API is currently has a few features which currently don't work yet
* Outliner currently only displays the names of the constraints instead of the fancy subtarget/target/constraint-name display it used to do. What gets displayed here needs further investigation, as the old way was certainly not that great (and is not compatible with the new system too)
2007-10-21 23:00:29 +00:00
|
|
|
}
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2020-11-23 23:42:05 +03:00
|
|
|
BKE_constraint_targets_flush(con, &targets, false);
|
== Constraints System - Recode 2 ==
Once again, I've recoded the constraints system. This time, the goals were:
* To make it more future-proof by 'modernising' the coding style. The long functions filled with switch statements, have given way to function-pointers with smaller functions for specific purposes.
* To make it support constraints which use multiple targets more readily that it did. In the past, it was assumed that constraints could only have at most one target.
As a result, a lot of code has been shuffled around, and modified. Also, the subversion number has been bumped up.
Known issues:
* PyConstraints, which were the main motivation for supporting multiple-targets, are currently broken. There are some bimport() error that keeps causing problems. I've also temporarily removed the doDriver support, although it may return in another form soon.
* Constraints BPy-API is currently has a few features which currently don't work yet
* Outliner currently only displays the names of the constraints instead of the fancy subtarget/target/constraint-name display it used to do. What gets displayed here needs further investigation, as the old way was certainly not that great (and is not compatible with the new system too)
2007-10-21 23:00:29 +00:00
|
|
|
}
|
2006-11-11 16:45:17 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-14 14:27:38 +02:00
|
|
|
bool BKE_object_pose_context_check(const Object *ob)
|
2011-09-14 01:48:55 +00:00
|
|
|
{
|
2012-09-23 18:50:56 +00:00
|
|
|
if ((ob) && (ob->type == OB_ARMATURE) && (ob->pose) && (ob->mode & OB_MODE_POSE)) {
|
2014-12-01 17:11:18 +01:00
|
|
|
return true;
|
2011-09-14 01:48:55 +00:00
|
|
|
}
|
2020-08-07 12:30:43 +02:00
|
|
|
|
|
|
|
|
return false;
|
2011-09-14 01:48:55 +00:00
|
|
|
}
|
|
|
|
|
|
2012-05-05 14:03:12 +00:00
|
|
|
Object *BKE_object_pose_armature_get(Object *ob)
|
2011-09-14 01:48:55 +00:00
|
|
|
{
|
2021-11-04 16:51:37 -03:00
|
|
|
if (ob == nullptr) {
|
|
|
|
|
return nullptr;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2011-09-14 01:48:55 +00:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (BKE_object_pose_context_check(ob)) {
|
2011-09-14 01:48:55 +00:00
|
|
|
return ob;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2011-09-14 01:48:55 +00:00
|
|
|
|
2020-05-08 10:14:02 +02:00
|
|
|
ob = BKE_modifiers_is_deformed_by_armature(ob);
|
2011-09-14 01:48:55 +00:00
|
|
|
|
2018-02-09 02:31:09 +11:00
|
|
|
/* Only use selected check when non-active. */
|
2019-04-22 09:39:35 +10:00
|
|
|
if (BKE_object_pose_context_check(ob)) {
|
2011-09-14 01:48:55 +00:00
|
|
|
return ob;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2011-09-14 01:48:55 +00:00
|
|
|
|
2021-11-04 16:51:37 -03:00
|
|
|
return nullptr;
|
2011-09-14 01:48:55 +00:00
|
|
|
}
|
|
|
|
|
|
2018-11-23 14:41:38 -02:00
|
|
|
Object *BKE_object_pose_armature_get_visible(Object *ob, ViewLayer *view_layer, View3D *v3d)
|
2018-02-09 02:31:09 +11:00
|
|
|
{
|
|
|
|
|
Object *ob_armature = BKE_object_pose_armature_get(ob);
|
|
|
|
|
if (ob_armature) {
|
|
|
|
|
Base *base = BKE_view_layer_base_find(view_layer, ob_armature);
|
|
|
|
|
if (base) {
|
2018-11-23 14:41:38 -02:00
|
|
|
if (BASE_VISIBLE(v3d, base)) {
|
2018-02-09 02:31:09 +11:00
|
|
|
return ob_armature;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-11-04 16:51:37 -03:00
|
|
|
return nullptr;
|
2018-02-09 02:31:09 +11:00
|
|
|
}
|
2018-04-17 10:13:32 +02:00
|
|
|
|
2018-11-25 09:50:34 -02:00
|
|
|
Object **BKE_object_pose_array_get_ex(ViewLayer *view_layer,
|
|
|
|
|
View3D *v3d,
|
|
|
|
|
uint *r_objects_len,
|
|
|
|
|
bool unique)
|
2018-04-17 10:13:32 +02:00
|
|
|
{
|
|
|
|
|
Object *ob_active = OBACT(view_layer);
|
|
|
|
|
Object *ob_pose = BKE_object_pose_armature_get(ob_active);
|
2021-11-04 16:51:37 -03:00
|
|
|
Object **objects = nullptr;
|
2018-04-17 10:13:32 +02:00
|
|
|
if (ob_pose == ob_active) {
|
2021-11-08 12:40:08 -03:00
|
|
|
ObjectsInModeParams ob_params{};
|
2021-11-04 16:51:37 -03:00
|
|
|
ob_params.object_mode = OB_MODE_POSE;
|
|
|
|
|
ob_params.no_dup_data = unique;
|
|
|
|
|
|
|
|
|
|
objects = BKE_view_layer_array_from_objects_in_mode_params(
|
|
|
|
|
view_layer, v3d, r_objects_len, &ob_params);
|
|
|
|
|
}
|
|
|
|
|
else if (ob_pose != nullptr) {
|
2018-04-17 10:13:32 +02:00
|
|
|
*r_objects_len = 1;
|
2021-11-04 16:51:37 -03:00
|
|
|
objects = (Object **)MEM_mallocN(sizeof(*objects), __func__);
|
2018-04-17 10:13:32 +02:00
|
|
|
objects[0] = ob_pose;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
*r_objects_len = 0;
|
2021-11-04 16:51:37 -03:00
|
|
|
objects = (Object **)MEM_mallocN(0, __func__);
|
2018-04-17 10:13:32 +02:00
|
|
|
}
|
|
|
|
|
return objects;
|
|
|
|
|
}
|
2018-11-25 09:50:34 -02:00
|
|
|
Object **BKE_object_pose_array_get_unique(ViewLayer *view_layer, View3D *v3d, uint *r_objects_len)
|
2018-04-17 10:13:32 +02:00
|
|
|
{
|
2018-11-25 09:50:34 -02:00
|
|
|
return BKE_object_pose_array_get_ex(view_layer, v3d, r_objects_len, true);
|
2018-04-17 10:13:32 +02:00
|
|
|
}
|
2018-11-25 09:50:34 -02:00
|
|
|
Object **BKE_object_pose_array_get(ViewLayer *view_layer, View3D *v3d, uint *r_objects_len)
|
2018-04-17 10:13:32 +02:00
|
|
|
{
|
2018-11-25 09:50:34 -02:00
|
|
|
return BKE_object_pose_array_get_ex(view_layer, v3d, r_objects_len, false);
|
2018-04-17 10:13:32 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-11-25 09:50:34 -02:00
|
|
|
Base **BKE_object_pose_base_array_get_ex(ViewLayer *view_layer,
|
|
|
|
|
View3D *v3d,
|
|
|
|
|
uint *r_bases_len,
|
|
|
|
|
bool unique)
|
2018-04-17 11:21:27 +02:00
|
|
|
{
|
|
|
|
|
Base *base_active = BASACT(view_layer);
|
2021-11-04 16:51:37 -03:00
|
|
|
Object *ob_pose = base_active ? BKE_object_pose_armature_get(base_active->object) : nullptr;
|
|
|
|
|
Base *base_pose = nullptr;
|
|
|
|
|
Base **bases = nullptr;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-04-17 11:21:27 +02:00
|
|
|
if (base_active) {
|
|
|
|
|
if (ob_pose == base_active->object) {
|
|
|
|
|
base_pose = base_active;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
base_pose = BKE_view_layer_base_find(view_layer, ob_pose);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
|
2018-04-17 11:21:27 +02:00
|
|
|
if (base_active && (base_pose == base_active)) {
|
2021-11-08 12:40:08 -03:00
|
|
|
ObjectsInModeParams ob_params{};
|
2021-11-04 16:51:37 -03:00
|
|
|
ob_params.object_mode = OB_MODE_POSE;
|
|
|
|
|
ob_params.no_dup_data = unique;
|
|
|
|
|
|
|
|
|
|
bases = BKE_view_layer_array_from_bases_in_mode_params(
|
|
|
|
|
view_layer, v3d, r_bases_len, &ob_params);
|
|
|
|
|
}
|
|
|
|
|
else if (base_pose != nullptr) {
|
2018-04-17 11:21:27 +02:00
|
|
|
*r_bases_len = 1;
|
2021-11-04 16:51:37 -03:00
|
|
|
bases = (Base **)MEM_mallocN(sizeof(*bases), __func__);
|
2018-04-17 11:21:27 +02:00
|
|
|
bases[0] = base_pose;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
*r_bases_len = 0;
|
2021-11-04 16:51:37 -03:00
|
|
|
bases = (Base **)MEM_mallocN(0, __func__);
|
2018-04-17 11:21:27 +02:00
|
|
|
}
|
|
|
|
|
return bases;
|
|
|
|
|
}
|
2018-11-25 09:50:34 -02:00
|
|
|
Base **BKE_object_pose_base_array_get_unique(ViewLayer *view_layer, View3D *v3d, uint *r_bases_len)
|
2018-04-17 11:21:27 +02:00
|
|
|
{
|
2018-11-25 09:50:34 -02:00
|
|
|
return BKE_object_pose_base_array_get_ex(view_layer, v3d, r_bases_len, true);
|
2018-04-17 11:21:27 +02:00
|
|
|
}
|
2018-11-25 09:50:34 -02:00
|
|
|
Base **BKE_object_pose_base_array_get(ViewLayer *view_layer, View3D *v3d, uint *r_bases_len)
|
2018-04-17 11:21:27 +02:00
|
|
|
{
|
2018-11-25 09:50:34 -02:00
|
|
|
return BKE_object_pose_base_array_get_ex(view_layer, v3d, r_bases_len, false);
|
2018-04-17 11:21:27 +02:00
|
|
|
}
|
|
|
|
|
|
2012-05-22 15:29:57 +00:00
|
|
|
void BKE_object_transform_copy(Object *ob_tar, const Object *ob_src)
|
2010-10-12 21:47:13 +00:00
|
|
|
{
|
|
|
|
|
copy_v3_v3(ob_tar->loc, ob_src->loc);
|
|
|
|
|
copy_v3_v3(ob_tar->rot, ob_src->rot);
|
2020-01-07 12:42:37 -03:00
|
|
|
copy_v4_v4(ob_tar->quat, ob_src->quat);
|
2010-10-12 21:47:13 +00:00
|
|
|
copy_v3_v3(ob_tar->rotAxis, ob_src->rotAxis);
|
2012-05-06 15:15:33 +00:00
|
|
|
ob_tar->rotAngle = ob_src->rotAngle;
|
|
|
|
|
ob_tar->rotmode = ob_src->rotmode;
|
2019-02-18 15:43:06 +11:00
|
|
|
copy_v3_v3(ob_tar->scale, ob_src->scale);
|
2010-10-12 21:47:13 +00:00
|
|
|
}
|
|
|
|
|
|
2021-11-04 16:51:37 -03:00
|
|
|
Object *BKE_object_duplicate(Main *bmain, Object *ob, uint dupflag, uint duplicate_options)
|
2019-02-26 16:15:30 -03:00
|
|
|
{
|
2020-06-17 15:02:04 +02:00
|
|
|
const bool is_subprocess = (duplicate_options & LIB_ID_DUPLICATE_IS_SUBPROCESS) != 0;
|
2021-08-24 12:23:39 +02:00
|
|
|
const bool is_root_id = (duplicate_options & LIB_ID_DUPLICATE_IS_ROOT_ID) != 0;
|
2021-09-30 15:22:16 +02:00
|
|
|
int copy_flags = LIB_ID_COPY_DEFAULT;
|
2020-06-17 15:02:04 +02:00
|
|
|
|
|
|
|
|
if (!is_subprocess) {
|
2021-05-27 22:44:02 +10:00
|
|
|
BKE_main_id_newptr_and_tag_clear(bmain);
|
2021-08-24 12:23:39 +02:00
|
|
|
}
|
2021-09-30 15:22:16 +02:00
|
|
|
else {
|
|
|
|
|
/* In case copying object is a sub-process of collection (or scene) copying, do not try to
|
|
|
|
|
* re-assign RB objects to existing RBW collections. */
|
|
|
|
|
copy_flags |= LIB_ID_COPY_RIGID_BODY_NO_COLLECTION_HANDLING;
|
|
|
|
|
}
|
2021-08-24 12:23:39 +02:00
|
|
|
if (is_root_id) {
|
2020-07-09 15:33:34 +02:00
|
|
|
/* In case root duplicated ID is linked, assume we want to get a local copy of it and duplicate
|
|
|
|
|
* all expected linked data. */
|
|
|
|
|
if (ID_IS_LINKED(ob)) {
|
|
|
|
|
dupflag |= USER_DUP_LINKED_ID;
|
|
|
|
|
}
|
2021-08-24 12:23:39 +02:00
|
|
|
duplicate_options &= ~LIB_ID_DUPLICATE_IS_ROOT_ID;
|
2020-06-17 15:02:04 +02:00
|
|
|
}
|
|
|
|
|
|
2019-02-26 16:15:30 -03:00
|
|
|
Material ***matarar;
|
2020-06-10 16:43:25 +02:00
|
|
|
|
2021-09-30 15:22:16 +02:00
|
|
|
Object *obn = (Object *)BKE_id_copy_for_duplicate(bmain, &ob->id, dupflag, copy_flags);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-26 16:15:30 -03:00
|
|
|
/* 0 == full linked. */
|
|
|
|
|
if (dupflag == 0) {
|
|
|
|
|
return obn;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-26 16:15:30 -03:00
|
|
|
if (dupflag & USER_DUP_MAT) {
|
2020-06-17 17:01:21 +02:00
|
|
|
for (int i = 0; i < obn->totcol; i++) {
|
2021-09-30 15:22:16 +02:00
|
|
|
BKE_id_copy_for_duplicate(bmain, (ID *)obn->mat[i], dupflag, copy_flags);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
}
|
2019-02-26 16:15:30 -03:00
|
|
|
if (dupflag & USER_DUP_PSYS) {
|
2021-11-04 16:51:37 -03:00
|
|
|
LISTBASE_FOREACH (ParticleSystem *, psys, &obn->particlesystem) {
|
2021-09-30 15:22:16 +02:00
|
|
|
BKE_id_copy_for_duplicate(bmain, (ID *)psys->part, dupflag, copy_flags);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-04 16:51:37 -03:00
|
|
|
ID *id_old = (ID *)obn->data;
|
|
|
|
|
ID *id_new = nullptr;
|
|
|
|
|
const bool need_to_duplicate_obdata = (id_old != nullptr) && (id_old->newid == nullptr);
|
2020-06-17 15:02:04 +02:00
|
|
|
|
2020-06-17 17:01:21 +02:00
|
|
|
switch (obn->type) {
|
|
|
|
|
case OB_MESH:
|
|
|
|
|
if (dupflag & USER_DUP_MESH) {
|
2021-09-30 15:22:16 +02:00
|
|
|
id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag, copy_flags);
|
2020-06-17 15:02:04 +02:00
|
|
|
}
|
2020-06-17 17:01:21 +02:00
|
|
|
break;
|
2022-02-18 09:50:29 -06:00
|
|
|
case OB_CURVES_LEGACY:
|
2020-06-17 17:01:21 +02:00
|
|
|
if (dupflag & USER_DUP_CURVE) {
|
2021-09-30 15:22:16 +02:00
|
|
|
id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag, copy_flags);
|
2019-02-26 16:15:30 -03:00
|
|
|
}
|
2020-06-17 17:01:21 +02:00
|
|
|
break;
|
|
|
|
|
case OB_SURF:
|
|
|
|
|
if (dupflag & USER_DUP_SURF) {
|
2021-09-30 15:22:16 +02:00
|
|
|
id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag, copy_flags);
|
2020-06-17 17:01:21 +02:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case OB_FONT:
|
|
|
|
|
if (dupflag & USER_DUP_FONT) {
|
2021-09-30 15:22:16 +02:00
|
|
|
id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag, copy_flags);
|
2020-06-17 17:01:21 +02:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case OB_MBALL:
|
|
|
|
|
if (dupflag & USER_DUP_MBALL) {
|
2021-09-30 15:22:16 +02:00
|
|
|
id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag, copy_flags);
|
2020-06-17 17:01:21 +02:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case OB_LAMP:
|
|
|
|
|
if (dupflag & USER_DUP_LAMP) {
|
2021-09-30 15:22:16 +02:00
|
|
|
id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag, copy_flags);
|
2020-06-17 17:01:21 +02:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case OB_ARMATURE:
|
|
|
|
|
if (dupflag & USER_DUP_ARM) {
|
2021-09-30 15:22:16 +02:00
|
|
|
id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag, copy_flags);
|
2020-06-17 17:01:21 +02:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case OB_LATTICE:
|
2021-10-22 12:33:03 +02:00
|
|
|
if (dupflag & USER_DUP_LATTICE) {
|
2021-09-30 15:22:16 +02:00
|
|
|
id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag, copy_flags);
|
2020-06-17 17:01:21 +02:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case OB_CAMERA:
|
2021-10-22 12:33:03 +02:00
|
|
|
if (dupflag & USER_DUP_CAMERA) {
|
2021-09-30 15:22:16 +02:00
|
|
|
id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag, copy_flags);
|
2020-06-17 17:01:21 +02:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case OB_LIGHTPROBE:
|
|
|
|
|
if (dupflag & USER_DUP_LIGHTPROBE) {
|
2021-09-30 15:22:16 +02:00
|
|
|
id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag, copy_flags);
|
2020-06-17 17:01:21 +02:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case OB_SPEAKER:
|
2021-10-22 12:33:03 +02:00
|
|
|
if (dupflag & USER_DUP_SPEAKER) {
|
2021-09-30 15:22:16 +02:00
|
|
|
id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag, copy_flags);
|
2020-06-17 17:01:21 +02:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case OB_GPENCIL:
|
|
|
|
|
if (dupflag & USER_DUP_GPENCIL) {
|
2021-09-30 15:22:16 +02:00
|
|
|
id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag, copy_flags);
|
2020-06-17 17:01:21 +02:00
|
|
|
}
|
|
|
|
|
break;
|
Curves: Rename "Hair" types, variables, and functions to "Curves"
Based on discussions from T95355 and T94193, the plan is to use
the name "Curves" to describe the data-block container for multiple
curves. Eventually this will replace the existing "Curve" data-block.
However, it will be a while before the curve data-block can be replaced
so in order to distinguish the two curve types in the UI, "Hair Curves"
will be used, but eventually changed back to "Curves".
This patch renames "hair-related" files, functions, types, and variable
names to this convention. A deep rename is preferred to keep code
consistent and to avoid any "hair" terminology from leaking, since the
new data-block is meant for all curve types, not just hair use cases.
The downside of this naming is that the difference between "Curve"
and "Curves" has become important. That was considered during
design discussons and deemed acceptable, especially given the
non-permanent nature of the somewhat common conflict.
Some points of interest:
- All DNA compatibility is lost, just like rBf59767ff9729.
- I renamed `ID_HA` to `ID_CV` so there is no complete mismatch.
- `hair_curves` is used where necessary to distinguish from the
existing "curves" plural.
- I didn't rename any of the cycles/rendering code function names,
since that is also used by the old hair particle system.
Differential Revision: https://developer.blender.org/D14007
2022-02-07 11:55:54 -06:00
|
|
|
case OB_CURVES:
|
|
|
|
|
if (dupflag & USER_DUP_CURVES) {
|
2021-09-30 15:22:16 +02:00
|
|
|
id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag, copy_flags);
|
2020-06-17 17:01:21 +02:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case OB_POINTCLOUD:
|
|
|
|
|
if (dupflag & USER_DUP_POINTCLOUD) {
|
2021-09-30 15:22:16 +02:00
|
|
|
id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag, copy_flags);
|
2020-06-17 17:01:21 +02:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case OB_VOLUME:
|
|
|
|
|
if (dupflag & USER_DUP_VOLUME) {
|
2021-09-30 15:22:16 +02:00
|
|
|
id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag, copy_flags);
|
2020-06-17 17:01:21 +02:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-06-17 17:01:21 +02:00
|
|
|
/* If obdata has been copied, we may also have to duplicate the materials assigned to it. */
|
2021-11-04 16:51:37 -03:00
|
|
|
if (need_to_duplicate_obdata && !ELEM(id_new, nullptr, id_old)) {
|
2019-02-26 16:15:30 -03:00
|
|
|
if (dupflag & USER_DUP_MAT) {
|
2020-03-05 08:08:23 +11:00
|
|
|
matarar = BKE_object_material_array_p(obn);
|
2019-02-26 16:15:30 -03:00
|
|
|
if (matarar) {
|
2020-06-17 17:01:21 +02:00
|
|
|
for (int i = 0; i < obn->totcol; i++) {
|
2021-09-30 15:22:16 +02:00
|
|
|
BKE_id_copy_for_duplicate(bmain, (ID *)(*matarar)[i], dupflag, copy_flags);
|
2019-02-26 16:15:30 -03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-17 15:02:04 +02:00
|
|
|
if (!is_subprocess) {
|
2021-06-26 21:35:18 +10:00
|
|
|
/* This code will follow into all ID links using an ID tagged with LIB_TAG_NEW. */
|
2021-11-01 15:19:17 +01:00
|
|
|
BKE_libblock_relink_to_newid(bmain, &obn->id, 0);
|
2020-06-17 15:02:04 +02:00
|
|
|
|
|
|
|
|
#ifndef NDEBUG
|
|
|
|
|
/* Call to `BKE_libblock_relink_to_newid` above is supposed to have cleared all those flags. */
|
|
|
|
|
ID *id_iter;
|
|
|
|
|
FOREACH_MAIN_ID_BEGIN (bmain, id_iter) {
|
|
|
|
|
BLI_assert((id_iter->tag & LIB_TAG_NEW) == 0);
|
|
|
|
|
}
|
|
|
|
|
FOREACH_MAIN_ID_END;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* Cleanup. */
|
2021-05-27 22:44:02 +10:00
|
|
|
BKE_main_id_newptr_and_tag_clear(bmain);
|
2020-06-17 15:02:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (obn->type == OB_ARMATURE) {
|
|
|
|
|
DEG_id_tag_update(&obn->id, ID_RECALC_GEOMETRY);
|
|
|
|
|
if (obn->pose) {
|
|
|
|
|
BKE_pose_tag_recalc(bmain, obn->pose);
|
|
|
|
|
}
|
|
|
|
|
// BKE_pose_rebuild(bmain, obn, obn->data, true);
|
|
|
|
|
}
|
2019-02-26 16:15:30 -03:00
|
|
|
|
2021-11-04 16:51:37 -03:00
|
|
|
if (obn->data != nullptr) {
|
2019-02-26 16:15:30 -03:00
|
|
|
DEG_id_tag_update_ex(bmain, (ID *)obn->data, ID_RECALC_EDITORS);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return obn;
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-14 14:27:38 +02:00
|
|
|
bool BKE_object_is_libdata(const Object *ob)
|
2009-07-19 00:49:44 +00:00
|
|
|
{
|
2017-11-06 17:17:10 +01:00
|
|
|
return (ob && ID_IS_LINKED(ob));
|
2009-07-19 00:49:44 +00:00
|
|
|
}
|
|
|
|
|
|
2018-04-14 14:27:38 +02:00
|
|
|
bool BKE_object_obdata_is_libdata(const Object *ob)
|
2009-05-21 15:34:09 +00:00
|
|
|
{
|
2016-07-06 14:37:03 +02:00
|
|
|
/* Linked objects with local obdata are forbidden! */
|
2017-11-06 17:17:10 +01:00
|
|
|
BLI_assert(!ob || !ob->data || (ID_IS_LINKED(ob) ? ID_IS_LINKED(ob->data) : true));
|
|
|
|
|
return (ob && ob->data && ID_IS_LINKED(ob->data));
|
2009-05-21 15:34:09 +00:00
|
|
|
}
|
|
|
|
|
|
2014-09-01 20:09:31 +10:00
|
|
|
void BKE_object_obdata_size_init(struct Object *ob, const float size)
|
|
|
|
|
{
|
|
|
|
|
/* apply radius as a scale to types that support it */
|
|
|
|
|
switch (ob->type) {
|
|
|
|
|
case OB_EMPTY: {
|
|
|
|
|
ob->empty_drawsize *= size;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case OB_FONT: {
|
2021-11-04 16:51:37 -03:00
|
|
|
Curve *cu = (Curve *)ob->data;
|
2014-09-01 20:09:31 +10:00
|
|
|
cu->fsize *= size;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case OB_CAMERA: {
|
2021-11-04 16:51:37 -03:00
|
|
|
Camera *cam = (Camera *)ob->data;
|
2014-09-01 20:09:31 +10:00
|
|
|
cam->drawsize *= size;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case OB_LAMP: {
|
2021-11-04 16:51:37 -03:00
|
|
|
Light *lamp = (Light *)ob->data;
|
2014-09-01 20:09:31 +10:00
|
|
|
lamp->dist *= size;
|
|
|
|
|
lamp->area_size *= size;
|
|
|
|
|
lamp->area_sizey *= size;
|
|
|
|
|
lamp->area_sizez *= size;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
/* Only lattice (not mesh, curve, mball...),
|
|
|
|
|
* because its got data when newly added */
|
|
|
|
|
case OB_LATTICE: {
|
2021-11-04 16:51:37 -03:00
|
|
|
Lattice *lt = (Lattice *)ob->data;
|
2014-09-01 20:09:31 +10:00
|
|
|
float mat[4][4];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-09-01 20:09:31 +10:00
|
|
|
unit_m4(mat);
|
|
|
|
|
scale_m4_fl(mat, size);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-09-01 20:09:31 +10:00
|
|
|
BKE_lattice_transform(lt, (float(*)[4])mat, false);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2006-11-11 16:45:17 +00:00
|
|
|
|
2020-04-07 22:20:41 +10:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Object Matrix Get/Set API
|
|
|
|
|
* \{ */
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-12-11 14:29:01 +00:00
|
|
|
void BKE_object_scale_to_mat3(Object *ob, float mat[3][3])
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2022-04-01 14:48:48 -05:00
|
|
|
float3 vec;
|
2019-02-18 15:43:06 +11:00
|
|
|
mul_v3_v3v3(vec, ob->scale, ob->dscale);
|
2012-04-29 15:47:02 +00:00
|
|
|
size_to_mat3(mat, vec);
|
2008-09-29 20:13:40 +00:00
|
|
|
}
|
|
|
|
|
|
2019-05-01 13:15:44 +10:00
|
|
|
void BKE_object_rot_to_mat3(const Object *ob, float mat[3][3], bool use_drot)
|
2008-09-29 20:13:40 +00:00
|
|
|
{
|
2009-09-28 10:19:20 +00:00
|
|
|
float rmat[3][3], dmat[3][3];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-05-14 05:42:58 +00:00
|
|
|
/* 'dmat' is the delta-rotation matrix, which will get (pre)multiplied
|
2009-09-28 10:19:20 +00:00
|
|
|
* with the rotation matrix to yield the appropriate rotation
|
|
|
|
|
*/
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2009-09-28 10:19:20 +00:00
|
|
|
/* rotations may either be quats, eulers (with various rotation orders), or axis-angle */
|
|
|
|
|
if (ob->rotmode > 0) {
|
2019-04-27 12:07:07 +10:00
|
|
|
/* Euler rotations
|
2021-01-04 11:29:11 +11:00
|
|
|
* (will cause gimbal lock, but this can be alleviated a bit with rotation orders). */
|
2011-05-14 05:42:58 +00:00
|
|
|
eulO_to_mat3(rmat, ob->rot, ob->rotmode);
|
|
|
|
|
eulO_to_mat3(dmat, ob->drot, ob->rotmode);
|
2009-09-28 10:19:20 +00:00
|
|
|
}
|
|
|
|
|
else if (ob->rotmode == ROT_MODE_AXISANGLE) {
|
2012-06-23 23:22:19 +00:00
|
|
|
/* axis-angle - not really that great for 3D-changing orientations */
|
2011-05-14 05:42:58 +00:00
|
|
|
axis_angle_to_mat3(rmat, ob->rotAxis, ob->rotAngle);
|
|
|
|
|
axis_angle_to_mat3(dmat, ob->drotAxis, ob->drotAngle);
|
2009-09-28 10:19:20 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2012-07-03 19:09:07 +00:00
|
|
|
/* quats are normalized before use to eliminate scaling issues */
|
2010-12-07 01:56:32 +00:00
|
|
|
float tquat[4];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2010-12-07 01:56:32 +00:00
|
|
|
normalize_qt_qt(tquat, ob->quat);
|
|
|
|
|
quat_to_mat3(rmat, tquat);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-01-18 15:02:58 +00:00
|
|
|
normalize_qt_qt(tquat, ob->dquat);
|
2010-12-07 01:56:32 +00:00
|
|
|
quat_to_mat3(dmat, tquat);
|
2009-09-28 10:19:20 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2009-09-28 10:19:20 +00:00
|
|
|
/* combine these rotations */
|
2019-04-22 09:39:35 +10:00
|
|
|
if (use_drot) {
|
2012-12-17 21:40:28 +00:00
|
|
|
mul_m3_m3m3(mat, dmat, rmat);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
else {
|
2012-12-17 21:40:28 +00:00
|
|
|
copy_m3_m3(mat, rmat);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2008-09-29 20:13:40 +00:00
|
|
|
}
|
|
|
|
|
|
2013-03-24 12:13:13 +00:00
|
|
|
void BKE_object_mat3_to_rot(Object *ob, float mat[3][3], bool use_compat)
|
2009-12-19 10:27:23 +00:00
|
|
|
{
|
2015-10-24 07:02:51 +11:00
|
|
|
BLI_ASSERT_UNIT_M3(mat);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-04-28 06:31:57 +00:00
|
|
|
switch (ob->rotmode) {
|
2012-05-06 15:15:33 +00:00
|
|
|
case ROT_MODE_QUAT: {
|
2011-02-02 01:01:01 +00:00
|
|
|
float dquat[4];
|
2015-10-24 07:02:51 +11:00
|
|
|
mat3_normalized_to_quat(ob->quat, mat);
|
2011-02-02 01:01:01 +00:00
|
|
|
normalize_qt_qt(dquat, ob->dquat);
|
2015-10-24 03:51:00 +11:00
|
|
|
invert_qt_normalized(dquat);
|
2011-02-02 01:01:01 +00:00
|
|
|
mul_qt_qtqt(ob->quat, dquat, ob->quat);
|
2013-07-19 15:23:42 +00:00
|
|
|
break;
|
2011-02-02 01:01:01 +00:00
|
|
|
}
|
2012-05-06 15:15:33 +00:00
|
|
|
case ROT_MODE_AXISANGLE: {
|
2015-09-25 09:03:30 +02:00
|
|
|
float quat[4];
|
|
|
|
|
float dquat[4];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-09-25 09:03:30 +02:00
|
|
|
/* without drot we could apply 'mat' directly */
|
2015-10-24 07:02:51 +11:00
|
|
|
mat3_normalized_to_quat(quat, mat);
|
2015-09-25 09:03:30 +02:00
|
|
|
axis_angle_to_quat(dquat, ob->drotAxis, ob->drotAngle);
|
2015-10-24 03:51:00 +11:00
|
|
|
invert_qt_normalized(dquat);
|
2015-09-25 09:03:30 +02:00
|
|
|
mul_qt_qtqt(quat, dquat, quat);
|
|
|
|
|
quat_to_axis_angle(ob->rotAxis, &ob->rotAngle, quat);
|
2012-05-06 15:15:33 +00:00
|
|
|
break;
|
2013-07-19 15:23:42 +00:00
|
|
|
}
|
2012-05-06 15:15:33 +00:00
|
|
|
default: /* euler */
|
2011-05-14 04:59:37 +00:00
|
|
|
{
|
|
|
|
|
float quat[4];
|
|
|
|
|
float dquat[4];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-05-14 04:59:37 +00:00
|
|
|
/* without drot we could apply 'mat' directly */
|
2015-10-24 07:02:51 +11:00
|
|
|
mat3_normalized_to_quat(quat, mat);
|
2011-05-14 04:59:37 +00:00
|
|
|
eulO_to_quat(dquat, ob->drot, ob->rotmode);
|
2015-10-24 03:51:00 +11:00
|
|
|
invert_qt_normalized(dquat);
|
2011-05-14 04:59:37 +00:00
|
|
|
mul_qt_qtqt(quat, dquat, quat);
|
|
|
|
|
/* end drot correction */
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (use_compat) {
|
2015-10-24 07:02:51 +11:00
|
|
|
quat_to_compatible_eulO(ob->rot, ob->rot, ob->rotmode, quat);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
else {
|
2015-10-24 07:02:51 +11:00
|
|
|
quat_to_eulO(ob->rot, ob->rotmode, quat);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2013-07-21 08:16:37 +00:00
|
|
|
break;
|
2009-12-19 10:27:23 +00:00
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
|
2012-05-05 14:03:12 +00:00
|
|
|
void BKE_object_tfm_protected_backup(const Object *ob, ObjectTfmProtectedChannels *obtfm)
|
2011-11-11 05:34:07 +00:00
|
|
|
{
|
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
#define TFMCPY(_v) (obtfm->_v = ob->_v)
|
|
|
|
|
#define TFMCPY3D(_v) copy_v3_v3(obtfm->_v, ob->_v)
|
|
|
|
|
#define TFMCPY4D(_v) copy_v4_v4(obtfm->_v, ob->_v)
|
2011-11-11 05:34:07 +00:00
|
|
|
|
|
|
|
|
TFMCPY3D(loc);
|
|
|
|
|
TFMCPY3D(dloc);
|
2019-02-18 15:43:06 +11:00
|
|
|
TFMCPY3D(scale);
|
2011-12-04 03:35:54 +00:00
|
|
|
TFMCPY3D(dscale);
|
2011-11-11 05:34:07 +00:00
|
|
|
TFMCPY3D(rot);
|
|
|
|
|
TFMCPY3D(drot);
|
|
|
|
|
TFMCPY4D(quat);
|
|
|
|
|
TFMCPY4D(dquat);
|
|
|
|
|
TFMCPY3D(rotAxis);
|
|
|
|
|
TFMCPY3D(drotAxis);
|
|
|
|
|
TFMCPY(rotAngle);
|
|
|
|
|
TFMCPY(drotAngle);
|
|
|
|
|
|
|
|
|
|
#undef TFMCPY
|
|
|
|
|
#undef TFMCPY3D
|
|
|
|
|
#undef TFMCPY4D
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-05 14:03:12 +00:00
|
|
|
void BKE_object_tfm_protected_restore(Object *ob,
|
2012-05-06 15:15:33 +00:00
|
|
|
const ObjectTfmProtectedChannels *obtfm,
|
|
|
|
|
const short protectflag)
|
2011-11-11 05:34:07 +00:00
|
|
|
{
|
|
|
|
|
unsigned int i;
|
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
for (i = 0; i < 3; i++) {
|
|
|
|
|
if (protectflag & (OB_LOCK_LOCX << i)) {
|
|
|
|
|
ob->loc[i] = obtfm->loc[i];
|
|
|
|
|
ob->dloc[i] = obtfm->dloc[i];
|
2011-11-11 05:34:07 +00:00
|
|
|
}
|
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
if (protectflag & (OB_LOCK_SCALEX << i)) {
|
2019-02-18 15:43:06 +11:00
|
|
|
ob->scale[i] = obtfm->scale[i];
|
2012-05-06 15:15:33 +00:00
|
|
|
ob->dscale[i] = obtfm->dscale[i];
|
2011-11-11 05:34:07 +00:00
|
|
|
}
|
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
if (protectflag & (OB_LOCK_ROTX << i)) {
|
|
|
|
|
ob->rot[i] = obtfm->rot[i];
|
|
|
|
|
ob->drot[i] = obtfm->drot[i];
|
2011-11-11 05:34:07 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
ob->quat[i + 1] = obtfm->quat[i + 1];
|
|
|
|
|
ob->dquat[i + 1] = obtfm->dquat[i + 1];
|
2011-11-11 05:34:07 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
ob->rotAxis[i] = obtfm->rotAxis[i];
|
|
|
|
|
ob->drotAxis[i] = obtfm->drotAxis[i];
|
2011-11-11 05:34:07 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((protectflag & OB_LOCK_ROT4D) && (protectflag & OB_LOCK_ROTW)) {
|
2012-05-06 15:15:33 +00:00
|
|
|
ob->quat[0] = obtfm->quat[0];
|
|
|
|
|
ob->dquat[0] = obtfm->dquat[0];
|
2011-11-11 05:34:07 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
ob->rotAngle = obtfm->rotAngle;
|
|
|
|
|
ob->drotAngle = obtfm->drotAngle;
|
2011-11-11 05:34:07 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-01 10:25:14 +01:00
|
|
|
void BKE_object_tfm_copy(Object *object_dst, const Object *object_src)
|
|
|
|
|
{
|
|
|
|
|
#define TFMCPY(_v) (object_dst->_v = object_src->_v)
|
|
|
|
|
#define TFMCPY3D(_v) copy_v3_v3(object_dst->_v, object_src->_v)
|
|
|
|
|
#define TFMCPY4D(_v) copy_v4_v4(object_dst->_v, object_src->_v)
|
|
|
|
|
|
|
|
|
|
TFMCPY3D(loc);
|
|
|
|
|
TFMCPY3D(dloc);
|
|
|
|
|
TFMCPY3D(scale);
|
|
|
|
|
TFMCPY3D(dscale);
|
|
|
|
|
TFMCPY3D(rot);
|
|
|
|
|
TFMCPY3D(drot);
|
|
|
|
|
TFMCPY4D(quat);
|
|
|
|
|
TFMCPY4D(dquat);
|
|
|
|
|
TFMCPY3D(rotAxis);
|
|
|
|
|
TFMCPY3D(drotAxis);
|
|
|
|
|
TFMCPY(rotAngle);
|
|
|
|
|
TFMCPY(drotAngle);
|
|
|
|
|
|
|
|
|
|
#undef TFMCPY
|
|
|
|
|
#undef TFMCPY3D
|
|
|
|
|
#undef TFMCPY4D
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-02 17:17:31 +10:00
|
|
|
void BKE_object_to_mat3(Object *ob, float r_mat[3][3]) /* no parent */
|
2008-09-29 20:13:40 +00:00
|
|
|
{
|
|
|
|
|
float smat[3][3];
|
|
|
|
|
float rmat[3][3];
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2021-06-26 21:40:28 +10:00
|
|
|
/* Scale. */
|
2012-05-05 14:03:12 +00:00
|
|
|
BKE_object_scale_to_mat3(ob, smat);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2021-06-26 21:40:28 +10:00
|
|
|
/* Rotation. */
|
2014-04-01 11:34:00 +11:00
|
|
|
BKE_object_rot_to_mat3(ob, rmat, true);
|
2020-08-02 17:17:31 +10:00
|
|
|
mul_m3_m3m3(r_mat, rmat, smat);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
2020-08-02 17:17:31 +10:00
|
|
|
void BKE_object_to_mat4(Object *ob, float r_mat[4][4])
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
|
|
|
|
float tmat[3][3];
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2012-05-05 14:03:12 +00:00
|
|
|
BKE_object_to_mat3(ob, tmat);
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2020-08-02 17:17:31 +10:00
|
|
|
copy_m4_m3(r_mat, tmat);
|
2010-07-03 17:47:06 +00:00
|
|
|
|
2020-08-02 17:17:31 +10:00
|
|
|
add_v3_v3v3(r_mat[3], ob->loc, ob->dloc);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
2020-08-02 17:17:31 +10:00
|
|
|
void BKE_object_matrix_local_get(struct Object *ob, float r_mat[4][4])
|
2013-07-12 12:58:01 +00:00
|
|
|
{
|
|
|
|
|
if (ob->parent) {
|
2014-12-29 15:23:12 +01:00
|
|
|
float par_imat[4][4];
|
|
|
|
|
|
2018-12-19 11:20:32 +01:00
|
|
|
BKE_object_get_parent_matrix(ob, ob->parent, par_imat);
|
2014-12-29 15:23:12 +01:00
|
|
|
invert_m4(par_imat);
|
2020-08-02 17:17:31 +10:00
|
|
|
mul_m4_m4m4(r_mat, par_imat, ob->obmat);
|
2013-07-12 12:58:01 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2020-08-02 17:17:31 +10:00
|
|
|
copy_m4_m4(r_mat, ob->obmat);
|
2013-07-12 12:58:01 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-17 14:26:27 +10:00
|
|
|
/**
|
|
|
|
|
* \return success if \a mat is set.
|
|
|
|
|
*/
|
2020-08-02 17:17:31 +10:00
|
|
|
static bool ob_parcurve(Object *ob, Object *par, float r_mat[4][4])
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2021-11-04 16:51:37 -03:00
|
|
|
Curve *cu = (Curve *)par->data;
|
2022-04-13 19:22:10 -05:00
|
|
|
float vec[4], quat[4], radius, ctime;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-12-19 11:20:32 +01:00
|
|
|
/* NOTE: Curve cache is supposed to be evaluated here already, however there
|
|
|
|
|
* are cases where we can not guarantee that. This includes, for example,
|
|
|
|
|
* dependency cycles. We can't correct anything from here, since that would
|
2022-04-13 19:22:10 -05:00
|
|
|
* cause threading conflicts.
|
2018-12-19 11:20:32 +01:00
|
|
|
*
|
2019-08-04 12:51:44 +10:00
|
|
|
* TODO(sergey): Some of the legit looking cases like T56619 need to be
|
2018-12-19 11:20:32 +01:00
|
|
|
* looked into, and maybe curve cache (and other dependencies) are to be
|
|
|
|
|
* evaluated prior to conversion. */
|
2021-11-04 16:51:37 -03:00
|
|
|
if (par->runtime.curve_cache == nullptr) {
|
2018-08-31 11:09:26 +10:00
|
|
|
return false;
|
|
|
|
|
}
|
2021-11-04 16:51:37 -03:00
|
|
|
if (par->runtime.curve_cache->anim_path_accum_length == nullptr) {
|
2015-08-17 14:26:27 +10:00
|
|
|
return false;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-27 12:07:07 +10:00
|
|
|
/* ctime is now a proper var setting of Curve which gets set by Animato like any other var
|
|
|
|
|
* that's animated, but this will only work if it actually is animated.
|
2019-01-28 17:52:46 +01:00
|
|
|
*
|
2020-07-28 21:49:37 +10:00
|
|
|
* We divide the curve-time calculated in the previous step by the length of the path,
|
2019-04-27 12:07:07 +10:00
|
|
|
* to get a time factor, which then gets clamped to lie within 0.0 - 1.0 range.
|
2019-01-28 17:52:46 +01:00
|
|
|
*/
|
|
|
|
|
if (cu->pathlen) {
|
|
|
|
|
ctime = cu->ctime / cu->pathlen;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2019-01-28 17:52:46 +01:00
|
|
|
ctime = cu->ctime;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-05-20 20:41:10 +02:00
|
|
|
if (cu->flag & CU_PATH_CLAMP) {
|
|
|
|
|
CLAMP(ctime, 0.0f, 1.0f);
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-02 17:17:31 +10:00
|
|
|
unit_m4(r_mat);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2004-11-21 10:42:42 +00:00
|
|
|
/* vec: 4 items! */
|
2021-04-08 15:51:08 +02:00
|
|
|
if (BKE_where_on_path(
|
2022-04-13 19:22:10 -05:00
|
|
|
par, ctime, vec, nullptr, (cu->flag & CU_FOLLOW) ? quat : nullptr, &radius, nullptr)) {
|
2012-02-23 02:17:50 +00:00
|
|
|
if (cu->flag & CU_FOLLOW) {
|
2010-10-08 07:29:08 +00:00
|
|
|
quat_apply_track(quat, ob->trackflag, ob->upflag);
|
2010-12-07 01:56:32 +00:00
|
|
|
normalize_qt(quat);
|
2020-08-02 17:17:31 +10:00
|
|
|
quat_to_mat4(r_mat, quat);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2012-02-23 02:17:50 +00:00
|
|
|
if (cu->flag & CU_PATH_RADIUS) {
|
2009-09-12 16:25:49 +00:00
|
|
|
float tmat[4][4], rmat[4][4];
|
2009-11-10 20:43:45 +00:00
|
|
|
scale_m4_fl(tmat, radius);
|
2020-08-02 17:17:31 +10:00
|
|
|
mul_m4_m4m4(rmat, tmat, r_mat);
|
|
|
|
|
copy_m4_m4(r_mat, rmat);
|
2009-09-12 16:25:49 +00:00
|
|
|
}
|
2020-08-02 17:17:31 +10:00
|
|
|
copy_v3_v3(r_mat[3], vec);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-08-17 14:26:27 +10:00
|
|
|
return true;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
2020-08-02 17:17:31 +10:00
|
|
|
static void ob_parbone(Object *ob, Object *par, float r_mat[4][4])
|
2018-06-17 17:05:51 +02:00
|
|
|
{
|
2022-04-01 14:48:48 -05:00
|
|
|
float3 vec;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
if (par->type != OB_ARMATURE) {
|
2020-08-02 17:17:31 +10:00
|
|
|
unit_m4(r_mat);
|
2002-10-12 11:37:38 +00:00
|
|
|
return;
|
Result of 2 weeks of quiet coding work in Greece :)
Aim was to get a total refresh of the animation system. This
is needed because;
- we need to upgrade it with 21st century features
- current code is spaghetti/hack combo, and hides good design
- it should become lag-free with using dependency graphs
A full log, with complete code API/structure/design explanation
will follow, that's a load of work... so here below the list with
hot changes;
- The entire object update system (matrices, geometry) is now
centralized. Calls to where_is_object and makeDispList are
forbidden, instead we tag objects 'changed' and let the
depgraph code sort it out
- Removed all old "Ika" code
- Depgraph is aware of all relationships, including meta balls,
constraints, bevelcurve, and so on.
- Made depgraph aware of relation types and layers, to do smart
flushing of 'changed' events. Nothing gets calculated too often!
- Transform uses depgraph to detect changes
- On frame-advance, depgraph flushes animated changes
Armatures;
Almost all armature related code has been fully built from scratch.
It now reveils the original design much better, with a very clean
implementation, lag free without even calculating each Bone more than
once. Result is quite a speedup yes!
Important to note is;
1) Armature is data containing the 'rest position'
2) Pose is the changes of rest position, and always on object level.
That way more Objects can use same Pose. Also constraints are in Pose
3) Actions only contain the Ipos to change values in Poses.
- Bones draw unrotated now
- Drawing bones speedup enormously (10-20 times)
- Bone selecting in EditMode, selection state is saved for PoseMode,
and vice-versa
- Undo in editmode
- Bone renaming does vertexgroups, constraints, posechannels, actions,
for all users of Armature in entire file
- Added Bone renaming in NKey panel
- Nkey PoseMode shows eulers now
- EditMode and PoseMode now have 'active' bone too (last clicked)
- Parenting in EditMode' CTRL+P, ALT+P, with nice options!
- Pose is added in Outliner now, with showing that constraints are in
the Pose, not Armature
- Disconnected IK solving from constraints. It's a separate phase now,
on top of the full Pose calculations
- Pose itself has a dependency graph too, so evaluation order is lag free.
TODO NOW;
- Rotating in Posemode has incorrect inverse transform (Martin will fix)
- Python Bone/Armature/Pose API disabled... needs full recode too
(wait for my doc!)
- Game engine will need upgrade too
- Depgraph code needs revision, cleanup, can be much faster!
(But, compliments for Jean-Luc, it works like a charm!)
- IK changed, it now doesnt use previous position to advance to next
position anymore. That system looks nice (no flips) but is not well
suited for NLA and background render.
TODO LATER;
We now can do loadsa new nifty features as well; like:
- Kill PoseMode (can be option for armatures itself)
- Make B-Bones (Bezier, Bspline, like for spines)
- Move all silly button level edit to 3d window (like CTRL+I = add
IK)
- Much better & informative drawing
- Fix action/nla editors
- Put all ipos in Actions (object, mesh key, lamp color)
- Add hooks
- Null bones
- Much more advanced constraints...
Bugfixes;
- OGL render (view3d header) had wrong first frame on anim render
- Ipo 'recording' mode had wrong playback speed
- Vertex-key mode now sticks to show 'active key', until frame change
-Ton-
2005-07-03 17:35:38 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
/* Make sure the bone is still valid */
|
2020-12-22 10:35:18 -06:00
|
|
|
bPoseChannel *pchan = BKE_pose_channel_find_name(par->pose, ob->parsubstr);
|
2012-11-04 12:13:26 +00:00
|
|
|
if (!pchan || !pchan->bone) {
|
2021-09-03 17:16:42 +02:00
|
|
|
CLOG_WARN(
|
|
|
|
|
&LOG, "Parent Bone: '%s' for Object: '%s' doesn't exist", ob->parsubstr, ob->id.name + 2);
|
2020-08-02 17:17:31 +10:00
|
|
|
unit_m4(r_mat);
|
2002-10-12 11:37:38 +00:00
|
|
|
return;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Result of 2 weeks of quiet coding work in Greece :)
Aim was to get a total refresh of the animation system. This
is needed because;
- we need to upgrade it with 21st century features
- current code is spaghetti/hack combo, and hides good design
- it should become lag-free with using dependency graphs
A full log, with complete code API/structure/design explanation
will follow, that's a load of work... so here below the list with
hot changes;
- The entire object update system (matrices, geometry) is now
centralized. Calls to where_is_object and makeDispList are
forbidden, instead we tag objects 'changed' and let the
depgraph code sort it out
- Removed all old "Ika" code
- Depgraph is aware of all relationships, including meta balls,
constraints, bevelcurve, and so on.
- Made depgraph aware of relation types and layers, to do smart
flushing of 'changed' events. Nothing gets calculated too often!
- Transform uses depgraph to detect changes
- On frame-advance, depgraph flushes animated changes
Armatures;
Almost all armature related code has been fully built from scratch.
It now reveils the original design much better, with a very clean
implementation, lag free without even calculating each Bone more than
once. Result is quite a speedup yes!
Important to note is;
1) Armature is data containing the 'rest position'
2) Pose is the changes of rest position, and always on object level.
That way more Objects can use same Pose. Also constraints are in Pose
3) Actions only contain the Ipos to change values in Poses.
- Bones draw unrotated now
- Drawing bones speedup enormously (10-20 times)
- Bone selecting in EditMode, selection state is saved for PoseMode,
and vice-versa
- Undo in editmode
- Bone renaming does vertexgroups, constraints, posechannels, actions,
for all users of Armature in entire file
- Added Bone renaming in NKey panel
- Nkey PoseMode shows eulers now
- EditMode and PoseMode now have 'active' bone too (last clicked)
- Parenting in EditMode' CTRL+P, ALT+P, with nice options!
- Pose is added in Outliner now, with showing that constraints are in
the Pose, not Armature
- Disconnected IK solving from constraints. It's a separate phase now,
on top of the full Pose calculations
- Pose itself has a dependency graph too, so evaluation order is lag free.
TODO NOW;
- Rotating in Posemode has incorrect inverse transform (Martin will fix)
- Python Bone/Armature/Pose API disabled... needs full recode too
(wait for my doc!)
- Game engine will need upgrade too
- Depgraph code needs revision, cleanup, can be much faster!
(But, compliments for Jean-Luc, it works like a charm!)
- IK changed, it now doesnt use previous position to advance to next
position anymore. That system looks nice (no flips) but is not well
suited for NLA and background render.
TODO LATER;
We now can do loadsa new nifty features as well; like:
- Kill PoseMode (can be option for armatures itself)
- Make B-Bones (Bezier, Bspline, like for spines)
- Move all silly button level edit to 3d window (like CTRL+I = add
IK)
- Much better & informative drawing
- Fix action/nla editors
- Put all ipos in Actions (object, mesh key, lamp color)
- Add hooks
- Null bones
- Much more advanced constraints...
Bugfixes;
- OGL render (view3d header) had wrong first frame on anim render
- Ipo 'recording' mode had wrong playback speed
- Vertex-key mode now sticks to show 'active key', until frame change
-Ton-
2005-07-03 17:35:38 +00:00
|
|
|
/* get bone transform */
|
2012-12-22 11:08:25 +00:00
|
|
|
if (pchan->bone->flag & BONE_RELATIVE_PARENTING) {
|
2018-12-24 12:31:39 +01:00
|
|
|
/* the new option uses the root - expected behavior, but differs from old... */
|
2012-12-22 11:08:25 +00:00
|
|
|
/* XXX check on version patching? */
|
2020-08-02 17:17:31 +10:00
|
|
|
copy_m4_m4(r_mat, pchan->chan_mat);
|
2012-12-22 11:08:25 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2020-08-02 17:17:31 +10:00
|
|
|
copy_m4_m4(r_mat, pchan->pose_mat);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-12-22 11:08:25 +00:00
|
|
|
/* but for backwards compatibility, the child has to move to the tail */
|
2020-08-02 17:17:31 +10:00
|
|
|
copy_v3_v3(vec, r_mat[1]);
|
2012-12-22 11:08:25 +00:00
|
|
|
mul_v3_fl(vec, pchan->bone->length);
|
2020-08-02 17:17:31 +10:00
|
|
|
add_v3_v3(r_mat[3], vec);
|
2012-12-22 11:08:25 +00:00
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-28 14:05:00 +00:00
|
|
|
static void give_parvert(Object *par, int nr, float vec[3])
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2012-09-15 06:03:49 +00:00
|
|
|
zero_v3(vec);
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
if (par->type == OB_MESH) {
|
2021-11-04 16:51:37 -03:00
|
|
|
Mesh *me = (Mesh *)par->data;
|
2019-02-17 18:05:18 +11:00
|
|
|
BMEditMesh *em = me->edit_mesh;
|
2022-01-11 15:42:07 +01:00
|
|
|
Mesh *me_eval = (em) ? BKE_object_get_editmesh_eval_final(par) :
|
|
|
|
|
BKE_object_get_evaluated_mesh(par);
|
2009-03-30 07:28:37 +00:00
|
|
|
|
2018-10-15 15:31:17 +11:00
|
|
|
if (me_eval) {
|
2012-09-23 18:50:56 +00:00
|
|
|
int count = 0;
|
2020-07-02 19:11:51 +10:00
|
|
|
int numVerts = me_eval->totvert;
|
2012-09-23 18:50:56 +00:00
|
|
|
|
2020-07-02 19:11:51 +10:00
|
|
|
if (em && me_eval->runtime.wrapper_type == ME_WRAPPER_TYPE_BMESH) {
|
|
|
|
|
numVerts = em->bm->totvert;
|
2020-01-21 17:52:44 +01:00
|
|
|
if (em->bm->elem_table_dirty & BM_VERT) {
|
2014-10-31 20:15:32 +01:00
|
|
|
#ifdef VPARENT_THREADING_HACK
|
2020-01-21 17:52:44 +01:00
|
|
|
BLI_mutex_lock(&vparent_lock);
|
|
|
|
|
if (em->bm->elem_table_dirty & BM_VERT) {
|
2018-11-20 11:29:38 +01:00
|
|
|
BM_mesh_elem_table_ensure(em->bm, BM_VERT);
|
2014-10-31 20:15:32 +01:00
|
|
|
}
|
2020-01-21 17:52:44 +01:00
|
|
|
BLI_mutex_unlock(&vparent_lock);
|
|
|
|
|
#else
|
2021-07-15 18:23:28 +10:00
|
|
|
BLI_assert_msg(0, "Not safe for threading");
|
2020-01-21 17:52:44 +01:00
|
|
|
BM_mesh_elem_table_ensure(em->bm, BM_VERT);
|
|
|
|
|
#endif
|
2014-10-31 20:15:32 +01:00
|
|
|
}
|
2020-07-02 19:11:51 +10:00
|
|
|
if (nr < numVerts) {
|
|
|
|
|
if (me_eval && me_eval->runtime.edit_data && me_eval->runtime.edit_data->vertexCos) {
|
|
|
|
|
add_v3_v3(vec, me_eval->runtime.edit_data->vertexCos[nr]);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
const BMVert *v = BM_vert_at_index(em->bm, nr);
|
|
|
|
|
add_v3_v3(vec, v->co);
|
|
|
|
|
}
|
|
|
|
|
count++;
|
|
|
|
|
}
|
2020-01-21 17:52:44 +01:00
|
|
|
}
|
2020-07-02 19:11:51 +10:00
|
|
|
else if (CustomData_has_layer(&me_eval->vdata, CD_ORIGINDEX)) {
|
2021-11-04 16:51:37 -03:00
|
|
|
const int *index = (const int *)CustomData_get_layer(&me_eval->vdata, CD_ORIGINDEX);
|
2020-01-21 17:52:44 +01:00
|
|
|
/* Get the average of all verts with (original index == nr). */
|
|
|
|
|
for (int i = 0; i < numVerts; i++) {
|
|
|
|
|
if (index[i] == nr) {
|
|
|
|
|
add_v3_v3(vec, me_eval->mvert[i].co);
|
2012-09-23 18:50:56 +00:00
|
|
|
count++;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
}
|
2012-09-23 18:50:56 +00:00
|
|
|
}
|
2020-01-21 17:52:44 +01:00
|
|
|
else {
|
|
|
|
|
if (nr < numVerts) {
|
|
|
|
|
add_v3_v3(vec, me_eval->mvert[nr].co);
|
|
|
|
|
count++;
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
if (count == 0) {
|
2012-04-29 15:47:02 +00:00
|
|
|
/* keep as 0, 0, 0 */
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
|
else if (count > 0) {
|
2010-07-28 16:47:12 +00:00
|
|
|
mul_v3_fl(vec, 1.0f / count);
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2010-07-28 16:47:12 +00:00
|
|
|
/* use first index if its out of range */
|
2018-10-15 15:31:17 +11:00
|
|
|
if (me_eval->totvert) {
|
|
|
|
|
copy_v3_v3(vec, me_eval->mvert[0].co);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
}
|
2018-10-15 15:31:17 +11:00
|
|
|
}
|
2012-07-25 22:37:52 +00:00
|
|
|
else {
|
2019-02-01 12:44:19 +11:00
|
|
|
CLOG_ERROR(&LOG,
|
|
|
|
|
"Evaluated mesh is needed to solve parenting, "
|
|
|
|
|
"object position can be wrong now");
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2012-07-25 22:37:52 +00:00
|
|
|
}
|
2022-02-18 09:50:29 -06:00
|
|
|
else if (ELEM(par->type, OB_CURVES_LEGACY, OB_SURF)) {
|
2014-10-21 14:44:08 +02:00
|
|
|
ListBase *nurb;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-04-28 14:58:52 -05:00
|
|
|
/* It is possible that a cycle in the dependency graph was resolved in a way that caused this
|
|
|
|
|
* object to be evaluated before its dependencies. In this case the curve cache may be null. */
|
|
|
|
|
if (par->runtime.curve_cache && par->runtime.curve_cache->deformed_nurbs.first != nullptr) {
|
2018-07-30 16:54:40 +02:00
|
|
|
nurb = &par->runtime.curve_cache->deformed_nurbs;
|
2014-10-21 14:44:08 +02:00
|
|
|
}
|
|
|
|
|
else {
|
2021-11-04 16:51:37 -03:00
|
|
|
Curve *cu = (Curve *)par->data;
|
2014-10-21 14:44:08 +02:00
|
|
|
nurb = BKE_curve_nurbs_get(cu);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-09-23 18:50:56 +00:00
|
|
|
BKE_nurbList_index_get_co(nurb, nr, vec);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2012-05-06 15:15:33 +00:00
|
|
|
else if (par->type == OB_LATTICE) {
|
2021-11-04 16:51:37 -03:00
|
|
|
Lattice *latt = (Lattice *)par->data;
|
2018-07-30 16:54:40 +02:00
|
|
|
DispList *dl = par->runtime.curve_cache ?
|
|
|
|
|
BKE_displist_find(&par->runtime.curve_cache->disp, DL_VERTS) :
|
2021-11-04 16:51:37 -03:00
|
|
|
nullptr;
|
|
|
|
|
float(*co)[3] = dl ? (float(*)[3])dl->verts : nullptr;
|
2012-09-23 18:50:56 +00:00
|
|
|
int tot;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (latt->editlatt) {
|
2012-05-06 15:15:33 +00:00
|
|
|
latt = latt->editlatt->latt;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-09-23 18:50:56 +00:00
|
|
|
tot = latt->pntsu * latt->pntsv * latt->pntsw;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-09-23 18:50:56 +00:00
|
|
|
/* ensure dl is correct size */
|
2021-11-04 16:51:37 -03:00
|
|
|
BLI_assert(dl == nullptr || dl->nr == tot);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-09-23 18:50:56 +00:00
|
|
|
if (nr < tot) {
|
|
|
|
|
if (co) {
|
|
|
|
|
copy_v3_v3(vec, co[nr]);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
copy_v3_v3(vec, latt->def[nr].vec);
|
2006-09-08 12:05:36 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
2020-08-02 17:17:31 +10:00
|
|
|
static void ob_parvert3(Object *ob, Object *par, float r_mat[4][4])
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2003-04-26 13:07:59 +00:00
|
|
|
/* in local ob space */
|
2013-09-01 22:38:41 +00:00
|
|
|
if (OB_TYPE_SUPPORT_PARVERT(par->type)) {
|
|
|
|
|
float cmat[3][3], v1[3], v2[3], v3[3], q[4];
|
|
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
give_parvert(par, ob->par1, v1);
|
|
|
|
|
give_parvert(par, ob->par2, v2);
|
|
|
|
|
give_parvert(par, ob->par3, v3);
|
2013-09-01 22:38:41 +00:00
|
|
|
|
2012-04-29 15:47:02 +00:00
|
|
|
tri_to_quat(q, v1, v2, v3);
|
|
|
|
|
quat_to_mat3(cmat, q);
|
2020-08-02 17:17:31 +10:00
|
|
|
copy_m4_m3(r_mat, cmat);
|
2013-09-01 22:38:41 +00:00
|
|
|
|
2020-08-02 17:17:31 +10:00
|
|
|
mid_v3_v3v3v3(r_mat[3], v1, v2, v3);
|
2013-09-01 22:38:41 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2020-08-02 17:17:31 +10:00
|
|
|
unit_m4(r_mat);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-02 17:17:31 +10:00
|
|
|
void BKE_object_get_parent_matrix(Object *ob, Object *par, float r_parentmat[4][4])
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
|
|
|
|
float tmat[4][4];
|
|
|
|
|
float vec[3];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-04-28 06:31:57 +00:00
|
|
|
switch (ob->partype & PARTYPE) {
|
2020-12-22 10:35:18 -06:00
|
|
|
case PAROBJECT: {
|
|
|
|
|
bool ok = false;
|
2022-02-18 09:50:29 -06:00
|
|
|
if (par->type == OB_CURVES_LEGACY) {
|
2015-08-17 14:26:27 +10:00
|
|
|
if ((((Curve *)par->data)->flag & CU_PATH) && (ob_parcurve(ob, par, tmat))) {
|
2020-12-22 10:35:18 -06:00
|
|
|
ok = true;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2012-05-06 15:15:33 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (ok) {
|
2020-08-02 17:17:31 +10:00
|
|
|
mul_m4_m4m4(r_parentmat, par->obmat, tmat);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
else {
|
2020-08-02 17:17:31 +10:00
|
|
|
copy_m4_m4(r_parentmat, par->obmat);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
break;
|
2020-12-22 10:35:18 -06:00
|
|
|
}
|
2012-05-06 15:15:33 +00:00
|
|
|
case PARBONE:
|
|
|
|
|
ob_parbone(ob, par, tmat);
|
2020-08-02 17:17:31 +10:00
|
|
|
mul_m4_m4m4(r_parentmat, par->obmat, tmat);
|
2012-05-06 15:15:33 +00:00
|
|
|
break;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
case PARVERT1:
|
2020-08-02 17:17:31 +10:00
|
|
|
unit_m4(r_parentmat);
|
2014-01-09 00:37:41 +01:00
|
|
|
give_parvert(par, ob->par1, vec);
|
2020-08-02 17:17:31 +10:00
|
|
|
mul_v3_m4v3(r_parentmat[3], par->obmat, vec);
|
2012-05-06 15:15:33 +00:00
|
|
|
break;
|
|
|
|
|
case PARVERT3:
|
|
|
|
|
ob_parvert3(ob, par, tmat);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-08-02 17:17:31 +10:00
|
|
|
mul_m4_m4m4(r_parentmat, par->obmat, tmat);
|
2012-05-06 15:15:33 +00:00
|
|
|
break;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
case PARSKEL:
|
2020-08-02 17:17:31 +10:00
|
|
|
copy_m4_m4(r_parentmat, par->obmat);
|
2012-05-06 15:15:33 +00:00
|
|
|
break;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2018-12-19 11:20:32 +01:00
|
|
|
}
|
|
|
|
|
|
2020-04-07 22:20:41 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Object Matrix Evaluation API
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2014-01-09 00:37:41 +01:00
|
|
|
/**
|
2019-04-27 12:07:07 +10:00
|
|
|
* \param r_originmat: Optional matrix that stores the space the object is in
|
|
|
|
|
* (without its own matrix applied)
|
2014-01-09 00:37:41 +01:00
|
|
|
*/
|
2019-01-28 17:52:46 +01:00
|
|
|
static void solve_parenting(
|
2020-08-02 17:17:31 +10:00
|
|
|
Object *ob, Object *par, const bool set_origin, float r_obmat[4][4], float r_originmat[3][3])
|
2014-01-09 00:37:41 +01:00
|
|
|
{
|
|
|
|
|
float totmat[4][4];
|
|
|
|
|
float tmat[4][4];
|
|
|
|
|
float locmat[4][4];
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2014-01-09 00:37:41 +01:00
|
|
|
BKE_object_to_mat4(ob, locmat);
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2019-01-28 17:52:46 +01:00
|
|
|
BKE_object_get_parent_matrix(ob, par, totmat);
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2012-07-07 22:51:57 +00:00
|
|
|
/* total */
|
2013-08-06 01:45:29 +00:00
|
|
|
mul_m4_m4m4(tmat, totmat, ob->parentinv);
|
2020-08-02 17:17:31 +10:00
|
|
|
mul_m4_m4m4(r_obmat, tmat, locmat);
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2014-01-09 00:37:41 +01:00
|
|
|
if (r_originmat) {
|
|
|
|
|
/* usable originmat */
|
|
|
|
|
copy_m3_m4(r_originmat, tmat);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2014-01-09 00:37:41 +01:00
|
|
|
/* origin, for help line */
|
|
|
|
|
if (set_origin) {
|
2012-05-06 15:15:33 +00:00
|
|
|
if ((ob->partype & PARTYPE) == PARSKEL) {
|
2019-02-19 11:37:27 +11:00
|
|
|
copy_v3_v3(ob->runtime.parent_display_origin, par->obmat[3]);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2019-02-19 11:37:27 +11:00
|
|
|
copy_v3_v3(ob->runtime.parent_display_origin, totmat[3]);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
}
|
2012-06-07 05:39:28 +00:00
|
|
|
}
|
|
|
|
|
|
2019-01-29 11:59:17 +01:00
|
|
|
static void object_where_is_calc_ex(Depsgraph *depsgraph,
|
2019-01-28 17:52:46 +01:00
|
|
|
Scene *scene,
|
|
|
|
|
Object *ob,
|
|
|
|
|
float ctime,
|
2017-08-16 12:45:11 +10:00
|
|
|
RigidBodyWorld *rbw,
|
|
|
|
|
float r_originmat[3][3])
|
2011-11-07 12:55:18 +00:00
|
|
|
{
|
2012-02-23 02:17:50 +00:00
|
|
|
if (ob->parent) {
|
2012-05-06 15:15:33 +00:00
|
|
|
Object *par = ob->parent;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-06-07 05:29:10 +00:00
|
|
|
/* calculate parent matrix */
|
2020-08-02 17:17:31 +10:00
|
|
|
solve_parenting(ob, par, true, ob->obmat, r_originmat);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2012-05-05 14:03:12 +00:00
|
|
|
BKE_object_to_mat4(ob, ob->obmat);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-02-17 19:38:08 +00:00
|
|
|
/* try to fall back to the scene rigid body world if none given */
|
|
|
|
|
rbw = rbw ? rbw : scene->rigidbody_world;
|
Bugfix [#33970] Background Scene does not show animation of rigid body objects
This was caused by multiple instantiations of the same basic problem. The
rigidbody handling code often assumed that "scene" pointers referred to the
scene where an object participating in the sim resided (and where the rigidbody
world for that sim lived). However, when dealing with background sets, "scene"
often only refers to the active scene, and not the set that the object actually
came from. Hence, the rigidbody code would often (wrongly) conclude that there
was nothing to do.
For example, we may have the following backgound set/scene chaining scenario:
"active" <-- ... <-- set i (rigidbody objects live here) <-- ... <-- set n
The fix here is a multi-part fix:
1) Moved sim-world calculation from BKE_scene_update_newframe() to
scene_update_tagged_recursive()
+ This is currently the only way that rigidbody sims in background sets will
get calculated, as part of the recursion
- These checks will get run on each update. <--- FIXME!!!
2) Tweaked depsgraph code so that when checking if there are any time-dependent
features on objects to tag for updating, the checking is done relative to the
scene that the object actually resides in (and not the active scene). Otherwise,
even if we recalculate the sim, the affected objects won't get tagged for
updating. This tagging is needed to actually flush the transforms out of the
RigidBodyObject structs (written by the sim/cache) and into the Object
transforms (obmat's)
3) Removed the requirement for rigidbody world to actually exist before we can
flush rigidbody transforms. In many cases, it should be sufficient to assume
that because the object with rigidbody data attached has been tagged for
updates, it should have updates to perform. Of course, we still check on this
data if we've got it, but that's only if the sim is in the active scene.
- TODO: if we have further problems, we should investigate passing the
"actual" scene down alongside the "active" scene for BKE_object_handle_update().
2013-02-15 11:49:22 +00:00
|
|
|
/* read values pushed into RBO from sim/cache... */
|
2013-02-16 16:17:45 +00:00
|
|
|
BKE_rigidbody_sync_transforms(rbw, ob, ctime);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
== Constraints System ==
After just over a week of coding, I've finished doing a major refactor/cleanup of the constraints code. In the process, quite a few old kludges and ugly hacks have been removed. Also, some new features which will greatly benefit riggers have been implemented.
=== What's New ===
* The long-awaited ``ChildOf Constraint'':
This allows you to animate parent influences, and choose which transformation channels the parent affects the child on (i.e. no translation/rotation/scaling). It should be noted that disabling some combinations may not totally work as expected. Also, the 'Set Inverse' and 'Clear Inverse' buttons at the bottom of this constraint's panel set/clear the inverse correction for the parent's effects. Use these to make the owner not stick/be glued to the parent.
* Constraint/Target Evaluation Spaces:
In some constraints, there are now 1-2 combo boxes at the bottom of their panel, which allows you to pick which `co-ordinate space' they are evaluated in. This is much more flexible than the old 'local' options for bones only were.
* Action Constraint - Loc/Rot/Size Inputs
The Action Constraint can finally use the target's location/rotation/scaling transforms as input, to control the owner of the constraint. This should work much more reliably than it used to. The target evaluation should now also be more accurate due to the new space conversion stuff.
* Transform - No longer in Crazy Space (TM)
Transforming objects/bones with constraints applied should no longer occur in Crazy Space. They are now correctly inverse-corrected. This also applies to old-style object tracking.
=== General Code Changes ===
* solve_constraints is now in constraints.c. I've removed the old `blend consecutive constraints of same type' junk, which made the code more complex than it needed to be.
* evaluate_constraint is now only passed the constraint, and two matrices. A few unused variables have been removed from here.
* A tempolary struct, bConstraintOb, is now passed to solve_constraints instead of relying on an ugly, static workobject in some cases. This works much better.
* Made the formatting of constraint code consistent
* There's a version patch for older files so that constraint settings are correctly converted to the new system. This is currently done for MajorVersion <= 244, and SubVersion < 3. I've bumped up the subversion to 3 for this purpose. However, with the imminent 2.45 release, this may need to be adjusted accordingly.
* LocEulSizeToMat4 and LocQuatSizeToMat4 now work in the order Size, Rot, Location. I've also added a few other math functions.
* Mat4BlendMat4 is now in arithb. I've modified it's method slightly, to use other arithb functions, instead of its crazy blending scheme.
* Moved some of the RigidBodyJoint constraint's code out of blenkernel, and into src. It shouldn't be setting its target in its data initialisation function based + accessing scene stuff where it was doing so.
=== Future Work ===
* Geometry to act as targets for constraints. A space has been reserved for this already.
* Tidy up UI buttons of constraints
2007-07-15 03:35:37 +00:00
|
|
|
/* solve constraints */
|
2011-01-27 01:29:40 +00:00
|
|
|
if (ob->constraints.first && !(ob->transflag & OB_NO_CONSTRAINTS)) {
|
== Constraints System ==
After just over a week of coding, I've finished doing a major refactor/cleanup of the constraints code. In the process, quite a few old kludges and ugly hacks have been removed. Also, some new features which will greatly benefit riggers have been implemented.
=== What's New ===
* The long-awaited ``ChildOf Constraint'':
This allows you to animate parent influences, and choose which transformation channels the parent affects the child on (i.e. no translation/rotation/scaling). It should be noted that disabling some combinations may not totally work as expected. Also, the 'Set Inverse' and 'Clear Inverse' buttons at the bottom of this constraint's panel set/clear the inverse correction for the parent's effects. Use these to make the owner not stick/be glued to the parent.
* Constraint/Target Evaluation Spaces:
In some constraints, there are now 1-2 combo boxes at the bottom of their panel, which allows you to pick which `co-ordinate space' they are evaluated in. This is much more flexible than the old 'local' options for bones only were.
* Action Constraint - Loc/Rot/Size Inputs
The Action Constraint can finally use the target's location/rotation/scaling transforms as input, to control the owner of the constraint. This should work much more reliably than it used to. The target evaluation should now also be more accurate due to the new space conversion stuff.
* Transform - No longer in Crazy Space (TM)
Transforming objects/bones with constraints applied should no longer occur in Crazy Space. They are now correctly inverse-corrected. This also applies to old-style object tracking.
=== General Code Changes ===
* solve_constraints is now in constraints.c. I've removed the old `blend consecutive constraints of same type' junk, which made the code more complex than it needed to be.
* evaluate_constraint is now only passed the constraint, and two matrices. A few unused variables have been removed from here.
* A tempolary struct, bConstraintOb, is now passed to solve_constraints instead of relying on an ugly, static workobject in some cases. This works much better.
* Made the formatting of constraint code consistent
* There's a version patch for older files so that constraint settings are correctly converted to the new system. This is currently done for MajorVersion <= 244, and SubVersion < 3. I've bumped up the subversion to 3 for this purpose. However, with the imminent 2.45 release, this may need to be adjusted accordingly.
* LocEulSizeToMat4 and LocQuatSizeToMat4 now work in the order Size, Rot, Location. I've also added a few other math functions.
* Mat4BlendMat4 is now in arithb. I've modified it's method slightly, to use other arithb functions, instead of its crazy blending scheme.
* Moved some of the RigidBodyJoint constraint's code out of blenkernel, and into src. It shouldn't be setting its target in its data initialisation function based + accessing scene stuff where it was doing so.
=== Future Work ===
* Geometry to act as targets for constraints. A space has been reserved for this already.
* Tidy up UI buttons of constraints
2007-07-15 03:35:37 +00:00
|
|
|
bConstraintOb *cob;
|
2021-11-04 16:51:37 -03:00
|
|
|
cob = BKE_constraints_make_evalob(depsgraph, scene, ob, nullptr, CONSTRAINT_OBTYPE_OBJECT);
|
2018-04-06 12:07:27 +02:00
|
|
|
BKE_constraints_solve(depsgraph, &ob->constraints, cob, ctime);
|
2012-12-23 11:31:15 +00:00
|
|
|
BKE_constraints_clear_evalob(cob);
|
== Constraints System ==
After just over a week of coding, I've finished doing a major refactor/cleanup of the constraints code. In the process, quite a few old kludges and ugly hacks have been removed. Also, some new features which will greatly benefit riggers have been implemented.
=== What's New ===
* The long-awaited ``ChildOf Constraint'':
This allows you to animate parent influences, and choose which transformation channels the parent affects the child on (i.e. no translation/rotation/scaling). It should be noted that disabling some combinations may not totally work as expected. Also, the 'Set Inverse' and 'Clear Inverse' buttons at the bottom of this constraint's panel set/clear the inverse correction for the parent's effects. Use these to make the owner not stick/be glued to the parent.
* Constraint/Target Evaluation Spaces:
In some constraints, there are now 1-2 combo boxes at the bottom of their panel, which allows you to pick which `co-ordinate space' they are evaluated in. This is much more flexible than the old 'local' options for bones only were.
* Action Constraint - Loc/Rot/Size Inputs
The Action Constraint can finally use the target's location/rotation/scaling transforms as input, to control the owner of the constraint. This should work much more reliably than it used to. The target evaluation should now also be more accurate due to the new space conversion stuff.
* Transform - No longer in Crazy Space (TM)
Transforming objects/bones with constraints applied should no longer occur in Crazy Space. They are now correctly inverse-corrected. This also applies to old-style object tracking.
=== General Code Changes ===
* solve_constraints is now in constraints.c. I've removed the old `blend consecutive constraints of same type' junk, which made the code more complex than it needed to be.
* evaluate_constraint is now only passed the constraint, and two matrices. A few unused variables have been removed from here.
* A tempolary struct, bConstraintOb, is now passed to solve_constraints instead of relying on an ugly, static workobject in some cases. This works much better.
* Made the formatting of constraint code consistent
* There's a version patch for older files so that constraint settings are correctly converted to the new system. This is currently done for MajorVersion <= 244, and SubVersion < 3. I've bumped up the subversion to 3 for this purpose. However, with the imminent 2.45 release, this may need to be adjusted accordingly.
* LocEulSizeToMat4 and LocQuatSizeToMat4 now work in the order Size, Rot, Location. I've also added a few other math functions.
* Mat4BlendMat4 is now in arithb. I've modified it's method slightly, to use other arithb functions, instead of its crazy blending scheme.
* Moved some of the RigidBodyJoint constraint's code out of blenkernel, and into src. It shouldn't be setting its target in its data initialisation function based + accessing scene stuff where it was doing so.
=== Future Work ===
* Geometry to act as targets for constraints. A space has been reserved for this already.
* Tidy up UI buttons of constraints
2007-07-15 03:35:37 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2004-05-29 16:17:46 +00:00
|
|
|
/* set negative scale flag in object */
|
2019-04-22 09:39:35 +10:00
|
|
|
if (is_negative_m4(ob->obmat)) {
|
2012-05-06 15:15:33 +00:00
|
|
|
ob->transflag |= OB_NEG_SCALE;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
else {
|
2012-05-06 15:15:33 +00:00
|
|
|
ob->transflag &= ~OB_NEG_SCALE;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
2018-04-06 12:07:27 +02:00
|
|
|
void BKE_object_where_is_calc_time(Depsgraph *depsgraph, Scene *scene, Object *ob, float ctime)
|
2013-02-16 16:17:45 +00:00
|
|
|
{
|
2019-01-29 11:59:17 +01:00
|
|
|
/* Execute drivers and animation. */
|
2019-07-31 14:56:17 +02:00
|
|
|
const bool flush_to_original = DEG_is_active(depsgraph);
|
T77086 Animation: Passing Dependency Graph to Drivers
Custom driver functions need access to the dependency graph that is
triggering the evaluation of the driver. This patch passes the
dependency graph pointer through all the animation-related calls.
Instead of passing the evaluation time to functions, the code now passes
an `AnimationEvalContext` pointer:
```
typedef struct AnimationEvalContext {
struct Depsgraph *const depsgraph;
const float eval_time;
} AnimationEvalContext;
```
These structs are read-only, meaning that the code cannot change the
evaluation time. Note that the `depsgraph` pointer itself is const, but
it points to a non-const depsgraph.
FCurves and Drivers can be evaluated at a different time than the
current scene time, for example when evaluating NLA strips. This means
that, even though the current time is stored in the dependency graph, we
need an explicit evaluation time.
There are two functions that allow creation of `AnimationEvalContext`
objects:
- `BKE_animsys_eval_context_construct(Depsgraph *depsgraph, float
eval_time)`, which creates a new context object from scratch, and
- `BKE_animsys_eval_context_construct_at(AnimationEvalContext
*anim_eval_context, float eval_time)`, which can be used to create a
`AnimationEvalContext` with the same depsgraph, but at a different
time. This makes it possible to later add fields without changing any
of the code that just want to change the eval time.
This also provides a fix for T75553, although it does require a change
to the custom driver function. The driver should call
`custom_function(depsgraph)`, and the function should use that depsgraph
instead of information from `bpy.context`.
Reviewed By: brecht, sergey
Differential Revision: https://developer.blender.org/D8047
2020-07-17 17:38:09 +02:00
|
|
|
const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(depsgraph,
|
|
|
|
|
ctime);
|
|
|
|
|
BKE_animsys_evaluate_animdata(
|
|
|
|
|
&ob->id, ob->adt, &anim_eval_context, ADT_RECALC_ALL, flush_to_original);
|
2021-11-04 16:51:37 -03:00
|
|
|
object_where_is_calc_ex(depsgraph, scene, ob, ctime, nullptr, nullptr);
|
2018-12-19 11:20:32 +01:00
|
|
|
}
|
|
|
|
|
|
2020-08-02 17:17:31 +10:00
|
|
|
void BKE_object_where_is_calc_mat4(Object *ob, float r_obmat[4][4])
|
2011-11-07 12:55:18 +00:00
|
|
|
{
|
2012-02-23 02:17:50 +00:00
|
|
|
if (ob->parent) {
|
2012-05-06 15:15:33 +00:00
|
|
|
Object *par = ob->parent;
|
2021-11-04 16:51:37 -03:00
|
|
|
solve_parenting(ob, par, false, r_obmat, nullptr);
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2020-08-02 17:17:31 +10:00
|
|
|
BKE_object_to_mat4(ob, r_obmat);
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
2018-04-06 12:07:27 +02:00
|
|
|
void BKE_object_where_is_calc_ex(
|
|
|
|
|
Depsgraph *depsgraph, Scene *scene, RigidBodyWorld *rbw, Object *ob, float r_originmat[3][3])
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2019-01-29 11:59:17 +01:00
|
|
|
float ctime = DEG_get_ctime(depsgraph);
|
|
|
|
|
object_where_is_calc_ex(depsgraph, scene, ob, ctime, rbw, r_originmat);
|
2013-02-16 16:17:45 +00:00
|
|
|
}
|
2018-04-06 12:07:27 +02:00
|
|
|
void BKE_object_where_is_calc(Depsgraph *depsgraph, Scene *scene, Object *ob)
|
2013-02-16 16:17:45 +00:00
|
|
|
{
|
2019-01-29 11:59:17 +01:00
|
|
|
float ctime = DEG_get_ctime(depsgraph);
|
2021-11-04 16:51:37 -03:00
|
|
|
object_where_is_calc_ex(depsgraph, scene, ob, ctime, nullptr, nullptr);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
2018-04-06 12:07:27 +02:00
|
|
|
void BKE_object_workob_calc_parent(Depsgraph *depsgraph, Scene *scene, Object *ob, Object *workob)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2012-05-05 14:03:12 +00:00
|
|
|
BKE_object_workob_clear(workob);
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2009-11-10 20:43:45 +00:00
|
|
|
unit_m4(workob->obmat);
|
|
|
|
|
unit_m4(workob->parentinv);
|
|
|
|
|
unit_m4(workob->constinv);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2019-04-27 12:07:07 +10:00
|
|
|
/* Since this is used while calculating parenting,
|
2021-11-04 16:51:37 -03:00
|
|
|
* at this moment ob_eval->parent is still nullptr. */
|
2018-05-29 14:00:36 +02:00
|
|
|
workob->parent = DEG_get_evaluated_object(depsgraph, ob->parent);
|
|
|
|
|
|
2019-02-05 15:43:34 +01:00
|
|
|
workob->trackflag = ob->trackflag;
|
|
|
|
|
workob->upflag = ob->upflag;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2019-02-05 15:43:34 +01:00
|
|
|
workob->partype = ob->partype;
|
|
|
|
|
workob->par1 = ob->par1;
|
|
|
|
|
workob->par2 = ob->par2;
|
|
|
|
|
workob->par3 = ob->par3;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2020-11-27 12:11:43 +01:00
|
|
|
/* The effects of constraints should NOT be included in the parent-inverse matrix. Constraints
|
|
|
|
|
* are supposed to be applied after the object's local loc/rot/scale. If the (inverted) effect of
|
|
|
|
|
* constraints would be included in the parent inverse matrix, these would be applied before the
|
|
|
|
|
* object's local loc/rot/scale instead of after. For example, a "Copy Rotation" constraint would
|
|
|
|
|
* rotate the object's local translation as well. See T82156. */
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2019-02-05 15:43:34 +01:00
|
|
|
BLI_strncpy(workob->parsubstr, ob->parsubstr, sizeof(workob->parsubstr));
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2018-04-06 12:07:27 +02:00
|
|
|
BKE_object_where_is_calc(depsgraph, scene, workob);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
2020-08-02 17:17:31 +10:00
|
|
|
void BKE_object_apply_mat4_ex(Object *ob,
|
|
|
|
|
const float mat[4][4],
|
|
|
|
|
Object *parent,
|
|
|
|
|
const float parentinv[4][4],
|
|
|
|
|
const bool use_compat)
|
2014-01-09 00:37:41 +01:00
|
|
|
{
|
2018-05-21 20:29:00 +02:00
|
|
|
/* see BKE_pchan_apply_mat4() for the equivalent 'pchan' function */
|
|
|
|
|
|
2014-01-09 00:37:41 +01:00
|
|
|
float rot[3][3];
|
|
|
|
|
|
2021-11-04 16:51:37 -03:00
|
|
|
if (parent != nullptr) {
|
2014-01-09 00:37:41 +01:00
|
|
|
float rmat[4][4], diff_mat[4][4], imat[4][4], parent_mat[4][4];
|
|
|
|
|
|
2018-12-19 11:20:32 +01:00
|
|
|
BKE_object_get_parent_matrix(ob, parent, parent_mat);
|
2014-01-09 00:37:41 +01:00
|
|
|
|
2018-05-21 20:29:00 +02:00
|
|
|
mul_m4_m4m4(diff_mat, parent_mat, parentinv);
|
2014-01-09 00:37:41 +01:00
|
|
|
invert_m4_m4(imat, diff_mat);
|
|
|
|
|
mul_m4_m4m4(rmat, imat, mat); /* get the parent relative matrix */
|
|
|
|
|
|
|
|
|
|
/* same as below, use rmat rather than mat */
|
2019-02-18 15:43:06 +11:00
|
|
|
mat4_to_loc_rot_size(ob->loc, rot, ob->scale, rmat);
|
2014-01-09 00:37:41 +01:00
|
|
|
}
|
|
|
|
|
else {
|
2019-02-18 15:43:06 +11:00
|
|
|
mat4_to_loc_rot_size(ob->loc, rot, ob->scale, mat);
|
2014-01-09 00:37:41 +01:00
|
|
|
}
|
|
|
|
|
|
2014-12-29 13:04:46 +11:00
|
|
|
BKE_object_mat3_to_rot(ob, rot, use_compat);
|
|
|
|
|
|
2014-01-09 00:37:41 +01:00
|
|
|
sub_v3_v3(ob->loc, ob->dloc);
|
|
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (ob->dscale[0] != 0.0f) {
|
2019-02-18 15:43:06 +11:00
|
|
|
ob->scale[0] /= ob->dscale[0];
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
if (ob->dscale[1] != 0.0f) {
|
2019-02-18 15:43:06 +11:00
|
|
|
ob->scale[1] /= ob->dscale[1];
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
if (ob->dscale[2] != 0.0f) {
|
2019-02-18 15:43:06 +11:00
|
|
|
ob->scale[2] /= ob->dscale[2];
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2014-01-09 00:37:41 +01:00
|
|
|
|
|
|
|
|
/* BKE_object_mat3_to_rot handles delta rotations */
|
|
|
|
|
}
|
|
|
|
|
|
2018-05-21 20:29:00 +02:00
|
|
|
void BKE_object_apply_mat4(Object *ob,
|
2020-08-02 17:17:31 +10:00
|
|
|
const float mat[4][4],
|
2018-05-21 20:29:00 +02:00
|
|
|
const bool use_compat,
|
|
|
|
|
const bool use_parent)
|
|
|
|
|
{
|
2021-11-04 16:51:37 -03:00
|
|
|
BKE_object_apply_mat4_ex(ob, mat, use_parent ? ob->parent : nullptr, ob->parentinv, use_compat);
|
2018-05-21 20:29:00 +02:00
|
|
|
}
|
|
|
|
|
|
Object: Set Parent (Keep Transform Without Inverse)
**Relevant to Artists:** This patch adds an option to the Parenting
menu, `Object (Keep Transform Without Inverse)`, and Apply menu, `Parent
Inverse`. The operators preserve the child's world transform without
using the parent inverse matrix. Effectively, we set the child's origin
to the parent. When the child has an identity local transform, then the
child is world-space aligned with its parent (scale excluded).
**Technical:** In both cases, the hidden parent inverse matrix is
generally set to identity (cleared or "not used") as long as the parent
has no shear. If the parent has shear, then this matrix will not be
entirely cleared. It will contain shear to counter the parent's shear.
This is required, otherwise the object's local matrix cannot be properly
decomposed into location, rotation and scale, and thus cannot preserve
the world transform.
If the child's world transform has shear, then its world transform is
not preserved. This is currently not supported for consistency in the
handling of shear during the other parenting ops: Parent (Keep
Transform), Clear [Parent] and Keep Transform. If it should work, then
another patch should add the support for all of them.
Reviewed By: sybren, RiggingDojo
Differential Revision: https://developer.blender.org/D14581
2022-04-14 18:16:23 -04:00
|
|
|
void BKE_object_apply_parent_inverse(struct Object *ob)
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* Use parent's world transform as the child's origin.
|
|
|
|
|
*
|
|
|
|
|
* Let:
|
2022-04-20 09:16:24 +10:00
|
|
|
* `local = identity`
|
|
|
|
|
* `world = orthonormalized(parent)`
|
Object: Set Parent (Keep Transform Without Inverse)
**Relevant to Artists:** This patch adds an option to the Parenting
menu, `Object (Keep Transform Without Inverse)`, and Apply menu, `Parent
Inverse`. The operators preserve the child's world transform without
using the parent inverse matrix. Effectively, we set the child's origin
to the parent. When the child has an identity local transform, then the
child is world-space aligned with its parent (scale excluded).
**Technical:** In both cases, the hidden parent inverse matrix is
generally set to identity (cleared or "not used") as long as the parent
has no shear. If the parent has shear, then this matrix will not be
entirely cleared. It will contain shear to counter the parent's shear.
This is required, otherwise the object's local matrix cannot be properly
decomposed into location, rotation and scale, and thus cannot preserve
the world transform.
If the child's world transform has shear, then its world transform is
not preserved. This is currently not supported for consistency in the
handling of shear during the other parenting ops: Parent (Keep
Transform), Clear [Parent] and Keep Transform. If it should work, then
another patch should add the support for all of them.
Reviewed By: sybren, RiggingDojo
Differential Revision: https://developer.blender.org/D14581
2022-04-14 18:16:23 -04:00
|
|
|
*
|
|
|
|
|
* Then:
|
2022-04-20 09:16:24 +10:00
|
|
|
* `world = parent @ parentinv @ local`
|
|
|
|
|
* `inv(parent) @ world = parentinv`
|
|
|
|
|
* `parentinv = inv(parent) @ world`
|
Object: Set Parent (Keep Transform Without Inverse)
**Relevant to Artists:** This patch adds an option to the Parenting
menu, `Object (Keep Transform Without Inverse)`, and Apply menu, `Parent
Inverse`. The operators preserve the child's world transform without
using the parent inverse matrix. Effectively, we set the child's origin
to the parent. When the child has an identity local transform, then the
child is world-space aligned with its parent (scale excluded).
**Technical:** In both cases, the hidden parent inverse matrix is
generally set to identity (cleared or "not used") as long as the parent
has no shear. If the parent has shear, then this matrix will not be
entirely cleared. It will contain shear to counter the parent's shear.
This is required, otherwise the object's local matrix cannot be properly
decomposed into location, rotation and scale, and thus cannot preserve
the world transform.
If the child's world transform has shear, then its world transform is
not preserved. This is currently not supported for consistency in the
handling of shear during the other parenting ops: Parent (Keep
Transform), Clear [Parent] and Keep Transform. If it should work, then
another patch should add the support for all of them.
Reviewed By: sybren, RiggingDojo
Differential Revision: https://developer.blender.org/D14581
2022-04-14 18:16:23 -04:00
|
|
|
*
|
2022-04-20 09:16:24 +10:00
|
|
|
* NOTE: If `ob->obmat` has shear, then this `parentinv` is insufficient because
|
|
|
|
|
* `parent @ parentinv => shearless result`
|
Object: Set Parent (Keep Transform Without Inverse)
**Relevant to Artists:** This patch adds an option to the Parenting
menu, `Object (Keep Transform Without Inverse)`, and Apply menu, `Parent
Inverse`. The operators preserve the child's world transform without
using the parent inverse matrix. Effectively, we set the child's origin
to the parent. When the child has an identity local transform, then the
child is world-space aligned with its parent (scale excluded).
**Technical:** In both cases, the hidden parent inverse matrix is
generally set to identity (cleared or "not used") as long as the parent
has no shear. If the parent has shear, then this matrix will not be
entirely cleared. It will contain shear to counter the parent's shear.
This is required, otherwise the object's local matrix cannot be properly
decomposed into location, rotation and scale, and thus cannot preserve
the world transform.
If the child's world transform has shear, then its world transform is
not preserved. This is currently not supported for consistency in the
handling of shear during the other parenting ops: Parent (Keep
Transform), Clear [Parent] and Keep Transform. If it should work, then
another patch should add the support for all of them.
Reviewed By: sybren, RiggingDojo
Differential Revision: https://developer.blender.org/D14581
2022-04-14 18:16:23 -04:00
|
|
|
*
|
|
|
|
|
* Thus, local will have shear which cannot be decomposed into TRS:
|
2022-04-20 09:16:24 +10:00
|
|
|
* `local = inv(parent @ parentinv) @ world`
|
Object: Set Parent (Keep Transform Without Inverse)
**Relevant to Artists:** This patch adds an option to the Parenting
menu, `Object (Keep Transform Without Inverse)`, and Apply menu, `Parent
Inverse`. The operators preserve the child's world transform without
using the parent inverse matrix. Effectively, we set the child's origin
to the parent. When the child has an identity local transform, then the
child is world-space aligned with its parent (scale excluded).
**Technical:** In both cases, the hidden parent inverse matrix is
generally set to identity (cleared or "not used") as long as the parent
has no shear. If the parent has shear, then this matrix will not be
entirely cleared. It will contain shear to counter the parent's shear.
This is required, otherwise the object's local matrix cannot be properly
decomposed into location, rotation and scale, and thus cannot preserve
the world transform.
If the child's world transform has shear, then its world transform is
not preserved. This is currently not supported for consistency in the
handling of shear during the other parenting ops: Parent (Keep
Transform), Clear [Parent] and Keep Transform. If it should work, then
another patch should add the support for all of them.
Reviewed By: sybren, RiggingDojo
Differential Revision: https://developer.blender.org/D14581
2022-04-14 18:16:23 -04:00
|
|
|
*
|
|
|
|
|
* This is currently not supported for consistency in the handling of shear during the other
|
|
|
|
|
* parenting ops: Parent (Keep Transform), Clear [Parent] and Keep Transform.
|
|
|
|
|
*/
|
|
|
|
|
float par_locrot[4][4], par_imat[4][4];
|
|
|
|
|
BKE_object_get_parent_matrix(ob, ob->parent, par_locrot);
|
|
|
|
|
invert_m4_m4(par_imat, par_locrot);
|
|
|
|
|
|
|
|
|
|
orthogonalize_m4_stable(par_locrot, 0, true);
|
|
|
|
|
|
|
|
|
|
mul_m4_m4m4(ob->parentinv, par_imat, par_locrot);
|
|
|
|
|
|
|
|
|
|
/* Now, preserve `world` given the new `parentinv`.
|
|
|
|
|
*
|
2022-04-20 09:16:24 +10:00
|
|
|
* `world = parent @ parentinv @ local`
|
|
|
|
|
* `inv(parent) @ world = parentinv @ local`
|
|
|
|
|
* `inv(parentinv) @ inv(parent) @ world = local`
|
Object: Set Parent (Keep Transform Without Inverse)
**Relevant to Artists:** This patch adds an option to the Parenting
menu, `Object (Keep Transform Without Inverse)`, and Apply menu, `Parent
Inverse`. The operators preserve the child's world transform without
using the parent inverse matrix. Effectively, we set the child's origin
to the parent. When the child has an identity local transform, then the
child is world-space aligned with its parent (scale excluded).
**Technical:** In both cases, the hidden parent inverse matrix is
generally set to identity (cleared or "not used") as long as the parent
has no shear. If the parent has shear, then this matrix will not be
entirely cleared. It will contain shear to counter the parent's shear.
This is required, otherwise the object's local matrix cannot be properly
decomposed into location, rotation and scale, and thus cannot preserve
the world transform.
If the child's world transform has shear, then its world transform is
not preserved. This is currently not supported for consistency in the
handling of shear during the other parenting ops: Parent (Keep
Transform), Clear [Parent] and Keep Transform. If it should work, then
another patch should add the support for all of them.
Reviewed By: sybren, RiggingDojo
Differential Revision: https://developer.blender.org/D14581
2022-04-14 18:16:23 -04:00
|
|
|
*
|
2022-04-20 09:16:24 +10:00
|
|
|
* `local = inv(parentinv) @ inv(parent) @ world`
|
Object: Set Parent (Keep Transform Without Inverse)
**Relevant to Artists:** This patch adds an option to the Parenting
menu, `Object (Keep Transform Without Inverse)`, and Apply menu, `Parent
Inverse`. The operators preserve the child's world transform without
using the parent inverse matrix. Effectively, we set the child's origin
to the parent. When the child has an identity local transform, then the
child is world-space aligned with its parent (scale excluded).
**Technical:** In both cases, the hidden parent inverse matrix is
generally set to identity (cleared or "not used") as long as the parent
has no shear. If the parent has shear, then this matrix will not be
entirely cleared. It will contain shear to counter the parent's shear.
This is required, otherwise the object's local matrix cannot be properly
decomposed into location, rotation and scale, and thus cannot preserve
the world transform.
If the child's world transform has shear, then its world transform is
not preserved. This is currently not supported for consistency in the
handling of shear during the other parenting ops: Parent (Keep
Transform), Clear [Parent] and Keep Transform. If it should work, then
another patch should add the support for all of them.
Reviewed By: sybren, RiggingDojo
Differential Revision: https://developer.blender.org/D14581
2022-04-14 18:16:23 -04:00
|
|
|
*/
|
|
|
|
|
float ob_local[4][4];
|
|
|
|
|
copy_m4_m4(ob_local, ob->parentinv);
|
|
|
|
|
invert_m4(ob_local);
|
|
|
|
|
mul_m4_m4_post(ob_local, par_imat);
|
|
|
|
|
mul_m4_m4_post(ob_local, ob->obmat);
|
|
|
|
|
|
|
|
|
|
/* Send use_compat=False so the rotation is predictable. */
|
|
|
|
|
BKE_object_apply_mat4(ob, ob_local, false, false);
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-07 22:20:41 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Object Bounding Box API
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2021-12-08 00:31:20 -05:00
|
|
|
BoundBox *BKE_boundbox_alloc_unit()
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2022-04-01 14:48:48 -05:00
|
|
|
BoundBox *bb = MEM_cnew<BoundBox>(__func__);
|
|
|
|
|
BKE_boundbox_init_from_minmax(bb, float3(-1), float3(1));
|
2005-07-18 17:33:51 +00:00
|
|
|
return bb;
|
|
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2013-06-09 21:25:27 +00:00
|
|
|
void BKE_boundbox_init_from_minmax(BoundBox *bb, const float min[3], const float max[3])
|
2005-07-18 17:33:51 +00:00
|
|
|
{
|
2012-05-06 15:15:33 +00:00
|
|
|
bb->vec[0][0] = bb->vec[1][0] = bb->vec[2][0] = bb->vec[3][0] = min[0];
|
|
|
|
|
bb->vec[4][0] = bb->vec[5][0] = bb->vec[6][0] = bb->vec[7][0] = max[0];
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
bb->vec[0][1] = bb->vec[1][1] = bb->vec[4][1] = bb->vec[5][1] = min[1];
|
|
|
|
|
bb->vec[2][1] = bb->vec[3][1] = bb->vec[6][1] = bb->vec[7][1] = max[1];
|
2005-07-18 17:33:51 +00:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
bb->vec[0][2] = bb->vec[3][2] = bb->vec[4][2] = bb->vec[7][2] = min[2];
|
|
|
|
|
bb->vec[1][2] = bb->vec[2][2] = bb->vec[5][2] = bb->vec[6][2] = max[2];
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
2014-08-11 13:25:25 +10:00
|
|
|
void BKE_boundbox_calc_center_aabb(const BoundBox *bb, float r_cent[3])
|
|
|
|
|
{
|
|
|
|
|
r_cent[0] = 0.5f * (bb->vec[0][0] + bb->vec[4][0]);
|
|
|
|
|
r_cent[1] = 0.5f * (bb->vec[0][1] + bb->vec[2][1]);
|
|
|
|
|
r_cent[2] = 0.5f * (bb->vec[0][2] + bb->vec[1][2]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BKE_boundbox_calc_size_aabb(const BoundBox *bb, float r_size[3])
|
|
|
|
|
{
|
|
|
|
|
r_size[0] = 0.5f * fabsf(bb->vec[0][0] - bb->vec[4][0]);
|
|
|
|
|
r_size[1] = 0.5f * fabsf(bb->vec[0][1] - bb->vec[2][1]);
|
|
|
|
|
r_size[2] = 0.5f * fabsf(bb->vec[0][2] - bb->vec[1][2]);
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-02 17:17:31 +10:00
|
|
|
void BKE_boundbox_minmax(const BoundBox *bb,
|
|
|
|
|
const float obmat[4][4],
|
|
|
|
|
float r_min[3],
|
|
|
|
|
float r_max[3])
|
2015-09-04 04:18:49 +10:00
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
for (i = 0; i < 8; i++) {
|
|
|
|
|
float vec[3];
|
|
|
|
|
mul_v3_m4v3(vec, obmat, bb->vec[i]);
|
|
|
|
|
minmax_v3v3_v3(r_min, r_max, vec);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-01 18:30:09 -05:00
|
|
|
const BoundBox *BKE_object_boundbox_get(Object *ob)
|
2006-06-14 08:50:41 +00:00
|
|
|
{
|
2021-11-04 16:51:37 -03:00
|
|
|
BoundBox *bb = nullptr;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-10-29 12:06:27 +01:00
|
|
|
switch (ob->type) {
|
|
|
|
|
case OB_MESH:
|
|
|
|
|
bb = BKE_mesh_boundbox_get(ob);
|
|
|
|
|
break;
|
2022-02-18 09:50:29 -06:00
|
|
|
case OB_CURVES_LEGACY:
|
2018-10-29 12:06:27 +01:00
|
|
|
case OB_SURF:
|
|
|
|
|
case OB_FONT:
|
2018-11-19 10:28:31 -02:00
|
|
|
bb = BKE_curve_boundbox_get(ob);
|
2018-10-29 12:06:27 +01:00
|
|
|
break;
|
|
|
|
|
case OB_MBALL:
|
|
|
|
|
bb = BKE_mball_boundbox_get(ob);
|
|
|
|
|
break;
|
|
|
|
|
case OB_LATTICE:
|
|
|
|
|
bb = BKE_lattice_boundbox_get(ob);
|
|
|
|
|
break;
|
|
|
|
|
case OB_ARMATURE:
|
|
|
|
|
bb = BKE_armature_boundbox_get(ob);
|
|
|
|
|
break;
|
|
|
|
|
case OB_GPENCIL:
|
|
|
|
|
bb = BKE_gpencil_boundbox_get(ob);
|
|
|
|
|
break;
|
Curves: Rename "Hair" types, variables, and functions to "Curves"
Based on discussions from T95355 and T94193, the plan is to use
the name "Curves" to describe the data-block container for multiple
curves. Eventually this will replace the existing "Curve" data-block.
However, it will be a while before the curve data-block can be replaced
so in order to distinguish the two curve types in the UI, "Hair Curves"
will be used, but eventually changed back to "Curves".
This patch renames "hair-related" files, functions, types, and variable
names to this convention. A deep rename is preferred to keep code
consistent and to avoid any "hair" terminology from leaking, since the
new data-block is meant for all curve types, not just hair use cases.
The downside of this naming is that the difference between "Curve"
and "Curves" has become important. That was considered during
design discussons and deemed acceptable, especially given the
non-permanent nature of the somewhat common conflict.
Some points of interest:
- All DNA compatibility is lost, just like rBf59767ff9729.
- I renamed `ID_HA` to `ID_CV` so there is no complete mismatch.
- `hair_curves` is used where necessary to distinguish from the
existing "curves" plural.
- I didn't rename any of the cycles/rendering code function names,
since that is also used by the old hair particle system.
Differential Revision: https://developer.blender.org/D14007
2022-02-07 11:55:54 -06:00
|
|
|
case OB_CURVES:
|
|
|
|
|
bb = BKE_curves_boundbox_get(ob);
|
2020-03-17 14:41:48 +01:00
|
|
|
break;
|
|
|
|
|
case OB_POINTCLOUD:
|
|
|
|
|
bb = BKE_pointcloud_boundbox_get(ob);
|
|
|
|
|
break;
|
|
|
|
|
case OB_VOLUME:
|
|
|
|
|
bb = BKE_volume_boundbox_get(ob);
|
|
|
|
|
break;
|
2018-10-29 12:06:27 +01:00
|
|
|
default:
|
|
|
|
|
break;
|
2015-08-13 18:12:08 +02:00
|
|
|
}
|
2006-06-14 08:50:41 +00:00
|
|
|
return bb;
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-04 16:51:37 -03:00
|
|
|
void BKE_object_boundbox_calc_from_mesh(Object *ob, const Mesh *me_eval)
|
2018-10-15 17:14:05 +11:00
|
|
|
{
|
2022-04-01 14:48:48 -05:00
|
|
|
float3 min(FLT_MAX);
|
|
|
|
|
float3 max(-FLT_MAX);
|
2018-10-15 17:14:05 +11:00
|
|
|
|
2020-05-25 20:16:42 +10:00
|
|
|
if (!BKE_mesh_wrapper_minmax(me_eval, min, max)) {
|
2022-04-01 14:48:48 -05:00
|
|
|
min = float3(0);
|
|
|
|
|
max = float3(0);
|
2018-12-10 19:27:49 +11:00
|
|
|
}
|
2018-10-15 17:14:05 +11:00
|
|
|
|
2021-11-04 16:51:37 -03:00
|
|
|
if (ob->runtime.bb == nullptr) {
|
2021-12-24 22:17:49 -05:00
|
|
|
ob->runtime.bb = MEM_cnew<BoundBox>("DM-BoundBox");
|
2018-10-15 17:14:05 +11:00
|
|
|
}
|
|
|
|
|
|
2019-02-17 12:24:08 +11:00
|
|
|
BKE_boundbox_init_from_minmax(ob->runtime.bb, min, max);
|
2018-10-15 17:14:05 +11:00
|
|
|
|
2019-02-17 12:24:08 +11:00
|
|
|
ob->runtime.bb->flag &= ~BOUNDBOX_DIRTY;
|
2018-10-15 17:14:05 +11:00
|
|
|
}
|
|
|
|
|
|
2021-11-24 14:32:19 -03:00
|
|
|
bool BKE_object_boundbox_calc_from_evaluated_geometry(Object *ob)
|
|
|
|
|
{
|
2022-04-01 14:48:48 -05:00
|
|
|
float3 min(FLT_MAX);
|
|
|
|
|
float3 max(-FLT_MAX);
|
2021-11-24 14:32:19 -03:00
|
|
|
|
|
|
|
|
if (ob->runtime.geometry_set_eval) {
|
2021-12-29 12:27:24 -03:00
|
|
|
if (!ob->runtime.geometry_set_eval->compute_boundbox_without_instances(&min, &max)) {
|
2022-04-01 14:48:48 -05:00
|
|
|
min = float3(0);
|
|
|
|
|
max = float3(0);
|
2021-12-29 12:27:24 -03:00
|
|
|
}
|
2021-11-24 14:32:19 -03:00
|
|
|
}
|
|
|
|
|
else if (const Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob)) {
|
|
|
|
|
if (!BKE_mesh_wrapper_minmax(mesh_eval, min, max)) {
|
2022-04-01 14:48:48 -05:00
|
|
|
min = float3(0);
|
|
|
|
|
max = float3(0);
|
2021-11-24 14:32:19 -03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (ob->runtime.curve_cache) {
|
|
|
|
|
BKE_displist_minmax(&ob->runtime.curve_cache->disp, min, max);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ob->runtime.bb == nullptr) {
|
2021-12-24 22:17:49 -05:00
|
|
|
ob->runtime.bb = MEM_cnew<BoundBox>(__func__);
|
2021-11-24 14:32:19 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BKE_boundbox_init_from_minmax(ob->runtime.bb, min, max);
|
|
|
|
|
|
|
|
|
|
ob->runtime.bb->flag &= ~BOUNDBOX_DIRTY;
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-07 22:20:41 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
2019-09-06 20:00:45 +10:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Object Dimension Get/Set
|
|
|
|
|
*
|
|
|
|
|
* \warning Setting dimensions is prone to feedback loops in evaluation.
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2020-08-02 17:17:31 +10:00
|
|
|
void BKE_object_dimensions_get(Object *ob, float r_vec[3])
|
2010-03-25 06:27:25 +00:00
|
|
|
{
|
2022-04-01 13:45:02 -05:00
|
|
|
const BoundBox *bb = BKE_object_boundbox_get(ob);
|
2010-03-25 06:27:25 +00:00
|
|
|
if (bb) {
|
2022-04-01 14:48:48 -05:00
|
|
|
float3 scale;
|
2012-04-29 15:47:02 +00:00
|
|
|
mat4_to_size(scale, ob->obmat);
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2020-08-02 17:17:31 +10:00
|
|
|
r_vec[0] = fabsf(scale[0]) * (bb->vec[4][0] - bb->vec[0][0]);
|
|
|
|
|
r_vec[1] = fabsf(scale[1]) * (bb->vec[2][1] - bb->vec[0][1]);
|
|
|
|
|
r_vec[2] = fabsf(scale[2]) * (bb->vec[1][2] - bb->vec[0][2]);
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2020-08-02 17:17:31 +10:00
|
|
|
zero_v3(r_vec);
|
2010-03-25 06:27:25 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-06 20:00:45 +10:00
|
|
|
void BKE_object_dimensions_set_ex(Object *ob,
|
|
|
|
|
const float value[3],
|
|
|
|
|
int axis_mask,
|
|
|
|
|
const float ob_scale_orig[3],
|
|
|
|
|
const float ob_obmat_orig[4][4])
|
2010-03-25 06:27:25 +00:00
|
|
|
{
|
2022-04-01 13:45:02 -05:00
|
|
|
const BoundBox *bb = BKE_object_boundbox_get(ob);
|
2010-03-25 06:27:25 +00:00
|
|
|
if (bb) {
|
2022-04-01 14:48:48 -05:00
|
|
|
float3 len;
|
|
|
|
|
len.x = bb->vec[4][0] - bb->vec[0][0];
|
|
|
|
|
len.y = bb->vec[2][1] - bb->vec[0][1];
|
|
|
|
|
len.z = bb->vec[1][2] - bb->vec[0][2];
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2019-01-04 19:52:13 +11:00
|
|
|
for (int i = 0; i < 3; i++) {
|
|
|
|
|
if (((1 << i) & axis_mask) == 0) {
|
2019-09-06 20:00:45 +10:00
|
|
|
|
2021-11-04 16:51:37 -03:00
|
|
|
if (ob_scale_orig != nullptr) {
|
2019-09-06 20:00:45 +10:00
|
|
|
const float scale_delta = len_v3(ob_obmat_orig[i]) / ob_scale_orig[i];
|
|
|
|
|
if (isfinite(scale_delta)) {
|
|
|
|
|
len[i] *= scale_delta;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-26 21:54:08 +10:00
|
|
|
const float scale = copysignf(value[i] / len[i], ob->scale[i]);
|
|
|
|
|
if (isfinite(scale)) {
|
|
|
|
|
ob->scale[i] = scale;
|
2019-01-04 19:52:13 +11:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-03-25 06:27:25 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-06 20:00:45 +10:00
|
|
|
void BKE_object_dimensions_set(Object *ob, const float value[3], int axis_mask)
|
|
|
|
|
{
|
2021-11-04 16:51:37 -03:00
|
|
|
BKE_object_dimensions_set_ex(ob, value, axis_mask, nullptr, nullptr);
|
2019-09-06 20:00:45 +10:00
|
|
|
}
|
|
|
|
|
|
2020-09-04 20:59:13 +02:00
|
|
|
void BKE_object_minmax(Object *ob, float r_min[3], float r_max[3], const bool use_hidden)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2013-11-26 06:39:14 +11:00
|
|
|
bool changed = false;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-04-28 06:31:57 +00:00
|
|
|
switch (ob->type) {
|
2022-02-18 09:50:29 -06:00
|
|
|
case OB_CURVES_LEGACY:
|
2012-05-06 15:15:33 +00:00
|
|
|
case OB_FONT:
|
|
|
|
|
case OB_SURF: {
|
2022-04-01 13:45:02 -05:00
|
|
|
const BoundBox bb = *BKE_curve_boundbox_get(ob);
|
2020-09-04 20:59:13 +02:00
|
|
|
BKE_boundbox_minmax(&bb, ob->obmat, r_min, r_max);
|
2013-11-26 06:39:14 +11:00
|
|
|
changed = true;
|
2013-07-19 10:40:12 +00:00
|
|
|
break;
|
2011-06-06 07:29:57 +00:00
|
|
|
}
|
2019-03-20 00:05:58 +11:00
|
|
|
case OB_MESH: {
|
2022-04-01 13:45:02 -05:00
|
|
|
const BoundBox bb = *BKE_mesh_boundbox_get(ob);
|
2020-09-04 20:59:13 +02:00
|
|
|
BKE_boundbox_minmax(&bb, ob->obmat, r_min, r_max);
|
2019-03-20 00:05:58 +11:00
|
|
|
changed = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case OB_GPENCIL: {
|
2022-04-01 13:45:02 -05:00
|
|
|
const BoundBox bb = *BKE_gpencil_boundbox_get(ob);
|
2020-09-04 20:59:13 +02:00
|
|
|
BKE_boundbox_minmax(&bb, ob->obmat, r_min, r_max);
|
2019-03-20 00:05:58 +11:00
|
|
|
changed = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2012-05-06 15:15:33 +00:00
|
|
|
case OB_LATTICE: {
|
2021-11-04 16:51:37 -03:00
|
|
|
Lattice *lt = (Lattice *)ob->data;
|
2012-05-06 15:15:33 +00:00
|
|
|
BPoint *bp = lt->def;
|
2011-06-06 07:29:57 +00:00
|
|
|
int u, v, w;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
for (w = 0; w < lt->pntsw; w++) {
|
|
|
|
|
for (v = 0; v < lt->pntsv; v++) {
|
|
|
|
|
for (u = 0; u < lt->pntsu; u++, bp++) {
|
2022-04-01 14:48:48 -05:00
|
|
|
float3 vec;
|
2011-06-06 07:29:57 +00:00
|
|
|
mul_v3_m4v3(vec, ob->obmat, bp->vec);
|
2020-09-04 20:59:13 +02:00
|
|
|
minmax_v3v3_v3(r_min, r_max, vec);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2011-06-06 07:29:57 +00:00
|
|
|
}
|
|
|
|
|
}
|
2013-11-26 06:39:14 +11:00
|
|
|
changed = true;
|
2013-07-19 10:40:12 +00:00
|
|
|
break;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2012-05-06 15:15:33 +00:00
|
|
|
case OB_ARMATURE: {
|
2020-09-04 20:59:13 +02:00
|
|
|
changed = BKE_pose_minmax(ob, r_min, r_max, use_hidden, false);
|
2012-05-06 15:15:33 +00:00
|
|
|
break;
|
2013-07-19 10:40:12 +00:00
|
|
|
}
|
2013-06-28 18:19:55 +00:00
|
|
|
case OB_MBALL: {
|
|
|
|
|
float ob_min[3], ob_max[3];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-11-04 16:51:37 -03:00
|
|
|
changed = BKE_mball_minmax_ex((const MetaBall *)ob->data, ob_min, ob_max, ob->obmat, 0);
|
2013-11-26 06:39:14 +11:00
|
|
|
if (changed) {
|
2020-09-04 20:59:13 +02:00
|
|
|
minmax_v3v3_v3(r_min, r_max, ob_min);
|
|
|
|
|
minmax_v3v3_v3(r_min, r_max, ob_max);
|
2013-06-28 18:19:55 +00:00
|
|
|
}
|
|
|
|
|
break;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
Curves: Rename "Hair" types, variables, and functions to "Curves"
Based on discussions from T95355 and T94193, the plan is to use
the name "Curves" to describe the data-block container for multiple
curves. Eventually this will replace the existing "Curve" data-block.
However, it will be a while before the curve data-block can be replaced
so in order to distinguish the two curve types in the UI, "Hair Curves"
will be used, but eventually changed back to "Curves".
This patch renames "hair-related" files, functions, types, and variable
names to this convention. A deep rename is preferred to keep code
consistent and to avoid any "hair" terminology from leaking, since the
new data-block is meant for all curve types, not just hair use cases.
The downside of this naming is that the difference between "Curve"
and "Curves" has become important. That was considered during
design discussons and deemed acceptable, especially given the
non-permanent nature of the somewhat common conflict.
Some points of interest:
- All DNA compatibility is lost, just like rBf59767ff9729.
- I renamed `ID_HA` to `ID_CV` so there is no complete mismatch.
- `hair_curves` is used where necessary to distinguish from the
existing "curves" plural.
- I didn't rename any of the cycles/rendering code function names,
since that is also used by the old hair particle system.
Differential Revision: https://developer.blender.org/D14007
2022-02-07 11:55:54 -06:00
|
|
|
case OB_CURVES: {
|
2022-04-01 13:45:02 -05:00
|
|
|
const BoundBox bb = *BKE_curves_boundbox_get(ob);
|
2020-09-04 20:59:13 +02:00
|
|
|
BKE_boundbox_minmax(&bb, ob->obmat, r_min, r_max);
|
2020-03-17 14:41:48 +01:00
|
|
|
changed = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case OB_POINTCLOUD: {
|
2022-04-01 13:45:02 -05:00
|
|
|
const BoundBox bb = *BKE_pointcloud_boundbox_get(ob);
|
2020-09-04 20:59:13 +02:00
|
|
|
BKE_boundbox_minmax(&bb, ob->obmat, r_min, r_max);
|
2020-03-17 14:41:48 +01:00
|
|
|
changed = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case OB_VOLUME: {
|
2022-04-01 13:45:02 -05:00
|
|
|
const BoundBox bb = *BKE_volume_boundbox_get(ob);
|
2020-09-04 20:59:13 +02:00
|
|
|
BKE_boundbox_minmax(&bb, ob->obmat, r_min, r_max);
|
2020-03-17 14:41:48 +01:00
|
|
|
changed = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2013-06-28 18:19:55 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-11-26 06:39:14 +11:00
|
|
|
if (changed == false) {
|
2022-04-01 14:48:48 -05:00
|
|
|
float3 size = ob->scale;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-18 15:43:06 +11:00
|
|
|
copy_v3_v3(size, ob->scale);
|
2019-02-27 20:46:04 +01:00
|
|
|
if (ob->type == OB_EMPTY) {
|
2022-04-01 14:48:48 -05:00
|
|
|
size *= ob->empty_drawsize;
|
2012-07-12 10:27:22 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-09-04 20:59:13 +02:00
|
|
|
minmax_v3v3_v3(r_min, r_max, ob->obmat[3]);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-04-01 14:48:48 -05:00
|
|
|
float3 vec;
|
2010-04-23 23:57:00 +00:00
|
|
|
copy_v3_v3(vec, ob->obmat[3]);
|
2012-07-12 10:27:22 +00:00
|
|
|
add_v3_v3(vec, size);
|
2020-09-04 20:59:13 +02:00
|
|
|
minmax_v3v3_v3(r_min, r_max, vec);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2010-04-23 23:57:00 +00:00
|
|
|
copy_v3_v3(vec, ob->obmat[3]);
|
2012-07-12 10:27:22 +00:00
|
|
|
sub_v3_v3(vec, size);
|
2020-09-04 20:59:13 +02:00
|
|
|
minmax_v3v3_v3(r_min, r_max, vec);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-13 21:57:05 +01:00
|
|
|
void BKE_object_empty_draw_type_set(Object *ob, const int value)
|
|
|
|
|
{
|
2014-02-03 13:55:26 +11:00
|
|
|
ob->empty_drawtype = value;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-02-03 13:55:26 +11:00
|
|
|
if (ob->type == OB_EMPTY && ob->empty_drawtype == OB_EMPTY_IMAGE) {
|
|
|
|
|
if (!ob->iuser) {
|
2021-12-24 22:17:49 -05:00
|
|
|
ob->iuser = MEM_cnew<ImageUser>("image user");
|
2018-05-24 21:19:38 +02:00
|
|
|
ob->iuser->flag |= IMA_ANIM_ALWAYS;
|
2014-02-03 13:55:26 +11:00
|
|
|
ob->iuser->frames = 100;
|
|
|
|
|
ob->iuser->sfra = 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
2021-08-06 13:59:38 +10:00
|
|
|
MEM_SAFE_FREE(ob->iuser);
|
2014-02-03 13:55:26 +11:00
|
|
|
}
|
2014-01-13 21:57:05 +01:00
|
|
|
}
|
|
|
|
|
|
2019-03-07 11:26:28 +11:00
|
|
|
bool BKE_object_empty_image_frame_is_visible_in_view3d(const Object *ob, const RegionView3D *rv3d)
|
2018-12-11 15:08:18 +11:00
|
|
|
{
|
2019-03-07 11:26:28 +11:00
|
|
|
const char visibility_flag = ob->empty_image_visibility_flag;
|
|
|
|
|
if (rv3d->is_persp) {
|
|
|
|
|
return (visibility_flag & OB_EMPTY_IMAGE_HIDE_PERSPECTIVE) == 0;
|
|
|
|
|
}
|
2020-08-07 12:30:43 +02:00
|
|
|
|
|
|
|
|
return (visibility_flag & OB_EMPTY_IMAGE_HIDE_ORTHOGRAPHIC) == 0;
|
2019-03-07 11:26:28 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool BKE_object_empty_image_data_is_visible_in_view3d(const Object *ob, const RegionView3D *rv3d)
|
|
|
|
|
{
|
|
|
|
|
/* Caller is expected to check this. */
|
|
|
|
|
BLI_assert(BKE_object_empty_image_frame_is_visible_in_view3d(ob, rv3d));
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-07 11:26:28 +11:00
|
|
|
const char visibility_flag = ob->empty_image_visibility_flag;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-12-17 14:49:16 +11:00
|
|
|
if ((visibility_flag & (OB_EMPTY_IMAGE_HIDE_BACK | OB_EMPTY_IMAGE_HIDE_FRONT)) != 0) {
|
2019-02-05 10:39:43 +11:00
|
|
|
float eps, dot;
|
|
|
|
|
if (rv3d->is_persp) {
|
2021-07-03 23:08:40 +10:00
|
|
|
/* NOTE: we could normalize the 'view_dir' then use 'eps'
|
2019-02-05 10:39:43 +11:00
|
|
|
* however the issue with empty objects being visible when viewed from the side
|
|
|
|
|
* is only noticeable in orthographic views. */
|
2022-04-01 14:48:48 -05:00
|
|
|
float3 view_dir;
|
2019-02-05 10:39:43 +11:00
|
|
|
sub_v3_v3v3(view_dir, rv3d->viewinv[3], ob->obmat[3]);
|
|
|
|
|
dot = dot_v3v3(ob->obmat[2], view_dir);
|
|
|
|
|
eps = 0.0f;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
dot = dot_v3v3(ob->obmat[2], rv3d->viewinv[2]);
|
|
|
|
|
eps = 1e-5f;
|
|
|
|
|
}
|
2018-12-17 14:49:16 +11:00
|
|
|
if (visibility_flag & OB_EMPTY_IMAGE_HIDE_BACK) {
|
2019-02-05 10:29:19 +11:00
|
|
|
if (dot < eps) {
|
2018-12-17 14:49:16 +11:00
|
|
|
return false;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2018-12-17 14:49:16 +11:00
|
|
|
}
|
|
|
|
|
if (visibility_flag & OB_EMPTY_IMAGE_HIDE_FRONT) {
|
2019-02-05 10:29:19 +11:00
|
|
|
if (dot > -eps) {
|
2018-12-17 14:49:16 +11:00
|
|
|
return false;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2018-12-17 14:49:16 +11:00
|
|
|
}
|
2018-12-11 15:08:18 +11:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-09-03 18:55:26 +10:00
|
|
|
if (visibility_flag & OB_EMPTY_IMAGE_HIDE_NON_AXIS_ALIGNED) {
|
2022-04-05 17:17:03 +02:00
|
|
|
float3 proj, ob_z_axis;
|
|
|
|
|
normalize_v3_v3(ob_z_axis, ob->obmat[2]);
|
|
|
|
|
project_plane_v3_v3v3(proj, ob_z_axis, rv3d->viewinv[2]);
|
2019-09-03 18:55:26 +10:00
|
|
|
const float proj_length_sq = len_squared_v3(proj);
|
|
|
|
|
if (proj_length_sq > 1e-5f) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-07 11:26:28 +11:00
|
|
|
return true;
|
2018-12-11 15:08:18 +11:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-07-07 14:57:43 +10:00
|
|
|
bool BKE_object_minmax_empty_drawtype(const struct Object *ob, float r_min[3], float r_max[3])
|
|
|
|
|
{
|
|
|
|
|
BLI_assert(ob->type == OB_EMPTY);
|
|
|
|
|
float3 min(0), max(0);
|
|
|
|
|
|
|
|
|
|
bool ok = false;
|
|
|
|
|
const float radius = ob->empty_drawsize;
|
|
|
|
|
|
|
|
|
|
switch (ob->empty_drawtype) {
|
|
|
|
|
case OB_ARROWS: {
|
|
|
|
|
max = float3(radius);
|
|
|
|
|
ok = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case OB_PLAINAXES:
|
|
|
|
|
case OB_CUBE:
|
|
|
|
|
case OB_EMPTY_SPHERE: {
|
|
|
|
|
min = float3(-radius);
|
|
|
|
|
max = float3(radius);
|
|
|
|
|
ok = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case OB_CIRCLE: {
|
|
|
|
|
max[0] = max[2] = radius;
|
|
|
|
|
min[0] = min[2] = -radius;
|
|
|
|
|
ok = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case OB_SINGLE_ARROW: {
|
|
|
|
|
max[2] = radius;
|
|
|
|
|
ok = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case OB_EMPTY_CONE: {
|
|
|
|
|
min = float3(-radius, 0.0f, -radius);
|
|
|
|
|
max = float3(radius, radius * 2.0f, radius);
|
|
|
|
|
ok = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case OB_EMPTY_IMAGE: {
|
|
|
|
|
const float *ofs = ob->ima_ofs;
|
|
|
|
|
/* NOTE: this is the best approximation that can be calculated without loading the image. */
|
|
|
|
|
min[0] = ofs[0] * radius;
|
|
|
|
|
min[1] = ofs[1] * radius;
|
|
|
|
|
max[0] = radius + (ofs[0] * radius);
|
|
|
|
|
max[1] = radius + (ofs[1] * radius);
|
|
|
|
|
/* Since the image aspect can shrink the bounds towards the object origin,
|
|
|
|
|
* adjust the min/max to account for that. */
|
|
|
|
|
for (int i = 0; i < 2; i++) {
|
|
|
|
|
CLAMP_MAX(min[i], 0.0f);
|
|
|
|
|
CLAMP_MIN(max[i], 0.0f);
|
|
|
|
|
}
|
|
|
|
|
ok = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ok) {
|
|
|
|
|
copy_v3_v3(r_min, min);
|
|
|
|
|
copy_v3_v3(r_max, max);
|
|
|
|
|
}
|
|
|
|
|
return ok;
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-06 12:07:27 +02:00
|
|
|
bool BKE_object_minmax_dupli(Depsgraph *depsgraph,
|
|
|
|
|
Scene *scene,
|
|
|
|
|
Object *ob,
|
|
|
|
|
float r_min[3],
|
|
|
|
|
float r_max[3],
|
|
|
|
|
const bool use_hidden)
|
2007-04-14 13:18:24 +00:00
|
|
|
{
|
2013-06-09 21:25:27 +00:00
|
|
|
bool ok = false;
|
2021-11-04 16:51:37 -03:00
|
|
|
if ((ob->transflag & OB_DUPLI) == 0 && ob->runtime.geometry_set_eval == nullptr) {
|
2010-02-24 20:11:35 +00:00
|
|
|
return ok;
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-12-22 10:35:18 -06:00
|
|
|
ListBase *lb = object_duplilist(depsgraph, scene, ob);
|
2021-11-04 16:51:37 -03:00
|
|
|
LISTBASE_FOREACH (DupliObject *, dob, lb) {
|
2022-02-16 18:58:01 +01:00
|
|
|
if (((use_hidden == false) && (dob->no_draw != 0)) || dob->ob_data == nullptr) {
|
2020-08-07 12:30:43 +02:00
|
|
|
/* pass */
|
|
|
|
|
}
|
|
|
|
|
else {
|
2022-03-23 12:05:47 +01:00
|
|
|
Object temp_ob = blender::dna::shallow_copy(*dob->ob);
|
2022-02-01 11:58:53 +01:00
|
|
|
/* Do not modify the original boundbox. */
|
|
|
|
|
temp_ob.runtime.bb = nullptr;
|
|
|
|
|
BKE_object_replace_data_on_shallow_copy(&temp_ob, dob->ob_data);
|
2022-04-01 13:45:02 -05:00
|
|
|
const BoundBox *bb = BKE_object_boundbox_get(&temp_ob);
|
2020-08-07 12:30:43 +02:00
|
|
|
|
|
|
|
|
if (bb) {
|
|
|
|
|
int i;
|
|
|
|
|
for (i = 0; i < 8; i++) {
|
2022-04-01 14:48:48 -05:00
|
|
|
float3 vec;
|
2020-08-07 12:30:43 +02:00
|
|
|
mul_v3_m4v3(vec, dob->mat, bb->vec[i]);
|
|
|
|
|
minmax_v3v3_v3(r_min, r_max, vec);
|
2007-04-14 13:18:24 +00:00
|
|
|
}
|
2020-08-07 12:30:43 +02:00
|
|
|
|
|
|
|
|
ok = true;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2022-02-01 11:58:53 +01:00
|
|
|
|
|
|
|
|
MEM_SAFE_FREE(temp_ob.runtime.bb);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2007-04-14 13:18:24 +00:00
|
|
|
}
|
2020-08-07 12:30:43 +02:00
|
|
|
free_object_duplilist(lb); /* does restore */
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2010-02-24 20:11:35 +00:00
|
|
|
return ok;
|
2007-04-14 13:18:24 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-07-08 14:17:47 +02:00
|
|
|
struct GPencilStrokePointIterData {
|
|
|
|
|
const float (*obmat)[4];
|
|
|
|
|
|
|
|
|
|
void (*point_func_cb)(const float co[3], void *user_data);
|
|
|
|
|
void *user_data;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static void foreach_display_point_gpencil_stroke_fn(bGPDlayer *UNUSED(layer),
|
|
|
|
|
bGPDframe *UNUSED(frame),
|
|
|
|
|
bGPDstroke *stroke,
|
|
|
|
|
void *thunk)
|
|
|
|
|
{
|
2021-11-04 16:51:37 -03:00
|
|
|
GPencilStrokePointIterData *iter_data = (GPencilStrokePointIterData *)thunk;
|
2021-07-08 14:17:47 +02:00
|
|
|
{
|
|
|
|
|
bGPDspoint *pt;
|
|
|
|
|
int i;
|
|
|
|
|
for (i = 0, pt = stroke->points; i < stroke->totpoints; i++, pt++) {
|
2022-04-01 14:48:48 -05:00
|
|
|
float3 co;
|
2021-07-08 14:17:47 +02:00
|
|
|
mul_v3_m4v3(co, iter_data->obmat, &pt->x);
|
|
|
|
|
iter_data->point_func_cb(co, iter_data->user_data);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-11-14 03:54:23 +00:00
|
|
|
void BKE_object_foreach_display_point(Object *ob,
|
2020-08-02 17:17:31 +10:00
|
|
|
const float obmat[4][4],
|
2011-11-14 03:54:23 +00:00
|
|
|
void (*func_cb)(const float[3], void *),
|
|
|
|
|
void *user_data)
|
|
|
|
|
{
|
2022-03-30 18:25:06 -05:00
|
|
|
/* TODO: pointcloud and curves object support */
|
2021-07-01 23:03:09 -05:00
|
|
|
const Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob);
|
2022-04-01 14:48:48 -05:00
|
|
|
float3 co;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-11-04 16:51:37 -03:00
|
|
|
if (mesh_eval != nullptr) {
|
2020-02-27 11:23:15 +01:00
|
|
|
const MVert *mv = mesh_eval->mvert;
|
|
|
|
|
const int totvert = mesh_eval->totvert;
|
2018-06-22 07:54:55 +02:00
|
|
|
for (int i = 0; i < totvert; i++, mv++) {
|
2011-11-14 03:54:23 +00:00
|
|
|
mul_v3_m4v3(co, obmat, mv->co);
|
|
|
|
|
func_cb(co, user_data);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2021-07-08 14:17:47 +02:00
|
|
|
else if (ob->type == OB_GPENCIL) {
|
2021-11-08 12:40:08 -03:00
|
|
|
GPencilStrokePointIterData iter_data{};
|
2021-11-04 16:51:37 -03:00
|
|
|
iter_data.obmat = obmat;
|
|
|
|
|
iter_data.point_func_cb = func_cb;
|
|
|
|
|
iter_data.user_data = user_data;
|
2021-07-08 14:17:47 +02:00
|
|
|
|
|
|
|
|
BKE_gpencil_visible_stroke_iter(
|
2021-11-04 16:51:37 -03:00
|
|
|
(bGPdata *)ob->data, nullptr, foreach_display_point_gpencil_stroke_fn, &iter_data);
|
2021-07-08 14:17:47 +02:00
|
|
|
}
|
2018-07-30 16:54:40 +02:00
|
|
|
else if (ob->runtime.curve_cache && ob->runtime.curve_cache->disp.first) {
|
2021-11-04 16:51:37 -03:00
|
|
|
LISTBASE_FOREACH (DispList *, dl, &ob->runtime.curve_cache->disp) {
|
2014-04-27 00:20:13 +10:00
|
|
|
const float *v3 = dl->verts;
|
2012-05-06 15:15:33 +00:00
|
|
|
int totvert = dl->nr;
|
2011-11-14 03:54:23 +00:00
|
|
|
int i;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
for (i = 0; i < totvert; i++, v3 += 3) {
|
2011-11-14 03:54:23 +00:00
|
|
|
mul_v3_m4v3(co, obmat, v3);
|
|
|
|
|
func_cb(co, user_data);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-11-14 03:54:23 +00:00
|
|
|
void BKE_scene_foreach_display_point(Depsgraph *depsgraph,
|
|
|
|
|
void (*func_cb)(const float[3], void *),
|
|
|
|
|
void *user_data)
|
|
|
|
|
{
|
2018-06-22 07:54:55 +02:00
|
|
|
DEG_OBJECT_ITER_BEGIN (depsgraph,
|
|
|
|
|
ob,
|
|
|
|
|
DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | DEG_ITER_OBJECT_FLAG_VISIBLE |
|
|
|
|
|
DEG_ITER_OBJECT_FLAG_DUPLI) {
|
|
|
|
|
if ((ob->base_flag & BASE_SELECTED) != 0) {
|
|
|
|
|
BKE_object_foreach_display_point(ob, ob->obmat, func_cb, user_data);
|
2011-11-14 03:54:23 +00:00
|
|
|
}
|
|
|
|
|
}
|
2018-06-22 07:54:55 +02:00
|
|
|
DEG_OBJECT_ITER_END;
|
2011-11-14 03:54:23 +00:00
|
|
|
}
|
|
|
|
|
|
2021-12-14 15:49:31 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Object Transform Channels (Backup/Restore)
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2020-09-07 14:33:24 +10:00
|
|
|
/**
|
2021-11-08 14:14:15 +11:00
|
|
|
* See struct members from #Object in DNA_object_types.h
|
2020-09-07 14:33:24 +10:00
|
|
|
*/
|
2021-11-04 16:51:37 -03:00
|
|
|
struct ObTfmBack {
|
2019-02-18 16:31:02 +11:00
|
|
|
float loc[3], dloc[3];
|
|
|
|
|
float scale[3], dscale[3];
|
2019-01-08 10:28:20 +11:00
|
|
|
float rot[3], drot[3];
|
|
|
|
|
float quat[4], dquat[4];
|
|
|
|
|
float rotAxis[3], drotAxis[3];
|
|
|
|
|
float rotAngle, drotAngle;
|
|
|
|
|
float obmat[4][4];
|
|
|
|
|
float parentinv[4][4];
|
|
|
|
|
float constinv[4][4];
|
|
|
|
|
float imat[4][4];
|
2021-11-04 16:51:37 -03:00
|
|
|
};
|
2010-02-26 08:47:20 +00:00
|
|
|
|
2012-05-05 14:03:12 +00:00
|
|
|
void *BKE_object_tfm_backup(Object *ob)
|
2010-02-26 08:47:20 +00:00
|
|
|
{
|
2021-11-04 16:51:37 -03:00
|
|
|
ObTfmBack *obtfm = (ObTfmBack *)MEM_mallocN(sizeof(ObTfmBack), "ObTfmBack");
|
2010-02-26 08:47:20 +00:00
|
|
|
copy_v3_v3(obtfm->loc, ob->loc);
|
|
|
|
|
copy_v3_v3(obtfm->dloc, ob->dloc);
|
2019-02-18 16:31:02 +11:00
|
|
|
copy_v3_v3(obtfm->scale, ob->scale);
|
2011-12-04 03:35:54 +00:00
|
|
|
copy_v3_v3(obtfm->dscale, ob->dscale);
|
2010-02-26 08:47:20 +00:00
|
|
|
copy_v3_v3(obtfm->rot, ob->rot);
|
|
|
|
|
copy_v3_v3(obtfm->drot, ob->drot);
|
|
|
|
|
copy_qt_qt(obtfm->quat, ob->quat);
|
|
|
|
|
copy_qt_qt(obtfm->dquat, ob->dquat);
|
|
|
|
|
copy_v3_v3(obtfm->rotAxis, ob->rotAxis);
|
|
|
|
|
copy_v3_v3(obtfm->drotAxis, ob->drotAxis);
|
2012-05-06 15:15:33 +00:00
|
|
|
obtfm->rotAngle = ob->rotAngle;
|
|
|
|
|
obtfm->drotAngle = ob->drotAngle;
|
2010-02-26 08:47:20 +00:00
|
|
|
copy_m4_m4(obtfm->obmat, ob->obmat);
|
|
|
|
|
copy_m4_m4(obtfm->parentinv, ob->parentinv);
|
|
|
|
|
copy_m4_m4(obtfm->constinv, ob->constinv);
|
|
|
|
|
copy_m4_m4(obtfm->imat, ob->imat);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2010-02-26 08:47:20 +00:00
|
|
|
return (void *)obtfm;
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-05 14:03:12 +00:00
|
|
|
void BKE_object_tfm_restore(Object *ob, void *obtfm_pt)
|
2010-02-26 08:47:20 +00:00
|
|
|
{
|
2012-05-06 15:15:33 +00:00
|
|
|
ObTfmBack *obtfm = (ObTfmBack *)obtfm_pt;
|
2010-02-26 08:47:20 +00:00
|
|
|
copy_v3_v3(ob->loc, obtfm->loc);
|
|
|
|
|
copy_v3_v3(ob->dloc, obtfm->dloc);
|
2019-02-18 16:31:02 +11:00
|
|
|
copy_v3_v3(ob->scale, obtfm->scale);
|
2011-12-04 03:35:54 +00:00
|
|
|
copy_v3_v3(ob->dscale, obtfm->dscale);
|
2010-02-26 08:47:20 +00:00
|
|
|
copy_v3_v3(ob->rot, obtfm->rot);
|
|
|
|
|
copy_v3_v3(ob->drot, obtfm->drot);
|
|
|
|
|
copy_qt_qt(ob->quat, obtfm->quat);
|
|
|
|
|
copy_qt_qt(ob->dquat, obtfm->dquat);
|
|
|
|
|
copy_v3_v3(ob->rotAxis, obtfm->rotAxis);
|
|
|
|
|
copy_v3_v3(ob->drotAxis, obtfm->drotAxis);
|
2012-05-06 15:15:33 +00:00
|
|
|
ob->rotAngle = obtfm->rotAngle;
|
|
|
|
|
ob->drotAngle = obtfm->drotAngle;
|
2010-02-26 08:47:20 +00:00
|
|
|
copy_m4_m4(ob->obmat, obtfm->obmat);
|
|
|
|
|
copy_m4_m4(ob->parentinv, obtfm->parentinv);
|
|
|
|
|
copy_m4_m4(ob->constinv, obtfm->constinv);
|
|
|
|
|
copy_m4_m4(ob->imat, obtfm->imat);
|
|
|
|
|
}
|
2007-04-14 13:18:24 +00:00
|
|
|
|
2021-12-14 15:49:31 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Object Evaluation/Update API
|
|
|
|
|
* \{ */
|
2011-12-16 10:39:43 +00:00
|
|
|
|
2018-04-06 12:07:27 +02:00
|
|
|
void BKE_object_handle_update_ex(Depsgraph *depsgraph,
|
2013-12-26 17:24:42 +06:00
|
|
|
Scene *scene,
|
|
|
|
|
Object *ob,
|
2022-02-03 17:57:40 +01:00
|
|
|
RigidBodyWorld *rbw)
|
Result of 2 weeks of quiet coding work in Greece :)
Aim was to get a total refresh of the animation system. This
is needed because;
- we need to upgrade it with 21st century features
- current code is spaghetti/hack combo, and hides good design
- it should become lag-free with using dependency graphs
A full log, with complete code API/structure/design explanation
will follow, that's a load of work... so here below the list with
hot changes;
- The entire object update system (matrices, geometry) is now
centralized. Calls to where_is_object and makeDispList are
forbidden, instead we tag objects 'changed' and let the
depgraph code sort it out
- Removed all old "Ika" code
- Depgraph is aware of all relationships, including meta balls,
constraints, bevelcurve, and so on.
- Made depgraph aware of relation types and layers, to do smart
flushing of 'changed' events. Nothing gets calculated too often!
- Transform uses depgraph to detect changes
- On frame-advance, depgraph flushes animated changes
Armatures;
Almost all armature related code has been fully built from scratch.
It now reveils the original design much better, with a very clean
implementation, lag free without even calculating each Bone more than
once. Result is quite a speedup yes!
Important to note is;
1) Armature is data containing the 'rest position'
2) Pose is the changes of rest position, and always on object level.
That way more Objects can use same Pose. Also constraints are in Pose
3) Actions only contain the Ipos to change values in Poses.
- Bones draw unrotated now
- Drawing bones speedup enormously (10-20 times)
- Bone selecting in EditMode, selection state is saved for PoseMode,
and vice-versa
- Undo in editmode
- Bone renaming does vertexgroups, constraints, posechannels, actions,
for all users of Armature in entire file
- Added Bone renaming in NKey panel
- Nkey PoseMode shows eulers now
- EditMode and PoseMode now have 'active' bone too (last clicked)
- Parenting in EditMode' CTRL+P, ALT+P, with nice options!
- Pose is added in Outliner now, with showing that constraints are in
the Pose, not Armature
- Disconnected IK solving from constraints. It's a separate phase now,
on top of the full Pose calculations
- Pose itself has a dependency graph too, so evaluation order is lag free.
TODO NOW;
- Rotating in Posemode has incorrect inverse transform (Martin will fix)
- Python Bone/Armature/Pose API disabled... needs full recode too
(wait for my doc!)
- Game engine will need upgrade too
- Depgraph code needs revision, cleanup, can be much faster!
(But, compliments for Jean-Luc, it works like a charm!)
- IK changed, it now doesnt use previous position to advance to next
position anymore. That system looks nice (no flips) but is not well
suited for NLA and background render.
TODO LATER;
We now can do loadsa new nifty features as well; like:
- Kill PoseMode (can be option for armatures itself)
- Make B-Bones (Bezier, Bspline, like for spines)
- Move all silly button level edit to 3d window (like CTRL+I = add
IK)
- Much better & informative drawing
- Fix action/nla editors
- Put all ipos in Actions (object, mesh key, lamp color)
- Add hooks
- Null bones
- Much more advanced constraints...
Bugfixes;
- OGL render (view3d header) had wrong first frame on anim render
- Ipo 'recording' mode had wrong playback speed
- Vertex-key mode now sticks to show 'active key', until frame change
-Ton-
2005-07-03 17:35:38 +00:00
|
|
|
{
|
2021-11-04 16:51:37 -03:00
|
|
|
const ID *object_data = (ID *)ob->data;
|
2018-12-06 17:52:37 +01:00
|
|
|
const bool recalc_object = (ob->id.recalc & ID_RECALC_ALL) != 0;
|
2021-11-04 16:51:37 -03:00
|
|
|
const bool recalc_data = (object_data != nullptr) ?
|
|
|
|
|
((object_data->recalc & ID_RECALC_ALL) != 0) :
|
|
|
|
|
false;
|
2017-12-01 12:11:38 +01:00
|
|
|
if (!recalc_object && !recalc_data) {
|
2017-11-29 16:12:39 +01:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
/* Speed optimization for animation lookups. */
|
2021-11-04 16:51:37 -03:00
|
|
|
if (ob->pose != nullptr) {
|
2021-04-30 15:28:13 +10:00
|
|
|
BKE_pose_channels_hash_ensure(ob->pose);
|
2017-11-29 16:12:39 +01:00
|
|
|
if (ob->pose->flag & POSE_CONSTRAINTS_NEED_UPDATE_FLAGS) {
|
|
|
|
|
BKE_pose_update_constraint_flags(ob->pose);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2015-03-19 18:28:49 +05:00
|
|
|
}
|
2017-12-01 12:11:38 +01:00
|
|
|
if (recalc_data) {
|
2017-11-29 16:12:39 +01:00
|
|
|
if (ob->type == OB_ARMATURE) {
|
|
|
|
|
/* this happens for reading old files and to match library armatures
|
|
|
|
|
* with poses we do it ahead of BKE_object_where_is_calc to ensure animation
|
|
|
|
|
* is evaluated on the rebuilt pose, otherwise we get incorrect poses
|
|
|
|
|
* on file load */
|
2021-11-04 16:51:37 -03:00
|
|
|
if (ob->pose == nullptr || (ob->pose->flag & POSE_RECALC)) {
|
2018-07-19 16:48:21 +02:00
|
|
|
/* No need to pass bmain here, we assume we do not need to rebuild DEG from here... */
|
2021-11-04 16:51:37 -03:00
|
|
|
BKE_pose_rebuild(nullptr, ob, (bArmature *)ob->data, true);
|
2018-07-19 16:48:21 +02:00
|
|
|
}
|
2010-07-07 18:47:49 +00:00
|
|
|
}
|
2017-11-29 16:12:39 +01:00
|
|
|
}
|
2018-12-06 17:52:37 +01:00
|
|
|
/* XXX new animsys warning: depsgraph tag ID_RECALC_GEOMETRY should not skip drivers,
|
2017-11-29 16:12:39 +01:00
|
|
|
* which is only in BKE_object_where_is_calc now */
|
2018-12-06 17:52:37 +01:00
|
|
|
/* XXX: should this case be ID_RECALC_TRANSFORM instead? */
|
2017-12-01 12:11:38 +01:00
|
|
|
if (recalc_object || recalc_data) {
|
2018-02-21 10:44:36 +01:00
|
|
|
if (G.debug & G_DEBUG_DEPSGRAPH_EVAL) {
|
2017-11-29 16:12:39 +01:00
|
|
|
printf("recalcob %s\n", ob->id.name + 2);
|
2006-11-11 16:45:17 +00:00
|
|
|
}
|
2022-02-03 17:57:40 +01:00
|
|
|
BKE_object_where_is_calc_ex(depsgraph, scene, rbw, ob, nullptr);
|
2017-11-29 16:12:39 +01:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2017-12-01 12:11:38 +01:00
|
|
|
if (recalc_data) {
|
2018-04-06 12:07:27 +02:00
|
|
|
BKE_object_handle_data_update(depsgraph, scene, ob);
|
Result of 2 weeks of quiet coding work in Greece :)
Aim was to get a total refresh of the animation system. This
is needed because;
- we need to upgrade it with 21st century features
- current code is spaghetti/hack combo, and hides good design
- it should become lag-free with using dependency graphs
A full log, with complete code API/structure/design explanation
will follow, that's a load of work... so here below the list with
hot changes;
- The entire object update system (matrices, geometry) is now
centralized. Calls to where_is_object and makeDispList are
forbidden, instead we tag objects 'changed' and let the
depgraph code sort it out
- Removed all old "Ika" code
- Depgraph is aware of all relationships, including meta balls,
constraints, bevelcurve, and so on.
- Made depgraph aware of relation types and layers, to do smart
flushing of 'changed' events. Nothing gets calculated too often!
- Transform uses depgraph to detect changes
- On frame-advance, depgraph flushes animated changes
Armatures;
Almost all armature related code has been fully built from scratch.
It now reveils the original design much better, with a very clean
implementation, lag free without even calculating each Bone more than
once. Result is quite a speedup yes!
Important to note is;
1) Armature is data containing the 'rest position'
2) Pose is the changes of rest position, and always on object level.
That way more Objects can use same Pose. Also constraints are in Pose
3) Actions only contain the Ipos to change values in Poses.
- Bones draw unrotated now
- Drawing bones speedup enormously (10-20 times)
- Bone selecting in EditMode, selection state is saved for PoseMode,
and vice-versa
- Undo in editmode
- Bone renaming does vertexgroups, constraints, posechannels, actions,
for all users of Armature in entire file
- Added Bone renaming in NKey panel
- Nkey PoseMode shows eulers now
- EditMode and PoseMode now have 'active' bone too (last clicked)
- Parenting in EditMode' CTRL+P, ALT+P, with nice options!
- Pose is added in Outliner now, with showing that constraints are in
the Pose, not Armature
- Disconnected IK solving from constraints. It's a separate phase now,
on top of the full Pose calculations
- Pose itself has a dependency graph too, so evaluation order is lag free.
TODO NOW;
- Rotating in Posemode has incorrect inverse transform (Martin will fix)
- Python Bone/Armature/Pose API disabled... needs full recode too
(wait for my doc!)
- Game engine will need upgrade too
- Depgraph code needs revision, cleanup, can be much faster!
(But, compliments for Jean-Luc, it works like a charm!)
- IK changed, it now doesnt use previous position to advance to next
position anymore. That system looks nice (no flips) but is not well
suited for NLA and background render.
TODO LATER;
We now can do loadsa new nifty features as well; like:
- Kill PoseMode (can be option for armatures itself)
- Make B-Bones (Bezier, Bspline, like for spines)
- Move all silly button level edit to 3d window (like CTRL+I = add
IK)
- Much better & informative drawing
- Fix action/nla editors
- Put all ipos in Actions (object, mesh key, lamp color)
- Add hooks
- Null bones
- Much more advanced constraints...
Bugfixes;
- OGL render (view3d header) had wrong first frame on anim render
- Ipo 'recording' mode had wrong playback speed
- Vertex-key mode now sticks to show 'active key', until frame change
-Ton-
2005-07-03 17:35:38 +00:00
|
|
|
}
|
|
|
|
|
}
|
2017-11-29 16:12:39 +01:00
|
|
|
|
2018-04-06 12:07:27 +02:00
|
|
|
void BKE_object_handle_update(Depsgraph *depsgraph, Scene *scene, Object *ob)
|
2013-02-16 16:17:45 +00:00
|
|
|
{
|
2022-02-03 17:57:40 +01:00
|
|
|
BKE_object_handle_update_ex(depsgraph, scene, ob, nullptr);
|
2013-02-16 16:17:45 +00:00
|
|
|
}
|
2008-01-19 16:32:29 +00:00
|
|
|
|
2019-01-09 10:16:51 +11:00
|
|
|
void BKE_object_sculpt_data_create(Object *ob)
|
|
|
|
|
{
|
2021-11-04 16:51:37 -03:00
|
|
|
BLI_assert((ob->sculpt == nullptr) && (ob->mode & OB_MODE_ALL_SCULPT));
|
2021-12-24 22:17:49 -05:00
|
|
|
ob->sculpt = MEM_cnew<SculptSession>(__func__);
|
2021-11-04 16:51:37 -03:00
|
|
|
ob->sculpt->mode_type = (eObjectMode)ob->mode;
|
2019-01-09 10:16:51 +11:00
|
|
|
}
|
|
|
|
|
|
2021-12-10 10:42:28 -06:00
|
|
|
bool BKE_object_obdata_texspace_get(Object *ob, char **r_texflag, float **r_loc, float **r_size)
|
2011-09-28 05:53:40 +00:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-11-04 16:51:37 -03:00
|
|
|
if (ob->data == nullptr) {
|
2020-09-02 19:10:18 +02:00
|
|
|
return false;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-04-01 11:14:34 +00:00
|
|
|
switch (GS(((ID *)ob->data)->name)) {
|
2012-05-06 15:15:33 +00:00
|
|
|
case ID_ME: {
|
2019-09-23 15:54:21 +02:00
|
|
|
BKE_mesh_texspace_get_reference((Mesh *)ob->data, r_texflag, r_loc, r_size);
|
2012-05-06 15:15:33 +00:00
|
|
|
break;
|
|
|
|
|
}
|
2022-02-18 09:50:29 -06:00
|
|
|
case ID_CU_LEGACY: {
|
2021-11-04 16:51:37 -03:00
|
|
|
Curve *cu = (Curve *)ob->data;
|
2019-09-23 15:31:11 +02:00
|
|
|
BKE_curve_texspace_ensure(cu);
|
2019-04-22 09:39:35 +10:00
|
|
|
if (r_texflag) {
|
2012-05-06 15:15:33 +00:00
|
|
|
*r_texflag = &cu->texflag;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
if (r_loc) {
|
2012-05-06 15:15:33 +00:00
|
|
|
*r_loc = cu->loc;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
if (r_size) {
|
2012-05-06 15:15:33 +00:00
|
|
|
*r_size = cu->size;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2012-05-06 15:15:33 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case ID_MB: {
|
2021-11-04 16:51:37 -03:00
|
|
|
MetaBall *mb = (MetaBall *)ob->data;
|
2019-04-22 09:39:35 +10:00
|
|
|
if (r_texflag) {
|
2012-05-06 15:15:33 +00:00
|
|
|
*r_texflag = &mb->texflag;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
if (r_loc) {
|
2012-05-06 15:15:33 +00:00
|
|
|
*r_loc = mb->loc;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
if (r_size) {
|
2012-05-06 15:15:33 +00:00
|
|
|
*r_size = mb->size;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2012-05-06 15:15:33 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
default:
|
2020-09-02 19:10:18 +02:00
|
|
|
return false;
|
2008-04-01 11:14:34 +00:00
|
|
|
}
|
2020-09-02 19:10:18 +02:00
|
|
|
return true;
|
2008-04-01 11:14:34 +00:00
|
|
|
}
|
2008-06-09 17:50:21 +00:00
|
|
|
|
OpenSubDiv: add support for an OpenGL evaluator
This evaluator is used in order to evaluate subdivision at render time, allowing for
faster renders of meshes with a subdivision surface modifier placed at the last
position in the modifier list.
When evaluating the subsurf modifier, we detect whether we can delegate evaluation
to the draw code. If so, the subdivision is first evaluated on the GPU using our own
custom evaluator (only the coarse data needs to be initially sent to the GPU), then,
buffers for the final `MeshBufferCache` are filled on the GPU using a set of
compute shaders. However, some buffers are still filled on the CPU side, if doing so
on the GPU is impractical (e.g. the line adjacency buffer used for x-ray, whose
logic is hardly GPU compatible).
This is done at the mesh buffer extraction level so that the result can be readily used
in the various OpenGL engines, without having to write custom geometry or tesselation
shaders.
We use our own subdivision evaluation shaders, instead of OpenSubDiv's vanilla one, in
order to control the data layout, and interpolation. For example, we store vertex colors
as compressed 16-bit integers, while OpenSubDiv's default evaluator only work for float
types.
In order to still access the modified geometry on the CPU side, for use in modifiers
or transform operators, a dedicated wrapper type is added `MESH_WRAPPER_TYPE_SUBD`.
Subdivision will be lazily evaluated via `BKE_object_get_evaluated_mesh` which will
create such a wrapper if possible. If the final subdivision surface is not needed on
the CPU side, `BKE_object_get_evaluated_mesh_no_subsurf` should be used.
Enabling or disabling GPU subdivision can be done through the user preferences (under
Viewport -> Subdivision).
See patch description for benchmarks.
Reviewed By: campbellbarton, jbakker, fclem, brecht, #eevee_viewport
Differential Revision: https://developer.blender.org/D12406
2021-12-27 16:34:47 +01:00
|
|
|
Mesh *BKE_object_get_evaluated_mesh_no_subsurf(const Object *object)
|
2018-05-25 12:27:54 +02:00
|
|
|
{
|
2021-11-05 11:51:34 -05:00
|
|
|
/* First attempt to retrieve the evaluated mesh from the evaluated geometry set. Most
|
|
|
|
|
* object types either store it there or add a reference to it if it's owned elsewhere. */
|
|
|
|
|
GeometrySet *geometry_set_eval = object->runtime.geometry_set_eval;
|
|
|
|
|
if (geometry_set_eval) {
|
2021-11-23 09:32:12 +01:00
|
|
|
/* Some areas expect to be able to modify the evaluated mesh in limited ways. Theoretically
|
|
|
|
|
* this should be avoided, or at least protected with a lock, so a const mesh could be returned
|
|
|
|
|
* from this function. We use a const_cast instead of #get_mesh_for_write, because that might
|
|
|
|
|
* result in a copy of the mesh when it is shared. */
|
|
|
|
|
Mesh *mesh = const_cast<Mesh *>(geometry_set_eval->get_mesh_for_read());
|
2021-11-05 11:51:34 -05:00
|
|
|
if (mesh) {
|
|
|
|
|
return mesh;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Some object types do not yet add the evaluated mesh to an evaluated geometry set, if they do
|
|
|
|
|
* not support evaluating to multiple data types. Eventually this should be removed, when all
|
|
|
|
|
* object types use #geometry_set_eval. */
|
2020-02-27 11:23:15 +01:00
|
|
|
ID *data_eval = object->runtime.data_eval;
|
2021-11-05 11:51:34 -05:00
|
|
|
if (data_eval && GS(data_eval->name) == ID_ME) {
|
|
|
|
|
return reinterpret_cast<Mesh *>(data_eval);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nullptr;
|
2018-06-04 15:48:37 +02:00
|
|
|
}
|
|
|
|
|
|
OpenSubDiv: add support for an OpenGL evaluator
This evaluator is used in order to evaluate subdivision at render time, allowing for
faster renders of meshes with a subdivision surface modifier placed at the last
position in the modifier list.
When evaluating the subsurf modifier, we detect whether we can delegate evaluation
to the draw code. If so, the subdivision is first evaluated on the GPU using our own
custom evaluator (only the coarse data needs to be initially sent to the GPU), then,
buffers for the final `MeshBufferCache` are filled on the GPU using a set of
compute shaders. However, some buffers are still filled on the CPU side, if doing so
on the GPU is impractical (e.g. the line adjacency buffer used for x-ray, whose
logic is hardly GPU compatible).
This is done at the mesh buffer extraction level so that the result can be readily used
in the various OpenGL engines, without having to write custom geometry or tesselation
shaders.
We use our own subdivision evaluation shaders, instead of OpenSubDiv's vanilla one, in
order to control the data layout, and interpolation. For example, we store vertex colors
as compressed 16-bit integers, while OpenSubDiv's default evaluator only work for float
types.
In order to still access the modified geometry on the CPU side, for use in modifiers
or transform operators, a dedicated wrapper type is added `MESH_WRAPPER_TYPE_SUBD`.
Subdivision will be lazily evaluated via `BKE_object_get_evaluated_mesh` which will
create such a wrapper if possible. If the final subdivision surface is not needed on
the CPU side, `BKE_object_get_evaluated_mesh_no_subsurf` should be used.
Enabling or disabling GPU subdivision can be done through the user preferences (under
Viewport -> Subdivision).
See patch description for benchmarks.
Reviewed By: campbellbarton, jbakker, fclem, brecht, #eevee_viewport
Differential Revision: https://developer.blender.org/D12406
2021-12-27 16:34:47 +01:00
|
|
|
Mesh *BKE_object_get_evaluated_mesh(const Object *object)
|
|
|
|
|
{
|
|
|
|
|
Mesh *mesh = BKE_object_get_evaluated_mesh_no_subsurf(object);
|
|
|
|
|
if (!mesh) {
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (object->data && GS(((const ID *)object->data)->name) == ID_ME) {
|
2022-06-24 16:16:43 -05:00
|
|
|
mesh = BKE_mesh_wrapper_ensure_subdivision(mesh);
|
OpenSubDiv: add support for an OpenGL evaluator
This evaluator is used in order to evaluate subdivision at render time, allowing for
faster renders of meshes with a subdivision surface modifier placed at the last
position in the modifier list.
When evaluating the subsurf modifier, we detect whether we can delegate evaluation
to the draw code. If so, the subdivision is first evaluated on the GPU using our own
custom evaluator (only the coarse data needs to be initially sent to the GPU), then,
buffers for the final `MeshBufferCache` are filled on the GPU using a set of
compute shaders. However, some buffers are still filled on the CPU side, if doing so
on the GPU is impractical (e.g. the line adjacency buffer used for x-ray, whose
logic is hardly GPU compatible).
This is done at the mesh buffer extraction level so that the result can be readily used
in the various OpenGL engines, without having to write custom geometry or tesselation
shaders.
We use our own subdivision evaluation shaders, instead of OpenSubDiv's vanilla one, in
order to control the data layout, and interpolation. For example, we store vertex colors
as compressed 16-bit integers, while OpenSubDiv's default evaluator only work for float
types.
In order to still access the modified geometry on the CPU side, for use in modifiers
or transform operators, a dedicated wrapper type is added `MESH_WRAPPER_TYPE_SUBD`.
Subdivision will be lazily evaluated via `BKE_object_get_evaluated_mesh` which will
create such a wrapper if possible. If the final subdivision surface is not needed on
the CPU side, `BKE_object_get_evaluated_mesh_no_subsurf` should be used.
Enabling or disabling GPU subdivision can be done through the user preferences (under
Viewport -> Subdivision).
See patch description for benchmarks.
Reviewed By: campbellbarton, jbakker, fclem, brecht, #eevee_viewport
Differential Revision: https://developer.blender.org/D12406
2021-12-27 16:34:47 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return mesh;
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-21 17:25:10 +10:00
|
|
|
Mesh *BKE_object_get_pre_modified_mesh(const Object *object)
|
2018-06-04 15:48:37 +02:00
|
|
|
{
|
2021-11-04 16:51:37 -03:00
|
|
|
if (object->type == OB_MESH && object->runtime.data_orig != nullptr) {
|
2018-06-04 15:48:37 +02:00
|
|
|
BLI_assert(object->id.tag & LIB_TAG_COPIED_ON_WRITE);
|
2021-11-04 16:51:37 -03:00
|
|
|
BLI_assert(object->id.orig_id != nullptr);
|
2020-02-27 11:23:15 +01:00
|
|
|
BLI_assert(object->runtime.data_orig->orig_id == ((Object *)object->id.orig_id)->data);
|
|
|
|
|
Mesh *result = (Mesh *)object->runtime.data_orig;
|
2018-06-04 15:48:37 +02:00
|
|
|
BLI_assert((result->id.tag & LIB_TAG_COPIED_ON_WRITE) != 0);
|
|
|
|
|
BLI_assert((result->id.tag & LIB_TAG_COPIED_ON_WRITE_EVAL_RESULT) == 0);
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
BLI_assert((object->id.tag & LIB_TAG_COPIED_ON_WRITE) == 0);
|
2021-11-04 16:51:37 -03:00
|
|
|
return (Mesh *)object->data;
|
2018-06-04 15:48:37 +02:00
|
|
|
}
|
|
|
|
|
|
2021-06-21 17:25:10 +10:00
|
|
|
Mesh *BKE_object_get_original_mesh(const Object *object)
|
2018-06-04 15:48:37 +02:00
|
|
|
{
|
2021-11-04 16:51:37 -03:00
|
|
|
Mesh *result = nullptr;
|
|
|
|
|
if (object->id.orig_id == nullptr) {
|
2018-06-04 15:48:37 +02:00
|
|
|
BLI_assert((object->id.tag & LIB_TAG_COPIED_ON_WRITE) == 0);
|
2021-11-04 16:51:37 -03:00
|
|
|
result = (Mesh *)object->data;
|
2018-06-04 15:48:37 +02:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
BLI_assert((object->id.tag & LIB_TAG_COPIED_ON_WRITE) != 0);
|
2021-11-04 16:51:37 -03:00
|
|
|
result = (Mesh *)((Object *)object->id.orig_id)->data;
|
2018-06-04 15:48:37 +02:00
|
|
|
}
|
2021-11-04 16:51:37 -03:00
|
|
|
BLI_assert(result != nullptr);
|
2018-06-04 15:48:37 +02:00
|
|
|
BLI_assert((result->id.tag & (LIB_TAG_COPIED_ON_WRITE | LIB_TAG_COPIED_ON_WRITE_EVAL_RESULT)) ==
|
|
|
|
|
0);
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-11 15:42:07 +01:00
|
|
|
Mesh *BKE_object_get_editmesh_eval_final(const Object *object)
|
|
|
|
|
{
|
|
|
|
|
BLI_assert(!DEG_is_original_id(&object->id));
|
|
|
|
|
BLI_assert(object->type == OB_MESH);
|
|
|
|
|
|
|
|
|
|
const Mesh *mesh = static_cast<const Mesh *>(object->data);
|
|
|
|
|
if (mesh->edit_mesh == nullptr) {
|
2022-01-26 16:06:22 +11:00
|
|
|
/* Happens when requesting material of evaluated 3d font object: the evaluated object get
|
2022-01-11 15:42:07 +01:00
|
|
|
* converted to mesh, and it does not have edit mesh. */
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return reinterpret_cast<Mesh *>(object->runtime.data_eval);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Mesh *BKE_object_get_editmesh_eval_cage(const Object *object)
|
|
|
|
|
{
|
|
|
|
|
BLI_assert(!DEG_is_original_id(&object->id));
|
|
|
|
|
BLI_assert(object->type == OB_MESH);
|
|
|
|
|
|
|
|
|
|
const Mesh *mesh = static_cast<const Mesh *>(object->data);
|
|
|
|
|
BLI_assert(mesh->edit_mesh != nullptr);
|
|
|
|
|
UNUSED_VARS_NDEBUG(mesh);
|
|
|
|
|
|
|
|
|
|
return object->runtime.editmesh_eval_cage;
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-29 10:14:53 +02:00
|
|
|
Lattice *BKE_object_get_lattice(const Object *object)
|
|
|
|
|
{
|
2021-11-04 16:51:37 -03:00
|
|
|
ID *data = (ID *)object->data;
|
|
|
|
|
if (data == nullptr || GS(data->name) != ID_LT) {
|
|
|
|
|
return nullptr;
|
2021-03-29 10:14:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Lattice *lt = (Lattice *)data;
|
|
|
|
|
if (lt->editlatt) {
|
|
|
|
|
return lt->editlatt->latt;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return lt;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Lattice *BKE_object_get_evaluated_lattice(const Object *object)
|
|
|
|
|
{
|
|
|
|
|
ID *data_eval = object->runtime.data_eval;
|
|
|
|
|
|
2021-11-04 16:51:37 -03:00
|
|
|
if (data_eval == nullptr || GS(data_eval->name) != ID_LT) {
|
|
|
|
|
return nullptr;
|
2021-03-29 10:14:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Lattice *lt_eval = (Lattice *)data_eval;
|
|
|
|
|
if (lt_eval->editlatt) {
|
|
|
|
|
return lt_eval->editlatt->latt;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return lt_eval;
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-14 15:49:31 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Object Point Cache
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2014-09-23 01:28:46 +10:00
|
|
|
static int pc_cmp(const void *a, const void *b)
|
2009-08-25 18:41:36 +00:00
|
|
|
{
|
2021-11-04 16:51:37 -03:00
|
|
|
const LinkData *ad = (const LinkData *)a, *bd = (const LinkData *)b;
|
2019-04-22 09:39:35 +10:00
|
|
|
if (POINTER_AS_INT(ad->data) > POINTER_AS_INT(bd->data)) {
|
2009-08-25 18:41:36 +00:00
|
|
|
return 1;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2020-08-07 12:30:43 +02:00
|
|
|
|
|
|
|
|
return 0;
|
2009-08-25 18:41:36 +00:00
|
|
|
}
|
|
|
|
|
|
2020-11-16 12:29:21 +01:00
|
|
|
/* TODO: Review the usages of this function, currently with COW it will be called for orig object
|
|
|
|
|
* and then again for COW copies of it, think this is bad since there is no guarantee that we get
|
|
|
|
|
* the same stack index in both cases? Order is important since this index is used for filenames on
|
|
|
|
|
* disk. */
|
2018-06-17 17:05:51 +02:00
|
|
|
int BKE_object_insert_ptcache(Object *ob)
|
2009-08-25 18:41:36 +00:00
|
|
|
{
|
2021-11-04 16:51:37 -03:00
|
|
|
LinkData *link = nullptr;
|
2009-08-25 18:41:36 +00:00
|
|
|
int i = 0;
|
|
|
|
|
|
2014-11-16 13:57:58 +01:00
|
|
|
BLI_listbase_sort(&ob->pc_ids, pc_cmp);
|
2009-08-25 18:41:36 +00:00
|
|
|
|
2021-11-04 16:51:37 -03:00
|
|
|
for (link = (LinkData *)ob->pc_ids.first, i = 0; link; link = link->next, i++) {
|
2018-09-19 12:05:58 +10:00
|
|
|
int index = POINTER_AS_INT(link->data);
|
2009-08-25 18:41:36 +00:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (i < index) {
|
2009-08-25 18:41:36 +00:00
|
|
|
break;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2009-08-25 18:41:36 +00:00
|
|
|
}
|
|
|
|
|
|
2021-12-24 22:17:49 -05:00
|
|
|
link = MEM_cnew<LinkData>("PCLink");
|
2018-09-19 12:05:58 +10:00
|
|
|
link->data = POINTER_FROM_INT(i);
|
2009-08-25 18:41:36 +00:00
|
|
|
BLI_addtail(&ob->pc_ids, link);
|
|
|
|
|
|
|
|
|
|
return i;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int pc_findindex(ListBase *listbase, int index)
|
|
|
|
|
{
|
2012-05-06 15:15:33 +00:00
|
|
|
int number = 0;
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2021-11-04 16:51:37 -03:00
|
|
|
if (listbase == nullptr) {
|
2009-08-25 18:41:36 +00:00
|
|
|
return -1;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2021-11-04 16:51:37 -03:00
|
|
|
LinkData *link = (LinkData *)listbase->first;
|
2009-08-25 18:41:36 +00:00
|
|
|
while (link) {
|
2019-04-22 09:39:35 +10:00
|
|
|
if (POINTER_AS_INT(link->data) == index) {
|
2009-08-25 18:41:36 +00:00
|
|
|
return number;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2009-08-25 18:41:36 +00:00
|
|
|
number++;
|
2012-05-06 15:15:33 +00:00
|
|
|
link = link->next;
|
2009-08-25 18:41:36 +00:00
|
|
|
}
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2009-08-25 18:41:36 +00:00
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-05 23:46:10 +06:00
|
|
|
void BKE_object_delete_ptcache(Object *ob, int index)
|
2009-08-25 18:41:36 +00:00
|
|
|
{
|
|
|
|
|
int list_index = pc_findindex(&ob->pc_ids, index);
|
2021-11-04 16:51:37 -03:00
|
|
|
LinkData *link = (LinkData *)BLI_findlink(&ob->pc_ids, list_index);
|
2009-08-25 18:41:36 +00:00
|
|
|
BLI_freelinkN(&ob->pc_ids, link);
|
|
|
|
|
}
|
2009-12-28 15:26:36 +00:00
|
|
|
|
2021-12-14 15:49:31 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
2020-04-07 22:20:41 +10:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Object Data Shape Key Insert
|
|
|
|
|
* \{ */
|
2009-12-28 15:26:36 +00:00
|
|
|
|
2020-09-07 14:33:24 +10:00
|
|
|
/** Mesh */
|
2018-06-12 12:53:27 +02:00
|
|
|
static KeyBlock *insert_meshkey(Main *bmain, Object *ob, const char *name, const bool from_mix)
|
2009-12-28 15:26:36 +00:00
|
|
|
{
|
2021-11-04 16:51:37 -03:00
|
|
|
Mesh *me = (Mesh *)ob->data;
|
2012-05-06 15:15:33 +00:00
|
|
|
Key *key = me->key;
|
2009-12-28 15:26:36 +00:00
|
|
|
KeyBlock *kb;
|
2012-05-06 15:15:33 +00:00
|
|
|
int newkey = 0;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-11-04 16:51:37 -03:00
|
|
|
if (key == nullptr) {
|
2018-06-12 12:53:27 +02:00
|
|
|
key = me->key = BKE_key_add(bmain, (ID *)me);
|
2012-05-06 15:15:33 +00:00
|
|
|
key->type = KEY_RELATIVE;
|
|
|
|
|
newkey = 1;
|
2009-12-28 15:26:36 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-04-01 11:34:00 +11:00
|
|
|
if (newkey || from_mix == false) {
|
2009-12-28 15:26:36 +00:00
|
|
|
/* create from mesh */
|
2014-04-01 11:34:00 +11:00
|
|
|
kb = BKE_keyblock_add_ctime(key, name, false);
|
2018-06-21 18:24:32 +02:00
|
|
|
BKE_keyblock_convert_from_mesh(me, key, kb);
|
2009-12-28 15:26:36 +00:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* copy from current values */
|
2013-01-03 06:47:44 +00:00
|
|
|
int totelem;
|
2015-01-07 02:02:55 +11:00
|
|
|
float *data = BKE_key_evaluate_object(ob, &totelem);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2010-05-27 14:00:32 +00:00
|
|
|
/* create new block with prepared data */
|
2014-04-01 11:34:00 +11:00
|
|
|
kb = BKE_keyblock_add_ctime(key, name, false);
|
2012-05-06 15:15:33 +00:00
|
|
|
kb->data = data;
|
2013-01-03 06:47:44 +00:00
|
|
|
kb->totelem = totelem;
|
2009-12-28 15:26:36 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2009-12-28 18:03:04 +00:00
|
|
|
return kb;
|
2009-12-28 15:26:36 +00:00
|
|
|
}
|
2020-09-07 14:33:24 +10:00
|
|
|
/** Lattice */
|
2018-06-12 12:53:27 +02:00
|
|
|
static KeyBlock *insert_lattkey(Main *bmain, Object *ob, const char *name, const bool from_mix)
|
2009-12-28 15:26:36 +00:00
|
|
|
{
|
2021-11-04 16:51:37 -03:00
|
|
|
Lattice *lt = (Lattice *)ob->data;
|
2012-05-06 15:15:33 +00:00
|
|
|
Key *key = lt->key;
|
2009-12-28 15:26:36 +00:00
|
|
|
KeyBlock *kb;
|
2012-05-06 15:15:33 +00:00
|
|
|
int newkey = 0;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-11-04 16:51:37 -03:00
|
|
|
if (key == nullptr) {
|
2018-06-12 12:53:27 +02:00
|
|
|
key = lt->key = BKE_key_add(bmain, (ID *)lt);
|
2012-05-06 15:15:33 +00:00
|
|
|
key->type = KEY_RELATIVE;
|
|
|
|
|
newkey = 1;
|
2009-12-28 15:26:36 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-04-01 11:34:00 +11:00
|
|
|
if (newkey || from_mix == false) {
|
|
|
|
|
kb = BKE_keyblock_add_ctime(key, name, false);
|
2011-05-26 06:34:31 +00:00
|
|
|
if (!newkey) {
|
2012-05-06 15:15:33 +00:00
|
|
|
KeyBlock *basekb = (KeyBlock *)key->block.first;
|
|
|
|
|
kb->data = MEM_dupallocN(basekb->data);
|
|
|
|
|
kb->totelem = basekb->totelem;
|
2011-05-26 06:34:31 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2014-11-16 19:15:23 +01:00
|
|
|
BKE_keyblock_convert_from_lattice(lt, kb);
|
2011-05-26 06:34:31 +00:00
|
|
|
}
|
2009-12-28 15:26:36 +00:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* copy from current values */
|
2013-01-03 06:47:44 +00:00
|
|
|
int totelem;
|
2015-01-07 02:02:55 +11:00
|
|
|
float *data = BKE_key_evaluate_object(ob, &totelem);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2010-05-27 14:00:32 +00:00
|
|
|
/* create new block with prepared data */
|
2014-04-01 11:34:00 +11:00
|
|
|
kb = BKE_keyblock_add_ctime(key, name, false);
|
2013-01-03 06:47:44 +00:00
|
|
|
kb->totelem = totelem;
|
2012-05-06 15:15:33 +00:00
|
|
|
kb->data = data;
|
2009-12-28 15:26:36 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2009-12-28 18:03:04 +00:00
|
|
|
return kb;
|
2009-12-28 15:26:36 +00:00
|
|
|
}
|
2020-09-07 14:33:24 +10:00
|
|
|
/** Curve */
|
2018-06-12 12:53:27 +02:00
|
|
|
static KeyBlock *insert_curvekey(Main *bmain, Object *ob, const char *name, const bool from_mix)
|
2009-12-28 15:26:36 +00:00
|
|
|
{
|
2021-11-04 16:51:37 -03:00
|
|
|
Curve *cu = (Curve *)ob->data;
|
2012-05-06 15:15:33 +00:00
|
|
|
Key *key = cu->key;
|
2009-12-28 15:26:36 +00:00
|
|
|
KeyBlock *kb;
|
2012-05-06 15:15:33 +00:00
|
|
|
ListBase *lb = BKE_curve_nurbs_get(cu);
|
|
|
|
|
int newkey = 0;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-11-04 16:51:37 -03:00
|
|
|
if (key == nullptr) {
|
2018-06-12 12:53:27 +02:00
|
|
|
key = cu->key = BKE_key_add(bmain, (ID *)cu);
|
2009-12-28 15:26:36 +00:00
|
|
|
key->type = KEY_RELATIVE;
|
2012-05-06 15:15:33 +00:00
|
|
|
newkey = 1;
|
2009-12-28 15:26:36 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-04-01 11:34:00 +11:00
|
|
|
if (newkey || from_mix == false) {
|
2009-12-28 15:26:36 +00:00
|
|
|
/* create from curve */
|
2014-04-01 11:34:00 +11:00
|
|
|
kb = BKE_keyblock_add_ctime(key, name, false);
|
2010-07-26 19:07:33 +00:00
|
|
|
if (!newkey) {
|
2012-05-06 15:15:33 +00:00
|
|
|
KeyBlock *basekb = (KeyBlock *)key->block.first;
|
|
|
|
|
kb->data = MEM_dupallocN(basekb->data);
|
|
|
|
|
kb->totelem = basekb->totelem;
|
2011-05-26 06:34:31 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2014-11-16 19:15:23 +01:00
|
|
|
BKE_keyblock_convert_from_curve(cu, kb, lb);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2011-05-26 06:34:31 +00:00
|
|
|
}
|
2009-12-28 15:26:36 +00:00
|
|
|
else {
|
|
|
|
|
/* copy from current values */
|
2013-01-03 06:47:44 +00:00
|
|
|
int totelem;
|
2015-01-07 02:02:55 +11:00
|
|
|
float *data = BKE_key_evaluate_object(ob, &totelem);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2010-05-27 14:00:32 +00:00
|
|
|
/* create new block with prepared data */
|
2014-04-01 11:34:00 +11:00
|
|
|
kb = BKE_keyblock_add_ctime(key, name, false);
|
2013-01-03 06:47:44 +00:00
|
|
|
kb->totelem = totelem;
|
2012-05-06 15:15:33 +00:00
|
|
|
kb->data = data;
|
2009-12-28 15:26:36 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2009-12-28 18:03:04 +00:00
|
|
|
return kb;
|
2009-12-28 15:26:36 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-04-07 22:20:41 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Object Shape Key API
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2018-06-12 12:53:27 +02:00
|
|
|
KeyBlock *BKE_object_shapekey_insert(Main *bmain,
|
|
|
|
|
Object *ob,
|
|
|
|
|
const char *name,
|
|
|
|
|
const bool from_mix)
|
2018-06-17 17:05:51 +02:00
|
|
|
{
|
2021-11-04 16:51:37 -03:00
|
|
|
KeyBlock *key = nullptr;
|
2020-09-15 15:41:06 +10:00
|
|
|
|
2012-03-25 22:35:18 +00:00
|
|
|
switch (ob->type) {
|
|
|
|
|
case OB_MESH:
|
2020-09-15 15:41:06 +10:00
|
|
|
key = insert_meshkey(bmain, ob, name, from_mix);
|
|
|
|
|
break;
|
2022-02-18 09:50:29 -06:00
|
|
|
case OB_CURVES_LEGACY:
|
2012-03-25 22:35:18 +00:00
|
|
|
case OB_SURF:
|
2020-09-15 15:41:06 +10:00
|
|
|
key = insert_curvekey(bmain, ob, name, from_mix);
|
|
|
|
|
break;
|
2012-03-25 22:35:18 +00:00
|
|
|
case OB_LATTICE:
|
2020-09-15 15:41:06 +10:00
|
|
|
key = insert_lattkey(bmain, ob, name, from_mix);
|
|
|
|
|
break;
|
2012-03-25 22:35:18 +00:00
|
|
|
default:
|
2020-09-15 15:41:06 +10:00
|
|
|
break;
|
2012-03-25 22:35:18 +00:00
|
|
|
}
|
2020-09-15 15:41:06 +10:00
|
|
|
|
|
|
|
|
/* Set the first active when none is set when called from RNA. */
|
2021-11-04 16:51:37 -03:00
|
|
|
if (key != nullptr) {
|
2020-09-15 15:41:06 +10:00
|
|
|
if (ob->shapenr <= 0) {
|
|
|
|
|
ob->shapenr = 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return key;
|
2009-12-28 15:26:36 +00:00
|
|
|
}
|
|
|
|
|
|
2015-06-08 19:49:01 +10:00
|
|
|
bool BKE_object_shapekey_free(Main *bmain, Object *ob)
|
|
|
|
|
{
|
|
|
|
|
Key **key_p, *key;
|
|
|
|
|
|
|
|
|
|
key_p = BKE_key_from_object_p(ob);
|
2021-11-04 16:51:37 -03:00
|
|
|
if (ELEM(nullptr, key_p, *key_p)) {
|
2015-06-08 19:49:01 +10:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
key = *key_p;
|
2021-11-04 16:51:37 -03:00
|
|
|
*key_p = nullptr;
|
2015-06-08 19:49:01 +10:00
|
|
|
|
2019-01-14 21:08:22 +01:00
|
|
|
BKE_id_free_us(bmain, key);
|
2015-06-08 19:49:01 +10:00
|
|
|
|
2019-08-16 12:52:40 +02:00
|
|
|
return true;
|
2015-06-08 19:49:01 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool BKE_object_shapekey_remove(Main *bmain, Object *ob, KeyBlock *kb)
|
|
|
|
|
{
|
|
|
|
|
Key *key = BKE_key_from_object(ob);
|
|
|
|
|
short kb_index;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-11-04 16:51:37 -03:00
|
|
|
if (key == nullptr) {
|
2015-06-08 19:49:01 +10:00
|
|
|
return false;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-06-08 19:49:01 +10:00
|
|
|
kb_index = BLI_findindex(&key->block, kb);
|
|
|
|
|
BLI_assert(kb_index != -1);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-11-04 16:51:37 -03:00
|
|
|
LISTBASE_FOREACH (KeyBlock *, rkb, &key->block) {
|
2015-06-08 19:49:01 +10:00
|
|
|
if (rkb->relative == kb_index) {
|
|
|
|
|
/* remap to the 'Basis' */
|
|
|
|
|
rkb->relative = 0;
|
|
|
|
|
}
|
|
|
|
|
else if (rkb->relative >= kb_index) {
|
|
|
|
|
/* Fix positional shift of the keys when kb is deleted from the list */
|
|
|
|
|
rkb->relative -= 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-06-08 19:49:01 +10:00
|
|
|
BLI_remlink(&key->block, kb);
|
|
|
|
|
key->totkey--;
|
|
|
|
|
if (key->refkey == kb) {
|
2021-11-04 16:51:37 -03:00
|
|
|
key->refkey = (KeyBlock *)key->block.first;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-06-08 19:49:01 +10:00
|
|
|
if (key->refkey) {
|
|
|
|
|
/* apply new basis key on original data */
|
|
|
|
|
switch (ob->type) {
|
2022-03-22 09:43:02 -05:00
|
|
|
case OB_MESH: {
|
|
|
|
|
Mesh *mesh = (Mesh *)ob->data;
|
|
|
|
|
BKE_keyblock_convert_to_mesh(key->refkey, mesh->mvert, mesh->totvert);
|
2015-06-08 19:49:01 +10:00
|
|
|
break;
|
2022-03-22 09:43:02 -05:00
|
|
|
}
|
2022-02-18 09:50:29 -06:00
|
|
|
case OB_CURVES_LEGACY:
|
2015-06-08 19:49:01 +10:00
|
|
|
case OB_SURF:
|
2021-11-04 16:51:37 -03:00
|
|
|
BKE_keyblock_convert_to_curve(
|
|
|
|
|
key->refkey, (Curve *)ob->data, BKE_curve_nurbs_get((Curve *)ob->data));
|
2015-06-08 19:49:01 +10:00
|
|
|
break;
|
|
|
|
|
case OB_LATTICE:
|
2021-11-04 16:51:37 -03:00
|
|
|
BKE_keyblock_convert_to_lattice(key->refkey, (Lattice *)ob->data);
|
2015-06-08 19:49:01 +10:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-06-08 19:49:01 +10:00
|
|
|
if (kb->data) {
|
|
|
|
|
MEM_freeN(kb->data);
|
|
|
|
|
}
|
|
|
|
|
MEM_freeN(kb);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-09-15 15:41:06 +10:00
|
|
|
/* Unset active when all are freed. */
|
|
|
|
|
if (BLI_listbase_is_empty(&key->block)) {
|
|
|
|
|
ob->shapenr = 0;
|
|
|
|
|
}
|
|
|
|
|
else if (ob->shapenr > 1) {
|
2015-06-08 19:49:01 +10:00
|
|
|
ob->shapenr--;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-06-08 19:49:01 +10:00
|
|
|
if (key->totkey == 0) {
|
|
|
|
|
BKE_object_shapekey_free(bmain, ob);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-06-08 19:49:01 +10:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-07 22:20:41 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
2021-12-14 15:49:31 +11:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Object Query API
|
|
|
|
|
* \{ */
|
|
|
|
|
|
|
|
|
|
bool BKE_object_parent_loop_check(const Object *par, const Object *ob)
|
|
|
|
|
{
|
|
|
|
|
/* test if 'ob' is a parent somewhere in par's parents */
|
|
|
|
|
if (par == nullptr) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if (ob == par) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return BKE_object_parent_loop_check(par->parent, ob);
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-04 14:38:16 +11:00
|
|
|
bool BKE_object_flag_test_recursive(const Object *ob, short flag)
|
|
|
|
|
{
|
|
|
|
|
if (ob->flag & flag) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2020-08-07 12:30:43 +02:00
|
|
|
if (ob->parent) {
|
2015-03-04 14:38:16 +11:00
|
|
|
return BKE_object_flag_test_recursive(ob->parent, flag);
|
|
|
|
|
}
|
2020-08-07 12:30:43 +02:00
|
|
|
|
|
|
|
|
return false;
|
2015-03-04 14:38:16 +11:00
|
|
|
}
|
|
|
|
|
|
2018-04-14 14:27:38 +02:00
|
|
|
bool BKE_object_is_child_recursive(const Object *ob_parent, const Object *ob_child)
|
2013-03-09 03:34:01 +00:00
|
|
|
{
|
2013-03-11 16:23:33 +00:00
|
|
|
for (ob_child = ob_child->parent; ob_child; ob_child = ob_child->parent) {
|
|
|
|
|
if (ob_child == ob_parent) {
|
2013-03-09 03:34:01 +00:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-05 14:03:12 +00:00
|
|
|
int BKE_object_is_modified(Scene *scene, Object *ob)
|
2011-03-16 08:53:35 +00:00
|
|
|
{
|
2020-05-20 17:54:47 +02:00
|
|
|
/* Always test on original object since evaluated object may no longer
|
|
|
|
|
* have shape keys or modifiers that were used to evaluate it. */
|
|
|
|
|
ob = DEG_get_original_object(ob);
|
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
int flag = 0;
|
2011-03-16 08:53:35 +00:00
|
|
|
|
2012-09-23 18:50:56 +00:00
|
|
|
if (BKE_key_from_object(ob)) {
|
2014-02-14 14:53:19 +01:00
|
|
|
flag |= eModifierMode_Render | eModifierMode_Realtime;
|
2011-03-16 08:53:35 +00:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
ModifierData *md;
|
2013-08-19 09:05:34 +00:00
|
|
|
VirtualModifierData virtualModifierData;
|
2011-03-16 08:53:35 +00:00
|
|
|
/* cloth */
|
2020-05-08 10:14:02 +02:00
|
|
|
for (md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData);
|
2012-02-23 02:17:50 +00:00
|
|
|
md && (flag != (eModifierMode_Render | eModifierMode_Realtime));
|
2012-05-06 15:15:33 +00:00
|
|
|
md = md->next) {
|
2012-04-30 12:49:26 +00:00
|
|
|
if ((flag & eModifierMode_Render) == 0 &&
|
2020-05-08 10:14:02 +02:00
|
|
|
BKE_modifier_is_enabled(scene, md, eModifierMode_Render)) {
|
2012-02-23 02:17:50 +00:00
|
|
|
flag |= eModifierMode_Render;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2012-02-23 02:17:50 +00:00
|
|
|
|
2012-04-30 12:49:26 +00:00
|
|
|
if ((flag & eModifierMode_Realtime) == 0 &&
|
2020-05-08 10:14:02 +02:00
|
|
|
BKE_modifier_is_enabled(scene, md, eModifierMode_Realtime)) {
|
2012-04-30 12:49:26 +00:00
|
|
|
flag |= eModifierMode_Realtime;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2012-04-30 12:49:26 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return flag;
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-26 17:59:27 +01:00
|
|
|
bool BKE_object_moves_in_time(const Object *object, bool recurse_parent)
|
2015-01-13 15:38:43 +05:00
|
|
|
{
|
2019-11-26 17:59:27 +01:00
|
|
|
/* If object has any sort of animation data assume it is moving. */
|
|
|
|
|
if (BKE_animdata_id_is_animated(&object->id)) {
|
|
|
|
|
return true;
|
2015-01-13 15:38:43 +05:00
|
|
|
}
|
|
|
|
|
if (!BLI_listbase_is_empty(&object->constraints)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2021-11-04 16:51:37 -03:00
|
|
|
if (recurse_parent && object->parent != nullptr) {
|
2019-11-26 17:59:27 +01:00
|
|
|
return BKE_object_moves_in_time(object->parent, true);
|
2015-01-13 15:38:43 +05:00
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-26 17:59:27 +01:00
|
|
|
static bool object_moves_in_time(const Object *object)
|
|
|
|
|
{
|
|
|
|
|
return BKE_object_moves_in_time(object, true);
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-01 15:53:40 +02:00
|
|
|
static bool object_deforms_in_time(Object *object)
|
|
|
|
|
{
|
2021-11-04 16:51:37 -03:00
|
|
|
if (BKE_key_from_object(object) != nullptr) {
|
2016-04-01 15:53:40 +02:00
|
|
|
return true;
|
|
|
|
|
}
|
2016-04-04 11:39:04 +02:00
|
|
|
if (!BLI_listbase_is_empty(&object->modifiers)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2016-04-01 15:53:40 +02:00
|
|
|
return object_moves_in_time(object);
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-22 16:55:37 +01:00
|
|
|
static bool constructive_modifier_is_deform_modified(Object *ob, ModifierData *md)
|
2015-01-13 15:38:43 +05:00
|
|
|
{
|
|
|
|
|
/* TODO(sergey): Consider generalizing this a bit so all modifier logic
|
|
|
|
|
* is concentrated in MOD_{modifier}.c file,
|
|
|
|
|
*/
|
|
|
|
|
if (md->type == eModifierType_Array) {
|
|
|
|
|
ArrayModifierData *amd = (ArrayModifierData *)md;
|
|
|
|
|
/* TODO(sergey): Check if curve is deformed. */
|
2021-11-04 16:51:37 -03:00
|
|
|
return (amd->start_cap != nullptr && object_moves_in_time(amd->start_cap)) ||
|
|
|
|
|
(amd->end_cap != nullptr && object_moves_in_time(amd->end_cap)) ||
|
|
|
|
|
(amd->curve_ob != nullptr && object_moves_in_time(amd->curve_ob)) ||
|
|
|
|
|
(amd->offset_ob != nullptr && object_moves_in_time(amd->offset_ob));
|
2015-01-13 15:38:43 +05:00
|
|
|
}
|
2020-08-07 12:30:43 +02:00
|
|
|
if (md->type == eModifierType_Mirror) {
|
2015-01-13 15:38:43 +05:00
|
|
|
MirrorModifierData *mmd = (MirrorModifierData *)md;
|
2021-11-04 16:51:37 -03:00
|
|
|
return mmd->mirror_ob != nullptr &&
|
2021-03-22 16:55:37 +01:00
|
|
|
(object_moves_in_time(mmd->mirror_ob) || object_moves_in_time(ob));
|
2015-01-13 15:38:43 +05:00
|
|
|
}
|
2020-08-07 12:30:43 +02:00
|
|
|
if (md->type == eModifierType_Screw) {
|
2015-01-13 15:38:43 +05:00
|
|
|
ScrewModifierData *smd = (ScrewModifierData *)md;
|
2021-11-04 16:51:37 -03:00
|
|
|
return smd->ob_axis != nullptr && object_moves_in_time(smd->ob_axis);
|
2015-01-13 15:38:43 +05:00
|
|
|
}
|
2020-08-07 12:30:43 +02:00
|
|
|
if (md->type == eModifierType_MeshSequenceCache) {
|
2016-10-05 12:37:09 +02:00
|
|
|
/* NOTE: Not ideal because it's unknown whether topology changes or not.
|
|
|
|
|
* This will be detected later, so by assuming it's only deformation
|
2020-11-18 16:14:48 -05:00
|
|
|
* going on here we allow baking deform-only mesh to Alembic and have
|
2016-10-05 12:37:09 +02:00
|
|
|
* proper motion blur after that.
|
|
|
|
|
*/
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2020-12-21 19:17:10 +01:00
|
|
|
if (md->type == eModifierType_Nodes) {
|
|
|
|
|
/* Not ideal for performance to always assume this is animated,
|
|
|
|
|
* but hard to detect in general. The better long term solution is likely
|
|
|
|
|
* to replace BKE_object_is_deform_modified by a test if the object was
|
|
|
|
|
* modified by the depsgraph when changing frames. */
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2015-01-13 15:38:43 +05:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-26 15:13:52 +01:00
|
|
|
static bool modifiers_has_animation_check(const Object *ob)
|
2015-01-13 15:38:43 +05:00
|
|
|
{
|
|
|
|
|
/* TODO(sergey): This is a bit code duplication with depsgraph, but
|
|
|
|
|
* would be nicer to solve this as a part of new dependency graph
|
|
|
|
|
* work, so we avoid conflicts and so.
|
|
|
|
|
*/
|
2021-11-04 16:51:37 -03:00
|
|
|
if (ob->adt != nullptr) {
|
2015-01-13 15:38:43 +05:00
|
|
|
AnimData *adt = ob->adt;
|
2021-11-04 16:51:37 -03:00
|
|
|
if (adt->action != nullptr) {
|
|
|
|
|
LISTBASE_FOREACH (FCurve *, fcu, &adt->action->curves) {
|
2015-01-13 15:38:43 +05:00
|
|
|
if (fcu->rna_path && strstr(fcu->rna_path, "modifiers[")) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-11-04 16:51:37 -03:00
|
|
|
LISTBASE_FOREACH (FCurve *, fcu, &adt->drivers) {
|
2015-01-13 15:38:43 +05:00
|
|
|
if (fcu->rna_path && strstr(fcu->rna_path, "modifiers[")) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-05 14:03:12 +00:00
|
|
|
int BKE_object_is_deform_modified(Scene *scene, Object *ob)
|
2012-04-30 12:49:26 +00:00
|
|
|
{
|
2020-05-20 17:54:47 +02:00
|
|
|
/* Always test on original object since evaluated object may no longer
|
|
|
|
|
* have shape keys or modifiers that were used to evaluate it. */
|
|
|
|
|
ob = DEG_get_original_object(ob);
|
|
|
|
|
|
2012-04-30 12:49:26 +00:00
|
|
|
ModifierData *md;
|
2013-08-19 09:05:34 +00:00
|
|
|
VirtualModifierData virtualModifierData;
|
2012-05-06 15:15:33 +00:00
|
|
|
int flag = 0;
|
2015-01-13 15:38:43 +05:00
|
|
|
const bool is_modifier_animated = modifiers_has_animation_check(ob);
|
2012-04-30 12:49:26 +00:00
|
|
|
|
2016-04-01 15:53:40 +02:00
|
|
|
if (BKE_key_from_object(ob)) {
|
2014-05-20 00:11:16 +10:00
|
|
|
flag |= eModifierMode_Realtime | eModifierMode_Render;
|
2016-04-01 15:53:40 +02:00
|
|
|
}
|
|
|
|
|
|
2022-02-18 09:50:29 -06:00
|
|
|
if (ob->type == OB_CURVES_LEGACY) {
|
2016-04-01 15:53:40 +02:00
|
|
|
Curve *cu = (Curve *)ob->data;
|
2021-11-04 16:51:37 -03:00
|
|
|
if (cu->taperobj != nullptr && object_deforms_in_time(cu->taperobj)) {
|
2016-04-01 15:53:40 +02:00
|
|
|
flag |= eModifierMode_Realtime | eModifierMode_Render;
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-05-19 14:23:56 +02:00
|
|
|
|
2012-04-30 12:49:26 +00:00
|
|
|
/* cloth */
|
2020-05-08 10:14:02 +02:00
|
|
|
for (md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData);
|
2012-05-06 15:15:33 +00:00
|
|
|
md && (flag != (eModifierMode_Render | eModifierMode_Realtime));
|
|
|
|
|
md = md->next) {
|
2021-11-04 16:51:37 -03:00
|
|
|
const ModifierTypeInfo *mti = BKE_modifier_get_info((const ModifierType)md->type);
|
2015-01-13 15:38:43 +05:00
|
|
|
bool can_deform = mti->type == eModifierTypeType_OnlyDeform || is_modifier_animated;
|
|
|
|
|
|
|
|
|
|
if (!can_deform) {
|
2021-03-22 16:55:37 +01:00
|
|
|
can_deform = constructive_modifier_is_deform_modified(ob, md);
|
2015-01-13 15:38:43 +05:00
|
|
|
}
|
2012-04-30 12:49:26 +00:00
|
|
|
|
2015-01-13 15:38:43 +05:00
|
|
|
if (can_deform) {
|
2020-05-08 19:02:03 +10:00
|
|
|
if (!(flag & eModifierMode_Render) &&
|
|
|
|
|
BKE_modifier_is_enabled(scene, md, eModifierMode_Render)) {
|
2012-04-30 12:49:26 +00:00
|
|
|
flag |= eModifierMode_Render;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2012-04-30 12:49:26 +00:00
|
|
|
|
|
|
|
|
if (!(flag & eModifierMode_Realtime) &&
|
2020-05-08 10:14:02 +02:00
|
|
|
BKE_modifier_is_enabled(scene, md, eModifierMode_Realtime)) {
|
2012-02-23 02:17:50 +00:00
|
|
|
flag |= eModifierMode_Realtime;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2011-03-16 08:53:35 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return flag;
|
|
|
|
|
}
|
2011-03-27 23:11:22 +00:00
|
|
|
|
2019-02-09 13:18:22 +01:00
|
|
|
int BKE_object_scenes_users_get(Main *bmain, Object *ob)
|
|
|
|
|
{
|
|
|
|
|
int num_scenes = 0;
|
2021-11-04 16:51:37 -03:00
|
|
|
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
|
2019-09-02 14:31:19 +02:00
|
|
|
if (BKE_collection_has_object_recursive(scene->master_collection, ob)) {
|
2019-02-09 13:18:22 +01:00
|
|
|
num_scenes++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return num_scenes;
|
|
|
|
|
}
|
|
|
|
|
|
2013-09-09 11:37:37 +00:00
|
|
|
MovieClip *BKE_object_movieclip_get(Scene *scene, Object *ob, bool use_default)
|
2011-11-07 12:55:18 +00:00
|
|
|
{
|
2021-11-04 16:51:37 -03:00
|
|
|
MovieClip *clip = use_default ? scene->clip : nullptr;
|
|
|
|
|
bConstraint *con = (bConstraint *)ob->constraints.first, *scon = nullptr;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-02-23 02:17:50 +00:00
|
|
|
while (con) {
|
2012-05-06 15:15:33 +00:00
|
|
|
if (con->type == CONSTRAINT_TYPE_CAMERASOLVER) {
|
2021-11-04 16:51:37 -03:00
|
|
|
if (scon == nullptr || (scon->flag & CONSTRAINT_OFF)) {
|
2012-05-06 15:15:33 +00:00
|
|
|
scon = con;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
con = con->next;
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-23 02:17:50 +00:00
|
|
|
if (scon) {
|
2021-11-04 16:51:37 -03:00
|
|
|
bCameraSolverConstraint *solver = (bCameraSolverConstraint *)scon->data;
|
2019-04-22 09:39:35 +10:00
|
|
|
if ((solver->flag & CAMERASOLVER_ACTIVECLIP) == 0) {
|
2012-05-06 15:15:33 +00:00
|
|
|
clip = solver->clip;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
else {
|
2012-05-06 15:15:33 +00:00
|
|
|
clip = scene->clip;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return clip;
|
|
|
|
|
}
|
2012-06-12 21:23:51 +00:00
|
|
|
|
2021-12-14 15:49:31 +11:00
|
|
|
bool BKE_object_supports_material_slots(struct Object *ob)
|
|
|
|
|
{
|
|
|
|
|
return ELEM(ob->type,
|
|
|
|
|
OB_MESH,
|
2022-02-18 09:50:29 -06:00
|
|
|
OB_CURVES_LEGACY,
|
2021-12-14 15:49:31 +11:00
|
|
|
OB_SURF,
|
|
|
|
|
OB_FONT,
|
|
|
|
|
OB_MBALL,
|
Curves: Rename "Hair" types, variables, and functions to "Curves"
Based on discussions from T95355 and T94193, the plan is to use
the name "Curves" to describe the data-block container for multiple
curves. Eventually this will replace the existing "Curve" data-block.
However, it will be a while before the curve data-block can be replaced
so in order to distinguish the two curve types in the UI, "Hair Curves"
will be used, but eventually changed back to "Curves".
This patch renames "hair-related" files, functions, types, and variable
names to this convention. A deep rename is preferred to keep code
consistent and to avoid any "hair" terminology from leaking, since the
new data-block is meant for all curve types, not just hair use cases.
The downside of this naming is that the difference between "Curve"
and "Curves" has become important. That was considered during
design discussons and deemed acceptable, especially given the
non-permanent nature of the somewhat common conflict.
Some points of interest:
- All DNA compatibility is lost, just like rBf59767ff9729.
- I renamed `ID_HA` to `ID_CV` so there is no complete mismatch.
- `hair_curves` is used where necessary to distinguish from the
existing "curves" plural.
- I didn't rename any of the cycles/rendering code function names,
since that is also used by the old hair particle system.
Differential Revision: https://developer.blender.org/D14007
2022-02-07 11:55:54 -06:00
|
|
|
OB_CURVES,
|
2021-12-14 15:49:31 +11:00
|
|
|
OB_POINTCLOUD,
|
|
|
|
|
OB_VOLUME,
|
|
|
|
|
OB_GPENCIL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Object Runtime
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2018-05-30 19:45:03 +02:00
|
|
|
void BKE_object_runtime_reset(Object *object)
|
|
|
|
|
{
|
2018-05-30 11:49:45 +02:00
|
|
|
memset(&object->runtime, 0, sizeof(object->runtime));
|
|
|
|
|
}
|
2012-06-12 21:23:51 +00:00
|
|
|
|
2019-02-13 14:29:27 +01:00
|
|
|
void BKE_object_runtime_reset_on_copy(Object *object, const int UNUSED(flag))
|
2018-12-17 12:28:16 +01:00
|
|
|
{
|
|
|
|
|
Object_Runtime *runtime = &object->runtime;
|
2021-11-04 16:51:37 -03:00
|
|
|
runtime->data_eval = nullptr;
|
|
|
|
|
runtime->gpd_eval = nullptr;
|
|
|
|
|
runtime->mesh_deform_eval = nullptr;
|
|
|
|
|
runtime->curve_cache = nullptr;
|
|
|
|
|
runtime->object_as_temp_mesh = nullptr;
|
|
|
|
|
runtime->object_as_temp_curve = nullptr;
|
|
|
|
|
runtime->geometry_set_eval = nullptr;
|
2022-01-05 09:53:48 +01:00
|
|
|
|
|
|
|
|
runtime->crazyspace_deform_imats = nullptr;
|
|
|
|
|
runtime->crazyspace_deform_cos = nullptr;
|
2018-12-17 12:28:16 +01:00
|
|
|
}
|
|
|
|
|
|
2021-04-30 22:35:47 +10:00
|
|
|
void BKE_object_runtime_free_data(Object *object)
|
2021-04-30 16:22:51 +10:00
|
|
|
{
|
|
|
|
|
/* Currently this is all that's needed. */
|
|
|
|
|
BKE_object_free_derived_caches(object);
|
2021-04-30 22:35:47 +10:00
|
|
|
|
|
|
|
|
BKE_object_runtime_reset(object);
|
2021-04-30 16:22:51 +10:00
|
|
|
}
|
|
|
|
|
|
2021-12-14 15:49:31 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Object Relationships
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2020-09-07 14:33:24 +10:00
|
|
|
/**
|
|
|
|
|
* Find an associated armature object.
|
2012-06-12 21:23:51 +00:00
|
|
|
*/
|
|
|
|
|
static Object *obrel_armature_find(Object *ob)
|
|
|
|
|
{
|
2021-11-04 16:51:37 -03:00
|
|
|
Object *ob_arm = nullptr;
|
2012-06-12 21:23:51 +00:00
|
|
|
|
|
|
|
|
if (ob->parent && ob->partype == PARSKEL && ob->parent->type == OB_ARMATURE) {
|
|
|
|
|
ob_arm = ob->parent;
|
|
|
|
|
}
|
|
|
|
|
else {
|
2012-06-12 22:05:33 +00:00
|
|
|
ModifierData *mod;
|
|
|
|
|
for (mod = (ModifierData *)ob->modifiers.first; mod; mod = mod->next) {
|
2012-06-12 21:23:51 +00:00
|
|
|
if (mod->type == eModifierType_Armature) {
|
2012-06-12 22:05:33 +00:00
|
|
|
ob_arm = ((ArmatureModifierData *)mod)->object;
|
2012-06-12 21:23:51 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ob_arm;
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-22 02:48:11 +11:00
|
|
|
static bool obrel_list_test(Object *ob)
|
2012-06-12 21:23:51 +00:00
|
|
|
{
|
Split id->flag in two, persistent flags and runtime tags.
This is purely internal sanitizing/cleanup, no change in behavior is expected at all.
This change was also needed because we were getting short on ID flags, and
future enhancement of 'user_one' ID behavior requires two new ones.
id->flag remains for persistent data (fakeuser only, so far!), this also allows us
100% backward & forward compatibility.
New id->tag is used for most flags. Though written in .blend files, its content
is cleared at read time.
Note that .blend file version was bumped, so that we can clear runtimeflags from
old .blends, important in case we add new persistent flags in future.
Also, behavior of tags (either status ones, or whether they need to be cleared before/after use)
has been added as comments to their declaration.
Reviewers: sergey, campbellbarton
Differential Revision: https://developer.blender.org/D1683
2015-12-27 11:53:50 +01:00
|
|
|
return ob && !(ob->id.tag & LIB_TAG_DOIT);
|
2012-06-12 21:23:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void obrel_list_add(LinkNode **links, Object *ob)
|
|
|
|
|
{
|
|
|
|
|
BLI_linklist_prepend(links, ob);
|
Split id->flag in two, persistent flags and runtime tags.
This is purely internal sanitizing/cleanup, no change in behavior is expected at all.
This change was also needed because we were getting short on ID flags, and
future enhancement of 'user_one' ID behavior requires two new ones.
id->flag remains for persistent data (fakeuser only, so far!), this also allows us
100% backward & forward compatibility.
New id->tag is used for most flags. Though written in .blend files, its content
is cleared at read time.
Note that .blend file version was bumped, so that we can clear runtimeflags from
old .blends, important in case we add new persistent flags in future.
Also, behavior of tags (either status ones, or whether they need to be cleared before/after use)
has been added as comments to their declaration.
Reviewers: sergey, campbellbarton
Differential Revision: https://developer.blender.org/D1683
2015-12-27 11:53:50 +01:00
|
|
|
ob->id.tag |= LIB_TAG_DOIT;
|
2012-06-12 21:23:51 +00:00
|
|
|
}
|
|
|
|
|
|
2017-11-22 10:52:39 -02:00
|
|
|
LinkNode *BKE_object_relational_superset(struct ViewLayer *view_layer,
|
|
|
|
|
eObjectSet objectSet,
|
|
|
|
|
eObRelationTypes includeFilter)
|
2012-06-12 21:23:51 +00:00
|
|
|
{
|
2021-11-04 16:51:37 -03:00
|
|
|
LinkNode *links = nullptr;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-06-12 21:23:51 +00:00
|
|
|
/* Remove markers from all objects */
|
2021-11-04 16:51:37 -03:00
|
|
|
LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
|
2017-04-04 19:17:42 +02:00
|
|
|
base->object->id.tag &= ~LIB_TAG_DOIT;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-06-12 21:23:51 +00:00
|
|
|
/* iterate over all selected and visible objects */
|
2021-11-04 16:51:37 -03:00
|
|
|
LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
|
2012-06-12 21:23:51 +00:00
|
|
|
if (objectSet == OB_SET_ALL) {
|
2012-07-07 22:51:57 +00:00
|
|
|
/* as we get all anyways just add it */
|
2012-06-12 21:23:51 +00:00
|
|
|
Object *ob = base->object;
|
|
|
|
|
obrel_list_add(&links, ob);
|
|
|
|
|
}
|
|
|
|
|
else {
|
2021-11-04 16:51:37 -03:00
|
|
|
if ((objectSet == OB_SET_SELECTED && BASE_SELECTED_EDITABLE(((View3D *)nullptr), base)) ||
|
|
|
|
|
(objectSet == OB_SET_VISIBLE && BASE_EDITABLE(((View3D *)nullptr), base))) {
|
2012-06-12 21:23:51 +00:00
|
|
|
Object *ob = base->object;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (obrel_list_test(ob)) {
|
2012-06-12 21:23:51 +00:00
|
|
|
obrel_list_add(&links, ob);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-06-12 21:23:51 +00:00
|
|
|
/* parent relationship */
|
2012-06-12 22:05:33 +00:00
|
|
|
if (includeFilter & (OB_REL_PARENT | OB_REL_PARENT_RECURSIVE)) {
|
2012-06-12 21:23:51 +00:00
|
|
|
Object *parent = ob->parent;
|
|
|
|
|
if (obrel_list_test(parent)) {
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-06-12 21:23:51 +00:00
|
|
|
obrel_list_add(&links, parent);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-06-12 21:23:51 +00:00
|
|
|
/* recursive parent relationship */
|
|
|
|
|
if (includeFilter & OB_REL_PARENT_RECURSIVE) {
|
|
|
|
|
parent = parent->parent;
|
2012-06-12 22:05:33 +00:00
|
|
|
while (obrel_list_test(parent)) {
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-06-12 21:23:51 +00:00
|
|
|
obrel_list_add(&links, parent);
|
|
|
|
|
parent = parent->parent;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
|
2012-06-12 21:23:51 +00:00
|
|
|
/* child relationship */
|
2012-06-12 22:05:33 +00:00
|
|
|
if (includeFilter & (OB_REL_CHILDREN | OB_REL_CHILDREN_RECURSIVE)) {
|
2021-11-04 16:51:37 -03:00
|
|
|
LISTBASE_FOREACH (Base *, local_base, &view_layer->object_bases) {
|
|
|
|
|
if (BASE_EDITABLE(((View3D *)nullptr), local_base)) {
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-06-12 21:23:51 +00:00
|
|
|
Object *child = local_base->object;
|
|
|
|
|
if (obrel_list_test(child)) {
|
2013-03-09 03:34:01 +00:00
|
|
|
if ((includeFilter & OB_REL_CHILDREN_RECURSIVE &&
|
|
|
|
|
BKE_object_is_child_recursive(ob, child)) ||
|
2012-06-12 22:05:33 +00:00
|
|
|
(includeFilter & OB_REL_CHILDREN && child->parent && child->parent == ob)) {
|
2012-06-12 21:23:51 +00:00
|
|
|
obrel_list_add(&links, child);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-06-12 21:23:51 +00:00
|
|
|
/* include related armatures */
|
|
|
|
|
if (includeFilter & OB_REL_MOD_ARMATURE) {
|
|
|
|
|
Object *arm = obrel_armature_find(ob);
|
|
|
|
|
if (obrel_list_test(arm)) {
|
|
|
|
|
obrel_list_add(&links, arm);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2012-06-12 21:23:51 +00:00
|
|
|
}
|
|
|
|
|
}
|
2012-06-12 22:05:33 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-06-12 21:23:51 +00:00
|
|
|
return links;
|
|
|
|
|
}
|
2012-07-18 09:45:50 +00:00
|
|
|
|
2019-03-12 19:55:33 -03:00
|
|
|
struct LinkNode *BKE_object_groups(Main *bmain, Scene *scene, Object *ob)
|
2012-07-18 09:45:50 +00:00
|
|
|
{
|
2021-11-04 16:51:37 -03:00
|
|
|
LinkNode *collection_linknode = nullptr;
|
|
|
|
|
Collection *collection = nullptr;
|
2019-03-12 19:55:33 -03:00
|
|
|
while ((collection = BKE_collection_object_find(bmain, scene, collection, ob))) {
|
Collections and groups unification
OVERVIEW
* In 2.7 terminology, all layers and groups are now collection datablocks.
* These collections are nestable, linkable, instanceable, overrideable, ..
which opens up new ways to set up scenes and link + override data.
* Viewport/render visibility and selectability are now a part of the collection
and shared across all view layers and linkable.
* View layers define which subset of the scene collection hierarchy is excluded
for each. For many workflows one view layer can be used, these are more of an
advanced feature now.
OUTLINER
* The outliner now has a "View Layer" display mode instead of "Collections",
which can display the collections and/or objects in the view layer.
* In this display mode, collections can be excluded with the right click menu.
These will then be greyed out and their objects will be excluded.
* To view collections not linked to any scene, the "Blender File" display mode
can be used, with the new filtering option to just see Colleciton datablocks.
* The outliner right click menus for collections and objects were reorganized.
* Drag and drop still needs to be improved. Like before, dragging the icon or
text gives different results, we'll unify this later.
LINKING AND OVERRIDES
* Collections can now be linked into the scene without creating an instance,
with the link/append operator or from the collections view in the outliner.
* Collections can get static overrides with the right click menu in the outliner,
but this is rather unreliable and not clearly communicated at the moment.
* We still need to improve the make override operator to turn collection instances
into collections with overrides directly in the scene.
PERFORMANCE
* We tried to make performance not worse than before and improve it in some
cases. The main thing that's still a bit slower is multiple scenes, we have to
change the layer syncing to only updated affected scenes.
* Collections keep a list of their parent collections for faster incremental
updates in syncing and caching.
* View layer bases are now in a object -> base hash to avoid quadratic time
lookups internally and in API functions like visible_get().
VERSIONING
* Compatibility with 2.7 files should be improved due to the new visibility
controls. Of course users may not want to set up their scenes differently
now to avoid having separate layers and groups.
* Compatibility with 2.8 is mostly there, and was tested on Eevee demo and Hero
files. There's a few things which are know to be not quite compatible, like
nested layer collections inside groups.
* The versioning code for 2.8 files is quite complicated, and isolated behind
#ifdef so it can be removed at the end of the release cycle.
KNOWN ISSUES
* The G-key group operators in the 3D viewport were left mostly as is, they
need to be modified still to fit better.
* Same for the groups panel in the object properties. This needs to be updated
still, or perhaps replaced by something better.
* Collections must all have a unique name. Less restrictive namespacing is to
be done later, we'll have to see how important this is as all objects within
the collections must also have a unique name anyway.
* Full scene copy and delete scene are exactly doing the right thing yet.
Differential Revision: https://developer.blender.org/D3383
https://code.blender.org/2018/05/collections-and-groups/
2018-04-30 15:57:22 +02:00
|
|
|
BLI_linklist_prepend(&collection_linknode, collection);
|
2012-07-18 09:45:50 +00:00
|
|
|
}
|
|
|
|
|
|
Collections and groups unification
OVERVIEW
* In 2.7 terminology, all layers and groups are now collection datablocks.
* These collections are nestable, linkable, instanceable, overrideable, ..
which opens up new ways to set up scenes and link + override data.
* Viewport/render visibility and selectability are now a part of the collection
and shared across all view layers and linkable.
* View layers define which subset of the scene collection hierarchy is excluded
for each. For many workflows one view layer can be used, these are more of an
advanced feature now.
OUTLINER
* The outliner now has a "View Layer" display mode instead of "Collections",
which can display the collections and/or objects in the view layer.
* In this display mode, collections can be excluded with the right click menu.
These will then be greyed out and their objects will be excluded.
* To view collections not linked to any scene, the "Blender File" display mode
can be used, with the new filtering option to just see Colleciton datablocks.
* The outliner right click menus for collections and objects were reorganized.
* Drag and drop still needs to be improved. Like before, dragging the icon or
text gives different results, we'll unify this later.
LINKING AND OVERRIDES
* Collections can now be linked into the scene without creating an instance,
with the link/append operator or from the collections view in the outliner.
* Collections can get static overrides with the right click menu in the outliner,
but this is rather unreliable and not clearly communicated at the moment.
* We still need to improve the make override operator to turn collection instances
into collections with overrides directly in the scene.
PERFORMANCE
* We tried to make performance not worse than before and improve it in some
cases. The main thing that's still a bit slower is multiple scenes, we have to
change the layer syncing to only updated affected scenes.
* Collections keep a list of their parent collections for faster incremental
updates in syncing and caching.
* View layer bases are now in a object -> base hash to avoid quadratic time
lookups internally and in API functions like visible_get().
VERSIONING
* Compatibility with 2.7 files should be improved due to the new visibility
controls. Of course users may not want to set up their scenes differently
now to avoid having separate layers and groups.
* Compatibility with 2.8 is mostly there, and was tested on Eevee demo and Hero
files. There's a few things which are know to be not quite compatible, like
nested layer collections inside groups.
* The versioning code for 2.8 files is quite complicated, and isolated behind
#ifdef so it can be removed at the end of the release cycle.
KNOWN ISSUES
* The G-key group operators in the 3D viewport were left mostly as is, they
need to be modified still to fit better.
* Same for the groups panel in the object properties. This needs to be updated
still, or perhaps replaced by something better.
* Collections must all have a unique name. Less restrictive namespacing is to
be done later, we'll have to see how important this is as all objects within
the collections must also have a unique name anyway.
* Full scene copy and delete scene are exactly doing the right thing yet.
Differential Revision: https://developer.blender.org/D3383
https://code.blender.org/2018/05/collections-and-groups/
2018-04-30 15:57:22 +02:00
|
|
|
return collection_linknode;
|
2012-07-18 09:45:50 +00:00
|
|
|
}
|
|
|
|
|
|
2019-03-12 19:55:33 -03:00
|
|
|
void BKE_object_groups_clear(Main *bmain, Scene *scene, Object *ob)
|
2012-07-18 09:45:50 +00:00
|
|
|
{
|
2021-11-04 16:51:37 -03:00
|
|
|
Collection *collection = nullptr;
|
2019-03-12 19:55:33 -03:00
|
|
|
while ((collection = BKE_collection_object_find(bmain, scene, collection, ob))) {
|
Collections and groups unification
OVERVIEW
* In 2.7 terminology, all layers and groups are now collection datablocks.
* These collections are nestable, linkable, instanceable, overrideable, ..
which opens up new ways to set up scenes and link + override data.
* Viewport/render visibility and selectability are now a part of the collection
and shared across all view layers and linkable.
* View layers define which subset of the scene collection hierarchy is excluded
for each. For many workflows one view layer can be used, these are more of an
advanced feature now.
OUTLINER
* The outliner now has a "View Layer" display mode instead of "Collections",
which can display the collections and/or objects in the view layer.
* In this display mode, collections can be excluded with the right click menu.
These will then be greyed out and their objects will be excluded.
* To view collections not linked to any scene, the "Blender File" display mode
can be used, with the new filtering option to just see Colleciton datablocks.
* The outliner right click menus for collections and objects were reorganized.
* Drag and drop still needs to be improved. Like before, dragging the icon or
text gives different results, we'll unify this later.
LINKING AND OVERRIDES
* Collections can now be linked into the scene without creating an instance,
with the link/append operator or from the collections view in the outliner.
* Collections can get static overrides with the right click menu in the outliner,
but this is rather unreliable and not clearly communicated at the moment.
* We still need to improve the make override operator to turn collection instances
into collections with overrides directly in the scene.
PERFORMANCE
* We tried to make performance not worse than before and improve it in some
cases. The main thing that's still a bit slower is multiple scenes, we have to
change the layer syncing to only updated affected scenes.
* Collections keep a list of their parent collections for faster incremental
updates in syncing and caching.
* View layer bases are now in a object -> base hash to avoid quadratic time
lookups internally and in API functions like visible_get().
VERSIONING
* Compatibility with 2.7 files should be improved due to the new visibility
controls. Of course users may not want to set up their scenes differently
now to avoid having separate layers and groups.
* Compatibility with 2.8 is mostly there, and was tested on Eevee demo and Hero
files. There's a few things which are know to be not quite compatible, like
nested layer collections inside groups.
* The versioning code for 2.8 files is quite complicated, and isolated behind
#ifdef so it can be removed at the end of the release cycle.
KNOWN ISSUES
* The G-key group operators in the 3D viewport were left mostly as is, they
need to be modified still to fit better.
* Same for the groups panel in the object properties. This needs to be updated
still, or perhaps replaced by something better.
* Collections must all have a unique name. Less restrictive namespacing is to
be done later, we'll have to see how important this is as all objects within
the collections must also have a unique name anyway.
* Full scene copy and delete scene are exactly doing the right thing yet.
Differential Revision: https://developer.blender.org/D3383
https://code.blender.org/2018/05/collections-and-groups/
2018-04-30 15:57:22 +02:00
|
|
|
BKE_collection_object_remove(bmain, collection, ob, false);
|
2018-12-06 17:52:37 +01:00
|
|
|
DEG_id_tag_update(&collection->id, ID_RECALC_COPY_ON_WRITE);
|
2012-07-18 09:45:50 +00:00
|
|
|
}
|
|
|
|
|
}
|
2013-09-01 22:01:21 +00:00
|
|
|
|
2021-12-14 15:49:31 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Object KD-Tree
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2019-03-20 00:46:33 +11:00
|
|
|
KDTree_3d *BKE_object_as_kdtree(Object *ob, int *r_tot)
|
2013-09-01 22:01:21 +00:00
|
|
|
{
|
2021-11-04 16:51:37 -03:00
|
|
|
KDTree_3d *tree = nullptr;
|
2013-09-01 22:01:21 +00:00
|
|
|
unsigned int tot = 0;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-09-01 22:01:21 +00:00
|
|
|
switch (ob->type) {
|
|
|
|
|
case OB_MESH: {
|
2021-11-04 16:51:37 -03:00
|
|
|
Mesh *me = (Mesh *)ob->data;
|
2013-09-01 22:01:21 +00:00
|
|
|
unsigned int i;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-10-12 19:22:34 +11:00
|
|
|
Mesh *me_eval = ob->runtime.mesh_deform_eval ? ob->runtime.mesh_deform_eval :
|
2021-09-08 16:50:21 +02:00
|
|
|
BKE_object_get_evaluated_mesh(ob);
|
2014-04-27 00:20:13 +10:00
|
|
|
const int *index;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-11-04 16:51:37 -03:00
|
|
|
if (me_eval && (index = (const int *)CustomData_get_layer(&me_eval->vdata, CD_ORIGINDEX))) {
|
2018-10-12 19:22:34 +11:00
|
|
|
MVert *mvert = me_eval->mvert;
|
|
|
|
|
uint totvert = me_eval->totvert;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-11-08 14:14:14 +11:00
|
|
|
/* Tree over-allocates in case where some verts have #ORIGINDEX_NONE. */
|
2013-09-01 22:01:21 +00:00
|
|
|
tot = 0;
|
2019-03-20 00:46:33 +11:00
|
|
|
tree = BLI_kdtree_3d_new(totvert);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-06-28 15:44:12 +10:00
|
|
|
/* We don't how many verts from the DM we can use. */
|
2013-09-01 22:01:21 +00:00
|
|
|
for (i = 0; i < totvert; i++) {
|
|
|
|
|
if (index[i] != ORIGINDEX_NONE) {
|
2013-09-12 19:51:31 +00:00
|
|
|
float co[3];
|
2013-09-01 22:01:21 +00:00
|
|
|
mul_v3_m4v3(co, ob->obmat, mvert[i].co);
|
2019-03-20 00:46:33 +11:00
|
|
|
BLI_kdtree_3d_insert(tree, index[i], co);
|
2013-09-01 22:01:21 +00:00
|
|
|
tot++;
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2013-09-01 22:01:21 +00:00
|
|
|
else {
|
|
|
|
|
MVert *mvert = me->mvert;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-09-01 22:01:21 +00:00
|
|
|
tot = me->totvert;
|
2019-03-20 00:46:33 +11:00
|
|
|
tree = BLI_kdtree_3d_new(tot);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-09-01 22:01:21 +00:00
|
|
|
for (i = 0; i < tot; i++) {
|
2013-09-12 19:51:31 +00:00
|
|
|
float co[3];
|
2013-09-01 22:01:21 +00:00
|
|
|
mul_v3_m4v3(co, ob->obmat, mvert[i].co);
|
2019-03-20 00:46:33 +11:00
|
|
|
BLI_kdtree_3d_insert(tree, i, co);
|
2013-09-01 22:01:21 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
|
2019-03-20 00:46:33 +11:00
|
|
|
BLI_kdtree_3d_balance(tree);
|
2013-09-01 22:01:21 +00:00
|
|
|
break;
|
|
|
|
|
}
|
2022-02-18 09:50:29 -06:00
|
|
|
case OB_CURVES_LEGACY:
|
2013-09-01 22:01:21 +00:00
|
|
|
case OB_SURF: {
|
|
|
|
|
/* TODO: take deformation into account */
|
2021-11-04 16:51:37 -03:00
|
|
|
Curve *cu = (Curve *)ob->data;
|
2013-09-01 22:01:21 +00:00
|
|
|
unsigned int i, a;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-09-01 22:01:21 +00:00
|
|
|
Nurb *nu;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-09-01 22:01:21 +00:00
|
|
|
tot = BKE_nurbList_verts_count_without_handles(&cu->nurb);
|
2019-03-20 00:46:33 +11:00
|
|
|
tree = BLI_kdtree_3d_new(tot);
|
2013-09-01 22:01:21 +00:00
|
|
|
i = 0;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-11-04 16:51:37 -03:00
|
|
|
nu = (Nurb *)cu->nurb.first;
|
2013-09-01 22:01:21 +00:00
|
|
|
while (nu) {
|
|
|
|
|
if (nu->bezt) {
|
|
|
|
|
BezTriple *bezt;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-09-01 22:01:21 +00:00
|
|
|
bezt = nu->bezt;
|
|
|
|
|
a = nu->pntsu;
|
|
|
|
|
while (a--) {
|
2013-09-12 19:51:31 +00:00
|
|
|
float co[3];
|
2013-09-01 22:01:21 +00:00
|
|
|
mul_v3_m4v3(co, ob->obmat, bezt->vec[1]);
|
2019-03-20 00:46:33 +11:00
|
|
|
BLI_kdtree_3d_insert(tree, i++, co);
|
2013-09-01 22:01:21 +00:00
|
|
|
bezt++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
BPoint *bp;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-09-01 22:01:21 +00:00
|
|
|
bp = nu->bp;
|
|
|
|
|
a = nu->pntsu * nu->pntsv;
|
|
|
|
|
while (a--) {
|
2013-09-12 19:51:31 +00:00
|
|
|
float co[3];
|
2013-09-01 22:01:21 +00:00
|
|
|
mul_v3_m4v3(co, ob->obmat, bp->vec);
|
2019-03-20 00:46:33 +11:00
|
|
|
BLI_kdtree_3d_insert(tree, i++, co);
|
2013-09-01 22:01:21 +00:00
|
|
|
bp++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
nu = nu->next;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-20 00:46:33 +11:00
|
|
|
BLI_kdtree_3d_balance(tree);
|
2013-09-01 22:01:21 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case OB_LATTICE: {
|
|
|
|
|
/* TODO: take deformation into account */
|
2021-11-04 16:51:37 -03:00
|
|
|
Lattice *lt = (Lattice *)ob->data;
|
2013-09-01 22:01:21 +00:00
|
|
|
BPoint *bp;
|
|
|
|
|
unsigned int i;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-09-01 22:01:21 +00:00
|
|
|
tot = lt->pntsu * lt->pntsv * lt->pntsw;
|
2019-03-20 00:46:33 +11:00
|
|
|
tree = BLI_kdtree_3d_new(tot);
|
2013-09-01 22:01:21 +00:00
|
|
|
i = 0;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-09-01 22:01:21 +00:00
|
|
|
for (bp = lt->def; i < tot; bp++) {
|
|
|
|
|
float co[3];
|
|
|
|
|
mul_v3_m4v3(co, ob->obmat, bp->vec);
|
2019-03-20 00:46:33 +11:00
|
|
|
BLI_kdtree_3d_insert(tree, i++, co);
|
2013-09-01 22:01:21 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-20 00:46:33 +11:00
|
|
|
BLI_kdtree_3d_balance(tree);
|
2013-09-01 22:01:21 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-09-01 22:01:21 +00:00
|
|
|
*r_tot = tot;
|
|
|
|
|
return tree;
|
|
|
|
|
}
|
2015-05-12 13:38:55 +05:00
|
|
|
|
2021-12-14 15:49:31 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Object Modifier Utilities
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2020-09-07 14:33:24 +10:00
|
|
|
/**
|
|
|
|
|
* Set "ignore cache" flag for all caches on this object.
|
|
|
|
|
*/
|
2016-01-09 04:37:53 +01:00
|
|
|
static void object_cacheIgnoreClear(Object *ob, int state)
|
|
|
|
|
{
|
|
|
|
|
ListBase pidlist;
|
2021-11-04 16:51:37 -03:00
|
|
|
BKE_ptcache_ids_from_object(&pidlist, ob, nullptr, 0);
|
2016-01-09 04:37:53 +01:00
|
|
|
|
2021-11-04 16:51:37 -03:00
|
|
|
LISTBASE_FOREACH (PTCacheID *, pid, &pidlist) {
|
2016-01-09 04:37:53 +01:00
|
|
|
if (pid->cache) {
|
2019-04-22 09:39:35 +10:00
|
|
|
if (state) {
|
2016-01-09 04:37:53 +01:00
|
|
|
pid->cache->flag |= PTCACHE_IGNORE_CLEAR;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
else {
|
2016-01-09 04:37:53 +01:00
|
|
|
pid->cache->flag &= ~PTCACHE_IGNORE_CLEAR;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2016-01-09 04:37:53 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BLI_freelistN(&pidlist);
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-16 12:45:11 +10:00
|
|
|
bool BKE_object_modifier_update_subframe(Depsgraph *depsgraph,
|
2018-04-06 12:07:27 +02:00
|
|
|
Scene *scene,
|
|
|
|
|
Object *ob,
|
|
|
|
|
bool update_mesh,
|
2017-08-16 12:45:11 +10:00
|
|
|
int parent_recursion,
|
|
|
|
|
float frame,
|
|
|
|
|
int type)
|
2016-01-09 04:37:53 +01:00
|
|
|
{
|
2019-07-31 14:56:17 +02:00
|
|
|
const bool flush_to_original = DEG_is_active(depsgraph);
|
2020-05-08 10:14:02 +02:00
|
|
|
ModifierData *md = BKE_modifiers_findby_type(ob, (ModifierType)type);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-01-09 04:37:53 +01:00
|
|
|
if (type == eModifierType_DynamicPaint) {
|
|
|
|
|
DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)md;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-01-09 04:37:53 +01:00
|
|
|
/* if other is dynamic paint canvas, don't update */
|
2019-04-22 09:39:35 +10:00
|
|
|
if (pmd && pmd->canvas) {
|
2016-01-09 04:37:53 +01:00
|
|
|
return true;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2016-01-09 04:37:53 +01:00
|
|
|
}
|
2019-12-16 15:50:14 +01:00
|
|
|
else if (type == eModifierType_Fluid) {
|
2020-07-03 11:51:15 +02:00
|
|
|
FluidModifierData *fmd = (FluidModifierData *)md;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-07-03 11:51:15 +02:00
|
|
|
if (fmd && (fmd->type & MOD_FLUID_TYPE_DOMAIN) != 0) {
|
2016-01-09 04:37:53 +01:00
|
|
|
return true;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2016-01-09 04:37:53 +01:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-01-09 04:37:53 +01:00
|
|
|
/* if object has parents, update them too */
|
|
|
|
|
if (parent_recursion) {
|
|
|
|
|
int recursion = parent_recursion - 1;
|
|
|
|
|
bool no_update = false;
|
2019-04-22 09:39:35 +10:00
|
|
|
if (ob->parent) {
|
2018-04-06 12:07:27 +02:00
|
|
|
no_update |= BKE_object_modifier_update_subframe(
|
2021-11-04 16:51:37 -03:00
|
|
|
depsgraph, scene, ob->parent, false, recursion, frame, type);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
if (ob->track) {
|
2018-04-06 12:07:27 +02:00
|
|
|
no_update |= BKE_object_modifier_update_subframe(
|
2021-11-04 16:51:37 -03:00
|
|
|
depsgraph, scene, ob->track, false, recursion, frame, type);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-01-09 04:37:53 +01:00
|
|
|
/* skip subframe if object is parented
|
2018-09-02 18:28:27 +10:00
|
|
|
* to vertex of a dynamic paint canvas */
|
2021-10-20 10:45:59 +11:00
|
|
|
if (no_update && (ELEM(ob->partype, PARVERT1, PARVERT3))) {
|
2016-01-09 04:37:53 +01:00
|
|
|
return false;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-01-09 04:37:53 +01:00
|
|
|
/* also update constraint targets */
|
2021-11-04 16:51:37 -03:00
|
|
|
LISTBASE_FOREACH (bConstraint *, con, &ob->constraints) {
|
|
|
|
|
ListBase targets = {nullptr, nullptr};
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-23 23:42:05 +03:00
|
|
|
if (BKE_constraint_targets_get(con, &targets)) {
|
2021-11-04 16:51:37 -03:00
|
|
|
LISTBASE_FOREACH (bConstraintTarget *, ct, &targets) {
|
2019-04-22 09:39:35 +10:00
|
|
|
if (ct->tar) {
|
2018-04-06 12:07:27 +02:00
|
|
|
BKE_object_modifier_update_subframe(
|
2021-11-04 16:51:37 -03:00
|
|
|
depsgraph, scene, ct->tar, false, recursion, frame, type);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2016-01-09 04:37:53 +01:00
|
|
|
}
|
|
|
|
|
/* free temp targets */
|
2020-11-23 23:42:05 +03:00
|
|
|
BKE_constraint_targets_flush(con, &targets, false);
|
2016-01-09 04:37:53 +01:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-03 23:08:40 +10:00
|
|
|
/* was originally ID_RECALC_ALL - TODO: which flags are really needed??? */
|
2017-12-01 12:11:38 +01:00
|
|
|
/* TODO(sergey): What about animation? */
|
T77086 Animation: Passing Dependency Graph to Drivers
Custom driver functions need access to the dependency graph that is
triggering the evaluation of the driver. This patch passes the
dependency graph pointer through all the animation-related calls.
Instead of passing the evaluation time to functions, the code now passes
an `AnimationEvalContext` pointer:
```
typedef struct AnimationEvalContext {
struct Depsgraph *const depsgraph;
const float eval_time;
} AnimationEvalContext;
```
These structs are read-only, meaning that the code cannot change the
evaluation time. Note that the `depsgraph` pointer itself is const, but
it points to a non-const depsgraph.
FCurves and Drivers can be evaluated at a different time than the
current scene time, for example when evaluating NLA strips. This means
that, even though the current time is stored in the dependency graph, we
need an explicit evaluation time.
There are two functions that allow creation of `AnimationEvalContext`
objects:
- `BKE_animsys_eval_context_construct(Depsgraph *depsgraph, float
eval_time)`, which creates a new context object from scratch, and
- `BKE_animsys_eval_context_construct_at(AnimationEvalContext
*anim_eval_context, float eval_time)`, which can be used to create a
`AnimationEvalContext` with the same depsgraph, but at a different
time. This makes it possible to later add fields without changing any
of the code that just want to change the eval time.
This also provides a fix for T75553, although it does require a change
to the custom driver function. The driver should call
`custom_function(depsgraph)`, and the function should use that depsgraph
instead of information from `bpy.context`.
Reviewed By: brecht, sergey
Differential Revision: https://developer.blender.org/D8047
2020-07-17 17:38:09 +02:00
|
|
|
const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(depsgraph,
|
|
|
|
|
frame);
|
|
|
|
|
|
2017-12-15 10:45:20 +01:00
|
|
|
ob->id.recalc |= ID_RECALC_ALL;
|
2016-01-09 04:37:53 +01:00
|
|
|
if (update_mesh) {
|
T77086 Animation: Passing Dependency Graph to Drivers
Custom driver functions need access to the dependency graph that is
triggering the evaluation of the driver. This patch passes the
dependency graph pointer through all the animation-related calls.
Instead of passing the evaluation time to functions, the code now passes
an `AnimationEvalContext` pointer:
```
typedef struct AnimationEvalContext {
struct Depsgraph *const depsgraph;
const float eval_time;
} AnimationEvalContext;
```
These structs are read-only, meaning that the code cannot change the
evaluation time. Note that the `depsgraph` pointer itself is const, but
it points to a non-const depsgraph.
FCurves and Drivers can be evaluated at a different time than the
current scene time, for example when evaluating NLA strips. This means
that, even though the current time is stored in the dependency graph, we
need an explicit evaluation time.
There are two functions that allow creation of `AnimationEvalContext`
objects:
- `BKE_animsys_eval_context_construct(Depsgraph *depsgraph, float
eval_time)`, which creates a new context object from scratch, and
- `BKE_animsys_eval_context_construct_at(AnimationEvalContext
*anim_eval_context, float eval_time)`, which can be used to create a
`AnimationEvalContext` with the same depsgraph, but at a different
time. This makes it possible to later add fields without changing any
of the code that just want to change the eval time.
This also provides a fix for T75553, although it does require a change
to the custom driver function. The driver should call
`custom_function(depsgraph)`, and the function should use that depsgraph
instead of information from `bpy.context`.
Reviewed By: brecht, sergey
Differential Revision: https://developer.blender.org/D8047
2020-07-17 17:38:09 +02:00
|
|
|
BKE_animsys_evaluate_animdata(
|
|
|
|
|
&ob->id, ob->adt, &anim_eval_context, ADT_RECALC_ANIM, flush_to_original);
|
2016-01-09 04:37:53 +01:00
|
|
|
/* ignore cache clear during subframe updates
|
2018-09-02 18:28:27 +10:00
|
|
|
* to not mess up cache validity */
|
2016-01-09 04:37:53 +01:00
|
|
|
object_cacheIgnoreClear(ob, 1);
|
2018-04-06 12:07:27 +02:00
|
|
|
BKE_object_handle_update(depsgraph, scene, ob);
|
2016-01-09 04:37:53 +01:00
|
|
|
object_cacheIgnoreClear(ob, 0);
|
|
|
|
|
}
|
2019-01-29 11:59:17 +01:00
|
|
|
else {
|
2018-04-06 12:07:27 +02:00
|
|
|
BKE_object_where_is_calc_time(depsgraph, scene, ob, frame);
|
2019-01-29 11:59:17 +01:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-01-09 04:37:53 +01:00
|
|
|
/* for curve following objects, parented curve has to be updated too */
|
2022-02-18 09:50:29 -06:00
|
|
|
if (ob->type == OB_CURVES_LEGACY) {
|
2021-11-04 16:51:37 -03:00
|
|
|
Curve *cu = (Curve *)ob->data;
|
T77086 Animation: Passing Dependency Graph to Drivers
Custom driver functions need access to the dependency graph that is
triggering the evaluation of the driver. This patch passes the
dependency graph pointer through all the animation-related calls.
Instead of passing the evaluation time to functions, the code now passes
an `AnimationEvalContext` pointer:
```
typedef struct AnimationEvalContext {
struct Depsgraph *const depsgraph;
const float eval_time;
} AnimationEvalContext;
```
These structs are read-only, meaning that the code cannot change the
evaluation time. Note that the `depsgraph` pointer itself is const, but
it points to a non-const depsgraph.
FCurves and Drivers can be evaluated at a different time than the
current scene time, for example when evaluating NLA strips. This means
that, even though the current time is stored in the dependency graph, we
need an explicit evaluation time.
There are two functions that allow creation of `AnimationEvalContext`
objects:
- `BKE_animsys_eval_context_construct(Depsgraph *depsgraph, float
eval_time)`, which creates a new context object from scratch, and
- `BKE_animsys_eval_context_construct_at(AnimationEvalContext
*anim_eval_context, float eval_time)`, which can be used to create a
`AnimationEvalContext` with the same depsgraph, but at a different
time. This makes it possible to later add fields without changing any
of the code that just want to change the eval time.
This also provides a fix for T75553, although it does require a change
to the custom driver function. The driver should call
`custom_function(depsgraph)`, and the function should use that depsgraph
instead of information from `bpy.context`.
Reviewed By: brecht, sergey
Differential Revision: https://developer.blender.org/D8047
2020-07-17 17:38:09 +02:00
|
|
|
BKE_animsys_evaluate_animdata(
|
|
|
|
|
&cu->id, cu->adt, &anim_eval_context, ADT_RECALC_ANIM, flush_to_original);
|
2016-01-09 04:37:53 +01:00
|
|
|
}
|
|
|
|
|
/* and armatures... */
|
|
|
|
|
if (ob->type == OB_ARMATURE) {
|
2021-11-04 16:51:37 -03:00
|
|
|
bArmature *arm = (bArmature *)ob->data;
|
T77086 Animation: Passing Dependency Graph to Drivers
Custom driver functions need access to the dependency graph that is
triggering the evaluation of the driver. This patch passes the
dependency graph pointer through all the animation-related calls.
Instead of passing the evaluation time to functions, the code now passes
an `AnimationEvalContext` pointer:
```
typedef struct AnimationEvalContext {
struct Depsgraph *const depsgraph;
const float eval_time;
} AnimationEvalContext;
```
These structs are read-only, meaning that the code cannot change the
evaluation time. Note that the `depsgraph` pointer itself is const, but
it points to a non-const depsgraph.
FCurves and Drivers can be evaluated at a different time than the
current scene time, for example when evaluating NLA strips. This means
that, even though the current time is stored in the dependency graph, we
need an explicit evaluation time.
There are two functions that allow creation of `AnimationEvalContext`
objects:
- `BKE_animsys_eval_context_construct(Depsgraph *depsgraph, float
eval_time)`, which creates a new context object from scratch, and
- `BKE_animsys_eval_context_construct_at(AnimationEvalContext
*anim_eval_context, float eval_time)`, which can be used to create a
`AnimationEvalContext` with the same depsgraph, but at a different
time. This makes it possible to later add fields without changing any
of the code that just want to change the eval time.
This also provides a fix for T75553, although it does require a change
to the custom driver function. The driver should call
`custom_function(depsgraph)`, and the function should use that depsgraph
instead of information from `bpy.context`.
Reviewed By: brecht, sergey
Differential Revision: https://developer.blender.org/D8047
2020-07-17 17:38:09 +02:00
|
|
|
BKE_animsys_evaluate_animdata(
|
|
|
|
|
&arm->id, arm->adt, &anim_eval_context, ADT_RECALC_ANIM, flush_to_original);
|
2018-04-06 12:07:27 +02:00
|
|
|
BKE_pose_where_is(depsgraph, scene, ob);
|
2016-01-09 04:37:53 +01:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-01-09 04:37:53 +01:00
|
|
|
return false;
|
|
|
|
|
}
|
2018-11-19 19:33:09 +01:00
|
|
|
|
2019-05-08 09:45:20 +02:00
|
|
|
void BKE_object_update_select_id(struct Main *bmain)
|
|
|
|
|
{
|
2021-11-04 16:51:37 -03:00
|
|
|
Object *ob = (Object *)bmain->objects.first;
|
2019-05-08 09:45:20 +02:00
|
|
|
int select_id = 1;
|
|
|
|
|
while (ob) {
|
|
|
|
|
ob->runtime.select_id = select_id++;
|
2021-11-04 16:51:37 -03:00
|
|
|
ob = (Object *)ob->id.next;
|
2019-05-08 09:45:20 +02:00
|
|
|
}
|
2019-05-16 14:11:11 +02:00
|
|
|
}
|
2019-05-16 13:49:21 +02:00
|
|
|
|
2021-12-14 15:49:31 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Object Conversion
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2019-05-24 14:37:47 +02:00
|
|
|
Mesh *BKE_object_to_mesh(Depsgraph *depsgraph, Object *object, bool preserve_all_data_layers)
|
2019-05-16 13:49:21 +02:00
|
|
|
{
|
|
|
|
|
BKE_object_to_mesh_clear(object);
|
|
|
|
|
|
2021-05-12 23:14:58 +02:00
|
|
|
Mesh *mesh = BKE_mesh_new_from_object(depsgraph, object, preserve_all_data_layers, false);
|
2019-05-16 13:49:21 +02:00
|
|
|
object->runtime.object_as_temp_mesh = mesh;
|
|
|
|
|
return mesh;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BKE_object_to_mesh_clear(Object *object)
|
|
|
|
|
{
|
2021-11-04 16:51:37 -03:00
|
|
|
if (object->runtime.object_as_temp_mesh == nullptr) {
|
2019-05-16 13:49:21 +02:00
|
|
|
return;
|
|
|
|
|
}
|
2021-11-04 16:51:37 -03:00
|
|
|
BKE_id_free(nullptr, object->runtime.object_as_temp_mesh);
|
|
|
|
|
object->runtime.object_as_temp_mesh = nullptr;
|
2019-05-16 13:49:21 +02:00
|
|
|
}
|
2020-08-05 11:54:18 +02:00
|
|
|
|
2021-02-20 18:05:13 +02:00
|
|
|
Curve *BKE_object_to_curve(Object *object, Depsgraph *depsgraph, bool apply_modifiers)
|
|
|
|
|
{
|
|
|
|
|
BKE_object_to_curve_clear(object);
|
|
|
|
|
|
|
|
|
|
Curve *curve = BKE_curve_new_from_object(object, depsgraph, apply_modifiers);
|
|
|
|
|
object->runtime.object_as_temp_curve = curve;
|
|
|
|
|
return curve;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BKE_object_to_curve_clear(Object *object)
|
|
|
|
|
{
|
2021-11-04 16:51:37 -03:00
|
|
|
if (object->runtime.object_as_temp_curve == nullptr) {
|
2021-02-20 18:05:13 +02:00
|
|
|
return;
|
|
|
|
|
}
|
2021-11-04 16:51:37 -03:00
|
|
|
BKE_id_free(nullptr, object->runtime.object_as_temp_curve);
|
|
|
|
|
object->runtime.object_as_temp_curve = nullptr;
|
2021-02-20 18:05:13 +02:00
|
|
|
}
|
|
|
|
|
|
2020-08-05 11:54:18 +02:00
|
|
|
void BKE_object_check_uuids_unique_and_report(const Object *object)
|
|
|
|
|
{
|
|
|
|
|
BKE_pose_check_uuids_unique_and_report(object->pose);
|
|
|
|
|
BKE_modifier_check_uuids_unique_and_report(object);
|
|
|
|
|
}
|
2020-11-06 16:42:37 +01:00
|
|
|
|
|
|
|
|
void BKE_object_modifiers_lib_link_common(void *userData,
|
|
|
|
|
struct Object *ob,
|
|
|
|
|
struct ID **idpoin,
|
|
|
|
|
int cb_flag)
|
|
|
|
|
{
|
2021-11-04 16:51:37 -03:00
|
|
|
BlendLibReader *reader = (BlendLibReader *)userData;
|
2020-11-06 16:42:37 +01:00
|
|
|
|
|
|
|
|
BLO_read_id_address(reader, ob->id.lib, idpoin);
|
2021-11-04 16:51:37 -03:00
|
|
|
if (*idpoin != nullptr && (cb_flag & IDWALK_CB_USER) != 0) {
|
2020-11-06 16:42:37 +01:00
|
|
|
id_us_plus_no_lib(*idpoin);
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-09-06 18:22:24 +02:00
|
|
|
|
OpenSubDiv: add support for an OpenGL evaluator
This evaluator is used in order to evaluate subdivision at render time, allowing for
faster renders of meshes with a subdivision surface modifier placed at the last
position in the modifier list.
When evaluating the subsurf modifier, we detect whether we can delegate evaluation
to the draw code. If so, the subdivision is first evaluated on the GPU using our own
custom evaluator (only the coarse data needs to be initially sent to the GPU), then,
buffers for the final `MeshBufferCache` are filled on the GPU using a set of
compute shaders. However, some buffers are still filled on the CPU side, if doing so
on the GPU is impractical (e.g. the line adjacency buffer used for x-ray, whose
logic is hardly GPU compatible).
This is done at the mesh buffer extraction level so that the result can be readily used
in the various OpenGL engines, without having to write custom geometry or tesselation
shaders.
We use our own subdivision evaluation shaders, instead of OpenSubDiv's vanilla one, in
order to control the data layout, and interpolation. For example, we store vertex colors
as compressed 16-bit integers, while OpenSubDiv's default evaluator only work for float
types.
In order to still access the modified geometry on the CPU side, for use in modifiers
or transform operators, a dedicated wrapper type is added `MESH_WRAPPER_TYPE_SUBD`.
Subdivision will be lazily evaluated via `BKE_object_get_evaluated_mesh` which will
create such a wrapper if possible. If the final subdivision surface is not needed on
the CPU side, `BKE_object_get_evaluated_mesh_no_subsurf` should be used.
Enabling or disabling GPU subdivision can be done through the user preferences (under
Viewport -> Subdivision).
See patch description for benchmarks.
Reviewed By: campbellbarton, jbakker, fclem, brecht, #eevee_viewport
Differential Revision: https://developer.blender.org/D12406
2021-12-27 16:34:47 +01:00
|
|
|
SubsurfModifierData *BKE_object_get_last_subsurf_modifier(const Object *ob)
|
|
|
|
|
{
|
|
|
|
|
ModifierData *md = (ModifierData *)(ob->modifiers.last);
|
|
|
|
|
|
|
|
|
|
while (md) {
|
|
|
|
|
if (md->type == eModifierType_Subsurf) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
md = md->prev;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (SubsurfModifierData *)(md);
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-06 18:22:24 +02:00
|
|
|
void BKE_object_replace_data_on_shallow_copy(Object *ob, ID *new_data)
|
|
|
|
|
{
|
|
|
|
|
ob->type = BKE_object_obdata_to_type(new_data);
|
2021-11-04 16:51:37 -03:00
|
|
|
ob->data = (void *)new_data;
|
|
|
|
|
ob->runtime.geometry_set_eval = nullptr;
|
2021-11-05 16:19:09 +01:00
|
|
|
ob->runtime.data_eval = new_data;
|
2021-11-04 16:51:37 -03:00
|
|
|
if (ob->runtime.bb != nullptr) {
|
2021-09-07 13:03:06 +02:00
|
|
|
ob->runtime.bb->flag |= BOUNDBOX_DIRTY;
|
|
|
|
|
}
|
2021-11-04 16:51:37 -03:00
|
|
|
ob->id.py_instance = nullptr;
|
2021-09-06 18:22:24 +02:00
|
|
|
}
|
2021-09-08 08:39:03 +02:00
|
|
|
|
2021-12-14 15:49:31 +11:00
|
|
|
/** \} */
|