Objects: add Volume object type, and prototypes for Hair and PointCloud
Only the volume object is exposed in the user interface. It is based on OpenVDB internally. Drawing and rendering code will follow in another commit. https://wiki.blender.org/wiki/Source/Objects/Volume https://wiki.blender.org/wiki/Reference/Release_Notes/2.83/Volumes Hair and PointCloud object types are hidden behind a WITH_NEW_OBJECT_TYPES build option. These are unfinished, and included only to make it easier to cooperate on development in the future and avoid tricky merges. https://wiki.blender.org/wiki/Source/Objects/New_Object_Types Ref T73201, T68981 Differential Revision: https://developer.blender.org/D6945
This commit is contained in:
		@@ -319,6 +319,10 @@ mark_as_advanced(WITH_SYSTEM_GLOG)
 | 
			
		||||
# Freestyle
 | 
			
		||||
option(WITH_FREESTYLE     "Enable Freestyle (advanced edges rendering)" ON)
 | 
			
		||||
 | 
			
		||||
# New object types
 | 
			
		||||
option(WITH_NEW_OBJECT_TYPES "Enable new hair and pointcloud objects (use for development only, don't save in files)" OFF)
 | 
			
		||||
mark_as_advanced(WITH_NEW_OBJECT_TYPES)
 | 
			
		||||
 | 
			
		||||
# Misc
 | 
			
		||||
if(WIN32)
 | 
			
		||||
  option(WITH_INPUT_IME "Enable Input Method Editor (IME) for complex Asian character input" ON)
 | 
			
		||||
 
 | 
			
		||||
@@ -35,14 +35,17 @@ _modules = [
 | 
			
		||||
    "properties_data_curve",
 | 
			
		||||
    "properties_data_empty",
 | 
			
		||||
    "properties_data_gpencil",
 | 
			
		||||
    "properties_data_hair",
 | 
			
		||||
    "properties_data_light",
 | 
			
		||||
    "properties_data_lattice",
 | 
			
		||||
    "properties_data_mesh",
 | 
			
		||||
    "properties_data_metaball",
 | 
			
		||||
    "properties_data_modifier",
 | 
			
		||||
    "properties_data_pointcloud",
 | 
			
		||||
    "properties_data_shaderfx",
 | 
			
		||||
    "properties_data_lightprobe",
 | 
			
		||||
    "properties_data_speaker",
 | 
			
		||||
    "properties_data_volume",
 | 
			
		||||
    "properties_mask_common",
 | 
			
		||||
    "properties_material",
 | 
			
		||||
    "properties_material_gpencil",
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										78
									
								
								release/scripts/startup/bl_ui/properties_data_hair.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								release/scripts/startup/bl_ui/properties_data_hair.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,78 @@
 | 
			
		||||
# ##### 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
 | 
			
		||||
from rna_prop_ui import PropertyPanel
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DataButtonsPanel:
 | 
			
		||||
    bl_space_type = 'PROPERTIES'
 | 
			
		||||
    bl_region_type = 'WINDOW'
 | 
			
		||||
    bl_context = "data"
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def poll(cls, context):
 | 
			
		||||
        engine = context.scene.render.engine
 | 
			
		||||
        return hasattr(context, 'hair') and context.hair and (engine in cls.COMPAT_ENGINES)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DATA_PT_context_hair(DataButtonsPanel, Panel):
 | 
			
		||||
    bl_label = ""
 | 
			
		||||
    bl_options = {'HIDE_HEADER'}
 | 
			
		||||
    COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
 | 
			
		||||
 | 
			
		||||
    def draw(self, context):
 | 
			
		||||
        layout = self.layout
 | 
			
		||||
 | 
			
		||||
        ob = context.object
 | 
			
		||||
        hair = context.hair
 | 
			
		||||
        space = context.space_data
 | 
			
		||||
 | 
			
		||||
        if ob:
 | 
			
		||||
            layout.template_ID(ob, "data")
 | 
			
		||||
        elif hair:
 | 
			
		||||
            layout.template_ID(space, "pin_id")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DATA_PT_hair(DataButtonsPanel, Panel):
 | 
			
		||||
    bl_label = "Hair"
 | 
			
		||||
    COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
 | 
			
		||||
 | 
			
		||||
    def draw(self, context):
 | 
			
		||||
        layout = self.layout
 | 
			
		||||
        hair = context.hair
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
class DATA_PT_custom_props_hair(DataButtonsPanel, PropertyPanel, Panel):
 | 
			
		||||
    COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
 | 
			
		||||
    _context_path = "object.data"
 | 
			
		||||
    _property_type = bpy.types.Hair if hasattr(bpy.types, "Hair") else None
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
classes = (
 | 
			
		||||
    DATA_PT_context_hair,
 | 
			
		||||
    DATA_PT_hair,
 | 
			
		||||
    DATA_PT_custom_props_hair,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
if __name__ == "__main__":  # only for live edit.
 | 
			
		||||
    from bpy.utils import register_class
 | 
			
		||||
    for cls in classes:
 | 
			
		||||
        register_class(cls)
 | 
			
		||||
							
								
								
									
										78
									
								
								release/scripts/startup/bl_ui/properties_data_pointcloud.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								release/scripts/startup/bl_ui/properties_data_pointcloud.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,78 @@
 | 
			
		||||
# ##### 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
 | 
			
		||||
from rna_prop_ui import PropertyPanel
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DataButtonsPanel:
 | 
			
		||||
    bl_space_type = 'PROPERTIES'
 | 
			
		||||
    bl_region_type = 'WINDOW'
 | 
			
		||||
    bl_context = "data"
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def poll(cls, context):
 | 
			
		||||
        engine = context.scene.render.engine
 | 
			
		||||
        return hasattr(context, 'pointcloud') and context.pointcloud and (engine in cls.COMPAT_ENGINES)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DATA_PT_context_pointcloud(DataButtonsPanel, Panel):
 | 
			
		||||
    bl_label = ""
 | 
			
		||||
    bl_options = {'HIDE_HEADER'}
 | 
			
		||||
    COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
 | 
			
		||||
 | 
			
		||||
    def draw(self, context):
 | 
			
		||||
        layout = self.layout
 | 
			
		||||
 | 
			
		||||
        ob = context.object
 | 
			
		||||
        pointcloud = context.pointcloud
 | 
			
		||||
        space = context.space_data
 | 
			
		||||
 | 
			
		||||
        if ob:
 | 
			
		||||
            layout.template_ID(ob, "data")
 | 
			
		||||
        elif pointcloud:
 | 
			
		||||
            layout.template_ID(space, "pin_id")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DATA_PT_pointcloud(DataButtonsPanel, Panel):
 | 
			
		||||
    bl_label = "Point Cloud"
 | 
			
		||||
    COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
 | 
			
		||||
 | 
			
		||||
    def draw(self, context):
 | 
			
		||||
        layout = self.layout
 | 
			
		||||
        pointcloud = context.pointcloud
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
class DATA_PT_custom_props_pointcloud(DataButtonsPanel, PropertyPanel, Panel):
 | 
			
		||||
    COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
 | 
			
		||||
    _context_path = "object.data"
 | 
			
		||||
    _property_type = bpy.types.PointCloud if hasattr(bpy.types, "PointCloud") else None
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
classes = (
 | 
			
		||||
    DATA_PT_context_pointcloud,
 | 
			
		||||
    DATA_PT_pointcloud,
 | 
			
		||||
    DATA_PT_custom_props_pointcloud,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
if __name__ == "__main__":  # only for live edit.
 | 
			
		||||
    from bpy.utils import register_class
 | 
			
		||||
    for cls in classes:
 | 
			
		||||
        register_class(cls)
 | 
			
		||||
							
								
								
									
										173
									
								
								release/scripts/startup/bl_ui/properties_data_volume.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										173
									
								
								release/scripts/startup/bl_ui/properties_data_volume.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,173 @@
 | 
			
		||||
# ##### 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
 | 
			
		||||
from rna_prop_ui import PropertyPanel
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DataButtonsPanel:
 | 
			
		||||
    bl_space_type = 'PROPERTIES'
 | 
			
		||||
    bl_region_type = 'WINDOW'
 | 
			
		||||
    bl_context = "data"
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def poll(cls, context):
 | 
			
		||||
        engine = context.scene.render.engine
 | 
			
		||||
        return context.volume and (engine in cls.COMPAT_ENGINES)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DATA_PT_context_volume(DataButtonsPanel, Panel):
 | 
			
		||||
    bl_label = ""
 | 
			
		||||
    bl_options = {'HIDE_HEADER'}
 | 
			
		||||
    COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
 | 
			
		||||
 | 
			
		||||
    def draw(self, context):
 | 
			
		||||
        layout = self.layout
 | 
			
		||||
 | 
			
		||||
        ob = context.object
 | 
			
		||||
        volume = context.volume
 | 
			
		||||
        space = context.space_data
 | 
			
		||||
 | 
			
		||||
        if ob:
 | 
			
		||||
            layout.template_ID(ob, "data")
 | 
			
		||||
        elif volume:
 | 
			
		||||
            layout.template_ID(space, "pin_id")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DATA_PT_volume_file(DataButtonsPanel, Panel):
 | 
			
		||||
    bl_label = "OpenVDB File"
 | 
			
		||||
    COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
 | 
			
		||||
 | 
			
		||||
    def draw(self, context):
 | 
			
		||||
        layout = self.layout
 | 
			
		||||
 | 
			
		||||
        volume = context.volume
 | 
			
		||||
        volume.grids.load()
 | 
			
		||||
 | 
			
		||||
        layout.prop(volume, "filepath", text="")
 | 
			
		||||
 | 
			
		||||
        if len(volume.filepath):
 | 
			
		||||
            layout.use_property_split = True
 | 
			
		||||
            layout.use_property_decorate = False
 | 
			
		||||
 | 
			
		||||
            col = layout.column(align=True)
 | 
			
		||||
            col.prop(volume, "is_sequence")
 | 
			
		||||
            if volume.is_sequence:
 | 
			
		||||
                col.prop(volume, "frame_duration", text="Frames")
 | 
			
		||||
                col.prop(volume, "frame_start", text="Start")
 | 
			
		||||
                col.prop(volume, "frame_offset", text="Offset")
 | 
			
		||||
                col.prop(volume, "sequence_mode", text="Mode")
 | 
			
		||||
 | 
			
		||||
        error_msg = volume.grids.error_message
 | 
			
		||||
        if len(error_msg):
 | 
			
		||||
          layout.separator()
 | 
			
		||||
          col = layout.column(align=True)
 | 
			
		||||
          col.label(text="Failed to load volume:")
 | 
			
		||||
          col.label(text=error_msg)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class VOLUME_UL_grids(UIList):
 | 
			
		||||
    def draw_item(self, context, layout, data, grid, icon, active_data, active_propname, index):
 | 
			
		||||
        name = grid.name
 | 
			
		||||
        data_type = grid.bl_rna.properties['data_type'].enum_items[grid.data_type]
 | 
			
		||||
 | 
			
		||||
        layout.label(text=name)
 | 
			
		||||
        row = layout.row()
 | 
			
		||||
        row.alignment = 'RIGHT'
 | 
			
		||||
        row.active = False
 | 
			
		||||
        row.label(text=data_type.name)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DATA_PT_volume_grids(DataButtonsPanel, Panel):
 | 
			
		||||
    bl_label = "Grids"
 | 
			
		||||
    COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
 | 
			
		||||
 | 
			
		||||
    def draw(self, context):
 | 
			
		||||
        layout = self.layout
 | 
			
		||||
 | 
			
		||||
        volume = context.volume
 | 
			
		||||
        volume.grids.load()
 | 
			
		||||
 | 
			
		||||
        layout.template_list("VOLUME_UL_grids", "grids", volume, "grids", volume.grids, "active_index", rows=3)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DATA_PT_volume_render(DataButtonsPanel, Panel):
 | 
			
		||||
    bl_label = "Render"
 | 
			
		||||
    COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
 | 
			
		||||
 | 
			
		||||
    def draw(self, context):
 | 
			
		||||
        layout = self.layout
 | 
			
		||||
        layout.use_property_split = True
 | 
			
		||||
        layout.use_property_decorate = False
 | 
			
		||||
 | 
			
		||||
        scene = context.scene
 | 
			
		||||
        volume = context.volume
 | 
			
		||||
        render = volume.render
 | 
			
		||||
 | 
			
		||||
        col = layout.column(align=True)
 | 
			
		||||
        col.prop(render, "space")
 | 
			
		||||
        col.prop(render, "step_size")
 | 
			
		||||
 | 
			
		||||
        if scene.render.engine == 'CYCLES':
 | 
			
		||||
            col = layout.column(align=True)
 | 
			
		||||
            col.prop(render, "clipping")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DATA_PT_volume_viewport_display(DataButtonsPanel, Panel):
 | 
			
		||||
    bl_label = "Viewport Display"
 | 
			
		||||
    COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
 | 
			
		||||
 | 
			
		||||
    def draw(self, context):
 | 
			
		||||
        layout = self.layout
 | 
			
		||||
        layout.use_property_split = True
 | 
			
		||||
        layout.use_property_decorate = False
 | 
			
		||||
 | 
			
		||||
        volume = context.volume
 | 
			
		||||
        display = volume.display
 | 
			
		||||
 | 
			
		||||
        col = layout.column(align=True)
 | 
			
		||||
        col.prop(display, "wireframe_type")
 | 
			
		||||
        sub = col.row()
 | 
			
		||||
        sub.active = display.wireframe_type in {'BOXES', 'POINTS'}
 | 
			
		||||
        sub.prop(display, "wireframe_detail", text="Detail")
 | 
			
		||||
 | 
			
		||||
        layout.prop(display, "density")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DATA_PT_custom_props_volume(DataButtonsPanel, PropertyPanel, Panel):
 | 
			
		||||
    COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
 | 
			
		||||
    _context_path = "object.data"
 | 
			
		||||
    _property_type = bpy.types.Volume
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
classes = (
 | 
			
		||||
    DATA_PT_context_volume,
 | 
			
		||||
    DATA_PT_volume_grids,
 | 
			
		||||
    DATA_PT_volume_file,
 | 
			
		||||
    DATA_PT_volume_viewport_display,
 | 
			
		||||
    DATA_PT_volume_render,
 | 
			
		||||
    DATA_PT_custom_props_volume,
 | 
			
		||||
    VOLUME_UL_grids,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
if __name__ == "__main__":  # only for live edit.
 | 
			
		||||
    from bpy.utils import register_class
 | 
			
		||||
    for cls in classes:
 | 
			
		||||
        register_class(cls)
 | 
			
		||||
@@ -216,7 +216,7 @@ class OBJECT_PT_display(ObjectButtonsPanel, Panel):
 | 
			
		||||
 | 
			
		||||
        obj = context.object
 | 
			
		||||
        obj_type = obj.type
 | 
			
		||||
        is_geometry = (obj_type in {'MESH', 'CURVE', 'SURFACE', 'META', 'FONT'})
 | 
			
		||||
        is_geometry = (obj_type in {'MESH', 'CURVE', 'SURFACE', 'META', 'FONT', 'VOLUME', 'HAIR', 'POINTCLOUD'})
 | 
			
		||||
        is_wire = (obj_type in {'CAMERA', 'EMPTY'})
 | 
			
		||||
        is_empty_image = (obj_type == 'EMPTY' and obj.empty_display_type == 'IMAGE')
 | 
			
		||||
        is_dupli = (obj.instance_type != 'NONE')
 | 
			
		||||
 
 | 
			
		||||
@@ -126,6 +126,12 @@ class DopesheetFilterPopoverBase:
 | 
			
		||||
            flow.prop(dopesheet, "show_lattices", text="Lattices")
 | 
			
		||||
        if bpy.data.metaballs:
 | 
			
		||||
            flow.prop(dopesheet, "show_metaballs", text="Metaballs")
 | 
			
		||||
        if hasattr(bpy.data, "hairs") and bpy.data.hairs:
 | 
			
		||||
            flow.prop(dopesheet, "show_hairs", text="Hairs")
 | 
			
		||||
        if hasattr(bpy.data, "pointclouds") and bpy.data.pointclouds:
 | 
			
		||||
            flow.prop(dopesheet, "show_pointclouds", text="Point Clouds")
 | 
			
		||||
        if bpy.data.volumes:
 | 
			
		||||
            flow.prop(dopesheet, "show_volumes", text="Volumes")
 | 
			
		||||
 | 
			
		||||
        # data types
 | 
			
		||||
        flow.prop(dopesheet, "show_worlds", text="Worlds")
 | 
			
		||||
 
 | 
			
		||||
@@ -137,6 +137,9 @@ class FILEBROWSER_PT_filter(Panel):
 | 
			
		||||
            row = col.row()
 | 
			
		||||
            row.label(icon='FILE_TEXT')
 | 
			
		||||
            row.prop(params, "use_filter_text", text="Text Files", toggle=0)
 | 
			
		||||
            row = col.row()
 | 
			
		||||
            row.label(icon='FILE_VOLUME')
 | 
			
		||||
            row.prop(params, "use_filter_volume", text="Volume Files", toggle=0)
 | 
			
		||||
 | 
			
		||||
        col.separator()
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -76,7 +76,8 @@ class NODE_HT_header(Header):
 | 
			
		||||
 | 
			
		||||
                layout.separator_spacer()
 | 
			
		||||
 | 
			
		||||
                types_that_support_material = {'MESH', 'CURVE', 'SURFACE', 'FONT', 'META', 'GPENCIL'}
 | 
			
		||||
                types_that_support_material = {'MESH', 'CURVE', 'SURFACE', 'FONT', 'META',
 | 
			
		||||
                                               'GPENCIL', 'VOLUME', 'HAIR', 'POINTCLOUD'}
 | 
			
		||||
                # disable material slot buttons when pinned, cannot find correct slot within id_from (#36589)
 | 
			
		||||
                # disable also when the selected object does not support materials
 | 
			
		||||
                has_material_slots = not snode.pin and ob_type in types_that_support_material
 | 
			
		||||
 
 | 
			
		||||
@@ -397,6 +397,9 @@ class OUTLINER_PT_filter(Panel):
 | 
			
		||||
        if (
 | 
			
		||||
                bpy.data.curves or
 | 
			
		||||
                bpy.data.metaballs or
 | 
			
		||||
                (hasattr(bpy.data, "hairs") and bpy.data.hairs) or
 | 
			
		||||
                (hasattr(bpy.data, "pointclouds") and bpy.data.pointclouds) or
 | 
			
		||||
                bpy.data.volumes or
 | 
			
		||||
                bpy.data.lightprobes or
 | 
			
		||||
                bpy.data.lattices or
 | 
			
		||||
                bpy.data.fonts or
 | 
			
		||||
 
 | 
			
		||||
@@ -390,18 +390,23 @@ class USERPREF_PT_edit_objects_duplicate_data(EditingPanel, CenterAlignMixIn, Pa
 | 
			
		||||
        col.prop(edit, "use_duplicate_armature", text="Armature")
 | 
			
		||||
        col.prop(edit, "use_duplicate_curve", text="Curve")
 | 
			
		||||
        # col.prop(edit, "use_duplicate_fcurve", text="F-Curve")  # Not implemented.
 | 
			
		||||
        col.prop(edit, "use_duplicate_grease_pencil", text="Grease Pencil")
 | 
			
		||||
        if hasattr(edit, "use_duplicate_hair"):
 | 
			
		||||
            col.prop(edit, "use_duplicate_hair", text="Hair")
 | 
			
		||||
        col.prop(edit, "use_duplicate_light", text="Light")
 | 
			
		||||
        col.prop(edit, "use_duplicate_lightprobe", text="Light Probe")
 | 
			
		||||
        col = flow.column()
 | 
			
		||||
        col.prop(edit, "use_duplicate_lightprobe", text="Light Probe")
 | 
			
		||||
        col.prop(edit, "use_duplicate_material", text="Material")
 | 
			
		||||
        col.prop(edit, "use_duplicate_mesh", text="Mesh")
 | 
			
		||||
        col.prop(edit, "use_duplicate_metaball", text="Metaball")
 | 
			
		||||
        col.prop(edit, "use_duplicate_particle", text="Particle")
 | 
			
		||||
        col = flow.column()
 | 
			
		||||
        if hasattr(edit, "use_duplicate_pointcloud"):
 | 
			
		||||
            col.prop(edit, "use_duplicate_pointcloud", text="Point Cloud")
 | 
			
		||||
        col.prop(edit, "use_duplicate_surface", text="Surface")
 | 
			
		||||
        col.prop(edit, "use_duplicate_text", text="Text")
 | 
			
		||||
        # col.prop(edit, "use_duplicate_texture", text="Texture")  # Not implemented.
 | 
			
		||||
        col.prop(edit, "use_duplicate_grease_pencil", text="Grease Pencil")
 | 
			
		||||
        col.prop(edit, "use_duplicate_volume", text="Volume")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class USERPREF_PT_edit_cursor(EditingPanel, CenterAlignMixIn, Panel):
 | 
			
		||||
 
 | 
			
		||||
@@ -2157,6 +2157,16 @@ class VIEW3D_MT_camera_add(Menu):
 | 
			
		||||
        layout.operator("object.camera_add", text="Camera", icon='OUTLINER_OB_CAMERA')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class VIEW3D_MT_volume_add(Menu):
 | 
			
		||||
    bl_idname = "VIEW3D_MT_volume_add"
 | 
			
		||||
    bl_label = "Volume"
 | 
			
		||||
 | 
			
		||||
    def draw(self, _context):
 | 
			
		||||
        layout = self.layout
 | 
			
		||||
        layout.operator("object.volume_import", text="Import OpenVDB...", icon='OUTLINER_DATA_VOLUME')
 | 
			
		||||
        layout.operator("object.volume_add", text="Empty", icon='OUTLINER_DATA_VOLUME')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class VIEW3D_MT_add(Menu):
 | 
			
		||||
    bl_label = "Add"
 | 
			
		||||
    bl_translation_context = i18n_contexts.operator_default
 | 
			
		||||
@@ -2179,6 +2189,11 @@ class VIEW3D_MT_add(Menu):
 | 
			
		||||
        layout.menu("VIEW3D_MT_surface_add", icon='OUTLINER_OB_SURFACE')
 | 
			
		||||
        layout.menu("VIEW3D_MT_metaball_add", text="Metaball", icon='OUTLINER_OB_META')
 | 
			
		||||
        layout.operator("object.text_add", text="Text", icon='OUTLINER_OB_FONT')
 | 
			
		||||
        if hasattr(bpy.data, "hairs"):
 | 
			
		||||
            layout.operator("object.hair_add", text="Hair", icon='OUTLINER_OB_HAIR')
 | 
			
		||||
        if hasattr(bpy.data, "pointclouds"):
 | 
			
		||||
            layout.operator("object.pointcloud_add", text="Point Cloud", icon='OUTLINER_OB_POINTCLOUD')
 | 
			
		||||
        layout.menu("VIEW3D_MT_volume_add", text="Volume", icon='OUTLINER_OB_VOLUME')
 | 
			
		||||
        layout.operator_menu_enum("object.gpencil_add", "type", text="Grease Pencil", icon='OUTLINER_OB_GREASEPENCIL')
 | 
			
		||||
 | 
			
		||||
        layout.separator()
 | 
			
		||||
@@ -5428,6 +5443,9 @@ class VIEW3D_PT_object_type_visibility(Panel):
 | 
			
		||||
            ("surf", "Surface"),
 | 
			
		||||
            ("meta", "Meta"),
 | 
			
		||||
            ("font", "Text"),
 | 
			
		||||
            ("hair", "Hair"),
 | 
			
		||||
            ("pointcloud", "Point Cloud"),
 | 
			
		||||
            ("volume", "Volume"),
 | 
			
		||||
            ("grease_pencil", "Grease Pencil"),
 | 
			
		||||
            (None, None),
 | 
			
		||||
            # Other
 | 
			
		||||
@@ -5445,6 +5463,11 @@ class VIEW3D_PT_object_type_visibility(Panel):
 | 
			
		||||
                col.separator()
 | 
			
		||||
                continue
 | 
			
		||||
 | 
			
		||||
            if attr == "hair" and not hasattr(bpy.data, "hairs"):
 | 
			
		||||
                continue
 | 
			
		||||
            elif attr == "pointcloud" and not hasattr(bpy.data, "pointclouds"):
 | 
			
		||||
                continue
 | 
			
		||||
 | 
			
		||||
            attr_v = "show_object_viewport_" f"{attr:s}"
 | 
			
		||||
            attr_s = "show_object_select_" f"{attr:s}"
 | 
			
		||||
 | 
			
		||||
@@ -7254,6 +7277,7 @@ classes = (
 | 
			
		||||
    VIEW3D_MT_light_add,
 | 
			
		||||
    VIEW3D_MT_lightprobe_add,
 | 
			
		||||
    VIEW3D_MT_camera_add,
 | 
			
		||||
    VIEW3D_MT_volume_add,
 | 
			
		||||
    VIEW3D_MT_add,
 | 
			
		||||
    VIEW3D_MT_image_add,
 | 
			
		||||
    VIEW3D_MT_object,
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										71
									
								
								source/blender/blenkernel/BKE_hair.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								source/blender/blenkernel/BKE_hair.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,71 @@
 | 
			
		||||
/*
 | 
			
		||||
 * ***** BEGIN GPL LICENSE BLOCK *****
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU General Public License
 | 
			
		||||
 * as published by the Free Software Foundation; either version 2
 | 
			
		||||
 * of the License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 | 
			
		||||
 *
 | 
			
		||||
 * Contributor(s): Brecht Van Lommel.
 | 
			
		||||
 *
 | 
			
		||||
 * ***** END GPL LICENSE BLOCK *****
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __BKE_HAIR_H__
 | 
			
		||||
#define __BKE_HAIR_H__
 | 
			
		||||
 | 
			
		||||
/** \file BKE_hair.h
 | 
			
		||||
 *  \ingroup bke
 | 
			
		||||
 *  \brief General operations for hairs.
 | 
			
		||||
 */
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
struct BoundBox;
 | 
			
		||||
struct Depsgraph;
 | 
			
		||||
struct Hair;
 | 
			
		||||
struct Main;
 | 
			
		||||
struct Object;
 | 
			
		||||
struct Scene;
 | 
			
		||||
 | 
			
		||||
void *BKE_hair_add(struct Main *bmain, const char *name);
 | 
			
		||||
struct Hair *BKE_hair_copy(struct Main *bmain, const struct Hair *hair);
 | 
			
		||||
 | 
			
		||||
struct BoundBox *BKE_hair_boundbox_get(struct Object *ob);
 | 
			
		||||
 | 
			
		||||
void BKE_hair_update_customdata_pointers(struct Hair *hair);
 | 
			
		||||
 | 
			
		||||
/* Depsgraph */
 | 
			
		||||
 | 
			
		||||
struct Hair *BKE_hair_new_for_eval(const struct Hair *hair_src, int totpoint, int totcurve);
 | 
			
		||||
struct Hair *BKE_hair_copy_for_eval(struct Hair *hair_src, bool reference);
 | 
			
		||||
 | 
			
		||||
void BKE_hair_data_update(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *object);
 | 
			
		||||
 | 
			
		||||
/* Draw Cache */
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
  BKE_HAIR_BATCH_DIRTY_ALL = 0,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void BKE_hair_batch_cache_dirty_tag(struct Hair *hair, int mode);
 | 
			
		||||
void BKE_hair_batch_cache_free(struct Hair *hair);
 | 
			
		||||
 | 
			
		||||
extern void (*BKE_hair_batch_cache_dirty_tag_cb)(struct Hair *hair, int mode);
 | 
			
		||||
extern void (*BKE_hair_batch_cache_free_cb)(struct Hair *hair);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@@ -26,6 +26,8 @@
 | 
			
		||||
 * ID type structure, helping to factorize common operations and data for all data-block types.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "BLI_sys_types.h"
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
@@ -160,6 +162,9 @@ extern IDTypeInfo IDType_ID_PC;
 | 
			
		||||
extern IDTypeInfo IDType_ID_CF;
 | 
			
		||||
extern IDTypeInfo IDType_ID_WS;
 | 
			
		||||
extern IDTypeInfo IDType_ID_LP;
 | 
			
		||||
extern IDTypeInfo IDType_ID_HA;
 | 
			
		||||
extern IDTypeInfo IDType_ID_PT;
 | 
			
		||||
extern IDTypeInfo IDType_ID_VO;
 | 
			
		||||
 | 
			
		||||
/* ********** Helpers/Utils API. ********** */
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -144,6 +144,9 @@ typedef struct Main {
 | 
			
		||||
  ListBase linestyles;
 | 
			
		||||
  ListBase cachefiles;
 | 
			
		||||
  ListBase workspaces;
 | 
			
		||||
  ListBase hairs;
 | 
			
		||||
  ListBase pointclouds;
 | 
			
		||||
  ListBase volumes;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Must be generated, used and freed by same code - never assume this is valid data unless you
 | 
			
		||||
@@ -217,7 +220,7 @@ const char *BKE_main_blendfile_path_from_global(void);
 | 
			
		||||
 | 
			
		||||
struct ListBase *which_libbase(struct Main *mainlib, short type);
 | 
			
		||||
 | 
			
		||||
#define MAX_LIBARRAY 37
 | 
			
		||||
#define MAX_LIBARRAY 40
 | 
			
		||||
int set_listbasepointers(struct Main *main, struct ListBase *lb[MAX_LIBARRAY]);
 | 
			
		||||
 | 
			
		||||
#define MAIN_VERSION_ATLEAST(main, ver, subver) \
 | 
			
		||||
 
 | 
			
		||||
@@ -37,6 +37,7 @@ struct PackedFile;
 | 
			
		||||
struct ReportList;
 | 
			
		||||
struct VFont;
 | 
			
		||||
struct bSound;
 | 
			
		||||
struct Volume;
 | 
			
		||||
 | 
			
		||||
enum ePF_FileCompare {
 | 
			
		||||
  PF_CMP_EQUAL = 0,
 | 
			
		||||
@@ -84,6 +85,10 @@ int BKE_packedfile_unpack_image(struct Main *bmain,
 | 
			
		||||
                                struct ReportList *reports,
 | 
			
		||||
                                struct Image *ima,
 | 
			
		||||
                                enum ePF_FileStatus how);
 | 
			
		||||
int BKE_packedfile_unpack_volume(struct Main *bmain,
 | 
			
		||||
                                 struct ReportList *reports,
 | 
			
		||||
                                 struct Volume *volume,
 | 
			
		||||
                                 enum ePF_FileStatus how);
 | 
			
		||||
void BKE_packedfile_unpack_all(struct Main *bmain,
 | 
			
		||||
                               struct ReportList *reports,
 | 
			
		||||
                               enum ePF_FileStatus how);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										74
									
								
								source/blender/blenkernel/BKE_pointcloud.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								source/blender/blenkernel/BKE_pointcloud.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,74 @@
 | 
			
		||||
/*
 | 
			
		||||
 * ***** BEGIN GPL LICENSE BLOCK *****
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU General Public License
 | 
			
		||||
 * as published by the Free Software Foundation; either version 2
 | 
			
		||||
 * of the License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 | 
			
		||||
 *
 | 
			
		||||
 * Contributor(s): Brecht Van Lommel.
 | 
			
		||||
 *
 | 
			
		||||
 * ***** END GPL LICENSE BLOCK *****
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __BKE_POINTCLOUD_H__
 | 
			
		||||
#define __BKE_POINTCLOUD_H__
 | 
			
		||||
 | 
			
		||||
/** \file BKE_pointcloud.h
 | 
			
		||||
 *  \ingroup bke
 | 
			
		||||
 *  \brief General operations for pointclouds.
 | 
			
		||||
 */
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
struct BoundBox;
 | 
			
		||||
struct Depsgraph;
 | 
			
		||||
struct Main;
 | 
			
		||||
struct Object;
 | 
			
		||||
struct PointCloud;
 | 
			
		||||
struct Scene;
 | 
			
		||||
 | 
			
		||||
void *BKE_pointcloud_add(struct Main *bmain, const char *name);
 | 
			
		||||
struct PointCloud *BKE_pointcloud_copy(struct Main *bmain, const struct PointCloud *pointcloud);
 | 
			
		||||
 | 
			
		||||
struct BoundBox *BKE_pointcloud_boundbox_get(struct Object *ob);
 | 
			
		||||
 | 
			
		||||
void BKE_pointcloud_update_customdata_pointers(struct PointCloud *pointcloud);
 | 
			
		||||
 | 
			
		||||
/* Dependency Graph */
 | 
			
		||||
 | 
			
		||||
struct PointCloud *BKE_pointcloud_new_for_eval(const struct PointCloud *pointcloud_src,
 | 
			
		||||
                                               int totpoint);
 | 
			
		||||
struct PointCloud *BKE_pointcloud_copy_for_eval(struct PointCloud *pointcloud_src, bool reference);
 | 
			
		||||
 | 
			
		||||
void BKE_pointcloud_data_update(struct Depsgraph *depsgraph,
 | 
			
		||||
                                struct Scene *scene,
 | 
			
		||||
                                struct Object *object);
 | 
			
		||||
 | 
			
		||||
/* Draw Cache */
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
  BKE_POINTCLOUD_BATCH_DIRTY_ALL = 0,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void BKE_pointcloud_batch_cache_dirty_tag(struct PointCloud *pointcloud, int mode);
 | 
			
		||||
void BKE_pointcloud_batch_cache_free(struct PointCloud *pointcloud);
 | 
			
		||||
 | 
			
		||||
extern void (*BKE_pointcloud_batch_cache_dirty_tag_cb)(struct PointCloud *pointcloud, int mode);
 | 
			
		||||
extern void (*BKE_pointcloud_batch_cache_free_cb)(struct PointCloud *pointcloud);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										168
									
								
								source/blender/blenkernel/BKE_volume.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										168
									
								
								source/blender/blenkernel/BKE_volume.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,168 @@
 | 
			
		||||
/*
 | 
			
		||||
 * ***** BEGIN GPL LICENSE BLOCK *****
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU General Public License
 | 
			
		||||
 * as published by the Free Software Foundation; either version 2
 | 
			
		||||
 * of the License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 | 
			
		||||
 *
 | 
			
		||||
 * Contributor(s): Brecht Van Lommel.
 | 
			
		||||
 *
 | 
			
		||||
 * ***** END GPL LICENSE BLOCK *****
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __BKE_VOLUME_H__
 | 
			
		||||
#define __BKE_VOLUME_H__
 | 
			
		||||
 | 
			
		||||
/** \file BKE_volume.h
 | 
			
		||||
 *  \ingroup bke
 | 
			
		||||
 *  \brief Volume datablock.
 | 
			
		||||
 */
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
struct BoundBox;
 | 
			
		||||
struct Depsgraph;
 | 
			
		||||
struct Main;
 | 
			
		||||
struct Object;
 | 
			
		||||
struct Scene;
 | 
			
		||||
struct Volume;
 | 
			
		||||
struct VolumeGridVector;
 | 
			
		||||
 | 
			
		||||
/* Module */
 | 
			
		||||
 | 
			
		||||
void BKE_volumes_init(void);
 | 
			
		||||
 | 
			
		||||
/* Datablock Management */
 | 
			
		||||
 | 
			
		||||
void BKE_volume_init_grids(struct Volume *volume);
 | 
			
		||||
void *BKE_volume_add(struct Main *bmain, const char *name);
 | 
			
		||||
struct Volume *BKE_volume_copy(struct Main *bmain, const struct Volume *volume);
 | 
			
		||||
 | 
			
		||||
struct BoundBox *BKE_volume_boundbox_get(struct Object *ob);
 | 
			
		||||
 | 
			
		||||
bool BKE_volume_is_y_up(const struct Volume *volume);
 | 
			
		||||
bool BKE_volume_is_points_only(const struct Volume *volume);
 | 
			
		||||
 | 
			
		||||
/* Depsgraph */
 | 
			
		||||
 | 
			
		||||
void BKE_volume_eval_geometry(struct Depsgraph *depsgraph, struct Volume *volume);
 | 
			
		||||
void BKE_volume_data_update(struct Depsgraph *depsgraph,
 | 
			
		||||
                            struct Scene *scene,
 | 
			
		||||
                            struct Object *object);
 | 
			
		||||
 | 
			
		||||
void BKE_volume_grids_backup_restore(struct Volume *volume,
 | 
			
		||||
                                     struct VolumeGridVector *grids,
 | 
			
		||||
                                     const char *filepath);
 | 
			
		||||
 | 
			
		||||
/* Draw Cache */
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
  BKE_VOLUME_BATCH_DIRTY_ALL = 0,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void BKE_volume_batch_cache_dirty_tag(struct Volume *volume, int mode);
 | 
			
		||||
void BKE_volume_batch_cache_free(struct Volume *volume);
 | 
			
		||||
 | 
			
		||||
extern void (*BKE_volume_batch_cache_dirty_tag_cb)(struct Volume *volume, int mode);
 | 
			
		||||
extern void (*BKE_volume_batch_cache_free_cb)(struct Volume *volume);
 | 
			
		||||
 | 
			
		||||
/* Grids
 | 
			
		||||
 *
 | 
			
		||||
 * For volumes referencing a file, the list of grids and metadata must be
 | 
			
		||||
 * loaded before it can be accessed. This happens on-demand, only when needed
 | 
			
		||||
 * by the user interface, dependency graph or render engine. */
 | 
			
		||||
 | 
			
		||||
typedef struct VolumeGrid VolumeGrid;
 | 
			
		||||
 | 
			
		||||
bool BKE_volume_load(struct Volume *volume, struct Main *bmain);
 | 
			
		||||
void BKE_volume_unload(struct Volume *volume);
 | 
			
		||||
bool BKE_volume_is_loaded(const struct Volume *volume);
 | 
			
		||||
 | 
			
		||||
int BKE_volume_num_grids(const struct Volume *volume);
 | 
			
		||||
const char *BKE_volume_grids_error_msg(const struct Volume *volume);
 | 
			
		||||
VolumeGrid *BKE_volume_grid_get(const struct Volume *volume, int grid_index);
 | 
			
		||||
VolumeGrid *BKE_volume_grid_active_get(const struct Volume *volume);
 | 
			
		||||
VolumeGrid *BKE_volume_grid_find(const struct Volume *volume, const char *name);
 | 
			
		||||
 | 
			
		||||
/* Grid
 | 
			
		||||
 *
 | 
			
		||||
 * By default only grid metadata is loaded, for access to the tree and voxels
 | 
			
		||||
 * BKE_volume_grid_load must be called first. */
 | 
			
		||||
 | 
			
		||||
typedef enum VolumeGridType {
 | 
			
		||||
  VOLUME_GRID_UNKNOWN = 0,
 | 
			
		||||
  VOLUME_GRID_BOOLEAN,
 | 
			
		||||
  VOLUME_GRID_FLOAT,
 | 
			
		||||
  VOLUME_GRID_DOUBLE,
 | 
			
		||||
  VOLUME_GRID_INT,
 | 
			
		||||
  VOLUME_GRID_INT64,
 | 
			
		||||
  VOLUME_GRID_MASK,
 | 
			
		||||
  VOLUME_GRID_STRING,
 | 
			
		||||
  VOLUME_GRID_VECTOR_FLOAT,
 | 
			
		||||
  VOLUME_GRID_VECTOR_DOUBLE,
 | 
			
		||||
  VOLUME_GRID_VECTOR_INT,
 | 
			
		||||
  VOLUME_GRID_POINTS,
 | 
			
		||||
} VolumeGridType;
 | 
			
		||||
 | 
			
		||||
bool BKE_volume_grid_load(const struct Volume *volume, struct VolumeGrid *grid);
 | 
			
		||||
void BKE_volume_grid_unload(const struct Volume *volume, struct VolumeGrid *grid);
 | 
			
		||||
bool BKE_volume_grid_is_loaded(const struct VolumeGrid *grid);
 | 
			
		||||
 | 
			
		||||
/* Metadata */
 | 
			
		||||
const char *BKE_volume_grid_name(const struct VolumeGrid *grid);
 | 
			
		||||
VolumeGridType BKE_volume_grid_type(const struct VolumeGrid *grid);
 | 
			
		||||
int BKE_volume_grid_channels(const struct VolumeGrid *grid);
 | 
			
		||||
void BKE_volume_grid_transform_matrix(const struct VolumeGrid *grid, float mat[4][4]);
 | 
			
		||||
 | 
			
		||||
/* Bounds */
 | 
			
		||||
bool BKE_volume_grid_bounds(const struct VolumeGrid *grid, float min[3], float max[3]);
 | 
			
		||||
 | 
			
		||||
/* Volume Editing
 | 
			
		||||
 *
 | 
			
		||||
 * These are intended for modifiers to use on evaluated datablocks.
 | 
			
		||||
 *
 | 
			
		||||
 * new_for_eval creates a volume datablock with no grids or file path, but
 | 
			
		||||
 * preserves other settings such as viewport display options.
 | 
			
		||||
 *
 | 
			
		||||
 * copy_for_eval creates a volume datablock preserving everything except the
 | 
			
		||||
 * file path. Grids are shared with the source datablock, not copied. */
 | 
			
		||||
 | 
			
		||||
struct Volume *BKE_volume_new_for_eval(const struct Volume *volume_src);
 | 
			
		||||
struct Volume *BKE_volume_copy_for_eval(struct Volume *volume_src, bool reference);
 | 
			
		||||
 | 
			
		||||
struct VolumeGrid *BKE_volume_grid_add(struct Volume *volume,
 | 
			
		||||
                                       const char *name,
 | 
			
		||||
                                       VolumeGridType type);
 | 
			
		||||
void BKE_volume_grid_remove(struct Volume *volume, struct VolumeGrid *grid);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* OpenVDB Grid Access
 | 
			
		||||
 *
 | 
			
		||||
 * Access to OpenVDB grid for C++. These will automatically load grids from
 | 
			
		||||
 * file or copy shared grids to make them writeable. */
 | 
			
		||||
 | 
			
		||||
#if defined(__cplusplus) && defined(WITH_OPENVDB)
 | 
			
		||||
#  include <openvdb/openvdb.h>
 | 
			
		||||
openvdb::GridBase::ConstPtr BKE_volume_grid_openvdb_for_metadata(const struct VolumeGrid *grid);
 | 
			
		||||
openvdb::GridBase::ConstPtr BKE_volume_grid_openvdb_for_read(const struct Volume *volume,
 | 
			
		||||
                                                             struct VolumeGrid *grid);
 | 
			
		||||
openvdb::GridBase::Ptr BKE_volume_grid_openvdb_for_write(const struct Volume *volume,
 | 
			
		||||
                                                         struct VolumeGrid *grid,
 | 
			
		||||
                                                         const bool clear);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@@ -120,6 +120,7 @@ set(SRC
 | 
			
		||||
  intern/freestyle.c
 | 
			
		||||
  intern/gpencil.c
 | 
			
		||||
  intern/gpencil_modifier.c
 | 
			
		||||
  intern/hair.c
 | 
			
		||||
  intern/icons.c
 | 
			
		||||
  intern/icons_rasterize.c
 | 
			
		||||
  intern/idcode.c
 | 
			
		||||
@@ -196,6 +197,7 @@ set(SRC
 | 
			
		||||
  intern/pbvh_bmesh.c
 | 
			
		||||
  intern/pbvh_parallel.cc
 | 
			
		||||
  intern/pointcache.c
 | 
			
		||||
  intern/pointcloud.c
 | 
			
		||||
  intern/report.c
 | 
			
		||||
  intern/rigidbody.c
 | 
			
		||||
  intern/scene.c
 | 
			
		||||
@@ -239,6 +241,7 @@ set(SRC
 | 
			
		||||
  intern/tracking_util.c
 | 
			
		||||
  intern/undo_system.c
 | 
			
		||||
  intern/unit.c
 | 
			
		||||
  intern/volume.cc
 | 
			
		||||
  intern/workspace.c
 | 
			
		||||
  intern/world.c
 | 
			
		||||
  intern/writeavi.c
 | 
			
		||||
@@ -296,12 +299,12 @@ set(SRC
 | 
			
		||||
  BKE_global.h
 | 
			
		||||
  BKE_gpencil.h
 | 
			
		||||
  BKE_gpencil_modifier.h
 | 
			
		||||
  BKE_hair.h
 | 
			
		||||
  BKE_icons.h
 | 
			
		||||
  BKE_idcode.h
 | 
			
		||||
  BKE_idprop.h
 | 
			
		||||
  BKE_idtype.h
 | 
			
		||||
  BKE_image.h
 | 
			
		||||
  BKE_image_save.h
 | 
			
		||||
  BKE_ipo.h
 | 
			
		||||
  BKE_kelvinlet.h
 | 
			
		||||
  BKE_key.h
 | 
			
		||||
@@ -345,6 +348,7 @@ set(SRC
 | 
			
		||||
  BKE_particle.h
 | 
			
		||||
  BKE_pbvh.h
 | 
			
		||||
  BKE_pointcache.h
 | 
			
		||||
  BKE_pointcloud.h
 | 
			
		||||
  BKE_report.h
 | 
			
		||||
  BKE_rigidbody.h
 | 
			
		||||
  BKE_scene.h
 | 
			
		||||
@@ -370,6 +374,7 @@ set(SRC
 | 
			
		||||
  BKE_tracking.h
 | 
			
		||||
  BKE_undo_system.h
 | 
			
		||||
  BKE_unit.h
 | 
			
		||||
  BKE_volume.h
 | 
			
		||||
  BKE_workspace.h
 | 
			
		||||
  BKE_world.h
 | 
			
		||||
  BKE_writeavi.h
 | 
			
		||||
@@ -634,16 +639,14 @@ if(WITH_OPENVDB)
 | 
			
		||||
  list(APPEND INC
 | 
			
		||||
     ../../../intern/openvdb
 | 
			
		||||
  )
 | 
			
		||||
  list(APPEND INC_SYS
 | 
			
		||||
    ${OPENVDB_INCLUDE_DIRS}
 | 
			
		||||
  )
 | 
			
		||||
  list(APPEND LIB
 | 
			
		||||
    bf_intern_openvdb
 | 
			
		||||
    ${OPENVDB_LIBRARIES}
 | 
			
		||||
  )
 | 
			
		||||
  add_definitions(-DWITH_OPENVDB)
 | 
			
		||||
 | 
			
		||||
  if(WITH_OPENVDB_BLOSC)
 | 
			
		||||
    add_definitions(
 | 
			
		||||
      -DWITH_OPENVDB_BLOSC
 | 
			
		||||
    )
 | 
			
		||||
  endif()
 | 
			
		||||
  add_definitions(-DWITH_OPENVDB ${OPENVDB_DEFINITIONS})
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
if(WITH_QUADRIFLOW)
 | 
			
		||||
 
 | 
			
		||||
@@ -110,6 +110,9 @@ bool id_type_can_have_animdata(const short id_type)
 | 
			
		||||
    case ID_MSK:
 | 
			
		||||
    case ID_GD:
 | 
			
		||||
    case ID_CF:
 | 
			
		||||
    case ID_HA:
 | 
			
		||||
    case ID_PT:
 | 
			
		||||
    case ID_VO:
 | 
			
		||||
      return true;
 | 
			
		||||
 | 
			
		||||
    /* no AnimData */
 | 
			
		||||
@@ -1327,6 +1330,15 @@ void BKE_animdata_main_cb(Main *bmain, ID_AnimData_Edit_Callback func, void *use
 | 
			
		||||
 | 
			
		||||
  /* cache files */
 | 
			
		||||
  ANIMDATA_IDS_CB(bmain->cachefiles.first);
 | 
			
		||||
 | 
			
		||||
  /* hairs */
 | 
			
		||||
  ANIMDATA_IDS_CB(bmain->hairs.first);
 | 
			
		||||
 | 
			
		||||
  /* pointclouds */
 | 
			
		||||
  ANIMDATA_IDS_CB(bmain->pointclouds.first);
 | 
			
		||||
 | 
			
		||||
  /* volumes */
 | 
			
		||||
  ANIMDATA_IDS_CB(bmain->volumes.first);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Fix all RNA-Paths throughout the database (directly access the Global.main version)
 | 
			
		||||
@@ -1427,6 +1439,15 @@ void BKE_animdata_fix_paths_rename_all(ID *ref_id,
 | 
			
		||||
  /* cache files */
 | 
			
		||||
  RENAMEFIX_ANIM_IDS(bmain->cachefiles.first);
 | 
			
		||||
 | 
			
		||||
  /* hairs */
 | 
			
		||||
  RENAMEFIX_ANIM_IDS(bmain->hairs.first);
 | 
			
		||||
 | 
			
		||||
  /* pointclouds */
 | 
			
		||||
  RENAMEFIX_ANIM_IDS(bmain->pointclouds.first);
 | 
			
		||||
 | 
			
		||||
  /* volumes */
 | 
			
		||||
  RENAMEFIX_ANIM_IDS(bmain->volumes.first);
 | 
			
		||||
 | 
			
		||||
  /* scenes */
 | 
			
		||||
  RENAMEFIX_ANIM_NODETREE_IDS(bmain->scenes.first, Scene);
 | 
			
		||||
}
 | 
			
		||||
@@ -4035,6 +4056,15 @@ void BKE_animsys_evaluate_all_animation(Main *main,
 | 
			
		||||
  /* cache files */
 | 
			
		||||
  EVAL_ANIM_IDS(main->cachefiles.first, ADT_RECALC_ANIM);
 | 
			
		||||
 | 
			
		||||
  /* hairs */
 | 
			
		||||
  EVAL_ANIM_IDS(main->hairs.first, ADT_RECALC_ANIM);
 | 
			
		||||
 | 
			
		||||
  /* pointclouds */
 | 
			
		||||
  EVAL_ANIM_IDS(main->pointclouds.first, ADT_RECALC_ANIM);
 | 
			
		||||
 | 
			
		||||
  /* volumes */
 | 
			
		||||
  EVAL_ANIM_IDS(main->volumes.first, ADT_RECALC_ANIM);
 | 
			
		||||
 | 
			
		||||
  /* objects */
 | 
			
		||||
  /* ADT_RECALC_ANIM doesn't need to be supplied here, since object AnimData gets
 | 
			
		||||
   * this tagged by Depsgraph on framechange. This optimization means that objects
 | 
			
		||||
 
 | 
			
		||||
@@ -61,6 +61,7 @@
 | 
			
		||||
#include "DNA_scene_types.h"
 | 
			
		||||
#include "DNA_fluid_types.h"
 | 
			
		||||
#include "DNA_freestyle_types.h"
 | 
			
		||||
#include "DNA_volume_types.h"
 | 
			
		||||
 | 
			
		||||
#include "BLI_blenlib.h"
 | 
			
		||||
#include "BLI_utildefines.h"
 | 
			
		||||
@@ -645,6 +646,13 @@ void BKE_bpath_traverse_id(
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case ID_VO: {
 | 
			
		||||
      Volume *volume = (Volume *)id;
 | 
			
		||||
      if (volume->packedfile == NULL || (flag & BKE_BPATH_TRAVERSE_SKIP_PACKED) == 0) {
 | 
			
		||||
        rewrite_path_fixed(volume->filepath, visit_cb, absbase, bpath_user_data);
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case ID_TXT:
 | 
			
		||||
      if (((Text *)id)->name) {
 | 
			
		||||
        rewrite_path_alloc(&((Text *)id)->name, visit_cb, absbase, bpath_user_data);
 | 
			
		||||
 
 | 
			
		||||
@@ -30,7 +30,9 @@
 | 
			
		||||
#define DNA_DEPRECATED_ALLOW
 | 
			
		||||
 | 
			
		||||
#include "DNA_customdata_types.h"
 | 
			
		||||
#include "DNA_hair_types.h"
 | 
			
		||||
#include "DNA_meshdata_types.h"
 | 
			
		||||
#include "DNA_pointcloud_types.h"
 | 
			
		||||
#include "DNA_ID.h"
 | 
			
		||||
 | 
			
		||||
#include "BLI_utildefines.h"
 | 
			
		||||
@@ -1623,6 +1625,14 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
 | 
			
		||||
    {sizeof(short[2]), "vec2s", 1, NULL, NULL, NULL, NULL, NULL, NULL},
 | 
			
		||||
    /* 42: CD_SCULPT_FACE_SETS */
 | 
			
		||||
    {sizeof(int), "", 0, NULL, NULL, NULL, NULL, NULL, NULL},
 | 
			
		||||
    /* 43: CD_LOCATION */
 | 
			
		||||
    {sizeof(float[3]), "vec3f", 1, NULL, NULL, NULL, NULL, NULL, NULL},
 | 
			
		||||
    /* 44: CD_RADIUS */
 | 
			
		||||
    {sizeof(float), "MFloatProperty", 1, NULL, NULL, NULL, NULL, NULL, NULL},
 | 
			
		||||
    /* 45: CD_HAIRCURVE */
 | 
			
		||||
    {sizeof(HairCurve), "HairCurve", 1, NULL, NULL, NULL, NULL, NULL, NULL},
 | 
			
		||||
    /* 46: CD_HAIR_MAPPING */
 | 
			
		||||
    {sizeof(HairMapping), "HairMapping", 1, NULL, NULL, NULL, NULL, NULL, NULL},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const char *LAYERTYPENAMES[CD_NUMTYPES] = {
 | 
			
		||||
@@ -1667,10 +1677,14 @@ static const char *LAYERTYPENAMES[CD_NUMTYPES] = {
 | 
			
		||||
    "CDMVertSkin",
 | 
			
		||||
    /* 37-38 */ "CDFreestyleEdge",
 | 
			
		||||
    "CDFreestyleFace",
 | 
			
		||||
    /* 39-41 */ "CDMLoopTangent",
 | 
			
		||||
    /* 39-42 */ "CDMLoopTangent",
 | 
			
		||||
    "CDTessLoopNormal",
 | 
			
		||||
    "CDCustomLoopNormal",
 | 
			
		||||
    "CDSculptFaceGroups",
 | 
			
		||||
    /* 43-46 */ "CDHairPoint",
 | 
			
		||||
    "CDHairCurve",
 | 
			
		||||
    "CDHairMapping",
 | 
			
		||||
    "CDPoint",
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const CustomData_MeshMasks CD_MASK_BAREMESH = {
 | 
			
		||||
 
 | 
			
		||||
@@ -656,6 +656,7 @@ int get_effector_data(EffectorCache *eff,
 | 
			
		||||
    efd->size = 0.0f;
 | 
			
		||||
  }
 | 
			
		||||
  else if (eff->pd && eff->pd->shape == PFIELD_SHAPE_POINTS) {
 | 
			
		||||
    /* TODO: hair and points object support */
 | 
			
		||||
    Mesh *me_eval = BKE_object_get_evaluated_mesh(eff->ob);
 | 
			
		||||
    if (me_eval != NULL) {
 | 
			
		||||
      copy_v3_v3(efd->loc, me_eval->mvert[*efd->index].co);
 | 
			
		||||
@@ -769,6 +770,7 @@ static void get_effector_tot(
 | 
			
		||||
  efd->index = p;
 | 
			
		||||
 | 
			
		||||
  if (eff->pd->shape == PFIELD_SHAPE_POINTS) {
 | 
			
		||||
    /* TODO: hair and points object support */
 | 
			
		||||
    Mesh *me_eval = BKE_object_get_evaluated_mesh(eff->ob);
 | 
			
		||||
    *tot = me_eval != NULL ? me_eval->totvert : 1;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										292
									
								
								source/blender/blenkernel/intern/hair.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										292
									
								
								source/blender/blenkernel/intern/hair.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,292 @@
 | 
			
		||||
/*
 | 
			
		||||
 * ***** 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/blenkernel/intern/hair.c
 | 
			
		||||
 *  \ingroup bke
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "MEM_guardedalloc.h"
 | 
			
		||||
 | 
			
		||||
#include "DNA_defaults.h"
 | 
			
		||||
#include "DNA_hair_types.h"
 | 
			
		||||
#include "DNA_object_types.h"
 | 
			
		||||
 | 
			
		||||
#include "BLI_listbase.h"
 | 
			
		||||
#include "BLI_math.h"
 | 
			
		||||
#include "BLI_rand.h"
 | 
			
		||||
#include "BLI_string.h"
 | 
			
		||||
#include "BLI_utildefines.h"
 | 
			
		||||
 | 
			
		||||
#include "BKE_animsys.h"
 | 
			
		||||
#include "BKE_customdata.h"
 | 
			
		||||
#include "BKE_idtype.h"
 | 
			
		||||
#include "BKE_global.h"
 | 
			
		||||
#include "BKE_hair.h"
 | 
			
		||||
#include "BKE_lib_id.h"
 | 
			
		||||
#include "BKE_lib_query.h"
 | 
			
		||||
#include "BKE_lib_remap.h"
 | 
			
		||||
#include "BKE_main.h"
 | 
			
		||||
#include "BKE_modifier.h"
 | 
			
		||||
#include "BKE_object.h"
 | 
			
		||||
 | 
			
		||||
#include "BLT_translation.h"
 | 
			
		||||
 | 
			
		||||
#include "DEG_depsgraph_query.h"
 | 
			
		||||
 | 
			
		||||
/* Hair datablock */
 | 
			
		||||
 | 
			
		||||
static void hair_random(Hair *hair)
 | 
			
		||||
{
 | 
			
		||||
  const int numpoints = 8;
 | 
			
		||||
 | 
			
		||||
  hair->totcurve = 500;
 | 
			
		||||
  hair->totpoint = hair->totcurve * numpoints;
 | 
			
		||||
 | 
			
		||||
  CustomData_realloc(&hair->pdata, hair->totpoint);
 | 
			
		||||
  CustomData_realloc(&hair->cdata, hair->totcurve);
 | 
			
		||||
  BKE_hair_update_customdata_pointers(hair);
 | 
			
		||||
 | 
			
		||||
  RNG *rng = BLI_rng_new(0);
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < hair->totcurve; i++) {
 | 
			
		||||
    HairCurve *curve = &hair->curves[i];
 | 
			
		||||
    curve->firstpoint = i * numpoints;
 | 
			
		||||
    curve->numpoints = numpoints;
 | 
			
		||||
 | 
			
		||||
    float theta = 2.0f * M_PI * BLI_rng_get_float(rng);
 | 
			
		||||
    float phi = saacosf(2.0f * BLI_rng_get_float(rng) - 1.0f);
 | 
			
		||||
 | 
			
		||||
    float no[3] = {sinf(theta) * sinf(phi), cosf(theta) * sinf(phi), cosf(phi)};
 | 
			
		||||
    normalize_v3(no);
 | 
			
		||||
 | 
			
		||||
    float co[3];
 | 
			
		||||
    copy_v3_v3(co, no);
 | 
			
		||||
 | 
			
		||||
    float(*curve_co)[3] = hair->co + curve->firstpoint;
 | 
			
		||||
    float *curve_radius = hair->radius + curve->firstpoint;
 | 
			
		||||
    for (int key = 0; key < numpoints; key++) {
 | 
			
		||||
      float t = key / (float)(numpoints - 1);
 | 
			
		||||
      copy_v3_v3(curve_co[key], co);
 | 
			
		||||
      curve_radius[key] = 0.02f * (1.0f - t);
 | 
			
		||||
 | 
			
		||||
      float offset[3] = {2.0f * BLI_rng_get_float(rng) - 1.0f,
 | 
			
		||||
                         2.0f * BLI_rng_get_float(rng) - 1.0f,
 | 
			
		||||
                         2.0f * BLI_rng_get_float(rng) - 1.0f};
 | 
			
		||||
      add_v3_v3(offset, no);
 | 
			
		||||
      madd_v3_v3fl(co, offset, 1.0f / numpoints);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  BLI_rng_free(rng);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void hair_init_data(ID *id)
 | 
			
		||||
{
 | 
			
		||||
  Hair *hair = (Hair *)id;
 | 
			
		||||
  BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(hair, id));
 | 
			
		||||
 | 
			
		||||
  MEMCPY_STRUCT_AFTER(hair, DNA_struct_default_get(Hair), id);
 | 
			
		||||
 | 
			
		||||
  CustomData_reset(&hair->pdata);
 | 
			
		||||
  CustomData_reset(&hair->cdata);
 | 
			
		||||
 | 
			
		||||
  CustomData_add_layer(&hair->pdata, CD_LOCATION, CD_CALLOC, NULL, hair->totpoint);
 | 
			
		||||
  CustomData_add_layer(&hair->pdata, CD_RADIUS, CD_CALLOC, NULL, hair->totpoint);
 | 
			
		||||
  CustomData_add_layer(&hair->cdata, CD_HAIRCURVE, CD_CALLOC, NULL, hair->totcurve);
 | 
			
		||||
  BKE_hair_update_customdata_pointers(hair);
 | 
			
		||||
 | 
			
		||||
  hair_random(hair);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void *BKE_hair_add(Main *bmain, const char *name)
 | 
			
		||||
{
 | 
			
		||||
  Hair *hair = BKE_libblock_alloc(bmain, ID_HA, name, 0);
 | 
			
		||||
 | 
			
		||||
  hair_init_data(&hair->id);
 | 
			
		||||
 | 
			
		||||
  return hair;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void hair_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, const int flag)
 | 
			
		||||
{
 | 
			
		||||
  Hair *hair_dst = (Hair *)id_dst;
 | 
			
		||||
  const Hair *hair_src = (const Hair *)id_src;
 | 
			
		||||
  hair_dst->mat = MEM_dupallocN(hair_dst->mat);
 | 
			
		||||
 | 
			
		||||
  const eCDAllocType alloc_type = (flag & LIB_ID_COPY_CD_REFERENCE) ? CD_REFERENCE : CD_DUPLICATE;
 | 
			
		||||
  CustomData_copy(&hair_src->pdata, &hair_dst->pdata, CD_MASK_ALL, alloc_type, hair_dst->totpoint);
 | 
			
		||||
  CustomData_copy(&hair_src->cdata, &hair_dst->cdata, CD_MASK_ALL, alloc_type, hair_dst->totcurve);
 | 
			
		||||
  BKE_hair_update_customdata_pointers(hair_dst);
 | 
			
		||||
 | 
			
		||||
  hair_dst->batch_cache = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Hair *BKE_hair_copy(Main *bmain, const Hair *hair)
 | 
			
		||||
{
 | 
			
		||||
  Hair *hair_copy;
 | 
			
		||||
  BKE_id_copy(bmain, &hair->id, (ID **)&hair_copy);
 | 
			
		||||
  return hair_copy;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void hair_make_local(Main *bmain, ID *id, const int flags)
 | 
			
		||||
{
 | 
			
		||||
  BKE_lib_id_make_local_generic(bmain, id, flags);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void hair_free_data(ID *id)
 | 
			
		||||
{
 | 
			
		||||
  Hair *hair = (Hair *)id;
 | 
			
		||||
  BKE_animdata_free(&hair->id, false);
 | 
			
		||||
 | 
			
		||||
  BKE_hair_batch_cache_free(hair);
 | 
			
		||||
 | 
			
		||||
  CustomData_free(&hair->pdata, hair->totpoint);
 | 
			
		||||
  CustomData_free(&hair->cdata, hair->totcurve);
 | 
			
		||||
 | 
			
		||||
  MEM_SAFE_FREE(hair->mat);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IDTypeInfo IDType_ID_HA = {
 | 
			
		||||
    .id_code = ID_HA,
 | 
			
		||||
    .id_filter = FILTER_ID_HA,
 | 
			
		||||
    .main_listbase_index = INDEX_ID_HA,
 | 
			
		||||
    .struct_size = sizeof(Hair),
 | 
			
		||||
    .name = "Hair",
 | 
			
		||||
    .name_plural = "hairs",
 | 
			
		||||
    .translation_context = BLT_I18NCONTEXT_ID_HAIR,
 | 
			
		||||
    .flags = 0,
 | 
			
		||||
 | 
			
		||||
    .init_data = hair_init_data,
 | 
			
		||||
    .copy_data = hair_copy_data,
 | 
			
		||||
    .free_data = hair_free_data,
 | 
			
		||||
    .make_local = hair_make_local,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
BoundBox *BKE_hair_boundbox_get(Object *ob)
 | 
			
		||||
{
 | 
			
		||||
  BLI_assert(ob->type == OB_HAIR);
 | 
			
		||||
  Hair *hair = ob->data;
 | 
			
		||||
 | 
			
		||||
  if (ob->runtime.bb != NULL && (ob->runtime.bb->flag & BOUNDBOX_DIRTY) == 0) {
 | 
			
		||||
    return ob->runtime.bb;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (ob->runtime.bb == NULL) {
 | 
			
		||||
    ob->runtime.bb = MEM_callocN(sizeof(BoundBox), "hair boundbox");
 | 
			
		||||
 | 
			
		||||
    float min[3], max[3];
 | 
			
		||||
    INIT_MINMAX(min, max);
 | 
			
		||||
 | 
			
		||||
    float(*hair_co)[3] = hair->co;
 | 
			
		||||
    float *hair_radius = hair->radius;
 | 
			
		||||
    for (int a = 0; a < hair->totpoint; a++) {
 | 
			
		||||
      float *co = hair_co[a];
 | 
			
		||||
      float radius = (hair_radius) ? hair_radius[a] : 0.0f;
 | 
			
		||||
      float co_min[3] = {co[0] - radius, co[1] - radius, co[2] - radius};
 | 
			
		||||
      float co_max[3] = {co[0] + radius, co[1] + radius, co[2] + radius};
 | 
			
		||||
      DO_MIN(co_min, min);
 | 
			
		||||
      DO_MAX(co_max, max);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    BKE_boundbox_init_from_minmax(ob->runtime.bb, min, max);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return ob->runtime.bb;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void BKE_hair_update_customdata_pointers(Hair *hair)
 | 
			
		||||
{
 | 
			
		||||
  hair->co = CustomData_get_layer(&hair->pdata, CD_LOCATION);
 | 
			
		||||
  hair->radius = CustomData_get_layer(&hair->pdata, CD_RADIUS);
 | 
			
		||||
  hair->curves = CustomData_get_layer(&hair->cdata, CD_HAIRCURVE);
 | 
			
		||||
  hair->mapping = CustomData_get_layer(&hair->cdata, CD_HAIRMAPPING);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Dependency Graph */
 | 
			
		||||
 | 
			
		||||
Hair *BKE_hair_new_for_eval(const Hair *hair_src, int totpoint, int totcurve)
 | 
			
		||||
{
 | 
			
		||||
  Hair *hair_dst = BKE_id_new_nomain(ID_HA, NULL);
 | 
			
		||||
 | 
			
		||||
  STRNCPY(hair_dst->id.name, hair_src->id.name);
 | 
			
		||||
  hair_dst->mat = MEM_dupallocN(hair_src->mat);
 | 
			
		||||
  hair_dst->totcol = hair_src->totcol;
 | 
			
		||||
 | 
			
		||||
  hair_dst->totpoint = totpoint;
 | 
			
		||||
  hair_dst->totcurve = totcurve;
 | 
			
		||||
  CustomData_copy(&hair_src->pdata, &hair_dst->pdata, CD_MASK_ALL, CD_CALLOC, totpoint);
 | 
			
		||||
  CustomData_copy(&hair_src->cdata, &hair_dst->cdata, CD_MASK_ALL, CD_CALLOC, totcurve);
 | 
			
		||||
  BKE_hair_update_customdata_pointers(hair_dst);
 | 
			
		||||
 | 
			
		||||
  return hair_dst;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Hair *BKE_hair_copy_for_eval(Hair *hair_src, bool reference)
 | 
			
		||||
{
 | 
			
		||||
  int flags = LIB_ID_COPY_LOCALIZE;
 | 
			
		||||
 | 
			
		||||
  if (reference) {
 | 
			
		||||
    flags |= LIB_ID_COPY_CD_REFERENCE;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Hair *result;
 | 
			
		||||
  BKE_id_copy_ex(NULL, &hair_src->id, (ID **)&result, flags);
 | 
			
		||||
  return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static Hair *hair_evaluate_modifiers(struct Depsgraph *UNUSED(depsgraph),
 | 
			
		||||
                                     struct Scene *UNUSED(scene),
 | 
			
		||||
                                     Object *UNUSED(object),
 | 
			
		||||
                                     Hair *hair_input)
 | 
			
		||||
{
 | 
			
		||||
  return hair_input;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void BKE_hair_data_update(struct Depsgraph *depsgraph, struct Scene *scene, Object *object)
 | 
			
		||||
{
 | 
			
		||||
  /* Free any evaluated data and restore original data. */
 | 
			
		||||
  BKE_object_free_derived_caches(object);
 | 
			
		||||
 | 
			
		||||
  /* Evaluate modifiers. */
 | 
			
		||||
  Hair *hair = object->data;
 | 
			
		||||
  Hair *hair_eval = hair_evaluate_modifiers(depsgraph, scene, object, hair);
 | 
			
		||||
 | 
			
		||||
  /* Assign evaluated object. */
 | 
			
		||||
  const bool is_owned = (hair != hair_eval);
 | 
			
		||||
  BKE_object_eval_assign_data(object, &hair_eval->id, is_owned);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Draw Cache */
 | 
			
		||||
void (*BKE_hair_batch_cache_dirty_tag_cb)(Hair *hair, int mode) = NULL;
 | 
			
		||||
void (*BKE_hair_batch_cache_free_cb)(Hair *hair) = NULL;
 | 
			
		||||
 | 
			
		||||
void BKE_hair_batch_cache_dirty_tag(Hair *hair, int mode)
 | 
			
		||||
{
 | 
			
		||||
  if (hair->batch_cache) {
 | 
			
		||||
    BKE_hair_batch_cache_dirty_tag_cb(hair, mode);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void BKE_hair_batch_cache_free(Hair *hair)
 | 
			
		||||
{
 | 
			
		||||
  if (hair->batch_cache) {
 | 
			
		||||
    BKE_hair_batch_cache_free_cb(hair);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -61,7 +61,7 @@ static IDType idtypes[] = {
 | 
			
		||||
  {ID_GR,   "Collection",         "collections",     BLT_I18NCONTEXT_ID_COLLECTION,         IDTYPE_FLAGS_ISLINKABLE},
 | 
			
		||||
  {ID_CU,   "Curve",              "curves",          BLT_I18NCONTEXT_ID_CURVE,              IDTYPE_FLAGS_ISLINKABLE},
 | 
			
		||||
  {ID_GD,   "GPencil",            "grease_pencils",  BLT_I18NCONTEXT_ID_GPENCIL,            IDTYPE_FLAGS_ISLINKABLE}, /* rename gpencil */
 | 
			
		||||
 | 
			
		||||
	{ID_HA,   "Hair",               "hair",            BLT_I18NCONTEXT_ID_HAIR,               IDTYPE_FLAGS_ISLINKABLE},
 | 
			
		||||
  {ID_IM,   "Image",              "images",          BLT_I18NCONTEXT_ID_IMAGE,              IDTYPE_FLAGS_ISLINKABLE},
 | 
			
		||||
  {ID_IP,   "Ipo",                "ipos",            "",                                    IDTYPE_FLAGS_ISLINKABLE}, /* deprecated */
 | 
			
		||||
  {ID_KE,   "Key",                "shape_keys",      BLT_I18NCONTEXT_ID_SHAPEKEY,           0                      },
 | 
			
		||||
@@ -80,6 +80,7 @@ static IDType idtypes[] = {
 | 
			
		||||
  {ID_PAL,  "Palettes",           "palettes",        BLT_I18NCONTEXT_ID_PALETTE,            IDTYPE_FLAGS_ISLINKABLE},
 | 
			
		||||
  {ID_PC,   "PaintCurve",         "paint_curves",    BLT_I18NCONTEXT_ID_PAINTCURVE,         IDTYPE_FLAGS_ISLINKABLE},
 | 
			
		||||
  {ID_LP,   "LightProbe",         "lightprobes",     BLT_I18NCONTEXT_ID_LIGHTPROBE,         IDTYPE_FLAGS_ISLINKABLE},
 | 
			
		||||
	{ID_PT,   "PointCloud",         "pointclouds",     BLT_I18NCONTEXT_ID_POINTCLOUD,         IDTYPE_FLAGS_ISLINKABLE},
 | 
			
		||||
  {ID_SCE,  "Scene",              "scenes",          BLT_I18NCONTEXT_ID_SCENE,              IDTYPE_FLAGS_ISLINKABLE},
 | 
			
		||||
  {ID_SCR,  "Screen",             "screens",         BLT_I18NCONTEXT_ID_SCREEN,             IDTYPE_FLAGS_ISLINKABLE},
 | 
			
		||||
  {ID_SEQ,  "Sequence",           "sequences",       BLT_I18NCONTEXT_ID_SEQUENCE,           0                      }, /* not actually ID data */
 | 
			
		||||
@@ -88,6 +89,7 @@ static IDType idtypes[] = {
 | 
			
		||||
  {ID_TE,   "Texture",            "textures",        BLT_I18NCONTEXT_ID_TEXTURE,            IDTYPE_FLAGS_ISLINKABLE},
 | 
			
		||||
  {ID_TXT,  "Text",               "texts",           BLT_I18NCONTEXT_ID_TEXT,               IDTYPE_FLAGS_ISLINKABLE},
 | 
			
		||||
  {ID_VF,   "VFont",              "fonts",           BLT_I18NCONTEXT_ID_VFONT,              IDTYPE_FLAGS_ISLINKABLE},
 | 
			
		||||
	{ID_VO,   "Volume",             "volumes",         BLT_I18NCONTEXT_ID_VOLUME,             IDTYPE_FLAGS_ISLINKABLE},
 | 
			
		||||
  {ID_WO,   "World",              "worlds",          BLT_I18NCONTEXT_ID_WORLD,              IDTYPE_FLAGS_ISLINKABLE},
 | 
			
		||||
  {ID_WM,   "WindowManager",      "window_managers", BLT_I18NCONTEXT_ID_WINDOWMANAGER,      0                       },
 | 
			
		||||
  {ID_WS,   "WorkSpace",          "workspaces",      BLT_I18NCONTEXT_ID_WORKSPACE,          IDTYPE_FLAGS_ISLINKABLE},
 | 
			
		||||
@@ -215,6 +217,9 @@ uint64_t BKE_idcode_to_idfilter(const short idcode)
 | 
			
		||||
    CASE_IDFILTER(TE);
 | 
			
		||||
    CASE_IDFILTER(TXT);
 | 
			
		||||
    CASE_IDFILTER(VF);
 | 
			
		||||
    CASE_IDFILTER(HA);
 | 
			
		||||
    CASE_IDFILTER(PT);
 | 
			
		||||
    CASE_IDFILTER(VO);
 | 
			
		||||
    CASE_IDFILTER(WO);
 | 
			
		||||
    CASE_IDFILTER(WS);
 | 
			
		||||
    default:
 | 
			
		||||
@@ -242,8 +247,10 @@ short BKE_idcode_from_idfilter(const uint64_t idfilter)
 | 
			
		||||
    CASE_IDFILTER(CU);
 | 
			
		||||
    CASE_IDFILTER(GD);
 | 
			
		||||
    CASE_IDFILTER(GR);
 | 
			
		||||
    CASE_IDFILTER(HA);
 | 
			
		||||
    CASE_IDFILTER(IM);
 | 
			
		||||
    CASE_IDFILTER(LA);
 | 
			
		||||
    CASE_IDFILTER(LP);
 | 
			
		||||
    CASE_IDFILTER(LS);
 | 
			
		||||
    CASE_IDFILTER(LT);
 | 
			
		||||
    CASE_IDFILTER(MA);
 | 
			
		||||
@@ -256,13 +263,14 @@ short BKE_idcode_from_idfilter(const uint64_t idfilter)
 | 
			
		||||
    CASE_IDFILTER(PA);
 | 
			
		||||
    CASE_IDFILTER(PAL);
 | 
			
		||||
    CASE_IDFILTER(PC);
 | 
			
		||||
    CASE_IDFILTER(LP);
 | 
			
		||||
    CASE_IDFILTER(PT);
 | 
			
		||||
    CASE_IDFILTER(SCE);
 | 
			
		||||
    CASE_IDFILTER(SPK);
 | 
			
		||||
    CASE_IDFILTER(SO);
 | 
			
		||||
    CASE_IDFILTER(TE);
 | 
			
		||||
    CASE_IDFILTER(TXT);
 | 
			
		||||
    CASE_IDFILTER(VF);
 | 
			
		||||
    CASE_IDFILTER(VO);
 | 
			
		||||
    CASE_IDFILTER(WO);
 | 
			
		||||
    default:
 | 
			
		||||
      return 0;
 | 
			
		||||
@@ -289,11 +297,13 @@ int BKE_idcode_to_index(const short idcode)
 | 
			
		||||
    CASE_IDINDEX(CU);
 | 
			
		||||
    CASE_IDINDEX(GD);
 | 
			
		||||
    CASE_IDINDEX(GR);
 | 
			
		||||
    CASE_IDINDEX(HA);
 | 
			
		||||
    CASE_IDINDEX(IM);
 | 
			
		||||
    CASE_IDINDEX(KE);
 | 
			
		||||
    CASE_IDINDEX(IP);
 | 
			
		||||
    CASE_IDINDEX(LA);
 | 
			
		||||
    CASE_IDINDEX(LI);
 | 
			
		||||
    CASE_IDINDEX(LP);
 | 
			
		||||
    CASE_IDINDEX(LS);
 | 
			
		||||
    CASE_IDINDEX(LT);
 | 
			
		||||
    CASE_IDINDEX(MA);
 | 
			
		||||
@@ -306,7 +316,7 @@ int BKE_idcode_to_index(const short idcode)
 | 
			
		||||
    CASE_IDINDEX(PA);
 | 
			
		||||
    CASE_IDINDEX(PAL);
 | 
			
		||||
    CASE_IDINDEX(PC);
 | 
			
		||||
    CASE_IDINDEX(LP);
 | 
			
		||||
    CASE_IDINDEX(PT);
 | 
			
		||||
    CASE_IDINDEX(SCE);
 | 
			
		||||
    CASE_IDINDEX(SCR);
 | 
			
		||||
    CASE_IDINDEX(SPK);
 | 
			
		||||
@@ -314,6 +324,7 @@ int BKE_idcode_to_index(const short idcode)
 | 
			
		||||
    CASE_IDINDEX(TE);
 | 
			
		||||
    CASE_IDINDEX(TXT);
 | 
			
		||||
    CASE_IDINDEX(VF);
 | 
			
		||||
    CASE_IDINDEX(VO);
 | 
			
		||||
    CASE_IDINDEX(WM);
 | 
			
		||||
    CASE_IDINDEX(WO);
 | 
			
		||||
    CASE_IDINDEX(WS);
 | 
			
		||||
@@ -343,11 +354,13 @@ short BKE_idcode_from_index(const int index)
 | 
			
		||||
    CASE_IDCODE(CU);
 | 
			
		||||
    CASE_IDCODE(GD);
 | 
			
		||||
    CASE_IDCODE(GR);
 | 
			
		||||
    CASE_IDCODE(HA);
 | 
			
		||||
    CASE_IDCODE(IM);
 | 
			
		||||
    CASE_IDCODE(KE);
 | 
			
		||||
    CASE_IDCODE(IP);
 | 
			
		||||
    CASE_IDCODE(LA);
 | 
			
		||||
    CASE_IDCODE(LI);
 | 
			
		||||
    CASE_IDCODE(LP);
 | 
			
		||||
    CASE_IDCODE(LS);
 | 
			
		||||
    CASE_IDCODE(LT);
 | 
			
		||||
    CASE_IDCODE(MA);
 | 
			
		||||
@@ -360,7 +373,7 @@ short BKE_idcode_from_index(const int index)
 | 
			
		||||
    CASE_IDCODE(PA);
 | 
			
		||||
    CASE_IDCODE(PAL);
 | 
			
		||||
    CASE_IDCODE(PC);
 | 
			
		||||
    CASE_IDCODE(LP);
 | 
			
		||||
    CASE_IDCODE(PT);
 | 
			
		||||
    CASE_IDCODE(SCE);
 | 
			
		||||
    CASE_IDCODE(SCR);
 | 
			
		||||
    CASE_IDCODE(SPK);
 | 
			
		||||
@@ -368,6 +381,7 @@ short BKE_idcode_from_index(const int index)
 | 
			
		||||
    CASE_IDCODE(TE);
 | 
			
		||||
    CASE_IDCODE(TXT);
 | 
			
		||||
    CASE_IDCODE(VF);
 | 
			
		||||
    CASE_IDCODE(VO);
 | 
			
		||||
    CASE_IDCODE(WM);
 | 
			
		||||
    CASE_IDCODE(WO);
 | 
			
		||||
    CASE_IDCODE(WS);
 | 
			
		||||
 
 | 
			
		||||
@@ -87,6 +87,9 @@ static void id_type_init(void)
 | 
			
		||||
  INIT_TYPE(ID_CF);
 | 
			
		||||
  INIT_TYPE(ID_WS);
 | 
			
		||||
  INIT_TYPE(ID_LP);
 | 
			
		||||
  INIT_TYPE(ID_HA);
 | 
			
		||||
  INIT_TYPE(ID_PT);
 | 
			
		||||
  INIT_TYPE(ID_VO);
 | 
			
		||||
 | 
			
		||||
#undef INIT_TYPE
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -43,6 +43,7 @@
 | 
			
		||||
#include "DNA_camera_types.h"
 | 
			
		||||
#include "DNA_collection_types.h"
 | 
			
		||||
#include "DNA_gpencil_types.h"
 | 
			
		||||
#include "DNA_hair_types.h"
 | 
			
		||||
#include "DNA_ipo_types.h"
 | 
			
		||||
#include "DNA_key_types.h"
 | 
			
		||||
#include "DNA_light_types.h"
 | 
			
		||||
@@ -55,6 +56,7 @@
 | 
			
		||||
#include "DNA_mask_types.h"
 | 
			
		||||
#include "DNA_node_types.h"
 | 
			
		||||
#include "DNA_object_types.h"
 | 
			
		||||
#include "DNA_pointcloud_types.h"
 | 
			
		||||
#include "DNA_lightprobe_types.h"
 | 
			
		||||
#include "DNA_scene_types.h"
 | 
			
		||||
#include "DNA_screen_types.h"
 | 
			
		||||
@@ -62,6 +64,7 @@
 | 
			
		||||
#include "DNA_sound_types.h"
 | 
			
		||||
#include "DNA_text_types.h"
 | 
			
		||||
#include "DNA_vfont_types.h"
 | 
			
		||||
#include "DNA_volume_types.h"
 | 
			
		||||
#include "DNA_windowmanager_types.h"
 | 
			
		||||
#include "DNA_world_types.h"
 | 
			
		||||
#include "DNA_workspace_types.h"
 | 
			
		||||
@@ -89,6 +92,7 @@
 | 
			
		||||
#include "BKE_font.h"
 | 
			
		||||
#include "BKE_global.h"
 | 
			
		||||
#include "BKE_gpencil.h"
 | 
			
		||||
#include "BKE_hair.h"
 | 
			
		||||
#include "BKE_idcode.h"
 | 
			
		||||
#include "BKE_idprop.h"
 | 
			
		||||
#include "BKE_idtype.h"
 | 
			
		||||
@@ -110,6 +114,7 @@
 | 
			
		||||
#include "BKE_object.h"
 | 
			
		||||
#include "BKE_paint.h"
 | 
			
		||||
#include "BKE_particle.h"
 | 
			
		||||
#include "BKE_pointcloud.h"
 | 
			
		||||
#include "BKE_lightprobe.h"
 | 
			
		||||
#include "BKE_rigidbody.h"
 | 
			
		||||
#include "BKE_sound.h"
 | 
			
		||||
@@ -117,6 +122,7 @@
 | 
			
		||||
#include "BKE_scene.h"
 | 
			
		||||
#include "BKE_text.h"
 | 
			
		||||
#include "BKE_texture.h"
 | 
			
		||||
#include "BKE_volume.h"
 | 
			
		||||
#include "BKE_world.h"
 | 
			
		||||
 | 
			
		||||
#include "DEG_depsgraph.h"
 | 
			
		||||
@@ -645,6 +651,9 @@ static void id_swap(Main *bmain, ID *id_a, ID *id_b, const bool do_full_id)
 | 
			
		||||
    CASE_SWAP(ID_PAL, Palette);
 | 
			
		||||
    CASE_SWAP(ID_PC, PaintCurve);
 | 
			
		||||
    CASE_SWAP(ID_CF, CacheFile);
 | 
			
		||||
    CASE_SWAP(ID_HA, Hair);
 | 
			
		||||
    CASE_SWAP(ID_PT, PointCloud);
 | 
			
		||||
    CASE_SWAP(ID_VO, Volume);
 | 
			
		||||
    case ID_IP:
 | 
			
		||||
      break; /* Deprecated. */
 | 
			
		||||
  }
 | 
			
		||||
@@ -1017,6 +1026,9 @@ size_t BKE_libblock_get_alloc_info(short type, const char **name)
 | 
			
		||||
    CASE_RETURN(ID_PC, PaintCurve);
 | 
			
		||||
    CASE_RETURN(ID_CF, CacheFile);
 | 
			
		||||
    CASE_RETURN(ID_WS, WorkSpace);
 | 
			
		||||
    CASE_RETURN(ID_HA, Hair);
 | 
			
		||||
    CASE_RETURN(ID_PT, PointCloud);
 | 
			
		||||
    CASE_RETURN(ID_VO, Volume);
 | 
			
		||||
  }
 | 
			
		||||
  return 0;
 | 
			
		||||
#undef CASE_RETURN
 | 
			
		||||
@@ -1182,8 +1194,8 @@ void BKE_libblock_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int ori
 | 
			
		||||
  BLI_assert((flag & LIB_ID_CREATE_NO_MAIN) != 0 || bmain != NULL);
 | 
			
		||||
  BLI_assert((flag & LIB_ID_CREATE_NO_MAIN) != 0 || (flag & LIB_ID_CREATE_NO_ALLOCATE) == 0);
 | 
			
		||||
  if (!is_private_id_data) {
 | 
			
		||||
    /* When we are handling private ID data, we might still want to manage usercounts, even though
 | 
			
		||||
     * that ID data-block is actually outside of Main... */
 | 
			
		||||
    /* When we are handling private ID data, we might still want to manage usercounts, even
 | 
			
		||||
     * though that ID data-block is actually outside of Main... */
 | 
			
		||||
    BLI_assert((flag & LIB_ID_CREATE_NO_MAIN) == 0 ||
 | 
			
		||||
               (flag & LIB_ID_CREATE_NO_USER_REFCOUNT) != 0);
 | 
			
		||||
  }
 | 
			
		||||
@@ -1394,10 +1406,10 @@ void id_sort_by_name(ListBase *lb, ID *id, ID *id_sorting_hint)
 | 
			
		||||
/**
 | 
			
		||||
 * Helper building final ID name from given base_name and number.
 | 
			
		||||
 *
 | 
			
		||||
 * If everything goes well and we do generate a valid final ID name in given name, we return true.
 | 
			
		||||
 * In case the final name would overflow the allowed ID name length, or given number is bigger than
 | 
			
		||||
 * maximum allowed value, we truncate further the base_name (and given name, which is assumed to
 | 
			
		||||
 * have the same 'base_name' part), and return false.
 | 
			
		||||
 * If everything goes well and we do generate a valid final ID name in given name, we return
 | 
			
		||||
 * true. In case the final name would overflow the allowed ID name length, or given number is
 | 
			
		||||
 * bigger than maximum allowed value, we truncate further the base_name (and given name, which is
 | 
			
		||||
 * assumed to have the same 'base_name' part), and return false.
 | 
			
		||||
 */
 | 
			
		||||
static bool id_name_final_build(char *name, char *base_name, size_t base_name_len, int number)
 | 
			
		||||
{
 | 
			
		||||
@@ -1459,10 +1471,10 @@ static bool check_for_dupid(ListBase *lb, ID *id, char *name, ID **r_id_sorting_
 | 
			
		||||
  static short prev_id_type = ID_LINK_PLACEHOLDER; /* Should never exist in actual ID list. */
 | 
			
		||||
  static int prev_number = MIN_NUMBER - 1;
 | 
			
		||||
 | 
			
		||||
  /* Initial test to check whether we can 'shortcut' the more complex loop of the main code below.
 | 
			
		||||
   * Note that we do not do that for low numbers, as that would prevent using actual smallest
 | 
			
		||||
   * available number in some cases, and benefits of this special case handling mostly show up with
 | 
			
		||||
   * high numbers anyway. */
 | 
			
		||||
  /* Initial test to check whether we can 'shortcut' the more complex loop of the main code
 | 
			
		||||
   * below. Note that we do not do that for low numbers, as that would prevent using actual
 | 
			
		||||
   * smallest available number in some cases, and benefits of this special case handling mostly
 | 
			
		||||
   * show up with high numbers anyway. */
 | 
			
		||||
  if (id_type == prev_id_type && prev_number >= MAX_NUMBERS_IN_USE &&
 | 
			
		||||
      prev_number < MAX_NUMBER - 1 && name[0] == prev_final_base_name[0]) {
 | 
			
		||||
 | 
			
		||||
@@ -1475,8 +1487,8 @@ static bool check_for_dupid(ListBase *lb, ID *id, char *name, ID **r_id_sorting_
 | 
			
		||||
 | 
			
		||||
    if (base_name_len == prev_orig_base_name_len &&
 | 
			
		||||
        STREQLEN(base_name, prev_orig_base_name, prev_orig_base_name_len)) {
 | 
			
		||||
      /* Once we have ensured given base_name and original previous one are the same, we can check
 | 
			
		||||
       * that previously used number is actually used, and that next one is free. */
 | 
			
		||||
      /* Once we have ensured given base_name and original previous one are the same, we can
 | 
			
		||||
       * check that previously used number is actually used, and that next one is free. */
 | 
			
		||||
      /* Note that from now on, we only used previous final base name, as it might have been
 | 
			
		||||
       * truncated from original one due to number suffix length. */
 | 
			
		||||
      char final_name[MAX_ID_NAME - 2];
 | 
			
		||||
@@ -1552,8 +1564,8 @@ static bool check_for_dupid(ListBase *lb, ID *id, char *name, ID **r_id_sorting_
 | 
			
		||||
          STREQLEN(name, id_test->name + 2, base_name_len) &&
 | 
			
		||||
          (BLI_split_name_num(base_name_test, &number_test, id_test->name + 2, '.') ==
 | 
			
		||||
           base_name_len)) {
 | 
			
		||||
        /* If we did not yet encounter exact same name as the given one, check the remaining parts
 | 
			
		||||
         * of the strings. */
 | 
			
		||||
        /* If we did not yet encounter exact same name as the given one, check the remaining
 | 
			
		||||
         * parts of the strings. */
 | 
			
		||||
        if (!is_orig_name_used) {
 | 
			
		||||
          is_orig_name_used = STREQ(name + base_name_len, id_test->name + 2 + base_name_len);
 | 
			
		||||
        }
 | 
			
		||||
@@ -1570,11 +1582,13 @@ static bool check_for_dupid(ListBase *lb, ID *id, char *name, ID **r_id_sorting_
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* If there is no double, we are done.
 | 
			
		||||
     * Note however that name might have been changed (truncated) in a previous iteration already.
 | 
			
		||||
     * Note however that name might have been changed (truncated) in a previous iteration
 | 
			
		||||
     * already.
 | 
			
		||||
     */
 | 
			
		||||
    if (!is_orig_name_used) {
 | 
			
		||||
      /* Don't bother updating prev_ static variables here, this case is not supposed to happen
 | 
			
		||||
       * that often, and is not straight-forward here, so just ignore and reset them to default. */
 | 
			
		||||
       * that often, and is not straight-forward here, so just ignore and reset them to default.
 | 
			
		||||
       */
 | 
			
		||||
      prev_id_type = ID_LINK_PLACEHOLDER;
 | 
			
		||||
      prev_final_base_name[0] = '\0';
 | 
			
		||||
      prev_number = MIN_NUMBER - 1;
 | 
			
		||||
@@ -1585,8 +1599,8 @@ static bool check_for_dupid(ListBase *lb, ID *id, char *name, ID **r_id_sorting_
 | 
			
		||||
      return is_name_changed;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Decide which value of number to use, either the smallest unused one if possible, or default
 | 
			
		||||
     * to the first largest unused one we got from previous loop. */
 | 
			
		||||
    /* Decide which value of number to use, either the smallest unused one if possible, or
 | 
			
		||||
     * default to the first largest unused one we got from previous loop. */
 | 
			
		||||
    for (int i = MIN_NUMBER; i < MAX_NUMBERS_IN_USE; i++) {
 | 
			
		||||
      if (ids_in_use[i] == NULL) {
 | 
			
		||||
        number = i;
 | 
			
		||||
@@ -1605,8 +1619,8 @@ static bool check_for_dupid(ListBase *lb, ID *id, char *name, ID **r_id_sorting_
 | 
			
		||||
    /* We know for wure that name will be changed. */
 | 
			
		||||
    is_name_changed = true;
 | 
			
		||||
 | 
			
		||||
    /* If id_name_final_build helper returns false, it had to truncate further given name, hence we
 | 
			
		||||
     * have to go over the whole check again. */
 | 
			
		||||
    /* If id_name_final_build helper returns false, it had to truncate further given name, hence
 | 
			
		||||
     * we have to go over the whole check again. */
 | 
			
		||||
    if (!id_name_final_build(name, base_name, base_name_len, number)) {
 | 
			
		||||
      /* We have to clear our list of small used numbers before we do the whole check again. */
 | 
			
		||||
      memset(ids_in_use, 0, sizeof(ids_in_use));
 | 
			
		||||
 
 | 
			
		||||
@@ -30,6 +30,7 @@
 | 
			
		||||
#include "DNA_collection_types.h"
 | 
			
		||||
#include "DNA_constraint_types.h"
 | 
			
		||||
#include "DNA_gpencil_types.h"
 | 
			
		||||
#include "DNA_hair_types.h"
 | 
			
		||||
#include "DNA_key_types.h"
 | 
			
		||||
#include "DNA_light_types.h"
 | 
			
		||||
#include "DNA_lattice_types.h"
 | 
			
		||||
@@ -43,6 +44,7 @@
 | 
			
		||||
#include "DNA_object_force_types.h"
 | 
			
		||||
#include "DNA_outliner_types.h"
 | 
			
		||||
#include "DNA_lightprobe_types.h"
 | 
			
		||||
#include "DNA_pointcloud_types.h"
 | 
			
		||||
#include "DNA_rigidbody_types.h"
 | 
			
		||||
#include "DNA_scene_types.h"
 | 
			
		||||
#include "DNA_sequence_types.h"
 | 
			
		||||
@@ -52,6 +54,7 @@
 | 
			
		||||
#include "DNA_sound_types.h"
 | 
			
		||||
#include "DNA_text_types.h"
 | 
			
		||||
#include "DNA_vfont_types.h"
 | 
			
		||||
#include "DNA_volume_types.h"
 | 
			
		||||
#include "DNA_windowmanager_types.h"
 | 
			
		||||
#include "DNA_workspace_types.h"
 | 
			
		||||
#include "DNA_world_types.h"
 | 
			
		||||
@@ -1250,6 +1253,27 @@ static void library_foreach_ID_link(Main *bmain,
 | 
			
		||||
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      case ID_HA: {
 | 
			
		||||
        Hair *hair = (Hair *)id;
 | 
			
		||||
        for (i = 0; i < hair->totcol; i++) {
 | 
			
		||||
          CALLBACK_INVOKE(hair->mat[i], IDWALK_CB_USER);
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      case ID_PT: {
 | 
			
		||||
        PointCloud *pointcloud = (PointCloud *)id;
 | 
			
		||||
        for (i = 0; i < pointcloud->totcol; i++) {
 | 
			
		||||
          CALLBACK_INVOKE(pointcloud->mat[i], IDWALK_CB_USER);
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      case ID_VO: {
 | 
			
		||||
        Volume *volume = (Volume *)id;
 | 
			
		||||
        for (i = 0; i < volume->totcol; i++) {
 | 
			
		||||
          CALLBACK_INVOKE(volume->mat[i], IDWALK_CB_USER);
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      case ID_SCR: {
 | 
			
		||||
        if (data.flag & IDWALK_INCLUDE_UI) {
 | 
			
		||||
@@ -1416,6 +1440,12 @@ bool BKE_library_id_can_use_idtype(ID *id_owner, const short id_type_used)
 | 
			
		||||
      return ELEM(id_type_used, ID_MA);
 | 
			
		||||
    case ID_WS:
 | 
			
		||||
      return ELEM(id_type_used, ID_SCR, ID_SCE);
 | 
			
		||||
    case ID_HA:
 | 
			
		||||
      return ELEM(id_type_used, ID_MA);
 | 
			
		||||
    case ID_PT:
 | 
			
		||||
      return ELEM(id_type_used, ID_MA);
 | 
			
		||||
    case ID_VO:
 | 
			
		||||
      return ELEM(id_type_used, ID_MA);
 | 
			
		||||
    case ID_IM:
 | 
			
		||||
    case ID_VF:
 | 
			
		||||
    case ID_TXT:
 | 
			
		||||
 
 | 
			
		||||
@@ -520,6 +520,9 @@ void BKE_libblock_remap_locked(Main *bmain, void *old_idv, void *new_idv, const
 | 
			
		||||
    case ID_ME:
 | 
			
		||||
    case ID_CU:
 | 
			
		||||
    case ID_MB:
 | 
			
		||||
    case ID_HA:
 | 
			
		||||
    case ID_PT:
 | 
			
		||||
    case ID_VO:
 | 
			
		||||
      if (new_id) { /* Only affects us in case obdata was relinked (changed). */
 | 
			
		||||
        for (Object *ob = bmain->objects.first; ob; ob = ob->id.next) {
 | 
			
		||||
          libblock_remap_data_postprocess_obdata_relink(bmain, ob, new_id);
 | 
			
		||||
 
 | 
			
		||||
@@ -473,6 +473,12 @@ ListBase *which_libbase(Main *bmain, short type)
 | 
			
		||||
      return &(bmain->cachefiles);
 | 
			
		||||
    case ID_WS:
 | 
			
		||||
      return &(bmain->workspaces);
 | 
			
		||||
    case ID_HA:
 | 
			
		||||
      return &(bmain->hairs);
 | 
			
		||||
    case ID_PT:
 | 
			
		||||
      return &(bmain->pointclouds);
 | 
			
		||||
    case ID_VO:
 | 
			
		||||
      return &(bmain->volumes);
 | 
			
		||||
  }
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
@@ -521,6 +527,9 @@ int set_listbasepointers(Main *bmain, ListBase **lb)
 | 
			
		||||
  lb[INDEX_ID_ME] = &(bmain->meshes);
 | 
			
		||||
  lb[INDEX_ID_CU] = &(bmain->curves);
 | 
			
		||||
  lb[INDEX_ID_MB] = &(bmain->metaballs);
 | 
			
		||||
  lb[INDEX_ID_HA] = &(bmain->hairs);
 | 
			
		||||
  lb[INDEX_ID_PT] = &(bmain->pointclouds);
 | 
			
		||||
  lb[INDEX_ID_VO] = &(bmain->volumes);
 | 
			
		||||
 | 
			
		||||
  lb[INDEX_ID_LT] = &(bmain->lattices);
 | 
			
		||||
  lb[INDEX_ID_LA] = &(bmain->lights);
 | 
			
		||||
 
 | 
			
		||||
@@ -37,11 +37,14 @@
 | 
			
		||||
#include "DNA_meshdata_types.h"
 | 
			
		||||
#include "DNA_customdata_types.h"
 | 
			
		||||
#include "DNA_gpencil_types.h"
 | 
			
		||||
#include "DNA_hair_types.h"
 | 
			
		||||
#include "DNA_ID.h"
 | 
			
		||||
#include "DNA_meta_types.h"
 | 
			
		||||
#include "DNA_node_types.h"
 | 
			
		||||
#include "DNA_object_types.h"
 | 
			
		||||
#include "DNA_pointcloud_types.h"
 | 
			
		||||
#include "DNA_scene_types.h"
 | 
			
		||||
#include "DNA_volume_types.h"
 | 
			
		||||
#include "DNA_defaults.h"
 | 
			
		||||
 | 
			
		||||
#include "BLI_math.h"
 | 
			
		||||
@@ -243,53 +246,67 @@ Material *BKE_material_localize(Material *ma)
 | 
			
		||||
 | 
			
		||||
Material ***BKE_object_material_array_p(Object *ob)
 | 
			
		||||
{
 | 
			
		||||
  Mesh *me;
 | 
			
		||||
  Curve *cu;
 | 
			
		||||
  MetaBall *mb;
 | 
			
		||||
  bGPdata *gpd;
 | 
			
		||||
 | 
			
		||||
  if (ob->type == OB_MESH) {
 | 
			
		||||
    me = ob->data;
 | 
			
		||||
    Mesh *me = ob->data;
 | 
			
		||||
    return &(me->mat);
 | 
			
		||||
  }
 | 
			
		||||
  else if (ELEM(ob->type, OB_CURVE, OB_FONT, OB_SURF)) {
 | 
			
		||||
    cu = ob->data;
 | 
			
		||||
    Curve *cu = ob->data;
 | 
			
		||||
    return &(cu->mat);
 | 
			
		||||
  }
 | 
			
		||||
  else if (ob->type == OB_MBALL) {
 | 
			
		||||
    mb = ob->data;
 | 
			
		||||
    MetaBall *mb = ob->data;
 | 
			
		||||
    return &(mb->mat);
 | 
			
		||||
  }
 | 
			
		||||
  else if (ob->type == OB_GPENCIL) {
 | 
			
		||||
    gpd = ob->data;
 | 
			
		||||
    bGPdata *gpd = ob->data;
 | 
			
		||||
    return &(gpd->mat);
 | 
			
		||||
  }
 | 
			
		||||
  else if (ob->type == OB_HAIR) {
 | 
			
		||||
    Hair *hair = ob->data;
 | 
			
		||||
    return &(hair->mat);
 | 
			
		||||
  }
 | 
			
		||||
  else if (ob->type == OB_POINTCLOUD) {
 | 
			
		||||
    PointCloud *pointcloud = ob->data;
 | 
			
		||||
    return &(pointcloud->mat);
 | 
			
		||||
  }
 | 
			
		||||
  else if (ob->type == OB_VOLUME) {
 | 
			
		||||
    Volume *volume = ob->data;
 | 
			
		||||
    return &(volume->mat);
 | 
			
		||||
  }
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
short *BKE_object_material_len_p(Object *ob)
 | 
			
		||||
{
 | 
			
		||||
  Mesh *me;
 | 
			
		||||
  Curve *cu;
 | 
			
		||||
  MetaBall *mb;
 | 
			
		||||
  bGPdata *gpd;
 | 
			
		||||
 | 
			
		||||
  if (ob->type == OB_MESH) {
 | 
			
		||||
    me = ob->data;
 | 
			
		||||
    Mesh *me = ob->data;
 | 
			
		||||
    return &(me->totcol);
 | 
			
		||||
  }
 | 
			
		||||
  else if (ELEM(ob->type, OB_CURVE, OB_FONT, OB_SURF)) {
 | 
			
		||||
    cu = ob->data;
 | 
			
		||||
    Curve *cu = ob->data;
 | 
			
		||||
    return &(cu->totcol);
 | 
			
		||||
  }
 | 
			
		||||
  else if (ob->type == OB_MBALL) {
 | 
			
		||||
    mb = ob->data;
 | 
			
		||||
    MetaBall *mb = ob->data;
 | 
			
		||||
    return &(mb->totcol);
 | 
			
		||||
  }
 | 
			
		||||
  else if (ob->type == OB_GPENCIL) {
 | 
			
		||||
    gpd = ob->data;
 | 
			
		||||
    bGPdata *gpd = ob->data;
 | 
			
		||||
    return &(gpd->totcol);
 | 
			
		||||
  }
 | 
			
		||||
  else if (ob->type == OB_HAIR) {
 | 
			
		||||
    Hair *hair = ob->data;
 | 
			
		||||
    return &(hair->totcol);
 | 
			
		||||
  }
 | 
			
		||||
  else if (ob->type == OB_POINTCLOUD) {
 | 
			
		||||
    PointCloud *pointcloud = ob->data;
 | 
			
		||||
    return &(pointcloud->totcol);
 | 
			
		||||
  }
 | 
			
		||||
  else if (ob->type == OB_VOLUME) {
 | 
			
		||||
    Volume *volume = ob->data;
 | 
			
		||||
    return &(volume->totcol);
 | 
			
		||||
  }
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -308,6 +325,12 @@ Material ***BKE_id_material_array_p(ID *id)
 | 
			
		||||
      return &(((MetaBall *)id)->mat);
 | 
			
		||||
    case ID_GD:
 | 
			
		||||
      return &(((bGPdata *)id)->mat);
 | 
			
		||||
    case ID_HA:
 | 
			
		||||
      return &(((Hair *)id)->mat);
 | 
			
		||||
    case ID_PT:
 | 
			
		||||
      return &(((PointCloud *)id)->mat);
 | 
			
		||||
    case ID_VO:
 | 
			
		||||
      return &(((Volume *)id)->mat);
 | 
			
		||||
    default:
 | 
			
		||||
      break;
 | 
			
		||||
  }
 | 
			
		||||
@@ -328,6 +351,12 @@ short *BKE_id_material_len_p(ID *id)
 | 
			
		||||
      return &(((MetaBall *)id)->totcol);
 | 
			
		||||
    case ID_GD:
 | 
			
		||||
      return &(((bGPdata *)id)->totcol);
 | 
			
		||||
    case ID_HA:
 | 
			
		||||
      return &(((Hair *)id)->totcol);
 | 
			
		||||
    case ID_PT:
 | 
			
		||||
      return &(((PointCloud *)id)->totcol);
 | 
			
		||||
    case ID_VO:
 | 
			
		||||
      return &(((Volume *)id)->totcol);
 | 
			
		||||
    default:
 | 
			
		||||
      break;
 | 
			
		||||
  }
 | 
			
		||||
@@ -347,7 +376,10 @@ static void material_data_index_remove_id(ID *id, short index)
 | 
			
		||||
      BKE_curve_material_index_remove((Curve *)id, index);
 | 
			
		||||
      break;
 | 
			
		||||
    case ID_MB:
 | 
			
		||||
      /* meta-elems don't have materials atm */
 | 
			
		||||
    case ID_HA:
 | 
			
		||||
    case ID_PT:
 | 
			
		||||
    case ID_VO:
 | 
			
		||||
      /* No material indices for these object data types. */
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      break;
 | 
			
		||||
@@ -387,7 +419,10 @@ static void material_data_index_clear_id(ID *id)
 | 
			
		||||
      BKE_curve_material_index_clear((Curve *)id);
 | 
			
		||||
      break;
 | 
			
		||||
    case ID_MB:
 | 
			
		||||
      /* meta-elems don't have materials atm */
 | 
			
		||||
    case ID_HA:
 | 
			
		||||
    case ID_PT:
 | 
			
		||||
    case ID_VO:
 | 
			
		||||
      /* No material indices for these object data types. */
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      break;
 | 
			
		||||
 
 | 
			
		||||
@@ -118,6 +118,9 @@
 | 
			
		||||
#include "BKE_camera.h"
 | 
			
		||||
#include "BKE_image.h"
 | 
			
		||||
#include "BKE_gpencil.h"
 | 
			
		||||
#include "BKE_hair.h"
 | 
			
		||||
#include "BKE_pointcloud.h"
 | 
			
		||||
#include "BKE_volume.h"
 | 
			
		||||
 | 
			
		||||
#include "DEG_depsgraph.h"
 | 
			
		||||
#include "DEG_depsgraph_query.h"
 | 
			
		||||
@@ -1013,6 +1016,12 @@ static const char *get_obdata_defname(int type)
 | 
			
		||||
      return DATA_("Armature");
 | 
			
		||||
    case OB_SPEAKER:
 | 
			
		||||
      return DATA_("Speaker");
 | 
			
		||||
    case OB_HAIR:
 | 
			
		||||
      return DATA_("Hair");
 | 
			
		||||
    case OB_POINTCLOUD:
 | 
			
		||||
      return DATA_("PointCloud");
 | 
			
		||||
    case OB_VOLUME:
 | 
			
		||||
      return DATA_("Volume");
 | 
			
		||||
    case OB_EMPTY:
 | 
			
		||||
      return DATA_("Empty");
 | 
			
		||||
    case OB_GPENCIL:
 | 
			
		||||
@@ -1076,6 +1085,12 @@ void *BKE_object_obdata_add_from_type(Main *bmain, int type, const char *name)
 | 
			
		||||
      return BKE_lightprobe_add(bmain, name);
 | 
			
		||||
    case OB_GPENCIL:
 | 
			
		||||
      return BKE_gpencil_data_addnew(bmain, name);
 | 
			
		||||
    case OB_HAIR:
 | 
			
		||||
      return BKE_hair_add(bmain, name);
 | 
			
		||||
    case OB_POINTCLOUD:
 | 
			
		||||
      return BKE_pointcloud_add(bmain, name);
 | 
			
		||||
    case OB_VOLUME:
 | 
			
		||||
      return BKE_volume_add(bmain, name);
 | 
			
		||||
    case OB_EMPTY:
 | 
			
		||||
      return NULL;
 | 
			
		||||
    default:
 | 
			
		||||
@@ -1768,6 +1783,39 @@ Object *BKE_object_duplicate(Main *bmain, const Object *ob, const int dupflag)
 | 
			
		||||
        id_us_min(id);
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    case OB_HAIR:
 | 
			
		||||
      if (dupflag & USER_DUP_HAIR) {
 | 
			
		||||
        ID_NEW_REMAP_US2(obn->data)
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
          obn->data = ID_NEW_SET(obn->data, BKE_hair_copy(bmain, obn->data));
 | 
			
		||||
          didit = 1;
 | 
			
		||||
        }
 | 
			
		||||
        id_us_min(id);
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    case OB_POINTCLOUD:
 | 
			
		||||
      if (dupflag & USER_DUP_POINTCLOUD) {
 | 
			
		||||
        ID_NEW_REMAP_US2(obn->data)
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
          obn->data = ID_NEW_SET(obn->data, BKE_pointcloud_copy(bmain, obn->data));
 | 
			
		||||
          didit = 1;
 | 
			
		||||
        }
 | 
			
		||||
        id_us_min(id);
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    case OB_VOLUME:
 | 
			
		||||
      if (dupflag & USER_DUP_VOLUME) {
 | 
			
		||||
        ID_NEW_REMAP_US2(obn->data)
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
          obn->data = ID_NEW_SET(obn->data, BKE_volume_copy(bmain, obn->data));
 | 
			
		||||
          didit = 1;
 | 
			
		||||
        }
 | 
			
		||||
        id_us_min(id);
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* Check if obdata is copied. */
 | 
			
		||||
@@ -2810,6 +2858,15 @@ BoundBox *BKE_object_boundbox_get(Object *ob)
 | 
			
		||||
    case OB_GPENCIL:
 | 
			
		||||
      bb = BKE_gpencil_boundbox_get(ob);
 | 
			
		||||
      break;
 | 
			
		||||
    case OB_HAIR:
 | 
			
		||||
      bb = BKE_hair_boundbox_get(ob);
 | 
			
		||||
      break;
 | 
			
		||||
    case OB_POINTCLOUD:
 | 
			
		||||
      bb = BKE_pointcloud_boundbox_get(ob);
 | 
			
		||||
      break;
 | 
			
		||||
    case OB_VOLUME:
 | 
			
		||||
      bb = BKE_volume_boundbox_get(ob);
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      break;
 | 
			
		||||
  }
 | 
			
		||||
@@ -2980,6 +3037,25 @@ void BKE_object_minmax(Object *ob, float min_r[3], float max_r[3], const bool us
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case OB_HAIR: {
 | 
			
		||||
      bb = *BKE_hair_boundbox_get(ob);
 | 
			
		||||
      BKE_boundbox_minmax(&bb, ob->obmat, min_r, max_r);
 | 
			
		||||
      changed = true;
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    case OB_POINTCLOUD: {
 | 
			
		||||
      bb = *BKE_pointcloud_boundbox_get(ob);
 | 
			
		||||
      BKE_boundbox_minmax(&bb, ob->obmat, min_r, max_r);
 | 
			
		||||
      changed = true;
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case OB_VOLUME: {
 | 
			
		||||
      bb = *BKE_volume_boundbox_get(ob);
 | 
			
		||||
      BKE_boundbox_minmax(&bb, ob->obmat, min_r, max_r);
 | 
			
		||||
      changed = true;
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (changed == false) {
 | 
			
		||||
@@ -3125,6 +3201,7 @@ void BKE_object_foreach_display_point(Object *ob,
 | 
			
		||||
                                      void (*func_cb)(const float[3], void *),
 | 
			
		||||
                                      void *user_data)
 | 
			
		||||
{
 | 
			
		||||
  /* TODO: pointcloud and hair objects support */
 | 
			
		||||
  Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob);
 | 
			
		||||
  float co[3];
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -45,6 +45,7 @@
 | 
			
		||||
#include "BKE_editmesh.h"
 | 
			
		||||
#include "BKE_effect.h"
 | 
			
		||||
#include "BKE_gpencil_modifier.h"
 | 
			
		||||
#include "BKE_hair.h"
 | 
			
		||||
#include "BKE_image.h"
 | 
			
		||||
#include "BKE_key.h"
 | 
			
		||||
#include "BKE_layer.h"
 | 
			
		||||
@@ -56,8 +57,10 @@
 | 
			
		||||
#include "BKE_object.h"
 | 
			
		||||
#include "BKE_particle.h"
 | 
			
		||||
#include "BKE_pointcache.h"
 | 
			
		||||
#include "BKE_pointcloud.h"
 | 
			
		||||
#include "BKE_scene.h"
 | 
			
		||||
#include "BKE_gpencil.h"
 | 
			
		||||
#include "BKE_volume.h"
 | 
			
		||||
 | 
			
		||||
#include "MEM_guardedalloc.h"
 | 
			
		||||
 | 
			
		||||
@@ -225,6 +228,15 @@ void BKE_object_handle_data_update(Depsgraph *depsgraph, Scene *scene, Object *o
 | 
			
		||||
      BKE_gpencil_update_layer_parent(depsgraph, ob);
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case OB_HAIR:
 | 
			
		||||
      BKE_hair_data_update(depsgraph, scene, ob);
 | 
			
		||||
      break;
 | 
			
		||||
    case OB_POINTCLOUD:
 | 
			
		||||
      BKE_pointcloud_data_update(depsgraph, scene, ob);
 | 
			
		||||
      break;
 | 
			
		||||
    case OB_VOLUME:
 | 
			
		||||
      BKE_volume_data_update(depsgraph, scene, ob);
 | 
			
		||||
      break;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* particles */
 | 
			
		||||
@@ -354,6 +366,15 @@ void BKE_object_batch_cache_dirty_tag(Object *ob)
 | 
			
		||||
    case OB_GPENCIL:
 | 
			
		||||
      BKE_gpencil_batch_cache_dirty_tag(ob->data);
 | 
			
		||||
      break;
 | 
			
		||||
    case OB_HAIR:
 | 
			
		||||
      BKE_hair_batch_cache_dirty_tag(ob->data, BKE_HAIR_BATCH_DIRTY_ALL);
 | 
			
		||||
      break;
 | 
			
		||||
    case OB_POINTCLOUD:
 | 
			
		||||
      BKE_pointcloud_batch_cache_dirty_tag(ob->data, BKE_POINTCLOUD_BATCH_DIRTY_ALL);
 | 
			
		||||
      break;
 | 
			
		||||
    case OB_VOLUME:
 | 
			
		||||
      BKE_volume_batch_cache_dirty_tag(ob->data, BKE_VOLUME_BATCH_DIRTY_ALL);
 | 
			
		||||
      break;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -37,6 +37,7 @@
 | 
			
		||||
#include "DNA_ID.h"
 | 
			
		||||
#include "DNA_packedFile_types.h"
 | 
			
		||||
#include "DNA_sound_types.h"
 | 
			
		||||
#include "DNA_volume_types.h"
 | 
			
		||||
#include "DNA_vfont_types.h"
 | 
			
		||||
 | 
			
		||||
#include "BLI_blenlib.h"
 | 
			
		||||
@@ -48,6 +49,7 @@
 | 
			
		||||
#include "BKE_packedFile.h"
 | 
			
		||||
#include "BKE_report.h"
 | 
			
		||||
#include "BKE_sound.h"
 | 
			
		||||
#include "BKE_volume.h"
 | 
			
		||||
 | 
			
		||||
int BKE_packedfile_seek(PackedFile *pf, int offset, int whence)
 | 
			
		||||
{
 | 
			
		||||
@@ -114,6 +116,7 @@ int BKE_packedfile_count_all(Main *bmain)
 | 
			
		||||
  Image *ima;
 | 
			
		||||
  VFont *vf;
 | 
			
		||||
  bSound *sound;
 | 
			
		||||
  Volume *volume;
 | 
			
		||||
  int count = 0;
 | 
			
		||||
 | 
			
		||||
  /* let's check if there are packed files... */
 | 
			
		||||
@@ -135,6 +138,12 @@ int BKE_packedfile_count_all(Main *bmain)
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  for (volume = bmain->volumes.first; volume; volume = volume->id.next) {
 | 
			
		||||
    if (volume->packedfile) {
 | 
			
		||||
      count++;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return count;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -234,6 +243,7 @@ void BKE_packedfile_pack_all(Main *bmain, ReportList *reports, bool verbose)
 | 
			
		||||
  Image *ima;
 | 
			
		||||
  VFont *vfont;
 | 
			
		||||
  bSound *sound;
 | 
			
		||||
  Volume *volume;
 | 
			
		||||
  int tot = 0;
 | 
			
		||||
 | 
			
		||||
  for (ima = bmain->images.first; ima; ima = ima->id.next) {
 | 
			
		||||
@@ -266,6 +276,14 @@ void BKE_packedfile_pack_all(Main *bmain, ReportList *reports, bool verbose)
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  for (volume = bmain->volumes.first; volume; volume = volume->id.next) {
 | 
			
		||||
    if (volume->packedfile == NULL && !ID_IS_LINKED(volume)) {
 | 
			
		||||
      volume->packedfile = BKE_packedfile_new(
 | 
			
		||||
          reports, volume->filepath, BKE_main_blendfile_path(bmain));
 | 
			
		||||
      tot++;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (tot > 0) {
 | 
			
		||||
    BKE_reportf(reports, RPT_INFO, "Packed %d file(s)", tot);
 | 
			
		||||
  }
 | 
			
		||||
@@ -524,6 +542,9 @@ static void unpack_generate_paths(const char *name,
 | 
			
		||||
    case ID_IM:
 | 
			
		||||
      BLI_snprintf(r_relpath, relpathlen, "//textures/%s", tempname);
 | 
			
		||||
      break;
 | 
			
		||||
    case ID_VO:
 | 
			
		||||
      BLI_snprintf(r_relpath, relpathlen, "//volumes/%s", tempname);
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      break;
 | 
			
		||||
  }
 | 
			
		||||
@@ -643,6 +664,36 @@ int BKE_packedfile_unpack_image(Main *bmain,
 | 
			
		||||
  return (ret_value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int BKE_packedfile_unpack_volume(Main *bmain,
 | 
			
		||||
                                 ReportList *reports,
 | 
			
		||||
                                 Volume *volume,
 | 
			
		||||
                                 enum ePF_FileStatus how)
 | 
			
		||||
{
 | 
			
		||||
  char localname[FILE_MAX], absname[FILE_MAX];
 | 
			
		||||
  char *newfilepath;
 | 
			
		||||
  int ret_value = RET_ERROR;
 | 
			
		||||
 | 
			
		||||
  if (volume != NULL) {
 | 
			
		||||
    unpack_generate_paths(
 | 
			
		||||
        volume->filepath, (ID *)volume, absname, localname, sizeof(absname), sizeof(localname));
 | 
			
		||||
    newfilepath = BKE_packedfile_unpack_to_file(
 | 
			
		||||
        reports, BKE_main_blendfile_path(bmain), absname, localname, volume->packedfile, how);
 | 
			
		||||
    if (newfilepath != NULL) {
 | 
			
		||||
      BLI_strncpy(volume->filepath, newfilepath, sizeof(volume->filepath));
 | 
			
		||||
      MEM_freeN(newfilepath);
 | 
			
		||||
 | 
			
		||||
      BKE_packedfile_free(volume->packedfile);
 | 
			
		||||
      volume->packedfile = NULL;
 | 
			
		||||
 | 
			
		||||
      BKE_volume_unload(volume);
 | 
			
		||||
 | 
			
		||||
      ret_value = RET_OK;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return (ret_value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int BKE_packedfile_unpack_all_libraries(Main *bmain, ReportList *reports)
 | 
			
		||||
{
 | 
			
		||||
  Library *lib;
 | 
			
		||||
@@ -702,6 +753,7 @@ void BKE_packedfile_unpack_all(Main *bmain, ReportList *reports, enum ePF_FileSt
 | 
			
		||||
  Image *ima;
 | 
			
		||||
  VFont *vf;
 | 
			
		||||
  bSound *sound;
 | 
			
		||||
  Volume *volume;
 | 
			
		||||
 | 
			
		||||
  for (ima = bmain->images.first; ima; ima = ima->id.next) {
 | 
			
		||||
    if (BKE_image_has_packedfile(ima)) {
 | 
			
		||||
@@ -720,6 +772,12 @@ void BKE_packedfile_unpack_all(Main *bmain, ReportList *reports, enum ePF_FileSt
 | 
			
		||||
      BKE_packedfile_unpack_sound(bmain, reports, sound, how);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  for (volume = bmain->volumes.first; volume; volume = volume->id.next) {
 | 
			
		||||
    if (volume->packedfile) {
 | 
			
		||||
      BKE_packedfile_unpack_volume(bmain, reports, volume, how);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* ID should be not NULL, return 1 if there's a packed file */
 | 
			
		||||
@@ -738,6 +796,10 @@ bool BKE_packedfile_id_check(ID *id)
 | 
			
		||||
      bSound *snd = (bSound *)id;
 | 
			
		||||
      return snd->packedfile != NULL;
 | 
			
		||||
    }
 | 
			
		||||
    case ID_VO: {
 | 
			
		||||
      Volume *volume = (Volume *)id;
 | 
			
		||||
      return volume->packedfile != NULL;
 | 
			
		||||
    }
 | 
			
		||||
    case ID_LI: {
 | 
			
		||||
      Library *li = (Library *)id;
 | 
			
		||||
      return li->packedfile != NULL;
 | 
			
		||||
@@ -773,6 +835,13 @@ void BKE_packedfile_id_unpack(Main *bmain, ID *id, ReportList *reports, enum ePF
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case ID_VO: {
 | 
			
		||||
      Volume *volume = (Volume *)id;
 | 
			
		||||
      if (volume->packedfile) {
 | 
			
		||||
        BKE_packedfile_unpack_volume(bmain, reports, volume, how);
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case ID_LI: {
 | 
			
		||||
      Library *li = (Library *)id;
 | 
			
		||||
      BKE_reportf(reports, RPT_ERROR, "Cannot unpack individual Library file, '%s'", li->name);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										257
									
								
								source/blender/blenkernel/intern/pointcloud.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										257
									
								
								source/blender/blenkernel/intern/pointcloud.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,257 @@
 | 
			
		||||
/*
 | 
			
		||||
 * ***** 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/blenkernel/intern/pointcloud.c
 | 
			
		||||
 *  \ingroup bke
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "MEM_guardedalloc.h"
 | 
			
		||||
 | 
			
		||||
#include "DNA_defaults.h"
 | 
			
		||||
#include "DNA_object_types.h"
 | 
			
		||||
#include "DNA_pointcloud_types.h"
 | 
			
		||||
 | 
			
		||||
#include "BLI_listbase.h"
 | 
			
		||||
#include "BLI_math.h"
 | 
			
		||||
#include "BLI_rand.h"
 | 
			
		||||
#include "BLI_string.h"
 | 
			
		||||
#include "BLI_utildefines.h"
 | 
			
		||||
 | 
			
		||||
#include "BKE_animsys.h"
 | 
			
		||||
#include "BKE_customdata.h"
 | 
			
		||||
#include "BKE_idtype.h"
 | 
			
		||||
#include "BKE_global.h"
 | 
			
		||||
#include "BKE_lib_id.h"
 | 
			
		||||
#include "BKE_lib_query.h"
 | 
			
		||||
#include "BKE_lib_remap.h"
 | 
			
		||||
#include "BKE_main.h"
 | 
			
		||||
#include "BKE_modifier.h"
 | 
			
		||||
#include "BKE_object.h"
 | 
			
		||||
#include "BKE_pointcloud.h"
 | 
			
		||||
 | 
			
		||||
#include "BLT_translation.h"
 | 
			
		||||
 | 
			
		||||
#include "DEG_depsgraph_query.h"
 | 
			
		||||
 | 
			
		||||
/* PointCloud datablock */
 | 
			
		||||
 | 
			
		||||
static void pointcloud_random(PointCloud *pointcloud)
 | 
			
		||||
{
 | 
			
		||||
  pointcloud->totpoint = 400;
 | 
			
		||||
  CustomData_realloc(&pointcloud->pdata, pointcloud->totpoint);
 | 
			
		||||
  BKE_pointcloud_update_customdata_pointers(pointcloud);
 | 
			
		||||
 | 
			
		||||
  RNG *rng = BLI_rng_new(0);
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < pointcloud->totpoint; i++) {
 | 
			
		||||
    pointcloud->co[i][0] = 2.0f * BLI_rng_get_float(rng) - 1.0f;
 | 
			
		||||
    pointcloud->co[i][1] = 2.0f * BLI_rng_get_float(rng) - 1.0f;
 | 
			
		||||
    pointcloud->co[i][2] = 2.0f * BLI_rng_get_float(rng) - 1.0f;
 | 
			
		||||
    pointcloud->radius[i] = 0.05f * BLI_rng_get_float(rng);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  BLI_rng_free(rng);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void pointcloud_init_data(ID *id)
 | 
			
		||||
{
 | 
			
		||||
  PointCloud *pointcloud = (PointCloud *)id;
 | 
			
		||||
  BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(pointcloud, id));
 | 
			
		||||
 | 
			
		||||
  MEMCPY_STRUCT_AFTER(pointcloud, DNA_struct_default_get(PointCloud), id);
 | 
			
		||||
 | 
			
		||||
  CustomData_reset(&pointcloud->pdata);
 | 
			
		||||
  CustomData_add_layer(&pointcloud->pdata, CD_LOCATION, CD_CALLOC, NULL, pointcloud->totpoint);
 | 
			
		||||
  CustomData_add_layer(&pointcloud->pdata, CD_RADIUS, CD_CALLOC, NULL, pointcloud->totpoint);
 | 
			
		||||
  BKE_pointcloud_update_customdata_pointers(pointcloud);
 | 
			
		||||
 | 
			
		||||
  pointcloud_random(pointcloud);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void *BKE_pointcloud_add(Main *bmain, const char *name)
 | 
			
		||||
{
 | 
			
		||||
  PointCloud *pointcloud = BKE_libblock_alloc(bmain, ID_PT, name, 0);
 | 
			
		||||
 | 
			
		||||
  pointcloud_init_data(&pointcloud->id);
 | 
			
		||||
 | 
			
		||||
  return pointcloud;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void pointcloud_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, const int flag)
 | 
			
		||||
{
 | 
			
		||||
  PointCloud *pointcloud_dst = (PointCloud *)id_dst;
 | 
			
		||||
  const PointCloud *pointcloud_src = (const PointCloud *)id_src;
 | 
			
		||||
  pointcloud_dst->mat = MEM_dupallocN(pointcloud_dst->mat);
 | 
			
		||||
 | 
			
		||||
  const eCDAllocType alloc_type = (flag & LIB_ID_COPY_CD_REFERENCE) ? CD_REFERENCE : CD_DUPLICATE;
 | 
			
		||||
  CustomData_copy(&pointcloud_src->pdata,
 | 
			
		||||
                  &pointcloud_dst->pdata,
 | 
			
		||||
                  CD_MASK_ALL,
 | 
			
		||||
                  alloc_type,
 | 
			
		||||
                  pointcloud_dst->totpoint);
 | 
			
		||||
  BKE_pointcloud_update_customdata_pointers(pointcloud_dst);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PointCloud *BKE_pointcloud_copy(Main *bmain, const PointCloud *pointcloud)
 | 
			
		||||
{
 | 
			
		||||
  PointCloud *pointcloud_copy;
 | 
			
		||||
  BKE_id_copy(bmain, &pointcloud->id, (ID **)&pointcloud_copy);
 | 
			
		||||
  return pointcloud_copy;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void pointcloud_make_local(Main *bmain, ID *id, const int flags)
 | 
			
		||||
{
 | 
			
		||||
  BKE_lib_id_make_local_generic(bmain, id, flags);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void pointcloud_free_data(ID *id)
 | 
			
		||||
{
 | 
			
		||||
  PointCloud *pointcloud = (PointCloud *)id;
 | 
			
		||||
  BKE_animdata_free(&pointcloud->id, false);
 | 
			
		||||
  BKE_pointcloud_batch_cache_free(pointcloud);
 | 
			
		||||
  CustomData_free(&pointcloud->pdata, pointcloud->totpoint);
 | 
			
		||||
  MEM_SAFE_FREE(pointcloud->mat);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IDTypeInfo IDType_ID_PT = {
 | 
			
		||||
    .id_code = ID_PT,
 | 
			
		||||
    .id_filter = FILTER_ID_PT,
 | 
			
		||||
    .main_listbase_index = INDEX_ID_PT,
 | 
			
		||||
    .struct_size = sizeof(PointCloud),
 | 
			
		||||
    .name = "PointCloud",
 | 
			
		||||
    .name_plural = "pointclouds",
 | 
			
		||||
    .translation_context = BLT_I18NCONTEXT_ID_POINTCLOUD,
 | 
			
		||||
    .flags = 0,
 | 
			
		||||
 | 
			
		||||
    .init_data = pointcloud_init_data,
 | 
			
		||||
    .copy_data = pointcloud_copy_data,
 | 
			
		||||
    .free_data = pointcloud_free_data,
 | 
			
		||||
    .make_local = pointcloud_make_local,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
BoundBox *BKE_pointcloud_boundbox_get(Object *ob)
 | 
			
		||||
{
 | 
			
		||||
  BLI_assert(ob->type == OB_POINTCLOUD);
 | 
			
		||||
  PointCloud *pointcloud = ob->data;
 | 
			
		||||
 | 
			
		||||
  if (ob->runtime.bb != NULL && (ob->runtime.bb->flag & BOUNDBOX_DIRTY) == 0) {
 | 
			
		||||
    return ob->runtime.bb;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (ob->runtime.bb == NULL) {
 | 
			
		||||
    ob->runtime.bb = MEM_callocN(sizeof(BoundBox), "pointcloud boundbox");
 | 
			
		||||
 | 
			
		||||
    float min[3], max[3];
 | 
			
		||||
    INIT_MINMAX(min, max);
 | 
			
		||||
 | 
			
		||||
    float(*pointcloud_co)[3] = pointcloud->co;
 | 
			
		||||
    float *pointcloud_radius = pointcloud->radius;
 | 
			
		||||
    for (int a = 0; a < pointcloud->totpoint; a++) {
 | 
			
		||||
      float *co = pointcloud_co[a];
 | 
			
		||||
      float radius = (pointcloud_radius) ? pointcloud_radius[a] : 0.0f;
 | 
			
		||||
      float co_min[3] = {co[0] - radius, co[1] - radius, co[2] - radius};
 | 
			
		||||
      float co_max[3] = {co[0] + radius, co[1] + radius, co[2] + radius};
 | 
			
		||||
      DO_MIN(co_min, min);
 | 
			
		||||
      DO_MAX(co_max, max);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    BKE_boundbox_init_from_minmax(ob->runtime.bb, min, max);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return ob->runtime.bb;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void BKE_pointcloud_update_customdata_pointers(PointCloud *pointcloud)
 | 
			
		||||
{
 | 
			
		||||
  pointcloud->co = CustomData_get_layer(&pointcloud->pdata, CD_LOCATION);
 | 
			
		||||
  pointcloud->radius = CustomData_get_layer(&pointcloud->pdata, CD_RADIUS);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Dependency Graph */
 | 
			
		||||
 | 
			
		||||
PointCloud *BKE_pointcloud_new_for_eval(const PointCloud *pointcloud_src, int totpoint)
 | 
			
		||||
{
 | 
			
		||||
  PointCloud *pointcloud_dst = BKE_id_new_nomain(ID_HA, NULL);
 | 
			
		||||
 | 
			
		||||
  STRNCPY(pointcloud_dst->id.name, pointcloud_src->id.name);
 | 
			
		||||
  pointcloud_dst->mat = MEM_dupallocN(pointcloud_src->mat);
 | 
			
		||||
  pointcloud_dst->totcol = pointcloud_src->totcol;
 | 
			
		||||
 | 
			
		||||
  pointcloud_dst->totpoint = totpoint;
 | 
			
		||||
  CustomData_copy(
 | 
			
		||||
      &pointcloud_src->pdata, &pointcloud_dst->pdata, CD_MASK_ALL, CD_CALLOC, totpoint);
 | 
			
		||||
  BKE_pointcloud_update_customdata_pointers(pointcloud_dst);
 | 
			
		||||
 | 
			
		||||
  return pointcloud_dst;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PointCloud *BKE_pointcloud_copy_for_eval(struct PointCloud *pointcloud_src, bool reference)
 | 
			
		||||
{
 | 
			
		||||
  int flags = LIB_ID_COPY_LOCALIZE;
 | 
			
		||||
 | 
			
		||||
  if (reference) {
 | 
			
		||||
    flags |= LIB_ID_COPY_CD_REFERENCE;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  PointCloud *result;
 | 
			
		||||
  BKE_id_copy_ex(NULL, &pointcloud_src->id, (ID **)&result, flags);
 | 
			
		||||
  return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static PointCloud *pointcloud_evaluate_modifiers(struct Depsgraph *UNUSED(depsgraph),
 | 
			
		||||
                                                 struct Scene *UNUSED(scene),
 | 
			
		||||
                                                 Object *UNUSED(object),
 | 
			
		||||
                                                 PointCloud *pointcloud_input)
 | 
			
		||||
{
 | 
			
		||||
  return pointcloud_input;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void BKE_pointcloud_data_update(struct Depsgraph *depsgraph, struct Scene *scene, Object *object)
 | 
			
		||||
{
 | 
			
		||||
  /* Free any evaluated data and restore original data. */
 | 
			
		||||
  BKE_object_free_derived_caches(object);
 | 
			
		||||
 | 
			
		||||
  /* Evaluate modifiers. */
 | 
			
		||||
  PointCloud *pointcloud = object->data;
 | 
			
		||||
  PointCloud *pointcloud_eval = pointcloud_evaluate_modifiers(
 | 
			
		||||
      depsgraph, scene, object, pointcloud);
 | 
			
		||||
 | 
			
		||||
  /* Assign evaluated object. */
 | 
			
		||||
  const bool is_owned = (pointcloud != pointcloud_eval);
 | 
			
		||||
  BKE_object_eval_assign_data(object, &pointcloud_eval->id, is_owned);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Draw Cache */
 | 
			
		||||
void (*BKE_pointcloud_batch_cache_dirty_tag_cb)(PointCloud *pointcloud, int mode) = NULL;
 | 
			
		||||
void (*BKE_pointcloud_batch_cache_free_cb)(PointCloud *pointcloud) = NULL;
 | 
			
		||||
 | 
			
		||||
void BKE_pointcloud_batch_cache_dirty_tag(PointCloud *pointcloud, int mode)
 | 
			
		||||
{
 | 
			
		||||
  if (pointcloud->batch_cache) {
 | 
			
		||||
    BKE_pointcloud_batch_cache_dirty_tag_cb(pointcloud, mode);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void BKE_pointcloud_batch_cache_free(PointCloud *pointcloud)
 | 
			
		||||
{
 | 
			
		||||
  if (pointcloud->batch_cache) {
 | 
			
		||||
    BKE_pointcloud_batch_cache_free_cb(pointcloud);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										1242
									
								
								source/blender/blenkernel/intern/volume.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1242
									
								
								source/blender/blenkernel/intern/volume.cc
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -402,6 +402,9 @@ BlendFileData *BLO_read_from_memfile(Main *oldmain,
 | 
			
		||||
    /* make lookups of existing sound data in old main */
 | 
			
		||||
    blo_make_sound_pointer_map(fd, oldmain);
 | 
			
		||||
 | 
			
		||||
    /* make lookups of existing volume data in old main */
 | 
			
		||||
    blo_make_volume_pointer_map(fd, oldmain);
 | 
			
		||||
 | 
			
		||||
    /* removed packed data from this trick - it's internal data that needs saves */
 | 
			
		||||
 | 
			
		||||
    bfd = blo_read_file_internal(fd, filename);
 | 
			
		||||
@@ -418,6 +421,9 @@ BlendFileData *BLO_read_from_memfile(Main *oldmain,
 | 
			
		||||
    /* ensures relinked sounds are not freed */
 | 
			
		||||
    blo_end_sound_pointer_map(fd, oldmain);
 | 
			
		||||
 | 
			
		||||
    /* ensures relinked volumes are not freed */
 | 
			
		||||
    blo_end_volume_pointer_map(fd, oldmain);
 | 
			
		||||
 | 
			
		||||
    /* Still in-use libraries have already been moved from oldmain to new mainlist,
 | 
			
		||||
     * but oldmain itself shall *never* be 'transferred' to new mainlist! */
 | 
			
		||||
    BLI_assert(old_mainlist.first == oldmain);
 | 
			
		||||
 
 | 
			
		||||
@@ -58,6 +58,7 @@
 | 
			
		||||
#include "DNA_gpencil_types.h"
 | 
			
		||||
#include "DNA_gpencil_modifier_types.h"
 | 
			
		||||
#include "DNA_shader_fx_types.h"
 | 
			
		||||
#include "DNA_hair_types.h"
 | 
			
		||||
#include "DNA_ipo_types.h"
 | 
			
		||||
#include "DNA_key_types.h"
 | 
			
		||||
#include "DNA_lattice_types.h"
 | 
			
		||||
@@ -74,6 +75,7 @@
 | 
			
		||||
#include "DNA_object_types.h"
 | 
			
		||||
#include "DNA_packedFile_types.h"
 | 
			
		||||
#include "DNA_particle_types.h"
 | 
			
		||||
#include "DNA_pointcloud_types.h"
 | 
			
		||||
#include "DNA_curveprofile_types.h"
 | 
			
		||||
#include "DNA_lightprobe_types.h"
 | 
			
		||||
#include "DNA_rigidbody_types.h"
 | 
			
		||||
@@ -88,6 +90,7 @@
 | 
			
		||||
#include "DNA_sound_types.h"
 | 
			
		||||
#include "DNA_space_types.h"
 | 
			
		||||
#include "DNA_vfont_types.h"
 | 
			
		||||
#include "DNA_volume_types.h"
 | 
			
		||||
#include "DNA_workspace_types.h"
 | 
			
		||||
#include "DNA_world_types.h"
 | 
			
		||||
#include "DNA_movieclip_types.h"
 | 
			
		||||
@@ -118,6 +121,7 @@
 | 
			
		||||
#include "BKE_fluid.h"
 | 
			
		||||
#include "BKE_global.h"  // for G
 | 
			
		||||
#include "BKE_gpencil_modifier.h"
 | 
			
		||||
#include "BKE_hair.h"
 | 
			
		||||
#include "BKE_idcode.h"
 | 
			
		||||
#include "BKE_idprop.h"
 | 
			
		||||
#include "BKE_layer.h"
 | 
			
		||||
@@ -136,13 +140,14 @@
 | 
			
		||||
#include "BKE_paint.h"
 | 
			
		||||
#include "BKE_particle.h"
 | 
			
		||||
#include "BKE_pointcache.h"
 | 
			
		||||
#include "BKE_curveprofile.h"
 | 
			
		||||
#include "BKE_pointcloud.h"
 | 
			
		||||
#include "BKE_report.h"
 | 
			
		||||
#include "BKE_scene.h"
 | 
			
		||||
#include "BKE_screen.h"
 | 
			
		||||
#include "BKE_sequencer.h"
 | 
			
		||||
#include "BKE_shader_fx.h"
 | 
			
		||||
#include "BKE_sound.h"
 | 
			
		||||
#include "BKE_volume.h"
 | 
			
		||||
#include "BKE_workspace.h"
 | 
			
		||||
 | 
			
		||||
#include "DRW_engine.h"
 | 
			
		||||
@@ -1595,6 +1600,9 @@ void blo_filedata_free(FileData *fd)
 | 
			
		||||
    if (fd->soundmap) {
 | 
			
		||||
      oldnewmap_free(fd->soundmap);
 | 
			
		||||
    }
 | 
			
		||||
    if (fd->volumemap) {
 | 
			
		||||
      oldnewmap_free(fd->volumemap);
 | 
			
		||||
    }
 | 
			
		||||
    if (fd->packedmap) {
 | 
			
		||||
      oldnewmap_free(fd->packedmap);
 | 
			
		||||
    }
 | 
			
		||||
@@ -1806,6 +1814,15 @@ static void *newsoundadr(FileData *fd, const void *adr)
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* used to restore volume data after undo */
 | 
			
		||||
static void *newvolumeadr(FileData *fd, const void *adr)
 | 
			
		||||
{
 | 
			
		||||
  if (fd->volumemap && adr) {
 | 
			
		||||
    return oldnewmap_lookup_and_inc(fd->volumemap, adr, true);
 | 
			
		||||
  }
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* used to restore packed data after undo */
 | 
			
		||||
static void *newpackedadr(FileData *fd, const void *adr)
 | 
			
		||||
{
 | 
			
		||||
@@ -2112,6 +2129,37 @@ void blo_end_sound_pointer_map(FileData *fd, Main *oldmain)
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void blo_make_volume_pointer_map(FileData *fd, Main *oldmain)
 | 
			
		||||
{
 | 
			
		||||
  fd->volumemap = oldnewmap_new();
 | 
			
		||||
 | 
			
		||||
  Volume *volume = oldmain->volumes.first;
 | 
			
		||||
  for (; volume; volume = volume->id.next) {
 | 
			
		||||
    if (volume->runtime.grids) {
 | 
			
		||||
      oldnewmap_insert(fd->volumemap, volume->runtime.grids, volume->runtime.grids, 0);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* set old main volume caches to zero if it has been restored */
 | 
			
		||||
/* this works because freeing old main only happens after this call */
 | 
			
		||||
void blo_end_volume_pointer_map(FileData *fd, Main *oldmain)
 | 
			
		||||
{
 | 
			
		||||
  OldNew *entry = fd->volumemap->entries;
 | 
			
		||||
  Volume *volume = oldmain->volumes.first;
 | 
			
		||||
  int i;
 | 
			
		||||
 | 
			
		||||
  /* used entries were restored, so we put them to zero */
 | 
			
		||||
  for (i = 0; i < fd->volumemap->nentries; i++, entry++) {
 | 
			
		||||
    if (entry->nr > 0)
 | 
			
		||||
      entry->newp = NULL;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  for (; volume; volume = volume->id.next) {
 | 
			
		||||
    volume->runtime.grids = newvolumeadr(fd, volume->runtime.grids);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* XXX disabled this feature - packed files also belong in temp saves and quit.blend,
 | 
			
		||||
 * to make restore work. */
 | 
			
		||||
 | 
			
		||||
@@ -2126,6 +2174,7 @@ void blo_make_packed_pointer_map(FileData *fd, Main *oldmain)
 | 
			
		||||
  Image *ima;
 | 
			
		||||
  VFont *vfont;
 | 
			
		||||
  bSound *sound;
 | 
			
		||||
  Volume *volume;
 | 
			
		||||
  Library *lib;
 | 
			
		||||
 | 
			
		||||
  fd->packedmap = oldnewmap_new();
 | 
			
		||||
@@ -2156,6 +2205,12 @@ void blo_make_packed_pointer_map(FileData *fd, Main *oldmain)
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  for (volume = oldmain->volumes.first; volume; volume = volume->id.next) {
 | 
			
		||||
    if (volume->packedfile) {
 | 
			
		||||
      insert_packedmap(fd, volume->packedfile);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  for (lib = oldmain->libraries.first; lib; lib = lib->id.next) {
 | 
			
		||||
    if (lib->packedfile) {
 | 
			
		||||
      insert_packedmap(fd, lib->packedfile);
 | 
			
		||||
@@ -2170,6 +2225,7 @@ void blo_end_packed_pointer_map(FileData *fd, Main *oldmain)
 | 
			
		||||
  Image *ima;
 | 
			
		||||
  VFont *vfont;
 | 
			
		||||
  bSound *sound;
 | 
			
		||||
  Volume *volume;
 | 
			
		||||
  Library *lib;
 | 
			
		||||
  OldNew *entry = fd->packedmap->entries;
 | 
			
		||||
  int i;
 | 
			
		||||
@@ -2202,6 +2258,10 @@ void blo_end_packed_pointer_map(FileData *fd, Main *oldmain)
 | 
			
		||||
  for (lib = oldmain->libraries.first; lib; lib = lib->id.next) {
 | 
			
		||||
    lib->packedfile = newpackedadr(fd, lib->packedfile);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  for (volume = oldmain->volumes.first; volume; volume = volume->id.next) {
 | 
			
		||||
    volume->packedfile = newpackedadr(fd, volume->packedfile);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* undo file support: add all library pointers in lookup */
 | 
			
		||||
@@ -8961,6 +9021,89 @@ static void direct_link_linestyle(FileData *fd, FreestyleLineStyle *linestyle)
 | 
			
		||||
 | 
			
		||||
/** \} */
 | 
			
		||||
 | 
			
		||||
/* -------------------------------------------------------------------- */
 | 
			
		||||
/** \name Read ID: Hair
 | 
			
		||||
 * \{ */
 | 
			
		||||
 | 
			
		||||
static void lib_link_hair(FileData *fd, Main *UNUSED(main), Hair *hair)
 | 
			
		||||
{
 | 
			
		||||
  for (int a = 0; a < hair->totcol; a++) {
 | 
			
		||||
    hair->mat[a] = newlibadr(fd, hair->id.lib, hair->mat[a]);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void direct_link_hair(FileData *fd, Hair *hair)
 | 
			
		||||
{
 | 
			
		||||
  hair->adt = newdataadr(fd, hair->adt);
 | 
			
		||||
  direct_link_animdata(fd, hair->adt);
 | 
			
		||||
 | 
			
		||||
  /* Geometry */
 | 
			
		||||
  direct_link_customdata(fd, &hair->pdata, hair->totpoint);
 | 
			
		||||
  direct_link_customdata(fd, &hair->cdata, hair->totcurve);
 | 
			
		||||
  BKE_hair_update_customdata_pointers(hair);
 | 
			
		||||
 | 
			
		||||
  /* Materials */
 | 
			
		||||
  hair->mat = newdataadr(fd, hair->mat);
 | 
			
		||||
  test_pointer_array(fd, (void **)&hair->mat);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** \} */
 | 
			
		||||
 | 
			
		||||
/* -------------------------------------------------------------------- */
 | 
			
		||||
/** \name Read ID: Point Cloud
 | 
			
		||||
 * \{ */
 | 
			
		||||
 | 
			
		||||
static void lib_link_pointcloud(FileData *fd, Main *UNUSED(main), PointCloud *pointcloud)
 | 
			
		||||
{
 | 
			
		||||
  for (int a = 0; a < pointcloud->totcol; a++) {
 | 
			
		||||
    pointcloud->mat[a] = newlibadr(fd, pointcloud->id.lib, pointcloud->mat[a]);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void direct_link_pointcloud(FileData *fd, PointCloud *pointcloud)
 | 
			
		||||
{
 | 
			
		||||
  pointcloud->adt = newdataadr(fd, pointcloud->adt);
 | 
			
		||||
  direct_link_animdata(fd, pointcloud->adt);
 | 
			
		||||
 | 
			
		||||
  /* Geometry */
 | 
			
		||||
  direct_link_customdata(fd, &pointcloud->pdata, pointcloud->totpoint);
 | 
			
		||||
  BKE_pointcloud_update_customdata_pointers(pointcloud);
 | 
			
		||||
 | 
			
		||||
  /* Materials */
 | 
			
		||||
  pointcloud->mat = newdataadr(fd, pointcloud->mat);
 | 
			
		||||
  test_pointer_array(fd, (void **)&pointcloud->mat);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** \} */
 | 
			
		||||
 | 
			
		||||
/* -------------------------------------------------------------------- */
 | 
			
		||||
/** \name Read ID: Volume
 | 
			
		||||
 * \{ */
 | 
			
		||||
 | 
			
		||||
static void lib_link_volume(FileData *fd, Main *UNUSED(main), Volume *volume)
 | 
			
		||||
{
 | 
			
		||||
  for (int a = 0; a < volume->totcol; a++) {
 | 
			
		||||
    volume->mat[a] = newlibadr(fd, volume->id.lib, volume->mat[a]);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void direct_link_volume(FileData *fd, Volume *volume)
 | 
			
		||||
{
 | 
			
		||||
  volume->adt = newdataadr(fd, volume->adt);
 | 
			
		||||
  direct_link_animdata(fd, volume->adt);
 | 
			
		||||
 | 
			
		||||
  volume->packedfile = direct_link_packedfile(fd, volume->packedfile);
 | 
			
		||||
  volume->runtime.grids = (fd->volumemap) ? newvolumeadr(fd, volume->runtime.grids) : NULL;
 | 
			
		||||
  volume->runtime.frame = 0;
 | 
			
		||||
  BKE_volume_init_grids(volume);
 | 
			
		||||
 | 
			
		||||
  /* materials */
 | 
			
		||||
  volume->mat = newdataadr(fd, volume->mat);
 | 
			
		||||
  test_pointer_array(fd, (void **)&volume->mat);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** \} */
 | 
			
		||||
 | 
			
		||||
/* -------------------------------------------------------------------- */
 | 
			
		||||
/** \name Read Library Data Block
 | 
			
		||||
 * \{ */
 | 
			
		||||
@@ -9073,6 +9216,12 @@ static const char *dataname(short id_code)
 | 
			
		||||
      return "Data from CF";
 | 
			
		||||
    case ID_WS:
 | 
			
		||||
      return "Data from WS";
 | 
			
		||||
    case ID_HA:
 | 
			
		||||
      return "Data from HA";
 | 
			
		||||
    case ID_PT:
 | 
			
		||||
      return "Data from PT";
 | 
			
		||||
    case ID_VO:
 | 
			
		||||
      return "Data from VO";
 | 
			
		||||
  }
 | 
			
		||||
  return "Data from Lib Block";
 | 
			
		||||
}
 | 
			
		||||
@@ -9498,6 +9647,15 @@ static BHead *read_libblock(FileData *fd,
 | 
			
		||||
    case ID_WS:
 | 
			
		||||
      direct_link_workspace(fd, (WorkSpace *)id, main);
 | 
			
		||||
      break;
 | 
			
		||||
    case ID_HA:
 | 
			
		||||
      direct_link_hair(fd, (Hair *)id);
 | 
			
		||||
      break;
 | 
			
		||||
    case ID_PT:
 | 
			
		||||
      direct_link_pointcloud(fd, (PointCloud *)id);
 | 
			
		||||
      break;
 | 
			
		||||
    case ID_VO:
 | 
			
		||||
      direct_link_volume(fd, (Volume *)id);
 | 
			
		||||
      break;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  oldnewmap_free_unused(fd->datamap);
 | 
			
		||||
@@ -9825,6 +9983,15 @@ static void lib_link_all(FileData *fd, Main *bmain)
 | 
			
		||||
      case ID_VF:
 | 
			
		||||
        lib_link_vfont(fd, bmain, (VFont *)id);
 | 
			
		||||
        break;
 | 
			
		||||
      case ID_HA:
 | 
			
		||||
        lib_link_hair(fd, bmain, (Hair *)id);
 | 
			
		||||
        break;
 | 
			
		||||
      case ID_PT:
 | 
			
		||||
        lib_link_pointcloud(fd, bmain, (PointCloud *)id);
 | 
			
		||||
        break;
 | 
			
		||||
      case ID_VO:
 | 
			
		||||
        lib_link_volume(fd, bmain, (Volume *)id);
 | 
			
		||||
        break;
 | 
			
		||||
      case ID_MA:
 | 
			
		||||
        lib_link_material(fd, bmain, (Material *)id);
 | 
			
		||||
        break;
 | 
			
		||||
@@ -11236,6 +11403,39 @@ static void expand_workspace(FileData *fd, Main *mainvar, WorkSpace *workspace)
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void expand_hair(FileData *fd, Main *mainvar, Hair *hair)
 | 
			
		||||
{
 | 
			
		||||
  for (int a = 0; a < hair->totcol; a++) {
 | 
			
		||||
    expand_doit(fd, mainvar, hair->mat[a]);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (hair->adt) {
 | 
			
		||||
    expand_animdata(fd, mainvar, hair->adt);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void expand_pointcloud(FileData *fd, Main *mainvar, PointCloud *pointcloud)
 | 
			
		||||
{
 | 
			
		||||
  for (int a = 0; a < pointcloud->totcol; a++) {
 | 
			
		||||
    expand_doit(fd, mainvar, pointcloud->mat[a]);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (pointcloud->adt) {
 | 
			
		||||
    expand_animdata(fd, mainvar, pointcloud->adt);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void expand_volume(FileData *fd, Main *mainvar, Volume *volume)
 | 
			
		||||
{
 | 
			
		||||
  for (int a = 0; a < volume->totcol; a++) {
 | 
			
		||||
    expand_doit(fd, mainvar, volume->mat[a]);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (volume->adt) {
 | 
			
		||||
    expand_animdata(fd, mainvar, volume->adt);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Set the callback func used over all ID data found by \a BLO_expand_main func.
 | 
			
		||||
 *
 | 
			
		||||
@@ -11356,6 +11556,15 @@ void BLO_expand_main(void *fdhandle, Main *mainvar)
 | 
			
		||||
            case ID_WS:
 | 
			
		||||
              expand_workspace(fd, mainvar, (WorkSpace *)id);
 | 
			
		||||
              break;
 | 
			
		||||
            case ID_HA:
 | 
			
		||||
              expand_hair(fd, mainvar, (Hair *)id);
 | 
			
		||||
              break;
 | 
			
		||||
            case ID_PT:
 | 
			
		||||
              expand_pointcloud(fd, mainvar, (PointCloud *)id);
 | 
			
		||||
              break;
 | 
			
		||||
            case ID_VO:
 | 
			
		||||
              expand_volume(fd, mainvar, (Volume *)id);
 | 
			
		||||
              break;
 | 
			
		||||
            default:
 | 
			
		||||
              break;
 | 
			
		||||
          }
 | 
			
		||||
 
 | 
			
		||||
@@ -124,6 +124,7 @@ typedef struct FileData {
 | 
			
		||||
  struct OldNewMap *movieclipmap;
 | 
			
		||||
  struct OldNewMap *scenemap;
 | 
			
		||||
  struct OldNewMap *soundmap;
 | 
			
		||||
  struct OldNewMap *volumemap;
 | 
			
		||||
  struct OldNewMap *packedmap;
 | 
			
		||||
 | 
			
		||||
  struct BHeadSort *bheadmap;
 | 
			
		||||
@@ -164,6 +165,8 @@ void blo_make_movieclip_pointer_map(FileData *fd, struct Main *oldmain);
 | 
			
		||||
void blo_end_movieclip_pointer_map(FileData *fd, struct Main *oldmain);
 | 
			
		||||
void blo_make_sound_pointer_map(FileData *fd, struct Main *oldmain);
 | 
			
		||||
void blo_end_sound_pointer_map(FileData *fd, struct Main *oldmain);
 | 
			
		||||
void blo_make_volume_pointer_map(FileData *fd, struct Main *oldmain);
 | 
			
		||||
void blo_end_volume_pointer_map(FileData *fd, struct Main *oldmain);
 | 
			
		||||
void blo_make_packed_pointer_map(FileData *fd, struct Main *oldmain);
 | 
			
		||||
void blo_end_packed_pointer_map(FileData *fd, struct Main *oldmain);
 | 
			
		||||
void blo_add_library_pointer_map(ListBase *old_mainlist, FileData *fd);
 | 
			
		||||
 
 | 
			
		||||
@@ -106,6 +106,7 @@
 | 
			
		||||
#include "DNA_gpencil_types.h"
 | 
			
		||||
#include "DNA_gpencil_modifier_types.h"
 | 
			
		||||
#include "DNA_shader_fx_types.h"
 | 
			
		||||
#include "DNA_hair_types.h"
 | 
			
		||||
#include "DNA_fileglobal_types.h"
 | 
			
		||||
#include "DNA_key_types.h"
 | 
			
		||||
#include "DNA_lattice_types.h"
 | 
			
		||||
@@ -121,6 +122,7 @@
 | 
			
		||||
#include "DNA_object_force_types.h"
 | 
			
		||||
#include "DNA_packedFile_types.h"
 | 
			
		||||
#include "DNA_particle_types.h"
 | 
			
		||||
#include "DNA_pointcloud_types.h"
 | 
			
		||||
#include "DNA_lightprobe_types.h"
 | 
			
		||||
#include "DNA_rigidbody_types.h"
 | 
			
		||||
#include "DNA_scene_types.h"
 | 
			
		||||
@@ -134,6 +136,7 @@
 | 
			
		||||
#include "DNA_text_types.h"
 | 
			
		||||
#include "DNA_view3d_types.h"
 | 
			
		||||
#include "DNA_vfont_types.h"
 | 
			
		||||
#include "DNA_volume_types.h"
 | 
			
		||||
#include "DNA_world_types.h"
 | 
			
		||||
#include "DNA_windowmanager_types.h"
 | 
			
		||||
#include "DNA_workspace_types.h"
 | 
			
		||||
@@ -3712,6 +3715,98 @@ static void write_workspace(WriteData *wd, WorkSpace *workspace)
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void write_hair(WriteData *wd, Hair *hair)
 | 
			
		||||
{
 | 
			
		||||
  if (hair->id.us > 0 || wd->use_memfile) {
 | 
			
		||||
    /* Write a copy of the hair with possibly reduced number of data layers.
 | 
			
		||||
     * Don't edit the original since other threads might be reading it. */
 | 
			
		||||
    Hair *old_hair = hair;
 | 
			
		||||
    Hair copy_hair = *hair;
 | 
			
		||||
    hair = ©_hair;
 | 
			
		||||
 | 
			
		||||
    CustomDataLayer *players = NULL, players_buff[CD_TEMP_CHUNK_SIZE];
 | 
			
		||||
    CustomDataLayer *clayers = NULL, clayers_buff[CD_TEMP_CHUNK_SIZE];
 | 
			
		||||
    CustomData_file_write_prepare(&hair->pdata, &players, players_buff, ARRAY_SIZE(players_buff));
 | 
			
		||||
    CustomData_file_write_prepare(&hair->cdata, &clayers, clayers_buff, ARRAY_SIZE(clayers_buff));
 | 
			
		||||
 | 
			
		||||
    /* Write LibData */
 | 
			
		||||
    writestruct_at_address(wd, ID_HA, Hair, 1, old_hair, hair);
 | 
			
		||||
    write_iddata(wd, &hair->id);
 | 
			
		||||
 | 
			
		||||
    /* Direct data */
 | 
			
		||||
    write_customdata(wd, &hair->id, hair->totpoint, &hair->pdata, players, CD_MASK_ALL);
 | 
			
		||||
    write_customdata(wd, &hair->id, hair->totcurve, &hair->cdata, clayers, CD_MASK_ALL);
 | 
			
		||||
    writedata(wd, DATA, sizeof(void *) * hair->totcol, hair->mat);
 | 
			
		||||
    if (hair->adt) {
 | 
			
		||||
      write_animdata(wd, hair->adt);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Remove temporary data. */
 | 
			
		||||
    if (players && players != players_buff) {
 | 
			
		||||
      MEM_freeN(players);
 | 
			
		||||
    }
 | 
			
		||||
    if (clayers && clayers != clayers_buff) {
 | 
			
		||||
      MEM_freeN(clayers);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* restore pointer */
 | 
			
		||||
    hair = old_hair;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void write_pointcloud(WriteData *wd, PointCloud *pointcloud)
 | 
			
		||||
{
 | 
			
		||||
  if (pointcloud->id.us > 0 || wd->use_memfile) {
 | 
			
		||||
    /* Write a copy of the pointcloud with possibly reduced number of data layers.
 | 
			
		||||
     * Don't edit the original since other threads might be reading it. */
 | 
			
		||||
    PointCloud *old_pointcloud = pointcloud;
 | 
			
		||||
    PointCloud copy_pointcloud = *pointcloud;
 | 
			
		||||
    pointcloud = ©_pointcloud;
 | 
			
		||||
 | 
			
		||||
    CustomDataLayer *players = NULL, players_buff[CD_TEMP_CHUNK_SIZE];
 | 
			
		||||
    CustomData_file_write_prepare(
 | 
			
		||||
        &pointcloud->pdata, &players, players_buff, ARRAY_SIZE(players_buff));
 | 
			
		||||
 | 
			
		||||
    /* Write LibData */
 | 
			
		||||
    writestruct_at_address(wd, ID_PT, PointCloud, 1, old_pointcloud, pointcloud);
 | 
			
		||||
    write_iddata(wd, &pointcloud->id);
 | 
			
		||||
 | 
			
		||||
    /* Direct data */
 | 
			
		||||
    write_customdata(
 | 
			
		||||
        wd, &pointcloud->id, pointcloud->totpoint, &pointcloud->pdata, players, CD_MASK_ALL);
 | 
			
		||||
    writedata(wd, DATA, sizeof(void *) * pointcloud->totcol, pointcloud->mat);
 | 
			
		||||
    if (pointcloud->adt) {
 | 
			
		||||
      write_animdata(wd, pointcloud->adt);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Remove temporary data. */
 | 
			
		||||
    if (players && players != players_buff) {
 | 
			
		||||
      MEM_freeN(players);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void write_volume(WriteData *wd, Volume *volume)
 | 
			
		||||
{
 | 
			
		||||
  if (volume->id.us > 0 || wd->use_memfile) {
 | 
			
		||||
    /* write LibData */
 | 
			
		||||
    writestruct(wd, ID_VO, Volume, 1, volume);
 | 
			
		||||
    write_iddata(wd, &volume->id);
 | 
			
		||||
 | 
			
		||||
    /* direct data */
 | 
			
		||||
    writedata(wd, DATA, sizeof(void *) * volume->totcol, volume->mat);
 | 
			
		||||
    if (volume->adt) {
 | 
			
		||||
      write_animdata(wd, volume->adt);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (volume->packedfile) {
 | 
			
		||||
      PackedFile *pf = volume->packedfile;
 | 
			
		||||
      writestruct(wd, DATA, PackedFile, 1, pf);
 | 
			
		||||
      writedata(wd, DATA, pf->size, pf->data);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Keep it last of write_foodata functions. */
 | 
			
		||||
static void write_libraries(WriteData *wd, Main *main)
 | 
			
		||||
{
 | 
			
		||||
@@ -4017,6 +4112,15 @@ static bool write_file_handle(Main *mainvar,
 | 
			
		||||
          case ID_CF:
 | 
			
		||||
            write_cachefile(wd, (CacheFile *)id);
 | 
			
		||||
            break;
 | 
			
		||||
          case ID_HA:
 | 
			
		||||
            write_hair(wd, (Hair *)id);
 | 
			
		||||
            break;
 | 
			
		||||
          case ID_PT:
 | 
			
		||||
            write_pointcloud(wd, (PointCloud *)id);
 | 
			
		||||
            break;
 | 
			
		||||
          case ID_VO:
 | 
			
		||||
            write_volume(wd, (Volume *)id);
 | 
			
		||||
            break;
 | 
			
		||||
          case ID_LI:
 | 
			
		||||
            /* Do nothing, handled below - and should never be reached. */
 | 
			
		||||
            BLI_assert(0);
 | 
			
		||||
 
 | 
			
		||||
@@ -117,6 +117,7 @@ bool BLT_lang_is_ime_supported(void);
 | 
			
		||||
#define BLT_I18NCONTEXT_ID_CURVE "Curve"
 | 
			
		||||
#define BLT_I18NCONTEXT_ID_FREESTYLELINESTYLE "FreestyleLineStyle"
 | 
			
		||||
#define BLT_I18NCONTEXT_ID_GPENCIL "GPencil"
 | 
			
		||||
#define BLT_I18NCONTEXT_ID_HAIR "Hair"
 | 
			
		||||
#define BLT_I18NCONTEXT_ID_ID "ID"
 | 
			
		||||
#define BLT_I18NCONTEXT_ID_IMAGE "Image"
 | 
			
		||||
/*#define BLT_I18NCONTEXT_ID_IPO                  "Ipo"*/ /* Deprecated */
 | 
			
		||||
@@ -132,6 +133,7 @@ bool BLT_lang_is_ime_supported(void);
 | 
			
		||||
#define BLT_I18NCONTEXT_ID_PAINTCURVE "PaintCurve"
 | 
			
		||||
#define BLT_I18NCONTEXT_ID_PALETTE "Palette"
 | 
			
		||||
#define BLT_I18NCONTEXT_ID_PARTICLESETTINGS "ParticleSettings"
 | 
			
		||||
#define BLT_I18NCONTEXT_ID_POINTCLOUD "PointCloud"
 | 
			
		||||
#define BLT_I18NCONTEXT_ID_LIGHTPROBE "LightProbe"
 | 
			
		||||
#define BLT_I18NCONTEXT_ID_SCENE "Scene"
 | 
			
		||||
#define BLT_I18NCONTEXT_ID_SCREEN "Screen"
 | 
			
		||||
@@ -141,6 +143,7 @@ bool BLT_lang_is_ime_supported(void);
 | 
			
		||||
#define BLT_I18NCONTEXT_ID_TEXTURE "Texture"
 | 
			
		||||
#define BLT_I18NCONTEXT_ID_TEXT "Text"
 | 
			
		||||
#define BLT_I18NCONTEXT_ID_VFONT "VFont"
 | 
			
		||||
#define BLT_I18NCONTEXT_ID_VOLUME "Volume"
 | 
			
		||||
#define BLT_I18NCONTEXT_ID_WORLD "World"
 | 
			
		||||
#define BLT_I18NCONTEXT_ID_WORKSPACE "WorkSpace"
 | 
			
		||||
#define BLT_I18NCONTEXT_ID_WINDOWMANAGER "WindowManager"
 | 
			
		||||
@@ -175,6 +178,7 @@ typedef struct {
 | 
			
		||||
        BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_CURVE, "id_curve"), \
 | 
			
		||||
        BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_FREESTYLELINESTYLE, "id_fs_linestyle"), \
 | 
			
		||||
        BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_GPENCIL, "id_gpencil"), \
 | 
			
		||||
        BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_HAIR, "id_hair"), \
 | 
			
		||||
        BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_ID, "id_id"), \
 | 
			
		||||
        BLT_I18NCONTEXTS_ITEM( \
 | 
			
		||||
            BLT_I18NCONTEXT_ID_IMAGE, \
 | 
			
		||||
@@ -193,6 +197,7 @@ typedef struct {
 | 
			
		||||
        BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_PAINTCURVE, "id_paintcurve"), \
 | 
			
		||||
        BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_PALETTE, "id_palette"), \
 | 
			
		||||
        BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_PARTICLESETTINGS, "id_particlesettings"), \
 | 
			
		||||
        BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_POINTCLOUD, "id_pointcloud"), \
 | 
			
		||||
        BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_LIGHTPROBE, "id_lightprobe"), \
 | 
			
		||||
        BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_SCENE, "id_scene"), \
 | 
			
		||||
        BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_SCREEN, "id_screen"), \
 | 
			
		||||
@@ -202,6 +207,7 @@ typedef struct {
 | 
			
		||||
        BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_TEXTURE, "id_texture"), \
 | 
			
		||||
        BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_TEXT, "id_text"), \
 | 
			
		||||
        BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_VFONT, "id_vfont"), \
 | 
			
		||||
        BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_VOLUME, "id_volume"), \
 | 
			
		||||
        BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_WORLD, "id_world"), \
 | 
			
		||||
        BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_WORKSPACE, "id_workspace"), \
 | 
			
		||||
        BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_WINDOWMANAGER, "id_windowmanager"), \
 | 
			
		||||
 
 | 
			
		||||
@@ -69,6 +69,7 @@ set(SRC
 | 
			
		||||
  intern/eval/deg_eval_runtime_backup_sequence.cc
 | 
			
		||||
  intern/eval/deg_eval_runtime_backup_sequencer.cc
 | 
			
		||||
  intern/eval/deg_eval_runtime_backup_sound.cc
 | 
			
		||||
  intern/eval/deg_eval_runtime_backup_volume.cc
 | 
			
		||||
  intern/eval/deg_eval_stats.cc
 | 
			
		||||
  intern/node/deg_node.cc
 | 
			
		||||
  intern/node/deg_node_component.cc
 | 
			
		||||
@@ -122,6 +123,7 @@ set(SRC
 | 
			
		||||
  intern/eval/deg_eval_runtime_backup_sequence.h
 | 
			
		||||
  intern/eval/deg_eval_runtime_backup_sequencer.h
 | 
			
		||||
  intern/eval/deg_eval_runtime_backup_sound.h
 | 
			
		||||
  intern/eval/deg_eval_runtime_backup_volume.h
 | 
			
		||||
  intern/eval/deg_eval_stats.h
 | 
			
		||||
  intern/node/deg_node.h
 | 
			
		||||
  intern/node/deg_node_component.h
 | 
			
		||||
 
 | 
			
		||||
@@ -97,6 +97,7 @@ extern "C" {
 | 
			
		||||
#include "BKE_shader_fx.h"
 | 
			
		||||
#include "BKE_sound.h"
 | 
			
		||||
#include "BKE_tracking.h"
 | 
			
		||||
#include "BKE_volume.h"
 | 
			
		||||
#include "BKE_world.h"
 | 
			
		||||
 | 
			
		||||
#include "RNA_access.h"
 | 
			
		||||
@@ -455,6 +456,9 @@ void DepsgraphNodeBuilder::build_id(ID *id)
 | 
			
		||||
    case ID_CU:
 | 
			
		||||
    case ID_MB:
 | 
			
		||||
    case ID_LT:
 | 
			
		||||
    case ID_HA:
 | 
			
		||||
    case ID_PT:
 | 
			
		||||
    case ID_VO:
 | 
			
		||||
      /* TODO(sergey): Get visibility from a "parent" somehow.
 | 
			
		||||
       *
 | 
			
		||||
       * NOTE: Similarly to above, we don't want false-positives on
 | 
			
		||||
@@ -700,6 +704,9 @@ void DepsgraphNodeBuilder::build_object_data(Object *object, bool is_object_visi
 | 
			
		||||
    case OB_MBALL:
 | 
			
		||||
    case OB_LATTICE:
 | 
			
		||||
    case OB_GPENCIL:
 | 
			
		||||
    case OB_HAIR:
 | 
			
		||||
    case OB_POINTCLOUD:
 | 
			
		||||
    case OB_VOLUME:
 | 
			
		||||
      build_object_data_geometry(object, is_object_visible);
 | 
			
		||||
      break;
 | 
			
		||||
    case OB_ARMATURE:
 | 
			
		||||
@@ -1326,6 +1333,26 @@ void DepsgraphNodeBuilder::build_object_data_geometry_datablock(ID *obdata, bool
 | 
			
		||||
      op_node->set_as_entry();
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case ID_HA: {
 | 
			
		||||
      op_node = add_operation_node(obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL);
 | 
			
		||||
      op_node->set_as_entry();
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case ID_PT: {
 | 
			
		||||
      op_node = add_operation_node(obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL);
 | 
			
		||||
      op_node->set_as_entry();
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case ID_VO: {
 | 
			
		||||
      /* Volume frame update. */
 | 
			
		||||
      op_node = add_operation_node(
 | 
			
		||||
          obdata,
 | 
			
		||||
          NodeType::GEOMETRY,
 | 
			
		||||
          OperationCode::GEOMETRY_EVAL,
 | 
			
		||||
          function_bind(BKE_volume_eval_geometry, _1, (Volume *)obdata_cow));
 | 
			
		||||
      op_node->set_as_entry();
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    default:
 | 
			
		||||
      BLI_assert(!"Should not happen");
 | 
			
		||||
      break;
 | 
			
		||||
 
 | 
			
		||||
@@ -64,6 +64,7 @@ extern "C" {
 | 
			
		||||
#include "DNA_sound_types.h"
 | 
			
		||||
#include "DNA_speaker_types.h"
 | 
			
		||||
#include "DNA_texture_types.h"
 | 
			
		||||
#include "DNA_volume_types.h"
 | 
			
		||||
#include "DNA_world_types.h"
 | 
			
		||||
#include "DNA_object_force_types.h"
 | 
			
		||||
 | 
			
		||||
@@ -537,6 +538,9 @@ void DepsgraphRelationBuilder::build_id(ID *id)
 | 
			
		||||
    case ID_CU:
 | 
			
		||||
    case ID_MB:
 | 
			
		||||
    case ID_LT:
 | 
			
		||||
    case ID_HA:
 | 
			
		||||
    case ID_PT:
 | 
			
		||||
    case ID_VO:
 | 
			
		||||
      build_object_data_geometry_datablock(id);
 | 
			
		||||
      break;
 | 
			
		||||
    case ID_SPK:
 | 
			
		||||
@@ -771,7 +775,10 @@ void DepsgraphRelationBuilder::build_object_data(Object *object)
 | 
			
		||||
    case OB_SURF:
 | 
			
		||||
    case OB_MBALL:
 | 
			
		||||
    case OB_LATTICE:
 | 
			
		||||
    case OB_GPENCIL: {
 | 
			
		||||
    case OB_GPENCIL:
 | 
			
		||||
    case OB_HAIR:
 | 
			
		||||
    case OB_POINTCLOUD:
 | 
			
		||||
    case OB_VOLUME: {
 | 
			
		||||
      build_object_data_geometry(object);
 | 
			
		||||
      /* TODO(sergey): Only for until we support granular
 | 
			
		||||
       * update of curves. */
 | 
			
		||||
@@ -2145,6 +2152,19 @@ void DepsgraphRelationBuilder::build_object_data_geometry_datablock(ID *obdata)
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case ID_HA:
 | 
			
		||||
      break;
 | 
			
		||||
    case ID_PT:
 | 
			
		||||
      break;
 | 
			
		||||
    case ID_VO: {
 | 
			
		||||
      Volume *volume = (Volume *)obdata;
 | 
			
		||||
      if (volume->is_sequence) {
 | 
			
		||||
        TimeSourceKey time_key;
 | 
			
		||||
        ComponentKey geometry_key(obdata, NodeType::GEOMETRY);
 | 
			
		||||
        add_relation(time_key, geometry_key, "Volume sequence time");
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    default:
 | 
			
		||||
      BLI_assert(!"Should not happen");
 | 
			
		||||
      break;
 | 
			
		||||
@@ -2593,7 +2613,7 @@ void DepsgraphRelationBuilder::build_copy_on_write_relations(IDNode *id_node)
 | 
			
		||||
      continue;
 | 
			
		||||
    }
 | 
			
		||||
    int rel_flag = (RELATION_FLAG_NO_FLUSH | RELATION_FLAG_GODMODE);
 | 
			
		||||
    if ((id_type == ID_ME && comp_node->type == NodeType::GEOMETRY) ||
 | 
			
		||||
    if ((ELEM(id_type, ID_ME, ID_HA, ID_PT, ID_VO) && comp_node->type == NodeType::GEOMETRY) ||
 | 
			
		||||
        (id_type == ID_CF && comp_node->type == NodeType::CACHE)) {
 | 
			
		||||
      rel_flag &= ~RELATION_FLAG_NO_FLUSH;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -89,7 +89,7 @@ void depsgraph_geometry_tag_to_component(const ID *id, NodeType *component_type)
 | 
			
		||||
 | 
			
		||||
bool is_selectable_data_id_type(const ID_Type id_type)
 | 
			
		||||
{
 | 
			
		||||
  return ELEM(id_type, ID_ME, ID_CU, ID_MB, ID_LT, ID_GD);
 | 
			
		||||
  return ELEM(id_type, ID_ME, ID_CU, ID_MB, ID_LT, ID_GD, ID_HA, ID_PT, ID_VO);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void depsgraph_select_tag_to_component_opcode(const ID *id,
 | 
			
		||||
@@ -582,6 +582,9 @@ NodeType geometry_tag_to_component(const ID *id)
 | 
			
		||||
        case OB_LATTICE:
 | 
			
		||||
        case OB_MBALL:
 | 
			
		||||
        case OB_GPENCIL:
 | 
			
		||||
        case OB_HAIR:
 | 
			
		||||
        case OB_POINTCLOUD:
 | 
			
		||||
        case OB_VOLUME:
 | 
			
		||||
          return NodeType::GEOMETRY;
 | 
			
		||||
        case OB_ARMATURE:
 | 
			
		||||
          return NodeType::EVAL_POSE;
 | 
			
		||||
@@ -593,6 +596,9 @@ NodeType geometry_tag_to_component(const ID *id)
 | 
			
		||||
    case ID_CU:
 | 
			
		||||
    case ID_LT:
 | 
			
		||||
    case ID_MB:
 | 
			
		||||
    case ID_HA:
 | 
			
		||||
    case ID_PT:
 | 
			
		||||
    case ID_VO:
 | 
			
		||||
      return NodeType::GEOMETRY;
 | 
			
		||||
    case ID_PA: /* Particles */
 | 
			
		||||
      return NodeType::UNDEFINED;
 | 
			
		||||
 
 | 
			
		||||
@@ -37,7 +37,8 @@ RuntimeBackup::RuntimeBackup(const Depsgraph *depsgraph)
 | 
			
		||||
      sound_backup(depsgraph),
 | 
			
		||||
      object_backup(depsgraph),
 | 
			
		||||
      drawdata_ptr(nullptr),
 | 
			
		||||
      movieclip_backup(depsgraph)
 | 
			
		||||
      movieclip_backup(depsgraph),
 | 
			
		||||
      volume_backup(depsgraph)
 | 
			
		||||
{
 | 
			
		||||
  drawdata_backup.first = drawdata_backup.last = nullptr;
 | 
			
		||||
}
 | 
			
		||||
@@ -64,6 +65,9 @@ void RuntimeBackup::init_from_id(ID *id)
 | 
			
		||||
    case ID_MC:
 | 
			
		||||
      movieclip_backup.init_from_movieclip(reinterpret_cast<MovieClip *>(id));
 | 
			
		||||
      break;
 | 
			
		||||
    case ID_VO:
 | 
			
		||||
      volume_backup.init_from_volume(reinterpret_cast<Volume *>(id));
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      break;
 | 
			
		||||
  }
 | 
			
		||||
@@ -95,6 +99,9 @@ void RuntimeBackup::restore_to_id(ID *id)
 | 
			
		||||
    case ID_MC:
 | 
			
		||||
      movieclip_backup.restore_to_movieclip(reinterpret_cast<MovieClip *>(id));
 | 
			
		||||
      break;
 | 
			
		||||
    case ID_VO:
 | 
			
		||||
      volume_backup.restore_to_volume(reinterpret_cast<Volume *>(id));
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      break;
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -30,6 +30,7 @@
 | 
			
		||||
#include "intern/eval/deg_eval_runtime_backup_object.h"
 | 
			
		||||
#include "intern/eval/deg_eval_runtime_backup_scene.h"
 | 
			
		||||
#include "intern/eval/deg_eval_runtime_backup_sound.h"
 | 
			
		||||
#include "intern/eval/deg_eval_runtime_backup_volume.h"
 | 
			
		||||
 | 
			
		||||
namespace DEG {
 | 
			
		||||
 | 
			
		||||
@@ -52,6 +53,7 @@ class RuntimeBackup {
 | 
			
		||||
  DrawDataList drawdata_backup;
 | 
			
		||||
  DrawDataList *drawdata_ptr;
 | 
			
		||||
  MovieClipBackup movieclip_backup;
 | 
			
		||||
  VolumeBackup volume_backup;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace DEG
 | 
			
		||||
 
 | 
			
		||||
@@ -129,6 +129,17 @@ void ObjectRuntimeBackup::restore_to_object(Object *object)
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  else if (ELEM(object->type, OB_HAIR, OB_POINTCLOUD, OB_VOLUME)) {
 | 
			
		||||
    if (object->id.recalc & ID_RECALC_GEOMETRY) {
 | 
			
		||||
      /* Free evaluated caches. */
 | 
			
		||||
      object->data = data_orig;
 | 
			
		||||
      BKE_object_free_derived_caches(object);
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
      object->data = object->runtime.data_eval;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  object->base_flag = base_flag;
 | 
			
		||||
  object->base_local_view_bits = base_local_view_bits;
 | 
			
		||||
  /* Restore modifier's runtime data.
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,60 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This program is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU General Public License
 | 
			
		||||
 * as published by the Free Software Foundation; either version 2
 | 
			
		||||
 * of the License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 | 
			
		||||
 *
 | 
			
		||||
 * The Original Code is Copyright (C) 2019 Blender Foundation.
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/** \file
 | 
			
		||||
 * \ingroup depsgraph
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "intern/eval/deg_eval_runtime_backup_volume.h"
 | 
			
		||||
 | 
			
		||||
#include "BLI_assert.h"
 | 
			
		||||
#include "BLI_string.h"
 | 
			
		||||
#include "BLI_utildefines.h"
 | 
			
		||||
 | 
			
		||||
#include "DNA_volume_types.h"
 | 
			
		||||
 | 
			
		||||
#include "BKE_volume.h"
 | 
			
		||||
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
 | 
			
		||||
namespace DEG {
 | 
			
		||||
 | 
			
		||||
VolumeBackup::VolumeBackup(const Depsgraph * /*depsgraph*/) : grids(nullptr)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void VolumeBackup::init_from_volume(Volume *volume)
 | 
			
		||||
{
 | 
			
		||||
  STRNCPY(filepath, volume->filepath);
 | 
			
		||||
  BLI_STATIC_ASSERT(sizeof(filepath) == sizeof(volume->filepath),
 | 
			
		||||
                    "VolumeBackup filepath length wrong");
 | 
			
		||||
 | 
			
		||||
  grids = volume->runtime.grids;
 | 
			
		||||
  volume->runtime.grids = nullptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void VolumeBackup::restore_to_volume(Volume *volume)
 | 
			
		||||
{
 | 
			
		||||
  if (grids) {
 | 
			
		||||
    BKE_volume_grids_backup_restore(volume, grids, filepath);
 | 
			
		||||
    grids = nullptr;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace DEG
 | 
			
		||||
@@ -0,0 +1,45 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This program is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU General Public License
 | 
			
		||||
 * as published by the Free Software Foundation; either version 2
 | 
			
		||||
 * of the License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 | 
			
		||||
 *
 | 
			
		||||
 * The Original Code is Copyright (C) 2019 Blender Foundation.
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/** \file
 | 
			
		||||
 * \ingroup depsgraph
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
struct Volume;
 | 
			
		||||
struct VolumeGridVector;
 | 
			
		||||
 | 
			
		||||
namespace DEG {
 | 
			
		||||
 | 
			
		||||
struct Depsgraph;
 | 
			
		||||
 | 
			
		||||
/* Backup of volume datablocks runtime data. */
 | 
			
		||||
class VolumeBackup {
 | 
			
		||||
 public:
 | 
			
		||||
  VolumeBackup(const Depsgraph *depsgraph);
 | 
			
		||||
 | 
			
		||||
  void init_from_volume(Volume *volume);
 | 
			
		||||
  void restore_to_volume(Volume *volume);
 | 
			
		||||
 | 
			
		||||
  VolumeGridVector *grids;
 | 
			
		||||
  char filepath[1024]; /* FILE_MAX */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace DEG
 | 
			
		||||
							
								
								
									
										72
									
								
								source/blender/draw/engines/overlay/overlay_pointcloud.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								source/blender/draw/engines/overlay/overlay_pointcloud.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,72 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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.
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright 2020, Blender Foundation.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/** \file
 | 
			
		||||
 * \ingroup draw_engine
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "DRW_render.h"
 | 
			
		||||
 | 
			
		||||
#include "DEG_depsgraph_query.h"
 | 
			
		||||
 | 
			
		||||
#include "DNA_pointcloud_types.h"
 | 
			
		||||
 | 
			
		||||
#include "BKE_pointcache.h"
 | 
			
		||||
 | 
			
		||||
#include "overlay_private.h"
 | 
			
		||||
 | 
			
		||||
/* -------------------------------------------------------------------- */
 | 
			
		||||
/** \name PointCloud
 | 
			
		||||
 * \{ */
 | 
			
		||||
 | 
			
		||||
void OVERLAY_pointcloud_cache_init(OVERLAY_Data *vedata)
 | 
			
		||||
{
 | 
			
		||||
  OVERLAY_PassList *psl = vedata->psl;
 | 
			
		||||
  OVERLAY_PrivateData *pd = vedata->stl->pd;
 | 
			
		||||
  GPUShader *sh;
 | 
			
		||||
  DRWShadingGroup *grp;
 | 
			
		||||
 | 
			
		||||
  DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
 | 
			
		||||
  DRW_PASS_CREATE(psl->pointcloud_ps, state | pd->clipping_state);
 | 
			
		||||
 | 
			
		||||
  sh = OVERLAY_shader_pointcloud_dot();
 | 
			
		||||
  pd->pointcloud_dots_grp = grp = DRW_shgroup_create(sh, psl->pointcloud_ps);
 | 
			
		||||
  DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OVERLAY_pointcloud_cache_populate(OVERLAY_Data *vedata, Object *ob)
 | 
			
		||||
{
 | 
			
		||||
  OVERLAY_PrivateData *pd = vedata->stl->pd;
 | 
			
		||||
 | 
			
		||||
  struct GPUBatch *geom = DRW_cache_pointcloud_get_dots(ob);
 | 
			
		||||
 | 
			
		||||
  const float color[4] = {0.0f, 0.0f, 0.0f, 1.0f};
 | 
			
		||||
 | 
			
		||||
  DRWShadingGroup *grp = DRW_shgroup_create_sub(pd->pointcloud_dots_grp);
 | 
			
		||||
  DRW_shgroup_uniform_vec4_copy(grp, "color", color);
 | 
			
		||||
  DRW_shgroup_call(grp, geom, ob);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OVERLAY_pointcloud_draw(OVERLAY_Data *vedata)
 | 
			
		||||
{
 | 
			
		||||
  OVERLAY_PassList *psl = vedata->psl;
 | 
			
		||||
 | 
			
		||||
  DRW_draw_pass(psl->pointcloud_ps);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** \} */
 | 
			
		||||
@@ -0,0 +1,16 @@
 | 
			
		||||
 | 
			
		||||
in vec4 finalColor;
 | 
			
		||||
 | 
			
		||||
out vec4 fragColor;
 | 
			
		||||
 | 
			
		||||
void main()
 | 
			
		||||
{
 | 
			
		||||
  float dist = length(gl_PointCoord - vec2(0.5));
 | 
			
		||||
 | 
			
		||||
  if (dist > 0.5) {
 | 
			
		||||
    discard;
 | 
			
		||||
  }
 | 
			
		||||
  /* Nice sphere falloff. */
 | 
			
		||||
  float intensity = sqrt(1.0 - dist * 2.0) * 0.5 + 0.5;
 | 
			
		||||
  fragColor = finalColor * vec4(intensity, intensity, intensity, 1.0);
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,27 @@
 | 
			
		||||
 | 
			
		||||
uniform vec4 color;
 | 
			
		||||
 | 
			
		||||
/* ---- Per instance Attrs ---- */
 | 
			
		||||
in vec3 pointcloud_pos;
 | 
			
		||||
in vec3 pointcloud_radius;
 | 
			
		||||
 | 
			
		||||
out vec4 finalColor;
 | 
			
		||||
 | 
			
		||||
void main()
 | 
			
		||||
{
 | 
			
		||||
  vec3 world_pos = point_object_to_world(pointcloud_pos);
 | 
			
		||||
 | 
			
		||||
  vec3 world_size = abs(mat3(ModelMatrix) * vec3(pointcloud_radius));
 | 
			
		||||
  float world_radius = (world_size.x + world_size.y + world_size.z) / 3.0;
 | 
			
		||||
 | 
			
		||||
  gl_Position = point_world_to_ndc(world_pos);
 | 
			
		||||
  /* World sized points. */
 | 
			
		||||
  gl_PointSize = sizePixel * world_radius * ProjectionMatrix[1][1] * sizeViewport.y /
 | 
			
		||||
                 gl_Position.w;
 | 
			
		||||
 | 
			
		||||
  finalColor = color;
 | 
			
		||||
 | 
			
		||||
#ifdef USE_WORLD_CLIP_PLANES
 | 
			
		||||
  world_clip_planes_calc_clip_distance(world_pos);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										349
									
								
								source/blender/draw/intern/draw_cache_impl_hair.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										349
									
								
								source/blender/draw/intern/draw_cache_impl_hair.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,349 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This program is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU General Public License
 | 
			
		||||
 * as published by the Free Software Foundation; either version 2
 | 
			
		||||
 * of the License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 | 
			
		||||
 *
 | 
			
		||||
 * The Original Code is Copyright (C) 2017 by Blender Foundation.
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/** \file
 | 
			
		||||
 * \ingroup draw
 | 
			
		||||
 *
 | 
			
		||||
 * \brief Hair API for render engines
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include "MEM_guardedalloc.h"
 | 
			
		||||
 | 
			
		||||
#include "BLI_math_base.h"
 | 
			
		||||
#include "BLI_math_vector.h"
 | 
			
		||||
#include "BLI_utildefines.h"
 | 
			
		||||
 | 
			
		||||
#include "DNA_hair_types.h"
 | 
			
		||||
#include "DNA_object_types.h"
 | 
			
		||||
 | 
			
		||||
#include "BKE_hair.h"
 | 
			
		||||
 | 
			
		||||
#include "GPU_batch.h"
 | 
			
		||||
#include "GPU_texture.h"
 | 
			
		||||
 | 
			
		||||
#include "draw_cache_impl.h"   /* own include */
 | 
			
		||||
#include "draw_hair_private.h" /* own include */
 | 
			
		||||
 | 
			
		||||
static void hair_batch_cache_clear(Hair *hair);
 | 
			
		||||
 | 
			
		||||
/* ---------------------------------------------------------------------- */
 | 
			
		||||
/* Hair GPUBatch Cache */
 | 
			
		||||
 | 
			
		||||
typedef struct HairBatchCache {
 | 
			
		||||
  ParticleHairCache hair;
 | 
			
		||||
 | 
			
		||||
  /* settings to determine if cache is invalid */
 | 
			
		||||
  bool is_dirty;
 | 
			
		||||
} HairBatchCache;
 | 
			
		||||
 | 
			
		||||
/* GPUBatch cache management. */
 | 
			
		||||
 | 
			
		||||
static bool hair_batch_cache_valid(Hair *hair)
 | 
			
		||||
{
 | 
			
		||||
  HairBatchCache *cache = hair->batch_cache;
 | 
			
		||||
  return (cache && cache->is_dirty == false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void hair_batch_cache_init(Hair *hair)
 | 
			
		||||
{
 | 
			
		||||
  HairBatchCache *cache = hair->batch_cache;
 | 
			
		||||
 | 
			
		||||
  if (!cache) {
 | 
			
		||||
    cache = hair->batch_cache = MEM_callocN(sizeof(*cache), __func__);
 | 
			
		||||
  }
 | 
			
		||||
  else {
 | 
			
		||||
    memset(cache, 0, sizeof(*cache));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  cache->is_dirty = false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DRW_hair_batch_cache_validate(Hair *hair)
 | 
			
		||||
{
 | 
			
		||||
  if (!hair_batch_cache_valid(hair)) {
 | 
			
		||||
    hair_batch_cache_clear(hair);
 | 
			
		||||
    hair_batch_cache_init(hair);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static HairBatchCache *hair_batch_cache_get(Hair *hair)
 | 
			
		||||
{
 | 
			
		||||
  DRW_hair_batch_cache_validate(hair);
 | 
			
		||||
  return hair->batch_cache;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DRW_hair_batch_cache_dirty_tag(Hair *hair, int mode)
 | 
			
		||||
{
 | 
			
		||||
  HairBatchCache *cache = hair->batch_cache;
 | 
			
		||||
  if (cache == NULL) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  switch (mode) {
 | 
			
		||||
    case BKE_HAIR_BATCH_DIRTY_ALL:
 | 
			
		||||
      cache->is_dirty = true;
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      BLI_assert(0);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void hair_batch_cache_clear(Hair *hair)
 | 
			
		||||
{
 | 
			
		||||
  HairBatchCache *cache = hair->batch_cache;
 | 
			
		||||
  if (!cache) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  particle_batch_cache_clear_hair(&cache->hair);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DRW_hair_batch_cache_free(Hair *hair)
 | 
			
		||||
{
 | 
			
		||||
  hair_batch_cache_clear(hair);
 | 
			
		||||
  MEM_SAFE_FREE(hair->batch_cache);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void ensure_seg_pt_count(Hair *hair, ParticleHairCache *hair_cache)
 | 
			
		||||
{
 | 
			
		||||
  if ((hair_cache->pos != NULL && hair_cache->indices != NULL) ||
 | 
			
		||||
      (hair_cache->proc_point_buf != NULL)) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  hair_cache->strands_len = 0;
 | 
			
		||||
  hair_cache->elems_len = 0;
 | 
			
		||||
  hair_cache->point_len = 0;
 | 
			
		||||
 | 
			
		||||
  HairCurve *curve = hair->curves;
 | 
			
		||||
  int num_curves = hair->totcurve;
 | 
			
		||||
  for (int i = 0; i < num_curves; i++, curve++) {
 | 
			
		||||
    hair_cache->strands_len++;
 | 
			
		||||
    hair_cache->elems_len += curve->numpoints + 1;
 | 
			
		||||
    hair_cache->point_len += curve->numpoints;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void hair_batch_cache_fill_segments_proc_pos(Hair *hair, GPUVertBufRaw *attr_step)
 | 
			
		||||
{
 | 
			
		||||
  /* TODO: use hair radius layer if available. */
 | 
			
		||||
  HairCurve *curve = hair->curves;
 | 
			
		||||
  int num_curves = hair->totcurve;
 | 
			
		||||
  for (int i = 0; i < num_curves; i++, curve++) {
 | 
			
		||||
    float(*curve_co)[3] = hair->co + curve->firstpoint;
 | 
			
		||||
    float total_len = 0.0f;
 | 
			
		||||
    float *co_prev = NULL, *seg_data_first;
 | 
			
		||||
    for (int j = 0; j < curve->numpoints; j++) {
 | 
			
		||||
      float *seg_data = (float *)GPU_vertbuf_raw_step(attr_step);
 | 
			
		||||
      copy_v3_v3(seg_data, curve_co[j]);
 | 
			
		||||
      if (co_prev) {
 | 
			
		||||
        total_len += len_v3v3(co_prev, curve_co[j]);
 | 
			
		||||
      }
 | 
			
		||||
      else {
 | 
			
		||||
        seg_data_first = seg_data;
 | 
			
		||||
      }
 | 
			
		||||
      seg_data[3] = total_len;
 | 
			
		||||
      co_prev = curve_co[j];
 | 
			
		||||
    }
 | 
			
		||||
    if (total_len > 0.0f) {
 | 
			
		||||
      /* Divide by total length to have a [0-1] number. */
 | 
			
		||||
      for (int j = 0; j < curve->numpoints; j++, seg_data_first += 4) {
 | 
			
		||||
        seg_data_first[3] /= total_len;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void hair_batch_cache_ensure_procedural_pos(Hair *hair, ParticleHairCache *cache)
 | 
			
		||||
{
 | 
			
		||||
  if (cache->proc_point_buf != NULL) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* initialize vertex format */
 | 
			
		||||
  GPUVertFormat format = {0};
 | 
			
		||||
  uint pos_id = GPU_vertformat_attr_add(&format, "posTime", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
 | 
			
		||||
 | 
			
		||||
  cache->proc_point_buf = GPU_vertbuf_create_with_format(&format);
 | 
			
		||||
  GPU_vertbuf_data_alloc(cache->proc_point_buf, cache->point_len);
 | 
			
		||||
 | 
			
		||||
  GPUVertBufRaw pos_step;
 | 
			
		||||
  GPU_vertbuf_attr_get_raw_data(cache->proc_point_buf, pos_id, &pos_step);
 | 
			
		||||
 | 
			
		||||
  hair_batch_cache_fill_segments_proc_pos(hair, &pos_step);
 | 
			
		||||
 | 
			
		||||
  /* Create vbo immediately to bind to texture buffer. */
 | 
			
		||||
  GPU_vertbuf_use(cache->proc_point_buf);
 | 
			
		||||
 | 
			
		||||
  cache->point_tex = GPU_texture_create_from_vertbuf(cache->proc_point_buf);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void hair_batch_cache_fill_strands_data(Hair *hair,
 | 
			
		||||
                                               GPUVertBufRaw *data_step,
 | 
			
		||||
                                               GPUVertBufRaw *seg_step)
 | 
			
		||||
{
 | 
			
		||||
  HairCurve *curve = hair->curves;
 | 
			
		||||
  int num_curves = hair->totcurve;
 | 
			
		||||
  for (int i = 0; i < num_curves; i++, curve++) {
 | 
			
		||||
    *(uint *)GPU_vertbuf_raw_step(data_step) = curve->firstpoint;
 | 
			
		||||
    *(ushort *)GPU_vertbuf_raw_step(seg_step) = curve->numpoints - 1;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void hair_batch_cache_ensure_procedural_strand_data(Hair *hair, ParticleHairCache *cache)
 | 
			
		||||
{
 | 
			
		||||
  GPUVertBufRaw data_step, seg_step;
 | 
			
		||||
 | 
			
		||||
  GPUVertFormat format_data = {0};
 | 
			
		||||
  uint data_id = GPU_vertformat_attr_add(&format_data, "data", GPU_COMP_U32, 1, GPU_FETCH_INT);
 | 
			
		||||
 | 
			
		||||
  GPUVertFormat format_seg = {0};
 | 
			
		||||
  uint seg_id = GPU_vertformat_attr_add(&format_seg, "data", GPU_COMP_U16, 1, GPU_FETCH_INT);
 | 
			
		||||
 | 
			
		||||
  /* Strand Data */
 | 
			
		||||
  cache->proc_strand_buf = GPU_vertbuf_create_with_format(&format_data);
 | 
			
		||||
  GPU_vertbuf_data_alloc(cache->proc_strand_buf, cache->strands_len);
 | 
			
		||||
  GPU_vertbuf_attr_get_raw_data(cache->proc_strand_buf, data_id, &data_step);
 | 
			
		||||
 | 
			
		||||
  cache->proc_strand_seg_buf = GPU_vertbuf_create_with_format(&format_seg);
 | 
			
		||||
  GPU_vertbuf_data_alloc(cache->proc_strand_seg_buf, cache->strands_len);
 | 
			
		||||
  GPU_vertbuf_attr_get_raw_data(cache->proc_strand_seg_buf, seg_id, &seg_step);
 | 
			
		||||
 | 
			
		||||
  hair_batch_cache_fill_strands_data(hair, &data_step, &seg_step);
 | 
			
		||||
 | 
			
		||||
  /* Create vbo immediately to bind to texture buffer. */
 | 
			
		||||
  GPU_vertbuf_use(cache->proc_strand_buf);
 | 
			
		||||
  cache->strand_tex = GPU_texture_create_from_vertbuf(cache->proc_strand_buf);
 | 
			
		||||
 | 
			
		||||
  GPU_vertbuf_use(cache->proc_strand_seg_buf);
 | 
			
		||||
  cache->strand_seg_tex = GPU_texture_create_from_vertbuf(cache->proc_strand_seg_buf);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void hair_batch_cache_ensure_procedural_final_points(ParticleHairCache *cache, int subdiv)
 | 
			
		||||
{
 | 
			
		||||
  /* Same format as point_tex. */
 | 
			
		||||
  GPUVertFormat format = {0};
 | 
			
		||||
  GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
 | 
			
		||||
 | 
			
		||||
  cache->final[subdiv].proc_buf = GPU_vertbuf_create_with_format(&format);
 | 
			
		||||
 | 
			
		||||
  /* Create a destination buffer for the transform feedback. Sized appropriately */
 | 
			
		||||
  /* Those are points! not line segments. */
 | 
			
		||||
  GPU_vertbuf_data_alloc(cache->final[subdiv].proc_buf,
 | 
			
		||||
                         cache->final[subdiv].strands_res * cache->strands_len);
 | 
			
		||||
 | 
			
		||||
  /* Create vbo immediately to bind to texture buffer. */
 | 
			
		||||
  GPU_vertbuf_use(cache->final[subdiv].proc_buf);
 | 
			
		||||
 | 
			
		||||
  cache->final[subdiv].proc_tex = GPU_texture_create_from_vertbuf(cache->final[subdiv].proc_buf);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void hair_batch_cache_fill_segments_indices(Hair *hair,
 | 
			
		||||
                                                   const int res,
 | 
			
		||||
                                                   GPUIndexBufBuilder *elb)
 | 
			
		||||
{
 | 
			
		||||
  HairCurve *curve = hair->curves;
 | 
			
		||||
  int num_curves = hair->totcurve;
 | 
			
		||||
  uint curr_point = 0;
 | 
			
		||||
  for (int i = 0; i < num_curves; i++, curve++) {
 | 
			
		||||
    for (int k = 0; k < res; k++) {
 | 
			
		||||
      GPU_indexbuf_add_generic_vert(elb, curr_point++);
 | 
			
		||||
    }
 | 
			
		||||
    GPU_indexbuf_add_primitive_restart(elb);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void hair_batch_cache_ensure_procedural_indices(Hair *hair,
 | 
			
		||||
                                                       ParticleHairCache *cache,
 | 
			
		||||
                                                       int thickness_res,
 | 
			
		||||
                                                       int subdiv)
 | 
			
		||||
{
 | 
			
		||||
  BLI_assert(thickness_res <= MAX_THICKRES); /* Cylinder strip not currently supported. */
 | 
			
		||||
 | 
			
		||||
  if (cache->final[subdiv].proc_hairs[thickness_res - 1] != NULL) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  int verts_per_hair = cache->final[subdiv].strands_res * thickness_res;
 | 
			
		||||
  /* +1 for primitive restart */
 | 
			
		||||
  int element_count = (verts_per_hair + 1) * cache->strands_len;
 | 
			
		||||
  GPUPrimType prim_type = (thickness_res == 1) ? GPU_PRIM_LINE_STRIP : GPU_PRIM_TRI_STRIP;
 | 
			
		||||
 | 
			
		||||
  static GPUVertFormat format = {0};
 | 
			
		||||
  GPU_vertformat_clear(&format);
 | 
			
		||||
 | 
			
		||||
  /* initialize vertex format */
 | 
			
		||||
  GPU_vertformat_attr_add(&format, "dummy", GPU_COMP_U8, 1, GPU_FETCH_INT_TO_FLOAT_UNIT);
 | 
			
		||||
 | 
			
		||||
  GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
 | 
			
		||||
  GPU_vertbuf_data_alloc(vbo, 1);
 | 
			
		||||
 | 
			
		||||
  GPUIndexBufBuilder elb;
 | 
			
		||||
  GPU_indexbuf_init_ex(&elb, prim_type, element_count, element_count);
 | 
			
		||||
 | 
			
		||||
  hair_batch_cache_fill_segments_indices(hair, verts_per_hair, &elb);
 | 
			
		||||
 | 
			
		||||
  cache->final[subdiv].proc_hairs[thickness_res - 1] = GPU_batch_create_ex(
 | 
			
		||||
      prim_type, vbo, GPU_indexbuf_build(&elb), GPU_BATCH_OWNS_VBO | GPU_BATCH_OWNS_INDEX);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Ensure all textures and buffers needed for GPU accelerated drawing. */
 | 
			
		||||
bool hair_ensure_procedural_data(Object *object,
 | 
			
		||||
                                 ParticleHairCache **r_hair_cache,
 | 
			
		||||
                                 int subdiv,
 | 
			
		||||
                                 int thickness_res)
 | 
			
		||||
{
 | 
			
		||||
  bool need_ft_update = false;
 | 
			
		||||
  Hair *hair = object->data;
 | 
			
		||||
 | 
			
		||||
  HairBatchCache *cache = hair_batch_cache_get(hair);
 | 
			
		||||
  *r_hair_cache = &cache->hair;
 | 
			
		||||
 | 
			
		||||
  const int steps = 2; /* TODO: don't hardcode? */
 | 
			
		||||
  (*r_hair_cache)->final[subdiv].strands_res = 1 << (steps + subdiv);
 | 
			
		||||
 | 
			
		||||
  /* Refreshed on combing and simulation. */
 | 
			
		||||
  if ((*r_hair_cache)->proc_point_buf == NULL) {
 | 
			
		||||
    ensure_seg_pt_count(hair, &cache->hair);
 | 
			
		||||
    hair_batch_cache_ensure_procedural_pos(hair, &cache->hair);
 | 
			
		||||
    need_ft_update = true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* Refreshed if active layer or custom data changes. */
 | 
			
		||||
  if ((*r_hair_cache)->strand_tex == NULL) {
 | 
			
		||||
    hair_batch_cache_ensure_procedural_strand_data(hair, &cache->hair);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* Refreshed only on subdiv count change. */
 | 
			
		||||
  if ((*r_hair_cache)->final[subdiv].proc_buf == NULL) {
 | 
			
		||||
    hair_batch_cache_ensure_procedural_final_points(&cache->hair, subdiv);
 | 
			
		||||
    need_ft_update = true;
 | 
			
		||||
  }
 | 
			
		||||
  if ((*r_hair_cache)->final[subdiv].proc_hairs[thickness_res - 1] == NULL) {
 | 
			
		||||
    hair_batch_cache_ensure_procedural_indices(hair, &cache->hair, thickness_res, subdiv);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return need_ft_update;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int DRW_hair_material_count_get(Hair *hair)
 | 
			
		||||
{
 | 
			
		||||
  return max_ii(1, hair->totcol);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										176
									
								
								source/blender/draw/intern/draw_cache_impl_pointcloud.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										176
									
								
								source/blender/draw/intern/draw_cache_impl_pointcloud.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,176 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This program is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU General Public License
 | 
			
		||||
 * as published by the Free Software Foundation; either version 2
 | 
			
		||||
 * of the License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 | 
			
		||||
 *
 | 
			
		||||
 * The Original Code is Copyright (C) 2017 by Blender Foundation.
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/** \file
 | 
			
		||||
 * \ingroup draw
 | 
			
		||||
 *
 | 
			
		||||
 * \brief PointCloud API for render engines
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include "MEM_guardedalloc.h"
 | 
			
		||||
 | 
			
		||||
#include "BLI_math_base.h"
 | 
			
		||||
#include "BLI_utildefines.h"
 | 
			
		||||
 | 
			
		||||
#include "DNA_object_types.h"
 | 
			
		||||
#include "DNA_pointcloud_types.h"
 | 
			
		||||
 | 
			
		||||
#include "BKE_pointcloud.h"
 | 
			
		||||
 | 
			
		||||
#include "GPU_batch.h"
 | 
			
		||||
 | 
			
		||||
#include "draw_cache_impl.h" /* own include */
 | 
			
		||||
 | 
			
		||||
static void pointcloud_batch_cache_clear(PointCloud *pointcloud);
 | 
			
		||||
 | 
			
		||||
/* ---------------------------------------------------------------------- */
 | 
			
		||||
/* PointCloud GPUBatch Cache */
 | 
			
		||||
 | 
			
		||||
typedef struct PointCloudBatchCache {
 | 
			
		||||
  GPUVertBuf *pos;
 | 
			
		||||
  GPUBatch *batch;
 | 
			
		||||
 | 
			
		||||
  /* settings to determine if cache is invalid */
 | 
			
		||||
  bool is_dirty;
 | 
			
		||||
} PointCloudBatchCache;
 | 
			
		||||
 | 
			
		||||
/* GPUBatch cache management. */
 | 
			
		||||
 | 
			
		||||
static bool pointcloud_batch_cache_valid(PointCloud *pointcloud)
 | 
			
		||||
{
 | 
			
		||||
  PointCloudBatchCache *cache = pointcloud->batch_cache;
 | 
			
		||||
  return (cache && cache->is_dirty == false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void pointcloud_batch_cache_init(PointCloud *pointcloud)
 | 
			
		||||
{
 | 
			
		||||
  PointCloudBatchCache *cache = pointcloud->batch_cache;
 | 
			
		||||
 | 
			
		||||
  if (!cache) {
 | 
			
		||||
    cache = pointcloud->batch_cache = MEM_callocN(sizeof(*cache), __func__);
 | 
			
		||||
  }
 | 
			
		||||
  else {
 | 
			
		||||
    memset(cache, 0, sizeof(*cache));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  cache->is_dirty = false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DRW_pointcloud_batch_cache_validate(PointCloud *pointcloud)
 | 
			
		||||
{
 | 
			
		||||
  if (!pointcloud_batch_cache_valid(pointcloud)) {
 | 
			
		||||
    pointcloud_batch_cache_clear(pointcloud);
 | 
			
		||||
    pointcloud_batch_cache_init(pointcloud);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static PointCloudBatchCache *pointcloud_batch_cache_get(PointCloud *pointcloud)
 | 
			
		||||
{
 | 
			
		||||
  return pointcloud->batch_cache;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DRW_pointcloud_batch_cache_dirty_tag(PointCloud *pointcloud, int mode)
 | 
			
		||||
{
 | 
			
		||||
  PointCloudBatchCache *cache = pointcloud->batch_cache;
 | 
			
		||||
  if (cache == NULL) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  switch (mode) {
 | 
			
		||||
    case BKE_POINTCLOUD_BATCH_DIRTY_ALL:
 | 
			
		||||
      cache->is_dirty = true;
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      BLI_assert(0);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void pointcloud_batch_cache_clear(PointCloud *pointcloud)
 | 
			
		||||
{
 | 
			
		||||
  PointCloudBatchCache *cache = pointcloud->batch_cache;
 | 
			
		||||
  if (!cache) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  GPU_BATCH_DISCARD_SAFE(cache->batch);
 | 
			
		||||
  GPU_VERTBUF_DISCARD_SAFE(cache->pos);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DRW_pointcloud_batch_cache_free(PointCloud *pointcloud)
 | 
			
		||||
{
 | 
			
		||||
  pointcloud_batch_cache_clear(pointcloud);
 | 
			
		||||
  MEM_SAFE_FREE(pointcloud->batch_cache);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void pointcloud_batch_cache_ensure_pos(Object *ob, PointCloudBatchCache *cache)
 | 
			
		||||
{
 | 
			
		||||
  if (cache->pos != NULL) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  PointCloud *pointcloud = ob->data;
 | 
			
		||||
 | 
			
		||||
  static GPUVertFormat format = {0};
 | 
			
		||||
  static uint pos_id;
 | 
			
		||||
  static uint radius_id;
 | 
			
		||||
  if (format.attr_len == 0) {
 | 
			
		||||
    /* initialize vertex format */
 | 
			
		||||
    pos_id = GPU_vertformat_attr_add(&format, "pointcloud_pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
 | 
			
		||||
    radius_id = GPU_vertformat_attr_add(
 | 
			
		||||
        &format, "pointcloud_radius", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  GPU_VERTBUF_DISCARD_SAFE(cache->pos);
 | 
			
		||||
  cache->pos = GPU_vertbuf_create_with_format(&format);
 | 
			
		||||
  GPU_vertbuf_data_alloc(cache->pos, pointcloud->totpoint);
 | 
			
		||||
  GPU_vertbuf_attr_fill(cache->pos, pos_id, pointcloud->co);
 | 
			
		||||
 | 
			
		||||
  if (pointcloud->radius) {
 | 
			
		||||
    GPU_vertbuf_attr_fill(cache->pos, radius_id, pointcloud->radius);
 | 
			
		||||
  }
 | 
			
		||||
  else if (pointcloud->totpoint) {
 | 
			
		||||
    /* TODO: optimize for constant radius by not including in vertex buffer at all? */
 | 
			
		||||
    float *radius = MEM_malloc_arrayN(pointcloud->totpoint, sizeof(float), __func__);
 | 
			
		||||
    for (int i = 0; i < pointcloud->totpoint; i++) {
 | 
			
		||||
      /* TODO: add default radius to PointCloud data structure. */
 | 
			
		||||
      radius[i] = 0.01f;
 | 
			
		||||
    }
 | 
			
		||||
    GPU_vertbuf_attr_fill(cache->pos, radius_id, radius);
 | 
			
		||||
    MEM_freeN(radius);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GPUBatch *DRW_pointcloud_batch_cache_get_dots(Object *ob)
 | 
			
		||||
{
 | 
			
		||||
  PointCloud *pointcloud = ob->data;
 | 
			
		||||
  PointCloudBatchCache *cache = pointcloud_batch_cache_get(pointcloud);
 | 
			
		||||
 | 
			
		||||
  if (cache->batch == NULL) {
 | 
			
		||||
    pointcloud_batch_cache_ensure_pos(ob, cache);
 | 
			
		||||
    cache->batch = GPU_batch_create(GPU_PRIM_POINTS, cache->pos, NULL);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return cache->batch;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int DRW_pointcloud_material_count_get(PointCloud *pointcloud)
 | 
			
		||||
{
 | 
			
		||||
  return max_ii(1, pointcloud->totcol);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										297
									
								
								source/blender/draw/intern/draw_cache_impl_volume.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										297
									
								
								source/blender/draw/intern/draw_cache_impl_volume.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,297 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This program is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU General Public License
 | 
			
		||||
 * as published by the Free Software Foundation; either version 2
 | 
			
		||||
 * of the License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 | 
			
		||||
 *
 | 
			
		||||
 * The Original Code is Copyright (C) 2017 by Blender Foundation.
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/** \file
 | 
			
		||||
 * \ingroup draw
 | 
			
		||||
 *
 | 
			
		||||
 * \brief Volume API for render engines
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include "MEM_guardedalloc.h"
 | 
			
		||||
 | 
			
		||||
#include "BLI_math_base.h"
 | 
			
		||||
#include "BLI_math_vector.h"
 | 
			
		||||
#include "BLI_utildefines.h"
 | 
			
		||||
 | 
			
		||||
#include "DNA_object_types.h"
 | 
			
		||||
#include "DNA_volume_types.h"
 | 
			
		||||
 | 
			
		||||
#include "BKE_global.h"
 | 
			
		||||
#include "BKE_volume.h"
 | 
			
		||||
#include "BKE_volume_render.h"
 | 
			
		||||
 | 
			
		||||
#include "GPU_batch.h"
 | 
			
		||||
#include "GPU_texture.h"
 | 
			
		||||
 | 
			
		||||
#include "DRW_render.h"
 | 
			
		||||
 | 
			
		||||
#include "draw_cache.h"      /* own include */
 | 
			
		||||
#include "draw_cache_impl.h" /* own include */
 | 
			
		||||
 | 
			
		||||
static void volume_batch_cache_clear(Volume *volume);
 | 
			
		||||
 | 
			
		||||
/* ---------------------------------------------------------------------- */
 | 
			
		||||
/* Volume GPUBatch Cache */
 | 
			
		||||
 | 
			
		||||
typedef struct VolumeBatchCache {
 | 
			
		||||
  /* 3D textures */
 | 
			
		||||
  ListBase grids;
 | 
			
		||||
 | 
			
		||||
  /* Wireframe */
 | 
			
		||||
  struct {
 | 
			
		||||
    GPUVertBuf *pos_nor_in_order;
 | 
			
		||||
    GPUBatch *batch;
 | 
			
		||||
  } face_wire;
 | 
			
		||||
 | 
			
		||||
  /* settings to determine if cache is invalid */
 | 
			
		||||
  bool is_dirty;
 | 
			
		||||
} VolumeBatchCache;
 | 
			
		||||
 | 
			
		||||
/* GPUBatch cache management. */
 | 
			
		||||
 | 
			
		||||
static bool volume_batch_cache_valid(Volume *volume)
 | 
			
		||||
{
 | 
			
		||||
  VolumeBatchCache *cache = volume->batch_cache;
 | 
			
		||||
  return (cache && cache->is_dirty == false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void volume_batch_cache_init(Volume *volume)
 | 
			
		||||
{
 | 
			
		||||
  VolumeBatchCache *cache = volume->batch_cache;
 | 
			
		||||
 | 
			
		||||
  if (!cache) {
 | 
			
		||||
    cache = volume->batch_cache = MEM_callocN(sizeof(*cache), __func__);
 | 
			
		||||
  }
 | 
			
		||||
  else {
 | 
			
		||||
    memset(cache, 0, sizeof(*cache));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  cache->is_dirty = false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DRW_volume_batch_cache_validate(Volume *volume)
 | 
			
		||||
{
 | 
			
		||||
  if (!volume_batch_cache_valid(volume)) {
 | 
			
		||||
    volume_batch_cache_clear(volume);
 | 
			
		||||
    volume_batch_cache_init(volume);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static VolumeBatchCache *volume_batch_cache_get(Volume *volume)
 | 
			
		||||
{
 | 
			
		||||
  DRW_volume_batch_cache_validate(volume);
 | 
			
		||||
  return volume->batch_cache;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DRW_volume_batch_cache_dirty_tag(Volume *volume, int mode)
 | 
			
		||||
{
 | 
			
		||||
  VolumeBatchCache *cache = volume->batch_cache;
 | 
			
		||||
  if (cache == NULL) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  switch (mode) {
 | 
			
		||||
    case BKE_VOLUME_BATCH_DIRTY_ALL:
 | 
			
		||||
      cache->is_dirty = true;
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      BLI_assert(0);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void volume_batch_cache_clear(Volume *volume)
 | 
			
		||||
{
 | 
			
		||||
  VolumeBatchCache *cache = volume->batch_cache;
 | 
			
		||||
  if (!cache) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  for (DRWVolumeGrid *grid = cache->grids.first; grid; grid = grid->next) {
 | 
			
		||||
    MEM_SAFE_FREE(grid->name);
 | 
			
		||||
    DRW_TEXTURE_FREE_SAFE(grid->texture);
 | 
			
		||||
  }
 | 
			
		||||
  BLI_freelistN(&cache->grids);
 | 
			
		||||
 | 
			
		||||
  GPU_VERTBUF_DISCARD_SAFE(cache->face_wire.pos_nor_in_order);
 | 
			
		||||
  GPU_BATCH_DISCARD_SAFE(cache->face_wire.batch);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DRW_volume_batch_cache_free(Volume *volume)
 | 
			
		||||
{
 | 
			
		||||
  volume_batch_cache_clear(volume);
 | 
			
		||||
  MEM_SAFE_FREE(volume->batch_cache);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void drw_volume_wireframe_cb(
 | 
			
		||||
    void *userdata, float (*verts)[3], int (*edges)[2], int totvert, int totedge)
 | 
			
		||||
{
 | 
			
		||||
  Volume *volume = userdata;
 | 
			
		||||
  VolumeBatchCache *cache = volume->batch_cache;
 | 
			
		||||
 | 
			
		||||
  /* Create vertex buffer. */
 | 
			
		||||
  static GPUVertFormat format = {0};
 | 
			
		||||
  static uint pos_id, nor_id;
 | 
			
		||||
  if (format.attr_len == 0) {
 | 
			
		||||
    pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
 | 
			
		||||
    nor_id = GPU_vertformat_attr_add(&format, "nor", GPU_COMP_I10, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static float normal[3] = {1.0f, 0.0f, 0.0f};
 | 
			
		||||
  GPUPackedNormal packed_normal = GPU_normal_convert_i10_v3(normal);
 | 
			
		||||
 | 
			
		||||
  cache->face_wire.pos_nor_in_order = GPU_vertbuf_create_with_format(&format);
 | 
			
		||||
  GPU_vertbuf_data_alloc(cache->face_wire.pos_nor_in_order, totvert);
 | 
			
		||||
  GPU_vertbuf_attr_fill(cache->face_wire.pos_nor_in_order, pos_id, verts);
 | 
			
		||||
  GPU_vertbuf_attr_fill_stride(cache->face_wire.pos_nor_in_order, nor_id, 0, &packed_normal);
 | 
			
		||||
 | 
			
		||||
  /* Create wiredata. */
 | 
			
		||||
  GPUVertBuf *vbo_wiredata = MEM_callocN(sizeof(GPUVertBuf), __func__);
 | 
			
		||||
  DRW_vertbuf_create_wiredata(vbo_wiredata, totvert);
 | 
			
		||||
 | 
			
		||||
  if (volume->display.wireframe_type == VOLUME_WIREFRAME_POINTS) {
 | 
			
		||||
    /* Create batch. */
 | 
			
		||||
    cache->face_wire.batch = GPU_batch_create(
 | 
			
		||||
        GPU_PRIM_POINTS, cache->face_wire.pos_nor_in_order, NULL);
 | 
			
		||||
  }
 | 
			
		||||
  else {
 | 
			
		||||
    /* Create edge index buffer. */
 | 
			
		||||
    GPUIndexBufBuilder elb;
 | 
			
		||||
    GPU_indexbuf_init(&elb, GPU_PRIM_LINES, totedge, totvert);
 | 
			
		||||
    for (int i = 0; i < totedge; i++) {
 | 
			
		||||
      GPU_indexbuf_add_line_verts(&elb, edges[i][0], edges[i][1]);
 | 
			
		||||
    }
 | 
			
		||||
    GPUIndexBuf *ibo = GPU_indexbuf_build(&elb);
 | 
			
		||||
 | 
			
		||||
    /* Create batch. */
 | 
			
		||||
    cache->face_wire.batch = GPU_batch_create_ex(
 | 
			
		||||
        GPU_PRIM_LINES, cache->face_wire.pos_nor_in_order, ibo, GPU_BATCH_OWNS_INDEX);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  GPU_batch_vertbuf_add_ex(cache->face_wire.batch, vbo_wiredata, true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GPUBatch *DRW_volume_batch_cache_get_wireframes_face(Volume *volume)
 | 
			
		||||
{
 | 
			
		||||
  if (volume->display.wireframe_type == VOLUME_WIREFRAME_NONE) {
 | 
			
		||||
    return NULL;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  VolumeBatchCache *cache = volume_batch_cache_get(volume);
 | 
			
		||||
 | 
			
		||||
  if (cache->face_wire.batch == NULL) {
 | 
			
		||||
    VolumeGrid *volume_grid = BKE_volume_grid_active_get(volume);
 | 
			
		||||
    if (volume_grid == NULL) {
 | 
			
		||||
      return NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Create wireframe from OpenVDB tree. */
 | 
			
		||||
    BKE_volume_grid_wireframe(volume, volume_grid, drw_volume_wireframe_cb, volume);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return cache->face_wire.batch;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static DRWVolumeGrid *volume_grid_cache_get(Volume *volume,
 | 
			
		||||
                                            VolumeGrid *grid,
 | 
			
		||||
                                            VolumeBatchCache *cache)
 | 
			
		||||
{
 | 
			
		||||
  const char *name = BKE_volume_grid_name(grid);
 | 
			
		||||
 | 
			
		||||
  /* Return cached grid. */
 | 
			
		||||
  DRWVolumeGrid *cache_grid;
 | 
			
		||||
  for (cache_grid = cache->grids.first; cache_grid; cache_grid = cache_grid->next) {
 | 
			
		||||
    if (STREQ(cache_grid->name, name)) {
 | 
			
		||||
      return cache_grid;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* Allocate new grid. */
 | 
			
		||||
  cache_grid = MEM_callocN(sizeof(DRWVolumeGrid), __func__);
 | 
			
		||||
  cache_grid->name = BLI_strdup(name);
 | 
			
		||||
  BLI_addtail(&cache->grids, cache_grid);
 | 
			
		||||
 | 
			
		||||
  /* TODO: can we load this earlier, avoid accessing the global and take
 | 
			
		||||
   * advantage of dependency graph multithreading? */
 | 
			
		||||
  BKE_volume_load(volume, G.main);
 | 
			
		||||
 | 
			
		||||
  /* Test if we support textures with the number of channels. */
 | 
			
		||||
  size_t channels = BKE_volume_grid_channels(grid);
 | 
			
		||||
  if (!ELEM(channels, 1, 3)) {
 | 
			
		||||
    return cache_grid;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* Load grid tree into memory, if not loaded already. */
 | 
			
		||||
  const bool was_loaded = BKE_volume_grid_is_loaded(grid);
 | 
			
		||||
  BKE_volume_grid_load(volume, grid);
 | 
			
		||||
 | 
			
		||||
  /* Compute dense voxel grid size. */
 | 
			
		||||
  int64_t dense_min[3], dense_max[3], resolution[3] = {0};
 | 
			
		||||
  if (BKE_volume_grid_dense_bounds(volume, grid, dense_min, dense_max)) {
 | 
			
		||||
    resolution[0] = dense_max[0] - dense_min[0];
 | 
			
		||||
    resolution[1] = dense_max[1] - dense_min[1];
 | 
			
		||||
    resolution[2] = dense_max[2] - dense_min[2];
 | 
			
		||||
  }
 | 
			
		||||
  size_t num_voxels = resolution[0] * resolution[1] * resolution[2];
 | 
			
		||||
  size_t elem_size = sizeof(float) * channels;
 | 
			
		||||
 | 
			
		||||
  /* Allocate and load voxels. */
 | 
			
		||||
  float *voxels = (num_voxels > 0) ? MEM_malloc_arrayN(num_voxels, elem_size, __func__) : NULL;
 | 
			
		||||
  if (voxels != NULL) {
 | 
			
		||||
    BKE_volume_grid_dense_voxels(volume, grid, dense_min, dense_max, voxels);
 | 
			
		||||
 | 
			
		||||
    /* Create GPU texture. */
 | 
			
		||||
    cache_grid->texture = GPU_texture_create_3d(resolution[0],
 | 
			
		||||
                                                resolution[1],
 | 
			
		||||
                                                resolution[2],
 | 
			
		||||
                                                (channels == 3) ? GPU_RGB16F : GPU_R16F,
 | 
			
		||||
                                                voxels,
 | 
			
		||||
                                                NULL);
 | 
			
		||||
 | 
			
		||||
    GPU_texture_bind(cache_grid->texture, 0);
 | 
			
		||||
    GPU_texture_swizzle_channel_auto(cache_grid->texture, channels);
 | 
			
		||||
    GPU_texture_unbind(cache_grid->texture);
 | 
			
		||||
 | 
			
		||||
    MEM_freeN(voxels);
 | 
			
		||||
 | 
			
		||||
    /* Compute transform matrices. */
 | 
			
		||||
    BKE_volume_grid_dense_transform_matrix(
 | 
			
		||||
        grid, dense_min, dense_max, cache_grid->texture_to_object);
 | 
			
		||||
    invert_m4_m4(cache_grid->object_to_texture, cache_grid->texture_to_object);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* Free grid from memory if it wasn't previously loaded. */
 | 
			
		||||
  if (!was_loaded) {
 | 
			
		||||
    BKE_volume_grid_unload(volume, grid);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return cache_grid;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DRWVolumeGrid *DRW_volume_batch_cache_get_grid(Volume *volume, VolumeGrid *volume_grid)
 | 
			
		||||
{
 | 
			
		||||
  VolumeBatchCache *cache = volume_batch_cache_get(volume);
 | 
			
		||||
  DRWVolumeGrid *grid = volume_grid_cache_get(volume, volume_grid, cache);
 | 
			
		||||
  return (grid->texture != NULL) ? grid : NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int DRW_volume_material_count_get(Volume *volume)
 | 
			
		||||
{
 | 
			
		||||
  return max_ii(1, volume->totcol);
 | 
			
		||||
}
 | 
			
		||||
@@ -35,6 +35,7 @@
 | 
			
		||||
#include "DNA_armature_types.h"
 | 
			
		||||
#include "DNA_cachefile_types.h"
 | 
			
		||||
#include "DNA_camera_types.h"
 | 
			
		||||
#include "DNA_hair_types.h"
 | 
			
		||||
#include "DNA_object_types.h"
 | 
			
		||||
#include "DNA_particle_types.h"
 | 
			
		||||
#include "DNA_screen_types.h"
 | 
			
		||||
@@ -48,6 +49,8 @@
 | 
			
		||||
#include "DNA_material_types.h"
 | 
			
		||||
#include "DNA_meta_types.h"
 | 
			
		||||
#include "DNA_node_types.h"
 | 
			
		||||
#include "DNA_pointcloud_types.h"
 | 
			
		||||
#include "DNA_volume_types.h"
 | 
			
		||||
#include "DNA_world_types.h"
 | 
			
		||||
#include "DNA_gpencil_types.h"
 | 
			
		||||
#include "DNA_speaker_types.h"
 | 
			
		||||
@@ -699,6 +702,12 @@ static int acf_object_icon(bAnimListElem *ale)
 | 
			
		||||
      return ICON_OUTLINER_OB_FONT;
 | 
			
		||||
    case OB_SURF:
 | 
			
		||||
      return ICON_OUTLINER_OB_SURFACE;
 | 
			
		||||
    case OB_HAIR:
 | 
			
		||||
      return ICON_OUTLINER_OB_HAIR;
 | 
			
		||||
    case OB_POINTCLOUD:
 | 
			
		||||
      return ICON_OUTLINER_OB_POINTCLOUD;
 | 
			
		||||
    case OB_VOLUME:
 | 
			
		||||
      return ICON_OUTLINER_OB_VOLUME;
 | 
			
		||||
    case OB_EMPTY:
 | 
			
		||||
      return ICON_OUTLINER_OB_EMPTY;
 | 
			
		||||
    case OB_GPENCIL:
 | 
			
		||||
@@ -2785,6 +2794,244 @@ static bAnimChannelType ACF_DSSPK = {
 | 
			
		||||
    acf_dsspk_setting_ptr,                /* pointer for setting */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Hair Expander  ------------------------------------------- */
 | 
			
		||||
 | 
			
		||||
// TODO: just get this from RNA?
 | 
			
		||||
static int acf_dshair_icon(bAnimListElem *UNUSED(ale))
 | 
			
		||||
{
 | 
			
		||||
  return ICON_HAIR_DATA;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* get the appropriate flag(s) for the setting when it is valid  */
 | 
			
		||||
static int acf_dshair_setting_flag(bAnimContext *UNUSED(ac),
 | 
			
		||||
                                   eAnimChannel_Settings setting,
 | 
			
		||||
                                   bool *neg)
 | 
			
		||||
{
 | 
			
		||||
  /* clear extra return data first */
 | 
			
		||||
  *neg = false;
 | 
			
		||||
 | 
			
		||||
  switch (setting) {
 | 
			
		||||
    case ACHANNEL_SETTING_EXPAND: /* expanded */
 | 
			
		||||
      return VO_DS_EXPAND;
 | 
			
		||||
 | 
			
		||||
    case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
 | 
			
		||||
      return ADT_NLA_EVAL_OFF;
 | 
			
		||||
 | 
			
		||||
    case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
 | 
			
		||||
      *neg = true;
 | 
			
		||||
      return ADT_CURVES_NOT_VISIBLE;
 | 
			
		||||
 | 
			
		||||
    case ACHANNEL_SETTING_SELECT: /* selected */
 | 
			
		||||
      return ADT_UI_SELECTED;
 | 
			
		||||
 | 
			
		||||
    default: /* unsupported */
 | 
			
		||||
      return 0;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* get pointer to the setting */
 | 
			
		||||
static void *acf_dshair_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
 | 
			
		||||
{
 | 
			
		||||
  Hair *hair = (Hair *)ale->data;
 | 
			
		||||
 | 
			
		||||
  /* clear extra return data first */
 | 
			
		||||
  *type = 0;
 | 
			
		||||
 | 
			
		||||
  switch (setting) {
 | 
			
		||||
    case ACHANNEL_SETTING_EXPAND: /* expanded */
 | 
			
		||||
      return GET_ACF_FLAG_PTR(hair->flag, type);
 | 
			
		||||
 | 
			
		||||
    case ACHANNEL_SETTING_SELECT:  /* selected */
 | 
			
		||||
    case ACHANNEL_SETTING_MUTE:    /* muted (for NLA only) */
 | 
			
		||||
    case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
 | 
			
		||||
      if (hair->adt)
 | 
			
		||||
        return GET_ACF_FLAG_PTR(hair->adt->flag, type);
 | 
			
		||||
      return NULL;
 | 
			
		||||
 | 
			
		||||
    default: /* unsupported */
 | 
			
		||||
      return NULL;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* hair expander type define */
 | 
			
		||||
static bAnimChannelType ACF_DSHAIR = {
 | 
			
		||||
    "Hair Expander",        /* type name */
 | 
			
		||||
    ACHANNEL_ROLE_EXPANDER, /* role */
 | 
			
		||||
 | 
			
		||||
    acf_generic_dataexpand_color,    /* backdrop color */
 | 
			
		||||
    acf_generic_dataexpand_backdrop, /* backdrop */
 | 
			
		||||
    acf_generic_indention_1,         /* indent level */
 | 
			
		||||
    acf_generic_basic_offset,        /* offset */
 | 
			
		||||
 | 
			
		||||
    acf_generic_idblock_name,      /* name */
 | 
			
		||||
    acf_generic_idblock_name_prop, /* name prop */
 | 
			
		||||
    acf_dshair_icon,               /* icon */
 | 
			
		||||
 | 
			
		||||
    acf_generic_dataexpand_setting_valid, /* has setting */
 | 
			
		||||
    acf_dshair_setting_flag,              /* flag for setting */
 | 
			
		||||
    acf_dshair_setting_ptr                /* pointer for setting */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* PointCloud Expander  ------------------------------------------- */
 | 
			
		||||
 | 
			
		||||
// TODO: just get this from RNA?
 | 
			
		||||
static int acf_dspointcloud_icon(bAnimListElem *UNUSED(ale))
 | 
			
		||||
{
 | 
			
		||||
  return ICON_POINTCLOUD_DATA;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* get the appropriate flag(s) for the setting when it is valid  */
 | 
			
		||||
static int acf_dspointcloud_setting_flag(bAnimContext *UNUSED(ac),
 | 
			
		||||
                                         eAnimChannel_Settings setting,
 | 
			
		||||
                                         bool *neg)
 | 
			
		||||
{
 | 
			
		||||
  /* clear extra return data first */
 | 
			
		||||
  *neg = false;
 | 
			
		||||
 | 
			
		||||
  switch (setting) {
 | 
			
		||||
    case ACHANNEL_SETTING_EXPAND: /* expanded */
 | 
			
		||||
      return VO_DS_EXPAND;
 | 
			
		||||
 | 
			
		||||
    case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
 | 
			
		||||
      return ADT_NLA_EVAL_OFF;
 | 
			
		||||
 | 
			
		||||
    case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
 | 
			
		||||
      *neg = true;
 | 
			
		||||
      return ADT_CURVES_NOT_VISIBLE;
 | 
			
		||||
 | 
			
		||||
    case ACHANNEL_SETTING_SELECT: /* selected */
 | 
			
		||||
      return ADT_UI_SELECTED;
 | 
			
		||||
 | 
			
		||||
    default: /* unsupported */
 | 
			
		||||
      return 0;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* get pointer to the setting */
 | 
			
		||||
static void *acf_dspointcloud_setting_ptr(bAnimListElem *ale,
 | 
			
		||||
                                          eAnimChannel_Settings setting,
 | 
			
		||||
                                          short *type)
 | 
			
		||||
{
 | 
			
		||||
  PointCloud *pointcloud = (PointCloud *)ale->data;
 | 
			
		||||
 | 
			
		||||
  /* clear extra return data first */
 | 
			
		||||
  *type = 0;
 | 
			
		||||
 | 
			
		||||
  switch (setting) {
 | 
			
		||||
    case ACHANNEL_SETTING_EXPAND: /* expanded */
 | 
			
		||||
      return GET_ACF_FLAG_PTR(pointcloud->flag, type);
 | 
			
		||||
 | 
			
		||||
    case ACHANNEL_SETTING_SELECT:  /* selected */
 | 
			
		||||
    case ACHANNEL_SETTING_MUTE:    /* muted (for NLA only) */
 | 
			
		||||
    case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
 | 
			
		||||
      if (pointcloud->adt)
 | 
			
		||||
        return GET_ACF_FLAG_PTR(pointcloud->adt->flag, type);
 | 
			
		||||
      return NULL;
 | 
			
		||||
 | 
			
		||||
    default: /* unsupported */
 | 
			
		||||
      return NULL;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* pointcloud expander type define */
 | 
			
		||||
static bAnimChannelType ACF_DSPOINTCLOUD = {
 | 
			
		||||
    "PointCloud Expander",  /* type name */
 | 
			
		||||
    ACHANNEL_ROLE_EXPANDER, /* role */
 | 
			
		||||
 | 
			
		||||
    acf_generic_dataexpand_color,    /* backdrop color */
 | 
			
		||||
    acf_generic_dataexpand_backdrop, /* backdrop */
 | 
			
		||||
    acf_generic_indention_1,         /* indent level */
 | 
			
		||||
    acf_generic_basic_offset,        /* offset */
 | 
			
		||||
 | 
			
		||||
    acf_generic_idblock_name,      /* name */
 | 
			
		||||
    acf_generic_idblock_name_prop, /* name prop */
 | 
			
		||||
    acf_dspointcloud_icon,         /* icon */
 | 
			
		||||
 | 
			
		||||
    acf_generic_dataexpand_setting_valid, /* has setting */
 | 
			
		||||
    acf_dspointcloud_setting_flag,        /* flag for setting */
 | 
			
		||||
    acf_dspointcloud_setting_ptr          /* pointer for setting */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Volume Expander  ------------------------------------------- */
 | 
			
		||||
 | 
			
		||||
// TODO: just get this from RNA?
 | 
			
		||||
static int acf_dsvolume_icon(bAnimListElem *UNUSED(ale))
 | 
			
		||||
{
 | 
			
		||||
  return ICON_VOLUME_DATA;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* get the appropriate flag(s) for the setting when it is valid  */
 | 
			
		||||
static int acf_dsvolume_setting_flag(bAnimContext *UNUSED(ac),
 | 
			
		||||
                                     eAnimChannel_Settings setting,
 | 
			
		||||
                                     bool *neg)
 | 
			
		||||
{
 | 
			
		||||
  /* clear extra return data first */
 | 
			
		||||
  *neg = false;
 | 
			
		||||
 | 
			
		||||
  switch (setting) {
 | 
			
		||||
    case ACHANNEL_SETTING_EXPAND: /* expanded */
 | 
			
		||||
      return VO_DS_EXPAND;
 | 
			
		||||
 | 
			
		||||
    case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
 | 
			
		||||
      return ADT_NLA_EVAL_OFF;
 | 
			
		||||
 | 
			
		||||
    case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
 | 
			
		||||
      *neg = true;
 | 
			
		||||
      return ADT_CURVES_NOT_VISIBLE;
 | 
			
		||||
 | 
			
		||||
    case ACHANNEL_SETTING_SELECT: /* selected */
 | 
			
		||||
      return ADT_UI_SELECTED;
 | 
			
		||||
 | 
			
		||||
    default: /* unsupported */
 | 
			
		||||
      return 0;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* get pointer to the setting */
 | 
			
		||||
static void *acf_dsvolume_setting_ptr(bAnimListElem *ale,
 | 
			
		||||
                                      eAnimChannel_Settings setting,
 | 
			
		||||
                                      short *type)
 | 
			
		||||
{
 | 
			
		||||
  Volume *volume = (Volume *)ale->data;
 | 
			
		||||
 | 
			
		||||
  /* clear extra return data first */
 | 
			
		||||
  *type = 0;
 | 
			
		||||
 | 
			
		||||
  switch (setting) {
 | 
			
		||||
    case ACHANNEL_SETTING_EXPAND: /* expanded */
 | 
			
		||||
      return GET_ACF_FLAG_PTR(volume->flag, type);
 | 
			
		||||
 | 
			
		||||
    case ACHANNEL_SETTING_SELECT:  /* selected */
 | 
			
		||||
    case ACHANNEL_SETTING_MUTE:    /* muted (for NLA only) */
 | 
			
		||||
    case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
 | 
			
		||||
      if (volume->adt)
 | 
			
		||||
        return GET_ACF_FLAG_PTR(volume->adt->flag, type);
 | 
			
		||||
      return NULL;
 | 
			
		||||
 | 
			
		||||
    default: /* unsupported */
 | 
			
		||||
      return NULL;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* volume expander type define */
 | 
			
		||||
static bAnimChannelType ACF_DSVOLUME = {
 | 
			
		||||
    "Volume Expander",      /* type name */
 | 
			
		||||
    ACHANNEL_ROLE_EXPANDER, /* role */
 | 
			
		||||
 | 
			
		||||
    acf_generic_dataexpand_color,    /* backdrop color */
 | 
			
		||||
    acf_generic_dataexpand_backdrop, /* backdrop */
 | 
			
		||||
    acf_generic_indention_1,         /* indent level */
 | 
			
		||||
    acf_generic_basic_offset,        /* offset */
 | 
			
		||||
 | 
			
		||||
    acf_generic_idblock_name,      /* name */
 | 
			
		||||
    acf_generic_idblock_name_prop, /* name prop */
 | 
			
		||||
    acf_dsvolume_icon,             /* icon */
 | 
			
		||||
 | 
			
		||||
    acf_generic_dataexpand_setting_valid, /* has setting */
 | 
			
		||||
    acf_dsvolume_setting_flag,            /* flag for setting */
 | 
			
		||||
    acf_dsvolume_setting_ptr              /* pointer for setting */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* GPencil Expander  ------------------------------------------- */
 | 
			
		||||
 | 
			
		||||
// TODO: just get this from RNA?
 | 
			
		||||
@@ -3798,6 +4045,9 @@ static void ANIM_init_channel_typeinfo_data(void)
 | 
			
		||||
    animchannelTypeInfo[type++] = &ACF_DSSPK;        /* Speaker Channel */
 | 
			
		||||
    animchannelTypeInfo[type++] = &ACF_DSGPENCIL;    /* GreasePencil Channel */
 | 
			
		||||
    animchannelTypeInfo[type++] = &ACF_DSMCLIP;      /* MovieClip Channel */
 | 
			
		||||
    animchannelTypeInfo[type++] = &ACF_DSHAIR;       /* Hair Channel */
 | 
			
		||||
    animchannelTypeInfo[type++] = &ACF_DSPOINTCLOUD; /* PointCloud Channel */
 | 
			
		||||
    animchannelTypeInfo[type++] = &ACF_DSVOLUME;     /* Volume Channel */
 | 
			
		||||
 | 
			
		||||
    animchannelTypeInfo[type++] = &ACF_SHAPEKEY; /* ShapeKey */
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -135,7 +135,10 @@ void ANIM_set_active_channel(bAnimContext *ac,
 | 
			
		||||
      case ANIMTYPE_DSLINESTYLE:
 | 
			
		||||
      case ANIMTYPE_DSSPK:
 | 
			
		||||
      case ANIMTYPE_DSGPENCIL:
 | 
			
		||||
      case ANIMTYPE_DSMCLIP: {
 | 
			
		||||
      case ANIMTYPE_DSMCLIP:
 | 
			
		||||
      case ANIMTYPE_DSHAIR:
 | 
			
		||||
      case ANIMTYPE_DSPOINTCLOUD:
 | 
			
		||||
      case ANIMTYPE_DSVOLUME: {
 | 
			
		||||
        /* need to verify that this data is valid for now */
 | 
			
		||||
        if (ale->adt) {
 | 
			
		||||
          ACHANNEL_SET_FLAG(ale->adt, ACHANNEL_SETFLAG_CLEAR, ADT_UI_ACTIVE);
 | 
			
		||||
@@ -188,7 +191,10 @@ void ANIM_set_active_channel(bAnimContext *ac,
 | 
			
		||||
      case ANIMTYPE_DSNTREE:
 | 
			
		||||
      case ANIMTYPE_DSTEX:
 | 
			
		||||
      case ANIMTYPE_DSGPENCIL:
 | 
			
		||||
      case ANIMTYPE_DSMCLIP: {
 | 
			
		||||
      case ANIMTYPE_DSMCLIP:
 | 
			
		||||
      case ANIMTYPE_DSHAIR:
 | 
			
		||||
      case ANIMTYPE_DSPOINTCLOUD:
 | 
			
		||||
      case ANIMTYPE_DSVOLUME: {
 | 
			
		||||
        /* need to verify that this data is valid for now */
 | 
			
		||||
        if (ale && ale->adt) {
 | 
			
		||||
          ale->adt->flag |= ADT_UI_ACTIVE;
 | 
			
		||||
@@ -323,7 +329,10 @@ void ANIM_deselect_anim_channels(
 | 
			
		||||
        case ANIMTYPE_DSLINESTYLE:
 | 
			
		||||
        case ANIMTYPE_DSSPK:
 | 
			
		||||
        case ANIMTYPE_DSGPENCIL:
 | 
			
		||||
        case ANIMTYPE_DSMCLIP: {
 | 
			
		||||
        case ANIMTYPE_DSMCLIP:
 | 
			
		||||
        case ANIMTYPE_DSHAIR:
 | 
			
		||||
        case ANIMTYPE_DSPOINTCLOUD:
 | 
			
		||||
        case ANIMTYPE_DSVOLUME: {
 | 
			
		||||
          if ((ale->adt) && (ale->adt->flag & ADT_UI_SELECTED)) {
 | 
			
		||||
            sel = ACHANNEL_SETFLAG_CLEAR;
 | 
			
		||||
          }
 | 
			
		||||
@@ -416,7 +425,10 @@ void ANIM_deselect_anim_channels(
 | 
			
		||||
      case ANIMTYPE_DSLINESTYLE:
 | 
			
		||||
      case ANIMTYPE_DSSPK:
 | 
			
		||||
      case ANIMTYPE_DSGPENCIL:
 | 
			
		||||
      case ANIMTYPE_DSMCLIP: {
 | 
			
		||||
      case ANIMTYPE_DSMCLIP:
 | 
			
		||||
      case ANIMTYPE_DSHAIR:
 | 
			
		||||
      case ANIMTYPE_DSPOINTCLOUD:
 | 
			
		||||
      case ANIMTYPE_DSVOLUME: {
 | 
			
		||||
        /* need to verify that this data is valid for now */
 | 
			
		||||
        if (ale->adt) {
 | 
			
		||||
          ACHANNEL_SET_FLAG(ale->adt, sel, ADT_UI_SELECTED);
 | 
			
		||||
@@ -2949,7 +2961,10 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index,
 | 
			
		||||
    case ANIMTYPE_DSLINESTYLE:
 | 
			
		||||
    case ANIMTYPE_DSSPK:
 | 
			
		||||
    case ANIMTYPE_DSGPENCIL:
 | 
			
		||||
    case ANIMTYPE_DSMCLIP: {
 | 
			
		||||
    case ANIMTYPE_DSMCLIP:
 | 
			
		||||
    case ANIMTYPE_DSHAIR:
 | 
			
		||||
    case ANIMTYPE_DSPOINTCLOUD:
 | 
			
		||||
    case ANIMTYPE_DSVOLUME: {
 | 
			
		||||
      /* sanity checking... */
 | 
			
		||||
      if (ale->adt) {
 | 
			
		||||
        /* select/deselect */
 | 
			
		||||
 
 | 
			
		||||
@@ -46,6 +46,7 @@
 | 
			
		||||
#include "DNA_armature_types.h"
 | 
			
		||||
#include "DNA_camera_types.h"
 | 
			
		||||
#include "DNA_cachefile_types.h"
 | 
			
		||||
#include "DNA_hair_types.h"
 | 
			
		||||
#include "DNA_light_types.h"
 | 
			
		||||
#include "DNA_lattice_types.h"
 | 
			
		||||
#include "DNA_linestyle_types.h"
 | 
			
		||||
@@ -58,11 +59,13 @@
 | 
			
		||||
#include "DNA_node_types.h"
 | 
			
		||||
#include "DNA_object_force_types.h"
 | 
			
		||||
#include "DNA_particle_types.h"
 | 
			
		||||
#include "DNA_pointcloud_types.h"
 | 
			
		||||
#include "DNA_space_types.h"
 | 
			
		||||
#include "DNA_sequence_types.h"
 | 
			
		||||
#include "DNA_scene_types.h"
 | 
			
		||||
#include "DNA_screen_types.h"
 | 
			
		||||
#include "DNA_speaker_types.h"
 | 
			
		||||
#include "DNA_volume_types.h"
 | 
			
		||||
#include "DNA_world_types.h"
 | 
			
		||||
#include "DNA_gpencil_types.h"
 | 
			
		||||
#include "DNA_brush_types.h"
 | 
			
		||||
@@ -787,6 +790,42 @@ static bAnimListElem *make_new_animlistelem(void *data,
 | 
			
		||||
        ale->adt = BKE_animdata_from_id(data);
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      case ANIMTYPE_DSHAIR: {
 | 
			
		||||
        Hair *hair = (Hair *)data;
 | 
			
		||||
        AnimData *adt = hair->adt;
 | 
			
		||||
 | 
			
		||||
        ale->flag = FILTER_HAIR_OBJD(hair);
 | 
			
		||||
 | 
			
		||||
        ale->key_data = (adt) ? adt->action : NULL;
 | 
			
		||||
        ale->datatype = ALE_ACT;
 | 
			
		||||
 | 
			
		||||
        ale->adt = BKE_animdata_from_id(data);
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      case ANIMTYPE_DSPOINTCLOUD: {
 | 
			
		||||
        PointCloud *pointcloud = (PointCloud *)data;
 | 
			
		||||
        AnimData *adt = pointcloud->adt;
 | 
			
		||||
 | 
			
		||||
        ale->flag = FILTER_POINTS_OBJD(pointcloud);
 | 
			
		||||
 | 
			
		||||
        ale->key_data = (adt) ? adt->action : NULL;
 | 
			
		||||
        ale->datatype = ALE_ACT;
 | 
			
		||||
 | 
			
		||||
        ale->adt = BKE_animdata_from_id(data);
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      case ANIMTYPE_DSVOLUME: {
 | 
			
		||||
        Volume *volume = (Volume *)data;
 | 
			
		||||
        AnimData *adt = volume->adt;
 | 
			
		||||
 | 
			
		||||
        ale->flag = FILTER_VOLUME_OBJD(volume);
 | 
			
		||||
 | 
			
		||||
        ale->key_data = (adt) ? adt->action : NULL;
 | 
			
		||||
        ale->datatype = ALE_ACT;
 | 
			
		||||
 | 
			
		||||
        ale->adt = BKE_animdata_from_id(data);
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      case ANIMTYPE_DSSKEY: {
 | 
			
		||||
        Key *key = (Key *)data;
 | 
			
		||||
        AnimData *adt = key->adt;
 | 
			
		||||
@@ -2544,6 +2583,39 @@ static size_t animdata_filter_ds_obdata(
 | 
			
		||||
      expanded = FILTER_SPK_OBJD(spk);
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case OB_HAIR: /* ---------- Hair ----------- */
 | 
			
		||||
    {
 | 
			
		||||
      Hair *hair = (Hair *)ob->data;
 | 
			
		||||
 | 
			
		||||
      if (ads->filterflag2 & ADS_FILTER_NOHAIR)
 | 
			
		||||
        return 0;
 | 
			
		||||
 | 
			
		||||
      type = ANIMTYPE_DSHAIR;
 | 
			
		||||
      expanded = FILTER_HAIR_OBJD(hair);
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case OB_POINTCLOUD: /* ---------- PointCloud ----------- */
 | 
			
		||||
    {
 | 
			
		||||
      PointCloud *pointcloud = (PointCloud *)ob->data;
 | 
			
		||||
 | 
			
		||||
      if (ads->filterflag2 & ADS_FILTER_NOPOINTCLOUD)
 | 
			
		||||
        return 0;
 | 
			
		||||
 | 
			
		||||
      type = ANIMTYPE_DSPOINTCLOUD;
 | 
			
		||||
      expanded = FILTER_POINTS_OBJD(pointcloud);
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case OB_VOLUME: /* ---------- Volume ----------- */
 | 
			
		||||
    {
 | 
			
		||||
      Volume *volume = (Volume *)ob->data;
 | 
			
		||||
 | 
			
		||||
      if (ads->filterflag2 & ADS_FILTER_NOVOLUME)
 | 
			
		||||
        return 0;
 | 
			
		||||
 | 
			
		||||
      type = ANIMTYPE_DSVOLUME;
 | 
			
		||||
      expanded = FILTER_VOLUME_OBJD(volume);
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* add object data animation channels */
 | 
			
		||||
 
 | 
			
		||||
@@ -226,6 +226,9 @@ typedef enum eAnim_ChannelType {
 | 
			
		||||
  ANIMTYPE_DSSPK,
 | 
			
		||||
  ANIMTYPE_DSGPENCIL,
 | 
			
		||||
  ANIMTYPE_DSMCLIP,
 | 
			
		||||
  ANIMTYPE_DSHAIR,
 | 
			
		||||
  ANIMTYPE_DSPOINTCLOUD,
 | 
			
		||||
  ANIMTYPE_DSVOLUME,
 | 
			
		||||
 | 
			
		||||
  ANIMTYPE_SHAPEKEY,
 | 
			
		||||
 | 
			
		||||
@@ -350,6 +353,9 @@ typedef enum eAnimFilter_Flags {
 | 
			
		||||
#define FILTER_MESH_OBJD(me) (CHECK_TYPE_INLINE(me, Mesh *), ((me->flag & ME_DS_EXPAND)))
 | 
			
		||||
#define FILTER_LATTICE_OBJD(lt) (CHECK_TYPE_INLINE(lt, Lattice *), ((lt->flag & LT_DS_EXPAND)))
 | 
			
		||||
#define FILTER_SPK_OBJD(spk) (CHECK_TYPE_INLINE(spk, Speaker *), ((spk->flag & SPK_DS_EXPAND)))
 | 
			
		||||
#define FILTER_HAIR_OBJD(ha) (CHECK_TYPE_INLINE(ha, Hair *), ((ha->flag & HA_DS_EXPAND)))
 | 
			
		||||
#define FILTER_POINTS_OBJD(pt) (CHECK_TYPE_INLINE(pt, PointCloud *), ((pt->flag & PT_DS_EXPAND)))
 | 
			
		||||
#define FILTER_VOLUME_OBJD(vo) (CHECK_TYPE_INLINE(vo, Volume *), ((vo->flag & VO_DS_EXPAND)))
 | 
			
		||||
/* Variable use expanders */
 | 
			
		||||
#define FILTER_NTREE_DATA(ntree) \
 | 
			
		||||
  (CHECK_TYPE_INLINE(ntree, bNodeTree *), ((ntree->flag & NTREE_DS_EXPAND)))
 | 
			
		||||
 
 | 
			
		||||
@@ -745,21 +745,22 @@ DEF_ICON_BLANK(252b)
 | 
			
		||||
DEF_ICON_BLANK(252c)
 | 
			
		||||
DEF_ICON(LAYER_USED)
 | 
			
		||||
DEF_ICON(LAYER_ACTIVE)
 | 
			
		||||
/* available */
 | 
			
		||||
DEF_ICON_BLANK(254)
 | 
			
		||||
DEF_ICON_BLANK(255)
 | 
			
		||||
DEF_ICON_BLANK(256)
 | 
			
		||||
DEF_ICON_BLANK(257)
 | 
			
		||||
DEF_ICON_BLANK(257b)
 | 
			
		||||
DEF_ICON_BLANK(258)
 | 
			
		||||
DEF_ICON_BLANK(259)
 | 
			
		||||
DEF_ICON_BLANK(260)
 | 
			
		||||
DEF_ICON_BLANK(261)
 | 
			
		||||
DEF_ICON_BLANK(262)
 | 
			
		||||
DEF_ICON_BLANK(263)
 | 
			
		||||
DEF_ICON_BLANK(264)
 | 
			
		||||
DEF_ICON_BLANK(265)
 | 
			
		||||
DEF_ICON_BLANK(266)
 | 
			
		||||
 | 
			
		||||
/* ADDITIONAL OBJECT TYPES */
 | 
			
		||||
DEF_ICON_OBJECT(OUTLINER_OB_HAIR)
 | 
			
		||||
DEF_ICON_OBJECT_DATA(OUTLINER_DATA_HAIR)
 | 
			
		||||
DEF_ICON_OBJECT_DATA(HAIR_DATA)
 | 
			
		||||
DEF_ICON_OBJECT(OUTLINER_OB_POINTCLOUD)
 | 
			
		||||
DEF_ICON_OBJECT_DATA(OUTLINER_DATA_POINTCLOUD)
 | 
			
		||||
DEF_ICON_OBJECT_DATA(POINTCLOUD_DATA)
 | 
			
		||||
DEF_ICON_OBJECT(OUTLINER_OB_VOLUME)
 | 
			
		||||
DEF_ICON_OBJECT_DATA(OUTLINER_DATA_VOLUME)
 | 
			
		||||
DEF_ICON_OBJECT_DATA(VOLUME_DATA)
 | 
			
		||||
DEF_ICON_BLANK(267)
 | 
			
		||||
DEF_ICON_BLANK(268)
 | 
			
		||||
DEF_ICON_BLANK(269)
 | 
			
		||||
 
 | 
			
		||||
@@ -2340,6 +2340,12 @@ int UI_idcode_icon_get(const int idcode)
 | 
			
		||||
      return ICON_TEXT;
 | 
			
		||||
    case ID_VF:
 | 
			
		||||
      return ICON_FONT_DATA;
 | 
			
		||||
    case ID_HA:
 | 
			
		||||
      return ICON_HAIR_DATA;
 | 
			
		||||
    case ID_PT:
 | 
			
		||||
      return ICON_POINTCLOUD_DATA;
 | 
			
		||||
    case ID_VO:
 | 
			
		||||
      return ICON_VOLUME_DATA;
 | 
			
		||||
    case ID_WO:
 | 
			
		||||
      return ICON_WORLD_DATA;
 | 
			
		||||
    case ID_WS:
 | 
			
		||||
 
 | 
			
		||||
@@ -668,6 +668,12 @@ static const char *template_id_browse_tip(const StructRNA *type)
 | 
			
		||||
        return N_("Browse Workspace to be linked");
 | 
			
		||||
      case ID_LP:
 | 
			
		||||
        return N_("Browse LightProbe to be linked");
 | 
			
		||||
      case ID_HA:
 | 
			
		||||
        return N_("Browse Hair Data to be linked");
 | 
			
		||||
      case ID_PT:
 | 
			
		||||
        return N_("Browse Point Cloud Data to be linked");
 | 
			
		||||
      case ID_VO:
 | 
			
		||||
        return N_("Browse Volume Data to be linked");
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return N_("Browse ID data to be linked");
 | 
			
		||||
@@ -730,7 +736,13 @@ static uiBut *template_id_def_new_but(uiBlock *block,
 | 
			
		||||
                            BLT_I18NCONTEXT_ID_GPENCIL,
 | 
			
		||||
                            BLT_I18NCONTEXT_ID_FREESTYLELINESTYLE,
 | 
			
		||||
                            BLT_I18NCONTEXT_ID_WORKSPACE,
 | 
			
		||||
                            BLT_I18NCONTEXT_ID_LIGHTPROBE, );
 | 
			
		||||
                            BLT_I18NCONTEXT_ID_LIGHTPROBE,
 | 
			
		||||
                            BLT_I18NCONTEXT_ID_HAIR,
 | 
			
		||||
                            BLT_I18NCONTEXT_ID_POINTCLOUD,
 | 
			
		||||
                            BLT_I18NCONTEXT_ID_VOLUME, );
 | 
			
		||||
  /* Note: BLT_I18N_MSGID_MULTI_CTXT takes a maximum number of parameters,
 | 
			
		||||
   * check the definition to see if a new call must be added when the limit
 | 
			
		||||
   * is exceeded. */
 | 
			
		||||
 | 
			
		||||
  if (newop) {
 | 
			
		||||
    but = uiDefIconTextButO(block,
 | 
			
		||||
 
 | 
			
		||||
@@ -65,6 +65,7 @@ set(SRC
 | 
			
		||||
  object_transform.c
 | 
			
		||||
  object_utils.c
 | 
			
		||||
  object_vgroup.c
 | 
			
		||||
  object_volume.c
 | 
			
		||||
  object_warp.c
 | 
			
		||||
 | 
			
		||||
  object_intern.h
 | 
			
		||||
@@ -88,4 +89,8 @@ if(WITH_INTERNATIONAL)
 | 
			
		||||
  add_definitions(-DWITH_INTERNATIONAL)
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
if(WITH_NEW_OBJECT_TYPES)
 | 
			
		||||
  add_definitions(-DWITH_NEW_OBJECT_TYPES)
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
blender_add_lib(bf_editor_object "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
 | 
			
		||||
 
 | 
			
		||||
@@ -65,6 +65,7 @@
 | 
			
		||||
#include "BKE_effect.h"
 | 
			
		||||
#include "BKE_font.h"
 | 
			
		||||
#include "BKE_gpencil.h"
 | 
			
		||||
#include "BKE_hair.h"
 | 
			
		||||
#include "BKE_key.h"
 | 
			
		||||
#include "BKE_light.h"
 | 
			
		||||
#include "BKE_lattice.h"
 | 
			
		||||
@@ -81,9 +82,11 @@
 | 
			
		||||
#include "BKE_nla.h"
 | 
			
		||||
#include "BKE_object.h"
 | 
			
		||||
#include "BKE_particle.h"
 | 
			
		||||
#include "BKE_pointcloud.h"
 | 
			
		||||
#include "BKE_report.h"
 | 
			
		||||
#include "BKE_scene.h"
 | 
			
		||||
#include "BKE_speaker.h"
 | 
			
		||||
#include "BKE_volume.h"
 | 
			
		||||
 | 
			
		||||
#include "DEG_depsgraph.h"
 | 
			
		||||
#include "DEG_depsgraph_build.h"
 | 
			
		||||
@@ -1459,9 +1462,82 @@ void OBJECT_OT_speaker_add(wmOperatorType *ot)
 | 
			
		||||
/** \} */
 | 
			
		||||
 | 
			
		||||
/* -------------------------------------------------------------------- */
 | 
			
		||||
/** \name Delete Object Operator
 | 
			
		||||
/** \name Add Hair Operator
 | 
			
		||||
 * \{ */
 | 
			
		||||
 | 
			
		||||
static int object_hair_add_exec(bContext *C, wmOperator *op)
 | 
			
		||||
{
 | 
			
		||||
  ushort local_view_bits;
 | 
			
		||||
  float loc[3], rot[3];
 | 
			
		||||
 | 
			
		||||
  if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, &local_view_bits, NULL)) {
 | 
			
		||||
    return OPERATOR_CANCELLED;
 | 
			
		||||
  }
 | 
			
		||||
  Object *object = ED_object_add_type(C, OB_HAIR, NULL, loc, rot, false, local_view_bits);
 | 
			
		||||
  object->dtx |= OB_DRAWBOUNDOX; /* TODO: remove once there is actual drawing. */
 | 
			
		||||
 | 
			
		||||
  return OPERATOR_FINISHED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OBJECT_OT_hair_add(wmOperatorType *ot)
 | 
			
		||||
{
 | 
			
		||||
  /* identifiers */
 | 
			
		||||
  ot->name = "Add Hair";
 | 
			
		||||
  ot->description = "Add a hair object to the scene";
 | 
			
		||||
  ot->idname = "OBJECT_OT_hair_add";
 | 
			
		||||
 | 
			
		||||
  /* api callbacks */
 | 
			
		||||
  ot->exec = object_hair_add_exec;
 | 
			
		||||
  ot->poll = ED_operator_objectmode;
 | 
			
		||||
 | 
			
		||||
  /* flags */
 | 
			
		||||
  ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 | 
			
		||||
 | 
			
		||||
  ED_object_add_generic_props(ot, false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** \} */
 | 
			
		||||
 | 
			
		||||
/* -------------------------------------------------------------------- */
 | 
			
		||||
/** \name Add Point Cloud Operator
 | 
			
		||||
 * \{ */
 | 
			
		||||
 | 
			
		||||
static int object_pointcloud_add_exec(bContext *C, wmOperator *op)
 | 
			
		||||
{
 | 
			
		||||
  ushort local_view_bits;
 | 
			
		||||
  float loc[3], rot[3];
 | 
			
		||||
 | 
			
		||||
  if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, &local_view_bits, NULL)) {
 | 
			
		||||
    return OPERATOR_CANCELLED;
 | 
			
		||||
  }
 | 
			
		||||
  Object *object = ED_object_add_type(C, OB_POINTCLOUD, NULL, loc, rot, false, local_view_bits);
 | 
			
		||||
  object->dtx |= OB_DRAWBOUNDOX; /* TODO: remove once there is actual drawing. */
 | 
			
		||||
 | 
			
		||||
  return OPERATOR_FINISHED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OBJECT_OT_pointcloud_add(wmOperatorType *ot)
 | 
			
		||||
{
 | 
			
		||||
  /* identifiers */
 | 
			
		||||
  ot->name = "Add Point Cloud";
 | 
			
		||||
  ot->description = "Add a point cloud object to the scene";
 | 
			
		||||
  ot->idname = "OBJECT_OT_pointcloud_add";
 | 
			
		||||
 | 
			
		||||
  /* api callbacks */
 | 
			
		||||
  ot->exec = object_pointcloud_add_exec;
 | 
			
		||||
  ot->poll = ED_operator_objectmode;
 | 
			
		||||
 | 
			
		||||
  /* flags */
 | 
			
		||||
  ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 | 
			
		||||
 | 
			
		||||
  ED_object_add_generic_props(ot, false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** \} */
 | 
			
		||||
 | 
			
		||||
/* -------------------------------------------------------------------- */
 | 
			
		||||
/** \name Delete Object Operator
 | 
			
		||||
 * \{ */
 | 
			
		||||
/* remove base from a specific scene */
 | 
			
		||||
/* note: now unlinks constraints as well */
 | 
			
		||||
void ED_object_base_free_and_unlink(Main *bmain, Scene *scene, Object *ob)
 | 
			
		||||
 
 | 
			
		||||
@@ -111,6 +111,8 @@ void OBJECT_OT_light_add(struct wmOperatorType *ot);
 | 
			
		||||
void OBJECT_OT_effector_add(struct wmOperatorType *ot);
 | 
			
		||||
void OBJECT_OT_camera_add(struct wmOperatorType *ot);
 | 
			
		||||
void OBJECT_OT_speaker_add(struct wmOperatorType *ot);
 | 
			
		||||
void OBJECT_OT_hair_add(struct wmOperatorType *ot);
 | 
			
		||||
void OBJECT_OT_pointcloud_add(struct wmOperatorType *ot);
 | 
			
		||||
void OBJECT_OT_collection_instance_add(struct wmOperatorType *ot);
 | 
			
		||||
 | 
			
		||||
void OBJECT_OT_duplicates_make_real(struct wmOperatorType *ot);
 | 
			
		||||
@@ -120,6 +122,10 @@ void OBJECT_OT_join(struct wmOperatorType *ot);
 | 
			
		||||
void OBJECT_OT_join_shapes(struct wmOperatorType *ot);
 | 
			
		||||
void OBJECT_OT_convert(struct wmOperatorType *ot);
 | 
			
		||||
 | 
			
		||||
/* object_volume.c */
 | 
			
		||||
void OBJECT_OT_volume_add(struct wmOperatorType *ot);
 | 
			
		||||
void OBJECT_OT_volume_import(struct wmOperatorType *ot);
 | 
			
		||||
 | 
			
		||||
/* object_hook.c */
 | 
			
		||||
void OBJECT_OT_hook_add_selob(struct wmOperatorType *ot);
 | 
			
		||||
void OBJECT_OT_hook_add_newob(struct wmOperatorType *ot);
 | 
			
		||||
 
 | 
			
		||||
@@ -53,6 +53,7 @@
 | 
			
		||||
#include "BKE_effect.h"
 | 
			
		||||
#include "BKE_global.h"
 | 
			
		||||
#include "BKE_gpencil_modifier.h"
 | 
			
		||||
#include "BKE_hair.h"
 | 
			
		||||
#include "BKE_key.h"
 | 
			
		||||
#include "BKE_lattice.h"
 | 
			
		||||
#include "BKE_lib_id.h"
 | 
			
		||||
@@ -67,9 +68,11 @@
 | 
			
		||||
#include "BKE_ocean.h"
 | 
			
		||||
#include "BKE_paint.h"
 | 
			
		||||
#include "BKE_particle.h"
 | 
			
		||||
#include "BKE_pointcloud.h"
 | 
			
		||||
#include "BKE_report.h"
 | 
			
		||||
#include "BKE_scene.h"
 | 
			
		||||
#include "BKE_softbody.h"
 | 
			
		||||
#include "BKE_volume.h"
 | 
			
		||||
 | 
			
		||||
#include "DEG_depsgraph.h"
 | 
			
		||||
#include "DEG_depsgraph_build.h"
 | 
			
		||||
@@ -114,6 +117,15 @@ static void object_force_modifier_update_for_bind(Depsgraph *depsgraph, Object *
 | 
			
		||||
  else if (ob->type == OB_GPENCIL) {
 | 
			
		||||
    BKE_gpencil_modifiers_calc(depsgraph, scene_eval, ob_eval);
 | 
			
		||||
  }
 | 
			
		||||
  else if (ob->type == OB_HAIR) {
 | 
			
		||||
    BKE_hair_data_update(depsgraph, scene_eval, ob);
 | 
			
		||||
  }
 | 
			
		||||
  else if (ob->type == OB_POINTCLOUD) {
 | 
			
		||||
    BKE_pointcloud_data_update(depsgraph, scene_eval, ob);
 | 
			
		||||
  }
 | 
			
		||||
  else if (ob->type == OB_VOLUME) {
 | 
			
		||||
    BKE_volume_data_update(depsgraph, scene_eval, ob);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void object_force_modifier_bind_simple_options(Depsgraph *depsgraph,
 | 
			
		||||
@@ -654,6 +666,7 @@ static int modifier_apply_shape(Main *bmain,
 | 
			
		||||
    BKE_id_free(NULL, mesh_applied);
 | 
			
		||||
  }
 | 
			
		||||
  else {
 | 
			
		||||
    /* TODO: implement for hair, pointclouds and volumes. */
 | 
			
		||||
    BKE_report(reports, RPT_ERROR, "Cannot apply modifier for this object type");
 | 
			
		||||
    return 0;
 | 
			
		||||
  }
 | 
			
		||||
@@ -732,6 +745,7 @@ static int modifier_apply_obdata(
 | 
			
		||||
    DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
 | 
			
		||||
  }
 | 
			
		||||
  else {
 | 
			
		||||
    /* TODO: implement for hair, pointclouds and volumes. */
 | 
			
		||||
    BKE_report(reports, RPT_ERROR, "Cannot apply modifier for this object type");
 | 
			
		||||
    return 0;
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -109,6 +109,12 @@ void ED_operatortypes_object(void)
 | 
			
		||||
  WM_operatortype_append(OBJECT_OT_light_add);
 | 
			
		||||
  WM_operatortype_append(OBJECT_OT_camera_add);
 | 
			
		||||
  WM_operatortype_append(OBJECT_OT_speaker_add);
 | 
			
		||||
#ifdef WITH_NEW_OBJECT_TYPES
 | 
			
		||||
  WM_operatortype_append(OBJECT_OT_hair_add);
 | 
			
		||||
  WM_operatortype_append(OBJECT_OT_pointcloud_add);
 | 
			
		||||
#endif
 | 
			
		||||
  WM_operatortype_append(OBJECT_OT_volume_add);
 | 
			
		||||
  WM_operatortype_append(OBJECT_OT_volume_import);
 | 
			
		||||
  WM_operatortype_append(OBJECT_OT_add);
 | 
			
		||||
  WM_operatortype_append(OBJECT_OT_add_named);
 | 
			
		||||
  WM_operatortype_append(OBJECT_OT_effector_add);
 | 
			
		||||
 
 | 
			
		||||
@@ -66,6 +66,7 @@
 | 
			
		||||
#include "BKE_editmesh.h"
 | 
			
		||||
#include "BKE_gpencil.h"
 | 
			
		||||
#include "BKE_fcurve.h"
 | 
			
		||||
#include "BKE_hair.h"
 | 
			
		||||
#include "BKE_idprop.h"
 | 
			
		||||
#include "BKE_light.h"
 | 
			
		||||
#include "BKE_lattice.h"
 | 
			
		||||
@@ -82,10 +83,12 @@
 | 
			
		||||
#include "BKE_modifier.h"
 | 
			
		||||
#include "BKE_node.h"
 | 
			
		||||
#include "BKE_object.h"
 | 
			
		||||
#include "BKE_pointcloud.h"
 | 
			
		||||
#include "BKE_report.h"
 | 
			
		||||
#include "BKE_scene.h"
 | 
			
		||||
#include "BKE_speaker.h"
 | 
			
		||||
#include "BKE_texture.h"
 | 
			
		||||
#include "BKE_volume.h"
 | 
			
		||||
 | 
			
		||||
#include "DEG_depsgraph.h"
 | 
			
		||||
#include "DEG_depsgraph_build.h"
 | 
			
		||||
@@ -1900,6 +1903,15 @@ static void single_obdata_users(
 | 
			
		||||
          case OB_GPENCIL:
 | 
			
		||||
            ob->data = ID_NEW_SET(ob->data, BKE_gpencil_copy(bmain, ob->data));
 | 
			
		||||
            break;
 | 
			
		||||
          case OB_HAIR:
 | 
			
		||||
            ob->data = ID_NEW_SET(ob->data, BKE_hair_copy(bmain, ob->data));
 | 
			
		||||
            break;
 | 
			
		||||
          case OB_POINTCLOUD:
 | 
			
		||||
            ob->data = ID_NEW_SET(ob->data, BKE_pointcloud_copy(bmain, ob->data));
 | 
			
		||||
            break;
 | 
			
		||||
          case OB_VOLUME:
 | 
			
		||||
            ob->data = ID_NEW_SET(ob->data, BKE_volume_copy(bmain, ob->data));
 | 
			
		||||
            break;
 | 
			
		||||
          default:
 | 
			
		||||
            printf("ERROR %s: can't copy %s\n", __func__, id->name);
 | 
			
		||||
            BLI_assert(!"This should never happen.");
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										193
									
								
								source/blender/editors/object/object_volume.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										193
									
								
								source/blender/editors/object/object_volume.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,193 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This program is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU General Public License
 | 
			
		||||
 * as published by the Free Software Foundation; either version 2
 | 
			
		||||
 * of the License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 | 
			
		||||
 *
 | 
			
		||||
 * The Original Code is Copyright (C) 2008 Blender Foundation.
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/** \file
 | 
			
		||||
 * \ingroup edobj
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include "MEM_guardedalloc.h"
 | 
			
		||||
 | 
			
		||||
#include "BLI_fileops.h"
 | 
			
		||||
#include "BLI_listbase.h"
 | 
			
		||||
#include "BLI_math_base.h"
 | 
			
		||||
#include "BLI_path_util.h"
 | 
			
		||||
#include "BLI_string.h"
 | 
			
		||||
 | 
			
		||||
#include "DNA_object_types.h"
 | 
			
		||||
#include "DNA_volume_types.h"
 | 
			
		||||
 | 
			
		||||
#include "RNA_access.h"
 | 
			
		||||
#include "RNA_define.h"
 | 
			
		||||
 | 
			
		||||
#include "BKE_context.h"
 | 
			
		||||
#include "BKE_lib_id.h"
 | 
			
		||||
#include "BKE_main.h"
 | 
			
		||||
#include "BKE_report.h"
 | 
			
		||||
#include "BKE_volume.h"
 | 
			
		||||
 | 
			
		||||
#include "WM_types.h"
 | 
			
		||||
#include "WM_api.h"
 | 
			
		||||
 | 
			
		||||
#include "ED_image.h"
 | 
			
		||||
#include "ED_object.h"
 | 
			
		||||
#include "ED_screen.h"
 | 
			
		||||
 | 
			
		||||
#include "object_intern.h"
 | 
			
		||||
 | 
			
		||||
/* Volume Add */
 | 
			
		||||
 | 
			
		||||
static Object *object_volume_add(bContext *C, wmOperator *op, const char *name)
 | 
			
		||||
{
 | 
			
		||||
  ushort local_view_bits;
 | 
			
		||||
  float loc[3], rot[3];
 | 
			
		||||
 | 
			
		||||
  if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, &local_view_bits, NULL)) {
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
  return ED_object_add_type(C, OB_VOLUME, name, loc, rot, false, local_view_bits);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int object_volume_add_exec(bContext *C, wmOperator *op)
 | 
			
		||||
{
 | 
			
		||||
  return (object_volume_add(C, op, NULL) != NULL) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OBJECT_OT_volume_add(wmOperatorType *ot)
 | 
			
		||||
{
 | 
			
		||||
  /* identifiers */
 | 
			
		||||
  ot->name = "Add Volume";
 | 
			
		||||
  ot->description = "Add a volume object to the scene";
 | 
			
		||||
  ot->idname = "OBJECT_OT_volume_add";
 | 
			
		||||
 | 
			
		||||
  /* api callbacks */
 | 
			
		||||
  ot->exec = object_volume_add_exec;
 | 
			
		||||
  ot->poll = ED_operator_objectmode;
 | 
			
		||||
 | 
			
		||||
  /* flags */
 | 
			
		||||
  ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 | 
			
		||||
 | 
			
		||||
  ED_object_add_generic_props(ot, false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Volume Import */
 | 
			
		||||
 | 
			
		||||
static int volume_import_exec(bContext *C, wmOperator *op)
 | 
			
		||||
{
 | 
			
		||||
  Main *bmain = CTX_data_main(C);
 | 
			
		||||
  const bool is_relative_path = RNA_boolean_get(op->ptr, "relative_path");
 | 
			
		||||
  bool imported = false;
 | 
			
		||||
 | 
			
		||||
  ListBase ranges = ED_image_filesel_detect_sequences(bmain, op, false);
 | 
			
		||||
  for (ImageFrameRange *range = ranges.first; range; range = range->next) {
 | 
			
		||||
    char filename[FILE_MAX];
 | 
			
		||||
    BLI_split_file_part(range->filepath, filename, sizeof(filename));
 | 
			
		||||
    BLI_path_extension_replace(filename, sizeof(filename), "");
 | 
			
		||||
 | 
			
		||||
    Object *object = object_volume_add(C, op, filename);
 | 
			
		||||
    Volume *volume = (Volume *)object->data;
 | 
			
		||||
 | 
			
		||||
    STRNCPY(volume->filepath, range->filepath);
 | 
			
		||||
    if (is_relative_path) {
 | 
			
		||||
      BLI_path_rel(volume->filepath, BKE_main_blendfile_path(bmain));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    volume->is_sequence = (range->length > 1);
 | 
			
		||||
    volume->frame_duration = (volume->is_sequence) ? range->length : 0;
 | 
			
		||||
    volume->frame_start = 1;
 | 
			
		||||
    volume->frame_offset = (volume->is_sequence) ? range->offset - 1 : 0;
 | 
			
		||||
 | 
			
		||||
    if (!BKE_volume_load(volume, bmain)) {
 | 
			
		||||
      BKE_reportf(op->reports,
 | 
			
		||||
                  RPT_WARNING,
 | 
			
		||||
                  "Volume \"%s\" failed to load: %s",
 | 
			
		||||
                  filename,
 | 
			
		||||
                  BKE_volume_grids_error_msg(volume));
 | 
			
		||||
      BKE_id_delete(bmain, &object->id);
 | 
			
		||||
      BKE_id_delete(bmain, &volume->id);
 | 
			
		||||
      continue;
 | 
			
		||||
    }
 | 
			
		||||
    else if (BKE_volume_is_points_only(volume)) {
 | 
			
		||||
      BKE_reportf(op->reports,
 | 
			
		||||
                  RPT_WARNING,
 | 
			
		||||
                  "Volume \"%s\" contains points, only voxel grids are supported",
 | 
			
		||||
                  filename);
 | 
			
		||||
      BKE_id_delete(bmain, &object->id);
 | 
			
		||||
      BKE_id_delete(bmain, &volume->id);
 | 
			
		||||
      continue;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (BKE_volume_is_y_up(volume)) {
 | 
			
		||||
      object->rot[0] += M_PI_2;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    imported = true;
 | 
			
		||||
  }
 | 
			
		||||
  BLI_freelistN(&ranges);
 | 
			
		||||
 | 
			
		||||
  return (imported) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int volume_import_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
 | 
			
		||||
{
 | 
			
		||||
  if (RNA_struct_property_is_set(op->ptr, "filepath")) {
 | 
			
		||||
    return volume_import_exec(C, op);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  RNA_string_set(op->ptr, "filepath", U.textudir);
 | 
			
		||||
  WM_event_add_fileselect(C, op);
 | 
			
		||||
 | 
			
		||||
  return OPERATOR_RUNNING_MODAL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* called by other space types too */
 | 
			
		||||
void OBJECT_OT_volume_import(wmOperatorType *ot)
 | 
			
		||||
{
 | 
			
		||||
  /* identifiers */
 | 
			
		||||
  ot->name = "Import OpenVDB Volume";
 | 
			
		||||
  ot->description = "Import OpenVDB volume file";
 | 
			
		||||
  ot->idname = "OBJECT_OT_volume_import";
 | 
			
		||||
 | 
			
		||||
  /* api callbacks */
 | 
			
		||||
  ot->exec = volume_import_exec;
 | 
			
		||||
  ot->invoke = volume_import_invoke;
 | 
			
		||||
 | 
			
		||||
  /* flags */
 | 
			
		||||
  ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 | 
			
		||||
 | 
			
		||||
  /* properties */
 | 
			
		||||
  WM_operator_properties_filesel(ot,
 | 
			
		||||
                                 FILE_TYPE_FOLDER | FILE_TYPE_VOLUME,
 | 
			
		||||
                                 FILE_SPECIAL,
 | 
			
		||||
                                 FILE_OPENFILE,
 | 
			
		||||
                                 WM_FILESEL_FILEPATH | WM_FILESEL_DIRECTORY | WM_FILESEL_FILES |
 | 
			
		||||
                                     WM_FILESEL_RELPATH,
 | 
			
		||||
                                 FILE_DEFAULTDISPLAY,
 | 
			
		||||
                                 FILE_SORT_ALPHA);
 | 
			
		||||
 | 
			
		||||
  RNA_def_boolean(
 | 
			
		||||
      ot->srna,
 | 
			
		||||
      "use_sequence_detection",
 | 
			
		||||
      true,
 | 
			
		||||
      "Detect Sequences",
 | 
			
		||||
      "Automatically detect animated sequences in selected volume files (based on file names)");
 | 
			
		||||
 | 
			
		||||
  ED_object_add_generic_props(ot, false);
 | 
			
		||||
}
 | 
			
		||||
@@ -628,6 +628,9 @@ static int gather_frames_to_render_for_id(LibraryIDLinkCallbackData *cb_data)
 | 
			
		||||
    case ID_MC:  /* MovieClip */
 | 
			
		||||
    case ID_MSK: /* Mask */
 | 
			
		||||
    case ID_LP:  /* LightProbe */
 | 
			
		||||
    case ID_HA:  /* Hair */
 | 
			
		||||
    case ID_PT:  /* PointCloud */
 | 
			
		||||
    case ID_VO:  /* Volume */
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
      /* Blacklist: */
 | 
			
		||||
 
 | 
			
		||||
@@ -54,4 +54,8 @@ if(WITH_FREESTYLE)
 | 
			
		||||
  add_definitions(-DWITH_FREESTYLE)
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
if(WITH_NEW_OBJECT_TYPES)
 | 
			
		||||
  add_definitions(-DWITH_NEW_OBJECT_TYPES)
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
blender_add_lib(bf_editor_space_buttons "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
 | 
			
		||||
 
 | 
			
		||||
@@ -251,6 +251,17 @@ static int buttons_context_path_data(ButsContextPath *path, int type)
 | 
			
		||||
  else if (RNA_struct_is_a(ptr->type, &RNA_GreasePencil) && (type == -1 || type == OB_GPENCIL)) {
 | 
			
		||||
    return 1;
 | 
			
		||||
  }
 | 
			
		||||
#ifdef WITH_NEW_OBJECT_TYPES
 | 
			
		||||
  else if (RNA_struct_is_a(ptr->type, &RNA_Hair) && (type == -1 || type == OB_HAIR)) {
 | 
			
		||||
    return 1;
 | 
			
		||||
  }
 | 
			
		||||
  else if (RNA_struct_is_a(ptr->type, &RNA_PointCloud) && (type == -1 || type == OB_POINTCLOUD)) {
 | 
			
		||||
    return 1;
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
  else if (RNA_struct_is_a(ptr->type, &RNA_Volume) && (type == -1 || type == OB_VOLUME)) {
 | 
			
		||||
    return 1;
 | 
			
		||||
  }
 | 
			
		||||
  /* try to get an object in the path, no pinning supported here */
 | 
			
		||||
  else if (buttons_context_path_object(path)) {
 | 
			
		||||
    ob = path->ptr[path->len - 1].data;
 | 
			
		||||
@@ -274,7 +285,16 @@ static int buttons_context_path_modifier(ButsContextPath *path)
 | 
			
		||||
  if (buttons_context_path_object(path)) {
 | 
			
		||||
    ob = path->ptr[path->len - 1].data;
 | 
			
		||||
 | 
			
		||||
    if (ob && ELEM(ob->type, OB_MESH, OB_CURVE, OB_FONT, OB_SURF, OB_LATTICE, OB_GPENCIL)) {
 | 
			
		||||
    if (ob && ELEM(ob->type,
 | 
			
		||||
                   OB_MESH,
 | 
			
		||||
                   OB_CURVE,
 | 
			
		||||
                   OB_FONT,
 | 
			
		||||
                   OB_SURF,
 | 
			
		||||
                   OB_LATTICE,
 | 
			
		||||
                   OB_GPENCIL,
 | 
			
		||||
                   OB_HAIR,
 | 
			
		||||
                   OB_POINTCLOUD,
 | 
			
		||||
                   OB_VOLUME)) {
 | 
			
		||||
      return 1;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
@@ -776,6 +796,11 @@ const char *buttons_context_dir[] = {
 | 
			
		||||
    "line_style",
 | 
			
		||||
    "collection",
 | 
			
		||||
    "gpencil",
 | 
			
		||||
#ifdef WITH_NEW_OBJECT_TYPES
 | 
			
		||||
    "hair",
 | 
			
		||||
    "pointcloud",
 | 
			
		||||
#endif
 | 
			
		||||
    "volume",
 | 
			
		||||
    NULL,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -853,6 +878,20 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r
 | 
			
		||||
    set_pointer_type(path, result, &RNA_LightProbe);
 | 
			
		||||
    return 1;
 | 
			
		||||
  }
 | 
			
		||||
#ifdef WITH_NEW_OBJECT_TYPES
 | 
			
		||||
  else if (CTX_data_equals(member, "hair")) {
 | 
			
		||||
    set_pointer_type(path, result, &RNA_Hair);
 | 
			
		||||
    return 1;
 | 
			
		||||
  }
 | 
			
		||||
  else if (CTX_data_equals(member, "pointcloud")) {
 | 
			
		||||
    set_pointer_type(path, result, &RNA_PointCloud);
 | 
			
		||||
    return 1;
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
  else if (CTX_data_equals(member, "volume")) {
 | 
			
		||||
    set_pointer_type(path, result, &RNA_Volume);
 | 
			
		||||
    return 1;
 | 
			
		||||
  }
 | 
			
		||||
  else if (CTX_data_equals(member, "material")) {
 | 
			
		||||
    set_pointer_type(path, result, &RNA_Material);
 | 
			
		||||
    return 1;
 | 
			
		||||
 
 | 
			
		||||
@@ -1080,6 +1080,9 @@ static int filelist_geticon_ex(FileDirEntry *file,
 | 
			
		||||
  else if (typeflag & FILE_TYPE_USD) {
 | 
			
		||||
    return ICON_FILE_3D;
 | 
			
		||||
  }
 | 
			
		||||
  else if (typeflag & FILE_TYPE_VOLUME) {
 | 
			
		||||
    return ICON_FILE_VOLUME;
 | 
			
		||||
  }
 | 
			
		||||
  else if (typeflag & FILE_TYPE_OBJECT_IO) {
 | 
			
		||||
    return ICON_FILE_3D;
 | 
			
		||||
  }
 | 
			
		||||
@@ -2236,6 +2239,9 @@ int ED_path_extension_type(const char *path)
 | 
			
		||||
  else if (BLI_path_extension_check_n(path, ".usd", ".usda", ".usdc", NULL)) {
 | 
			
		||||
    return FILE_TYPE_USD;
 | 
			
		||||
  }
 | 
			
		||||
  else if (BLI_path_extension_check(path, ".vdb")) {
 | 
			
		||||
    return FILE_TYPE_VOLUME;
 | 
			
		||||
  }
 | 
			
		||||
  else if (BLI_path_extension_check(path, ".zip")) {
 | 
			
		||||
    return FILE_TYPE_ARCHIVE;
 | 
			
		||||
  }
 | 
			
		||||
@@ -2298,6 +2304,8 @@ int ED_file_extension_icon(const char *path)
 | 
			
		||||
      return ICON_FILE_TEXT;
 | 
			
		||||
    case FILE_TYPE_ARCHIVE:
 | 
			
		||||
      return ICON_FILE_ARCHIVE;
 | 
			
		||||
    case FILE_TYPE_VOLUME:
 | 
			
		||||
      return ICON_FILE_VOLUME;
 | 
			
		||||
    default:
 | 
			
		||||
      return ICON_FILE_BLANK;
 | 
			
		||||
  }
 | 
			
		||||
@@ -2625,9 +2633,9 @@ static void filelist_readjob_main_rec(Main *bmain, FileList *filelist)
 | 
			
		||||
  if (filelist->dir[0] == 0) {
 | 
			
		||||
    /* make directories */
 | 
			
		||||
#  ifdef WITH_FREESTYLE
 | 
			
		||||
    filelist->filelist.nbr_entries = 24;
 | 
			
		||||
		filelist->filelist.nbr_entries = 27;
 | 
			
		||||
#  else
 | 
			
		||||
    filelist->filelist.nbr_entries = 23;
 | 
			
		||||
		filelist->filelist.nbr_entries = 26;
 | 
			
		||||
#  endif
 | 
			
		||||
    filelist_resize(filelist, filelist->filelist.nbr_entries);
 | 
			
		||||
 | 
			
		||||
@@ -2658,8 +2666,11 @@ static void filelist_readjob_main_rec(Main *bmain, FileList *filelist)
 | 
			
		||||
    filelist->filelist.entries[20].entry->relpath = BLI_strdup("Action");
 | 
			
		||||
    filelist->filelist.entries[21].entry->relpath = BLI_strdup("NodeTree");
 | 
			
		||||
    filelist->filelist.entries[22].entry->relpath = BLI_strdup("Speaker");
 | 
			
		||||
		filelist->filelist.entries[23].entry->relpath = BLI_strdup("Hair");
 | 
			
		||||
		filelist->filelist.entries[24].entry->relpath = BLI_strdup("Point Cloud");
 | 
			
		||||
		filelist->filelist.entries[25].entry->relpath = BLI_strdup("Volume");
 | 
			
		||||
#  ifdef WITH_FREESTYLE
 | 
			
		||||
    filelist->filelist.entries[23].entry->relpath = BLI_strdup("FreestyleLineStyle");
 | 
			
		||||
		filelist->filelist.entries[26].entry->relpath = BLI_strdup("FreestyleLineStyle");
 | 
			
		||||
#  endif
 | 
			
		||||
  }
 | 
			
		||||
  else {
 | 
			
		||||
 
 | 
			
		||||
@@ -218,6 +218,9 @@ short ED_fileselect_set_params(SpaceFile *sfile)
 | 
			
		||||
    if ((prop = RNA_struct_find_property(op->ptr, "filter_usd"))) {
 | 
			
		||||
      params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_USD : 0;
 | 
			
		||||
    }
 | 
			
		||||
    if ((prop = RNA_struct_find_property(op->ptr, "filter_volume"))) {
 | 
			
		||||
      params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_VOLUME : 0;
 | 
			
		||||
    }
 | 
			
		||||
    if ((prop = RNA_struct_find_property(op->ptr, "filter_glob"))) {
 | 
			
		||||
      /* Protection against pyscripts not setting proper size limit... */
 | 
			
		||||
      char *tmp = RNA_property_string_get_alloc(
 | 
			
		||||
 
 | 
			
		||||
@@ -204,6 +204,11 @@ static void stats_object(Object *ob, SceneStats *stats, GSet *objects_gset)
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case OB_HAIR:
 | 
			
		||||
    case OB_POINTCLOUD:
 | 
			
		||||
    case OB_VOLUME: {
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -140,7 +140,10 @@ bool nla_panel_context(const bContext *C,
 | 
			
		||||
      case ANIMTYPE_DSLINESTYLE:
 | 
			
		||||
      case ANIMTYPE_DSSPK:
 | 
			
		||||
      case ANIMTYPE_DSGPENCIL:
 | 
			
		||||
      case ANIMTYPE_PALETTE: {
 | 
			
		||||
      case ANIMTYPE_PALETTE:
 | 
			
		||||
      case ANIMTYPE_DSHAIR:
 | 
			
		||||
      case ANIMTYPE_DSPOINTCLOUD:
 | 
			
		||||
      case ANIMTYPE_DSVOLUME: {
 | 
			
		||||
        /* for these channels, we only do AnimData */
 | 
			
		||||
        if (ale->adt && adt_ptr) {
 | 
			
		||||
          ID *id;
 | 
			
		||||
 
 | 
			
		||||
@@ -190,7 +190,10 @@ static int mouse_nla_channels(
 | 
			
		||||
    case ANIMTYPE_DSLINESTYLE:
 | 
			
		||||
    case ANIMTYPE_DSSPK:
 | 
			
		||||
    case ANIMTYPE_DSGPENCIL:
 | 
			
		||||
    case ANIMTYPE_PALETTE: {
 | 
			
		||||
    case ANIMTYPE_PALETTE:
 | 
			
		||||
    case ANIMTYPE_DSHAIR:
 | 
			
		||||
    case ANIMTYPE_DSPOINTCLOUD:
 | 
			
		||||
    case ANIMTYPE_DSVOLUME: {
 | 
			
		||||
      /* sanity checking... */
 | 
			
		||||
      if (ale->adt) {
 | 
			
		||||
        /* select/deselect */
 | 
			
		||||
 
 | 
			
		||||
@@ -446,8 +446,17 @@ void ED_node_shader_default(const bContext *C, ID *id)
 | 
			
		||||
 | 
			
		||||
  if (GS(id->name) == ID_MA) {
 | 
			
		||||
    /* Materials */
 | 
			
		||||
    Object *ob = CTX_data_active_object(C);
 | 
			
		||||
    Material *ma = (Material *)id;
 | 
			
		||||
    Material *ma_default = BKE_material_default_surface();
 | 
			
		||||
    Material *ma_default;
 | 
			
		||||
 | 
			
		||||
    if (ob && ob->type == OB_VOLUME) {
 | 
			
		||||
      ma_default = BKE_material_default_volume();
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
      ma_default = BKE_material_default_surface();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ma->nodetree = ntreeCopyTree(bmain, ma_default->nodetree);
 | 
			
		||||
    ntreeUpdateTree(bmain, ma->nodetree);
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -2418,6 +2418,15 @@ TreeElementIcon tree_element_get_icon(TreeStoreElem *tselem, TreeElement *te)
 | 
			
		||||
        case OB_LIGHTPROBE:
 | 
			
		||||
          data.icon = ICON_OUTLINER_OB_LIGHTPROBE;
 | 
			
		||||
          break;
 | 
			
		||||
        case OB_HAIR:
 | 
			
		||||
          data.icon = ICON_OUTLINER_OB_HAIR;
 | 
			
		||||
          break;
 | 
			
		||||
        case OB_POINTCLOUD:
 | 
			
		||||
          data.icon = ICON_OUTLINER_OB_POINTCLOUD;
 | 
			
		||||
          break;
 | 
			
		||||
        case OB_VOLUME:
 | 
			
		||||
          data.icon = ICON_OUTLINER_OB_VOLUME;
 | 
			
		||||
          break;
 | 
			
		||||
        case OB_EMPTY:
 | 
			
		||||
          if (ob->instance_collection && (ob->transflag & OB_DUPLICOLLECTION)) {
 | 
			
		||||
            data.icon = ICON_OUTLINER_OB_GROUP_INSTANCE;
 | 
			
		||||
@@ -2515,6 +2524,15 @@ TreeElementIcon tree_element_get_icon(TreeStoreElem *tselem, TreeElement *te)
 | 
			
		||||
        case ID_GR:
 | 
			
		||||
          data.icon = ICON_GROUP;
 | 
			
		||||
          break;
 | 
			
		||||
        case ID_HA:
 | 
			
		||||
          data.icon = ICON_OUTLINER_DATA_HAIR;
 | 
			
		||||
          break;
 | 
			
		||||
        case ID_PT:
 | 
			
		||||
          data.icon = ICON_OUTLINER_DATA_POINTCLOUD;
 | 
			
		||||
          break;
 | 
			
		||||
        case ID_VO:
 | 
			
		||||
          data.icon = ICON_OUTLINER_DATA_VOLUME;
 | 
			
		||||
          break;
 | 
			
		||||
        case ID_LI:
 | 
			
		||||
          if (tselem->id->tag & LIB_TAG_MISSING) {
 | 
			
		||||
            data.icon = ICON_LIBRARY_DATA_BROKEN;
 | 
			
		||||
 
 | 
			
		||||
@@ -105,7 +105,10 @@ typedef struct TreeElementIcon {
 | 
			
		||||
        ID_PA, \
 | 
			
		||||
        ID_GD, \
 | 
			
		||||
        ID_LS, \
 | 
			
		||||
        ID_LP) || /* Only in 'blendfile' mode ... :/ */ \
 | 
			
		||||
        ID_LP, \
 | 
			
		||||
        ID_HA, \
 | 
			
		||||
        ID_PT, \
 | 
			
		||||
        ID_VO) || /* Only in 'blendfile' mode ... :/ */ \
 | 
			
		||||
   ELEM(GS((_id)->name), \
 | 
			
		||||
        ID_SCR, \
 | 
			
		||||
        ID_WM, \
 | 
			
		||||
 
 | 
			
		||||
@@ -27,13 +27,16 @@
 | 
			
		||||
#include "DNA_armature_types.h"
 | 
			
		||||
#include "DNA_collection_types.h"
 | 
			
		||||
#include "DNA_gpencil_types.h"
 | 
			
		||||
#include "DNA_hair_types.h"
 | 
			
		||||
#include "DNA_light_types.h"
 | 
			
		||||
#include "DNA_linestyle_types.h"
 | 
			
		||||
#include "DNA_material_types.h"
 | 
			
		||||
#include "DNA_mesh_types.h"
 | 
			
		||||
#include "DNA_meta_types.h"
 | 
			
		||||
#include "DNA_pointcloud_types.h"
 | 
			
		||||
#include "DNA_scene_types.h"
 | 
			
		||||
#include "DNA_sequence_types.h"
 | 
			
		||||
#include "DNA_volume_types.h"
 | 
			
		||||
#include "DNA_world_types.h"
 | 
			
		||||
#include "DNA_object_types.h"
 | 
			
		||||
#include "DNA_constraint_types.h"
 | 
			
		||||
@@ -153,6 +156,9 @@ static void set_operation_types(SpaceOutliner *soops,
 | 
			
		||||
          case ID_CF:
 | 
			
		||||
          case ID_WS:
 | 
			
		||||
          case ID_LP:
 | 
			
		||||
          case ID_HA:
 | 
			
		||||
          case ID_PT:
 | 
			
		||||
          case ID_VO:
 | 
			
		||||
            is_standard_id = true;
 | 
			
		||||
            break;
 | 
			
		||||
          case ID_WM:
 | 
			
		||||
@@ -230,6 +236,21 @@ static void unlink_material_cb(bContext *UNUSED(C),
 | 
			
		||||
    totcol = mb->totcol;
 | 
			
		||||
    matar = mb->mat;
 | 
			
		||||
  }
 | 
			
		||||
  else if (GS(tsep->id->name) == ID_HA) {
 | 
			
		||||
    Hair *hair = (Hair *)tsep->id;
 | 
			
		||||
    totcol = hair->totcol;
 | 
			
		||||
    matar = hair->mat;
 | 
			
		||||
  }
 | 
			
		||||
  else if (GS(tsep->id->name) == ID_PT) {
 | 
			
		||||
    PointCloud *pointcloud = (PointCloud *)tsep->id;
 | 
			
		||||
    totcol = pointcloud->totcol;
 | 
			
		||||
    matar = pointcloud->mat;
 | 
			
		||||
  }
 | 
			
		||||
  else if (GS(tsep->id->name) == ID_VO) {
 | 
			
		||||
    Volume *volume = (Volume *)tsep->id;
 | 
			
		||||
    totcol = volume->totcol;
 | 
			
		||||
    matar = volume->mat;
 | 
			
		||||
  }
 | 
			
		||||
  else {
 | 
			
		||||
    BLI_assert(0);
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -33,6 +33,7 @@
 | 
			
		||||
#include "DNA_cachefile_types.h"
 | 
			
		||||
#include "DNA_collection_types.h"
 | 
			
		||||
#include "DNA_gpencil_types.h"
 | 
			
		||||
#include "DNA_hair_types.h"
 | 
			
		||||
#include "DNA_key_types.h"
 | 
			
		||||
#include "DNA_light_types.h"
 | 
			
		||||
#include "DNA_material_types.h"
 | 
			
		||||
@@ -40,7 +41,9 @@
 | 
			
		||||
#include "DNA_meta_types.h"
 | 
			
		||||
#include "DNA_lightprobe_types.h"
 | 
			
		||||
#include "DNA_particle_types.h"
 | 
			
		||||
#include "DNA_pointcloud_types.h"
 | 
			
		||||
#include "DNA_scene_types.h"
 | 
			
		||||
#include "DNA_volume_types.h"
 | 
			
		||||
#include "DNA_world_types.h"
 | 
			
		||||
#include "DNA_sequence_types.h"
 | 
			
		||||
#include "DNA_speaker_types.h"
 | 
			
		||||
@@ -750,6 +753,25 @@ static void outliner_add_id_contents(SpaceOutliner *soops,
 | 
			
		||||
        Collection *collection = (Collection *)id;
 | 
			
		||||
        outliner_add_collection_recursive(soops, collection, te);
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case ID_HA: {
 | 
			
		||||
      Hair *hair = (Hair *)id;
 | 
			
		||||
      if (outliner_animdata_test(hair->adt))
 | 
			
		||||
        outliner_add_element(soops, &te->subtree, hair, te, TSE_ANIM_DATA, 0);
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case ID_PT: {
 | 
			
		||||
      PointCloud *pointcloud = (PointCloud *)id;
 | 
			
		||||
      if (outliner_animdata_test(pointcloud->adt))
 | 
			
		||||
        outliner_add_element(soops, &te->subtree, pointcloud, te, TSE_ANIM_DATA, 0);
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case ID_VO: {
 | 
			
		||||
      Volume *volume = (Volume *)id;
 | 
			
		||||
      if (outliner_animdata_test(volume->adt))
 | 
			
		||||
        outliner_add_element(soops, &te->subtree, volume, te, TSE_ANIM_DATA, 0);
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    default:
 | 
			
		||||
      break;
 | 
			
		||||
 
 | 
			
		||||
@@ -559,6 +559,14 @@ static bool view3d_ima_empty_drop_poll(bContext *C,
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool view3d_volume_drop_poll(bContext *UNUSED(C),
 | 
			
		||||
                                    wmDrag *drag,
 | 
			
		||||
                                    const wmEvent *UNUSED(event),
 | 
			
		||||
                                    const char **UNUSED(tooltip))
 | 
			
		||||
{
 | 
			
		||||
  return (drag->type == WM_DRAG_PATH) && (drag->icon == ICON_FILE_VOLUME);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void view3d_ob_drop_copy(wmDrag *drag, wmDropBox *drop)
 | 
			
		||||
{
 | 
			
		||||
  ID *id = WM_drag_ID(drag, ID_OB);
 | 
			
		||||
@@ -626,6 +634,7 @@ static void view3d_dropboxes(void)
 | 
			
		||||
      lb, "VIEW3D_OT_background_image_add", view3d_ima_bg_drop_poll, view3d_id_path_drop_copy);
 | 
			
		||||
  WM_dropbox_add(
 | 
			
		||||
      lb, "OBJECT_OT_drop_named_image", view3d_ima_empty_drop_poll, view3d_id_path_drop_copy);
 | 
			
		||||
  WM_dropbox_add(lb, "OBJECT_OT_volume_import", view3d_volume_drop_poll, view3d_id_path_drop_copy);
 | 
			
		||||
  WM_dropbox_add(lb,
 | 
			
		||||
                 "OBJECT_OT_collection_instance_add",
 | 
			
		||||
                 view3d_collection_drop_poll,
 | 
			
		||||
 
 | 
			
		||||
@@ -1591,8 +1591,8 @@ static void view3d_panel_transform(const bContext *C, Panel *pa)
 | 
			
		||||
    RNA_id_pointer_create(&ob->id, &obptr);
 | 
			
		||||
    v3d_transform_butsR(col, &obptr);
 | 
			
		||||
 | 
			
		||||
    /* dimensions and editmode just happen to be the same checks */
 | 
			
		||||
    if (OB_TYPE_SUPPORT_EDITMODE(ob->type)) {
 | 
			
		||||
    /* Dimensions and editmode are mostly the same check. */
 | 
			
		||||
    if (OB_TYPE_SUPPORT_EDITMODE(ob->type) || ELEM(ob->type, OB_VOLUME, OB_HAIR, OB_POINTCLOUD)) {
 | 
			
		||||
      View3D *v3d = CTX_wm_view3d(C);
 | 
			
		||||
      v3d_object_dimension_buts(NULL, col, v3d, ob);
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -405,6 +405,9 @@ typedef enum ID_Type {
 | 
			
		||||
  ID_CF = MAKE_ID2('C', 'F'),  /* CacheFile */
 | 
			
		||||
  ID_WS = MAKE_ID2('W', 'S'),  /* WorkSpace */
 | 
			
		||||
  ID_LP = MAKE_ID2('L', 'P'),  /* LightProbe */
 | 
			
		||||
  ID_HA = MAKE_ID2('H', 'A'),  /* Hair */
 | 
			
		||||
  ID_PT = MAKE_ID2('P', 'T'),  /* PointCloud */
 | 
			
		||||
  ID_VO = MAKE_ID2('V', 'O'),  /* Volume */
 | 
			
		||||
} ID_Type;
 | 
			
		||||
 | 
			
		||||
/* Only used as 'placeholder' in .blend files for directly linked data-blocks. */
 | 
			
		||||
@@ -670,39 +673,40 @@ typedef enum IDRecalcFlag {
 | 
			
		||||
} IDRecalcFlag;
 | 
			
		||||
 | 
			
		||||
/* To filter ID types (filter_id). 64 bit to fit all types. */
 | 
			
		||||
enum {
 | 
			
		||||
  FILTER_ID_AC = (1ULL << 0),
 | 
			
		||||
  FILTER_ID_AR = (1ULL << 1),
 | 
			
		||||
  FILTER_ID_BR = (1ULL << 2),
 | 
			
		||||
  FILTER_ID_CA = (1ULL << 3),
 | 
			
		||||
  FILTER_ID_CU = (1ULL << 4),
 | 
			
		||||
  FILTER_ID_GD = (1ULL << 5),
 | 
			
		||||
  FILTER_ID_GR = (1ULL << 6),
 | 
			
		||||
  FILTER_ID_IM = (1ULL << 7),
 | 
			
		||||
  FILTER_ID_LA = (1ULL << 8),
 | 
			
		||||
  FILTER_ID_LS = (1ULL << 9),
 | 
			
		||||
  FILTER_ID_LT = (1ULL << 10),
 | 
			
		||||
  FILTER_ID_MA = (1ULL << 11),
 | 
			
		||||
  FILTER_ID_MB = (1ULL << 12),
 | 
			
		||||
  FILTER_ID_MC = (1ULL << 13),
 | 
			
		||||
  FILTER_ID_ME = (1ULL << 14),
 | 
			
		||||
  FILTER_ID_MSK = (1ULL << 15),
 | 
			
		||||
  FILTER_ID_NT = (1ULL << 16),
 | 
			
		||||
  FILTER_ID_OB = (1ULL << 17),
 | 
			
		||||
  FILTER_ID_PAL = (1ULL << 18),
 | 
			
		||||
  FILTER_ID_PC = (1ULL << 19),
 | 
			
		||||
  FILTER_ID_SCE = (1ULL << 20),
 | 
			
		||||
  FILTER_ID_SPK = (1ULL << 21),
 | 
			
		||||
  FILTER_ID_SO = (1ULL << 22),
 | 
			
		||||
  FILTER_ID_TE = (1ULL << 23),
 | 
			
		||||
  FILTER_ID_TXT = (1ULL << 24),
 | 
			
		||||
  FILTER_ID_VF = (1ULL << 25),
 | 
			
		||||
  FILTER_ID_WO = (1ULL << 26),
 | 
			
		||||
  FILTER_ID_PA = (1ULL << 27),
 | 
			
		||||
  FILTER_ID_CF = (1ULL << 28),
 | 
			
		||||
  FILTER_ID_WS = (1ULL << 29),
 | 
			
		||||
  FILTER_ID_LP = (1ULL << 31),
 | 
			
		||||
};
 | 
			
		||||
#define FILTER_ID_AC (1ULL << 0)
 | 
			
		||||
#define FILTER_ID_AR (1ULL << 1)
 | 
			
		||||
#define FILTER_ID_BR (1ULL << 2)
 | 
			
		||||
#define FILTER_ID_CA (1ULL << 3)
 | 
			
		||||
#define FILTER_ID_CU (1ULL << 4)
 | 
			
		||||
#define FILTER_ID_GD (1ULL << 5)
 | 
			
		||||
#define FILTER_ID_GR (1ULL << 6)
 | 
			
		||||
#define FILTER_ID_IM (1ULL << 7)
 | 
			
		||||
#define FILTER_ID_LA (1ULL << 8)
 | 
			
		||||
#define FILTER_ID_LS (1ULL << 9)
 | 
			
		||||
#define FILTER_ID_LT (1ULL << 10)
 | 
			
		||||
#define FILTER_ID_MA (1ULL << 11)
 | 
			
		||||
#define FILTER_ID_MB (1ULL << 12)
 | 
			
		||||
#define FILTER_ID_MC (1ULL << 13)
 | 
			
		||||
#define FILTER_ID_ME (1ULL << 14)
 | 
			
		||||
#define FILTER_ID_MSK (1ULL << 15)
 | 
			
		||||
#define FILTER_ID_NT (1ULL << 16)
 | 
			
		||||
#define FILTER_ID_OB (1ULL << 17)
 | 
			
		||||
#define FILTER_ID_PAL (1ULL << 18)
 | 
			
		||||
#define FILTER_ID_PC (1ULL << 19)
 | 
			
		||||
#define FILTER_ID_SCE (1ULL << 20)
 | 
			
		||||
#define FILTER_ID_SPK (1ULL << 21)
 | 
			
		||||
#define FILTER_ID_SO (1ULL << 22)
 | 
			
		||||
#define FILTER_ID_TE (1ULL << 23)
 | 
			
		||||
#define FILTER_ID_TXT (1ULL << 24)
 | 
			
		||||
#define FILTER_ID_VF (1ULL << 25)
 | 
			
		||||
#define FILTER_ID_WO (1ULL << 26)
 | 
			
		||||
#define FILTER_ID_PA (1ULL << 27)
 | 
			
		||||
#define FILTER_ID_CF (1ULL << 28)
 | 
			
		||||
#define FILTER_ID_WS (1ULL << 29)
 | 
			
		||||
#define FILTER_ID_LP (1ULL << 31)
 | 
			
		||||
#define FILTER_ID_HA (1ULL << 32)
 | 
			
		||||
#define FILTER_ID_PT (1ULL << 33)
 | 
			
		||||
#define FILTER_ID_VO (1ULL << 34)
 | 
			
		||||
 | 
			
		||||
#define FILTER_ID_ALL \
 | 
			
		||||
  (FILTER_ID_AC | FILTER_ID_AR | FILTER_ID_BR | FILTER_ID_CA | FILTER_ID_CU | FILTER_ID_GD | \
 | 
			
		||||
@@ -710,7 +714,7 @@ enum {
 | 
			
		||||
   FILTER_ID_MB | FILTER_ID_MC | FILTER_ID_ME | FILTER_ID_MSK | FILTER_ID_NT | FILTER_ID_OB | \
 | 
			
		||||
   FILTER_ID_PA | FILTER_ID_PAL | FILTER_ID_PC | FILTER_ID_SCE | FILTER_ID_SPK | FILTER_ID_SO | \
 | 
			
		||||
   FILTER_ID_TE | FILTER_ID_TXT | FILTER_ID_VF | FILTER_ID_WO | FILTER_ID_CF | FILTER_ID_WS | \
 | 
			
		||||
   FILTER_ID_LP)
 | 
			
		||||
   FILTER_ID_LP | FILTER_ID_HA | FILTER_ID_PT | FILTER_ID_VO)
 | 
			
		||||
 | 
			
		||||
/* IMPORTANT: this enum matches the order currently use in set_listbasepointers,
 | 
			
		||||
 * keep them in sync! */
 | 
			
		||||
@@ -731,6 +735,9 @@ enum {
 | 
			
		||||
  INDEX_ID_ME,
 | 
			
		||||
  INDEX_ID_CU,
 | 
			
		||||
  INDEX_ID_MB,
 | 
			
		||||
  INDEX_ID_HA,
 | 
			
		||||
  INDEX_ID_PT,
 | 
			
		||||
  INDEX_ID_VO,
 | 
			
		||||
  INDEX_ID_LT,
 | 
			
		||||
  INDEX_ID_LA,
 | 
			
		||||
  INDEX_ID_CA,
 | 
			
		||||
 
 | 
			
		||||
@@ -776,6 +776,9 @@ typedef enum eDopeSheet_FilterFlag {
 | 
			
		||||
typedef enum eDopeSheet_FilterFlag2 {
 | 
			
		||||
  ADS_FILTER_NOCACHEFILES = (1 << 1),
 | 
			
		||||
  ADS_FILTER_NOMOVIECLIPS = (1 << 2),
 | 
			
		||||
  ADS_FILTER_NOHAIR = (1 << 3),
 | 
			
		||||
  ADS_FILTER_NOPOINTCLOUD = (1 << 4),
 | 
			
		||||
  ADS_FILTER_NOVOLUME = (1 << 5),
 | 
			
		||||
} eDopeSheet_FilterFlag2;
 | 
			
		||||
 | 
			
		||||
/* DopeSheet general flags */
 | 
			
		||||
 
 | 
			
		||||
@@ -76,7 +76,7 @@ typedef struct CustomData {
 | 
			
		||||
   * MUST be >= CD_NUMTYPES, but we cant use a define here.
 | 
			
		||||
   * Correct size is ensured in CustomData_update_typemap assert().
 | 
			
		||||
   */
 | 
			
		||||
  int typemap[43];
 | 
			
		||||
  int typemap[47];
 | 
			
		||||
  /** Number of layers, size of layers array. */
 | 
			
		||||
  int totlayer, maxlayer;
 | 
			
		||||
  /** In editmode, total size of all data layers. */
 | 
			
		||||
@@ -147,7 +147,13 @@ typedef enum CustomDataType {
 | 
			
		||||
  CD_CUSTOMLOOPNORMAL = 41,
 | 
			
		||||
  CD_SCULPT_FACE_SETS = 42,
 | 
			
		||||
 | 
			
		||||
  CD_NUMTYPES = 43,
 | 
			
		||||
  /* Hair and PointCloud */
 | 
			
		||||
  CD_LOCATION = 43,
 | 
			
		||||
  CD_RADIUS = 44,
 | 
			
		||||
  CD_HAIRCURVE = 45,
 | 
			
		||||
  CD_HAIRMAPPING = 46,
 | 
			
		||||
 | 
			
		||||
  CD_NUMTYPES = 47,
 | 
			
		||||
} CustomDataType;
 | 
			
		||||
 | 
			
		||||
/* Bits for CustomDataMask */
 | 
			
		||||
@@ -203,6 +209,9 @@ typedef enum CustomDataType {
 | 
			
		||||
/** Multires loop data. */
 | 
			
		||||
#define CD_MASK_MULTIRES_GRIDS (CD_MASK_MDISPS | CD_GRID_PAINT_MASK)
 | 
			
		||||
 | 
			
		||||
/* All data layers. */
 | 
			
		||||
#define CD_MASK_ALL (~0LL)
 | 
			
		||||
 | 
			
		||||
typedef struct CustomData_MeshMasks {
 | 
			
		||||
  uint64_t vmask;
 | 
			
		||||
  uint64_t emask;
 | 
			
		||||
 
 | 
			
		||||
@@ -29,6 +29,10 @@
 | 
			
		||||
 | 
			
		||||
#include "BLI_utildefines.h"
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "dna_type_offsets.h"
 | 
			
		||||
 | 
			
		||||
extern const void *DNA_default_table[SDNA_TYPE_MAX];
 | 
			
		||||
@@ -45,4 +49,8 @@ char *_DNA_struct_default_alloc_impl(const char *data_src, size_t size, const ch
 | 
			
		||||
  (struct_name *)_DNA_struct_default_alloc_impl( \
 | 
			
		||||
      DNA_default_table[SDNA_TYPE_FROM_STRUCT(struct_name)], sizeof(struct_name), __func__)
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* __DNA_DEFAULTS_H__ */
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										40
									
								
								source/blender/makesdna/DNA_hair_defaults.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								source/blender/makesdna/DNA_hair_defaults.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,40 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This program is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU General Public License
 | 
			
		||||
 * as published by the Free Software Foundation; either version 2
 | 
			
		||||
 * of the License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/** \file
 | 
			
		||||
 * \ingroup DNA
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __DNA_HAIR_DEFAULTS_H__
 | 
			
		||||
#define __DNA_HAIR_DEFAULTS_H__
 | 
			
		||||
 | 
			
		||||
/* Struct members on own line. */
 | 
			
		||||
/* clang-format off */
 | 
			
		||||
 | 
			
		||||
/* -------------------------------------------------------------------- */
 | 
			
		||||
/** \name Hair Struct
 | 
			
		||||
 * \{ */
 | 
			
		||||
 | 
			
		||||
#define _DNA_DEFAULT_Hair \
 | 
			
		||||
  { \
 | 
			
		||||
    .flag = 0, \
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
/** \} */
 | 
			
		||||
 | 
			
		||||
/* clang-format on */
 | 
			
		||||
 | 
			
		||||
#endif /* __DNA_HAIR_DEFAULTS_H__ */
 | 
			
		||||
							
								
								
									
										82
									
								
								source/blender/makesdna/DNA_hair_types.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								source/blender/makesdna/DNA_hair_types.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,82 @@
 | 
			
		||||
/*
 | 
			
		||||
 * ***** 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 DNA_hair_types.h
 | 
			
		||||
 *  \ingroup DNA
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __DNA_HAIR_TYPES_H__
 | 
			
		||||
#define __DNA_HAIR_TYPES_H__
 | 
			
		||||
 | 
			
		||||
#include "DNA_ID.h"
 | 
			
		||||
#include "DNA_customdata_types.h"
 | 
			
		||||
 | 
			
		||||
typedef struct HairCurve {
 | 
			
		||||
  /* Index of first point of hair curve. */
 | 
			
		||||
  int firstpoint;
 | 
			
		||||
  /* Number of points in hair curve, must be 2 or higher. */
 | 
			
		||||
  int numpoints;
 | 
			
		||||
} HairCurve;
 | 
			
		||||
 | 
			
		||||
/* Hair attachment to a mesh.
 | 
			
		||||
 * TODO: attach to tesselated triangles or polygons?
 | 
			
		||||
 * TODO: what type of interpolation to use for uv? */
 | 
			
		||||
typedef struct HairMapping {
 | 
			
		||||
  float uv[2];
 | 
			
		||||
  int poly;
 | 
			
		||||
} HairMapping;
 | 
			
		||||
 | 
			
		||||
typedef struct Hair {
 | 
			
		||||
  ID id;
 | 
			
		||||
  struct AnimData *adt; /* animation data (must be immediately after id) */
 | 
			
		||||
 | 
			
		||||
  int flag;
 | 
			
		||||
  int _pad1[1];
 | 
			
		||||
 | 
			
		||||
  /* Geometry */
 | 
			
		||||
  float (*co)[3];
 | 
			
		||||
  float *radius;
 | 
			
		||||
  struct HairCurve *curves;
 | 
			
		||||
  struct HairMaping *mapping;
 | 
			
		||||
  int totpoint;
 | 
			
		||||
  int totcurve;
 | 
			
		||||
 | 
			
		||||
  /* Custom Data */
 | 
			
		||||
  struct CustomData pdata;
 | 
			
		||||
  struct CustomData cdata;
 | 
			
		||||
 | 
			
		||||
  /* Material */
 | 
			
		||||
  struct Material **mat;
 | 
			
		||||
  short totcol;
 | 
			
		||||
  short _pad2[3];
 | 
			
		||||
 | 
			
		||||
  /* Draw Cache */
 | 
			
		||||
  void *batch_cache;
 | 
			
		||||
} Hair;
 | 
			
		||||
 | 
			
		||||
/* Hair.flag */
 | 
			
		||||
enum {
 | 
			
		||||
  HA_DS_EXPAND = (1 << 0),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Only one material supported currently. */
 | 
			
		||||
#define HAIR_MATERIAL_NR 1
 | 
			
		||||
 | 
			
		||||
#endif /* __DNA_HAIR_TYPES_H__ */
 | 
			
		||||
@@ -456,12 +456,18 @@ enum {
 | 
			
		||||
  /** Grease Pencil object used in 3D view but not used for annotation in 2D. */
 | 
			
		||||
  OB_GPENCIL = 26,
 | 
			
		||||
 | 
			
		||||
  OB_HAIR = 27,
 | 
			
		||||
 | 
			
		||||
  OB_POINTCLOUD = 28,
 | 
			
		||||
 | 
			
		||||
  OB_VOLUME = 29,
 | 
			
		||||
 | 
			
		||||
  OB_TYPE_MAX,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* check if the object type supports materials */
 | 
			
		||||
#define OB_TYPE_SUPPORT_MATERIAL(_type) \
 | 
			
		||||
  (((_type) >= OB_MESH && (_type) <= OB_MBALL) || ((_type) == OB_GPENCIL))
 | 
			
		||||
  (((_type) >= OB_MESH && (_type) <= OB_MBALL) || ((_type) >= OB_GPENCIL && (_type) <= OB_VOLUME))
 | 
			
		||||
#define OB_TYPE_SUPPORT_VGROUP(_type) (ELEM(_type, OB_MESH, OB_LATTICE, OB_GPENCIL))
 | 
			
		||||
#define OB_TYPE_SUPPORT_EDITMODE(_type) \
 | 
			
		||||
  (ELEM(_type, OB_MESH, OB_FONT, OB_CURVE, OB_SURF, OB_MBALL, OB_LATTICE, OB_ARMATURE))
 | 
			
		||||
@@ -472,7 +478,20 @@ enum {
 | 
			
		||||
 | 
			
		||||
/* is this ID type used as object data */
 | 
			
		||||
#define OB_DATA_SUPPORT_ID(_id_type) \
 | 
			
		||||
  (ELEM(_id_type, ID_ME, ID_CU, ID_MB, ID_LA, ID_SPK, ID_LP, ID_CA, ID_LT, ID_GD, ID_AR))
 | 
			
		||||
  (ELEM(_id_type, \
 | 
			
		||||
        ID_ME, \
 | 
			
		||||
        ID_CU, \
 | 
			
		||||
        ID_MB, \
 | 
			
		||||
        ID_LA, \
 | 
			
		||||
        ID_SPK, \
 | 
			
		||||
        ID_LP, \
 | 
			
		||||
        ID_CA, \
 | 
			
		||||
        ID_LT, \
 | 
			
		||||
        ID_GD, \
 | 
			
		||||
        ID_AR, \
 | 
			
		||||
        ID_HA, \
 | 
			
		||||
        ID_PT, \
 | 
			
		||||
        ID_VO))
 | 
			
		||||
 | 
			
		||||
#define OB_DATA_SUPPORT_ID_CASE \
 | 
			
		||||
ID_ME: \
 | 
			
		||||
@@ -484,7 +503,10 @@ case ID_LP: \
 | 
			
		||||
case ID_CA: \
 | 
			
		||||
case ID_LT: \
 | 
			
		||||
case ID_GD: \
 | 
			
		||||
case ID_AR
 | 
			
		||||
case ID_AR: \
 | 
			
		||||
case ID_HA: \
 | 
			
		||||
case ID_PT: \
 | 
			
		||||
case ID_VO
 | 
			
		||||
 | 
			
		||||
/* partype: first 4 bits: type */
 | 
			
		||||
enum {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										40
									
								
								source/blender/makesdna/DNA_pointcloud_defaults.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								source/blender/makesdna/DNA_pointcloud_defaults.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,40 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This program is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU General Public License
 | 
			
		||||
 * as published by the Free Software Foundation; either version 2
 | 
			
		||||
 * of the License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/** \file
 | 
			
		||||
 * \ingroup DNA
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __DNA_POINTCLOUD_DEFAULTS_H__
 | 
			
		||||
#define __DNA_POINTCLOUD_DEFAULTS_H__
 | 
			
		||||
 | 
			
		||||
/* Struct members on own line. */
 | 
			
		||||
/* clang-format off */
 | 
			
		||||
 | 
			
		||||
/* -------------------------------------------------------------------- */
 | 
			
		||||
/** \name PointCloud Struct
 | 
			
		||||
 * \{ */
 | 
			
		||||
 | 
			
		||||
#define _DNA_DEFAULT_PointCloud \
 | 
			
		||||
  { \
 | 
			
		||||
    .flag = 0, \
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
/** \} */
 | 
			
		||||
 | 
			
		||||
/* clang-format on */
 | 
			
		||||
 | 
			
		||||
#endif /* __DNA_POINTCLOUD_DEFAULTS_H__ */
 | 
			
		||||
							
								
								
									
										64
									
								
								source/blender/makesdna/DNA_pointcloud_types.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								source/blender/makesdna/DNA_pointcloud_types.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,64 @@
 | 
			
		||||
/*
 | 
			
		||||
 * ***** 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 DNA_pointcloud_types.h
 | 
			
		||||
 *  \ingroup DNA
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __DNA_POINTCLOUD_TYPES_H__
 | 
			
		||||
#define __DNA_POINTCLOUD_TYPES_H__
 | 
			
		||||
 | 
			
		||||
#include "DNA_ID.h"
 | 
			
		||||
#include "DNA_customdata_types.h"
 | 
			
		||||
 | 
			
		||||
typedef struct PointCloud {
 | 
			
		||||
  ID id;
 | 
			
		||||
  struct AnimData *adt; /* animation data (must be immediately after id) */
 | 
			
		||||
 | 
			
		||||
  int flag;
 | 
			
		||||
  int _pad1[1];
 | 
			
		||||
 | 
			
		||||
  /* Geometry */
 | 
			
		||||
  float (*co)[3];
 | 
			
		||||
  float *radius;
 | 
			
		||||
  int totpoint;
 | 
			
		||||
  int _pad2[1];
 | 
			
		||||
 | 
			
		||||
  /* Custom Data */
 | 
			
		||||
  struct CustomData pdata;
 | 
			
		||||
 | 
			
		||||
  /* Material */
 | 
			
		||||
  struct Material **mat;
 | 
			
		||||
  short totcol;
 | 
			
		||||
  short _pad3[3];
 | 
			
		||||
 | 
			
		||||
  /* Draw Cache */
 | 
			
		||||
  void *batch_cache;
 | 
			
		||||
} PointCloud;
 | 
			
		||||
 | 
			
		||||
/* PointCloud.flag */
 | 
			
		||||
enum {
 | 
			
		||||
  PT_DS_EXPAND = (1 << 0),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Only one material supported currently. */
 | 
			
		||||
#define POINTCLOUD_MATERIAL_NR 1
 | 
			
		||||
 | 
			
		||||
#endif /* __DNA_POINTCLOUD_TYPES_H__ */
 | 
			
		||||
@@ -858,6 +858,7 @@ typedef enum eFileSel_File_Types {
 | 
			
		||||
  /** For all kinds of recognized import/export formats. No need for specialized types. */
 | 
			
		||||
  FILE_TYPE_OBJECT_IO = (1 << 17),
 | 
			
		||||
  FILE_TYPE_USD = (1 << 18),
 | 
			
		||||
  FILE_TYPE_VOLUME = (1 << 19),
 | 
			
		||||
 | 
			
		||||
  /** An FS directory (i.e. S_ISDIR on its path is true). */
 | 
			
		||||
  FILE_TYPE_DIR = (1 << 30),
 | 
			
		||||
 
 | 
			
		||||
@@ -1133,6 +1133,9 @@ typedef enum eDupli_ID_Flags {
 | 
			
		||||
  USER_DUP_PSYS = (1 << 11),
 | 
			
		||||
  USER_DUP_LIGHTPROBE = (1 << 12),
 | 
			
		||||
  USER_DUP_GPENCIL = (1 << 13),
 | 
			
		||||
  USER_DUP_HAIR = (1 << 14),
 | 
			
		||||
  USER_DUP_POINTCLOUD = (1 << 15),
 | 
			
		||||
  USER_DUP_VOLUME = (1 << 16),
 | 
			
		||||
} eDupli_ID_Flags;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										59
									
								
								source/blender/makesdna/DNA_volume_defaults.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								source/blender/makesdna/DNA_volume_defaults.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,59 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This program is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU General Public License
 | 
			
		||||
 * as published by the Free Software Foundation; either version 2
 | 
			
		||||
 * of the License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/** \file
 | 
			
		||||
 * \ingroup DNA
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __DNA_VOLUME_DEFAULTS_H__
 | 
			
		||||
#define __DNA_VOLUME_DEFAULTS_H__
 | 
			
		||||
 | 
			
		||||
/* Struct members on own line. */
 | 
			
		||||
/* clang-format off */
 | 
			
		||||
 | 
			
		||||
/* -------------------------------------------------------------------- */
 | 
			
		||||
/** \name Volume Struct
 | 
			
		||||
 * \{ */
 | 
			
		||||
 | 
			
		||||
#define _DNA_DEFAULT_VolumeDisplay \
 | 
			
		||||
  { \
 | 
			
		||||
    .density = 1.0f, \
 | 
			
		||||
    .wireframe_type = VOLUME_WIREFRAME_BOXES, \
 | 
			
		||||
    .wireframe_detail = VOLUME_WIREFRAME_COARSE, \
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
#define _DNA_DEFAULT_VolumeRender \
 | 
			
		||||
  { \
 | 
			
		||||
    .space = VOLUME_SPACE_OBJECT, \
 | 
			
		||||
    .step_size = 0.0f, \
 | 
			
		||||
    .clipping = 0.001f, \
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
#define _DNA_DEFAULT_Volume \
 | 
			
		||||
  { \
 | 
			
		||||
    .filepath[0] = '\0', \
 | 
			
		||||
    .frame_start = 1, \
 | 
			
		||||
    .frame_offset = 0, \
 | 
			
		||||
    .frame_duration = 0, \
 | 
			
		||||
    .display = _DNA_DEFAULT_VolumeDisplay, \
 | 
			
		||||
    .render = _DNA_DEFAULT_VolumeRender, \
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
/** \} */
 | 
			
		||||
 | 
			
		||||
/* clang-format on */
 | 
			
		||||
 | 
			
		||||
#endif /* __DNA_VOLUME_DEFAULTS_H__ */
 | 
			
		||||
							
								
								
									
										130
									
								
								source/blender/makesdna/DNA_volume_types.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										130
									
								
								source/blender/makesdna/DNA_volume_types.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,130 @@
 | 
			
		||||
/*
 | 
			
		||||
 * ***** 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 DNA_volume_types.h
 | 
			
		||||
 *  \ingroup DNA
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __DNA_VOLUME_TYPES_H__
 | 
			
		||||
#define __DNA_VOLUME_TYPES_H__
 | 
			
		||||
 | 
			
		||||
#include "DNA_ID.h"
 | 
			
		||||
 | 
			
		||||
struct PackedFile;
 | 
			
		||||
struct VolumeGridVector;
 | 
			
		||||
 | 
			
		||||
typedef struct Volume_Runtime {
 | 
			
		||||
  /* OpenVDB Grids */
 | 
			
		||||
  struct VolumeGridVector *grids;
 | 
			
		||||
 | 
			
		||||
  /* Current frame in sequence for evaluated volume */
 | 
			
		||||
  int frame;
 | 
			
		||||
  int _pad;
 | 
			
		||||
} Volume_Runtime;
 | 
			
		||||
 | 
			
		||||
typedef struct VolumeDisplay {
 | 
			
		||||
  float density;
 | 
			
		||||
  int wireframe_type;
 | 
			
		||||
  int wireframe_detail;
 | 
			
		||||
  int _pad[1];
 | 
			
		||||
} VolumeDisplay;
 | 
			
		||||
 | 
			
		||||
typedef struct VolumeRender {
 | 
			
		||||
  int precision;
 | 
			
		||||
  int space;
 | 
			
		||||
  float step_size;
 | 
			
		||||
  float clipping;
 | 
			
		||||
} VolumeRender;
 | 
			
		||||
 | 
			
		||||
typedef struct Volume {
 | 
			
		||||
  ID id;
 | 
			
		||||
  struct AnimData *adt; /* animation data (must be immediately after id) */
 | 
			
		||||
 | 
			
		||||
  /* File */
 | 
			
		||||
  char filepath[1024]; /* FILE_MAX */
 | 
			
		||||
  struct PackedFile *packedfile;
 | 
			
		||||
 | 
			
		||||
  /* Sequence */
 | 
			
		||||
  char is_sequence;
 | 
			
		||||
  char sequence_mode;
 | 
			
		||||
  char _pad1[2];
 | 
			
		||||
  int frame_start;
 | 
			
		||||
  int frame_duration;
 | 
			
		||||
  int frame_offset;
 | 
			
		||||
 | 
			
		||||
  /* Flag */
 | 
			
		||||
  int flag;
 | 
			
		||||
 | 
			
		||||
  /* Grids */
 | 
			
		||||
  int active_grid;
 | 
			
		||||
 | 
			
		||||
  /* Material */
 | 
			
		||||
  struct Material **mat;
 | 
			
		||||
  short totcol;
 | 
			
		||||
  short _pad2[3];
 | 
			
		||||
 | 
			
		||||
  /* Render & Display Settings */
 | 
			
		||||
  VolumeRender render;
 | 
			
		||||
  VolumeDisplay display;
 | 
			
		||||
 | 
			
		||||
  /* Draw Cache */
 | 
			
		||||
  void *batch_cache;
 | 
			
		||||
 | 
			
		||||
  /* Runtime Data */
 | 
			
		||||
  Volume_Runtime runtime;
 | 
			
		||||
} Volume;
 | 
			
		||||
 | 
			
		||||
/* Volume.flag */
 | 
			
		||||
enum {
 | 
			
		||||
  VO_DS_EXPAND = (1 << 0),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Volume.sequence_mode */
 | 
			
		||||
typedef enum VolumeSequenceMode {
 | 
			
		||||
  VOLUME_SEQUENCE_CLIP = 0,
 | 
			
		||||
  VOLUME_SEQUENCE_EXTEND,
 | 
			
		||||
  VOLUME_SEQUENCE_REPEAT,
 | 
			
		||||
  VOLUME_SEQUENCE_PING_PONG,
 | 
			
		||||
} VolumeSequenceMode;
 | 
			
		||||
 | 
			
		||||
/* VolumeDisplay.wireframe_type */
 | 
			
		||||
typedef enum VolumeWireframeType {
 | 
			
		||||
  VOLUME_WIREFRAME_NONE = 0,
 | 
			
		||||
  VOLUME_WIREFRAME_BOUNDS = 1,
 | 
			
		||||
  VOLUME_WIREFRAME_BOXES = 2,
 | 
			
		||||
  VOLUME_WIREFRAME_POINTS = 3,
 | 
			
		||||
} VolumeWireframeType;
 | 
			
		||||
 | 
			
		||||
/* VolumeDisplay.wireframe_detail */
 | 
			
		||||
typedef enum VolumeWireframeDetail {
 | 
			
		||||
  VOLUME_WIREFRAME_COARSE = 0,
 | 
			
		||||
  VOLUME_WIREFRAME_FINE = 1,
 | 
			
		||||
} VolumeWireframeDetail;
 | 
			
		||||
 | 
			
		||||
/* VolumeRender.space */
 | 
			
		||||
typedef enum VolumeRenderSpace {
 | 
			
		||||
  VOLUME_SPACE_OBJECT = 0,
 | 
			
		||||
  VOLUME_SPACE_WORLD = 1,
 | 
			
		||||
} VolumeRenderSpace;
 | 
			
		||||
 | 
			
		||||
/* Only one material supported currently. */
 | 
			
		||||
#define VOLUME_MATERIAL_NR 1
 | 
			
		||||
 | 
			
		||||
#endif /* __DNA_VOLUME_TYPES_H__ */
 | 
			
		||||
@@ -135,6 +135,7 @@ set(SRC
 | 
			
		||||
  ../DNA_curve_defaults.h
 | 
			
		||||
  ../DNA_defaults.h
 | 
			
		||||
  ../DNA_image_defaults.h
 | 
			
		||||
  ../DNA_hair_defaults.h
 | 
			
		||||
  ../DNA_lattice_defaults.h
 | 
			
		||||
  ../DNA_light_defaults.h
 | 
			
		||||
  ../DNA_lightprobe_defaults.h
 | 
			
		||||
@@ -143,11 +144,13 @@ set(SRC
 | 
			
		||||
  ../DNA_mesh_defaults.h
 | 
			
		||||
  ../DNA_meta_defaults.h
 | 
			
		||||
  ../DNA_object_defaults.h
 | 
			
		||||
  ../DNA_pointcloud_defaults.h
 | 
			
		||||
  ../DNA_scene_defaults.h
 | 
			
		||||
  ../DNA_speaker_defaults.h
 | 
			
		||||
  ../DNA_texture_defaults.h
 | 
			
		||||
  ../DNA_vec_defaults.h
 | 
			
		||||
  ../DNA_view3d_defaults.h
 | 
			
		||||
  ../DNA_volume_defaults.h
 | 
			
		||||
  ../DNA_world_defaults.h
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -59,6 +59,7 @@
 | 
			
		||||
#include "DNA_camera_types.h"
 | 
			
		||||
#include "DNA_curve_types.h"
 | 
			
		||||
#include "DNA_image_types.h"
 | 
			
		||||
#include "DNA_hair_types.h"
 | 
			
		||||
#include "DNA_key_types.h"
 | 
			
		||||
#include "DNA_lattice_types.h"
 | 
			
		||||
#include "DNA_light_types.h"
 | 
			
		||||
@@ -68,10 +69,12 @@
 | 
			
		||||
#include "DNA_mesh_types.h"
 | 
			
		||||
#include "DNA_meta_types.h"
 | 
			
		||||
#include "DNA_object_types.h"
 | 
			
		||||
#include "DNA_pointcloud_types.h"
 | 
			
		||||
#include "DNA_scene_types.h"
 | 
			
		||||
#include "DNA_space_types.h"
 | 
			
		||||
#include "DNA_speaker_types.h"
 | 
			
		||||
#include "DNA_texture_types.h"
 | 
			
		||||
#include "DNA_volume_types.h"
 | 
			
		||||
#include "DNA_world_types.h"
 | 
			
		||||
 | 
			
		||||
#include "DNA_brush_defaults.h"
 | 
			
		||||
@@ -79,6 +82,7 @@
 | 
			
		||||
#include "DNA_camera_defaults.h"
 | 
			
		||||
#include "DNA_curve_defaults.h"
 | 
			
		||||
#include "DNA_image_defaults.h"
 | 
			
		||||
#include "DNA_hair_defaults.h"
 | 
			
		||||
#include "DNA_lattice_defaults.h"
 | 
			
		||||
#include "DNA_light_defaults.h"
 | 
			
		||||
#include "DNA_lightprobe_defaults.h"
 | 
			
		||||
@@ -87,9 +91,11 @@
 | 
			
		||||
#include "DNA_mesh_defaults.h"
 | 
			
		||||
#include "DNA_meta_defaults.h"
 | 
			
		||||
#include "DNA_object_defaults.h"
 | 
			
		||||
#include "DNA_pointcloud_defaults.h"
 | 
			
		||||
#include "DNA_scene_defaults.h"
 | 
			
		||||
#include "DNA_speaker_defaults.h"
 | 
			
		||||
#include "DNA_texture_defaults.h"
 | 
			
		||||
#include "DNA_volume_defaults.h"
 | 
			
		||||
#include "DNA_world_defaults.h"
 | 
			
		||||
 | 
			
		||||
#define SDNA_DEFAULT_DECL_STRUCT(struct_name) \
 | 
			
		||||
@@ -110,6 +116,9 @@ SDNA_DEFAULT_DECL_STRUCT(Curve);
 | 
			
		||||
/* DNA_image_defaults.h */
 | 
			
		||||
SDNA_DEFAULT_DECL_STRUCT(Image);
 | 
			
		||||
 | 
			
		||||
/* DNA_hair_defaults.h */
 | 
			
		||||
SDNA_DEFAULT_DECL_STRUCT(Hair);
 | 
			
		||||
 | 
			
		||||
/* DNA_lattice_defaults.h */
 | 
			
		||||
SDNA_DEFAULT_DECL_STRUCT(Lattice);
 | 
			
		||||
 | 
			
		||||
@@ -134,6 +143,9 @@ SDNA_DEFAULT_DECL_STRUCT(MetaBall);
 | 
			
		||||
/* DNA_object_defaults.h */
 | 
			
		||||
SDNA_DEFAULT_DECL_STRUCT(Object);
 | 
			
		||||
 | 
			
		||||
/* DNA_pointcloud_defaults.h */
 | 
			
		||||
SDNA_DEFAULT_DECL_STRUCT(PointCloud);
 | 
			
		||||
 | 
			
		||||
/* DNA_scene_defaults.h */
 | 
			
		||||
SDNA_DEFAULT_DECL_STRUCT(Scene);
 | 
			
		||||
SDNA_DEFAULT_DECL_STRUCT(ToolSettings);
 | 
			
		||||
@@ -147,6 +159,9 @@ SDNA_DEFAULT_DECL_STRUCT(Tex);
 | 
			
		||||
/* DNA_view3d_defaults.h */
 | 
			
		||||
SDNA_DEFAULT_DECL_STRUCT(View3D);
 | 
			
		||||
 | 
			
		||||
/* DNA_volume_defaults.h */
 | 
			
		||||
SDNA_DEFAULT_DECL_STRUCT(Volume);
 | 
			
		||||
 | 
			
		||||
/* DNA_world_defaults.h */
 | 
			
		||||
SDNA_DEFAULT_DECL_STRUCT(World);
 | 
			
		||||
 | 
			
		||||
@@ -194,6 +209,9 @@ const void *DNA_default_table[SDNA_TYPE_MAX] = {
 | 
			
		||||
    /* DNA_image_defaults.h */
 | 
			
		||||
    SDNA_DEFAULT_DECL(Image),
 | 
			
		||||
 | 
			
		||||
    /* DNA_hair_defaults.h */
 | 
			
		||||
    SDNA_DEFAULT_DECL(Hair),
 | 
			
		||||
 | 
			
		||||
    /* DNA_lattice_defaults.h */
 | 
			
		||||
    SDNA_DEFAULT_DECL(Lattice),
 | 
			
		||||
 | 
			
		||||
@@ -218,6 +236,9 @@ const void *DNA_default_table[SDNA_TYPE_MAX] = {
 | 
			
		||||
    /* DNA_object_defaults.h */
 | 
			
		||||
    SDNA_DEFAULT_DECL(Object),
 | 
			
		||||
 | 
			
		||||
    /* DNA_pointcloud_defaults.h */
 | 
			
		||||
    SDNA_DEFAULT_DECL(PointCloud),
 | 
			
		||||
 | 
			
		||||
    /* DNA_scene_defaults.h */
 | 
			
		||||
    SDNA_DEFAULT_DECL(Scene),
 | 
			
		||||
    SDNA_DEFAULT_DECL_EX(RenderData, Scene.r),
 | 
			
		||||
@@ -259,6 +280,9 @@ const void *DNA_default_table[SDNA_TYPE_MAX] = {
 | 
			
		||||
    SDNA_DEFAULT_DECL_EX(View3DShading, View3D.shading),
 | 
			
		||||
    SDNA_DEFAULT_DECL_EX(View3DCursor, Scene.cursor),
 | 
			
		||||
 | 
			
		||||
    /* DNA_volume_defaults.h */
 | 
			
		||||
    SDNA_DEFAULT_DECL(Volume),
 | 
			
		||||
 | 
			
		||||
    /* DNA_world_defaults.h */
 | 
			
		||||
    SDNA_DEFAULT_DECL(World),
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user