Skip to content
Snippets Groups Projects
Commit 1f36b196 authored by Eugenio Pignataro's avatar Eugenio Pignataro
Browse files

Add Oscurart Tools for 2.8

parent 7fbe7166
Branches
Tags
No related merge requests found
# ##### 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>
bl_info = {
"name": "Oscurart Tools",
"author": "Oscurart, CodemanX",
"version": (4, 0, 0),
"blender": (2, 80, 0),
"location": "View3D > Toolbar and View3D > Specials (W-key)",
"description": "Tools for objects, render, shapes, and files.",
"warning": "",
"wiki_url": "https://wiki.blender.org/index.php/Extensions:2.6/Py/"
"Scripts/3D_interaction/Oscurart_Tools",
"category": "Object",
}
import bpy
from bpy.types import Menu
from oscurart_tools.files import reload_images
from oscurart_tools.files import save_incremental
from oscurart_tools.files import collect_images
from oscurart_tools.mesh import overlap_uvs
from oscurart_tools.mesh import overlap_island
from oscurart_tools.mesh import select_doubles
from oscurart_tools.mesh import shapes_to_objects
from oscurart_tools.object import distribute
from oscurart_tools.object import selection
from oscurart_tools.object import search_and_select
from oscurart_tools.mesh import apply_linked_meshes
from bpy.types import (
AddonPreferences,
Panel,
PropertyGroup,
)
from bpy.props import (
StringProperty,
BoolProperty,
IntProperty,
PointerProperty,
CollectionProperty,
)
# mesh
class VIEW3D_MT_edit_mesh_oscurarttools(Menu):
bl_label = "OscurartTools"
def draw(self, context):
layout = self.layout
layout.operator("mesh.uv_island_copy")
layout.operator("mesh.uv_island_paste")
layout.operator("mesh.select_doubles")
layout.separator()
layout.operator("image.reload_images_osc")
layout.operator("file.save_incremental_backup")
layout.operator("file.collect_all_images")
def menu_funcMesh(self, context):
self.layout.menu("VIEW3D_MT_edit_mesh_oscurarttools")
self.layout.separator()
# image
class IMAGE_MT_uvs_oscurarttools(Menu):
bl_label = "OscurartTools"
def draw(self, context):
layout = self.layout
layout.operator("mesh.uv_island_copy")
layout.operator("mesh.uv_island_paste")
layout.operator("mesh.overlap_uv_faces")
layout.separator()
layout.operator("image.reload_images_osc")
layout.operator("file.save_incremental_backup")
layout.operator("file.collect_all_images")
def menu_funcImage(self, context):
self.layout.menu("IMAGE_MT_uvs_oscurarttools")
self.layout.separator()
# object
class VIEW3D_MT_object_oscurarttools(Menu):
bl_label = "OscurartTools"
def draw(self, context):
layout = self.layout
layout.operator("object.distribute_osc")
layout.operator("object.search_and_select_osc")
layout.operator("object.shape_key_to_objects_osc")
layout.operator("mesh.apply_linked_meshes")
layout.separator()
layout.operator("image.reload_images_osc")
layout.operator("file.save_incremental_backup")
layout.operator("file.collect_all_images")
def menu_funcObject(self, context):
self.layout.menu("VIEW3D_MT_object_oscurarttools")
self.layout.separator()
# ========================= End of Scripts =========================
classes = (
VIEW3D_MT_edit_mesh_oscurarttools,
IMAGE_MT_uvs_oscurarttools,
VIEW3D_MT_object_oscurarttools,
reload_images.reloadImages,
overlap_uvs.CopyUvIsland,
overlap_uvs.PasteUvIsland,
distribute.DistributeOsc,
selection.OscSelection,
save_incremental.saveIncrementalBackup,
collect_images.collectImagesOsc,
overlap_island.OscOverlapUv,
select_doubles.SelectDoubles,
shapes_to_objects.ShapeToObjects,
search_and_select.SearchAndSelectOt,
apply_linked_meshes.ApplyLRT,
)
def register():
from bpy.types import Scene
Scene.multimeshedit = StringProperty()
bpy.types.VIEW3D_MT_edit_mesh_specials.prepend(menu_funcMesh)
bpy.types.IMAGE_MT_specials.prepend(menu_funcImage)
bpy.types.VIEW3D_MT_object_specials.prepend(menu_funcObject)
from bpy.utils import register_class
for cls in classes:
register_class(cls)
def unregister():
del bpy.types.Scene.SearchAndSelectOt
bpy.types.VIEW3D_MT_edit_mesh_specials.remove(menu_funcMesh)
bpy.types.IMAGE_MT_specials.remove(menu_funcImage)
bpy.types.VIEW3D_MT_object_specials.remove(menu_funcObject)
from bpy.utils import unregister_class
for cls in reversed(classes):
unregister_class(cls)
if __name__ == "__main__":
register()
# ##### 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 Operator
import os
import shutil
class collectImagesOsc(Operator):
"""Collect all images in the blend file and put them in IMAGES folder"""
bl_idname = "file.collect_all_images"
bl_label = "Collect Images"
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
imagespath = "%s/IMAGES" % (os.path.dirname(bpy.data.filepath))
if not os.path.exists(imagespath):
os.mkdir(imagespath)
bpy.ops.file.make_paths_absolute()
for image in bpy.data.images:
try:
image.update()
if image.has_data:
if not os.path.exists(os.path.join(imagespath,os.path.basename(image.filepath))):
shutil.copy(image.filepath, os.path.join(imagespath,os.path.basename(image.filepath)))
image.filepath = os.path.join(imagespath,os.path.basename(image.filepath))
else:
print("%s exists." % (image.name))
else:
print("%s missing path." % (image.name))
except:
print("%s missing path." % (image.name))
bpy.ops.file.make_paths_relative()
return {'FINISHED'}
# ##### 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 Operator
class reloadImages (Operator):
"""Reloads all bitmaps in the scene"""
bl_idname = "image.reload_images_osc"
bl_label = "Reload Images"
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
for imgs in bpy.data.images:
imgs.reload()
return {'FINISHED'}
# ##### 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 Operator
import os
def saveBkp (self, context):
fileFolder = os.path.dirname(bpy.data.filepath)
versionFolder = os.path.join(fileFolder,"VERSIONS")
#creo folder
if os.path.exists(versionFolder):
print("existe")
else:
os.mkdir(versionFolder)
#sin version a versionada
if not bpy.data.filepath.count("_v"):
filelist = [file for file in os.listdir(versionFolder) if file.count("_v") and not file.count("blend1")]
filelower = 0
print(filelist)
for file in filelist:
if int(file.split(".")[0][-2:]) > filelower:
filelower = int(file.split(".")[0][-2:])
savepath = "%s/VERSIONS/%s_v%02d.blend" % (os.path.dirname(bpy.data.filepath),bpy.path.basename(bpy.data.filepath).split('.')[0],filelower+1)
print("Copia versionada guardada.")
bpy.ops.wm.save_as_mainfile()
bpy.ops.wm.save_as_mainfile(filepath=savepath, copy=True)
else:
#versionada a sin version
if bpy.data.filepath.count("_v"):
filename = "%s/../%s.blend" % (os.path.dirname(bpy.data.filepath),os.path.basename(bpy.data.filepath).rpartition(".")[0].rpartition("_")[0])
print(filename)
bpy.ops.wm.save_as_mainfile(filepath=filename, copy=True)
print("Copia sin version guardada.")
class saveIncrementalBackup (bpy.types.Operator):
"""Save incremental backup in versions folder"""
bl_idname = "file.save_incremental_backup"
bl_label = "Save Incremental Backup"
bl_options = {'REGISTER', 'UNDO'}
def execute(self, context):
saveBkp(self, context)
return {'FINISHED'}
# ##### 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
def applyLRTEx(self, context):
actObj = bpy.context.active_object
actObjMatrixWorld = actObj.matrix_world.copy()
bpy.ops.object.select_linked(extend=False, type="OBDATA")
linkedObjects = bpy.context.selected_objects
linkedObjects.remove(actObj)
for vert in actObj.data.vertices:
vert.co = actObjMatrixWorld @ vert.co
actObj.location = (0,0,0)
actObj.rotation_euler = (0,0,0)
actObj.scale = (1,1,1)
for ob in linkedObjects:
ob.matrix_world = ob.matrix_world @ actObj.matrix_world.inverted()
class ApplyLRT(bpy.types.Operator):
"""Apply LRT with linked mesh data"""
bl_idname = "mesh.apply_linked_meshes"
bl_label = "Apply LRT with linked meshes"
bl_options = {"REGISTER", "UNDO"}
@classmethod
def poll(cls, context):
return (context.view_layer.objects.active is not None and
context.view_layer.objects.active.type == 'MESH')
def execute(self, context):
applyLRTEx(self, context)
return {'FINISHED'}
# ##### 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 mathutils import Vector
from bpy.types import Operator
from bpy.props import (
IntProperty,
BoolProperty,
FloatProperty,
EnumProperty,
)
import bmesh
import time
C = bpy.context
D = bpy.data
def DefOscOverlapUv(self,offset,rotate):
me = bpy.context.object.data
bm = bmesh.from_edit_mesh(me)
bm.faces.ensure_lookup_table()
faces = [face for face in bm.faces if face.select]
uv_layer = bm.loops.layers.uv[bpy.context.object.data.uv_layers.active.name]
faceDict = {}
faceReverse = []
bm.select_mode = {'FACE'}
for face in faces:
bpy.ops.mesh.select_all(action="DESELECT")
face.select = True
bpy.ops.mesh.select_mirror()
faceDict[face.index] = [mirrorface for mirrorface in bm.faces if mirrorface.select][0].index
faceReverse.append([mirrorface for mirrorface in bm.faces if mirrorface.select][0])
for selFace,mirrorFace in faceDict.items():
for loop,mirrorLoop in zip(bm.faces[selFace].loops,bm.faces[mirrorFace].loops):
mirrorLoop.copy_from(loop)
if offset:
for loop,mirrorLoop in zip(bm.faces[selFace].loops,bm.faces[mirrorFace].loops):
mirrorLoop[uv_layer].uv += Vector((1,0))
#invierto direcciones
bmesh.ops.reverse_uvs(bm, faces=[f for f in faceReverse])
bmesh.ops.rotate_uvs(bm, faces=[f for f in faceReverse])
if rotate:
bmesh.ops.rotate_uvs(bm, faces=[f for f in faceReverse])
bmesh.update_edit_mesh(me)
class OscOverlapUv(Operator):
"""Overlaps the uvs on one side of the model symmetry plane. """ \
"""Useful to get more detail on fixed resolution bitmaps"""
bl_idname = "mesh.overlap_uv_faces"
bl_label = "Overlap Uvs"
bl_options = {"REGISTER", "UNDO"}
@classmethod
def poll(cls, context):
return (context.active_object is not None and
context.active_object.type == 'MESH')
offset : BoolProperty(
default=True,
name="Offset"
)
rotate : BoolProperty(
default=False,
name="Rotate"
)
def execute(self, context):
DefOscOverlapUv(self,self.offset,self.rotate)
return {'FINISHED'}
# ##### 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 mathutils import Vector
from bpy.types import Operator
from bpy.props import (
IntProperty,
BoolProperty,
FloatProperty,
EnumProperty,
)
import os
import bmesh
C = bpy.context
D = bpy.data
# -------------------------- OVERLAP UV ISLANDS
def defCopyUvsIsland(self, context):
bpy.ops.object.mode_set(mode="OBJECT")
global obLoop
global islandFaces
obLoop = []
islandFaces = []
for poly in bpy.context.object.data.polygons:
if poly.select:
islandFaces.append(poly.index)
for li in poly.loop_indices:
obLoop.append(li)
bpy.ops.object.mode_set(mode="EDIT")
def defPasteUvsIsland(self, uvOffset, rotateUv,context):
bpy.ops.object.mode_set(mode="OBJECT")
selPolys = [poly.index for poly in bpy.context.object.data.polygons if poly.select]
for island in selPolys:
bpy.ops.object.mode_set(mode="EDIT")
bpy.ops.mesh.select_all(action="DESELECT")
bpy.ops.object.mode_set(mode="OBJECT")
bpy.context.object.data.polygons[island].select = True
bpy.ops.object.mode_set(mode="EDIT")
bpy.ops.mesh.select_linked()
bpy.ops.object.mode_set(mode="OBJECT")
TobLoop = []
TislandFaces = []
for poly in bpy.context.object.data.polygons:
if poly.select:
TislandFaces.append(poly.index)
for li in poly.loop_indices:
TobLoop.append(li)
for source,target in zip(range(min(obLoop),max(obLoop)+1),range(min(TobLoop),max(TobLoop)+1)):
bpy.context.object.data.uv_layers.active.data[target].uv = bpy.context.object.data.uv_layers.active.data[source].uv + Vector((uvOffset,0))
bpy.ops.object.mode_set(mode="EDIT")
if rotateUv:
bpy.ops.object.mode_set(mode="OBJECT")
for poly in selPolys:
bpy.context.object.data.polygons[poly].select = True
bpy.ops.object.mode_set(mode="EDIT")
bm = bmesh.from_edit_mesh(bpy.context.object.data)
bmesh.ops.reverse_uvs(bm, faces=[f for f in bm.faces if f.select])
bmesh.ops.rotate_uvs(bm, faces=[f for f in bm.faces if f.select])
#bmesh.update_edit_mesh(bpy.context.object.data, tessface=False, destructive=False)
class CopyUvIsland(Operator):
"""Copy Uv Island"""
bl_idname = "mesh.uv_island_copy"
bl_label = "Copy Uv Island"
bl_options = {"REGISTER", "UNDO"}
@classmethod
def poll(cls, context):
return (context.active_object is not None and
context.active_object.type == 'MESH' and
context.active_object.mode == "EDIT")
def execute(self, context):
defCopyUvsIsland(self, context)
return {'FINISHED'}
class PasteUvIsland(Operator):
"""Paste Uv Island"""
bl_idname = "mesh.uv_island_paste"
bl_label = "Paste Uv Island"
bl_options = {"REGISTER", "UNDO"}
uvOffset : BoolProperty(
name="Uv Offset",
default=False
)
rotateUv : BoolProperty(
name="Rotate Uv Corner",
default=False
)
@classmethod
def poll(cls, context):
return (context.active_object is not None and
context.active_object.type == 'MESH' and
context.active_object.mode == "EDIT")
def execute(self, context):
defPasteUvsIsland(self, self.uvOffset, self.rotateUv, context)
return {'FINISHED'}
# ##### 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 mathutils import Vector
from bpy.types import Operator
from bpy.props import (
IntProperty,
BoolProperty,
FloatProperty,
EnumProperty,
)
import os
import bmesh
C = bpy.context
D = bpy.data
def SelDoubles(self, context):
bm = bmesh.from_edit_mesh(bpy.context.object.data)
for v in bm.verts:
v.select = 0
dictloc = {}
rd = lambda x: (round(x[0], 4), round(x[1], 4), round(x[2], 4))
for vert in bm.verts:
dictloc.setdefault(rd(vert.co), []).append(vert.index)
for loc, ind in dictloc.items():
if len(ind) > 1:
for v in ind:
bm.verts[v].select = 1
bpy.context.view_layer.objects.active = bpy.context.view_layer.objects.active
class SelectDoubles(Operator):
"""Selects duplicated vertex without merge them"""
bl_idname = "mesh.select_doubles"
bl_label = "Select Doubles"
bl_options = {"REGISTER", "UNDO"}
@classmethod
def poll(cls, context):
return (context.view_layer.objects.active is not None and
context.view_layer.objects.active.type == 'MESH' and
context.view_layer.objects.active.mode == "EDIT")
def execute(self, context):
SelDoubles(self, context)
return {'FINISHED'}
# ##### 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 Operator
from bpy.props import (
BoolProperty,
FloatProperty,
)
import math
class ShapeToObjects(Operator):
"""It creates a new object for every shapekey in the selected object, ideal to export to other 3D software Apps"""
bl_idname = "object.shape_key_to_objects_osc"
bl_label = "Shapes To Objects"
bl_options = {"REGISTER", "UNDO"}
@classmethod
def poll(cls, context):
return (context.view_layer.objects.active is not None and
context.view_layer.objects.active.type in
{'MESH', 'SURFACE', 'CURVE'})
def execute(self, context):
OBJACT = bpy.context.view_layer.objects.active
has_keys = hasattr(getattr(OBJACT.data, "shape_keys", None), "key_blocks")
if has_keys:
for SHAPE in OBJACT.data.shape_keys.key_blocks[:]:
print(SHAPE.name)
bpy.ops.object.shape_key_clear()
SHAPE.value = 1
mesh = OBJACT.to_mesh(bpy.context.depsgraph, True, calc_undeformed=False)
object = bpy.data.objects.new(SHAPE.name, mesh)
bpy.context.scene.collection.objects.link(object)
else:
self.report({'INFO'}, message="Active object doesn't have shape keys")
return {'CANCELLED'}
return {'FINISHED'}
# ##### 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
import os
from bpy.types import Operator
from bpy.props import BoolProperty
def ObjectDistributeOscurart(self, X, Y, Z):
if len(bpy.selection_osc[:]) > 1:
# VARIABLES
dif = bpy.selection_osc[-1].location - bpy.selection_osc[0].location
chunkglobal = dif / (len(bpy.selection_osc[:]) - 1)
chunkx = 0
chunky = 0
chunkz = 0
deltafst = bpy.selection_osc[0].location
# ORDENA
for OBJECT in bpy.selection_osc[:]:
if X:
OBJECT.location.x = deltafst[0] + chunkx
if Y:
OBJECT.location[1] = deltafst[1] + chunky
if Z:
OBJECT.location.z = deltafst[2] + chunkz
chunkx += chunkglobal[0]
chunky += chunkglobal[1]
chunkz += chunkglobal[2]
else:
self.report({'INFO'}, "Needs at least two selected objects")
class DistributeOsc(Operator):
"""Distribute evenly the selected objects in x y z"""
bl_idname = "object.distribute_osc"
bl_label = "Distribute Objects"
Boolx : BoolProperty(name="X")
Booly : BoolProperty(name="Y")
Boolz : BoolProperty(name="Z")
def execute(self, context):
ObjectDistributeOscurart(self, self.Boolx, self.Booly, self.Boolz)
return {'FINISHED'}
def invoke(self, context, event):
self.Boolx = True
self.Booly = True
self.Boolz = True
return context.window_manager.invoke_props_dialog(self)
# ##### 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 Operator
from bpy.props import BoolProperty
from bpy.props import StringProperty
# ------------------------ SEARCH AND SELECT ------------------------
class SearchAndSelectOt(bpy.types.Operator):
"""Search and select objects, by name"""
bl_idname = "object.search_and_select_osc"
bl_label = "Search And Select"
bl_options = {"REGISTER", "UNDO"}
keyword : StringProperty(name="Keyword", default="Type Here")
start : BoolProperty(name="Start With", default=True)
count : BoolProperty(name="Contain", default=True)
end : BoolProperty(name="End", default=True)
def execute(self, context):
for objeto in bpy.context.scene.objects:
variableNombre = self.keyword
if self.start:
if objeto.name.startswith(variableNombre):
objeto.select_set(True)
if self.count:
if objeto.name.count(variableNombre):
objeto.select_set(True)
if self.end:
if objeto.name.count(variableNombre):
objeto.select_set(True)
return {'FINISHED'}
def invoke(self, context, event):
self.keyword = "Type Here"
self.start = True
self.count = True
self.end = True
return context.window_manager.invoke_props_dialog(self)
# ##### 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
# ------------------------------------ SELECTION -------------------------
bpy.selection_osc = []
def select_osc():
if bpy.context.mode == "OBJECT":
obj = bpy.context.object
sel = len(bpy.context.selected_objects)
if sel == 0:
bpy.selection_osc = []
else:
if sel == 1:
bpy.selection_osc = []
bpy.selection_osc.append(obj)
elif sel > len(bpy.selection_osc):
for sobj in bpy.context.selected_objects:
if (sobj in bpy.selection_osc) is False:
bpy.selection_osc.append(sobj)
elif sel < len(bpy.selection_osc):
for it in bpy.selection_osc:
if (it in bpy.context.selected_objects) is False:
bpy.selection_osc.remove(it)
class OscSelection(bpy.types.Header):
bl_label = "Selection Osc"
bl_space_type = "VIEW_3D"
def __init__(self):
select_osc()
def draw(self, context):
"""
layout = self.layout
row = layout.row()
row.label("Sels: "+str(len(bpy.selection_osc)))
"""
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment