1
1

Compare commits

...

286 Commits

Author SHA1 Message Date
Julian Eisel
8927bc5dff Swap order of selectability/visibility toggles
Just to be consistent with outliner.
2017-02-09 14:34:08 +01:00
Julian Eisel
39739c1c5f Add columns for visibility and selectability toggles
Good example of where the table API is useful: Adding new columns is a
small change.
2017-02-09 14:28:55 +01:00
Julian Eisel
7821985196 Use entire width of collections editor for table 2017-02-09 14:01:51 +01:00
Julian Eisel
86c70c5d6d Use table background drawing for collections editor 2017-02-09 13:58:17 +01:00
Julian Eisel
fea46f6ad6 Merge branch 'uiTable' into temp-layers-ui-table 2017-02-09 13:52:03 +01:00
Julian Eisel
ac5cbf8c0e Fix mistakes with background drawing 2017-02-09 13:51:39 +01:00
Julian Eisel
c4a6f70783 Draw collection names using layout/button engine
Instead of drawing it directly via BLF call.
2017-02-09 05:22:40 +01:00
Julian Eisel
c38aee2b46 Merge branch 'uiTable' into temp-layers-ui-table 2017-02-09 05:09:56 +01:00
Julian Eisel
d1fb6819d5 Create and pass a uiLayout to cells
Played with a more complex and more efficient version, but that made
things pretty complicated. Now this is a simple, but less optimized, solution.
2017-02-09 05:09:10 +01:00
Julian Eisel
5caeb054ee Support drawing some background color alternating per row 2017-02-09 02:56:27 +01:00
Julian Eisel
2f43ab5935 Draw tables row by row, not column by column 2017-02-08 00:04:09 +01:00
Julian Eisel
4e3cfaeb16 Unit tests for uiTable API (and fix bugs found using it :) 2017-02-07 00:45:33 +01:00
Julian Eisel
185f588e1c Initial commit to use uiTable API for collections editor
Does nothing but drawing a single column for collection name, but it
shows that the API works ;)
2017-02-05 18:22:47 +01:00
Julian Eisel
7dfd122dc9 Merge branch 'uiTable' into temp-layers-ui-table 2017-02-05 17:47:56 +01:00
Julian Eisel
1807c09986 Cleanup: Add assert, remove unused variable 2017-02-05 17:25:12 +01:00
Julian Eisel
1a7eeb4fef Initial implementation of a uiTable API
This adds an initial (and already working), generic API for defining, handling and drawing of table UIs.

It supports two types of tables:
* Vertical flow: Rows are all in a vertical stack.
* Horizontal flow: Rows are stacked vertically, until some threshold height is reached. The table is then split into another vertical stack that is drawn next to the former one. Such drawing could be used for the file browser in non-thumbnail mode.

A table is built out of - guess what - rows and columns. The API allows defining new collumns (identified by an id-name) and inserting new rows at any point. When drawing, we draw a cell for each column/row combination, using a custom cell-drawing callback.
The uiTable API will probably get some support for drawing buttons (uiBut) into custom layouts (uiLayout).

The API is written with big data sets in mind. In future we may get a spreadsheet view where data like all vertices of a mesh is displayed. That would result in thousands of rows, the uiTable API should be ready for this.
2017-02-05 16:43:56 +01:00
Dalai Felinto
0412b0d296 Merge remote-tracking branch 'origin/clay-engine' into render-layers 2017-02-03 18:18:58 +01:00
71c8db2a0c Build Clay engine by default 2017-02-03 17:51:04 +01:00
Dalai Felinto
1e69c9e1c8 Another fixup for rB6cdb3845 (Added collection props getter/setter)
Values were getting clamped
2017-02-03 17:39:54 +01:00
Dalai Felinto
16385ae285 Merge remote-tracking branch 'origin/clay-engine' into render-layers 2017-02-03 17:22:51 +01:00
Dalai Felinto
2b04710d61 UI: use the "USE" flag for collection settings
Note, this should be a proper uiTemplate, but a pure python approach seems to work fine for now
2017-02-03 16:16:39 +01:00
Dalai Felinto
35fb0e341b RNA: macros to wrap collection settings use 2017-02-03 16:16:39 +01:00
Dalai Felinto
83fea5307b layer: getter/setter for USE flag 2017-02-03 16:16:39 +01:00
Dalai Felinto
6644ff25f2 Update collection engine setings when updating collection values 2017-02-03 16:16:39 +01:00
Dalai Felinto
7f2da487a6 Placeholder for depsgraph evaluation of collection engine settings 2017-02-03 16:16:39 +01:00
41ba828131 Fix bplayer (c) 2017-02-03 15:18:32 +01:00
Dalai Felinto
79924fce49 RNA: use new getter/setter functions for LayerEngineSettings 2017-02-03 15:06:11 +01:00
Dalai Felinto
865a0de03d Fixup for rB6cdb3845 (Added collection props getter/setter) 2017-02-03 15:05:11 +01:00
4a84884e99 Fix warnings 2017-02-03 14:52:33 +01:00
7203aa24f9 New CMake flag for Clay Engine 2017-02-03 14:38:11 +01:00
9fb97e3f85 Fix hang infinite loop 2017-02-03 14:37:50 +01:00
0ee52a5741 Get rid of runtime data struct. 2017-02-03 13:33:59 +01:00
6cdb3845a3 Added collection settings getter/setter 2017-02-03 13:33:59 +01:00
8a22429db2 Change settings order 2017-02-03 13:33:59 +01:00
Dalai Felinto
eaf9748f23 Fix new objects are invisible 2017-02-03 12:46:47 +01:00
Dalai Felinto
a8ce1c98fe Set COLLECTION_PROP_USE when setting a layer_engine_settings property
We still need depsgraph to evaluate those changes
2017-02-03 12:23:01 +01:00
Dalai Felinto
5a9cd6a14d Util function to create CollectionEngineSettings
This may be run by Depsgraph, as well as internal layercollection create routines
2017-02-03 12:23:01 +01:00
Dalai Felinto
fa2bf9381b Util function to free CollectionEngineSettings
This may be run by Depsgraph, as well as internal layercollection free routines
2017-02-03 12:23:01 +01:00
Dalai Felinto
e1b13c0fa7 Fix storage of CollectionSettings in DNA_object_types.h 2017-02-03 12:23:01 +01:00
Dalai Felinto
85f7ad95ed Remove unused enum values (COLLECTION_PROP_TYPE_POINTER/BOOL) 2017-02-03 12:23:01 +01:00
Dalai Felinto
bd0367d1e6 Fix return in BKE_scene_layer_find_from_collection 2017-02-03 10:51:13 +01:00
0e3ba7cf41 More lamp work 2017-02-02 22:19:23 +01:00
e148661d8d Use vec2 for screen space stuff 2017-02-02 21:44:14 +01:00
6f1bdaab9d Lamp sunrays and shadow circles 2017-02-02 21:39:58 +01:00
Dalai Felinto
fbb9bffe1b Bring back the select button for the UI 2017-02-02 18:06:27 +01:00
8641fa1397 Fix unfreed memory 2017-02-02 17:15:26 +01:00
b12d2fb922 Fix warnings 2017-02-02 17:03:21 +01:00
e572cf1239 Fix depth not cleared 2017-02-02 16:54:34 +01:00
f695c9861f Bypass wires. 2017-02-02 16:54:15 +01:00
c1057ac196 Fix ogl warnings. 2017-02-02 16:28:16 +01:00
b1add8e5bd Fix assert 2017-02-02 16:23:21 +01:00
92a2b444b0 Added Lamp screen space visual 2017-02-02 14:17:29 +01:00
0ccfa297f9 Start of Lamp drawing 2017-02-02 11:58:24 +01:00
6144721778 Groundline/GroundPoint shader for lights 2017-02-02 11:58:24 +01:00
Dalai Felinto
003c64757d Clay Engine per-collection settings
Note: this is still not used by rendering
2017-02-02 11:26:36 +01:00
Dalai Felinto
0b834c4fd9 Introduce Per-Collection Render settings
Pending:

* UI template for those settings (showing USE)
* Depsgraph evaluation of them (to flush into objects)
* RNA to see if a settings is being used
2017-02-02 11:26:36 +01:00
0651227c4a Fixing Memory Leak 2017-02-01 14:32:48 +01:00
160c643131 Implemented All Empties type drawing 2017-02-01 13:58:49 +01:00
Dalai Felinto
a19607ca56 Silence more warnings
This should silence the current warnings, and gives us real warnings if
the bContext data is tampered with.
2017-02-01 11:59:59 +01:00
Dalai Felinto
0526088819 Silence warning
There is still a warning because of `DST.context = C;` which discards
'const' qualifier. I find this a legit problem, I suspect we are not
suppose to store bContext at all.
2017-02-01 11:47:03 +01:00
85194046e6 Giving Overlay Edges a try 2017-02-01 00:28:16 +01:00
242715b843 Code cleanup 2017-01-31 17:27:19 +01:00
81db4d2b43 Added wire outlines 2017-01-31 17:27:05 +01:00
641828bf85 Code Cleanup 2017-01-31 16:15:06 +01:00
Dalai Felinto
f6b66e76e1 Use new temporary depsgraph
The idea is to use only Object, never Base
2017-01-31 15:21:40 +01:00
Dalai Felinto
dd4c638c0d Remove unused function (silence warning) 2017-01-31 15:20:40 +01:00
Dalai Felinto
71d7c57997 Merge branch 'render-layers' into clay-engine 2017-01-31 15:06:51 +01:00
Dalai Felinto
835f9742e6 Depsgraph hack: DEG_OBJECT_ITER and base_flag
This is a temporary iterator that flushes the base flag to the object
2017-01-31 15:06:34 +01:00
481785f153 Merge branch 'render-layers' of git.blender.org:blender into clay-engine 2017-01-31 14:03:00 +01:00
581b0c9a4f More Object mode work. 2017-01-31 14:01:23 +01:00
Dalai Felinto
a6191d0e27 UI: temporary panels for layer/collections 2017-01-31 13:06:26 +01:00
Dalai Felinto
6064ffdc83 bpy.ops.collections.* accessible outside collection editor 2017-01-31 13:05:26 +01:00
Dalai Felinto
c955b77f7d bpy.ops.collections.select()
When we introduce overrides we will extend it to have override_index,
and if it is -1, only set the collection
2017-01-31 13:05:23 +01:00
Dalai Felinto
a0e4ae5d37 bpy.ops.collections.collection_new() 2017-01-31 13:05:19 +01:00
Dalai Felinto
7f498b4bde Remove old layers bitflag from viewport 3d header template 2017-01-31 11:46:02 +01:00
Dalai Felinto
fb5682412d Let scene_collection and layer_collection to have the same fallback 2017-01-31 11:45:09 +01:00
c4c3951c4f Initial implementation of instancing 2017-01-31 11:44:40 +01:00
75d6a30cc2 Show Render Layer panel to clay engine. 2017-01-31 11:44:40 +01:00
Dalai Felinto
64b07e866a Add icon to collection panel 2017-01-31 10:52:09 +01:00
Dalai Felinto
52e1728a12 Fix logic for bpy.context.scene_collection 2017-01-31 10:46:06 +01:00
Dalai Felinto
910f16576d Unittest: refresh blender between tests 2017-01-31 10:14:46 +01:00
Dalai Felinto
5fa0315a75 Mesh batch caches should not be stored in file 2017-01-30 18:31:29 +01:00
Dalai Felinto
a35a66f702 Properties Editor: Collection context 2017-01-30 18:24:33 +01:00
Dalai Felinto
f35d38e5a7 Collections Editor: populate header with operators 2017-01-30 18:23:51 +01:00
Dalai Felinto
45b9dee8bd SceneCollection.objects.active_index (for user interface) 2017-01-30 18:23:05 +01:00
Dalai Felinto
8605eb9c97 Collection related operators barebones
Those are the operators for the collections editor, and the collection property panel
2017-01-30 18:21:36 +01:00
Dalai Felinto
1bfc6e79ee RNA: collection override 2017-01-30 18:21:34 +01:00
Dalai Felinto
f51c34185e bpy.context.layer_collection 2017-01-30 18:21:07 +01:00
f2e217938e Fixed unfreed memory 2017-01-30 15:35:12 +01:00
106f415ddd Fix crash on read file 2017-01-30 15:17:03 +01:00
b86e5a9fbf Fixed Pointer problem. Now materials are working. 2017-01-30 15:09:35 +01:00
12bac207c7 Added scene.active_engine_settings 2017-01-30 14:41:58 +01:00
Dalai Felinto
3da834e83c Collection Editor 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 didn't include the editors/space_collections/ draw and util files.

I still need to bring the drawing code here, so we see something.
2017-01-30 14:20:31 +01:00
Dalai Felinto
dce8ef49ff Layers: allow anonymous collection, and set active collection when linking it 2017-01-30 14:15:07 +01:00
08675b94ef Fixed Engine name length 2017-01-30 13:03:30 +01:00
ba4a30c71b Fix read/writefile.c 2017-01-30 12:19:51 +01:00
e15c16f11c Changes to DNA/RNA. Follow same layout as sensors. 2017-01-30 02:24:18 +01:00
744f26b612 Change in DNA/RNA. Still missing freeing and read/write. 2017-01-29 00:55:46 +01:00
5bf60530e5 Added switch to test viewport cache 2017-01-27 17:17:01 +01:00
Dalai Felinto
86887fe1c5 Temporarily prevent crash on edit mode 2017-01-27 15:20:19 +01:00
Dalai Felinto
29669db7d7 Merge remote-tracking branch 'origin/render-layers' into clay-engine 2017-01-27 12:46:39 +01:00
efa401b086 Introduce Dynamic Batches + Relationship lines + Clear some matrix warnings 2017-01-27 11:18:16 +01:00
4c416aea3b Merge branch 'render-layers' of git.blender.org:blender into clay-engine
# Conflicts:
#	source/blender/makesdna/DNA_scene_types.h
2017-01-26 19:49:09 +01:00
Dalai Felinto
c1742b88a4 Merge remote-tracking branch 'origin/blender2.8' into render-layers
Note:

renamed blo_do_versions_after_linking_280 to do_versions_after_linking_280 to following the pattern of do_versions_after_linking_270
2017-01-26 19:17:22 +01:00
Dalai Felinto
8f673cb40c Fix blenderplayer build 2017-01-26 19:01:49 +01:00
fcd5880d12 Fix include compilation error on MSVC 2015. 2017-01-26 18:51:22 +01:00
92e5dfbeed Fix compilation error on windows 2017-01-26 18:33:24 +01:00
Dalai Felinto
40aa8a1c79 Fixup for selected_objects context
This was making crash happen for any operation :/ shame on me
2017-01-26 18:27:30 +01:00
Dalai Felinto
51f77a10eb Fixup in doversioning 2017-01-26 18:25:08 +01:00
00c3c6824d Integrated MBC functions. Added Object centers and empties. 2017-01-26 15:56:40 +01:00
Dalai Felinto
e346927111 Remove unused panels (layer_passes and layer_options) 2017-01-25 18:02:58 +01:00
Dalai Felinto
dd61b7d346 Add scene active layer 2017-01-25 18:02:09 +01:00
Dalai Felinto
99e8618202 Remove scene layer and collection from context 2017-01-25 17:01:39 +01:00
72ff78a951 Merge branch 'render-layers' of git.blender.org:blender into clay-engine
# Conflicts:
#	source/blender/editors/space_view3d/drawobject.c
2017-01-25 12:28:52 +01:00
95e9790704 Fix compile error 2017-01-25 12:21:43 +01:00
Dalai Felinto
212e5d60d3 Merge remote-tracking branch 'origin/blender2.8' into render-layers 2017-01-25 10:17:38 +01:00
c5ed943479 Clay Material work. 2017-01-23 18:36:30 +01:00
Dalai Felinto
673a149e87 Merge remote-tracking branch 'origin/blender2.8' into render-layers 2017-01-23 11:17:09 +01:00
efa46d7db0 Initial support of Uniform Buffer objects 2017-01-23 09:54:54 +01:00
bbbb8405b6 Removed Batch storage
Also lots of renaming
Small visual tweaks
Material Settings Struct is now shared by Scene and material
2017-01-20 01:11:42 +01:00
Dalai Felinto
f8e4999656 I hereby declare layers syncing fully implemented! 2017-01-19 18:25:18 +01:00
Dalai Felinto
1edabaee72 curve convert and mesh separation working 2017-01-19 18:25:18 +01:00
Dalai Felinto
8a8e5055e3 Refactor mball util function, untested
I have not address MBalls directly, so there are probably other parts that are required to conform to the new code before consider than useful
2017-01-19 18:25:18 +01:00
Dalai Felinto
adcb6a1b90 Handle main object dupli functions
Missing: mesh separation, material split, mesh conversion (curve to mesh)
2017-01-19 18:25:18 +01:00
Dalai Felinto
971aa5f838 unittest: bpy.ops.object.duplicate 2017-01-19 18:25:18 +01:00
Dalai Felinto
caf59d3709 Use more of the FOREACH macros in screen_context.c 2017-01-19 17:15:19 +01:00
Dalai Felinto
bd14352a01 object/base iterator refactor + add FOREACH_VISIBLE_BASE 2017-01-19 12:07:12 +01:00
Dalai Felinto
32662bc95d Using static for prototypes 2017-01-19 12:06:18 +01:00
76dead8603 Basic Implementation of GTAO :
There is still artifacts to remove and optimisation to do.
2017-01-18 18:55:56 +01:00
Dalai Felinto
550446bade Tag areas of code that require TODO_LAYER_COPY 2017-01-18 15:41:27 +01:00
Dalai Felinto
10db593060 Merge remote-tracking branch 'origin/blender2.8' into render-layers
Manual fix: collection.c layer.c
2017-01-18 15:40:05 +01:00
Dalai Felinto
03fc433e18 Fix unittest for cases where we set render_layer but not scene_collection 2017-01-18 11:59:26 +01:00
Dalai Felinto
597cafb873 Fix context operator test
We needed a fallback for the cases where the layer was specified but not a scene_collection
2017-01-18 11:56:28 +01:00
Dalai Felinto
53eabca4e8 BKE_scene_layer_has_collection
Util function to check if a SceneCollection is linked to a SceneLayer

This is needed for corner cases of bpy.context.scene_collection when the context render_layer mismatches the context scene_collection.
2017-01-18 11:48:40 +01:00
Dalai Felinto
096f251122 Left-over from previous commit (remove OBJECT_OT_move_to_layer) 2017-01-17 17:58:56 +01:00
Dalai Felinto
b3ce0625c6 Remove OBJECT_OT_move_to_layer 2017-01-17 17:45:08 +01:00
Dalai Felinto
ef7dc52b53 Link objects in scene using ObjectBase 2017-01-17 17:42:32 +01:00
Dalai Felinto
74ba736fc4 Update selected_editable_bases to use ObjectBase 2017-01-17 15:33:46 +01:00
Dalai Felinto
78b630844b Remove base from BKE_object_groups_clear 2017-01-17 15:32:55 +01:00
Dalai Felinto
b1ff8e8703 Remove OB_FROMGROUP from base, and add util funcs to sync base/object flags
I still want to remove the syncing of base/object flags. But for now
this will at least help future refactor.
2017-01-17 14:58:41 +01:00
Dalai Felinto
216273d9e9 ObjectBase need a flag for from_dupli temp objects 2017-01-17 14:13:53 +01:00
e6bba9fa3a Edge AO improvement when geometry is over the background. 2017-01-17 12:59:39 +01:00
Dalai Felinto
fd99d52448 Fixup on versioning (re: selected objects) 2017-01-17 12:46:31 +01:00
Dalai Felinto
c36cdb92d6 Update selectable_bases to use ObjectBase 2017-01-16 17:49:35 +01:00
Dalai Felinto
9ddb221aab Update visible_bases to use ObjectBase 2017-01-16 17:04:02 +01:00
Dalai Felinto
5ff3dd5d97 Fix logic for BKE_scene_layer_base_flag_recalculate 2017-01-16 16:36:53 +01:00
Dalai Felinto
d2f97224b5 Remove select by layer operator 2017-01-16 15:12:58 +01:00
Dalai Felinto
10754500b0 Add BASE_SELECTABLED flag 2017-01-16 15:12:58 +01:00
Dalai Felinto
8a3dd31658 Rename: BASE_VISIBLE > BASE_VISIBLED
BASE_VISIBLE was already defined on DNA_scene_types.h
2017-01-16 15:12:58 +01:00
Dalai Felinto
911c31c201 Remove object hide operators 2017-01-16 15:12:58 +01:00
Dalai Felinto
c21e00683c Remove outliner restrict options for objects (and groups) 2017-01-16 15:12:58 +01:00
Dalai Felinto
0ad3979a6c Implement update of selected/visible based on collection tree 2017-01-16 10:54:34 +01:00
Dalai Felinto
c4e34a84e0 Outliner: initial work for render-layers
Remove Base references, still need to do some adjustments
2017-01-13 18:34:18 +01:00
Dalai Felinto
baad441362 FOREACH_VISIBLE_OBJECT macro
Also adding a new flag value for ObjectBase to store visibility.

I still need this to be synced, but the idea is to centralize the
logic of tree evluation, and keep the visibility cached.
2017-01-13 18:34:18 +01:00
Dalai Felinto
533965db73 Initial syncing of selection and visibility flag
When we make a collection invisible or unselectable, selected object have to be re-evaluated
Same goes for when we add a new object, its base visibility has to be
refreshed.

TODO also add a call for this when we remove a scene collection, or
unlink a scene layer.
2017-01-13 18:34:18 +01:00
33ca692256 Added object mode wires to new drawing pipeline. 2017-01-13 18:25:06 +01:00
Dalai Felinto
988024063f Use ObjectBase only to delete objects 2017-01-13 11:21:20 +01:00
Dalai Felinto
07d571ea22 Remove Bases onces and for all
This officially makes the viewport not draw anything, until we get the
new ObjectBase * to use.

This is easily revertable, but for now I prefer to make sure this is not
in the way of refactoring.
2017-01-12 18:23:01 +01:00
Dalai Felinto
0fba4655bf Updated python files to use select_get/_set() [not addons] 2017-01-12 17:51:09 +01:00
e954a6b8bc Fix crash. 2017-01-12 12:29:58 +01:00
306711c7ab Separate SSAO code & add orthographic support 2017-01-12 01:15:16 +01:00
382ade4c29 Added saturation and value slider + fix versioning 2017-01-11 19:48:51 +01:00
2c3d9f2762 Merge remote-tracking branch 'origin/render-layers' into clay-engine
# Conflicts:
#	source/blender/editors/space_view3d/drawobject.c
#	source/blender/gpu/intern/gpu_viewport.c
2017-01-11 17:41:18 +01:00
ddd95b9712 Fixed versionning 2017-01-11 17:38:00 +01:00
a94b4c2ff0 Fix Crash and Unfreed Memory 2017-01-11 16:58:08 +01:00
fd7f78d89f Introduce Batch storage. 2017-01-11 16:34:02 +01:00
Dalai Felinto
d97c6c36b8 Fix mem freed twice 2017-01-11 16:20:10 +01:00
Dalai Felinto
051f0a0b15 _free() functions should not clear the pointer itself 2017-01-11 15:54:56 +01:00
Dalai Felinto
a80d94c289 BLI_assert fix 2017-01-11 15:54:26 +01:00
Dalai Felinto
4180ca9b92 Doversion: set selected objects for "Render Layer" 2017-01-11 12:58:54 +01:00
Dalai Felinto
6d68195a9b Doversion: set active object for "Render Layer"
We don't do it for the other render layers (the ones converted from
SceneRenderLayer)
2017-01-11 12:58:25 +01:00
Dalai Felinto
345eb6f7cc RNA: object.select_get/set(action={'SELECT', 'DESELECT', 'TOGGLE'}) 2017-01-11 12:48:36 +01:00
Dalai Felinto
ec65bc6e76 Introduce ObjectBase rna wrapper for bpy.context.active_base 2017-01-11 11:45:41 +01:00
Dalai Felinto
b00cfb77cd Use active_object instead of active_base for edit mode enter
(prevent a crash after recent Base > ObjectBase commit)
2017-01-11 11:05:22 +01:00
Dalai Felinto
70ddef82b7 Merge remote-tracking branch 'origin/blender2.8' into render-layers 2017-01-11 09:47:30 +01:00
8c3a98e583 Added Matcap HSV variation (only Hue exposed). 2017-01-11 01:49:03 +01:00
89d99b6b77 Added matcap rotation 2017-01-10 23:52:13 +01:00
1ceeac2cab Use overall matcap colors as AO color avoiding completelly dark areas. 2017-01-10 22:03:57 +01:00
Dalai Felinto
d89274e83a Merge remote-tracking branch 'origin/blender2.8' into render-layers 2017-01-10 18:37:06 +01:00
Dalai Felinto
a771249d7d Add new objects and some Base > ObjectBase convertion
New objects are properly added to the correct collection, and are synced
into the correct collections.
2017-01-10 17:56:31 +01:00
c8162c5a2c Added SSAO to give cavity / Edge highlight effect. 2017-01-10 17:33:30 +01:00
Dalai Felinto
143c869bd0 Fix selected_objects iterator 2017-01-10 16:17:22 +01:00
Dalai Felinto
33ee18ad6f rename ob_base > base, it will simplify further refactors 2017-01-10 16:17:22 +01:00
Dalai Felinto
d16bfecde1 Removing Bases from clay.c and other fixes
Listbase was used wrongly in draw_manager, using LinkData elements now
2017-01-09 17:52:06 +01:00
Dalai Felinto
2ad2b23911 Merge remote-tracking branch 'origin/render-layers' into clay-engine 2017-01-09 16:35:25 +01:00
Dalai Felinto
052b45ac2a Fixup for iterator
(this is a placeholder anyways, what we really need is DEG_OBJECT_ITER()
2017-01-09 16:33:42 +01:00
Dalai Felinto
551852f4ca Adding FOREACH_OBJECT iterator 2017-01-09 16:17:04 +01:00
c9c0d6c24f Add properties to clay material (not exposed yet) 2017-01-09 15:06:17 +01:00
Dalai Felinto
1020914980 unittest: check context overriden passed to operator 2017-01-06 18:13:32 +01:00
Dalai Felinto
9f333a0889 unittest: use proper setUpModule class method() 2017-01-06 18:01:08 +01:00
Dalai Felinto
7e57905385 unittest: use assertEqual instead of assertTrue
(thanks to Sybren Stuvel)
2017-01-06 16:37:15 +01:00
ca4618bdbf Apply changes GPU_texture change. 2017-01-06 14:39:34 +01:00
2cf79f41fe Modifications to GPU_texture:
-Remove NPOT check as it should be supported by default with OGL 3.3
-All custom texture creation follow the same path now
-Now explicit texture format is required when creating a custom texture (Non RGBA8)
-Support for arrays of textures
2017-01-06 14:38:36 +01:00
Dalai Felinto
6933bb4e9a Fixup for bpy.context.scene_collection 2017-01-06 14:31:48 +01:00
Dalai Felinto
b5d41b1d71 RNA: bpy.context.scene_collection
We will need this for UI eventually, and now I need this to update the
Python add object routine.
2017-01-05 18:25:29 +01:00
Dalai Felinto
71e5e87f01 Unittest debug options, set context via override and bpy.context.scene_collection
For some reason ID is not being passed when we get SceneCollection from
bpy.context. This test fails in that case.
2017-01-05 18:24:28 +01:00
5333b2aa00 (Clay) Free memory + lots of renaming/reorganizing
Signed-off-by: Clément Foucault <foucault.clem@gmail.com>
2017-01-05 16:13:20 +01:00
c990364559 Merge remote-tracking branch 'origin/render-layers' into clay-engine 2017-01-05 11:28:28 +01:00
624f3c254f (Clay) Added Render settings:
- Default clay settings inside Scene RNA
- Material clay settings RNA is here and will be used once we can render multiple meshes
2017-01-05 11:28:11 +01:00
Dalai Felinto
d80372c9f4 handle objects removal only on preprocess 2017-01-04 18:34:49 +01:00
Dalai Felinto
7bd56f207d Merge remote-tracking branch 'origin/blender2.8' into render-layers 2017-01-04 18:27:14 +01:00
Dalai Felinto
ac6019e079 unittest: del via operator fixup 2017-01-04 18:26:13 +01:00
Dalai Felinto
ac80793592 Include object unlinking in library_remap preprocessing 2017-01-04 18:19:51 +01:00
Dalai Felinto
f8dd25afb8 remove objects from collections when ED_base_object_free_and_unlink 2017-01-04 18:04:32 +01:00
0c4776280d More work on Clay engine:
- Calculate normals with dfdy while waiting for a proper way to draw mesh normals.
- Added initial support for 2d texture arrays.
- Better API naming.
- Generate Matcap texture arrays and draw with it.
2017-01-04 11:01:14 +01:00
Dalai Felinto
3bdd555159 Massive fixup on BLI_iterator and the iterators using it 2017-01-03 18:21:15 +01:00
Dalai Felinto
36c34b96b3 From review: handle post processing of objects after they are removed 2017-01-03 16:46:05 +01:00
Dalai Felinto
caed6aad4b unittest: object delete 2017-01-03 16:42:57 +01:00
Dalai Felinto
b89b1b58b2 From review: proper handle of library_query 2017-01-03 11:48:42 +01:00
fe0df0a972 Beginning Clay Viewport Engine :
- Added temporary draw_mesh function to render edit mesh
- DRW_draw_batch_list allows to render a list of objects with optimal state change
- All viewport rendering is done offscreen for the moment

Signed-off-by: Clément Foucault <foucault.clem@gmail.com>
2017-01-03 10:44:24 +01:00
Dalai Felinto
e758b9d869 unittest: fixup 2017-01-02 14:22:46 +01:00
Dalai Felinto
2fa175eb8a Revert "Make sure new objects go to the correct (active) collection"
This reverts commit c51a32554e.
2016-12-23 19:25:29 +01:00
Dalai Felinto
2c55b4cbc8 Revert "Fix warning"
This reverts commit 280da49595.
2016-12-23 19:25:21 +01:00
Dalai Felinto
66bc0616fc unittest: object_add 2016-12-23 18:17:06 +01:00
Dalai Felinto
eae6e02759 unittest: active_collection_index 2016-12-23 17:42:35 +01:00
Dalai Felinto
7ba2a5feb5 bpy.context.render_layer 2016-12-23 17:04:10 +01:00
Dalai Felinto
280da49595 Fix warning 2016-12-23 15:59:33 +01:00
Dalai Felinto
ee6214dc80 Merge remote-tracking branch 'origin/blender2.8' into render-layers
Include manual changes to accomodate new do_versions_after_liblink
2016-12-23 15:56:13 +01:00
Dalai Felinto
c51a32554e Make sure new objects go to the correct (active) collection 2016-12-23 15:34:36 +01:00
Dalai Felinto
95e183b7f4 unittest touch ups 2016-12-22 12:14:46 +01:00
Dalai Felinto
a9cc4d0c5c render_layer.collections.link/unlink() 2016-12-22 12:14:32 +01:00
Dalai Felinto
4d998fb373 unittest: new layer, layer_collection_link/unlink 2016-12-21 19:14:44 +01:00
Dalai Felinto
5e79ebce13 Fixup for rna_SceneCollection_remove 2016-12-21 18:44:43 +01:00
Dalai Felinto
52c4adc4df Debug UI revamp 2016-12-21 18:44:42 +01:00
Dalai Felinto
c8978b160d unittest: syncing when unlinking a collection 2016-12-21 18:44:42 +01:00
Dalai Felinto
5c22ade95a Syncing: update layercollection tree when an object is unlinked
Note: filtering is not implemented/fully considered yet
2016-12-21 18:05:22 +01:00
Dalai Felinto
d550554d0c unittest: make tests more granular 2016-12-21 17:41:50 +01:00
Dalai Felinto
18ee712bf1 Layers: unittest to cover unlinking of objects 2016-12-21 17:41:50 +01:00
Dalai Felinto
a6cf5cfe9c Syncing: an object added to a scenecollection
Also changed the ObjectBase->refcount logic a bit, to simplify
further implementations of syncing.
2016-12-21 17:41:50 +01:00
Dalai Felinto
0abcddf470 Syncing: update layercollection tree when a new scenecollection is added 2016-12-21 12:27:50 +01:00
Dalai Felinto
1abef41657 Add nesting collections into unittest 2016-12-20 16:27:09 +01:00
Dalai Felinto
51984897d8 Temporary UI for layer/collections (for debug/testing) 2016-12-20 15:59:13 +01:00
Dalai Felinto
a508029fbc Make hide/hide_select icons dynamic 2016-12-20 15:37:23 +01:00
Dalai Felinto
619cbca39f From review: "doxygen"
I do not compile doxygen (assuming it is compiled, I do not even know). But it does not hurt to add the extra * everywhere
2016-12-20 11:21:10 +01:00
Dalai Felinto
72bd463127 Merge remote-tracking branch 'origin/blender2.8' into render-layers 2016-12-20 10:58:10 +01:00
Dalai Felinto
42bb135480 Fresh morning fixup of iterator logics
(and fix unfreed memory)
2016-12-20 10:42:26 +01:00
Dalai Felinto
9d2b6b56ac Fixup on BKE_scene_objects_Iterator_next 2016-12-19 18:13:47 +01:00
Dalai Felinto
d4cebc998b Use FOREACH_OBJECT_FLAG in more places 2016-12-19 17:57:45 +01:00
Dalai Felinto
60aa0b5b15 Reworked logic of iterators
otherwise I could not get different iterators based on a flag (SELECT), which is used everywhere in object_relations.c
The alternative would be to split every function in object_relations.c into _all, and _selected
2016-12-19 17:57:05 +01:00
Dalai Felinto
f59b6ff410 Using an iterator to go over objects, and use this for library_query
This is not the ideal iterator (it loops over the scene collection tree 3x).
One solution (I want to discuss with Bastien Montagne @mont29) is whether to store the *parent of a SceneCollection to help with that. That would speed things up, and cost less memory.

We do not even need to store it in the file, since it can be re-generated at read time
2016-12-19 14:11:58 +01:00
Dalai Felinto
57a5f2ef44 Iterator util function 2016-12-19 10:49:11 +01:00
Dalai Felinto
a3fd4274cf From review: curly brackets reinforcement
(even though the other related functions are not following this rule ... How I miss a code refactor dev!)
2016-12-16 16:04:47 +01:00
Dalai Felinto
0da8957bc5 From review: move nodetree syncing of layers to util function 2016-12-16 16:03:00 +01:00
Dalai Felinto
75b7a25014 From review: do_versions_after_linking skipped on undo 2016-12-16 15:53:23 +01:00
Dalai Felinto
29961ad597 From review: blo_do_versions_280_after_linking > blo_do_versions_after_linking_280 2016-12-16 15:51:17 +01:00
Dalai Felinto
3f9432b76a From review: use typedef for callbacks 2016-12-16 15:50:08 +01:00
Dalai Felinto
59fbc6db8d Merge remote-tracking branch 'origin/blender2.8' into render-layers 2016-12-16 14:46:17 +01:00
Dalai Felinto
c75e7516c3 Merge remote-tracking branch 'origin/blender2.8' into render-layers
plus manual rna fixup
2016-12-13 13:03:57 +01:00
Dalai Felinto
b7a42fe69f unittest: test cleanup 2016-12-12 13:08:58 +01:00
Dalai Felinto
3839afe03d Layers: change the API so that we can run a function on every object of the scene
use tag to make sure we call each object only once
2016-12-12 12:56:40 +01:00
Dalai Felinto
c96c3c8bbe Scene copy (full or link) working for layers
I'm using the flags in the objects instead of bases.
2016-12-12 12:12:42 +01:00
Dalai Felinto
ef6a35b0af scenelayer: unittest more granular, for debugging 2016-12-12 11:52:58 +01:00
Dalai Felinto
df8d4299a2 Unittest scene copy 2016-12-07 18:19:51 +01:00
Dalai Felinto
6fdd6f7d7c Unitest: doversion, write and read test for layers 2016-12-07 15:37:19 +01:00
Dalai Felinto
dddf38dc42 Fix new scenes should have a default renderlayer 2016-12-06 19:17:12 +01:00
Dalai Felinto
3c3c818d1b Fix all unfreed memory 2016-12-06 19:13:02 +01:00
Dalai Felinto
a2e81fa2e9 Final cleanup of read/write to have things in the right order (pure cosmetic) 2016-12-06 16:37:13 +01:00
Dalai Felinto
866b3268a5 Fix write of nested LayerCollections (and DNA cleanup) 2016-12-06 16:20:36 +01:00
Dalai Felinto
97109b654e Fix stupidest mistake (objects > filter_objects) 2016-12-06 15:57:04 +01:00
Dalai Felinto
6e6750a06a Fixing writing objects 2016-12-06 14:48:49 +01:00
Dalai Felinto
8146a4498a Fix writing nested scene collections 2016-12-06 14:16:42 +01:00
Dalai Felinto
3acb83c6f4 Use pointer for master collection
This allows this pointer to be used, otherwise the pointer is not written
2016-12-05 21:52:38 +01:00
Dalai Felinto
d0ef44218e Rename: collections > scene/layer_collections 2016-12-05 20:43:02 +01:00
Dalai Felinto
4ad8789a38 Read/Write, first take 2016-12-05 20:20:17 +01:00
Dalai Felinto
1db50e9a88 Fix objects not disappearing after unlinking collection 2016-12-05 14:58:26 +01:00
Dalai Felinto
87330b4729 RNA: layer.objects.selected
Instead of exposing the base I think this may be nicer for the API. We still need a way to change select for a layer though (expose the ObjectBase perhaps? :/)
2016-12-03 02:44:06 +01:00
Dalai Felinto
2b09fb3f30 layer.engine 2016-12-03 02:23:44 +01:00
Dalai Felinto
d085e62693 layer.objects.active 2016-12-03 02:23:44 +01:00
Dalai Felinto
89d20732a1 layer.active_collection
This one is straight from the "layers" branch. I nailed it quite nicely there, so it was simply a matter of bringing it over :)
2016-12-03 02:23:44 +01:00
Dalai Felinto
bc2321025b Shuffle code around to re-order functions 2016-12-03 02:23:43 +01:00
Dalai Felinto
52fdf5d06c layer.objects 2016-12-03 02:23:43 +01:00
Dalai Felinto
63780823a7 DNA documentation 2016-12-03 00:33:03 +01:00
Dalai Felinto
f304e2e273 BKE_collection_remove: (also first of five of the syncing functions) 2016-12-02 23:57:14 +01:00
Dalai Felinto
84d94fc06f RNA layer collections 2016-12-02 22:57:48 +01:00
Dalai Felinto
25f1e97408 Fixup for new layers 2016-12-02 22:16:14 +01:00
Dalai Felinto
d2b91a1c7c Rename CollectionBase > LayerCollection 2016-12-02 18:31:17 +01:00
Dalai Felinto
3c65f2f542 More RNA: objects, objects_filter (for SceneCollection), .new, remove 2016-12-02 17:50:53 +01:00
Dalai Felinto
b4799b23ec RNA (start), and some refactor (scene.main_collection)
Instead of storing a libstbase in scene, we simply store a collection, the api (RNA) is much more clear now
2016-12-02 16:29:10 +01:00
Dalai Felinto
91d7c345d4 Rename Collection > SceneCollection
We may want to re-use part of this struct (or concept) for groups and armatures. But filter is something specific to SceneCollections, so may as well keep it in a separate struct, and re-evaluate that once/if we get to it.
2016-12-02 12:43:08 +01:00
Dalai Felinto
bc66ca246c DNA fixups 2016-12-02 11:33:43 +01:00
Dalai Felinto
477fc97bd5 Renaming RenderLayer > SceneLayer
RenderLayer was the struct for RenderResult, better not to clash namespace here. For the Python API we still stick to scene.render_layers
2016-12-01 19:13:40 +01:00
Dalai Felinto
58acb05061 Add description for the functions 2016-11-30 13:04:09 +01:00
Dalai Felinto
cb11ab9b09 More versioning, and more DNA 2016-11-30 12:39:55 +01:00
Dalai Felinto
8d55fe9899 Start of versioning and more work 2016-11-29 18:24:00 +01:00
Dalai Felinto
dc3154b29f New DNA for layers 2016-11-29 15:23:26 +01:00
Dalai Felinto
34520c0ffc Barebones for dna files 2016-11-29 15:15:51 +01:00
188 changed files with 13572 additions and 2447 deletions

View File

@@ -242,6 +242,8 @@ endif()
option(WITH_PLAYER "Build Player" OFF)
option(WITH_OPENCOLORIO "Enable OpenColorIO color management" ${_init_OPENCOLORIO})
option(WITH_CLAY_ENGINE "Enable New Clay engine (Breaks Mac and Intel compatibility)" ON)
# Compositor
option(WITH_COMPOSITOR "Enable the tile based nodal compositor" ON)

View File

@@ -566,6 +566,7 @@ function(SETUP_BLENDER_SORTED_LIBS)
bf_editor_space_userpref
bf_editor_space_view3d
bf_editor_space_clip
bf_editor_space_collections
bf_editor_transform
bf_editor_util
@@ -597,6 +598,7 @@ function(SETUP_BLENDER_SORTED_LIBS)
bf_modifiers
bf_bmesh
bf_gpu
bf_draw
bf_blenloader
bf_blenkernel
bf_physics

View File

@@ -103,9 +103,9 @@ def add_object_align_init(context, operator):
return location * rotation
def object_data_add(context, obdata, operator=None, use_active_layer=True, name=None):
def object_data_add(context, obdata, operator=None, name=None):
"""
Add an object using the view context and preference to to initialize the
Add an object using the view context and preference to initialize the
location, rotation and layer.
:arg context: The context to use.
@@ -117,52 +117,24 @@ def object_data_add(context, obdata, operator=None, use_active_layer=True, name=
:arg name: Optional name
:type name: string
:return: the newly created object in the scene.
:rtype: :class:`bpy.types.ObjectBase`
:rtype: :class:`bpy.types.Object`
"""
scene = context.scene
layer = context.render_layer
scene_collection = context.scene_collection
# ugh, could be made nicer
for ob in scene.objects:
ob.select = False
bpy.ops.object.select_all(action='DESELECT')
if name is None:
name = "Object" if obdata is None else obdata.name
obj_new = bpy.data.objects.new(name, obdata)
base = scene.objects.link(obj_new)
base.select = True
v3d = None
if context.space_data and context.space_data.type == 'VIEW_3D':
v3d = context.space_data
if v3d and v3d.local_view:
base.layers_from_view(context.space_data)
if operator is not None and any(operator.layers):
base.layers = operator.layers
else:
if use_active_layer:
if v3d and v3d.local_view:
base.layers[scene.active_layer] = True
else:
if v3d and not v3d.lock_camera_and_layers:
base.layers = [True if i == v3d.active_layer
else False for i in range(len(v3d.layers))]
else:
base.layers = [True if i == scene.active_layer
else False for i in range(len(scene.layers))]
else:
if v3d:
base.layers_from_view(context.space_data)
if operator is not None:
operator.layers = base.layers
scene_collection.objects.link(obj_new)
obj_new.select_set(action='SELECT')
obj_new.matrix_world = add_object_align_init(context, operator)
obj_act = scene.objects.active
obj_act = layer.objects.active
# XXX
# caused because entering edit-mode does not add a empty undo slot!
@@ -174,8 +146,8 @@ def object_data_add(context, obdata, operator=None, use_active_layer=True, name=
_obdata = bpy.data.meshes.new(name)
obj_act = bpy.data.objects.new(_obdata.name, _obdata)
obj_act.matrix_world = obj_new.matrix_world
scene.objects.link(obj_act)
scene.objects.active = obj_act
scene_collection.objects.link(obj_act)
layer.objects.active = obj_act
bpy.ops.object.mode_set(mode='EDIT')
# need empty undo step
bpy.ops.ed.undo_push(message="Enter Editmode")
@@ -185,7 +157,7 @@ def object_data_add(context, obdata, operator=None, use_active_layer=True, name=
bpy.ops.mesh.select_all(action='DESELECT')
bpy.ops.object.mode_set(mode='OBJECT')
obj_act.select = True
obj_act.select_set(action='SELECT')
scene.update() # apply location
# scene.objects.active = obj_new
@@ -200,16 +172,14 @@ def object_data_add(context, obdata, operator=None, use_active_layer=True, name=
bpy.ops.object.join() # join into the active.
if obdata:
bpy.data.meshes.remove(obdata)
# base is freed, set to active object
base = scene.object_bases.active
bpy.ops.object.mode_set(mode='EDIT')
else:
scene.objects.active = obj_new
layer.objects.active = obj_new
if context.user_preferences.edit.use_enter_edit_mode:
bpy.ops.object.mode_set(mode='EDIT')
return base
return obj_new
class AddObjectHelper:
@@ -230,12 +200,6 @@ class AddObjectHelper:
name="Rotation",
subtype='EULER',
)
layers = BoolVectorProperty(
name="Layers",
size=20,
subtype='LAYER',
options={'HIDDEN', 'SKIP_SAVE'},
)
@classmethod
def poll(self, context):

View File

@@ -330,7 +330,6 @@ kmi = km.keymap_items.new('object.hide_view_set', 'H', 'PRESS', shift=True)
kmi.properties.unselected = True
kmi = km.keymap_items.new('object.hide_render_clear', 'H', 'PRESS', ctrl=True, alt=True)
kmi = km.keymap_items.new('object.hide_render_set', 'H', 'PRESS', ctrl=True)
kmi = km.keymap_items.new('object.move_to_layer', 'M', 'PRESS')
kmi = km.keymap_items.new('object.delete', 'X', 'PRESS')
kmi.properties.use_global = False
kmi = km.keymap_items.new('object.delete', 'X', 'PRESS', shift=True)

View File

@@ -384,7 +384,6 @@ kmi = km.keymap_items.new('object.hide_view_clear', 'H', 'PRESS', shift=True, ct
kmi = km.keymap_items.new('object.hide_view_set', 'H', 'PRESS', ctrl=True)
kmi = km.keymap_items.new('object.hide_view_set', 'H', 'PRESS', alt=True)
kmi.properties.unselected = True
kmi = km.keymap_items.new('object.move_to_layer', 'M', 'PRESS')
kmi = km.keymap_items.new('object.delete', 'BACK_SPACE', 'PRESS')
kmi = km.keymap_items.new('object.delete', 'DEL', 'PRESS')
kmi = km.keymap_items.new('wm.call_menu', 'A', 'PRESS', shift=True)

View File

@@ -232,7 +232,7 @@ class CLIP_OT_track_to_empty(Operator):
ob = None
ob = bpy.data.objects.new(name=track.name, object_data=None)
ob.select = True
ob.select_set(action='SELECT')
context.scene.objects.link(ob)
context.scene.objects.active = ob
@@ -506,7 +506,7 @@ object's movement caused by this constraint"""
# XXX, should probably use context.selected_editable_objects
# since selected objects can be from a lib or in hidden layer!
for ob in scene.objects:
if ob.select:
if ob.select_set(action='SELECT'):
self._bake_object(scene, ob)
return {'FINISHED'}

View File

@@ -74,7 +74,7 @@ class SCENE_OT_freestyle_fill_range_by_selection(bpy.types.Operator):
self.report({'ERROR'}, "Unexpected modifier type: " + m.type)
return {'CANCELLED'}
# Find selected mesh objects
selection = [ob for ob in scene.objects if ob.select and ob.type == 'MESH' and ob.name != source.name]
selection = [ob for ob in scene.objects if ob.select_get() and ob.type == 'MESH' and ob.name != source.name]
if selection:
# Compute the min/max distance between selected mesh objects and the source
min_dist = sys.float_info.max

View File

@@ -81,16 +81,18 @@ class SelectPattern(Operator):
# Can be pose bones or objects
for item in items:
if pattern_match(item.name, self.pattern):
item.select = True
# hrmf, perhaps there should be a utility function for this.
if is_ebone:
item.select = True
item.select_head = True
item.select_tail = True
if item.use_connect:
item_parent = item.parent
if item_parent is not None:
item_parent.select_tail = True
else:
item.select_set(action='SELECT')
return {'FINISHED'}
@@ -136,7 +138,7 @@ class SelectCamera(Operator):
bpy.ops.object.select_all(action='DESELECT')
scene.objects.active = camera
camera.hide = False
camera.select = True
camera.select_set(action='SELECT')
return {'FINISHED'}
return {'CANCELLED'}
@@ -202,7 +204,7 @@ class SelectHierarchy(Operator):
bpy.ops.object.select_all(action='DESELECT')
for obj in select_new:
obj.select = True
obj.select_set(action='SELECT')
scene.objects.active = act_new
return {'FINISHED'}
@@ -644,8 +646,8 @@ class MakeDupliFace(Operator):
ob_new.use_dupli_faces_scale = True
ob_new.dupli_faces_scale = 1.0 / SCALE_FAC
ob_inst.select = True
ob_new.select = True
ob_inst.select_set(action='SELECT')
ob_new.select_set(action='SELECT')
def execute(self, context):
self._main(context)
@@ -664,7 +666,7 @@ class IsolateTypeRender(Operator):
for obj in context.visible_objects:
if obj.select:
if obj.select_get():
obj.hide_render = False
else:
if obj.type == act_type:
@@ -1029,8 +1031,8 @@ class LodGenerate(Operator):
for level in ob.lod_levels[1:]:
level.object.hide = level.object.hide_render = True
lod.select = False
ob.select = True
lod.select_set(action='DESELECT')
ob.select_set(action='SELECT')
scene.objects.active = ob
return {'FINISHED'}

View File

@@ -63,7 +63,7 @@ class CopyRigidbodySettings(Operator):
# deselect all but mesh objects
for o in context.selected_objects:
if o.type != 'MESH':
o.select = False
o.select_set(action='DESELECT')
elif o.rigid_body is None:
# Add rigidbody to object!
scene.objects.active = o
@@ -125,7 +125,7 @@ class BakeToKeyframes(Operator):
# filter objects selection
for obj in context.selected_objects:
if not obj.rigid_body or obj.rigid_body.type != 'ACTIVE':
obj.select = False
obj.select_set(action='DESELECT')
objects = context.selected_objects
@@ -258,7 +258,7 @@ class ConnectRigidBodies(Operator):
ob.location = loc
context.scene.objects.link(ob)
context.scene.objects.active = ob
ob.select = True
ob.select_set(action='SELECT')
bpy.ops.rigidbody.constraint_add()
con_obj = context.active_object
@@ -303,7 +303,7 @@ class ConnectRigidBodies(Operator):
# restore selection
bpy.ops.object.select_all(action='DESELECT')
for obj in objects:
obj.select = True
obj.select_set(action='SELECT')
scene.objects.active = obj_act
return {'FINISHED'}
else:

View File

@@ -29,6 +29,7 @@ if "bpy" in locals():
_modules = [
"properties_animviz",
"properties_collection",
"properties_constraint",
"properties_data_armature",
"properties_data_bone",
@@ -69,6 +70,7 @@ _modules = [
"space_graph",
"space_image",
"space_info",
"space_collections",
"space_logic",
"space_nla",
"space_node",

View File

@@ -0,0 +1,128 @@
# ##### BEGIN GPL LICENSE BLOCK #####
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
import bpy
from bpy.types import Panel, UIList
class CollectionButtonsPanel:
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "collection"
class COLLECTION_PT_context_collection(CollectionButtonsPanel, Panel):
bl_label = ""
bl_options = {'HIDE_HEADER'}
def draw(self, context):
layout = self.layout
space = context.space_data
collection = context.layer_collection
name = collection.name
if name == 'Master Collection':
layout.label(text=name, icon='COLLAPSEMENU')
else:
layout.prop(collection, "name", text="", icon='COLLAPSEMENU')
class COLLECTION_UL_objects(UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
# assert(isinstance(item, bpy.types.Object)
ob = item
if self.layout_type in {'DEFAULT', 'COMPACT'}:
layout.label(ob.name, icon_value=icon)
elif self.layout_type == 'GRID':
layout.alignment = 'CENTER'
layout.label("", icon_value=icon)
class COLLECTION_PT_objects(CollectionButtonsPanel, Panel):
bl_label = "Objects"
def draw(self, context):
layout = self.layout
scene = context.scene
collection = context.scene_collection
row = layout.row()
row.template_list("COLLECTION_UL_objects", "name", collection, "objects", collection.objects, "active_index", rows=2)
col = row.column(align=True)
col.operator("collections.objects_add", icon='ZOOMIN', text="")
col.operator("collections.objects_remove", icon='ZOOMOUT', text="")
row = layout.row(align=True)
row.operator("collections.objects_select", text="Select")
row.operator("collections.objects_deselect", text="Deselect")
def template_engine_settings(col, settings, name, use_icon_view=False):
icons = {
False: 'ZOOMIN',
True: 'X',
}
use_name = "{0}_use".format(name)
use = getattr(settings, use_name)
row = col.row()
col = row.column()
col.active = use
if use_icon_view:
col.template_icon_view(settings, name)
else:
col.prop(settings, name)
row.prop(settings, "{}_use".format(name), text="", icon=icons[use], emboss=False)
class COLLECTION_PT_clay_settings(CollectionButtonsPanel, Panel):
bl_label = "Render Settings"
COMPAT_ENGINES = {'BLENDER_CLAY'}
@classmethod
def poll(cls, context):
scene = context.scene
return scene and (scene.render.engine in cls.COMPAT_ENGINES)
def draw(self, context):
layout = self.layout
collection = context.layer_collection
settings = collection.get_engine_settings()
col = layout.column()
template_engine_settings(col, settings, "type")
template_engine_settings(col, settings, "matcap_icon", use_icon_view=True)
template_engine_settings(col, settings, "matcap_rotation")
template_engine_settings(col, settings, "matcap_hue")
template_engine_settings(col, settings, "matcap_saturation")
template_engine_settings(col, settings, "matcap_value")
template_engine_settings(col, settings, "ssao_factor_cavity")
template_engine_settings(col, settings, "ssao_factor_edge")
template_engine_settings(col, settings, "ssao_distance")
template_engine_settings(col, settings, "ssao_attenuation")
if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)

View File

@@ -106,7 +106,7 @@ class MaterialButtonsPanel:
class MATERIAL_PT_context_material(MaterialButtonsPanel, Panel):
bl_label = ""
bl_options = {'HIDE_HEADER'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME', 'BLENDER_CLAY'}
@classmethod
def poll(cls, context):
@@ -1052,5 +1052,25 @@ class MATERIAL_PT_custom_props(MaterialButtonsPanel, PropertyPanel, Panel):
_context_path = "material"
_property_type = bpy.types.Material
class MATERIAL_PT_clay_settings(MaterialButtonsPanel, Panel):
bl_label = "Matcap"
COMPAT_ENGINES = {'BLENDER_CLAY'}
def draw(self, context):
layout = self.layout;
settings = context.material.clay_settings
# layout.template_icon_view(settings, "matcap_icon")
# layout.prop(settings, "type")
# layout.prop(settings, "matcap_rotation")
# layout.prop(settings, "matcap_hue")
# layout.prop(settings, "matcap_saturation")
# layout.prop(settings, "matcap_value")
# layout.prop(settings, "ssao_factor_cavity")
# layout.prop(settings, "ssao_factor_edge")
# layout.prop(settings, "ssao_distance")
# layout.prop(settings, "ssao_attenuation")
if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)

View File

@@ -584,5 +584,24 @@ class RENDER_PT_bake(RenderButtonsPanel, Panel):
sub.prop(rd, "bake_user_scale", text="User Scale")
class RENDER_PT_clay(RenderButtonsPanel, Panel):
bl_label = "Default Clay"
COMPAT_ENGINES = {'BLENDER_CLAY'}
def draw(self, context):
layout = self.layout;
settings = context.scene.active_engine_settings
layout.template_icon_view(settings, "matcap_icon")
layout.prop(settings, "matcap_rotation")
layout.prop(settings, "matcap_hue")
layout.prop(settings, "matcap_saturation")
layout.prop(settings, "matcap_value")
layout.prop(settings, "ssao_factor_cavity")
layout.prop(settings, "ssao_factor_edge")
layout.prop(settings, "ssao_distance")
layout.prop(settings, "ssao_attenuation")
layout.prop(settings, "ssao_samples")
if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)

View File

@@ -35,7 +35,7 @@ class RenderLayerButtonsPanel:
class RENDERLAYER_UL_renderlayers(UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
# assert(isinstance(item, bpy.types.SceneRenderLayer)
# assert(isinstance(item, bpy.types.SceneLayer)
layer = item
if self.layout_type in {'DEFAULT', 'COMPACT'}:
layout.prop(layer, "name", text="", icon_value=icon, emboss=False)
@@ -48,7 +48,7 @@ class RENDERLAYER_UL_renderlayers(UIList):
class RENDERLAYER_PT_layers(RenderLayerButtonsPanel, Panel):
bl_label = "Layer List"
bl_options = {'HIDE_HEADER'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME', 'BLENDER_CLAY'}
def draw(self, context):
layout = self.layout
@@ -62,7 +62,7 @@ class RENDERLAYER_PT_layers(RenderLayerButtonsPanel, Panel):
row = layout.row()
col = row.column()
col.template_list("RENDERLAYER_UL_renderlayers", "", rd, "layers", rd.layers, "active_index", rows=2)
col.template_list("RENDERLAYER_UL_renderlayers", "", scene, "render_layers", scene.render_layers, "active_index", rows=2)
col = row.column()
sub = col.column(align=True)
@@ -71,103 +71,6 @@ class RENDERLAYER_PT_layers(RenderLayerButtonsPanel, Panel):
col.prop(rd, "use_single_layer", icon_only=True)
class RENDERLAYER_PT_layer_options(RenderLayerButtonsPanel, Panel):
bl_label = "Layer"
COMPAT_ENGINES = {'BLENDER_RENDER'}
def draw(self, context):
layout = self.layout
scene = context.scene
rd = scene.render
rl = rd.layers.active
split = layout.split()
col = split.column()
col.prop(scene, "layers", text="Scene")
col.label(text="")
col.prop(rl, "light_override", text="Lights")
col.prop(rl, "material_override", text="Material")
col = split.column()
col.prop(rl, "layers", text="Layer")
col.prop(rl, "layers_zmask", text="Mask Layer")
layout.separator()
layout.label(text="Include:")
split = layout.split()
col = split.column()
col.prop(rl, "use_zmask")
row = col.row()
row.prop(rl, "invert_zmask", text="Negate")
row.active = rl.use_zmask
col.prop(rl, "use_all_z")
col = split.column()
col.prop(rl, "use_solid")
col.prop(rl, "use_halo")
col.prop(rl, "use_ztransp")
col = split.column()
col.prop(rl, "use_sky")
col.prop(rl, "use_edge_enhance")
col.prop(rl, "use_strand")
if bpy.app.build_options.freestyle:
row = col.row()
row.prop(rl, "use_freestyle")
row.active = rd.use_freestyle
class RENDERLAYER_PT_layer_passes(RenderLayerButtonsPanel, Panel):
bl_label = "Passes"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER'}
@staticmethod
def draw_pass_type_buttons(box, rl, pass_type):
# property names
use_pass_type = "use_pass_" + pass_type
exclude_pass_type = "exclude_" + pass_type
# draw pass type buttons
row = box.row()
row.prop(rl, use_pass_type)
row.prop(rl, exclude_pass_type, text="")
def draw(self, context):
layout = self.layout
scene = context.scene
rd = scene.render
rl = rd.layers.active
split = layout.split()
col = split.column()
col.prop(rl, "use_pass_combined")
col.prop(rl, "use_pass_z")
col.prop(rl, "use_pass_vector")
col.prop(rl, "use_pass_normal")
col.prop(rl, "use_pass_uv")
col.prop(rl, "use_pass_mist")
col.prop(rl, "use_pass_object_index")
col.prop(rl, "use_pass_material_index")
col.prop(rl, "use_pass_color")
col = split.column()
col.prop(rl, "use_pass_diffuse")
self.draw_pass_type_buttons(col, rl, "specular")
self.draw_pass_type_buttons(col, rl, "shadow")
self.draw_pass_type_buttons(col, rl, "emit")
self.draw_pass_type_buttons(col, rl, "ambient_occlusion")
self.draw_pass_type_buttons(col, rl, "environment")
self.draw_pass_type_buttons(col, rl, "indirect")
self.draw_pass_type_buttons(col, rl, "reflection")
self.draw_pass_type_buttons(col, rl, "refraction")
class RENDERLAYER_UL_renderviews(UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
# assert(isinstance(item, bpy.types.SceneRenderView)

View File

@@ -0,0 +1,41 @@
# ##### BEGIN GPL LICENSE BLOCK #####
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
import bpy
from bpy.types import Header, Menu
class COLLECTIONS_HT_header(Header):
bl_space_type = 'COLLECTION_MANAGER'
def draw(self, context):
layout = self.layout
layout.template_header()
row = layout.row(align=True)
row.operator("collections.collection_new", text="", icon='NEW')
row.operator("collections.override_new", text="", icon='LINK_AREA')
row.operator("collections.collection_link", text="", icon='LINKED')
row.operator("collections.collection_unlink", text="", icon='UNLINKED')
row.operator("collections.delete", text="", icon='X')
if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)

View File

@@ -634,7 +634,6 @@ class VIEW3D_MT_select_object(Menu):
layout.operator("object.select_all", text="Inverse").action = 'INVERT'
layout.operator("object.select_random", text="Random")
layout.operator("object.select_mirror", text="Mirror")
layout.operator("object.select_by_layer", text="Select All by Layer")
layout.operator_menu_enum("object.select_by_type", "type", text="Select All by Type...")
layout.operator("object.select_camera", text="Select Camera")
@@ -1311,15 +1310,6 @@ class VIEW3D_MT_object(Menu):
layout.separator()
if is_local_view:
layout.operator_context = 'EXEC_REGION_WIN'
layout.operator("object.move_to_layer", text="Move out of Local View")
layout.operator_context = 'INVOKE_REGION_WIN'
else:
layout.operator("object.move_to_layer", text="Move to Layer...")
layout.menu("VIEW3D_MT_object_showhide")
layout.operator_menu_enum("object.convert", "target")
@@ -1597,17 +1587,6 @@ class VIEW3D_MT_object_quick_effects(Menu):
layout.operator("object.quick_fluid")
class VIEW3D_MT_object_showhide(Menu):
bl_label = "Show/Hide"
def draw(self, context):
layout = self.layout
layout.operator("object.hide_view_clear", text="Show Hidden")
layout.operator("object.hide_view_set", text="Hide Selected").unselected = False
layout.operator("object.hide_view_set", text="Hide Unselected").unselected = True
class VIEW3D_MT_make_single_user(Menu):
bl_label = "Make Single User"
@@ -3167,6 +3146,74 @@ class VIEW3D_PT_viewport_debug(Panel):
col.row(align=True).prop(view, "debug_background", expand=True)
class VIEW3D_PT_collections_editor(Panel):
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
bl_label = "Collections"
bl_options = {'DEFAULT_CLOSED'}
@classmethod
def poll(cls, context):
return context.space_data
def draw(self, context):
layout = self.layout
layer = context.render_layer
active_collection = context.layer_collection
col = layout.column()
box = col.box()
index = -1
for collection in layer.collections:
index = self._draw_layer_collection(box, index, active_collection, collection, True, True)
row = layout.row(align=True)
row.operator("collections.collection_new", text="", icon='NEW')
row.operator("collections.override_new", text="", icon='LINK_AREA')
row.operator("collections.collection_link", text="", icon='LINKED')
row.operator("collections.collection_unlink", text="", icon='UNLINKED')
row.operator("collections.delete", text="", icon='X')
def _draw_layer_collection(self, box, index, active_collection, collection, is_active, is_draw, depth=0):
index += 1
nested_collections = collection.collections
if is_draw:
row = box.row()
row.active = is_active
is_collection_selected = (collection == active_collection)
if is_collection_selected:
sub_box = row.box()
row = sub_box.row()
row.label(text="{0}{1}{2}".format(
" " * depth,
u'\u21b3 ' if depth else "",
collection.name))
row.prop(collection, "hide", text="", emboss=False)
row.prop(collection, "hide_select", text="", emboss=False)
row.operator("collections.select", text="", icon='BLANK1' if is_collection_selected else 'HAND', emboss=False).collection_index=index
if nested_collections:
row.prop(collection, "is_unfolded", text="", emboss=False)
else:
row.label(icon='BLANK1')
if not collection.is_unfolded:
is_draw = False
is_active &= not collection.hide
for nested_collection in nested_collections:
index = self._draw_layer_collection(box, index, active_collection, nested_collection, is_active, is_draw, depth + 1)
return index
class VIEW3D_PT_grease_pencil(GreasePencilDataPanel, Panel):
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'

View File

@@ -18,7 +18,7 @@ bpy.ops.object.select_all(action='DESELECT')
for obj in selection:
obj.select = True
obj.select_set(action='SELECT')
# some exporters only use the active object
scene.objects.active = obj
@@ -31,7 +31,7 @@ for obj in selection:
## Can be used for multiple formats
# bpy.ops.export_scene.x3d(filepath=fn + ".x3d", use_selection=True)
obj.select = False
obj.select_set(action='DESELECT')
print("written:", fn)
@@ -39,4 +39,4 @@ for obj in selection:
scene.objects.active = obj_active
for obj in selection:
obj.select = True
obj.select_set(action='SELECT')

View File

@@ -67,7 +67,7 @@ def main(context, event):
# now we have the object under the mouse cursor,
# we could do lots of stuff but for the example just select.
if best_obj is not None:
best_obj.select = True
best_obj.select_set(action='SELECT')
context.scene.objects.active = best_obj

View File

@@ -100,6 +100,7 @@ add_subdirectory(windowmanager)
add_subdirectory(blenkernel)
add_subdirectory(blenlib)
add_subdirectory(bmesh)
add_subdirectory(draw)
add_subdirectory(render)
add_subdirectory(blenfont)
add_subdirectory(blentranslation)

View File

@@ -0,0 +1,91 @@
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Dalai Felinto
*
* ***** END GPL LICENSE BLOCK *****
*/
#ifndef __BKE_COLLECTION_H__
#define __BKE_COLLECTION_H__
/** \file blender/blenkernel/BKE_collection.h
* \ingroup bke
*/
#include "BLI_ghash.h"
#include "BLI_iterator.h"
#include "DNA_listBase.h"
#ifdef __cplusplus
extern "C" {
#endif
struct Iterator;
struct SceneCollection;
struct Object;
struct ObjectBase;
struct Main;
struct Scene;
struct SceneCollection *BKE_collection_add(struct Scene *scene, struct SceneCollection *sc_parent, const char *name);
bool BKE_collection_remove(struct Scene *scene, struct SceneCollection *sc);
struct SceneCollection *BKE_collection_master(struct Scene *scene);
void BKE_collection_master_free(struct Scene *scene);
void BKE_collection_object_add(struct Scene *scene, struct SceneCollection *sc, struct Object *object);
void BKE_collection_object_add_from(struct Scene *scene, struct Object *ob_src, struct Object *ob_dst);
void BKE_collection_object_remove(struct Main *bmain, struct Scene *scene, struct SceneCollection *sc, struct Object *object, const bool free_us);
void BKE_collections_object_remove(struct Main *bmain, struct Scene *scene, struct Object *object, const bool free_us);
typedef void (*BKE_scene_objects_Cb)(struct Object *ob, void *data);
typedef void (*BKE_scene_collections_Cb)(struct SceneCollection *ob, void *data);
void BKE_scene_collections_callback(struct Scene *scene, BKE_scene_collections_Cb callback, void *data);
void BKE_scene_objects_callback(struct Scene *scene, BKE_scene_objects_Cb callback, void *data);
/* iterators */
void BKE_scene_collections_Iterator_begin(struct Iterator *iter, void *data_in);
void BKE_scene_collections_Iterator_next(struct Iterator *iter);
void BKE_scene_collections_Iterator_end(struct Iterator *iter);
void BKE_scene_objects_Iterator_begin(struct Iterator *iter, void *data_in);
void BKE_scene_objects_Iterator_next(struct Iterator *iter);
void BKE_scene_objects_Iterator_end(struct Iterator *iter);
#define FOREACH_SCENE_COLLECTION(scene, _sc) \
ITER_BEGIN(BKE_scene_collections_Iterator_begin, \
BKE_scene_collections_Iterator_next, \
BKE_scene_collections_Iterator_end, \
scene, _sc)
#define FOREACH_SCENE_COLLECTION_END \
ITER_END
#define FOREACH_SCENE_OBJECT(scene, _ob) \
ITER_BEGIN(BKE_scene_objects_Iterator_begin, \
BKE_scene_objects_Iterator_next, \
BKE_scene_objects_Iterator_end, \
scene, _ob)
#define FOREACH_SCENE_OBJECT_END \
ITER_END
#ifdef __cplusplus
}
#endif
#endif /* __BKE_COLLECTION_H__ */

View File

@@ -40,12 +40,16 @@ extern "C" {
struct ARegion;
struct bScreen;
struct CacheFile;
struct LayerCollection;
struct ListBase;
struct Main;
struct Object;
struct ObjectBase;
struct PointerRNA;
struct ReportList;
struct Scene;
struct SceneCollection;
struct SceneLayer;
struct ScrArea;
struct SpaceLink;
struct View3D;
@@ -166,6 +170,7 @@ struct SpaceAction *CTX_wm_space_action(const bContext *C);
struct SpaceInfo *CTX_wm_space_info(const bContext *C);
struct SpaceUserPref *CTX_wm_space_userpref(const bContext *C);
struct SpaceClip *CTX_wm_space_clip(const bContext *C);
struct SpaceCollections *CTX_wm_space_collections(const bContext *C);
void CTX_wm_manager_set(bContext *C, struct wmWindowManager *wm);
void CTX_wm_window_set(bContext *C, struct wmWindow *win);
@@ -239,6 +244,9 @@ int ctx_data_list_count(const bContext *C, int (*func)(const bContext *, ListBas
struct Main *CTX_data_main(const bContext *C);
struct Scene *CTX_data_scene(const bContext *C);
struct LayerCollection *CTX_data_layer_collection(const bContext *C);
struct SceneCollection *CTX_data_scene_collection(const bContext *C);
struct SceneLayer *CTX_data_scene_layer(const bContext *C);
struct ToolSettings *CTX_data_tool_settings(const bContext *C);
const char *CTX_data_mode_string(const bContext *C);
@@ -263,7 +271,7 @@ int CTX_data_selectable_objects(const bContext *C, ListBase *list);
int CTX_data_selectable_bases(const bContext *C, ListBase *list);
struct Object *CTX_data_active_object(const bContext *C);
struct Base *CTX_data_active_base(const bContext *C);
struct ObjectBase *CTX_data_active_base(const bContext *C);
struct Object *CTX_data_edit_object(const bContext *C);
struct Image *CTX_data_edit_image(const bContext *C);

View File

@@ -34,6 +34,7 @@
*/
struct Base;
struct ObjectBase;
struct EvaluationContext;
struct Group;
struct Main;
@@ -44,8 +45,8 @@ void BKE_group_free(struct Group *group);
struct Group *BKE_group_add(struct Main *bmain, const char *name);
struct Group *BKE_group_copy(struct Main *bmain, struct Group *group);
void BKE_group_make_local(struct Main *bmain, struct Group *group, const bool lib_local);
bool BKE_group_object_add(struct Group *group, struct Object *ob, struct Scene *scene, struct Base *base);
bool BKE_group_object_unlink(struct Group *group, struct Object *ob, struct Scene *scene, struct Base *base);
bool BKE_group_object_add(struct Group *group, struct Object *ob);
bool BKE_group_object_unlink(struct Group *group, struct Object *ob);
struct Group *BKE_group_object_find(struct Group *group, struct Object *ob);
bool BKE_group_object_exists(struct Group *group, struct Object *ob);
bool BKE_group_object_cyclic_check(struct Main *bmain, struct Object *object, struct Group *group);

View File

@@ -0,0 +1,217 @@
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Dalai Felinto
*
* ***** END GPL LICENSE BLOCK *****
*/
#ifndef __BKE_LAYER_H__
#define __BKE_LAYER_H__
/** \file blender/blenkernel/BKE_layer.h
* \ingroup bke
*/
#include "BKE_collection.h"
#ifdef __cplusplus
extern "C" {
#endif
#define TODO_LAYER_SYNC /* syncing of SceneCollection and LayerCollection trees*/
#define TODO_LAYER_SYNC_FILTER /* syncing of filter_objects across all trees */
#define TODO_LAYER_OVERRIDE /* CollectionOverride */
#define TODO_LAYER_CONTEXT /* get/set current (context) SceneLayer */
#define TODO_LAYER_BASE /* Base to ObjectBase related TODO */
#define TODO_LAYER_OPERATORS /* collection mamanger and property panel operators */
#define TODO_LAYER_DEPSGRAPH /* placeholder for real Depsgraph fix */
#define TODO_LAYER /* generic todo */
struct CollectionEngineSettings;
struct LayerCollection;
struct ID;
struct ListBase;
struct Main;
struct Object;
struct ObjectBase;
struct RenderEngine;
struct Scene;
struct SceneCollection;
struct SceneLayer;
struct SceneLayer *BKE_scene_layer_add(struct Scene *scene, const char *name);
bool BKE_scene_layer_remove(struct Main *bmain, struct Scene *scene, struct SceneLayer *sl);
void BKE_scene_layer_free(struct SceneLayer *sl);
void BKE_scene_layer_engine_set(struct SceneLayer *sl, const char *engine);
void BKE_scene_layer_selected_objects_tag(struct SceneLayer *sl, const int tag);
struct SceneLayer *BKE_scene_layer_find_from_collection(struct Scene *scene, struct LayerCollection *lc);
struct ObjectBase *BKE_scene_layer_base_find(struct SceneLayer *sl, struct Object *ob);
void BKE_scene_layer_base_deselect_all(struct SceneLayer *sl);
void BKE_scene_layer_base_select(struct SceneLayer *sl, struct ObjectBase *selbase);
void BKE_scene_layer_base_flag_recalculate(struct SceneLayer *sl);
void BKE_scene_layer_engine_settings_recalculate(struct SceneLayer *sl);
void BKE_scene_layer_engine_settings_update(struct SceneLayer *sl);
void BKE_layer_collection_free(struct SceneLayer *sl, struct LayerCollection *lc);
struct LayerCollection *BKE_layer_collection_active(struct SceneLayer *sl);
int BKE_layer_collection_count(struct SceneLayer *sl);
int BKE_layer_collection_findindex(struct SceneLayer *sl, struct LayerCollection *lc);
struct LayerCollection *BKE_collection_link(struct SceneLayer *sl, struct SceneCollection *sc);
void BKE_collection_unlink(struct SceneLayer *sl, struct LayerCollection *lc);
bool BKE_scene_layer_has_collection(struct SceneLayer *sl, struct SceneCollection *sc);
bool BKE_scene_has_object(struct Scene *scene, struct Object *ob);
/* syncing */
void BKE_layer_sync_new_scene_collection(struct Scene *scene, const struct SceneCollection *sc_parent, struct SceneCollection *sc);
void BKE_layer_sync_object_link(struct Scene *scene, struct SceneCollection *sc, struct Object *ob);
void BKE_layer_sync_object_unlink(struct Scene *scene, struct SceneCollection *sc, struct Object *ob);
/* override */
void BKE_collection_override_datablock_add(struct LayerCollection *lc, const char *data_path, struct ID *id);
/* engine settings */
typedef void (*CollectionEngineSettingsCB)(struct RenderEngine *engine, struct CollectionEngineSettings *ces);
struct CollectionEngineSettings *BKE_layer_collection_engine_get(struct LayerCollection *lc, const char *engine_name);
void BKE_layer_collection_engine_settings_callback_register(struct Main *bmain, const char *engine_name, CollectionEngineSettingsCB func);
void BKE_layer_collection_engine_settings_callback_free(void);
void BKE_layer_collection_engine_settings_create(struct ListBase *lb, const char *engine_name);
void BKE_layer_collection_engine_settings_free(struct ListBase *lb);
void BKE_collection_engine_property_add_float(struct CollectionEngineSettings *ces, const char *name, float value);
void BKE_collection_engine_property_add_int(struct CollectionEngineSettings *ces, const char *name, int value);
struct CollectionEngineProperty *BKE_collection_engine_property_get(struct CollectionEngineSettings *ces, const char *name);
int BKE_collection_engine_property_value_get_int(struct CollectionEngineSettings *ces, const char *name);
float BKE_collection_engine_property_value_get_float(struct CollectionEngineSettings *ces, const char *name);
void BKE_collection_engine_property_value_set_int(struct CollectionEngineSettings *ces, const char *name, int value);
void BKE_collection_engine_property_value_set_float(struct CollectionEngineSettings *ces, const char *name, float value);
bool BKE_collection_engine_property_use_get(struct CollectionEngineSettings *ces, const char *name);
void BKE_collection_engine_property_use_set(struct CollectionEngineSettings *ces, const char *name, bool value);
/* iterators */
void BKE_selected_objects_Iterator_begin(Iterator *iter, void *data_in);
void BKE_selected_objects_Iterator_next(Iterator *iter);
void BKE_selected_objects_Iterator_end(Iterator *iter);
void BKE_visible_objects_Iterator_begin(Iterator *iter, void *data_in);
void BKE_visible_objects_Iterator_next(Iterator *iter);
void BKE_visible_objects_Iterator_end(Iterator *iter);
void BKE_visible_bases_Iterator_begin(Iterator *iter, void *data_in);
void BKE_visible_bases_Iterator_next(Iterator *iter);
void BKE_visible_bases_Iterator_end(Iterator *iter);
#define FOREACH_SELECTED_OBJECT(sl, _ob) \
ITER_BEGIN(BKE_selected_objects_Iterator_begin, \
BKE_selected_objects_Iterator_next, \
BKE_selected_objects_Iterator_end, \
sl, _ob)
#define FOREACH_SELECTED_OBJECT_END \
ITER_END
#define FOREACH_VISIBLE_OBJECT(sl, _ob) \
ITER_BEGIN(BKE_visible_objects_Iterator_begin, \
BKE_visible_objects_Iterator_next, \
BKE_visible_objects_Iterator_end, \
sl, _ob)
#define FOREACH_VISIBLE_OBJECT_END \
ITER_END
#define FOREACH_VISIBLE_BASE(sl, _object_base) \
ITER_BEGIN(BKE_visible_bases_Iterator_begin, \
BKE_visible_bases_Iterator_next, \
BKE_visible_bases_Iterator_end, \
sl, _object_base)
#define FOREACH_VISIBLE_BASE_END \
ITER_END
#define FOREACH_OBJECT(sl, _ob) \
{ \
ObjectBase *base; \
for (base = sl->object_bases.first; base; base = base->next) { \
_ob = base->object;
#define FOREACH_OBJECT_END \
} \
}
#define FOREACH_OBJECT_FLAG(scene, sl, flag, _ob) \
{ \
IteratorBeginCb func_begin; \
IteratorCb func_next, func_end; \
void *data_in; \
\
if (flag == SELECT) { \
func_begin = &BKE_selected_objects_Iterator_begin; \
func_next = &BKE_selected_objects_Iterator_next; \
func_end = &BKE_selected_objects_Iterator_end; \
data_in = sl; \
} \
else { \
func_begin = BKE_scene_objects_Iterator_begin; \
func_next = BKE_scene_objects_Iterator_next; \
func_end = BKE_scene_objects_Iterator_end; \
data_in = scene; \
} \
ITER_BEGIN(func_begin, func_next, func_end, data_in, _ob)
#define FOREACH_OBJECT_FLAG_END \
ITER_END \
}
/* temporary hacky solution waiting for final depsgraph evaluation */
#define DEG_OBJECT_ITER(sl_, ob_) \
{ \
/* temporary solution, waiting for depsgraph update */ \
BKE_scene_layer_engine_settings_update(sl); \
\
/* flush all the data to objects*/ \
ObjectBase *base_; \
for (base_ = sl->object_bases.first; base_; base_ = base_->next) { \
ob_ = base_->object; \
ob_->base_flag = base_->flag;
#define DEG_OBJECT_ITER_END \
} \
}
#ifdef __cplusplus
}
#endif
#endif /* __BKE_LAYER_H__ */

View File

@@ -687,6 +687,13 @@ bool BKE_node_tree_iter_step(struct NodeTreeIterStore *ntreeiter,
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Node Tree
*/
void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, const int layer_index);
/* -------------------------------------------------------------------- */
/** \name Shader Nodes
*/

View File

@@ -41,6 +41,7 @@ struct Scene;
struct Object;
struct BoundBox;
struct View3D;
struct SceneLayer;
struct SoftBody;
struct BulletSoftBody;
struct MovieClip;
@@ -89,9 +90,9 @@ struct Object *BKE_object_add_only_object(
int type, const char *name)
ATTR_NONNULL(1) ATTR_RETURNS_NONNULL;
struct Object *BKE_object_add(
struct Main *bmain, struct Scene *scene,
struct Main *bmain, struct Scene *scene, struct SceneLayer *sl,
int type, const char *name)
ATTR_NONNULL(1, 2) ATTR_RETURNS_NONNULL;
ATTR_NONNULL(1, 2, 3) ATTR_RETURNS_NONNULL;
void *BKE_object_obdata_add_from_type(
struct Main *bmain,
int type, const char *name)
@@ -260,7 +261,7 @@ typedef enum eObjectSet {
struct LinkNode *BKE_object_relational_superset(struct Scene *scene, eObjectSet objectSet, eObRelationTypes includeFilter);
struct LinkNode *BKE_object_groups(struct Object *ob);
void BKE_object_groups_clear(struct Scene *scene, struct Base *base, struct Object *object);
void BKE_object_groups_clear(struct Object *object);
struct KDTree *BKE_object_as_kdtree(struct Object *ob, int *r_tot);

View File

@@ -42,6 +42,7 @@ struct Base;
struct EvaluationContext;
struct Main;
struct Object;
struct ObjectBase;
struct QuicktimeCodecData;
struct RenderData;
struct SceneRenderLayer;
@@ -70,6 +71,8 @@ void BKE_scene_free(struct Scene *sce);
void BKE_scene_init(struct Scene *sce);
struct Scene *BKE_scene_add(struct Main *bmain, const char *name);
void BKE_scene_remove_rigidbody_object(struct Scene *scene, struct Object *ob);
/* base functions */
struct Base *BKE_scene_base_find_by_name(struct Scene *scene, const char *name);
struct Base *BKE_scene_base_find(struct Scene *scene, struct Object *ob);
@@ -94,6 +97,10 @@ int BKE_scene_base_iter_next(struct EvaluationContext *eval_ctx, struct SceneBas
void BKE_scene_base_flag_to_objects(struct Scene *scene);
void BKE_scene_base_flag_from_objects(struct Scene *scene);
void BKE_scene_base_flag_sync_from_base(struct Base *base);
void BKE_scene_base_flag_sync_from_object(struct Base *base);
void BKE_scene_object_base_flag_sync_from_base(struct ObjectBase *base);
void BKE_scene_object_base_flag_sync_from_object(struct ObjectBase *base);
void BKE_scene_set_background(struct Main *bmain, struct Scene *sce);
struct Scene *BKE_scene_set_name(struct Main *bmain, const char *name);

View File

@@ -85,6 +85,7 @@ set(SRC
intern/camera.c
intern/cdderivedmesh.c
intern/cloth.c
intern/collection.c
intern/collision.c
intern/colortools.c
intern/constraint.c
@@ -157,6 +158,7 @@ set(SRC
intern/pbvh_bmesh.c
intern/pointcache.c
intern/property.c
intern/layer.c
intern/report.c
intern/rigidbody.c
intern/sca.c
@@ -214,6 +216,7 @@ set(SRC
BKE_ccg.h
BKE_cdderivedmesh.h
BKE_cloth.h
BKE_collection.h
BKE_collision.h
BKE_colortools.h
BKE_constraint.h
@@ -274,6 +277,7 @@ set(SRC
BKE_pbvh.h
BKE_pointcache.h
BKE_property.h
BKE_layer.h
BKE_report.h
BKE_rigidbody.h
BKE_sca.h

View File

@@ -0,0 +1,455 @@
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Dalai Felinto
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file blender/blenkernel/intern/collection.c
* \ingroup bke
*/
#include "BLI_blenlib.h"
#include "BLI_ghash.h"
#include "BLI_iterator.h"
#include "BLI_listbase.h"
#include "BLT_translation.h"
#include "BLI_string_utils.h"
#include "BKE_collection.h"
#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_scene.h"
#include "DNA_ID.h"
#include "DNA_layer_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "MEM_guardedalloc.h"
/**
* Add a collection to a collection ListBase and syncronize all render layers
* The ListBase is NULL when the collection is to be added to the master collection
*/
SceneCollection *BKE_collection_add(Scene *scene, SceneCollection *sc_parent, const char *name)
{
SceneCollection *sc_master = BKE_collection_master(scene);
SceneCollection *sc = MEM_callocN(sizeof(SceneCollection), "New Collection");
if (!name) {
name = DATA_("New Collection");
}
if (!sc_parent) {
sc_parent = sc_master;
}
BLI_strncpy(sc->name, name, sizeof(sc->name));
BLI_uniquename(&sc_master->scene_collections, sc, DATA_("Collection"), '.', offsetof(SceneCollection, name), sizeof(sc->name));
BLI_addtail(&sc_parent->scene_collections, sc);
BKE_layer_sync_new_scene_collection(scene, sc_parent, sc);
return sc;
}
/**
* Free the collection items recursively
*/
static void collection_free(SceneCollection *sc)
{
for (LinkData *link = sc->objects.first; link; link = link->next) {
id_us_min(link->data);
}
BLI_freelistN(&sc->objects);
for (LinkData *link = sc->filter_objects.first; link; link = link->next) {
id_us_min(link->data);
}
BLI_freelistN(&sc->filter_objects);
for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
collection_free(nsc);
}
BLI_freelistN(&sc->scene_collections);
}
/**
* Unlink the collection recursively
* return true if unlinked
*/
static bool collection_remlink(SceneCollection *sc_parent, SceneCollection *sc_gone)
{
for (SceneCollection *sc = sc_parent->scene_collections.first; sc; sc = sc->next)
{
if (sc == sc_gone) {
BLI_remlink(&sc_parent->scene_collections, sc_gone);
return true;
}
if (collection_remlink(sc, sc_gone)) {
return true;
}
}
return false;
}
/**
* Recursively remove any instance of this SceneCollection
*/
static void layer_collection_remove(SceneLayer *sl, ListBase *lb, const SceneCollection *sc)
{
LayerCollection *lc = lb->first;
while(lc) {
if (lc->scene_collection == sc) {
BKE_layer_collection_free(sl, lc);
BLI_remlink(lb, lc);
LayerCollection *lc_next = lc->next;
MEM_freeN(lc);
lc = lc_next;
/* only the "top-level" layer collections may have the
* same SceneCollection in a sibling tree.
*/
if (lb != &sl->layer_collections) {
return;
}
}
else {
layer_collection_remove(sl, &lc->layer_collections, sc);
lc = lc->next;
}
}
}
/**
* Remove a collection from the scene, and syncronize all render layers
*/
bool BKE_collection_remove(Scene *scene, SceneCollection *sc)
{
SceneCollection *sc_master = BKE_collection_master(scene);
/* the master collection cannot be removed */
if (sc == sc_master) {
return false;
}
/* unlink from the respective collection tree */
if (!collection_remlink(sc_master, sc)) {
BLI_assert(false);
}
/* clear the collection items */
collection_free(sc);
/* check all layers that use this collection and clear them */
for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) {
layer_collection_remove(sl, &sl->layer_collections, sc);
BKE_scene_layer_base_flag_recalculate(sl);
sl->active_collection = 0;
}
MEM_freeN(sc);
return true;
}
/**
* Returns the master collection
*/
SceneCollection *BKE_collection_master(Scene *scene)
{
return scene->collection;
}
/**
* Free (or release) any data used by the master collection (does not free the master collection itself).
* Used only to clear the entire scene data since it's not doing re-syncing of the LayerCollection tree
*/
void BKE_collection_master_free(Scene *scene){
collection_free(BKE_collection_master(scene));
}
static void collection_object_add(Scene *scene, SceneCollection *sc, Object *ob)
{
BLI_addtail(&sc->objects, BLI_genericNodeN(ob));
id_us_plus((ID *)ob);
BKE_layer_sync_object_link(scene, sc, ob);
}
/**
* Add object to collection
*/
void BKE_collection_object_add(Scene *scene, SceneCollection *sc, Object *ob)
{
if (BLI_findptr(&sc->objects, ob, offsetof(LinkData, data))) {
/* don't add the same object twice */
return;
}
collection_object_add(scene, sc, ob);
}
/**
* Add object to all collections that reference objects is in
* (used to copy objects)
*/
void BKE_collection_object_add_from(Scene *scene, Object *ob_src, Object *ob_dst)
{
SceneCollection *sc;
FOREACH_SCENE_COLLECTION(scene, sc)
{
if (BLI_findptr(&sc->objects, ob_src, offsetof(LinkData, data))) {
collection_object_add(scene, sc, ob_dst);
}
}
FOREACH_SCENE_COLLECTION_END
}
/**
* Remove object from collection
*/
void BKE_collection_object_remove(Main *bmain, Scene *scene, SceneCollection *sc, Object *ob, const bool free_us)
{
LinkData *link = BLI_findptr(&sc->objects, ob, offsetof(LinkData, data));
if (link == NULL) {
return;
}
BLI_remlink(&sc->objects, link);
MEM_freeN(link);
TODO_LAYER_SYNC_FILTER; /* need to remove all instances of ob in scene collections -> filter_objects */
BKE_layer_sync_object_unlink(scene, sc, ob);
if (free_us) {
BKE_libblock_free_us(bmain, ob);
}
else {
id_us_min(&ob->id);
}
}
/**
* Remove object from all collections of scene
*/
void BKE_collections_object_remove(Main *bmain, Scene *scene, Object *ob, const bool free_us)
{
BKE_scene_remove_rigidbody_object(scene, ob);
SceneCollection *sc;
FOREACH_SCENE_COLLECTION(scene, sc)
{
BKE_collection_object_remove(bmain, scene, sc, ob, free_us);
}
FOREACH_SCENE_COLLECTION_END
}
/* ---------------------------------------------------------------------- */
/* Iteractors */
/* scene collection iteractor */
typedef struct SceneCollectionsIteratorData {
Scene *scene;
void **array;
int tot, cur;
} SceneCollectionsIteratorData;
static void scene_collection_callback(SceneCollection *sc, BKE_scene_collections_Cb callback, void *data)
{
callback(sc, data);
for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
scene_collection_callback(nsc, callback, data);
}
}
static void scene_collections_count(SceneCollection *UNUSED(sc), void *data)
{
int *tot = data;
(*tot)++;
}
static void scene_collections_build_array(SceneCollection *sc, void *data)
{
SceneCollection ***array = data;
**array = sc;
(*array)++;
}
static void scene_collections_array(Scene *scene, SceneCollection ***collections_array, int *tot)
{
SceneCollection *sc = BKE_collection_master(scene);
SceneCollection **array;
*collections_array = NULL;
*tot = 0;
if (scene == NULL)
return;
scene_collection_callback(sc, scene_collections_count, tot);
if (*tot == 0)
return;
*collections_array = array = MEM_mallocN(sizeof(SceneCollection *) * (*tot), "SceneCollectionArray");
scene_collection_callback(sc, scene_collections_build_array, &array);
}
/**
* Only use this in non-performance critical situations
* (it iterates over all scene collections twice)
*/
void BKE_scene_collections_Iterator_begin(Iterator *iter, void *data_in)
{
Scene *scene = data_in;
SceneCollectionsIteratorData *data = MEM_callocN(sizeof(SceneCollectionsIteratorData), __FUNCTION__);
data->scene = scene;
iter->data = data;
scene_collections_array(scene, (SceneCollection ***)&data->array, &data->tot);
BLI_assert(data->tot != 0);
data->cur = 0;
iter->current = data->array[data->cur];
iter->valid = true;
}
void BKE_scene_collections_Iterator_next(struct Iterator *iter)
{
SceneCollectionsIteratorData *data = iter->data;
if (++data->cur < data->tot) {
iter->current = data->array[data->cur];
}
else {
iter->valid = false;
}
}
void BKE_scene_collections_Iterator_end(struct Iterator *iter)
{
SceneCollectionsIteratorData *data = iter->data;
if (data) {
if (data->array) {
MEM_freeN(data->array);
}
MEM_freeN(data);
}
iter->valid = false;
}
/* scene objects iteractor */
typedef struct SceneObjectsIteratorData {
GSet *visited;
LinkData *link;
Iterator scene_collection_iter;
} SceneObjectsIteratorData;
void BKE_scene_objects_Iterator_begin(Iterator *iter, void *data_in)
{
Scene *scene = data_in;
SceneObjectsIteratorData *data = MEM_callocN(sizeof(SceneObjectsIteratorData), __FUNCTION__);
iter->data = data;
/* lookup list ot make sure each object is object called once */
data->visited = BLI_gset_ptr_new(__func__);
/* we wrap the scenecollection iterator here to go over the scene collections */
BKE_scene_collections_Iterator_begin(&data->scene_collection_iter, scene);
SceneCollection *sc = data->scene_collection_iter.current;
iter->current = sc->objects.first;
if (iter->current == NULL) {
BKE_scene_objects_Iterator_next(iter);
}
}
/**
* Gets the next unique object
*/
static LinkData *object_base_next(GSet *gs, LinkData *link)
{
if (link == NULL) {
return NULL;
}
LinkData *link_next = link->next;
if (link_next) {
Object *ob = link_next->data;
if (!BLI_gset_haskey(gs, ob)) {
BLI_gset_add(gs, ob);
return link_next;
}
else {
return object_base_next(gs, link_next);
}
}
return NULL;
}
void BKE_scene_objects_Iterator_next(Iterator *iter)
{
SceneObjectsIteratorData *data = iter->data;
LinkData *link = object_base_next(data->visited, data->link);
if (link) {
data->link = link;
iter->current = link->data;
}
else {
/* if this is the last object of this ListBase look at the next SceneCollection */
SceneCollection *sc;
BKE_scene_collections_Iterator_next(&data->scene_collection_iter);
do {
sc = data->scene_collection_iter.current;
/* get the first unique object of this collection */
LinkData *new_link = object_base_next(data->visited, sc->objects.first);
if (new_link) {
data->link = new_link;
iter->current = data->link->data;
return;
}
BKE_scene_collections_Iterator_next(&data->scene_collection_iter);
} while (data->scene_collection_iter.valid);
if (!data->scene_collection_iter.valid) {
iter->valid = false;
}
}
}
void BKE_scene_objects_Iterator_end(Iterator *iter)
{
SceneObjectsIteratorData *data = iter->data;
if (data) {
BKE_scene_collections_Iterator_end(&data->scene_collection_iter);
BLI_gset_free(data->visited, NULL);
MEM_freeN(data);
}
}

View File

@@ -47,6 +47,7 @@
#include "BLT_translation.h"
#include "BKE_context.h"
#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_screen.h"
#include "BKE_sound.h"
@@ -814,6 +815,14 @@ struct SpaceClip *CTX_wm_space_clip(const bContext *C)
return NULL;
}
struct SpaceCollections *CTX_wm_space_collections(const bContext *C)
{
ScrArea *sa = CTX_wm_area(C);
if (sa && sa->spacetype == SPACE_COLLECTIONS)
return sa->spacedata.first;
return NULL;
}
void CTX_wm_manager_set(bContext *C, wmWindowManager *wm)
{
C->wm.manager = wm;
@@ -836,8 +845,9 @@ void CTX_wm_window_set(bContext *C, wmWindow *win)
void CTX_wm_screen_set(bContext *C, bScreen *screen)
{
C->wm.screen = screen;
if (C->wm.screen)
C->data.scene = C->wm.screen->scene;
if (C->wm.screen) {
CTX_data_scene_set(C, C->wm.screen->scene);
}
C->wm.area = NULL;
C->wm.region = NULL;
}
@@ -896,6 +906,62 @@ Scene *CTX_data_scene(const bContext *C)
return C->data.scene;
}
SceneLayer *CTX_data_scene_layer(const bContext *C)
{
SceneLayer *sl;
if (ctx_data_pointer_verify(C, "render_layer", (void *)&sl)) {
return sl;
}
else {
Scene *scene = CTX_data_scene(C);
sl = BLI_findlink(&scene->render_layers, scene->active_layer);
BLI_assert(sl);
return sl;
}
}
/**
* This is tricky. Sometimes the user overrides the render_layer
* but not the scene_collection. In this case what to do?
*
* If the scene_collection is linked to the SceneLayer we use it.
* Otherwise we fallback to the active one of the SceneLayer.
*/
LayerCollection *CTX_data_layer_collection(const bContext *C)
{
SceneLayer *sl = CTX_data_scene_layer(C);
LayerCollection *lc;
if (ctx_data_pointer_verify(C, "layer_collection", (void *)&lc)) {
if (BKE_scene_layer_has_collection(sl, lc->scene_collection)) {
return lc;
}
}
/* fallback */
return BKE_layer_collection_active(sl);
}
SceneCollection *CTX_data_scene_collection(const bContext *C)
{
SceneCollection *sc;
if (ctx_data_pointer_verify(C, "scene_collection", (void *)&sc)) {
if (BKE_scene_layer_has_collection(CTX_data_scene_layer(C), sc)) {
return sc;
}
}
LayerCollection *lc = CTX_data_layer_collection(C);
if (lc) {
return lc->scene_collection;
}
/* fallback */
Scene *scene = CTX_data_scene(C);
return BKE_collection_master(scene);
}
int CTX_data_mode_enum(const bContext *C)
{
Object *obedit = CTX_data_edit_object(C);
@@ -1034,7 +1100,7 @@ struct Object *CTX_data_active_object(const bContext *C)
return ctx_data_pointer_get(C, "active_object");
}
struct Base *CTX_data_active_base(const bContext *C)
struct ObjectBase *CTX_data_active_base(const bContext *C)
{
return ctx_data_pointer_get(C, "active_base");
}

View File

@@ -130,18 +130,11 @@ static bool group_object_add_internal(Group *group, Object *ob)
return true;
}
bool BKE_group_object_add(Group *group, Object *object, Scene *scene, Base *base)
bool BKE_group_object_add(Group *group, Object *object)
{
if (group_object_add_internal(group, object)) {
if ((object->flag & OB_FROMGROUP) == 0) {
if (scene && base == NULL)
base = BKE_scene_base_find(scene, object);
object->flag |= OB_FROMGROUP;
if (base)
base->flag |= OB_FROMGROUP;
}
return true;
}
@@ -208,18 +201,12 @@ bool BKE_group_object_cyclic_check(Main *bmain, Object *object, Group *group)
return group_object_cyclic_check_internal(object, group);
}
bool BKE_group_object_unlink(Group *group, Object *object, Scene *scene, Base *base)
bool BKE_group_object_unlink(Group *group, Object *object)
{
if (group_object_unlink_internal(group, object)) {
/* object can be NULL */
if (object && BKE_group_object_find(NULL, object) == NULL) {
if (scene && base == NULL)
base = BKE_scene_base_find(scene, object);
object->flag &= ~OB_FROMGROUP;
if (base)
base->flag &= ~OB_FROMGROUP;
}
return true;
}

View File

@@ -0,0 +1,924 @@
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Dalai Felinto
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file blender/blenkernel/intern/layer.c
* \ingroup bke
*/
#include "BLI_listbase.h"
#include "BLI_string.h"
#include "BLI_string_utf8.h"
#include "BLI_string_utils.h"
#include "BLT_translation.h"
#include "BKE_layer.h"
#include "BKE_collection.h"
#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_node.h"
#include "DNA_ID.h"
#include "DNA_layer_types.h"
#include "DNA_object_types.h"
#include "DNA_node_types.h"
#include "DNA_scene_types.h"
#include "MEM_guardedalloc.h"
/* prototype */
struct CollectionEngineSettingsCB_Type;
static void layer_collection_free(SceneLayer *sl, LayerCollection *lc);
static LayerCollection *layer_collection_add(SceneLayer *sl, ListBase *lb, SceneCollection *sc);
static LayerCollection *find_layer_collection_by_scene_collection(LayerCollection *lc, const SceneCollection *sc);
static void collection_engine_settings_create(ListBase *lb, struct CollectionEngineSettingsCB_Type *ces_type);
static void layer_collection_create_engine_settings(LayerCollection *lc);
static void object_bases_Iterator_next(Iterator *iter, const int flag);
/* RenderLayer */
/**
* Add a new renderlayer
* by default, a renderlayer has the master collection
*/
SceneLayer *BKE_scene_layer_add(Scene *scene, const char *name)
{
if (!name) {
name = DATA_("Render Layer");
}
SceneLayer *sl = MEM_callocN(sizeof(SceneLayer), "Scene Layer");
sl->flag |= SCENE_LAYER_RENDER;
BLI_addtail(&scene->render_layers, sl);
/* unique name */
BLI_strncpy_utf8(sl->name, name, sizeof(sl->name));
BLI_uniquename(&scene->render_layers, sl, DATA_("SceneLayer"), '.', offsetof(SceneLayer, name), sizeof(sl->name));
SceneCollection *sc = BKE_collection_master(scene);
layer_collection_add(sl, &sl->layer_collections, sc);
return sl;
}
bool BKE_scene_layer_remove(Main *bmain, Scene *scene, SceneLayer *sl)
{
const int act = BLI_findindex(&scene->render_layers, sl);
if (act == -1) {
return false;
}
else if ( (scene->render_layers.first == scene->render_layers.last) &&
(scene->render_layers.first == sl))
{
/* ensure 1 layer is kept */
return false;
}
BLI_remlink(&scene->render_layers, sl);
BKE_scene_layer_free(sl);
MEM_freeN(sl);
scene->active_layer = 0;
/* TODO WORKSPACE: set active_layer to 0 */
for (Scene *sce = bmain->scene.first; sce; sce = sce->id.next) {
if (sce->nodetree) {
BKE_nodetree_remove_layer_n(sce->nodetree, scene, act);
}
}
return true;
}
/**
* Free (or release) any data used by this SceneLayer (does not free the SceneLayer itself).
*/
void BKE_scene_layer_free(SceneLayer *sl)
{
sl->basact = NULL;
BLI_freelistN(&sl->object_bases);
for (LayerCollection *lc = sl->layer_collections.first; lc; lc = lc->next) {
layer_collection_free(NULL, lc);
}
BLI_freelistN(&sl->layer_collections);
}
/**
* Set the render engine of a renderlayer
*/
void BKE_scene_layer_engine_set(SceneLayer *sl, const char *engine)
{
BLI_strncpy_utf8(sl->engine, engine, sizeof(sl->engine));
}
/**
* Tag all the selected objects of a renderlayer
*/
void BKE_scene_layer_selected_objects_tag(SceneLayer *sl, const int tag)
{
for (ObjectBase *base = sl->object_bases.first; base; base = base->next) {
if ((base->flag & BASE_SELECTED) != 0) {
base->object->flag |= tag;
}
else {
base->object->flag &= ~tag;
}
}
}
static bool find_scene_collection_in_scene_collections(ListBase *lb, const LayerCollection *lc)
{
for (LayerCollection *lcn = lb->first; lcn; lcn = lcn->next) {
if (lcn == lc) {
return true;
}
if (find_scene_collection_in_scene_collections(&lcn->layer_collections, lc)) {
return true;
}
}
return false;
}
/**
* Find the SceneLayer a LayerCollection belongs to
*/
SceneLayer *BKE_scene_layer_find_from_collection(Scene *scene, LayerCollection *lc)
{
for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) {
if (find_scene_collection_in_scene_collections(&sl->layer_collections, lc)) {
return sl;
}
}
return NULL;
}
/* ObjectBase */
ObjectBase *BKE_scene_layer_base_find(SceneLayer *sl, Object *ob)
{
return BLI_findptr(&sl->object_bases, ob, offsetof(ObjectBase, object));
}
void BKE_scene_layer_base_deselect_all(SceneLayer *sl)
{
ObjectBase *base;
for (base = sl->object_bases.first; base; base = base->next) {
base->flag &= ~BASE_SELECTED;
}
}
void BKE_scene_layer_base_select(struct SceneLayer *sl, ObjectBase *selbase)
{
sl->basact = selbase;
if ((selbase->flag & BASE_SELECTABLED) != 0) {
selbase->flag |= BASE_SELECTED;
}
}
static void scene_layer_object_base_unref(SceneLayer* sl, ObjectBase *base)
{
base->refcount--;
/* It only exists in the RenderLayer */
if (base->refcount == 0) {
if (sl->basact == base) {
sl->basact = NULL;
}
BLI_remlink(&sl->object_bases, base);
MEM_freeN(base);
}
}
static void layer_collection_base_flag_recalculate(LayerCollection *lc, const bool tree_is_visible, const bool tree_is_selectable)
{
bool is_visible = tree_is_visible && ((lc->flag & COLLECTION_VISIBLE) != 0);
/* an object can only be selected if it's visible */
bool is_selectable = tree_is_selectable && is_visible && ((lc->flag & COLLECTION_SELECTABLE) != 0);
for (LinkData *link = lc->object_bases.first; link; link = link->next) {
ObjectBase *base = link->data;
if (is_visible) {
base->flag |= BASE_VISIBLED;
}
else {
base->flag &= ~BASE_VISIBLED;
}
if (is_selectable) {
base->flag |= BASE_SELECTABLED;
}
else {
base->flag &= ~BASE_SELECTABLED;
}
}
for (LayerCollection *lcn = lc->layer_collections.first; lcn; lcn = lcn->next) {
layer_collection_base_flag_recalculate(lcn, is_visible, is_selectable);
}
}
/**
* Re-evaluate the ObjectBase flags for SceneLayer
*/
void BKE_scene_layer_base_flag_recalculate(SceneLayer *sl)
{
for (LayerCollection *lc = sl->layer_collections.first; lc; lc = lc->next) {
layer_collection_base_flag_recalculate(lc, true, true);
}
/* if base is not selectabled, clear select */
for (ObjectBase *base = sl->object_bases.first; base; base = base->next) {
if ((base->flag & BASE_SELECTABLED) == 0) {
base->flag &= ~BASE_SELECTED;
}
}
BKE_scene_layer_engine_settings_recalculate(sl);
}
/**
* Tag Scene Layer to recalculation
*
* Temporary function, waiting for real depsgraph
*/
void BKE_scene_layer_engine_settings_recalculate(struct SceneLayer *sl)
{
sl->flag |= SCENE_LAYER_ENGINE_DIRTY;
}
/**
* Re-calculate the engine settings for all the objects in SceneLayer
*
* Temporary function, waiting for real depsgraph
*/
void BKE_scene_layer_engine_settings_update(struct SceneLayer *sl)
{
if ((sl->flag & SCENE_LAYER_ENGINE_DIRTY) == 0) {
return;
}
/* do the complete settings update */
TODO_LAYER_DEPSGRAPH;
sl->flag &= ~SCENE_LAYER_ENGINE_DIRTY;
}
/**
* Return the base if existent, or create it if necessary
* Always bump the refcount
*/
static ObjectBase *object_base_add(SceneLayer *sl, Object *ob)
{
ObjectBase *base;
base = BKE_scene_layer_base_find(sl, ob);
if (base == NULL) {
base = MEM_callocN(sizeof(ObjectBase), "Object Base");
/* do not bump user count, leave it for SceneCollections */
base->object = ob;
BLI_addtail(&sl->object_bases, base);
}
base->refcount++;
return base;
}
/* LayerCollection */
/**
* When freeing the entire SceneLayer at once we don't bother with unref
* otherwise SceneLayer is passed to keep the syncing of the LayerCollection tree
*/
static void layer_collection_free(SceneLayer *sl, LayerCollection *lc)
{
if (sl) {
for (LinkData *link = lc->object_bases.first; link; link = link->next) {
scene_layer_object_base_unref(sl, link->data);
}
}
BLI_freelistN(&lc->object_bases);
BLI_freelistN(&lc->overrides);
BKE_layer_collection_engine_settings_free(&lc->engine_settings);
for (LayerCollection *nlc = lc->layer_collections.first; nlc; nlc = nlc->next) {
layer_collection_free(sl, nlc);
}
BLI_freelistN(&lc->layer_collections);
}
/**
* Free (or release) LayerCollection from SceneLayer
* (does not free the LayerCollection itself).
*/
void BKE_layer_collection_free(SceneLayer *sl, LayerCollection *lc)
{
layer_collection_free(sl, lc);
}
/* LayerCollection */
/**
* Recursively get the collection for a given index
*/
static LayerCollection *collection_from_index(ListBase *lb, const int number, int *i)
{
for (LayerCollection *lc = lb->first; lc; lc = lc->next) {
if (*i == number) {
return lc;
}
(*i)++;
LayerCollection *lc_nested = collection_from_index(&lc->layer_collections, number, i);
if (lc_nested) {
return lc_nested;
}
}
return NULL;
}
/**
* Get the active collection
*/
LayerCollection *BKE_layer_collection_active(SceneLayer *sl)
{
int i = 0;
return collection_from_index(&sl->layer_collections, sl->active_collection, &i);
}
/**
* Recursively get the count of collections
*/
static int collection_count(ListBase *lb)
{
int i = 0;
for (LayerCollection *lc = lb->first; lc; lc = lc->next) {
i += collection_count(&lc->layer_collections) + 1;
}
return i;
}
/**
* Get the total number of collections
* (including all the nested collections)
*/
int BKE_layer_collection_count(SceneLayer *sl)
{
return collection_count(&sl->layer_collections);
}
/**
* Recursively get the index for a given collection
*/
static int index_from_collection(ListBase *lb, LayerCollection *lc, int *i)
{
for (LayerCollection *lcol = lb->first; lcol; lcol = lcol->next) {
if (lcol == lc) {
return *i;
}
(*i)++;
int i_nested = index_from_collection(&lcol->layer_collections, lc, i);
if (i_nested != -1) {
return i_nested;
}
}
return -1;
}
/**
* Return -1 if not found
*/
int BKE_layer_collection_findindex(SceneLayer *sl, LayerCollection *lc)
{
int i = 0;
return index_from_collection(&sl->layer_collections, lc, &i);
}
/**
* Link a collection to a renderlayer
* The collection needs to be created separately
*/
LayerCollection *BKE_collection_link(SceneLayer *sl, SceneCollection *sc)
{
LayerCollection *lc = layer_collection_add(sl, &sl->layer_collections, sc);
sl->active_collection = BKE_layer_collection_findindex(sl, lc);
return lc;
}
/**
* Unlink a collection base from a renderlayer
* The corresponding collection is not removed from the master collection
*/
void BKE_collection_unlink(SceneLayer *sl, LayerCollection *lc)
{
BKE_layer_collection_free(sl, lc);
BKE_scene_layer_base_flag_recalculate(sl);
BLI_remlink(&sl->layer_collections, lc);
MEM_freeN(lc);
sl->active_collection = 0;
}
static void layer_collection_object_add(SceneLayer *sl, LayerCollection *lc, Object *ob)
{
ObjectBase *base = object_base_add(sl, ob);
/* only add an object once - prevent SceneCollection->objects and
* SceneCollection->filter_objects to add the same object */
if (BLI_findptr(&lc->object_bases, base, offsetof(LinkData, data))) {
return;
}
BLI_addtail(&lc->object_bases, BLI_genericNodeN(base));
BKE_scene_layer_base_flag_recalculate(sl);
}
static void layer_collection_object_remove(SceneLayer *sl, LayerCollection *lc, Object *ob)
{
ObjectBase *base;
base = BKE_scene_layer_base_find(sl, ob);
LinkData *link = BLI_findptr(&lc->object_bases, base, offsetof(LinkData, data));
BLI_remlink(&lc->object_bases, link);
MEM_freeN(link);
scene_layer_object_base_unref(sl, base);
}
static void layer_collection_objects_populate(SceneLayer *sl, LayerCollection *lc, ListBase *objects)
{
for (LinkData *link = objects->first; link; link = link->next) {
layer_collection_object_add(sl, lc, link->data);
}
}
static void layer_collection_populate(SceneLayer *sl, LayerCollection *lc, SceneCollection *sc)
{
layer_collection_objects_populate(sl, lc, &sc->objects);
layer_collection_objects_populate(sl, lc, &sc->filter_objects);
for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
layer_collection_add(sl, &lc->layer_collections, nsc);
}
}
static LayerCollection *layer_collection_add(SceneLayer *sl, ListBase *lb, SceneCollection *sc)
{
LayerCollection *lc = MEM_callocN(sizeof(LayerCollection), "Collection Base");
BLI_addtail(lb, lc);
lc->scene_collection = sc;
lc->flag = COLLECTION_VISIBLE + COLLECTION_SELECTABLE + COLLECTION_FOLDED;
layer_collection_create_engine_settings(lc);
layer_collection_populate(sl, lc, sc);
return lc;
}
/* ---------------------------------------------------------------------- */
/**
* See if render layer has the scene collection linked directly, or indirectly (nested)
*/
bool BKE_scene_layer_has_collection(struct SceneLayer *sl, struct SceneCollection *sc)
{
for (LayerCollection *lc = sl->layer_collections.first; lc; lc = lc->next) {
if (find_layer_collection_by_scene_collection(lc, sc) != NULL) {
return true;
}
}
return false;
}
/**
* See if the object is in any of the scene layers of the scene
*/
bool BKE_scene_has_object(Scene *scene, Object *ob)
{
for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) {
ObjectBase *base = BKE_scene_layer_base_find(sl, ob);
if (base) {
return true;
}
}
return false;
}
/* ---------------------------------------------------------------------- */
/* Syncing */
static LayerCollection *find_layer_collection_by_scene_collection(LayerCollection *lc, const SceneCollection *sc)
{
if (lc->scene_collection == sc) {
return lc;
}
for (LayerCollection *nlc = lc->layer_collections.first; nlc; nlc = nlc->next) {
LayerCollection *found = find_layer_collection_by_scene_collection(nlc, sc);
if (found) {
return found;
}
}
return NULL;
}
/**
* Add a new LayerCollection for all the SceneLayers that have sc_parent
*/
void BKE_layer_sync_new_scene_collection(Scene *scene, const SceneCollection *sc_parent, SceneCollection *sc)
{
for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) {
for (LayerCollection *lc = sl->layer_collections.first; lc; lc = lc->next) {
LayerCollection *lc_parent = find_layer_collection_by_scene_collection(lc, sc_parent);
if (lc_parent) {
layer_collection_add(sl, &lc_parent->layer_collections, sc);
}
}
}
}
/**
* Add a corresponding ObjectBase to all the equivalent LayerCollection
*/
void BKE_layer_sync_object_link(Scene *scene, SceneCollection *sc, Object *ob)
{
for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) {
for (LayerCollection *lc = sl->layer_collections.first; lc; lc = lc->next) {
LayerCollection *found = find_layer_collection_by_scene_collection(lc, sc);
if (found) {
layer_collection_object_add(sl, found, ob);
}
}
}
}
/**
* Remove the equivalent object base to all layers that have this collection
* also remove all reference to ob in the filter_objects
*/
void BKE_layer_sync_object_unlink(Scene *scene, SceneCollection *sc, Object *ob)
{
for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) {
for (LayerCollection *lc = sl->layer_collections.first; lc; lc = lc->next) {
LayerCollection *found = find_layer_collection_by_scene_collection(lc, sc);
if (found) {
layer_collection_object_remove(sl, found, ob);
}
}
BKE_scene_layer_base_flag_recalculate(sl);
}
}
/* ---------------------------------------------------------------------- */
/* Override */
/**
* Add a new datablock override
*/
void BKE_collection_override_datablock_add(LayerCollection *UNUSED(lc), const char *UNUSED(data_path), ID *UNUSED(id))
{
TODO_LAYER_OVERRIDE;
}
/* ---------------------------------------------------------------------- */
/* Engine Settings */
ListBase R_engines_settings_callbacks = {NULL, NULL};
typedef struct CollectionEngineSettingsCB_Type {
struct CollectionEngineSettingsCB_Type *next, *prev;
char name[MAX_NAME]; /* engine name */
CollectionEngineSettingsCB callback;
} CollectionEngineSettingsCB_Type;
static void create_engine_settings_layer_collection(LayerCollection *lc, CollectionEngineSettingsCB_Type *ces_type)
{
if (BKE_layer_collection_engine_get(lc, ces_type->name)) {
return;
}
collection_engine_settings_create(&lc->engine_settings, ces_type);
for (LayerCollection *lcn = lc->layer_collections.first; lcn; lcn = lcn->next) {
create_engine_settings_layer_collection(lcn, ces_type);
}
}
static void create_engines_settings_scene(Scene *scene, CollectionEngineSettingsCB_Type *ces_type)
{
for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) {
for (LayerCollection *lc = sl->layer_collections.first; lc; lc = lc->next) {
create_engine_settings_layer_collection(lc, ces_type);
}
}
}
void BKE_layer_collection_engine_settings_callback_register(
Main *bmain, const char *engine_name, CollectionEngineSettingsCB func)
{
CollectionEngineSettingsCB_Type *ces_type;
/* cleanup in case it existed */
ces_type = BLI_findstring(&R_engines_settings_callbacks, engine_name, offsetof(CollectionEngineSettingsCB_Type, name));
if (ces_type) {
BLI_remlink(&R_engines_settings_callbacks, ces_type);
MEM_freeN(ces_type);
}
ces_type = MEM_callocN(sizeof(CollectionEngineSettingsCB_Type), "collection_engine_type");
BLI_strncpy_utf8(ces_type->name, engine_name, sizeof(ces_type->name));
ces_type->callback = func;
BLI_addtail(&R_engines_settings_callbacks, ces_type);
if (bmain) {
/* populate all of the collections of the scene with those settings */
for (Scene *scene = bmain->scene.first; scene; scene = scene->id.next) {
create_engines_settings_scene(scene, ces_type);
}
}
}
void BKE_layer_collection_engine_settings_callback_free(void)
{
BLI_freelistN(&R_engines_settings_callbacks);
}
static void collection_engine_settings_create(ListBase *lb, CollectionEngineSettingsCB_Type *ces_type)
{
/* create callback data */
CollectionEngineSettings *ces = MEM_callocN(sizeof(CollectionEngineSettings), "Collection Engine Settings");
BLI_strncpy_utf8(ces->name, ces_type->name, sizeof(ces->name));
BLI_addtail(lb, ces);
/* call callback */
ces_type->callback(NULL, ces);
}
/**
* Initialize a CollectionEngineSettings
*
* Usually we would pass LayerCollection->engine_settings
* But depsgraph uses this for Object->collection_settings
*/
void BKE_layer_collection_engine_settings_create(ListBase *lb, const char *engine_name)
{
CollectionEngineSettingsCB_Type *ces_type;
ces_type = BLI_findstring(&R_engines_settings_callbacks, engine_name, offsetof(CollectionEngineSettingsCB_Type, name));
BLI_assert(ces_type);
collection_engine_settings_create(lb, ces_type);
}
/**
* Free the CollectionEngineSettings ListBase
*
* Usually we would pass LayerCollection->engine_settings
* But depsgraph uses this for Object->collection_settings
*/
void BKE_layer_collection_engine_settings_free(ListBase *lb)
{
for (CollectionEngineSettings *cse = lb->first; cse; cse = cse->next) {
BLI_freelistN(&cse->properties);
}
BLI_freelistN(lb);
}
/**
* Initialize the render settings for a single LayerCollection
*/
static void layer_collection_create_engine_settings(LayerCollection *lc)
{
CollectionEngineSettingsCB_Type *ces_type;
for (ces_type = R_engines_settings_callbacks.first; ces_type; ces_type = ces_type->next) {
create_engine_settings_layer_collection(lc, ces_type);
}
}
/**
* Return layer collection engine settings for specified engine
*/
CollectionEngineSettings *BKE_layer_collection_engine_get(LayerCollection *lc, const char *engine_name)
{
CollectionEngineSettings *ces;
ces = BLI_findstring(&lc->engine_settings, engine_name, offsetof(CollectionEngineSettings, name));
return ces;
}
/* ---------------------------------------------------------------------- */
/* Engine Settings Properties */
void BKE_collection_engine_property_add_float(CollectionEngineSettings *ces, const char *name, float value)
{
CollectionEnginePropertyFloat *prop;
prop = MEM_callocN(sizeof(CollectionEnginePropertyFloat), "collection engine settings float");
prop->data.type = COLLECTION_PROP_TYPE_FLOAT;
BLI_strncpy_utf8(prop->data.name, name, sizeof(prop->data.name));
prop->value = value;
BLI_addtail(&ces->properties, prop);
}
void BKE_collection_engine_property_add_int(CollectionEngineSettings *ces, const char *name, int value)
{
CollectionEnginePropertyInt *prop;
prop = MEM_callocN(sizeof(CollectionEnginePropertyInt), "collection engine settings int");
prop->data.type = COLLECTION_PROP_TYPE_INT;
BLI_strncpy_utf8(prop->data.name, name, sizeof(prop->data.name));
prop->value = value;
BLI_addtail(&ces->properties, prop);
}
CollectionEngineProperty *BKE_collection_engine_property_get(CollectionEngineSettings *ces, const char *name)
{
return BLI_findstring(&ces->properties, name, offsetof(CollectionEngineProperty, name));
}
int BKE_collection_engine_property_value_get_int(CollectionEngineSettings *ces, const char *name)
{
CollectionEnginePropertyInt *prop;
prop = (CollectionEnginePropertyInt *)BLI_findstring(&ces->properties, name, offsetof(CollectionEngineProperty, name));
return prop->value;
}
float BKE_collection_engine_property_value_get_float(CollectionEngineSettings *ces, const char *name)
{
CollectionEnginePropertyFloat *prop;
prop = (CollectionEnginePropertyFloat *)BLI_findstring(&ces->properties, name, offsetof(CollectionEngineProperty, name));
return prop->value;
}
void BKE_collection_engine_property_value_set_int(CollectionEngineSettings *ces, const char *name, int value)
{
CollectionEnginePropertyInt *prop;
prop = (CollectionEnginePropertyInt *)BLI_findstring(&ces->properties, name, offsetof(CollectionEngineProperty, name));
prop->value = value;
prop->data.flag |= COLLECTION_PROP_USE;
}
void BKE_collection_engine_property_value_set_float(CollectionEngineSettings *ces, const char *name, float value)
{
CollectionEnginePropertyFloat *prop;
prop = (CollectionEnginePropertyFloat *)BLI_findstring(&ces->properties, name, offsetof(CollectionEngineProperty, name));
prop->value = value;
prop->data.flag |= COLLECTION_PROP_USE;
}
bool BKE_collection_engine_property_use_get(CollectionEngineSettings *ces, const char *name)
{
CollectionEngineProperty *prop;
prop = (CollectionEngineProperty *)BLI_findstring(&ces->properties, name, offsetof(CollectionEngineProperty, name));
return ((prop->flag & COLLECTION_PROP_USE) != 0);
}
void BKE_collection_engine_property_use_set(CollectionEngineSettings *ces, const char *name, bool value)
{
CollectionEngineProperty *prop;
prop = (CollectionEngineProperty *)BLI_findstring(&ces->properties, name, offsetof(CollectionEngineProperty, name));
if (value) {
prop->flag |= COLLECTION_PROP_USE;
}
else {
prop->flag &= ~COLLECTION_PROP_USE;
}
}
/* ---------------------------------------------------------------------- */
/* Iterators */
static void object_bases_Iterator_begin(Iterator *iter, void *data_in, const int flag)
{
SceneLayer *sl = data_in;
ObjectBase *base = sl->object_bases.first;
/* when there are no objects */
if (base == NULL) {
iter->valid = false;
return;
}
iter->valid = true;
iter->data = base;
if ((base->flag & flag) == 0) {
object_bases_Iterator_next(iter, flag);
}
else {
iter->current = base;
}
}
static void object_bases_Iterator_next(Iterator *iter, const int flag)
{
ObjectBase *base = ((ObjectBase *)iter->data)->next;
while (base) {
if ((base->flag & flag) != 0) {
iter->current = base;
iter->data = base;
return;
}
base = base->next;
}
iter->current = NULL;
iter->valid = false;
}
static void objects_Iterator_begin(Iterator *iter, void *data_in, const int flag)
{
object_bases_Iterator_begin(iter, data_in, flag);
if (iter->valid) {
iter->current = ((ObjectBase *)iter->current)->object;
}
}
static void objects_Iterator_next(Iterator *iter, const int flag)
{
object_bases_Iterator_next(iter, flag);
if (iter->valid) {
iter->current = ((ObjectBase *)iter->current)->object;
}
}
void BKE_selected_objects_Iterator_begin(Iterator *iter, void *data_in)
{
objects_Iterator_begin(iter, data_in, BASE_SELECTED);
}
void BKE_selected_objects_Iterator_next(Iterator *iter)
{
objects_Iterator_next(iter, BASE_SELECTED);
}
void BKE_selected_objects_Iterator_end(Iterator *UNUSED(iter))
{
/* do nothing */
}
void BKE_visible_objects_Iterator_begin(Iterator *iter, void *data_in)
{
objects_Iterator_begin(iter, data_in, BASE_VISIBLED);
}
void BKE_visible_objects_Iterator_next(Iterator *iter)
{
objects_Iterator_next(iter, BASE_VISIBLED);
}
void BKE_visible_objects_Iterator_end(Iterator *UNUSED(iter))
{
/* do nothing */
}
void BKE_visible_bases_Iterator_begin(Iterator *iter, void *data_in)
{
object_bases_Iterator_begin(iter, data_in, BASE_VISIBLED);
}
void BKE_visible_bases_Iterator_next(Iterator *iter)
{
object_bases_Iterator_next(iter, BASE_VISIBLED);
}
void BKE_visible_bases_Iterator_end(Iterator *UNUSED(iter))
{
/* do nothing */
}

View File

@@ -67,6 +67,7 @@
#include "BLI_linklist_stack.h"
#include "BKE_animsys.h"
#include "BKE_collection.h"
#include "BKE_constraint.h"
#include "BKE_fcurve.h"
#include "BKE_library.h"
@@ -333,7 +334,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
Scene *scene = (Scene *) id;
ToolSettings *toolsett = scene->toolsettings;
SceneRenderLayer *srl;
Base *base;
Base *legacy_base;
CALLBACK_INVOKE(scene->camera, IDWALK_NOP);
CALLBACK_INVOKE(scene->world, IDWALK_USER);
@@ -390,8 +391,28 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
CALLBACK_INVOKE(scene->gpd, IDWALK_USER);
for (base = scene->base.first; base; base = base->next) {
CALLBACK_INVOKE(base->object, IDWALK_USER);
for (legacy_base = scene->base.first; legacy_base; legacy_base = legacy_base->next) {
CALLBACK_INVOKE(legacy_base->object, IDWALK_USER);
}
SceneCollection *sc;
FOREACH_SCENE_COLLECTION(scene, sc)
{
for (LinkData *link = sc->objects.first; link; link = link->next) {
CALLBACK_INVOKE_ID(link->data, IDWALK_USER);
}
for (LinkData *link = sc->filter_objects.first; link; link = link->next) {
CALLBACK_INVOKE_ID(link->data, IDWALK_USER);
}
}
FOREACH_SCENE_COLLECTION_END
SceneLayer *sl;
for (sl = scene->render_layers.first; sl; sl = sl->next) {
for (ObjectBase *base = sl->object_bases.first; base; base = base->next) {
CALLBACK_INVOKE(base->object, IDWALK_NOP);
}
}
for (TimeMarker *marker = scene->markers.first; marker; marker = marker->next) {

View File

@@ -71,6 +71,7 @@
#include "BKE_brush.h"
#include "BKE_camera.h"
#include "BKE_cachefile.h"
#include "BKE_collection.h"
#include "BKE_curve.h"
#include "BKE_depsgraph.h"
#include "BKE_fcurve.h"
@@ -254,6 +255,22 @@ static void libblock_remap_data_preprocess_scene_base_unlink(
}
}
/* Some remapping unfortunately require extra and/or specific handling, tackle those here. */
static void libblock_remap_data_preprocess_scene_object_unlink(
IDRemap *r_id_remap_data, Scene *sce, Object *ob, const bool skip_indirect, const bool is_indirect)
{
if (skip_indirect && is_indirect) {
r_id_remap_data->skipped_indirect++;
r_id_remap_data->skipped_refcounted++;
}
else {
BKE_collections_object_remove(r_id_remap_data->bmain, sce, ob, false);
if (!is_indirect) {
r_id_remap_data->status |= ID_REMAP_IS_LINKED_DIRECT;
}
}
}
static void libblock_remap_data_preprocess(IDRemap *r_id_remap_data)
{
switch (GS(r_id_remap_data->id->name)) {
@@ -268,6 +285,15 @@ static void libblock_remap_data_preprocess(IDRemap *r_id_remap_data)
/* In case we are unlinking... */
if (!r_id_remap_data->old_id) {
/* ... everything from scene. */
Object *ob_iter;
FOREACH_SCENE_OBJECT(sce, ob_iter)
{
libblock_remap_data_preprocess_scene_object_unlink(
r_id_remap_data, sce, ob_iter, skip_indirect, is_indirect);
}
FOREACH_SCENE_OBJECT_END
Base *base, *base_next;
for (base = sce->base.first; base; base = base_next) {
base_next = base->next;
@@ -278,8 +304,11 @@ static void libblock_remap_data_preprocess(IDRemap *r_id_remap_data)
else if (GS(r_id_remap_data->old_id->name) == ID_OB) {
/* ... a specific object from scene. */
Object *old_ob = (Object *)r_id_remap_data->old_id;
Base *base = BKE_scene_base_find(sce, old_ob);
libblock_remap_data_preprocess_scene_object_unlink(
r_id_remap_data, sce, old_ob, skip_indirect, is_indirect);
Base *base = BKE_scene_base_find(sce, old_ob);
if (base) {
libblock_remap_data_preprocess_scene_base_unlink(
r_id_remap_data, sce, base, skip_indirect, is_indirect);
@@ -325,7 +354,7 @@ static void libblock_remap_data_postprocess_object_fromgroup_update(Main *bmain,
}
if (new_ob == NULL) { /* We need to remove NULL-ified groupobjects... */
for (Group *group = bmain->group.first; group; group = group->id.next) {
BKE_group_object_unlink(group, NULL, NULL, NULL);
BKE_group_object_unlink(group, NULL);
}
}
else {
@@ -339,22 +368,16 @@ static void libblock_remap_data_postprocess_group_scene_unlink(Main *UNUSED(bmai
/* Note that here we assume no object has no base (i.e. all objects are assumed instanced
* in one scene...). */
for (Base *base = sce->base.first; base; base = base->next) {
if (base->flag & OB_FROMGROUP) {
Object *ob = base->object;
Object *ob = base->object;
if (ob->flag & OB_FROMGROUP) {
Group *grp = BKE_group_object_find(NULL, ob);
if (ob->flag & OB_FROMGROUP) {
Group *grp = BKE_group_object_find(NULL, ob);
/* Unlinked group (old_id) is still in bmain... */
if (grp && (&grp->id == old_id || grp->id.us == 0)) {
grp = BKE_group_object_find(grp, ob);
}
if (!grp) {
ob->flag &= ~OB_FROMGROUP;
}
/* Unlinked group (old_id) is still in bmain... */
if (grp && (&grp->id == old_id || grp->id.us == 0)) {
grp = BKE_group_object_find(grp, ob);
}
if (!(ob->flag & OB_FROMGROUP)) {
base->flag &= ~OB_FROMGROUP;
if (!grp) {
ob->flag &= ~OB_FROMGROUP;
}
}
}

View File

@@ -111,6 +111,12 @@ void BKE_material_free(Material *ma)
BKE_icon_id_delete((ID *)ma);
BKE_previewimg_free(&ma->preview);
for (MaterialEngineSettings *mes = ma->engines_settings.first; mes; mes = mes->next) {
if (mes->data)
MEM_SAFE_FREE(mes->data);
}
BLI_freelistN(&ma->engines_settings);
}
void BKE_material_init(Material *ma)
@@ -248,6 +254,8 @@ Material *BKE_material_copy(Main *bmain, Material *ma)
BLI_listbase_clear(&man->gpumaterial);
/* TODO Duplicate Engine Settings and set runtime to NULL */
BKE_id_copy_ensure_local(bmain, &ma->id, &man->id);
return man;
@@ -279,6 +287,8 @@ Material *localize_material(Material *ma)
man->nodetree = ntreeLocalize(ma->nodetree);
BLI_listbase_clear(&man->gpumaterial);
/* TODO Duplicate Engine Settings and set runtime to NULL */
return man;
}
@@ -1698,6 +1708,7 @@ void copy_matcopybuf(Material *ma)
matcopybuf.nodetree = ntreeCopyTree_ex(ma->nodetree, G.main, false);
matcopybuf.preview = NULL;
BLI_listbase_clear(&matcopybuf.gpumaterial);
/* TODO Duplicate Engine Settings and set runtime to NULL */
matcopied = 1;
}

View File

@@ -359,27 +359,25 @@ void BKE_mball_properties_copy(Scene *scene, Object *active_object)
*/
Object *BKE_mball_basis_find(Scene *scene, Object *basis)
{
Scene *sce_iter = scene;
Base *base;
Object *ob, *bob = basis;
Object *bob = basis;
int basisnr, obnr;
char basisname[MAX_ID_NAME], obname[MAX_ID_NAME];
SceneBaseIter iter;
EvaluationContext *eval_ctx = G.main->eval_ctx;
BLI_split_name_num(basisname, &basisnr, basis->id.name + 2, '.');
BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 0, NULL, NULL);
while (BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 1, &base, &ob)) {
if ((ob->type == OB_MBALL) && !(base->flag & OB_FROMDUPLI)) {
if (ob != bob) {
BLI_split_name_num(obname, &obnr, ob->id.name + 2, '.');
for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) {
for (ObjectBase *base = sl->object_bases.first; base; base = base->next) {
Object *ob = base->object;
if ((ob->type == OB_MBALL) && !(base->flag & OB_FROMDUPLI)) {
if (ob != bob) {
BLI_split_name_num(obname, &obnr, ob->id.name + 2, '.');
/* object ob has to be in same "group" ... it means, that it has to have same base of its name */
if (STREQ(obname, basisname)) {
if (obnr < basisnr) {
basis = ob;
basisnr = obnr;
/* object ob has to be in same "group" ... it means, that it has to have same base of its name */
if (STREQ(obname, basisname)) {
if (obnr < basisnr) {
basis = ob;
basisnr = obnr;
}
}
}
}

View File

@@ -47,7 +47,7 @@
/* Mesh Interface */
#define MESH_RENDER_FUNCTION(func_name) \
if (me->edit_btmesh) { \
if (me->edit_btmesh && me->edit_btmesh->derivedFinal) { \
return mesh_bmesh_##func_name(me); \
} \
else { \

View File

@@ -3776,3 +3776,20 @@ bool BKE_node_tree_iter_step(struct NodeTreeIterStore *ntreeiter,
return true;
}
/* -------------------------------------------------------------------- */
/* NodeTree kernel functions */
void BKE_nodetree_remove_layer_n(bNodeTree *ntree, Scene *scene, const int layer_index)
{
for (bNode *node = ntree->nodes.first; node; node = node->next) {
if (node->type == CMP_NODE_R_LAYERS && (Scene *)node->id == scene) {
if (node->custom1 == layer_index) {
node->custom1 = 0;
}
else if (node->custom1 > layer_index) {
node->custom1--;
}
}
}
}

View File

@@ -91,6 +91,7 @@
#include "BKE_icons.h"
#include "BKE_key.h"
#include "BKE_lamp.h"
#include "BKE_layer.h"
#include "BKE_lattice.h"
#include "BKE_library.h"
#include "BKE_library_query.h"
@@ -677,23 +678,25 @@ Object *BKE_object_add_only_object(Main *bmain, int type, const char *name)
/* general add: to scene, with layer from area and default name */
/* creates minimum required data, but without vertices etc. */
Object *BKE_object_add(
Main *bmain, Scene *scene,
Main *bmain, Scene *scene, SceneLayer *sl,
int type, const char *name)
{
Object *ob;
Base *base;
ObjectBase *base;
LayerCollection *lc;
ob = BKE_object_add_only_object(bmain, type, name);
ob->data = BKE_object_obdata_add_from_type(bmain, type, name);
ob->lay = scene->lay;
base = BKE_scene_base_add(scene, ob);
BKE_scene_base_deselect_all(scene);
BKE_scene_base_select(scene, base);
DAG_id_tag_update_ex(bmain, &ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
lc = BKE_layer_collection_active(sl);
BKE_collection_object_add(scene, lc->scene_collection, ob);
base = BKE_scene_layer_base_find(sl, ob);
BKE_scene_layer_base_deselect_all(sl);
BKE_scene_layer_base_select(sl, base);
DAG_id_tag_update_ex(bmain, &ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
return ob;
}
@@ -3492,18 +3495,11 @@ struct LinkNode *BKE_object_groups(Object *ob)
return group_linknode;
}
void BKE_object_groups_clear(Scene *scene, Base *base, Object *object)
void BKE_object_groups_clear(Object *ob)
{
Group *group = NULL;
BLI_assert((base == NULL) || (base->object == object));
if (scene && base == NULL) {
base = BKE_scene_base_find(scene, object);
}
while ((group = BKE_group_object_find(group, base->object))) {
BKE_group_object_unlink(group, object, scene, base);
while ((group = BKE_group_object_find(group, ob))) {
BKE_group_object_unlink(group, ob);
}
}

View File

@@ -67,6 +67,7 @@
#include "BKE_action.h"
#include "BKE_armature.h"
#include "BKE_cachefile.h"
#include "BKE_collection.h"
#include "BKE_colortools.h"
#include "BKE_depsgraph.h"
#include "BKE_editmesh.h"
@@ -78,6 +79,7 @@
#include "BKE_icons.h"
#include "BKE_idprop.h"
#include "BKE_image.h"
#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_library_remap.h"
#include "BKE_linestyle.h"
@@ -107,6 +109,7 @@
const char *RE_engine_id_BLENDER_RENDER = "BLENDER_RENDER";
const char *RE_engine_id_BLENDER_GAME = "BLENDER_GAME";
const char *RE_engine_id_BLENDER_CLAY = "BLENDER_CLAY";
const char *RE_engine_id_CYCLES = "CYCLES";
void free_avicodecdata(AviCodecData *acd)
@@ -154,13 +157,66 @@ static void remove_sequencer_fcurves(Scene *sce)
}
}
/* copy SceneCollection tree but keep pointing to the same objects */
static void scene_collection_copy(SceneCollection *scn, SceneCollection *sc)
{
BLI_duplicatelist(&scn->objects, &sc->objects);
for (LinkData *link = scn->objects.first; link; link = link->next) {
id_us_plus(link->data);
}
BLI_duplicatelist(&scn->filter_objects, &sc->filter_objects);
for (LinkData *link = scn->filter_objects.first; link; link = link->next) {
id_us_plus(link->data);
}
BLI_duplicatelist(&scn->scene_collections, &sc->scene_collections);
SceneCollection *nscn = scn->scene_collections.first; /* nested SceneCollection new */
for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
scene_collection_copy(nscn, nsc);
nscn = nscn->next;
}
}
/* Find the equivalent SceneCollection in the new tree */
static SceneCollection *scene_collection_from_new_tree(SceneCollection *sc_reference, SceneCollection *scn, SceneCollection *sc)
{
if (sc == sc_reference) {
return scn;
}
SceneCollection *nscn = scn->scene_collections.first; /* nested master collection new */
for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
SceneCollection *found = scene_collection_from_new_tree(sc_reference, nscn, nsc);
if (found) {
return found;
}
nscn = nscn->next;
}
return NULL;
}
/* recreate the LayerCollection tree */
static void layer_collections_recreate(SceneLayer *sl, ListBase *lb, SceneCollection *mcn, SceneCollection *mc)
{
for (LayerCollection *lc = lb->first; lc; lc = lc->next) {
SceneCollection *sc = scene_collection_from_new_tree(lc->scene_collection, mcn, mc);
BLI_assert(sc);
/* instead of syncronizing both trees we simply re-create it */
BKE_collection_link(sl, sc);
}
}
Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type)
{
Scene *scen;
SceneRenderLayer *srl, *new_srl;
FreestyleLineSet *lineset;
ToolSettings *ts;
Base *base, *obase;
Base *legacy_base, *olegacy_base;
if (type == SCE_COPY_EMPTY) {
ListBase rl, rv;
@@ -214,14 +270,14 @@ Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type)
BKE_libblock_relink_ex(bmain, scen->nodetree, &sce->id, &scen->id, false);
}
obase = sce->base.first;
base = scen->base.first;
while (base) {
id_us_plus(&base->object->id);
if (obase == sce->basact) scen->basact = base;
olegacy_base = sce->base.first;
legacy_base = scen->base.first;
while (legacy_base) {
id_us_plus(&legacy_base->object->id);
if (olegacy_base == sce->basact) scen->basact = legacy_base;
obase = obase->next;
base = base->next;
olegacy_base = olegacy_base->next;
legacy_base = legacy_base->next;
}
/* copy action and remove animation used by sequencer */
@@ -244,6 +300,36 @@ Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type)
}
new_srl = new_srl->next;
}
/* layers and collections */
scen->collection = MEM_dupallocN(sce->collection);
SceneCollection *mcn = BKE_collection_master(scen);
SceneCollection *mc = BKE_collection_master(sce);
/* recursively creates a new SceneCollection tree */
scene_collection_copy(mcn, mc);
BLI_duplicatelist(&scen->render_layers, &sce->render_layers);
SceneLayer *new_sl = scen->render_layers.first;
for (SceneLayer *sl = sce->render_layers.first; sl; sl = sl->next) {
/* we start fresh with no overrides and no visibility flags set
* instead of syncing both trees we simply unlink and relink the scene collection */
BLI_listbase_clear(&new_sl->layer_collections);
BLI_listbase_clear(&new_sl->object_bases);
layer_collections_recreate(new_sl, &sl->layer_collections, mcn, mc);
if (sl->basact) {
Object *active_ob = sl->basact->object;
for (ObjectBase *base = new_sl->object_bases.first; base; base = base->next) {
if (base->object == active_ob) {
new_sl->basact = base;
break;
}
}
}
new_sl = new_sl->next;
}
}
/* copy color management settings */
@@ -471,6 +557,23 @@ void BKE_scene_free(Scene *sce)
BKE_previewimg_free(&sce->preview);
curvemapping_free_data(&sce->r.mblur_shutter_curve);
for (SceneLayer *sl = sce->render_layers.first; sl; sl = sl->next) {
BKE_scene_layer_free(sl);
}
BLI_freelistN(&sce->render_layers);
/* Master Collection */
BKE_collection_master_free(sce);
MEM_freeN(sce->collection);
sce->collection = NULL;
/* Runtime Engine Data */
for (RenderEngineSettings *res = sce->engines_settings.first; res; res = res->next) {
if (res->data)
MEM_freeN(res->data);
}
BLI_freelistN(&sce->engines_settings);
}
void BKE_scene_init(Scene *sce)
@@ -820,6 +923,12 @@ void BKE_scene_init(Scene *sce)
sce->toolsettings->gpencil_v2d_align = GP_PROJECT_VIEWSPACE;
sce->toolsettings->gpencil_seq_align = GP_PROJECT_VIEWSPACE;
sce->toolsettings->gpencil_ima_align = GP_PROJECT_VIEWSPACE;
/* Master Collection */
sce->collection = MEM_callocN(sizeof(SceneCollection), "Master Collection");
BLI_strncpy(sce->collection->name, "Master Collection", sizeof(sce->collection->name));
BKE_scene_layer_add(sce, "Render Layer");
}
Scene *BKE_scene_add(Main *bmain, const char *name)
@@ -865,7 +974,6 @@ void BKE_scene_set_background(Main *bmain, Scene *scene)
Object *ob;
Group *group;
GroupObject *go;
int flag;
/* check for cyclic sets, for reading old files but also for definite security (py?) */
BKE_scene_validate_setscene(bmain, scene);
@@ -897,13 +1005,7 @@ void BKE_scene_set_background(Main *bmain, Scene *scene)
ob->lay = base->lay;
/* group patch... */
base->flag &= ~(OB_FROMGROUP);
flag = ob->flag & (OB_FROMGROUP);
base->flag |= flag;
/* not too nice... for recovering objects with lost data */
//if (ob->pose == NULL) base->flag &= ~OB_POSEMODE;
ob->flag = base->flag;
BKE_scene_base_flag_sync_from_base(base);
}
/* no full animation update, this to enable render code to work (render code calls own animation updates) */
}
@@ -1154,6 +1256,15 @@ char *BKE_scene_find_last_marker_name(Scene *scene, int frame)
return best_marker ? best_marker->name : NULL;
}
void BKE_scene_remove_rigidbody_object(Scene *scene, Object *ob)
{
/* remove rigid body constraint from world before removing object */
if (ob->rigidbody_constraint)
BKE_rigidbody_remove_constraint(scene, ob);
/* remove rigid body object from world before removing object */
if (ob->rigidbody_object)
BKE_rigidbody_remove_object(scene, ob);
}
Base *BKE_scene_base_add(Scene *sce, Object *ob)
{
@@ -1169,13 +1280,8 @@ Base *BKE_scene_base_add(Scene *sce, Object *ob)
void BKE_scene_base_unlink(Scene *sce, Base *base)
{
/* remove rigid body constraint from world before removing object */
if (base->object->rigidbody_constraint)
BKE_rigidbody_remove_constraint(sce, base->object);
/* remove rigid body object from world before removing object */
if (base->object->rigidbody_object)
BKE_rigidbody_remove_object(sce, base->object);
BKE_scene_remove_rigidbody_object(sce, base->object);
BLI_remlink(&sce->base, base);
if (sce->basact == base)
sce->basact = NULL;
@@ -1187,7 +1293,9 @@ void BKE_scene_base_deselect_all(Scene *sce)
for (b = sce->base.first; b; b = b->next) {
b->flag &= ~SELECT;
int flag = b->object->flag & (OB_FROMGROUP);
b->object->flag = b->flag;
b->object->flag |= flag;
}
}
@@ -1492,15 +1600,7 @@ bool BKE_scene_remove_render_layer(Main *bmain, Scene *scene, SceneRenderLayer *
for (sce = bmain->scene.first; sce; sce = sce->id.next) {
if (sce->nodetree) {
bNode *node;
for (node = sce->nodetree->nodes.first; node; node = node->next) {
if (node->type == CMP_NODE_R_LAYERS && (Scene *)node->id == scene) {
if (node->custom1 == act)
node->custom1 = 0;
else if (node->custom1 > act)
node->custom1--;
}
}
BKE_nodetree_remove_layer_n(sce->nodetree, scene, act);
}
}
@@ -1651,7 +1751,7 @@ void BKE_scene_base_flag_to_objects(struct Scene *scene)
Base *base = scene->base.first;
while (base) {
base->object->flag = base->flag;
BKE_scene_base_flag_sync_from_base(base);
base = base->next;
}
}
@@ -1661,11 +1761,43 @@ void BKE_scene_base_flag_from_objects(struct Scene *scene)
Base *base = scene->base.first;
while (base) {
base->flag = base->object->flag;
BKE_scene_base_flag_sync_from_object(base);
base = base->next;
}
}
void BKE_scene_base_flag_sync_from_base(Base *base)
{
Object *ob = base->object;
/* keep the object only flags untouched */
int flag = ob->flag & OB_FROMGROUP;
ob->flag = base->flag;
ob->flag |= flag;
}
void BKE_scene_base_flag_sync_from_object(Base *base)
{
base->flag = base->object->flag;
}
void BKE_scene_object_base_flag_sync_from_base(ObjectBase *base)
{
Object *ob = base->object;
/* keep the object only flags untouched */
int flag = ob->flag & OB_FROMGROUP;
ob->flag = base->flag;
ob->flag |= flag;
}
void BKE_scene_object_base_flag_sync_from_object(ObjectBase *base)
{
base->flag = base->object->flag;
}
void BKE_scene_disable_color_management(Scene *scene)
{
ColorManagedDisplaySettings *display_settings = &scene->display_settings;

View File

@@ -32,6 +32,7 @@
* \ingroup bli
*/
#include "BLI_blenlib.h"
#include "BLI_sys_types.h" /* for bool */
#include "BLI_compiler_attrs.h"

View File

@@ -0,0 +1,54 @@
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Dalai Felinto
*
* ***** END GPL LICENSE BLOCK *****
*/
#ifndef __BLI_ITERATOR_H__
#define __BLI_ITERATOR_H__
/** \file BLI_iterator.h
* \ingroup bli
*/
typedef struct Iterator {
void *current; /* current pointer we iterate over */
void *data; /* stored data required for this iterator */
bool valid;
} Iterator;
typedef void (*IteratorCb)(Iterator *iter);
typedef void (*IteratorBeginCb)(Iterator *iter, void *data_in);
#define ITER_BEGIN(callback_begin, callback_next, callback_end, _data_in, _data_out) \
{ \
IteratorCb callback_end_func = callback_end; \
Iterator iter_macro; \
for (callback_begin(&iter_macro, _data_in); \
iter_macro.valid; \
callback_next(&iter_macro)) \
{ \
_data_out = iter_macro.current;
#define ITER_END \
} \
callback_end_func(&iter_macro); \
}
#endif /* __BLI_ITERATOR_H__ */

View File

@@ -155,6 +155,7 @@ set(SRC
BLI_hash_md5.h
BLI_hash_mm2a.h
BLI_heap.h
BLI_iterator.h
BLI_jitter.h
BLI_kdopbvh.h
BLI_kdtree.h

View File

@@ -53,6 +53,7 @@ set(SRC
intern/versioning_250.c
intern/versioning_260.c
intern/versioning_270.c
intern/versioning_280.c
intern/versioning_defaults.c
intern/versioning_legacy.c
intern/writefile.c

View File

@@ -72,6 +72,7 @@
#include "DNA_ipo_types.h"
#include "DNA_key_types.h"
#include "DNA_lattice_types.h"
#include "DNA_layer_types.h"
#include "DNA_lamp_types.h"
#include "DNA_linestyle_types.h"
#include "DNA_meta_types.h"
@@ -102,6 +103,8 @@
#include "DNA_movieclip_types.h"
#include "DNA_mask_types.h"
#include "RNA_access.h"
#include "MEM_guardedalloc.h"
#include "BLI_endian_switch.h"
@@ -3967,6 +3970,7 @@ static void lib_link_material(FileData *fd, Main *main)
static void direct_link_material(FileData *fd, Material *ma)
{
int a;
MaterialEngineSettings *mes;
ma->adt = newdataadr(fd, ma->adt);
direct_link_animdata(fd, ma->adt);
@@ -3987,6 +3991,11 @@ static void direct_link_material(FileData *fd, Material *ma)
ma->preview = direct_link_preview_image(fd, ma->preview);
BLI_listbase_clear(&ma->gpumaterial);
link_list(fd, &ma->engines_settings);
for (mes = ma->engines_settings.first; mes; mes = mes->next) {
mes->data = newdataadr(fd, mes->data);
}
}
/* ************ READ PARTICLE SETTINGS ***************** */
@@ -4607,6 +4616,7 @@ static void direct_link_mesh(FileData *fd, Mesh *mesh)
mesh->bb = NULL;
mesh->edit_btmesh = NULL;
mesh->batch_cache = NULL;
/* happens with old files */
if (mesh->mselect == NULL) {
@@ -5548,6 +5558,7 @@ static void direct_link_object(FileData *fd, Object *ob)
ob->bb = NULL;
ob->derivedDeform = NULL;
ob->derivedFinal = NULL;
ob->collection_settings = NULL;
BLI_listbase_clear(&ob->gpulamp);
link_list(fd, &ob->pc_ids);
@@ -5629,11 +5640,29 @@ static bool scene_validate_setscene__liblink(Scene *sce, const int totscene)
}
#endif
static void lib_link_scene_collection(FileData *fd, Library *lib, SceneCollection *sc)
{
for (LinkData *link = sc->objects.first; link; link = link->next) {
link->data = newlibadr_us(fd, lib, link->data);
BLI_assert(link->data);
}
for (LinkData *link = sc->filter_objects.first; link; link = link->next) {
link->data = newlibadr_us(fd, lib, link->data);
BLI_assert(link->data);
}
for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
lib_link_scene_collection(fd, lib, nsc);
}
}
static void lib_link_scene(FileData *fd, Main *main)
{
Scene *sce;
Base *base, *next;
Base *base_legacy, *base_legacy_next;
Sequence *seq;
SceneLayer *sl;
SceneRenderLayer *srl;
FreestyleModuleConfig *fmc;
FreestyleLineSet *fls;
@@ -5683,17 +5712,17 @@ static void lib_link_scene(FileData *fd, Main *main)
sce->toolsettings->particle.shape_object = newlibadr(fd, sce->id.lib, sce->toolsettings->particle.shape_object);
for (base = sce->base.first; base; base = next) {
next = base->next;
for (base_legacy = sce->base.first; base_legacy; base_legacy = base_legacy_next) {
base_legacy_next = base_legacy->next;
base->object = newlibadr_us(fd, sce->id.lib, base->object);
base_legacy->object = newlibadr_us(fd, sce->id.lib, base_legacy->object);
if (base->object == NULL) {
if (base_legacy->object == NULL) {
blo_reportf_wrap(fd->reports, RPT_WARNING, TIP_("LIB: object lost from scene: '%s'"),
sce->id.name + 2);
BLI_remlink(&sce->base, base);
if (base == sce->basact) sce->basact = NULL;
MEM_freeN(base);
BLI_remlink(&sce->base, base_legacy);
if (base_legacy == sce->basact) sce->basact = NULL;
MEM_freeN(base_legacy);
}
}
@@ -5779,6 +5808,15 @@ static void lib_link_scene(FileData *fd, Main *main)
/* Motion Tracking */
sce->clip = newlibadr_us(fd, sce->id.lib, sce->clip);
lib_link_scene_collection(fd, sce->id.lib, sce->collection);
for (sl = sce->render_layers.first; sl; sl = sl->next) {
for (ObjectBase *base = sl->object_bases.first; base; base = base->next) {
/* we only bump the use count for the collection objects */
base->object = newlibadr(fd, sce->id.lib, base->object);
}
}
#ifdef USE_SETSCENE_CHECK
if (sce->set != NULL) {
/* link flag for scenes with set would be reset later,
@@ -5882,13 +5920,54 @@ static void direct_link_view_settings(FileData *fd, ColorManagedViewSettings *vi
direct_link_curvemapping(fd, view_settings->curve_mapping);
}
static void direct_link_scene_collection(FileData *fd, SceneCollection *sc)
{
link_list(fd, &sc->objects);
link_list(fd, &sc->filter_objects);
link_list(fd, &sc->scene_collections);
for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
direct_link_scene_collection(fd, nsc);
}
}
static void direct_link_engine_settings(FileData *fd, ListBase *lb)
{
link_list(fd, lb);
for (CollectionEngineSettings *ces = lb->first; ces; ces = ces->next) {
link_list(fd, &ces->properties);
}
}
static void direct_link_layer_collections(FileData *fd, ListBase *lb)
{
link_list(fd, lb);
for (LayerCollection *lc = lb->first; lc; lc = lc->next) {
lc->scene_collection = newdataadr(fd, lc->scene_collection);
link_list(fd, &lc->object_bases);
for (LinkData *link = lc->object_bases.first; link; link = link->next) {
link->data = newdataadr(fd, link->data);
}
link_list(fd, &lc->overrides);
direct_link_engine_settings(fd, &lc->engine_settings);
direct_link_layer_collections(fd, &lc->layer_collections);
}
}
static void direct_link_scene(FileData *fd, Scene *sce)
{
Editing *ed;
Sequence *seq;
MetaStack *ms;
RigidBodyWorld *rbw;
SceneLayer *sl;
SceneRenderLayer *srl;
RenderEngineSettings *res;
sce->theDag = NULL;
sce->depsgraph = NULL;
@@ -6138,6 +6217,24 @@ static void direct_link_scene(FileData *fd, Scene *sce)
sce->preview = direct_link_preview_image(fd, sce->preview);
direct_link_curvemapping(fd, &sce->r.mblur_shutter_curve);
/* this runs before the very first doversion */
if (sce->collection) {
sce->collection = newdataadr(fd, sce->collection);
direct_link_scene_collection(fd, sce->collection);
}
link_list(fd, &sce->render_layers);
for (sl = sce->render_layers.first; sl; sl = sl->next) {
link_list(fd, &sl->object_bases);
sl->basact = newdataadr(fd, sl->basact);
direct_link_layer_collections(fd, &sl->layer_collections);
}
link_list(fd, &sce->engines_settings);
for (res = sce->engines_settings.first; res; res = res->next) {
res->data = newdataadr(fd, res->data);
}
}
/* ************ READ WM ***************** */
@@ -6481,6 +6578,10 @@ static void lib_link_screen(FileData *fd, Main *main)
slogic->gpd = newlibadr_us(fd, sc->id.lib, slogic->gpd);
}
else if (sl->spacetype == SPACE_COLLECTIONS) {
SpaceCollections *slayer = (SpaceCollections *)sl;
slayer->flag |= SC_COLLECTION_DATA_REFRESH;
}
}
}
sc->id.tag &= ~LIB_TAG_NEED_LINK;
@@ -6866,6 +6967,10 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc
slogic->gpd = restore_pointer_by_name(id_map, (ID *)slogic->gpd, USER_REAL);
}
else if (sl->spacetype == SPACE_COLLECTIONS) {
SpaceCollections *slayer = (SpaceCollections *)sl;
slayer->flag |= SC_COLLECTION_DATA_REFRESH;
}
}
}
}
@@ -7260,6 +7365,10 @@ static bool direct_link_screen(FileData *fd, bScreen *sc)
sclip->scopes.track_preview = NULL;
sclip->scopes.ok = 0;
}
else if (sl->spacetype == SPACE_COLLECTIONS) {
SpaceCollections *slayer = (SpaceCollections *)sl;
slayer->flag |= SC_COLLECTION_DATA_REFRESH;
}
}
BLI_listbase_clear(&sa->actionzones);
@@ -7456,7 +7565,7 @@ static void lib_link_group(FileData *fd, Main *main)
if (add_us) {
id_us_ensure_real(&group->id);
}
BKE_group_object_unlink(group, NULL, NULL, NULL); /* removes NULL entries */
BKE_group_object_unlink(group, NULL); /* removes NULL entries */
}
}
}
@@ -8388,6 +8497,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
blo_do_versions_250(fd, lib, main);
blo_do_versions_260(fd, lib, main);
blo_do_versions_270(fd, lib, main);
blo_do_versions_280(fd, lib, main);
/* WATCH IT!!!: pointers from libdata have not been converted yet here! */
/* WATCH IT 2!: Userdef struct init see do_versions_userdef() above! */
@@ -8399,8 +8509,8 @@ static void do_versions_after_linking(Main *main)
{
// printf("%s for %s (%s), %d.%d\n", __func__, main->curlib ? main->curlib->name : main->name,
// main->curlib ? "LIB" : "MAIN", main->versionfile, main->subversionfile);
do_versions_after_linking_270(main);
do_versions_after_linking_280(main);
}
static void lib_link_all(FileData *fd, Main *main)
@@ -9483,6 +9593,21 @@ static void expand_object(FileData *fd, Main *mainvar, Object *ob)
}
}
static void expand_scene_collection(FileData *fd, Main *mainvar, SceneCollection *sc)
{
for (LinkData *link = sc->objects.first; link; link = link->next) {
expand_doit(fd, mainvar, link->data);
}
for (LinkData *link = sc->filter_objects.first; link; link = link->next) {
expand_doit(fd, mainvar, link->data);
}
for (SceneCollection *nsc= sc->scene_collections.first; nsc; nsc = nsc->next) {
expand_scene_collection(fd, mainvar, nsc);
}
}
static void expand_scene(FileData *fd, Main *mainvar, Scene *sce)
{
Base *base;
@@ -9552,6 +9677,8 @@ static void expand_scene(FileData *fd, Main *mainvar, Scene *sce)
}
expand_doit(fd, mainvar, sce->clip);
expand_scene_collection(fd, mainvar, sce->collection);
}
static void expand_camera(FileData *fd, Main *mainvar, Camera *ca)
@@ -9834,7 +9961,7 @@ static void give_base_to_objects(Main *mainvar, Scene *scene, View3D *v3d, Libra
base->object = ob;
base->lay = ob->lay;
base->flag = ob->flag;
BKE_scene_base_flag_sync_from_object(base);
CLAMP_MIN(ob->id.us, 0);
id_us_plus_no_lib((ID *)ob);
@@ -9868,7 +9995,7 @@ static void give_base_to_groups(
/* assign the base */
base = BKE_scene_base_add(scene, ob);
base->flag |= SELECT;
base->object->flag = base->flag;
BKE_scene_base_flag_sync_from_base(base);
DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
scene->basact = base;
@@ -9971,7 +10098,7 @@ static void link_object_postprocess(ID *id, Scene *scene, View3D *v3d, const sho
if (flag & FILE_AUTOSELECT) {
base->flag |= SELECT;
base->object->flag = base->flag;
BKE_scene_base_flag_sync_from_base(base);
/* do NOT make base active here! screws up GUI stuff, if you want it do it on src/ level */
}
}

View File

@@ -34,6 +34,8 @@
#define __READFILE_H__
#include "zlib.h"
#include "DNA_sdna_types.h"
#include "DNA_space_types.h"
#include "DNA_windowmanager_types.h" /* for ReportType */
struct OldNewMap;
@@ -169,8 +171,10 @@ void blo_do_versions_pre250(struct FileData *fd, struct Library *lib, struct Mai
void blo_do_versions_250(struct FileData *fd, struct Library *lib, struct Main *main);
void blo_do_versions_260(struct FileData *fd, struct Library *lib, struct Main *main);
void blo_do_versions_270(struct FileData *fd, struct Library *lib, struct Main *main);
void blo_do_versions_280(struct FileData *fd, struct Library *lib, struct Main *main);
void do_versions_after_linking_270(struct Main *main);
void do_versions_after_linking_280(struct Main *main);
#endif

View File

@@ -0,0 +1,182 @@
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Dalai Felinto
*
* ***** END GPL LICENSE BLOCK *****
*
*/
/** \file blender/blenloader/intern/versioning_280.c
* \ingroup blenloader
*/
/* allow readfile to use deprecated functionality */
#define DNA_DEPRECATED_ALLOW
#include "DNA_object_types.h"
#include "DNA_layer_types.h"
#include "DNA_material_types.h"
#include "DNA_scene_types.h"
#include "DNA_genfile.h"
#include "BKE_collection.h"
#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_scene.h"
#include "BLI_listbase.h"
#include "BLI_string.h"
#include "BLO_readfile.h"
#include "readfile.h"
#include "MEM_guardedalloc.h"
void do_versions_after_linking_280(Main *main)
{
if (!MAIN_VERSION_ATLEAST(main, 280, 0)) {
for (Scene *scene = main->scene.first; scene; scene = scene->id.next) {
/* since we don't have access to FileData we check the (always valid) first render layer instead */
if (scene->render_layers.first == NULL) {
SceneCollection *sc_master = BKE_collection_master(scene);
BLI_strncpy(sc_master->name, "Master Collection", sizeof(sc_master->name));
SceneCollection *collections[20] = {NULL};
bool is_visible[20];
int lay_used = 0;
for (int i = 0; i < 20; i++) {
char name[MAX_NAME];
BLI_snprintf(name, sizeof(collections[i]->name), "%d", i + 1);
collections[i] = BKE_collection_add(scene, sc_master, name);
is_visible[i] = (scene->lay & (1 << i));
}
for (Base *base = scene->base.first; base; base = base->next) {
lay_used |= base->lay & ((1 << 20) - 1); /* ignore localview */
for (int i = 0; i < 20; i++) {
if ((base->lay & (1 << i)) != 0) {
BKE_collection_object_add(scene, collections[i], base->object);
}
}
}
scene->active_layer = 0;
if (!BKE_scene_uses_blender_game(scene)) {
for (SceneRenderLayer *srl = scene->r.layers.first; srl; srl = srl->next) {
SceneLayer *sl = BKE_scene_layer_add(scene, srl->name);
BKE_scene_layer_engine_set(sl, scene->r.engine);
if (srl->mat_override) {
BKE_collection_override_datablock_add((LayerCollection *)sl->layer_collections.first, "material", (ID *)srl->mat_override);
}
if (srl->light_override && BKE_scene_uses_blender_internal(scene)) {
/* not sure how we handle this, pending until we design the override system */
TODO_LAYER_OVERRIDE;
}
if (srl->lay != scene->lay) {
/* unlink master collection */
BKE_collection_unlink(sl, sl->layer_collections.first);
/* add new collection bases */
for (int i = 0; i < 20; i++) {
if ((srl->lay & (1 << i)) != 0) {
BKE_collection_link(sl, collections[i]);
}
}
}
/* TODO: passes, samples, mask_layesr, exclude, ... */
}
if (BLI_findlink(&scene->render_layers, scene->r.actlay)) {
scene->active_layer = scene->r.actlay;
}
}
SceneLayer *sl = BKE_scene_layer_add(scene, "Render Layer");
/* In this particular case we can safely assume the data struct */
LayerCollection *lc = ((LayerCollection *)sl->layer_collections.first)->layer_collections.first;
for (int i = 0; i < 20; i++) {
if (!is_visible[i]) {
lc->flag &= ~COLLECTION_VISIBLE;
}
lc = lc->next;
}
/* but we still need to make the flags synced */
BKE_scene_layer_base_flag_recalculate(sl);
/* convert active base */
if (scene->basact) {
sl->basact = BKE_scene_layer_base_find(sl, scene->basact->object);
}
/* convert selected bases */
for (Base *base = scene->base.first; base; base = base->next) {
ObjectBase *ob_base = BKE_scene_layer_base_find(sl, base->object);
if ((base->flag & SELECT) != 0) {
if ((ob_base->flag & BASE_SELECTABLED) != 0) {
ob_base->flag |= BASE_SELECTED;
}
}
else {
ob_base->flag &= ~BASE_SELECTED;
}
}
/* TODO: copy scene render data to layer */
/* Cleanup */
for (int i = 0; i < 20; i++) {
if ((lay_used & (1 << i)) == 0) {
BKE_collection_remove(scene, collections[i]);
}
}
/* remove bases once and for all */
for (Base *base = scene->base.first; base; base = base->next) {
id_us_min(&base->object->id);
}
BLI_freelistN(&scene->base);
scene->basact = NULL;
}
}
}
}
void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *main)
{
if (!MAIN_VERSION_ATLEAST(main, 280, 0)) {
if (!DNA_struct_elem_find(fd->filesdna, "Scene", "ListBase", "render_layers")) {
for (Scene *scene = main->scene.first; scene; scene = scene->id.next) {
/* Master Collection */
scene->collection = MEM_callocN(sizeof(SceneCollection), "Master Collection");
BLI_strncpy(scene->collection->name, "Master Collection", sizeof(scene->collection->name));
}
}
}
}

View File

@@ -120,6 +120,7 @@
#include "DNA_key_types.h"
#include "DNA_lattice_types.h"
#include "DNA_lamp_types.h"
#include "DNA_layer_types.h"
#include "DNA_linestyle_types.h"
#include "DNA_meta_types.h"
#include "DNA_mesh_types.h"
@@ -1893,6 +1894,8 @@ static void write_objects(WriteData *wd, ListBase *idbase)
writelist(wd, DATA, LinkData, &ob->pc_ids);
writelist(wd, DATA, LodLevel, &ob->lodlevels);
ob->collection_settings = NULL;
}
write_previews(wd, ob->preview);
@@ -2270,6 +2273,7 @@ static void write_meshes(WriteData *wd, ListBase *idbase)
CustomData_reset(&mesh->pdata);
CustomData_reset(&mesh->ldata);
mesh->edit_btmesh = NULL;
mesh->batch_cache = NULL;
/* now fill in polys to mfaces */
/* XXX This breaks writing design, by using temp allocated memory, which will likely generate
@@ -2467,6 +2471,21 @@ static void write_textures(WriteData *wd, ListBase *idbase)
mywrite_flush(wd);
}
static void write_material_engines_settings(WriteData *wd, ListBase *lb)
{
for (MaterialEngineSettings *res = lb->first; res; res = res->next) {
writestruct(wd, DATA, MaterialEngineSettings, 1, res);
if (STREQ(res->name, RE_engine_id_BLENDER_CLAY)) {
writestruct(wd, DATA, MaterialEngineSettingsClay, 1, res->data);
}
else {
/* No engine matched */
/* error: don't know how to write this file */
}
}
}
static void write_materials(WriteData *wd, ListBase *idbase)
{
Material *ma;
@@ -2503,6 +2522,8 @@ static void write_materials(WriteData *wd, ListBase *idbase)
}
write_previews(wd, ma->preview);
write_material_engines_settings(wd, &ma->engines_settings);
}
ma = ma->id.next;
}
@@ -2625,6 +2646,67 @@ static void write_paint(WriteData *wd, Paint *p)
}
}
static void write_scene_collection(WriteData *wd, SceneCollection *sc)
{
writestruct(wd, DATA, SceneCollection, 1, sc);
writelist(wd, DATA, LinkData, &sc->objects);
writelist(wd, DATA, LinkData, &sc->filter_objects);
for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
write_scene_collection(wd, nsc);
}
}
static void write_collection_engine_settings(WriteData *wd, ListBase *lb)
{
for (CollectionEngineSettings *ces = lb->first; ces; ces = ces->next) {
writestruct(wd, DATA, CollectionEngineSettings, 1, ces);
for (CollectionEngineProperty *prop = ces->properties.first; prop; prop = prop->next) {
switch (prop->type) {
case COLLECTION_PROP_TYPE_FLOAT:
writestruct(wd, DATA, CollectionEnginePropertyFloat, 1, prop);
break;
case COLLECTION_PROP_TYPE_INT:
writestruct(wd, DATA, CollectionEnginePropertyInt, 1, prop);
break;
default:
; /* error: don't know how to write this file */
}
}
}
}
static void write_layer_collections(WriteData *wd, ListBase *lb)
{
for (LayerCollection *lc = lb->first; lc; lc = lc->next) {
writestruct(wd, DATA, LayerCollection, 1, lc);
writelist(wd, DATA, LinkData, &lc->object_bases);
writelist(wd, DATA, CollectionOverride, &lc->overrides);
write_collection_engine_settings(wd, &lc->engine_settings);
write_layer_collections(wd, &lc->layer_collections);
}
}
static void write_render_engines_settings(WriteData *wd, ListBase *lb)
{
for (RenderEngineSettings *res = lb->first; res; res = res->next) {
writestruct(wd, DATA, RenderEngineSettings, 1, res);
if (STREQ(res->name, RE_engine_id_BLENDER_CLAY)) {
writestruct(wd, DATA, RenderEngineSettingsClay, 1, res->data);
}
else {
/* No engine matched */
/* error: don't know how to write this file */
}
}
}
static void write_scenes(WriteData *wd, ListBase *scebase)
{
Scene *sce;
@@ -2640,6 +2722,7 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
ToolSettings *tos;
FreestyleModuleConfig *fmc;
FreestyleLineSet *fls;
SceneLayer *sl;
sce = scebase->first;
while (sce) {
@@ -2845,6 +2928,16 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
write_previews(wd, sce->preview);
write_curvemapping_curves(wd, &sce->r.mblur_shutter_curve);
write_scene_collection(wd, sce->collection);
for (sl = sce->render_layers.first; sl; sl = sl->next) {
writestruct(wd, DATA, SceneLayer, 1, sl);
writelist(wd, DATA, ObjectBase, &sl->object_bases);
write_layer_collections(wd, &sl->layer_collections);
}
write_render_engines_settings(wd, &sce->engines_settings);
sce = sce->id.next;
}
@@ -3166,6 +3259,9 @@ static void write_screens(WriteData *wd, ListBase *scrbase)
else if (sl->spacetype == SPACE_INFO) {
writestruct(wd, DATA, SpaceInfo, 1, sl);
}
else if (sl->spacetype == SPACE_COLLECTIONS) {
writestruct(wd, DATA, SpaceCollections, 1, sl);
}
sl = sl->next;
}

View File

@@ -57,6 +57,7 @@ extern "C" {
#include "BLI_fileops.h"
#include "BKE_camera.h"
#include "BKE_collection.h"
#include "BKE_main.h"
#include "BKE_lamp.h"
#include "BKE_library.h"
@@ -418,7 +419,7 @@ Object *DocumentImporter::create_instance_node(Object *source_ob, COLLADAFW::Nod
Object *obn = BKE_object_copy(G.main, source_ob);
DAG_id_tag_update(&obn->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
BKE_scene_base_add(sce, obn);
BKE_collection_object_add_from(sce, source_ob, obn);
if (instance_node) {
anim_importer.read_node_transform(instance_node, obn);

View File

@@ -26,37 +26,53 @@
set(INC
.
intern
nodes
operations
engines/clay
../blenkernel
../blenlib
../blentranslation
../imbuf
../depsgraph
../makesdna
../makesrna
../windowmanager
../nodes
../nodes/composite
../nodes/intern
../gpu
../editors/include
../editors/space_view3d
../render/extern/include
../render/intern/include
../../../extern/clew/include
../../../intern/glew-mx
../../../intern/guardedalloc
../../../intern/atomic
)
set(INC_SYS
${GLEW_INCLUDE_PATH}
)
set(SRC
DRW_defines.h
intern/draw_manager.c
intern/draw_mode_pass.c
intern/draw_cache.c
engines/clay/clay.c
intern/DRW_render.h
intern/draw_mode_pass.h
intern/draw_cache.h
engines/clay/clay.h
./DRW_engine.h
)
if(WITH_CLAY_ENGINE)
add_definitions(-DWITH_CLAY_ENGINE)
endif()
data_to_c_simple(engines/clay/shaders/clay_frag.glsl SRC)
data_to_c_simple(engines/clay/shaders/clay_vert.glsl SRC)
data_to_c_simple(engines/clay/shaders/ssao_alchemy.glsl SRC)
data_to_c_simple(engines/clay/shaders/ssao_groundtruth.glsl SRC)
list(APPEND INC
)
endif()
blender_add_lib(bf_draw "${SRC}" "${INC}" "${INC_SYS}")

View File

@@ -0,0 +1,45 @@
/*
* Copyright 2016, Blender Foundation.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Blender Institute
*
*/
/** \file DRW_engine.h
* \ingroup draw
*/
#ifndef __DRW_ENGINE_H__
#define __DRW_ENGINE_H__
//#define WITH_VIEWPORT_CACHE_TEST
struct DRWPass;
struct Material;
struct Scene;
void DRW_engines_init(void);
void DRW_engines_free(void);
/* This is here because GPUViewport needs it */
void DRW_pass_free(struct DRWPass *pass);
/* Settings */
void *DRW_material_settings_get(struct Material *ma, const char *engine_name);
void *DRW_render_settings_get(struct Scene *scene, const char *engine_name);
#endif /* __DRW_ENGINE_H__ */

View File

@@ -0,0 +1,722 @@
/*
* Copyright 2016, Blender Foundation.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Blender Institute
*
*/
#include "DRW_render.h"
#include "BKE_icons.h"
#include "BKE_main.h"
#include "BLI_dynstr.h"
#include "BLI_rand.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
#include "UI_resources.h"
#include "UI_interface_icons.h"
#include "clay.h"
#ifdef WITH_CLAY_ENGINE
/* Shaders */
extern char datatoc_clay_frag_glsl[];
extern char datatoc_clay_vert_glsl[];
extern char datatoc_ssao_alchemy_glsl[];
extern char datatoc_ssao_groundtruth_glsl[];
/* Storage */
/* UBOs data needs to be 16 byte aligned (size of vec4) */
/* Reminder : float, int, bool are 4 bytes */
typedef struct CLAY_UBO_Material {
float ssao_params_var[4];
/* - 16 -*/
float matcap_hsv[3];
float matcap_id; /* even float encoding have enough precision */
/* - 16 -*/
float matcap_rot[2];
float pad[2]; /* ensure 16 bytes alignement */
} CLAY_UBO_Material; /* 48 bytes */
typedef struct CLAY_UBO_Storage {
CLAY_UBO_Material materials[512]; /* 512 = 9 bit material id */
} CLAY_UBO_Storage;
static struct CLAY_data {
/* Depth Pre Pass */
struct GPUShader *depth_sh;
/* Shading Pass */
struct GPUShader *clay_sh;
/* Materials Parameter UBO */
struct GPUUniformBuffer *mat_ubo;
CLAY_UBO_Storage mat_storage;
short ubo_flag;
/* Matcap textures */
struct GPUTexture *matcap_array;
float matcap_colors[24][3];
/* Ssao */
float winmat[4][4];
float viewvecs[3][4];
float ssao_params[4];
struct GPUTexture *jitter_tx;
struct GPUTexture *sampling_tx;
} data = {NULL};
/* CLAY_data.ubo_flag */
enum {
CLAY_UBO_CLEAR = (1 << 0),
CLAY_UBO_REFRESH = (1 << 1),
};
/* keep it under MAX_BUFFERS */
typedef struct CLAY_FramebufferList{
/* default */
struct GPUFrameBuffer *default_fb;
/* engine specific */
struct GPUFrameBuffer *downsample_depth;
} CLAY_FramebufferList;
/* keep it under MAX_TEXTURES */
typedef struct CLAY_TextureList{
/* default */
struct GPUTexture *color;
struct GPUTexture *depth;
/* engine specific */
struct GPUTexture *depth_low;
} CLAY_TextureList;
/* for clarity follow the same layout as CLAY_TextureList */
enum {
SCENE_COLOR,
SCENE_DEPTH,
SCENE_DEPTH_LOW,
};
/* keep it under MAX_PASSES */
typedef struct CLAY_PassList{
/* default */
struct DRWPass *non_meshes_pass;
struct DRWPass *ob_center_pass;
/* engine specific */
struct DRWPass *depth_pass;
struct DRWPass *clay_pass;
struct DRWPass *wire_overlay_pass;
struct DRWPass *wire_outline_pass;
} CLAY_PassList;
//#define GTAO
/* Functions */
static void add_icon_to_rect(PreviewImage *prv, float *final_rect, int layer)
{
int image_size = prv->w[0] * prv->h[0];
float *new_rect = &final_rect[image_size * 4 * layer];
IMB_buffer_float_from_byte(new_rect, (unsigned char *)prv->rect[0], IB_PROFILE_SRGB, IB_PROFILE_SRGB,
false, prv->w[0], prv->h[0], prv->w[0], prv->w[0]);
/* Find overall color */
for (int y = 0; y < 4; ++y) {
for (int x = 0; x < 4; ++x) {
data.matcap_colors[layer][0] += new_rect[y * 512 * 128 * 4 + x * 128 * 4 + 0];
data.matcap_colors[layer][1] += new_rect[y * 512 * 128 * 4 + x * 128 * 4 + 1];
data.matcap_colors[layer][2] += new_rect[y * 512 * 128 * 4 + x * 128 * 4 + 2];
}
}
data.matcap_colors[layer][0] /= 16.0f * 2.0f; /* the * 2 is to darken for shadows */
data.matcap_colors[layer][1] /= 16.0f * 2.0f;
data.matcap_colors[layer][2] /= 16.0f * 2.0f;
}
static struct GPUTexture *load_matcaps(PreviewImage *prv[24], int nbr)
{
struct GPUTexture *tex;
int w = prv[0]->w[0];
int h = prv[0]->h[0];
float *final_rect = MEM_callocN(sizeof(float) * 4 * w * h * nbr, "Clay Matcap array rect");
for (int i = 0; i < nbr; ++i) {
add_icon_to_rect(prv[i], final_rect, i);
BKE_previewimg_free(&prv[i]);
}
tex = DRW_texture_create_2D_array(w, h, nbr, DRW_TEX_RGBA_8, DRW_TEX_FILTER, final_rect);
MEM_freeN(final_rect);
return tex;
}
static int matcap_to_index(int matcap)
{
if (matcap == ICON_MATCAP_02) return 1;
else if (matcap == ICON_MATCAP_03) return 2;
else if (matcap == ICON_MATCAP_04) return 3;
else if (matcap == ICON_MATCAP_05) return 4;
else if (matcap == ICON_MATCAP_06) return 5;
else if (matcap == ICON_MATCAP_07) return 6;
else if (matcap == ICON_MATCAP_08) return 7;
else if (matcap == ICON_MATCAP_09) return 8;
else if (matcap == ICON_MATCAP_10) return 9;
else if (matcap == ICON_MATCAP_11) return 10;
else if (matcap == ICON_MATCAP_12) return 11;
else if (matcap == ICON_MATCAP_13) return 12;
else if (matcap == ICON_MATCAP_14) return 13;
else if (matcap == ICON_MATCAP_15) return 14;
else if (matcap == ICON_MATCAP_16) return 15;
else if (matcap == ICON_MATCAP_17) return 16;
else if (matcap == ICON_MATCAP_18) return 17;
else if (matcap == ICON_MATCAP_19) return 18;
else if (matcap == ICON_MATCAP_20) return 19;
else if (matcap == ICON_MATCAP_21) return 20;
else if (matcap == ICON_MATCAP_22) return 21;
else if (matcap == ICON_MATCAP_23) return 22;
else if (matcap == ICON_MATCAP_24) return 23;
return 0;
}
static struct GPUTexture *create_spiral_sample_texture(int numsaples)
{
struct GPUTexture *tex;
float (*texels)[2] = MEM_mallocN(sizeof(float[2]) * numsaples, "concentric_tex");
const float numsaples_inv = 1.0f / numsaples;
int i;
/* arbitrary number to ensure we don't get conciding samples every circle */
const float spirals = 7.357;
for (i = 0; i < numsaples; i++) {
float r = (i + 0.5f) * numsaples_inv;
float phi = r * spirals * (float)(2.0 * M_PI);
texels[i][0] = r * cosf(phi);
texels[i][1] = r * sinf(phi);
}
tex = DRW_texture_create_1D(numsaples, DRW_TEX_RG_16, 0, (float *)texels);
MEM_freeN(texels);
return tex;
}
static struct GPUTexture *create_jitter_texture(void)
{
float jitter[64 * 64][2];
int i;
/* TODO replace by something more evenly distributed like blue noise */
for (i = 0; i < 64 * 64; i++) {
#ifdef GTAO
jitter[i][0] = BLI_frand();
jitter[i][1] = BLI_frand();
#else
jitter[i][0] = 2.0f * BLI_frand() - 1.0f;
jitter[i][1] = 2.0f * BLI_frand() - 1.0f;
normalize_v2(jitter[i]);
#endif
}
return DRW_texture_create_2D(64, 64, DRW_TEX_RG_16, DRW_TEX_FILTER | DRW_TEX_WRAP, &jitter[0][0]);
}
static void clay_material_settings_init(MaterialEngineSettingsClay *ma)
{
ma->matcap_icon = ICON_MATCAP_01;
ma->matcap_rot = 0.0f;
ma->matcap_hue = 0.5f;
ma->matcap_sat = 0.5f;
ma->matcap_val = 0.5f;
ma->ssao_distance = 0.2;
ma->ssao_attenuation = 1.0f;
ma->ssao_factor_cavity = 1.0f;
ma->ssao_factor_edge = 1.0f;
}
RenderEngineSettings *CLAY_render_settings_create(void)
{
RenderEngineSettingsClay *settings = MEM_callocN(sizeof(RenderEngineSettingsClay), "RenderEngineSettingsClay");
clay_material_settings_init((MaterialEngineSettingsClay *)settings);
settings->ssao_samples = 32;
return (RenderEngineSettings *)settings;
}
MaterialEngineSettings *CLAY_material_settings_create(void)
{
MaterialEngineSettingsClay *settings = MEM_callocN(sizeof(MaterialEngineSettingsClay), "MaterialEngineSettingsClay");
clay_material_settings_init(settings);
return (MaterialEngineSettings *)settings;
}
static void CLAY_engine_init(const bContext *C)
{
Main *bmain = CTX_data_main(C);
/* Create Texture Array */
if (!data.matcap_array) {
PreviewImage *prv[24]; /* For now use all of the 24 internal matcaps */
/* TODO only load used matcaps */
prv[0] = UI_icon_to_preview(ICON_MATCAP_01);
prv[1] = UI_icon_to_preview(ICON_MATCAP_02);
prv[2] = UI_icon_to_preview(ICON_MATCAP_03);
prv[3] = UI_icon_to_preview(ICON_MATCAP_04);
prv[4] = UI_icon_to_preview(ICON_MATCAP_05);
prv[5] = UI_icon_to_preview(ICON_MATCAP_06);
prv[6] = UI_icon_to_preview(ICON_MATCAP_07);
prv[7] = UI_icon_to_preview(ICON_MATCAP_08);
prv[8] = UI_icon_to_preview(ICON_MATCAP_09);
prv[9] = UI_icon_to_preview(ICON_MATCAP_10);
prv[10] = UI_icon_to_preview(ICON_MATCAP_11);
prv[11] = UI_icon_to_preview(ICON_MATCAP_12);
prv[12] = UI_icon_to_preview(ICON_MATCAP_13);
prv[13] = UI_icon_to_preview(ICON_MATCAP_14);
prv[14] = UI_icon_to_preview(ICON_MATCAP_15);
prv[15] = UI_icon_to_preview(ICON_MATCAP_16);
prv[16] = UI_icon_to_preview(ICON_MATCAP_17);
prv[17] = UI_icon_to_preview(ICON_MATCAP_18);
prv[18] = UI_icon_to_preview(ICON_MATCAP_19);
prv[19] = UI_icon_to_preview(ICON_MATCAP_20);
prv[20] = UI_icon_to_preview(ICON_MATCAP_21);
prv[21] = UI_icon_to_preview(ICON_MATCAP_22);
prv[22] = UI_icon_to_preview(ICON_MATCAP_23);
prv[23] = UI_icon_to_preview(ICON_MATCAP_24);
data.matcap_array = load_matcaps(prv, 24);
}
/* AO Jitter */
if (!data.jitter_tx) {
data.jitter_tx = create_jitter_texture();
}
/* AO Samples */
/* TODO use hammersley sequence */
if (!data.sampling_tx) {
data.sampling_tx = create_spiral_sample_texture(500);
}
/* Depth prepass */
if (!data.depth_sh) {
data.depth_sh = DRW_shader_create_3D_depth_only();
}
if (!data.mat_ubo) {
data.mat_ubo = DRW_uniformbuffer_create(sizeof(CLAY_UBO_Storage), NULL);
}
/* Shading pass */
if (!data.clay_sh) {
DynStr *ds = BLI_dynstr_new();
const char *max_mat =
"#define MAX_MATERIAL 512\n"
"#define USE_ROTATION\n"
"#define USE_AO\n"
"#define USE_HSV\n";
char *matcap_with_ao;
BLI_dynstr_append(ds, datatoc_clay_frag_glsl);
#ifdef GTAO
BLI_dynstr_append(ds, datatoc_ssao_groundtruth_glsl);
#else
BLI_dynstr_append(ds, datatoc_ssao_alchemy_glsl);
#endif
matcap_with_ao = BLI_dynstr_get_cstring(ds);
data.clay_sh = DRW_shader_create(datatoc_clay_vert_glsl, NULL, matcap_with_ao, max_mat);
BLI_dynstr_free(ds);
MEM_freeN(matcap_with_ao);
}
/* Cleanup all runtime data loaded from file */
for (Scene *sce = bmain->scene.first; sce; sce = sce->id.next) {
/* Using render settings as material settings */
MaterialEngineSettingsClay *res = DRW_render_settings_get(sce, RE_engine_id_BLENDER_CLAY);
res->flag = CLAY_OUTDATED;
res->ubo_index = -1;
/* Update Collections Materials */
for (SceneLayer *sl = sce->render_layers.first; sl; sl = sl->next) {
for (LayerCollection *lc = sl->layer_collections.first; lc; lc = lc->next) {
CollectionEngineSettings *ces;
ces = BKE_layer_collection_engine_get(lc, RE_engine_id_BLENDER_CLAY);
if (ces) { /* May not exists */
BKE_collection_engine_property_value_set_int(ces, "flag", CLAY_OUTDATED);
BKE_collection_engine_property_value_set_int(ces, "ubo_index", -1);
}
}
}
}
data.ubo_flag |= CLAY_UBO_REFRESH;
}
static void CLAY_ssao_setup(void)
{
float invproj[4][4];
float dfdyfacs[2];
bool is_persp = DRW_viewport_is_persp_get();
/* view vectors for the corners of the view frustum. Can be used to recreate the world space position easily */
float viewvecs[3][4] = {
{-1.0f, -1.0f, -1.0f, 1.0f},
{1.0f, -1.0f, -1.0f, 1.0f},
{-1.0f, 1.0f, -1.0f, 1.0f}
};
int i;
float *size = DRW_viewport_size_get();
RenderEngineSettingsClay *settings = DRW_render_settings_get(NULL, RE_engine_id_BLENDER_CLAY);
DRW_get_dfdy_factors(dfdyfacs);
data.ssao_params[0] = settings->ssao_samples;
data.ssao_params[1] = size[0] / 64.0;
data.ssao_params[2] = size[1] / 64.0;
data.ssao_params[3] = dfdyfacs[1]; /* dfdy sign for offscreen */
/* invert the view matrix */
DRW_viewport_matrix_get(data.winmat, DRW_MAT_WIN);
invert_m4_m4(invproj, data.winmat);
/* convert the view vectors to view space */
for (i = 0; i < 3; i++) {
mul_m4_v4(invproj, viewvecs[i]);
/* normalized trick see http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer */
mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][3]);
if (is_persp)
mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][2]);
viewvecs[i][3] = 1.0;
copy_v4_v4(data.viewvecs[i], viewvecs[i]);
}
/* we need to store the differences */
data.viewvecs[1][0] -= data.viewvecs[0][0];
data.viewvecs[1][1] = data.viewvecs[2][1] - data.viewvecs[0][1];
/* calculate a depth offset as well */
if (!is_persp) {
float vec_far[] = {-1.0f, -1.0f, 1.0f, 1.0f};
mul_m4_v4(invproj, vec_far);
mul_v3_fl(vec_far, 1.0f / vec_far[3]);
data.viewvecs[1][2] = vec_far[2] - data.viewvecs[0][2];
}
}
static DRWShadingGroup *CLAY_shgroup_create(DRWPass *pass, int *UNUSED(material_id))
{
const int depthloc = 0, matcaploc = 1, jitterloc = 2, sampleloc = 3;
//CLAY_UBO_Material *mat = &data.mat_storage.materials[0];
DRWShadingGroup *grp = DRW_shgroup_create(data.clay_sh, pass);
DRW_shgroup_uniform_vec2(grp, "screenres", DRW_viewport_size_get(), 1);
DRW_shgroup_uniform_buffer(grp, "depthtex", SCENE_DEPTH, depthloc);
DRW_shgroup_uniform_texture(grp, "matcaps", data.matcap_array, matcaploc);
DRW_shgroup_uniform_mat4(grp, "WinMatrix", (float *)data.winmat);
DRW_shgroup_uniform_vec4(grp, "viewvecs", (float *)data.viewvecs, 3);
DRW_shgroup_uniform_vec4(grp, "ssao_params", data.ssao_params, 1);
DRW_shgroup_uniform_vec3(grp, "matcaps_color", (float *)data.matcap_colors, 24);
//DRW_shgroup_uniform_int(grp, "material_id", material_id, 1);
#ifndef GTAO
DRW_shgroup_uniform_texture(grp, "ssao_jitter", data.jitter_tx, jitterloc);
DRW_shgroup_uniform_texture(grp, "ssao_samples", data.sampling_tx, sampleloc);
#endif
return grp;
}
static void update_ubo_storage(float matcap_rot, float matcap_hue, float matcap_sat, float matcap_val,
float ssao_distance, float ssao_factor_cavity, float ssao_factor_edge,
float ssao_attenuation, int matcap_icon, unsigned int current_id)
{
CLAY_UBO_Material *ubo = &data.mat_storage.materials[current_id];
ubo->matcap_rot[0] = cosf(matcap_rot * 3.14159f * 2.0f);
ubo->matcap_rot[1] = sinf(matcap_rot * 3.14159f * 2.0f);
ubo->matcap_hsv[0] = matcap_hue + 0.5f;
ubo->matcap_hsv[1] = matcap_sat * 2.0f;
ubo->matcap_hsv[2] = matcap_val * 2.0f;
ubo->ssao_params_var[0] = ssao_distance;
ubo->ssao_params_var[1] = ssao_factor_cavity;
ubo->ssao_params_var[2] = ssao_factor_edge;
ubo->ssao_params_var[3] = ssao_attenuation;
ubo->matcap_id = matcap_to_index(matcap_icon);
}
static void CLAY_update_material_ubo(const struct bContext *C)
{
Main *bmain = CTX_data_main(C);
/* Update Default materials */
for (Scene *sce = bmain->scene.first; sce; sce = sce->id.next) {
/* Using render settings as material settings */
MaterialEngineSettingsClay *res = DRW_render_settings_get(sce, RE_engine_id_BLENDER_CLAY);
if (res->flag & CLAY_OUTDATED)
data.ubo_flag |= CLAY_UBO_REFRESH;
if (res->matcap_icon < ICON_MATCAP_01 ||
res->matcap_icon > ICON_MATCAP_24)
{
res->matcap_icon = ICON_MATCAP_01;
}
res->flag &= ~CLAY_OUTDATED;
/* Update Collections Materials */
for (SceneLayer *sl = sce->render_layers.first; sl; sl = sl->next) {
for (LayerCollection *lc = sl->layer_collections.first; lc; lc = lc->next) {
CollectionEngineSettings *ces;
ces = BKE_layer_collection_engine_get(lc, RE_engine_id_BLENDER_CLAY);
BKE_collection_engine_property_value_set_int(ces, "flag", 0);
BKE_collection_engine_property_value_set_int(ces, "ubo_index", 0);
}
}
}
if (data.ubo_flag & CLAY_UBO_REFRESH) {
int current_id = 0;
/* Default materials */
for (Scene *sce = bmain->scene.first; sce; sce = sce->id.next) {
MaterialEngineSettingsClay *res = DRW_render_settings_get(sce, RE_engine_id_BLENDER_CLAY);
update_ubo_storage(res->matcap_rot, res->matcap_hue, res->matcap_sat, res->matcap_val,
res->ssao_distance, res->ssao_factor_cavity, res->ssao_factor_edge,
res->ssao_attenuation, res->matcap_icon, current_id);
current_id++;
for (SceneLayer *sl = sce->render_layers.first; sl; sl = sl->next) {
for (LayerCollection *lc = sl->layer_collections.first; lc; lc = lc->next) {
/* TODO */
current_id++;
}
}
current_id++;
}
DRW_uniformbuffer_update(data.mat_ubo, &data.mat_storage);
}
data.ubo_flag = 0;
}
static void CLAY_create_cache(CLAY_PassList *passes, const struct bContext *C)
{
SceneLayer *sl = CTX_data_scene_layer(C);
DRWShadingGroup *default_shgrp, *depthbatch;
/* Depth Pass */
{
passes->depth_pass = DRW_pass_create("Depth Pass", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
depthbatch = DRW_shgroup_create(data.depth_sh, passes->depth_pass);
}
/* Clay Pass */
{
MaterialEngineSettingsClay *settings = DRW_render_settings_get(NULL, RE_engine_id_BLENDER_CLAY);
passes->clay_pass = DRW_pass_create("Clay Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
default_shgrp = CLAY_shgroup_create(passes->clay_pass, &settings->ubo_index);
DRW_shgroup_uniform_block(default_shgrp, "material_block", data.mat_ubo, 0);
}
/* Object Mode */
{
DRW_pass_setup_common(&passes->wire_overlay_pass,
&passes->wire_outline_pass,
&passes->non_meshes_pass,
&passes->ob_center_pass);
}
/* TODO Create hash table of batch based on material id*/
Object *ob;
DEG_OBJECT_ITER(sl, ob)
{
if ((ob->base_flag & BASE_VISIBLED) == 0) {
continue;
}
struct Batch *geom;
//bool do_outlines;
switch (ob->type) {
case OB_MESH:
geom = DRW_cache_surface_get(ob);
/* Add everything for now */
DRW_shgroup_call_add(depthbatch, geom, ob->obmat);
DRW_shgroup_call_add(default_shgrp, geom, ob->obmat);
//DRW_shgroup_wire_overlay(passes->wire_overlay_pass, ob);
//do_outlines = ((ob->base_flag & BASE_SELECTED) != 0);
//DRW_shgroup_wire_outline(passes->wire_outline_pass, ob, false, false, do_outlines);
/* When encountering a new material :
* - Create new Batch
* - Initialize Batch
* - Push it to the hash table
* - The pass takes care of inserting it
* next to the same shader calls */
/* Free hash table */
break;
case OB_LAMP:
case OB_CAMERA:
case OB_EMPTY:
default:
DRW_shgroup_non_meshes(passes->non_meshes_pass, ob);
break;
}
DRW_shgroup_object_center(passes->ob_center_pass, ob);
DRW_shgroup_relationship_lines(passes->non_meshes_pass, ob);
}
DEG_OBJECT_ITER_END
}
static void CLAY_view_draw(RenderEngine *UNUSED(engine), const bContext *context)
{
/* This function may run for multiple viewports
* so get the current viewport buffers */
CLAY_FramebufferList *buffers = NULL;
CLAY_TextureList *textures = NULL;
CLAY_PassList *passes = NULL;
DRW_viewport_init(context, (void **)&buffers, (void **)&textures, (void **)&passes);
CLAY_engine_init(context);
CLAY_update_material_ubo(context);
/* TODO : tag to refresh by the deps graph */
/* ideally only refresh when objects are added/removed */
/* or render properties / materials change */
#ifdef WITH_VIEWPORT_CACHE_TEST
static bool once = false;
#endif
if (DRW_viewport_cache_is_dirty()
#ifdef WITH_VIEWPORT_CACHE_TEST
&& !once
#endif
) {
#ifdef WITH_VIEWPORT_CACHE_TEST
once = true;
#endif
CLAY_create_cache(passes, context);
}
/* Start Drawing */
DRW_draw_background();
/* Pass 1 : Depth pre-pass */
DRW_draw_pass(passes->depth_pass);
/* Pass 2 (Optionnal) : Separated Downsampled AO */
DRW_framebuffer_texture_detach(textures->depth);
/* TODO */
/* Pass 3 : Shading */
CLAY_ssao_setup();
DRW_draw_pass(passes->clay_pass);
/* Pass 4 : Overlays */
DRW_framebuffer_texture_attach(buffers->default_fb, textures->depth, 0);
//DRW_draw_pass(passes->wire_overlay_pass);
//DRW_draw_pass(passes->wire_outline_pass);
DRW_draw_pass(passes->non_meshes_pass);
DRW_draw_pass(passes->ob_center_pass);
/* Always finish by this */
DRW_state_reset();
}
static void CLAY_collection_settings_create(RenderEngine *UNUSED(engine), CollectionEngineSettings *ces)
{
BLI_assert(ces);
BKE_collection_engine_property_add_int(ces, "matcap_icon", ICON_MATCAP_01);
BKE_collection_engine_property_add_int(ces, "type", CLAY_MATCAP_NONE);
BKE_collection_engine_property_add_float(ces, "matcap_rotation", 0.0f);
BKE_collection_engine_property_add_float(ces, "matcap_hue", 0.5f);
BKE_collection_engine_property_add_float(ces, "matcap_saturation", 0.5f);
BKE_collection_engine_property_add_float(ces, "matcap_value", 0.5f);
BKE_collection_engine_property_add_float(ces, "ssao_distance", 0.2f);
BKE_collection_engine_property_add_float(ces, "ssao_attenuation", 1.0f);
BKE_collection_engine_property_add_float(ces, "ssao_factor_cavity", 1.0f);
BKE_collection_engine_property_add_float(ces, "ssao_factor_edge", 1.0f);
/* Runtime data (not display in settings) */
BKE_collection_engine_property_add_int(ces, "ubo_index", -1);
BKE_collection_engine_property_add_int(ces, "flag", CLAY_OUTDATED);
}
void clay_engine_free(void)
{
/* data.depth_sh Is builtin so it's automaticaly freed */
if (data.clay_sh) {
DRW_shader_free(data.clay_sh);
}
if (data.matcap_array) {
DRW_texture_free(data.matcap_array);
}
if (data.jitter_tx) {
DRW_texture_free(data.jitter_tx);
}
if (data.sampling_tx) {
DRW_texture_free(data.sampling_tx);
}
if (data.mat_ubo) {
DRW_uniformbuffer_free(data.mat_ubo);
}
}
RenderEngineType viewport_clay_type = {
NULL, NULL,
"BLENDER_CLAY", N_("Clay"), RE_INTERNAL | RE_USE_OGL_PIPELINE,
NULL, NULL, NULL, NULL, &CLAY_view_draw, NULL, &CLAY_collection_settings_create,
{NULL, NULL, NULL}
};
#endif

View File

@@ -19,7 +19,18 @@
*
*/
#ifndef __DRW_DEFINES_H__
#define __DRW_DEFINES_H__
/** \file clay.h
* \ingroup DNA
*/
#endif /* __DRW_DEFINES_H__ */
#ifndef __ENGINE_CLAY_H__
#define __ENGINE_CLAY_H__
extern RenderEngineType viewport_clay_type;
struct RenderEngineSettings *CLAY_render_settings_create(void);
struct MaterialEngineSettings *CLAY_material_settings_create(void);
void clay_engine_free(void);
#endif /* __ENGINE_CLAY_H__ */

View File

@@ -0,0 +1,207 @@
uniform vec2 screenres;
uniform sampler2D depthtex;
uniform mat4 WinMatrix;
/* Matcap */
uniform sampler2DArray matcaps;
uniform vec3 matcaps_color[24];
/* Screen Space Occlusion */
/* store the view space vectors for the corners of the view frustum here.
* It helps to quickly reconstruct view space vectors by using uv coordinates,
* see http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer */
uniform vec4 viewvecs[3];
uniform vec4 ssao_params;
uniform sampler2D ssao_jitter;
uniform sampler1D ssao_samples;
/* Material Parameters packed in an UBO */
struct Material {
vec4 ssao_params_var;
vec4 matcap_hsv_id;
vec4 matcap_rot; /* vec4 to ensure 16 bytes alignement (don't trust compiler) */
};
layout(std140) uniform material_block {
Material matcaps_param[MAX_MATERIAL];
};
int mat_id;
/* Aliases */
#define ssao_samples_num ssao_params.x
#define jitter_tilling ssao_params.yz
#define dfdy_sign ssao_params.w
#define matcap_hsv matcaps_param[mat_id].matcap_hsv_id.xyz
#define matcap_index matcaps_param[mat_id].matcap_hsv_id.w
#define matcap_rotation matcaps_param[mat_id].matcap_rot.xy
in vec3 normal;
out vec4 fragColor;
/* TODO Move this to SSAO modules */
/* simple depth reconstruction, see http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer
* we change the factors from the article to fit the OpennGL model. */
vec3 get_view_space_from_depth(in vec2 uvcoords, in float depth)
{
if (WinMatrix[3][3] == 0.0) {
/* Perspective */
float d = 2.0 * depth - 1.0;
float zview = -WinMatrix[3][2] / (d + WinMatrix[2][2]);
return zview * (viewvecs[0].xyz + vec3(uvcoords, 0.0) * viewvecs[1].xyz);
}
else {
/* Orthographic */
vec3 offset = vec3(uvcoords, depth);
return viewvecs[0].xyz + offset * viewvecs[1].xyz;
}
}
/* TODO remove this when switching to geometric normals */
vec3 calculate_view_space_normal(in vec3 viewposition)
{
vec3 normal = cross(normalize(dFdx(viewposition)), dfdy_sign * normalize(dFdy(viewposition)));
return normalize(normal);
}
#ifdef USE_HSV
void rgb_to_hsv(vec3 rgb, out vec3 outcol)
{
float cmax, cmin, h, s, v, cdelta;
vec3 c;
cmax = max(rgb[0], max(rgb[1], rgb[2]));
cmin = min(rgb[0], min(rgb[1], rgb[2]));
cdelta = cmax - cmin;
v = cmax;
if (cmax != 0.0)
s = cdelta / cmax;
else {
s = 0.0;
h = 0.0;
}
if (s == 0.0) {
h = 0.0;
}
else {
c = (vec3(cmax, cmax, cmax) - rgb.xyz) / cdelta;
if (rgb.x == cmax) h = c[2] - c[1];
else if (rgb.y == cmax) h = 2.0 + c[0] - c[2];
else h = 4.0 + c[1] - c[0];
h /= 6.0;
if (h < 0.0)
h += 1.0;
}
outcol = vec3(h, s, v);
}
void hsv_to_rgb(vec3 hsv, out vec3 outcol)
{
float i, f, p, q, t, h, s, v;
vec3 rgb;
h = hsv[0];
s = hsv[1];
v = hsv[2];
if (s == 0.0) {
rgb = vec3(v, v, v);
}
else {
if (h == 1.0)
h = 0.0;
h *= 6.0;
i = floor(h);
f = h - i;
rgb = vec3(f, f, f);
p = v * (1.0 - s);
q = v * (1.0 - (s * f));
t = v * (1.0 - (s * (1.0 - f)));
if (i == 0.0) rgb = vec3(v, t, p);
else if (i == 1.0) rgb = vec3(q, v, p);
else if (i == 2.0) rgb = vec3(p, v, t);
else if (i == 3.0) rgb = vec3(p, q, v);
else if (i == 4.0) rgb = vec3(t, p, v);
else rgb = vec3(v, p, q);
}
outcol = rgb;
}
void hue_sat(float hue, float sat, float value, inout vec3 col)
{
vec3 hsv;
rgb_to_hsv(col, hsv);
hsv.x += hue;
hsv.x -= floor(hsv.x);
hsv.y *= sat;
hsv.y = clamp(hsv.y, 0.0, 1.0);
hsv.z *= value;
hsv.z = clamp(hsv.z, 0.0, 1.0);
hsv_to_rgb(hsv, col);
}
#endif
#ifdef USE_AO
/* Prototype */
void ssao_factors(in float depth, in vec3 normal, in vec3 position, in vec2 screenco, out float cavities, out float edges);
#endif
void main() {
vec2 screenco = vec2(gl_FragCoord.xy) / screenres;
float depth = texture(depthtex, screenco).r;
vec3 position = get_view_space_from_depth(screenco, depth);
vec3 normal = calculate_view_space_normal(position);
//mat_id = int(screenco.x*3.0);
/* Manual Depth test */
/* Doing this test earlier gives problem with dfdx calculations
* TODO move this before when we have proper geometric normals */
if (gl_FragCoord.z > depth + 1e-5)
discard;
#ifdef USE_ROTATION
/* Rotate texture coordinates */
vec2 rotY = vec2(-matcap_rotation.y, matcap_rotation.x);
vec2 texco = abs(vec2(dot(normal.xy, matcap_rotation), dot(normal.xy, rotY)) * .49 + 0.5);
#else
vec2 texco = abs(normal.xy * .49 + 0.5);
#endif
vec3 col = texture(matcaps, vec3(texco, matcap_index)).rgb;
#ifdef USE_AO
float cavity, edges;
ssao_factors(depth, normal, position, screenco, cavity, edges);
col *= mix(vec3(1.0), matcaps_color[int(matcap_index)], cavity);
#endif
#ifdef USE_HSV
hue_sat(matcap_hsv.x, matcap_hsv.y, matcap_hsv.z, col);
#endif
#ifdef USE_AO
/* Apply highlights after hue shift */
col *= edges + 1.0;
#endif
fragColor = vec4(col, 1.0);
}

View File

@@ -0,0 +1,20 @@
uniform mat4 ModelViewProjectionMatrix;
uniform mat3 NormalMatrix;
#if __VERSION__ == 120
attribute vec3 pos;
attribute vec3 nor;
varying vec3 normal;
#else
in vec3 pos;
in vec3 nor;
out vec3 normal;
#endif
void main()
{
normal = normalize(NormalMatrix * nor);
gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
}

View File

@@ -0,0 +1,73 @@
#define ssao_distance matcaps_param[mat_id].ssao_params_var.x
#define ssao_factor_cavity matcaps_param[mat_id].ssao_params_var.y
#define ssao_factor_edge matcaps_param[mat_id].ssao_params_var.z
#define ssao_attenuation matcaps_param[mat_id].ssao_params_var.w
/* from The Alchemy screen-space ambient obscurance algorithm
* http://graphics.cs.williams.edu/papers/AlchemyHPG11/VV11AlchemyAO.pdf */
void ssao_factors(in float depth, in vec3 normal, in vec3 position, in vec2 screenco, out float cavities, out float edges)
{
/* take the normalized ray direction here */
vec2 rotX = texture2D(ssao_jitter, screenco.xy * jitter_tilling).rg;
vec2 rotY = vec2(-rotX.y, rotX.x);
/* find the offset in screen space by multiplying a point
* in camera space at the depth of the point by the projection matrix. */
vec2 offset;
float homcoord = WinMatrix[2][3] * position.z + WinMatrix[3][3];
offset.x = WinMatrix[0][0] * ssao_distance / homcoord;
offset.y = WinMatrix[1][1] * ssao_distance / homcoord;
/* convert from -1.0...1.0 range to 0.0..1.0 for easy use with texture coordinates */
offset *= 0.5;
cavities = edges = 0.0;
int x;
int num_samples = int(ssao_samples_num);
for (x = 0; x < num_samples; x++) {
/* TODO : optimisation replace by constant */
vec2 dir_sample = texture1D(ssao_samples, (float(x) + 0.5) / ssao_samples_num).rg;
/* rotate with random direction to get jittered result */
vec2 dir_jittered = vec2(dot(dir_sample, rotX), dot(dir_sample, rotY));
vec2 uvcoords = screenco.xy + dir_jittered * offset;
if (uvcoords.x > 1.0 || uvcoords.x < 0.0 || uvcoords.y > 1.0 || uvcoords.y < 0.0)
continue;
float depth_new = texture2D(depthtex, uvcoords).r;
/* Handle Background case */
bool is_background = (depth_new == 1.0);
/* This trick provide good edge effect even if no neighboor is found. */
vec3 pos_new = get_view_space_from_depth(uvcoords, (is_background) ? depth : depth_new);
if (is_background)
pos_new.z -= ssao_distance;
vec3 dir = pos_new - position;
float len = length(dir);
float f_cavities = dot(dir, normal);
float f_edge = -f_cavities;
float f_bias = 0.05 * len + 0.0001;
float attenuation = 1.0 / (len * (1.0 + len * len * ssao_attenuation));
/* use minor bias here to avoid self shadowing */
if (f_cavities > -f_bias)
cavities += f_cavities * attenuation;
if (f_edge > f_bias)
edges += f_edge * attenuation;
}
cavities /= ssao_samples_num;
edges /= ssao_samples_num;
/* don't let cavity wash out the surface appearance */
cavities = clamp(cavities * ssao_factor_cavity, 0.0, 1.0);
edges = edges * ssao_factor_edge;
}

View File

@@ -0,0 +1,120 @@
#define ssao_distance matcaps_param[mat_id].ssao_params_var.x
#define ssao_factor_cavity matcaps_param[mat_id].ssao_params_var.y
#define ssao_factor_edge matcaps_param[mat_id].ssao_params_var.z
#define ssao_attenuation matcaps_param[mat_id].ssao_params_var.w
/* Based on Practical Realtime Strategies for Accurate Indirect Occlusion
* http://blog.selfshadow.com/publications/s2016-shading-course/activision/s2016_pbs_activision_occlusion.pdf
* http://blog.selfshadow.com/publications/s2016-shading-course/activision/s2016_pbs_activision_occlusion.pptx */
#define COSINE_WEIGHTING
float integrate_arc(in float h1, in float h2, in float gamma, in float n_proj_len)
{
float a = 0.0;
#ifdef COSINE_WEIGHTING
float cos_gamma = cos(gamma);
float sin_gamma_2 = 2.0 * sin(gamma);
a += -cos(2.0 * h1 - gamma) + cos_gamma + h1 * sin_gamma_2;
a += -cos(2.0 * h2 - gamma) + cos_gamma + h2 * sin_gamma_2;
a *= 0.25; /* 1/4 */
a *= n_proj_len;
#else
/* Uniform weighting (slide 59) */
a += 1 - cos(h1);
a += 1 - cos(h2);
#endif
return a;
}
float get_max_horizon(in vec2 co, in vec3 x, in vec3 omega_o, in float h)
{
if (co.x > 1.0 || co.x < 0.0 || co.y > 1.0 || co.y < 0.0)
return h;
float depth = texture2D(depthtex, co).r;
/* Background case */
if (depth == 1.0)
return h;
vec3 s = get_view_space_from_depth(co, depth); /* s View coordinate */
vec3 omega_s = s - x;
float len = length(omega_s);
if (len < ssao_distance) {
omega_s /= len;
h = max(h, dot(omega_s, omega_o));
}
return h;
}
void ssao_factors(in float depth, in vec3 normal, in vec3 position, in vec2 screenco, out float cavities, out float edges)
{
/* Renaming */
vec3 omega_o = -normalize(position); /* viewvec */
vec2 x_ = screenco; /* x^ Screen coordinate */
vec3 x = position; /* x view space coordinate */
#ifdef SPATIAL_DENOISE
float noise_dir = (1.0 / 16.0) * float(((int(gl_FragCoord.x + gl_FragCoord.y) & 0x3) << 2) + (int(gl_FragCoord.x) & 0x3));
float noise_offset = (1.0 / 4.0) * float(int(gl_FragCoord.y - gl_FragCoord.x) & 0x3);
#else
float noise_dir = (1.0 / 16.0) * float(((int(gl_FragCoord.x + gl_FragCoord.y) & 0x3) << 2) + (int(gl_FragCoord.x) & 0x3));
float noise_offset = (0.5 / 16.0) + (1.0 / 16.0) * float(((int(gl_FragCoord.x - gl_FragCoord.y) & 0x3) << 2) + (int(gl_FragCoord.x) & 0x3));
#endif
const float phi_step = 16.0;
const float theta_step = 16.0;
const float m_pi = 3.14159265358979323846;
vec2 pixel_ratio = vec2(screenres.y / screenres.x, 1.0);
vec2 pixel_size = vec2(1.0) / screenres.xy;
float min_stride = length(pixel_size);
float homcco = WinMatrix[2][3] * position.z + WinMatrix[3][3];
float n = max(min_stride * theta_step, ssao_distance / homcco); /* Search distance */
/* Integral over PI */
float A = 0.0;
for (float i = 0.0; i < phi_step; i++) {
float phi = m_pi * ((noise_dir + i) / phi_step);
vec2 t_phi = vec2(cos(phi), sin(phi)); /* Screen space direction */
/* Search maximum horizon angles Theta1 and Theta2 */
float theta1 = -1.0, theta2 = -1.0; /* init at cos(pi) */
for (float j = 0.0; j < theta_step; j++) {
vec2 s_ = t_phi * pixel_ratio * n * ((j + noise_offset)/ theta_step); /* s^ Screen coordinate */
vec2 co;
co = x_ + s_;
theta1 = get_max_horizon(co, x, omega_o, theta1);
co = x_ - s_;
theta2 = get_max_horizon(co, x, omega_o, theta2);
}
/* (Slide 54) */
theta1 = -acos(theta1);
theta2 = acos(theta2);
/* Projecting Normal to Plane P defined by t_phi and omega_o */
vec3 h = normalize(cross(vec3(t_phi, 0.0), omega_o)); /* Normal vector to Integration plane */
vec3 t = cross(h, omega_o); /* Normal vector to plane */
vec3 n_proj = normal - h * dot(normal, h);
float n_proj_len = length(n_proj);
vec3 n_proj_norm = normalize(n_proj);
/* Clamping thetas (slide 58) */
float gamma = sign(dot(n_proj_norm, t)) * acos(dot(normal, omega_o)); /* Angle between view vec and normal */
theta1 = gamma + max(theta1 - gamma, -m_pi * 0.5);
theta2 = gamma + min(theta2 - gamma, m_pi * 0.5);
/* Solving inner integral */
A += integrate_arc(theta1, theta2, gamma, n_proj_len);
}
A /= phi_step;
cavities = 1.0 - A;
edges = 0.0;
}

View File

@@ -0,0 +1,221 @@
/*
* Copyright 2016, Blender Foundation.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Blender Institute
*
*/
/** \file DRW_render.h
* \ingroup draw
*/
/* This is the Render Functions used by Realtime engines to draw with OpenGL */
#ifndef __DRW_RENDER_H__
#define __DRW_RENDER_H__
#include "BKE_context.h"
#include "BKE_layer.h"
#include "BKE_scene.h"
#include "BLI_listbase.h"
#include "BLI_math_matrix.h"
#include "BLI_math_vector.h"
#include "BLI_string.h"
#include "BLT_translation.h"
#include "DNA_object_types.h"
#include "DNA_lamp_types.h"
#include "DNA_material_types.h"
#include "DNA_scene_types.h"
#include "draw_mode_pass.h"
#include "draw_cache.h"
#include "MEM_guardedalloc.h"
#include "RE_engine.h"
//#define WITH_VIEWPORT_CACHE_TEST
struct GPUFrameBuffer;
struct GPUShader;
struct GPUTexture;
struct GPUUniformBuffer;
struct Object;
struct Batch;
typedef struct DRWUniform DRWUniform;
typedef struct DRWInterface DRWInterface;
typedef struct DRWPass DRWPass;
typedef struct DRWShadingGroup DRWShadingGroup;
/* Textures */
typedef enum {
DRW_TEX_RGBA_8,
DRW_TEX_RGBA_16,
DRW_TEX_RGBA_32,
DRW_TEX_RGB_8,
DRW_TEX_RGB_16,
DRW_TEX_RGB_32,
DRW_TEX_RG_8,
DRW_TEX_RG_16,
DRW_TEX_RG_32,
DRW_TEX_R_8,
DRW_TEX_R_16,
DRW_TEX_R_32,
DRW_TEX_DEPTH_16,
DRW_TEX_DEPTH_24,
DRW_TEX_DEPTH_32,
} DRWTextureFormat;
typedef enum {
DRW_TEX_FILTER = (1 << 0),
DRW_TEX_WRAP = (1 << 1),
DRW_TEX_COMPARE = (1 << 2),
} DRWTextureFlag;
struct GPUTexture *DRW_texture_create_1D(
int w, DRWTextureFormat format, DRWTextureFlag flags, const float *fpixels);
struct GPUTexture *DRW_texture_create_2D(
int w, int h, DRWTextureFormat format, DRWTextureFlag flags, const float *fpixels);
struct GPUTexture *DRW_texture_create_2D_array(
int w, int h, int d, DRWTextureFormat UNUSED(format), DRWTextureFlag flags, const float *fpixels);
void DRW_texture_free(struct GPUTexture *tex);
/* UBOs */
struct GPUUniformBuffer *DRW_uniformbuffer_create(int size, const void *data);
void DRW_uniformbuffer_update(struct GPUUniformBuffer *ubo, const void *data);
void DRW_uniformbuffer_free(struct GPUUniformBuffer *ubo);
/* Buffers */
/* DRWFboTexture->format */
#define DRW_BUF_DEPTH_16 1
#define DRW_BUF_DEPTH_24 2
#define DRW_BUF_R_8 3
#define DRW_BUF_R_16 4
#define DRW_BUF_R_32 5
#define DRW_BUF_RG_8 6
#define DRW_BUF_RG_16 7
#define DRW_BUF_RG_32 8
#define DRW_BUF_RGB_8 9
#define DRW_BUF_RGB_16 10
#define DRW_BUF_RGB_32 11
#define DRW_BUF_RGBA_8 12
#define DRW_BUF_RGBA_16 13
#define DRW_BUF_RGBA_32 14
#define MAX_FBO_TEX 5
typedef struct DRWFboTexture {
struct GPUTexture **tex;
int format;
} DRWFboTexture;
void DRW_framebuffer_init(struct GPUFrameBuffer **fb, int width, int height, DRWFboTexture textures[MAX_FBO_TEX], int texnbr);
void DRW_framebuffer_bind(struct GPUFrameBuffer *fb);
void DRW_framebuffer_texture_attach(struct GPUFrameBuffer *fb, struct GPUTexture *tex, int slot);
void DRW_framebuffer_texture_detach(struct GPUTexture *tex);
/* Shaders */
struct GPUShader *DRW_shader_create(const char *vert, const char *geom, const char *frag, const char *defines);
struct GPUShader *DRW_shader_create_2D(const char *frag, const char *defines);
struct GPUShader *DRW_shader_create_3D(const char *frag, const char *defines);
struct GPUShader *DRW_shader_create_3D_depth_only(void);
void DRW_shader_free(struct GPUShader *shader);
/* Batches */
typedef enum {
DRW_STATE_WRITE_DEPTH = (1 << 0),
DRW_STATE_WRITE_COLOR = (1 << 1),
DRW_STATE_DEPTH_LESS = (1 << 2),
DRW_STATE_DEPTH_EQUAL = (1 << 3),
DRW_STATE_CULL_BACK = (1 << 4),
DRW_STATE_CULL_FRONT = (1 << 5),
DRW_STATE_WIRE = (1 << 6),
DRW_STATE_WIRE_LARGE = (1 << 7),
DRW_STATE_POINT = (1 << 8),
DRW_STATE_STIPPLE_2 = (1 << 9),
DRW_STATE_STIPPLE_3 = (1 << 10),
DRW_STATE_STIPPLE_4 = (1 << 11),
DRW_STATE_BLEND = (1 << 12),
} DRWState;
/* Used by DRWShadingGroup.dyntype */
#define DRW_DYN_POINTS 1
#define DRW_DYN_LINES 2
#define DRW_DYN_INSTANCE 3
DRWShadingGroup *DRW_shgroup_create(struct GPUShader *shader, DRWPass *pass);
void DRW_shgroup_free(struct DRWShadingGroup *shgroup);
void DRW_shgroup_call_add(DRWShadingGroup *shgroup, struct Batch *geom, float (*obmat)[4]);
void DRW_shgroup_state_set(DRWShadingGroup *shgroup, DRWState state);
void DRW_shgroup_dyntype_set(DRWShadingGroup *shgroup, int type);
void DRW_shgroup_uniform_texture(DRWShadingGroup *shgroup, const char *name, const struct GPUTexture *tex, int loc);
void DRW_shgroup_uniform_block(DRWShadingGroup *shgroup, const char *name, const struct GPUUniformBuffer *ubo, int loc);
void DRW_shgroup_uniform_buffer(DRWShadingGroup *shgroup, const char *name, const int value, int loc);
void DRW_shgroup_uniform_bool(DRWShadingGroup *shgroup, const char *name, const bool *value, int arraysize);
void DRW_shgroup_uniform_float(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize);
void DRW_shgroup_uniform_vec2(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize);
void DRW_shgroup_uniform_vec3(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize);
void DRW_shgroup_uniform_vec4(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize);
void DRW_shgroup_uniform_int(DRWShadingGroup *shgroup, const char *name, const int *value, int arraysize);
void DRW_shgroup_uniform_ivec2(DRWShadingGroup *shgroup, const char *name, const int *value, int arraysize);
void DRW_shgroup_uniform_ivec3(DRWShadingGroup *shgroup, const char *name, const int *value, int arraysize);
void DRW_shgroup_uniform_mat3(DRWShadingGroup *shgroup, const char *name, const float *value);
void DRW_shgroup_uniform_mat4(DRWShadingGroup *shgroup, const char *name, const float *value);
/* Passes */
DRWPass *DRW_pass_create(const char *name, DRWState state);
DRWShadingGroup *DRW_pass_nth_shgroup_get(DRWPass *pass, int n);
/* Viewport */
typedef enum {
DRW_MAT_PERS,
DRW_MAT_WIEW,
DRW_MAT_WIN,
} DRWViewportMatrixType;
void DRW_viewport_init(const bContext *C, void **buffers, void **textures, void **passes);
void DRW_viewport_matrix_get(float mat[4][4], DRWViewportMatrixType type);
float *DRW_viewport_size_get(void);
float *DRW_viewport_screenvecs_get(void);
float *DRW_viewport_pixelsize_get(void);
bool DRW_viewport_is_persp_get(void);
bool DRW_viewport_cache_is_dirty(void);
/* Settings */
#ifndef __DRW_ENGINE_H__
void *DRW_material_settings_get(Material *ma, const char *engine_name);
void *DRW_render_settings_get(Scene *scene, const char *engine_name);
#endif /* __DRW_ENGINE_H__ */
/* Draw commands */
void DRW_draw_background(void);
void DRW_centercircle(const float co[3]);
void DRW_draw_pass(DRWPass *pass);
void DRW_state_reset(void);
/* Other */
void DRW_get_dfdy_factors(float dfdyfac[2]);
#endif /* __DRW_RENDER_H__ */

View File

@@ -0,0 +1,543 @@
/*
* Copyright 2016, Blender Foundation.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Blender Institute
*
*/
/** \file draw_cache.c
* \ingroup draw
*/
#include "DNA_scene_types.h"
#include "DNA_mesh_types.h"
#include "DNA_object_types.h"
#include "BLI_utildefines.h"
#include "BLI_math.h"
#include "BKE_mesh_render.h"
#include "GPU_batch.h"
#include "draw_cache.h"
static struct DRWShapeCache{
Batch *drw_single_vertice;
Batch *drw_fullscreen_quad;
Batch *drw_plain_axes;
Batch *drw_single_arrow;
Batch *drw_single_arrow_line;
Batch *drw_cube;
Batch *drw_circle;
Batch *drw_empty_sphere;
Batch *drw_empty_cone;
Batch *drw_arrows;
Batch *drw_lamp;
Batch *drw_lamp_sunrays;
} SHC = {NULL};
void DRW_shape_cache_free(void)
{
if (SHC.drw_single_vertice)
Batch_discard_all(SHC.drw_single_vertice);
if (SHC.drw_fullscreen_quad)
Batch_discard_all(SHC.drw_fullscreen_quad);
if (SHC.drw_plain_axes)
Batch_discard_all(SHC.drw_plain_axes);
if (SHC.drw_single_arrow)
Batch_discard_all(SHC.drw_single_arrow);
if (SHC.drw_single_arrow_line)
Batch_discard_all(SHC.drw_single_arrow_line);
if (SHC.drw_cube)
Batch_discard_all(SHC.drw_cube);
if (SHC.drw_circle)
Batch_discard_all(SHC.drw_circle);
if (SHC.drw_empty_sphere)
Batch_discard_all(SHC.drw_empty_sphere);
if (SHC.drw_empty_cone)
Batch_discard_all(SHC.drw_empty_cone);
if (SHC.drw_arrows)
Batch_discard_all(SHC.drw_arrows);
if (SHC.drw_lamp)
Batch_discard_all(SHC.drw_lamp);
if (SHC.drw_lamp_sunrays)
Batch_discard_all(SHC.drw_lamp_sunrays);
}
/* Quads */
Batch *DRW_cache_fullscreen_quad_get(void)
{
if (!SHC.drw_fullscreen_quad) {
float v1[2] = {-1.0f, -1.0f};
float v2[2] = { 1.0f, -1.0f};
float v3[2] = {-1.0f, 1.0f};
float v4[2] = { 1.0f, 1.0f};
/* Position Only 3D format */
static VertexFormat format = { 0 };
static unsigned pos_id;
if (format.attrib_ct == 0) {
pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
}
VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
VertexBuffer_allocate_data(vbo, 6);
setAttrib(vbo, pos_id, 0, v1);
setAttrib(vbo, pos_id, 1, v2);
setAttrib(vbo, pos_id, 2, v3);
setAttrib(vbo, pos_id, 3, v2);
setAttrib(vbo, pos_id, 4, v3);
setAttrib(vbo, pos_id, 5, v4);
SHC.drw_fullscreen_quad = Batch_create(GL_TRIANGLES, vbo, NULL);
}
return SHC.drw_fullscreen_quad;
}
/* Common */
Batch *DRW_cache_cube_get(void)
{
if (!SHC.drw_cube) {
const GLfloat verts[8][3] = {
{-1.0f, -1.0f, -1.0f},
{-1.0f, -1.0f, 1.0f},
{-1.0f, 1.0f, -1.0f},
{-1.0f, 1.0f, 1.0f},
{ 1.0f, -1.0f, -1.0f},
{ 1.0f, -1.0f, 1.0f},
{ 1.0f, 1.0f, -1.0f},
{ 1.0f, 1.0f, 1.0f}
};
const GLubyte indices[24] = {0,1,1,3,3,2,2,0,0,4,4,5,5,7,7,6,6,4,1,5,3,7,2,6};
/* Position Only 3D format */
static VertexFormat format = { 0 };
static unsigned pos_id;
if (format.attrib_ct == 0) {
pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
}
VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
VertexBuffer_allocate_data(vbo, 24);
for (int i = 0; i < 24; ++i) {
setAttrib(vbo, pos_id, i, verts[indices[i]]);
}
SHC.drw_cube = Batch_create(GL_LINES, vbo, NULL);
}
return SHC.drw_cube;
}
Batch *DRW_cache_circle_get(void)
{
#define CIRCLE_RESOL 32
if (!SHC.drw_circle) {
float v[3] = {0.0f, 0.0f, 0.0f};
/* Position Only 3D format */
static VertexFormat format = { 0 };
static unsigned pos_id;
if (format.attrib_ct == 0) {
pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
}
VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
VertexBuffer_allocate_data(vbo, CIRCLE_RESOL * 2);
for (int a = 0; a < CIRCLE_RESOL; a++) {
v[0] = sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
v[1] = cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
v[2] = 0.0f;
setAttrib(vbo, pos_id, a * 2, v);
v[0] = sinf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
v[1] = cosf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
v[2] = 0.0f;
setAttrib(vbo, pos_id, a * 2 + 1, v);
}
SHC.drw_circle = Batch_create(GL_LINES, vbo, NULL);
}
return SHC.drw_circle;
#undef CIRCLE_RESOL
}
/* Empties */
Batch *DRW_cache_plain_axes_get(void)
{
if (!SHC.drw_plain_axes) {
int axis;
float v1[3] = {0.0f, 0.0f, 0.0f};
float v2[3] = {0.0f, 0.0f, 0.0f};
/* Position Only 3D format */
static VertexFormat format = { 0 };
static unsigned pos_id;
if (format.attrib_ct == 0) {
pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
}
VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
VertexBuffer_allocate_data(vbo, 6);
for (axis = 0; axis < 3; axis++) {
v1[axis] = 1.0f;
v2[axis] = -1.0f;
setAttrib(vbo, pos_id, axis * 2, v1);
setAttrib(vbo, pos_id, axis * 2 + 1, v2);
/* reset v1 & v2 to zero for next axis */
v1[axis] = v2[axis] = 0.0f;
}
SHC.drw_plain_axes = Batch_create(GL_LINES, vbo, NULL);
}
return SHC.drw_plain_axes;
}
Batch *DRW_cache_single_arrow_get(Batch **line)
{
if (!SHC.drw_single_arrow_line || !SHC.drw_single_arrow) {
float v1[3] = {0.0f, 0.0f, 0.0f}, v2[3], v3[3];
/* Position Only 3D format */
static VertexFormat format = { 0 };
static unsigned pos_id;
if (format.attrib_ct == 0) {
pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
}
/* Line */
VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
VertexBuffer_allocate_data(vbo, 2);
setAttrib(vbo, pos_id, 0, v1);
v1[2] = 1.0f;
setAttrib(vbo, pos_id, 1, v1);
SHC.drw_single_arrow_line = Batch_create(GL_LINES, vbo, NULL);
/* Square Pyramid */
vbo = VertexBuffer_create_with_format(&format);
VertexBuffer_allocate_data(vbo, 12);
v2[0] = 0.035f; v2[1] = 0.035f;
v3[0] = -0.035f; v3[1] = 0.035f;
v2[2] = v3[2] = 0.75f;
for (int sides = 0; sides < 4; sides++) {
if (sides % 2 == 1) {
v2[0] = -v2[0];
v3[1] = -v3[1];
}
else {
v2[1] = -v2[1];
v3[0] = -v3[0];
}
setAttrib(vbo, pos_id, sides * 3 + 0, v1);
setAttrib(vbo, pos_id, sides * 3 + 1, v2);
setAttrib(vbo, pos_id, sides * 3 + 2, v3);
}
SHC.drw_single_arrow = Batch_create(GL_TRIANGLES, vbo, NULL);
}
*line = SHC.drw_single_arrow_line;
return SHC.drw_single_arrow;
}
Batch *DRW_cache_empty_sphere_get(void)
{
#define NSEGMENTS 16
if (!SHC.drw_empty_sphere) {
/* a single ring of vertices */
float p[NSEGMENTS][2];
for (int i = 0; i < NSEGMENTS; ++i) {
float angle = 2 * M_PI * ((float)i / (float)NSEGMENTS);
p[i][0] = cosf(angle);
p[i][1] = sinf(angle);
}
/* Position Only 3D format */
static VertexFormat format = { 0 };
static unsigned pos_id;
if (format.attrib_ct == 0) {
pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
}
VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
VertexBuffer_allocate_data(vbo, NSEGMENTS * 2 * 3);
for (int axis = 0; axis < 3; ++axis) {
for (int i = 0; i < NSEGMENTS; ++i) {
for (int j = 0; j < 2; ++j) {
float cv[2], v[3];
cv[0] = p[(i+j) % NSEGMENTS][0];
cv[1] = p[(i+j) % NSEGMENTS][1];
if (axis == 0)
v[0] = cv[0], v[1] = cv[1], v[2] = 0.0f;
else if (axis == 1)
v[0] = cv[0], v[1] = 0.0f, v[2] = cv[1];
else
v[0] = 0.0f, v[1] = cv[0], v[2] = cv[1];
setAttrib(vbo, pos_id, i*2 + j + (NSEGMENTS * 2 * axis), v);
}
}
}
SHC.drw_empty_sphere = Batch_create(GL_LINES, vbo, NULL);
}
return SHC.drw_empty_sphere;
#undef NSEGMENTS
}
Batch *DRW_cache_empty_cone_get(void)
{
#define NSEGMENTS 8
if (!SHC.drw_empty_cone) {
/* a single ring of vertices */
float p[NSEGMENTS][2];
for (int i = 0; i < NSEGMENTS; ++i) {
float angle = 2 * M_PI * ((float)i / (float)NSEGMENTS);
p[i][0] = cosf(angle);
p[i][1] = sinf(angle);
}
/* Position Only 3D format */
static VertexFormat format = { 0 };
static unsigned pos_id;
if (format.attrib_ct == 0) {
pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
}
VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
VertexBuffer_allocate_data(vbo, NSEGMENTS * 4);
for (int i = 0; i < NSEGMENTS; ++i) {
float cv[2], v[3];
cv[0] = p[(i) % NSEGMENTS][0];
cv[1] = p[(i) % NSEGMENTS][1];
/* cone sides */
v[0] = cv[0], v[1] = 0.0f, v[2] = cv[1];
setAttrib(vbo, pos_id, i*4, v);
v[0] = 0.0f, v[1] = 2.0f, v[2] = 0.0f;
setAttrib(vbo, pos_id, i*4 + 1, v);
/* end ring */
v[0] = cv[0], v[1] = 0.0f, v[2] = cv[1];
setAttrib(vbo, pos_id, i*4 + 2, v);
cv[0] = p[(i+1) % NSEGMENTS][0];
cv[1] = p[(i+1) % NSEGMENTS][1];
v[0] = cv[0], v[1] = 0.0f, v[2] = cv[1];
setAttrib(vbo, pos_id, i*4 + 3, v);
}
SHC.drw_empty_cone = Batch_create(GL_LINES, vbo, NULL);
}
return SHC.drw_empty_cone;
#undef NSEGMENTS
}
Batch *DRW_cache_arrows_get(void)
{
if (!SHC.drw_arrows) {
float v1[3] = {0.0, 0.0, 0.0};
float v2[3] = {0.0, 0.0, 0.0};
/* Position Only 3D format */
static VertexFormat format = { 0 };
static unsigned pos_id;
if (format.attrib_ct == 0) {
pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
}
/* Line */
VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
VertexBuffer_allocate_data(vbo, 6 * 3);
for (int axis = 0; axis < 3; axis++) {
const int arrow_axis = (axis == 0) ? 1 : 0;
v2[axis] = 1.0f;
setAttrib(vbo, pos_id, axis * 6 + 0, v1);
setAttrib(vbo, pos_id, axis * 6 + 1, v2);
v1[axis] = 0.85f;
v1[arrow_axis] = -0.08f;
setAttrib(vbo, pos_id, axis * 6 + 2, v1);
setAttrib(vbo, pos_id, axis * 6 + 3, v2);
v1[arrow_axis] = 0.08f;
setAttrib(vbo, pos_id, axis * 6 + 4, v1);
setAttrib(vbo, pos_id, axis * 6 + 5, v2);
/* reset v1 & v2 to zero */
v1[arrow_axis] = v1[axis] = v2[axis] = 0.0f;
}
SHC.drw_arrows = Batch_create(GL_LINES, vbo, NULL);
}
return SHC.drw_arrows;
}
/* Lamps */
Batch *DRW_cache_lamp_get(void)
{
#define NSEGMENTS 8
if (!SHC.drw_lamp) {
float v[2];
/* Position Only 3D format */
static VertexFormat format = { 0 };
static unsigned pos_id;
if (format.attrib_ct == 0) {
pos_id = add_attrib(&format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
}
VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
VertexBuffer_allocate_data(vbo, NSEGMENTS * 2);
for (int a = 0; a < NSEGMENTS; a++) {
v[0] = sinf((2.0f * M_PI * a) / ((float)NSEGMENTS));
v[1] = cosf((2.0f * M_PI * a) / ((float)NSEGMENTS));
setAttrib(vbo, pos_id, a * 2, v);
v[0] = sinf((2.0f * M_PI * (a + 1)) / ((float)NSEGMENTS));
v[1] = cosf((2.0f * M_PI * (a + 1)) / ((float)NSEGMENTS));
setAttrib(vbo, pos_id, a * 2 + 1, v);
}
SHC.drw_lamp = Batch_create(GL_LINES, vbo, NULL);
}
return SHC.drw_lamp;
#undef NSEGMENTS
}
Batch *DRW_cache_lamp_sunrays_get(void)
{
if (!SHC.drw_lamp_sunrays) {
float v[2], v1[2], v2[2];
/* Position Only 3D format */
static VertexFormat format = { 0 };
static unsigned pos_id;
if (format.attrib_ct == 0) {
pos_id = add_attrib(&format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
}
VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
VertexBuffer_allocate_data(vbo, 16);
for (int a = 0; a < 8; a++) {
v[0] = sinf((2.0f * M_PI * a) / 8.0f);
v[1] = cosf((2.0f * M_PI * a) / 8.0f);
mul_v2_v2fl(v1, v, 1.2f);
mul_v2_v2fl(v2, v, 2.5f);
setAttrib(vbo, pos_id, a * 2, v1);
setAttrib(vbo, pos_id, a * 2 + 1, v2);
}
SHC.drw_lamp_sunrays = Batch_create(GL_LINES, vbo, NULL);
}
return SHC.drw_lamp_sunrays;
}
/* Object Center */
Batch *DRW_cache_single_vert_get(void)
{
if (!SHC.drw_single_vertice) {
float v1[3] = {0.0f, 0.0f, 0.0f};
/* Position Only 3D format */
static VertexFormat format = { 0 };
static unsigned pos_id;
if (format.attrib_ct == 0) {
pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
}
VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
VertexBuffer_allocate_data(vbo, 1);
setAttrib(vbo, pos_id, 0, v1);
SHC.drw_single_vertice = Batch_create(GL_POINTS, vbo, NULL);
}
return SHC.drw_single_vertice;
}
/* Meshes */
Batch *DRW_cache_wire_overlay_get(Object *ob)
{
Batch *overlay_wire = NULL;
BLI_assert(ob->type == OB_MESH);
Mesh *me = ob->data;
#if 1 /* new version not working */
overlay_wire = BKE_mesh_batch_cache_get_overlay_edges(me);
#else
overlay_wire = BKE_mesh_batch_cache_get_all_edges(me);
#endif
return overlay_wire;
}
Batch *DRW_cache_wire_outline_get(Object *ob)
{
Batch *fancy_wire = NULL;
BLI_assert(ob->type == OB_MESH);
Mesh *me = ob->data;
fancy_wire = BKE_mesh_batch_cache_get_fancy_edges(me);
return fancy_wire;
}
Batch *DRW_cache_surface_get(Object *ob)
{
Batch *surface = NULL;
BLI_assert(ob->type == OB_MESH);
Mesh *me = ob->data;
surface = BKE_mesh_batch_cache_get_all_triangles(me);
return surface;
}
#if 0 /* TODO */
struct Batch *DRW_cache_surface_material_get(Object *ob, int nr) {
/* TODO */
return NULL;
}
#endif

View File

@@ -0,0 +1,56 @@
/*
* Copyright 2016, Blender Foundation.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Blender Institute
*
*/
/** \file draw_cache.h
* \ingroup draw
*/
#ifndef __DRAW_CACHE_H__
#define __DRAW_CACHE_H__
struct Batch;
struct Object;
void DRW_shape_cache_free(void);
/* Common Shapes */
struct Batch *DRW_cache_fullscreen_quad_get(void);
struct Batch *DRW_cache_single_vert_get(void);
/* Empties */
struct Batch *DRW_cache_plain_axes_get(void);
struct Batch *DRW_cache_single_arrow_get(struct Batch **line);
struct Batch *DRW_cache_cube_get(void);
struct Batch *DRW_cache_circle_get(void);
struct Batch *DRW_cache_empty_sphere_get(void);
struct Batch *DRW_cache_empty_cone_get(void);
struct Batch *DRW_cache_arrows_get(void);
/* Lamps */
struct Batch *DRW_cache_lamp_get(void);
struct Batch *DRW_cache_lamp_sunrays_get(void);
/* Meshes */
struct Batch *DRW_cache_wire_overlay_get(struct Object *ob);
struct Batch *DRW_cache_wire_outline_get(struct Object *ob);
struct Batch *DRW_cache_surface_get(struct Object *ob);
#endif /* __DRAW_CACHE_H__ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,787 @@
/*
* Copyright 2016, Blender Foundation.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Blender Institute
*
*/
/** \file blender/draw/draw_mode_pass.c
* \ingroup draw
*/
#include "DNA_userdef_types.h"
#include "GPU_shader.h"
#include "UI_resources.h"
#include "BKE_global.h"
#include "draw_mode_pass.h"
/* ************************** OBJECT MODE ******************************* */
/* Store list of shading group for easy access*/
/* Empties */
static DRWShadingGroup *plain_axes_wire;
static DRWShadingGroup *plain_axes_active;
static DRWShadingGroup *plain_axes_select;
static DRWShadingGroup *plain_axes_transform;
static DRWShadingGroup *plain_axes_group;
static DRWShadingGroup *plain_axes_group_active;
static DRWShadingGroup *cube_wire;
static DRWShadingGroup *cube_active;
static DRWShadingGroup *cube_select;
static DRWShadingGroup *cube_transform;
static DRWShadingGroup *cube_group;
static DRWShadingGroup *cube_group_active;
static DRWShadingGroup *circle_wire;
static DRWShadingGroup *circle_active;
static DRWShadingGroup *circle_select;
static DRWShadingGroup *circle_transform;
static DRWShadingGroup *circle_group;
static DRWShadingGroup *circle_group_active;
static DRWShadingGroup *sphere_wire;
static DRWShadingGroup *sphere_active;
static DRWShadingGroup *sphere_select;
static DRWShadingGroup *sphere_transform;
static DRWShadingGroup *sphere_group;
static DRWShadingGroup *sphere_group_active;
static DRWShadingGroup *cone_wire;
static DRWShadingGroup *cone_active;
static DRWShadingGroup *cone_select;
static DRWShadingGroup *cone_transform;
static DRWShadingGroup *cone_group;
static DRWShadingGroup *cone_group_active;
static DRWShadingGroup *single_arrow_wire;
static DRWShadingGroup *single_arrow_active;
static DRWShadingGroup *single_arrow_select;
static DRWShadingGroup *single_arrow_transform;
static DRWShadingGroup *single_arrow_group;
static DRWShadingGroup *single_arrow_group_active;
static DRWShadingGroup *single_arrow_line_wire;
static DRWShadingGroup *single_arrow_line_active;
static DRWShadingGroup *single_arrow_line_select;
static DRWShadingGroup *single_arrow_line_transform;
static DRWShadingGroup *single_arrow_line_group;
static DRWShadingGroup *single_arrow_line_group_active;
static DRWShadingGroup *arrows_wire;
static DRWShadingGroup *arrows_active;
static DRWShadingGroup *arrows_select;
static DRWShadingGroup *arrows_transform;
static DRWShadingGroup *arrows_group;
static DRWShadingGroup *arrows_group_active;
/* Lamps */
static DRWShadingGroup *lamp_center;
static DRWShadingGroup *lamp_center_group;
static DRWShadingGroup *lamp_groundpoint;
static DRWShadingGroup *lamp_groundline;
static DRWShadingGroup *lamp_circle;
static DRWShadingGroup *lamp_circle_active;
static DRWShadingGroup *lamp_circle_select;
static DRWShadingGroup *lamp_circle_transform;
static DRWShadingGroup *lamp_circle_group;
static DRWShadingGroup *lamp_circle_group_active;
static DRWShadingGroup *lamp_circle_shadow;
static DRWShadingGroup *lamp_circle_shadow_active;
static DRWShadingGroup *lamp_circle_shadow_select;
static DRWShadingGroup *lamp_circle_shadow_transform;
static DRWShadingGroup *lamp_circle_shadow_group;
static DRWShadingGroup *lamp_circle_shadow_group_active;
static DRWShadingGroup *lamp_sunrays;
static DRWShadingGroup *lamp_sunrays_active;
static DRWShadingGroup *lamp_sunrays_select;
static DRWShadingGroup *lamp_sunrays_transform;
static DRWShadingGroup *lamp_sunrays_group;
static DRWShadingGroup *lamp_sunrays_group_active;
/* Helpers */
static DRWShadingGroup *relationship_lines;
/* Objects Centers */
static DRWShadingGroup *center_active;
static DRWShadingGroup *center_selected;
static DRWShadingGroup *center_deselected;
static DRWShadingGroup *shgroup_instance_uniform_color(DRWPass *pass, float color[4])
{
GPUShader *sh_inst = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR_INSTANCE);
DRWShadingGroup *grp = DRW_shgroup_create(sh_inst, pass);
DRW_shgroup_uniform_vec4(grp, "color", color, 1);
DRW_shgroup_dyntype_set(grp, DRW_DYN_INSTANCE);
return grp;
}
static DRWShadingGroup *shgroup_dynlines_uniform_color(DRWPass *pass, float color[4])
{
GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
DRW_shgroup_uniform_vec4(grp, "color", color, 1);
DRW_shgroup_dyntype_set(grp, DRW_DYN_LINES);
return grp;
}
static DRWShadingGroup *shgroup_dynpoints_uniform_color(DRWPass *pass, float color[4], float *size)
{
GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_SMOOTH);
DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
DRW_shgroup_uniform_vec4(grp, "color", color, 1);
DRW_shgroup_uniform_float(grp, "size", size, 1);
DRW_shgroup_dyntype_set(grp, DRW_DYN_POINTS);
DRW_shgroup_state_set(grp, DRW_STATE_POINT);
return grp;
}
static DRWShadingGroup *shgroup_groundlines_uniform_color(DRWPass *pass, float color[4])
{
GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_GROUNDLINE);
DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
DRW_shgroup_uniform_vec4(grp, "color", color, 1);
DRW_shgroup_dyntype_set(grp, DRW_DYN_POINTS);
return grp;
}
static DRWShadingGroup *shgroup_groundpoints_uniform_color(DRWPass *pass, float color[4])
{
GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_GROUNDPOINT);
DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
DRW_shgroup_uniform_vec4(grp, "color", color, 1);
DRW_shgroup_dyntype_set(grp, DRW_DYN_POINTS);
DRW_shgroup_state_set(grp, DRW_STATE_POINT);
return grp;
}
static DRWShadingGroup *shgroup_lamp(DRWPass *pass, float color[4], float *size)
{
GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_LAMP_COMMON);
DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
DRW_shgroup_uniform_vec4(grp, "color", color, 1);
DRW_shgroup_uniform_float(grp, "size", size, 1);
DRW_shgroup_uniform_float(grp, "pixel_size", DRW_viewport_pixelsize_get(), 1);
DRW_shgroup_uniform_vec3(grp, "screen_vecs", DRW_viewport_screenvecs_get(), 2);
DRW_shgroup_dyntype_set(grp, DRW_DYN_INSTANCE);
DRW_shgroup_state_set(grp, DRW_STATE_STIPPLE_3);
return grp;
}
/* This Function setup the passes needed for the mode rendering.
* The passes are populated by the rendering engine using the DRW_shgroup_* functions. */
void DRW_pass_setup_common(DRWPass **wire_overlay, DRWPass **wire_outline, DRWPass **non_meshes, DRWPass **ob_center)
{
/* Theses are defined for the whole application so make sure they rely on global settings */
static float colorWire[4], colorWireEdit[4];
static float colorActive[4], colorSelect[4], colorTransform[4], colorGroup[4], colorGroupActive[4];
static float colorEmpty[4], colorLamp[4], colorCamera[4], colorSpeaker[4];
static float lampCenterSize, lampCircleRad, lampCircleShadowRad, colorLampNoAlpha[4];
UI_GetThemeColor4fv(TH_WIRE, colorWire);
UI_GetThemeColor4fv(TH_WIRE_EDIT, colorWireEdit);
UI_GetThemeColor4fv(TH_ACTIVE, colorActive);
UI_GetThemeColor4fv(TH_SELECT, colorSelect);
UI_GetThemeColor4fv(TH_TRANSFORM, colorTransform);
UI_GetThemeColor4fv(TH_GROUP_ACTIVE, colorGroupActive);
UI_GetThemeColor4fv(TH_GROUP, colorGroup);
UI_GetThemeColor4fv(TH_LAMP, colorLamp);
UI_GetThemeColor4fv(TH_LAMP, colorLampNoAlpha);
UI_GetThemeColor4fv(TH_SPEAKER, colorSpeaker);
UI_GetThemeColor4fv(TH_CAMERA, colorCamera);
UI_GetThemeColor4fv(TH_EMPTY, colorEmpty);
colorLampNoAlpha[3] = 1.0f;
if (wire_overlay) {
/* This pass can draw mesh edges top of Shaded Meshes without any Z fighting */
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_BLEND;
*wire_overlay = DRW_pass_create("Wire Overlays Pass", state);
}
if (wire_outline) {
/* This pass can draw mesh outlines and/or fancy wireframe */
/* Fancy wireframes are not meant to be occluded (without Z offset) */
/* Outlines and Fancy Wires use the same VBO */
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND;
*wire_outline = DRW_pass_create("Wire + Outlines Pass", state);
}
if (non_meshes) {
/* Non Meshes Pass (Camera, empties, lamps ...) */
DRWShadingGroup *grp;
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND;
state |= DRW_STATE_WIRE;
*non_meshes = DRW_pass_create("Non Meshes Pass", state);
GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
/* Empties */
plain_axes_wire = shgroup_instance_uniform_color(*non_meshes, colorEmpty);
plain_axes_active = shgroup_instance_uniform_color(*non_meshes, colorActive);
plain_axes_select = shgroup_instance_uniform_color(*non_meshes, colorSelect);
plain_axes_transform = shgroup_instance_uniform_color(*non_meshes, colorTransform);
plain_axes_group = shgroup_instance_uniform_color(*non_meshes, colorGroup);
plain_axes_group_active = shgroup_instance_uniform_color(*non_meshes, colorGroupActive);
cube_wire = shgroup_instance_uniform_color(*non_meshes, colorEmpty);
cube_active = shgroup_instance_uniform_color(*non_meshes, colorActive);
cube_select = shgroup_instance_uniform_color(*non_meshes, colorSelect);
cube_transform = shgroup_instance_uniform_color(*non_meshes, colorTransform);
cube_group = shgroup_instance_uniform_color(*non_meshes, colorGroup);
cube_group_active = shgroup_instance_uniform_color(*non_meshes, colorGroupActive);
circle_wire = shgroup_instance_uniform_color(*non_meshes, colorEmpty);
circle_active = shgroup_instance_uniform_color(*non_meshes, colorActive);
circle_select = shgroup_instance_uniform_color(*non_meshes, colorSelect);
circle_transform = shgroup_instance_uniform_color(*non_meshes, colorTransform);
circle_group = shgroup_instance_uniform_color(*non_meshes, colorGroup);
circle_group_active = shgroup_instance_uniform_color(*non_meshes, colorGroupActive);
sphere_wire = shgroup_instance_uniform_color(*non_meshes, colorEmpty);
sphere_active = shgroup_instance_uniform_color(*non_meshes, colorActive);
sphere_select = shgroup_instance_uniform_color(*non_meshes, colorSelect);
sphere_transform = shgroup_instance_uniform_color(*non_meshes, colorTransform);
sphere_group = shgroup_instance_uniform_color(*non_meshes, colorGroup);
sphere_group_active = shgroup_instance_uniform_color(*non_meshes, colorGroupActive);
cone_wire = shgroup_instance_uniform_color(*non_meshes, colorEmpty);
cone_active = shgroup_instance_uniform_color(*non_meshes, colorActive);
cone_select = shgroup_instance_uniform_color(*non_meshes, colorSelect);
cone_transform = shgroup_instance_uniform_color(*non_meshes, colorTransform);
cone_group = shgroup_instance_uniform_color(*non_meshes, colorGroup);
cone_group_active = shgroup_instance_uniform_color(*non_meshes, colorGroupActive);
single_arrow_wire = shgroup_instance_uniform_color(*non_meshes, colorEmpty);
single_arrow_active = shgroup_instance_uniform_color(*non_meshes, colorActive);
single_arrow_select = shgroup_instance_uniform_color(*non_meshes, colorSelect);
single_arrow_transform = shgroup_instance_uniform_color(*non_meshes, colorTransform);
single_arrow_group = shgroup_instance_uniform_color(*non_meshes, colorGroup);
single_arrow_group_active = shgroup_instance_uniform_color(*non_meshes, colorGroupActive);
single_arrow_line_wire = shgroup_instance_uniform_color(*non_meshes, colorEmpty);
single_arrow_line_active = shgroup_instance_uniform_color(*non_meshes, colorActive);
single_arrow_line_select = shgroup_instance_uniform_color(*non_meshes, colorSelect);
single_arrow_line_transform = shgroup_instance_uniform_color(*non_meshes, colorTransform);
single_arrow_line_group = shgroup_instance_uniform_color(*non_meshes, colorGroup);
single_arrow_line_group_active = shgroup_instance_uniform_color(*non_meshes, colorGroupActive);
arrows_wire = shgroup_instance_uniform_color(*non_meshes, colorEmpty);
arrows_active = shgroup_instance_uniform_color(*non_meshes, colorActive);
arrows_select = shgroup_instance_uniform_color(*non_meshes, colorSelect);
arrows_transform = shgroup_instance_uniform_color(*non_meshes, colorTransform);
arrows_group = shgroup_instance_uniform_color(*non_meshes, colorGroup);
arrows_group_active = shgroup_instance_uniform_color(*non_meshes, colorGroupActive);
/* Lamps */
lampCenterSize = (U.obcenter_dia + 1.5f) * U.pixelsize;
lampCircleRad = U.pixelsize * 9.0f;
lampCircleShadowRad = lampCircleRad + U.pixelsize * 3.0f;
/* TODO
* for now we create 3 times the same VBO with only lamp center coordinates
* but ideally we would only create it once */
lamp_center = shgroup_dynpoints_uniform_color(*non_meshes, colorLampNoAlpha, &lampCenterSize);
lamp_center_group = shgroup_dynpoints_uniform_color(*non_meshes, colorGroup, &lampCenterSize);
lamp_circle = shgroup_lamp(*non_meshes, colorLampNoAlpha, &lampCircleRad);
lamp_circle_active = shgroup_lamp(*non_meshes, colorActive, &lampCircleRad);
lamp_circle_select = shgroup_lamp(*non_meshes, colorSelect, &lampCircleRad);
lamp_circle_transform = shgroup_lamp(*non_meshes, colorTransform, &lampCircleRad);
lamp_circle_group = shgroup_lamp(*non_meshes, colorGroup, &lampCircleRad);
lamp_circle_group_active = shgroup_lamp(*non_meshes, colorGroupActive, &lampCircleRad);
lamp_circle_shadow = shgroup_lamp(*non_meshes, colorLampNoAlpha, &lampCircleShadowRad);
lamp_circle_shadow_active = shgroup_lamp(*non_meshes, colorActive, &lampCircleShadowRad);
lamp_circle_shadow_select = shgroup_lamp(*non_meshes, colorSelect, &lampCircleShadowRad);
lamp_circle_shadow_transform = shgroup_lamp(*non_meshes, colorTransform, &lampCircleShadowRad);
lamp_circle_shadow_group = shgroup_lamp(*non_meshes, colorGroup, &lampCircleShadowRad);
lamp_circle_shadow_group_active = shgroup_lamp(*non_meshes, colorGroupActive, &lampCircleShadowRad);
lamp_sunrays = shgroup_lamp(*non_meshes, colorLampNoAlpha, &lampCircleRad);
lamp_sunrays_active = shgroup_lamp(*non_meshes, colorActive, &lampCircleRad);
lamp_sunrays_select = shgroup_lamp(*non_meshes, colorSelect, &lampCircleRad);
lamp_sunrays_transform = shgroup_lamp(*non_meshes, colorTransform, &lampCircleRad);
lamp_sunrays_group = shgroup_lamp(*non_meshes, colorGroup, &lampCircleRad);
lamp_sunrays_group_active = shgroup_lamp(*non_meshes, colorGroupActive, &lampCircleRad);
lamp_groundline = shgroup_groundlines_uniform_color(*non_meshes, colorLamp);
lamp_groundpoint = shgroup_groundpoints_uniform_color(*non_meshes, colorLamp);
/* Stipple Wires */
grp = DRW_shgroup_create(sh, *non_meshes);
DRW_shgroup_state_set(grp, DRW_STATE_STIPPLE_2);
grp = DRW_shgroup_create(sh, *non_meshes);
DRW_shgroup_state_set(grp, DRW_STATE_STIPPLE_3);
grp = DRW_shgroup_create(sh, *non_meshes);
DRW_shgroup_state_set(grp, DRW_STATE_STIPPLE_4);
/* Relationship Lines */
relationship_lines = shgroup_dynlines_uniform_color(*non_meshes, colorWire);
DRW_shgroup_state_set(relationship_lines, DRW_STATE_STIPPLE_3);
}
if (ob_center) {
/* Object Center pass grouped by State */
DRWShadingGroup *grp;
static float colorDeselect[4], outlineColor[4];
static float outlineWidth, size;
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND | DRW_STATE_POINT;
*ob_center = DRW_pass_create("Obj Center Pass", state);
outlineWidth = 1.0f * U.pixelsize;
size = U.obcenter_dia * U.pixelsize + outlineWidth;
//UI_GetThemeColorShadeAlpha4fv(TH_ACTIVE, 0, -80, colorActive);
//UI_GetThemeColorShadeAlpha4fv(TH_SELECT, 0, -80, colorSelect);
UI_GetThemeColorShadeAlpha4fv(TH_TRANSFORM, 0, -80, colorDeselect);
UI_GetThemeColorShadeAlpha4fv(TH_WIRE, 0, -30, outlineColor);
GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_SMOOTH);
/* Active */
grp = DRW_shgroup_create(sh, *ob_center);
DRW_shgroup_dyntype_set(grp, DRW_DYN_POINTS);
DRW_shgroup_uniform_float(grp, "size", &size, 1);
DRW_shgroup_uniform_float(grp, "outlineWidth", &outlineWidth, 1);
DRW_shgroup_uniform_vec4(grp, "color", colorActive, 1);
DRW_shgroup_uniform_vec4(grp, "outlineColor", outlineColor, 1);
center_active = grp;
/* Select */
grp = DRW_shgroup_create(sh, *ob_center);
DRW_shgroup_dyntype_set(grp, DRW_DYN_POINTS);
DRW_shgroup_uniform_vec4(grp, "color", colorSelect, 1);
center_selected = grp;
/* Deselect */
grp = DRW_shgroup_create(sh, *ob_center);
DRW_shgroup_dyntype_set(grp, DRW_DYN_POINTS);
DRW_shgroup_uniform_vec4(grp, "color", colorDeselect, 1);
center_deselected = grp;
}
}
/* ******************************************** WIRES *********************************************** */
/* TODO FINISH */
static int draw_object_wire_theme(Object *ob)
{
const bool is_edit = (ob->mode & OB_MODE_EDIT) != 0;
/* confusing logic here, there are 2 methods of setting the color
* 'colortab[colindex]' and 'theme_id', colindex overrides theme_id.
*
* note: no theme yet for 'colindex' */
int theme_id = is_edit ? TH_WIRE_EDIT : TH_WIRE;
if (//(scene->obedit == NULL) &&
((G.moving & G_TRANSFORM_OBJ) != 0) &&
((ob->base_flag & BASE_SELECTED) != 0))
{
theme_id = TH_TRANSFORM;
}
else {
/* Sets the 'theme_id' or fallback to wire */
if ((ob->flag & OB_FROMGROUP) != 0) {
if ((ob->base_flag & BASE_SELECTED) != 0) {
/* uses darker active color for non-active + selected */
theme_id = TH_GROUP_ACTIVE;
// if (scene->basact != base) {
// theme_shade = -16;
// }
}
else {
theme_id = TH_GROUP;
}
}
else {
if ((ob->base_flag & BASE_SELECTED) != 0) {
theme_id = //scene->basact == base ? TH_ACTIVE :
TH_SELECT;
}
else {
if (ob->type == OB_LAMP) theme_id = TH_LAMP;
else if (ob->type == OB_SPEAKER) theme_id = TH_SPEAKER;
else if (ob->type == OB_CAMERA) theme_id = TH_CAMERA;
else if (ob->type == OB_EMPTY) theme_id = TH_EMPTY;
/* fallback to TH_WIRE */
}
}
}
return theme_id;
}
void DRW_shgroup_wire_overlay(DRWPass *wire_overlay, Object *ob)
{
#if 1
struct Batch *geom = DRW_cache_wire_overlay_get(ob);
GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_EDGES_OVERLAY);
DRWShadingGroup *grp = DRW_shgroup_create(sh, wire_overlay);
DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1);
DRW_shgroup_call_add(grp, geom, ob->obmat);
#else
static float col[4] = {0.0f, 0.0f, 0.0f, 1.0f};
struct Batch *geom = DRW_cache_wire_overlay_get(ob);
GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
DRWShadingGroup *grp = DRW_shgroup_create(sh, wire_overlay);
DRW_shgroup_uniform_vec4(grp, "color", col, 1);
DRW_shgroup_call_add(grp, geom, ob->obmat);
#endif
}
void DRW_shgroup_wire_outline(DRWPass *wire_outline, Object *ob,
const bool do_front, const bool do_back, const bool do_outline)
{
GPUShader *sh;
struct Batch *geom = DRW_cache_wire_outline_get(ob);
/* Get color */
/* TODO get the right color depending on ob state (Groups, overides etc..) */
static float frontcol[4], backcol[4], color[4];
UI_GetThemeColor4fv(TH_ACTIVE, color);
copy_v4_v4(frontcol, color);
copy_v4_v4(backcol, color);
backcol[3] = 0.333f;
frontcol[3] = 0.667f;
#if 1 /* New wire */
bool is_perps = DRW_viewport_is_persp_get();
static bool bTrue = true;
static bool bFalse = false;
/* Note (TODO) : this requires cache to be discarded on ortho/perp switch
* It may be preferable (or not depending on performance implication)
* to introduce a shader uniform switch */
if (is_perps) {
sh = GPU_shader_get_builtin_shader(GPU_SHADER_EDGES_FRONT_BACK_PERSP);
}
else {
sh = GPU_shader_get_builtin_shader(GPU_SHADER_EDGES_FRONT_BACK_ORTHO);
}
if (do_front || do_back) {
bool *bFront = (do_front) ? &bTrue : &bFalse;
bool *bBack = (do_back) ? &bTrue : &bFalse;
DRWShadingGroup *grp = DRW_shgroup_create(sh, wire_outline);
DRW_shgroup_state_set(grp, DRW_STATE_WIRE);
DRW_shgroup_uniform_vec4(grp, "frontColor", frontcol, 1);
DRW_shgroup_uniform_vec4(grp, "backColor", backcol, 1);
DRW_shgroup_uniform_bool(grp, "drawFront", bFront, 1);
DRW_shgroup_uniform_bool(grp, "drawBack", bBack, 1);
DRW_shgroup_uniform_bool(grp, "drawSilhouette", &bFalse, 1);
DRW_shgroup_call_add(grp, geom, ob->obmat);
}
if (do_outline) {
DRWShadingGroup *grp = DRW_shgroup_create(sh, wire_outline);
DRW_shgroup_state_set(grp, DRW_STATE_WIRE_LARGE);
DRW_shgroup_uniform_vec4(grp, "silhouetteColor", color, 1);
DRW_shgroup_uniform_bool(grp, "drawFront", &bFalse, 1);
DRW_shgroup_uniform_bool(grp, "drawBack", &bFalse, 1);
DRW_shgroup_uniform_bool(grp, "drawSilhouette", &bTrue, 1);
DRW_shgroup_call_add(grp, geom, ob->obmat);
}
#else /* Old (flat) wire */
sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
DRWShadingGroup *grp = DRW_shgroup_create(sh, wire_outline);
DRW_shgroup_state_set(grp, DRW_STATE_WIRE_LARGE);
DRW_shgroup_uniform_vec4(grp, "color", frontcol, 1);
DRW_shgroup_call_add(grp, geom, ob->obmat);
#endif
}
/* ***************************** NON MESHES ********************** */
static void DRW_draw_lamp(Object *ob)
{
struct Batch *center = DRW_cache_single_vert_get();
struct Batch *lamp = DRW_cache_lamp_get();
struct Batch *sunrays = DRW_cache_lamp_sunrays_get();
Lamp *la = ob->data;
int theme_id = draw_object_wire_theme(ob);
/* Don't draw the center if it's selected or active */
if (theme_id == TH_GROUP)
DRW_shgroup_call_add(lamp_center_group, center, ob->obmat);
else if (theme_id == TH_LAMP)
DRW_shgroup_call_add(lamp_center, center, ob->obmat);
/* First circle */
if (theme_id == TH_ACTIVE)
DRW_shgroup_call_add(lamp_circle_active, lamp, ob->obmat);
else if (theme_id == TH_SELECT)
DRW_shgroup_call_add(lamp_circle_select, lamp, ob->obmat);
else if (theme_id == TH_GROUP)
DRW_shgroup_call_add(lamp_circle_group, lamp, ob->obmat);
else if (theme_id == TH_GROUP_ACTIVE)
DRW_shgroup_call_add(lamp_circle_group_active, lamp, ob->obmat);
else if (theme_id == TH_TRANSFORM)
DRW_shgroup_call_add(lamp_circle_transform, lamp, ob->obmat);
else
DRW_shgroup_call_add(lamp_circle, lamp, ob->obmat);
/* draw dashed outer circle if shadow is on. remember some lamps can't have certain shadows! */
if (la->type != LA_HEMI) {
if ((la->mode & LA_SHAD_RAY) || ((la->mode & LA_SHAD_BUF) && (la->type == LA_SPOT))) {
if (theme_id == TH_ACTIVE)
DRW_shgroup_call_add(lamp_circle_shadow_active, lamp, ob->obmat);
else if (theme_id == TH_SELECT)
DRW_shgroup_call_add(lamp_circle_shadow_select, lamp, ob->obmat);
else if (theme_id == TH_GROUP)
DRW_shgroup_call_add(lamp_circle_shadow_group, lamp, ob->obmat);
else if (theme_id == TH_GROUP_ACTIVE)
DRW_shgroup_call_add(lamp_circle_shadow_group_active, lamp, ob->obmat);
else if (theme_id == TH_TRANSFORM)
DRW_shgroup_call_add(lamp_circle_shadow_transform, lamp, ob->obmat);
else
DRW_shgroup_call_add(lamp_circle_shadow, lamp, ob->obmat);
}
}
/* Sunrays */
if (la->type == LA_SUN) {
if (theme_id == TH_ACTIVE)
DRW_shgroup_call_add(lamp_sunrays_active, sunrays, ob->obmat);
else if (theme_id == TH_SELECT)
DRW_shgroup_call_add(lamp_sunrays_select, sunrays, ob->obmat);
else if (theme_id == TH_GROUP)
DRW_shgroup_call_add(lamp_sunrays_group, sunrays, ob->obmat);
else if (theme_id == TH_GROUP_ACTIVE)
DRW_shgroup_call_add(lamp_sunrays_group_active, sunrays, ob->obmat);
else if (theme_id == TH_TRANSFORM)
DRW_shgroup_call_add(lamp_sunrays_transform, sunrays, ob->obmat);
else
DRW_shgroup_call_add(lamp_sunrays, sunrays, ob->obmat);
}
/* Line and point going to the ground */
DRW_shgroup_call_add(lamp_groundline, center, ob->obmat);
DRW_shgroup_call_add(lamp_groundpoint, center, ob->obmat);
}
static void DRW_draw_empty(Object *ob)
{
struct Batch *geom, *geom2;
DRWShadingGroup *grp, *grp2;
int theme_id = draw_object_wire_theme(ob);
switch (ob->empty_drawtype) {
case OB_PLAINAXES:
if (theme_id == TH_ACTIVE)
grp = plain_axes_active;
else if (theme_id == TH_SELECT)
grp = plain_axes_select;
else if (theme_id == TH_GROUP_ACTIVE)
grp = plain_axes_group_active;
else if (theme_id == TH_GROUP)
grp = plain_axes_group;
else if (theme_id == TH_TRANSFORM)
grp = plain_axes_transform;
else
grp = plain_axes_wire;
geom = DRW_cache_plain_axes_get();
DRW_shgroup_call_add(grp, geom, ob->obmat);
break;
case OB_SINGLE_ARROW:
if (theme_id == TH_ACTIVE) {
grp = single_arrow_active;
grp2 = single_arrow_line_active;
}
else if (theme_id == TH_SELECT) {
grp = single_arrow_select;
grp2 = single_arrow_line_select;
}
else if (theme_id == TH_GROUP_ACTIVE) {
grp = single_arrow_group_active;
grp2 = single_arrow_line_group_active;
}
else if (theme_id == TH_GROUP) {
grp = single_arrow_group;
grp2 = single_arrow_line_group;
}
else if (theme_id == TH_TRANSFORM) {
grp = single_arrow_transform;
grp2 = single_arrow_line_transform;
}
else {
grp = single_arrow_wire;
grp2 = single_arrow_line_wire;
}
geom = DRW_cache_single_arrow_get(&geom2);
DRW_shgroup_call_add(grp, geom, ob->obmat);
DRW_shgroup_call_add(grp2, geom2, ob->obmat);
break;
case OB_CUBE:
if (theme_id == TH_ACTIVE)
grp = cube_active;
else if (theme_id == TH_SELECT)
grp = cube_select;
else if (theme_id == TH_GROUP_ACTIVE)
grp = cube_group_active;
else if (theme_id == TH_GROUP)
grp = cube_group;
else if (theme_id == TH_TRANSFORM)
grp = cube_transform;
else
grp = cube_wire;
geom = DRW_cache_cube_get();
DRW_shgroup_call_add(grp, geom, ob->obmat);
break;
case OB_CIRCLE:
if (theme_id == TH_ACTIVE)
grp = circle_active;
else if (theme_id == TH_SELECT)
grp = circle_select;
else if (theme_id == TH_GROUP_ACTIVE)
grp = circle_group_active;
else if (theme_id == TH_GROUP)
grp = circle_group;
else if (theme_id == TH_TRANSFORM)
grp = circle_transform;
else
grp = circle_wire;
geom = DRW_cache_circle_get();
DRW_shgroup_call_add(grp, geom, ob->obmat);
break;
case OB_EMPTY_SPHERE:
if (theme_id == TH_ACTIVE)
grp = sphere_active;
else if (theme_id == TH_SELECT)
grp = sphere_select;
else if (theme_id == TH_GROUP_ACTIVE)
grp = sphere_group_active;
else if (theme_id == TH_GROUP)
grp = sphere_group;
else if (theme_id == TH_TRANSFORM)
grp = sphere_transform;
else
grp = sphere_wire;
geom = DRW_cache_empty_sphere_get();
DRW_shgroup_call_add(grp, geom, ob->obmat);
break;
case OB_EMPTY_CONE:
if (theme_id == TH_ACTIVE)
grp = cone_active;
else if (theme_id == TH_SELECT)
grp = cone_select;
else if (theme_id == TH_GROUP_ACTIVE)
grp = cone_group_active;
else if (theme_id == TH_GROUP)
grp = cone_group;
else if (theme_id == TH_TRANSFORM)
grp = cone_transform;
else
grp = cone_wire;
geom = DRW_cache_empty_cone_get();
DRW_shgroup_call_add(grp, geom, ob->obmat);
break;
case OB_ARROWS:
default:
if (theme_id == TH_ACTIVE)
grp = arrows_active;
else if (theme_id == TH_SELECT)
grp = arrows_select;
else if (theme_id == TH_GROUP_ACTIVE)
grp = arrows_group_active;
else if (theme_id == TH_GROUP)
grp = arrows_group;
else if (theme_id == TH_TRANSFORM)
grp = arrows_transform;
else
grp = arrows_wire;
geom = DRW_cache_arrows_get();
DRW_shgroup_call_add(grp, geom, ob->obmat);
/* TODO Missing axes names */
break;
}
}
void DRW_shgroup_non_meshes(DRWPass *UNUSED(non_meshes), Object *ob)
{
switch (ob->type) {
case OB_LAMP:
DRW_draw_lamp(ob);
break;
case OB_CAMERA:
case OB_EMPTY:
DRW_draw_empty(ob);
default:
break;
}
}
void DRW_shgroup_relationship_lines(DRWPass *UNUSED(non_meshes), Object *ob)
{
if (ob->parent) {
struct Batch *geom = DRW_cache_single_vert_get();
DRW_shgroup_call_add(relationship_lines, geom, ob->obmat);
DRW_shgroup_call_add(relationship_lines, geom, ob->parent->obmat);
}
}
/* ***************************** COMMON **************************** */
void DRW_shgroup_object_center(DRWPass *UNUSED(ob_center), Object *ob)
{
struct Batch *geom = DRW_cache_single_vert_get();
if ((ob->base_flag & BASE_SELECTED) != 0) {
DRW_shgroup_call_add(center_selected, geom, ob->obmat);
}
else if (0) {
DRW_shgroup_call_add(center_deselected, geom, ob->obmat);
}
}

View File

@@ -0,0 +1,45 @@
/*
* Copyright 2016, Blender Foundation.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Blender Institute
*
*/
/** \file draw_mode_pass.h
* \ingroup draw
*/
#ifndef __DRAW_MODE_PASS_H__
#define __DRAW_MODE_PASS_H__
#include "DRW_render.h"
struct DRWPass;
struct Batch;
struct Object;
void DRW_pass_setup_common(struct DRWPass **wire_overlay, struct DRWPass **wire_outline, struct DRWPass **non_meshes, struct DRWPass **ob_center);
void DRW_shgroup_wire_overlay(struct DRWPass *wire_overlay, struct Object *ob);
void DRW_shgroup_wire_outline(
struct DRWPass *wire_outline, struct Object *ob, const bool do_front, const bool do_back, const bool do_outline);
void DRW_shgroup_non_meshes(struct DRWPass *non_meshes, struct Object *ob);
void DRW_shgroup_relationship_lines(struct DRWPass *non_meshes, struct Object *ob);
void DRW_shgroup_object_center(struct DRWPass *ob_center, struct Object *ob);
#endif /* __DRAW_MODE_PASS_H__ */

View File

@@ -47,6 +47,7 @@ if(WITH_BLENDER)
add_subdirectory(space_graph)
add_subdirectory(space_image)
add_subdirectory(space_info)
add_subdirectory(space_collections)
add_subdirectory(space_logic)
add_subdirectory(space_nla)
add_subdirectory(space_node)

View File

@@ -57,6 +57,7 @@
#include "BKE_context.h"
#include "BKE_mask.h"
#include "BKE_global.h"
#include "BKE_scene.h"
#include "UI_view2d.h"
@@ -2690,7 +2691,7 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index,
if (selectmode == SELECT_INVERT) {
/* swap select */
base->flag ^= SELECT;
ob->flag = base->flag;
BKE_scene_base_flag_sync_from_base(base);
if (adt) adt->flag ^= ADT_UI_SELECTED;
}
@@ -2701,7 +2702,7 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index,
/* TODO: should this deselect all other types of channels too? */
for (b = sce->base.first; b; b = b->next) {
b->flag &= ~SELECT;
b->object->flag = b->flag;
BKE_scene_base_flag_sync_from_base(b);
if (b->object->adt) b->object->adt->flag &= ~(ADT_UI_SELECTED | ADT_UI_ACTIVE);
}

View File

@@ -50,6 +50,7 @@
#include "BKE_depsgraph.h"
#include "BKE_fcurve.h"
#include "BKE_global.h"
#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_report.h"
@@ -268,7 +269,7 @@ int join_armature_exec(bContext *C, wmOperator *op)
if (!arm || arm->edbo)
return OPERATOR_CANCELLED;
CTX_DATA_BEGIN(C, Base *, base, selected_editable_bases)
CTX_DATA_BEGIN(C, ObjectBase *, base, selected_editable_bases)
{
if (base->object == ob) {
ok = true;
@@ -290,7 +291,7 @@ int join_armature_exec(bContext *C, wmOperator *op)
pose = ob->pose;
ob->mode &= ~OB_MODE_POSE;
CTX_DATA_BEGIN(C, Base *, base, selected_editable_bases)
CTX_DATA_BEGIN(C, ObjectBase *, base, selected_editable_bases)
{
if ((base->object->type == OB_ARMATURE) && (base->object != ob)) {
tJoinArmature_AdtFixData afd = {NULL};
@@ -400,7 +401,7 @@ int join_armature_exec(bContext *C, wmOperator *op)
}
/* Free the old object data */
ED_base_object_free_and_unlink(bmain, scene, base);
ED_base_object_free_and_unlink(bmain, scene, base->object);
}
}
CTX_DATA_END;
@@ -579,9 +580,10 @@ static int separate_armature_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
SceneLayer *sl = CTX_data_scene_layer(C);
Object *obedit = CTX_data_edit_object(C);
Object *oldob, *newob;
Base *oldbase, *newbase;
ObjectBase *oldbase, *newbase;
/* sanity checks */
if (obedit == NULL)
@@ -600,16 +602,20 @@ static int separate_armature_exec(bContext *C, wmOperator *op)
/* 1) only edit-base selected */
/* TODO: use context iterators for this? */
CTX_DATA_BEGIN(C, Base *, base, visible_bases)
CTX_DATA_BEGIN(C, ObjectBase *, base, visible_bases)
{
if (base->object == obedit) base->flag |= SELECT;
else base->flag &= ~SELECT;
if (base->object == obedit) {
ED_object_base_select(base, BA_SELECT);
}
else {
ED_object_base_select(base, BA_DESELECT);
}
}
CTX_DATA_END;
/* 1) store starting settings and exit editmode */
oldob = obedit;
oldbase = BASACT;
oldbase = sl->basact;
oldob->mode &= ~OB_MODE_POSE;
//oldbase->flag &= ~OB_POSEMODE;
@@ -617,13 +623,13 @@ static int separate_armature_exec(bContext *C, wmOperator *op)
ED_armature_edit_free(obedit->data);
/* 2) duplicate base */
newbase = ED_object_add_duplicate(bmain, scene, oldbase, USER_DUP_ARM); /* only duplicate linked armature */
newbase = ED_object_add_duplicate(bmain, scene, sl, oldbase, USER_DUP_ARM); /* only duplicate linked armature */
DAG_relations_tag_update(bmain);
newob = newbase->object;
newbase->flag &= ~SELECT;
newbase->flag &= ~BASE_SELECTED;
/* 3) remove bones that shouldn't still be around on both armatures */
separate_armature_bones(oldob, 1);
separate_armature_bones(newob, 0);

View File

@@ -2518,7 +2518,7 @@ void BIF_retargetArmature(bContext *C)
printf("Reeb Graph created\n");
CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
CTX_DATA_BEGIN (C, ObjectBase *, base, selected_editable_bases)
{
Object *ob = base->object;

View File

@@ -81,7 +81,7 @@ Object *ED_pose_object_from_context(bContext *C)
}
/* This function is used to process the necessary updates for */
void ED_armature_enter_posemode(bContext *C, Base *base)
void ED_armature_enter_posemode(bContext *C, ObjectBase *base)
{
ReportList *reports = CTX_wm_reports(C);
Object *ob = base->object;
@@ -107,7 +107,7 @@ void ED_armature_enter_posemode(bContext *C, Base *base)
//ED_object_toggle_modes(C, ob->mode);
}
void ED_armature_exit_posemode(bContext *C, Base *base)
void ED_armature_exit_posemode(bContext *C, ObjectBase *base)
{
if (base) {
Object *ob = base->object;

View File

@@ -50,6 +50,7 @@
#include "BKE_fcurve.h"
#include "BKE_global.h"
#include "BKE_key.h"
#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_report.h"
@@ -1270,8 +1271,9 @@ static int separate_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
SceneLayer *sl = CTX_data_scene_layer(C);
Object *oldob, *newob;
Base *oldbase, *newbase;
ObjectBase *oldbase, *newbase;
Curve *oldcu, *newcu;
EditNurb *newedit;
ListBase newnurb = {NULL, NULL};
@@ -1297,7 +1299,7 @@ static int separate_exec(bContext *C, wmOperator *op)
}
/* 2. duplicate the object and data */
newbase = ED_object_add_duplicate(bmain, scene, oldbase, 0); /* 0 = fully linked */
newbase = ED_object_add_duplicate(bmain, scene, sl, oldbase, 0); /* 0 = fully linked */
DAG_relations_tag_update(bmain);
newob = newbase->object;
@@ -5961,7 +5963,7 @@ int join_curve_exec(bContext *C, wmOperator *op)
int a;
bool ok = false;
CTX_DATA_BEGIN(C, Base *, base, selected_editable_bases)
CTX_DATA_BEGIN(C, ObjectBase *, base, selected_editable_bases)
{
if (base->object == ob) {
ok = true;
@@ -5981,7 +5983,7 @@ int join_curve_exec(bContext *C, wmOperator *op)
/* trasnform all selected curves inverse in obact */
invert_m4_m4(imat, ob->obmat);
CTX_DATA_BEGIN(C, Base *, base, selected_editable_bases)
CTX_DATA_BEGIN(C, ObjectBase *, base, selected_editable_bases)
{
if (base->object->type == ob->type) {
if (base->object != ob) {
@@ -6024,7 +6026,7 @@ int join_curve_exec(bContext *C, wmOperator *op)
}
}
ED_base_object_free_and_unlink(bmain, scene, base);
ED_base_object_free_and_unlink(bmain, scene, base->object);
}
}
}

View File

@@ -420,17 +420,18 @@ static void txt_add_object(bContext *C, TextLine *firstline, int totline, const
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
SceneLayer *sl = CTX_data_scene_layer(C);
Curve *cu;
Object *obedit;
Base *base;
ObjectBase *base;
struct TextLine *tmp;
int nchars = 0, nbytes = 0;
char *s;
int a;
float rot[3] = {0.f, 0.f, 0.f};
obedit = BKE_object_add(bmain, scene, OB_FONT, NULL);
base = scene->basact;
obedit = BKE_object_add(bmain, scene, sl, OB_FONT, NULL);
base = sl->basact;
/* seems to assume view align ? TODO - look into this, could be an operator option */
ED_object_base_init_transform(C, base, NULL, rot);

View File

@@ -1217,7 +1217,8 @@ static void gp_layer_to_curve(bContext *C, ReportList *reports, bGPdata *gpd, bG
/* set the layer and select */
base_new->lay = ob->lay = base_orig ? base_orig->lay : BKE_screen_view3d_layer_active(v3d, scene);
base_new->flag = ob->flag = base_new->flag | SELECT;
base_new->flag |= SELECT;
BKE_scene_base_flag_sync_from_base(base_new);
}
/* --- */

View File

@@ -49,6 +49,7 @@ struct ColorManagedDisplaySettings;
void fdrawline(float x1, float y1, float x2, float y2); /* DEPRECATED */
void fdrawbox(float x1, float y1, float x2, float y2); /* DEPRECATED */
void fdrawbox_filled(float x1, float y1, float x2, float y2);
void sdrawline(int x1, int y1, int x2, int y2); /* DEPRECATED */
void sdrawbox(int x1, int y1, int x2, int y2); /* DEPRECATED */

View File

@@ -44,6 +44,7 @@ struct ListBase;
struct MeshDeformModifierData;
struct DerivedMesh;
struct Object;
struct ObjectBase;
struct ReportList;
struct Scene;
struct ViewContext;
@@ -183,8 +184,8 @@ void ED_armature_ebone_selectflag_enable(EditBone *ebone, int flag);
void ED_armature_ebone_selectflag_disable(EditBone *ebone, int flag);
/* poseobject.c */
void ED_armature_exit_posemode(struct bContext *C, struct Base *base);
void ED_armature_enter_posemode(struct bContext *C, struct Base *base);
void ED_armature_exit_posemode(struct bContext *C, struct ObjectBase *base);
void ED_armature_enter_posemode(struct bContext *C, struct ObjectBase *base);
void ED_pose_de_selectall(struct Object *ob, int select_mode, const bool ignore_visibility);
void ED_pose_bone_select(struct Object *ob, struct bPoseChannel *pchan, bool select);
void ED_pose_recalculate_paths(struct Scene *scene, struct Object *ob);

View File

@@ -41,8 +41,10 @@ struct ID;
struct Main;
struct ModifierData;
struct Object;
struct ObjectBase;
struct ReportList;
struct Scene;
struct SceneLayer;
struct bConstraint;
struct bContext;
struct bPoseChannel;
@@ -53,6 +55,7 @@ struct wmOperatorType;
struct PointerRNA;
struct PropertyRNA;
struct EnumPropertyItem;
struct LayerTree;
/* object_edit.c */
struct Object *ED_object_context(struct bContext *C); /* context.object */
@@ -89,7 +92,6 @@ bool ED_object_parent_set(struct ReportList *reports, struct Main *bmain, struct
struct Object *par, int partype, const bool xmirror, const bool keep_transform,
const int vert_par[3]);
void ED_object_parent_clear(struct Object *ob, const int type);
struct Base *ED_object_scene_link(struct Scene *scene, struct Object *ob);
void ED_keymap_proportional_cycle(struct wmKeyConfig *keyconf, struct wmKeyMap *keymap);
void ED_keymap_proportional_obmode(struct wmKeyConfig *keyconf, struct wmKeyMap *keymap);
@@ -102,10 +104,16 @@ void ED_base_object_select(struct Base *base, short mode);
/* includes notifier */
void ED_base_object_activate(struct bContext *C, struct Base *base);
void ED_base_object_free_and_unlink(struct Main *bmain, struct Scene *scene, struct Base *base);
void ED_object_base_select(struct ObjectBase *base, short mode);
void ED_object_base_activate(struct bContext *C, struct ObjectBase *base);
void ED_base_object_free_and_unlink(struct Main *bmain, struct Scene *scene, struct Object *ob);
void ED_base_object_sync_from_base(struct Base *base, struct Object *ob);
void ED_base_object_sync_from_object(struct Base *base, struct Object *ob);
/* single object duplicate, if (dupflag == 0), fully linked, else it uses the flags given */
struct Base *ED_object_add_duplicate(struct Main *bmain, struct Scene *scene, struct Base *base, int dupflag);
struct ObjectBase *ED_object_add_duplicate(struct Main *bmain, struct Scene *scene, struct SceneLayer *sl, struct ObjectBase *base, int dupflag);
void ED_object_parent(struct Object *ob, struct Object *parent, const int type, const char *substr);
@@ -126,7 +134,7 @@ bool ED_object_editmode_calc_active_center(struct Object *obedit, const bool sel
void ED_object_location_from_view(struct bContext *C, float loc[3]);
void ED_object_rotation_from_view(struct bContext *C, float rot[3], const char align_axis);
void ED_object_base_init_transform(struct bContext *C, struct Base *base, const float loc[3], const float rot[3]);
void ED_object_base_init_transform(struct bContext *C, struct ObjectBase *base, const float loc[3], const float rot[3]);
float ED_object_new_primitive_matrix(
struct bContext *C, struct Object *editob,
const float loc[3], const float rot[3], float primmat[4][4]);
@@ -191,7 +199,7 @@ void ED_object_modifier_clear(struct Main *bmain, struct Object *ob);
int ED_object_modifier_move_down(struct ReportList *reports, struct Object *ob, struct ModifierData *md);
int ED_object_modifier_move_up(struct ReportList *reports, struct Object *ob, struct ModifierData *md);
int ED_object_modifier_convert(struct ReportList *reports, struct Main *bmain, struct Scene *scene,
struct Object *ob, struct ModifierData *md);
struct SceneLayer *sl, struct Object *ob, struct ModifierData *md);
int ED_object_modifier_apply(struct ReportList *reports, struct Scene *scene,
struct Object *ob, struct ModifierData *md, int mode);
int ED_object_modifier_copy(struct ReportList *reports, struct Object *ob, struct ModifierData *md);

View File

@@ -162,6 +162,7 @@ int ED_operator_image_active(struct bContext *C);
int ED_operator_nla_active(struct bContext *C);
int ED_operator_logic_active(struct bContext *C);
int ED_operator_info_active(struct bContext *C);
int ED_operator_collections_active(struct bContext *C);
int ED_operator_console_active(struct bContext *C);

View File

@@ -58,6 +58,7 @@ void ED_spacetype_logic(void);
void ED_spacetype_console(void);
void ED_spacetype_userpref(void);
void ED_spacetype_clip(void);
void ED_spacetype_collections(void);
/* calls for instancing and freeing spacetype static data
* called in WM_init_exit */

View File

@@ -212,6 +212,9 @@ enum {
UI_BUT_ALIGN_STITCH_TOP = (1 << 18),
UI_BUT_ALIGN_STITCH_LEFT = (1 << 19),
UI_BUT_ALIGN_ALL = (UI_BUT_ALIGN | UI_BUT_ALIGN_STITCH_TOP | UI_BUT_ALIGN_STITCH_LEFT),
/* Another hack, in some rare cases we don't want any text margin */
UI_BUT_TEXT_NO_MARGIN = (1 << 20),
};
/* scale fixed button widths by this to account for DPI */
@@ -997,7 +1000,7 @@ void uiItemsFullEnumO(
struct IDProperty *properties, int context, int flag);
void uiItemsFullEnumO_items(
uiLayout *layout, struct wmOperatorType *ot, PointerRNA ptr, PropertyRNA *prop,
IDProperty *properties, int context, int flag,
struct IDProperty *properties, int context, int flag,
const EnumPropertyItem *item_array, int totitem);
void uiItemL(uiLayout *layout, const char *name, int icon); /* label */

View File

@@ -83,5 +83,6 @@ struct PreviewImage *UI_icon_to_preview(int icon_id);
int UI_rnaptr_icon_get(struct bContext *C, struct PointerRNA *ptr, int rnaicon, const bool big);
int UI_idcode_icon_get(const int idcode);
int UI_colorset_icon_get(const int set_idx);
#endif /* __UI_INTERFACE_ICONS_H__ */

View File

@@ -0,0 +1,76 @@
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file UI_table.h
* \ingroup editorui
*/
#ifndef __UI_TABLE_H__
#define __UI_TABLE_H__
#include "BLI_compiler_attrs.h"
struct rcti;
struct uiBlock;
struct uiLayout;
struct uiStyle;
typedef struct uiTable uiTable;
typedef struct uiTableColumn uiTableColumn;
typedef struct uiTableRow uiTableRow;
typedef struct uiTableSize uiTableSize;
typedef void (*uiTableCellDrawFunc)(struct uiLayout *layout, void *rowdata, struct rcti drawrect);
enum uiTableColumnAlignemt {
TABLE_COLUMN_ALIGN_LEFT,
TABLE_COLUMN_ALIGN_RIGHT,
};
enum uiTableUnit {
TABLE_UNIT_PX,
TABLE_UNIT_PERCENT,
};
uiTable *UI_table_horizontal_flow_create(void) ATTR_WARN_UNUSED_RESULT;
uiTable *UI_table_vertical_flow_create(void) ATTR_WARN_UNUSED_RESULT;
void UI_table_free(uiTable *table) ATTR_NONNULL();
void UI_table_max_width_set(uiTable *table, const unsigned int max_width) ATTR_NONNULL();
void UI_table_horizontal_flow_max_height_set(uiTable *table, const unsigned int max_height) ATTR_NONNULL();
void UI_table_background_colors_set(uiTable *table, const unsigned char rgb1[3], const unsigned char rgb2[3]);
void UI_table_draw(uiTable *table, struct uiBlock *block, struct uiStyle *style) ATTR_NONNULL(1);
/* *** Columns *** */
uiTableColumn *UI_table_column_add(uiTable *table, const char *idname, const char *drawname,
uiTableCellDrawFunc cell_draw) ATTR_NONNULL(1, 2);
void UI_table_column_remove(uiTable *table, uiTableColumn *column) ATTR_NONNULL();
uiTableColumn *UI_table_column_lookup(uiTable *table, const char *idname) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT;
void UI_table_column_width_set(uiTableColumn *column, const unsigned int width, enum uiTableUnit unit,
const int min_width_px) ATTR_NONNULL();
void UI_table_column_alignment_set(uiTableColumn *column, enum uiTableColumnAlignemt alignment) ATTR_NONNULL();
/* *** Rows *** */
uiTableRow *UI_table_row_add(uiTable *table, void *rowdata) ATTR_NONNULL(1);
void UI_table_row_height_set(uiTable *table, uiTableRow *row, unsigned int height) ATTR_NONNULL();
unsigned int UI_table_get_rowcount(const uiTable *table);
#endif /* __UI_TABLE_H__ */

View File

@@ -55,6 +55,7 @@ set(SRC
interface_utils.c
interface_widgets.c
resources.c
table.c
view2d.c
view2d_ops.c

View File

@@ -1385,6 +1385,14 @@ int UI_idcode_icon_get(const int idcode)
}
}
/**
* \param set_idx: A value from #rna_enum_color_sets_items.
*/
int UI_colorset_icon_get(const int set_idx)
{
return (set_idx < 1) ? ICON_NONE : VICO_COLORSET_01_VEC - 1 + set_idx;
}
static void icon_draw_at_size(
float x, float y, int icon_id, float aspect, float alpha,
enum eIconSizes size, const bool nocreate)

View File

@@ -1575,7 +1575,10 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB
}
}
if (but->editstr || (but->drawflag & UI_BUT_TEXT_LEFT)) {
if (but->drawflag & UI_BUT_TEXT_NO_MARGIN) {
/* skip */
}
else if (but->editstr || (but->drawflag & UI_BUT_TEXT_LEFT)) {
rect->xmin += (UI_TEXT_MARGIN_X * U.widget_unit) / but->block->aspect;
}
else if ((but->drawflag & UI_BUT_TEXT_RIGHT)) {

View File

@@ -165,6 +165,9 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
case SPACE_CLIP:
ts = &btheme->tclip;
break;
case SPACE_COLLECTIONS:
ts = &btheme->tcollections;
break;
default:
ts = &btheme->tv3d;
break;
@@ -1206,6 +1209,11 @@ void ui_theme_init_default(void)
rgba_char_args_set(btheme->tclip.strip_select, 0xff, 0x8c, 0x00, 0xff);
btheme->tclip.handle_vertex_size = 5;
ui_theme_space_init_handles_color(&btheme->tclip);
/* space collection manager */
btheme->tcollections = btheme->tv3d;
rgba_char_args_set_fl(btheme->tcollections.back, 0.42, 0.42, 0.42, 1.0);
rgba_char_args_set(btheme->tcollections.hilite, 255, 140, 25, 255); /* selected files */
}
void ui_style_init_default(void)
@@ -2834,7 +2842,11 @@ void init_userdef_do_versions(void)
* (keep this block even if it becomes empty).
*/
{
for (bTheme *btheme = U.themes.first; btheme; btheme = btheme->next) {
btheme->tcollections = btheme->tv3d;
rgba_char_args_set_fl(btheme->tcollections.back, 0.42, 0.42, 0.42, 1.0);
rgba_char_args_set(btheme->tcollections.hilite, 255, 140, 25, 255); /* selected files */
}
}
if (U.pixelsize == 0.0f)

View File

@@ -0,0 +1,498 @@
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file blender/editors/interface/table.c
* \ingroup edinterface
*/
#include <limits.h>
#include <string.h>
#include "BLI_alloca.h"
#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_mempool.h"
#include "BLI_rect.h"
#include "DNA_userdef_types.h"
#include "GPU_immediate.h"
#include "MEM_guardedalloc.h"
#include "UI_interface.h"
#include "UI_table.h"
typedef struct uiTable {
BLI_mempool *row_pool;
ListBase columns;
unsigned int tot_columns;
enum {
TABLE_FLOW_VERTICAL,
TABLE_FLOW_HORIZONTAL,
} flow_direction;
unsigned int max_width;
unsigned char rgb1[3];
unsigned char rgb2[3];
char flag;
} uiTable;
enum eTableFlags {
/* All rows have the same height. In this case we can avoid iterating
* over rows for calculations like intersection checks. */
TABLE_ROWS_CONSTANT_HEIGHT = (1 << 0),
TABLE_DRAW_BACKGROUND = (1 << 1),
};
typedef struct TableHorizontalFlow {
uiTable table;
/* if this height is reached, we split the table */
unsigned int max_height;
} TableHorizontalFlow;
/**
* This struct allows using either relative or absolute scales
* for size properties (only column widths right now).
*/
typedef struct uiTableSize {
enum uiTableUnit unit;
int value;
} uiTableSize;
typedef struct uiTableRow {
void *rowdata;
unsigned int height;
} uiTableRow;
typedef struct uiTableColumn {
struct uiTableColumn *next, *prev;
const char *idname;
const char *drawname;
uiTableSize width;
unsigned int min_width;
enum uiTableColumnAlignemt alignment;
uiTableCellDrawFunc cell_draw;
} uiTableColumn;
/* -------------------------------------------------------------------- */
struct TableColumnDrawInfo {
/* While drawing: Total width of the already drawn columns depending on alignment (left of right). */
unsigned int totwidth_left;
unsigned int totwidth_right;
/* Total width of all non-fixed width columns (having size in px instead of percent). */
unsigned int totwidth_nonfixed;
};
/**
* Iterate over all columns in \a table. Supports removing columns while iterating.
*/
#define TABLE_COLUMNS_ITER_BEGIN(table, column_name) \
for (uiTableColumn *column_name = (table)->columns.first, *column_name##_next; \
column_name; \
column_name = column_name##_next) \
{ \
column_name##_next = column_name->next;
#define TABLE_COLUMNS_ITER_END } (void)0
static void table_init(uiTable *table)
{
table->row_pool = BLI_mempool_create(sizeof(uiTableRow), 0, 64, BLI_MEMPOOL_ALLOW_ITER);
table->flag |= TABLE_ROWS_CONSTANT_HEIGHT;
}
static void table_column_free(uiTableColumn *column)
{
MEM_freeN(column);
}
static void table_columns_free(uiTable *table)
{
TABLE_COLUMNS_ITER_BEGIN(table, column)
{
table_column_free(column);
}
TABLE_COLUMNS_ITER_END;
}
static void table_row_height_set(uiTable *table, uiTableRow *row, unsigned int height)
{
row->height = height;
/* Figure out if the new height breaks the 'every row has the same height' state. If so, unset flag.
* To avoid any additional iterations, we just check if we need to set it again on drawing */
if (table->flag & TABLE_ROWS_CONSTANT_HEIGHT) {
uiTableRow *row_first = BLI_mempool_findelem(table->row_pool, 0);
if (row_first->height != row->height) {
table->flag &= ~TABLE_ROWS_CONSTANT_HEIGHT;
}
}
}
static unsigned int table_column_width_clamp(const uiTableColumn *column, const unsigned int maxwidth,
const unsigned int unclamped_width)
{
unsigned int width = unclamped_width;
CLAMP(width, column->min_width, maxwidth);
return width;
}
static unsigned int table_calc_tot_width_unfixed_columns(const uiTable *table)
{
unsigned int nonfixed_width = table->max_width;
TABLE_COLUMNS_ITER_BEGIN(table, column)
{
if (column->width.unit == TABLE_UNIT_PX) {
unsigned int width = table_column_width_clamp(column, table->max_width, column->width.value);
BLI_assert(nonfixed_width >= width);
nonfixed_width -= width;
}
}
TABLE_COLUMNS_ITER_END;
return nonfixed_width;
}
static struct TableColumnDrawInfo table_column_drawinfo_init(const uiTable *table)
{
struct TableColumnDrawInfo drawinfo = {};
drawinfo.totwidth_nonfixed = table_calc_tot_width_unfixed_columns(table);
BLI_assert(drawinfo.totwidth_nonfixed <= table->max_width);
return drawinfo;
}
static unsigned int table_column_calc_width(const uiTableColumn *column, const struct TableColumnDrawInfo *drawinfo,
const unsigned int maxwidth)
{
unsigned int width = column->width.value;
if (column->width.unit == TABLE_UNIT_PERCENT) {
CLAMP_MAX(width, 100); /* more than 100% doesn't make sense */
width = iroundf(width * 0.01f * drawinfo->totwidth_nonfixed);
}
return table_column_width_clamp(column, maxwidth, width);
}
/**
* Calculate the table-flow relative x-coordinates, meaning we don't account for horizontal-flow
* yet, the first column aligned to the left will just always be at xmin = 0.
*/
static void table_column_calc_x_coords(const uiTableColumn *column, const float max_width,
struct TableColumnDrawInfo *io_drawinfo,
int *r_xmin, int *r_xmax)
{
const unsigned int width = table_column_calc_width(column, io_drawinfo, max_width);
if (column->alignment == TABLE_COLUMN_ALIGN_LEFT) {
*r_xmin = io_drawinfo->totwidth_left;
*r_xmax = *r_xmin + width;
io_drawinfo->totwidth_left += width;
}
else {
BLI_assert(column->alignment == TABLE_COLUMN_ALIGN_RIGHT);
*r_xmax = max_width - io_drawinfo->totwidth_right;
*r_xmin = *r_xmax - width;
io_drawinfo->totwidth_right += width;
}
}
static void table_row_calc_y_coords(uiTable *table, uiTableRow *row,
unsigned int *io_ofs_x, unsigned int *io_ofs_y,
int *r_ymin, int *r_ymax)
{
unsigned int height = row->height;
if (table->flow_direction == TABLE_FLOW_HORIZONTAL) {
TableHorizontalFlow *horizontal_table = (TableHorizontalFlow *)table;
CLAMP_MAX(height, horizontal_table->max_height);
if ((*io_ofs_y + height) > horizontal_table->max_height) {
*io_ofs_x += table->max_width;
*io_ofs_y = 0;
}
}
/* Assuming inverted direction, from top to bottom. */
*r_ymax = -(*io_ofs_y);
*r_ymin = *r_ymax - height;
}
static void table_row_draw_background(const uiTable *table, const int row_index, const unsigned int height,
const unsigned int ofs_x, const unsigned int ofs_y)
{
if (table->flag & TABLE_DRAW_BACKGROUND) {
unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_INT, 2, CONVERT_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor3ubv((row_index % 2) ? table->rgb1 : table->rgb2);
/* remember, drawing is done top to bottom with upper left being (0, 0), use negative y coordinates */
immRecti(pos, ofs_x, -ofs_y, ofs_x + table->max_width, -(ofs_y + height));
immUnbindProgram();
}
}
/* -------------------------------------------------------------------- */
/** \name UI Table API
*
* Generic API to define, handle and draw tables with custom data types.
* Note, this API is purely for UI purposes, not data management.
*
* \{ */
uiTable *UI_table_vertical_flow_create(void)
{
uiTable *table = MEM_callocN(sizeof(*table), __func__);
table->flow_direction = TABLE_FLOW_VERTICAL;
table_init(table);
return table;
}
uiTable *UI_table_horizontal_flow_create(void)
{
TableHorizontalFlow *horizontal_table = MEM_callocN(sizeof(*horizontal_table), __func__);
horizontal_table->table.flow_direction = TABLE_FLOW_HORIZONTAL;
horizontal_table->max_height = UINT_MAX;
table_init(&horizontal_table->table);
return &horizontal_table->table;
}
void UI_table_free(uiTable *table)
{
table_columns_free(table);
BLI_mempool_destroy(table->row_pool);
MEM_freeN(table);
}
/**
* Set the maximum width a table can use.
* For horizontal-flow that would be the width of each section the table may be split into.
*/
void UI_table_max_width_set(uiTable *table, const unsigned int max_width)
{
table->max_width = max_width;
}
/**
* Set the height at which the table would be split;
*/
void UI_table_horizontal_flow_max_height_set(uiTable *table, const unsigned int max_height)
{
TableHorizontalFlow *horizontal_table = (TableHorizontalFlow *)table;
BLI_assert(table->flow_direction == TABLE_FLOW_HORIZONTAL);
horizontal_table->max_height = max_height;
}
void UI_table_background_colors_set(uiTable *table, const unsigned char rgb1[3], const unsigned char rgb2[3])
{
copy_v3_v3_uchar(table->rgb1, rgb1);
copy_v3_v3_uchar(table->rgb2, rgb2);
table->flag |= TABLE_DRAW_BACKGROUND;
}
/**
* Insert a new column into \a table with default parameters (100% available width, 0px min width, aligned to left).
*
* \param id_name: Identifier of the column. Has to be unique within this table!
* \param drawname: Name of the column that may be drawin in the UI. Allowed to be NULL.
* \param cell_draw: The callback to call when drawing a cell of this column type. Passes custom data stored in row.
*/
uiTableColumn *UI_table_column_add(uiTable *table, const char *idname, const char *drawname,
uiTableCellDrawFunc cell_draw)
{
uiTableColumn *col = MEM_callocN(sizeof(*col), __func__);
col->idname = idname;
col->drawname = drawname;
col->cell_draw = cell_draw;
col->alignment = TABLE_COLUMN_ALIGN_LEFT;
UI_table_column_width_set(col, 100, TABLE_UNIT_PERCENT, 0);
BLI_addtail(&table->columns, col);
table->tot_columns++;
return col;
}
void UI_table_column_remove(uiTable *table, uiTableColumn *column)
{
BLI_assert(BLI_findindex(&table->columns, column) != -1);
BLI_remlink(&table->columns, column);
table->tot_columns--;
}
uiTableColumn *UI_table_column_lookup(uiTable *table, const char *idname)
{
TABLE_COLUMNS_ITER_BEGIN(table, column)
{
if (STREQ(column->idname, idname)) {
return column;
}
}
TABLE_COLUMNS_ITER_END;
return NULL;
}
/**
* Set the size info for \a col.
* \param width: The width in either pixels (#UI_table_size_px), or percentage (#UI_table_size_percentage).
* \param min_width_px: Minimum width for the column (always in px).
*/
void UI_table_column_width_set(uiTableColumn *column, const unsigned int width, enum uiTableUnit unit,
const int min_width_px)
{
column->width.unit = unit;
column->width.value = width;
column->min_width = min_width_px;
}
void UI_table_column_alignment_set(uiTableColumn *column, enum uiTableColumnAlignemt alignment)
{
column->alignment = alignment;
}
/*
* Insert a new row into \a table with default parameters (height of UI_UNIT_Y). Should
* be fine to use this for inserting many rows at once. It's using BLI_mempool with a
* chunck size of 64, so it only allocates memory for every 65th element.
*
* \param rowdata: Custom data passed when drawing the row. It should contain
* enough information to draw all columns for this row.
*/
uiTableRow *UI_table_row_add(uiTable *table, void *rowdata)
{
uiTableRow *row = BLI_mempool_calloc(table->row_pool);
row->rowdata = rowdata;
table_row_height_set(table, row, UI_UNIT_Y);
return row;
}
void UI_table_row_height_set(uiTable *table, uiTableRow *row, unsigned int height)
{
table_row_height_set(table, row, height);
}
void UI_table_draw(uiTable *table, uiBlock *block, uiStyle *style)
{
struct TableColumnDrawInfo column_drawinfo = table_column_drawinfo_init(table);
struct {
int xmin;
int xmax;
} *column_xcoords = BLI_array_alloca(column_xcoords, table->tot_columns);
BLI_mempool_iter iter;
unsigned int prev_row_height = 0; /* to check if rows have consistent height */
unsigned int xofs = 0, yofs = 0;
bool consistent_row_height = true;
int row_index = 0;
BLI_mempool_iternew(table->row_pool, &iter);
for (uiTableRow *row = BLI_mempool_iterstep(&iter); row; row = BLI_mempool_iterstep(&iter)) {
rcti drawrect;
unsigned int draw_height;
int column_index = 0;
table_row_calc_y_coords(table, row, &xofs, &yofs, &drawrect.ymin, &drawrect.ymax);
draw_height = BLI_rcti_size_y(&drawrect);
/* check for consistent row height */
if ((row_index > 0) && (draw_height != prev_row_height)) {
consistent_row_height = false;
}
table_row_draw_background(table, row_index, draw_height, xofs, yofs);
TABLE_COLUMNS_ITER_BEGIN(table, column)
{
uiLayout *cell_layout = NULL;
if (row_index == 0) {
/* Store column x-coords for further iterations over this column. */
table_column_calc_x_coords(column, table->max_width, &column_drawinfo,
&column_xcoords[column_index].xmin,
&column_xcoords[column_index].xmax);
}
drawrect.xmin = column_xcoords[column_index].xmin;
drawrect.xmax = column_xcoords[column_index].xmax;
if (block && style) {
/* Room for optimization: UI_block_layout allocates memory twice, could be avoided by
* pre-allocating into an array (uiLayout would need some changes to support this). */
cell_layout = UI_block_layout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, drawrect.xmin, drawrect.ymax,
BLI_rcti_size_x(&drawrect), 0, 0, style);
}
column->cell_draw(cell_layout, row->rowdata, drawrect);
if (block) {
UI_block_layout_resolve(block, NULL, NULL);
}
column_index++;
}
TABLE_COLUMNS_ITER_END;
BLI_assert(column_index == table->tot_columns);
yofs += draw_height;
prev_row_height = draw_height;
row_index++;
}
if (consistent_row_height) {
table->flag |= TABLE_ROWS_CONSTANT_HEIGHT;
}
else {
BLI_assert((table->flag & TABLE_ROWS_CONSTANT_HEIGHT) == 0);
}
}
unsigned int UI_table_get_rowcount(const uiTable *table)
{
return BLI_mempool_count(table->row_pool);
}
/** \} */ /* UI Table API */

View File

@@ -47,6 +47,7 @@
#include "BLI_rand.h"
#include "BLI_sort_utils.h"
#include "BKE_layer.h"
#include "BKE_material.h"
#include "BKE_context.h"
#include "BKE_deform.h"
@@ -3010,9 +3011,9 @@ enum {
MESH_SEPARATE_LOOSE = 2,
};
static Base *mesh_separate_tagged(Main *bmain, Scene *scene, Base *base_old, BMesh *bm_old)
static ObjectBase *mesh_separate_tagged(Main *bmain, Scene *scene, SceneLayer *sl, ObjectBase *base_old, BMesh *bm_old)
{
Base *base_new;
ObjectBase *base_new;
Object *obedit = base_old->object;
BMesh *bm_new;
@@ -3031,11 +3032,11 @@ static Base *mesh_separate_tagged(Main *bmain, Scene *scene, Base *base_old, BMe
CustomData_bmesh_init_pool(&bm_new->ldata, bm_mesh_allocsize_default.totloop, BM_LOOP);
CustomData_bmesh_init_pool(&bm_new->pdata, bm_mesh_allocsize_default.totface, BM_FACE);
base_new = ED_object_add_duplicate(bmain, scene, base_old, USER_DUP_MESH);
base_new = ED_object_add_duplicate(bmain, scene, sl, base_old, USER_DUP_MESH);
/* DAG_relations_tag_update(bmain); */ /* normally would call directly after but in this case delay recalc */
assign_matarar(base_new->object, give_matarar(obedit), *give_totcolp(obedit)); /* new in 2.5 */
ED_base_object_select(base_new, BA_SELECT);
ED_object_base_select(base_new, BA_SELECT);
BMO_op_callf(bm_old, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE),
"duplicate geom=%hvef dest=%p", BM_ELEM_TAG, bm_new);
@@ -3057,7 +3058,7 @@ static Base *mesh_separate_tagged(Main *bmain, Scene *scene, Base *base_old, BMe
return base_new;
}
static bool mesh_separate_selected(Main *bmain, Scene *scene, Base *base_old, BMesh *bm_old)
static bool mesh_separate_selected(Main *bmain, Scene *scene, SceneLayer *sl, ObjectBase *base_old, BMesh *bm_old)
{
/* we may have tags from previous operators */
BM_mesh_elem_hflag_disable_all(bm_old, BM_FACE | BM_EDGE | BM_VERT, BM_ELEM_TAG, false);
@@ -3065,7 +3066,7 @@ static bool mesh_separate_selected(Main *bmain, Scene *scene, Base *base_old, BM
/* sel -> tag */
BM_mesh_elem_hflag_enable_test(bm_old, BM_FACE | BM_EDGE | BM_VERT, BM_ELEM_TAG, true, false, BM_ELEM_SELECT);
return (mesh_separate_tagged(bmain, scene, base_old, bm_old) != NULL);
return (mesh_separate_tagged(bmain, scene, sl, base_old, bm_old) != NULL);
}
/* flush a hflag to from verts to edges/faces */
@@ -3164,14 +3165,14 @@ static void mesh_separate_material_assign_mat_nr(Main *bmain, Object *ob, const
}
}
static bool mesh_separate_material(Main *bmain, Scene *scene, Base *base_old, BMesh *bm_old)
static bool mesh_separate_material(Main *bmain, Scene *scene, SceneLayer *sl, ObjectBase *base_old, BMesh *bm_old)
{
BMFace *f_cmp, *f;
BMIter iter;
bool result = false;
while ((f_cmp = BM_iter_at_index(bm_old, BM_FACES_OF_MESH, NULL, 0))) {
Base *base_new;
ObjectBase *base_new;
const short mat_nr = f_cmp->mat_nr;
int tot = 0;
@@ -3205,7 +3206,7 @@ static bool mesh_separate_material(Main *bmain, Scene *scene, Base *base_old, BM
}
/* Move selection into a separate object */
base_new = mesh_separate_tagged(bmain, scene, base_old, bm_old);
base_new = mesh_separate_tagged(bmain, scene, sl, base_old, bm_old);
if (base_new) {
mesh_separate_material_assign_mat_nr(bmain, base_new->object, mat_nr);
}
@@ -3216,7 +3217,7 @@ static bool mesh_separate_material(Main *bmain, Scene *scene, Base *base_old, BM
return result;
}
static bool mesh_separate_loose(Main *bmain, Scene *scene, Base *base_old, BMesh *bm_old)
static bool mesh_separate_loose(Main *bmain, Scene *scene, SceneLayer *sl, ObjectBase *base_old, BMesh *bm_old)
{
int i;
BMEdge *e;
@@ -3269,7 +3270,7 @@ static bool mesh_separate_loose(Main *bmain, Scene *scene, Base *base_old, BMesh
bm_mesh_hflag_flush_vert(bm_old, BM_ELEM_TAG);
/* Move selection into a separate object */
result |= (mesh_separate_tagged(bmain, scene, base_old, bm_old) != NULL);
result |= (mesh_separate_tagged(bmain, scene, sl, base_old, bm_old) != NULL);
}
return result;
@@ -3279,11 +3280,12 @@ static int edbm_separate_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
SceneLayer *sl = CTX_data_scene_layer(C);
const int type = RNA_enum_get(op->ptr, "type");
int retval = 0;
if (ED_operator_editmesh(C)) {
Base *base = CTX_data_active_base(C);
ObjectBase *base = CTX_data_active_base(C);
BMEditMesh *em = BKE_editmesh_from_object(base->object);
if (type == 0) {
@@ -3299,13 +3301,13 @@ static int edbm_separate_exec(bContext *C, wmOperator *op)
/* editmode separate */
switch (type) {
case MESH_SEPARATE_SELECTED:
retval = mesh_separate_selected(bmain, scene, base, em->bm);
retval = mesh_separate_selected(bmain, scene, sl, base, em->bm);
break;
case MESH_SEPARATE_MATERIAL:
retval = mesh_separate_material(bmain, scene, base, em->bm);
retval = mesh_separate_material(bmain, scene, sl, base, em->bm);
break;
case MESH_SEPARATE_LOOSE:
retval = mesh_separate_loose(bmain, scene, base, em->bm);
retval = mesh_separate_loose(bmain, scene, sl, base, em->bm);
break;
default:
BLI_assert(0);
@@ -3323,7 +3325,7 @@ static int edbm_separate_exec(bContext *C, wmOperator *op)
}
/* object mode separate */
CTX_DATA_BEGIN(C, Base *, base_iter, selected_editable_bases)
CTX_DATA_BEGIN(C, ObjectBase *, base_iter, selected_editable_bases)
{
Object *ob = base_iter->object;
if (ob->type == OB_MESH) {
@@ -3340,10 +3342,10 @@ static int edbm_separate_exec(bContext *C, wmOperator *op)
switch (type) {
case MESH_SEPARATE_MATERIAL:
retval_iter = mesh_separate_material(bmain, scene, base_iter, bm_old);
retval_iter = mesh_separate_material(bmain, scene, sl, base_iter, bm_old);
break;
case MESH_SEPARATE_LOOSE:
retval_iter = mesh_separate_loose(bmain, scene, base_iter, bm_old);
retval_iter = mesh_separate_loose(bmain, scene, sl, base_iter, bm_old);
break;
default:
BLI_assert(0);

View File

@@ -461,14 +461,15 @@ static Object *createRepresentation(bContext *C, struct recast_polyMesh *pmesh,
static int navmesh_create_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
SceneLayer *sl = CTX_data_scene_layer(C);
LinkNode *obs = NULL;
Base *navmeshBase = NULL;
CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
CTX_DATA_BEGIN (C, ObjectBase *, base, selected_editable_bases)
{
if (base->object->type == OB_MESH) {
if (base->object->body_type == OB_BODY_TYPE_NAVMESH) {
if (!navmeshBase || base == scene->basact) {
if (!navmeshBase || base == sl->basact) {
navmeshBase = base;
}
}

View File

@@ -109,7 +109,7 @@ int join_mesh_exec(bContext *C, wmOperator *op)
}
/* count & check */
CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
CTX_DATA_BEGIN (C, ObjectBase *, base, selected_editable_bases)
{
if (base->object->type == OB_MESH) {
me = base->object->data;
@@ -188,7 +188,7 @@ int join_mesh_exec(bContext *C, wmOperator *op)
}
/* first pass over objects - copying materials and vertexgroups across */
CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
CTX_DATA_BEGIN (C, ObjectBase *, base, selected_editable_bases)
{
/* only act if a mesh, and not the one we're joining to */
if ((ob != base->object) && (base->object->type == OB_MESH)) {
@@ -302,7 +302,7 @@ int join_mesh_exec(bContext *C, wmOperator *op)
/* inverse transform for all selected meshes in this object */
invert_m4_m4(imat, ob->obmat);
CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
CTX_DATA_BEGIN (C, ObjectBase *, base, selected_editable_bases)
{
/* only join if this is a mesh */
if (base->object->type == OB_MESH) {
@@ -481,7 +481,7 @@ int join_mesh_exec(bContext *C, wmOperator *op)
/* free base, now that data is merged */
if (base->object != ob)
ED_base_object_free_and_unlink(bmain, scene, base);
ED_base_object_free_and_unlink(bmain, scene, base->object);
}
}
CTX_DATA_END;
@@ -589,7 +589,7 @@ int join_mesh_shapes_exec(bContext *C, wmOperator *op)
KeyBlock *kb;
bool ok = false, nonequal_verts = false;
CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
CTX_DATA_BEGIN (C, ObjectBase *, base, selected_editable_bases)
{
if (base->object == ob) continue;
@@ -622,7 +622,7 @@ int join_mesh_shapes_exec(bContext *C, wmOperator *op)
}
/* now ready to add new keys from selected meshes */
CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
CTX_DATA_BEGIN (C, ObjectBase *, base, selected_editable_bases)
{
if (base->object == ob) continue;

View File

@@ -63,6 +63,7 @@
#include "BKE_animsys.h"
#include "BKE_armature.h"
#include "BKE_camera.h"
#include "BKE_collection.h"
#include "BKE_context.h"
#include "BKE_curve.h"
#include "BKE_depsgraph.h"
@@ -73,6 +74,7 @@
#include "BKE_group.h"
#include "BKE_lamp.h"
#include "BKE_lattice.h"
#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_library_query.h"
#include "BKE_library_remap.h"
@@ -204,7 +206,7 @@ void ED_object_rotation_from_view(bContext *C, float rot[3], const char align_ax
}
}
void ED_object_base_init_transform(bContext *C, Base *base, const float loc[3], const float rot[3])
void ED_object_base_init_transform(bContext *C, ObjectBase *base, const float loc[3], const float rot[3])
{
Object *ob = base->object;
Scene *scene = CTX_data_scene(C);
@@ -405,10 +407,11 @@ Object *ED_object_add_type(
bContext *C,
int type, const char *name,
const float loc[3], const float rot[3],
bool enter_editmode, unsigned int layer)
bool enter_editmode, unsigned int UNUSED(layer))
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
SceneLayer *sl = CTX_data_scene_layer(C);
Object *ob;
/* for as long scene has editmode... */
@@ -416,13 +419,12 @@ Object *ED_object_add_type(
ED_object_editmode_exit(C, EM_FREEDATA | EM_FREEUNDO | EM_WAITCURSOR | EM_DO_UNDO); /* freedata, and undo */
/* deselects all, sets scene->basact */
ob = BKE_object_add(bmain, scene, type, name);
BASACT->lay = ob->lay = layer;
ob = BKE_object_add(bmain, scene, sl, type, name);
/* editor level activate, notifiers */
ED_base_object_activate(C, BASACT);
ED_object_base_activate(C, sl->basact);
/* more editor stuff */
ED_object_base_init_transform(C, BASACT, loc, rot);
ED_object_base_init_transform(C, sl->basact, loc, rot);
/* Ignore collisions by default for non-mesh objects */
if (type != OB_MESH) {
@@ -1109,21 +1111,19 @@ static void object_delete_check_glsl_update(Object *ob)
/* remove base from a specific scene */
/* note: now unlinks constraints as well */
void ED_base_object_free_and_unlink(Main *bmain, Scene *scene, Base *base)
void ED_base_object_free_and_unlink(Main *bmain, Scene *scene, Object *ob)
{
if (BKE_library_ID_is_indirectly_used(bmain, base->object) &&
ID_REAL_USERS(base->object) <= 1 && ID_EXTRA_USERS(base->object) == 0)
if (BKE_library_ID_is_indirectly_used(bmain, ob) &&
ID_REAL_USERS(ob) <= 1 && ID_EXTRA_USERS(ob) == 0)
{
/* We cannot delete indirectly used object... */
printf("WARNING, undeletable object '%s', should have been catched before reaching this function!",
base->object->id.name + 2);
ob->id.name + 2);
return;
}
BKE_scene_base_unlink(scene, base);
object_delete_check_glsl_update(base->object);
BKE_libblock_free_us(bmain, base->object);
MEM_freeN(base);
object_delete_check_glsl_update(ob);
BKE_collections_object_remove(bmain, scene, ob, true);
DAG_id_type_tag(bmain, ID_OB);
}
@@ -1139,56 +1139,46 @@ static int object_delete_exec(bContext *C, wmOperator *op)
if (CTX_data_edit_object(C))
return OPERATOR_CANCELLED;
CTX_DATA_BEGIN (C, Base *, base, selected_bases)
CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
{
const bool is_indirectly_used = BKE_library_ID_is_indirectly_used(bmain, base->object);
if (base->object->id.tag & LIB_TAG_INDIRECT) {
const bool is_indirectly_used = BKE_library_ID_is_indirectly_used(bmain, ob);
if (ob->id.tag & LIB_TAG_INDIRECT) {
/* Can this case ever happen? */
BKE_reportf(op->reports, RPT_WARNING, "Cannot delete indirectly linked object '%s'", base->object->id.name + 2);
BKE_reportf(op->reports, RPT_WARNING, "Cannot delete indirectly linked object '%s'", ob->id.name + 2);
continue;
}
else if (is_indirectly_used && ID_REAL_USERS(base->object) <= 1 && ID_EXTRA_USERS(base->object) == 0) {
else if (is_indirectly_used && ID_REAL_USERS(ob) <= 1 && ID_EXTRA_USERS(ob) == 0) {
BKE_reportf(op->reports, RPT_WARNING,
"Cannot delete object '%s' from scene '%s', indirectly used objects need at least one user",
base->object->id.name + 2, scene->id.name + 2);
ob->id.name + 2, scene->id.name + 2);
continue;
}
/* remove from Grease Pencil parent */
for (bGPdata *gpd = bmain->gpencil.first; gpd; gpd = gpd->id.next) {
for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
if (gpl->parent != NULL) {
Object *ob = gpl->parent;
Object *curob = base->object;
if (ob == curob) {
if (gpl->parent == ob) {
gpl->parent = NULL;
}
}
}
}
/* deselect object -- it could be used in other scenes */
base->object->flag &= ~SELECT;
/* remove from current scene only */
ED_base_object_free_and_unlink(bmain, scene, base);
ED_base_object_free_and_unlink(bmain, scene, ob);
changed = true;
if (use_global) {
Scene *scene_iter;
Base *base_other;
for (scene_iter = bmain->scene.first; scene_iter; scene_iter = scene_iter->id.next) {
if (scene_iter != scene && !ID_IS_LINKED_DATABLOCK(scene_iter)) {
base_other = BKE_scene_base_find(scene_iter, base->object);
if (base_other) {
if (is_indirectly_used && ID_REAL_USERS(base->object) <= 1 && ID_EXTRA_USERS(base->object) == 0) {
BKE_reportf(op->reports, RPT_WARNING,
"Cannot delete object '%s' from scene '%s', indirectly used objects need at least one user",
base->object->id.name + 2, scene_iter->id.name + 2);
break;
}
ED_base_object_free_and_unlink(bmain, scene_iter, base_other);
if (is_indirectly_used && ID_REAL_USERS(ob) <= 1 && ID_EXTRA_USERS(ob) == 0) {
BKE_reportf(op->reports, RPT_WARNING,
"Cannot delete object '%s' from scene '%s', indirectly used objects need at least one user",
ob->id.name + 2, scene_iter->id.name + 2);
break;
}
ED_base_object_free_and_unlink(bmain, scene_iter, ob);
}
}
}
@@ -1324,11 +1314,12 @@ static bool dupliobject_cmp(const void *a_, const void *b_)
return false;
}
static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
static void make_object_duplilist_real(bContext *C, Scene *scene, ObjectBase *base,
const bool use_base_parent,
const bool use_hierarchy)
{
Main *bmain = CTX_data_main(C);
SceneLayer *sl = CTX_data_scene_layer(C);
ListBase *lb;
DupliObject *dob;
GHash *dupli_gh = NULL, *parent_gh = NULL;
@@ -1352,7 +1343,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
}
for (dob = lb->first; dob; dob = dob->next) {
Base *basen;
ObjectBase *basen;
Object *ob = ID_NEW_SET(dob->ob, BKE_object_copy(bmain, dob->ob));
/* font duplis can have a totcol without material, we get them from parent
@@ -1360,12 +1351,10 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
*/
if (ob->mat == NULL) ob->totcol = 0;
basen = MEM_dupallocN(base);
basen->flag &= ~(OB_FROMDUPLI | OB_FROMGROUP);
ob->flag = basen->flag;
basen->lay = base->lay;
BLI_addhead(&scene->base, basen); /* addhead: othwise eternal loop */
basen->object = ob;
BKE_collection_object_add_from(scene, dob->ob, ob);
basen = BKE_scene_layer_base_find(sl, ob);
BKE_scene_object_base_flag_sync_from_base(basen);
/* make sure apply works */
BKE_animdata_free(&ob->id, true);
@@ -1380,7 +1369,6 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
BLI_listbase_clear(&ob->constraints);
ob->curve_cache = NULL;
ob->transflag &= ~OB_DUPLI;
ob->lay = base->lay;
copy_m4_m4(ob->obmat, dob->mat);
BKE_object_apply_mat4(ob, ob->obmat, false, false);
@@ -1507,7 +1495,7 @@ static int object_duplicates_make_real_exec(bContext *C, wmOperator *op)
BKE_main_id_clear_newpoins(bmain);
CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
CTX_DATA_BEGIN (C, ObjectBase *, base, selected_editable_bases)
{
make_object_duplilist_real(C, scene, base, use_base_parent, use_hierarchy);
@@ -1589,10 +1577,10 @@ static int convert_poll(bContext *C)
}
/* Helper for convert_exec */
static Base *duplibase_for_convert(Main *bmain, Scene *scene, Base *base, Object *ob)
static ObjectBase *duplibase_for_convert(Main *bmain, Scene *scene, SceneLayer *sl, ObjectBase *base, Object *ob)
{
Object *obn;
Base *basen;
ObjectBase *basen;
if (ob == NULL) {
ob = base->object;
@@ -1600,16 +1588,11 @@ static Base *duplibase_for_convert(Main *bmain, Scene *scene, Base *base, Object
obn = BKE_object_copy(bmain, ob);
DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
BKE_collection_object_add_from(scene, ob, obn);
basen = MEM_mallocN(sizeof(Base), "duplibase");
*basen = *base;
BLI_addhead(&scene->base, basen); /* addhead: otherwise eternal loop */
basen->object = obn;
basen->flag |= SELECT;
obn->flag |= SELECT;
base->flag &= ~SELECT;
ob->flag &= ~SELECT;
basen = BKE_scene_layer_base_find(sl, obn);
ED_object_base_select(basen, BA_SELECT);
ED_object_base_select(basen, BA_DESELECT);
return basen;
}
@@ -1617,7 +1600,8 @@ static int convert_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
Base *basen = NULL, *basact = NULL;
SceneLayer *sl = CTX_data_scene_layer(C);
ObjectBase *basen = NULL, *basact = NULL;
Object *ob, *ob1, *newob, *obact = CTX_data_active_object(C);
DerivedMesh *dm;
Curve *cu;
@@ -1655,7 +1639,7 @@ static int convert_exec(bContext *C, wmOperator *op)
}
}
CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
CTX_DATA_BEGIN (C, ObjectBase *, base, selected_editable_bases)
{
ob = base->object;
@@ -1678,7 +1662,7 @@ static int convert_exec(bContext *C, wmOperator *op)
ob->flag |= OB_DONE;
if (keep_original) {
basen = duplibase_for_convert(bmain, scene, base, NULL);
basen = duplibase_for_convert(bmain, scene, sl, base, NULL);
newob = basen->object;
/* decrement original mesh's usage count */
@@ -1703,7 +1687,7 @@ static int convert_exec(bContext *C, wmOperator *op)
ob->flag |= OB_DONE;
if (keep_original) {
basen = duplibase_for_convert(bmain, scene, base, NULL);
basen = duplibase_for_convert(bmain, scene, sl, base, NULL);
newob = basen->object;
/* decrement original mesh's usage count */
@@ -1735,7 +1719,7 @@ static int convert_exec(bContext *C, wmOperator *op)
ob->flag |= OB_DONE;
if (keep_original) {
basen = duplibase_for_convert(bmain, scene, base, NULL);
basen = duplibase_for_convert(bmain, scene, sl, base, NULL);
newob = basen->object;
/* decrement original curve's usage count */
@@ -1806,7 +1790,7 @@ static int convert_exec(bContext *C, wmOperator *op)
if (target == OB_MESH) {
if (keep_original) {
basen = duplibase_for_convert(bmain, scene, base, NULL);
basen = duplibase_for_convert(bmain, scene, sl, base, NULL);
newob = basen->object;
/* decrement original curve's usage count */
@@ -1841,7 +1825,7 @@ static int convert_exec(bContext *C, wmOperator *op)
if (!(baseob->flag & OB_DONE)) {
baseob->flag |= OB_DONE;
basen = duplibase_for_convert(bmain, scene, base, baseob);
basen = duplibase_for_convert(bmain, scene, sl, base, baseob);
newob = basen->object;
mb = newob->data;
@@ -1892,23 +1876,21 @@ static int convert_exec(bContext *C, wmOperator *op)
if (!keep_original) {
if (mballConverted) {
Base *base, *base_next;
for (base = scene->base.first; base; base = base_next) {
base_next = base->next;
ob = base->object;
Object *ob_mball;
FOREACH_SCENE_OBJECT(scene, ob_mball)
{
if (ob->type == OB_MBALL) {
if (ob->flag & OB_DONE) {
Object *ob_basis = NULL;
if (BKE_mball_is_basis(ob) ||
((ob_basis = BKE_mball_basis_find(scene, ob)) && (ob_basis->flag & OB_DONE)))
if (BKE_mball_is_basis(ob_mball) ||
((ob_basis = BKE_mball_basis_find(scene, ob_mball)) && (ob_basis->flag & OB_DONE)))
{
ED_base_object_free_and_unlink(bmain, scene, base);
ED_base_object_free_and_unlink(bmain, scene, ob_mball);
}
}
}
}
FOREACH_SCENE_OBJECT_END
}
/* delete object should renew depsgraph */
@@ -1920,12 +1902,12 @@ static int convert_exec(bContext *C, wmOperator *op)
if (basact) {
/* active base was changed */
ED_base_object_activate(C, basact);
BASACT = basact;
ED_object_base_activate(C, basact);
BASACT_NEW = basact;
}
else if (BASACT->object->flag & OB_DONE) {
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, BASACT->object);
WM_event_add_notifier(C, NC_OBJECT | ND_DATA, BASACT->object);
else if (BASACT_NEW->object->flag & OB_DONE) {
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, BASACT_NEW->object);
WM_event_add_notifier(C, NC_OBJECT | ND_DATA, BASACT_NEW->object);
}
DAG_relations_tag_update(bmain);
@@ -1967,18 +1949,17 @@ void OBJECT_OT_convert(wmOperatorType *ot)
/* used below, assumes id.new is correct */
/* leaves selection of base/object unaltered */
/* Does set ID->newid pointers. */
static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base, int dupflag)
static ObjectBase *object_add_duplicate_internal(Main *bmain, Scene *scene, SceneLayer *sl, Object *ob, int dupflag)
{
#define ID_NEW_REMAP_US(a) if ( (a)->id.newid) { (a) = (void *)(a)->id.newid; (a)->id.us++; }
#define ID_NEW_REMAP_US2(a) if (((ID *)a)->newid) { (a) = ((ID *)a)->newid; ((ID *)a)->us++; }
Base *basen = NULL;
ObjectBase *basen = NULL;
Material ***matarar;
Object *ob, *obn;
Object *obn;
ID *id;
int a, didit;
ob = base->object;
if (ob->mode & OB_MODE_POSE) {
; /* nothing? */
}
@@ -1986,20 +1967,18 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
obn = ID_NEW_SET(ob, BKE_object_copy(bmain, ob));
DAG_id_tag_update(&obn->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
basen = MEM_mallocN(sizeof(Base), "duplibase");
*basen = *base;
BLI_addhead(&scene->base, basen); /* addhead: prevent eternal loop */
basen->object = obn;
BKE_collection_object_add_from(scene, ob, obn);
basen = BKE_scene_layer_base_find(sl, obn);
/* 1) duplis should end up in same group as the original
* 2) Rigid Body sim participants MUST always be part of a group...
*/
// XXX: is 2) really a good measure here?
if ((basen->flag & OB_FROMGROUP) || ob->rigidbody_object || ob->rigidbody_constraint) {
if ((ob->flag & OB_FROMGROUP) != 0 || ob->rigidbody_object || ob->rigidbody_constraint) {
Group *group;
for (group = bmain->group.first; group; group = group->id.next) {
if (BKE_group_object_exists(group, ob))
BKE_group_object_add(group, obn, scene, basen);
BKE_group_object_add(group, obn);
}
}
@@ -2207,14 +2186,14 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
* note: don't call this within a loop since clear_* funcs loop over the entire database.
* note: caller must do DAG_relations_tag_update(bmain);
* this is not done automatic since we may duplicate many objects in a batch */
Base *ED_object_add_duplicate(Main *bmain, Scene *scene, Base *base, int dupflag)
ObjectBase *ED_object_add_duplicate(Main *bmain, Scene *scene, SceneLayer *sl, ObjectBase *base, int dupflag)
{
Base *basen;
ObjectBase *basen;
Object *ob;
clear_sca_new_poins(); /* BGE logic */
basen = object_add_duplicate_internal(bmain, scene, base, dupflag);
basen = object_add_duplicate_internal(bmain, scene, sl, base->object, dupflag);
if (basen == NULL) {
return NULL;
}
@@ -2241,26 +2220,27 @@ static int duplicate_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
SceneLayer *sl = CTX_data_scene_layer(C);
const bool linked = RNA_boolean_get(op->ptr, "linked");
int dupflag = (linked) ? 0 : U.dupflag;
clear_sca_new_poins(); /* BGE logic */
CTX_DATA_BEGIN (C, Base *, base, selected_bases)
CTX_DATA_BEGIN (C, ObjectBase *, base, selected_bases)
{
Base *basen = object_add_duplicate_internal(bmain, scene, base, dupflag);
ObjectBase *basen = object_add_duplicate_internal(bmain, scene, sl, base->object, dupflag);
/* note that this is safe to do with this context iterator,
* the list is made in advance */
ED_base_object_select(base, BA_DESELECT);
ED_object_base_select(base, BA_DESELECT);
if (basen == NULL) {
continue;
}
/* new object becomes active */
if (BASACT == base)
ED_base_object_activate(C, basen);
if (BASACT_NEW == base)
ED_object_base_activate(C, basen);
if (basen->object->data) {
DAG_id_tag_update(basen->object->data, 0);
@@ -2308,9 +2288,9 @@ static int add_named_exec(bContext *C, wmOperator *op)
wmWindow *win = CTX_wm_window(C);
const wmEvent *event = win ? win->eventstate : NULL;
Main *bmain = CTX_data_main(C);
View3D *v3d = CTX_wm_view3d(C); /* may be NULL */
Scene *scene = CTX_data_scene(C);
Base *basen, *base;
SceneLayer *sl = CTX_data_scene_layer(C);
ObjectBase *basen;
Object *ob;
const bool linked = RNA_boolean_get(op->ptr, "linked");
int dupflag = (linked) ? 0 : U.dupflag;
@@ -2325,22 +2305,17 @@ static int add_named_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
base = MEM_callocN(sizeof(Base), "duplibase");
base->object = ob;
base->flag = ob->flag;
/* prepare dupli */
clear_sca_new_poins(); /* BGE logic */
basen = object_add_duplicate_internal(bmain, scene, base, dupflag);
basen = object_add_duplicate_internal(bmain, scene, sl, ob, dupflag);
BKE_scene_object_base_flag_sync_from_object(basen);
if (basen == NULL) {
MEM_freeN(base);
BKE_report(op->reports, RPT_ERROR, "Object could not be duplicated");
return OPERATOR_CANCELLED;
}
basen->lay = basen->object->lay = BKE_screen_view3d_layer_active(v3d, scene);
basen->object->restrictflag &= ~OB_RESTRICT_VIEW;
if (event) {
@@ -2351,8 +2326,8 @@ static int add_named_exec(bContext *C, wmOperator *op)
ED_view3d_cursor3d_position(C, basen->object->loc, mval);
}
ED_base_object_select(basen, BA_SELECT);
ED_base_object_activate(C, basen);
ED_object_base_select(basen, BA_SELECT);
ED_object_base_activate(C, basen);
copy_object_set_idnew(C);
@@ -2360,8 +2335,6 @@ static int add_named_exec(bContext *C, wmOperator *op)
DAG_relations_tag_update(bmain);
MEM_freeN(base);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT | ND_OB_ACTIVE, scene);
return OPERATOR_FINISHED;

View File

@@ -116,7 +116,7 @@ static bool multiresbake_check(bContext *C, wmOperator *op)
bool ok = true;
int a;
CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
CTX_DATA_BEGIN (C, ObjectBase *, base, selected_editable_bases)
{
ob = base->object;
@@ -310,7 +310,7 @@ static int multiresbake_image_exec_locked(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
if (scene->r.bake_flag & R_BAKE_CLEAR) { /* clear images */
CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
CTX_DATA_BEGIN (C, ObjectBase *, base, selected_editable_bases)
{
Mesh *me;
ClearFlag clear_flag = 0;
@@ -330,7 +330,7 @@ static int multiresbake_image_exec_locked(bContext *C, wmOperator *op)
CTX_DATA_END;
}
CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
CTX_DATA_BEGIN (C, ObjectBase *, base, selected_editable_bases)
{
MultiresBakeRender bkr = {NULL};
@@ -390,7 +390,7 @@ static void init_multiresbake_job(bContext *C, MultiresBakeJob *bkj)
bkj->user_scale = (scene->r.bake_flag & R_BAKE_USERSCALE) ? scene->r.bake_user_scale : -1.0f;
//bkj->reports = op->reports;
CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
CTX_DATA_BEGIN (C, ObjectBase *, base, selected_editable_bases)
{
MultiresBakerJobData *data;
int lvl;

View File

@@ -1682,11 +1682,12 @@ static bool get_new_constraint_target(bContext *C, int con_type, Object **tar_ob
if ((found == false) && (add)) {
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
SceneLayer *sl = CTX_data_scene_layer(C);
Base *base = BASACT, *newbase = NULL;
Object *obt;
/* add new target object */
obt = BKE_object_add(bmain, scene, OB_EMPTY, NULL);
obt = BKE_object_add(bmain, scene, sl, OB_EMPTY, NULL);
/* set layers OK */
newbase = BASACT;

View File

@@ -132,189 +132,6 @@ Object *ED_object_active_context(bContext *C)
}
/* ********* clear/set restrict view *********/
static int object_hide_view_clear_exec(bContext *C, wmOperator *UNUSED(op))
{
Main *bmain = CTX_data_main(C);
ScrArea *sa = CTX_wm_area(C);
View3D *v3d = sa->spacedata.first;
Scene *scene = CTX_data_scene(C);
Base *base;
bool changed = false;
/* XXX need a context loop to handle such cases */
for (base = FIRSTBASE; base; base = base->next) {
if ((base->lay & v3d->lay) && base->object->restrictflag & OB_RESTRICT_VIEW) {
if (!(base->object->restrictflag & OB_RESTRICT_SELECT)) {
base->flag |= SELECT;
}
base->object->flag = base->flag;
base->object->restrictflag &= ~OB_RESTRICT_VIEW;
changed = true;
}
}
if (changed) {
DAG_id_type_tag(bmain, ID_OB);
DAG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
}
return OPERATOR_FINISHED;
}
void OBJECT_OT_hide_view_clear(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Clear Restrict View";
ot->description = "Reveal the object by setting the hide flag";
ot->idname = "OBJECT_OT_hide_view_clear";
/* api callbacks */
ot->exec = object_hide_view_clear_exec;
ot->poll = ED_operator_view3d_active;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int object_hide_view_set_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
bool changed = false;
const bool unselected = RNA_boolean_get(op->ptr, "unselected");
CTX_DATA_BEGIN(C, Base *, base, visible_bases)
{
if (!unselected) {
if (base->flag & SELECT) {
base->flag &= ~SELECT;
base->object->flag = base->flag;
base->object->restrictflag |= OB_RESTRICT_VIEW;
changed = true;
if (base == BASACT) {
ED_base_object_activate(C, NULL);
}
}
}
else {
if (!(base->flag & SELECT)) {
base->object->restrictflag |= OB_RESTRICT_VIEW;
changed = true;
if (base == BASACT) {
ED_base_object_activate(C, NULL);
}
}
}
}
CTX_DATA_END;
if (changed) {
DAG_id_type_tag(bmain, ID_OB);
DAG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
}
return OPERATOR_FINISHED;
}
void OBJECT_OT_hide_view_set(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Set Restrict View";
ot->description = "Hide the object by setting the hide flag";
ot->idname = "OBJECT_OT_hide_view_set";
/* api callbacks */
ot->exec = object_hide_view_set_exec;
ot->poll = ED_operator_view3d_active;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected objects");
}
/* 99% same as above except no need for scene refreshing (TODO, update render preview) */
static int object_hide_render_clear_exec(bContext *C, wmOperator *UNUSED(op))
{
bool changed = false;
/* XXX need a context loop to handle such cases */
CTX_DATA_BEGIN(C, Object *, ob, selected_editable_objects)
{
if (ob->restrictflag & OB_RESTRICT_RENDER) {
ob->restrictflag &= ~OB_RESTRICT_RENDER;
changed = true;
}
}
CTX_DATA_END;
if (changed)
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_OUTLINER, NULL);
return OPERATOR_FINISHED;
}
void OBJECT_OT_hide_render_clear(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Clear Restrict Render";
ot->description = "Reveal the render object by setting the hide render flag";
ot->idname = "OBJECT_OT_hide_render_clear";
/* api callbacks */
ot->exec = object_hide_render_clear_exec;
ot->poll = ED_operator_view3d_active;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int object_hide_render_set_exec(bContext *C, wmOperator *op)
{
const bool unselected = RNA_boolean_get(op->ptr, "unselected");
CTX_DATA_BEGIN(C, Base *, base, visible_bases)
{
if (!unselected) {
if (base->flag & SELECT) {
base->object->restrictflag |= OB_RESTRICT_RENDER;
}
}
else {
if (!(base->flag & SELECT)) {
base->object->restrictflag |= OB_RESTRICT_RENDER;
}
}
}
CTX_DATA_END;
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_OUTLINER, NULL);
return OPERATOR_FINISHED;
}
void OBJECT_OT_hide_render_set(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Set Restrict Render";
ot->description = "Hide the render object by setting the hide render flag";
ot->idname = "OBJECT_OT_hide_render_set";
/* api callbacks */
ot->exec = object_hide_render_set_exec;
ot->poll = ED_operator_view3d_active;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected objects");
}
/* ******************* toggle editmode operator ***************** */
static bool mesh_needs_keyindex(const Mesh *me)
@@ -465,31 +282,22 @@ void ED_object_editmode_exit(bContext *C, int flag)
void ED_object_editmode_enter(bContext *C, int flag)
{
Scene *scene = CTX_data_scene(C);
Base *base = NULL;
SceneLayer *sl = CTX_data_scene_layer(C);
Object *ob;
ScrArea *sa = CTX_wm_area(C);
View3D *v3d = NULL;
bool ok = false;
if (ID_IS_LINKED_DATABLOCK(scene)) return;
if (sa && sa->spacetype == SPACE_VIEW3D)
v3d = sa->spacedata.first;
if ((flag & EM_IGNORE_LAYER) == 0) {
base = CTX_data_active_base(C); /* active layer checked here for view3d */
ob = CTX_data_active_object(C); /* active layer checked here for view3d */
if (base == NULL) return;
else if (v3d && (base->lay & v3d->lay) == 0) return;
else if (!v3d && (base->lay & scene->lay) == 0) return;
if (ob == NULL) return;
}
else {
base = scene->basact;
ob = sl->basact->object;
}
if (ELEM(NULL, base, base->object, base->object->data)) return;
ob = base->object;
if (ELEM(NULL, ob, ob->data)) return;
/* this checks actual object->data, for cases when other scenes have it in editmode context */
if (BKE_object_is_in_editmode(ob))
@@ -652,7 +460,7 @@ void OBJECT_OT_editmode_toggle(wmOperatorType *ot)
static int posemode_exec(bContext *C, wmOperator *op)
{
Base *base = CTX_data_active_base(C);
ObjectBase *base = CTX_data_active_base(C);
Object *ob = base->object;
const int mode_flag = OB_MODE_POSE;
const bool is_mode_set = (ob->mode & mode_flag) != 0;

View File

@@ -128,7 +128,6 @@ static int objects_add_active_exec(bContext *C, wmOperator *op)
{
Object *ob = ED_object_context(C);
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
int single_group_index = RNA_enum_get(op->ptr, "group");
Group *single_group = group_object_active_find_index(ob, single_group_index);
Group *group;
@@ -145,13 +144,13 @@ static int objects_add_active_exec(bContext *C, wmOperator *op)
if (!BKE_group_object_exists(group, ob))
continue;
CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
CTX_DATA_BEGIN (C, ObjectBase *, base, selected_editable_bases)
{
if (BKE_group_object_exists(group, base->object))
continue;
if (!BKE_group_object_cyclic_check(bmain, base->object, group)) {
BKE_group_object_add(group, base->object, scene, base);
BKE_group_object_add(group, base->object);
updated = true;
}
else {
@@ -200,8 +199,8 @@ void GROUP_OT_objects_add_active(wmOperatorType *ot)
static int objects_remove_active_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
Object *ob = OBACT;
SceneLayer *sl = CTX_data_scene_layer(C);
Object *ob = OBACT_NEW;
int single_group_index = RNA_enum_get(op->ptr, "group");
Group *single_group = group_object_active_find_index(ob, single_group_index);
Group *group;
@@ -219,9 +218,9 @@ static int objects_remove_active_exec(bContext *C, wmOperator *op)
if (BKE_group_object_exists(group, ob)) {
/* Remove groups from selected objects */
CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
CTX_DATA_BEGIN (C, ObjectBase *, base, selected_editable_bases)
{
BKE_group_object_unlink(group, base->object, scene, base);
BKE_group_object_unlink(group, base->object);
ok = 1;
}
CTX_DATA_END;
@@ -264,11 +263,10 @@ void GROUP_OT_objects_remove_active(wmOperatorType *ot)
static int group_objects_remove_all_exec(bContext *C, wmOperator *UNUSED(op))
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
CTX_DATA_BEGIN (C, ObjectBase *, base, selected_editable_bases)
{
BKE_object_groups_clear(scene, base, base->object);
BKE_object_groups_clear(base->object);
}
CTX_DATA_END;
@@ -297,7 +295,6 @@ static int group_objects_remove_exec(bContext *C, wmOperator *op)
{
Object *ob = ED_object_context(C);
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
int single_group_index = RNA_enum_get(op->ptr, "group");
Group *single_group = group_object_active_find_index(ob, single_group_index);
Group *group;
@@ -313,9 +310,9 @@ static int group_objects_remove_exec(bContext *C, wmOperator *op)
continue;
/* now remove all selected objects from the group */
CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
CTX_DATA_BEGIN (C, ObjectBase *, base, selected_editable_bases)
{
BKE_group_object_unlink(group, base->object, scene, base);
BKE_group_object_unlink(group, base->object);
updated = true;
}
CTX_DATA_END;
@@ -357,7 +354,6 @@ void GROUP_OT_objects_remove(wmOperatorType *ot)
static int group_create_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
Group *group = NULL;
char name[MAX_ID_NAME - 2]; /* id name */
@@ -365,9 +361,9 @@ static int group_create_exec(bContext *C, wmOperator *op)
group = BKE_group_add(bmain, name);
CTX_DATA_BEGIN (C, Base *, base, selected_bases)
CTX_DATA_BEGIN (C, ObjectBase *, base, selected_bases)
{
BKE_group_object_add(group, base->object, scene, base);
BKE_group_object_add(group, base->object);
}
CTX_DATA_END;
@@ -398,7 +394,6 @@ void GROUP_OT_create(wmOperatorType *ot)
static int group_add_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
Object *ob = ED_object_context(C);
Main *bmain = CTX_data_main(C);
Group *group;
@@ -407,7 +402,7 @@ static int group_add_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_CANCELLED;
group = BKE_group_add(bmain, "Group");
BKE_group_object_add(group, ob, scene, NULL);
BKE_group_object_add(group, ob);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
@@ -432,7 +427,6 @@ void OBJECT_OT_group_add(wmOperatorType *ot)
static int group_link_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
Object *ob = ED_object_context(C);
Group *group = BLI_findlink(&bmain->group, RNA_enum_get(op->ptr, "group"));
@@ -457,7 +451,7 @@ static int group_link_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
BKE_group_object_add(group, ob, scene, NULL);
BKE_group_object_add(group, ob);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
@@ -490,14 +484,13 @@ void OBJECT_OT_group_link(wmOperatorType *ot)
static int group_remove_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
Object *ob = ED_object_context(C);
Group *group = CTX_data_pointer_get_type(C, "group", &RNA_Group).data;
if (!ob || !group)
return OPERATOR_CANCELLED;
BKE_group_object_unlink(group, ob, scene, NULL); /* base will be used if found */
BKE_group_object_unlink(group, ob);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
@@ -558,10 +551,12 @@ static int select_grouped_exec(bContext *C, wmOperator *UNUSED(op)) /* Select o
if (!group)
return OPERATOR_CANCELLED;
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
CTX_DATA_BEGIN (C, ObjectBase *, base, visible_bases)
{
if (!(base->flag & SELECT) && BKE_group_object_exists(group, base->object)) {
ED_base_object_select(base, BA_SELECT);
if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) {
if (BKE_group_object_exists(group, base->object)) {
ED_object_base_select(base, BA_SELECT);
}
}
}
CTX_DATA_END;

View File

@@ -445,12 +445,12 @@ static int hook_op_edit_poll(bContext *C)
return 0;
}
static Object *add_hook_object_new(Main *bmain, Scene *scene, Object *obedit)
static Object *add_hook_object_new(Main *bmain, Scene *scene, SceneLayer *sl, Object *obedit)
{
Base *base, *basedit;
Object *ob;
ob = BKE_object_add(bmain, scene, OB_EMPTY, NULL);
ob = BKE_object_add(bmain, scene, sl, OB_EMPTY, NULL);
basedit = BKE_scene_base_find(scene, obedit);
base = scene->basact;
@@ -464,7 +464,7 @@ static Object *add_hook_object_new(Main *bmain, Scene *scene, Object *obedit)
return ob;
}
static int add_hook_object(Main *bmain, Scene *scene, Object *obedit, Object *ob, int mode, ReportList *reports)
static int add_hook_object(Main *bmain, Scene *scene, SceneLayer *sl, Object *obedit, Object *ob, int mode, ReportList *reports)
{
ModifierData *md = NULL;
HookModifierData *hmd = NULL;
@@ -482,7 +482,7 @@ static int add_hook_object(Main *bmain, Scene *scene, Object *obedit, Object *ob
if (mode == OBJECT_ADDHOOK_NEWOB && !ob) {
ob = add_hook_object_new(bmain, scene, obedit);
ob = add_hook_object_new(bmain, scene, sl, obedit);
/* transform cent to global coords for loc */
mul_v3_m4v3(ob->loc, obedit->obmat, cent);
@@ -556,6 +556,7 @@ static int object_add_hook_selob_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
SceneLayer *sl = CTX_data_scene_layer(C);
Object *obedit = CTX_data_edit_object(C);
Object *obsel = NULL;
const bool use_bone = RNA_boolean_get(op->ptr, "use_bone");
@@ -580,7 +581,7 @@ static int object_add_hook_selob_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
if (add_hook_object(bmain, scene, obedit, obsel, mode, op->reports)) {
if (add_hook_object(bmain, scene, sl, obedit, obsel, mode, op->reports)) {
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, obedit);
return OPERATOR_FINISHED;
}
@@ -611,9 +612,10 @@ static int object_add_hook_newob_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
SceneLayer *sl = CTX_data_scene_layer(C);
Object *obedit = CTX_data_edit_object(C);
if (add_hook_object(bmain, scene, obedit, NULL, OBJECT_ADDHOOK_NEWOB, op->reports)) {
if (add_hook_object(bmain, scene, sl, obedit, NULL, OBJECT_ADDHOOK_NEWOB, op->reports)) {
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, obedit);
return OPERATOR_FINISHED;

View File

@@ -70,7 +70,6 @@ void OBJECT_OT_make_local(struct wmOperatorType *ot);
void OBJECT_OT_make_single_user(struct wmOperatorType *ot);
void OBJECT_OT_make_links_scene(struct wmOperatorType *ot);
void OBJECT_OT_make_links_data(struct wmOperatorType *ot);
void OBJECT_OT_move_to_layer(struct wmOperatorType *ot);
void OBJECT_OT_drop_named_material(struct wmOperatorType *ot);
void OBJECT_OT_unlink_data(struct wmOperatorType *ot);
@@ -78,10 +77,6 @@ void OBJECT_OT_unlink_data(struct wmOperatorType *ot);
void OBJECT_OT_mode_set(struct wmOperatorType *ot);
void OBJECT_OT_editmode_toggle(struct wmOperatorType *ot);
void OBJECT_OT_posemode_toggle(struct wmOperatorType *ot);
void OBJECT_OT_hide_view_set(struct wmOperatorType *ot);
void OBJECT_OT_hide_view_clear(struct wmOperatorType *ot);
void OBJECT_OT_hide_render_set(struct wmOperatorType *ot);
void OBJECT_OT_hide_render_clear(struct wmOperatorType *ot);
void OBJECT_OT_proxy_make(struct wmOperatorType *ot);
void OBJECT_OT_shade_smooth(struct wmOperatorType *ot);
void OBJECT_OT_shade_flat(struct wmOperatorType *ot);

View File

@@ -411,7 +411,7 @@ int ED_object_modifier_move_down(ReportList *reports, Object *ob, ModifierData *
return 1;
}
int ED_object_modifier_convert(ReportList *UNUSED(reports), Main *bmain, Scene *scene, Object *ob, ModifierData *md)
int ED_object_modifier_convert(ReportList *UNUSED(reports), Main *bmain, Scene *scene, SceneLayer *sl, Object *ob, ModifierData *md)
{
Object *obn;
ParticleSystem *psys;
@@ -463,7 +463,7 @@ int ED_object_modifier_convert(ReportList *UNUSED(reports), Main *bmain, Scene *
if (totvert == 0) return 0;
/* add new mesh */
obn = BKE_object_add(bmain, scene, OB_MESH, NULL);
obn = BKE_object_add(bmain, scene, sl, OB_MESH, NULL);
me = obn->data;
me->totvert = totvert;
@@ -1048,10 +1048,11 @@ static int modifier_convert_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
SceneLayer *sl = CTX_data_scene_layer(C);
Object *ob = ED_object_active_context(C);
ModifierData *md = edit_modifier_property_get(op, ob, 0);
if (!md || !ED_object_modifier_convert(op->reports, bmain, scene, ob, md))
if (!md || !ED_object_modifier_convert(op->reports, bmain, scene, sl, ob, md))
return OPERATOR_CANCELLED;
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
@@ -1683,7 +1684,7 @@ static void skin_armature_bone_create(Object *skin_ob,
}
}
static Object *modifier_skin_armature_create(Main *bmain, Scene *scene, Object *skin_ob)
static Object *modifier_skin_armature_create(Main *bmain, Scene *scene, SceneLayer *sl, Object *skin_ob)
{
BLI_bitmap *edges_visited;
DerivedMesh *deform_dm;
@@ -1706,7 +1707,7 @@ static Object *modifier_skin_armature_create(Main *bmain, Scene *scene, Object *
NULL,
me->totvert);
arm_ob = BKE_object_add(bmain, scene, OB_ARMATURE, NULL);
arm_ob = BKE_object_add(bmain, scene, sl, OB_ARMATURE, NULL);
BKE_object_transform_copy(arm_ob, skin_ob);
arm = arm_ob->data;
arm->layer = 1;
@@ -1765,6 +1766,7 @@ static int skin_armature_create_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
SceneLayer *sl = CTX_data_scene_layer(C);
Object *ob = CTX_data_active_object(C), *arm_ob;
Mesh *me = ob->data;
ModifierData *skin_md;
@@ -1776,7 +1778,7 @@ static int skin_armature_create_exec(bContext *C, wmOperator *op)
}
/* create new armature */
arm_ob = modifier_skin_armature_create(bmain, scene, ob);
arm_ob = modifier_skin_armature_create(bmain, scene, sl, ob);
/* add a modifier to connect the new armature to the mesh */
arm_md = (ArmatureModifierData *)modifier_new(eModifierType_Armature);

View File

@@ -67,10 +67,6 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_editmode_toggle);
WM_operatortype_append(OBJECT_OT_posemode_toggle);
WM_operatortype_append(OBJECT_OT_proxy_make);
WM_operatortype_append(OBJECT_OT_hide_view_clear);
WM_operatortype_append(OBJECT_OT_hide_view_set);
WM_operatortype_append(OBJECT_OT_hide_render_clear);
WM_operatortype_append(OBJECT_OT_hide_render_set);
WM_operatortype_append(OBJECT_OT_shade_smooth);
WM_operatortype_append(OBJECT_OT_shade_flat);
WM_operatortype_append(OBJECT_OT_paths_calculate);
@@ -90,13 +86,11 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_make_single_user);
WM_operatortype_append(OBJECT_OT_make_links_scene);
WM_operatortype_append(OBJECT_OT_make_links_data);
WM_operatortype_append(OBJECT_OT_move_to_layer);
WM_operatortype_append(OBJECT_OT_select_random);
WM_operatortype_append(OBJECT_OT_select_all);
WM_operatortype_append(OBJECT_OT_select_same_group);
WM_operatortype_append(OBJECT_OT_select_by_type);
WM_operatortype_append(OBJECT_OT_select_by_layer);
WM_operatortype_append(OBJECT_OT_select_linked);
WM_operatortype_append(OBJECT_OT_select_grouped);
WM_operatortype_append(OBJECT_OT_select_mirror);
@@ -382,25 +376,6 @@ void ED_keymap_object(wmKeyConfig *keyconf)
WM_keymap_verify_item(keymap, "OBJECT_OT_origin_clear", OKEY, KM_PRESS, KM_ALT, 0);
WM_keymap_add_item(keymap, "OBJECT_OT_hide_view_clear", HKEY, KM_PRESS, KM_ALT, 0);
kmi = WM_keymap_add_item(keymap, "OBJECT_OT_hide_view_set", HKEY, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "unselected", false);
kmi = WM_keymap_add_item(keymap, "OBJECT_OT_hide_view_set", HKEY, KM_PRESS, KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "unselected", true);
/* same as above but for rendering */
WM_keymap_add_item(keymap, "OBJECT_OT_hide_render_clear", HKEY, KM_PRESS, KM_ALT | KM_CTRL, 0);
WM_keymap_add_item(keymap, "OBJECT_OT_hide_render_set", HKEY, KM_PRESS, KM_CTRL, 0);
/* conflicts, removing */
#if 0
kmi = WM_keymap_add_item(keymap, "OBJECT_OT_hide_render_set", HKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0)
RNA_boolean_set(kmi->ptr, "unselected", true);
#endif
WM_keymap_add_item(keymap, "OBJECT_OT_move_to_layer", MKEY, KM_PRESS, 0, 0);
kmi = WM_keymap_add_item(keymap, "OBJECT_OT_delete", XKEY, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "use_global", false);

View File

@@ -63,6 +63,7 @@
#include "BKE_animsys.h"
#include "BKE_armature.h"
#include "BKE_camera.h"
#include "BKE_collection.h"
#include "BKE_context.h"
#include "BKE_constraint.h"
#include "BKE_curve.h"
@@ -74,6 +75,7 @@
#include "BKE_fcurve.h"
#include "BKE_lamp.h"
#include "BKE_lattice.h"
#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_library_query.h"
#include "BKE_library_remap.h"
@@ -331,6 +333,7 @@ static int make_proxy_exec(bContext *C, wmOperator *op)
Object *ob, *gob = ED_object_active_context(C);
GroupObject *go;
Scene *scene = CTX_data_scene(C);
SceneLayer *sl = CTX_data_scene_layer(C);
if (gob->dup_group != NULL) {
go = BLI_findlink(&gob->dup_group->gobject, RNA_enum_get(op->ptr, "object"));
@@ -349,7 +352,7 @@ static int make_proxy_exec(bContext *C, wmOperator *op)
BLI_snprintf(name, sizeof(name), "%s_proxy", ((ID *)(gob ? gob : ob))->name + 2);
/* Add new object for the proxy */
newob = BKE_object_add(bmain, scene, OB_EMPTY, name);
newob = BKE_object_add(bmain, scene, sl, OB_EMPTY, name);
/* set layers OK */
newbase = BASACT; /* BKE_object_add sets active... */
@@ -1305,119 +1308,6 @@ void OBJECT_OT_track_set(wmOperatorType *ot)
ot->prop = RNA_def_enum(ot->srna, "type", prop_make_track_types, 0, "Type", "");
}
/************************** Move to Layer Operator *****************************/
static unsigned int move_to_layer_init(bContext *C, wmOperator *op)
{
int values[20], a;
unsigned int lay = 0;
if (!RNA_struct_property_is_set(op->ptr, "layers")) {
/* note: layers are set in bases, library objects work for this */
CTX_DATA_BEGIN (C, Base *, base, selected_bases)
{
lay |= base->lay;
}
CTX_DATA_END;
for (a = 0; a < 20; a++)
values[a] = (lay & (1 << a)) != 0;
RNA_boolean_set_array(op->ptr, "layers", values);
}
else {
RNA_boolean_get_array(op->ptr, "layers", values);
for (a = 0; a < 20; a++)
if (values[a])
lay |= (1 << a);
}
return lay;
}
static int move_to_layer_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
View3D *v3d = CTX_wm_view3d(C);
if (v3d && v3d->localvd) {
return WM_operator_confirm_message(C, op, "Move out of Local View");
}
else {
move_to_layer_init(C, op);
return WM_operator_props_popup(C, op, event);
}
}
static int move_to_layer_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
unsigned int lay, local;
/* bool is_lamp = false; */ /* UNUSED */
lay = move_to_layer_init(C, op);
lay &= 0xFFFFFF;
if (lay == 0) return OPERATOR_CANCELLED;
if (v3d && v3d->localvd) {
/* now we can move out of localview. */
/* note: layers are set in bases, library objects work for this */
CTX_DATA_BEGIN (C, Base *, base, selected_bases)
{
lay = base->lay & ~v3d->lay;
base->lay = lay;
base->object->lay = lay;
base->object->flag &= ~SELECT;
base->flag &= ~SELECT;
/* if (base->object->type == OB_LAMP) is_lamp = true; */
}
CTX_DATA_END;
}
else {
/* normal non localview operation */
/* note: layers are set in bases, library objects work for this */
CTX_DATA_BEGIN (C, Base *, base, selected_bases)
{
/* upper byte is used for local view */
local = base->lay & 0xFF000000;
base->lay = lay + local;
base->object->lay = base->lay;
/* if (base->object->type == OB_LAMP) is_lamp = true; */
}
CTX_DATA_END;
}
/* warning, active object may be hidden now */
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, scene);
WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene);
DAG_relations_tag_update(bmain);
return OPERATOR_FINISHED;
}
void OBJECT_OT_move_to_layer(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Move to Layer";
ot->description = "Move the object to different layers";
ot->idname = "OBJECT_OT_move_to_layer";
/* api callbacks */
ot->invoke = move_to_layer_invoke;
ot->exec = move_to_layer_exec;
ot->poll = ED_operator_objectmode;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
RNA_def_boolean_layer_member(ot->srna, "layers", 20, NULL, "Layer", "");
}
/************************** Link to Scene Operator *****************************/
#if 0
@@ -1440,20 +1330,6 @@ static void link_to_scene(Main *UNUSED(bmain), unsigned short UNUSED(nr))
}
#endif
Base *ED_object_scene_link(Scene *scene, Object *ob)
{
Base *base;
if (BKE_scene_base_find(scene, ob)) {
return NULL;
}
base = BKE_scene_base_add(scene, ob);
id_us_plus(&ob->id);
return base;
}
static int make_links_scene_exec(bContext *C, wmOperator *op)
{
Scene *scene_to = BLI_findlink(&CTX_data_main(C)->scene, RNA_enum_get(op->ptr, "scene"));
@@ -1473,9 +1349,10 @@ static int make_links_scene_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
CTX_DATA_BEGIN (C, Base *, base, selected_bases)
SceneCollection *sc_to = BKE_collection_master(scene_to);
CTX_DATA_BEGIN (C, ObjectBase *, base, selected_bases)
{
ED_object_scene_link(scene_to, base->object);
BKE_collection_object_add(scene_to, sc_to, base->object);
}
CTX_DATA_END;
@@ -1531,7 +1408,6 @@ static bool allow_make_links_data(const int type, Object *ob_src, Object *ob_dst
static int make_links_data_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
const int type = RNA_enum_get(op->ptr, "type");
Object *ob_src;
ID *obdata_id;
@@ -1549,7 +1425,7 @@ static int make_links_data_exec(bContext *C, wmOperator *op)
ob_groups = BKE_object_groups(ob_src);
}
CTX_DATA_BEGIN (C, Base *, base_dst, selected_editable_bases)
CTX_DATA_BEGIN (C, ObjectBase *, base_dst, selected_editable_bases)
{
Object *ob_dst = base_dst->object;
@@ -1594,12 +1470,12 @@ static int make_links_data_exec(bContext *C, wmOperator *op)
LinkNode *group_node;
/* first clear groups */
BKE_object_groups_clear(scene, base_dst, ob_dst);
BKE_object_groups_clear(ob_dst);
/* now add in the groups from the link nodes */
for (group_node = ob_groups; group_node; group_node = group_node->next) {
if (ob_dst->dup_group != group_node->link) {
BKE_group_object_add(group_node->link, ob_dst, scene, base_dst);
BKE_group_object_add(group_node->link, ob_dst);
}
else {
is_cycle = true;
@@ -1732,48 +1608,82 @@ void OBJECT_OT_make_links_data(wmOperatorType *ot)
/**************************** Make Single User ********************************/
static Object *single_object_users_object(Main *bmain, Scene *scene, Object *ob, const bool copy_groups)
{
if (!ID_IS_LINKED_DATABLOCK(ob) && ob->id.us > 1) {
/* base gets copy of object */
Object *obn = ID_NEW_SET(ob, BKE_object_copy(bmain, ob));
if (copy_groups) {
if (ob->flag & OB_FROMGROUP) {
obn->flag |= OB_FROMGROUP;
}
}
else {
/* copy already clears */
}
/* remap gpencil parenting */
if (scene->gpd) {
bGPdata *gpd = scene->gpd;
for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
if (gpl->parent == ob) {
gpl->parent = obn;
}
}
}
id_us_min(&ob->id);
return obn;
}
return NULL;
}
static void libblock_relink_scene_collection(SceneCollection *sc)
{
for (LinkData *link = sc->objects.first; link; link = link->next) {
BKE_libblock_relink_to_newid(link->data);
}
for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
libblock_relink_scene_collection(nsc);
}
}
static void single_object_users_scene_collection(Main *bmain, Scene *scene, SceneCollection *sc, const int flag, const bool copy_groups)
{
for (LinkData *link = sc->objects.first; link; link = link->next) {
Object *ob = link->data;
/* an object may be in more than one collection */
if ((ob->id.newid == NULL) && ((ob->flag & flag) == flag)) {
link->data = single_object_users_object(bmain, scene, link->data, copy_groups);
}
}
/* we reset filter objects because they should be regenerated after this */
BLI_freelistN(&sc->filter_objects);
for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
single_object_users_scene_collection(bmain, scene, nsc, flag, copy_groups);
}
}
/* Warning, sets ID->newid pointers of objects and groups, but does not clear them. */
static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const int flag, const bool copy_groups)
{
Base *base;
Object *ob, *obn;
Group *group, *groupn;
GroupObject *go;
clear_sca_new_poins(); /* BGE logic */
/* duplicate (must set newid) */
for (base = FIRSTBASE; base; base = base->next) {
ob = base->object;
/* duplicate all the objects of the scene */
SceneCollection *msc = BKE_collection_master(scene);
single_object_users_scene_collection(bmain, scene, msc, flag, copy_groups);
if ((base->flag & flag) == flag) {
if (!ID_IS_LINKED_DATABLOCK(ob) && ob->id.us > 1) {
/* base gets copy of object */
base->object = obn = ID_NEW_SET(ob, BKE_object_copy(bmain, ob));
if (copy_groups) {
if (ob->flag & OB_FROMGROUP) {
obn->flag |= OB_FROMGROUP;
}
}
else {
/* copy already clears */
}
/* remap gpencil parenting */
if (scene->gpd) {
bGPdata *gpd = scene->gpd;
for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
if (gpl->parent == ob) {
gpl->parent = obn;
}
}
}
base->flag = obn->flag;
id_us_min(&ob->id);
}
/* loop over SceneLayers and assign the pointers accordingly */
for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) {
for (ObjectBase *base = sl->object_bases.first; base; base = base->next) {
ID_NEW_REMAP(base->object);
}
}
@@ -1806,27 +1716,29 @@ static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const in
if (v3d) ID_NEW_REMAP(v3d->camera);
/* object and group pointers */
for (base = FIRSTBASE; base; base = base->next) {
BKE_libblock_relink_to_newid(&base->object->id);
}
libblock_relink_scene_collection(msc);
set_sca_new_poins();
/* TODO redo filter */
TODO_LAYER_SYNC_FILTER
}
/* not an especially efficient function, only added so the single user
* button can be functional.*/
void ED_object_single_user(Main *bmain, Scene *scene, Object *ob)
{
Base *base;
const bool copy_groups = false;
for (base = FIRSTBASE; base; base = base->next) {
if (base->object == ob) base->flag |= OB_DONE;
else base->flag &= ~OB_DONE;
Object *ob_iter;
FOREACH_SCENE_OBJECT(scene, ob_iter)
{
ob_iter->flag &= ~OB_DONE;
}
FOREACH_SCENE_OBJECT_END
single_object_users(bmain, scene, NULL, OB_DONE, copy_groups);
/* tag only the one object */
ob->flag |= OB_DONE;
single_object_users(bmain, scene, NULL, OB_DONE, false);
BKE_main_id_clear_newpoins(bmain);
}
@@ -1863,6 +1775,8 @@ static void single_obdata_users(Main *bmain, Scene *scene, const int flag)
ID *id;
int a;
TODO_LAYER; /* need to use scene->collection base instead of scene->bases */
for (base = FIRSTBASE; base; base = base->next) {
ob = base->object;
if (!ID_IS_LINKED_DATABLOCK(ob) && (base->flag & flag) == flag) {
@@ -1939,31 +1853,27 @@ static void single_obdata_users(Main *bmain, Scene *scene, const int flag)
}
}
static void single_object_action_users(Scene *scene, const int flag)
static void single_object_action_users(Scene *scene, SceneLayer *sl, const int flag)
{
Object *ob;
Base *base;
for (base = FIRSTBASE; base; base = base->next) {
ob = base->object;
if (!ID_IS_LINKED_DATABLOCK(ob) && (flag == 0 || (base->flag & SELECT)) ) {
FOREACH_OBJECT_FLAG(scene, sl, flag, ob)
if (!ID_IS_LINKED_DATABLOCK(ob)) {
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
BKE_animdata_copy_id_action(&ob->id, false);
}
}
FOREACH_OBJECT_FLAG_END
}
static void single_mat_users(Main *bmain, Scene *scene, const int flag, const bool do_textures)
static void single_mat_users(Main *bmain, Scene *scene, SceneLayer *sl, const int flag, const bool do_textures)
{
Object *ob;
Base *base;
Material *ma, *man;
Tex *tex;
int a, b;
for (base = FIRSTBASE; base; base = base->next) {
ob = base->object;
if (!ID_IS_LINKED_DATABLOCK(ob) && (flag == 0 || (base->flag & SELECT)) ) {
Object *ob;
FOREACH_OBJECT_FLAG(scene, sl, flag, ob)
if (!ID_IS_LINKED_DATABLOCK(ob)) {
for (a = 1; a <= ob->totcol; a++) {
ma = give_current_material(ob, a);
if (ma) {
@@ -1992,7 +1902,7 @@ static void single_mat_users(Main *bmain, Scene *scene, const int flag, const bo
}
}
}
}
FOREACH_OBJECT_FLAG_END
}
static void do_single_tex_user(Main *bmain, Tex **from)
@@ -2096,7 +2006,7 @@ void ED_object_single_users(Main *bmain, Scene *scene, const bool full, const bo
if (full) {
single_obdata_users(bmain, scene, 0);
single_object_action_users(scene, 0);
single_object_action_users(scene, NULL, 0);
single_mat_users_expand(bmain);
single_tex_users_expand(bmain);
}
@@ -2200,7 +2110,7 @@ static bool make_local_all__instance_indirect_unused(Main *bmain, Scene *scene)
base = BKE_scene_base_add(scene, ob);
base->flag |= SELECT;
base->object->flag = base->flag;
BKE_scene_base_flag_sync_from_base(base);
DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
changed = true;
@@ -2366,13 +2276,20 @@ static int make_single_user_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
SceneLayer *sl = CTX_data_scene_layer(C);
View3D *v3d = CTX_wm_view3d(C); /* ok if this is NULL */
const int flag = (RNA_enum_get(op->ptr, "type") == MAKE_SINGLE_USER_SELECTED) ? SELECT : 0;
const bool copy_groups = false;
bool update_deps = false;
if (RNA_boolean_get(op->ptr, "object")) {
single_object_users(bmain, scene, v3d, flag, copy_groups);
if (flag == SELECT) {
BKE_scene_layer_selected_objects_tag(sl, OB_DONE);
single_object_users(bmain, scene, v3d, OB_DONE, copy_groups);
}
else {
single_object_users(bmain, scene, v3d, 0, copy_groups);
}
/* needed since object relationships may have changed */
update_deps = true;
@@ -2383,7 +2300,7 @@ static int make_single_user_exec(bContext *C, wmOperator *op)
}
if (RNA_boolean_get(op->ptr, "material")) {
single_mat_users(bmain, scene, flag, RNA_boolean_get(op->ptr, "texture"));
single_mat_users(bmain, scene, sl, flag, RNA_boolean_get(op->ptr, "texture"));
}
#if 0 /* can't do this separate from materials */
@@ -2391,7 +2308,7 @@ static int make_single_user_exec(bContext *C, wmOperator *op)
single_mat_users(scene, flag, true);
#endif
if (RNA_boolean_get(op->ptr, "animation")) {
single_object_action_users(scene, flag);
single_object_action_users(scene, sl, flag);
}
BKE_main_id_clear_newpoins(bmain);

View File

@@ -52,6 +52,7 @@
#include "BKE_context.h"
#include "BKE_group.h"
#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_particle.h"
@@ -96,7 +97,7 @@ void ED_base_object_select(Base *base, short mode)
else if (mode == BA_DESELECT) {
base->flag &= ~SELECT;
}
base->object->flag = base->flag;
BKE_scene_base_flag_sync_from_base(base);
}
}
@@ -119,6 +120,33 @@ void ED_base_object_activate(bContext *C, Base *base)
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, NULL);
}
void ED_object_base_select(ObjectBase *base, short mode)
{
if (base) {
if (mode == BA_SELECT) {
if ((base->flag & BASE_SELECTABLED) != 0) {
base->flag |= BASE_SELECTED;
}
}
else if (mode == BA_DESELECT) {
base->flag &= ~BASE_SELECTED;
}
}
}
void ED_object_base_activate(bContext *C, ObjectBase *base)
{
SceneLayer *sl = CTX_data_scene_layer(C);
sl->basact = base;
if (base) {
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, sl);
}
else {
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, NULL);
}
}
/********************** Selection Operators **********************/
static int objects_selectable_poll(bContext *C)
@@ -145,17 +173,17 @@ static int object_select_by_type_exec(bContext *C, wmOperator *op)
extend = RNA_boolean_get(op->ptr, "extend");
if (extend == 0) {
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
CTX_DATA_BEGIN (C, ObjectBase *, base, visible_bases)
{
ED_base_object_select(base, BA_DESELECT);
ED_object_base_select(base, BA_DESELECT);
}
CTX_DATA_END;
}
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
CTX_DATA_BEGIN (C, ObjectBase *, base, visible_bases)
{
if (base->object->type == obtype) {
ED_base_object_select(base, BA_SELECT);
ED_object_base_select(base, BA_SELECT);
}
}
CTX_DATA_END;
@@ -210,38 +238,15 @@ static EnumPropertyItem prop_select_linked_types[] = {
{0, NULL, 0, NULL, NULL}
};
// XXX old animation system
#if 0
static int object_select_all_by_ipo(bContext *C, Ipo *ipo)
{
bool changed = false;
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
{
if (base->object->ipo == ipo) {
base->flag |= SELECT;
base->object->flag = base->flag;
changed = true;
}
}
CTX_DATA_END;
return changed;
}
#endif
static bool object_select_all_by_obdata(bContext *C, void *obdata)
{
bool changed = false;
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
CTX_DATA_BEGIN (C, ObjectBase *, base, visible_bases)
{
if ((base->flag & SELECT) == 0) {
if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) {
if (base->object->data == obdata) {
base->flag |= SELECT;
base->object->flag = base->flag;
ED_object_base_select(base, BA_SELECT);
changed = true;
}
}
@@ -255,9 +260,9 @@ static bool object_select_all_by_material_texture(bContext *C, int use_texture,
{
bool changed = false;
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
CTX_DATA_BEGIN (C, ObjectBase *, base, visible_bases)
{
if ((base->flag & SELECT) == 0) {
if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) {
Object *ob = base->object;
Material *mat1;
int a, b;
@@ -267,7 +272,7 @@ static bool object_select_all_by_material_texture(bContext *C, int use_texture,
if (!use_texture) {
if (mat1 == mat) {
base->flag |= SELECT;
ED_object_base_select(base, BA_SELECT);
changed = true;
}
}
@@ -275,7 +280,7 @@ static bool object_select_all_by_material_texture(bContext *C, int use_texture,
for (b = 0; b < MAX_MTEX; b++) {
if (mat1->mtex[b]) {
if (tex == mat1->mtex[b]->tex) {
base->flag |= SELECT;
ED_object_base_select(base, BA_SELECT);
changed = true;
break;
}
@@ -283,8 +288,6 @@ static bool object_select_all_by_material_texture(bContext *C, int use_texture,
}
}
}
base->object->flag = base->flag;
}
}
CTX_DATA_END;
@@ -297,14 +300,12 @@ static bool object_select_all_by_dup_group(bContext *C, Object *ob)
bool changed = false;
Group *dup_group = (ob->transflag & OB_DUPLIGROUP) ? ob->dup_group : NULL;
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
CTX_DATA_BEGIN (C, ObjectBase *, base, visible_bases)
{
if ((base->flag & SELECT) == 0) {
if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) {
Group *dup_group_other = (base->object->transflag & OB_DUPLIGROUP) ? base->object->dup_group : NULL;
if (dup_group == dup_group_other) {
base->flag |= SELECT;
base->object->flag = base->flag;
ED_object_base_select(base, BA_SELECT);
changed = true;
}
}
@@ -319,25 +320,23 @@ static bool object_select_all_by_particle(bContext *C, Object *ob)
ParticleSystem *psys_act = psys_get_current(ob);
bool changed = false;
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
CTX_DATA_BEGIN (C, ObjectBase *, base, visible_bases)
{
if ((base->flag & SELECT) == 0) {
if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) {
/* loop through other particles*/
ParticleSystem *psys;
for (psys = base->object->particlesystem.first; psys; psys = psys->next) {
if (psys->part == psys_act->part) {
base->flag |= SELECT;
ED_object_base_select(base, BA_SELECT);
changed = true;
break;
}
if (base->flag & SELECT) {
if (base->flag & BASE_SELECTED) {
break;
}
}
base->object->flag = base->flag;
}
}
CTX_DATA_END;
@@ -349,13 +348,11 @@ static bool object_select_all_by_library(bContext *C, Library *lib)
{
bool changed = false;
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
CTX_DATA_BEGIN (C, ObjectBase *, base, visible_bases)
{
if ((base->flag & SELECT) == 0) {
if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) {
if (lib == base->object->id.lib) {
base->flag |= SELECT;
base->object->flag = base->flag;
ED_object_base_select(base, BA_SELECT);
changed = true;
}
}
@@ -369,13 +366,11 @@ static bool object_select_all_by_library_obdata(bContext *C, Library *lib)
{
bool changed = false;
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
CTX_DATA_BEGIN (C, ObjectBase *, base, visible_bases)
{
if ((base->flag & SELECT) == 0) {
if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) {
if (base->object->data && lib == ((ID *)base->object->data)->lib) {
base->flag |= SELECT;
base->object->flag = base->flag;
ED_object_base_select(base, BA_SELECT);
changed = true;
}
}
@@ -415,9 +410,9 @@ static int object_select_linked_exec(bContext *C, wmOperator *op)
extend = RNA_boolean_get(op->ptr, "extend");
if (extend == 0) {
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
CTX_DATA_BEGIN (C, ObjectBase *, base, visible_bases)
{
ED_base_object_select(base, BA_DESELECT);
ED_object_base_select(base, BA_DESELECT);
}
CTX_DATA_END;
}
@@ -517,7 +512,7 @@ enum {
OBJECT_GRPSEL_PARENT = 2,
OBJECT_GRPSEL_SIBLINGS = 3,
OBJECT_GRPSEL_TYPE = 4,
OBJECT_GRPSEL_LAYER = 5,
/*OBJECT_GRPSEL_LAYER = 5,*/
OBJECT_GRPSEL_GROUP = 6,
OBJECT_GRPSEL_HOOK = 7,
OBJECT_GRPSEL_PASS = 8,
@@ -533,7 +528,6 @@ static EnumPropertyItem prop_select_grouped_types[] = {
{OBJECT_GRPSEL_PARENT, "PARENT", 0, "Parent", ""},
{OBJECT_GRPSEL_SIBLINGS, "SIBLINGS", 0, "Siblings", "Shared Parent"},
{OBJECT_GRPSEL_TYPE, "TYPE", 0, "Type", "Shared object type"},
{OBJECT_GRPSEL_LAYER, "LAYER", 0, "Layer", "Shared layers"},
{OBJECT_GRPSEL_GROUP, "GROUP", 0, "Group", "Shared group"},
{OBJECT_GRPSEL_HOOK, "HOOK", 0, "Hook", ""},
{OBJECT_GRPSEL_PASS, "PASS", 0, "Pass", "Render pass Index"},
@@ -548,16 +542,17 @@ static bool select_grouped_children(bContext *C, Object *ob, const bool recursiv
{
bool changed = false;
CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
CTX_DATA_BEGIN (C, ObjectBase *, base, selectable_bases)
{
if (ob == base->object->parent) {
if (!(base->flag & SELECT)) {
ED_base_object_select(base, BA_SELECT);
if ((base->flag & BASE_SELECTED) == 0) {
ED_object_base_select(base, BA_SELECT);
changed = true;
}
if (recursive)
if (recursive) {
changed |= select_grouped_children(C, base->object, 1);
}
}
}
CTX_DATA_END;
@@ -566,20 +561,21 @@ static bool select_grouped_children(bContext *C, Object *ob, const bool recursiv
static bool select_grouped_parent(bContext *C) /* Makes parent active and de-selected OBACT */
{
Scene *scene = CTX_data_scene(C);
SceneLayer *sl = CTX_data_scene_layer(C);
View3D *v3d = CTX_wm_view3d(C);
ObjectBase *baspar, *basact = CTX_data_active_base(C);
bool changed = false;
Base *baspar, *basact = CTX_data_active_base(C);
if (!basact || !(basact->object->parent)) return 0; /* we know OBACT is valid */
if (!basact || !(basact->object->parent)) {
return 0; /* we know OBACT is valid */
}
baspar = BKE_scene_base_find(scene, basact->object->parent);
baspar = BKE_scene_layer_base_find(sl, basact->object->parent);
/* can be NULL if parent in other scene */
if (baspar && BASE_SELECTABLE(v3d, baspar)) {
ED_base_object_select(baspar, BA_SELECT);
ED_base_object_activate(C, baspar);
ED_object_base_select(baspar, BA_SELECT);
ED_object_base_activate(C, baspar);
changed = true;
}
return changed;
@@ -606,11 +602,13 @@ static bool select_grouped_group(bContext *C, Object *ob) /* Select objects in
return 0;
else if (group_count == 1) {
group = ob_groups[0];
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
CTX_DATA_BEGIN (C, ObjectBase *, base, visible_bases)
{
if (!(base->flag & SELECT) && BKE_group_object_exists(group, base->object)) {
ED_base_object_select(base, BA_SELECT);
changed = true;
if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) {
if (BKE_group_object_exists(group, base->object)) {
ED_object_base_select(base, BA_SELECT);
changed = true;
}
}
}
CTX_DATA_END;
@@ -661,10 +659,10 @@ static bool select_grouped_siblings(bContext *C, Object *ob)
{
bool changed = false;
CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
CTX_DATA_BEGIN (C, ObjectBase *, base, selectable_bases)
{
if ((base->object->parent == ob->parent) && !(base->flag & SELECT)) {
ED_base_object_select(base, BA_SELECT);
if ((base->object->parent == ob->parent) && ((base->flag & BASE_SELECTED) == 0)) {
ED_object_base_select(base, BA_SELECT);
changed = true;
}
}
@@ -677,12 +675,12 @@ static bool select_grouped_lamptype(bContext *C, Object *ob)
bool changed = false;
CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
CTX_DATA_BEGIN (C, ObjectBase *, base, selectable_bases)
{
if (base->object->type == OB_LAMP) {
Lamp *la_test = base->object->data;
if ((la->type == la_test->type) && !(base->flag & SELECT)) {
ED_base_object_select(base, BA_SELECT);
if ((la->type == la_test->type) && ((base->flag & BASE_SELECTED) == 0)) {
ED_object_base_select(base, BA_SELECT);
changed = true;
}
}
@@ -694,25 +692,10 @@ static bool select_grouped_type(bContext *C, Object *ob)
{
bool changed = false;
CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
CTX_DATA_BEGIN (C, ObjectBase *, base, selectable_bases)
{
if ((base->object->type == ob->type) && !(base->flag & SELECT)) {
ED_base_object_select(base, BA_SELECT);
changed = true;
}
}
CTX_DATA_END;
return changed;
}
static bool select_grouped_layer(bContext *C, Object *ob)
{
bool changed = false;
CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
{
if ((base->lay & ob->lay) && !(base->flag & SELECT)) {
ED_base_object_select(base, BA_SELECT);
if ((base->object->type == ob->type) && ((base->flag & BASE_SELECTED) == 0)) {
ED_object_base_select(base, BA_SELECT);
changed = true;
}
}
@@ -724,10 +707,10 @@ static bool select_grouped_index_object(bContext *C, Object *ob)
{
bool changed = false;
CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
CTX_DATA_BEGIN (C, ObjectBase *, base, selectable_bases)
{
if ((base->object->index == ob->index) && !(base->flag & SELECT)) {
ED_base_object_select(base, BA_SELECT);
if ((base->object->index == ob->index) && ((base->flag & BASE_SELECTED) == 0)) {
ED_object_base_select(base, BA_SELECT);
changed = true;
}
}
@@ -739,10 +722,10 @@ static bool select_grouped_color(bContext *C, Object *ob)
{
bool changed = false;
CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
CTX_DATA_BEGIN (C, ObjectBase *, base, selectable_bases)
{
if (!(base->flag & SELECT) && (compare_v3v3(base->object->col, ob->col, 0.005f))) {
ED_base_object_select(base, BA_SELECT);
if (((base->flag & BASE_SELECTED) == 0) && (compare_v3v3(base->object->col, ob->col, 0.005f))) {
ED_object_base_select(base, BA_SELECT);
changed = true;
}
}
@@ -766,10 +749,10 @@ static bool select_grouped_gameprops(bContext *C, Object *ob)
{
bool changed = false;
CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
CTX_DATA_BEGIN (C, ObjectBase *, base, selectable_bases)
{
if (!(base->flag & SELECT) && (objects_share_gameprop(base->object, ob))) {
ED_base_object_select(base, BA_SELECT);
if (((base->flag & BASE_SELECTED) == 0) && (objects_share_gameprop(base->object, ob))) {
ED_object_base_select(base, BA_SELECT);
changed = true;
}
}
@@ -804,10 +787,10 @@ static bool select_grouped_keyingset(bContext *C, Object *UNUSED(ob), ReportList
/* select each object that Keying Set refers to */
/* TODO: perhaps to be more in line with the rest of these, we should only take objects
* if the passed in object is included in this too */
CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
CTX_DATA_BEGIN (C, ObjectBase *, base, selectable_bases)
{
/* only check for this object if it isn't selected already, to limit time wasted */
if ((base->flag & SELECT) == 0) {
if ((base->flag & BASE_SELECTED) == 0) {
KS_Path *ksp;
/* this is the slow way... we could end up with > 500 items here,
@@ -816,7 +799,7 @@ static bool select_grouped_keyingset(bContext *C, Object *UNUSED(ob), ReportList
for (ksp = ks->paths.first; ksp; ksp = ksp->next) {
/* if id matches, select then stop looping (match found) */
if (ksp->id == (ID *)base->object) {
ED_base_object_select(base, BA_SELECT);
ED_object_base_select(base, BA_SELECT);
changed = true;
break;
}
@@ -838,9 +821,9 @@ static int object_select_grouped_exec(bContext *C, wmOperator *op)
extend = RNA_boolean_get(op->ptr, "extend");
if (extend == 0) {
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
CTX_DATA_BEGIN (C, ObjectBase *, base, visible_bases)
{
ED_base_object_select(base, BA_DESELECT);
ED_object_base_select(base, BA_DESELECT);
changed = true;
}
CTX_DATA_END;
@@ -868,9 +851,6 @@ static int object_select_grouped_exec(bContext *C, wmOperator *op)
case OBJECT_GRPSEL_TYPE:
changed |= select_grouped_type(C, ob);
break;
case OBJECT_GRPSEL_LAYER:
changed |= select_grouped_layer(C, ob);
break;
case OBJECT_GRPSEL_GROUP:
changed |= select_grouped_group(C, ob);
break;
@@ -928,85 +908,6 @@ void OBJECT_OT_select_grouped(wmOperatorType *ot)
ot->prop = RNA_def_enum(ot->srna, "type", prop_select_grouped_types, 0, "Type", "");
}
/************************* Select by Layer **********************/
enum {
OB_SEL_LAYERMATCH_EXACT = 1,
OB_SEL_LAYERMATCH_SHARED = 2,
};
static int object_select_by_layer_exec(bContext *C, wmOperator *op)
{
unsigned int layernum;
bool extend;
int match;
extend = RNA_boolean_get(op->ptr, "extend");
layernum = RNA_int_get(op->ptr, "layers");
match = RNA_enum_get(op->ptr, "match");
if (extend == false) {
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
{
ED_base_object_select(base, BA_DESELECT);
}
CTX_DATA_END;
}
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
{
bool ok = false;
switch (match) {
case OB_SEL_LAYERMATCH_EXACT:
/* Mask out bits used for local view, only work on real layer ones, see T45783. */
ok = ((base->lay & ((1 << 20) - 1)) == (1 << (layernum - 1)));
break;
case OB_SEL_LAYERMATCH_SHARED:
ok = (base->lay & (1 << (layernum - 1))) != 0;
break;
default:
break;
}
if (ok) {
ED_base_object_select(base, BA_SELECT);
}
}
CTX_DATA_END;
/* undo? */
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
return OPERATOR_FINISHED;
}
void OBJECT_OT_select_by_layer(wmOperatorType *ot)
{
static EnumPropertyItem match_items[] = {
{OB_SEL_LAYERMATCH_EXACT, "EXACT", 0, "Exact Match", ""},
{OB_SEL_LAYERMATCH_SHARED, "SHARED", 0, "Shared Layers", ""},
{0, NULL, 0, NULL, NULL}
};
/* identifiers */
ot->name = "Select by Layer";
ot->description = "Select all visible objects on a layer";
ot->idname = "OBJECT_OT_select_by_layer";
/* api callbacks */
/*ot->invoke = XXX - need a int grid popup*/
ot->exec = object_select_by_layer_exec;
ot->poll = objects_selectable_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
RNA_def_enum(ot->srna, "match", match_items, OB_SEL_LAYERMATCH_EXACT, "Match", "");
RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection instead of deselecting everything first");
RNA_def_int(ot->srna, "layers", 1, 1, 20, "Layer", "", 1, 20);
}
/**************************** (De)select All ****************************/
static int object_select_all_exec(bContext *C, wmOperator *op)
@@ -1018,9 +919,9 @@ static int object_select_all_exec(bContext *C, wmOperator *op)
if (action == SEL_TOGGLE) {
action = SEL_SELECT;
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
CTX_DATA_BEGIN (C, ObjectBase *, base, visible_bases)
{
if (base->flag & SELECT) {
if ((base->flag & BASE_SELECTED) != 0) {
action = SEL_DESELECT;
break;
}
@@ -1028,21 +929,21 @@ static int object_select_all_exec(bContext *C, wmOperator *op)
CTX_DATA_END;
}
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
CTX_DATA_BEGIN (C, ObjectBase *, base, visible_bases)
{
switch (action) {
case SEL_SELECT:
ED_base_object_select(base, BA_SELECT);
ED_object_base_select(base, BA_SELECT);
break;
case SEL_DESELECT:
ED_base_object_select(base, BA_DESELECT);
ED_object_base_select(base, BA_DESELECT);
break;
case SEL_INVERT:
if (base->flag & SELECT) {
ED_base_object_select(base, BA_DESELECT);
if ((base->flag & BASE_SELECTED) != 0) {
ED_object_base_select(base, BA_DESELECT);
}
else {
ED_base_object_select(base, BA_SELECT);
ED_object_base_select(base, BA_SELECT);
}
break;
}
@@ -1090,10 +991,13 @@ static int object_select_same_group_exec(bContext *C, wmOperator *op)
return OPERATOR_PASS_THROUGH;
}
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
CTX_DATA_BEGIN (C, ObjectBase *, base, visible_bases)
{
if (!(base->flag & SELECT) && BKE_group_object_exists(group, base->object))
ED_base_object_select(base, BA_SELECT);
if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) {
if (BKE_group_object_exists(group, base->object)) {
ED_object_base_select(base, BA_SELECT);
}
}
}
CTX_DATA_END;
@@ -1124,11 +1028,12 @@ void OBJECT_OT_select_same_group(wmOperatorType *ot)
static int object_select_mirror_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
SceneLayer *sl = CTX_data_scene_layer(C);
bool extend;
extend = RNA_boolean_get(op->ptr, "extend");
CTX_DATA_BEGIN (C, Base *, primbase, selected_bases)
CTX_DATA_BEGIN (C, ObjectBase *, primbase, selected_bases)
{
char name_flip[MAXBONENAME];
@@ -1137,15 +1042,15 @@ static int object_select_mirror_exec(bContext *C, wmOperator *op)
if (!STREQ(name_flip, primbase->object->id.name + 2)) {
Object *ob = (Object *)BKE_libblock_find_name(ID_OB, name_flip);
if (ob) {
Base *secbase = BKE_scene_base_find(scene, ob);
ObjectBase *secbase = BKE_scene_layer_base_find(sl, ob);
if (secbase) {
ED_base_object_select(secbase, BA_SELECT);
ED_object_base_select(secbase, BA_SELECT);
}
}
}
if (extend == false) ED_base_object_select(primbase, BA_DESELECT);
if (extend == false) ED_object_base_select(primbase, BA_DESELECT);
}
CTX_DATA_END;
@@ -1180,9 +1085,9 @@ void OBJECT_OT_select_mirror(wmOperatorType *ot)
static bool object_select_more_less(bContext *C, const bool select)
{
Scene *scene = CTX_data_scene(C);
SceneLayer *sl = CTX_data_scene_layer(C);
for (Base *base = scene->base.first; base; base = base->next) {
for (Base *base = sl->object_bases.first; base; base = base->next) {
Object *ob = base->object;
ob->flag &= ~OB_DONE;
ob->id.tag &= ~LIB_TAG_DOIT;
@@ -1206,7 +1111,7 @@ static bool object_select_more_less(bContext *C, const bool select)
for (ctx_base = ctx_base_list.first; ctx_base; ctx_base = ctx_base->next) {
Object *ob = ((Base *)ctx_base->ptr.data)->object;
Object *ob = ((ObjectBase *)ctx_base->ptr.data)->object;
if (ob->parent) {
if ((ob->flag & OB_DONE) != (ob->parent->flag & OB_DONE)) {
ob->id.tag |= LIB_TAG_DOIT;
@@ -1220,10 +1125,10 @@ static bool object_select_more_less(bContext *C, const bool select)
const short select_flag = select ? SELECT : 0;
for (ctx_base = ctx_base_list.first; ctx_base; ctx_base = ctx_base->next) {
Base *base = ctx_base->ptr.data;
ObjectBase *base = ctx_base->ptr.data;
Object *ob = base->object;
if ((ob->id.tag & LIB_TAG_DOIT) && ((ob->flag & SELECT) != select_flag)) {
ED_base_object_select(base, select_mode);
ED_object_base_select(base, select_mode);
changed = true;
}
}
@@ -1302,10 +1207,10 @@ static int object_select_random_exec(bContext *C, wmOperator *op)
RNG *rng = BLI_rng_new_srandom(seed);
CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
CTX_DATA_BEGIN (C, ObjectBase *, base, selectable_bases)
{
if (BLI_rng_get_float(rng) < randfac) {
ED_base_object_select(base, select);
ED_object_base_select(base, select);
}
}
CTX_DATA_END;

View File

@@ -89,7 +89,7 @@ bool ED_rigidbody_constraint_add(Main *bmain, Scene *scene, Object *ob, int type
ob->rigidbody_constraint->flag |= RBC_FLAG_NEEDS_VALIDATE;
/* add constraint to rigid body constraint group */
BKE_group_object_add(rbw->constraints, ob, scene, NULL);
BKE_group_object_add(rbw->constraints, ob);
DAG_relations_tag_update(bmain);
DAG_id_tag_update(&ob->id, OB_RECALC_OB);
@@ -102,7 +102,7 @@ void ED_rigidbody_constraint_remove(Main *bmain, Scene *scene, Object *ob)
BKE_rigidbody_remove_constraint(scene, ob);
if (rbw)
BKE_group_object_unlink(rbw->constraints, ob, scene, NULL);
BKE_group_object_unlink(rbw->constraints, ob);
DAG_relations_tag_update(bmain);
DAG_id_tag_update(&ob->id, OB_RECALC_OB);

View File

@@ -119,7 +119,7 @@ bool ED_rigidbody_object_add(Main *bmain, Scene *scene, Object *ob, int type, Re
ob->rigidbody_object->flag |= RBO_FLAG_NEEDS_VALIDATE;
/* add object to rigid body group */
BKE_group_object_add(rbw->group, ob, scene, NULL);
BKE_group_object_add(rbw->group, ob);
DAG_relations_tag_update(bmain);
DAG_id_tag_update(&ob->id, OB_RECALC_OB);
@@ -133,7 +133,7 @@ void ED_rigidbody_object_remove(Main *bmain, Scene *scene, Object *ob)
BKE_rigidbody_remove_object(scene, ob);
if (rbw)
BKE_group_object_unlink(rbw->group, ob, scene, NULL);
BKE_group_object_unlink(rbw->group, ob);
DAG_relations_tag_update(bmain);
DAG_id_tag_update(&ob->id, OB_RECALC_OB);

Some files were not shown because too many files have changed in this diff Show More