Oscurart Tools: Remove entire addon
This commit is contained in:
parent
8dfa2220aa
commit
731efb6801
Notes:
blender-bot
2023-02-13 15:15:13 +01:00
Referenced by issue blender/blender#98720, Blender 3.2: Missing Oscurant Tools Addon
|
@ -1,200 +0,0 @@
|
|||
# ##### 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",
|
||||
"version": (4, 0, 0),
|
||||
"blender": (2, 90, 0),
|
||||
"location": "View3D > Context Menu > Object/Edit Modes",
|
||||
"description": "Tools for objects, render, shapes, and files.",
|
||||
"warning": "",
|
||||
"doc_url": "https://www.oscurart.com.ar",
|
||||
"category": "Object",
|
||||
}
|
||||
|
||||
|
||||
import bpy
|
||||
from bpy.app.handlers import persistent
|
||||
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.mesh import remove_modifiers
|
||||
from oscurart_tools.mesh import vertex_color_id
|
||||
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 oscurart_tools.render import render_tokens
|
||||
from oscurart_tools.render import batch_maker
|
||||
from oscurart_tools.render import material_overrides
|
||||
from oscurart_tools.mesh import flipped_uvs
|
||||
from oscurart_tools.mesh import print_uv_stats
|
||||
|
||||
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.operator("mesh.print_uv_stats")
|
||||
layout.separator()
|
||||
layout.operator("image.reload_images_osc")
|
||||
layout.operator("file.save_incremental_backup")
|
||||
layout.operator("file.collect_all_images")
|
||||
layout.operator("file.create_batch_maker_osc")
|
||||
|
||||
|
||||
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.operator("mesh.select_flipped_uvs")
|
||||
layout.separator()
|
||||
layout.operator("image.reload_images_osc")
|
||||
layout.operator("file.save_incremental_backup")
|
||||
layout.operator("file.collect_all_images")
|
||||
layout.operator("file.create_batch_maker_osc")
|
||||
|
||||
|
||||
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("mesh.vertex_color_mask")
|
||||
layout.operator("object.distribute_osc")
|
||||
layout.operator("mesh.remove_modifiers")
|
||||
layout.operator("object.search_and_select_osc")
|
||||
layout.operator("object.shape_key_to_objects_osc")
|
||||
layout.operator("mesh.apply_linked_meshes")
|
||||
layout.operator("mesh.print_uv_stats")
|
||||
layout.separator()
|
||||
layout.operator("image.reload_images_osc")
|
||||
layout.operator("file.save_incremental_backup")
|
||||
layout.operator("file.collect_all_images")
|
||||
layout.operator("file.create_batch_maker_osc")
|
||||
|
||||
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.OSSELECTION_HT_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,
|
||||
batch_maker.oscBatchMaker,
|
||||
remove_modifiers.RemoveModifiers,
|
||||
vertex_color_id.createVCMask,
|
||||
material_overrides.OVERRIDES_PT_OscOverridesGUI,
|
||||
material_overrides.OscTransferOverrides,
|
||||
material_overrides.OscAddOverridesSlot,
|
||||
material_overrides.OscRemoveOverridesSlot,
|
||||
material_overrides.OscOverridesUp,
|
||||
material_overrides.OscOverridesDown,
|
||||
material_overrides.OscOverridesKill,
|
||||
flipped_uvs.selectFlippedUvs,
|
||||
print_uv_stats.uvStats
|
||||
)
|
||||
|
||||
def register():
|
||||
from bpy.types import Scene
|
||||
Scene.multimeshedit = StringProperty()
|
||||
bpy.types.VIEW3D_MT_edit_mesh_context_menu.prepend(menu_funcMesh)
|
||||
bpy.types.IMAGE_MT_uvs_context_menu.prepend(menu_funcImage)
|
||||
bpy.types.VIEW3D_MT_object_context_menu.prepend(menu_funcObject)
|
||||
bpy.app.handlers.render_init.append(render_tokens.replaceTokens)
|
||||
bpy.app.handlers.render_cancel.append(render_tokens.restoreTokens)
|
||||
bpy.app.handlers.render_complete.append(render_tokens.restoreTokens)
|
||||
bpy.app.handlers.render_pre.append(material_overrides.ApplyOverrides)
|
||||
bpy.app.handlers.render_cancel.append(material_overrides.RestoreOverrides)
|
||||
bpy.app.handlers.render_post.append(material_overrides.RestoreOverrides)
|
||||
|
||||
from bpy.utils import register_class
|
||||
for cls in classes:
|
||||
register_class(cls)
|
||||
|
||||
|
||||
def unregister():
|
||||
bpy.types.VIEW3D_MT_edit_mesh_context_menu.remove(menu_funcMesh)
|
||||
bpy.types.IMAGE_MT_uvs_context_menu.remove(menu_funcImage)
|
||||
bpy.types.VIEW3D_MT_object_context_menu.remove(menu_funcObject)
|
||||
|
||||
from bpy.utils import unregister_class
|
||||
for cls in reversed(classes):
|
||||
unregister_class(cls)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
register()
|
|
@ -1,59 +0,0 @@
|
|||
# ##### 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'}
|
|
@ -1,35 +0,0 @@
|
|||
# ##### 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'}
|
|
@ -1,68 +0,0 @@
|
|||
# ##### 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'}
|
|
@ -1,55 +0,0 @@
|
|||
# ##### 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'}
|
|
@ -1,60 +0,0 @@
|
|||
# ##### 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 bmesh
|
||||
|
||||
def defSelectFlippedUvs(self, context):
|
||||
bm = bmesh.from_edit_mesh(bpy.context.active_object.data)
|
||||
bpy.context.scene.tool_settings.use_uv_select_sync = True
|
||||
|
||||
uvLayer = bm.loops.layers.uv.verify()
|
||||
|
||||
|
||||
for face in bm.faces:
|
||||
sum_edges = 0
|
||||
|
||||
for i in range(3):
|
||||
uv_A = face.loops[i][uvLayer].uv
|
||||
uv_B = face.loops[(i+1)%3][uvLayer].uv
|
||||
sum_edges += uv_B.cross(uv_A)
|
||||
|
||||
if sum_edges > 0:
|
||||
face.select_set(True)
|
||||
|
||||
bmesh.update_edit_mesh(bpy.context.object.data)
|
||||
|
||||
|
||||
class selectFlippedUvs(bpy.types.Operator):
|
||||
"""Copy Uv Island"""
|
||||
bl_idname = "mesh.select_flipped_uvs"
|
||||
bl_label = "Select Flipped Uvs"
|
||||
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):
|
||||
defSelectFlippedUvs(self, context)
|
||||
return {'FINISHED'}
|
|
@ -1,97 +0,0 @@
|
|||
# ##### 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'}
|
|
@ -1,122 +0,0 @@
|
|||
# ##### 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
|
||||
|
||||
# -------------------------- OVERLAP UV ISLANDS
|
||||
|
||||
def defCopyUvsIsland(self, context):
|
||||
global islandSet
|
||||
islandSet = {}
|
||||
islandSet["Loop"] = []
|
||||
|
||||
bpy.context.scene.tool_settings.use_uv_select_sync = True
|
||||
bpy.ops.uv.select_linked()
|
||||
bm = bmesh.from_edit_mesh(bpy.context.object.data)
|
||||
uv_lay = bm.loops.layers.uv.active
|
||||
faceSel = 0
|
||||
for face in bm.faces:
|
||||
if face.select:
|
||||
faceSel +=1
|
||||
for loop in face.loops:
|
||||
islandSet["Loop"].append(loop[uv_lay].uv.copy())
|
||||
islandSet["Size"] = faceSel
|
||||
|
||||
def defPasteUvsIsland(self, uvOffset, rotateUv,context):
|
||||
bm = bmesh.from_edit_mesh(bpy.context.object.data)
|
||||
bpy.context.scene.tool_settings.use_uv_select_sync = True
|
||||
pickedFaces = [face for face in bm.faces if face.select]
|
||||
for face in pickedFaces:
|
||||
bpy.ops.mesh.select_all(action="DESELECT")
|
||||
face.select=True
|
||||
bmesh.update_edit_mesh(bpy.context.object.data)
|
||||
bpy.ops.uv.select_linked()
|
||||
uv_lay = bm.loops.layers.uv.active
|
||||
faceSel = 0
|
||||
for face in bm.faces:
|
||||
if face.select:
|
||||
faceSel +=1
|
||||
i = 0
|
||||
if faceSel == islandSet["Size"]:
|
||||
for face in bm.faces:
|
||||
if face.select:
|
||||
for loop in face.loops:
|
||||
loop[uv_lay].uv = islandSet["Loop"][i] if uvOffset == False else islandSet["Loop"][i]+Vector((1,0))
|
||||
i += 1
|
||||
else:
|
||||
print("the island have a different size of geometry")
|
||||
|
||||
if rotateUv:
|
||||
bpy.ops.object.mode_set(mode="EDIT")
|
||||
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])
|
||||
|
||||
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'}
|
|
@ -1,125 +0,0 @@
|
|||
# ##### 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 #####
|
||||
|
||||
|
||||
|
||||
import bpy
|
||||
import bmesh
|
||||
from mathutils.geometry import area_tri
|
||||
from math import sqrt
|
||||
from math import pow
|
||||
|
||||
|
||||
def setImageRes(object):
|
||||
global pixels
|
||||
mat = object.material_slots[object.active_material_index].material
|
||||
if mat.node_tree.nodes.active.type in ["TEX_IMAGE"]:
|
||||
pixels = [mat.node_tree.nodes.active.image.size[0] ,mat.node_tree.nodes.active.image.size[1] ]
|
||||
return(True)
|
||||
|
||||
else:
|
||||
print("Please select image node first")
|
||||
return(False)
|
||||
|
||||
|
||||
def makeTessellate(actObj):
|
||||
global bm_tess
|
||||
ob = actObj
|
||||
me = ob.data
|
||||
bm = bmesh.new()
|
||||
bm.from_mesh(me)
|
||||
bmesh.ops.triangulate(bm, faces=bm.faces[:])
|
||||
bm_tess = bpy.data.meshes.new("Tris")
|
||||
bm.to_mesh(bm_tess)
|
||||
|
||||
|
||||
def calcArea():
|
||||
global totalArea
|
||||
totalArea = 0
|
||||
for poly in bm_tess.polygons:
|
||||
uno = bm_tess.uv_layers.active.data[poly.loop_indices[0]].uv
|
||||
dos = bm_tess.uv_layers.active.data[poly.loop_indices[1]].uv
|
||||
tres = bm_tess.uv_layers.active.data[poly.loop_indices[2]].uv
|
||||
area = area_tri(uno, dos, tres)
|
||||
totalArea += area
|
||||
|
||||
bpy.data.meshes.remove(
|
||||
bm_tess,
|
||||
do_unlink=True,
|
||||
do_id_user=True,
|
||||
do_ui_user=True)
|
||||
|
||||
|
||||
def calcMeshArea(ob):
|
||||
global GlobLog
|
||||
polyArea = 0
|
||||
for poly in ob.data.polygons:
|
||||
polyArea += poly.area
|
||||
ta = "UvGain: %s%s || " % (round(totalArea * 100),"%")
|
||||
ma = "MeshArea: %s || " % (polyArea)
|
||||
pg = "PixelsGain: %s || " % (round(totalArea * (pixels[0] * pixels[1])))
|
||||
pl = "PixelsLost: %s || " % ((pixels[0]*pixels[1]) - round(totalArea * (pixels[0] * pixels[1])))
|
||||
tx = "Texel: %s pix/meter" % (round(sqrt(totalArea * pixels[0] * pixels[1] / polyArea)))
|
||||
GlobLog = ta+ma+pg+pl+tx
|
||||
|
||||
|
||||
|
||||
|
||||
class uvStats(bpy.types.Operator):
|
||||
"""Print Uv Stats"""
|
||||
bl_idname = "mesh.print_uv_stats"
|
||||
bl_label = "Print Uv Stats"
|
||||
bl_options = {'REGISTER'}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return context.active_object is not None
|
||||
|
||||
def execute(self, context):
|
||||
if round(
|
||||
bpy.context.object.scale.x,
|
||||
2) == 1 and round(
|
||||
bpy.context.object.scale.y,
|
||||
2) == 1 and round(
|
||||
bpy.context.object.scale.x,
|
||||
2) == 1:
|
||||
if setImageRes(bpy.context.object):
|
||||
makeTessellate(bpy.context.object)
|
||||
calcArea()
|
||||
calcMeshArea(bpy.context.object)
|
||||
else:
|
||||
print("Warning: Non Uniform Scale Object")
|
||||
|
||||
copyOb = bpy.context.object.copy()
|
||||
copyMe = bpy.context.object.data.copy()
|
||||
bpy.context.scene.collection.objects.link(copyOb)
|
||||
copyOb.data = copyMe
|
||||
bpy.ops.object.select_all(action="DESELECT")
|
||||
copyOb.select_set(1)
|
||||
bpy.ops.object.transform_apply()
|
||||
|
||||
if setImageRes(copyOb):
|
||||
makeTessellate(copyOb)
|
||||
calcArea()
|
||||
calcMeshArea(copyOb)
|
||||
|
||||
bpy.data.objects.remove(copyOb)
|
||||
bpy.data.meshes.remove(copyMe)
|
||||
|
||||
self.report({'INFO'}, GlobLog)
|
||||
return {'FINISHED'}
|
|
@ -1,44 +0,0 @@
|
|||
# ##### 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 funcRemoveModifiers(self,context):
|
||||
for ob in bpy.context.selected_objects:
|
||||
if ob.type == "MESH":
|
||||
for mod in ob.modifiers:
|
||||
ob.modifiers.remove(mod)
|
||||
|
||||
class RemoveModifiers(bpy.types.Operator):
|
||||
"""Remove all mesh modifiers"""
|
||||
bl_idname = "mesh.remove_modifiers"
|
||||
bl_label = "Remove Modifiers"
|
||||
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):
|
||||
funcRemoveModifiers(self,context)
|
||||
return {'FINISHED'}
|
|
@ -1,74 +0,0 @@
|
|||
# ##### 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, distance):
|
||||
obj = bpy.context.object
|
||||
me = obj.data
|
||||
bm = bmesh.from_edit_mesh(me)
|
||||
double = bmesh.ops.find_doubles(bm, verts=bm.verts, dist=distance)
|
||||
|
||||
bpy.ops.mesh.select_all(action = 'DESELECT')
|
||||
|
||||
for vertice in double['targetmap']:
|
||||
vertice.select = True
|
||||
|
||||
# Switch to vertex select
|
||||
bpy.ops.mesh.select_mode(use_extend=False, use_expand=False, type='VERT')
|
||||
|
||||
# Show the updates in the viewport
|
||||
bmesh.update_edit_mesh(me, False)
|
||||
|
||||
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")
|
||||
|
||||
distance : bpy.props.FloatProperty(
|
||||
default=.0001,
|
||||
name="Distance")
|
||||
|
||||
def execute(self, context):
|
||||
SelDoubles(self, context,self.distance)
|
||||
return {'FINISHED'}
|
|
@ -1,60 +0,0 @@
|
|||
# ##### 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:
|
||||
depsgraph = bpy.context.evaluated_depsgraph_get()
|
||||
for SHAPE in OBJACT.data.shape_keys.key_blocks[:]:
|
||||
print(SHAPE.name)
|
||||
bpy.ops.object.shape_key_clear()
|
||||
SHAPE.value = 1
|
||||
OBJACT_eval = OBJACT.evaluated_get(depsgraph)
|
||||
mesh = bpy.data.meshes.new_from_object(OBJACT_eval)
|
||||
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'}
|
|
@ -1,67 +0,0 @@
|
|||
# ##### 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 bmesh
|
||||
from random import uniform
|
||||
|
||||
def vertexColorMask(self,context):
|
||||
obj = bpy.context.active_object
|
||||
mesh= obj.data
|
||||
bpy.ops.object.mode_set(mode='EDIT', toggle=False)
|
||||
bpy.ops.mesh.select_all(action="DESELECT")
|
||||
bm = bmesh.from_edit_mesh(mesh)
|
||||
bm.faces.ensure_lookup_table()
|
||||
islands = []
|
||||
faces = bm.faces
|
||||
try:
|
||||
color_layer = bm.loops.layers.color["RGBMask"]
|
||||
except:
|
||||
color_layer = bm.loops.layers.color.new("RGBMask")
|
||||
while faces:
|
||||
faces[0].select_set(True)
|
||||
bpy.ops.mesh.select_linked()
|
||||
islands.append([f for f in faces if f.select])
|
||||
bpy.ops.mesh.hide(unselected=False)
|
||||
faces = [f for f in bm.faces if not f.hide]
|
||||
bpy.ops.mesh.reveal()
|
||||
for island in islands:
|
||||
color = (uniform(0,1),uniform(0,1),uniform(0,1),1)
|
||||
for face in island:
|
||||
for loop in face.loops:
|
||||
loop[color_layer] = color
|
||||
bpy.ops.object.mode_set(mode="VERTEX_PAINT")
|
||||
|
||||
|
||||
class createVCMask(bpy.types.Operator):
|
||||
bl_idname = "mesh.vertex_color_mask"
|
||||
bl_label = "Vertex Color Mask"
|
||||
bl_description = ("Create a Vertex Color Mask")
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
obj = context.active_object
|
||||
return obj is not None
|
||||
|
||||
def execute(self, context):
|
||||
vertexColorMask(self, context)
|
||||
return {'FINISHED'}
|
|
@ -1,69 +0,0 @@
|
|||
# ##### 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)
|
|
@ -1,59 +0,0 @@
|
|||
# ##### 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)
|
|
@ -1,63 +0,0 @@
|
|||
# ##### 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 OSSELECTION_HT_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(text="Sels: "+str(len(bpy.selection_osc)))
|
||||
"""
|
|
@ -1,50 +0,0 @@
|
|||
import bpy
|
||||
import os
|
||||
|
||||
# ---------------------------BATCH MAKER------------------
|
||||
|
||||
|
||||
def batchMaker(BIN):
|
||||
|
||||
if os.name == "nt":
|
||||
print("PLATFORM: WINDOWS")
|
||||
SYSBAR = os.sep
|
||||
EXTSYS = ".bat"
|
||||
QUOTES = '"'
|
||||
else:
|
||||
print("PLATFORM:LINUX")
|
||||
SYSBAR = os.sep
|
||||
EXTSYS = ".sh"
|
||||
QUOTES = ''
|
||||
|
||||
FILENAME = bpy.data.filepath.rpartition(SYSBAR)[-1].rpartition(".")[0]
|
||||
BINDIR = bpy.app[4]
|
||||
SHFILE = os.path.join(
|
||||
bpy.data.filepath.rpartition(SYSBAR)[0],
|
||||
FILENAME + EXTSYS)
|
||||
|
||||
renpath = bpy.context.scene.render.filepath
|
||||
|
||||
with open(SHFILE, "w") as FILE:
|
||||
if not BIN:
|
||||
for scene in bpy.data.scenes:
|
||||
FILE.writelines("'%s' -b '%s' --scene %s --python-text Text -a \n" % (bpy.app.binary_path,bpy.data.filepath,scene.name))
|
||||
else:
|
||||
for scene in bpy.data.scenes:
|
||||
FILE.writelines("blender -b '%s' --scene %s --python-text Text -a \n" % (bpy.data.filepath,scene.name))
|
||||
|
||||
|
||||
|
||||
class oscBatchMaker (bpy.types.Operator):
|
||||
"""It creates .bat(win) or .sh(unix) file, to execute and render from Console/Terminal"""
|
||||
bl_idname = "file.create_batch_maker_osc"
|
||||
bl_label = "Make render batch"
|
||||
bl_options = {'REGISTER', 'UNDO'}
|
||||
|
||||
bin : bpy.props.BoolProperty(
|
||||
default=False,
|
||||
name="Use Environment Variable")
|
||||
|
||||
def execute(self, context):
|
||||
batchMaker(self.bin)
|
||||
return {'FINISHED'}
|
|
@ -1,226 +0,0 @@
|
|||
# ------------------------------------------------
|
||||
|
||||
|
||||
obDict = []
|
||||
import bpy
|
||||
from bpy.app.handlers import persistent
|
||||
|
||||
|
||||
@persistent
|
||||
def ApplyOverrides(dummy):
|
||||
global obDict
|
||||
|
||||
for override in bpy.context.scene.ovlist:
|
||||
|
||||
# set collections clean name
|
||||
collClean = override.colloverride
|
||||
obClean = override.oboverride
|
||||
|
||||
|
||||
|
||||
if collClean != None:
|
||||
for ob in collClean.all_objects:
|
||||
if ob.type == "MESH": #si es un mesh
|
||||
if not ob.hide_viewport and not ob.hide_render:
|
||||
obDict.append([ob,[mat for mat in ob.data.materials]])
|
||||
if ob.type == "EMPTY": #si es un coleccion instance
|
||||
if not ob.instance_collection == None:
|
||||
for iob in ob.instance_collection.all_objects:
|
||||
if iob.type == "MESH":
|
||||
if not iob.hide_viewport and not iob.hide_render:
|
||||
obDict.append([iob,[mat for mat in iob.data.materials]])
|
||||
else:
|
||||
obDict.append([obClean,[mat for mat in obClean.data.materials]])
|
||||
|
||||
|
||||
for override in bpy.context.scene.ovlist:
|
||||
|
||||
# set collections clean name
|
||||
collClean = override.colloverride
|
||||
# set material clean name
|
||||
matClean = override.matoverride
|
||||
# set objeto clean name
|
||||
obClean = override.oboverride
|
||||
|
||||
print(matClean)
|
||||
|
||||
if collClean != None:
|
||||
for ob in collClean.all_objects:
|
||||
if ob.type == "MESH":
|
||||
if not ob.hide_viewport and not ob.hide_render:
|
||||
for i,mat in enumerate(ob.data.materials):
|
||||
ob.data.materials[i] = matClean
|
||||
if ob.type == "EMPTY":
|
||||
if not ob.instance_collection == None:
|
||||
for iob in ob.instance_collection.all_objects:
|
||||
if iob.type == "MESH":
|
||||
if not iob.hide_viewport and not iob.hide_render:
|
||||
for i,mat in enumerate(iob.data.materials):
|
||||
iob.data.materials[i] = matClean
|
||||
else:
|
||||
if obClean.type == "MESH":
|
||||
if not obClean.hide_viewport and not obClean.hide_render:
|
||||
for i,mat in enumerate(obClean.data.materials):
|
||||
obClean.data.materials[i] = matClean
|
||||
|
||||
|
||||
@persistent
|
||||
def RestoreOverrides(dummy):
|
||||
global obDict
|
||||
|
||||
for set in obDict:
|
||||
for i,mat in enumerate(set[1]):
|
||||
set[0].data.materials[i] = mat
|
||||
|
||||
obDict = []
|
||||
|
||||
|
||||
# ---------------------------------------------------
|
||||
|
||||
|
||||
|
||||
class OscOverridesProp(bpy.types.PropertyGroup):
|
||||
colloverride: bpy.props.PointerProperty(
|
||||
name="Collection Override",
|
||||
type=bpy.types.Collection,
|
||||
description="All objects in this collection will be override",
|
||||
)
|
||||
oboverride: bpy.props.PointerProperty(
|
||||
name="Object Override",
|
||||
type=bpy.types.Object,
|
||||
description="Only this object will be override.",
|
||||
)
|
||||
matoverride: bpy.props.PointerProperty(
|
||||
name="Material Override",
|
||||
type=bpy.types.Material,
|
||||
description="Material for override objects",
|
||||
)
|
||||
|
||||
bpy.utils.register_class(OscOverridesProp)
|
||||
bpy.types.Scene.ovlist = bpy.props.CollectionProperty(type=OscOverridesProp)
|
||||
|
||||
|
||||
class OVERRIDES_PT_OscOverridesGUI(bpy.types.Panel):
|
||||
bl_label = "Oscurart Material Overrides"
|
||||
bl_idname = "OVERRIDES_PT_layout"
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "render"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
def draw(self, context):
|
||||
|
||||
layout = self.layout
|
||||
col = layout.column(align=1)
|
||||
colrow = col.row(align=1)
|
||||
colrow.operator("render.overrides_add_slot")
|
||||
colrow.operator("render.overrides_remove_slot")
|
||||
col.operator("render.overrides_transfer")
|
||||
for i, m in enumerate(bpy.context.scene.ovlist):
|
||||
colrow = col.row(align=1)
|
||||
colrow.prop(m, "colloverride", text="")
|
||||
colrow.prop(m, "oboverride", text="")
|
||||
colrow.prop(m, "matoverride", text="")
|
||||
if i != len(bpy.context.scene.ovlist) - 1:
|
||||
pa = colrow.operator(
|
||||
"ovlist.move_down",
|
||||
text="",
|
||||
icon="TRIA_DOWN")
|
||||
pa.index = i
|
||||
if i > 0:
|
||||
p = colrow.operator("ovlist.move_up", text="", icon="TRIA_UP")
|
||||
p.index = i
|
||||
pb = colrow.operator("ovlist.kill", text="", icon="X")
|
||||
pb.index = i
|
||||
|
||||
|
||||
class OscTransferOverrides(bpy.types.Operator):
|
||||
"""Applies the previously configured slots (Groups < Material) to the Scene. """ \
|
||||
"""This should be transfer once the override groups are set"""
|
||||
bl_idname = "render.overrides_transfer"
|
||||
bl_label = "Transfer Overrides"
|
||||
|
||||
def execute(self, context):
|
||||
# CREO LISTA
|
||||
OSCOV = [[OVERRIDE.grooverride, OVERRIDE.matoverride]
|
||||
for OVERRIDE in bpy.context.scene.ovlist[:]
|
||||
if OVERRIDE.matoverride != "" and OVERRIDE.grooverride != ""]
|
||||
|
||||
bpy.context.scene.oscurart.overrides = str(OSCOV)
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
class OscAddOverridesSlot(bpy.types.Operator):
|
||||
"""Add override slot"""
|
||||
bl_idname = "render.overrides_add_slot"
|
||||
bl_label = "Add Override Slot"
|
||||
|
||||
def execute(self, context):
|
||||
prop = bpy.context.scene.ovlist.add()
|
||||
prop.matoverride = None
|
||||
prop.grooverride = None
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
class OscRemoveOverridesSlot(bpy.types.Operator):
|
||||
"""Remove override slot"""
|
||||
bl_idname = "render.overrides_remove_slot"
|
||||
bl_label = "Remove Override Slot"
|
||||
|
||||
def execute(self, context):
|
||||
context.scene.ovlist.remove(len(bpy.context.scene.ovlist) - 1)
|
||||
return {'FINISHED'}
|
||||
|
||||
class OscOverridesUp(bpy.types.Operator):
|
||||
"""Move override slot up"""
|
||||
bl_idname = 'ovlist.move_up'
|
||||
bl_label = 'Move Override up'
|
||||
bl_options = {'INTERNAL'}
|
||||
|
||||
index: bpy.props.IntProperty(min=0)
|
||||
|
||||
@classmethod
|
||||
def poll(self, context):
|
||||
return len(context.scene.ovlist)
|
||||
|
||||
def execute(self, context):
|
||||
ovlist = context.scene.ovlist
|
||||
ovlist.move(self.index, self.index - 1)
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
class OscOverridesDown(bpy.types.Operator):
|
||||
"""Move override slot down"""
|
||||
bl_idname = 'ovlist.move_down'
|
||||
bl_label = 'Move Override down'
|
||||
bl_options = {'INTERNAL'}
|
||||
|
||||
index: bpy.props.IntProperty(min=0)
|
||||
|
||||
@classmethod
|
||||
def poll(self, context):
|
||||
return len(context.scene.ovlist)
|
||||
|
||||
def execute(self, context):
|
||||
ovlist = context.scene.ovlist
|
||||
ovlist.move(self.index, self.index + 1)
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
class OscOverridesKill(bpy.types.Operator):
|
||||
"""Remove override slot"""
|
||||
bl_idname = 'ovlist.kill'
|
||||
bl_label = 'Kill Override'
|
||||
bl_options = {'INTERNAL'}
|
||||
|
||||
index: bpy.props.IntProperty(min=0)
|
||||
|
||||
@classmethod
|
||||
def poll(self, context):
|
||||
return len(context.scene.ovlist)
|
||||
|
||||
def execute(self, context):
|
||||
ovlist = context.scene.ovlist
|
||||
ovlist.remove(self.index)
|
||||
return {'FINISHED'}
|
|
@ -1,61 +0,0 @@
|
|||
# ##### 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.app.handlers import persistent
|
||||
|
||||
@persistent
|
||||
def replaceTokens (dummy):
|
||||
global renpath
|
||||
global nodeDict
|
||||
tokens = {
|
||||
"$Scene":bpy.context.scene.name,
|
||||
"$File":os.path.basename(bpy.data.filepath).split(".")[0],
|
||||
"$ViewLayer":bpy.context.view_layer.name,
|
||||
"$Camera": "NoCamera" if bpy.context.scene.camera == None else bpy.context.scene.camera.name}
|
||||
|
||||
renpath = bpy.context.scene.render.filepath
|
||||
|
||||
nodeDict = []
|
||||
#compositor nodes
|
||||
if bpy.context.scene.use_nodes:
|
||||
for node in bpy.context.scene.node_tree.nodes:
|
||||
if node.type == "OUTPUT_FILE":
|
||||
nodeDict.append([node,node.base_path])
|
||||
node.base_path = node.base_path.replace("$Scene",tokens["$Scene"]).replace("$File",tokens["$File"]).replace("$ViewLayer",tokens["$ViewLayer"]).replace("$Camera",tokens["$Camera"])
|
||||
|
||||
|
||||
|
||||
bpy.context.scene.render.filepath = renpath.replace("$Scene",tokens["$Scene"]).replace("$File",tokens["$File"]).replace("$ViewLayer",tokens["$ViewLayer"]).replace("$Camera",tokens["$Camera"])
|
||||
print(bpy.context.scene.render.filepath)
|
||||
|
||||
|
||||
@persistent
|
||||
def restoreTokens (dummy):
|
||||
global renpath
|
||||
bpy.context.scene.render.filepath = renpath
|
||||
|
||||
#restore nodes
|
||||
for node in nodeDict:
|
||||
node[0].base_path = node[1]
|
||||
|
||||
|
||||
# //RENDER/$Scene/$File/$ViewLayer/$Camera
|
Loading…
Reference in New Issue