2025-07-01

This commit is contained in:
2026-03-17 14:30:01 -06:00
parent f9a22056dd
commit 62b5978595
4579 changed files with 1257472 additions and 0 deletions
@@ -0,0 +1,45 @@
"""
Copyright (C) 2019 Remington Creative
This file is part of Atomic Data Manager.
Atomic Data Manager 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 3 of the
License, or (at your option) any later version.
Atomic Data Manager 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 Atomic Data Manager. If not, see <https://www.gnu.org/licenses/>.
---
This file handles the registration of the atomic_data_manager.ops package
"""
from atomic_data_manager.ops import main_ops
from atomic_data_manager.ops import inspect_ops
from atomic_data_manager.ops import direct_use_ops
from atomic_data_manager.ops import missing_file_ops
from atomic_data_manager.ops import support_me_ops
def register():
main_ops.register()
inspect_ops.register()
direct_use_ops.register()
missing_file_ops.register()
support_me_ops.register()
def unregister():
main_ops.unregister()
inspect_ops.unregister()
direct_use_ops.unregister()
missing_file_ops.unregister()
support_me_ops.unregister()
@@ -0,0 +1,793 @@
"""
Copyright (C) 2019 Remington Creative
This file is part of Atomic Data Manager.
Atomic Data Manager 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 3 of the
License, or (at your option) any later version.
Atomic Data Manager 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 Atomic Data Manager. If not, see <https://www.gnu.org/licenses/>.
---
This file contains the direct use operators, intended to be used with
Atomic's pie menu interface. However, they can be implemented anywhere
if they need to be.
These operators basically wrap the functions from ops.utils.nuke.py and
ops.utils.clean.py into operators so they can be easily called by other
intefaces in Blender.
"""
import bpy
from bpy.utils import register_class
from bpy.utils import unregister_class
from atomic_data_manager import config
from atomic_data_manager.stats import unused
from atomic_data_manager.ops.utils import nuke
from atomic_data_manager.ops.utils import clean
from atomic_data_manager.ui.utils import ui_layouts
class ATOMIC_OT_invoke_pie_menu_ui(bpy.types.Operator):
"""Invokes Atomic's pie menu UI if the \"Enable Pie Menu UI\"
preference is enabled in Atomic's preferences panel"""
bl_idname = "atomic.invoke_pie_menu_ui"
bl_label = "Invoke Pie Menu UI"
def execute(self, context):
if config.enable_pie_menu_ui:
bpy.ops.wm.call_menu_pie(name="ATOMIC_MT_main_pie")
return {'FINISHED'}
# Atomic Data Manager Nuke All Operator
class ATOMIC_OT_nuke_all(bpy.types.Operator):
"""Remove all data-blocks from the selected categories"""
bl_idname = "atomic.nuke_all"
bl_label = "CAUTION!"
def draw(self, context):
layout = self.layout
col = layout.column()
col.label(text="Remove the following data-blocks?")
collections = sorted(bpy.data.collections.keys())
ui_layouts.box_list(
layout=layout,
title="Collections",
items=collections,
icon="OUTLINER_OB_GROUP_INSTANCE"
)
images = sorted(bpy.data.images.keys())
ui_layouts.box_list(
layout=layout,
title="Images",
items=images,
icon="IMAGE_DATA"
)
lights = sorted(bpy.data.lights.keys())
ui_layouts.box_list(
layout=layout,
title="Lights",
items=lights,
icon="OUTLINER_OB_LIGHT"
)
materials = sorted(bpy.data.materials.keys())
ui_layouts.box_list(
layout=layout,
title="Materials",
items=materials,
icon="MATERIAL"
)
node_groups = sorted(bpy.data.node_groups.keys())
ui_layouts.box_list(
layout=layout,
title="Node Groups",
items=node_groups,
icon="NODETREE"
)
particles = sorted(bpy.data.particles.keys())
ui_layouts.box_list(
layout=layout,
title="Particle Systems",
items=particles,
icon="PARTICLES"
)
textures = sorted(bpy.data.textures.keys())
ui_layouts.box_list(
layout=layout,
title="Textures",
items=textures,
icon="TEXTURE"
)
worlds = sorted(bpy.data.worlds.keys())
ui_layouts.box_list(
layout=layout,
title="Worlds",
items=worlds,
icon="WORLD"
)
row = layout.row() # extra spacing
def execute(self, context):
nuke.collections()
nuke.images()
nuke.lights()
nuke.materials()
nuke.node_groups()
nuke.particles()
nuke.textures()
nuke.worlds()
return {'FINISHED'}
def invoke(self, context, event):
wm = context.window_manager
return wm.invoke_props_dialog(self)
# Atomic Data Manager Clean All Operator
class ATOMIC_OT_clean_all(bpy.types.Operator):
"""Remove all unused data-blocks from the selected categories"""
bl_idname = "atomic.clean_all"
bl_label = "Clean All"
unused_collections = []
unused_images = []
unused_lights = []
unused_materials = []
unused_node_groups = []
unused_particles = []
unused_textures = []
unused_worlds = []
def draw(self, context):
layout = self.layout
col = layout.column()
col.label(text="Remove the following data-blocks?")
collections = sorted(unused.collections_deep())
ui_layouts.box_list(
layout=layout,
title="Collections",
items=collections,
icon="OUTLINER_OB_GROUP_INSTANCE"
)
images = sorted(unused.images_deep())
ui_layouts.box_list(
layout=layout,
title="Images",
items=images,
icon="IMAGE_DATA"
)
lights = sorted(unused.lights_deep())
ui_layouts.box_list(
layout=layout,
title="Lights",
items=lights,
icon="OUTLINER_OB_LIGHT"
)
materials = sorted(unused.materials_deep())
ui_layouts.box_list(
layout=layout,
title="Materials",
items=materials,
icon="MATERIAL"
)
node_groups = sorted(unused.node_groups_deep())
ui_layouts.box_list(
layout=layout,
title="Node Groups",
items=node_groups,
icon="NODETREE"
)
particles = sorted(unused.particles_deep())
ui_layouts.box_list(
layout=layout,
title="Particle Systems",
items=particles,
icon="PARTICLES"
)
textures = sorted(unused.textures_deep())
ui_layouts.box_list(
layout=layout,
title="Textures",
items=textures,
icon="TEXTURE"
)
worlds = sorted(unused.worlds())
ui_layouts.box_list(
layout=layout,
title="Worlds",
items=worlds,
icon="WORLD"
)
row = layout.row() # extra spacing
def execute(self, context):
clean.collections()
clean.images()
clean.lights()
clean.materials()
clean.node_groups()
clean.particles()
clean.textures()
clean.worlds()
return {'FINISHED'}
def invoke(self, context, event):
wm = context.window_manager
self.unused_collections = unused.collections_deep()
self.unused_images = unused.images_deep()
self.unused_lights = unused.lights_deep()
self.unused_materials = unused.materials_deep()
self.unused_node_groups = unused.node_groups_deep()
self.unused_particles = unused.particles_deep()
self.unused_textures = unused.textures_deep()
self.unused_worlds = unused.worlds()
return wm.invoke_props_dialog(self)
# Atomic Data Manager Nuke Collections Operator
class ATOMIC_OT_nuke_collections(bpy.types.Operator):
"""Remove all collections from this project"""
bl_idname = "atomic.nuke_collections"
bl_label = "Nuke Collections"
def draw(self, context):
layout = self.layout
row = layout.row()
row.label(text="Remove the following data-blocks?")
collections = bpy.data.collections.keys()
ui_layouts.box_list(
layout=layout,
items=collections,
icon="OUTLINER_OB_GROUP_INSTANCE"
)
row = layout.row() # extra space
def execute(self, context):
nuke.collections()
return {'FINISHED'}
def invoke(self, context, event):
wm = context.window_manager
return wm.invoke_props_dialog(self)
# Atomic Data Manager Nuke Images Operator
class ATOMIC_OT_nuke_images(bpy.types.Operator):
"""Remove all images from this project"""
bl_idname = "atomic.nuke_images"
bl_label = "Nuke Images"
def draw(self, context):
layout = self.layout
row = layout.row()
row.label(text="Remove the following data-blocks?")
images = bpy.data.images.keys()
ui_layouts.box_list(
layout=layout,
items=images,
icon="IMAGE_DATA"
)
row = layout.row() # extra space
def execute(self, context):
nuke.images()
return {'FINISHED'}
def invoke(self, context, event):
wm = context.window_manager
return wm.invoke_props_dialog(self)
# Atomic Data Manager Nuke Lights Operator
class ATOMIC_OT_nuke_lights(bpy.types.Operator):
"""Remove all lights from this project"""
bl_idname = "atomic.nuke_lights"
bl_label = "Nuke Lights"
def draw(self, context):
layout = self.layout
row = layout.row()
row.label(text="Remove the following data-blocks?")
lights = bpy.data.lights.keys()
ui_layouts.box_list(
layout=layout,
items=lights,
icon="OUTLINER_OB_LIGHT"
)
row = layout.row() # extra space
def execute(self, context):
nuke.lights()
return {'FINISHED'}
def invoke(self, context, event):
wm = context.window_manager
return wm.invoke_props_dialog(self)
# Atomic Data Manager Nuke Materials Operator
class ATOMIC_OT_nuke_materials(bpy.types.Operator):
"""Remove all materials from this project"""
bl_idname = "atomic.nuke_materials"
bl_label = "Nuke Materials"
def draw(self, context):
layout = self.layout
row = layout.row()
row.label(text="Remove the following data-blocks?")
materials = bpy.data.materials.keys()
ui_layouts.box_list(
layout=layout,
items=materials,
icon="MATERIAL"
)
row = layout.row() # extra space
def execute(self, context):
nuke.materials()
return {'FINISHED'}
def invoke(self, context, event):
wm = context.window_manager
return wm.invoke_props_dialog(self)
# Atomic Data Manager Nuke Node Groups Operator
class ATOMIC_OT_nuke_node_groups(bpy.types.Operator):
"""Remove all node groups from this project"""
bl_idname = "atomic.nuke_node_groups"
bl_label = "Nuke Node Groups"
def draw(self, context):
layout = self.layout
row = layout.row()
row.label(text="Remove the following data-blocks?")
node_groups = bpy.data.node_groups.keys()
ui_layouts.box_list(
layout=layout,
items=node_groups,
icon="NODETREE"
)
row = layout.row() # extra space
def execute(self, context):
nuke.node_groups()
return {'FINISHED'}
def invoke(self, context, event):
wm = context.window_manager
return wm.invoke_props_dialog(self)
# Atomic Data Manager Nuke Particles Operator
class ATOMIC_OT_nuke_particles(bpy.types.Operator):
"""Remove all particle systems from this project"""
bl_idname = "atomic.nuke_particles"
bl_label = "Nuke Particles"
def draw(self, context):
layout = self.layout
row = layout.row()
row.label(text="Remove the following data-blocks?")
particles = bpy.data.particles.keys()
ui_layouts.box_list(
layout=layout,
items=particles,
icon="PARTICLES"
)
row = layout.row() # extra space
def execute(self, context):
nuke.particles()
return {'FINISHED'}
def invoke(self, context, event):
wm = context.window_manager
return wm.invoke_props_dialog(self)
# Atomic Data Manager Nuke Textures Operator
class ATOMIC_OT_nuke_textures(bpy.types.Operator):
"""Remove all textures from this project"""
bl_idname = "atomic.nuke_textures"
bl_label = "Nuke Textures"
def draw(self, context):
layout = self.layout
row = layout.row()
row.label(text="Remove the following data-blocks?")
textures = bpy.data.textures.keys()
ui_layouts.box_list(
layout=layout,
items=textures,
icon="TEXTURE"
)
row = layout.row() # extra space
def execute(self, context):
nuke.textures()
return {'FINISHED'}
def invoke(self, context, event):
wm = context.window_manager
return wm.invoke_props_dialog(self)
# Atomic Data Manager Nuke Worlds Operator
class ATOMIC_OT_nuke_worlds(bpy.types.Operator):
"""Remove all worlds from this project"""
bl_idname = "atomic.nuke_worlds"
bl_label = "Nuke Worlds"
def draw(self, context):
layout = self.layout
row = layout.row()
row.label(text="Remove the following data-blocks?")
worlds = bpy.data.worlds.keys()
ui_layouts.box_list(
layout=layout,
items=worlds,
icon="WORLD"
)
row = layout.row() # extra space
def execute(self, context):
nuke.worlds()
return {'FINISHED'}
def invoke(self, context, event):
wm = context.window_manager
return wm.invoke_props_dialog(self)
# Atomic Data Manager Clean Collections Operator
class ATOMIC_OT_clean_collections(bpy.types.Operator):
"""Remove all unused collections from this project"""
bl_idname = "atomic.clean_collections"
bl_label = "Clean Collections"
unused_collections = []
def draw(self, context):
layout = self.layout
row = layout.row()
row.label(text="Remove the following data-blocks?")
ui_layouts.box_list(
layout=layout,
items=self.unused_collections,
icon="OUTLINER_OB_GROUP_INSTANCE"
)
row = layout.row() # extra space
def execute(self, context):
clean.collections()
return {'FINISHED'}
def invoke(self, context, event):
wm = context.window_manager
self.unused_collections = unused.collections_deep()
return wm.invoke_props_dialog(self)
# Atomic Data Manager Clean Images Operator
class ATOMIC_OT_clean_images(bpy.types.Operator):
"""Remove all unused images from this project"""
bl_idname = "atomic.clean_images"
bl_label = "Clean Images"
unused_images = []
def draw(self, context):
layout = self.layout
row = layout.row()
row.label(text="Remove the following data-blocks?")
ui_layouts.box_list(
layout=layout,
items=self.unused_images,
icon="IMAGE_DATA"
)
row = layout.row() # extra space
def execute(self, context):
clean.images()
return {'FINISHED'}
def invoke(self, context, event):
wm = context.window_manager
self.unused_images =unused.images_deep()
return wm.invoke_props_dialog(self)
# Atomic Data Manager Clean Lights Operator
class ATOMIC_OT_clean_lights(bpy.types.Operator):
"""Remove all unused lights from this project"""
bl_idname = "atomic.clean_lights"
bl_label = "Clean Lights"
unused_lights = []
def draw(self, context):
layout = self.layout
row = layout.row()
row.label(text="Remove the following data-blocks?")
ui_layouts.box_list(
layout=layout,
items=self.unused_lights,
icon="OUTLINER_OB_LIGHT"
)
row = layout.row() # extra space
def execute(self, context):
clean.lights()
return {'FINISHED'}
def invoke(self, context, event):
wm = context.window_manager
self.unused_lights = unused.lights_deep()
return wm.invoke_props_dialog(self)
# Atomic Data Manager Clean Materials Operator
class ATOMIC_OT_clean_materials(bpy.types.Operator):
"""Remove all unused materials from this project"""
bl_idname = "atomic.clean_materials"
bl_label = "Clean Materials"
unused_materials = []
def draw(self, context):
layout = self.layout
row = layout.row()
row.label(text="Remove the following data-blocks?")
ui_layouts.box_list(
layout=layout,
items=self.unused_materials,
icon="MATERIAL"
)
row = layout.row() # extra space
def execute(self, context):
clean.materials()
return {'FINISHED'}
def invoke(self, context, event):
wm = context.window_manager
self.unused_materials = unused.materials_deep()
return wm.invoke_props_dialog(self)
# Atomic Data Manager Clean Node Groups Operator
class ATOMIC_OT_clean_node_groups(bpy.types.Operator):
"""Remove all unused node groups from this project"""
bl_idname = "atomic.clean_node_groups"
bl_label = "Clean Node Groups"
unused_node_groups = []
def draw(self, context):
layout = self.layout
row = layout.row()
row.label(text="Remove the following data-blocks?")
ui_layouts.box_list(
layout=layout,
items=self.unused_node_groups,
icon="NODETREE"
)
row = layout.row() # extra space
def execute(self, context):
clean.node_groups()
return {'FINISHED'}
def invoke(self, context, event):
wm = context.window_manager
self.unused_node_groups = unused.node_groups_deep()
return wm.invoke_props_dialog(self)
# Atomic Data Manager Clean Particles Operator
class ATOMIC_OT_clean_particles(bpy.types.Operator):
"""Remove all unused particle systems from this project"""
bl_idname = "atomic.clean_particles"
bl_label = "Clean Particles"
unused_particles = []
def draw(self, context):
layout = self.layout
row = layout.row()
row.label(text="Remove the following data-blocks?")
ui_layouts.box_list(
layout=layout,
items=self.unused_particles,
icon="PARTICLES"
)
row = layout.row() # extra space
def execute(self, context):
clean.particles()
return {'FINISHED'}
def invoke(self, context, event):
wm = context.window_manager
self.unused_particles = unused.particles_deep()
return wm.invoke_props_dialog(self)
# Atomic Data Manager Clean Textures Operator
class ATOMIC_OT_clean_textures(bpy.types.Operator):
"""Remove all unused textures from this project"""
bl_idname = "atomic.clean_textures"
bl_label = "Clean Textures"
unused_textures = []
def draw(self, context):
layout = self.layout
row = layout.row()
row.label(text="Remove the following data-blocks?")
ui_layouts.box_list(
layout=layout,
items=self.unused_textures,
icon="TEXTURE"
)
row = layout.row() # extra space
def execute(self, context):
clean.textures()
return {'FINISHED'}
def invoke(self, context, event):
wm = context.window_manager
self.unused_textures = unused.textures_deep()
return wm.invoke_props_dialog(self)
# Atomic Data Manager Clean Worlds Operator
class ATOMIC_OT_clean_worlds(bpy.types.Operator):
"""Remove all unused worlds from this project"""
bl_idname = "atomic.clean_worlds"
bl_label = "Clean Worlds"
unused_worlds = []
def draw(self, context):
layout = self.layout
row = layout.row()
row.label(text="Remove the following data-blocks?")
ui_layouts.box_list(
layout=layout,
items=self.unused_worlds,
icon="WORLD"
)
row = layout.row() # extra space
def execute(self, context):
clean.worlds()
return {'FINISHED'}
def invoke(self, context, event):
wm = context.window_manager
self.unused_worlds = unused.worlds()
return wm.invoke_props_dialog(self)
reg_list = [
ATOMIC_OT_invoke_pie_menu_ui,
ATOMIC_OT_nuke_all,
ATOMIC_OT_clean_all,
ATOMIC_OT_nuke_collections,
ATOMIC_OT_nuke_images,
ATOMIC_OT_nuke_lights,
ATOMIC_OT_nuke_materials,
ATOMIC_OT_nuke_node_groups,
ATOMIC_OT_nuke_particles,
ATOMIC_OT_nuke_textures,
ATOMIC_OT_nuke_worlds,
ATOMIC_OT_clean_collections,
ATOMIC_OT_clean_images,
ATOMIC_OT_clean_lights,
ATOMIC_OT_clean_materials,
ATOMIC_OT_clean_node_groups,
ATOMIC_OT_clean_particles,
ATOMIC_OT_clean_textures,
ATOMIC_OT_clean_worlds
]
def register():
for item in reg_list:
register_class(item)
def unregister():
for item in reg_list:
unregister_class(item)
@@ -0,0 +1,440 @@
"""
Copyright (C) 2019 Remington Creative
This file is part of Atomic Data Manager.
Atomic Data Manager 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 3 of the
License, or (at your option) any later version.
Atomic Data Manager 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 Atomic Data Manager. If not, see <https://www.gnu.org/licenses/>.
---
This file contains the operators used in the inspection UI's header.
This includes the rename, replace, toggle fake user, delete, and duplicate
operators.
"""
import bpy
from bpy.utils import register_class
from bpy.utils import unregister_class
from atomic_data_manager.ops.utils import delete
from atomic_data_manager.ops.utils import duplicate
# Atomic Data Manager Inspection Rename Operator
class ATOMIC_OT_inspection_rename(bpy.types.Operator):
"""Give this data-block a new name"""
bl_idname = "atomic.rename"
bl_label = "Rename Data-Block"
def draw(self, context):
atom = bpy.context.scene.atomic
layout = self.layout
row = layout.row()
row.prop(atom, "rename_field", text="", icon="GREASEPENCIL")
def execute(self, context):
atom = bpy.context.scene.atomic
inspection = atom.active_inspection
name = atom.rename_field
if inspection == 'COLLECTIONS':
bpy.data.collections[atom.collections_field].name = name
atom.collections_field = name
if inspection == 'IMAGES':
bpy.data.images[atom.images_field].name = name
atom.images_field = name
if inspection == 'LIGHTS':
bpy.data.lights[atom.lights_field].name = name
atom.lights_field = name
if inspection == 'MATERIALS':
bpy.data.materials[atom.materials_field].name = name
atom.materials_field = name
if inspection == 'NODE_GROUPS':
bpy.data.node_groups[atom.node_groups_field].name = name
atom.node_groups_field = name
if inspection == 'PARTICLES':
bpy.data.particles[atom.particles_field].name = name
atom.particles_field = name
if inspection == 'TEXTURES':
bpy.data.textures[atom.textures_field].name = name
atom.textures_field = name
if inspection == 'WORLDS':
bpy.data.worlds[atom.worlds_field].name = name
atom.worlds_field = name
atom.rename_field = ""
return {'FINISHED'}
def invoke(self, context, event):
wm = context.window_manager
return wm.invoke_props_dialog(self, width=200)
# Atomic Data Manager Inspection Replaces Operator
class ATOMIC_OT_inspection_replace(bpy.types.Operator):
"""Replace all instances of this data-block with another data-block"""
bl_idname = "atomic.replace"
bl_label = "Replace Data-Block"
def draw(self, context):
atom = bpy.context.scene.atomic
inspection = atom.active_inspection
layout = self.layout
row = layout.row()
if inspection == 'IMAGES':
row.prop_search(
atom,
"replace_field",
bpy.data,
"images",
text=""
)
if inspection == 'LIGHTS':
row.prop_search(
atom,
"replace_field",
bpy.data,
"lights",
text=""
)
if inspection == 'MATERIALS':
row.prop_search(
atom,
"replace_field",
bpy.data,
"materials",
text=""
)
if inspection == 'NODE_GROUPS':
row.prop_search(
atom,
"replace_field",
bpy.data,
"node_groups",
text=""
)
if inspection == 'PARTICLES':
row.prop_search(
atom,
"replace_field",
bpy.data,
"particles",
text=""
)
if inspection == 'TEXTURES':
row.prop_search(
atom,
"replace_field",
bpy.data,
"textures",
text=""
)
if inspection == 'WORLDS':
row.prop_search(
atom,
"replace_field",
bpy.data,
"worlds",
text=""
)
def execute(self, context):
atom = bpy.context.scene.atomic
inspection = atom.active_inspection
if inspection == 'IMAGES' and \
atom.replace_field in bpy.data.images.keys():
bpy.data.images[atom.images_field].user_remap(
bpy.data.images[atom.replace_field])
atom.images_field = atom.replace_field
if inspection == 'LIGHTS' and \
atom.replace_field in bpy.data.lights.keys():
bpy.data.lights[atom.lights_field].user_remap(
bpy.data.lights[atom.replace_field])
atom.lights_field = atom.replace_field
if inspection == 'MATERIALS' and \
atom.replace_field in bpy.data.materials.keys():
bpy.data.materials[atom.materials_field].user_remap(
bpy.data.materials[atom.replace_field])
atom.materials_field = atom.replace_field
if inspection == 'NODE_GROUPS' and \
atom.replace_field in bpy.data.node_groups.keys():
bpy.data.node_groups[atom.node_groups_field].user_remap(
bpy.data.node_groups[atom.replace_field])
atom.node_groups_field = atom.replace_field
if inspection == 'PARTICLES' and \
atom.replace_field in bpy.data.particles.keys():
bpy.data.particles[atom.particles_field].user_remap(
bpy.data.particles[atom.replace_field])
atom.particles_field = atom.replace_field
if inspection == 'TEXTURES' and \
atom.replace_field in bpy.data.textures.keys():
bpy.data.textures[atom.textures_field].user_remap(
bpy.data.textures[atom.replace_field])
atom.textures_field = atom.replace_field
if inspection == 'WORLDS' and \
atom.replace_field in bpy.data.worlds.keys():
bpy.data.worlds[atom.worlds_field].user_remap(
bpy.data.worlds[atom.replace_field])
atom.worlds_field = atom.replace_field
atom.replace_field = ""
return {'FINISHED'}
def invoke(self, context, event):
wm = context.window_manager
return wm.invoke_props_dialog(self, width=200)
# Atomic Data Manager Inspection Toggle Fake User Operator
class ATOMIC_OT_inspection_toggle_fake_user(bpy.types.Operator):
"""Save this data-block even if it has no users"""
bl_idname = "atomic.toggle_fake_user"
bl_label = "Toggle Fake User"
def execute(self, context):
atom = bpy.context.scene.atomic
inspection = atom.active_inspection
if inspection == 'IMAGES':
image = bpy.data.images[atom.images_field]
bpy.data.images[atom.images_field].use_fake_user = \
not image.use_fake_user
if inspection == 'LIGHTS':
light = bpy.data.lights[atom.lights_field]
bpy.data.lights[atom.lights_field].use_fake_user = \
not light.use_fake_user
if inspection == 'MATERIALS':
material = bpy.data.materials[atom.materials_field]
bpy.data.materials[atom.materials_field].use_fake_user = \
not material.use_fake_user
if inspection == 'NODE_GROUPS':
node_group = bpy.data.node_groups[atom.node_groups_field]
bpy.data.node_groups[atom.node_groups_field].use_fake_user = \
not node_group.use_fake_user
if inspection == 'PARTICLES':
particle = bpy.data.particles[atom.particles_field]
bpy.data.particles[atom.particles_field].use_fake_user = \
not particle.use_fake_user
if inspection == 'TEXTURES':
texture = bpy.data.textures[atom.textures_field]
bpy.data.textures[atom.textures_field].use_fake_user = \
not texture.use_fake_user
if inspection == 'WORLDS':
world = bpy.data.worlds[atom.worlds_field]
bpy.data.worlds[atom.worlds_field].use_fake_user = \
not world.use_fake_user
return {'FINISHED'}
# Atomic Data Manager Inspection Duplicate Operator
class ATOMIC_OT_inspection_duplicate(bpy.types.Operator):
"""Make an exact copy of this data-block"""
bl_idname = "atomic.inspection_duplicate"
bl_label = "Duplicate Data-Block"
def execute(self, context):
atom = bpy.context.scene.atomic
inspection = atom.active_inspection
if inspection == 'COLLECTIONS':
key = atom.collections_field
collections = bpy.data.collections
if key in collections.keys():
copy_key = duplicate.collection(key)
atom.collections_field = copy_key
elif inspection == 'IMAGES':
key = atom.images_field
images = bpy.data.images
if key in images.keys():
copy_key = duplicate.image(key)
atom.images_field = copy_key
elif inspection == 'LIGHTS':
key = atom.lights_field
lights = bpy.data.lights
if key in lights.keys():
copy_key = duplicate.light(key)
atom.lights_field = copy_key
elif inspection == 'MATERIALS':
key = atom.materials_field
materials = bpy.data.materials
if key in materials.keys():
copy_key = duplicate.material(key)
atom.materials_field = copy_key
elif inspection == 'NODE_GROUPS':
key = atom.node_groups_field
node_groups = bpy.data.node_groups
if key in node_groups.keys():
copy_key = duplicate.node_group(key)
atom.node_groups_field = copy_key
elif inspection == 'PARTICLES':
key = atom.particles_field
particles = bpy.data.particles
if key in particles.keys():
copy_key = duplicate.particle(key)
atom.particles_field = copy_key
elif inspection == 'TEXTURES':
key = atom.textures_field
textures = bpy.data.textures
if key in textures.keys():
copy_key = duplicate.texture(key)
atom.textures_field = copy_key
elif inspection == 'WORLDS':
key = atom.worlds_field
worlds = bpy.data.worlds
if key in worlds.keys():
copy_key = duplicate.world(key)
atom.worlds_field = copy_key
return {'FINISHED'}
# Atomic Data Manager Inspection Delete Operator
class ATOMIC_OT_inspection_delete(bpy.types.Operator):
"""Forcibly remove this data-block from the project"""
bl_idname = "atomic.inspection_delete"
bl_label = "Delete Data-Block"
def execute(self, context):
atom = bpy.context.scene.atomic
inspection = atom.active_inspection
if inspection == 'COLLECTIONS':
key = atom.collections_field
collections = bpy.data.collections
if key in collections.keys():
delete.collection(key)
atom.collections_field = ""
elif inspection == 'IMAGES':
key = atom.images_field
images = bpy.data.images
if key in images.keys():
delete.image(key)
atom.images_field = ""
elif inspection == 'LIGHTS':
key = atom.lights_field
lights = bpy.data.lights
if key in lights.keys():
delete.light(key)
atom.lights_field = ""
elif inspection == 'MATERIALS':
key = atom.materials_field
materials = bpy.data.materials
if key in materials.keys():
delete.material(key)
atom.materials_field = ""
elif inspection == 'NODE_GROUPS':
key = atom.node_groups_field
node_groups = bpy.data.node_groups
if key in node_groups.keys():
delete.node_group(key)
atom.node_groups_field = ""
elif inspection == 'PARTICLES':
key = atom.particles_field
particles = bpy.data.particles
if key in particles.keys():
delete.particle(key)
atom.particles_field = ""
elif inspection == 'TEXTURES':
key = atom.textures_field
textures = bpy.data.textures
if key in textures.keys():
delete.texture(key)
atom.textures_field = ""
elif inspection == 'WORLDS':
key = atom.worlds_field
worlds = bpy.data.worlds
if key in worlds.keys():
delete.world(key)
atom.worlds_field = ""
return {'FINISHED'}
reg_list = [
ATOMIC_OT_inspection_rename,
ATOMIC_OT_inspection_replace,
ATOMIC_OT_inspection_toggle_fake_user,
ATOMIC_OT_inspection_duplicate,
ATOMIC_OT_inspection_delete
]
def register():
for item in reg_list:
register_class(item)
def unregister():
for item in reg_list:
unregister_class(item)
@@ -0,0 +1,444 @@
"""
Copyright (C) 2019 Remington Creative
This file is part of Atomic Data Manager.
Atomic Data Manager 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 3 of the
License, or (at your option) any later version.
Atomic Data Manager 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 Atomic Data Manager. If not, see <https://www.gnu.org/licenses/>.
---
This file contains the main operators found in the main panel of the
Atomic Data Manager interface. This includes nuke, clean, undo, and the
various selection operations.
"""
import bpy
from bpy.utils import register_class
from bpy.utils import unregister_class
from atomic_data_manager.stats import unused
from atomic_data_manager.ops.utils import clean
from atomic_data_manager.ops.utils import nuke
from atomic_data_manager.ui.utils import ui_layouts
# Atomic Data Manager Nuke Operator
class ATOMIC_OT_nuke(bpy.types.Operator):
"""Remove all data-blocks from the selected categories"""
bl_idname = "atomic.nuke"
bl_label = "CAUTION!"
def draw(self, context):
atom = bpy.context.scene.atomic
layout = self.layout
col = layout.column()
col.label(text="Remove the following data-blocks?")
# No Data Section
if not (atom.collections or atom.images or atom.lights or
atom.materials or atom.node_groups or atom.particles or
atom.textures or atom.worlds):
ui_layouts.box_list(
layout=layout,
)
# display when the main panel collections property is toggled
if atom.collections:
collections = sorted(bpy.data.collections.keys())
ui_layouts.box_list(
layout=layout,
title="Collections",
items=collections,
icon="OUTLINER_OB_GROUP_INSTANCE"
)
# display when the main panel images property is toggled
if atom.images:
images = sorted(bpy.data.images.keys())
ui_layouts.box_list(
layout=layout,
title="Images",
items=images,
icon="IMAGE_DATA"
)
# display when the main panel lights property is toggled
if atom.lights:
lights = sorted(bpy.data.lights.keys())
ui_layouts.box_list(
layout=layout,
title="Lights",
items=lights,
icon="OUTLINER_OB_LIGHT"
)
# display when the main panel materials property is toggled
if atom.materials:
materials = sorted(bpy.data.materials.keys())
ui_layouts.box_list(
layout=layout,
title="Materials",
items=materials,
icon="MATERIAL"
)
# display when the main panel node groups property is toggled
if atom.node_groups:
node_groups = sorted(bpy.data.node_groups.keys())
ui_layouts.box_list(
layout=layout,
title="Node Groups",
items=node_groups,
icon="NODETREE"
)
# display when the main panel particle systems property is toggled
if atom.particles:
particles = sorted(bpy.data.particles.keys())
ui_layouts.box_list(
layout=layout,
title="Particle Systems",
items=particles,
icon="PARTICLES"
)
# display when the main panel textures property is toggled
if atom.textures:
textures = sorted(bpy.data.textures.keys())
ui_layouts.box_list(
layout=layout,
title="Textures",
items=textures,
icon="TEXTURE"
)
# display when the main panel worlds property is toggled
if atom.worlds:
worlds = sorted(bpy.data.worlds.keys())
ui_layouts.box_list(
layout=layout,
title="Worlds",
items=worlds,
icon="WORLD"
)
row = layout.row() # extra spacing
def execute(self, context):
atom = bpy.context.scene.atomic
if atom.collections:
nuke.collections()
if atom.images:
nuke.images()
if atom.lights:
nuke.lights()
if atom.materials:
nuke.materials()
if atom.node_groups:
nuke.node_groups()
if atom.particles:
nuke.particles()
if atom.textures:
nuke.textures()
if atom.worlds:
nuke.worlds()
bpy.ops.atomic.deselect_all()
return {'FINISHED'}
def invoke(self, context, event):
wm = context.window_manager
return wm.invoke_props_dialog(self)
# Atomic Data Manager Clean Operator
class ATOMIC_OT_clean(bpy.types.Operator):
"""Remove all unused data-blocks from the selected categories"""
bl_idname = "atomic.clean"
bl_label = "Clean"
unused_collections = []
unused_images = []
unused_lights = []
unused_materials = []
unused_node_groups = []
unused_particles = []
unused_textures = []
unused_worlds = []
def draw(self, context):
atom = bpy.context.scene.atomic
layout = self.layout
col = layout.column()
col.label(text="Remove the following data-blocks?")
# display if no main panel properties are toggled
if not (atom.collections or atom.images or atom.lights or
atom.materials or atom.node_groups or atom.particles
or atom.textures or atom.worlds):
ui_layouts.box_list(
layout=layout,
)
# display when the main panel collections property is toggled
if atom.collections:
ui_layouts.box_list(
layout=layout,
title="Collections",
items=self.unused_collections,
icon="OUTLINER_OB_GROUP_INSTANCE"
)
# display when the main panel images property is toggled
if atom.images:
ui_layouts.box_list(
layout=layout,
title="Images",
items=self.unused_images,
icon="IMAGE_DATA"
)
# display when the main panel lights property is toggled
if atom.lights:
ui_layouts.box_list(
layout=layout,
title="Lights",
items=self.unused_lights,
icon="OUTLINER_OB_LIGHT"
)
# display when the main panel materials property is toggled
if atom.materials:
ui_layouts.box_list(
layout=layout,
title="Materials",
items=self.unused_materials,
icon="MATERIAL"
)
# display when the main panel node groups property is toggled
if atom.node_groups:
ui_layouts.box_list(
layout=layout,
title="Node Groups",
items=self.unused_node_groups,
icon="NODETREE"
)
# display when the main panel particle systems property is toggled
if atom.particles:
ui_layouts.box_list(
layout=layout,
title="Particle Systems",
items=self.unused_particles,
icon="PARTICLES"
)
# display when the main panel textures property is toggled
if atom.textures:
textures = sorted(unused.textures_deep())
ui_layouts.box_list(
layout=layout,
title="Textures",
items=textures,
icon="TEXTURE"
)
# display when the main panel worlds property is toggled
if atom.worlds:
ui_layouts.box_list(
layout=layout,
title="Worlds",
items=self.unused_worlds,
icon="WORLD"
)
row = layout.row() # extra spacing
def execute(self, context):
atom = bpy.context.scene.atomic
if atom.collections:
clean.collections()
if atom.images:
clean.images()
if atom.lights:
clean.lights()
if atom.materials:
clean.materials()
if atom.node_groups:
clean.node_groups()
if atom.particles:
clean.particles()
if atom.textures:
clean.textures()
if atom.worlds:
clean.worlds()
bpy.ops.atomic.deselect_all()
return {'FINISHED'}
def invoke(self, context, event):
wm = context.window_manager
atom = bpy.context.scene.atomic
if atom.collections:
self.unused_collections = unused.collections_deep()
if atom.images:
self.unused_images = unused.images_deep()
if atom.lights:
self.unused_lights = unused.lights_deep()
if atom.materials:
self.unused_materials = unused.materials_deep()
if atom.node_groups:
self.unused_node_groups = unused.node_groups_deep()
if atom.particles:
self.unused_particles = unused.particles_deep()
if atom.textures:
self.unused_textures = unused.textures_deep()
if atom.worlds:
self.unused_worlds = unused.worlds()
return wm.invoke_props_dialog(self)
# Atomic Data Manager Undo Operator
class ATOMIC_OT_undo(bpy.types.Operator):
"""Undo the previous action"""
bl_idname = "atomic.undo"
bl_label = "Undo"
def execute(self, context):
bpy.ops.ed.undo()
return {'FINISHED'}
# Atomic Data Manager Smart Select Operator
class ATOMIC_OT_smart_select(bpy.types.Operator):
"""Auto-select categories with unused data"""
bl_idname = "atomic.smart_select"
bl_label = "Smart Select"
def execute(self, context):
bpy.context.scene.atomic.collections = \
any(unused.collections_deep())
bpy.context.scene.atomic.images = \
any(unused.images_deep())
bpy.context.scene.atomic.lights = \
any(unused.lights_deep())
bpy.context.scene.atomic.materials = \
any(unused.materials_deep())
bpy.context.scene.atomic.node_groups = \
any(unused.node_groups_deep())
bpy.context.scene.atomic.particles = \
any(unused.particles_deep())
bpy.context.scene.atomic.textures = \
any(unused.textures_deep())
bpy.context.scene.atomic.worlds = \
any(unused.worlds())
return {'FINISHED'}
# Atomic Data Manager Select All Operator
class ATOMIC_OT_select_all(bpy.types.Operator):
"""Select all categories"""
bl_idname = "atomic.select_all"
bl_label = "Select All"
def execute(self, context):
bpy.context.scene.atomic.collections = True
bpy.context.scene.atomic.images = True
bpy.context.scene.atomic.lights = True
bpy.context.scene.atomic.materials = True
bpy.context.scene.atomic.node_groups = True
bpy.context.scene.atomic.particles = True
bpy.context.scene.atomic.textures = True
bpy.context.scene.atomic.worlds = True
return {'FINISHED'}
# Atomic Data Manager Deselect All Operator
class ATOMIC_OT_deselect_all(bpy.types.Operator):
"""Deselect all categories"""
bl_idname = "atomic.deselect_all"
bl_label = "Deselect All"
def execute(self, context):
bpy.context.scene.atomic.collections = False
bpy.context.scene.atomic.images = False
bpy.context.scene.atomic.lights = False
bpy.context.scene.atomic.materials = False
bpy.context.scene.atomic.node_groups = False
bpy.context.scene.atomic.particles = False
bpy.context.scene.atomic.textures = False
bpy.context.scene.atomic.worlds = False
return {'FINISHED'}
reg_list = [
ATOMIC_OT_nuke,
ATOMIC_OT_clean,
ATOMIC_OT_undo,
ATOMIC_OT_smart_select,
ATOMIC_OT_select_all,
ATOMIC_OT_deselect_all
]
def register():
for item in reg_list:
register_class(item)
def unregister():
for item in reg_list:
unregister_class(item)
@@ -0,0 +1,195 @@
"""
Copyright (C) 2019 Remington Creative
This file is part of Atomic Data Manager.
Atomic Data Manager 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 3 of the
License, or (at your option) any later version.
Atomic Data Manager 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 Atomic Data Manager. If not, see <https://www.gnu.org/licenses/>.
---
This file contains operations for missing file handling. This includes
the option to reload, remove, replace, and search for these missing files.
It also contains the post-reload report dialog that appears after
attempting to reload missing project files.
# TODO: implement missing file replace and search once Blender fixes the
# TODO: bugs with the file chooser not opening from a dialog
"""
import bpy
from bpy.utils import register_class
from bpy.utils import unregister_class
from atomic_data_manager.stats import missing
from atomic_data_manager.ui.utils import ui_layouts
# Atomic Data Manager Reload Missing Files Operator
class ATOMIC_OT_reload_missing(bpy.types.Operator):
"""Reload missing files"""
bl_idname = "atomic.reload_missing"
bl_label = "Reload Missing Files"
def execute(self, context):
# reload images
for image in bpy.data.images:
image.reload()
# reload libraries
for library in bpy.data.libraries:
library.reload()
# call reload report
bpy.ops.atomic.reload_report('INVOKE_DEFAULT')
return {'FINISHED'}
# Atomic Data Manager Reload Missing Files Report Operator
class ATOMIC_OT_reload_report(bpy.types.Operator):
"""Reload report for missing files"""
bl_idname = "atomic.reload_report"
bl_label = "Missing File Reload Report"
def draw(self, context):
layout = self.layout
missing_images = missing.images()
missing_libraries = missing.libraries()
if missing_images or missing_libraries:
row = layout.row()
row.label(
text="Atomic was unable to reload the following files:"
)
if missing_images:
ui_layouts.box_list(
layout=self.layout,
items=missing_images,
icon='IMAGE_DATA',
columns=2
)
if missing_libraries:
ui_layouts.box_list(
layout=self.layout,
items=missing_images,
icon='LIBRARY_DATA_DIRECT',
columns=2
)
else:
row = layout.row()
row.label(text="All files successfully reloaded!")
row = layout.row() # extra space
def execute(self, context):
return {'FINISHED'}
def invoke(self, context, event):
wm = context.window_manager
return wm.invoke_props_dialog(self)
# Atomic Data Manager Remove Missing Files Operator
class ATOMIC_OT_remove_missing(bpy.types.Operator):
"""Remove all missing files from this project"""
bl_idname = "atomic.remove_missing"
bl_label = "Remove Missing Files"
def draw(self, context):
layout = self.layout
row = layout.row()
row.label(text="Remove the following data-blocks?")
ui_layouts.box_list(
layout=layout,
items=missing.images(),
icon="IMAGE_DATA",
columns=2
)
row = layout.row() # extra space
def execute(self, context):
for image_key in missing.images():
bpy.data.images.remove(bpy.data.images[image_key])
return {'FINISHED'}
def invoke(self, context, event):
wm = context.window_manager
return wm.invoke_props_dialog(self)
# TODO: Implement search for missing once file browser bugs are fixed
# Atomic Data Manager Search for Missing Files Operator
class ATOMIC_OT_search_missing(bpy.types.Operator):
"""Search a specified directory for the missing files"""
bl_idname = "atomic.search_missing"
bl_label = "Search for Missing Files"
def draw(self, context):
layout = self.layout
row = layout.row()
row.label(text="Unsupported Operation!")
def execute(self, context):
return {'FINISHED'}
def invoke(self, context, event):
wm = context.window_manager
return wm.invoke_props_dialog(self)
# TODO: Implement replace missing once file browser bugs are fixed
# Atomic Data Manager Replace Missing Files Operator
class ATOMIC_OT_replace_missing(bpy.types.Operator):
"""Replace each missing file with a new file"""
bl_idname = "atomic.replace_missing"
bl_label = "Replace Missing Files"
def draw(self, context):
layout = self.layout
row = layout.row()
row.label(text="Unsupported Operation!")
def execute(self, context):
return {'FINISHED'}
def invoke(self, context, event):
wm = context.window_manager
return wm.invoke_props_dialog(self)
reg_list = [
ATOMIC_OT_reload_missing,
ATOMIC_OT_reload_report,
ATOMIC_OT_search_missing,
ATOMIC_OT_replace_missing,
ATOMIC_OT_remove_missing
]
def register():
for item in reg_list:
register_class(item)
def unregister():
for item in reg_list:
unregister_class(item)
@@ -0,0 +1,55 @@
"""
Copyright (C) 2019 Remington Creative
This file is part of Atomic Data Manager.
Atomic Data Manager 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 3 of the
License, or (at your option) any later version.
Atomic Data Manager 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 Atomic Data Manager. If not, see <https://www.gnu.org/licenses/>.
---
This file contains the operator for opening the Remington Creative
support page in the web browser.
"""
import bpy
import webbrowser
from bpy.utils import register_class
from bpy.utils import unregister_class
# Atomic Data Manager Open Support Me Operator
class ATOMIC_OT_open_support_me(bpy.types.Operator):
"""Opens the Remington Creative \"Support Me\" webpage"""
bl_idname = "atomic.open_support_me"
bl_label = "Support Me"
def execute(self, context):
webbrowser.open("https://remingtoncreative.com/support/")
return {'FINISHED'}
reg_list = [ATOMIC_OT_open_support_me]
def register():
for cls in reg_list:
register_class(cls)
def unregister():
for cls in reg_list:
unregister_class(cls)
@@ -0,0 +1,74 @@
"""
Copyright (C) 2019 Remington Creative
This file is part of Atomic Data Manager.
Atomic Data Manager 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 3 of the
License, or (at your option) any later version.
Atomic Data Manager 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 Atomic Data Manager. If not, see <https://www.gnu.org/licenses/>.
---
This file contains functions for cleaning out specific data categories.
"""
import bpy
from atomic_data_manager.stats import unused
def collections():
# removes all unused collections from the project
for collection_key in unused.collections_deep():
bpy.data.collections.remove(bpy.data.collections[collection_key])
def images():
# removes all unused images from the project
for image_key in unused.images_deep():
bpy.data.images.remove(bpy.data.images[image_key])
def lights():
# removes all unused lights from the project
for light_key in unused.lights_deep():
bpy.data.lights.remove(bpy.data.lights[light_key])
def materials():
# removes all unused materials from the project
for light_key in unused.materials_deep():
bpy.data.materials.remove(bpy.data.materials[light_key])
def node_groups():
# removes all unused node groups from the project
for node_group_key in unused.node_groups_deep():
bpy.data.node_groups.remove(bpy.data.node_groups[node_group_key])
def particles():
# removes all unused particle systems from the project
for particle_key in unused.particles_deep():
bpy.data.particles.remove(bpy.data.particles[particle_key])
def textures():
# removes all unused textures from the project
for texture_key in unused.textures_deep():
bpy.data.textures.remove(bpy.data.textures[texture_key])
def worlds():
# removes all unused worlds from the project
for world_key in unused.worlds():
bpy.data.worlds.remove(bpy.data.worlds[world_key])
@@ -0,0 +1,71 @@
"""
Copyright (C) 2019 Remington Creative
This file is part of Atomic Data Manager.
Atomic Data Manager 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 3 of the
License, or (at your option) any later version.
Atomic Data Manager 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 Atomic Data Manager. If not, see <https://www.gnu.org/licenses/>.
---
This file contains functions for deleting individual data-blocks from
Atomic's inspection inteface.
"""
import bpy
def delete_datablock(data, key):
# deletes a specific data-block from a set of data
data.remove(data[key])
def collection(key):
# removes a specific collection
delete_datablock(bpy.data.collections, key)
def image(key):
# removes a specific image
delete_datablock(bpy.data.images, key)
def light(key):
# removes a specific light
delete_datablock(bpy.data.lights, key)
def material(key):
# removes a specific material
delete_datablock(bpy.data.materials, key)
def node_group(key):
# removes a specific node group
delete_datablock(bpy.data.node_groups, key)
def particle(key):
# removes a specific particle system
delete_datablock(bpy.data.particles, key)
def texture(key):
# removes a specific texture
delete_datablock(bpy.data.textures, key)
def world(key):
# removes a specific world
delete_datablock(bpy.data.worlds, key)
@@ -0,0 +1,77 @@
"""
Copyright (C) 2019 Remington Creative
This file is part of Atomic Data Manager.
Atomic Data Manager 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 3 of the
License, or (at your option) any later version.
Atomic Data Manager 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 Atomic Data Manager. If not, see <https://www.gnu.org/licenses/>.
---
This file contains functions for duplicating data-blocks from Atomic's
inspection interface.
"""
import bpy
def duplicate_data(data, key):
# creates a copy of the specified data-block and returns its key
return data[key].copy().name
def collection(key):
# creates of copy of the specified collection and places it under the
# scene collection
collections = bpy.data.collections
scene_collection = bpy.context.scene.collection
copy_key = duplicate_data(collections, key)
scene_collection.children.link(collections[copy_key])
return copy_key
def image(key):
# creates of copy of the specified image
return duplicate_data(bpy.data.images, key)
def light(key):
# creates of copy of the specified light
return duplicate_data(bpy.data.lights, key)
def material(key):
# creates of copy of the specified material
return duplicate_data(bpy.data.materials, key)
def node_group(key):
# creates of copy of the specified node group
return duplicate_data(bpy.data.node_groups, key)
def particle(key):
# creates of copy of the specified particle
return duplicate_data(bpy.data.particles, key)
def texture(key):
# creates of copy of the specified texture
return duplicate_data(bpy.data.textures, key)
def world(key):
# creates of copy of the specified world
return duplicate_data(bpy.data.worlds, key)
@@ -0,0 +1,72 @@
"""
Copyright (C) 2019 Remington Creative
This file is part of Atomic Data Manager.
Atomic Data Manager 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 3 of the
License, or (at your option) any later version.
Atomic Data Manager 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 Atomic Data Manager. If not, see <https://www.gnu.org/licenses/>.
---
This file contains functions for removing all data-blocks from specified
data categories.
"""
import bpy
def nuke_data(data):
# removes all data-blocks from the indicated set of data
for key in data.keys():
data.remove(data[key])
def collections():
# removes all collections from the project
nuke_data(bpy.data.collections)
def images():
# removes all images from the project
nuke_data(bpy.data.images)
def lights():
# removes all lights from the project
nuke_data(bpy.data.lights)
def materials():
# removes all materials from the project
nuke_data(bpy.data.materials)
def node_groups():
# removes all node groups from the project
nuke_data(bpy.data.node_groups)
def particles():
# removes all particle systems from the project
nuke_data(bpy.data.particles)
def textures():
# removes all textures from the project
nuke_data(bpy.data.textures)
def worlds():
# removes all worlds from the project
nuke_data(bpy.data.worlds)