diff options
186 files changed, 6294 insertions, 2280 deletions
diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake index 09428953a46..83ae56636b0 100644 --- a/build_files/cmake/macros.cmake +++ b/build_files/cmake/macros.cmake @@ -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 diff --git a/release/scripts/modules/bpy_extras/object_utils.py b/release/scripts/modules/bpy_extras/object_utils.py index c48f03c133d..d740137b0c3 100644 --- a/release/scripts/modules/bpy_extras/object_utils.py +++ b/release/scripts/modules/bpy_extras/object_utils.py @@ -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): diff --git a/release/scripts/presets/keyconfig/3dsmax.py b/release/scripts/presets/keyconfig/3dsmax.py index 7694e338d68..b6b0a0c926f 100644 --- a/release/scripts/presets/keyconfig/3dsmax.py +++ b/release/scripts/presets/keyconfig/3dsmax.py @@ -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) diff --git a/release/scripts/presets/keyconfig/maya.py b/release/scripts/presets/keyconfig/maya.py index 67fd1fddcac..f542ecf810b 100644 --- a/release/scripts/presets/keyconfig/maya.py +++ b/release/scripts/presets/keyconfig/maya.py @@ -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) diff --git a/release/scripts/startup/bl_operators/clip.py b/release/scripts/startup/bl_operators/clip.py index 0c77ea2ab7e..d60703236d6 100644 --- a/release/scripts/startup/bl_operators/clip.py +++ b/release/scripts/startup/bl_operators/clip.py @@ -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'} diff --git a/release/scripts/startup/bl_operators/freestyle.py b/release/scripts/startup/bl_operators/freestyle.py index fe3b00d54cd..43cd3110beb 100644 --- a/release/scripts/startup/bl_operators/freestyle.py +++ b/release/scripts/startup/bl_operators/freestyle.py @@ -102,7 +102,7 @@ class SCENE_OT_freestyle_fill_range_by_selection(bpy.types.Operator): m.range_max = max_dist return {'FINISHED'} # Find selected mesh objects - selection = [ob for ob in scene.objects if ob.select and ob.type == 'MESH' and ob.name != ref.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 from the reference to mesh vertices min_dist = sys.float_info.max diff --git a/release/scripts/startup/bl_operators/object.py b/release/scripts/startup/bl_operators/object.py index 6356da216b1..be680a6df0c 100644 --- a/release/scripts/startup/bl_operators/object.py +++ b/release/scripts/startup/bl_operators/object.py @@ -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'} diff --git a/release/scripts/startup/bl_operators/rigidbody.py b/release/scripts/startup/bl_operators/rigidbody.py index 750a5b0bf0f..cba49c629be 100644 --- a/release/scripts/startup/bl_operators/rigidbody.py +++ b/release/scripts/startup/bl_operators/rigidbody.py @@ -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: diff --git a/release/scripts/startup/bl_ui/__init__.py b/release/scripts/startup/bl_ui/__init__.py index 2389be6787d..0f26ff75715 100644 --- a/release/scripts/startup/bl_ui/__init__.py +++ b/release/scripts/startup/bl_ui/__init__.py @@ -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", diff --git a/release/scripts/startup/bl_ui/properties_collection.py b/release/scripts/startup/bl_ui/properties_collection.py new file mode 100644 index 00000000000..d67d694aec9 --- /dev/null +++ b/release/scripts/startup/bl_ui/properties_collection.py @@ -0,0 +1,79 @@ +# ##### 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") + + +if __name__ == "__main__": # only for live edit. + bpy.utils.register_module(__name__) diff --git a/release/scripts/startup/bl_ui/properties_render_layer.py b/release/scripts/startup/bl_ui/properties_render_layer.py index 9b8bc237db9..45c93dd9335 100644 --- a/release/scripts/startup/bl_ui/properties_render_layer.py +++ b/release/scripts/startup/bl_ui/properties_render_layer.py @@ -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) @@ -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) diff --git a/release/scripts/startup/bl_ui/space_collections.py b/release/scripts/startup/bl_ui/space_collections.py new file mode 100644 index 00000000000..9b612ce2ecd --- /dev/null +++ b/release/scripts/startup/bl_ui/space_collections.py @@ -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__) diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index f8e4d1338f9..e397a85aa58 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -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' diff --git a/release/scripts/templates_py/batch_export.py b/release/scripts/templates_py/batch_export.py index 6c77c5d6a1a..8de7a5e2903 100644 --- a/release/scripts/templates_py/batch_export.py +++ b/release/scripts/templates_py/batch_export.py @@ -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') diff --git a/release/scripts/templates_py/operator_modal_view3d_raycast.py b/release/scripts/templates_py/operator_modal_view3d_raycast.py index c4d661b4c1f..e3b63813fc4 100644 --- a/release/scripts/templates_py/operator_modal_view3d_raycast.py +++ b/release/scripts/templates_py/operator_modal_view3d_raycast.py @@ -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 diff --git a/source/blender/alembic/intern/abc_exporter.cc b/source/blender/alembic/intern/abc_exporter.cc index ff8b0442ab6..cc61d5ad49f 100644 --- a/source/blender/alembic/intern/abc_exporter.cc +++ b/source/blender/alembic/intern/abc_exporter.cc @@ -341,7 +341,7 @@ void AbcExporter::operator()(Main *bmain, float &progress, bool &was_canceled) void AbcExporter::createTransformWritersHierarchy(EvaluationContext *eval_ctx) { - Base *base = static_cast<Base *>(m_scene->base.first); + BaseLegacy *base = static_cast<BaseLegacy *>(m_scene->base.first); while (base) { Object *ob = base->object; @@ -366,7 +366,7 @@ void AbcExporter::createTransformWritersHierarchy(EvaluationContext *eval_ctx) void AbcExporter::createTransformWritersFlat() { - Base *base = static_cast<Base *>(m_scene->base.first); + BaseLegacy *base = static_cast<BaseLegacy *>(m_scene->base.first); while (base) { Object *ob = base->object; @@ -445,7 +445,7 @@ void AbcExporter::createTransformWriter(Object *ob, Object *parent, Object *dupl void AbcExporter::createShapeWriters(EvaluationContext *eval_ctx) { - Base *base = static_cast<Base *>(m_scene->base.first); + BaseLegacy *base = static_cast<BaseLegacy *>(m_scene->base.first); while (base) { Object *ob = base->object; diff --git a/source/blender/blenkernel/BKE_collection.h b/source/blender/blenkernel/BKE_collection.h new file mode 100644 index 00000000000..c3f461dacd6 --- /dev/null +++ b/source/blender/blenkernel/BKE_collection.h @@ -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 Base; +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__ */ diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h index 4da6a61cbfa..23f9ff28f8b 100644 --- a/source/blender/blenkernel/BKE_context.h +++ b/source/blender/blenkernel/BKE_context.h @@ -40,12 +40,16 @@ extern "C" { struct ARegion; struct bScreen; struct CacheFile; +struct LayerCollection; struct ListBase; struct Main; struct Object; +struct Base; 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); diff --git a/source/blender/blenkernel/BKE_group.h b/source/blender/blenkernel/BKE_group.h index 09a069ee36f..f718e9c8555 100644 --- a/source/blender/blenkernel/BKE_group.h +++ b/source/blender/blenkernel/BKE_group.h @@ -33,6 +33,7 @@ * \author nzc */ +struct BaseLegacy; struct Base; struct EvaluationContext; struct Group; @@ -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); diff --git a/source/blender/blenkernel/BKE_layer.h b/source/blender/blenkernel/BKE_layer.h new file mode 100644 index 00000000000..850c63f535f --- /dev/null +++ b/source/blender/blenkernel/BKE_layer.h @@ -0,0 +1,189 @@ +/* + * ***** 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 /* BaseLegacy to Base related TODO */ +#define TODO_LAYER_OPERATORS /* collection mamanger and property panel operators */ +#define TODO_LAYER /* generic todo */ + +struct Base; +struct ID; +struct LayerCollection; +struct Main; +struct Object; +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 Base *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 Base *selbase); +void BKE_scene_layer_base_flag_recalculate(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); + +/* 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) \ +{ \ + Base *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_) \ +{ \ + /* flush all the data to objects*/ \ + Base *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__ */ diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 546f0d97c2b..67f7fa5e029 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -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 */ diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index b1e218d3e5f..c1655d3e9c6 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -35,12 +35,13 @@ extern "C" { #include "BLI_compiler_attrs.h" -struct Base; +struct BaseLegacy; struct EvaluationContext; 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) @@ -255,7 +256,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); diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h index d2152950bff..53bb69aedb6 100644 --- a/source/blender/blenkernel/BKE_scene.h +++ b/source/blender/blenkernel/BKE_scene.h @@ -38,10 +38,11 @@ extern "C" { #endif struct AviCodecData; -struct Base; +struct BaseLegacy; struct EvaluationContext; struct Main; struct Object; +struct Base; struct QuicktimeCodecData; struct RenderData; struct SceneRenderLayer; @@ -61,7 +62,7 @@ struct Main; _base; \ _base = _setlooper_base_step(&_sce_iter, _base) -struct Base *_setlooper_base_step(struct Scene **sce_iter, struct Base *base); +struct BaseLegacy *_setlooper_base_step(struct Scene **sce_iter, struct BaseLegacy *base); void free_avicodecdata(struct AviCodecData *acd); void free_qtcodecdata(struct QuicktimeCodecData *acd); @@ -70,13 +71,15 @@ 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); -struct Base *BKE_scene_base_add(struct Scene *sce, struct Object *ob); -void BKE_scene_base_unlink(struct Scene *sce, struct Base *base); +struct BaseLegacy *BKE_scene_base_find_by_name(struct Scene *scene, const char *name); +struct BaseLegacy *BKE_scene_base_find(struct Scene *scene, struct Object *ob); +struct BaseLegacy *BKE_scene_base_add(struct Scene *sce, struct Object *ob); +void BKE_scene_base_unlink(struct Scene *sce, struct BaseLegacy *base); void BKE_scene_base_deselect_all(struct Scene *sce); -void BKE_scene_base_select(struct Scene *sce, struct Base *selbase); +void BKE_scene_base_select(struct Scene *sce, struct BaseLegacy *selbase); /* Scene base iteration function. * Define struct here, so no need to bother with alloc/free it. @@ -90,10 +93,14 @@ typedef struct SceneBaseIter { } SceneBaseIter; int BKE_scene_base_iter_next(struct EvaluationContext *eval_ctx, struct SceneBaseIter *iter, - struct Scene **scene, int val, struct Base **base, struct Object **ob); + struct Scene **scene, int val, struct BaseLegacy **base, struct Object **ob); 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 BaseLegacy *base); +void BKE_scene_base_flag_sync_from_object(struct BaseLegacy *base); +void BKE_scene_object_base_flag_sync_from_base(struct Base *base); +void BKE_scene_object_base_flag_sync_from_object(struct Base *base); void BKE_scene_set_background(struct Main *bmain, struct Scene *sce); struct Scene *BKE_scene_set_name(struct Main *bmain, const char *name); diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index f3bab55b47d..6202c84f320 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -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 diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index 2f65e71c6d2..237e4e80172 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -283,7 +283,7 @@ void animviz_get_object_motionpaths(Object *ob, ListBase *targets) /* tweak the object ordering to trick depsgraph into making MotionPath calculations run faster */ static void motionpaths_calc_optimise_depsgraph(Scene *scene, ListBase *targets) { - Base *base, *baseNext; + BaseLegacy *base, *baseNext; MPathTarget *mpt; /* make sure our temp-tag isn't already in use */ @@ -321,7 +321,7 @@ static void motionpaths_calc_update_scene(Scene *scene) BKE_scene_update_for_newframe(G.main->eval_ctx, G.main, scene, scene->lay); } else { /* otherwise we can optimize by restricting updates */ - Base *base, *last = NULL; + BaseLegacy *base, *last = NULL; /* only stuff that moves or needs display still */ DAG_scene_update_flags(G.main, scene, scene->lay, true, false); diff --git a/source/blender/blenkernel/intern/cachefile.c b/source/blender/blenkernel/intern/cachefile.c index 3dce08eb756..8630e8562b0 100644 --- a/source/blender/blenkernel/intern/cachefile.c +++ b/source/blender/blenkernel/intern/cachefile.c @@ -205,7 +205,7 @@ float BKE_cachefile_time_offset(CacheFile *cache_file, const float time, const f /* TODO(kevin): replace this with some depsgraph mechanism, or something similar. */ void BKE_cachefile_clean(Scene *scene, CacheFile *cache_file) { - for (Base *base = scene->base.first; base; base = base->next) { + for (BaseLegacy *base = scene->base.first; base; base = base->next) { Object *ob = base->object; ModifierData *md = modifiers_findByType(ob, eModifierType_MeshSequenceCache); diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c index 9cb553aa27b..978204f1cf5 100644 --- a/source/blender/blenkernel/intern/camera.c +++ b/source/blender/blenkernel/intern/camera.c @@ -853,7 +853,7 @@ static Object *camera_multiview_advanced(Scene *scene, Object *camera, const cha } if (name[0] != '\0') { - Base *base = BKE_scene_base_find_by_name(scene, name); + BaseLegacy *base = BKE_scene_base_find_by_name(scene, name); if (base) { return base->object; } diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c new file mode 100644 index 00000000000..f374ebd1e53 --- /dev/null +++ b/source/blender/blenkernel/intern/collection.c @@ -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); + } +} diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index ee25be36855..b5f76240c0b 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -514,7 +514,7 @@ static void add_collision_object(Object ***objs, unsigned int *numobj, unsigned // collision object will exclude self Object **get_collisionobjects_ext(Scene *scene, Object *self, Group *group, int layer, unsigned int *numcollobj, unsigned int modifier_type, bool dupli) { - Base *base; + BaseLegacy *base; Object **objs; GroupObject *go; unsigned int numobj= 0, maxobj= 100; @@ -596,7 +596,7 @@ ListBase *get_collider_cache(Scene *scene, Object *self, Group *group) } else { Scene *sce_iter; - Base *base; + BaseLegacy *base; /* add objects in same layer in scene */ for (SETLOOPER(scene, sce_iter, base)) { diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c index 4c01bfd35f2..1cbf8cf01c8 100644 --- a/source/blender/blenkernel/intern/context.c +++ b/source/blender/blenkernel/intern/context.c @@ -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); diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c index bc9871aee54..39d06a13e6e 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.c +++ b/source/blender/blenkernel/intern/dynamicpaint.c @@ -488,7 +488,7 @@ static void scene_setSubframe(Scene *scene, float subframe) static int surface_getBrushFlags(DynamicPaintSurface *surface, const Scene *scene) { - Base *base = NULL; + BaseLegacy *base = NULL; GroupObject *go = NULL; Object *brushObj = NULL; ModifierData *md = NULL; @@ -5780,7 +5780,7 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su * Loop through surface's target paint objects and do painting */ { - Base *base = NULL; + BaseLegacy *base = NULL; GroupObject *go = NULL; Object *brushObj = NULL; ModifierData *md = NULL; diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index fe8f5ebdca6..668d4d6c9e2 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -209,7 +209,7 @@ static void add_particles_to_effectors(ListBase **effectors, Scene *scene, Effec ListBase *pdInitEffectors(Scene *scene, Object *ob_src, ParticleSystem *psys_src, EffectorWeights *weights, bool for_simulation) { - Base *base; + BaseLegacy *base; unsigned int layer= ob_src->lay; ListBase *effectors = NULL; diff --git a/source/blender/blenkernel/intern/group.c b/source/blender/blenkernel/intern/group.c index 9b011dbb003..9c81a8b49be 100644 --- a/source/blender/blenkernel/intern/group.c +++ b/source/blender/blenkernel/intern/group.c @@ -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; } diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c new file mode 100644 index 00000000000..cec1d70463f --- /dev/null +++ b/source/blender/blenkernel/intern/layer.c @@ -0,0 +1,684 @@ +/* + * ***** 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 */ +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 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 (Base *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; +} + +/* Base */ + +Base *BKE_scene_layer_base_find(SceneLayer *sl, Object *ob) +{ + return BLI_findptr(&sl->object_bases, ob, offsetof(Base, object)); +} + +void BKE_scene_layer_base_deselect_all(SceneLayer *sl) +{ + Base *base; + + for (base = sl->object_bases.first; base; base = base->next) { + base->flag &= ~BASE_SELECTED; + } +} + +void BKE_scene_layer_base_select(struct SceneLayer *sl, Base *selbase) +{ + sl->basact = selbase; + if ((selbase->flag & BASE_SELECTABLED) != 0) { + selbase->flag |= BASE_SELECTED; + } +} + +static void scene_layer_object_base_unref(SceneLayer* sl, Base *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) { + Base *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 (Base *base = sl->object_bases.first; base; base = base->next) { + if ((base->flag & BASE_SELECTABLED) == 0) { + base->flag &= ~BASE_SELECTED; + } + } +} + +/** + * Return the base if existent, or create it if necessary + * Always bump the refcount + */ +static Base *object_base_add(SceneLayer *sl, Object *ob) +{ + Base *base; + base = BKE_scene_layer_base_find(sl, ob); + + if (base == NULL) { + base = MEM_callocN(sizeof(Base), "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); + + 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) +{ + Base *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) +{ + Base *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_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) { + Base *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; +} + +/* ---------------------------------------------------------------------- */ +/* Iterators */ + +static void object_bases_Iterator_begin(Iterator *iter, void *data_in, const int flag) +{ + SceneLayer *sl = data_in; + Base *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) +{ + Base *base = ((Base *)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 = ((Base *)iter->current)->object; + } +} + +static void objects_Iterator_next(Iterator *iter, const int flag) +{ + object_bases_Iterator_next(iter, flag); + + if (iter->valid) { + iter->current = ((Base *)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 */ +} diff --git a/source/blender/blenkernel/intern/library_query.c b/source/blender/blenkernel/intern/library_query.c index 9685f1f5af6..a071b3202be 100644 --- a/source/blender/blenkernel/intern/library_query.c +++ b/source/blender/blenkernel/intern/library_query.c @@ -68,6 +68,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" @@ -354,7 +355,7 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call Scene *scene = (Scene *) id; ToolSettings *toolsett = scene->toolsettings; SceneRenderLayer *srl; - Base *base; + BaseLegacy *legacy_base; CALLBACK_INVOKE(scene->camera, IDWALK_CB_NOP); CALLBACK_INVOKE(scene->world, IDWALK_CB_USER); @@ -411,8 +412,28 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call CALLBACK_INVOKE(scene->gpd, IDWALK_CB_USER); - for (base = scene->base.first; base; base = base->next) { - CALLBACK_INVOKE(base->object, IDWALK_CB_USER); + for (legacy_base = scene->base.first; legacy_base; legacy_base = legacy_base->next) { + CALLBACK_INVOKE(legacy_base->object, IDWALK_CB_USER); + } + + SceneCollection *sc; + FOREACH_SCENE_COLLECTION(scene, sc) + { + for (LinkData *link = sc->objects.first; link; link = link->next) { + CALLBACK_INVOKE_ID(link->data, IDWALK_CB_USER); + } + + for (LinkData *link = sc->filter_objects.first; link; link = link->next) { + CALLBACK_INVOKE_ID(link->data, IDWALK_CB_USER); + } + } + FOREACH_SCENE_COLLECTION_END + + SceneLayer *sl; + for (sl = scene->render_layers.first; sl; sl = sl->next) { + for (Base *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) { diff --git a/source/blender/blenkernel/intern/library_remap.c b/source/blender/blenkernel/intern/library_remap.c index a408b498f18..9946d1cc81f 100644 --- a/source/blender/blenkernel/intern/library_remap.c +++ b/source/blender/blenkernel/intern/library_remap.c @@ -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" @@ -242,7 +243,7 @@ static int foreach_libblock_remap_callback(void *user_data, ID *id_self, ID **id /* Some reamapping unfortunately require extra and/or specific handling, tackle those here. */ static void libblock_remap_data_preprocess_scene_base_unlink( - IDRemap *r_id_remap_data, Scene *sce, Base *base, const bool skip_indirect, const bool is_indirect) + IDRemap *r_id_remap_data, Scene *sce, BaseLegacy *base, const bool skip_indirect, const bool is_indirect) { if (skip_indirect && is_indirect) { r_id_remap_data->skipped_indirect++; @@ -258,6 +259,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)) { @@ -272,7 +289,16 @@ 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. */ - Base *base, *base_next; + 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 + + + BaseLegacy *base, *base_next; for (base = sce->base.first; base; base = base_next) { base_next = base->next; libblock_remap_data_preprocess_scene_base_unlink( @@ -282,8 +308,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); + + BaseLegacy *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); @@ -329,7 +358,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 { @@ -342,23 +371,17 @@ 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; - - 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; - } + for (BaseLegacy *base = sce->base.first; base; base = base->next) { + Object *ob = base->object; + 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 (!(ob->flag & OB_FROMGROUP)) { - base->flag &= ~OB_FROMGROUP; + if (!grp) { + ob->flag &= ~OB_FROMGROUP; } } } diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c index 97033a9555d..2632acea58b 100644 --- a/source/blender/blenkernel/intern/mball.c +++ b/source/blender/blenkernel/intern/mball.c @@ -316,7 +316,7 @@ bool BKE_mball_is_basis_for(Object *ob1, Object *ob2) void BKE_mball_properties_copy(Scene *scene, Object *active_object) { Scene *sce_iter = scene; - Base *base; + BaseLegacy *base; Object *ob; MetaBall *active_mball = (MetaBall *)active_object->data; int basisnr, obnr; @@ -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, '.'); - - /* 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; + for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) { + for (Base *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; + } } } } diff --git a/source/blender/blenkernel/intern/mball_tessellate.c b/source/blender/blenkernel/intern/mball_tessellate.c index 5c0b09f0ff0..144a885ffd4 100644 --- a/source/blender/blenkernel/intern/mball_tessellate.c +++ b/source/blender/blenkernel/intern/mball_tessellate.c @@ -1080,7 +1080,7 @@ static void polygonize(PROCESS *process) static void init_meta(EvaluationContext *eval_ctx, PROCESS *process, Scene *scene, Object *ob) { Scene *sce_iter = scene; - Base *base; + BaseLegacy *base; Object *bob; MetaBall *mb; const MetaElem *ml; @@ -1102,7 +1102,7 @@ static void init_meta(EvaluationContext *eval_ctx, PROCESS *process, Scene *scen zero_size = 0; ml = NULL; - if (bob == ob && (base->flag & OB_FROMDUPLI) == 0) { + if (bob == ob && (base->flag_legacy & OB_FROMDUPLI) == 0) { mb = ob->data; if (mb->editelems) ml = mb->editelems->first; diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 3f3b4896653..05422a01dbf 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -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--; + } + } + } +} diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index ff8be5892e9..08cb9e57ab4 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -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" @@ -153,7 +154,7 @@ void BKE_object_workob_clear(Object *workob) void BKE_object_update_base_layer(struct Scene *scene, Object *ob) { - Base *base = scene->base.first; + BaseLegacy *base = scene->base.first; while (base) { if (base->object == ob) base->lay = ob->lay; @@ -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; + 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; } @@ -2542,11 +2545,11 @@ void BKE_scene_foreach_display_point( Scene *scene, View3D *v3d, const short flag, void (*func_cb)(const float[3], void *), void *user_data) { - Base *base; + BaseLegacy *base; Object *ob; for (base = FIRSTBASE; base; base = base->next) { - if (BASE_VISIBLE_BGMODE(v3d, scene, base) && (base->flag & flag) == flag) { + if (BASE_VISIBLE_BGMODE(v3d, scene, base) && (base->flag_legacy & flag) == flag) { ob = base->object; if ((ob->transflag & OB_DUPLI) == 0) { @@ -3351,7 +3354,7 @@ LinkNode *BKE_object_relational_superset(struct Scene *scene, eObjectSet objectS { LinkNode *links = NULL; - Base *base; + BaseLegacy *base; /* Remove markers from all objects */ for (base = scene->base.first; base; base = base->next) { @@ -3395,7 +3398,7 @@ LinkNode *BKE_object_relational_superset(struct Scene *scene, eObjectSet objectS /* child relationship */ if (includeFilter & (OB_REL_CHILDREN | OB_REL_CHILDREN_RECURSIVE)) { - Base *local_base; + BaseLegacy *local_base; for (local_base = scene->base.first; local_base; local_base = local_base->next) { if (BASE_EDITABLE_BGMODE(((View3D *)NULL), scene, local_base)) { @@ -3441,18 +3444,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); } } diff --git a/source/blender/blenkernel/intern/object_dupli.c b/source/blender/blenkernel/intern/object_dupli.c index e3b801b3193..26af1c48afb 100644 --- a/source/blender/blenkernel/intern/object_dupli.c +++ b/source/blender/blenkernel/intern/object_dupli.c @@ -241,7 +241,7 @@ static void make_child_duplis(const DupliContext *ctx, void *userdata, MakeChild else { unsigned int lay = ctx->scene->lay; int baseid = 0; - Base *base; + BaseLegacy *base; for (base = ctx->scene->base.first; base; base = base->next, baseid++) { Object *ob = base->object; diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 943dc781246..8531c7c9df9 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -2896,7 +2896,7 @@ static void psys_update_path_cache(ParticleSimulationData *sim, float cfra, cons ParticleSystem *psys = sim->psys; ParticleSettings *part = psys->part; ParticleEditSettings *pset = &sim->scene->toolsettings->particle; - Base *base; + BaseLegacy *base; int distr=0, alloc=0, skip=0; if ((psys->part->childtype && psys->totchild != psys_get_tot_child(sim->scene, psys)) || psys->recalc&PSYS_RECALC_RESET) diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index 30eb8dcb287..c3f2107c5af 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -3541,7 +3541,7 @@ void BKE_ptcache_bake(PTCacheBaker *baker) Main *bmain = baker->main; Scene *scene = baker->scene; Scene *sce_iter; /* SETLOOPER macro only */ - Base *base; + BaseLegacy *base; ListBase pidlist; PTCacheID *pid = &baker->pid; PointCache *cache = NULL; diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index a1338b4ea10..d47982f96eb 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -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" @@ -154,13 +156,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; + BaseLegacy *legacy_base, *olegacy_base; if (type == SCE_COPY_EMPTY) { ListBase rl, rv; @@ -214,14 +269,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 +299,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 (Base *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 +556,16 @@ 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; } void BKE_scene_init(Scene *sce) @@ -820,6 +915,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) @@ -835,9 +936,9 @@ Scene *BKE_scene_add(Main *bmain, const char *name) return sce; } -Base *BKE_scene_base_find_by_name(struct Scene *scene, const char *name) +BaseLegacy *BKE_scene_base_find_by_name(struct Scene *scene, const char *name) { - Base *base; + BaseLegacy *base; for (base = scene->base.first; base; base = base->next) { if (STREQ(base->object->id.name + 2, name)) { @@ -848,9 +949,9 @@ Base *BKE_scene_base_find_by_name(struct Scene *scene, const char *name) return base; } -Base *BKE_scene_base_find(Scene *scene, Object *ob) +BaseLegacy *BKE_scene_base_find(Scene *scene, Object *ob) { - return BLI_findptr(&scene->base, ob, offsetof(Base, object)); + return BLI_findptr(&scene->base, ob, offsetof(BaseLegacy, object)); } /** @@ -861,11 +962,10 @@ Base *BKE_scene_base_find(Scene *scene, Object *ob) void BKE_scene_set_background(Main *bmain, Scene *scene) { Scene *sce; - Base *base; + BaseLegacy *base; 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 +997,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) */ } @@ -924,7 +1018,7 @@ Scene *BKE_scene_set_name(Main *bmain, const char *name) /* Used by metaballs, return *all* objects (including duplis) existing in the scene (including scene's sets) */ int BKE_scene_base_iter_next(EvaluationContext *eval_ctx, SceneBaseIter *iter, - Scene **scene, int val, Base **base, Object **ob) + Scene **scene, int val, BaseLegacy **base, Object **ob) { bool run_again = true; @@ -1006,7 +1100,7 @@ int BKE_scene_base_iter_next(EvaluationContext *eval_ctx, SceneBaseIter *iter, } /* handle dupli's */ if (iter->dupob) { - (*base)->flag |= OB_FROMDUPLI; + (*base)->flag_legacy |= OB_FROMDUPLI; *ob = iter->dupob->ob; iter->phase = F_DUPLI; @@ -1025,7 +1119,7 @@ int BKE_scene_base_iter_next(EvaluationContext *eval_ctx, SceneBaseIter *iter, } else if (iter->phase == F_DUPLI) { iter->phase = F_SCENE; - (*base)->flag &= ~OB_FROMDUPLI; + (*base)->flag_legacy &= ~OB_FROMDUPLI; if (iter->dupli_refob) { /* Restore last object's real matrix. */ @@ -1052,7 +1146,7 @@ int BKE_scene_base_iter_next(EvaluationContext *eval_ctx, SceneBaseIter *iter, Object *BKE_scene_camera_find(Scene *sc) { - Base *base; + BaseLegacy *base; for (base = sc->base.first; base; base = base->next) if (base->object->type == OB_CAMERA) @@ -1154,28 +1248,32 @@ 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) +BaseLegacy *BKE_scene_base_add(Scene *sce, Object *ob) { - Base *b = MEM_callocN(sizeof(*b), __func__); + BaseLegacy *b = MEM_callocN(sizeof(*b), __func__); BLI_addhead(&sce->base, b); b->object = ob; - b->flag = ob->flag; + b->flag_legacy = ob->flag; b->lay = ob->lay; return b; } -void BKE_scene_base_unlink(Scene *sce, Base *base) +void BKE_scene_base_unlink(Scene *sce, BaseLegacy *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; @@ -1183,18 +1281,20 @@ void BKE_scene_base_unlink(Scene *sce, Base *base) void BKE_scene_base_deselect_all(Scene *sce) { - Base *b; + BaseLegacy *b; for (b = sce->base.first; b; b = b->next) { - b->flag &= ~SELECT; - b->object->flag = b->flag; + b->flag_legacy &= ~SELECT; + int flag = b->object->flag & (OB_FROMGROUP); + b->object->flag = b->flag_legacy; + b->object->flag |= flag; } } -void BKE_scene_base_select(Scene *sce, Base *selbase) +void BKE_scene_base_select(Scene *sce, BaseLegacy *selbase) { - selbase->flag |= SELECT; - selbase->object->flag = selbase->flag; + selbase->flag_legacy |= SELECT; + selbase->object->flag = selbase->flag_legacy; sce->basact = selbase; } @@ -1492,15 +1592,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); } } @@ -1588,7 +1680,7 @@ float get_render_aosss_error(const RenderData *r, float error) } /* helper function for the SETLOOPER macro */ -Base *_setlooper_base_step(Scene **sce_iter, Base *base) +BaseLegacy *_setlooper_base_step(Scene **sce_iter, BaseLegacy *base) { if (base && base->next) { /* common case, step to the next */ @@ -1596,12 +1688,12 @@ Base *_setlooper_base_step(Scene **sce_iter, Base *base) } else if (base == NULL && (*sce_iter)->base.first) { /* first time looping, return the scenes first base */ - return (Base *)(*sce_iter)->base.first; + return (BaseLegacy *)(*sce_iter)->base.first; } else { /* reached the end, get the next base in the set */ while ((*sce_iter = (*sce_iter)->set)) { - base = (Base *)(*sce_iter)->base.first; + base = (BaseLegacy *)(*sce_iter)->base.first; if (base) { return base; } @@ -1648,24 +1740,56 @@ bool BKE_scene_uses_blender_game(const Scene *scene) void BKE_scene_base_flag_to_objects(struct Scene *scene) { - Base *base = scene->base.first; + BaseLegacy *base = scene->base.first; while (base) { - base->object->flag = base->flag; + BKE_scene_base_flag_sync_from_base(base); base = base->next; } } void BKE_scene_base_flag_from_objects(struct Scene *scene) { - Base *base = scene->base.first; + BaseLegacy *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(BaseLegacy *base) +{ + Object *ob = base->object; + + /* keep the object only flags untouched */ + int flag = ob->flag & OB_FROMGROUP; + + ob->flag = base->flag_legacy; + ob->flag |= flag; +} + +void BKE_scene_base_flag_sync_from_object(BaseLegacy *base) +{ + base->flag_legacy = base->object->flag; +} + +void BKE_scene_object_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_object_base_flag_sync_from_object(Base *base) +{ + base->flag = base->object->flag; +} + void BKE_scene_disable_color_management(Scene *scene) { ColorManagedDisplaySettings *display_settings = &scene->display_settings; diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c index d0ef5cfc092..f1ce69d3945 100644 --- a/source/blender/blenkernel/intern/smoke.c +++ b/source/blender/blenkernel/intern/smoke.c @@ -698,7 +698,7 @@ static float calc_voxel_transp(float *result, float *input, int res[3], int *pix static int get_lamp(Scene *scene, float *light) { - Base *base_tmp = NULL; + BaseLegacy *base_tmp = NULL; int found_lamp = 0; // try to find a lamp, preferably local diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index 660107eb2e6..e7df1d810c9 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -530,7 +530,7 @@ static void ccd_build_deflector_hash(Scene *scene, Group *group, Object *vertexo } } else { - for (Base *base = scene->base.first; base; base = base->next) { + for (BaseLegacy *base = scene->base.first; base; base = base->next) { /*Only proceed for mesh object in same layer */ if (base->object->type == OB_MESH && (base->lay & vertexowner->lay)) { ob= base->object; @@ -576,7 +576,7 @@ static void ccd_update_deflector_hash(Scene *scene, Group *group, Object *vertex } } else { - for (Base *base = scene->base.first; base; base = base->next) { + for (BaseLegacy *base = scene->base.first; base; base = base->next) { /*Only proceed for mesh object in same layer */ if (base->object->type == OB_MESH && (base->lay & vertexowner->lay)) { ob= base->object; @@ -986,7 +986,7 @@ static bool are_there_deflectors(Scene *scene, Group *group, unsigned int layer) } } else { - for (Base *base = scene->base.first; base; base= base->next) { + for (BaseLegacy *base = scene->base.first; base; base= base->next) { if ( (base->lay & layer) && base->object->pd) { if (base->object->pd->deflect) return 1; diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c index 22288127119..e10f9207896 100644 --- a/source/blender/blenkernel/intern/sound.c +++ b/source/blender/blenkernel/intern/sound.c @@ -782,7 +782,7 @@ void BKE_sound_read_waveform(bSound *sound, short *stop) void BKE_sound_update_scene(Main *bmain, struct Scene *scene) { Object *ob; - Base *base; + BaseLegacy *base; NlaTrack *track; NlaStrip *strip; Speaker *speaker; diff --git a/source/blender/blenlib/BLI_ghash.h b/source/blender/blenlib/BLI_ghash.h index 7e3a009ede8..068c188e336 100644 --- a/source/blender/blenlib/BLI_ghash.h +++ b/source/blender/blenlib/BLI_ghash.h @@ -32,6 +32,7 @@ * \ingroup bli */ +#include "BLI_blenlib.h" #include "BLI_sys_types.h" /* for bool */ #include "BLI_compiler_attrs.h" diff --git a/source/blender/blenlib/BLI_iterator.h b/source/blender/blenlib/BLI_iterator.h new file mode 100644 index 00000000000..cfa303bb1cd --- /dev/null +++ b/source/blender/blenlib/BLI_iterator.h @@ -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__ */ diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt index 3277519c66e..97225170f67 100644 --- a/source/blender/blenlib/CMakeLists.txt +++ b/source/blender/blenlib/CMakeLists.txt @@ -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 diff --git a/source/blender/blenloader/CMakeLists.txt b/source/blender/blenloader/CMakeLists.txt index 8cb9ef837b2..e40692f4a88 100644 --- a/source/blender/blenloader/CMakeLists.txt +++ b/source/blender/blenloader/CMakeLists.txt @@ -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 diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 060d290df32..e669bf3b4a6 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -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" @@ -5630,11 +5633,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; + BaseLegacy *base_legacy, *base_legacy_next; Sequence *seq; + SceneLayer *sl; SceneRenderLayer *srl; FreestyleModuleConfig *fmc; FreestyleLineSet *fls; @@ -5684,17 +5705,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); } } @@ -5780,6 +5801,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 (Base *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, @@ -5883,12 +5913,42 @@ 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_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_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; sce->theDag = NULL; @@ -6139,6 +6199,19 @@ 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); + } } /* ************ READ WM ***************** */ @@ -6482,6 +6555,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; @@ -6867,6 +6944,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; + } } } } @@ -7261,6 +7342,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); @@ -7457,7 +7542,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 */ } } } @@ -8389,6 +8474,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! */ @@ -8400,8 +8486,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) @@ -9484,9 +9570,24 @@ 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; + BaseLegacy *base; SceneRenderLayer *srl; FreestyleModuleConfig *module; FreestyleLineSet *lineset; @@ -9553,6 +9654,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) @@ -9799,7 +9902,7 @@ static bool object_in_any_scene(Main *mainvar, Object *ob) static void give_base_to_objects(Main *mainvar, Scene *scene, View3D *v3d, Library *lib, const short flag) { Object *ob; - Base *base; + BaseLegacy *base; const unsigned int active_lay = (flag & FILE_ACTIVELAY) ? BKE_screen_view3d_layer_active(v3d, scene) : 0; const bool is_link = (flag & FILE_LINK) != 0; @@ -9820,7 +9923,7 @@ static void give_base_to_objects(Main *mainvar, Scene *scene, View3D *v3d, Libra } if (do_it) { - base = MEM_callocN(sizeof(Base), __func__); + base = MEM_callocN(sizeof(BaseLegacy), __func__); BLI_addtail(&scene->base, base); if (active_lay) { @@ -9835,7 +9938,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); @@ -9851,7 +9954,7 @@ static void give_base_to_groups( Main *mainvar, Scene *scene, View3D *v3d, Library *UNUSED(lib), const short UNUSED(flag)) { Group *group; - Base *base; + BaseLegacy *base; Object *ob; const unsigned int active_lay = BKE_screen_view3d_layer_active(v3d, scene); @@ -9868,8 +9971,8 @@ static void give_base_to_groups( /* assign the base */ base = BKE_scene_base_add(scene, ob); - base->flag |= SELECT; - base->object->flag = base->flag; + base->flag_legacy |= SELECT; + 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; @@ -9951,10 +10054,10 @@ static ID *link_named_part( static void link_object_postprocess(ID *id, Scene *scene, View3D *v3d, const short flag) { if (scene) { - Base *base; + BaseLegacy *base; Object *ob; - base = MEM_callocN(sizeof(Base), "app_nam_part"); + base = MEM_callocN(sizeof(BaseLegacy), "app_nam_part"); BLI_addtail(&scene->base, base); ob = (Object *)id; @@ -9967,12 +10070,12 @@ static void link_object_postprocess(ID *id, Scene *scene, View3D *v3d, const sho ob->mode = OB_MODE_OBJECT; base->lay = ob->lay; base->object = ob; - base->flag = ob->flag; + base->flag_legacy = ob->flag; id_us_plus_no_lib((ID *)ob); if (flag & FILE_AUTOSELECT) { - base->flag |= SELECT; - base->object->flag = base->flag; + base->flag_legacy |= SELECT; + 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 */ } } diff --git a/source/blender/blenloader/intern/readfile.h b/source/blender/blenloader/intern/readfile.h index d97bef13a78..50cdeca16b5 100644 --- a/source/blender/blenloader/intern/readfile.h +++ b/source/blender/blenloader/intern/readfile.h @@ -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 diff --git a/source/blender/blenloader/intern/versioning_250.c b/source/blender/blenloader/intern/versioning_250.c index 1956a17d57b..943e5479d9a 100644 --- a/source/blender/blenloader/intern/versioning_250.c +++ b/source/blender/blenloader/intern/versioning_250.c @@ -736,7 +736,7 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *main) if (main->versionfile < 250) { bScreen *screen; Scene *scene; - Base *base; + BaseLegacy *base; Material *ma; Camera *cam; Mesh *me; diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c new file mode 100644 index 00000000000..a4e69c9d514 --- /dev/null +++ b/source/blender/blenloader/intern/versioning_280.c @@ -0,0 +1,181 @@ +/* + * ***** 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_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 (BaseLegacy *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 (BaseLegacy *base = scene->base.first; base; base = base->next) { + Base *ob_base = BKE_scene_layer_base_find(sl, base->object); + if ((base->flag_legacy & 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 (BaseLegacy *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)); + } + } + } +} diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 5011f9836b7..4ddf83d306b 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -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" @@ -2626,10 +2627,34 @@ 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_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_layer_collections(wd, &lc->layer_collections); + } +} + static void write_scenes(WriteData *wd, ListBase *scebase) { Scene *sce; - Base *base; + BaseLegacy *base; Editing *ed; Sequence *seq; MetaStack *ms; @@ -2641,6 +2666,7 @@ static void write_scenes(WriteData *wd, ListBase *scebase) ToolSettings *tos; FreestyleModuleConfig *fmc; FreestyleLineSet *fls; + SceneLayer *sl; sce = scebase->first; while (sce) { @@ -2656,7 +2682,7 @@ static void write_scenes(WriteData *wd, ListBase *scebase) /* direct data */ base = sce->base.first; while (base) { - writestruct(wd, DATA, Base, 1, base); + writestruct(wd, DATA, BaseLegacy, 1, base); base = base->next; } @@ -2846,6 +2872,14 @@ 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, Base, &sl->object_bases); + write_layer_collections(wd, &sl->layer_collections); + } + sce = sce->id.next; } @@ -3167,6 +3201,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; } diff --git a/source/blender/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp index 226f319cefd..ef505e5ed3e 100644 --- a/source/blender/collada/DocumentImporter.cpp +++ b/source/blender/collada/DocumentImporter.cpp @@ -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" @@ -264,7 +265,7 @@ void DocumentImporter::finish() for (it = libnode_ob.begin(); it != libnode_ob.end(); it++) { Object *ob = *it; - Base *base = BKE_scene_base_find(sce, ob); + BaseLegacy *base = BKE_scene_base_find(sce, ob); if (base) { BLI_remlink(&sce->base, base); BKE_libblock_free_us(G.main, base->object); @@ -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); diff --git a/source/blender/collada/EffectExporter.cpp b/source/blender/collada/EffectExporter.cpp index 76b51148509..7d9599c8554 100644 --- a/source/blender/collada/EffectExporter.cpp +++ b/source/blender/collada/EffectExporter.cpp @@ -66,7 +66,7 @@ EffectsExporter::EffectsExporter(COLLADASW::StreamWriter *sw, const ExportSettin bool EffectsExporter::hasEffects(Scene *sce) { - Base *base = (Base *)sce->base.first; + BaseLegacy *base = (BaseLegacy *)sce->base.first; while (base) { Object *ob = base->object; diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc index 9fea68fc941..373d9dc4348 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc @@ -338,7 +338,7 @@ void DepsgraphNodeBuilder::begin_build(Main *bmain) { } void DepsgraphNodeBuilder::build_group(Scene *scene, - Base *base, + BaseLegacy *base, Group *group) { ID *group_id = &group->id; @@ -387,7 +387,7 @@ SubgraphDepsNode *DepsgraphNodeBuilder::build_subgraph(Group *group) return subgraph_node; } -void DepsgraphNodeBuilder::build_object(Scene *scene, Base *base, Object *ob) +void DepsgraphNodeBuilder::build_object(Scene *scene, BaseLegacy *base, Object *ob) { const bool has_object = (ob->id.tag & LIB_TAG_DOIT); IDDepsNode *id_node = (has_object) diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h index c5035f35f6e..ab66fb90160 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h @@ -32,7 +32,10 @@ #include "intern/depsgraph_types.h" -struct Base; +/* XXX: Temporary solution to get proper Baselegacy. */ +#include "DNA_scene_types.h" + +struct BaseLegacy; struct CacheFile; struct bGPdata; struct ListBase; @@ -126,8 +129,8 @@ struct DepsgraphNodeBuilder { void build_scene(Main *bmain, Scene *scene); SubgraphDepsNode *build_subgraph(Group *group); - void build_group(Scene *scene, Base *base, Group *group); - void build_object(Scene *scene, Base *base, Object *ob); + void build_group(Scene *scene, BaseLegacy *base, Group *group); + void build_object(Scene *scene, BaseLegacy *base, Object *ob); void build_object_transform(Scene *scene, Object *ob); void build_object_constraints(Scene *scene, Object *ob); void build_pose_constraints(Object *ob, bPoseChannel *pchan); diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc index 99e61692231..507f2572927 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc @@ -79,7 +79,7 @@ void DepsgraphNodeBuilder::build_scene(Main *bmain, Scene *scene) } /* scene objects */ - LINKLIST_FOREACH (Base *, base, &scene->base) { + LINKLIST_FOREACH (BaseLegacy *, base, &scene->base) { Object *ob = base->object; /* object itself */ diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.h b/source/blender/depsgraph/intern/builder/deg_builder_relations.h index 054e4103290..2e6fa7b5801 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.h @@ -45,7 +45,7 @@ #include "intern/nodes/deg_node.h" #include "intern/nodes/deg_node_operation.h" -struct Base; +struct BaseLegacy; struct bGPdata; struct CacheFile; struct ListBase; diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc index 8a3476cff45..8b68516a027 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc @@ -74,7 +74,7 @@ void DepsgraphRelationBuilder::build_scene(Main *bmain, Scene *scene) } /* scene objects */ - LINKLIST_FOREACH (Base *, base, &scene->base) { + LINKLIST_FOREACH (BaseLegacy *, base, &scene->base) { Object *ob = base->object; /* object itself */ diff --git a/source/blender/editors/CMakeLists.txt b/source/blender/editors/CMakeLists.txt index 1559512d713..7e804a5bbfc 100644 --- a/source/blender/editors/CMakeLists.txt +++ b/source/blender/editors/CMakeLists.txt @@ -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) diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c index 4163cbfe113..ef8dabc1631 100644 --- a/source/blender/editors/animation/anim_channels_defines.c +++ b/source/blender/editors/animation/anim_channels_defines.c @@ -631,7 +631,7 @@ static bAnimChannelType ACF_SCENE = static int acf_object_icon(bAnimListElem *ale) { - Base *base = (Base *)ale->data; + BaseLegacy *base = (BaseLegacy *)ale->data; Object *ob = base->object; /* icon depends on object-type */ @@ -666,7 +666,7 @@ static int acf_object_icon(bAnimListElem *ale) /* name for object */ static void acf_object_name(bAnimListElem *ale, char *name) { - Base *base = (Base *)ale->data; + BaseLegacy *base = (BaseLegacy *)ale->data; Object *ob = base->object; /* just copy the name... */ @@ -686,7 +686,7 @@ static bool acf_object_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRN /* check if some setting exists for this channel */ static bool acf_object_setting_valid(bAnimContext *ac, bAnimListElem *ale, eAnimChannel_Settings setting) { - Base *base = (Base *)ale->data; + BaseLegacy *base = (BaseLegacy *)ale->data; Object *ob = base->object; switch (setting) { @@ -743,7 +743,7 @@ static int acf_object_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settin /* get pointer to the setting */ static void *acf_object_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type) { - Base *base = (Base *)ale->data; + BaseLegacy *base = (BaseLegacy *)ale->data; Object *ob = base->object; /* clear extra return data first */ diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index 117b8549712..22578b6a518 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -57,6 +57,7 @@ #include "BKE_context.h" #include "BKE_mask.h" #include "BKE_global.h" +#include "BKE_scene.h" #include "UI_view2d.h" @@ -2682,31 +2683,31 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index, { bDopeSheet *ads = (bDopeSheet *)ac->data; Scene *sce = (Scene *)ads->source; - Base *base = (Base *)ale->data; + BaseLegacy *base = (BaseLegacy *)ale->data; Object *ob = base->object; AnimData *adt = ob->adt; /* set selection status */ if (selectmode == SELECT_INVERT) { /* swap select */ - base->flag ^= SELECT; - ob->flag = base->flag; + base->flag_legacy ^= SELECT; + BKE_scene_base_flag_sync_from_base(base); if (adt) adt->flag ^= ADT_UI_SELECTED; } else { - Base *b; + BaseLegacy *b; /* deselect all */ /* 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; + b->flag_legacy &= ~SELECT; + BKE_scene_base_flag_sync_from_base(b); if (b->object->adt) b->object->adt->flag &= ~(ADT_UI_SELECTED | ADT_UI_ACTIVE); } /* select object now */ - base->flag |= SELECT; + base->flag_legacy |= SELECT; ob->flag |= SELECT; if (adt) adt->flag |= ADT_UI_SELECTED; } diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index 2f73eb6b71c..7b6d30469a4 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -601,7 +601,7 @@ static bAnimListElem *make_new_animlistelem(void *data, short datatype, ID *owne } case ANIMTYPE_OBJECT: { - Base *base = (Base *)data; + BaseLegacy *base = (BaseLegacy *)data; Object *ob = base->object; ale->flag = ob->flag; @@ -1683,7 +1683,7 @@ static size_t animdata_filter_gpencil(bAnimContext *ac, ListBase *anim_data, voi if (ads->filterflag & ADS_FILTER_GP_3DONLY) { Scene *scene = (Scene *)ads->source; - Base *base; + BaseLegacy *base; /* Active scene's GPencil block first - No parent item needed... */ if (scene->gpd) { @@ -1714,7 +1714,7 @@ static size_t animdata_filter_gpencil(bAnimContext *ac, ListBase *anim_data, voi } /* check selection and object type filters */ - if ( (ads->filterflag & ADS_FILTER_ONLYSEL) && !((base->flag & SELECT) /*|| (base == scene->basact)*/) ) { + if ( (ads->filterflag & ADS_FILTER_ONLYSEL) && !((base->flag_legacy & SELECT) /*|| (base == scene->basact)*/) ) { /* only selected should be shown */ continue; } @@ -2573,7 +2573,7 @@ static size_t animdata_filter_ds_obanim(bAnimContext *ac, ListBase *anim_data, b } /* get animation channels from object2 */ -static size_t animdata_filter_dopesheet_ob(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode) +static size_t animdata_filter_dopesheet_ob(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, BaseLegacy *base, int filter_mode) { ListBase tmp_data = {NULL, NULL}; Object *ob = base->object; @@ -2629,7 +2629,7 @@ static size_t animdata_filter_dopesheet_ob(bAnimContext *ac, ListBase *anim_data if (filter_mode & ANIMFILTER_LIST_CHANNELS) { /* check if filtering by selection */ // XXX: double-check on this - most of the time, a lot of tools need to filter out these channels! - if (ANIMCHANNEL_SELOK((base->flag & SELECT))) { + if (ANIMCHANNEL_SELOK((base->flag_legacy & SELECT))) { /* check if filtering by active status */ if (ANIMCHANNEL_ACTIVEOK(ob)) { ANIMCHANNEL_NEW_CHANNEL(base, ANIMTYPE_OBJECT, ob); @@ -2853,7 +2853,7 @@ static size_t animdata_filter_dopesheet_movieclips(bAnimContext *ac, ListBase *a } /* Helper for animdata_filter_dopesheet() - For checking if an object should be included or not */ -static bool animdata_filter_base_is_ok(bDopeSheet *ads, Scene *scene, Base *base, int filter_mode) +static bool animdata_filter_base_is_ok(bDopeSheet *ads, Scene *scene, BaseLegacy *base, int filter_mode) { Object *ob = base->object; @@ -2906,7 +2906,7 @@ static bool animdata_filter_base_is_ok(bDopeSheet *ads, Scene *scene, Base *base } /* check selection and object type filters */ - if ((ads->filterflag & ADS_FILTER_ONLYSEL) && !((base->flag & SELECT) /*|| (base == sce->basact)*/)) { + if ((ads->filterflag & ADS_FILTER_ONLYSEL) && !((base->flag_legacy & SELECT) /*|| (base == sce->basact)*/)) { /* only selected should be shown */ return false; } @@ -2927,28 +2927,28 @@ static bool animdata_filter_base_is_ok(bDopeSheet *ads, Scene *scene, Base *base /* Helper for animdata_filter_ds_sorted_bases() - Comparison callback for two Base pointers... */ static int ds_base_sorting_cmp(const void *base1_ptr, const void *base2_ptr) { - const Base *b1 = *((const Base **)base1_ptr); - const Base *b2 = *((const Base **)base2_ptr); + const BaseLegacy *b1 = *((const BaseLegacy **)base1_ptr); + const BaseLegacy *b2 = *((const BaseLegacy **)base2_ptr); return strcmp(b1->object->id.name + 2, b2->object->id.name + 2); } /* Get a sorted list of all the bases - for inclusion in dopesheet (when drawing channels) */ -static Base **animdata_filter_ds_sorted_bases(bDopeSheet *ads, Scene *scene, int filter_mode, size_t *r_usable_bases) +static BaseLegacy **animdata_filter_ds_sorted_bases(bDopeSheet *ads, Scene *scene, int filter_mode, size_t *r_usable_bases) { /* Create an array with space for all the bases, but only containing the usable ones */ size_t tot_bases = BLI_listbase_count(&scene->base); size_t num_bases = 0; - Base **sorted_bases = MEM_mallocN(sizeof(Base *) * tot_bases, "Dopesheet Usable Sorted Bases"); - for (Base *base = scene->base.first; base; base = base->next) { + BaseLegacy **sorted_bases = MEM_mallocN(sizeof(BaseLegacy *) * tot_bases, "Dopesheet Usable Sorted Bases"); + for (BaseLegacy *base = scene->base.first; base; base = base->next) { if (animdata_filter_base_is_ok(ads, scene, base, filter_mode)) { sorted_bases[num_bases++] = base; } } /* Sort this list of pointers (based on the names) */ - qsort(sorted_bases, num_bases, sizeof(Base *), ds_base_sorting_cmp); + qsort(sorted_bases, num_bases, sizeof(BaseLegacy *), ds_base_sorting_cmp); /* Return list of sorted bases */ *r_usable_bases = num_bases; @@ -3002,7 +3002,7 @@ static size_t animdata_filter_dopesheet(bAnimContext *ac, ListBase *anim_data, b { /* Filter list of bases (i.e. objects), sort them, then add their contents normally... */ // TODO: Cache the old sorted order - if the set of bases hasn't changed, don't re-sort... - Base **sorted_bases; + BaseLegacy **sorted_bases; size_t num_bases; sorted_bases = animdata_filter_ds_sorted_bases(ads, scene, filter_mode, &num_bases); @@ -3022,7 +3022,7 @@ static size_t animdata_filter_dopesheet(bAnimContext *ac, ListBase *anim_data, b /* Filter and add contents of each base (i.e. object) without them sorting first * NOTE: This saves performance in cases where order doesn't matter */ - for (Base *base = scene->base.first; base; base = base->next) { + for (BaseLegacy *base = scene->base.first; base; base = base->next) { if (animdata_filter_base_is_ok(ads, scene, base, filter_mode)) { /* since we're still here, this object should be usable */ items += animdata_filter_dopesheet_ob(ac, anim_data, ads, base, filter_mode); diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c index 823cde75334..f4a673a888b 100644 --- a/source/blender/editors/animation/anim_markers.c +++ b/source/blender/editors/animation/anim_markers.c @@ -1124,7 +1124,7 @@ static int ed_marker_select(bContext *C, const wmEvent *event, bool extend, bool if (camera) { Scene *scene = CTX_data_scene(C); - Base *base; + BaseLegacy *base; TimeMarker *marker; int sel = 0; diff --git a/source/blender/editors/animation/keyframes_draw.c b/source/blender/editors/animation/keyframes_draw.c index 5f675e690b9..c66fb27e525 100644 --- a/source/blender/editors/animation/keyframes_draw.c +++ b/source/blender/editors/animation/keyframes_draw.c @@ -938,7 +938,7 @@ void ob_to_keylist(bDopeSheet *ads, Object *ob, DLRBT_Tree *keys, DLRBT_Tree *bl int filter; bAnimListElem dummychan = {NULL}; - Base dummybase = {NULL}; + BaseLegacy dummybase = {NULL}; if (ob == NULL) return; diff --git a/source/blender/editors/animation/keyframes_edit.c b/source/blender/editors/animation/keyframes_edit.c index 4571df0f077..f4922fec385 100644 --- a/source/blender/editors/animation/keyframes_edit.c +++ b/source/blender/editors/animation/keyframes_edit.c @@ -193,7 +193,7 @@ static short ob_keyframes_loop(KeyframeEditData *ked, bDopeSheet *ads, Object *o int ret = 0; bAnimListElem dummychan = {NULL}; - Base dummybase = {NULL}; + BaseLegacy dummybase = {NULL}; if (ob == NULL) return 0; diff --git a/source/blender/editors/armature/armature_intern.h b/source/blender/editors/armature/armature_intern.h index b39b4bd81ee..d75193a46ff 100644 --- a/source/blender/editors/armature/armature_intern.h +++ b/source/blender/editors/armature/armature_intern.h @@ -37,7 +37,7 @@ struct wmOperatorType; struct bContext; struct Scene; struct Object; -struct Base; +struct BaseLegacy; struct bAction; struct bPoseChannel; @@ -248,7 +248,7 @@ void armature_select_mirrored(struct bArmature *arm); void armature_tag_unselect(struct bArmature *arm); void *get_nearest_bone(struct bContext *C, short findunsel, int x, int y); -void *get_bone_from_selectbuffer(struct Scene *scene, struct Base *base, unsigned int *buffer, short hits, short findunsel, bool do_nearest); +void *get_bone_from_selectbuffer(struct Scene *scene, struct BaseLegacy *base, unsigned int *buffer, short hits, short findunsel, bool do_nearest); int bone_looper(struct Object *ob, struct Bone *bone, void *data, int (*bone_func)(struct Object *, struct Bone *, void *)); diff --git a/source/blender/editors/armature/armature_relations.c b/source/blender/editors/armature/armature_relations.c index 1c342657eec..0dc97483dfc 100644 --- a/source/blender/editors/armature/armature_relations.c +++ b/source/blender/editors/armature/armature_relations.c @@ -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" @@ -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,6 +580,7 @@ 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; @@ -602,14 +604,18 @@ static int separate_armature_exec(bContext *C, wmOperator *op) /* TODO: use context iterators for this? */ CTX_DATA_BEGIN(C, Base *, 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); diff --git a/source/blender/editors/armature/armature_select.c b/source/blender/editors/armature/armature_select.c index e9946abba0b..1f994a7f13e 100644 --- a/source/blender/editors/armature/armature_select.c +++ b/source/blender/editors/armature/armature_select.c @@ -74,7 +74,7 @@ Bone *get_indexed_bone(Object *ob, int index) /* See if there are any selected bones in this buffer */ /* only bones from base are checked on */ -void *get_bone_from_selectbuffer(Scene *scene, Base *base, unsigned int *buffer, short hits, short findunsel, bool do_nearest) +void *get_bone_from_selectbuffer(Scene *scene, BaseLegacy *base, unsigned int *buffer, short hits, short findunsel, bool do_nearest) { Object *obedit = scene->obedit; // XXX get from context Bone *bone; diff --git a/source/blender/editors/armature/editarmature_sketch.c b/source/blender/editors/armature/editarmature_sketch.c index cc4c1809fbc..caa18b91775 100644 --- a/source/blender/editors/armature/editarmature_sketch.c +++ b/source/blender/editors/armature/editarmature_sketch.c @@ -142,7 +142,7 @@ void BIF_makeListTemplates(const bContext *C) Object *obedit = CTX_data_edit_object(C); Scene *scene = CTX_data_scene(C); ToolSettings *ts = CTX_data_tool_settings(C); - Base *base; + BaseLegacy *base; int index = 0; if (TEMPLATES_HASH != NULL) { diff --git a/source/blender/editors/armature/pose_select.c b/source/blender/editors/armature/pose_select.c index 44470c1f827..903d309cb1f 100644 --- a/source/blender/editors/armature/pose_select.c +++ b/source/blender/editors/armature/pose_select.c @@ -132,7 +132,7 @@ void ED_pose_bone_select(Object *ob, bPoseChannel *pchan, bool select) /* called from editview.c, for mode-less pose selection */ /* assumes scene obact and basact is still on old situation */ -int ED_do_pose_selectbuffer(Scene *scene, Base *base, unsigned int *buffer, short hits, +int ED_do_pose_selectbuffer(Scene *scene, BaseLegacy *base, unsigned int *buffer, short hits, bool extend, bool deselect, bool toggle, bool do_nearest) { Object *ob = base->object; diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index e9fd5fb5a43..6b5a5d81d32 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -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,6 +1271,7 @@ 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; Curve *oldcu, *newcu; @@ -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; @@ -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); } } } diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c index 57e731874b4..d86091aaa77 100644 --- a/source/blender/editors/curve/editfont.c +++ b/source/blender/editors/curve/editfont.c @@ -420,6 +420,7 @@ 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; @@ -429,8 +430,8 @@ static void txt_add_object(bContext *C, TextLine *firstline, int totline, const 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); diff --git a/source/blender/editors/gpencil/gpencil_convert.c b/source/blender/editors/gpencil/gpencil_convert.c index d0f68c4b8f3..505114869ac 100644 --- a/source/blender/editors/gpencil/gpencil_convert.c +++ b/source/blender/editors/gpencil/gpencil_convert.c @@ -1128,7 +1128,7 @@ static void gp_layer_to_curve(bContext *C, ReportList *reports, bGPdata *gpd, bG Object *ob; Curve *cu; Nurb *nu = NULL; - Base *base_orig = BASACT, *base_new = NULL; + BaseLegacy *base_orig = BASACT, *base_new = NULL; float minmax_weights[2] = {1.0f, 0.0f}; /* camera framing */ @@ -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_legacy |= SELECT; + BKE_scene_base_flag_sync_from_base(base_new); } /* --- */ diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c index 76e85f20c36..e3b6b748227 100644 --- a/source/blender/editors/gpencil/gpencil_utils.c +++ b/source/blender/editors/gpencil/gpencil_utils.c @@ -204,7 +204,7 @@ bGPdata *ED_gpencil_data_get_active(const bContext *C) // XXX: this should be removed... We really shouldn't duplicate logic like this! bGPdata *ED_gpencil_data_get_active_v3d(Scene *scene, View3D *v3d) { - Base *base = scene->basact; + BaseLegacy *base = scene->basact; bGPdata *gpd = NULL; /* We have to make sure active object is actually visible and selected, else we must use default scene gpd, * to be consistent with ED_gpencil_data_get_active's behavior. diff --git a/source/blender/editors/include/BIF_glutil.h b/source/blender/editors/include/BIF_glutil.h index 35d38bf4ca1..96532f748e4 100644 --- a/source/blender/editors/include/BIF_glutil.h +++ b/source/blender/editors/include/BIF_glutil.h @@ -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 */ diff --git a/source/blender/editors/include/ED_armature.h b/source/blender/editors/include/ED_armature.h index 7ad61671b1b..3bde01a1bdd 100644 --- a/source/blender/editors/include/ED_armature.h +++ b/source/blender/editors/include/ED_armature.h @@ -35,7 +35,7 @@ extern "C" { #endif struct bArmature; -struct Base; +struct BaseLegacy; struct bContext; struct Bone; struct bPoseChannel; @@ -44,6 +44,7 @@ struct ListBase; struct MeshDeformModifierData; struct DerivedMesh; struct Object; +struct Base; struct ReportList; struct Scene; struct ViewContext; @@ -130,7 +131,7 @@ void ED_armature_ebone_listbase_temp_clear(struct ListBase *lb); void ED_armature_deselect_all(struct Object *obedit); void ED_armature_deselect_all_visible(struct Object *obedit); -int ED_do_pose_selectbuffer(struct Scene *scene, struct Base *base, unsigned int *buffer, +int ED_do_pose_selectbuffer(struct Scene *scene, struct BaseLegacy *base, unsigned int *buffer, short hits, bool extend, bool deselect, bool toggle, bool do_nearest); bool ED_armature_select_pick(struct bContext *C, const int mval[2], bool extend, bool deselect, bool toggle); int join_armature_exec(struct bContext *C, struct wmOperator *op); diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h index 04ff5692717..4d79a42e64e 100644 --- a/source/blender/editors/include/ED_object.h +++ b/source/blender/editors/include/ED_object.h @@ -35,14 +35,16 @@ extern "C" { #endif -struct Base; +struct BaseLegacy; struct EnumPropertyItem; struct ID; struct Main; struct ModifierData; struct Object; +struct Base; 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); @@ -98,14 +100,20 @@ void ED_keymap_proportional_editmode(struct wmKeyConfig *keyconf, struct wmKeyMa const bool do_connected); /* send your own notifier for select! */ -void ED_base_object_select(struct Base *base, short mode); +void ED_base_object_select(struct BaseLegacy *base, short mode); /* includes notifier */ -void ED_base_object_activate(struct bContext *C, struct Base *base); +void ED_base_object_activate(struct bContext *C, struct BaseLegacy *base); + +void ED_object_base_select(struct Base *base, short mode); +void ED_object_base_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_base_object_free_and_unlink(struct Main *bmain, struct Scene *scene, struct Object *ob); + +void ED_base_object_sync_from_base(struct BaseLegacy *base, struct Object *ob); +void ED_base_object_sync_from_object(struct BaseLegacy *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 Base *ED_object_add_duplicate(struct Main *bmain, struct Scene *scene, struct SceneLayer *sl, struct Base *base, int dupflag); void ED_object_parent(struct Object *ob, struct Object *parent, const int type, const char *substr); @@ -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); diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index f5f66a07aea..01be63919be 100644 --- a/source/blender/editors/include/ED_screen.h +++ b/source/blender/editors/include/ED_screen.h @@ -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); diff --git a/source/blender/editors/include/ED_space_api.h b/source/blender/editors/include/ED_space_api.h index d268c578cf2..b754e1ba20f 100644 --- a/source/blender/editors/include/ED_space_api.h +++ b/source/blender/editors/include/ED_space_api.h @@ -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 */ diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h index ebd2a3dcb7a..898eecd3e42 100644 --- a/source/blender/editors/include/ED_transform.h +++ b/source/blender/editors/include/ED_transform.h @@ -109,7 +109,7 @@ enum TfmMode { bool calculateTransformCenter(struct bContext *C, int centerMode, float cent3d[3], float cent2d[2]); struct TransInfo; -struct Base; +struct BaseLegacy; struct Scene; struct Object; struct wmOperator; diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index 53253c1274f..3bbc7617745 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -37,7 +37,7 @@ struct BMEdge; struct BMFace; struct BMVert; struct BPoint; -struct Base; +struct BaseLegacy; struct BezTriple; struct BoundBox; struct EditBone; @@ -187,7 +187,7 @@ void pose_foreachScreenBone( void ED_view3d_project_float_v2_m4(const struct ARegion *ar, const float co[3], float r_co[2], float mat[4][4]); void ED_view3d_project_float_v3_m4(const struct ARegion *ar, const float co[3], float r_co[3], float mat[4][4]); -eV3DProjStatus ED_view3d_project_base(const struct ARegion *ar, struct Base *base); +eV3DProjStatus ED_view3d_project_base(const struct ARegion *ar, struct BaseLegacy *base); /* *** short *** */ eV3DProjStatus ED_view3d_project_short_ex(const struct ARegion *ar, float perspmat[4][4], const bool is_local, @@ -353,7 +353,7 @@ struct ImBuf *ED_view3d_draw_offscreen_imbuf_simple( int alpha_mode, int samples, bool full_samples, const char *viewname, struct GPUFX *fx, struct GPUOffScreen *ofs, char err_out[256]); -struct Base *ED_view3d_give_base_under_cursor(struct bContext *C, const int mval[2]); +struct BaseLegacy *ED_view3d_give_base_under_cursor(struct bContext *C, const int mval[2]); void ED_view3d_quadview_update(struct ScrArea *sa, struct ARegion *ar, bool do_clip); void ED_view3d_update_viewmat(struct Scene *scene, struct View3D *v3d, struct ARegion *ar, float viewmat[4][4], float winmat[4][4]); bool ED_view3d_quat_from_axis_view(const char view, float quat[4]); diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 286ac6054e2..8caf772ca9a 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -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 */ diff --git a/source/blender/editors/include/UI_interface_icons.h b/source/blender/editors/include/UI_interface_icons.h index 945ac1b6db9..f08c46af8a6 100644 --- a/source/blender/editors/include/UI_interface_icons.h +++ b/source/blender/editors/include/UI_interface_icons.h @@ -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__ */ diff --git a/source/blender/editors/interface/interface_eyedropper.c b/source/blender/editors/interface/interface_eyedropper.c index 0a21c89e692..a50c0f5a4f4 100644 --- a/source/blender/editors/interface/interface_eyedropper.c +++ b/source/blender/editors/interface/interface_eyedropper.c @@ -597,7 +597,7 @@ static void datadropper_id_sample_pt(bContext *C, DataDropper *ddr, int mx, int const int mval[2] = { mx - ar->winrct.xmin, my - ar->winrct.ymin}; - Base *base; + BaseLegacy *base; CTX_wm_area_set(C, sa); CTX_wm_region_set(C, ar); diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index 0573e8d9c94..70bfd30c2d8 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -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) diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index b580d394dd0..84b022ca440 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -1576,7 +1576,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)) { diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index 76b8f348c9c..8bd671873be 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -167,6 +167,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; @@ -1208,6 +1211,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) @@ -2859,7 +2867,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) diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 8f004bcf72b..549bcd4c4b6 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -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,7 +3011,7 @@ enum { MESH_SEPARATE_LOOSE = 2, }; -static Base *mesh_separate_tagged(Main *bmain, Scene *scene, Base *base_old, BMesh *bm_old) +static Base *mesh_separate_tagged(Main *bmain, Scene *scene, SceneLayer *sl, Base *base_old, BMesh *bm_old) { Base *base_new; Object *obedit = base_old->object; @@ -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, Base *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,7 +3165,7 @@ 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, Base *base_old, BMesh *bm_old) { BMFace *f_cmp, *f; BMIter iter; @@ -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, Base *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,6 +3280,7 @@ 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; @@ -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); @@ -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); diff --git a/source/blender/editors/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.c index 772bb1bd308..036d084a91c 100644 --- a/source/blender/editors/mesh/mesh_data.c +++ b/source/blender/editors/mesh/mesh_data.c @@ -551,7 +551,7 @@ static int drop_named_image_invoke(bContext *C, wmOperator *op, const wmEvent *e Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); View3D *v3d = CTX_wm_view3d(C); - Base *base; + BaseLegacy *base; Image *ima = NULL; Mesh *me; Object *obedit; diff --git a/source/blender/editors/mesh/mesh_navmesh.c b/source/blender/editors/mesh/mesh_navmesh.c index b95921964eb..443f2f0baa8 100644 --- a/source/blender/editors/mesh/mesh_navmesh.c +++ b/source/blender/editors/mesh/mesh_navmesh.c @@ -326,7 +326,7 @@ static bool buildNavMesh(const RecastData *recastParams, int nverts, float *vert } static Object *createRepresentation(bContext *C, struct recast_polyMesh *pmesh, struct recast_polyMeshDetail *dmesh, - Base *base, unsigned int lay) + BaseLegacy *base, unsigned int lay) { float co[3], rot[3]; BMEditMesh *em; @@ -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; + BaseLegacy *navmeshBase = NULL; CTX_DATA_BEGIN (C, Base *, 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; } } diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c index 743efb246ab..c8b0955c70f 100644 --- a/source/blender/editors/mesh/meshtools.c +++ b/source/blender/editors/mesh/meshtools.c @@ -526,7 +526,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); } } } diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index 02b2d8492b4..e7223f6f1ee 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -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" @@ -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) { @@ -830,7 +832,7 @@ static int empty_drop_named_image_invoke(bContext *C, wmOperator *op, const wmEv { Scene *scene = CTX_data_scene(C); - Base *base = NULL; + BaseLegacy *base = NULL; Image *ima = NULL; Object *ob = NULL; @@ -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); } } } @@ -1329,6 +1319,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base, 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; @@ -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); @@ -1589,7 +1577,7 @@ static int convert_poll(bContext *C) } /* Helper for convert_exec */ -static Base *duplibase_for_convert(Main *bmain, Scene *scene, Base *base, Object *ob) +static Base *duplibase_for_convert(Main *bmain, Scene *scene, SceneLayer *sl, Base *base, Object *ob) { Object *obn; Base *basen; @@ -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,6 +1600,7 @@ static int 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); Base *basen = NULL, *basact = NULL; Object *ob, *ob1, *newob, *obact = CTX_data_active_object(C); DerivedMesh *dm; @@ -1631,7 +1615,7 @@ static int convert_exec(bContext *C, wmOperator *op) /* don't forget multiple users! */ { - Base *base; + BaseLegacy *base; for (base = scene->base.first; base; base = base->next) { 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 Base *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; 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) +Base *ED_object_add_duplicate(Main *bmain, Scene *scene, SceneLayer *sl, Base *base, int dupflag) { Base *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,6 +2220,7 @@ 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; @@ -2248,19 +2228,19 @@ static int duplicate_exec(bContext *C, wmOperator *op) CTX_DATA_BEGIN (C, Base *, base, selected_bases) { - Base *basen = object_add_duplicate_internal(bmain, scene, base, dupflag); + Base *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); + Base *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; diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c index 59d78f13ccb..1cd80327b42 100644 --- a/source/blender/editors/object/object_constraint.c +++ b/source/blender/editors/object/object_constraint.c @@ -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); - Base *base = BASACT, *newbase = NULL; + SceneLayer *sl = CTX_data_scene_layer(C); + BaseLegacy *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; @@ -1709,7 +1710,7 @@ static bool get_new_constraint_target(bContext *C, int con_type, Object **tar_ob /* restore, BKE_object_add sets active */ BASACT = base; - base->flag |= SELECT; + base->flag_legacy |= SELECT; /* make our new target the new object */ *tar_ob = obt; diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index edd7b5dd1be..2a4557f3610 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -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)) @@ -698,7 +506,7 @@ static void copymenu_properties(Scene *scene, View3D *v3d, Object *ob) { //XXX no longer used - to be removed - replaced by game_properties_copy_exec bProperty *prop; - Base *base; + BaseLegacy *base; int nr, tot = 0; char *str; @@ -758,7 +566,7 @@ static void copymenu_properties(Scene *scene, View3D *v3d, Object *ob) static void copymenu_logicbricks(Scene *scene, View3D *v3d, Object *ob) { //XXX no longer used - to be removed - replaced by logicbricks_copy_exec - Base *base; + BaseLegacy *base; for (base = FIRSTBASE; base; base = base->next) { if (base->object != ob) { @@ -844,7 +652,7 @@ static void copy_texture_space(Object *to, Object *ob) static void copy_attr(Main *bmain, Scene *scene, View3D *v3d, short event) { Object *ob; - Base *base; + BaseLegacy *base; Curve *cu, *cu1; Nurb *nu; bool do_depgraph_update = false; @@ -1512,7 +1320,7 @@ void OBJECT_OT_shade_smooth(wmOperatorType *ot) static void UNUSED_FUNCTION(image_aspect) (Scene *scene, View3D *v3d) { /* all selected objects with an image map: scale in image aspect */ - Base *base; + BaseLegacy *base; Object *ob; Material *ma; Tex *tex; diff --git a/source/blender/editors/object/object_group.c b/source/blender/editors/object/object_group.c index 0fe43c44d7d..b22b034ecab 100644 --- a/source/blender/editors/object/object_group.c +++ b/source/blender/editors/object/object_group.c @@ -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; @@ -151,7 +150,7 @@ static int objects_add_active_exec(bContext *C, wmOperator *op) 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; @@ -221,7 +220,7 @@ static int objects_remove_active_exec(bContext *C, wmOperator *op) /* Remove groups from selected objects */ CTX_DATA_BEGIN (C, Base *, 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) { - 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; @@ -315,7 +312,7 @@ static int group_objects_remove_exec(bContext *C, wmOperator *op) /* now remove all selected objects from the group */ CTX_DATA_BEGIN (C, Base *, 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 */ @@ -367,7 +363,7 @@ static int group_create_exec(bContext *C, wmOperator *op) CTX_DATA_BEGIN (C, Base *, 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); @@ -560,8 +553,10 @@ static int select_grouped_exec(bContext *C, wmOperator *UNUSED(op)) /* Select o CTX_DATA_BEGIN (C, Base *, 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; diff --git a/source/blender/editors/object/object_hook.c b/source/blender/editors/object/object_hook.c index 438c10c51fa..f41f21f5bd4 100644 --- a/source/blender/editors/object/object_hook.c +++ b/source/blender/editors/object/object_hook.c @@ -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; + BaseLegacy *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; diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h index 9710e4f843d..fe0ceb15d70 100644 --- a/source/blender/editors/object/object_intern.h +++ b/source/blender/editors/object/object_intern.h @@ -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); diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index 06f495fb9f1..bca7a163e90 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -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); diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c index 7e7e1ef182c..19526db2ce8 100644 --- a/source/blender/editors/object/object_ops.c +++ b/source/blender/editors/object/object_ops.c @@ -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); diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index b5fbe4ba586..c79c702837a 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -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")); @@ -343,13 +346,13 @@ static int make_proxy_exec(bContext *C, wmOperator *op) if (ob) { Object *newob; - Base *newbase, *oldbase = BASACT; + BaseLegacy *newbase, *oldbase = BASACT; char name[MAX_ID_NAME + 4]; 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; } + SceneCollection *sc_to = BKE_collection_master(scene_to); CTX_DATA_BEGIN (C, Base *, 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; @@ -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; - - 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; + /* duplicate all the objects of the scene */ + SceneCollection *msc = BKE_collection_master(scene); + single_object_users_scene_collection(bmain, scene, msc, flag, copy_groups); - 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 (Base *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); } @@ -1857,15 +1769,17 @@ static void single_obdata_users(Main *bmain, Scene *scene, const int flag) Lamp *la; Curve *cu; /* Camera *cam; */ - Base *base; + BaseLegacy *base; Mesh *me; Lattice *lat; 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) { + if (!ID_IS_LINKED_DATABLOCK(ob) && (base->flag_legacy & flag) == flag) { id = ob->data; if (id && id->us > 1 && !ID_IS_LINKED_DATABLOCK(id)) { @@ -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); } @@ -2194,13 +2104,13 @@ static bool make_local_all__instance_indirect_unused(Main *bmain, Scene *scene) for (ob = bmain->object.first; ob; ob = ob->id.next) { if (ID_IS_LINKED_DATABLOCK(ob) && (ob->id.us == 0)) { - Base *base; + BaseLegacy *base; id_us_plus(&ob->id); base = BKE_scene_base_add(scene, ob); - base->flag |= SELECT; - base->object->flag = base->flag; + base->flag_legacy |= SELECT; + 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); @@ -2438,7 +2355,7 @@ void OBJECT_OT_make_single_user(wmOperatorType *ot) static int drop_named_material_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - Base *base = ED_view3d_give_base_under_cursor(C, event->mval); + BaseLegacy *base = ED_view3d_give_base_under_cursor(C, event->mval); Material *ma; char name[MAX_ID_NAME - 2]; diff --git a/source/blender/editors/object/object_select.c b/source/blender/editors/object/object_select.c index b5131df3eaa..961278c2c83 100644 --- a/source/blender/editors/object/object_select.c +++ b/source/blender/editors/object/object_select.c @@ -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" @@ -86,22 +87,22 @@ /* Note: send a NC_SCENE|ND_OB_SELECT notifier yourself! (or * or a NC_SCENE|ND_OB_VISIBLE in case of visibility toggling */ -void ED_base_object_select(Base *base, short mode) +void ED_base_object_select(BaseLegacy *base, short mode) { if (base) { if (mode == BA_SELECT) { if (!(base->object->restrictflag & OB_RESTRICT_SELECT)) - base->flag |= SELECT; + base->flag_legacy |= SELECT; } else if (mode == BA_DESELECT) { - base->flag &= ~SELECT; + base->flag_legacy &= ~SELECT; } - base->object->flag = base->flag; + BKE_scene_base_flag_sync_from_base(base); } } /* also to set active NULL */ -void ED_base_object_activate(bContext *C, Base *base) +void ED_base_object_activate(bContext *C, BaseLegacy *base) { Scene *scene = CTX_data_scene(C); @@ -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(Base *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, Base *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) @@ -147,7 +175,7 @@ static int object_select_by_type_exec(bContext *C, wmOperator *op) if (extend == 0) { CTX_DATA_BEGIN (C, Base *, base, visible_bases) { - ED_base_object_select(base, BA_DESELECT); + ED_object_base_select(base, BA_DESELECT); } CTX_DATA_END; } @@ -155,7 +183,7 @@ static int object_select_by_type_exec(bContext *C, wmOperator *op) CTX_DATA_BEGIN (C, Base *, 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) { - 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; } } @@ -257,7 +262,7 @@ static bool object_select_all_by_material_texture(bContext *C, int use_texture, CTX_DATA_BEGIN (C, Base *, 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; @@ -299,12 +302,10 @@ static bool object_select_all_by_dup_group(bContext *C, Object *ob) CTX_DATA_BEGIN (C, Base *, 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; } } @@ -321,23 +322,21 @@ static bool object_select_all_by_particle(bContext *C, Object *ob) CTX_DATA_BEGIN (C, Base *, 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; @@ -351,11 +350,9 @@ static bool object_select_all_by_library(bContext *C, Library *lib) CTX_DATA_BEGIN (C, Base *, 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; } } @@ -371,11 +368,9 @@ static bool object_select_all_by_library_obdata(bContext *C, Library *lib) CTX_DATA_BEGIN (C, Base *, 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; } } @@ -417,7 +412,7 @@ static int object_select_linked_exec(bContext *C, wmOperator *op) if (extend == 0) { CTX_DATA_BEGIN (C, Base *, 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"}, @@ -551,13 +545,14 @@ static bool select_grouped_children(bContext *C, Object *ob, const bool recursiv CTX_DATA_BEGIN (C, Base *, 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); - - bool changed = false; Base *baspar, *basact = CTX_data_active_base(C); + bool changed = false; - 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; @@ -608,9 +604,11 @@ static bool select_grouped_group(bContext *C, Object *ob) /* Select objects in group = ob_groups[0]; CTX_DATA_BEGIN (C, Base *, 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; @@ -636,7 +634,7 @@ static bool select_grouped_object_hooks(bContext *C, Object *ob) View3D *v3d = CTX_wm_view3d(C); bool changed = false; - Base *base; + BaseLegacy *base; ModifierData *md; HookModifierData *hmd; @@ -663,8 +661,8 @@ static bool select_grouped_siblings(bContext *C, Object *ob) CTX_DATA_BEGIN (C, Base *, 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; } } @@ -681,8 +679,8 @@ static bool select_grouped_lamptype(bContext *C, Object *ob) { 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; } } @@ -696,23 +694,8 @@ static bool select_grouped_type(bContext *C, Object *ob) CTX_DATA_BEGIN (C, Base *, 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; } } @@ -726,8 +709,8 @@ static bool select_grouped_index_object(bContext *C, Object *ob) CTX_DATA_BEGIN (C, Base *, 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; } } @@ -741,8 +724,8 @@ static bool select_grouped_color(bContext *C, Object *ob) CTX_DATA_BEGIN (C, Base *, 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; } } @@ -768,8 +751,8 @@ static bool select_grouped_gameprops(bContext *C, Object *ob) CTX_DATA_BEGIN (C, Base *, 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; } } @@ -807,7 +790,7 @@ static bool select_grouped_keyingset(bContext *C, Object *UNUSED(ob), ReportList CTX_DATA_BEGIN (C, Base *, 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; } @@ -840,7 +823,7 @@ static int object_select_grouped_exec(bContext *C, wmOperator *op) if (extend == 0) { CTX_DATA_BEGIN (C, Base *, 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) @@ -1020,7 +921,7 @@ static int object_select_all_exec(bContext *C, wmOperator *op) action = SEL_SELECT; CTX_DATA_BEGIN (C, Base *, base, visible_bases) { - if (base->flag & SELECT) { + if ((base->flag & BASE_SELECTED) != 0) { action = SEL_DESELECT; break; } @@ -1032,17 +933,17 @@ static int object_select_all_exec(bContext *C, wmOperator *op) { 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; } @@ -1092,8 +993,11 @@ static int object_select_same_group_exec(bContext *C, wmOperator *op) CTX_DATA_BEGIN (C, Base *, 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,6 +1028,7 @@ 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"); @@ -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); + Base *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 (BaseLegacy *base = sl->object_bases.first; base; base = base->next) { Object *ob = base->object; ob->flag &= ~OB_DONE; ob->id.tag &= ~LIB_TAG_DOIT; @@ -1223,7 +1128,7 @@ static bool object_select_more_less(bContext *C, const bool select) Base *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; } } @@ -1305,7 +1210,7 @@ static int object_select_random_exec(bContext *C, wmOperator *op) CTX_DATA_BEGIN (C, Base *, 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; diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c index 56f59dca9a1..5454a930485 100644 --- a/source/blender/editors/object/object_vgroup.c +++ b/source/blender/editors/object/object_vgroup.c @@ -3296,7 +3296,7 @@ static int vertex_group_copy_to_linked_exec(bContext *C, wmOperator *UNUSED(op)) { Scene *scene = CTX_data_scene(C); Object *ob = ED_object_context(C); - Base *base; + BaseLegacy *base; int retval = OPERATOR_CANCELLED; for (base = scene->base.first; base; base = base->next) { diff --git a/source/blender/editors/physics/physics_fluid.c b/source/blender/editors/physics/physics_fluid.c index b5adf38527b..bb3375b91a6 100644 --- a/source/blender/editors/physics/physics_fluid.c +++ b/source/blender/editors/physics/physics_fluid.c @@ -329,7 +329,7 @@ static void free_all_fluidobject_channels(ListBase *fobjects) static void fluid_init_all_channels(bContext *C, Object *UNUSED(fsDomain), FluidsimSettings *domainSettings, FluidAnimChannels *channels, ListBase *fobjects) { Scene *scene = CTX_data_scene(C); - Base *base; + BaseLegacy *base; int i; int length = channels->length; float eval_time; @@ -572,7 +572,7 @@ static void export_fluid_objects(ListBase *fobjects, Scene *scene, int length) static int fluid_validate_scene(ReportList *reports, Scene *scene, Object *fsDomain) { - Base *base; + BaseLegacy *base; Object *newdomain = NULL; int channelObjCount = 0; int fluidInputCount = 0; diff --git a/source/blender/editors/physics/physics_pointcache.c b/source/blender/editors/physics/physics_pointcache.c index e81aa584586..4b19e235d9c 100644 --- a/source/blender/editors/physics/physics_pointcache.c +++ b/source/blender/editors/physics/physics_pointcache.c @@ -254,7 +254,7 @@ static void ptcache_bake_cancel(bContext *C, wmOperator *op) static int ptcache_free_bake_all_exec(bContext *C, wmOperator *UNUSED(op)) { Scene *scene= CTX_data_scene(C); - Base *base; + BaseLegacy *base; PTCacheID *pid; ListBase pidlist; diff --git a/source/blender/editors/physics/rigidbody_constraint.c b/source/blender/editors/physics/rigidbody_constraint.c index 1bfc162a331..b7be31602d9 100644 --- a/source/blender/editors/physics/rigidbody_constraint.c +++ b/source/blender/editors/physics/rigidbody_constraint.c @@ -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); diff --git a/source/blender/editors/physics/rigidbody_object.c b/source/blender/editors/physics/rigidbody_object.c index 30597d95497..c9e32fa5194 100644 --- a/source/blender/editors/physics/rigidbody_object.c +++ b/source/blender/editors/physics/rigidbody_object.c @@ -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); diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index 8c5d25ad44d..07f4679a32a 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -784,7 +784,7 @@ static void clean_viewport_memory(Main *bmain, Scene *scene, int renderlay) { Object *object; Scene *sce_iter; - Base *base; + BaseLegacy *base; for (object = bmain->object.first; object; object = object->id.next) { object->id.tag |= LIB_TAG_DOIT; diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c index c48e142f233..cb54f0efd85 100644 --- a/source/blender/editors/render/render_preview.c +++ b/source/blender/editors/render/render_preview.c @@ -276,7 +276,7 @@ static Scene *preview_get_scene(Main *pr_main) static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_type, ShaderPreview *sp) { Scene *sce; - Base *base; + BaseLegacy *base; Main *pr_main = sp->pr_main; memcpy(pr_main->name, bmain->name, sizeof(pr_main->name)); diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c index 837573ad175..984aa6e43c2 100644 --- a/source/blender/editors/render/render_shading.c +++ b/source/blender/editors/render/render_shading.c @@ -54,6 +54,7 @@ #include "BKE_font.h" #include "BKE_global.h" #include "BKE_image.h" +#include "BKE_layer.h" #include "BKE_library.h" #include "BKE_linestyle.h" #include "BKE_main.h" @@ -626,11 +627,11 @@ static int render_layer_add_exec(bContext *C, wmOperator *UNUSED(op)) { Scene *scene = CTX_data_scene(C); - BKE_scene_add_render_layer(scene, NULL); - scene->r.actlay = BLI_listbase_count(&scene->r.layers) - 1; + BKE_scene_layer_add(scene, NULL); + scene->active_layer = BLI_listbase_count(&scene->render_layers) - 1; DAG_id_tag_update(&scene->id, 0); - WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene); + WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene); return OPERATOR_FINISHED; } @@ -652,10 +653,11 @@ void SCENE_OT_render_layer_add(wmOperatorType *ot) static int render_layer_remove_exec(bContext *C, wmOperator *UNUSED(op)) { Scene *scene = CTX_data_scene(C); - SceneRenderLayer *rl = BLI_findlink(&scene->r.layers, scene->r.actlay); + SceneLayer *sl = BLI_findlink(&scene->render_layers, scene->active_layer); - if (!BKE_scene_remove_render_layer(CTX_data_main(C), scene, rl)) + if (!BKE_scene_layer_remove(CTX_data_main(C), scene, sl)) { return OPERATOR_CANCELLED; + } DAG_id_tag_update(&scene->id, 0); WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene); diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c index ef514dd5e84..f2933cfa935 100644 --- a/source/blender/editors/screen/glutil.c +++ b/source/blender/editors/screen/glutil.c @@ -75,6 +75,18 @@ void fdrawbox(float x1, float y1, float x2, float y2) glEnd(); } +void fdrawbox_filled(float x1, float y1, float x2, float y2) +{ + glBegin(GL_POLYGON); + + glVertex2f(x1, y1); + glVertex2f(x1, y2); + glVertex2f(x2, y2); + glVertex2f(x2, y1); + + glEnd(); +} + void fdrawcheckerboard(float x1, float y1, float x2, float y2) /* DEPRECATED */ { unsigned char col1[4] = {40, 40, 40}, col2[4] = {50, 50, 50}; diff --git a/source/blender/editors/screen/screen_context.c b/source/blender/editors/screen/screen_context.c index c165bbfd301..c82a210725c 100644 --- a/source/blender/editors/screen/screen_context.c +++ b/source/blender/editors/screen/screen_context.c @@ -47,6 +47,7 @@ #include "BKE_action.h" #include "BKE_armature.h" #include "BKE_gpencil.h" +#include "BKE_layer.h" #include "BKE_screen.h" #include "BKE_sequencer.h" @@ -60,20 +61,8 @@ #include "screen_intern.h" -static unsigned int context_layers(bScreen *sc, Scene *scene, ScrArea *sa_ctx) -{ - /* needed for 'USE_ALLSELECT' define, otherwise we end up editing off-screen layers. */ - if (sc && sa_ctx && (sa_ctx->spacetype == SPACE_BUTS)) { - const unsigned int lay = BKE_screen_view3d_layer_all(sc); - if (lay) { - return lay; - } - } - return scene->lay; -} - const char *screen_context_dir[] = { - "scene", "visible_objects", "visible_bases", "selectable_objects", "selectable_bases", + "scene", "render_layer", "visible_objects", "visible_bases", "selectable_objects", "selectable_bases", "selected_objects", "selected_bases", "editable_objects", "editable_bases", "selected_editable_objects", "selected_editable_bases", @@ -95,17 +84,9 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult bScreen *sc = CTX_wm_screen(C); ScrArea *sa = CTX_wm_area(C); Scene *scene = sc->scene; - Base *base; - -#if 0 /* Using the context breaks adding objects in the UI. Need to find out why - campbell */ - Object *obact = CTX_data_active_object(C); - Object *obedit = CTX_data_edit_object(C); - base = CTX_data_active_base(C); -#else + SceneLayer *sl = CTX_data_scene_layer(C); Object *obedit = scene->obedit; - Object *obact = OBACT; - base = BASACT; -#endif + Object *obact = sl->basact ? sl->basact->object : NULL; if (CTX_data_dir(member)) { CTX_data_dir_set(result, screen_context_dir); @@ -115,84 +96,105 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult CTX_data_id_pointer_set(result, &scene->id); return 1; } - else if (CTX_data_equals(member, "visible_objects") || CTX_data_equals(member, "visible_bases")) { - const unsigned int lay = context_layers(sc, scene, sa); - const bool visible_objects = CTX_data_equals(member, "visible_objects"); - - for (base = scene->base.first; base; base = base->next) { - if (((base->object->restrictflag & OB_RESTRICT_VIEW) == 0) && (base->lay & lay)) { - if (visible_objects) - CTX_data_id_list_add(result, &base->object->id); - else - CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base); + else if (CTX_data_equals(member, "visible_objects")) { + Object *ob; + FOREACH_VISIBLE_OBJECT(sl, ob) + { + CTX_data_id_list_add(result, &ob->id); + } + FOREACH_VISIBLE_BASE_END + CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); + return 1; + } + else if (CTX_data_equals(member, "selectable_objects")) { + for (Base *base = sl->object_bases.first; base; base = base->next) { + if (((base->flag & BASE_VISIBLED) != 0) && ((base->flag & BASE_SELECTABLED) != 0)) { + CTX_data_id_list_add(result, &base->object->id); } } CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); return 1; } - else if (CTX_data_equals(member, "selectable_objects") || CTX_data_equals(member, "selectable_bases")) { - const unsigned int lay = context_layers(sc, scene, sa); - const bool selectable_objects = CTX_data_equals(member, "selectable_objects"); - - for (base = scene->base.first; base; base = base->next) { - if (base->lay & lay) { - if ((base->object->restrictflag & OB_RESTRICT_VIEW) == 0 && (base->object->restrictflag & OB_RESTRICT_SELECT) == 0) { - if (selectable_objects) - CTX_data_id_list_add(result, &base->object->id); - else - CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base); - } + else if (CTX_data_equals(member, "selected_objects")) { + Object *ob; + FOREACH_SELECTED_OBJECT(sl, ob) + { + CTX_data_id_list_add(result, &ob->id); + } + FOREACH_SELECTED_OBJECT_END + CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); + return 1; + } + else if (CTX_data_equals(member, "selected_editable_objects")) { + Object *ob; + FOREACH_SELECTED_OBJECT(sl, ob) + { + if (0 == BKE_object_is_libdata(ob)) { + CTX_data_id_list_add(result, &ob->id); } } + FOREACH_SELECTED_OBJECT_END CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); return 1; } - else if (CTX_data_equals(member, "selected_objects") || CTX_data_equals(member, "selected_bases")) { - const unsigned int lay = context_layers(sc, scene, sa); - const bool selected_objects = CTX_data_equals(member, "selected_objects"); - - for (base = scene->base.first; base; base = base->next) { - if ((base->flag & SELECT) && (base->lay & lay)) { - if (selected_objects) - CTX_data_id_list_add(result, &base->object->id); - else - CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base); + else if (CTX_data_equals(member, "editable_objects")) { + /* Visible + Editable, but not necessarily selected */ + Object *ob; + FOREACH_VISIBLE_OBJECT(sl, ob) + { + if (0 == BKE_object_is_libdata(ob)) { + CTX_data_id_list_add(result, &ob->id); } } + FOREACH_VISIBLE_OBJECT_END CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); return 1; } - else if (CTX_data_equals(member, "selected_editable_objects") || CTX_data_equals(member, "selected_editable_bases")) { - const unsigned int lay = context_layers(sc, scene, sa); - const bool selected_editable_objects = CTX_data_equals(member, "selected_editable_objects"); - - for (base = scene->base.first; base; base = base->next) { - if ((base->flag & SELECT) && (base->lay & lay)) { - if ((base->object->restrictflag & OB_RESTRICT_VIEW) == 0) { - if (0 == BKE_object_is_libdata(base->object)) { - if (selected_editable_objects) - CTX_data_id_list_add(result, &base->object->id); - else - CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base); - } + else if ( CTX_data_equals(member, "visible_bases")) { + Base *base; + FOREACH_VISIBLE_BASE(sl, base) + { + CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base); + } + FOREACH_VISIBLE_BASE_END + CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); + return 1; + } + else if (CTX_data_equals(member, "selectable_bases")) { + for (Base *base = sl->object_bases.first; base; base = base->next) { + if ((base->flag & BASE_SELECTABLED) != 0) { + CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base); + } + } + CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); + return 1; + } + else if (CTX_data_equals(member, "selected_bases")) { + for (Base *base = sl->object_bases.first; base; base = base->next) { + if ((base->flag & BASE_SELECTED) != 0) { + CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base); + } + } + CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); + return 1; + } + else if (CTX_data_equals(member, "selected_editable_bases")) { + for (Base *base = sl->object_bases.first; base; base = base->next) { + if ((base->flag & BASE_SELECTED) != 0) { + if (0 == BKE_object_is_libdata(base->object)) { + CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base); } } } CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); return 1; } - else if (CTX_data_equals(member, "editable_objects") || CTX_data_equals(member, "editable_bases")) { - const unsigned int lay = context_layers(sc, scene, sa); - const bool editable_objects = CTX_data_equals(member, "editable_objects"); - + else if (CTX_data_equals(member, "editable_bases")) { /* Visible + Editable, but not necessarily selected */ - for (base = scene->base.first; base; base = base->next) { - if (((base->object->restrictflag & OB_RESTRICT_VIEW) == 0) && (base->lay & lay)) { + for (Base *base = sl->object_bases.first; base; base = base->next) { + if ((base->flag & BASE_VISIBLED) != 0) { if (0 == BKE_object_is_libdata(base->object)) { - if (editable_objects) - CTX_data_id_list_add(result, &base->object->id); - else - CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base); + CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base); } } } @@ -344,8 +346,8 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult } } else if (CTX_data_equals(member, "active_base")) { - if (base) - CTX_data_pointer_set(result, &scene->id, &RNA_ObjectBase, base); + if (sl->basact) + CTX_data_pointer_set(result, &scene->id, &RNA_ObjectBase, sl->basact); return 1; } diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 32b63aca34c..a55d6c2143f 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -321,6 +321,10 @@ int ED_operator_info_active(bContext *C) return ed_spacetype_test(C, SPACE_INFO); } +int ED_operator_collections_active(bContext *C) +{ + return ed_spacetype_test(C, SPACE_COLLECTIONS); +} int ED_operator_console_active(bContext *C) { diff --git a/source/blender/editors/space_api/spacetypes.c b/source/blender/editors/space_api/spacetypes.c index 5ff1d758563..8c278c0b3ae 100644 --- a/source/blender/editors/space_api/spacetypes.c +++ b/source/blender/editors/space_api/spacetypes.c @@ -96,6 +96,7 @@ void ED_spacetypes_init(void) ED_spacetype_console(); ED_spacetype_userpref(); ED_spacetype_clip(); + ED_spacetype_collections(); // ... /* register operator types for screen and all spaces */ diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c index da3364d872d..8106e0cfddf 100644 --- a/source/blender/editors/space_buttons/buttons_context.c +++ b/source/blender/editors/space_buttons/buttons_context.c @@ -49,6 +49,7 @@ #include "BKE_context.h" #include "BKE_action.h" +#include "BKE_layer.h" #include "BKE_material.h" #include "BKE_modifier.h" #include "BKE_paint.h" @@ -553,6 +554,28 @@ static bool buttons_context_linestyle_pinnable(const bContext *C) } #endif +static int buttons_context_path_collection(const bContext *C, ButsContextPath *path) +{ + PointerRNA *ptr = &path->ptr[path->len - 1]; + + /* if we already have a (pinned) Collection, we're done */ + if (RNA_struct_is_a(ptr->type, &RNA_LayerCollection)) { + return 1; + } + + SceneLayer *sl = CTX_data_scene_layer(C); + LayerCollection *sc = BKE_layer_collection_active(sl); + + if (sc) { + RNA_pointer_create(NULL, &RNA_LayerCollection, sc, &path->ptr[path->len]); + path->len++; + return 1; + } + + /* no path to a collection possible */ + return 0; +} + static int buttons_context_path(const bContext *C, ButsContextPath *path, int mainb, int flag) { SpaceButs *sbuts = CTX_wm_space_buts(C); @@ -627,7 +650,10 @@ static int buttons_context_path(const bContext *C, ButsContextPath *path, int ma case BCONTEXT_BONE_CONSTRAINT: found = buttons_context_path_pose_bone(path); break; - default: + case BCONTEXT_COLLECTION: + found = buttons_context_path_collection(C, path); + break; + default: found = 0; break; } @@ -744,7 +770,7 @@ const char *buttons_context_dir[] = { "texture", "texture_user", "texture_user_property", "bone", "edit_bone", "pose_bone", "particle_system", "particle_system_editable", "particle_settings", "cloth", "soft_body", "fluid", "smoke", "collision", "brush", "dynamic_paint", - "line_style", NULL + "line_style", "collection", NULL }; int buttons_context(const bContext *C, const char *member, bContextDataResult *result) @@ -1064,6 +1090,10 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r set_pointer_type(path, result, &RNA_FreestyleLineStyle); return 1; } + else if (CTX_data_equals(member, "collection")) { + set_pointer_type(path, result, &RNA_LayerCollection); + return 1; + } else { return 0; /* not found */ } diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c index e4c23ad74f8..608287939bd 100644 --- a/source/blender/editors/space_buttons/space_buttons.c +++ b/source/blender/editors/space_buttons/space_buttons.c @@ -171,6 +171,8 @@ static void buttons_main_region_draw(const bContext *C, ARegion *ar) ED_region_panels(C, ar, "constraint", sbuts->mainb, vertical); else if (sbuts->mainb == BCONTEXT_BONE_CONSTRAINT) ED_region_panels(C, ar, "bone_constraint", sbuts->mainb, vertical); + else if (sbuts->mainb == BCONTEXT_COLLECTION) + ED_region_panels(C, ar, "collection", sbuts->mainb, vertical); sbuts->re_align = 0; sbuts->mainbo = sbuts->mainb; diff --git a/source/blender/editors/space_clip/tracking_ops_orient.c b/source/blender/editors/space_clip/tracking_ops_orient.c index f81180d65a9..7fe73f8d0b4 100644 --- a/source/blender/editors/space_clip/tracking_ops_orient.c +++ b/source/blender/editors/space_clip/tracking_ops_orient.c @@ -69,7 +69,7 @@ static Object *get_camera_with_movieclip(Scene *scene, MovieClip *clip) return camera; } - for (Base *base = scene->base.first; + for (BaseLegacy *base = scene->base.first; base != NULL; base = base->next) { diff --git a/source/blender/editors/space_collections/CMakeLists.txt b/source/blender/editors/space_collections/CMakeLists.txt new file mode 100644 index 00000000000..1cc4a40d657 --- /dev/null +++ b/source/blender/editors/space_collections/CMakeLists.txt @@ -0,0 +1,45 @@ +# ***** 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): Jacques Beaurain. +# +# ***** END GPL LICENSE BLOCK ***** + +set(INC + ../include + ../../blenkernel + ../../blenlib + ../../blentranslation + ../../gpu + ../../makesdna + ../../makesrna + ../../windowmanager + ../../../../intern/guardedalloc + ../../../../intern/glew-mx +) + +set(INC_SYS + ${GLEW_INCLUDE_PATH} +) + +set(SRC + collections_ops.c + space_collections.c + + collections_intern.h +) + +blender_add_lib(bf_editor_space_collections "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/editors/space_collections/collections_intern.h b/source/blender/editors/space_collections/collections_intern.h new file mode 100644 index 00000000000..866f59659c3 --- /dev/null +++ b/source/blender/editors/space_collections/collections_intern.h @@ -0,0 +1,35 @@ +/* + * ***** 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/space_collections/collections_intern.h + * \ingroup spcollections + */ + +#ifndef __COLLECTIONS_INTERN_H__ +#define __COLLECTIONS_INTERN_H__ + +struct wmKeyConfig; + +/* collections_ops.c */ +void collections_operatortypes(void); +void collections_keymap(struct wmKeyConfig *keyconf); + +#endif /* __COLLECTIONS_INTERN_H__ */ + diff --git a/source/blender/editors/space_collections/collections_ops.c b/source/blender/editors/space_collections/collections_ops.c new file mode 100644 index 00000000000..7e1bf8091b0 --- /dev/null +++ b/source/blender/editors/space_collections/collections_ops.c @@ -0,0 +1,340 @@ +/* + * ***** 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/space_collections/collections_ops.c + * \ingroup spcollections + */ + +#include "BKE_context.h" +#include "BKE_layer.h" +#include "BKE_report.h" + +#include "ED_screen.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "RNA_access.h" +#include "RNA_define.h" + +#include "collections_intern.h" /* own include */ + +/* -------------------------------------------------------------------- */ +/* polls */ + +static SceneCollection *collection_manager_collection_active(bContext *C) +{ + TODO_LAYER_OPERATORS; + /* consider that we may have overrides active + * leading to no active collections */ + return CTX_data_scene_collection(C); +} + +static int operator_not_master_collection_active(bContext *C) +{ + SceneCollection *sc = collection_manager_collection_active(C); + if (sc == NULL) { + return 1; + } + + return (sc == BKE_collection_master(CTX_data_scene(C))) ? 0 : 1; +} + +static int operator_top_collection_active(bContext *C) +{ + SceneCollection *sc = collection_manager_collection_active(C); + if (sc == NULL) { + return 0; + } + + TODO_LAYER_OPERATORS; + /* see if it's a top collection */ + return 1; +} + +static int operator_collection_active(bContext *C) +{ + return collection_manager_collection_active(C) ? 1 : 0; +} + +/* -------------------------------------------------------------------- */ +/* collection manager operators */ + +static int collection_link_invoke(bContext *UNUSED(C), wmOperator *op, const wmEvent *UNUSED(event)) +{ + TODO_LAYER_OPERATORS; + BKE_report(op->reports, RPT_ERROR, "COLLECTIONS_OT_collection_link not implemented yet"); + return OPERATOR_CANCELLED; +} + +static void COLLECTIONS_OT_collection_link(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Add Collection"; + ot->idname = "COLLECTIONS_OT_collection_link"; + ot->description = "Link a new collection to the active layer"; + + /* api callbacks */ + ot->invoke = collection_link_invoke; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +static int collection_unlink_invoke(bContext *UNUSED(C), wmOperator *op, const wmEvent *UNUSED(event)) +{ + TODO_LAYER_OPERATORS; + BKE_report(op->reports, RPT_ERROR, "COLLECTIONS_OT_collection_unlink not implemented yet"); + return OPERATOR_CANCELLED; +} + +static void COLLECTIONS_OT_collection_unlink(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Add Collection"; + ot->idname = "COLLECTIONS_OT_collection_unlink"; + ot->description = "Link a new collection to the active layer"; + + /* api callbacks */ + ot->invoke = collection_unlink_invoke; + ot->poll = operator_top_collection_active; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +static int collection_new_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); + + SceneCollection *sc = BKE_collection_add(scene, NULL, NULL); + BKE_collection_link(sl, sc); + + WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL); + return OPERATOR_FINISHED; +} + +static void COLLECTIONS_OT_collection_new(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "New Collection"; + ot->idname = "COLLECTIONS_OT_collection_new"; + ot->description = "Add a new collection to the scene, and link it to the active layer"; + + /* api callbacks */ + ot->exec = collection_new_exec; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +static int override_new_invoke(bContext *UNUSED(C), wmOperator *op, const wmEvent *UNUSED(event)) +{ + TODO_LAYER_OPERATORS; + TODO_LAYER_OVERRIDE; + BKE_report(op->reports, RPT_ERROR, "COLLECTIONS_OT_override_new not implemented yet"); + return OPERATOR_CANCELLED; +} + +static void COLLECTIONS_OT_override_new(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "New Override"; + ot->idname = "COLLECTIONS_OT_override_new"; + ot->description = "Add a new override to the active collection"; + + /* api callbacks */ + ot->invoke = override_new_invoke; + ot->poll = operator_collection_active; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +static int delete_invoke(bContext *UNUSED(C), wmOperator *op, const wmEvent *UNUSED(event)) +{ + TODO_LAYER_OPERATORS; + BKE_report(op->reports, RPT_ERROR, "COLLECTIONS_OT_delete not implemented yet"); + return OPERATOR_CANCELLED; +} + +static void COLLECTIONS_OT_delete(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Delete"; + ot->idname = "COLLECTIONS_OT_delete"; + ot->description = "Delete active override or collection"; + + /* api callbacks */ + ot->invoke = delete_invoke; + ot->poll = operator_not_master_collection_active; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +static int select_exec(bContext *C, wmOperator *op) +{ + SceneLayer *sl = CTX_data_scene_layer(C); + const int collection_index = RNA_int_get(op->ptr, "collection_index"); + sl->active_collection = collection_index; + WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL); + return OPERATOR_FINISHED; +} + +static void COLLECTIONS_OT_select(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Select"; + ot->idname = "COLLECTIONS_OT_select"; + ot->description = "Change active collection or override"; + + /* api callbacks */ + ot->exec = select_exec; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + RNA_def_int(ot->srna, "collection_index", 0, 0, INT_MAX, "Index", + "Index of collection to select", 0, INT_MAX); +} + +static int rename_invoke(bContext *UNUSED(C), wmOperator *op, const wmEvent *UNUSED(event)) +{ + TODO_LAYER_OPERATORS; + BKE_report(op->reports, RPT_ERROR, "COLLECTIONS_rename not implemented yet"); + return OPERATOR_CANCELLED; +} + +static void COLLECTIONS_OT_rename(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Rename"; + ot->idname = "COLLECTIONS_OT_rename"; + ot->description = "Rename active collection or override"; + + /* api callbacks */ + ot->invoke = rename_invoke; + ot->poll = operator_not_master_collection_active; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +/* -------------------------------------------------------------------- */ +/* property editor operators */ + +static int stubs_invoke(bContext *UNUSED(C), wmOperator *op, const wmEvent *UNUSED(event)) +{ + TODO_LAYER_OPERATORS; + BKE_report(op->reports, RPT_ERROR, "Operator not implemented yet"); + return OPERATOR_CANCELLED; +} + +static void COLLECTIONS_OT_objects_add(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Add Objects"; + ot->idname = "COLLECTIONS_OT_objects_add"; + ot->description = "Add selected objects to collection"; + + /* api callbacks */ + ot->invoke = stubs_invoke; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +static void COLLECTIONS_OT_objects_remove(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Remove Object"; + ot->idname = "COLLECTIONS_OT_objects_remove"; + ot->description = "Remove object from collection"; + + /* api callbacks */ + ot->invoke = stubs_invoke; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +static void COLLECTIONS_OT_objects_select(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Select Objects"; + ot->idname = "COLLECTIONS_OT_objects_select"; + ot->description = "Selected collection objects"; + + /* api callbacks */ + ot->invoke = stubs_invoke; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +static void COLLECTIONS_OT_objects_deselect(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Deselect Objects"; + ot->idname = "COLLECTIONS_OT_objects_deselect"; + ot->description = "Deselected collection objects"; + + /* api callbacks */ + ot->invoke = stubs_invoke; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +/* ************************** registration - operator types **********************************/ + +void collections_operatortypes(void) +{ + WM_operatortype_append(COLLECTIONS_OT_delete); + WM_operatortype_append(COLLECTIONS_OT_select); + WM_operatortype_append(COLLECTIONS_OT_rename); + WM_operatortype_append(COLLECTIONS_OT_collection_link); + WM_operatortype_append(COLLECTIONS_OT_collection_unlink); + WM_operatortype_append(COLLECTIONS_OT_collection_new); + WM_operatortype_append(COLLECTIONS_OT_override_new); + + WM_operatortype_append(COLLECTIONS_OT_objects_add); + WM_operatortype_append(COLLECTIONS_OT_objects_remove); + WM_operatortype_append(COLLECTIONS_OT_objects_select); + WM_operatortype_append(COLLECTIONS_OT_objects_deselect); +} + +void collections_keymap(wmKeyConfig *keyconf) +{ + wmKeyMap *keymap = WM_keymap_find(keyconf, "Collections Manager", SPACE_COLLECTIONS, 0); + + /* selection */ + WM_keymap_add_item(keymap, "COLLECTIONS_OT_select", LEFTMOUSE, KM_CLICK, 0, 0); + + WM_keymap_add_item(keymap, "COLLECTIONS_OT_rename", LEFTMOUSE, KM_DBL_CLICK, 0, 0); + WM_keymap_add_item(keymap, "COLLECTIONS_OT_rename", LEFTMOUSE, KM_PRESS, KM_CTRL, 0); + + WM_keymap_add_item(keymap, "COLLECTIONS_OT_collection_new", NKEY, KM_PRESS, KM_CTRL, 0); + + WM_keymap_add_item(keymap, "COLLECTIONS_OT_delete", XKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "COLLECTIONS_OT_delete", DELKEY, KM_PRESS, 0, 0); +} diff --git a/source/blender/editors/space_collections/space_collections.c b/source/blender/editors/space_collections/space_collections.c new file mode 100644 index 00000000000..7dd50e5cbac --- /dev/null +++ b/source/blender/editors/space_collections/space_collections.c @@ -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. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/space_collections/space_collections.c + * \ingroup spcollections + */ + +#include <string.h> + +#include "MEM_guardedalloc.h" + +#include "BIF_gl.h" + +#include "BKE_context.h" +#include "BKE_screen.h" + +#include "BLI_ghash.h" +#include "BLI_listbase.h" + +#include "ED_screen.h" +#include "ED_space_api.h" + +#include "UI_resources.h" +#include "UI_view2d.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "collections_intern.h" /* own include */ + +/* ******************** default callbacks for collection manager space ***************** */ + +static SpaceLink *collections_new(const bContext *UNUSED(C)) +{ + ARegion *ar; + SpaceCollections *scollection; /* hmm, that's actually a good band name... */ + + scollection = MEM_callocN(sizeof(SpaceCollections), __func__); + scollection->spacetype = SPACE_COLLECTIONS; + + /* header */ + ar = MEM_callocN(sizeof(ARegion), "header for collection manager"); + BLI_addtail(&scollection->regionbase, ar); + ar->regiontype = RGN_TYPE_HEADER; + ar->alignment = RGN_ALIGN_BOTTOM; + + /* main region */ + ar = MEM_callocN(sizeof(ARegion), "main region for collection manager"); + BLI_addtail(&scollection->regionbase, ar); + ar->regiontype = RGN_TYPE_WINDOW; + ar->v2d.scroll = (V2D_SCROLL_RIGHT | V2D_SCROLL_BOTTOM | V2D_SCROLL_HORIZONTAL_HIDE | V2D_SCROLL_VERTICAL_HIDE); + ar->v2d.align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_POS_Y); + + return (SpaceLink *)scollection; +} + +static void collections_free(SpaceLink *UNUSED(sl)) +{ +} + +static SpaceLink *collections_duplicate(SpaceLink *sl) +{ + SpaceCollections *scollection = MEM_dupallocN(sl); + + /* clear or remove stuff from old */ + + return (SpaceLink *)scollection; +} + +/* add handlers, stuff you only do once or on area/region changes */ +static void collection_main_region_init(wmWindowManager *wm, ARegion *ar) +{ + UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy); + ar->v2d.scroll |= (V2D_SCROLL_VERTICAL_FULLR | V2D_SCROLL_HORIZONTAL_FULLR); + + /* own keymap */ + wmKeyMap *keymap = WM_keymap_find(wm->defaultconf, "Layer Manager", SPACE_COLLECTIONS, 0); + WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); +} + +static void collections_main_region_draw(const bContext *C, ARegion *ar) +{ + SpaceCollections *spc = CTX_wm_space_collections(C); + View2D *v2d = &ar->v2d; + + if (spc->flag & SC_COLLECTION_DATA_REFRESH) { + } + + /* v2d has initialized flag, so this call will only set the mask correct */ + UI_view2d_region_reinit(v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy); + + UI_ThemeClearColor(TH_BACK); + glClear(GL_COLOR_BUFFER_BIT); + + /* reset view matrix */ + UI_view2d_view_restore(C); + + /* scrollers */ + View2DScrollers *scrollers; + scrollers = UI_view2d_scrollers_calc(C, v2d, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY); + UI_view2d_scrollers_draw(C, v2d, scrollers); + UI_view2d_scrollers_free(scrollers); +} + +/* add handlers, stuff you only do once or on area/region changes */ +static void collections_header_region_init(wmWindowManager *UNUSED(wm), ARegion *ar) +{ + ED_region_header_init(ar); +} + +static void collections_header_region_draw(const bContext *C, ARegion *ar) +{ + ED_region_header(C, ar); +} + +static void collections_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn) +{ + switch (wmn->category) { + case NC_SCENE: + if (wmn->data == ND_LAYER) { + ED_region_tag_redraw(ar); + } + break; + case NC_SPACE: + if (wmn->data == ND_SPACE_COLLECTIONS) { + ED_region_tag_redraw(ar); + } + } +} + +/* only called once, from space/spacetypes.c */ +void ED_spacetype_collections(void) +{ + SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype collections"); + ARegionType *art; + + st->spaceid = SPACE_COLLECTIONS; + strncpy(st->name, "LayerManager", BKE_ST_MAXNAME); + + st->new = collections_new; + st->free = collections_free; + st->duplicate = collections_duplicate; + st->operatortypes = collections_operatortypes; + st->keymap = collections_keymap; + + /* regions: main window */ + art = MEM_callocN(sizeof(ARegionType), "spacetype collections region"); + art->regionid = RGN_TYPE_WINDOW; + art->init = collection_main_region_init; + art->draw = collections_main_region_draw; + art->listener = collections_main_region_listener; + art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D; + BLI_addhead(&st->regiontypes, art); + + /* regions: header */ + art = MEM_callocN(sizeof(ARegionType), "spacetype collections header"); + art->regionid = RGN_TYPE_HEADER; + art->prefsizey = HEADERY; + art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_HEADER; + art->init = collections_header_region_init; + art->draw = collections_header_region_draw; + BLI_addhead(&st->regiontypes, art); + + BKE_spacetype_register(st); +} diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c index 8dc6c4229b2..435d9b2ee26 100644 --- a/source/blender/editors/space_info/info_stats.c +++ b/source/blender/editors/space_info/info_stats.c @@ -269,9 +269,9 @@ static void stats_object_sculpt_dynamic_topology(Object *ob, SceneStats *stats) stats->tottri = ob->sculpt->bm->totface; } -static void stats_dupli_object(Base *base, Object *ob, SceneStats *stats) +static void stats_dupli_object(BaseLegacy *base, Object *ob, SceneStats *stats) { - if (base->flag & SELECT) stats->totobjsel++; + if (base->flag_legacy & SELECT) stats->totobjsel++; if (ob->transflag & OB_DUPLIPARTS) { /* Dupli Particles */ @@ -300,7 +300,7 @@ static void stats_dupli_object(Base *base, Object *ob, SceneStats *stats) } } - stats_object(ob, base->flag & SELECT, 1, stats); + stats_object(ob, base->flag_legacy & SELECT, 1, stats); stats->totobj++; } else if (ob->parent && (ob->parent->transflag & (OB_DUPLIVERTS | OB_DUPLIFACES))) { @@ -316,23 +316,23 @@ static void stats_dupli_object(Base *base, Object *ob, SceneStats *stats) } stats->totobj += tot; - stats_object(ob, base->flag & SELECT, tot, stats); + stats_object(ob, base->flag_legacy & SELECT, tot, stats); } else if (ob->transflag & OB_DUPLIFRAMES) { /* Dupli Frames */ int tot = count_duplilist(ob); stats->totobj += tot; - stats_object(ob, base->flag & SELECT, tot, stats); + stats_object(ob, base->flag_legacy & SELECT, tot, stats); } else if ((ob->transflag & OB_DUPLIGROUP) && ob->dup_group) { /* Dupli Group */ int tot = count_duplilist(ob); stats->totobj += tot; - stats_object(ob, base->flag & SELECT, tot, stats); + stats_object(ob, base->flag_legacy & SELECT, tot, stats); } else { /* No Dupli */ - stats_object(ob, base->flag & SELECT, 1, stats); + stats_object(ob, base->flag_legacy & SELECT, 1, stats); stats->totobj++; } } @@ -348,7 +348,7 @@ static void stats_update(Scene *scene) { SceneStats stats = {0}; Object *ob = (scene->basact) ? scene->basact->object : NULL; - Base *base; + BaseLegacy *base; if (scene->obedit) { /* Edit Mode */ diff --git a/source/blender/editors/space_logic/logic_window.c b/source/blender/editors/space_logic/logic_window.c index 3de44174d6a..f1a08a45c29 100644 --- a/source/blender/editors/space_logic/logic_window.c +++ b/source/blender/editors/space_logic/logic_window.c @@ -460,7 +460,7 @@ static void set_sca_ob(Object *ob) static ID **get_selected_and_linked_obs(bContext *C, short *count, short scavisflag) { - Base *base; + BaseLegacy *base; Main *bmain= CTX_data_main(C); Scene *scene= CTX_data_scene(C); Object *ob, *obt, *obact= CTX_data_active_object(C); @@ -491,7 +491,7 @@ static ID **get_selected_and_linked_obs(bContext *C, short *count, short scavisf base= FIRSTBASE; while (base) { if (base->lay & lay) { - if (base->flag & SELECT) { + if (base->flag_legacy & SELECT) { if (scavisflag & BUTS_SENS_SEL) base->object->scavisflag |= OB_VIS_SENS; if (scavisflag & BUTS_CONT_SEL) base->object->scavisflag |= OB_VIS_CONT; if (scavisflag & BUTS_ACT_SEL) base->object->scavisflag |= OB_VIS_ACT; diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c index e9c46e9d04b..48e822ef876 100644 --- a/source/blender/editors/space_nla/nla_channels.c +++ b/source/blender/editors/space_nla/nla_channels.c @@ -45,6 +45,7 @@ #include "BKE_nla.h" #include "BKE_context.h" #include "BKE_global.h" +#include "BKE_scene.h" #include "BKE_screen.h" #include "BKE_report.h" @@ -125,7 +126,7 @@ static int mouse_nla_channels(bContext *C, bAnimContext *ac, float x, int channe { bDopeSheet *ads = (bDopeSheet *)ac->data; Scene *sce = (Scene *)ads->source; - Base *base = (Base *)ale->data; + BaseLegacy *base = (BaseLegacy *)ale->data; Object *ob = base->object; AnimData *adt = ob->adt; @@ -133,24 +134,24 @@ static int mouse_nla_channels(bContext *C, bAnimContext *ac, float x, int channe /* set selection status */ if (selectmode == SELECT_INVERT) { /* swap select */ - base->flag ^= SELECT; - ob->flag = base->flag; + base->flag_legacy ^= SELECT; + BKE_scene_base_flag_sync_from_base(base); if (adt) adt->flag ^= ADT_UI_SELECTED; } else { - Base *b; + BaseLegacy *b; /* deselect all */ /* 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; + b->flag_legacy &= ~SELECT; + BKE_scene_base_flag_sync_from_base(b); if (b->object->adt) b->object->adt->flag &= ~(ADT_UI_SELECTED | ADT_UI_ACTIVE); } /* select object now */ - base->flag |= SELECT; + base->flag_legacy |= SELECT; ob->flag |= SELECT; if (adt) adt->flag |= ADT_UI_SELECTED; } diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index 998dad6466b..d7229729e26 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -174,116 +174,6 @@ static void restrictbutton_recursive_bone(Bone *bone_parent, int flag, bool set_ } -static void restrictbutton_recursive_child(bContext *C, Scene *scene, Object *ob_parent, char flag, - bool state, bool deselect, const char *rnapropname) -{ - Main *bmain = CTX_data_main(C); - Object *ob; - - for (ob = bmain->object.first; ob; ob = ob->id.next) { - if (BKE_object_is_child_recursive(ob_parent, ob)) { - /* only do if child object is selectable */ - if ((flag == OB_RESTRICT_SELECT) || (ob->restrictflag & OB_RESTRICT_SELECT) == 0) { - if (state) { - ob->restrictflag |= flag; - if (deselect) { - ED_base_object_select(BKE_scene_base_find(scene, ob), BA_DESELECT); - } - } - else { - ob->restrictflag &= ~flag; - } - } - - if (rnapropname) { - PointerRNA ptr; - PropertyRNA *prop; - ID *id; - bAction *action; - FCurve *fcu; - bool driven, special; - - RNA_id_pointer_create(&ob->id, &ptr); - prop = RNA_struct_find_property(&ptr, rnapropname); - fcu = rna_get_fcurve_context_ui(C, &ptr, prop, 0, NULL, &action, &driven, &special); - - if (fcu && !driven) { - id = ptr.id.data; - if (autokeyframe_cfra_can_key(scene, id)) { - ReportList *reports = CTX_wm_reports(C); - ToolSettings *ts = scene->toolsettings; - eInsertKeyFlags key_flag = ANIM_get_keyframing_flags(scene, 1); - - fcu->flag &= ~FCURVE_SELECTED; - insert_keyframe(reports, id, action, ((fcu->grp) ? (fcu->grp->name) : (NULL)), - fcu->rna_path, fcu->array_index, CFRA, ts->keyframe_type, key_flag); - /* Assuming this is not necessary here, since 'ancestor' object button will do it anyway. */ - /* WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); */ - } - } - } - } - } -} - -static void restrictbutton_view_cb(bContext *C, void *poin, void *poin2) -{ - Scene *scene = (Scene *)poin; - Object *ob = (Object *)poin2; - - if (!common_restrict_check(C, ob)) return; - - /* deselect objects that are invisible */ - if (ob->restrictflag & OB_RESTRICT_VIEW) { - /* Ouch! There is no backwards pointer from Object to Base, - * so have to do loop to find it. */ - ED_base_object_select(BKE_scene_base_find(scene, ob), BA_DESELECT); - } - - if (CTX_wm_window(C)->eventstate->ctrl) { - restrictbutton_recursive_child(C, scene, ob, OB_RESTRICT_VIEW, - (ob->restrictflag & OB_RESTRICT_VIEW) != 0, true, "hide"); - } - - WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); - -} - -static void restrictbutton_sel_cb(bContext *C, void *poin, void *poin2) -{ - Scene *scene = (Scene *)poin; - Object *ob = (Object *)poin2; - - if (!common_restrict_check(C, ob)) return; - - /* if select restriction has just been turned on */ - if (ob->restrictflag & OB_RESTRICT_SELECT) { - /* Ouch! There is no backwards pointer from Object to Base, - * so have to do loop to find it. */ - ED_base_object_select(BKE_scene_base_find(scene, ob), BA_DESELECT); - } - - if (CTX_wm_window(C)->eventstate->ctrl) { - restrictbutton_recursive_child(C, scene, ob, OB_RESTRICT_SELECT, - (ob->restrictflag & OB_RESTRICT_SELECT) != 0, true, NULL); - } - - WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); - -} - -static void restrictbutton_rend_cb(bContext *C, void *poin, void *poin2) -{ - Object *ob = (Object *)poin2; - - if (CTX_wm_window(C)->eventstate->ctrl) { - restrictbutton_recursive_child(C, (Scene *)poin, ob, OB_RESTRICT_RENDER, - (ob->restrictflag & OB_RESTRICT_RENDER) != 0, false, "hide_render"); - } - - WM_event_add_notifier(C, NC_SCENE | ND_OB_RENDER, poin); -} - static void restrictbutton_r_lay_cb(bContext *C, void *poin, void *UNUSED(poin2)) { WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, poin); @@ -357,98 +247,6 @@ static void restrictbutton_gp_layer_flag_cb(bContext *C, void *UNUSED(poin), voi WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); } -static int group_restrict_flag(Group *gr, int flag) -{ - GroupObject *gob; - -#ifdef USE_GROUP_SELECT - for (gob = gr->gobject.first; gob; gob = gob->next) { - if ((gob->ob->restrictflag & flag) == 0) - return 0; - } - return 1; -#else - /* weak but fast */ - if ((gob = gr->gobject.first)) - if ((gob->ob->restrictflag & flag) == 0) - return 0; - return 1; -#endif -} - -static int group_select_flag(Group *gr) -{ - GroupObject *gob; - -#ifdef USE_GROUP_SELECT - for (gob = gr->gobject.first; gob; gob = gob->next) - if ((gob->ob->flag & SELECT)) - return 1; - - return 0; -#else - /* weak but fast */ - if ((gob = gr->gobject.first)) - if (gob->ob->flag & SELECT) - return 1; - return 0; -#endif -} - -void restrictbutton_gr_restrict_flag(void *poin, void *poin2, int flag) -{ - Scene *scene = (Scene *)poin; - GroupObject *gob; - Group *gr = (Group *)poin2; - - if (group_restrict_flag(gr, flag)) { - for (gob = gr->gobject.first; gob; gob = gob->next) { - if (ID_IS_LINKED_DATABLOCK(gob->ob)) - continue; - - gob->ob->restrictflag &= ~flag; - - if (flag == OB_RESTRICT_VIEW) - if (gob->ob->flag & SELECT) - ED_base_object_select(BKE_scene_base_find(scene, gob->ob), BA_DESELECT); - } - } - else { - for (gob = gr->gobject.first; gob; gob = gob->next) { - if (ID_IS_LINKED_DATABLOCK(gob->ob)) - continue; - - /* not in editmode */ - if (scene->obedit != gob->ob) { - gob->ob->restrictflag |= flag; - - if (ELEM(flag, OB_RESTRICT_SELECT, OB_RESTRICT_VIEW)) { - if ((gob->ob->flag & SELECT)) { - ED_base_object_select(BKE_scene_base_find(scene, gob->ob), BA_DESELECT); - } - } - } - } - } -} - -static void restrictbutton_gr_restrict_view(bContext *C, void *poin, void *poin2) -{ - restrictbutton_gr_restrict_flag(poin, poin2, OB_RESTRICT_VIEW); - WM_event_add_notifier(C, NC_GROUP, NULL); - DAG_id_type_tag(CTX_data_main(C), ID_OB); -} -static void restrictbutton_gr_restrict_select(bContext *C, void *poin, void *poin2) -{ - restrictbutton_gr_restrict_flag(poin, poin2, OB_RESTRICT_SELECT); - WM_event_add_notifier(C, NC_GROUP, NULL); -} -static void restrictbutton_gr_restrict_render(bContext *C, void *poin, void *poin2) -{ - restrictbutton_gr_restrict_flag(poin, poin2, OB_RESTRICT_RENDER); - WM_event_add_notifier(C, NC_GROUP, NULL); -} - static void restrictbutton_id_user_toggle(bContext *UNUSED(C), void *poin, void *UNUSED(poin2)) { ID *id = (ID *)poin; @@ -605,7 +403,6 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar TreeElement *te; TreeStoreElem *tselem; Object *ob = NULL; - Group *gr = NULL; PropertyRNA *object_prop_hide, *object_prop_hide_select, *object_prop_hide_render; @@ -619,73 +416,8 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar for (te = lb->first; te; te = te->next) { tselem = TREESTORE(te); if (te->ys + 2 * UI_UNIT_Y >= ar->v2d.cur.ymin && te->ys <= ar->v2d.cur.ymax) { - /* objects have toggle-able restriction flags */ - if (tselem->type == 0 && te->idcode == ID_OB) { - PointerRNA ptr; - - ob = (Object *)tselem->id; - RNA_pointer_create((ID *)ob, &RNA_Object, ob, &ptr); - - UI_block_emboss_set(block, UI_EMBOSS_NONE); - bt = uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0, ICON_RESTRICT_VIEW_OFF, - (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X, UI_UNIT_Y, - &ptr, object_prop_hide, -1, 0, 0, -1, -1, - TIP_("Restrict viewport visibility (Ctrl - Recursive)")); - UI_but_func_set(bt, restrictbutton_view_cb, scene, ob); - UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); - - bt = uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0, ICON_RESTRICT_SELECT_OFF, - (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys, UI_UNIT_X, UI_UNIT_Y, - &ptr, object_prop_hide_select, -1, 0, 0, -1, -1, - TIP_("Restrict viewport selection (Ctrl - Recursive)")); - UI_but_func_set(bt, restrictbutton_sel_cb, scene, ob); - UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); - - bt = uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0, ICON_RESTRICT_RENDER_OFF, - (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), te->ys, UI_UNIT_X, UI_UNIT_Y, - &ptr, object_prop_hide_render, -1, 0, 0, -1, -1, - TIP_("Restrict rendering (Ctrl - Recursive)")); - UI_but_func_set(bt, restrictbutton_rend_cb, scene, ob); - UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); - - UI_block_emboss_set(block, UI_EMBOSS); - - } - if (tselem->type == 0 && te->idcode == ID_GR) { - int restrict_bool; - int but_flag = UI_BUT_DRAG_LOCK; - gr = (Group *)tselem->id; - - if (ID_IS_LINKED_DATABLOCK(gr)) - but_flag |= UI_BUT_DISABLED; - - UI_block_emboss_set(block, UI_EMBOSS_NONE); - - restrict_bool = group_restrict_flag(gr, OB_RESTRICT_VIEW); - bt = uiDefIconBut(block, UI_BTYPE_ICON_TOGGLE, 0, restrict_bool ? ICON_RESTRICT_VIEW_ON : ICON_RESTRICT_VIEW_OFF, - (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X, UI_UNIT_Y, - NULL, 0, 0, 0, 0, TIP_("Restrict/Allow visibility in the 3D View")); - UI_but_func_set(bt, restrictbutton_gr_restrict_view, scene, gr); - UI_but_flag_enable(bt, but_flag); - - restrict_bool = group_restrict_flag(gr, OB_RESTRICT_SELECT); - bt = uiDefIconBut(block, UI_BTYPE_ICON_TOGGLE, 0, restrict_bool ? ICON_RESTRICT_SELECT_ON : ICON_RESTRICT_SELECT_OFF, - (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys, UI_UNIT_X, UI_UNIT_Y, - NULL, 0, 0, 0, 0, TIP_("Restrict/Allow selection in the 3D View")); - UI_but_func_set(bt, restrictbutton_gr_restrict_select, scene, gr); - UI_but_flag_enable(bt, but_flag); - - restrict_bool = group_restrict_flag(gr, OB_RESTRICT_RENDER); - bt = uiDefIconBut(block, UI_BTYPE_ICON_TOGGLE, 0, restrict_bool ? ICON_RESTRICT_RENDER_ON : ICON_RESTRICT_RENDER_OFF, - (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), te->ys, UI_UNIT_X, UI_UNIT_Y, - NULL, 0, 0, 0, 0, TIP_("Restrict/Allow renderability")); - UI_but_func_set(bt, restrictbutton_gr_restrict_render, scene, gr); - UI_but_flag_enable(bt, but_flag); - - UI_block_emboss_set(block, UI_EMBOSS); - } /* scene render layers and passes have toggle-able flags too! */ - else if (tselem->type == TSE_R_LAYER) { + if (tselem->type == TSE_R_LAYER) { UI_block_emboss_set(block, UI_EMBOSS_NONE); bt = uiDefIconButBitI(block, UI_BTYPE_ICON_TOGGLE_N, SCE_LAY_DISABLE, 0, ICON_CHECKBOX_HLT - 1, @@ -1467,16 +1199,6 @@ static void outliner_draw_tree_element( active = OL_DRAWSEL_ACTIVE; } } - else if (te->idcode == ID_GR) { - Group *gr = (Group *)tselem->id; - if (group_select_flag(gr)) { - char col[4]; - UI_GetThemeColorType4ubv(TH_SELECT, SPACE_VIEW3D, col); - rgba_float_args_set(color, (float)col[0] / 255, (float)col[1] / 255, (float)col[2] / 255, alpha); - - active = OL_DRAWSEL_ACTIVE; - } - } else if (te->idcode == ID_OB) { Object *ob = (Object *)tselem->id; @@ -1882,6 +1604,7 @@ void draw_outliner(const bContext *C) { Main *mainvar = CTX_data_main(C); Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); ARegion *ar = CTX_wm_region(C); View2D *v2d = &ar->v2d; SpaceOops *soops = CTX_wm_space_outliner(C); @@ -1890,7 +1613,7 @@ void draw_outliner(const bContext *C) TreeElement *te_edit = NULL; bool has_restrict_icons; - outliner_build_tree(mainvar, scene, soops); // always + outliner_build_tree(mainvar, scene, sl, soops); // always /* get extents of data */ outliner_height(soops, &soops->tree, &sizey); diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c index 4dcdcc69d6d..c35f2006f09 100644 --- a/source/blender/editors/space_outliner/outliner_edit.c +++ b/source/blender/editors/space_outliner/outliner_edit.c @@ -54,6 +54,7 @@ #include "BKE_depsgraph.h" #include "BKE_global.h" #include "BKE_idcode.h" +#include "BKE_layer.h" #include "BKE_library.h" #include "BKE_library_query.h" #include "BKE_library_remap.h" @@ -882,181 +883,6 @@ int common_restrict_check(bContext *C, Object *ob) } /* =============================================== */ -/* Restriction toggles */ - -/* Toggle Visibility ---------------------------------------- */ - -void object_toggle_visibility_cb( - bContext *C, ReportList *reports, Scene *scene, TreeElement *te, - TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data)) -{ - Base *base = (Base *)te->directdata; - Object *ob = (Object *)tselem->id; - - if (ID_IS_LINKED_DATABLOCK(tselem->id)) { - BKE_report(reports, RPT_WARNING, "Cannot edit external libdata"); - return; - } - - /* add check for edit mode */ - if (!common_restrict_check(C, ob)) return; - - if (base || (base = BKE_scene_base_find(scene, ob))) { - if ((base->object->restrictflag ^= OB_RESTRICT_VIEW)) { - ED_base_object_select(base, BA_DESELECT); - } - } -} - -void group_toggle_visibility_cb( - bContext *UNUSED(C), ReportList *UNUSED(reports), Scene *scene, TreeElement *UNUSED(te), - TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data)) -{ - Group *group = (Group *)tselem->id; - restrictbutton_gr_restrict_flag(scene, group, OB_RESTRICT_VIEW); -} - -static int outliner_toggle_visibility_exec(bContext *C, wmOperator *op) -{ - Main *bmain = CTX_data_main(C); - SpaceOops *soops = CTX_wm_space_outliner(C); - Scene *scene = CTX_data_scene(C); - ARegion *ar = CTX_wm_region(C); - - outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, object_toggle_visibility_cb); - - DAG_id_type_tag(bmain, ID_OB); - WM_event_add_notifier(C, NC_SCENE | ND_OB_VISIBLE, scene); - ED_region_tag_redraw(ar); - - return OPERATOR_FINISHED; -} - -void OUTLINER_OT_visibility_toggle(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Toggle Visibility"; - ot->idname = "OUTLINER_OT_visibility_toggle"; - ot->description = "Toggle the visibility of selected items"; - - /* callbacks */ - ot->exec = outliner_toggle_visibility_exec; - ot->poll = ED_operator_outliner_active_no_editobject; - - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; -} - -/* Toggle Selectability ---------------------------------------- */ - -void object_toggle_selectability_cb( - bContext *UNUSED(C), ReportList *reports, Scene *scene, TreeElement *te, - TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data)) -{ - Base *base = (Base *)te->directdata; - - if (ID_IS_LINKED_DATABLOCK(tselem->id)) { - BKE_report(reports, RPT_WARNING, "Cannot edit external libdata"); - return; - } - - if (base == NULL) base = BKE_scene_base_find(scene, (Object *)tselem->id); - if (base) { - base->object->restrictflag ^= OB_RESTRICT_SELECT; - } -} - -void group_toggle_selectability_cb( - bContext *UNUSED(C), ReportList *UNUSED(reports), Scene *scene, TreeElement *UNUSED(te), - TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data)) -{ - Group *group = (Group *)tselem->id; - restrictbutton_gr_restrict_flag(scene, group, OB_RESTRICT_SELECT); -} - -static int outliner_toggle_selectability_exec(bContext *C, wmOperator *op) -{ - SpaceOops *soops = CTX_wm_space_outliner(C); - Scene *scene = CTX_data_scene(C); - ARegion *ar = CTX_wm_region(C); - - outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, object_toggle_selectability_cb); - - WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); - ED_region_tag_redraw(ar); - - return OPERATOR_FINISHED; -} - -void OUTLINER_OT_selectability_toggle(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Toggle Selectability"; - ot->idname = "OUTLINER_OT_selectability_toggle"; - ot->description = "Toggle the selectability"; - - /* callbacks */ - ot->exec = outliner_toggle_selectability_exec; - ot->poll = ED_operator_outliner_active_no_editobject; - - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; -} - -/* Toggle Renderability ---------------------------------------- */ - -void object_toggle_renderability_cb( - bContext *UNUSED(C), ReportList *reports, Scene *scene, TreeElement *te, - TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data)) -{ - Base *base = (Base *)te->directdata; - - if (ID_IS_LINKED_DATABLOCK(tselem->id)) { - BKE_report(reports, RPT_WARNING, "Cannot edit external libdata"); - return; - } - - if (base == NULL) base = BKE_scene_base_find(scene, (Object *)tselem->id); - if (base) { - base->object->restrictflag ^= OB_RESTRICT_RENDER; - } -} - -void group_toggle_renderability_cb( - bContext *UNUSED(C), ReportList *UNUSED(reports), Scene *scene, TreeElement *UNUSED(te), - TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data)) -{ - Group *group = (Group *)tselem->id; - restrictbutton_gr_restrict_flag(scene, group, OB_RESTRICT_RENDER); -} - -static int outliner_toggle_renderability_exec(bContext *C, wmOperator *op) -{ - Main *bmain = CTX_data_main(C); - SpaceOops *soops = CTX_wm_space_outliner(C); - Scene *scene = CTX_data_scene(C); - - outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, object_toggle_renderability_cb); - - DAG_id_type_tag(bmain, ID_OB); - WM_event_add_notifier(C, NC_SCENE | ND_OB_RENDER, scene); - - return OPERATOR_FINISHED; -} - -void OUTLINER_OT_renderability_toggle(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Toggle Renderability"; - ot->idname = "OUTLINER_OT_renderability_toggle"; - ot->description = "Toggle the renderability of selected items"; - - /* callbacks */ - ot->exec = outliner_toggle_renderability_exec; - ot->poll = ED_operator_outliner_active; - - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; -} - -/* =============================================== */ /* Outliner setting toggles */ /* Toggle Expanded (Outliner) ---------------------------------------- */ @@ -2345,8 +2171,6 @@ static int scene_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event) te = outliner_dropzone_find(soops, fmval, false); if (te) { - Base *base; - RNA_string_set(op->ptr, "scene", te->name); scene = (Scene *)BKE_libblock_find_name(ID_SCE, te->name); @@ -2357,16 +2181,26 @@ static int scene_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event) return OPERATOR_CANCELLED; } - base = ED_object_scene_link(scene, ob); - - if (base == NULL) { + if (BKE_scene_has_object(scene, ob)) { return OPERATOR_CANCELLED; } - if (scene == CTX_data_scene(C)) { - /* when linking to an inactive scene don't touch the layer */ - ob->lay = base->lay; - ED_base_object_select(base, BA_SELECT); + SceneCollection *sc; + if (scene != CTX_data_scene(C)) { + /* when linking to an inactive scene link to the master collection */ + sc = BKE_collection_master(scene); + } + else { + sc = CTX_data_scene_collection(C); + } + + BKE_collection_object_add(scene, sc, ob); + + for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) { + Base *base = BKE_scene_layer_base_find(sl, ob); + if (base) { + ED_object_base_select(base, BA_SELECT); + } } DAG_relations_tag_update(bmain); @@ -2461,7 +2295,6 @@ static int group_link_invoke(bContext *C, wmOperator *op, const wmEvent *event) Main *bmain = CTX_data_main(C); Group *group = NULL; Object *ob = NULL; - Scene *scene = CTX_data_scene(C); SpaceOops *soops = CTX_wm_space_outliner(C); ARegion *ar = CTX_wm_region(C); TreeElement *te = NULL; @@ -2491,7 +2324,7 @@ static int group_link_invoke(bContext *C, wmOperator *op, const wmEvent *event) 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); return OPERATOR_FINISHED; diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h index f23c294c488..67af793a412 100644 --- a/source/blender/editors/space_outliner/outliner_intern.h +++ b/source/blender/editors/space_outliner/outliner_intern.h @@ -40,6 +40,7 @@ struct wmOperatorType; struct TreeStoreElem; struct bContext; struct Scene; +struct SceneLayer; struct ID; struct Object; struct bPoseChannel; @@ -141,7 +142,7 @@ TreeElement *outliner_find_posechannel(ListBase *lb, const struct bPoseChannel * TreeElement *outliner_find_editbone(ListBase *lb, const struct EditBone *ebone); struct ID *outliner_search_back(SpaceOops *soops, TreeElement *te, short idcode); -void outliner_build_tree(struct Main *mainvar, struct Scene *scene, struct SpaceOops *soops); +void outliner_build_tree(struct Main *mainvar, struct Scene *scene, struct SceneLayer *sl, struct SpaceOops *soops); /* outliner_draw.c ---------------------------------------------- */ @@ -239,10 +240,6 @@ void OUTLINER_OT_expanded_toggle(struct wmOperatorType *ot); void OUTLINER_OT_scroll_page(struct wmOperatorType *ot); -void OUTLINER_OT_renderability_toggle(struct wmOperatorType *ot); -void OUTLINER_OT_selectability_toggle(struct wmOperatorType *ot); -void OUTLINER_OT_visibility_toggle(struct wmOperatorType *ot); - void OUTLINER_OT_keyingset_add_selected(struct wmOperatorType *ot); void OUTLINER_OT_keyingset_remove_selected(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_outliner/outliner_ops.c b/source/blender/editors/space_outliner/outliner_ops.c index f0c2d848f7a..5ddfdddc80d 100644 --- a/source/blender/editors/space_outliner/outliner_ops.c +++ b/source/blender/editors/space_outliner/outliner_ops.c @@ -71,10 +71,6 @@ void outliner_operatortypes(void) WM_operatortype_append(OUTLINER_OT_selected_toggle); WM_operatortype_append(OUTLINER_OT_expanded_toggle); - WM_operatortype_append(OUTLINER_OT_renderability_toggle); - WM_operatortype_append(OUTLINER_OT_selectability_toggle); - WM_operatortype_append(OUTLINER_OT_visibility_toggle); - WM_operatortype_append(OUTLINER_OT_keyingset_add_selected); WM_operatortype_append(OUTLINER_OT_keyingset_remove_selected); @@ -143,11 +139,6 @@ void outliner_keymap(wmKeyConfig *keyconf) WM_keymap_verify_item(keymap, "OUTLINER_OT_selected_toggle", AKEY, KM_PRESS, 0, 0); WM_keymap_verify_item(keymap, "OUTLINER_OT_expanded_toggle", AKEY, KM_PRESS, KM_SHIFT, 0); - WM_keymap_verify_item(keymap, "OUTLINER_OT_renderability_toggle", RKEY, KM_PRESS, 0, 0); - WM_keymap_verify_item(keymap, "OUTLINER_OT_selectability_toggle", SKEY, KM_PRESS, 0, 0); - WM_keymap_verify_item(keymap, "OUTLINER_OT_visibility_toggle", VKEY, KM_PRESS, 0, 0); - - /* keying sets - only for databrowse */ WM_keymap_verify_item(keymap, "OUTLINER_OT_keyingset_add_selected", KKEY, KM_PRESS, 0, 0); WM_keymap_verify_item(keymap, "OUTLINER_OT_keyingset_remove_selected", KKEY, KM_PRESS, KM_ALT, 0); diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c index a73e160f357..3018ef1e571 100644 --- a/source/blender/editors/space_outliner/outliner_select.c +++ b/source/blender/editors/space_outliner/outliner_select.c @@ -46,6 +46,7 @@ #include "BKE_context.h" #include "BKE_depsgraph.h" #include "BKE_object.h" +#include "BKE_layer.h" #include "BKE_scene.h" #include "BKE_sequencer.h" #include "BKE_armature.h" @@ -99,7 +100,7 @@ static eOLDrawState tree_element_active_renderlayer( */ static void do_outliner_object_select_recursive(Scene *scene, Object *ob_parent, bool select) { - Base *base; + BaseLegacy *base; for (base = FIRSTBASE; base; base = base->next) { Object *ob = base->object; @@ -140,7 +141,7 @@ static eOLDrawState tree_element_set_active_object( { TreeStoreElem *tselem = TREESTORE(te); Scene *sce; - Base *base; + BaseLegacy *base; Object *ob = NULL; /* if id is not object, we search back */ @@ -169,7 +170,7 @@ static eOLDrawState tree_element_set_active_object( if (base) { if (set == OL_SETSEL_EXTEND) { /* swap select */ - if (base->flag & SELECT) + if (base->flag_legacy & SELECT) ED_base_object_select(base, BA_DESELECT); else ED_base_object_select(base, BA_SELECT); @@ -655,8 +656,10 @@ static eOLDrawState tree_element_active_text( static eOLDrawState tree_element_active_pose( bContext *C, Scene *scene, TreeElement *UNUSED(te), TreeStoreElem *tselem, const eOLSetState set) { + TODO_LAYER_CONTEXT; /* we may need to pass SceneLayer instead of Scene here */ + SceneLayer *sl = CTX_data_scene_layer(C); Object *ob = (Object *)tselem->id; - Base *base = BKE_scene_base_find(scene, ob); + Base *base = BKE_scene_layer_base_find(sl, ob); if (set != OL_SETSEL_NONE) { if (scene->obedit) diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c index 4560b7cd6e7..550dc63dd3c 100644 --- a/source/blender/editors/space_outliner/outliner_tools.c +++ b/source/blender/editors/space_outliner/outliner_tools.c @@ -56,6 +56,7 @@ #include "BKE_depsgraph.h" #include "BKE_fcurve.h" #include "BKE_group.h" +#include "BKE_layer.h" #include "BKE_library.h" #include "BKE_library_query.h" #include "BKE_library_remap.h" @@ -360,15 +361,15 @@ void OUTLINER_OT_scene_operation(wmOperatorType *ot) /* ******************************************** */ static void object_select_cb( - bContext *UNUSED(C), ReportList *UNUSED(reports), Scene *scene, TreeElement *te, + bContext *C, ReportList *UNUSED(reports), Scene *UNUSED(scene), TreeElement *UNUSED(te), TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data)) { - Base *base = (Base *)te->directdata; - - if (base == NULL) base = BKE_scene_base_find(scene, (Object *)tselem->id); - if (base && ((base->object->restrictflag & OB_RESTRICT_VIEW) == 0)) { - base->flag |= SELECT; - base->object->flag |= SELECT; + SceneLayer *sl = CTX_data_scene_layer(C); + Object *ob = (Object *)tselem->id; + Base *base = BKE_scene_layer_base_find(sl, ob); + + if (base && ((base->flag & BASE_VISIBLED) != 0)) { + base->flag |= BASE_SELECTED; } } @@ -385,46 +386,43 @@ static void object_select_hierarchy_cb( static void object_deselect_cb( - bContext *UNUSED(C), ReportList *UNUSED(reports), Scene *scene, TreeElement *te, + bContext *C, ReportList *UNUSED(reports), Scene *UNUSED(scene), TreeElement *UNUSED(te), TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data)) { - Base *base = (Base *)te->directdata; - - if (base == NULL) base = BKE_scene_base_find(scene, (Object *)tselem->id); + SceneLayer *sl = CTX_data_scene_layer(C); + Object *ob = (Object *)tselem->id; + Base *base = BKE_scene_layer_base_find(sl, ob); + if (base) { - base->flag &= ~SELECT; - base->object->flag &= ~SELECT; + base->flag &= ~BASE_SELECTED; } } static void object_delete_cb( - bContext *C, ReportList *reports, Scene *scene, TreeElement *te, + bContext *C, ReportList *reports, Scene *scene, TreeElement *UNUSED(te), TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data)) { - Base *base = (Base *)te->directdata; - - if (base == NULL) - base = BKE_scene_base_find(scene, (Object *)tselem->id); - if (base) { + Object *ob = (Object *)tselem->id; + if (ob) { Main *bmain = CTX_data_main(C); - if (base->object->id.tag & LIB_TAG_INDIRECT) { - BKE_reportf(reports, RPT_WARNING, "Cannot delete indirectly linked object '%s'", base->object->id.name + 2); + if (ob->id.tag & LIB_TAG_INDIRECT) { + BKE_reportf(reports, RPT_WARNING, "Cannot delete indirectly linked object '%s'", ob->id.name + 2); return; } - else if (BKE_library_ID_is_indirectly_used(bmain, base->object) && - ID_REAL_USERS(base->object) <= 1 && ID_EXTRA_USERS(base->object) == 0) + else if (BKE_library_ID_is_indirectly_used(bmain, ob) && + ID_REAL_USERS(ob) <= 1 && ID_EXTRA_USERS(ob) == 0) { BKE_reportf(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); return; } // check also library later - if (scene->obedit == base->object) + if (scene->obedit == ob) ED_object_editmode_exit(C, EM_FREEDATA | EM_FREEUNDO | EM_WAITCURSOR | EM_DO_UNDO); - ED_base_object_free_and_unlink(CTX_data_main(C), scene, base); + ED_base_object_free_and_unlink(CTX_data_main(C), scene, ob); /* leave for ED_outliner_id_unref to handle */ #if 0 te->directdata = NULL; @@ -520,7 +518,7 @@ static void group_linkobs2scene_cb( { Group *group = (Group *)tselem->id; GroupObject *gob; - Base *base; + BaseLegacy *base; for (gob = group->gobject.first; gob; gob = gob->next) { base = BKE_scene_base_find(scene, gob->ob); @@ -530,7 +528,7 @@ static void group_linkobs2scene_cb( id_us_plus(&gob->ob->id); } base->object->flag |= SELECT; - base->flag |= SELECT; + base->flag_legacy |= SELECT; } } @@ -820,9 +818,9 @@ static void outliner_do_data_operation(SpaceOops *soops, int type, int event, Li } } -static Base *outline_delete_hierarchy(bContext *C, ReportList *reports, Scene *scene, Base *base) +static BaseLegacy *outline_delete_hierarchy(bContext *C, ReportList *reports, Scene *scene, BaseLegacy *base) { - Base *child_base, *base_next; + BaseLegacy *child_base, *base_next; Object *parent; if (!base) { @@ -852,7 +850,7 @@ static Base *outline_delete_hierarchy(bContext *C, ReportList *reports, Scene *s base->object->id.name + 2, scene->id.name + 2); return base_next; } - ED_base_object_free_and_unlink(CTX_data_main(C), scene, base); + ED_base_object_free_and_unlink(CTX_data_main(C), scene, base->object); return base_next; } @@ -860,6 +858,7 @@ static void object_delete_hierarchy_cb( bContext *C, ReportList *reports, Scene *scene, TreeElement *te, TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data)) { +#if 0 Base *base = (Base *)te->directdata; Object *obedit = scene->obedit; @@ -882,6 +881,15 @@ static void object_delete_hierarchy_cb( } WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); +#else + (void) C; + (void) scene; + (void) te; + (void) tselem; + (void) outline_delete_hierarchy; + BKE_reportf(reports, RPT_ERROR, "Delete from outliner not supported at the moment"); + TODO_LAYER_BASE +#endif } /* **************************************** */ @@ -985,21 +993,6 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op) outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, id_local_cb); str = "Localized Objects"; } - else if (event == OL_OP_TOGVIS) { - outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, object_toggle_visibility_cb); - str = "Toggle Visibility"; - WM_event_add_notifier(C, NC_SCENE | ND_OB_VISIBLE, scene); - } - else if (event == OL_OP_TOGSEL) { - outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, object_toggle_selectability_cb); - str = "Toggle Selectability"; - WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); - } - else if (event == OL_OP_TOGREN) { - outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, object_toggle_renderability_cb); - str = "Toggle Renderability"; - WM_event_add_notifier(C, NC_SCENE | ND_OB_RENDER, scene); - } else if (event == OL_OP_RENAME) { outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, item_rename_cb); str = "Rename Object"; @@ -1095,15 +1088,6 @@ static int outliner_group_operation_exec(bContext *C, wmOperator *op) case OL_GROUPOP_REMAP: outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, id_remap_cb, NULL); break; - case OL_GROUPOP_TOGVIS: - outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, group_toggle_visibility_cb, NULL); - break; - case OL_GROUPOP_TOGSEL: - outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, group_toggle_selectability_cb, NULL); - break; - case OL_GROUPOP_TOGREN: - outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, group_toggle_renderability_cb, NULL); - break; case OL_GROUPOP_RENAME: outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, item_rename_cb, NULL); break; diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c index ec46c5df9a0..a4f59f60f31 100644 --- a/source/blender/editors/space_outliner/outliner_tree.c +++ b/source/blender/editors/space_outliner/outliner_tree.c @@ -63,6 +63,7 @@ #include "BKE_fcurve.h" #include "BKE_main.h" +#include "BKE_layer.h" #include "BKE_library.h" #include "BKE_modifier.h" #include "BKE_sequencer.h" @@ -1619,9 +1620,8 @@ static int outliner_filter_tree(SpaceOops *soops, ListBase *lb) /* Main entry point for building the tree data-structure that the outliner represents */ // TODO: split each mode into its own function? -void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops) +void outliner_build_tree(Main *mainvar, Scene *scene, SceneLayer *sl, SpaceOops *soops) { - Base *base; TreeElement *te = NULL, *ten; TreeStoreElem *tselem; int show_opened = !soops->treestore || !BLI_mempool_count(soops->treestore); /* on first view, we open scenes */ @@ -1702,31 +1702,43 @@ void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops) tselem = TREESTORE(te); if (sce == scene && show_opened) tselem->flag &= ~TSE_CLOSED; - - for (base = sce->base.first; base; base = base->next) { - ten = outliner_add_element(soops, &te->subtree, base->object, te, 0, 0); - ten->directdata = base; + + Object *ob; + FOREACH_SCENE_OBJECT(scene, ob) + { + ten = outliner_add_element(soops, &te->subtree, ob, te, 0, 0); } + FOREACH_SCENE_OBJECT_END + outliner_make_hierarchy(&te->subtree); + /* clear id.newid, to prevent objects be inserted in wrong scenes (parent in other scene) */ - for (base = sce->base.first; base; base = base->next) base->object->id.newid = NULL; + FOREACH_SCENE_OBJECT(scene, ob) + { + ob->id.newid = NULL; + } + FOREACH_SCENE_OBJECT_END } } else if (soops->outlinevis == SO_CUR_SCENE) { outliner_add_scene_contents(soops, &soops->tree, scene, NULL); - - for (base = scene->base.first; base; base = base->next) { - ten = outliner_add_element(soops, &soops->tree, base->object, NULL, 0, 0); - ten->directdata = base; + + Object *ob; + FOREACH_SCENE_OBJECT(scene, ob) + { + ten = outliner_add_element(soops, &soops->tree, ob, NULL, 0, 0); } + FOREACH_SCENE_OBJECT_END outliner_make_hierarchy(&soops->tree); } else if (soops->outlinevis == SO_VISIBLE) { - for (base = scene->base.first; base; base = base->next) { - if (base->lay & scene->lay) - outliner_add_element(soops, &soops->tree, base->object, NULL, 0, 0); + Object *ob; + FOREACH_VISIBLE_OBJECT(sl, ob) + { + outliner_add_element(soops, &soops->tree, ob, NULL, 0, 0); } + FOREACH_VISIBLE_OBJECT_END outliner_make_hierarchy(&soops->tree); } else if (soops->outlinevis == SO_GROUPS) { @@ -1739,7 +1751,6 @@ void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops) for (go = group->gobject.first; go; go = go->next) { ten = outliner_add_element(soops, &te->subtree, go->ob, te, 0, 0); - ten->directdata = NULL; /* eh, why? */ } outliner_make_hierarchy(&te->subtree); /* clear id.newid, to prevent objects be inserted in wrong scenes (parent in other scene) */ @@ -1748,26 +1759,26 @@ void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops) } } else if (soops->outlinevis == SO_SAME_TYPE) { - Object *ob = OBACT; - if (ob) { - for (base = scene->base.first; base; base = base->next) { - if (base->object->type == ob->type) { - ten = outliner_add_element(soops, &soops->tree, base->object, NULL, 0, 0); - ten->directdata = base; + Object *ob_active = OBACT_NEW; + if (ob_active) { + Object *ob; + FOREACH_SCENE_OBJECT(scene, ob) + { + if (ob->type == ob_active->type) { + ten = outliner_add_element(soops, &soops->tree, ob, NULL, 0, 0); } } + FOREACH_SCENE_OBJECT_END outliner_make_hierarchy(&soops->tree); } } else if (soops->outlinevis == SO_SELECTED) { - for (base = scene->base.first; base; base = base->next) { - if (base->lay & scene->lay) { - if (base->flag & SELECT) { - ten = outliner_add_element(soops, &soops->tree, base->object, NULL, 0, 0); - ten->directdata = base; - } - } + Object *ob; + FOREACH_SELECTED_OBJECT(sl, ob) + { + ten = outliner_add_element(soops, &soops->tree, ob, NULL, 0, 0); } + FOREACH_SELECTED_OBJECT_END outliner_make_hierarchy(&soops->tree); } else if (soops->outlinevis == SO_SEQUENCE) { @@ -1822,8 +1833,7 @@ void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops) outliner_add_orphaned_datablocks(mainvar, soops); } else { - ten = outliner_add_element(soops, &soops->tree, OBACT, NULL, 0, 0); - if (ten) ten->directdata = BASACT; + ten = outliner_add_element(soops, &soops->tree, OBACT_NEW, NULL, 0, 0); } if ((soops->flag & SO_SKIP_SORT_ALPHA) == 0) { diff --git a/source/blender/editors/space_time/space_time.c b/source/blender/editors/space_time/space_time.c index 5e7060d6651..e9306c04cfa 100644 --- a/source/blender/editors/space_time/space_time.c +++ b/source/blender/editors/space_time/space_time.c @@ -402,7 +402,7 @@ static void time_draw_caches_keyframes(Main *bmain, Scene *scene, View2D *v2d, b cache_file->draw_flag &= ~CACHEFILE_KEYFRAME_DRAWN; } - for (Base *base = scene->base.first; base; base = base->next) { + for (BaseLegacy *base = scene->base.first; base; base = base->next) { Object *ob = base->object; ModifierData *md = modifiers_findByType(ob, eModifierType_MeshSequenceCache); diff --git a/source/blender/editors/space_view3d/drawarmature.c b/source/blender/editors/space_view3d/drawarmature.c index af041e392c5..325c635dcf3 100644 --- a/source/blender/editors/space_view3d/drawarmature.c +++ b/source/blender/editors/space_view3d/drawarmature.c @@ -1733,7 +1733,7 @@ static void bone_matrix_translate_y(float mat[4][4], float y) } /* assumes object is Armature with pose */ -static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, +static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, BaseLegacy *base, const short dt, const unsigned char ob_wire_col[4], const bool do_const_color, const bool is_outline) { @@ -2106,7 +2106,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, /* draw DoFs */ if (arm->flag & ARM_POSEMODE) { - if (((base->flag & OB_FROMDUPLI) == 0) && ((v3d->flag & V3D_HIDE_HELPLINES) == 0)) { + if (((base->flag_legacy & OB_FROMDUPLI) == 0) && ((v3d->flag & V3D_HIDE_HELPLINES) == 0)) { draw_pose_dofs(ob); } } @@ -2114,7 +2114,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, /* finally names and axes */ if ((arm->flag & (ARM_DRAWNAMES | ARM_DRAWAXES)) && (is_outline == 0) && - ((base->flag & OB_FROMDUPLI) == 0)) + ((base->flag_legacy & OB_FROMDUPLI) == 0)) { /* patch for several 3d cards (IBM mostly) that crash on GL_SELECT with text drawing */ if ((G.f & G_PICKSEL) == 0) { @@ -2445,7 +2445,7 @@ static void ghost_poses_tag_unselected(Object *ob, short unset) /* draw ghosts that occur within a frame range * note: object should be in posemode */ -static void draw_ghost_poses_range(Scene *scene, View3D *v3d, ARegion *ar, Base *base) +static void draw_ghost_poses_range(Scene *scene, View3D *v3d, ARegion *ar, BaseLegacy *base) { Object *ob = base->object; AnimData *adt = BKE_animdata_from_id(&ob->id); @@ -2511,7 +2511,7 @@ static void draw_ghost_poses_range(Scene *scene, View3D *v3d, ARegion *ar, Base /* draw ghosts on keyframes in action within range * - object should be in posemode */ -static void draw_ghost_poses_keys(Scene *scene, View3D *v3d, ARegion *ar, Base *base) +static void draw_ghost_poses_keys(Scene *scene, View3D *v3d, ARegion *ar, BaseLegacy *base) { Object *ob = base->object; AnimData *adt = BKE_animdata_from_id(&ob->id); @@ -2592,7 +2592,7 @@ static void draw_ghost_poses_keys(Scene *scene, View3D *v3d, ARegion *ar, Base * /* draw ghosts around current frame * - object is supposed to be armature in posemode */ -static void draw_ghost_poses(Scene *scene, View3D *v3d, ARegion *ar, Base *base) +static void draw_ghost_poses(Scene *scene, View3D *v3d, ARegion *ar, BaseLegacy *base) { Object *ob = base->object; AnimData *adt = BKE_animdata_from_id(&ob->id); @@ -2686,7 +2686,7 @@ static void draw_ghost_poses(Scene *scene, View3D *v3d, ARegion *ar, Base *base) /* called from drawobject.c, return true if nothing was drawn * (ob_wire_col == NULL) when drawing ghost */ -bool draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base, +bool draw_armature(Scene *scene, View3D *v3d, ARegion *ar, BaseLegacy *base, const short dt, const short dflag, const unsigned char ob_wire_col[4], const bool is_outline) { @@ -2733,7 +2733,7 @@ bool draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base, } /* drawing posemode selection indices or colors only in these cases */ - if (!(base->flag & OB_FROMDUPLI)) { + if (!(base->flag_legacy & OB_FROMDUPLI)) { if (G.f & G_PICKSEL) { #if 0 /* nifty but actually confusing to allow bone selection out of posemode */ diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index d0841129126..44de13c95fd 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -323,9 +323,9 @@ bool draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, const char dt) return false; } -static bool check_alpha_pass(Base *base) +static bool check_alpha_pass(BaseLegacy *base) { - if (base->flag & OB_FROMDUPLI) + if (base->flag_legacy & OB_FROMDUPLI) return false; if (G.f & G_PICKSEL) @@ -1231,7 +1231,7 @@ static void draw_transp_sun_volume(Lamp *la, unsigned pos) } #endif -void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base, +void drawlamp(View3D *v3d, RegionView3D *rv3d, BaseLegacy *base, const char dt, const short dflag, const unsigned char ob_wire_col[4], const bool is_obact) { Object *ob = base->object; @@ -1247,7 +1247,7 @@ void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base, !(G.f & G_PICKSEL) && (la->type == LA_SPOT) && (la->mode & LA_SHOW_CONE) && - !(base->flag & OB_FROMDUPLI) && + !(base->flag_legacy & OB_FROMDUPLI) && !is_view); #ifdef WITH_GAMEENGINE @@ -1259,7 +1259,7 @@ void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base, ((la->mode & LA_SHAD_BUF) || (la->mode & LA_SHAD_RAY)) && (la->mode & LA_SHOW_SHADOW_BOX) && - !(base->flag & OB_FROMDUPLI) && + !(base->flag_legacy & OB_FROMDUPLI) && !is_view); #else const bool drawshadowbox = false; @@ -1690,7 +1690,7 @@ static void draw_bundle_sphere(void) } static void draw_viewport_object_reconstruction( - Scene *scene, Base *base, const View3D *v3d, const RegionView3D *rv3d, + Scene *scene, BaseLegacy *base, const View3D *v3d, const RegionView3D *rv3d, MovieClip *clip, MovieTrackingObject *tracking_object, const short dflag, const unsigned char ob_wire_col[4], int *global_track_index, bool draw_selected) @@ -1852,7 +1852,7 @@ static void draw_viewport_object_reconstruction( } static void draw_viewport_reconstruction( - Scene *scene, Base *base, const View3D *v3d, const RegionView3D *rv3d, MovieClip *clip, + Scene *scene, BaseLegacy *base, const View3D *v3d, const RegionView3D *rv3d, MovieClip *clip, const short dflag, const unsigned char ob_wire_col[4], const bool draw_selected) { @@ -2121,7 +2121,7 @@ static void drawcamera_stereo3d( } /* flag similar to draw_object() */ -void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, +void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, BaseLegacy *base, const short dflag, const unsigned char ob_wire_col[4]) { /* a standing up pyramid with (0,0,0) as top */ @@ -4188,7 +4188,7 @@ static bool object_is_halo(Scene *scene, Object *ob) return (ma && (ma->material_type == MA_TYPE_HALO) && !BKE_scene_use_new_shading_nodes(scene)); } -static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, +static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, BaseLegacy *base, const char dt, const unsigned char ob_wire_col[4], const short dflag) { #ifdef WITH_GAMEENGINE @@ -4254,7 +4254,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D if ((v3d->flag & V3D_SELECT_OUTLINE) && ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) && - (base->flag & SELECT) && + (base->flag_legacy & SELECT) && !(G.f & G_PICKSEL || (draw_flags & DRAW_FACE_SELECT)) && (draw_wire == OBDRAW_WIRE_OFF)) { @@ -4325,7 +4325,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D /* draw outline */ if ((v3d->flag & V3D_SELECT_OUTLINE) && ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) && - (base->flag & SELECT) && + (base->flag_legacy & SELECT) && (draw_wire == OBDRAW_WIRE_OFF) && (ob->sculpt == NULL)) { @@ -4349,7 +4349,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D if ((v3d->flag & V3D_SELECT_OUTLINE) && ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) && - (base->flag & SELECT) && + (base->flag_legacy & SELECT) && (draw_wire == OBDRAW_WIRE_OFF) && (ob->sculpt == NULL)) { @@ -4451,7 +4451,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D } /* returns true if nothing was drawn, for detecting to draw an object center */ -static bool draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, +static bool draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, BaseLegacy *base, const char dt, const unsigned char ob_wire_col[4], const short dflag) { Object *ob = base->object; @@ -4541,7 +4541,7 @@ static bool draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3 } } - if ((dflag & DRAW_PICKING) == 0 && (base->flag & OB_FROMDUPLI) == 0 && (v3d->flag2 & V3D_RENDER_SHADOW) == 0) { + if ((dflag & DRAW_PICKING) == 0 && (base->flag_legacy & OB_FROMDUPLI) == 0 && (v3d->flag2 & V3D_RENDER_SHADOW) == 0) { /* GPU_begin_object_materials checked if this is needed */ if (do_alpha_after) { if (ob->dtx & OB_DRAWXRAY) { @@ -4595,7 +4595,7 @@ static void make_color_variations(const unsigned char base_ubyte[4], float low[4 high[3] = base[3]; } -static void draw_mesh_fancy_new(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, +static void draw_mesh_fancy_new(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, BaseLegacy *base, const char dt, const unsigned char ob_wire_col[4], const short dflag, const bool other_obedit) { if (dflag & (DRAW_PICKING | DRAW_CONSTCOLOR)) { @@ -4731,7 +4731,7 @@ static void draw_mesh_fancy_new(Scene *scene, ARegion *ar, View3D *v3d, RegionVi if ((v3d->flag & V3D_SELECT_OUTLINE) && ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) && - (base->flag & SELECT) && + (base->flag_legacy & SELECT) && !(G.f & G_PICKSEL || (draw_flags & DRAW_FACE_SELECT)) && (draw_wire == OBDRAW_WIRE_OFF)) { @@ -4798,7 +4798,7 @@ static void draw_mesh_fancy_new(Scene *scene, ARegion *ar, View3D *v3d, RegionVi /* TODO: move this into a separate pass */ if ((v3d->flag & V3D_SELECT_OUTLINE) && ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) && - (base->flag & SELECT) && + (base->flag_legacy & SELECT) && (draw_wire == OBDRAW_WIRE_OFF) && (ob->sculpt == NULL)) { @@ -4822,7 +4822,7 @@ static void draw_mesh_fancy_new(Scene *scene, ARegion *ar, View3D *v3d, RegionVi if ((v3d->flag & V3D_SELECT_OUTLINE) && ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) && - (base->flag & SELECT) && + (base->flag_legacy & SELECT) && (draw_wire == OBDRAW_WIRE_OFF) && (ob->sculpt == NULL)) { @@ -4914,7 +4914,7 @@ static void draw_mesh_fancy_new(Scene *scene, ARegion *ar, View3D *v3d, RegionVi dm->release(dm); } -static bool draw_mesh_object_new(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, +static bool draw_mesh_object_new(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, BaseLegacy *base, const char dt, const unsigned char ob_wire_col[4], const short dflag) { Object *ob = base->object; @@ -5253,7 +5253,7 @@ static void drawCurveDMWired(Object *ob) } /* return true when nothing was drawn */ -static bool drawCurveDerivedMesh(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, const char dt) +static bool drawCurveDerivedMesh(Scene *scene, View3D *v3d, RegionView3D *rv3d, BaseLegacy *base, const char dt) { Object *ob = base->object; DerivedMesh *dm = ob->derivedFinal; @@ -5289,7 +5289,7 @@ static bool drawCurveDerivedMesh(Scene *scene, View3D *v3d, RegionView3D *rv3d, * Only called by #drawDispList * \return true when nothing was drawn */ -static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, +static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3d, BaseLegacy *base, const char dt, const short dflag, const unsigned char ob_wire_col[4]) { Object *ob = base->object; @@ -5410,7 +5410,7 @@ static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3 return false; } -static bool drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, +static bool drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, BaseLegacy *base, const char dt, const short dflag, const unsigned char ob_wire_col[4]) { bool retval; @@ -5678,7 +5678,7 @@ static void draw_particle_data(ParticleSystem *psys, RegionView3D *rv3d, * 7. clean up */ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv3d, - Base *base, ParticleSystem *psys, + BaseLegacy *base, ParticleSystem *psys, const char ob_dt, const short dflag) { Object *ob = base->object; @@ -5768,7 +5768,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv timestep = psys_get_timestep(&sim); - if ((base->flag & OB_FROMDUPLI) && (ob->flag & OB_FROMGROUP)) { + if ((ob->flag & OB_FROMGROUP) != 0) { float mat[4][4]; mul_m4_m4m4(mat, ob->obmat, psys->imat); glMultMatrixf(mat); @@ -6399,7 +6399,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv pdd->ma_col = NULL; } - if ((base->flag & OB_FROMDUPLI) && (ob->flag & OB_FROMGROUP)) { + if ((ob->flag & OB_FROMGROUP) != 0) { glLoadMatrixf(rv3d->viewmat); } } @@ -7059,7 +7059,7 @@ static void draw_editnurb_splines(Object *ob, Nurb *nurb, const bool sel) } static void draw_editnurb( - Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, Nurb *nurb, + Scene *scene, View3D *v3d, RegionView3D *rv3d, BaseLegacy *base, Nurb *nurb, const char dt, const short dflag, const unsigned char ob_wire_col[4]) { ToolSettings *ts = scene->toolsettings; @@ -7169,7 +7169,7 @@ static void draw_editfont_textcurs(RegionView3D *rv3d, float textcurs[4][2]) ED_view3d_polygon_offset(rv3d, 0.0); } -static void draw_editfont(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, +static void draw_editfont(Scene *scene, View3D *v3d, RegionView3D *rv3d, BaseLegacy *base, const char dt, const short dflag, const unsigned char ob_wire_col[4]) { Object *ob = base->object; @@ -7527,7 +7527,7 @@ static void imm_drawcone(const float vec[3], float radius, float height, float t } /* return true if nothing was drawn */ -static bool drawmball(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, +static bool drawmball(Scene *scene, View3D *v3d, RegionView3D *rv3d, BaseLegacy *base, const char dt, const short dflag, const unsigned char ob_wire_col[4]) { Object *ob = base->object; @@ -7548,7 +7548,7 @@ static bool drawmball(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, ml = mb->editelems->first; } else { - if ((base->flag & OB_FROMDUPLI) == 0) { + if ((base->flag_legacy & OB_FROMDUPLI) == 0) { drawDispList(scene, v3d, rv3d, base, dt, dflag, ob_wire_col); } ml = mb->elems.first; @@ -7942,7 +7942,7 @@ static void drawtexspace(Object *ob) } /* draws wire outline */ -static void drawObjectSelect(Scene *scene, View3D *v3d, ARegion *ar, Base *base, +static void drawObjectSelect(Scene *scene, View3D *v3d, ARegion *ar, BaseLegacy *base, const unsigned char ob_wire_col[4]) { RegionView3D *rv3d = ar->regiondata; @@ -7982,7 +7982,7 @@ static void drawObjectSelect(Scene *scene, View3D *v3d, ARegion *ar, Base *base, } else if (ob->type == OB_MBALL) { if (BKE_mball_is_basis(ob)) { - if ((base->flag & OB_FROMDUPLI) == 0) { + if ((base->flag_legacy & OB_FROMDUPLI) == 0) { glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f); drawDispListwire(&ob->curve_cache->disp, ob->type); } @@ -8095,7 +8095,7 @@ static void draw_rigid_body_pivot(bRigidBodyJointConstraint *data, setlinestyle(0); } -void draw_object_wire_color(Scene *scene, Base *base, unsigned char r_ob_wire_col[4]) +void draw_object_wire_color(Scene *scene, BaseLegacy *base, unsigned char r_ob_wire_col[4]) { Object *ob = base->object; int colindex = 0; @@ -8109,19 +8109,19 @@ void draw_object_wire_color(Scene *scene, Base *base, unsigned char r_ob_wire_co if ((scene->obedit == NULL) && (G.moving & G_TRANSFORM_OBJ) && - (base->flag & (SELECT + BA_WAS_SEL))) + (base->flag_legacy & (SELECT + BA_WAS_SEL))) { theme_id = TH_TRANSFORM; } else { /* Sets the 'colindex' */ if (ID_IS_LINKED_DATABLOCK(ob)) { - colindex = (base->flag & (SELECT + BA_WAS_SEL)) ? 2 : 1; + colindex = (base->flag_legacy & (SELECT + BA_WAS_SEL)) ? 2 : 1; } /* Sets the 'theme_id' or fallback to wire */ else { - if (ob->flag & OB_FROMGROUP) { - if (base->flag & (SELECT + BA_WAS_SEL)) { + if ((ob->flag & OB_FROMGROUP) != 0) { + if (base->flag_legacy & (SELECT + BA_WAS_SEL)) { /* uses darker active color for non-active + selected */ theme_id = TH_GROUP_ACTIVE; @@ -8134,7 +8134,7 @@ void draw_object_wire_color(Scene *scene, Base *base, unsigned char r_ob_wire_co } } else { - if (base->flag & (SELECT + BA_WAS_SEL)) { + if (base->flag_legacy & (SELECT + BA_WAS_SEL)) { theme_id = scene->basact == base ? TH_ACTIVE : TH_SELECT; } else { @@ -8233,7 +8233,7 @@ void draw_rigidbody_shape(Object *ob) * main object drawing function, draws in selection * \param dflag (draw flag) can be DRAW_PICKING and/or DRAW_CONSTCOLOR, DRAW_SCENESET */ -void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short dflag) +void draw_object(Scene *scene, ARegion *ar, View3D *v3d, BaseLegacy *base, const short dflag) { ModifierData *md = NULL; Object *ob = base->object; @@ -8283,7 +8283,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short } } - if (((base->flag & OB_FROMDUPLI) == 0) && + if (((base->flag_legacy & OB_FROMDUPLI) == 0) && (md = modifiers_findByType(ob, eModifierType_Smoke)) && (modifier_isEnabled(scene, md, eModifierMode_Realtime))) { @@ -8307,7 +8307,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short /* xray delay? */ - if ((dflag & DRAW_PICKING) == 0 && (base->flag & OB_FROMDUPLI) == 0 && (v3d->flag2 & V3D_RENDER_SHADOW) == 0) { + if ((dflag & DRAW_PICKING) == 0 && (base->flag_legacy & OB_FROMDUPLI) == 0 && (v3d->flag2 & V3D_RENDER_SHADOW) == 0) { /* don't do xray in particle mode, need the z-buffer */ if (!(ob->mode & OB_MODE_PARTICLE_EDIT)) { /* xray and transp are set when it is drawing the 2nd/3rd pass */ @@ -8805,7 +8805,7 @@ afterdraw: glDisable(GL_DEPTH_TEST); } - if ((base->flag & OB_FROMDUPLI) || render_override) { + if ((base->flag_legacy & OB_FROMDUPLI) || render_override) { ED_view3d_clear_mats_rv3d(rv3d); return; } @@ -8819,7 +8819,7 @@ afterdraw: } else if (is_obact) do_draw_center = ACTIVE; - else if (base->flag & SELECT) + else if (base->flag_legacy & SELECT) do_draw_center = SELECT; else if (empty_object || (v3d->flag & V3D_DRAW_CENTERS)) do_draw_center = DESELECT; diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index 81122f3b661..a3d4f6ef031 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -647,7 +647,7 @@ static int view3d_ima_bg_drop_poll(bContext *C, wmDrag *drag, const wmEvent *eve static int view3d_ima_empty_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event) { - Base *base = ED_view3d_give_base_under_cursor(C, event->mval); + BaseLegacy *base = ED_view3d_give_base_under_cursor(C, event->mval); /* either holding and ctrl and no object, or dropping to empty */ if (((base == NULL) && event->ctrl) || @@ -661,7 +661,7 @@ static int view3d_ima_empty_drop_poll(bContext *C, wmDrag *drag, const wmEvent * static int view3d_ima_mesh_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event) { - Base *base = ED_view3d_give_base_under_cursor(C, event->mval); + BaseLegacy *base = ED_view3d_give_base_under_cursor(C, event->mval); if (base && base->object->type == OB_MESH) return view3d_ima_drop_poll(C, drag, event); @@ -784,7 +784,7 @@ static void view3d_recalc_used_layers(ARegion *ar, wmNotifier *wmn, Scene *scene wmWindow *win = wmn->wm->winactive; ScrArea *sa; unsigned int lay_used = 0; - Base *base; + BaseLegacy *base; if (!win) return; @@ -1274,8 +1274,6 @@ static void space_view3d_listener(bScreen *UNUSED(sc), ScrArea *sa, struct wmNot } const char *view3d_context_dir[] = { - "selected_objects", "selected_bases", "selected_editable_objects", - "selected_editable_bases", "visible_objects", "visible_bases", "selectable_objects", "selectable_bases", "active_base", "active_object", NULL }; @@ -1286,109 +1284,27 @@ static int view3d_context(const bContext *C, const char *member, bContextDataRes if (CTX_data_dir(member)) { CTX_data_dir_set(result, view3d_context_dir); } - else if (CTX_data_equals(member, "selected_objects") || CTX_data_equals(member, "selected_bases")) { - View3D *v3d = CTX_wm_view3d(C); - Scene *scene = CTX_data_scene(C); - const unsigned int lay = v3d ? v3d->lay : scene->lay; - Base *base; - const bool selected_objects = CTX_data_equals(member, "selected_objects"); - - for (base = scene->base.first; base; base = base->next) { - if ((base->flag & SELECT) && (base->lay & lay)) { - if ((base->object->restrictflag & OB_RESTRICT_VIEW) == 0) { - if (selected_objects) - CTX_data_id_list_add(result, &base->object->id); - else - CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base); - } - } - } - CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); - return 1; - } - else if (CTX_data_equals(member, "selected_editable_objects") || CTX_data_equals(member, "selected_editable_bases")) { - View3D *v3d = CTX_wm_view3d(C); - Scene *scene = CTX_data_scene(C); - const unsigned int lay = v3d ? v3d->lay : scene->lay; - Base *base; - const bool selected_editable_objects = CTX_data_equals(member, "selected_editable_objects"); - - for (base = scene->base.first; base; base = base->next) { - if ((base->flag & SELECT) && (base->lay & lay)) { - if ((base->object->restrictflag & OB_RESTRICT_VIEW) == 0) { - if (0 == BKE_object_is_libdata(base->object)) { - if (selected_editable_objects) - CTX_data_id_list_add(result, &base->object->id); - else - CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base); - } - } - } - } - CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); - return 1; - } - else if (CTX_data_equals(member, "visible_objects") || CTX_data_equals(member, "visible_bases")) { - View3D *v3d = CTX_wm_view3d(C); - Scene *scene = CTX_data_scene(C); - const unsigned int lay = v3d ? v3d->lay : scene->lay; - Base *base; - const bool visible_objects = CTX_data_equals(member, "visible_objects"); - - for (base = scene->base.first; base; base = base->next) { - if (base->lay & lay) { - if ((base->object->restrictflag & OB_RESTRICT_VIEW) == 0) { - if (visible_objects) - CTX_data_id_list_add(result, &base->object->id); - else - CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base); - } - } - } - CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); - return 1; - } - else if (CTX_data_equals(member, "selectable_objects") || CTX_data_equals(member, "selectable_bases")) { - View3D *v3d = CTX_wm_view3d(C); - Scene *scene = CTX_data_scene(C); - const unsigned int lay = v3d ? v3d->lay : scene->lay; - Base *base; - const bool selectable_objects = CTX_data_equals(member, "selectable_objects"); - - for (base = scene->base.first; base; base = base->next) { - if (base->lay & lay) { - if ((base->object->restrictflag & OB_RESTRICT_VIEW) == 0 && (base->object->restrictflag & OB_RESTRICT_SELECT) == 0) { - if (selectable_objects) - CTX_data_id_list_add(result, &base->object->id); - else - CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base); - } - } - } - CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); - return 1; - } else if (CTX_data_equals(member, "active_base")) { - View3D *v3d = CTX_wm_view3d(C); Scene *scene = CTX_data_scene(C); - const unsigned int lay = v3d ? v3d->lay : scene->lay; - if (scene->basact && (scene->basact->lay & lay)) { - Object *ob = scene->basact->object; + SceneLayer *sl = CTX_data_scene_layer(C); + if (sl->basact) { + Object *ob = sl->basact->object; /* if hidden but in edit mode, we still display, can happen with animation */ - if ((ob->restrictflag & OB_RESTRICT_VIEW) == 0 || (ob->mode & OB_MODE_EDIT)) - CTX_data_pointer_set(result, &scene->id, &RNA_ObjectBase, scene->basact); + if ((sl->basact->flag & BASE_VISIBLED) != 0 || (ob->mode & OB_MODE_EDIT)) { + CTX_data_pointer_set(result, &scene->id, &RNA_ObjectBase, sl->basact); + } } return 1; } else if (CTX_data_equals(member, "active_object")) { - View3D *v3d = CTX_wm_view3d(C); - Scene *scene = CTX_data_scene(C); - const unsigned int lay = v3d ? v3d->lay : scene->lay; - if (scene->basact && (scene->basact->lay & lay)) { - Object *ob = scene->basact->object; - if ((ob->restrictflag & OB_RESTRICT_VIEW) == 0 || (ob->mode & OB_MODE_EDIT)) - CTX_data_id_pointer_set(result, &scene->basact->object->id); + SceneLayer *sl = CTX_data_scene_layer(C); + if (sl->basact) { + Object *ob = sl->basact->object; + /* if hidden but in edit mode, we still display, can happen with animation */ + if ((sl->basact->flag & BASE_VISIBLED) != 0 || (ob->mode & OB_MODE_EDIT) != 0) { + CTX_data_id_pointer_set(result, &ob->id); + } } return 1; diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index c374bd7ae6f..b0faffcab3b 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -1767,7 +1767,7 @@ static void draw_rotation_guide(RegionView3D *rv3d) /* ******************** non-meshes ***************** */ static void view3d_draw_non_mesh( -Scene *scene, Object *ob, Base *base, View3D *v3d, +Scene *scene, Object *ob, BaseLegacy *base, View3D *v3d, RegionView3D *rv3d, const bool is_boundingbox, const unsigned char color[4]) { glMatrixMode(GL_PROJECTION); @@ -1872,6 +1872,7 @@ static void view3d_draw_setup_view(const bContext *C, ARegion *ar) static void draw_all_objects(const bContext *C, ARegion *ar, const bool only_depth, const bool use_depth) { Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); View3D *v3d = CTX_wm_view3d(C); if (only_depth) @@ -1884,8 +1885,8 @@ static void draw_all_objects(const bContext *C, ARegion *ar, const bool only_dep v3d->zbuf = true; } - for (Base *base = scene->base.first; base; base = base->next) { - if (v3d->lay & base->lay) { + for (Base *base = sl->object_bases.first; base; base = base->next) { + if ((base->flag & BASE_VISIBLED) != 0) { /* dupli drawing */ if (base->object->transflag & OB_DUPLI) draw_dupli_objects(scene, ar, v3d, base); @@ -1968,6 +1969,7 @@ static void view3d_draw_non_meshes(const bContext *C, ARegion *ar) * we filter them based on the plates/layers */ Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); View3D *v3d = CTX_wm_view3d(C); RegionView3D *rv3d = ar->regiondata; @@ -1981,8 +1983,8 @@ static void view3d_draw_non_meshes(const bContext *C, ARegion *ar) * for now let's avoid writing again to zbuffer to prevent glitches */ - for (Base *base = scene->base.first; base; base = base->next) { - if (v3d->lay & base->lay) { + for (Base *base = sl->object_bases.first; base; base = base->next) { + if ((base->flag & BASE_VISIBLED) != 0) { Object *ob = base->object; unsigned char ob_wire_col[4]; diff --git a/source/blender/editors/space_view3d/view3d_draw_legacy.c b/source/blender/editors/space_view3d/view3d_draw_legacy.c index b3f1804398b..e75e15c02c5 100644 --- a/source/blender/editors/space_view3d/view3d_draw_legacy.c +++ b/source/blender/editors/space_view3d/view3d_draw_legacy.c @@ -60,6 +60,7 @@ #include "BKE_DerivedMesh.h" #include "BKE_image.h" #include "BKE_key.h" +#include "BKE_layer.h" #include "BKE_main.h" #include "BKE_object.h" #include "BKE_global.h" @@ -415,7 +416,7 @@ static void draw_selected_name(Scene *scene, Object *ob, rcti *rect) static void backdrawview3d(Scene *scene, wmWindow *win, ARegion *ar, View3D *v3d) { RegionView3D *rv3d = ar->regiondata; - struct Base *base = scene->basact; + struct BaseLegacy *base = scene->basact; int multisample_enabled; BLI_assert(ar->regiontype == RGN_TYPE_WINDOW); @@ -1031,15 +1032,15 @@ static void view3d_draw_bgpic_test(Scene *scene, ARegion *ar, View3D *v3d, typedef struct View3DAfter { struct View3DAfter *next, *prev; - struct Base *base; + struct BaseLegacy *base; short dflag; } View3DAfter; /* temp storage of Objects that need to be drawn as last */ -void ED_view3d_after_add(ListBase *lb, Base *base, const short dflag) +void ED_view3d_after_add(ListBase *lb, BaseLegacy *base, const short dflag) { View3DAfter *v3da = MEM_callocN(sizeof(View3DAfter), "View 3d after"); - BLI_assert((base->flag & OB_FROMDUPLI) == 0); + BLI_assert((base->flag_legacy & OB_FROMDUPLI) == 0); BLI_addtail(lb, v3da); v3da->base = base; v3da->dflag = dflag; @@ -1133,13 +1134,13 @@ static DupliObject *dupli_step(DupliObject *dob) } static void draw_dupli_objects_color( - Scene *scene, ARegion *ar, View3D *v3d, Base *base, + Scene *scene, ARegion *ar, View3D *v3d, BaseLegacy *base, const short dflag, const int color) { RegionView3D *rv3d = ar->regiondata; ListBase *lb; LodLevel *savedlod; - Base tbase = {NULL}; + BaseLegacy tbase = {NULL}; BoundBox bb, *bb_tmp; /* use a copy because draw_object, calls clear_mesh_caches */ GLuint displist = 0; unsigned char color_rgb[3]; @@ -1160,7 +1161,7 @@ static void draw_dupli_objects_color( UI_GetThemeColorBlend3ubv(color, TH_BACK, 0.5f, color_rgb); } - tbase.flag = OB_FROMDUPLI | base->flag; + tbase.flag_legacy = OB_FROMDUPLI | base->flag_legacy; lb = object_duplilist(G.main->eval_ctx, scene, base->object); // BLI_listbase_sort(lb, dupli_ob_sort); /* might be nice to have if we have a dupli list with mixed objects. */ @@ -1293,12 +1294,12 @@ static void draw_dupli_objects_color( glDeleteLists(displist, 1); } -void draw_dupli_objects(Scene *scene, ARegion *ar, View3D *v3d, Base *base) +void draw_dupli_objects(Scene *scene, ARegion *ar, View3D *v3d, BaseLegacy *base) { /* define the color here so draw_dupli_objects_color can be called * from the set loop */ - int color = (base->flag & SELECT) ? TH_SELECT : TH_WIRE; + int color = (base->flag_legacy & SELECT) ? TH_SELECT : TH_WIRE; /* debug */ if (base->object->dup_group && base->object->dup_group->id.us < 1) color = TH_REDALERT; @@ -1445,15 +1446,16 @@ void ED_view3d_draw_depth_gpencil(Scene *scene, ARegion *ar, View3D *v3d) void ED_view3d_draw_depth(Scene *scene, ARegion *ar, View3D *v3d, bool alphaoverride) { RegionView3D *rv3d = ar->regiondata; - Base *base; + BaseLegacy *base; short zbuf = v3d->zbuf; short flag = v3d->flag; float glalphaclip = U.glalphaclip; int obcenter_dia = U.obcenter_dia; + TODO_LAYER_CONTEXT; /* we should pass context, really */ + SceneLayer *sl = BLI_findlink(&scene->render_layers, scene->active_layer); /* no need for color when drawing depth buffer */ const short dflag_depth = DRAW_CONSTCOLOR; /* temp set drawtype to solid */ - /* Setting these temporarily is not nice */ v3d->flag &= ~V3D_SELECT_OUTLINE; U.glalphaclip = alphaoverride ? 0.5f : glalphaclip; /* not that nice but means we wont zoom into billboards */ @@ -1492,8 +1494,8 @@ void ED_view3d_draw_depth(Scene *scene, ARegion *ar, View3D *v3d, bool alphaover } } - for (base = scene->base.first; base; base = base->next) { - if (v3d->lay & base->lay) { + for (base = sl->object_bases.first; base; base = base->next) { + if ((base->flag & BASE_VISIBLED) != 0) { /* dupli drawing */ if (base->object->transflag & OB_DUPLI) { draw_dupli_objects_color(scene, ar, v3d, base, dflag_depth, TH_UNDEFINED); @@ -1604,7 +1606,7 @@ static void gpu_update_lamps_shadows_world(Scene *scene, View3D *v3d) { ListBase shadows; Scene *sce_iter; - Base *base; + BaseLegacy *base; World *world = scene->world; SceneRenderLayer *srl = v3d->scenelock ? BLI_findlink(&scene->r.layers, scene->r.actlay) : NULL; @@ -1738,8 +1740,9 @@ static void view3d_draw_objects( const char **grid_unit, const bool do_bgpic, const bool draw_offscreen, GPUFX *fx) { + SceneLayer *sl = CTX_data_scene_layer(C); RegionView3D *rv3d = ar->regiondata; - Base *base; + BaseLegacy *base; const bool do_camera_frame = !draw_offscreen; const bool draw_grids = !draw_offscreen && (v3d->flag2 & V3D_RENDER_OVERRIDE) == 0; const bool draw_floor = (rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO); @@ -1811,8 +1814,8 @@ static void view3d_draw_objects( } if (draw_offscreen) { - for (base = scene->base.first; base; base = base->next) { - if (v3d->lay & base->lay) { + for (base = sl->object_bases.first; base; base = base->next) { + if ((base->flag & BASE_VISIBLED) != 0) { /* dupli drawing */ if (base->object->transflag & OB_DUPLI) draw_dupli_objects(scene, ar, v3d, base); @@ -1825,16 +1828,16 @@ static void view3d_draw_objects( unsigned int lay_used = 0; /* then draw not selected and the duplis, but skip editmode object */ - for (base = scene->base.first; base; base = base->next) { + for (base = sl->object_bases.first; base; base = base->next) { lay_used |= base->lay; - if (v3d->lay & base->lay) { + if ((base->flag & BASE_VISIBLED) != 0) { /* dupli drawing */ if (base->object->transflag & OB_DUPLI) { draw_dupli_objects(scene, ar, v3d, base); } - if ((base->flag & SELECT) == 0) { + if ((base->flag & BASE_SELECTED) == 0) { if (base->object != scene->obedit) draw_object(scene, ar, v3d, base, 0); } @@ -1845,9 +1848,9 @@ static void view3d_draw_objects( v3d->lay_used = lay_used & ((1 << 20) - 1); /* draw selected and editmode */ - for (base = scene->base.first; base; base = base->next) { - if (v3d->lay & base->lay) { - if (base->object == scene->obedit || (base->flag & SELECT)) { + for (base = sl->object_bases.first; base; base = base->next) { + if ((base->flag & BASE_VISIBLED) != 0) { + if (base->object == scene->obedit || (base->flag & BASE_SELECTED)) { draw_object(scene, ar, v3d, base, 0); } } @@ -2540,7 +2543,7 @@ static void view3d_stereo3d_setup_offscreen(Scene *scene, View3D *v3d, ARegion * static void update_lods(Scene *scene, float camera_pos[3]) { Scene *sce_iter; - Base *base; + BaseLegacy *base; for (SETLOOPER(scene, sce_iter, base)) { Object *ob = base->object; diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 2b53eb71d99..902be0e839c 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -670,7 +670,7 @@ static bool view3d_orbit_calc_center(bContext *C, float r_dyn_ofs[3]) else if (ob_act == NULL || ob_act->mode == OB_MODE_OBJECT) { /* object mode use boundbox centers */ View3D *v3d = CTX_wm_view3d(C); - Base *base; + BaseLegacy *base; unsigned int tot = 0; float select_center[3]; @@ -2940,7 +2940,7 @@ static int view3d_all_exec(bContext *C, wmOperator *op) /* was view3d_home() in ARegion *ar = CTX_wm_region(C); View3D *v3d = CTX_wm_view3d(C); Scene *scene = CTX_data_scene(C); - Base *base; + BaseLegacy *base; float *curs; const bool use_all_regions = RNA_boolean_get(op->ptr, "use_all_regions"); const bool skip_camera = (ED_view3d_camera_lock_check(v3d, ar->regiondata) || @@ -3045,7 +3045,7 @@ static int viewselected_exec(bContext *C, wmOperator *op) if (ob && (ob->mode & OB_MODE_WEIGHT_PAINT)) { /* hard-coded exception, we look for the one selected armature */ /* this is weak code this way, we should make a generic active/selection callback interface once... */ - Base *base; + BaseLegacy *base; for (base = scene->base.first; base; base = base->next) { if (TESTBASELIB(v3d, base)) { if (base->object->type == OB_ARMATURE) @@ -3091,7 +3091,7 @@ static int viewselected_exec(bContext *C, wmOperator *op) ok_dist = 0; /* don't zoom */ } else { - Base *base; + BaseLegacy *base; for (base = FIRSTBASE; base; base = base->next) { if (TESTBASE(v3d, base)) { @@ -3540,6 +3540,7 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op) View3D *v3d = CTX_wm_view3d(C); RegionView3D *rv3d = CTX_wm_region_view3d(C); Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); int gesture_mode; const int smooth_viewtx = WM_operator_smooth_viewtx_get(op); diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c index 67e258669d6..cdb9900ee4d 100644 --- a/source/blender/editors/space_view3d/view3d_header.c +++ b/source/blender/editors/space_view3d/view3d_header.c @@ -373,11 +373,6 @@ void uiTemplateHeader3D(uiLayout *layout, struct bContext *C) } if (obedit == NULL && v3d->localvd == NULL) { - unsigned int ob_lay = ob ? ob->lay : 0; - - /* Layers */ - uiTemplateLayers(layout, v3d->scenelock ? &sceneptr : &v3dptr, "layers", &v3dptr, "layers_used", ob_lay); - /* Scene lock */ uiItemR(layout, &v3dptr, "lock_camera_and_layers", UI_ITEM_R_ICON_ONLY, "", ICON_NONE); } diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index 504a8383a41..bed47354d89 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -142,19 +142,19 @@ void draw_motion_paths_cleanup(View3D *v3d); /* drawobject.c */ -void draw_object(Scene *scene, struct ARegion *ar, View3D *v3d, Base *base, const short dflag); +void draw_object(Scene *scene, struct ARegion *ar, View3D *v3d, BaseLegacy *base, const short dflag); void draw_mesh_object_outline(View3D *v3d, Object *ob, struct DerivedMesh *dm); bool draw_glsl_material(Scene *scene, struct Object *ob, View3D *v3d, const char dt); void draw_object_instance(Scene *scene, View3D *v3d, RegionView3D *rv3d, struct Object *ob, const char dt, int outline); void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, struct Object *ob); -void draw_object_wire_color(Scene *scene, Base *base, unsigned char r_ob_wire_col[4]); +void draw_object_wire_color(Scene *scene, BaseLegacy *base, unsigned char r_ob_wire_col[4]); void drawaxes(const float viewmat_local[4][4], float size, char drawtype, const unsigned char color[4]); -void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base, +void drawlamp(View3D *v3d, RegionView3D *rv3d, BaseLegacy *base, const char dt, const short dflag, const unsigned char ob_wire_col[4], const bool is_obact); -void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, +void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, BaseLegacy *base, const short dflag, const unsigned char ob_wire_col[4]); void drawspeaker(const unsigned char ob_wire_col[3]); void draw_bounding_volume(struct Object *ob, char type); @@ -179,7 +179,7 @@ enum { int view3d_effective_drawtype(const struct View3D *v3d); /* drawarmature.c */ -bool draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base, +bool draw_armature(Scene *scene, View3D *v3d, ARegion *ar, BaseLegacy *base, const short dt, const short dflag, const unsigned char ob_wire_col[4], const bool is_outline); @@ -210,7 +210,7 @@ void view3d_main_region_draw(const struct bContext *C, struct ARegion *ar); void view3d_main_region_draw_legacy(const struct bContext *C, struct ARegion *ar); void ED_view3d_draw_depth(Scene *scene, struct ARegion *ar, View3D *v3d, bool alphaoverride); void ED_view3d_draw_depth_gpencil(Scene *scene, ARegion *ar, View3D *v3d); -void ED_view3d_after_add(ListBase *lb, Base *base, const short dflag); +void ED_view3d_after_add(ListBase *lb, BaseLegacy *base, const short dflag); void circ(float x, float y, float rad); void view3d_update_depths_rect(struct ARegion *ar, struct ViewDepths *d, struct rcti *rect); @@ -334,7 +334,7 @@ void VP_legacy_drawfloor(Scene *scene, View3D *v3d, const char **grid_unit, bool void VP_legacy_view3d_main_region_setup_view(Scene *scene, View3D *v3d, ARegion *ar, float viewmat[4][4], float winmat[4][4]); bool VP_legacy_view3d_stereo3d_active(const struct bContext *C, Scene *scene, View3D *v3d, RegionView3D *rv3d); void VP_legacy_view3d_stereo3d_setup(Scene *scene, View3D *v3d, ARegion *ar); -void draw_dupli_objects(Scene *scene, ARegion *ar, View3D *v3d, Base *base); +void draw_dupli_objects(Scene *scene, ARegion *ar, View3D *v3d, BaseLegacy *base); bool VP_legacy_use_depth(Scene *scene, View3D *v3d); void VP_drawviewborder(Scene *scene, ARegion *ar, View3D *v3d); void VP_drawrenderborder(ARegion *ar, View3D *v3d); diff --git a/source/blender/editors/space_view3d/view3d_project.c b/source/blender/editors/space_view3d/view3d_project.c index 65a6dee2f6c..32d3e01a6b5 100644 --- a/source/blender/editors/space_view3d/view3d_project.c +++ b/source/blender/editors/space_view3d/view3d_project.c @@ -101,7 +101,7 @@ void ED_view3d_project_float_v3_m4(const ARegion *ar, const float vec[3], float /* Clipping Projection Functions * ***************************** */ -eV3DProjStatus ED_view3d_project_base(const struct ARegion *ar, struct Base *base) +eV3DProjStatus ED_view3d_project_base(const struct ARegion *ar, struct BaseLegacy *base) { eV3DProjStatus ret = ED_view3d_project_short_global(ar, base->object->obmat[3], &base->sx, V3D_PROJ_TEST_CLIP_DEFAULT); diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index 3239d07553f..e7c8cd340c8 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -64,11 +64,13 @@ #include "BKE_context.h" #include "BKE_curve.h" #include "BKE_depsgraph.h" +#include "BKE_layer.h" #include "BKE_mball.h" #include "BKE_mesh.h" #include "BKE_object.h" #include "BKE_paint.h" #include "BKE_editmesh.h" +#include "BKE_scene.h" #include "BKE_tracking.h" #include "BKE_utildefines.h" @@ -401,7 +403,7 @@ static void do_lasso_select_pose(ViewContext *vc, Object *ob, const int mcords[] static void object_deselect_all_visible(Scene *scene, View3D *v3d) { - Base *base; + BaseLegacy *base; for (base = scene->base.first; base; base = base->next) { if (BASE_SELECTABLE(v3d, base)) { @@ -413,7 +415,7 @@ static void object_deselect_all_visible(Scene *scene, View3D *v3d) static void do_lasso_select_objects(ViewContext *vc, const int mcords[][2], const short moves, const bool extend, const bool select) { - Base *base; + BaseLegacy *base; if (extend == false && select) object_deselect_all_visible(vc->scene, vc->v3d); @@ -424,7 +426,6 @@ static void do_lasso_select_objects(ViewContext *vc, const int mcords[][2], cons if (BLI_lasso_is_point_inside(mcords, moves, base->sx, base->sy, IS_CLIPPED)) { ED_base_object_select(base, select ? BA_SELECT : BA_DESELECT); - base->object->flag = base->flag; } } if (vc->obact == base->object && (base->object->mode & OB_MODE_POSE)) { @@ -1017,8 +1018,8 @@ static int object_select_menu_exec(bContext *C, wmOperator *op) if (!toggle) { CTX_DATA_BEGIN (C, Base *, base, selectable_bases) { - if (base->flag & SELECT) { - ED_base_object_select(base, BA_DESELECT); + if ((base->flag & BASE_SELECTED) != 0) { + ED_object_base_select(base, BA_DESELECT); changed = true; } } @@ -1029,8 +1030,8 @@ static int object_select_menu_exec(bContext *C, wmOperator *op) { /* this is a bit dodjy, there should only be ONE object with this name, but library objects can mess this up */ if (STREQ(name, base->object->id.name + 2)) { - ED_base_object_activate(C, base); - ED_base_object_select(base, BA_SELECT); + ED_object_base_activate(C, base); + ED_object_base_select(base, BA_SELECT); changed = true; } } @@ -1074,12 +1075,12 @@ void VIEW3D_OT_select_menu(wmOperatorType *ot) RNA_def_boolean(ot->srna, "toggle", 0, "Toggle", "Toggle selection instead of deselecting everything first"); } -static void deselectall_except(Scene *scene, Base *b) /* deselect all except b */ +static void deselectall_except(Scene *scene, BaseLegacy *b) /* deselect all except b */ { - Base *base; + BaseLegacy *base; for (base = FIRSTBASE; base; base = base->next) { - if (base->flag & SELECT) { + if (base->flag_legacy & SELECT) { if (b != base) { ED_base_object_select(base, BA_DESELECT); } @@ -1087,12 +1088,16 @@ static void deselectall_except(Scene *scene, Base *b) /* deselect all except b } } -static Base *object_mouse_select_menu(bContext *C, ViewContext *vc, unsigned int *buffer, int hits, const int mval[2], short toggle) +static BaseLegacy *object_mouse_select_menu(bContext *C, ViewContext *vc, unsigned int *buffer, int hits, const int mval[2], short toggle) { short baseCount = 0; bool ok; LinkNode *linklist = NULL; - + + /* handle base->selcol */ + TODO_LAYER_BASE; +#if 0 + CTX_DATA_BEGIN (C, Base *, base, selectable_bases) { ok = false; @@ -1164,6 +1169,19 @@ static Base *object_mouse_select_menu(bContext *C, ViewContext *vc, unsigned int BLI_linklist_free(linklist, NULL); return NULL; } +#else + + (void)C; + (void)vc, + (void)buffer; + (void)hits; + (void)mval; + (void)toggle; + (void)baseCount; + (void)ok; + (void)linklist; + return NULL; +#endif } static bool selectbuffer_has_bones(const unsigned int *buffer, const unsigned int hits) @@ -1275,12 +1293,12 @@ static short mixed_bones_object_selectbuffer( } /* returns basact */ -static Base *mouse_select_eval_buffer(ViewContext *vc, unsigned int *buffer, int hits, - Base *startbase, bool has_bones, bool do_nearest) +static BaseLegacy *mouse_select_eval_buffer(ViewContext *vc, unsigned int *buffer, int hits, + BaseLegacy *startbase, bool has_bones, bool do_nearest) { Scene *scene = vc->scene; View3D *v3d = vc->v3d; - Base *base, *basact = NULL; + BaseLegacy *base, *basact = NULL; int a; if (do_nearest) { @@ -1299,7 +1317,7 @@ static Base *mouse_select_eval_buffer(ViewContext *vc, unsigned int *buffer, int } else { /* only exclude active object when it is selected... */ - if (BASACT && (BASACT->flag & SELECT) && hits > 1) notcol = BASACT->selcol; + if (BASACT && (BASACT->flag_legacy & SELECT) && hits > 1) notcol = BASACT->selcol; for (a = 0; a < hits; a++) { if (min > buffer[4 * a + 1] && notcol != (buffer[4 * a + 3] & 0xFFFF)) { @@ -1358,10 +1376,10 @@ static Base *mouse_select_eval_buffer(ViewContext *vc, unsigned int *buffer, int } /* mval comes from event->mval, only use within region handlers */ -Base *ED_view3d_give_base_under_cursor(bContext *C, const int mval[2]) +BaseLegacy *ED_view3d_give_base_under_cursor(bContext *C, const int mval[2]) { ViewContext vc; - Base *basact = NULL; + BaseLegacy *basact = NULL; unsigned int buffer[MAXPICKBUF]; int hits; bool do_nearest; @@ -1408,7 +1426,7 @@ static bool ed_object_select_pick( ARegion *ar = CTX_wm_region(C); View3D *v3d = CTX_wm_view3d(C); Scene *scene = CTX_data_scene(C); - Base *base, *startbase = NULL, *basact = NULL, *oldbasact = NULL; + BaseLegacy *base, *startbase = NULL, *basact = NULL, *oldbasact = NULL; bool is_obedit; float dist = ED_view3d_select_dist_px() * 1.3333f; bool retval = false; @@ -1520,8 +1538,8 @@ static bool ed_object_select_pick( changed = true; } - basact->flag |= SELECT; - basact->object->flag = basact->flag; + basact->flag_legacy |= SELECT; + basact->object->flag = basact->flag_legacy; retval = true; @@ -1544,8 +1562,8 @@ static bool ed_object_select_pick( /* we make the armature selected: * not-selected active object in posemode won't work well for tools */ - basact->flag |= SELECT; - basact->object->flag = basact->flag; + basact->flag_legacy |= SELECT; + basact->object->flag = basact->flag_legacy; retval = true; WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, basact->object); @@ -1586,7 +1604,7 @@ static bool ed_object_select_pick( ED_base_object_select(basact, BA_DESELECT); } else if (toggle) { - if (basact->flag & SELECT) { + if (basact->flag_legacy & SELECT) { if (basact == oldbasact) { ED_base_object_select(basact, BA_DESELECT); } @@ -2051,7 +2069,7 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, b */ if (hits > 0) { /* no need to loop if there's no hit */ - Base *base; + BaseLegacy *base; col = vbuffer + 3; for (base = vc->scene->base.first; base && hits; base = base->next) { @@ -2793,9 +2811,9 @@ static bool object_circle_select(ViewContext *vc, const bool select, const int m const int select_flag = select ? SELECT : 0; - Base *base; + BaseLegacy *base; for (base = FIRSTBASE; base; base = base->next) { - if (BASE_SELECTABLE(vc->v3d, base) && ((base->flag & SELECT) != select_flag)) { + if (BASE_SELECTABLE(vc->v3d, base) && ((base->flag_legacy & SELECT) != select_flag)) { float screen_co[2]; if (ED_view3d_project_float_global(vc->ar, base->object->obmat[3], screen_co, V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK) diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index 8582952d1a0..137e8162aed 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -1107,7 +1107,7 @@ static void view3d_select_loop(ViewContext *vc, Scene *scene, View3D *v3d, ARegi } } else { - Base *base; + BaseLegacy *base; v3d->xray = true; /* otherwise it postpones drawing */ for (base = scene->base.first; base; base = base->next) { @@ -1128,9 +1128,9 @@ static void view3d_select_loop(ViewContext *vc, Scene *scene, View3D *v3d, ARegi if ((base->object->transflag & OB_DUPLI)) { ListBase *lb; DupliObject *dob; - Base tbase; + BaseLegacy tbase; - tbase.flag = OB_FROMDUPLI; + tbase.flag_legacy = OB_FROMDUPLI; lb = object_duplilist(G.main->eval_ctx, scene, base->object); for (dob = lb->first; dob; dob = dob->next) { @@ -1319,7 +1319,7 @@ static bool view3d_localview_init( ReportList *reports) { View3D *v3d = sa->spacedata.first; - Base *base; + BaseLegacy *base; float min[3], max[3], box[3], mid[3]; float size = 0.0f; unsigned int locallay; @@ -1422,7 +1422,7 @@ static bool view3d_localview_init( if (base->lay & locallay) { base->lay -= locallay; if (base->lay == 0) base->lay = v3d->layact; - if (base->object != scene->obedit) base->flag |= SELECT; + if (base->object != scene->obedit) base->flag_legacy |= SELECT; base->object->lay = base->lay; } } @@ -1493,7 +1493,7 @@ static bool view3d_localview_exit( Main *bmain, Scene *scene, ScrArea *sa, const int smooth_viewtx) { View3D *v3d = sa->spacedata.first; - struct Base *base; + struct BaseLegacy *base; unsigned int locallay; if (v3d->localvd) { @@ -1510,7 +1510,7 @@ static bool view3d_localview_exit( base->lay -= locallay; if (base->lay == 0) base->lay = v3d->layact; if (base->object != scene->obedit) { - base->flag |= SELECT; + base->flag_legacy |= SELECT; base->object->flag |= SELECT; } base->object->lay = base->lay; diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 3e355deef33..cb828914735 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -5353,7 +5353,7 @@ static void set_trans_object_base_flags(TransInfo *t) * if Base selected and has parent selected: * base->flag = BA_WAS_SEL */ - Base *base; + BaseLegacy *base; /* don't do it if we're not actually going to recalculate anything */ if (t->mode == TFM_DUMMY) @@ -5374,7 +5374,7 @@ static void set_trans_object_base_flags(TransInfo *t) } for (base = scene->base.first; base; base = base->next) { - base->flag &= ~BA_WAS_SEL; + base->flag_legacy &= ~BA_WAS_SEL; if (TESTBASELIB_BGMODE(v3d, scene, base)) { Object *ob = base->object; @@ -5383,7 +5383,7 @@ static void set_trans_object_base_flags(TransInfo *t) /* if parent selected, deselect */ while (parsel) { if (parsel->flag & SELECT) { - Base *parbase = BKE_scene_base_find(scene, parsel); + BaseLegacy *parbase = BKE_scene_base_find(scene, parsel); if (parbase) { /* in rare cases this can fail */ if (TESTBASELIB_BGMODE(v3d, scene, parbase)) { break; @@ -5398,11 +5398,11 @@ static void set_trans_object_base_flags(TransInfo *t) if ((t->around == V3D_AROUND_LOCAL_ORIGINS) && (t->mode == TFM_ROTATION || t->mode == TFM_TRACKBALL)) { - base->flag |= BA_TRANSFORM_CHILD; + base->flag_legacy |= BA_TRANSFORM_CHILD; } else { - base->flag &= ~SELECT; - base->flag |= BA_WAS_SEL; + base->flag_legacy &= ~SELECT; + base->flag_legacy |= BA_WAS_SEL; } } DAG_id_tag_update(&ob->id, OB_RECALC_OB); @@ -5413,9 +5413,9 @@ static void set_trans_object_base_flags(TransInfo *t) /* this because after doing updates, the object->recalc is cleared */ for (base = scene->base.first; base; base = base->next) { if (base->object->recalc & OB_RECALC_OB) - base->flag |= BA_HAS_RECALC_OB; + base->flag_legacy |= BA_HAS_RECALC_OB; if (base->object->recalc & OB_RECALC_DATA) - base->flag |= BA_HAS_RECALC_DATA; + base->flag_legacy |= BA_HAS_RECALC_DATA; } } @@ -5439,7 +5439,7 @@ static int count_proportional_objects(TransInfo *t) int total = 0; Scene *scene = t->scene; View3D *v3d = t->view; - Base *base; + BaseLegacy *base; /* rotations around local centers are allowed to propagate, so we take all objects */ if (!((t->around == V3D_AROUND_LOCAL_ORIGINS) && @@ -5491,9 +5491,9 @@ static int count_proportional_objects(TransInfo *t) /* this because after doing updates, the object->recalc is cleared */ for (base = scene->base.first; base; base = base->next) { if (base->object->recalc & OB_RECALC_OB) - base->flag |= BA_HAS_RECALC_OB; + base->flag_legacy |= BA_HAS_RECALC_OB; if (base->object->recalc & OB_RECALC_DATA) - base->flag |= BA_HAS_RECALC_DATA; + base->flag_legacy |= BA_HAS_RECALC_DATA; } return total; @@ -5502,13 +5502,13 @@ static int count_proportional_objects(TransInfo *t) static void clear_trans_object_base_flags(TransInfo *t) { Scene *sce = t->scene; - Base *base; + BaseLegacy *base; for (base = sce->base.first; base; base = base->next) { - if (base->flag & BA_WAS_SEL) - base->flag |= SELECT; + if (base->flag_legacy & BA_WAS_SEL) + base->flag_legacy |= SELECT; - base->flag &= ~(BA_WAS_SEL | BA_HAS_RECALC_OB | BA_HAS_RECALC_DATA | BA_TEMP_TAG | BA_TRANSFORM_CHILD | BA_TRANSFORM_PARENT); + base->flag_legacy &= ~(BA_WAS_SEL | BA_HAS_RECALC_OB | BA_HAS_RECALC_DATA | BA_TEMP_TAG | BA_TRANSFORM_CHILD | BA_TRANSFORM_PARENT); } } @@ -6426,7 +6426,7 @@ static void createTransObject(bContext *C, TransInfo *t) if (is_prop_edit) { View3D *v3d = t->view; - Base *base; + BaseLegacy *base; for (base = scene->base.first; base; base = base->next) { Object *ob = base->object; @@ -8040,7 +8040,7 @@ void createTransData(bContext *C, TransInfo *t) * lines below just check is also visible */ Object *ob_armature = modifiers_isDeformedByArmature(ob); if (ob_armature && ob_armature->mode & OB_MODE_POSE) { - Base *base_arm = BKE_scene_base_find(t->scene, ob_armature); + BaseLegacy *base_arm = BKE_scene_base_find(t->scene, ob_armature); if (base_arm) { View3D *v3d = t->view; if (BASE_VISIBLE(v3d, base_arm)) { diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index a9eb4c705b7..7351214f4ee 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -708,7 +708,7 @@ static void recalcData_spaceclip(TransInfo *t) /* helper for recalcData() - for object transforms, typically in the 3D view */ static void recalcData_objects(TransInfo *t) { - Base *base = t->scene->basact; + BaseLegacy *base = t->scene->basact; if (t->obedit) { if (ELEM(t->obedit->type, OB_CURVE, OB_SURF)) { diff --git a/source/blender/editors/transform/transform_manipulator.c b/source/blender/editors/transform/transform_manipulator.c index e1abf34b0f4..b25e8ef5241 100644 --- a/source/blender/editors/transform/transform_manipulator.c +++ b/source/blender/editors/transform/transform_manipulator.c @@ -274,7 +274,7 @@ static int calc_manipulator_stats(const bContext *C) Object *obedit = CTX_data_edit_object(C); View3D *v3d = sa->spacedata.first; RegionView3D *rv3d = ar->regiondata; - Base *base; + BaseLegacy *base; Object *ob = OBACT; bGPdata *gpd = CTX_data_gpencil_data(C); const bool is_gp_edit = ((gpd) && (gpd->flag & GP_DATA_STROKE_EDITMODE)); diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c index 058af768885..62360c8972a 100644 --- a/source/blender/editors/transform/transform_orientations.c +++ b/source/blender/editors/transform/transform_orientations.c @@ -588,7 +588,7 @@ int getTransformOrientation_ex(const bContext *C, float normal[3], float plane[3 { Scene *scene = CTX_data_scene(C); Object *obedit = CTX_data_edit_object(C); - Base *base; + BaseLegacy *base; Object *ob = OBACT; int result = ORIENTATION_NONE; const bool activeOnly = (around == V3D_AROUND_ACTIVE); diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index 81f7af5a2ce..8ffcc41258a 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -532,7 +532,7 @@ static void initSnappingMode(TransInfo *t) ToolSettings *ts = t->settings; Object *obedit = t->obedit; Scene *scene = t->scene; - Base *base_act = scene->basact; + BaseLegacy *base_act = scene->basact; if (t->spacetype == SPACE_NODE) { /* force project off when not supported */ diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c index 85209b07677..90c8b236397 100644 --- a/source/blender/editors/transform/transform_snap_object.c +++ b/source/blender/editors/transform/transform_snap_object.c @@ -1801,7 +1801,7 @@ static bool snapObjectsRay( * * To solve that problem, we do it first as an exception. * */ - Base *base_act = sctx->scene->basact; + BaseLegacy *base_act = sctx->scene->basact; if (base_act && base_act->object && base_act->object->mode & OB_MODE_PARTICLE_EDIT) { Object *ob = base_act->object; @@ -1822,11 +1822,11 @@ static bool snapObjectsRay( ignore_object_active = true; break; } - for (Base *base = sctx->scene->base.first; base != NULL; base = base->next) { + for (BaseLegacy *base = sctx->scene->base.first; base != NULL; base = base->next) { if ((BASE_VISIBLE_BGMODE(sctx->v3d_data.v3d, sctx->scene, base)) && - (base->flag & (BA_HAS_RECALC_OB | BA_HAS_RECALC_DATA)) == 0 && + (base->flag_legacy & (BA_HAS_RECALC_OB | BA_HAS_RECALC_DATA)) == 0 && - !((ignore_object_selected && (base->flag & (SELECT | BA_WAS_SEL))) || + !((ignore_object_selected && (base->flag_legacy & (SELECT | BA_WAS_SEL))) || (ignore_object_active && base == base_act))) { Object *ob = base->object; diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c index 5c5e84ee5f0..93cf88e62ca 100644 --- a/source/blender/editors/uvedit/uvedit_draw.c +++ b/source/blender/editors/uvedit/uvedit_draw.c @@ -470,14 +470,14 @@ static void draw_uvs_other_mesh(Object *ob, const Image *curimage, const bool ne static void draw_uvs_other(Scene *scene, Object *obedit, const Image *curimage, const bool new_shading_nodes, const int other_uv_filter) { - Base *base; + BaseLegacy *base; UI_ThemeColor(TH_UV_OTHERS); for (base = scene->base.first; base; base = base->next) { Object *ob = base->object; - if (!(base->flag & SELECT)) continue; + if (!(base->flag_legacy & SELECT)) continue; if (!(base->lay & scene->lay)) continue; if (ob->restrictflag & OB_RESTRICT_VIEW) continue; diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp index f63cf771120..0e03ab84a47 100644 --- a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp +++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp @@ -127,7 +127,7 @@ BlenderStrokeRenderer::BlenderStrokeRenderer(Render *re, int render_count) : Str BKE_scene_set_background(freestyle_bmain, freestyle_scene); // Camera - Object *object_camera = BKE_object_add(freestyle_bmain, freestyle_scene, OB_CAMERA, NULL); + Object *object_camera = BKE_object_add(freestyle_bmain, freestyle_scene, (SceneLayer *)freestyle_scene->render_layers.first, OB_CAMERA, NULL); DAG_relations_tag_update(freestyle_bmain); Camera *camera = (Camera *)object_camera->data; @@ -166,7 +166,7 @@ BlenderStrokeRenderer::~BlenderStrokeRenderer() // compositor has finished. // release objects and data blocks - for (Base *b = (Base *)freestyle_scene->base.first; b; b = b->next) { + for (BaseLegacy *b = (BaseLegacy *)freestyle_scene->base.first; b; b = b->next) { Object *ob = b->object; void *data = ob->data; char *name = ob->id.name; @@ -674,7 +674,7 @@ int BlenderStrokeRenderer::get_stroke_count() const void BlenderStrokeRenderer::GenerateStrokeMesh(StrokeGroup *group, bool hasTex) { #if 0 - Object *object_mesh = BKE_object_add(freestyle_bmain, freestyle_scene, OB_MESH); + Object *object_mesh = BKE_object_add(freestyle_bmain, freestyle_scene, (SceneLayer *)freestyle_scene->render_layers.first, OB_MESH); DAG_relations_tag_update(freestyle_bmain); #else Object *object_mesh = NewMesh(); @@ -922,7 +922,7 @@ void BlenderStrokeRenderer::GenerateStrokeMesh(StrokeGroup *group, bool hasTex) Object *BlenderStrokeRenderer::NewMesh() const { Object *ob; - Base *base; + BaseLegacy *base; char name[MAX_ID_NAME]; unsigned int mesh_id = get_stroke_mesh_id(); diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index bea9452f0d6..c2b3207dfa3 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -2159,7 +2159,7 @@ int GPU_scene_object_lights(Scene *scene, Object *ob, int lay, float viewmat[4][ int count = 0; - for (Base *base = scene->base.first; base; base = base->next) { + for (BaseLegacy *base = scene->base.first; base; base = base->next) { if (base->object->type != OB_LAMP) continue; diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index 28cf7bd1c76..9e08f629bcb 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -1016,7 +1016,7 @@ static void shade_one_light(GPUShadeInput *shi, GPUShadeResult *shr, GPULamp *la static void material_lights(GPUShadeInput *shi, GPUShadeResult *shr) { - Base *base; + BaseLegacy *base; Scene *sce_iter; for (SETLOOPER(shi->gpumat->scene, sce_iter, base)) { diff --git a/source/blender/makesdna/DNA_layer_types.h b/source/blender/makesdna/DNA_layer_types.h new file mode 100644 index 00000000000..6f6c6d7d145 --- /dev/null +++ b/source/blender/makesdna/DNA_layer_types.h @@ -0,0 +1,112 @@ +/* + * ***** 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 DNA_layer_types.h + * \ingroup DNA + */ + +#ifndef __DNA_LAYER_TYPES_H__ +#define __DNA_LAYER_TYPES_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "DNA_listBase.h" + +typedef struct Base { + struct Base *next, *prev; + short flag; + short refcount; + short sx, sy; + struct Object *object; + unsigned int selcol; + unsigned int lay; + int flag_legacy; + int pad; +} Base; + +typedef struct CollectionOverride { + struct CollectionOverride *next, *prev; + char name[64]; /* MAX_NAME */ + /* TODO proper data */ +} CollectionOverride; + +typedef struct LayerCollection { + struct LayerCollection *next, *prev; + struct SceneCollection *scene_collection; + short flag; + short pad[3]; + ListBase object_bases; /* (ObjectBase *)LinkData->data - synced with collection->objects and collection->filter_objects */ + ListBase overrides; + ListBase layer_collections; /* synced with collection->collections */ +} LayerCollection; + +typedef struct SceneLayer { + struct SceneLayer *next, *prev; + char name[64]; /* MAX_NAME */ + char engine[32]; /* render engine */ + short active_collection; + short flag; + short pad[2]; + ListBase object_bases; /* ObjectBase */ + struct Base *basact; + ListBase layer_collections; /* LayerCollection */ +} SceneLayer; + +typedef struct SceneCollection { + struct SceneCollection *next, *prev; + char name[64]; /* MAX_NAME */ + char filter[64]; /* MAX_NAME */ + int active_object_index; /* for UI */ + int pad; + ListBase objects; /* (Object *)LinkData->data */ + ListBase filter_objects; /* (Object *)LinkData->data */ + ListBase scene_collections; /* nested collections */ +} SceneCollection; + +/* Base->flag */ +enum { + BASE_SELECTED = (1 << 0), + BASE_VISIBLED = (1 << 1), + BASE_SELECTABLED = (1 << 2), + BASE_FROMDUPLI = (1 << 3), +}; + +/* LayerCollection->flag */ +enum { + COLLECTION_VISIBLE = (1 << 0), + COLLECTION_SELECTABLE = (1 << 1), + COLLECTION_FOLDED = (1 << 2), +}; + +/* SceneLayer->flag */ +enum { + SCENE_LAYER_RENDER = (1 << 0), +}; + +#ifdef __cplusplus +} +#endif + +#endif /* __DNA_LAYER_TYPES_H__ */ + diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index d24c7faa9f5..60aaa4ace20 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -223,7 +223,10 @@ typedef struct Object { float jump_speed; float fall_speed; unsigned char max_jumps; - char pad2[3]; + char pad2; + + /* Depsgraph */ + short base_flag; /* used by depsgraph, flushed from base */ /** Collision mask settings */ unsigned short col_group, col_mask; diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 8ee15ef21a3..ba5e50ec441 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -47,6 +47,7 @@ extern "C" { #include "DNA_ID.h" #include "DNA_freestyle_types.h" #include "DNA_gpu_types.h" +#include "DNA_layer_types.h" #include "DNA_userdef_types.h" struct CurveMapping; @@ -65,18 +66,13 @@ struct bGPdata; struct bGPDbrush; struct MovieClip; struct ColorSpace; +struct SceneCollection; /* ************************************************************* */ /* Scene Data */ /* Base - Wrapper for referencing Objects in a Scene */ -typedef struct Base { - struct Base *next, *prev; - unsigned int lay, selcol; - int flag; - short sx, sy; - struct Object *object; -} Base; +#define BaseLegacy Base /* ************************************************************* */ /* Output Format Data */ @@ -1628,7 +1624,7 @@ typedef struct Scene { struct Scene *set; ListBase base; - struct Base *basact; /* active base */ + struct BaseLegacy *basact; /* active base */ struct Object *obedit; /* name replaces old G.obedit */ float cursor[3]; /* 3d cursor location */ @@ -1706,6 +1702,11 @@ typedef struct Scene { struct RigidBodyWorld *rigidbody_world; struct PreviewImage *preview; + + ListBase render_layers; + struct SceneCollection *collection; + int active_layer; + int pad4; } Scene; /* **************** RENDERDATA ********************* */ @@ -1912,16 +1913,16 @@ extern const char *RE_engine_id_CYCLES; /* depricate this! */ #define TESTBASE(v3d, base) ( \ - ((base)->flag & SELECT) && \ + ((base)->flag_legacy & SELECT) && \ ((base)->lay & v3d->lay) && \ (((base)->object->restrictflag & OB_RESTRICT_VIEW) == 0)) #define TESTBASELIB(v3d, base) ( \ - ((base)->flag & SELECT) && \ + ((base)->flag_legacy & SELECT) && \ ((base)->lay & v3d->lay) && \ ((base)->object->id.lib == NULL) && \ (((base)->object->restrictflag & OB_RESTRICT_VIEW) == 0)) #define TESTBASELIB_BGMODE(v3d, scene, base) ( \ - ((base)->flag & SELECT) && \ + ((base)->flag_legacy & SELECT) && \ ((base)->lay & (v3d ? v3d->lay : scene->lay)) && \ ((base)->object->id.lib == NULL) && \ (((base)->object->restrictflag & OB_RESTRICT_VIEW) == 0)) @@ -1930,7 +1931,7 @@ extern const char *RE_engine_id_CYCLES; ((base)->object->id.lib == NULL) && \ (((base)->object->restrictflag & OB_RESTRICT_VIEW) == 0)) #define BASE_SELECTABLE(v3d, base) ( \ - (base->lay & v3d->lay) && \ + (v3d != NULL) && \ (base->object->restrictflag & (OB_RESTRICT_SELECT | OB_RESTRICT_VIEW)) == 0) #define BASE_VISIBLE(v3d, base) ( \ (base->lay & v3d->lay) && \ @@ -1943,6 +1944,8 @@ extern const char *RE_engine_id_CYCLES; #define LASTBASE scene->base.last #define BASACT (scene->basact) #define OBACT (BASACT ? BASACT->object: NULL) +#define BASACT_NEW (sl->basact) +#define OBACT_NEW (BASACT_NEW ? BASACT_NEW->object: NULL) #define V3D_CAMERA_LOCAL(v3d) ((!(v3d)->scenelock && (v3d)->camera) ? (v3d)->camera : NULL) #define V3D_CAMERA_SCENE(scene, v3d) ((!(v3d)->scenelock && (v3d)->camera) ? (v3d)->camera : (scene)->camera) @@ -1958,7 +1961,7 @@ extern const char *RE_engine_id_CYCLES; #define TIME2FRA(a) ((((double) scene->r.frs_sec) * (double)(a)) / (double)scene->r.frs_sec_base) #define FPS (((double) scene->r.frs_sec) / (double)scene->r.frs_sec_base) -/* base->flag is in DNA_object_types.h */ +/* base->legacy_flag is in DNA_object_types.h */ /* toolsettings->snap_flag */ #define SCE_SNAP 1 diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 5e015544dc9..14eb93e7f23 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -181,7 +181,8 @@ typedef enum eSpaceButtons_Context { BCONTEXT_CONSTRAINT = 11, BCONTEXT_BONE_CONSTRAINT = 12, BCONTEXT_RENDER_LAYER = 13, - + BCONTEXT_COLLECTION = 14, + /* always as last... */ BCONTEXT_TOT } eSpaceButtons_Context; @@ -1343,6 +1344,20 @@ typedef enum eSpaceClip_GPencil_Source { SC_GPENCIL_SRC_TRACK = 1, } eSpaceClip_GPencil_Source; +/* Collection Manager ======================================= */ + +typedef struct SpaceCollections { + SpaceLink *next, *prev; + ListBase regionbase; /* storage of regions for inactive spaces */ + int spacetype; + int flag; /* eSpaceCollections_Flag */ +} SpaceCollections; + +/* SpaceClip->flag */ +typedef enum eSpaceCollections_Flag { + SC_COLLECTION_DATA_REFRESH = (1 << 0), /* recreate/update SpaceCollections layer data, needed for undo/read/write */ +} eSpaceCollections_Flag; + /* **************** SPACE DEFINES ********************* */ /* space types, moved from DNA_screen_types.h */ @@ -1372,8 +1387,9 @@ typedef enum eSpace_Type { SPACE_CONSOLE = 18, SPACE_USERPREF = 19, SPACE_CLIP = 20, - - SPACEICONMAX = SPACE_CLIP + SPACE_COLLECTIONS = 21, + + SPACEICONMAX = SPACE_COLLECTIONS } eSpace_Type; /* use for function args */ diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index 1dc6c7ab578..6cc24f74cee 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -390,7 +390,8 @@ typedef struct bTheme { ThemeSpace tuserpref; ThemeSpace tconsole; ThemeSpace tclip; - + ThemeSpace tcollections; + /* 20 sets of bone colors for this theme */ ThemeWireColor tarm[20]; /*ThemeWireColor tobj[20];*/ diff --git a/source/blender/makesdna/intern/makesdna.c b/source/blender/makesdna/intern/makesdna.c index 2cea8715a65..b6cf3d555fa 100644 --- a/source/blender/makesdna/intern/makesdna.c +++ b/source/blender/makesdna/intern/makesdna.c @@ -130,6 +130,7 @@ static const char *includefiles[] = { "DNA_freestyle_types.h", "DNA_linestyle_types.h", "DNA_cachefile_types.h", + "DNA_layer_types.h", /* see comment above before editing! */ /* empty string to indicate end of includefiles */ @@ -1342,4 +1343,5 @@ int main(int argc, char **argv) #include "DNA_freestyle_types.h" #include "DNA_linestyle_types.h" #include "DNA_cachefile_types.h" +#include "DNA_layer_types.h" /* end of list */ diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index 66e6f30feeb..9c45e34f211 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -317,6 +317,8 @@ extern StructRNA RNA_LaplacianSmoothModifier; extern StructRNA RNA_Lattice; extern StructRNA RNA_LatticeModifier; extern StructRNA RNA_LatticePoint; +extern StructRNA RNA_LayerCollection; +extern StructRNA RNA_LayerCollectionOverride; extern StructRNA RNA_Library; extern StructRNA RNA_LimitDistanceConstraint; extern StructRNA RNA_LimitLocationConstraint; @@ -504,6 +506,7 @@ extern StructRNA RNA_RigidBodyJointConstraint; extern StructRNA RNA_SPHFluidSettings; extern StructRNA RNA_Scene; extern StructRNA RNA_SceneGameData; +extern StructRNA RNA_SceneLayer; extern StructRNA RNA_SceneRenderLayer; extern StructRNA RNA_SceneSequence; extern StructRNA RNA_SceneObjects; @@ -573,6 +576,7 @@ extern StructRNA RNA_SpaceFileBrowser; extern StructRNA RNA_SpaceGraphEditor; extern StructRNA RNA_SpaceImageEditor; extern StructRNA RNA_SpaceInfo; +extern StructRNA RNA_SpaceCollectionManager; extern StructRNA RNA_SpaceLogicEditor; extern StructRNA RNA_SpaceNLA; extern StructRNA RNA_SpaceNodeEditor; @@ -641,6 +645,7 @@ extern StructRNA RNA_ThemeFontStyle; extern StructRNA RNA_ThemeGraphEditor; extern StructRNA RNA_ThemeImageEditor; extern StructRNA RNA_ThemeInfo; +extern StructRNA RNA_ThemeCollectionManager; extern StructRNA RNA_ThemeLogicEditor; extern StructRNA RNA_ThemeNLAEditor; extern StructRNA RNA_ThemeNodeEditor; diff --git a/source/blender/makesrna/intern/rna_context.c b/source/blender/makesrna/intern/rna_context.c index d7a679e9702..27e88f592ab 100644 --- a/source/blender/makesrna/intern/rna_context.c +++ b/source/blender/makesrna/intern/rna_context.c @@ -107,6 +107,26 @@ static PointerRNA rna_Context_scene_get(PointerRNA *ptr) return rna_pointer_inherit_refine(ptr, &RNA_Scene, CTX_data_scene(C)); } +static PointerRNA rna_Context_scene_layer_get(PointerRNA *ptr) +{ + bContext *C = (bContext *)ptr->data; + return rna_pointer_inherit_refine(ptr, &RNA_SceneLayer, CTX_data_scene_layer(C)); +} + +static PointerRNA rna_Context_scene_collection_get(PointerRNA *ptr) +{ + bContext *C = (bContext *)ptr->data; + ptr->id.data = CTX_data_scene(C); + return rna_pointer_inherit_refine(ptr, &RNA_SceneCollection, CTX_data_scene_collection(C)); +} + +static PointerRNA rna_Context_layer_collection_get(PointerRNA *ptr) +{ + bContext *C = (bContext *)ptr->data; + ptr->id.data = CTX_data_scene(C); + return rna_pointer_inherit_refine(ptr, &RNA_LayerCollection, CTX_data_layer_collection(C)); +} + static PointerRNA rna_Context_tool_settings_get(PointerRNA *ptr) { bContext *C = (bContext *)ptr->data; @@ -203,6 +223,21 @@ void RNA_def_context(BlenderRNA *brna) RNA_def_property_struct_type(prop, "Scene"); RNA_def_property_pointer_funcs(prop, "rna_Context_scene_get", NULL, NULL, NULL); + prop = RNA_def_property(srna, "render_layer", PROP_POINTER, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_struct_type(prop, "SceneLayer"); + RNA_def_property_pointer_funcs(prop, "rna_Context_scene_layer_get", NULL, NULL, NULL); + + prop = RNA_def_property(srna, "scene_collection", PROP_POINTER, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_struct_type(prop, "SceneCollection"); + RNA_def_property_pointer_funcs(prop, "rna_Context_scene_collection_get", NULL, NULL, NULL); + + prop = RNA_def_property(srna, "layer_collection", PROP_POINTER, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_struct_type(prop, "LayerCollection"); + RNA_def_property_pointer_funcs(prop, "rna_Context_layer_collection_get", NULL, NULL, NULL); + prop = RNA_def_property(srna, "tool_settings", PROP_POINTER, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_struct_type(prop, "ToolSettings"); diff --git a/source/blender/makesrna/intern/rna_group.c b/source/blender/makesrna/intern/rna_group.c index aa02a3c159d..2a5a0011279 100644 --- a/source/blender/makesrna/intern/rna_group.c +++ b/source/blender/makesrna/intern/rna_group.c @@ -53,9 +53,9 @@ static PointerRNA rna_Group_objects_get(CollectionPropertyIterator *iter) return rna_pointer_inherit_refine(&iter->parent, &RNA_Object, ((GroupObject *)internal->link)->ob); } -static void rna_Group_objects_link(Group *group, bContext *C, ReportList *reports, Object *object) +static void rna_Group_objects_link(Group *group, ReportList *reports, Object *object) { - if (!BKE_group_object_add(group, object, CTX_data_scene(C), NULL)) { + if (!BKE_group_object_add(group, object)) { BKE_reportf(reports, RPT_ERROR, "Object '%s' already in group '%s'", object->id.name + 2, group->id.name + 2); return; } @@ -63,9 +63,9 @@ static void rna_Group_objects_link(Group *group, bContext *C, ReportList *report WM_main_add_notifier(NC_OBJECT | ND_DRAW, &object->id); } -static void rna_Group_objects_unlink(Group *group, bContext *C, ReportList *reports, Object *object) +static void rna_Group_objects_unlink(Group *group, ReportList *reports, Object *object) { - if (!BKE_group_object_unlink(group, object, CTX_data_scene(C), NULL)) { + if (!BKE_group_object_unlink(group, object)) { BKE_reportf(reports, RPT_ERROR, "Object '%s' not in group '%s'", object->id.name + 2, group->id.name + 2); return; } @@ -91,7 +91,7 @@ static void rna_def_group_objects(BlenderRNA *brna, PropertyRNA *cprop) /* add object */ func = RNA_def_function(srna, "link", "rna_Group_objects_link"); - RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS); + RNA_def_function_flag(func, FUNC_USE_REPORTS); RNA_def_function_ui_description(func, "Add this object to a group"); /* object to add */ parm = RNA_def_pointer(func, "object", "Object", "", "Object to add"); @@ -100,7 +100,7 @@ static void rna_def_group_objects(BlenderRNA *brna, PropertyRNA *cprop) /* remove object */ func = RNA_def_function(srna, "unlink", "rna_Group_objects_unlink"); RNA_def_function_ui_description(func, "Remove this object to a group"); - RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS); + RNA_def_function_flag(func, FUNC_USE_REPORTS); /* object to remove */ parm = RNA_def_pointer(func, "object", "Object", "", "Object to remove"); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h index 76455adbc78..b904b65a37a 100644 --- a/source/blender/makesrna/intern/rna_internal.h +++ b/source/blender/makesrna/intern/rna_internal.h @@ -279,7 +279,7 @@ void RNA_api_material(StructRNA *srna); void RNA_api_mesh(struct StructRNA *srna); void RNA_api_meta(struct StructRNA *srna); void RNA_api_object(struct StructRNA *srna); -void RNA_api_object_base(struct StructRNA *srna); +void RNA_api_object_base_legacy(struct StructRNA *srna); void RNA_api_pose(struct StructRNA *srna); void RNA_api_pose_channel(struct StructRNA *srna); void RNA_api_scene(struct StructRNA *srna); diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index 0cffba47f16..f8b3bdd62e9 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -297,23 +297,14 @@ static void rna_Object_dependency_update(Main *bmain, Scene *UNUSED(scene), Poin } /* when changing the selection flag the scene needs updating */ -static void rna_Object_select_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr) -{ - if (scene) { - Object *ob = (Object *)ptr->id.data; - short mode = (ob->flag & SELECT) ? BA_SELECT : BA_DESELECT; - ED_base_object_select(BKE_scene_base_find(scene, ob), mode); - } -} - static void rna_Base_select_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - Base *base = (Base *)ptr->data; - short mode = (base->flag & BA_SELECT) ? BA_SELECT : BA_DESELECT; + BaseLegacy *base = (BaseLegacy *)ptr->data; + short mode = (base->flag_legacy & BA_SELECT) ? BA_SELECT : BA_DESELECT; ED_base_object_select(base, mode); } -static void rna_Object_layer_update__internal(Main *bmain, Scene *scene, Base *base, Object *ob) +static void rna_Object_layer_update__internal(Main *bmain, Scene *scene, BaseLegacy *base, Object *ob) { /* try to avoid scene sort */ if (scene == NULL) { @@ -335,7 +326,7 @@ static void rna_Object_layer_update__internal(Main *bmain, Scene *scene, Base *b static void rna_Object_layer_update(Main *bmain, Scene *scene, PointerRNA *ptr) { Object *ob = (Object *)ptr->id.data; - Base *base; + BaseLegacy *base; base = scene ? BKE_scene_base_find(scene, ob) : NULL; if (!base) @@ -351,7 +342,7 @@ static void rna_Object_layer_update(Main *bmain, Scene *scene, PointerRNA *ptr) static void rna_Base_layer_update(Main *bmain, Scene *scene, PointerRNA *ptr) { - Base *base = (Base *)ptr->data; + BaseLegacy *base = (BaseLegacy *)ptr->data; Object *ob = (Object *)base->object; rna_Object_layer_update__internal(bmain, scene, base, ob); @@ -1120,7 +1111,7 @@ static void rna_Object_layer_set(PointerRNA *ptr, const int *values) static void rna_Base_layer_set(PointerRNA *ptr, const int *values) { - Base *base = (Base *)ptr->data; + BaseLegacy *base = (BaseLegacy *)ptr->data; unsigned int lay; lay = rna_Object_layer_validate__internal(values, base->lay); @@ -2246,11 +2237,6 @@ static void rna_def_object(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Local View Layers", "3D local view layers the object is on"); - prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", SELECT); - RNA_def_property_ui_text(prop, "Select", "Object selection state"); - RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_select_update"); - /* for data access */ prop = RNA_def_property(srna, "bound_box", PROP_FLOAT, PROP_NONE); RNA_def_property_multi_array(prop, 2, boundbox_dimsize); @@ -2895,14 +2881,14 @@ static void rna_def_dupli_object(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Dupli Type", "Duplicator type that generated this dupli object"); } -static void rna_def_object_base(BlenderRNA *brna) +static void rna_def_object_base_legacy(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - srna = RNA_def_struct(brna, "ObjectBase", NULL); + srna = RNA_def_struct(brna, "ObjectBaseLegacy", NULL); RNA_def_struct_sdna(srna, "Base"); - RNA_def_struct_ui_text(srna, "Object Base", "An object instance in a scene"); + RNA_def_struct_ui_text(srna, "Object Base Legacy", "An object instance in a scene (deprecated)"); RNA_def_struct_ui_icon(srna, ICON_OBJECT_DATA); prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE); @@ -2922,13 +2908,13 @@ static void rna_def_object_base(BlenderRNA *brna) RNA_def_property_array(prop, 8); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Local View Layers", "3D local view layers the object base is on"); - + prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", BA_SELECT); + RNA_def_property_boolean_sdna(prop, NULL, "flag_legacy", BA_SELECT); RNA_def_property_ui_text(prop, "Select", "Object base selection state"); RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Base_select_update"); - - RNA_api_object_base(srna); + + RNA_api_object_base_legacy(srna); } void RNA_def_object(BlenderRNA *brna) @@ -2937,7 +2923,7 @@ void RNA_def_object(BlenderRNA *brna) RNA_define_animate_sdna(false); rna_def_object_game_settings(brna); - rna_def_object_base(brna); + rna_def_object_base_legacy(brna); rna_def_vertex_group(brna); rna_def_material_slot(brna); rna_def_dupli_object(brna); diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c index c680abe71a4..c93f72e798f 100644 --- a/source/blender/makesrna/intern/rna_object_api.c +++ b/source/blender/makesrna/intern/rna_object_api.c @@ -40,10 +40,12 @@ #include "RNA_define.h" #include "DNA_constraint_types.h" +#include "DNA_layer_types.h" #include "DNA_modifier_types.h" #include "DNA_object_types.h" #include "BKE_depsgraph.h" +#include "BKE_layer.h" #include "rna_internal.h" /* own include */ @@ -90,6 +92,49 @@ static EnumPropertyItem space_items[] = { #include "DEG_depsgraph.h" +static void rna_Object_select_set(Object *ob, bContext *C, ReportList *reports, int action) +{ + SceneLayer *sl = CTX_data_scene_layer(C); + Base *base = BKE_scene_layer_base_find(sl, ob); + + if (!base) { + BKE_reportf(reports, RPT_ERROR, "Object '%s' not in Render Layer '%s'!", ob->id.name + 2, sl->name); + return; + } + + if (action == 2) { /* TOGGLE */ + if ((base->flag & BASE_SELECTED) != 0) { + action = 1; /* DESELECT */ + } + else { + action = 0; /* SELECT */ + } + } + + switch (action) { + case 1: /* DESELECT */ + base->flag &= ~BASE_SELECTED; + break; + case 0: /* SELECT */ + default: + BKE_scene_layer_base_select(sl, base); + break; + } +} + +static int rna_Object_select_get(Object *ob, bContext *C, ReportList *reports) +{ + SceneLayer *sl = CTX_data_scene_layer(C); + Base *base = BKE_scene_layer_base_find(sl, ob); + + if (!base) { + BKE_reportf(reports, RPT_ERROR, "Object '%s' not in Render Layer '%s'!", ob->id.name + 2, sl->name); + return -1; + } + + return ((base->flag & BASE_SELECTED) != 0) ? 1 : 0; +} + /* Convert a given matrix from a space to another (using the object and/or a bone as reference). */ static void rna_Scene_mat_convert_space(Object *ob, ReportList *reports, bPoseChannel *pchan, float *mat, float *mat_ret, int from, int to) @@ -413,9 +458,9 @@ finally: free_bvhtree_from_mesh(&treeData); } -/* ObjectBase */ +/* ObjectBaseLegacy */ -static void rna_ObjectBase_layers_from_view(Base *base, View3D *v3d) +static void rna_ObjectBaseLegacy_layers_from_view(BaseLegacy *base, View3D *v3d) { base->lay = base->object->lay = v3d->lay; } @@ -504,6 +549,26 @@ void RNA_api_object(StructRNA *srna) }; #endif + static EnumPropertyItem object_select_items[] = { + {0, "SELECT", 0, "Select", "Select object from the active render layer"}, + {1, "DESELECT", 0, "Deselect", "Deselect object from the active render layer"}, + {2, "TOGGLE", 0, "Toggle", "Toggle object selection from the active render layer"}, + {0, NULL, 0, NULL, NULL} + }; + + /* Special wrapper to access the base selection value */ + func = RNA_def_function(srna, "select_set", "rna_Object_select_set"); + RNA_def_function_ui_description(func, "Select the object (for the active render layer)"); + RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS); + parm = RNA_def_enum(func, "action", object_select_items, 0, "Action", "Select mode"); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + + func = RNA_def_function(srna, "select_get", "rna_Object_select_get"); + RNA_def_function_ui_description(func, "Get the object selection for the active render layer"); + RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS); + parm = RNA_def_boolean(func, "result", 0, "", "Object selected"); + RNA_def_function_return(func, parm); + /* Matrix space conversion */ func = RNA_def_function(srna, "convert_space", "rna_Scene_mat_convert_space"); RNA_def_function_ui_description(func, "Convert (transform) the given matrix from one space to another"); @@ -707,12 +772,12 @@ void RNA_api_object(StructRNA *srna) } -void RNA_api_object_base(StructRNA *srna) +void RNA_api_object_base_legacy(StructRNA *srna) { FunctionRNA *func; PropertyRNA *parm; - func = RNA_def_function(srna, "layers_from_view", "rna_ObjectBase_layers_from_view"); + func = RNA_def_function(srna, "layers_from_view", "rna_ObjectBaseLegacy_layers_from_view"); RNA_def_function_ui_description(func, "Sets the object layers from a 3D View (use when adding an object in local view)"); parm = RNA_def_pointer(func, "view", "SpaceView3D", "", ""); diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c index 1d89f7535c4..5fd4762e5be 100644 --- a/source/blender/makesrna/intern/rna_object_force.c +++ b/source/blender/makesrna/intern/rna_object_force.c @@ -605,7 +605,7 @@ static void rna_EffectorWeight_update(Main *UNUSED(bmain), Scene *UNUSED(scene), if (id && GS(id->name) == ID_SCE) { Scene *scene = (Scene *)id; - Base *base; + BaseLegacy *base; for (base = scene->base.first; base; base = base->next) { BKE_ptcache_object_reset(scene, base->object, PTCACHE_RESET_DEPSGRAPH); diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 1166fb89a0a..8f36af96cf4 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -32,6 +32,7 @@ #include "DNA_particle_types.h" #include "DNA_rigidbody_types.h" #include "DNA_scene_types.h" +#include "DNA_layer_types.h" #include "DNA_linestyle_types.h" #include "DNA_userdef_types.h" #include "DNA_world_types.h" @@ -47,6 +48,8 @@ #include "BKE_editmesh.h" #include "BKE_paint.h" +#include "ED_object.h" + #include "GPU_extensions.h" #include "RNA_define.h" @@ -445,10 +448,12 @@ EnumPropertyItem rna_enum_gpencil_interpolation_mode_items[] = { #include "MEM_guardedalloc.h" #include "BKE_brush.h" +#include "BKE_collection.h" #include "BKE_colortools.h" #include "BKE_context.h" #include "BKE_global.h" #include "BKE_image.h" +#include "BKE_layer.h" #include "BKE_main.h" #include "BKE_node.h" #include "BKE_pointcache.h" @@ -606,11 +611,11 @@ static void rna_SpaceImageEditor_uv_sculpt_update(Main *bmain, Scene *scene, Poi static int rna_Scene_object_bases_lookup_string(PointerRNA *ptr, const char *key, PointerRNA *r_ptr) { Scene *scene = (Scene *)ptr->data; - Base *base; + BaseLegacy *base; for (base = scene->base.first; base; base = base->next) { if (STREQLEN(base->object->id.name + 2, key, sizeof(base->object->id.name) - 2)) { - *r_ptr = rna_pointer_inherit_refine(ptr, &RNA_ObjectBase, base); + *r_ptr = rna_pointer_inherit_refine(ptr, &RNA_ObjectBaseLegacy, base); return true; } } @@ -623,13 +628,13 @@ static PointerRNA rna_Scene_objects_get(CollectionPropertyIterator *iter) ListBaseIterator *internal = &iter->internal.listbase; /* we are actually iterating a Base list, so override get */ - return rna_pointer_inherit_refine(&iter->parent, &RNA_Object, ((Base *)internal->link)->object); + return rna_pointer_inherit_refine(&iter->parent, &RNA_Object, ((BaseLegacy *)internal->link)->object); } -static Base *rna_Scene_object_link(Scene *scene, bContext *C, ReportList *reports, Object *ob) +static BaseLegacy *rna_Scene_object_link(Scene *scene, bContext *C, ReportList *reports, Object *ob) { Scene *scene_act = CTX_data_scene(C); - Base *base; + BaseLegacy *base; if (BKE_scene_base_find(scene, ob)) { BKE_reportf(reports, RPT_ERROR, "Object '%s' is already in scene '%s'", ob->id.name + 2, scene->id.name + 2); @@ -660,7 +665,7 @@ static Base *rna_Scene_object_link(Scene *scene, bContext *C, ReportList *report static void rna_Scene_object_unlink(Scene *scene, ReportList *reports, Object *ob) { - Base *base = BKE_scene_base_find(scene, ob); + BaseLegacy *base = BKE_scene_base_find(scene, ob); if (!base) { BKE_reportf(reports, RPT_ERROR, "Object '%s' is not in this scene '%s'", ob->id.name + 2, scene->id.name + 2); return; @@ -1707,7 +1712,7 @@ static void rna_Scene_use_nodes_update(bContext *C, PointerRNA *ptr) static void rna_Physics_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { Scene *scene = (Scene *)ptr->id.data; - Base *base; + BaseLegacy *base; for (base = scene->base.first; base; base = base->next) BKE_ptcache_object_reset(scene, base->object, PTCACHE_RESET_DEPSGRAPH); @@ -1778,7 +1783,7 @@ static void rna_Scene_use_simplify_update(Main *bmain, Scene *UNUSED(scene), Poi { Scene *sce = ptr->id.data; Scene *sce_iter; - Base *base; + BaseLegacy *base; BKE_main_id_tag_listbase(&bmain->object, LIB_TAG_DOIT, true); for (SETLOOPER(sce, sce_iter, base)) @@ -2185,6 +2190,442 @@ static int rna_gpu_is_hq_supported_get(PointerRNA *UNUSED(ptr)) return GPU_instanced_drawing_support() && GPU_geometry_shader_support(); } +static void rna_SceneCollection_name_set(PointerRNA *ptr, const char *value) +{ + Scene *scene = (Scene *)ptr->id.data; + SceneCollection *sc = (SceneCollection *)ptr->data; + SceneCollection *sc_master = BKE_collection_master(scene); + + BLI_strncpy_utf8(sc->name, value, sizeof(sc->name)); + BLI_uniquename(&sc_master->scene_collections, sc, DATA_("SceneCollection"), '.', offsetof(SceneCollection, name), sizeof(sc->name)); +} + +static void rna_SceneCollection_filter_set(PointerRNA *ptr, const char *value) +{ + Scene *scene = (Scene *)ptr->id.data; + SceneCollection *sc = (SceneCollection *)ptr->data; + BLI_strncpy_utf8(sc->filter, value, sizeof(sc->filter)); + + TODO_LAYER_SYNC_FILTER; + (void)scene; +} + +static PointerRNA rna_SceneCollection_objects_get(CollectionPropertyIterator *iter) +{ + ListBaseIterator *internal = &iter->internal.listbase; + + /* we are actually iterating a LinkData list, so override get */ + return rna_pointer_inherit_refine(&iter->parent, &RNA_Object, ((LinkData *)internal->link)->data); +} + +static SceneCollection *rna_SceneCollection_new(ID *id, SceneCollection *sc_parent, const char *name) +{ + Scene *scene = (Scene *)id; + SceneCollection *sc = BKE_collection_add(scene, sc_parent, name); + + DAG_id_tag_update(&scene->id, 0); + WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL); + + return sc; +} + +static void rna_SceneCollection_remove( + ID *id, SceneCollection *sc_parent, ReportList *reports, PointerRNA *sc_ptr) +{ + Scene *scene = (Scene *)id; + SceneCollection *sc = sc_ptr->data; + + const int index = BLI_findindex(&sc_parent->scene_collections, sc); + if (index == -1) { + BKE_reportf(reports, RPT_ERROR, "Collection '%s' is not a sub-collection of '%s'", + sc->name, sc_parent->name); + return; + } + + if (!BKE_collection_remove(scene, sc)) { + BKE_reportf(reports, RPT_ERROR, "Collection '%s' could not be removed from collection '%s'", + sc->name, sc_parent->name); + return; + } + + RNA_POINTER_INVALIDATE(sc_ptr); + + DAG_id_tag_update(&scene->id, 0); + WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL); +} + +static int rna_SceneCollection_objects_active_index_get(PointerRNA *ptr) +{ + SceneCollection *sc = (SceneCollection *)ptr->data; + return sc->active_object_index; +} + +static void rna_SceneCollection_objects_active_index_set(PointerRNA *ptr, int value) +{ + SceneCollection *sc = (SceneCollection *)ptr->data; + sc->active_object_index = value; +} + +static void rna_SceneCollection_objects_active_index_range( + PointerRNA *ptr, int *min, int *max, int *UNUSED(softmin), int *UNUSED(softmax)) +{ + SceneCollection *sc = (SceneCollection *)ptr->data; + *min = 0; + *max = max_ii(0, BLI_listbase_count(&sc->objects) - 1); +} + +void rna_SceneCollection_object_link( + ID *id, SceneCollection *sc, Main *bmain, ReportList *reports, Object *ob) +{ + Scene *scene = (Scene *)id; + + if (BLI_findptr(&sc->objects, ob, offsetof(LinkData, data))) { + BKE_reportf(reports, RPT_ERROR, "Object '%s' is already in collection '%s'", ob->id.name + 2, sc->name); + return; + } + + BKE_collection_object_add(scene, sc, ob); + + /* TODO(sergey): Only update relations for the current scene. */ + DAG_relations_tag_update(bmain); + DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); + + WM_main_add_notifier(NC_SCENE | ND_LAYER | ND_OB_ACTIVE, scene); +} + +static void rna_SceneCollection_object_unlink( + ID *id, SceneCollection *sc, Main *bmain, ReportList *reports, Object *ob) +{ + Scene *scene = (Scene *)id; + + if (!BLI_findptr(&sc->objects, ob, offsetof(LinkData, data))) { + BKE_reportf(reports, RPT_ERROR, "Object '%s' is not in collection '%s'", ob->id.name + 2, sc->name); + return; + } + + BKE_collection_object_remove(bmain, scene, sc, ob, false); + + /* needed otherwise the depgraph will contain freed objects which can crash, see [#20958] */ + DAG_relations_tag_update(bmain); + + WM_main_add_notifier(NC_SCENE | ND_LAYER | ND_OB_ACTIVE, scene); +} + +static void rna_LayerCollection_name_get(PointerRNA *ptr, char *value) +{ + SceneCollection *sc = ((LayerCollection *)ptr->data)->scene_collection; + strcpy(value, sc->name); +} + +static int rna_LayerCollection_name_length(PointerRNA *ptr) +{ + SceneCollection *sc = ((LayerCollection *)ptr->data)->scene_collection; + return strnlen(sc->name, sizeof(sc->name)); +} + +static void rna_LayerCollection_name_set(PointerRNA *ptr, const char *value) +{ + Scene *scene = (Scene *)ptr->id.data; + SceneCollection *sc = ((LayerCollection *)ptr->data)->scene_collection; + SceneCollection *sc_master = BKE_collection_master(scene); + + BLI_strncpy_utf8(sc->name, value, sizeof(sc->name)); + BLI_uniquename(&sc_master->scene_collections, sc, DATA_("SceneCollection"), '.', offsetof(SceneCollection, name), sizeof(sc->name)); +} + +static PointerRNA rna_LayerCollection_objects_get(CollectionPropertyIterator *iter) +{ + ListBaseIterator *internal = &iter->internal.listbase; + Base *base = ((LinkData *)internal->link)->data; + return rna_pointer_inherit_refine(&iter->parent, &RNA_Object, base->object); +} + +static void rna_LayerCollection_hide_update(bContext *C, PointerRNA *ptr) +{ + Scene *scene = CTX_data_scene(C); + LayerCollection *lc = ptr->data; + SceneLayer *sl = BKE_scene_layer_find_from_collection(scene, lc); + + /* hide and deselect bases that are directly influenced by this LayerCollection */ + BKE_scene_layer_base_flag_recalculate(sl); + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); +} + +static void rna_LayerCollection_hide_select_update(bContext *C, PointerRNA *ptr) +{ + LayerCollection *lc = ptr->data; + + if ((lc->flag & COLLECTION_SELECTABLE) == 0) { + Scene *scene = CTX_data_scene(C); + SceneLayer *sl = BKE_scene_layer_find_from_collection(scene, lc); + + /* deselect bases that are directly influenced by this LayerCollection */ + BKE_scene_layer_base_flag_recalculate(sl); + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C)); + } +} + +static int rna_LayerCollections_active_collection_index_get(PointerRNA *ptr) +{ + SceneLayer *sl = (SceneLayer *)ptr->data; + return sl->active_collection; +} + +static void rna_LayerCollections_active_collection_index_set(PointerRNA *ptr, int value) +{ + SceneLayer *sl = (SceneLayer *)ptr->data; + int num_collections = BKE_layer_collection_count(sl); + sl->active_collection = min_ff(value, num_collections - 1); +} + +static void rna_LayerCollections_active_collection_index_range( + PointerRNA *ptr, int *min, int *max, int *UNUSED(softmin), int *UNUSED(softmax)) +{ + SceneLayer *sl = (SceneLayer *)ptr->data; + *min = 0; + *max = max_ii(0, BKE_layer_collection_count(sl) - 1); +} + +static PointerRNA rna_LayerCollections_active_collection_get(PointerRNA *ptr) +{ + SceneLayer *sl = (SceneLayer *)ptr->data; + LayerCollection *lc = BKE_layer_collection_active(sl); + return rna_pointer_inherit_refine(ptr, &RNA_LayerCollection, lc); +} + +static void rna_LayerCollections_active_collection_set(PointerRNA *ptr, PointerRNA value) +{ + SceneLayer *sl = (SceneLayer *)ptr->data; + LayerCollection *lc = (LayerCollection *)value.data; + const int index = BKE_layer_collection_findindex(sl, lc); + if (index != -1) sl->active_collection = index; +} + +LayerCollection * rna_SceneLayer_collection_link( + ID *id, SceneLayer *sl, Main *bmain, SceneCollection *sc) +{ + Scene *scene = (Scene *)id; + LayerCollection *lc = BKE_collection_link(sl, sc); + + /* TODO(sergey/dfelinto): Only update relations for the current scenelayer. */ + DAG_relations_tag_update(bmain); + WM_main_add_notifier(NC_SCENE | ND_LAYER, scene); + + return lc; +} + +static void rna_SceneLayer_collection_unlink( + ID *id, SceneLayer *sl, Main *bmain, ReportList *reports, LayerCollection *lc) +{ + Scene *scene = (Scene *)id; + + if (BLI_findindex(&sl->layer_collections, lc) == -1) { + BKE_reportf(reports, RPT_ERROR, "Layer collection '%s' is not in '%s'", lc->scene_collection->name, sl->name); + return; + } + + BKE_collection_unlink(sl, lc); + + /* needed otherwise the depgraph will contain freed objects which can crash, see [#20958] */ + /* TODO(sergey/dfelinto): Only update relations for the current scenelayer. */ + DAG_relations_tag_update(bmain); + + WM_main_add_notifier(NC_SCENE | ND_LAYER | ND_OB_ACTIVE, scene); +} + +static PointerRNA rna_LayerObjects_active_object_get(PointerRNA *ptr) +{ + SceneLayer *sl = (SceneLayer *)ptr->data; + return rna_pointer_inherit_refine(ptr, &RNA_Object, sl->basact ? sl->basact->object : NULL); +} + +static void rna_LayerObjects_active_object_set(PointerRNA *ptr, PointerRNA value) +{ + SceneLayer *sl = (SceneLayer *)ptr->data; + if (value.data) + sl->basact = BKE_scene_layer_base_find(sl, (Object *)value.data); + else + sl->basact = NULL; +} + +static void rna_SceneLayer_name_set(PointerRNA *ptr, const char *value) +{ + Scene *scene = (Scene *)ptr->id.data; + SceneLayer *sl = (SceneLayer *)ptr->data; + char oldname[sizeof(sl->name)]; + + BLI_strncpy(oldname, sl->name, sizeof(sl->name)); + + BLI_strncpy_utf8(sl->name, value, sizeof(sl->name)); + BLI_uniquename(&scene->render_layers, sl, DATA_("SceneLayer"), '.', offsetof(SceneLayer, name), sizeof(sl->name)); + + if (scene->nodetree) { + bNode *node; + int index = BLI_findindex(&scene->render_layers, sl); + + for (node = scene->nodetree->nodes.first; node; node = node->next) { + if (node->type == CMP_NODE_R_LAYERS && node->id == NULL) { + if (node->custom1 == index) + BLI_strncpy(node->name, sl->name, NODE_MAXSTR); + } + } + } +} + +static PointerRNA rna_SceneLayer_objects_get(CollectionPropertyIterator *iter) +{ + ListBaseIterator *internal = &iter->internal.listbase; + + /* we are actually iterating a ObjectBase list, so override get */ + Base *base = (Base *)internal->link; + return rna_pointer_inherit_refine(&iter->parent, &RNA_Object, base->object); +} + +static int rna_SceneLayer_objects_selected_skip(CollectionPropertyIterator *iter, void *UNUSED(data)) +{ + ListBaseIterator *internal = &iter->internal.listbase; + Base *base = (Base *)internal->link; + + if ((base->flag & BASE_SELECTED) != 0) { + return 0; + } + + return 1; +}; + +static void rna_LayerObjects_selected_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) +{ + SceneLayer *sl = (SceneLayer *)ptr->data; + rna_iterator_listbase_begin(iter, &sl->object_bases, rna_SceneLayer_objects_selected_skip); +} + +static void rna_SceneLayer_engine_set(PointerRNA *ptr, int value) +{ + SceneLayer *sl = (SceneLayer *)ptr->data; + RenderEngineType *type = BLI_findlink(&R_engines, value); + + if (type) + BKE_scene_layer_engine_set(sl, type->idname); +} + +static EnumPropertyItem *rna_SceneLayer_engine_itemf( + bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free) +{ + RenderEngineType *type; + EnumPropertyItem *item = NULL; + EnumPropertyItem tmp = {0, "", 0, "", ""}; + int a = 0, totitem = 0; + + for (type = R_engines.first; type; type = type->next, a++) { + tmp.value = a; + tmp.identifier = type->idname; + tmp.name = type->name; + RNA_enum_item_add(&item, &totitem, &tmp); + } + + RNA_enum_item_end(&item, &totitem); + *r_free = true; + + return item; +} + +static int rna_SceneLayer_engine_get(PointerRNA *ptr) +{ + SceneLayer *sl = (SceneLayer *)ptr->data; + RenderEngineType *type; + int a = 0; + + for (type = R_engines.first; type; type = type->next, a++) + if (STREQ(type->idname, sl->engine)) + return a; + + return 0; +} + +static void rna_SceneLayer_engine_update(Main *bmain, Scene *UNUSED(unused), PointerRNA *UNUSED(ptr)) +{ + ED_render_engine_changed(bmain); +} + +static int rna_SceneLayer_multiple_engines_get(PointerRNA *UNUSED(ptr)) +{ + return (BLI_listbase_count(&R_engines) > 1); +} + +static int rna_SceneLayer_active_layer_index_get(PointerRNA *ptr) +{ + Scene *scene = (Scene *)ptr->data; + return scene->active_layer; +} + +static void rna_SceneLayer_active_layer_index_set(PointerRNA *ptr, int value) +{ + Scene *scene = (Scene *)ptr->data; + int num_layers = BLI_listbase_count(&scene->render_layers); + scene->active_layer = min_ff(value, num_layers - 1); +} + +static void rna_SceneLayer_active_layer_index_range( + PointerRNA *ptr, int *min, int *max, int *UNUSED(softmin), int *UNUSED(softmax)) +{ + Scene *scene = (Scene *)ptr->data; + + *min = 0; + *max = max_ii(0, BLI_listbase_count(&scene->render_layers) - 1); +} + +static PointerRNA rna_SceneLayer_active_layer_get(PointerRNA *ptr) +{ + Scene *scene = (Scene *)ptr->data; + SceneLayer *sl = BLI_findlink(&scene->render_layers, scene->active_layer); + + return rna_pointer_inherit_refine(ptr, &RNA_SceneLayer, sl); +} + +static void rna_SceneLayer_active_layer_set(PointerRNA *ptr, PointerRNA value) +{ + Scene *scene = (Scene *)ptr->data; + SceneLayer *sl = (SceneLayer *)value.data; + const int index = BLI_findindex(&scene->render_layers, sl); + if (index != -1) scene->active_layer = index; +} + +static SceneLayer *rna_SceneLayer_new(ID *id, Scene *UNUSED(sce), const char *name) +{ + Scene *scene = (Scene *)id; + SceneLayer *sl = BKE_scene_layer_add(scene, name); + + DAG_id_tag_update(&scene->id, 0); + WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL); + + return sl; +} + +static void rna_SceneLayer_remove( + ID *id, Scene *UNUSED(sce), Main *bmain, ReportList *reports, PointerRNA *sl_ptr) +{ + Scene *scene = (Scene *)id; + SceneLayer *sl = sl_ptr->data; + + if (!BKE_scene_layer_remove(bmain, scene, sl)) { + BKE_reportf(reports, RPT_ERROR, "Render layer '%s' could not be removed from scene '%s'", + sl->name, scene->id.name + 2); + return; + } + + RNA_POINTER_INVALIDATE(sl_ptr); + + DAG_id_tag_update(&scene->id, 0); + WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL); +} + +static void rna_ObjectBase_select_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) +{ + Base *base = (Base *)ptr->data; + short mode = (base->flag & BASE_SELECTED) ? BA_SELECT : BA_DESELECT; + ED_object_base_select(base, mode); +} + #else /* Grease Pencil Interpolation tool settings */ @@ -5046,6 +5487,371 @@ static void rna_def_gpu_fx(BlenderRNA *brna) RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_GPUFXSettings_fx_update"); } +/* Render Layers and Collections */ + +static void rna_def_scene_collections(BlenderRNA *brna, PropertyRNA *cprop) +{ + StructRNA *srna; + FunctionRNA *func; + PropertyRNA *parm; + + RNA_def_property_srna(cprop, "SceneCollections"); + srna = RNA_def_struct(brna, "SceneCollections", NULL); + RNA_def_struct_sdna(srna, "SceneCollection"); + RNA_def_struct_ui_text(srna, "Scene Collection", "Collection of scene collections"); + + func = RNA_def_function(srna, "new", "rna_SceneCollection_new"); + RNA_def_function_ui_description(func, "Add a collection to scene"); + RNA_def_function_flag(func, FUNC_USE_SELF_ID); + parm = RNA_def_string(func, "name", "SceneCollection", 0, "", "New name for the collection (not unique)"); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_pointer(func, "result", "SceneCollection", "", "Newly created collection"); + RNA_def_function_return(func, parm); + + func = RNA_def_function(srna, "remove", "rna_SceneCollection_remove"); + RNA_def_function_ui_description(func, "Remove a collection layer"); + RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_SELF_ID); + parm = RNA_def_pointer(func, "layer", "SceneCollection", "", "Collection to remove"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR); + RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0); +} + +static void rna_def_collection_objects(BlenderRNA *brna, PropertyRNA *cprop) +{ + StructRNA *srna; + FunctionRNA *func; + PropertyRNA *parm; + PropertyRNA *prop; + + RNA_def_property_srna(cprop, "CollectionObjects"); + srna = RNA_def_struct(brna, "CollectionObjects", NULL); + RNA_def_struct_sdna(srna, "SceneCollection"); + RNA_def_struct_ui_text(srna, "Collection Objects", "Objects of a collection"); + + prop = RNA_def_property(srna, "active_index", PROP_INT, PROP_UNSIGNED); + RNA_def_property_int_funcs(prop, "rna_SceneCollection_objects_active_index_get", + "rna_SceneCollection_objects_active_index_set", + "rna_SceneCollection_objects_active_index_range"); + RNA_def_property_ui_text(prop, "Active Object Index", "Active index in collection objects array"); + RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, NULL); + + func = RNA_def_function(srna, "link", "rna_SceneCollection_object_link"); + RNA_def_function_ui_description(func, "Link an object to collection"); + RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN | FUNC_USE_REPORTS); + parm = RNA_def_pointer(func, "object", "Object", "", "Object to add to collection"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + + func = RNA_def_function(srna, "unlink", "rna_SceneCollection_object_unlink"); + RNA_def_function_ui_description(func, "Unlink object from collection"); + RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN | FUNC_USE_REPORTS); + parm = RNA_def_pointer(func, "object", "Object", "", "Object to remove from collection"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); +} + +static void rna_def_scene_collection(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "SceneCollection", NULL); + RNA_def_struct_ui_text(srna, "Scene Collection", "Collection"); + + prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); + RNA_def_property_string_funcs(prop, NULL, NULL, "rna_SceneCollection_name_set"); + RNA_def_property_ui_text(prop, "Name", "Collection name"); + RNA_def_struct_name_property(srna, prop); + RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, NULL); + + prop = RNA_def_property(srna, "filter", PROP_STRING, PROP_NONE); + RNA_def_property_string_funcs(prop, NULL, NULL, "rna_SceneCollection_filter_set"); + RNA_def_property_ui_text(prop, "Filter", "Filter to dynamically include objects based on their names (e.g., CHAR_*)"); + RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, NULL); + + prop = RNA_def_property(srna, "collections", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_sdna(prop, NULL, "scene_collections", NULL); + RNA_def_property_struct_type(prop, "SceneCollection"); + RNA_def_property_ui_text(prop, "SceneCollections", ""); + rna_def_scene_collections(brna, prop); + + prop = RNA_def_property(srna, "objects", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_sdna(prop, NULL, "objects", NULL); + RNA_def_property_struct_type(prop, "Object"); + RNA_def_property_collection_funcs(prop, NULL, NULL, NULL, "rna_SceneCollection_objects_get", NULL, NULL, NULL, NULL); + RNA_def_property_ui_text(prop, "Objects", "All the objects directly added to this collection (not including sub-collection objects)"); + rna_def_collection_objects(brna, prop); + + prop = RNA_def_property(srna, "filters_objects", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_sdna(prop, NULL, "filter_objects", NULL); + RNA_def_property_struct_type(prop, "Object"); + RNA_def_property_collection_funcs(prop, NULL, NULL, NULL, "rna_SceneCollection_objects_get", NULL, NULL, NULL, NULL); + RNA_def_property_ui_text(prop, "Filter Objects", "All the objects dynamically added to this collection via the filter"); +} + +static void rna_def_layer_collection_override(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "LayerCollectionOverride", NULL); + RNA_def_struct_sdna(srna, "CollectionOverride"); + RNA_def_struct_ui_text(srna, "Collection Override", "Collection Override"); + + prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); + RNA_def_property_ui_text(prop, "Name", "Collection name"); + RNA_def_struct_name_property(srna, prop); + RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, NULL); +} + +static void rna_def_layer_collection(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "LayerCollection", NULL); + RNA_def_struct_ui_text(srna, "Layer Collection", "Layer collection"); + + prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); + RNA_def_property_string_funcs(prop, "rna_LayerCollection_name_get", "rna_LayerCollection_name_length", "rna_LayerCollection_name_set"); + RNA_def_property_ui_text(prop, "Name", "Collection name"); + RNA_def_struct_name_property(srna, prop); + RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, NULL); + + prop = RNA_def_property(srna, "collection", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); + RNA_def_property_pointer_sdna(prop, NULL, "scene_collection"); + RNA_def_property_struct_type(prop, "SceneCollection"); + RNA_def_property_ui_text(prop, "Collection", "Collection this layer collection is wrapping"); + + prop = RNA_def_property(srna, "collections", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_sdna(prop, NULL, "layer_collections", NULL); + RNA_def_property_struct_type(prop, "LayerCollection"); + RNA_def_property_ui_text(prop, "Layer Collections", ""); + + prop = RNA_def_property(srna, "objects", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_sdna(prop, NULL, "object_bases", NULL); + RNA_def_property_struct_type(prop, "Object"); + RNA_def_property_collection_funcs(prop, NULL, NULL, NULL, "rna_LayerCollection_objects_get", NULL, NULL, NULL, NULL); + RNA_def_property_ui_text(prop, "Objects", "All the objects directly or indirectly added to this collection (not including sub-collection objects)"); + + prop = RNA_def_property(srna, "overrides", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_sdna(prop, NULL, "overrides", NULL); + RNA_def_property_struct_type(prop, "LayerCollectionOverride"); + RNA_def_property_ui_text(prop, "Collection Overrides", ""); + + /* Flags */ + prop = RNA_def_property(srna, "hide", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", COLLECTION_VISIBLE); + RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); + RNA_def_property_ui_icon(prop, ICON_RESTRICT_VIEW_OFF, 1); + RNA_def_property_ui_text(prop, "Hide", "Restrict visiblity"); + RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_LayerCollection_hide_update"); + + prop = RNA_def_property(srna, "hide_select", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", COLLECTION_SELECTABLE); + RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); + RNA_def_property_ui_icon(prop, ICON_RESTRICT_SELECT_OFF, 1); + RNA_def_property_ui_text(prop, "Hide Selectable", "Restrict selection"); + RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_LayerCollection_hide_select_update"); + + prop = RNA_def_property(srna, "is_unfolded", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", COLLECTION_FOLDED); + RNA_def_property_ui_icon(prop, ICON_RIGHTARROW, 1); + RNA_def_property_ui_text(prop, "Folded", "Folded collection"); + RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, NULL); + + /* TODO_LAYER_OVERRIDE */ +} + +static void rna_def_layer_collections(BlenderRNA *brna, PropertyRNA *cprop) +{ + StructRNA *srna; + FunctionRNA *func; + PropertyRNA *prop; + PropertyRNA *parm; + + RNA_def_property_srna(cprop, "LayerCollections"); + srna = RNA_def_struct(brna, "LayerCollections", NULL); + RNA_def_struct_sdna(srna, "SceneLayer"); + RNA_def_struct_ui_text(srna, "Layer Collections", "Collections of render layer"); + + prop = RNA_def_property(srna, "active_index", PROP_INT, PROP_UNSIGNED); + RNA_def_property_int_sdna(prop, NULL, "active_collection"); + RNA_def_property_int_funcs(prop, "rna_LayerCollections_active_collection_index_get", + "rna_LayerCollections_active_collection_index_set", + "rna_LayerCollections_active_collection_index_range"); + RNA_def_property_ui_text(prop, "Active Collection Index", "Active index in layer collection array"); + RNA_def_property_update(prop, NC_SCENE | ND_LAYER, NULL); + + prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "LayerCollection"); + RNA_def_property_pointer_funcs(prop, "rna_LayerCollections_active_collection_get", + "rna_LayerCollections_active_collection_set", NULL, NULL); + RNA_def_property_flag(prop, PROP_EDITABLE | PROP_NEVER_NULL); + RNA_def_property_ui_text(prop, "Active Layer Collection", "Active Layer Collection"); + RNA_def_property_update(prop, NC_SCENE | ND_LAYER, NULL); + + func = RNA_def_function(srna, "link", "rna_SceneLayer_collection_link"); + RNA_def_function_ui_description(func, "Link a collection to render layer"); + RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN); + parm = RNA_def_pointer(func, "scene_collection", "SceneCollection", "", "Collection to add to render layer"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_pointer(func, "result", "LayerCollection", "", "Newly created layer collection"); + RNA_def_function_return(func, parm); + + func = RNA_def_function(srna, "unlink", "rna_SceneLayer_collection_unlink"); + RNA_def_function_ui_description(func, "Unlink a collection from render layer"); + RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN | FUNC_USE_REPORTS); + parm = RNA_def_pointer(func, "layer_collection", "LayerCollection", "", "Layer collection to remove from render layer"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); +} + +static void rna_def_layer_objects(BlenderRNA *brna, PropertyRNA *cprop) +{ + StructRNA *srna; + PropertyRNA *prop; + + RNA_def_property_srna(cprop, "LayerObjects"); + srna = RNA_def_struct(brna, "LayerObjects", NULL); + RNA_def_struct_sdna(srna, "SceneLayer"); + RNA_def_struct_ui_text(srna, "Layer Objects", "Collections of objects"); + + prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "Object"); + RNA_def_property_pointer_funcs(prop, "rna_LayerObjects_active_object_get", "rna_LayerObjects_active_object_set", NULL, NULL); + RNA_def_property_flag(prop, PROP_EDITABLE | PROP_NEVER_UNLINK); + RNA_def_property_ui_text(prop, "Active Object", "Active object for this layer"); + /* Could call: ED_base_object_activate(C, rl->basact); + * but would be a bad level call and it seems the notifier is enough */ + RNA_def_property_update(prop, NC_SCENE | ND_OB_ACTIVE, NULL); + + prop = RNA_def_property(srna, "selected", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_sdna(prop, NULL, "object_bases", NULL); + RNA_def_property_struct_type(prop, "Object"); + RNA_def_property_collection_funcs(prop, "rna_LayerObjects_selected_begin", "rna_iterator_listbase_next", + "rna_iterator_listbase_end", "rna_SceneLayer_objects_get", + NULL, NULL, NULL, NULL); + RNA_def_property_ui_text(prop, "Selected Objects", "All the selected objects of this layer"); +} + +static void rna_def_scene_layer(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + static EnumPropertyItem engine_items[] = { + {0, "BLENDER_RENDER", 0, "Blender Render", "Use the Blender internal rendering engine for rendering"}, + {0, NULL, 0, NULL, NULL} + }; + + srna = RNA_def_struct(brna, "SceneLayer", NULL); + RNA_def_struct_ui_text(srna, "Render Layer", "Render layer"); + RNA_def_struct_ui_icon(srna, ICON_RENDERLAYERS); + + prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); + RNA_def_property_string_funcs(prop, NULL, NULL, "rna_SceneLayer_name_set"); + RNA_def_property_ui_text(prop, "Name", "Render layer name"); + RNA_def_struct_name_property(srna, prop); + RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, NULL); + + prop = RNA_def_property(srna, "collections", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_sdna(prop, NULL, "layer_collections", NULL); + RNA_def_property_struct_type(prop, "LayerCollection"); + RNA_def_property_ui_text(prop, "Layer Collections", ""); + rna_def_layer_collections(brna, prop); + + prop = RNA_def_property(srna, "objects", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_sdna(prop, NULL, "object_bases", NULL); + RNA_def_property_struct_type(prop, "Object"); + RNA_def_property_collection_funcs(prop, NULL, NULL, NULL, "rna_SceneLayer_objects_get", NULL, NULL, NULL, NULL); + RNA_def_property_ui_text(prop, "Objects", "All the objects in this layer"); + rna_def_layer_objects(brna, prop); + + /* layer options */ + prop = RNA_def_property(srna, "use", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", SCENE_LAYER_RENDER); + RNA_def_property_ui_text(prop, "Enabled", "Disable or enable the render layer"); + RNA_def_property_update(prop, NC_SCENE | ND_LAYER, NULL); + + /* engine */ + prop = RNA_def_property(srna, "engine", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, engine_items); + RNA_def_property_enum_funcs(prop, "rna_SceneLayer_engine_get", "rna_SceneLayer_engine_set", + "rna_SceneLayer_engine_itemf"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_ui_text(prop, "Engine", "Engine to use for rendering"); + RNA_def_property_update(prop, NC_WINDOW, "rna_SceneLayer_engine_update"); + + prop = RNA_def_property(srna, "has_multiple_engines", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_funcs(prop, "rna_SceneLayer_multiple_engines_get", NULL); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Multiple Engines", "More than one rendering engine is available"); +} + +static void rna_def_scene_layers(BlenderRNA *brna, PropertyRNA *cprop) +{ + StructRNA *srna; + FunctionRNA *func; + PropertyRNA *parm; + PropertyRNA *prop; + + RNA_def_property_srna(cprop, "SceneLayers"); + srna = RNA_def_struct(brna, "SceneLayers", NULL); + RNA_def_struct_sdna(srna, "Scene"); + RNA_def_struct_ui_text(srna, "Render Layers", "Collection of render layers"); + + prop = RNA_def_property(srna, "active_index", PROP_INT, PROP_UNSIGNED); + RNA_def_property_int_sdna(prop, NULL, "active_layer"); + RNA_def_property_int_funcs(prop, "rna_SceneLayer_active_layer_index_get", + "rna_SceneLayer_active_layer_index_set", + "rna_SceneLayer_active_layer_index_range"); + RNA_def_property_ui_text(prop, "Active Layer Index", "Active index in render layer array"); + RNA_def_property_update(prop, NC_SCENE | ND_LAYER, NULL); + + prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "SceneLayer"); + RNA_def_property_pointer_funcs(prop, "rna_SceneLayer_active_layer_get", + "rna_SceneLayer_active_layer_set", NULL, NULL); + RNA_def_property_flag(prop, PROP_EDITABLE | PROP_NEVER_NULL); + RNA_def_property_ui_text(prop, "Active Render Layer", "Active Render Layer"); + RNA_def_property_update(prop, NC_SCENE | ND_LAYER, NULL); + + func = RNA_def_function(srna, "new", "rna_SceneLayer_new"); + RNA_def_function_ui_description(func, "Add a render layer to scene"); + RNA_def_function_flag(func, FUNC_USE_SELF_ID); + parm = RNA_def_string(func, "name", "SceneLayer", 0, "", "New name for the render layer (not unique)"); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_pointer(func, "result", "SceneLayer", "", "Newly created render layer"); + RNA_def_function_return(func, parm); + + func = RNA_def_function(srna, "remove", "rna_SceneLayer_remove"); + RNA_def_function_ui_description(func, "Remove a render layer"); + RNA_def_function_flag(func, FUNC_USE_MAIN | FUNC_USE_REPORTS | FUNC_USE_SELF_ID); + parm = RNA_def_pointer(func, "layer", "SceneLayer", "", "Render layer to remove"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR); + RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0); +} + +static void rna_def_object_base(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "ObjectBase", NULL); + RNA_def_struct_sdna(srna, "Base"); + RNA_def_struct_ui_text(srna, "Object Base", "An object instance in a render layer"); + RNA_def_struct_ui_icon(srna, ICON_OBJECT_DATA); + + prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "object"); + RNA_def_property_ui_text(prop, "Object", "Object this base links to"); + + prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", BASE_SELECTED); + RNA_def_property_ui_text(prop, "Select", "Object base selection state"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_ObjectBase_select_update"); +} + +/* TODO LAYERS: legacy SceneRenderLayers, to be removed */ static void rna_def_scene_render_layer(BlenderRNA *brna) { @@ -6760,7 +7566,7 @@ static void rna_def_scene_objects(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS); parm = RNA_def_pointer(func, "object", "Object", "", "Object to add to scene"); RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); - parm = RNA_def_pointer(func, "base", "ObjectBase", "", "The newly created base"); + parm = RNA_def_pointer(func, "base", "ObjectBaseLegacy", "", "The newly created base"); RNA_def_function_return(func, parm); func = RNA_def_function(srna, "unlink", "rna_Scene_object_unlink"); @@ -6795,7 +7601,7 @@ static void rna_def_scene_bases(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_struct_ui_text(srna, "Scene Bases", "Collection of scene bases"); prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE); - RNA_def_property_struct_type(prop, "ObjectBase"); + RNA_def_property_struct_type(prop, "ObjectBaseLegacy"); RNA_def_property_pointer_sdna(prop, NULL, "basact"); RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Active Base", "Active object base in the scene"); @@ -7039,7 +7845,7 @@ void RNA_def_scene(BlenderRNA *brna) /* Bases/Objects */ prop = RNA_def_property(srna, "object_bases", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "base", NULL); - RNA_def_property_struct_type(prop, "ObjectBase"); + RNA_def_property_struct_type(prop, "ObjectBaseLegacy"); RNA_def_property_ui_text(prop, "Bases", ""); RNA_def_property_collection_funcs(prop, NULL, NULL, NULL, NULL, NULL, NULL, "rna_Scene_object_bases_lookup_string", NULL); @@ -7385,6 +8191,19 @@ void RNA_def_scene(BlenderRNA *brna) RNA_def_property_struct_type(prop, "Depsgraph"); RNA_def_property_ui_text(prop, "Dependency Graph", "Dependencies in the scene data"); + /* Layer and Collections */ + prop = RNA_def_property(srna, "render_layers", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_sdna(prop, NULL, "render_layers", NULL); + RNA_def_property_struct_type(prop, "SceneLayer"); + RNA_def_property_ui_text(prop, "Render Layers", ""); + rna_def_scene_layers(brna, prop); + + prop = RNA_def_property(srna, "master_collection", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); + RNA_def_property_pointer_sdna(prop, NULL, "collection"); + RNA_def_property_struct_type(prop, "SceneCollection"); + RNA_def_property_ui_text(prop, "Master Collection", "Collection that contains all other collections"); + /* Nestled Data */ /* *** Non-Animated *** */ RNA_define_animate_sdna(false); @@ -7400,6 +8219,11 @@ void RNA_def_scene(BlenderRNA *brna) rna_def_transform_orientation(brna); rna_def_selected_uv_element(brna); rna_def_display_safe_areas(brna); + rna_def_scene_collection(brna); + rna_def_layer_collection(brna); + rna_def_layer_collection_override(brna); + rna_def_scene_layer(brna); + rna_def_object_base(brna); RNA_define_animate_sdna(true); /* *** Animated *** */ rna_def_scene_render_data(brna); diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index af4fb9d0d8a..9bfe70a7faa 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -79,6 +79,7 @@ EnumPropertyItem rna_enum_space_type_items[] = { {0, "", ICON_NONE, NULL, NULL}, {SPACE_BUTS, "PROPERTIES", ICON_BUTS, "Properties", "Edit properties of active object and related data-blocks"}, {SPACE_OUTLINER, "OUTLINER", ICON_OOPS, "Outliner", "Overview of scene graph and all available data-blocks"}, + {SPACE_COLLECTIONS, "COLLECTION_MANAGER", ICON_COLLAPSEMENU, "Collections", "Edit collections of active render layer"}, {SPACE_USERPREF, "USER_PREFERENCES", ICON_PREFERENCES, "User Preferences", "Edit persistent configuration settings"}, {SPACE_INFO, "INFO", ICON_INFO, "Info", "Main menu bar and list of error messages (drag down to expand and display)"}, {0, "", ICON_NONE, NULL, NULL}, @@ -208,6 +209,7 @@ static EnumPropertyItem buttons_context_items[] = { {BCONTEXT_TEXTURE, "TEXTURE", ICON_TEXTURE, "Texture", "Texture"}, {BCONTEXT_PARTICLE, "PARTICLES", ICON_PARTICLES, "Particles", "Particle"}, {BCONTEXT_PHYSICS, "PHYSICS", ICON_PHYSICS, "Physics", "Physics"}, + {BCONTEXT_COLLECTION, "COLLECTION", ICON_COLLAPSEMENU, "Collection", "Collection"}, {0, NULL, 0, NULL, NULL} }; @@ -315,6 +317,8 @@ static StructRNA *rna_Space_refine(struct PointerRNA *ptr) return &RNA_SpaceUserPreferences; case SPACE_CLIP: return &RNA_SpaceClipEditor; + case SPACE_COLLECTIONS: + return &RNA_SpaceCollectionManager; default: return &RNA_Space; } @@ -1076,6 +1080,10 @@ static EnumPropertyItem *rna_SpaceProperties_context_itemf(bContext *UNUSED(C), RNA_enum_items_add_value(&item, &totitem, buttons_context_items, BCONTEXT_SCENE); } + if (sbuts->pathflag & (1 << BCONTEXT_COLLECTION)) { + RNA_enum_items_add_value(&item, &totitem, buttons_context_items, BCONTEXT_COLLECTION); + } + if (sbuts->pathflag & (1 << BCONTEXT_WORLD)) { RNA_enum_items_add_value(&item, &totitem, buttons_context_items, BCONTEXT_WORLD); } @@ -4812,6 +4820,15 @@ static void rna_def_space_clip(BlenderRNA *brna) RNA_def_property_update(prop, NC_SPACE | ND_SPACE_CLIP, NULL); } +static void rna_def_space_collections(BlenderRNA *brna) +{ + StructRNA *srna; + + srna = RNA_def_struct(brna, "SpaceCollectionManager", "Space"); + RNA_def_struct_sdna(srna, "SpaceCollections"); + RNA_def_struct_ui_text(srna, "Space Collection Manager", "Layer Collection space data"); +} + void RNA_def_space(BlenderRNA *brna) { @@ -4838,6 +4855,7 @@ void RNA_def_space(BlenderRNA *brna) rna_def_space_node(brna); rna_def_space_logic(brna); rna_def_space_clip(brna); + rna_def_space_collections(brna); } #endif diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index e68e67586e9..29cb76f5029 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -2956,6 +2956,26 @@ static void rna_def_userdef_theme_space_clip(BlenderRNA *brna) rna_def_userdef_theme_spaces_curves(srna, false, false, false, true); } +static void rna_def_userdef_theme_space_collections(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "ThemeCollectionManager", NULL); + RNA_def_struct_sdna(srna, "ThemeSpace"); + RNA_def_struct_clear_flag(srna, STRUCT_UNDO); + RNA_def_struct_ui_text(srna, "Theme Collection Manager", "Theme settings for the Collection Manager"); + + rna_def_userdef_theme_spaces_main(srna); + rna_def_userdef_theme_spaces_list_main(srna); + + prop = RNA_def_property(srna, "selected_collection", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_float_sdna(prop, NULL, "hilite"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Selected Collection", ""); + RNA_def_property_update(prop, 0, "rna_userdef_update"); +} + static void rna_def_userdef_themes(BlenderRNA *brna) { StructRNA *srna; @@ -2982,6 +3002,7 @@ static void rna_def_userdef_themes(BlenderRNA *brna) {16, "FILE_BROWSER", ICON_FILESEL, "File Browser", ""}, {17, "CONSOLE", ICON_CONSOLE, "Python Console", ""}, {20, "CLIP_EDITOR", ICON_CLIP, "Movie Clip Editor", ""}, + {21, "COLLECTION_MANAGER", ICON_COLLAPSEMENU, "Collection Manager", ""}, {0, NULL, 0, NULL, NULL} }; @@ -3115,6 +3136,12 @@ static void rna_def_userdef_themes(BlenderRNA *brna) RNA_def_property_pointer_sdna(prop, NULL, "tclip"); RNA_def_property_struct_type(prop, "ThemeClipEditor"); RNA_def_property_ui_text(prop, "Clip Editor", ""); + + prop = RNA_def_property(srna, "collection_manager", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); + RNA_def_property_pointer_sdna(prop, NULL, "tcollections"); + RNA_def_property_struct_type(prop, "ThemeCollectionManager"); + RNA_def_property_ui_text(prop, "Collection Manager", ""); } static void rna_def_userdef_addon(BlenderRNA *brna) @@ -3205,6 +3232,7 @@ static void rna_def_userdef_dothemes(BlenderRNA *brna) rna_def_userdef_theme_space_console(brna); rna_def_userdef_theme_space_logic(brna); rna_def_userdef_theme_space_clip(brna); + rna_def_userdef_theme_space_collections(brna); rna_def_userdef_theme_colorset(brna); rna_def_userdef_themes(brna); } diff --git a/source/blender/modifiers/intern/MOD_fluidsim.c b/source/blender/modifiers/intern/MOD_fluidsim.c index bed25fa82db..35e9afe722b 100644 --- a/source/blender/modifiers/intern/MOD_fluidsim.c +++ b/source/blender/modifiers/intern/MOD_fluidsim.c @@ -109,7 +109,7 @@ static void updateDepsgraph(ModifierData *md, FluidsimModifierData *fluidmd = (FluidsimModifierData *) md; if (fluidmd && fluidmd->fss) { if (fluidmd->fss->type == OB_FLUIDSIM_DOMAIN) { - Base *base; + BaseLegacy *base; for (base = scene->base.first; base; base = base->next) { Object *ob1 = base->object; if (ob1 != ob) { diff --git a/source/blender/python/intern/bpy_rna_callback.c b/source/blender/python/intern/bpy_rna_callback.c index df1c4155a6d..b8c9b3ff9e9 100644 --- a/source/blender/python/intern/bpy_rna_callback.c +++ b/source/blender/python/intern/bpy_rna_callback.c @@ -174,6 +174,7 @@ static eSpace_Type rna_Space_refine_reverse(StructRNA *srna) if (srna == &RNA_SpaceConsole) return SPACE_CONSOLE; if (srna == &RNA_SpaceUserPreferences) return SPACE_USERPREF; if (srna == &RNA_SpaceClipEditor) return SPACE_CLIP; + if (srna == &RNA_SpaceCollectionManager) return SPACE_COLLECTIONS; return SPACE_EMPTY; } diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index 263ea3d4ef2..094e62e6ceb 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -4977,7 +4977,7 @@ static void add_group_render_dupli_obs(Render *re, Group *group, int nolamps, in static void database_init_objects(Render *re, unsigned int renderlay, int nolamps, int onlyselected, Object *actob, int timeoffset) { - Base *base; + BaseLegacy *base; Object *ob; Group *group; ObjectInstanceRen *obi; diff --git a/source/blender/render/intern/source/envmap.c b/source/blender/render/intern/source/envmap.c index d97e18d6511..7de20ab2056 100644 --- a/source/blender/render/intern/source/envmap.c +++ b/source/blender/render/intern/source/envmap.c @@ -247,7 +247,7 @@ static void envmap_transmatrix(float mat[4][4], int part) static void env_set_imats(Render *re) { - Base *base; + BaseLegacy *base; float mat[4][4]; base = re->scene->base.first; diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 52eca5f7005..34966e1b111 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -2015,7 +2015,7 @@ bool RE_allow_render_generic_object(Object *ob) static void tag_dependend_objects_for_render(Scene *scene, int renderlay) { Scene *sce_iter; - Base *base; + BaseLegacy *base; for (SETLOOPER(scene, sce_iter, base)) { Object *object = base->object; diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index 3bed4dac2cf..49e70b4f200 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -364,6 +364,7 @@ typedef struct wmNotifier { #define ND_SPACE_CHANGED (18<<16) /*sent to a new editor type after it's replaced an old one*/ #define ND_SPACE_CLIP (19<<16) #define ND_SPACE_FILE_PREVIEW (20<<16) +#define ND_SPACE_COLLECTIONS (21<<16) /* subtype, 256 entries too */ #define NOTE_SUBTYPE 0x0000FF00 diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c index e201fa433d4..4179ac7f993 100644 --- a/source/blender/windowmanager/intern/wm_keymap.c +++ b/source/blender/windowmanager/intern/wm_keymap.c @@ -1861,6 +1861,10 @@ wmKeyMap *WM_keymap_guess_opname(const bContext *C, const char *opname) else if (STRPREFIX(opname, "OUTLINER_OT")) { km = WM_keymap_find_all(C, "Outliner", sl->spacetype, 0); } + /* Layer Manager */ + else if (STRPREFIX(opname, "COLLECTIONS_OT")) { + km = WM_keymap_find_all(C, "Collection Manager", sl->spacetype, 0); + } /* Transform */ else if (STRPREFIX(opname, "TRANSFORM_OT")) { /* check for relevant editor */ diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c index 6b615f5a121..e74f6f3208c 100644 --- a/source/blenderplayer/bad_level_call_stubs/stubs.c +++ b/source/blenderplayer/bad_level_call_stubs/stubs.c @@ -45,6 +45,7 @@ struct ARegion; struct ARegionType; struct BMEditMesh; struct Base; +struct BaseLegacy; struct bContext; struct BoundBox; struct Brush; @@ -485,7 +486,8 @@ void ED_view3d_shade_update(struct Main *bmain, struct Scene *scene, struct View void ED_node_shader_default(const struct bContext *C, struct ID *id) RET_NONE void ED_screen_animation_timer_update(struct bScreen *screen, int redraws, int refresh) RET_NONE struct bScreen *ED_screen_animation_playing(const struct wmWindowManager *wm) RET_NULL -void ED_base_object_select(struct Base *base, short mode) RET_NONE +void ED_base_object_select(struct BaseLegacy *base, short mode) RET_NONE +void ED_object_base_select(struct Base *base, short mode) RET_NONE bool ED_object_modifier_remove(struct ReportList *reports, struct Main *bmain, struct Object *ob, struct ModifierData *md) RET_ZERO struct ModifierData *ED_object_modifier_add(struct ReportList *reports, struct Main *bmain, struct Scene *scene, struct Object *ob, const char *name, int type) RET_ZERO void ED_object_modifier_clear(struct Main *bmain, struct Object *ob) RET_NONE @@ -506,7 +508,7 @@ void uiLayoutSetAlignment(uiLayout *layout, char alignment) RET_NONE void uiLayoutSetScaleX(struct uiLayout *layout, float scale) RET_NONE void uiLayoutSetScaleY(struct uiLayout *layout, float scale) RET_NONE void uiTemplateIconView(struct uiLayout *layout, struct PointerRNA *ptr, const char *propname, int show_labels, float icon_scale) RET_NONE -void ED_base_object_free_and_unlink(struct Main *bmain, struct Scene *scene, struct Base *base) RET_NONE +void ED_base_object_free_and_unlink(struct Main *bmain, struct Scene *scene, struct Object *base) RET_NONE void ED_mesh_update(struct Mesh *mesh, struct bContext *C, int calc_edges, int calc_tessface) RET_NONE void ED_mesh_vertices_add(struct Mesh *mesh, struct ReportList *reports, int count) RET_NONE void ED_mesh_edges_add(struct Mesh *mesh, struct ReportList *reports, int count) RET_NONE diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index 4751e60996d..2aa0145d1f3 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -394,7 +394,7 @@ static void SetDefaultLightMode(Scene* scene) { default_light_mode = false; Scene *sce_iter; - Base *base; + BaseLegacy *base; for (SETLOOPER(scene, sce_iter, base)) { @@ -1736,11 +1736,11 @@ static void UNUSED_FUNCTION(print_active_constraints2)(Object *ob) //not used, u static void blenderSceneSetBackground(Scene *blenderscene) { Scene *it; - Base *base; + BaseLegacy *base; for (SETLOOPER(blenderscene, it, base)) { base->object->lay = base->lay; - base->object->flag = base->flag; + BKE_scene_base_flag_sync_from_base(base); } } @@ -1911,7 +1911,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie, Scene *blenderscene = kxscene->GetBlenderScene(); // for SETLOOPER Scene *sce_iter; - Base *base; + BaseLegacy *base; // Get the frame settings of the canvas. // Get the aspect ratio of the canvas as designed by the user. diff --git a/source/gameengine/Ketsji/KX_Light.cpp b/source/gameengine/Ketsji/KX_Light.cpp index 5f490747c2b..b2a480e99ca 100644 --- a/source/gameengine/Ketsji/KX_Light.cpp +++ b/source/gameengine/Ketsji/KX_Light.cpp @@ -34,6 +34,7 @@ #endif #include <stdio.h> +#include "DNA_scene_types.h" #include "KX_Light.h" #include "KX_Camera.h" @@ -44,7 +45,6 @@ #include "KX_PyMath.h" #include "DNA_object_types.h" -#include "DNA_scene_types.h" #include "DNA_lamp_types.h" #include "BKE_scene.h" diff --git a/source/gameengine/Ketsji/KX_Light.h b/source/gameengine/Ketsji/KX_Light.h index b446acd6e63..469f2d62b76 100644 --- a/source/gameengine/Ketsji/KX_Light.h +++ b/source/gameengine/Ketsji/KX_Light.h @@ -38,7 +38,7 @@ struct GPULamp; struct Scene; -struct Base; +struct BaseLegacy; class KX_Camera; class RAS_IRasterizer; class RAS_ILightObject; @@ -51,7 +51,7 @@ protected: RAS_ILightObject* m_lightobj; class RAS_IRasterizer* m_rasterizer; //needed for registering and replication of lightobj Scene* m_blenderscene; - Base* m_base; + BaseLegacy* m_base; public: KX_LightObject(void* sgReplicationInfo,SG_Callbacks callbacks,RAS_IRasterizer* rasterizer,RAS_ILightObject* lightobj, bool glsl); diff --git a/tests/python/CMakeLists.txt b/tests/python/CMakeLists.txt index 4b5666e9b5a..4e0283adf88 100644 --- a/tests/python/CMakeLists.txt +++ b/tests/python/CMakeLists.txt @@ -425,3 +425,10 @@ if(WITH_CYCLES) MESSAGE(STATUS "Disabling Cycles tests because tests folder does not exist") endif() endif() + +# ------------------------------------------------------------------------------ +# LAYER SYSTEM TESTS +add_test(render_layer ${TEST_BLENDER_EXE} + --python ${CMAKE_CURRENT_LIST_DIR}/bl_render_layer.py -- + --testdir="${TEST_SRC_DIR}/layers" +) diff --git a/tests/python/bl_render_layer.py b/tests/python/bl_render_layer.py new file mode 100644 index 00000000000..e0b1711c9dc --- /dev/null +++ b/tests/python/bl_render_layer.py @@ -0,0 +1,1040 @@ +# Apache License, Version 2.0 + +# ./blender.bin --background -noaudio --python tests/python/bl_render_layer.py -- --testdir="/data/lib/tests/" +import unittest + + +# ############################################################ +# Layer Collection Crawler +# ############################################################ + +def listbase_iter(data, struct, listbase): + element = data.get_pointer((struct, listbase, b'first')) + while element is not None: + yield element + element = element.get_pointer(b'next') + + +def linkdata_iter(collection, data): + element = collection.get_pointer((data, b'first')) + while element is not None: + yield element + element = element.get_pointer(b'next') + + +def get_layer_collection(layer_collection): + data = {} + flag = layer_collection.get(b'flag') + + data['is_visible'] = (flag & (1 << 0)) != 0; + data['is_selectable'] = (flag & (1 << 1)) != 0; + data['is_folded'] = (flag & (1 << 2)) != 0; + + scene_collection = layer_collection.get_pointer(b'scene_collection') + if scene_collection is None: + name = 'Fail!' + else: + name = scene_collection.get(b'name') + data['name'] = name + + objects = [] + for link in linkdata_iter(layer_collection, b'object_bases'): + ob_base = link.get_pointer(b'data') + ob = ob_base.get_pointer(b'object') + objects.append(ob.get((b'id', b'name'))[2:]) + data['objects'] = objects + + collections = {} + for nested_layer_collection in linkdata_iter(layer_collection, b'layer_collections'): + subname, subdata = get_layer_collection(nested_layer_collection) + collections[subname] = subdata + data['collections'] = collections + + return name, data + + +def get_layer(layer): + data = {} + name = layer.get(b'name') + + data['name'] = name + data['active_object'] = layer.get((b'basact', b'object', b'id', b'name'))[2:] + data['engine'] = layer.get(b'engine') + + objects = [] + for link in linkdata_iter(layer, b'object_bases'): + ob = link.get_pointer(b'object') + objects.append(ob.get((b'id', b'name'))[2:]) + data['objects'] = objects + + collections = {} + for layer_collection in linkdata_iter(layer, b'layer_collections'): + subname, subdata = get_layer_collection(layer_collection) + collections[subname] = subdata + data['collections'] = collections + + return name, data + + +def get_layers(scene): + """Return all the render layers and their data""" + layers = {} + for layer in linkdata_iter(scene, b'render_layers'): + name, data = get_layer(layer) + layers[name] = data + return layers + + +def get_scene_collection_objects(collection, listbase): + objects = [] + for link in linkdata_iter(collection, listbase): + ob = link.get_pointer(b'data') + if ob is None: + name = 'Fail!' + else: + name = ob.get((b'id', b'name'))[2:] + objects.append(name) + return objects + + +def get_scene_collection(collection): + """""" + data = {} + name = collection.get(b'name') + + data['name'] = name + data['filter'] = collection.get(b'filter') + + data['objects'] = get_scene_collection_objects(collection, b'objects') + data['filter_objects'] = get_scene_collection_objects(collection, b'filter_objects') + + collections = {} + for nested_collection in linkdata_iter(collection, b'scene_collections'): + subname, subdata = get_scene_collection(nested_collection) + collections[subname] = subdata + data['collections'] = collections + + return name, data + + +def get_scene_collections(scene): + """Return all the scene collections ahd their data""" + master_collection = scene.get_pointer(b'collection') + return get_scene_collection(master_collection) + + +def query_scene(filepath, name, callbacks): + """Return the equivalent to bpy.context.scene""" + import blendfile + with blendfile.open_blend(filepath) as blend: + scenes = [block for block in blend.blocks if block.code == b'SC'] + for scene in scenes: + if scene.get((b'id', b'name'))[2:] == name: + output = [] + for callback in callbacks: + output.append(callback(scene)) + return output + + +# ############################################################ +# Utils +# ############################################################ + +def import_blendfile(): + import bpy + import os, sys + path = os.path.join( + bpy.utils.resource_path('LOCAL'), + 'scripts', + 'addons', + 'io_blend_utils', + 'blend', + ) + + if path not in sys.path: + sys.path.append(path) + + +def dump(data): + import json + return json.dumps( + data, + sort_keys=True, + indent=4, + separators=(',', ': '), + ) + + +# ############################################################ +# Tests +# ############################################################ + +PDB = False +DUMP_DIFF = True + +def compare_files(file_a, file_b): + import filecmp + + if not filecmp.cmp( + file_a, + file_b): + + if DUMP_DIFF: + import subprocess + subprocess.call(["diff", "-u", file_a, file_b]) + + if PDB: + import pdb + print("Files differ:", file_a, file_b) + pdb.set_trace() + + return False + + return True + + +class UnitsTesting(unittest.TestCase): + _test_simple = False + + @classmethod + def setUpClass(cls): + """Runs once""" + cls.pretest_import_blendfile() + cls.pretest_parsing() + + @classmethod + def setUp(cls): + """Runs once per test""" + import bpy + bpy.ops.wm.read_factory_settings() + + def path_exists(self, filepath): + import os + self.assertTrue( + os.path.exists(filepath), + "Test file \"{0}\" not found".format(filepath)) + + @classmethod + def get_root(cls): + """ + return the folder with the test files + """ + arguments = {} + for argument in extra_arguments: + name, value = argument.split('=') + cls.assertTrue(name and name.startswith("--"), "Invalid argument \"{0}\"".format(argument)) + cls.assertTrue(value, "Invalid argument \"{0}\"".format(argument)) + arguments[name[2:]] = value.strip('"') + + return arguments.get('testdir') + + @classmethod + def pretest_parsing(cls): + """ + Test if the arguments are properly set, and store ROOT + name has extra _ because we need this test to run first + """ + root = cls.get_root() + cls.assertTrue(root, "Testdir not set") + + @staticmethod + def pretest_import_blendfile(): + """ + Make sure blendfile imports with no problems + name has extra _ because we need this test to run first + """ + import_blendfile() + import blendfile + + def do_scene_write_read(self, filepath_layers, filepath_layers_json, data_callbacks, do_read): + """ + See if write/read is working for scene collections and layers + """ + import bpy + import os + import tempfile + import filecmp + + with tempfile.TemporaryDirectory() as dirpath: + (self.path_exists(f) for f in (filepath_layers, filepath_layers_json)) + + filepath_doversion = os.path.join(dirpath, 'doversion.blend') + filepath_saved = os.path.join(dirpath, 'doversion_saved.blend') + filepath_read_json = os.path.join(dirpath, "read.json") + + # doversion + write test + bpy.ops.wm.open_mainfile('EXEC_DEFAULT', filepath=filepath_layers) + bpy.ops.wm.save_mainfile('EXEC_DEFAULT', filepath=filepath_doversion) + + datas = query_scene(filepath_doversion, 'Main', data_callbacks) + self.assertTrue(datas, "Data is not valid") + + filepath_doversion_json = os.path.join(dirpath, "doversion.json") + with open(filepath_doversion_json, "w") as f: + for data in datas: + f.write(dump(data)) + + self.assertTrue(compare_files( + filepath_doversion_json, + filepath_layers_json, + ), + "Run: test_scene_write_layers") + + if do_read: + # read test, simply open and save the file + bpy.ops.wm.open_mainfile('EXEC_DEFAULT', filepath=filepath_doversion) + bpy.ops.wm.save_mainfile('EXEC_DEFAULT', filepath=filepath_saved) + + datas = query_scene(filepath_saved, 'Main', data_callbacks) + self.assertTrue(datas, "Data is not valid") + + with open(filepath_read_json, "w") as f: + for data in datas: + f.write(dump(data)) + + self.assertTrue(compare_files( + filepath_read_json, + filepath_layers_json, + ), + "Scene dump files differ") + + def test_scene_write_collections(self): + """ + See if the doversion and writing are working for scene collections + """ + import os + + ROOT = self.get_root() + filepath_layers = os.path.join(ROOT, 'layers.blend') + filepath_layers_json = os.path.join(ROOT, 'layers_simple.json') + + self.do_scene_write_read( + filepath_layers, + filepath_layers_json, + (get_scene_collections,), + False) + + def test_scene_write_layers(self): + """ + See if the doversion and writing are working for collections and layers + """ + import os + + ROOT = self.get_root() + filepath_layers = os.path.join(ROOT, 'layers.blend') + filepath_layers_json = os.path.join(ROOT, 'layers.json') + + self.do_scene_write_read( + filepath_layers, + filepath_layers_json, + (get_scene_collections, get_layers), + False) + + def test_scene_read_collections(self): + """ + See if read is working for scene collections + (run `test_scene_write_colections` first) + """ + import os + + ROOT = self.get_root() + filepath_layers = os.path.join(ROOT, 'layers.blend') + filepath_layers_json = os.path.join(ROOT, 'layers_simple.json') + + self.do_scene_write_read( + filepath_layers, + filepath_layers_json, + (get_scene_collections,), + True) + + def test_scene_read_layers(self): + """ + See if read is working for scene layers + (run `test_scene_write_layers` first) + """ + import os + + ROOT = self.get_root() + filepath_layers = os.path.join(ROOT, 'layers.blend') + filepath_layers_json = os.path.join(ROOT, 'layers.json') + + self.do_scene_write_read( + filepath_layers, + filepath_layers_json, + (get_scene_collections, get_layers), + True) + + def do_scene_copy(self, filepath_json_reference, copy_mode, data_callbacks): + import bpy + import os + import tempfile + import filecmp + + ROOT = self.get_root() + with tempfile.TemporaryDirectory() as dirpath: + filepath_layers = os.path.join(ROOT, 'layers.blend') + + (self.path_exists(f) for f in ( + filepath_layers, + filepath_json_reference, + )) + + filepath_saved = os.path.join(dirpath, '{0}.blend'.format(copy_mode)) + filepath_json = os.path.join(dirpath, "{0}.json".format(copy_mode)) + + bpy.ops.wm.open_mainfile('EXEC_DEFAULT', filepath=filepath_layers) + bpy.ops.scene.new(type=copy_mode) + bpy.ops.wm.save_mainfile('EXEC_DEFAULT', filepath=filepath_saved) + + datas = query_scene(filepath_saved, 'Main.001', data_callbacks) + self.assertTrue(datas, "Data is not valid") + + with open(filepath_json, "w") as f: + for data in datas: + f.write(dump(data)) + + self.assertTrue(compare_files( + filepath_json, + filepath_json_reference, + ), + "Scene copy \"{0}\" test failed".format(copy_mode.title())) + + def test_scene_collections_copy_full(self): + """ + See if scene copying 'FULL_COPY' is working for scene collections + """ + import os + ROOT = self.get_root() + + filepath_layers_json_copy = os.path.join(ROOT, 'layers_copy_full_simple.json') + self.do_scene_copy( + filepath_layers_json_copy, + 'FULL_COPY', + (get_scene_collections,)) + + def test_scene_collections_link(self): + """ + See if scene copying 'LINK_OBJECTS' is working for scene collections + """ + import os + ROOT = self.get_root() + + # note: nothing should change, so using `layers_simple.json` + filepath_layers_json_copy = os.path.join(ROOT, 'layers_simple.json') + self.do_scene_copy( + filepath_layers_json_copy, + 'LINK_OBJECTS', + (get_scene_collections,)) + + def test_scene_layers_copy(self): + """ + See if scene copying 'FULL_COPY' is working for scene layers + """ + import os + ROOT = self.get_root() + + filepath_layers_json_copy = os.path.join(ROOT, 'layers_copy_full.json') + self.do_scene_copy( + filepath_layers_json_copy, + 'FULL_COPY', + (get_scene_collections, get_layers)) + + def test_scene_layers_link(self): + """ + See if scene copying 'FULL_COPY' is working for scene layers + """ + import os + ROOT = self.get_root() + + filepath_layers_json_copy = os.path.join(ROOT, 'layers_copy_link.json') + self.do_scene_copy( + filepath_layers_json_copy, + 'LINK_OBJECTS', + (get_scene_collections, get_layers)) + + def do_syncing(self, filepath_json, unlink_mode): + import bpy + import os + import tempfile + import filecmp + + ROOT = self.get_root() + with tempfile.TemporaryDirectory() as dirpath: + filepath_layers = os.path.join(ROOT, 'layers.blend') + + # open file + bpy.ops.wm.open_mainfile('EXEC_DEFAULT', filepath=filepath_layers) + + # create sub-collections + three_b = bpy.data.objects.get('T.3b') + three_c = bpy.data.objects.get('T.3c') + three_d = bpy.data.objects.get('T.3d') + + scene = bpy.context.scene + + subzero = scene.master_collection.collections['1'].collections.new('sub-zero') + scorpion = scene.master_collection.collections['1'].collections.new('scorpion') + + # test linking sync + subzero.objects.link(three_b) + scorpion.objects.link(three_c) + + # test unlinking sync + if unlink_mode in {'OBJECT', 'COLLECTION'}: + scorpion.objects.link(three_d) + scorpion.objects.unlink(three_d) + + if unlink_mode == 'COLLECTION': + scorpion.objects.link(three_d) + scene.master_collection.collections['1'].collections.remove(subzero) + scene.master_collection.collections['1'].collections.remove(scorpion) + + # save file + filepath_nested = os.path.join(dirpath, 'nested.blend') + bpy.ops.wm.save_mainfile('EXEC_DEFAULT', filepath=filepath_nested) + + # get the generated json + datas = query_scene(filepath_nested, 'Main', (get_scene_collections, get_layers)) + self.assertTrue(datas, "Data is not valid") + + filepath_nested_json = os.path.join(dirpath, "nested.json") + with open(filepath_nested_json, "w") as f: + for data in datas: + f.write(dump(data)) + + self.assertTrue(compare_files( + filepath_nested_json, + filepath_json, + ), + "Scene dump files differ") + + def test_syncing_link(self): + """ + See if scene collections and layer collections are in sync + when we create new subcollections and link new objects + """ + import os + ROOT = self.get_root() + filepath_json = os.path.join(ROOT, 'layers_nested.json') + self.do_syncing(filepath_json, 'NONE') + + def test_syncing_unlink_object(self): + """ + See if scene collections and layer collections are in sync + when we create new subcollections, link new objects and unlink + some. + """ + import os + ROOT = self.get_root() + filepath_json = os.path.join(ROOT, 'layers_nested.json') + self.do_syncing(filepath_json, 'OBJECT') + + def test_syncing_unlink_collection(self): + """ + See if scene collections and layer collections are in sync + when we create new subcollections, link new objects and unlink full collections + some. + """ + import os + ROOT = self.get_root() + filepath_json = os.path.join(ROOT, 'layers.json') + self.do_syncing(filepath_json, 'COLLECTION') + + def do_layer_linking(self, filepath_json, link_mode): + import bpy + import os + import tempfile + import filecmp + + ROOT = self.get_root() + with tempfile.TemporaryDirectory() as dirpath: + filepath_layers = os.path.join(ROOT, 'layers.blend') + + # open file + bpy.ops.wm.open_mainfile('EXEC_DEFAULT', filepath=filepath_layers) + + # create sub-collections + three_b = bpy.data.objects.get('T.3b') + three_c = bpy.data.objects.get('T.3c') + + scene = bpy.context.scene + + subzero = scene.master_collection.collections['1'].collections.new('sub-zero') + scorpion = subzero.collections.new('scorpion') + + # test linking sync + subzero.objects.link(three_b) + scorpion.objects.link(three_c) + + # test unlinking sync + layer = scene.render_layers.new('Fresh new Layer') + + if link_mode in {'COLLECTION_LINK', 'COLLECTION_UNLINK'}: + layer.collections.link(subzero) + + if link_mode == 'COLLECTION_UNLINK': + initial_collection = layer.collections['Master Collection'] + layer.collections.unlink(initial_collection) + + # save file + filepath_nested = os.path.join(dirpath, 'nested.blend') + bpy.ops.wm.save_mainfile('EXEC_DEFAULT', filepath=filepath_nested) + + # get the generated json + datas = query_scene(filepath_nested, 'Main', (get_scene_collections, get_layers)) + self.assertTrue(datas, "Data is not valid") + + filepath_nested_json = os.path.join(dirpath, "nested.json") + with open(filepath_nested_json, "w") as f: + for data in datas: + f.write(dump(data)) + + self.assertTrue(compare_files( + filepath_nested_json, + filepath_json, + ), + "Scene dump files differ") + + def test_syncing_layer_new(self): + """ + See if the creation of new layers is going well + """ + import os + ROOT = self.get_root() + filepath_json = os.path.join(ROOT, 'layers_new_layer.json') + self.do_layer_linking(filepath_json, 'LAYER_NEW') + + def test_syncing_layer_collection_link(self): + """ + See if the creation of new layers is going well + And linking a new scene collection in the layer works + """ + import os + ROOT = self.get_root() + filepath_json = os.path.join(ROOT, 'layers_layer_collection_link.json') + self.do_layer_linking(filepath_json, 'COLLECTION_LINK') + + def test_syncing_layer_collection_unlink(self): + """ + See if the creation of new layers is going well + And unlinking the origin scene collection works + """ + import os + ROOT = self.get_root() + filepath_json = os.path.join(ROOT, 'layers_layer_collection_unlink.json') + self.do_layer_linking(filepath_json, 'COLLECTION_UNLINK') + + def test_active_collection(self): + """ + See if active collection index is working + layer.collections.active_index works recursively + """ + import bpy + import os + + ROOT = self.get_root() + filepath_layers = os.path.join(ROOT, 'layers.blend') + + # open file + bpy.ops.wm.open_mainfile('EXEC_DEFAULT', filepath=filepath_layers) + + # create sub-collections + three_b = bpy.data.objects.get('T.3b') + three_c = bpy.data.objects.get('T.3c') + + scene = bpy.context.scene + subzero = scene.master_collection.collections['1'].collections.new('sub-zero') + scorpion = subzero.collections.new('scorpion') + subzero.objects.link(three_b) + scorpion.objects.link(three_c) + layer = scene.render_layers.new('Fresh new Layer') + layer.collections.link(subzero) + + lookup = [ + 'Master Collection', + '1', + 'sub-zero', + 'scorpion', + '2', + '3', + '4', + '5', + 'sub-zero', + 'scorpion'] + + for i, name in enumerate(lookup): + layer.collections.active_index = i + self.assertEqual(name, layer.collections.active.name, + "Collection index mismatch: [{0}] : {1} != {2}".format( + i, name, layer.collections.active.name)) + + def do_object_delete(self, del_mode): + import bpy + import os + import tempfile + import filecmp + + ROOT = self.get_root() + with tempfile.TemporaryDirectory() as dirpath: + filepath_layers = os.path.join(ROOT, 'layers.blend') + filepath_reference_json = os.path.join(ROOT, 'layers_object_delete.json') + + # open file + bpy.ops.wm.open_mainfile('EXEC_DEFAULT', filepath=filepath_layers) + + # create sub-collections + three_b = bpy.data.objects.get('T.3b') + three_d = bpy.data.objects.get('T.3d') + + scene = bpy.context.scene + + # mangle the file a bit with some objects linked across collections + subzero = scene.master_collection.collections['1'].collections.new('sub-zero') + scorpion = subzero.collections.new('scorpion') + subzero.objects.link(three_d) + scorpion.objects.link(three_b) + scorpion.objects.link(three_d) + + # object to delete + ob = three_d + + # delete object + if del_mode == 'DATA': + bpy.data.objects.remove(ob, do_unlink=True) + + elif del_mode == 'OPERATOR': + bpy.ops.object.select_all(action='DESELECT') + ob.select_set(action='SELECT') + bpy.ops.object.delete() + + # save file + filepath_generated = os.path.join(dirpath, 'generated.blend') + bpy.ops.wm.save_mainfile('EXEC_DEFAULT', filepath=filepath_generated) + + # get the generated json + datas = query_scene(filepath_generated, 'Main', (get_scene_collections, get_layers)) + self.assertTrue(datas, "Data is not valid") + + filepath_generated_json = os.path.join(dirpath, "generated.json") + with open(filepath_generated_json, "w") as f: + for data in datas: + f.write(dump(data)) + + self.assertTrue(compare_files( + filepath_generated_json, + filepath_reference_json, + ), + "Scene dump files differ") + + def test_object_delete_data(self): + """ + See if objects are removed correctly from all related collections + bpy.data.objects.remove() + """ + self.do_object_delete('DATA') + + def test_object_delete_operator(self): + """ + See if new objects are added to the correct collection + bpy.ops.object.del() + """ + self.do_object_delete('OPERATOR') + + def do_link(self, master_collection): + import bpy + self.assertEqual(master_collection.name, "Master Collection") + self.assertEqual(master_collection, bpy.context.scene.master_collection) + master_collection.objects.link(bpy.data.objects.new('object', None)) + + def test_link_scene(self): + """ + See if we can link objects + """ + import bpy + master_collection = bpy.context.scene.master_collection + self.do_link(master_collection) + + def test_link_context(self): + """ + See if we can link objects via bpy.context.scene_collection + """ + import bpy + bpy.context.scene.render_layers.active_index = len(bpy.context.scene.render_layers) - 1 + master_collection = bpy.context.scene_collection + self.do_link(master_collection) + + def test_operator_context(self): + """ + See if render layer context is properly set/get with operators overrides + when we set render_layer in context, the collection should change as well + """ + import bpy + import os + + class SampleOperator(bpy.types.Operator): + bl_idname = "testing.sample" + bl_label = "Sample Operator" + + render_layer = bpy.props.StringProperty( + default="Not Set", + options={'SKIP_SAVE'}, + ) + + scene_collection = bpy.props.StringProperty( + default="", + options={'SKIP_SAVE'}, + ) + + use_verbose = bpy.props.BoolProperty( + default=False, + options={'SKIP_SAVE'}, + ) + + def execute(self, context): + render_layer = context.render_layer + ret = {'FINISHED'} + + # this is simply playing safe + if render_layer.name != self.render_layer: + if self.use_verbose: + print('ERROR: Render Layer mismatch: "{0}" != "{1}"'.format( + render_layer.name, self.render_layer)) + ret = {'CANCELLED'} + + scene_collection_name = None + if self.scene_collection: + scene_collection_name = self.scene_collection + else: + scene_collection_name = render_layer.collections.active.name + + # while this is the real test + if context.scene_collection.name != scene_collection_name: + if self.use_verbose: + print('ERROR: Scene Collection mismatch: "{0}" != "{1}"'.format( + context.scene_collection.name, scene_collection_name)) + ret = {'CANCELLED'} + return ret + + bpy.utils.register_class(SampleOperator) + + # open sample file + ROOT = self.get_root() + filepath_layers = os.path.join(ROOT, 'layers.blend') + bpy.ops.wm.open_mainfile('EXEC_DEFAULT', filepath=filepath_layers) + + # change the file + three_b = bpy.data.objects.get('T.3b') + three_c = bpy.data.objects.get('T.3c') + scene = bpy.context.scene + subzero = scene.master_collection.collections['1'].collections.new('sub-zero') + scorpion = subzero.collections.new('scorpion') + subzero.objects.link(three_b) + scorpion.objects.link(three_c) + layer = scene.render_layers.new('Fresh new Layer') + layer.collections.unlink(layer.collections.active) + layer.collections.link(subzero) + layer.collections.active_index = 3 + self.assertEqual(layer.collections.active.name, 'scorpion') + + scene = bpy.context.scene + scene.render_layers.active_index = len(scene.render_layers) - 2 + self.assertEqual(scene.render_layers.active.name, "Render Layer") + + # old layer + self.assertEqual(bpy.ops.testing.sample(render_layer='Render Layer', use_verbose=True), {'FINISHED'}) + + # expected to fail + self.assertTrue(bpy.ops.testing.sample(render_layer=layer.name), {'CANCELLED'}) + + # set render layer and scene collection + override = bpy.context.copy() + override["render_layer"] = layer + override["scene_collection"] = subzero + self.assertEqual(bpy.ops.testing.sample(override, + render_layer=layer.name, + scene_collection=subzero.name, # 'sub-zero' + use_verbose=True), {'FINISHED'}) + + # set only render layer + override = bpy.context.copy() + override["render_layer"] = layer + + self.assertEqual(bpy.ops.testing.sample(override, + render_layer=layer.name, + scene_collection=layer.collections.active.name, # 'scorpion' + use_verbose=True), {'FINISHED'}) + + def do_object_add(self, filepath_json, add_mode): + import bpy + import os + import tempfile + import filecmp + + ROOT = self.get_root() + with tempfile.TemporaryDirectory() as dirpath: + filepath_layers = os.path.join(ROOT, 'layers.blend') + + # open file + bpy.ops.wm.open_mainfile('EXEC_DEFAULT', filepath=filepath_layers) + + # create sub-collections + three_b = bpy.data.objects.get('T.3b') + three_c = bpy.data.objects.get('T.3c') + + scene = bpy.context.scene + subzero = scene.master_collection.collections['1'].collections.new('sub-zero') + scorpion = subzero.collections.new('scorpion') + subzero.objects.link(three_b) + scorpion.objects.link(three_c) + layer = scene.render_layers.new('Fresh new Layer') + layer.collections.link(subzero) + + # change active collection + layer.collections.active_index = 3 + self.assertEqual(layer.collections.active.name, 'scorpion', "Run: test_syncing_object_add") + + # change active layer + override = bpy.context.copy() + override["render_layer"] = layer + override["scene_collection"] = layer.collections.active.collection + + # add new objects + if add_mode == 'EMPTY': + bpy.ops.object.add(override) # 'Empty' + + elif add_mode == 'CYLINDER': + bpy.ops.mesh.primitive_cylinder_add(override) # 'Cylinder' + + elif add_mode == 'TORUS': + bpy.ops.mesh.primitive_torus_add(override) # 'Torus' + + # save file + filepath_objects = os.path.join(dirpath, 'objects.blend') + bpy.ops.wm.save_mainfile('EXEC_DEFAULT', filepath=filepath_objects) + + # get the generated json + datas = query_scene(filepath_objects, 'Main', (get_scene_collections, get_layers)) + self.assertTrue(datas, "Data is not valid") + + filepath_objects_json = os.path.join(dirpath, "objects.json") + with open(filepath_objects_json, "w") as f: + for data in datas: + f.write(dump(data)) + + self.assertTrue(compare_files( + filepath_objects_json, + filepath_json, + ), + "Scene dump files differ") + + def test_syncing_object_add_empty(self): + """ + See if new objects are added to the correct collection + bpy.ops.object.add() + """ + import os + ROOT = self.get_root() + filepath_json = os.path.join(ROOT, 'layers_object_add_empty.json') + self.do_object_add(filepath_json, 'EMPTY') + + def test_syncing_object_add_cylinder(self): + """ + See if new objects are added to the correct collection + bpy.ops.mesh.primitive_cylinder_add() + """ + import os + ROOT = self.get_root() + filepath_json = os.path.join(ROOT, 'layers_object_add_cylinder.json') + self.do_object_add(filepath_json, 'CYLINDER') + + def test_syncing_object_add_torus(self): + """ + See if new objects are added to the correct collection + bpy.ops.mesh.primitive_torus_add() + """ + import os + ROOT = self.get_root() + filepath_json = os.path.join(ROOT, 'layers_object_add_torus.json') + self.do_object_add(filepath_json, 'TORUS') + + def do_copy_object(self, mode): + import bpy + import os + import tempfile + import filecmp + + ROOT = self.get_root() + with tempfile.TemporaryDirectory() as dirpath: + filepath_layers = os.path.join(ROOT, 'layers.blend') + filepath_json = os.path.join(ROOT, 'layers_object_copy_duplicate.json') + + # open file + bpy.ops.wm.open_mainfile('EXEC_DEFAULT', filepath=filepath_layers) + + # create sub-collections + three_b = bpy.data.objects.get('T.3b') + three_c = bpy.data.objects.get('T.3c') + + scene = bpy.context.scene + subzero = scene.master_collection.collections['1'].collections.new('sub-zero') + scorpion = subzero.collections.new('scorpion') + subzero.objects.link(three_b) + scorpion.objects.link(three_c) + layer = scene.render_layers.new('Fresh new Layer') + layer.collections.link(subzero) + + scene.render_layers.active_index = len(scene.render_layers) - 1 + + if mode == 'DUPLICATE': + # assuming the latest layer is the active layer + bpy.ops.object.select_all(action='DESELECT') + three_c.select_set(action='SELECT') + bpy.ops.object.duplicate() + + elif mode == 'NAMED': + bpy.ops.object.add_named(name=three_c.name) + + # save file + filepath_objects = os.path.join(dirpath, 'objects.blend') + bpy.ops.wm.save_mainfile('EXEC_DEFAULT', filepath=filepath_objects) + + # get the generated json + datas = query_scene(filepath_objects, 'Main', (get_scene_collections, get_layers)) + self.assertTrue(datas, "Data is not valid") + + filepath_objects_json = os.path.join(dirpath, "objects.json") + with open(filepath_objects_json, "w") as f: + for data in datas: + f.write(dump(data)) + + self.assertTrue(compare_files( + filepath_objects_json, + filepath_json, + ), + "Scene dump files differ") + + def test_copy_object(self): + """ + OBJECT_OT_duplicate + """ + self.do_copy_object('DUPLICATE') + + def test_copy_object_named(self): + """ + OBJECT_OT_add_named + """ + self.do_copy_object('NAMED') + + +# ############################################################ +# Main +# ############################################################ + +if __name__ == '__main__': + import sys + + global extra_arguments + extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else [] + + sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else []) + unittest.main() |