Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlijenstina <lijenstina@gmail.com>2017-05-24 19:31:25 +0300
committerlijenstina <lijenstina@gmail.com>2017-05-24 19:31:25 +0300
commit331f2982d714f51cb6ded56b3f6b10ba004ff62f (patch)
treeb74d92ae548eb9f54980901b84f08c91aa1119ff
parent97bf32a8b84b7a9ef40b9406802f293e0280814f (diff)
Add Advanced Objects: Bump to ver. 0.1.3, Cleanup, Fixes
Bump version to 0.1.3 Cleanup - some style and UI modifications Improved Tooltips, add missing descriptions Menu and Panel Listing in the preferences Move scene props to init for proper reg - unreg Translate comments into English Fix several bugs with scripts: - Drop to ground: add missing poll for Drop all - Cubester: fix sound generation, missing checks for data move properties to __init__ together with the update functions - Make Struts: add a try block allows the global undo to be restored, fix division by zero error, add missing poll - rope_alpha: fix several crashes with hardcoded names on re-runs make the similation work for new scenes - Circle array: fix (flawed attempt) check for allowed types - Copy2: add check for properties passed, error handling, division by 0 on non mesh copy objects, add a missing poll - Unfold Transition: fix polls for active objects, division by 0 add a warning about selecting an another armature - oscurart_constellation: add a try block, move the prop to init - easy_lattice: simplify enumproperty, polling - Laplacian Lightning: prints are optional, API change to obj.raycast, UI refactor, move winmgr props to scene properties - add_light_template - try block, fix crash with constraints and no camera in the scene
-rw-r--r--add_advanced_objects/__init__.py669
-rw-r--r--add_advanced_objects/add_light_template.py187
-rw-r--r--add_advanced_objects/add_mesh_aggregate.py188
-rw-r--r--add_advanced_objects/arrange_on_curve.py165
-rw-r--r--add_advanced_objects/circle_array.py55
-rw-r--r--add_advanced_objects/copy2.py213
-rw-r--r--add_advanced_objects/cubester.py621
-rw-r--r--add_advanced_objects/delaunay_voronoi/DelaunayVoronoi.py16
-rw-r--r--add_advanced_objects/delaunay_voronoi/__init__.py3
-rw-r--r--add_advanced_objects/delaunay_voronoi/delaunayVoronoiBlender.py142
-rw-r--r--add_advanced_objects/delaunay_voronoi/oscurart_constellation.py63
-rw-r--r--add_advanced_objects/drop_to_ground.py97
-rw-r--r--add_advanced_objects/make_struts.py155
-rw-r--r--add_advanced_objects/mesh_easylattice.py96
-rw-r--r--add_advanced_objects/object_add_chain.py93
-rw-r--r--add_advanced_objects/object_laplace_lightning.py712
-rw-r--r--add_advanced_objects/object_mangle_tools.py134
-rw-r--r--add_advanced_objects/oscurart_chain_maker.py66
-rw-r--r--add_advanced_objects/pixelate_3d.py78
-rw-r--r--add_advanced_objects/random_box_structure.py164
-rw-r--r--add_advanced_objects/rope_alpha.py706
-rw-r--r--add_advanced_objects/scene_objects_bi.py332
-rw-r--r--add_advanced_objects/scene_objects_cycles.py244
-rw-r--r--add_advanced_objects/scene_texture_render.py104
-rw-r--r--add_advanced_objects/trilighting.py335
-rw-r--r--add_advanced_objects/unfold_transition.py263
26 files changed, 3340 insertions, 2561 deletions
diff --git a/add_advanced_objects/__init__.py b/add_advanced_objects/__init__.py
index 3c15d1b4..cad3c077 100644
--- a/add_advanced_objects/__init__.py
+++ b/add_advanced_objects/__init__.py
@@ -20,19 +20,18 @@
# meta-androcto, Bill Currie, Jorge Hernandez - Melenedez Jacob Morris, Oscurart #
# Rebellion, Antonis Karvelas, Eleanor Howick, lijenstina, Daniel Schalla, Domlysz #
# Unnikrishnan(kodemax), Florian Meyer, Omar ahmed, Brian Hinton (Nichod), liero #
-# Dannyboy, Mano-Wii, Kursad Karatas, teldredge
+# Atom, Dannyboy, Mano-Wii, Kursad Karatas, teldredge, Phil Cote #
bl_info = {
"name": "Add Advanced Objects",
"author": "Meta Androcto,",
- "version": (0, 1, 1),
+ "version": (0, 1, 3),
"blender": (2, 78, 0),
"location": "View3D > Add ",
"description": "Add Object & Camera extras",
"warning": "",
"wiki_url": "https://wiki.blender.org/index.php/Extensions:2.6"
"/Py/Scripts",
- "tracker_url": "",
"category": "Object"}
if "bpy" in locals():
@@ -64,46 +63,54 @@ if "bpy" in locals():
importlib.reload(oscurart_chain_maker)
else:
- from . import (
- add_light_template,
- scene_objects_bi,
- scene_objects_cycles,
- scene_texture_render,
- trilighting,
- pixelate_3d,
- object_add_chain,
- oscurart_chain_maker,
- drop_to_ground,
- circle_array,
- unfold_transition,
- copy2,
- make_struts,
- random_box_structure,
- cubester,
- rope_alpha,
- add_mesh_aggregate,
- object_mangle_tools,
- arrange_on_curve,
- object_laplace_lightning,
- mesh_easylattice
- )
- from .delaunay_voronoi import (
- DelaunayVoronoi,
- delaunayVoronoiBlender,
- oscurart_constellation
- )
+ from . import add_light_template
+ from . import scene_objects_bi
+ from . import scene_objects_cycles
+ from . import scene_texture_render
+ from . import trilighting
+ from . import pixelate_3d
+ from . import object_add_chain
+ from . import oscurart_chain_maker
+ from . import drop_to_ground
+ from . import circle_array
+ from . import unfold_transition
+ from . import copy2
+ from . import make_struts
+ from . import random_box_structure
+ from . import cubester
+ from . import rope_alpha
+ from . import add_mesh_aggregate
+ from . import object_mangle_tools
+ from . import arrange_on_curve
+ from . import object_laplace_lightning
+ from . import mesh_easylattice
+
+ from .delaunay_voronoi import DelaunayVoronoi
+ from .delaunay_voronoi import delaunayVoronoiBlender
+ from .delaunay_voronoi import oscurart_constellation
import bpy
from bpy.types import (
Menu,
AddonPreferences,
+ PropertyGroup,
+ )
+from bpy.props import (
+ BoolProperty,
+ BoolVectorProperty,
+ EnumProperty,
+ FloatProperty,
+ FloatVectorProperty,
+ IntProperty,
+ StringProperty,
+ PointerProperty,
)
+# Define the "Scenes" menu
class INFO_MT_scene_elements_add(Menu):
- # Define the "scenes" menu
bl_idname = "INFO_MT_scene_elements"
- bl_label = "Test scenes"
+ bl_label = "Test Scenes"
def draw(self, context):
layout = self.layout
@@ -116,8 +123,8 @@ class INFO_MT_scene_elements_add(Menu):
text="Scene_Textures_Cycles")
+# Define the "Lights" menu
class INFO_MT_mesh_lamps_add(Menu):
- # Define the "lights" menu
bl_idname = "INFO_MT_scene_lamps"
bl_label = "Lighting Sets"
@@ -130,8 +137,8 @@ class INFO_MT_mesh_lamps_add(Menu):
text="Add Tri Lighting")
+# Define the "Chains" menu
class INFO_MT_mesh_chain_add(Menu):
- # Define the "Chains" menu
bl_idname = "INFO_MT_mesh_chain"
bl_label = "Chains"
@@ -142,47 +149,45 @@ class INFO_MT_mesh_chain_add(Menu):
layout.operator("mesh.primitive_oscurart_chain_add", icon="LINKED")
+# Define the "Array" Menu
class INFO_MT_array_mods_add(Menu):
- # Define the "array" menu
bl_idname = "INFO_MT_array_mods"
bl_label = "Array Mods"
def draw(self, context):
layout = self.layout
layout.operator_context = 'INVOKE_REGION_WIN'
- self.layout.menu("INFO_MT_mesh_chain", icon="LINKED")
+
+ layout.menu("INFO_MT_mesh_chain", icon="LINKED")
+
layout.operator("objects.circle_array_operator",
- text="Circle Array", icon='MOD_ARRAY')
+ text="Circle Array", icon="MOD_ARRAY")
layout.operator("object.agregate_mesh",
- text="Aggregate Mesh", icon='MOD_ARRAY')
- obj = context.object
- if obj.type in ['MESH',]:
- layout.operator("mesh.copy2",
- text="Copy To Vert/Edge", icon='MOD_ARRAY')
-
+ text="Aggregate Mesh", icon="MOD_ARRAY")
+ layout.operator("mesh.copy2",
+ text="Copy To Vert/Edge", icon="MOD_ARRAY")
+# Define the "Blocks" Menu
class INFO_MT_quick_blocks_add(Menu):
- # Define the "Blocks" menu
bl_idname = "INFO_MT_quick_tools"
bl_label = "Block Tools"
def draw(self, context):
layout = self.layout
layout.operator_context = 'INVOKE_REGION_WIN'
- layout.operator('object.pixelate', icon='MESH_GRID')
- obj = context.object
- if obj.type in ['MESH',]:
- layout.operator("mesh.generate_struts",
- text="Struts", icon='GRID')
- layout.operator("object.easy_lattice",
- text="Easy Lattice", icon='MOD_LATTICE')
- layout.operator("object.make_structure",
- text="Random Boxes", icon='SEQ_SEQUENCER')
+ layout.operator("object.pixelate", icon="MESH_GRID")
+ layout.operator("mesh.generate_struts",
+ text="Struts", icon="GRID")
+ layout.operator("object.make_structure",
+ text="Random Boxes", icon="SEQ_SEQUENCER")
+ layout.operator("object.easy_lattice",
+ text="Easy Lattice", icon="MOD_LATTICE")
+
+# Define the "Phsysics Tools" Menu
class INFO_MT_Physics_tools_add(Menu):
- # Define the "mesh objects" menu
bl_idname = "INFO_MT_physics_tools"
bl_label = "Physics Tools"
@@ -190,7 +195,7 @@ class INFO_MT_Physics_tools_add(Menu):
layout = self.layout
layout.operator_context = 'INVOKE_REGION_WIN'
layout.operator("object.drop_on_active",
- text="Drop To Ground")
+ text="Drop To Ground", icon="SORTSIZE")
layout.operator("ball.rope",
text="Wrecking Ball", icon='PHYSICS')
layout.operator("clot.rope",
@@ -211,22 +216,551 @@ def menu(self, context):
# Addons Preferences
-class AddonPreferences(AddonPreferences):
+class AdvancedObjPreferences(AddonPreferences):
bl_idname = __name__
+ show_menu_list = BoolProperty(
+ name="Menu List",
+ description="Show/Hide the Add Menu items",
+ default=False
+ )
+ show_panel_list = BoolProperty(
+ name="Panels List",
+ description="Show/Hide the Panel items",
+ default=False
+ )
+
def draw(self, context):
layout = self.layout
- layout.label(text="----Add Menu Advanced----")
- layout.label(text="Quick Tools:")
- layout.label(text="Drop, Pixelate & Wrecking Ball")
- layout.label(text="Array Mods:")
- layout.label(text="Circle Array, Chains, Vert to Edge, Aggregate")
+
+ icon_1 = "TRIA_RIGHT" if not self.show_menu_list else "TRIA_DOWN"
+ box = layout.box()
+ box.prop(self, "show_menu_list", emboss=False, icon=icon_1)
+
+ if self.show_menu_list:
+ box.label(text="Items located in the Add Menu (default shortcut Ctrl + A):",
+ icon="LAYER_USED")
+ box.label(text="Test Scenes:", icon="LAYER_ACTIVE")
+ box.label(text="Scene Objects BI, Scene Objects Cycles, Scene Textures Cycles",
+ icon="LAYER_USED")
+ box.label(text="Lighting Sets:", icon="LAYER_ACTIVE")
+ box.label(text="Add Light Template, Add Tri Lighting", icon="LAYER_USED")
+ box.label(text="Array Mods:", icon="LAYER_ACTIVE")
+ box.label(text="Circle Array, Chains submenu, Copy Vert/Edge and Aggregate Mesh",
+ icon="LAYER_ACTIVE")
+ box.label(text="Chains Submenu - Add Chain, Chain to Bones",
+ icon="LAYER_ACTIVE")
+ box.label(text="Block Tools:", icon="LAYER_ACTIVE")
+ box.label(text="Pixelate Object, Struts, Random Boxes, Easy Lattice",
+ icon="LAYER_USED")
+ box.label(text="Physics Tools:", icon="LAYER_ACTIVE")
+ box.label(text="Drop to Ground, Wrecking Ball and Cloth Rope", icon="LAYER_USED")
+
+ icon_2 = "TRIA_RIGHT" if not self.show_panel_list else "TRIA_DOWN"
+ box = layout.box()
+ box.prop(self, "show_panel_list", emboss=False, icon=icon_2)
+
+ if self.show_panel_list:
+ box.label(text="Panels located in 3D View Tools Region > Create",
+ icon="LAYER_ACTIVE")
+ box.label(text="Drop to Ground", icon="LAYER_USED")
+ box.label(text="Unfold Transition", icon="LAYER_USED")
+ box.label(text="CubeSter", icon="LAYER_USED")
+ box.label(text="Mangle tools", icon="LAYER_USED")
+ box.label(text="Laplacian Lighting", icon="LAYER_USED")
+ box.label(text="Delaunay Voronoi", icon="LAYER_USED")
+ box.label(text="Duplicate on Curve (Shown if an Active Curve Object is it the 3D View)",
+ icon="LAYER_USED")
+
+
+# Cubester update functions
+def find_audio_length(self, context):
+ adv_obj = context.scene.advanced_objects
+ audio_file = adv_obj.cubester_audio_path
+ length = 0
+
+ if audio_file != "":
+ # confirm that strip hasn't been loaded yet
+ get_sequence = getattr(context.scene.sequence_editor, "sequences_all", [])
+ for strip in get_sequence:
+ if type(strip) == bpy.types.SoundSequence and strip.sound.filepath == audio_file:
+ length = strip.frame_final_duration
+
+ if length == 0:
+ area = context.area
+ old_type = area.type
+ area.type = "SEQUENCE_EDITOR"
+ try:
+ bpy.ops.sequencer.sound_strip_add(filepath=audio_file)
+ adv_obj.cubester_check_audio = True
+ except Exception as e:
+ print("\n[Add Advanced Objects]\n Function: "
+ "find_audio_length\n {}\n".format(e))
+ adv_obj.cubester_check_audio = False
+ pass
+
+ area.type = old_type
+
+ # find audio file
+ for strip in context.scene.sequence_editor.sequences_all:
+ if type(strip) == bpy.types.SoundSequence and strip.sound.filepath == audio_file:
+ adv_obj.cubester_check_audio = True
+ length = strip.frame_final_duration
+
+ adv_obj.cubester_audio_file_length = length
+
+
+# load image if possible
+def adjust_selected_image(self, context):
+ scene = context.scene.advanced_objects
+ try:
+ image = bpy.data.images.load(scene.cubester_load_image)
+ scene.cubester_image = image.name
+ except Exception as e:
+ print("\n[Add Advanced Objects]\n Function: "
+ "adjust_selected_image\n {}\n".format(e))
+
+
+# load color image if possible
+def adjust_selected_color_image(self, context):
+ scene = context.scene.advanced_objects
+ try:
+ image = bpy.data.images.load(scene.cubester_load_color_image)
+ scene.cubester_color_image = image.name
+ except Exception as e:
+ print("\nAdd Advanced Objects]\n Function: "
+ "adjust_selected_color_image\n {}\n".format(e))
+
+
+class AdvancedObjProperties(PropertyGroup):
+ # cubester
+ # main properties
+ cubester_check_audio = BoolProperty(
+ name="",
+ default=False
+ )
+ cubester_audio_image = EnumProperty(
+ name="Input Type",
+ items=(("image", "Image",
+ "Use an Image as input for generating Geometry", "IMAGE_COL", 0),
+ ("audio", "Audio",
+ "Use a Sound Strip as input for generating Geometry", "FILE_SOUND", 1))
+ )
+ cubester_audio_file_length = IntProperty(
+ default=0
+ )
+ # audio
+ cubester_audio_path = StringProperty(
+ default="",
+ name="Audio File",
+ subtype="FILE_PATH",
+ update=find_audio_length
+ )
+ cubester_audio_min_freq = IntProperty(
+ name="Minimum Frequency",
+ min=20, max=100000,
+ default=20
+ )
+ cubester_audio_max_freq = IntProperty(
+ name="Maximum Frequency",
+ min=21, max=999999,
+ default=5000
+ )
+ cubester_audio_offset_type = EnumProperty(
+ name="Offset Type",
+ items=(("freq", "Frequency Offset", ""),
+ ("frame", "Frame Offset", "")),
+ description="Type of offset per row of mesh"
+ )
+ cubester_audio_frame_offset = IntProperty(
+ name="Frame Offset",
+ min=0, max=10,
+ default=2
+ )
+ cubester_audio_block_layout = EnumProperty(
+ name="Block Layout",
+ items=(("rectangle", "Rectangular", ""),
+ ("radial", "Radial", ""))
+ )
+ cubester_audio_width_blocks = IntProperty(
+ name="Width Block Count",
+ min=1, max=10000,
+ default=5
+ )
+ cubester_audio_length_blocks = IntProperty(
+ name="Length Block Count",
+ min=1, max=10000,
+ default=50
+ )
+ # image
+ cubester_load_type = EnumProperty(
+ name="Image Input Type",
+ items=(("single", "Single Image", ""),
+ ("multiple", "Image Sequence", ""))
+ )
+ cubester_image = StringProperty(
+ default="",
+ name=""
+ )
+ cubester_load_image = StringProperty(
+ default="",
+ name="Load Image",
+ subtype="FILE_PATH",
+ update=adjust_selected_image
+ )
+ cubester_skip_images = IntProperty(
+ name="Image Step",
+ min=1, max=30,
+ default=1,
+ description="Step from image to image by this number"
+ )
+ cubester_max_images = IntProperty(
+ name="Max Number Of Images",
+ min=2, max=1000,
+ default=10,
+ description="Maximum number of images to be used"
+ )
+ cubester_frame_step = IntProperty(
+ name="Frame Step Size",
+ min=1, max=10,
+ default=4,
+ description="The number of frames each picture is used"
+ )
+ cubester_skip_pixels = IntProperty(
+ name="Skip # Pixels",
+ min=0, max=256,
+ default=64,
+ description="Skip this number of pixels before placing the next"
+ )
+ cubester_mesh_style = EnumProperty(
+ name="Mesh Type",
+ items=(("blocks", "Blocks", ""),
+ ("plane", "Plane", "")),
+ description="Compose mesh of multiple blocks or of a single plane"
+ )
+ cubester_block_style = EnumProperty(
+ name="Block Style",
+ items=(("size", "Vary Size", ""),
+ ("position", "Vary Position", "")),
+ description="Vary Z-size of block, or vary Z-position"
+ )
+ cubester_height_scale = FloatProperty(
+ name="Height Scale",
+ subtype="DISTANCE",
+ min=0.1, max=2,
+ default=0.2
+ )
+ cubester_invert = BoolProperty(
+ name="Invert Height",
+ default=False
+ )
+ # general adjustments
+ cubester_size_per_hundred_pixels = FloatProperty(
+ name="Size Per 100 Blocks/Points",
+ subtype="DISTANCE",
+ min=0.001, max=5,
+ default=1
+ )
+ # material based stuff
+ cubester_materials = EnumProperty(
+ name="Material",
+ items=(("vertex", "Vertex Colors", ""),
+ ("image", "Image", "")),
+ description="Color with vertex colors, or uv unwrap and use an image"
+ )
+ cubester_use_image_color = BoolProperty(
+ name="Use Original Image Colors'?",
+ default=True,
+ description="Use original image colors, or replace with an another one"
+ )
+ cubester_color_image = StringProperty(
+ default="",
+ name=""
+ )
+ cubester_load_color_image = StringProperty(
+ default="",
+ name="Load Color Image",
+ subtype="FILE_PATH",
+ update=adjust_selected_color_image
+ )
+ cubester_vertex_colors = {}
+ # advanced
+ cubester_advanced = BoolProperty(
+ name="Advanced Options",
+ default=False
+ )
+ cubester_random_weights = BoolProperty(
+ name="Random Weights",
+ default=False
+ )
+ cubester_weight_r = FloatProperty(
+ name="Red",
+ subtype="FACTOR",
+ min=0.01, max=1.0,
+ default=0.25
+ )
+ cubester_weight_g = FloatProperty(
+ name="Green",
+ subtype="FACTOR",
+ min=0.01, max=1.0,
+ default=0.25
+ )
+ cubester_weight_b = FloatProperty(
+ name="Blue",
+ subtype="FACTOR",
+ min=0.01, max=1.0,
+ default=0.25
+ )
+ cubester_weight_a = FloatProperty(
+ name="Alpha",
+ subtype="FACTOR",
+ min=0.01, max=1.0,
+ default=0.25
+ )
+
+ # pixelate_3d properties
+ pixelate_3d_size = FloatProperty(
+ name="Size",
+ min=.05, max=5,
+ default=.25,
+ description="Size of the cube / grid"
+ )
+ pixelate_3d_gap = IntProperty(
+ name="Gap",
+ min=0, max=90,
+ default=10,
+ subtype='PERCENTAGE',
+ description="Separation - percent of size"
+ )
+ pixelate_3d_smooth = FloatProperty(
+ name="Smooth",
+ min=0, max=1,
+ default=.0,
+ description="Smooth factor when subdividing mesh"
+ )
+ # arrange_on_curve
+ arrange_c_use_selected = BoolProperty(
+ name="Use Selected",
+ description="Use the selected objects to duplicate",
+ default=True,
+ )
+ arrange_c_obj_arranjar = StringProperty(
+ name=""
+ )
+ arrange_c_select_type = EnumProperty(
+ name="Type",
+ description="Select object or group",
+ items=[
+ ('O', "Object", "Make duplicates of a specific object"),
+ ('G', "Group", "Make duplicates of the objects in a group"),
+ ],
+ default='O',
+ )
+ # object_laplace_lighting props
+ ORIGIN = FloatVectorProperty(
+ name="Origin charge"
+ )
+ GROUNDZ = IntProperty(
+ name="Ground Z coordinate"
+ )
+ HORDER = IntProperty(
+ name="Secondary paths orders",
+ default=1
+ )
+ # object_laplace_lighting UI props
+ TSTEPS = IntProperty(
+ name="Iterations",
+ default=350,
+ description="Number of cells to create\n"
+ "Will end early if hits ground plane or cloud"
+ )
+ GSCALE = FloatProperty(
+ name="Grid unit size",
+ default=0.12,
+ description="scale of cells, .25 = 4 cells per blenderUnit"
+ )
+ BIGVAR = FloatProperty(
+ name="Straightness",
+ default=6.3,
+ description="Straightness/branchiness of bolt, \n"
+ "<2 is mush, >12 is staight line, 6.3 is good"
+ )
+ GROUNDBOOL = BoolProperty(
+ name="Use Ground object",
+ description="Use ground plane or not",
+ default=True
+ )
+ GROUNDC = IntProperty(
+ name="Ground charge",
+ default=-250,
+ description="Charge of the ground plane"
+ )
+ CLOUDBOOL = BoolProperty(
+ name="Use Cloud object",
+ default=False,
+ description="Use cloud object - attracts and terminates like ground but\n"
+ "any obj instead of z plane\n"
+ "Can slow down loop if obj is large, overrides ground"
+ )
+ CLOUDC = IntProperty(
+ name="Cloud charge",
+ default=-1,
+ description="Charge of a cell in cloud object\n"
+ "(so total charge also depends on obj size)"
+ )
+ VMMESH = BoolProperty(
+ name="Multi mesh",
+ default=True,
+ description="Output to multi-meshes for different materials on main/sec/side branches"
+ )
+ VSMESH = BoolProperty(
+ name="Single mesh",
+ default=False,
+ description="Output to single mesh for using build modifier and particles for effects"
+ )
+ VCUBE = BoolProperty(
+ name="Cubes",
+ default=False,
+ description="CTRL-J after run to JOIN\n"
+ "Outputs a bunch of cube objects, mostly for testing"
+ )
+ VVOX = BoolProperty(
+ name="Voxel (experimental)",
+ default=False,
+ description="Output to a voxel file to bpy.data.filepath\FSLGvoxels.raw\n"
+ "(doesn't work well right now)"
+ )
+ IBOOL = BoolProperty(
+ name="Use Insulator object",
+ default=False,
+ description="Use insulator mesh object to prevent growth of bolt in areas"
+ )
+ OOB = StringProperty(
+ name="Select",
+ default="",
+ description="Origin of bolt, can be an Empty\n"
+ "if object is a mesh will use all verts as charges")
+ GOB = StringProperty(
+ name="Select",
+ default="",
+ description="Object to use as ground plane, uses z coord only"
+ )
+ COB = StringProperty(
+ name="Select",
+ default="",
+ description="Object to use as cloud, best to use a cube"
+ )
+ IOB = StringProperty(
+ name="Select",
+ default="",
+ description="Object to use as insulator, 'voxelized'\n"
+ "before generating bolt (can be slow)"
+ )
+ # object_mangle_tools properties
+ mangle_constraint_vector = BoolVectorProperty(
+ name="Mangle Constraint",
+ default=(True, True, True),
+ subtype='XYZ',
+ description="Constrains Mangle Direction"
+ )
+ mangle_random_magnitude = IntProperty(
+ name="Mangle Severity",
+ default=5,
+ min=1, max=30,
+ description="Severity of mangling"
+ )
+ mangle_name = StringProperty(
+ name="Shape Key Name",
+ default="mangle",
+ description="Name given for mangled shape keys"
+ )
+ # unfold_transition properties
+ unfold_arm_name = StringProperty(
+ default=""
+ )
+ unfold_modo = EnumProperty(
+ name="",
+ items=[("cursor", "3D Cursor", "Use the Distance to 3D Cursor"),
+ ("weight", "Weight Map", "Use a Painted Weight map"),
+ ("index", "Mesh Indices", "Use Faces and Vertices index")],
+ description="How to Sort Bones for animation", default="cursor"
+ )
+ unfold_flip = BoolProperty(
+ name="Flipping Faces",
+ default=False,
+ description="Rotate faces around the Center and skip Scaling - "
+ "keep checked for both operators"
+ )
+ unfold_fold_duration = IntProperty(
+ name="Total Time",
+ min=5, soft_min=25,
+ max=10000, soft_max=2500,
+ default=200,
+ description="Total animation length"
+ )
+ unfold_sca_time = IntProperty(
+ name="Scale Time",
+ min=1,
+ max=5000, soft_max=500,
+ default=10,
+ description="Faces scaling time"
+ )
+ unfold_rot_time = IntProperty(
+ name="Rotation Time",
+ min=1, soft_min=5,
+ max=5000, soft_max=500,
+ default=15,
+ description="Faces rotation time"
+ )
+ unfold_rot_max = IntProperty(
+ name="Angle",
+ min=-180,
+ max=180,
+ default=135,
+ description="Faces rotation angle"
+ )
+ unfold_fold_noise = IntProperty(
+ name="Noise",
+ min=0,
+ max=500, soft_max=50,
+ default=0,
+ description="Offset some faces animation"
+ )
+ unfold_bounce = FloatProperty(
+ name="Bounce",
+ min=0,
+ max=10, soft_max=2.5,
+ default=0,
+ description="Add some bounce to rotation"
+ )
+ unfold_from_point = BoolProperty(
+ name="Point",
+ default=False,
+ description="Scale faces from a Point instead of from an Edge"
+ )
+ unfold_wiggle_rot = BoolProperty(
+ name="Wiggle",
+ default=False,
+ description="Use all Axis + Random Rotation instead of X Aligned"
+ )
+ # oscurart_constellation
+ constellation_limit = FloatProperty(
+ name="Inital Threshold",
+ description="Edges will be created only if the distance\n"
+ "between vertices is smaller than this value\n"
+ "This is a starting value on Operator Invoke",
+ default=2,
+ min=0
+ )
def register():
- object_mangle_tools.register()
- arrange_on_curve.register()
bpy.utils.register_module(__name__)
+
+ bpy.types.Scene.advanced_objects = PointerProperty(
+ type=AdvancedObjProperties
+ )
+
# Add "Extras" menu to the "Add" menu
bpy.types.INFO_MT_add.append(menu)
try:
@@ -236,8 +770,6 @@ def register():
def unregister():
- object_mangle_tools.unregister()
- arrange_on_curve.unregister()
# Remove "Extras" menu from the "Add" menu.
bpy.types.INFO_MT_add.remove(menu)
try:
@@ -246,6 +778,11 @@ def unregister():
pass
bpy.utils.unregister_module(__name__)
+ del bpy.types.Scene.advanced_objects
+
+ # cleanup Easy Lattice Scene Property if it was created
+ if hasattr(bpy.types.Scene, "activelatticeobject"):
+ del bpy.types.Scene.activelatticeobject
if __name__ == "__main__":
diff --git a/add_advanced_objects/add_light_template.py b/add_advanced_objects/add_light_template.py
index 312b2d9e..9e2c139f 100644
--- a/add_advanced_objects/add_light_template.py
+++ b/add_advanced_objects/add_light_template.py
@@ -6,120 +6,129 @@ from bpy.props import BoolProperty
def add_lamps(self, context):
- try:
- if self.bKeyLight:
- keyLight = bpy.data.lamps.new(name="Key_Light", type="SPOT")
- ob = bpy.data.objects.new("Key_Light", keyLight)
- constraint = ob.constraints.new(type='COPY_LOCATION')
- constraint.use_offset = True
- constraint.owner_space = 'LOCAL'
- constraint.target = self.camera
- constraint = ob.constraints.new(type='TRACK_TO')
- constraint.target = self.target
- constraint.track_axis = 'TRACK_NEGATIVE_Z'
- constraint.up_axis = 'UP_X'
- constraint.owner_space = 'LOCAL'
- bpy.context.scene.objects.link(ob)
- ob.rotation_euler[2] = -0.785398
-
- if self.bFillLight:
- fillLight = bpy.data.lamps.new(name="Fill_Light", type="SPOT")
- ob = bpy.data.objects.new("Fill_Light", fillLight)
- constraint = ob.constraints.new(type='COPY_LOCATION')
- constraint.use_offset = True
- constraint.owner_space = 'LOCAL'
- constraint.target = self.camera
- constraint = ob.constraints.new(type='TRACK_TO')
- constraint.target = self.target
- constraint.track_axis = 'TRACK_NEGATIVE_Z'
- constraint.up_axis = 'UP_X'
- constraint.owner_space = 'LOCAL'
- bpy.context.scene.objects.link(ob)
- ob.rotation_euler[2] = 0.785398
- ob.data.energy = 0.3
-
- if self.bBackLight:
- backLight = bpy.data.lamps.new(name="Back_Light", type="SPOT")
- ob = bpy.data.objects.new("Back_Light", backLight)
- constraint = ob.constraints.new(type='COPY_LOCATION')
- constraint.use_offset = True
- constraint.owner_space = 'LOCAL'
- constraint.target = self.camera
- constraint = ob.constraints.new(type='TRACK_TO')
- constraint.target = self.target
- constraint.track_axis = 'TRACK_NEGATIVE_Z'
- constraint.up_axis = 'UP_X'
- constraint.owner_space = 'LOCAL'
- bpy.context.scene.objects.link(ob)
- ob.rotation_euler[2] = 3.14159
- ob.data.energy = 0.2
-
- if self.camera_constraint:
- constraint = self.camera.constraints.new(type='TRACK_TO')
- constraint.target = self.target
- constraint.track_axis = 'TRACK_NEGATIVE_Z'
- constraint.up_axis = 'UP_Y'
-
- except Exception as e:
- self.report({'WARNING'},
- "Some operations could not be performed (See Console for more info)")
-
- print("\n[object.add_light_template]\nError: {}".format(e))
+
+ if self.bKeyLight:
+ keyLight = bpy.data.lamps.new(name="Key_Light", type="SPOT")
+ ob = bpy.data.objects.new("Key_Light", keyLight)
+ constraint = ob.constraints.new(type='COPY_LOCATION')
+ constraint.use_offset = True
+ constraint.owner_space = 'LOCAL'
+ constraint.target = self.camera
+ constraint = ob.constraints.new(type='TRACK_TO')
+ constraint.target = self.target
+ constraint.track_axis = 'TRACK_NEGATIVE_Z'
+ constraint.up_axis = 'UP_X'
+ constraint.owner_space = 'LOCAL'
+ bpy.context.scene.objects.link(ob)
+ ob.rotation_euler[2] = -0.785398
+
+ if self.bFillLight:
+ fillLight = bpy.data.lamps.new(name="Fill_Light", type="SPOT")
+ ob = bpy.data.objects.new("Fill_Light", fillLight)
+ constraint = ob.constraints.new(type='COPY_LOCATION')
+ constraint.use_offset = True
+ constraint.owner_space = 'LOCAL'
+ constraint.target = self.camera
+ constraint = ob.constraints.new(type='TRACK_TO')
+ constraint.target = self.target
+ constraint.track_axis = 'TRACK_NEGATIVE_Z'
+ constraint.up_axis = 'UP_X'
+ constraint.owner_space = 'LOCAL'
+ bpy.context.scene.objects.link(ob)
+ ob.rotation_euler[2] = 0.785398
+ ob.data.energy = 0.3
+
+ if self.bBackLight:
+ backLight = bpy.data.lamps.new(name="Back_Light", type="SPOT")
+ ob = bpy.data.objects.new("Back_Light", backLight)
+ constraint = ob.constraints.new(type='COPY_LOCATION')
+ constraint.use_offset = True
+ constraint.owner_space = 'LOCAL'
+ constraint.target = self.camera
+ constraint = ob.constraints.new(type='TRACK_TO')
+ constraint.target = self.target
+ constraint.track_axis = 'TRACK_NEGATIVE_Z'
+ constraint.up_axis = 'UP_X'
+ constraint.owner_space = 'LOCAL'
+ bpy.context.scene.objects.link(ob)
+ ob.rotation_euler[2] = 3.14159
+ ob.data.energy = 0.2
+
+ if self.camera_constraint and self.camera is not None and \
+ self.camera.type == "CAMERA":
+
+ constraint = self.camera.constraints.new(type='TRACK_TO')
+ constraint.target = self.target
+ constraint.track_axis = 'TRACK_NEGATIVE_Z'
+ constraint.up_axis = 'UP_Y'
class OBJECT_OT_add_light_template(Operator):
bl_idname = "object.add_light_template"
bl_label = "Add Light Template"
- bl_description = "Add Key, Fill & Back Lights"
+ bl_description = ("Add Key, Fill and Back Lights to the Scene\n"
+ "Needs an existing Active Object")
bl_options = {'REGISTER', 'UNDO'}
camera = None
target = None
bKeyLight = BoolProperty(
- name="Key Light",
- default=True
- )
+ name="Key Light",
+ description="Enable Key Light in the Scene",
+ default=True
+ )
bFillLight = BoolProperty(
- name="Fill Light",
- default=True
- )
+ name="Fill Light",
+ description="Enable Fill Light in the Scene",
+ default=True
+ )
bBackLight = BoolProperty(
- name="Back Light",
- default=True
- )
+ name="Back Light",
+ description="Enable Back Light in the Scene",
+ default=True
+ )
camera_constraint = BoolProperty(
- name="Camera Constraint",
- default=False
- )
+ name="Camera Constraint",
+ description="Add a Constraint to the Camera Object",
+ default=False
+ )
@classmethod
def poll(cls, context):
return context.active_object is not None
def execute(self, context):
- objects = context.selected_objects
-
- if len(objects) == 2:
- for ob in objects:
- if ob.type == 'CAMERA':
- self.camera = ob
+ try:
+ objects = context.selected_objects
+
+ if len(objects) == 2:
+ for ob in objects:
+ if ob.type == 'CAMERA':
+ self.camera = ob
+ else:
+ self.target = ob
+ elif len(objects) == 1:
+ if objects[0].type == 'CAMERA':
+ self.camera = objects[0]
+ bpy.ops.object.empty_add()
+ self.target = context.active_object
else:
- self.target = ob
- elif len(objects) == 1:
- if objects[0].type == 'CAMERA':
- self.camera = objects[0]
+ self.camera = context.scene.camera
+ self.target = context.active_object
+ elif len(objects) == 0:
bpy.ops.object.empty_add()
self.target = context.active_object
- else:
self.camera = context.scene.camera
- self.target = context.active_object
- elif len(objects) == 0:
- bpy.ops.object.empty_add()
- self.target = context.active_object
- self.camera = context.scene.camera
- add_lamps(self, context)
+ add_lamps(self, context)
+
+ except Exception as e:
+ self.report({'WARNING'},
+ "Some operations could not be performed (See Console for more info)")
+
+ print("\n[Add Advanced Objects]\nOperator: "
+ "object.add_light_template\nError: {}".format(e))
return {'FINISHED'}
diff --git a/add_advanced_objects/add_mesh_aggregate.py b/add_advanced_objects/add_mesh_aggregate.py
index e2ac5f07..6072cb9c 100644
--- a/add_advanced_objects/add_mesh_aggregate.py
+++ b/add_advanced_objects/add_mesh_aggregate.py
@@ -72,107 +72,108 @@ class OBJECT_OT_agregate_mesh(Operator):
bl_options = {'REGISTER', 'UNDO', 'PRESET'}
volX = FloatProperty(
- name="Volume X",
- min=0.1, max=25,
- default=3,
- description="The cloud around cursor"
- )
+ name="Volume X",
+ min=0.1, max=25,
+ default=3,
+ description="The cloud around cursor"
+ )
volY = FloatProperty(
- name="Volume Y",
- min=0.1, max=25,
- default=3,
- description="The cloud around cursor"
- )
+ name="Volume Y",
+ min=0.1, max=25,
+ default=3,
+ description="The cloud around cursor"
+ )
volZ = FloatProperty(
- name="Volume Z",
- min=0.1, max=25,
- default=3,
- description="The cloud around cursor"
- )
+ name="Volume Z",
+ min=0.1, max=25,
+ default=3,
+ description="The cloud around cursor"
+ )
baseSca = FloatProperty(
- name="Scale",
- min=0.01, max=5,
- default=.25,
- description="Particle Scale"
- )
+ name="Scale",
+ min=0.01, max=5,
+ default=.25,
+ description="Particle Scale"
+ )
varSca = FloatProperty(
- name="Var",
- min=0, max=1,
- default=0,
- description="Particle Scale Variation"
- )
+ name="Var",
+ min=0, max=1,
+ default=0,
+ description="Particle Scale Variation"
+ )
rotX = FloatProperty(
- name="Rot Var X",
- min=0, max=2,
- default=0,
- description="X Rotation Variation"
- )
+ name="Rot Var X",
+ min=0, max=2,
+ default=0,
+ description="X Rotation Variation"
+ )
rotY = FloatProperty(
- name="Rot Var Y",
- min=0, max=2,
- default=0,
- description="Y Rotation Variation"
- )
+ name="Rot Var Y",
+ min=0, max=2,
+ default=0,
+ description="Y Rotation Variation"
+ )
rotZ = FloatProperty(
- name="Rot Var Z",
- min=0, max=2,
- default=1,
- description="Z Rotation Variation"
- )
+ name="Rot Var Z",
+ min=0, max=2,
+ default=1,
+ description="Z Rotation Variation"
+ )
rSeed = IntProperty(
- name="Random seed",
- min=0, max=999999,
- default=1,
- description="Seed to feed random values"
- )
+ name="Random seed",
+ min=0, max=999999,
+ default=1,
+ description="Seed to feed random values"
+ )
numP = IntProperty(
- name="Number",
- min=1,
- max=9999, soft_max=500,
- default=50,
- description="Number of particles"
- )
+ name="Number",
+ min=1,
+ max=9999, soft_max=500,
+ default=50,
+ description="Number of particles"
+ )
nor = BoolProperty(
- name="Normal Oriented",
- default=False,
- description="Align Z axis with Faces normals"
- )
+ name="Normal Oriented",
+ default=False,
+ description="Align Z axis with Faces normals"
+ )
cent = BoolProperty(
- name="Use Face Center",
- default=False,
- description="Center on Faces"
- )
+ name="Use Face Center",
+ default=False,
+ description="Center on Faces"
+ )
track = BoolProperty(
- name="Cursor Follows",
- default=False,
- description="Cursor moves as structure grows / more compact results"
- )
+ name="Cursor Follows",
+ default=False,
+ description="Cursor moves as structure grows / more compact results"
+ )
anim = BoolProperty(
- name="Animatable",
- default=False,
- description="Sort faces so you can regrow with Build Modifier, materials are lost"
- )
-
- refresh = bpy.props.BoolProperty(
- name="Update",
- default=False
- )
- auto_refresh = bpy.props.BoolProperty(
- name="Auto",
- description="Auto update spline",
- default=False
- )
+ name="Animatable",
+ default=False,
+ description="Sort faces so you can regrow with Build Modifier, materials are lost"
+ )
+ refresh = BoolProperty(
+ name="Update",
+ default=False
+ )
+ auto_refresh = BoolProperty(
+ name="Auto",
+ description="Auto update spline",
+ default=False
+ )
def draw(self, context):
layout = self.layout
col = layout.column(align=True)
row = col.row(align=True)
+
if self.auto_refresh is False:
self.refresh = False
elif self.auto_refresh is True:
self.refresh = True
- row.prop(self, 'auto_refresh', toggle=True, icon='AUTO')
- row.prop(self, 'refresh', toggle=True, icon='FILE_REFRESH')
+
+ row.prop(self, "auto_refresh", toggle=True, icon="AUTO")
+ row.prop(self, "refresh", toggle=True, icon="FILE_REFRESH")
col = layout.column(align=True)
col.separator()
@@ -194,18 +195,20 @@ class OBJECT_OT_agregate_mesh(Operator):
col = layout.column(align=True)
col.prop(self, "rSeed", slider=False)
+ col.prop(self, "numP")
- col = layout.column(align=True)
- col.prop(self, "nor")
- col.prop(self, "cent")
- col.prop(self, "track")
- col.prop(self, "anim")
+ row = layout.row(align=True)
+ row.prop(self, "nor")
+ row.prop(self, "cent")
- col.prop(self, 'numP')
+ row = layout.row(align=True)
+ row.prop(self, "track")
+ row.prop(self, "anim")
@classmethod
def poll(cls, context):
- return(len(bpy.context.selected_objects) > 1 and bpy.context.object.type == 'MESH')
+ return (len(bpy.context.selected_objects) > 1 and
+ bpy.context.object.type == 'MESH')
def invoke(self, context, event):
self.refresh = True
@@ -227,8 +230,10 @@ class OBJECT_OT_agregate_mesh(Operator):
(0, 0, 0, 1))
)
if obj.matrix_world != mat:
- self.report({'WARNING'}, "Apply transformations to Active Object first!")
+ self.report({'WARNING'},
+ "Please, Apply transformations to Active Object first")
return{'FINISHED'}
+
par = [o for o in bpy.context.selected_objects if o.type == 'MESH' and o != obj]
if not par:
return{'FINISHED'}
@@ -296,9 +301,8 @@ class OBJECT_OT_agregate_mesh(Operator):
bme.to_mesh(obj.data)
remover(True)
-
- newobj.data.user_clear()
- bpy.data.meshes.remove(newobj.data)
+ # Note: foo.user_clear() is deprecated use do_unlink=True instead
+ bpy.data.meshes.remove(newobj.data, do_unlink=True)
else:
scn.objects.active = obj
@@ -318,8 +322,6 @@ class OBJECT_OT_agregate_mesh(Operator):
if self.auto_refresh is False:
self.refresh = False
- #elif self.auto_refresh is True:
- # self.refresh = True
return{'FINISHED'}
@@ -333,4 +335,4 @@ def unregister():
if __name__ == '__main__':
- register() \ No newline at end of file
+ register()
diff --git a/add_advanced_objects/arrange_on_curve.py b/add_advanced_objects/arrange_on_curve.py
index 9894de12..14017480 100644
--- a/add_advanced_objects/arrange_on_curve.py
+++ b/add_advanced_objects/arrange_on_curve.py
@@ -9,10 +9,12 @@ bl_info = {
"description": "Arrange objects along a curve",
"warning": "Select curve",
"wiki_url": "",
- "tracker_url": "https://developer.blender.org/maniphest/task/edit/form/2/",
"category": "3D View"
}
+# Note: scene properties are moved into __init__
+# search for patterns advanced_objects and adv_obj
+
import bpy
import mathutils
from bpy.types import (
@@ -20,11 +22,9 @@ from bpy.types import (
Panel,
)
from bpy.props import (
- BoolProperty,
EnumProperty,
FloatProperty,
IntProperty,
- StringProperty,
)
FLT_MIN = 0.004
@@ -44,82 +44,90 @@ class PanelDupliCurve(Panel):
def draw(self, context):
layout = self.layout
- layout.prop(context.scene, "use_selected")
- if not context.scene.use_selected:
- layout.prop(context.scene, "select_type", expand=True)
- if context.scene.select_type == 'O':
+ adv_obj = context.scene.advanced_objects
+
+ layout.prop(adv_obj, "arrange_c_use_selected")
+
+ if not adv_obj.arrange_c_use_selected:
+ layout.prop(adv_obj, "arrange_c_select_type", expand=True)
+ if adv_obj.arrange_c_select_type == 'O':
layout.column(align=True).prop_search(
- context.scene, "objeto_arranjar",
- bpy.data, "objects"
- )
- elif context.scene.select_type == 'G':
+ adv_obj, "arrange_c_obj_arranjar",
+ bpy.data, "objects"
+ )
+ elif adv_obj.arrange_c_select_type == 'G':
layout.column(align=True).prop_search(
- context.scene, "objeto_arranjar",
- bpy.data, "groups"
- )
+ adv_obj, "arrange_c_obj_arranjar",
+ bpy.data, "groups"
+ )
if context.object.type == 'CURVE':
layout.operator("object.arranjar_numa_curva", text="Arrange Objects")
class DupliCurve(Operator):
bl_idname = "object.arranjar_numa_curva"
- bl_label = "Arrange Objects"
+ bl_label = "Arrange Objects along a Curve"
+ bl_description = "Arange chosen / selected objects along the Active Curve"
bl_options = {'REGISTER', 'UNDO'}
use_distance = EnumProperty(
- items=[
- ("D", "Distance", "Objects are arranged depending on the distance", 0),
- ("Q", "Quantity", "Objects are arranged depending on the quantity", 1),
- ("R", "Range", "Objects are arranged uniformly between the corners", 2)
- ]
- )
+ name="Arrangement",
+ items=[
+ ("D", "Distance", "Objects are arranged depending on the distance", 0),
+ ("Q", "Quantity", "Objects are arranged depending on the quantity", 1),
+ ("R", "Range", "Objects are arranged uniformly between the corners", 2)
+ ]
+ )
distance = FloatProperty(
- name="Distance",
- description="Distancia entre objetos",
- default=1.0,
- min=FLT_MIN,
- soft_min=0.1,
- unit='LENGTH',
- )
+ name="Distance",
+ description="Distance between Objects",
+ default=1.0,
+ min=FLT_MIN,
+ soft_min=0.1,
+ unit='LENGTH',
+ )
object_qt = IntProperty(
- name="Quantity",
- description="Object amount.",
- default=2,
- min=0,
- )
+ name="Quantity",
+ description="Object amount",
+ default=2,
+ min=0,
+ )
scale = FloatProperty(
- name="Scale",
- description="Object Scale",
- default=1.0,
- min=FLT_MIN,
- unit='LENGTH',
+ name="Scale",
+ description="Object Scale",
+ default=1.0,
+ min=FLT_MIN,
+ unit='LENGTH',
)
Yaw = FloatProperty(
- default=0.0,
- name="X",
- unit='ROTATION'
- )
+ name="X",
+ description="Rotate around the X axis (Yaw)",
+ default=0.0,
+ unit='ROTATION'
+ )
Pitch = FloatProperty(
- default=0.0,
- name="Y",
- unit='ROTATION'
- )
+ default=0.0,
+ description="Rotate around the Y axis (Pitch)",
+ name="Y",
+ unit='ROTATION'
+ )
Roll = FloatProperty(
- default=0.0,
- name="Z",
- unit='ROTATION'
- )
+ default=0.0,
+ description="Rotate around the Z axis (Roll)",
+ name="Z",
+ unit='ROTATION'
+ )
max_angle = FloatProperty(
- default=1.57079,
- max=3.141592,
- name="Angle",
- unit='ROTATION'
- )
+ default=1.57079,
+ max=3.141592,
+ name="Angle",
+ unit='ROTATION'
+ )
offset = FloatProperty(
- default=0.0,
- name="offset",
- unit='LENGTH'
- )
+ default=0.0,
+ name="Offset",
+ unit='LENGTH'
+ )
@classmethod
def poll(cls, context):
@@ -191,7 +199,8 @@ class DupliCurve(Operator):
tmp_Gpoints.append(tuple(sp2))
sp2 = [lp]
except Exception as e:
- print(e)
+ print("\n[Add Advanced Objects]\nOperator: "
+ "object.arranjar_numa_curva\nError: {}".format(e))
pass
sp2.append(p)
v1 = v2
@@ -216,21 +225,25 @@ class DupliCurve(Operator):
curve = context.active_object
Gpoints, lengs = self.Glpoints(curve)
+ adv_obj = context.scene.advanced_objects
- if context.scene.use_selected:
+ if adv_obj.arrange_c_use_selected:
G_Objeto = context.selected_objects
G_Objeto.remove(curve)
+
if not G_Objeto:
return {'CANCELLED'}
- elif context.scene.select_type == 'O':
- G_Objeto = bpy.data.objects[context.scene.objeto_arranjar],
- elif context.scene.select_type == 'G':
- G_Objeto = bpy.data.groups[context.scene.objeto_arranjar].objects
+
+ elif adv_obj.arrange_c_select_type == 'O':
+ G_Objeto = bpy.data.objects[adv_obj.arrange_c_obj_arranjar],
+ elif adv_obj.arrange_c_select_type == 'G':
+ G_Objeto = bpy.data.groups[adv_obj.arrange_c_obj_arranjar].objects
+
yawMatrix = mathutils.Matrix.Rotation(self.Yaw, 4, 'X')
pitchMatrix = mathutils.Matrix.Rotation(self.Pitch, 4, 'Y')
rollMatrix = mathutils.Matrix.Rotation(self.Roll, 4, 'Z')
- max_angle = self.max_angle # is this used?
+ max_angle = self.max_angle # max_angle is called in Glpoints
if self.use_distance == "D":
dist = self.distance
@@ -331,31 +344,11 @@ class DupliCurve(Operator):
def register():
bpy.utils.register_class(PanelDupliCurve)
bpy.utils.register_class(DupliCurve)
- bpy.types.Scene.use_selected = BoolProperty(
- name='Use Selected',
- description='Use the selected objects to duplicate',
- default=True,
- )
- bpy.types.Scene.objeto_arranjar = StringProperty(
- name=""
- )
- bpy.types.Scene.select_type = EnumProperty(
- name="Type",
- description="Select object or group",
- items=[
- ('O', "OBJECT", "make duplicates of a specific object"),
- ('G', "GROUP", "make duplicates of the objects in a group"),
- ],
- default='O',
- )
def unregister():
bpy.utils.unregister_class(PanelDupliCurve)
bpy.utils.unregister_class(DupliCurve)
- del bpy.types.Scene.objeto_arranjar
- del bpy.types.Scene.use_selected
- del bpy.types.Scene.select_type
if __name__ == "__main__":
diff --git a/add_advanced_objects/circle_array.py b/add_advanced_objects/circle_array.py
index 170ea7a6..af5a6a0a 100644
--- a/add_advanced_objects/circle_array.py
+++ b/add_advanced_objects/circle_array.py
@@ -5,14 +5,13 @@
bl_info = {
"name": "Circle Array",
"author": "Antonis Karvelas",
- "version": (1, 0),
+ "version": (1, 0, 1),
"blender": (2, 6, 7),
"location": "View3D > Object > Circle_Array",
"description": "Uses an existing array and creates an empty, "
"rotates it properly and makes a Circle Array",
"warning": "",
"wiki_url": "",
- "tracker_url": "",
"category": "Mesh"
}
@@ -26,7 +25,10 @@ class Circle_Array(Operator):
bl_label = "Circle Array"
bl_idname = "objects.circle_array_operator"
bl_description = ("Creates an Array Modifier with offset empty object\n"
- "Works with Mesh, Curve, Text & Surface")
+ "Works with Mesh, Curve, Text and Surface\n"
+ "Use an object with an existing Array modifier\n"
+ "or rotate the newly created Empty with the name pattern\n"
+ "EMPTY_C_Array_ if the Array doesn't exist (angle: 360/Count)")
@classmethod
def poll(cls, context):
@@ -53,27 +55,52 @@ class Circle_Array(Operator):
return None
def execute(self, context):
+ is_allowed = True
try:
allowed_obj = ['MESH', 'CURVE', 'SURFACE', 'FONT']
- if context.active_object.type not in allowed_obj:
+ for obj in context.selected_objects:
+ if obj.type not in allowed_obj:
+ is_allowed = False
+ break
+
+ if not is_allowed:
self.report(
{"WARNING"},
- "Operation Cancelled. The active object is not of "
- "Mesh, Curve, Surface or Font type"
+ "The Active/Selected objects are not of "
+ "Mesh, Curve, Surface or Font type. Operation Cancelled"
)
return {'CANCELLED'}
default_name = self.check_empty_name(context) or "EMPTY_C_Array"
bpy.ops.object.modifier_add(type='ARRAY')
- if len(bpy.context.selected_objects) == 2:
- list = bpy.context.selected_objects
- active = list[0]
+ if len(context.selected_objects) == 2:
+ selected = context.selected_objects
+ lists = [obj for obj in selected if obj != context.active_object]
+ active = lists[0]
+ # check if the list object has a modifier
+ check_mod = None
+ for mod in active.modifiers[:]:
+ if mod.type == "ARRAY":
+ check_mod = mod
+ break
+
+ if check_mod:
+ check_mod.use_object_offset = True
+ check_mod.use_relative_offset = False
+ else:
+ # fallback
+ bpy.context.scene.objects.active = active
+ bpy.ops.object.modifier_add(type='ARRAY')
+ active.modifiers[0].use_object_offset = True
+ active.modifiers[0].use_relative_offset = False
+
active.modifiers[0].use_object_offset = True
active.modifiers[0].use_relative_offset = False
active.select = False
- bpy.context.scene.objects.active = list[0]
+ bpy.context.scene.objects.active = context.active_object
bpy.ops.view3d.snap_cursor_to_selected()
+
if active.modifiers[0].offset_object is None:
bpy.ops.object.add(type='EMPTY')
empty_name = bpy.context.active_object
@@ -98,6 +125,7 @@ class Circle_Array(Operator):
active.modifiers[0].use_object_offset = True
active.modifiers[0].use_relative_offset = False
bpy.ops.view3d.snap_cursor_to_selected()
+
if active.modifiers[0].offset_object is None:
bpy.ops.object.add(type='EMPTY')
empty_name = bpy.context.active_object
@@ -116,6 +144,7 @@ class Circle_Array(Operator):
active.select = True
return {'FINISHED'}
+
except Exception as e:
self.report({'WARNING'},
"Circle Array operator could not be executed (See the console for more info)")
@@ -125,18 +154,12 @@ class Circle_Array(Operator):
# Register
-def circle_array_menu(self, context):
- self.layout.operator(Circle_Array.bl_idname, text="Circle_Array")
-
-
def register():
bpy.utils.register_class(Circle_Array)
- bpy.types.VIEW3D_MT_object.append(circle_array_menu)
def unregister():
bpy.utils.unregister_class(Circle_Array)
- bpy.types.VIEW3D_MT_object.remove(circle_array_menu)
if __name__ == "__main__":
diff --git a/add_advanced_objects/copy2.py b/add_advanced_objects/copy2.py
index 3afdef22..489f6dee 100644
--- a/add_advanced_objects/copy2.py
+++ b/add_advanced_objects/copy2.py
@@ -1,4 +1,4 @@
-# ***** BEGIN GPL LICENSE BLOCK *****
+# ##### 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
@@ -15,12 +15,12 @@
# or write to the Free Software Foundation, Inc., 51 Franklin Street,
# Fifth Floor, Boston, MA 02110-1301, USA.
#
-# ***** END GPL LICENSE BLOCK *****
+# ##### END GPL LICENSE BLOCK #####
bl_info = {
- "name": "Copy2 vertices, edges or faces",
+ "name": "Copy2 Vertices, Edges or Faces",
"author": "Eleanor Howick (elfnor.com)",
- "version": (0, 1),
+ "version": (0, 1, 1),
"blender": (2, 71, 0),
"location": "3D View > Object > Copy 2",
"description": "Copy one object to the selected vertices, edges or faces of another object",
@@ -29,13 +29,23 @@ bl_info = {
}
import bpy
-
-from mathutils import Vector, Matrix
-
-
-class Copy2(bpy.types.Operator):
+from bpy.types import Operator
+from bpy.props import (
+ BoolProperty,
+ EnumProperty,
+ FloatProperty,
+ )
+from mathutils import (
+ Vector,
+ Matrix,
+ )
+
+
+class Copy2(Operator):
bl_idname = "mesh.copy2"
bl_label = "Copy 2"
+ bl_description = ("Copy Vertices, Edges or Faces to the Selected object\n"
+ "Needs an existing Active Mesh Object")
bl_options = {"REGISTER", "UNDO"}
obj_list = None
@@ -45,84 +55,126 @@ class Copy2(bpy.types.Operator):
def sec_axes_list_cb(self, context):
if self.priaxes == 'X':
- sec_list = [('Y', 'Y', 'Y'), ('Z', 'Z', 'Z')]
+ sec_list = [('Y', "Y", "Secondary axis Y"),
+ ('Z', "Z", "Secondary axis Z")]
if self.priaxes == 'Y':
- sec_list = [('X', 'X', 'X'), ('Z', 'Z', 'Z')]
+ sec_list = [('X', "X", "Secondary axis X"),
+ ('Z', "Z", "Secondary axis Z")]
if self.priaxes == 'Z':
- sec_list = [('X', 'X', 'X'), ('Y', 'Y', 'Y')]
+ sec_list = [('X', "X", "Secondary axis X"),
+ ('Y', "Y", "Secondary axis Y")]
return sec_list
- copytype = bpy.props.EnumProperty(items=(('V', '', 'paste to vertices', 'VERTEXSEL', 0),
- ('E', '', 'paste to edges', 'EDGESEL', 1),
- ('F', '', 'paste to faces', 'FACESEL', 2)),
- description='where to paste to')
-
- copyfromobject = bpy.props.EnumProperty(items=obj_list_cb, name='Copy from:')
-
- priaxes = bpy.props.EnumProperty(items=(('X', 'X', 'along X'),
- ('Y', 'Y', 'along Y'),
- ('Z', 'Z', 'along Z')),
- )
-
- edgescale = bpy.props.BoolProperty(name='Scale to fill edge?')
-
- secaxes = bpy.props.EnumProperty(items=sec_axes_list_cb, name='Secondary Axis')
-
- scale = bpy.props.FloatProperty(default=1.0, min=0.0, name='Scale')
+ copytype = EnumProperty(
+ items=(('V', "Vertex",
+ "Paste the Copied Geometry to Vertices of the Active Object", 'VERTEXSEL', 0),
+ ('E', "Edge",
+ "Paste the Copied Geometry to Edges of the Active Object", 'EDGESEL', 1),
+ ('F', "Face",
+ "Paste the Copied Geometry to Faces of the Active Object", 'FACESEL', 2)),
+ )
+ copyfromobject = EnumProperty(
+ name="Copy from",
+ description="Copy an Object from the list",
+ items=obj_list_cb
+ )
+ priaxes = EnumProperty(
+ description="Primary axes used for Copied Object orientation",
+ items=(('X', "X", "Along X"),
+ ('Y', "Y", "Along Y"),
+ ('Z', "Z", "Along Z")),
+ )
+ edgescale = BoolProperty(
+ name="Scale to fill edge",
+ default=False
+ )
+ secaxes = EnumProperty(
+ name="Secondary Axis",
+ description="Secondary axis used for Copied Object orientation",
+ items=sec_axes_list_cb
+ )
+ scale = FloatProperty(
+ name="Scale",
+ default=1.0,
+ min=0.0,
+ )
+
+ @classmethod
+ def poll(cls, context):
+ obj = context.active_object
+ return obj and obj.type == "MESH"
def draw(self, context):
layout = self.layout
- layout.prop(self, 'copyfromobject')
+ layout.prop(self, "copyfromobject")
layout.label("to:")
- layout.prop(self, 'copytype', expand=True)
- layout.label("primary axis:")
- layout.prop(self, 'priaxes', expand=True)
- layout.label("secondary axis:")
- layout.prop(self, 'secaxes', expand=True)
- if self.copytype == 'E':
- layout.prop(self, 'edgescale')
+ layout.prop(self, "copytype", expand=True)
+ layout.label("Primary axis:")
+ layout.prop(self, "priaxes", expand=True)
+ layout.label("Secondary axis:")
+ layout.prop(self, "secaxes", expand=True)
+ if self.copytype == "E":
+ layout.prop(self, "edgescale")
if self.edgescale:
- layout.prop(self, 'scale')
+ layout.prop(self, "scale")
return
def execute(self, context):
copytoobject = context.active_object.name
axes = self.priaxes + self.secaxes
- copy_list = copy_to_from(context.scene,
- bpy.data.objects[copytoobject],
- bpy.data.objects[self.copyfromobject],
- self.copytype,
- axes,
- self.edgescale,
- self.scale)
+
+ # check if there is a problem with the strings related to some chars
+ copy_to_object = bpy.data.objects[copytoobject] if \
+ copytoobject in bpy.data.objects else None
+
+ copy_from_object = bpy.data.objects[self.copyfromobject] if \
+ self.copyfromobject in bpy.data.objects else None
+
+ if copy_to_object is None or copy_from_object is None:
+ self.report({"WARNING"},
+ "There was a problem with retrieving Object data. Operation Cancelled")
+ return {"CANCELLED"}
+ try:
+ copy_to_from(
+ context.scene,
+ copy_to_object,
+ copy_from_object,
+ self.copytype,
+ axes,
+ self.edgescale,
+ self.scale
+ )
+ except Exception as e:
+ self.report({"WARNING"},
+ "Copy2 could not be completed (Check the Console for more info)")
+ print("\n[Add Advanced Objects]\nOperator: mesh.copy2\n{}\n".format(e))
+
+ return {"CANCELLED"}
+
return {"FINISHED"}
def invoke(self, context, event):
Copy2.obj_list = [(obj.name, obj.name, obj.name) for obj in bpy.data.objects]
- return {"FINISHED"}
-# end Copy2 class
-
-#---------------------------------------------------------------------------------------
-
-
-def add_to_menu(self, context):
- self.layout.operator(Copy2.bl_idname)
- return
+ return {"FINISHED"}
-#-----------------------------------------------------------------
def copy_to_from(scene, to_obj, from_obj, copymode, axes, edgescale, scale):
if copymode == 'V':
- copy_list = vertex_copy(scene, to_obj, from_obj, axes)
+ vertex_copy(scene, to_obj, from_obj, axes)
+
if copymode == 'E':
- copy_list = edge_copy(scene, to_obj, from_obj, axes, edgescale, scale)
+ # don't pass edgescalling to object types that cannot be scaled
+ if from_obj.type in ["CAMERA", "LAMP", "EMPTY", "ARMATURE", "SPEAKER", "META"]:
+ edgescale = False
+ edge_copy(scene, to_obj, from_obj, axes, edgescale, scale)
+
if copymode == 'F':
- copy_list = face_copy(scene, to_obj, from_obj, axes)
- return copy_list
+ face_copy(scene, to_obj, from_obj, axes)
+
axes_dict = {'XY': (1, 2, 0),
'XZ': (2, 1, 0),
@@ -133,9 +185,9 @@ axes_dict = {'XY': (1, 2, 0),
def copyto(scene, source_obj, pos, xdir, zdir, axes, scale=None):
- """
- copy the source_obj to pos, so its primary axis points in zdir and its
- secondary axis points in xdir
+ """
+ copy the source_obj to pos, so its primary axis points in zdir and its
+ secondary axis points in xdir
"""
copy_obj = source_obj.copy()
scene.objects.link(copy_obj)
@@ -161,7 +213,7 @@ def copyto(scene, source_obj, pos, xdir, zdir, axes, scale=None):
copy_obj.location = pos
# scale object
- if scale != None:
+ if scale is not None:
copy_obj.scale = scale
return copy_obj
@@ -171,8 +223,9 @@ def vertex_copy(scene, obj, source_obj, axes):
# vertex select mode
sel_verts = []
copy_list = []
+
for v in obj.data.vertices:
- if v.select == True:
+ if v.select is True:
sel_verts.append(v)
# make a set for each vertex. The set contains all the connected vertices
@@ -198,20 +251,22 @@ def vertex_copy(scene, obj, source_obj, axes):
copy = copyto(scene, source_obj, pos, xdir, zdir, axes)
copy_list.append(copy)
+
# select all copied objects
for copy in copy_list:
copy.select = True
obj.select = False
- return copy_list
def edge_copy(scene, obj, source_obj, axes, es, scale):
# edge select mode
sel_edges = []
copy_list = []
+
for e in obj.data.edges:
- if e.select == True:
+ if e.select is True:
sel_edges.append(e)
+
for e in sel_edges:
# pos is average of two edge vertexs
v0 = obj.data.vertices[e.vertices[0]].co * obj.matrix_world.transposed()
@@ -222,10 +277,10 @@ def edge_copy(scene, obj, source_obj, axes, es, scale):
xlen = xdir.magnitude
xdir = xdir.normalized()
# project each edge vertex normal onto plane normal to xdir
- vn0 = (obj.data.vertices[e.vertices[0]].co * obj.matrix_world.transposed()
- + obj.data.vertices[e.vertices[0]].normal) - v0
- vn1 = (obj.data.vertices[e.vertices[1]].co * obj.matrix_world.transposed()
- + obj.data.vertices[e.vertices[1]].normal) - v1
+ vn0 = (obj.data.vertices[e.vertices[0]].co * obj.matrix_world.transposed() +
+ obj.data.vertices[e.vertices[0]].normal) - v0
+ vn1 = (obj.data.vertices[e.vertices[1]].co * obj.matrix_world.transposed() +
+ obj.data.vertices[e.vertices[1]].normal) - v1
vn0p = vn0 - vn0.dot(xdir) * xdir
vn1p = vn1 - vn1.dot(xdir) * xdir
# the mean of the two projected normals is the zdir
@@ -239,20 +294,22 @@ def edge_copy(scene, obj, source_obj, axes, es, scale):
copy = copyto(scene, source_obj, pos, xdir, zdir, axes, scale=escale)
copy_list.append(copy)
+
# select all copied objects
for copy in copy_list:
copy.select = True
obj.select = False
- return copy_list
def face_copy(scene, obj, source_obj, axes):
# face select mode
sel_faces = []
copy_list = []
+
for f in obj.data.polygons:
- if f.select == True:
+ if f.select is True:
sel_faces.append(f)
+
for f in sel_faces:
fco = f.center * obj.matrix_world.transposed()
# get first vertex corner of transformed object
@@ -263,25 +320,19 @@ def face_copy(scene, obj, source_obj, axes):
copy = copyto(scene, source_obj, fco, vco - fco, fn, axes)
copy_list.append(copy)
+
# select all copied objects
for copy in copy_list:
copy.select = True
obj.select = False
- return copy_list
-
-#-------------------------------------------------------------------
def register():
-
- bpy.utils.register_module(__name__)
- bpy.types.VIEW3D_MT_object.append(add_to_menu)
+ bpy.utils.register_class(Copy2)
def unregister():
-
- bpy.types.VIEW3D_MT_object.remove(add_to_menu)
- bpy.utils.unregister_module(__name__)
+ bpy.utils.unregister_class(Copy2)
if __name__ == "__main__":
diff --git a/add_advanced_objects/cubester.py b/add_advanced_objects/cubester.py
index 83053ad1..1a516bd0 100644
--- a/add_advanced_objects/cubester.py
+++ b/add_advanced_objects/cubester.py
@@ -19,10 +19,13 @@
# Original Author = Jacob Morris
# URL = blendingjacob.blogspot.com
+# Note: scene properties are moved into __init__ together with the 3 update functions
+# for properties search for the name patterns adv_obj and advanced_objects
+
bl_info = {
"name": "CubeSter",
"author": "Jacob Morris",
- "version": (0, 7),
+ "version": (0, 7, 1),
"blender": (2, 78, 0),
"location": "View 3D > Toolbar > CubeSter",
"description": "Takes image, image sequence, or audio file and converts it "
@@ -32,13 +35,6 @@ bl_info = {
import bpy
import bmesh
-from bpy.props import (
- BoolProperty,
- IntProperty,
- FloatProperty,
- StringProperty,
- EnumProperty,
- )
from bpy.types import (
Operator,
Panel,
@@ -53,29 +49,9 @@ from os import (
)
-# load image if possible
-def adjust_selected_image(self, context):
- scene = context.scene
- try:
- image = bpy.data.images.load(scene.cubester_load_image)
- scene.cubester_image = image.name
- except RuntimeError:
- self.report({"ERROR"}, "CubeSter: '{}' could not be loaded".format(scene.cubester_load_image))
-
-
-# load color image if possible
-def adjust_selected_color_image(self, context):
- scene = context.scene
- try:
- image = bpy.data.images.load(scene.cubester_load_color_image)
- scene.cubester_color_image = image.name
- except RuntimeError:
- self.report({"ERROR"}, "CubeSter: '{}' could not be loaded".format(scene.cubester_load_color_image))
-
-
-# crate block at center position x, y with block width 2 * hx and 2 * hy and height of h
+# create block at center position x, y with block width 2 * hx and 2 * hy and height of h
def create_block(x, y, hw, h, verts: list, faces: list):
- if bpy.context.scene.cubester_block_style == "size":
+ if bpy.context.scene.advanced_objects.cubester_block_style == "size":
z = 0.0
else:
z = h
@@ -134,12 +110,20 @@ def create_f_curves(mesh, frames, frame_step_size, style):
# create material with given name, apply to object
def create_material(scene, ob, name):
mat = bpy.data.materials.new("CubeSter_" + name)
+ adv_obj = scene.advanced_objects
+ image = None
# image
- if not scene.cubester_use_image_color and scene.cubester_color_image in bpy.data.images:
- image = bpy.data.images[scene.cubester_color_image]
+ if not adv_obj.cubester_use_image_color and adv_obj.cubester_color_image in bpy.data.images:
+ try:
+ image = bpy.data.images[adv_obj.cubester_color_image]
+ except:
+ pass
else:
- image = bpy.data.images[scene.cubester_image]
+ try:
+ image = bpy.data.images[adv_obj.cubester_image]
+ except:
+ pass
if scene.render.engine == "CYCLES":
mat.use_nodes = True
@@ -150,16 +134,17 @@ def create_material(scene, ob, name):
att.location = (-200, 300)
att = nodes.new("ShaderNodeTexImage")
- att.image = image
+ if image:
+ att.image = image
- if scene.cubester_load_type == "multiple":
+ if adv_obj.cubester_load_type == "multiple":
att.image.source = "SEQUENCE"
att.location = (-200, 700)
att = nodes.new("ShaderNodeTexCoord")
att.location = (-450, 600)
- if scene.cubester_materials == "image":
+ if adv_obj.cubester_materials == "image":
mat.node_tree.links.new(
nodes["Image Texture"].outputs[0],
nodes["Diffuse BSDF"].inputs[0]
@@ -174,9 +159,10 @@ def create_material(scene, ob, name):
nodes["Diffuse BSDF"].inputs[0]
)
else:
- if scene.cubester_materials == "image" or scene.render.engine != "BLENDER_RENDER":
+ if adv_obj.cubester_materials == "image" or scene.render.engine != "BLENDER_RENDER":
tex = bpy.data.textures.new("CubeSter_" + name, "IMAGE")
- tex.image = image
+ if image:
+ tex.image = image
slot = mat.texture_slots.add()
slot.texture = tex
else:
@@ -187,10 +173,11 @@ def create_material(scene, ob, name):
# generate mesh from audio
def create_mesh_from_audio(self, scene, verts, faces):
- audio_filepath = scene.cubester_audio_path
- width = scene.cubester_audio_width_blocks
- length = scene.cubester_audio_length_blocks
- size_per_hundred = scene.cubester_size_per_hundred_pixels
+ adv_obj = scene.advanced_objects
+ audio_filepath = adv_obj.cubester_audio_path
+ width = adv_obj.cubester_audio_width_blocks
+ length = adv_obj.cubester_audio_length_blocks
+ size_per_hundred = adv_obj.cubester_size_per_hundred_pixels
size = size_per_hundred / 100
@@ -213,8 +200,8 @@ def create_mesh_from_audio(self, scene, verts, faces):
ob.select = True
# inital vertex colors
- if scene.cubester_materials == "image":
- picture = bpy.data.images[scene.cubester_color_image]
+ if adv_obj.cubester_materials == "image" and adv_obj.cubester_color_image != "":
+ picture = bpy.data.images[adv_obj.cubester_color_image]
pixels = list(picture.pixels)
vert_colors = []
@@ -228,22 +215,25 @@ def create_mesh_from_audio(self, scene, verts, faces):
vert_colors += [(r, g, b) for i in range(24)]
bpy.ops.mesh.vertex_color_add()
+
i = 0
+ vert_colors_size = len(vert_colors)
for c in ob.data.vertex_colors[0].data:
- c.color = vert_colors[i]
- i += 1
+ if i < vert_colors_size:
+ c.color = vert_colors[i]
+ i += 1
# image sequence handling
- if scene.cubester_load_type == "multiple":
+ if adv_obj.cubester_load_type == "multiple":
images = find_sequence_images(self, bpy.context)
frames_vert_colors = []
- max_images = scene.cubester_max_images + 1 if \
- len(images[0]) > scene.cubester_max_images else len(images[0])
+ max_images = adv_obj.cubester_max_images + 1 if \
+ len(images[0]) > adv_obj.cubester_max_images else len(images[0])
# goes through and for each image for each block finds new height
- for image_index in range(0, max_images, scene.cubester_skip_images):
+ for image_index in range(0, max_images, adv_obj.cubester_skip_images):
filepath = images[0][image_index]
name = images[1][image_index]
picture = fetch_image(self, name, filepath)
@@ -258,9 +248,10 @@ def create_mesh_from_audio(self, scene, verts, faces):
frames_vert_colors.append(frame_colors)
- scene.cubester_vertex_colors[ob.name] = {"type": "vertex", "frames": frames_vert_colors,
- "frame_skip": scene.cubester_frame_step,
- "total_images": max_images}
+ adv_obj.cubester_vertex_colors[ob.name] = \
+ {"type": "vertex", "frames": frames_vert_colors,
+ "frame_skip": adv_obj.cubester_frame_step,
+ "total_images": max_images}
# either add material or create
if ("CubeSter_" + "Vertex") in bpy.data.materials:
@@ -285,14 +276,14 @@ def create_mesh_from_audio(self, scene, verts, faces):
for i in fcurves:
i.select = False
- max_images = scene.cubester_audio_max_freq
- min_freq = scene.cubester_audio_min_freq
- freq_frame = scene.cubester_audio_offset_type
+ max_images = adv_obj.cubester_audio_max_freq
+ min_freq = adv_obj.cubester_audio_min_freq
+ freq_frame = adv_obj.cubester_audio_offset_type
freq_step = (max_images - min_freq) / length
freq_sub_step = freq_step / width
- frame_step = scene.cubester_audio_frame_offset
+ frame_step = adv_obj.cubester_audio_frame_offset
# animate each block with a portion of the frequency
for c in range(length):
@@ -314,8 +305,10 @@ def create_mesh_from_audio(self, scene, verts, faces):
for i in range(index, index + 4):
curve = i * 3 + 2 # fcurve location
fcurves[curve].select = True
-
- bpy.ops.graph.sound_bake(filepath=bpy.path.abspath(audio_filepath), low=l, high=h)
+ try:
+ bpy.ops.graph.sound_bake(filepath=bpy.path.abspath(audio_filepath), low=l, high=h)
+ except:
+ pass
# deselect curves
for i in range(index, index + 4):
@@ -328,7 +321,7 @@ def create_mesh_from_audio(self, scene, verts, faces):
create_uv_map(bpy.context, width, length)
# if radial apply needed modifiers
- if scene.cubester_audio_block_layout == "radial":
+ if adv_obj.cubester_audio_block_layout == "radial":
# add bezier curve of correct width
bpy.ops.curve.primitive_bezier_circle_add()
curve = bpy.context.object
@@ -358,14 +351,15 @@ def create_mesh_from_audio(self, scene, verts, faces):
# generate mesh from image(s)
def create_mesh_from_image(self, scene, verts, faces):
context = bpy.context
- picture = bpy.data.images[scene.cubester_image]
+ adv_obj = scene.advanced_objects
+ picture = bpy.data.images[adv_obj.cubester_image]
pixels = list(picture.pixels)
- x_pixels = picture.size[0] / (scene.cubester_skip_pixels + 1)
- y_pixels = picture.size[1] / (scene.cubester_skip_pixels + 1)
+ x_pixels = picture.size[0] / (adv_obj.cubester_skip_pixels + 1)
+ y_pixels = picture.size[1] / (adv_obj.cubester_skip_pixels + 1)
- width = x_pixels / 100 * scene.cubester_size_per_hundred_pixels
- height = y_pixels / 100 * scene.cubester_size_per_hundred_pixels
+ width = x_pixels / 100 * adv_obj.cubester_size_per_hundred_pixels
+ height = y_pixels / 100 * adv_obj.cubester_size_per_hundred_pixels
step = width / x_pixels
half_width = step / 2
@@ -376,18 +370,18 @@ def create_mesh_from_image(self, scene, verts, faces):
weights = [uniform(0.0, 1.0) for i in range(4)] # random weights
rows = 0
- # go through each row of pixels stepping by scene.cubester_skip_pixels + 1
- for row in range(0, picture.size[1], scene.cubester_skip_pixels + 1):
+ # go through each row of pixels stepping by adv_obj.cubester_skip_pixels + 1
+ for row in range(0, picture.size[1], adv_obj.cubester_skip_pixels + 1):
rows += 1
x = -width / 2 + half_width # reset to left edge of mesh
# go through each column, step by appropriate amount
- for column in range(0, picture.size[0] * 4, 4 + scene.cubester_skip_pixels * 4):
+ for column in range(0, picture.size[0] * 4, 4 + adv_obj.cubester_skip_pixels * 4):
r, g, b, a = get_pixel_values(picture, pixels, row, column)
h = find_point_height(r, g, b, a, scene)
# if not transparent
if h != -1:
- if scene.cubester_mesh_style == "blocks":
+ if adv_obj.cubester_mesh_style == "blocks":
create_block(x, y, half_width, h, verts, faces)
vert_colors += [(r, g, b) for i in range(24)]
else:
@@ -399,11 +393,11 @@ def create_mesh_from_image(self, scene, verts, faces):
# if plane not blocks, then remove last 4 items from vertex_colors
# as the faces have already wrapped around
- if scene.cubester_mesh_style == "plane":
+ if adv_obj.cubester_mesh_style == "plane":
del vert_colors[len(vert_colors) - 4:len(vert_colors)]
# create faces if plane based and not block based
- if scene.cubester_mesh_style == "plane":
+ if adv_obj.cubester_mesh_style == "plane":
off = int(len(verts) / rows)
for r in range(rows - 1):
for c in range(off - 1):
@@ -417,20 +411,21 @@ def create_mesh_from_image(self, scene, verts, faces):
ob.select = True
# uv unwrap
- if scene.cubester_mesh_style == "blocks":
+ if adv_obj.cubester_mesh_style == "blocks":
create_uv_map(context, rows, int(len(faces) / 6 / rows))
else:
create_uv_map(context, rows - 1, int(len(faces) / (rows - 1)))
# material
# determine name and if already created
- if scene.cubester_materials == "vertex": # vertex color
+ if adv_obj.cubester_materials == "vertex": # vertex color
image_name = "Vertex"
- elif not scene.cubester_use_image_color and scene.cubester_color_image in bpy.data.images and \
- scene.cubester_materials == "image": # replaced image
- image_name = scene.cubester_color_image
+ elif not adv_obj.cubester_use_image_color and \
+ adv_obj.cubester_color_image in bpy.data.images and \
+ adv_obj.cubester_materials == "image": # replaced image
+ image_name = adv_obj.cubester_color_image
else: # normal image
- image_name = scene.cubester_image
+ image_name = adv_obj.cubester_image
# either add material or create
if ("CubeSter_" + image_name) in bpy.data.materials:
@@ -449,15 +444,15 @@ def create_mesh_from_image(self, scene, verts, faces):
frames = []
# image sequence handling
- if scene.cubester_load_type == "multiple":
+ if adv_obj.cubester_load_type == "multiple":
images = find_sequence_images(self, context)
frames_vert_colors = []
- max_images = scene.cubester_max_images + 1 if \
- len(images[0]) > scene.cubester_max_images else len(images[0])
+ max_images = adv_obj.cubester_max_images + 1 if \
+ len(images[0]) > adv_obj.cubester_max_images else len(images[0])
# goes through and for each image for each block finds new height
- for image_index in range(0, max_images, scene.cubester_skip_images):
+ for image_index in range(0, max_images, adv_obj.cubester_skip_images):
filepath = images[0][image_index]
name = images[1][image_index]
picture = fetch_image(self, name, filepath)
@@ -466,45 +461,50 @@ def create_mesh_from_image(self, scene, verts, faces):
frame_heights = []
frame_colors = []
- for row in range(0, picture.size[1], scene.cubester_skip_pixels + 1):
- for column in range(0, picture.size[0] * 4, 4 + scene.cubester_skip_pixels * 4):
+ for row in range(0, picture.size[1], adv_obj.cubester_skip_pixels + 1):
+ for column in range(0, picture.size[0] * 4, 4 + adv_obj.cubester_skip_pixels * 4):
r, g, b, a = get_pixel_values(picture, pixels, row, column)
h = find_point_height(r, g, b, a, scene)
if h != -1:
frame_heights.append(h)
- if scene.cubester_mesh_style == "blocks":
+ if adv_obj.cubester_mesh_style == "blocks":
frame_colors += [(r, g, b) for i in range(24)]
else:
frame_colors += [(r, g, b) for i in range(4)]
- if scene.cubester_mesh_style == "plane":
+ if adv_obj.cubester_mesh_style == "plane":
del vert_colors[len(vert_colors) - 4:len(vert_colors)]
frames.append(frame_heights)
frames_vert_colors.append(frame_colors)
# determine what data to use
- if scene.cubester_materials == "vertex" or scene.render.engine == "BLENDER_ENGINE":
- scene.cubester_vertex_colors[ob.name] = {
- "type": "vertex", "frames": frames_vert_colors,
- "frame_skip": scene.cubester_frame_step,
- "total_images": max_images
- }
+ if adv_obj.cubester_materials == "vertex" or scene.render.engine == "BLENDER_ENGINE":
+ adv_obj.cubester_vertex_colors[ob.name] = {
+ "type": "vertex", "frames": frames_vert_colors,
+ "frame_skip": adv_obj.cubester_frame_step,
+ "total_images": max_images
+ }
else:
- scene.cubester_vertex_colors[ob.name] = {
- "type": "image", "frame_skip": scene.cubester_frame_step,
- "total_images": max_images
- }
+ adv_obj.cubester_vertex_colors[ob.name] = {
+ "type": "image", "frame_skip": scene.cubester_frame_step,
+ "total_images": max_images
+ }
att = get_image_node(ob.data.materials[0])
- att.image_user.frame_duration = len(frames) * scene.cubester_frame_step
+ att.image_user.frame_duration = len(frames) * adv_obj.cubester_frame_step
# animate mesh
- create_f_curves(mesh, frames, scene.cubester_frame_step, scene.cubester_mesh_style)
+ create_f_curves(
+ mesh, frames,
+ adv_obj.cubester_frame_step,
+ adv_obj.cubester_mesh_style
+ )
# generate uv map for object
def create_uv_map(context, rows, columns):
+ adv_obj = context.scene.advanced_objects
mesh = context.object.data
mesh.uv_textures.new("cubester")
bm = bmesh.new()
@@ -521,7 +521,7 @@ def create_uv_map(context, rows, columns):
count = columns - 1 # hold current count to compare to if need to go to next row
# if blocks
- if context.scene.cubester_mesh_style == "blocks":
+ if adv_obj.cubester_mesh_style == "blocks":
for fa in range(int(len(bm.faces) / 6)):
for i in range(6):
pos = (fa * 6) + i
@@ -555,33 +555,6 @@ def create_uv_map(context, rows, columns):
bm.to_mesh(mesh)
-# returns length in frames
-def find_audio_length(self, context):
- audio_file = context.scene.cubester_audio_path
- length = 0
-
- if audio_file != "":
- # confirm that strip hasn't been loaded yet
- for strip in context.scene.sequence_editor.sequences_all:
- if type(strip) == bpy.types.SoundSequence and strip.sound.filepath == audio_file:
- length = strip.frame_final_duration
-
- if length == 0:
- area = context.area
- old_type = area.type
- area.type = "SEQUENCE_EDITOR"
-
- bpy.ops.sequencer.sound_strip_add(filepath=audio_file)
- area.type = old_type
-
- # find audio file
- for strip in context.scene.sequence_editor.sequences_all:
- if type(strip) == bpy.types.SoundSequence and strip.sound.filepath == audio_file:
- length = strip.frame_final_duration
-
- context.scene.cubester_audio_file_length = str(length)
-
-
# if already loaded return image, else load and return
def fetch_image(self, name, load_path):
if name in bpy.data.images:
@@ -597,19 +570,20 @@ def fetch_image(self, name, load_path):
# find height for point
def find_point_height(r, g, b, a, scene):
+ adv_obj = scene.advanced_objects
if a: # if not completely transparent
normalize = 1
# channel weighting
- if not scene.cubester_advanced:
+ if not adv_obj.cubester_advanced:
composed = 0.25 * r + 0.25 * g + 0.25 * b + 0.25 * a
else:
# user defined weighting
- if not scene.cubester_random_weights:
- composed = scene.cubester_weight_r * r + scene.cubester_weight_g * g + \
- scene.cubester_weight_b * b + scene.cubester_weight_a * a
- total = scene.cubester_weight_r + scene.cubester_weight_g + scene.cubester_weight_b + \
- scene.cubester_weight_a
+ if not adv_obj.cubester_random_weights:
+ composed = adv_obj.cubester_weight_r * r + adv_obj.cubester_weight_g * g + \
+ adv_obj.cubester_weight_b * b + adv_obj.cubester_weight_a * a
+ total = adv_obj.cubester_weight_r + adv_obj.cubester_weight_g + adv_obj.cubester_weight_b + \
+ adv_obj.cubester_weight_a
normalize = 1 / total
# random weighting
@@ -619,10 +593,10 @@ def find_point_height(r, g, b, a, scene):
total = weights[0] + weights[1] + weights[2] + weights[3]
normalize = 1 / total
- if scene.cubester_invert:
- h = (1 - composed) * scene.cubester_height_scale * normalize
+ if adv_obj.cubester_invert:
+ h = (1 - composed) * adv_obj.cubester_height_scale * normalize
else:
- h = composed * scene.cubester_height_scale * normalize
+ h = composed * adv_obj.cubester_height_scale * normalize
return h
else:
@@ -634,8 +608,8 @@ def find_sequence_images(self, context):
scene = context.scene
images = [[], []]
- if scene.cubester_image in bpy.data.images:
- image = bpy.data.images[scene.cubester_image]
+ if scene.advanced_objects.cubester_image in bpy.data.images:
+ image = bpy.data.images[scene.advanced_objects.cubester_image]
main = image.name.split(".")[0]
# first part of name to check against other files
@@ -685,15 +659,16 @@ def get_pixel_values(picture, pixels, row, column):
# frame change handler for materials
def material_frame_handler(scene):
frame = scene.frame_current
+ adv_obj = scene.advanced_objects
- keys = list(scene.cubester_vertex_colors.keys())
+ keys = list(adv_obj.cubester_vertex_colors.keys())
# get keys and see if object is still in scene
for i in keys:
# if object is in scene then update information
if i in bpy.data.objects:
ob = bpy.data.objects[i]
- data = scene.cubester_vertex_colors[ob.name]
+ data = adv_obj.advanced_objects.cubester_vertex_colors[ob.name]
skip_frames = data["frame_skip"]
# update materials using vertex colors
@@ -716,183 +691,7 @@ def material_frame_handler(scene):
# if the object is no longer in the scene then delete then entry
else:
- del scene.cubester_vertex_colors[i]
-
-
-# main properties
-bpy.types.Scene.cubester_audio_image = EnumProperty(
- name="Input Type",
- items=(("image", "Image", ""),
- ("audio", "Audio", ""))
- )
-bpy.types.Scene.cubester_audio_file_length = StringProperty(
- default=""
- )
-# audio
-bpy.types.Scene.cubester_audio_path = StringProperty(
- default="",
- name="Audio File",
- subtype="FILE_PATH",
- update=find_audio_length
- )
-bpy.types.Scene.cubester_audio_min_freq = IntProperty(
- name="Minimum Frequency",
- min=20, max=100000,
- default=20
- )
-bpy.types.Scene.cubester_audio_max_freq = IntProperty(
- name="Maximum Frequency",
- min=21, max=999999,
- default=5000
- )
-bpy.types.Scene.cubester_audio_offset_type = EnumProperty(
- name="Offset Type",
- items=(("freq", "Frequency Offset", ""),
- ("frame", "Frame Offset", "")),
- description="Type of offset per row of mesh"
- )
-bpy.types.Scene.cubester_audio_frame_offset = IntProperty(
- name="Frame Offset",
- min=0, max=10,
- default=2
- )
-bpy.types.Scene.cubester_audio_block_layout = EnumProperty(
- name="Block Layout",
- items=(("rectangle", "Rectangular", ""),
- ("radial", "Radial", ""))
- )
-bpy.types.Scene.cubester_audio_width_blocks = IntProperty(
- name="Width Block Count",
- min=1, max=10000,
- default=5
- )
-bpy.types.Scene.cubester_audio_length_blocks = IntProperty(
- name="Length Block Count",
- min=1, max=10000,
- default=50
- )
-# image
-bpy.types.Scene.cubester_load_type = EnumProperty(
- name="Image Input Type",
- items=(("single", "Single Image", ""),
- ("multiple", "Image Sequence", ""))
- )
-bpy.types.Scene.cubester_image = StringProperty(
- default="",
- name=""
- )
-bpy.types.Scene.cubester_load_image = StringProperty(
- default="",
- name="Load Image",
- subtype="FILE_PATH",
- update=adjust_selected_image
- )
-bpy.types.Scene.cubester_skip_images = IntProperty(
- name="Image Step",
- min=1, max=30,
- default=1,
- description="Step from image to image by this number"
- )
-bpy.types.Scene.cubester_max_images = IntProperty(
- name="Max Number Of Images",
- min=2, max=1000,
- default=10,
- description="Maximum number of images to be used"
- )
-bpy.types.Scene.cubester_frame_step = IntProperty(
- name="Frame Step Size",
- min=1, max=10,
- default=4,
- description="The number of frames each picture is used"
- )
-bpy.types.Scene.cubester_skip_pixels = IntProperty(
- name="Skip # Pixels",
- min=0, max=256,
- default=64,
- description="Skip this number of pixels before placing the next"
- )
-bpy.types.Scene.cubester_mesh_style = EnumProperty(
- name="Mesh Type",
- items=(("blocks", "Blocks", ""),
- ("plane", "Plane", "")),
- description="Compose mesh of multiple blocks or of a single plane"
- )
-bpy.types.Scene.cubester_block_style = EnumProperty(
- name="Block Style",
- items=(("size", "Vary Size", ""),
- ("position", "Vary Position", "")),
- description="Vary Z-size of block, or vary Z-position"
- )
-bpy.types.Scene.cubester_height_scale = FloatProperty(
- name="Height Scale",
- subtype="DISTANCE",
- min=0.1, max=2,
- default=0.2
- )
-bpy.types.Scene.cubester_invert = BoolProperty(
- name="Invert Height?",
- default=False
- )
-# general adjustments
-bpy.types.Scene.cubester_size_per_hundred_pixels = FloatProperty(
- name="Size Per 100 Blocks/Points",
- subtype="DISTANCE",
- min=0.001, max=5,
- default=1
- )
-# material based stuff
-bpy.types.Scene.cubester_materials = EnumProperty(
- name="Material",
- items=(("vertex", "Vertex Colors", ""),
- ("image", "Image", "")),
- description="Color with vertex colors, or uv unwrap and use an image"
- )
-bpy.types.Scene.cubester_use_image_color = BoolProperty(
- name="Use Original Image Colors'?",
- default=True,
- description="Use original image colors, or replace with other"
- )
-bpy.types.Scene.cubester_color_image = StringProperty(
- default="", name=""
- )
-bpy.types.Scene.cubester_load_color_image = StringProperty(
- default="",
- name="Load Color Image",
- subtype="FILE_PATH",
- update=adjust_selected_color_image
- )
-bpy.types.Scene.cubester_vertex_colors = {}
-# advanced
-bpy.types.Scene.cubester_advanced = BoolProperty(
- name="Advanced Options?"
- )
-bpy.types.Scene.cubester_random_weights = BoolProperty(
- name="Random Weights?"
- )
-bpy.types.Scene.cubester_weight_r = FloatProperty(
- name="Red",
- subtype="FACTOR",
- min=0.01, max=1.0,
- default=0.25
- )
-bpy.types.Scene.cubester_weight_g = FloatProperty(
- name="Green",
- subtype="FACTOR",
- min=0.01, max=1.0,
- default=0.25
- )
-bpy.types.Scene.cubester_weight_b = FloatProperty(
- name="Blue",
- subtype="FACTOR",
- min=0.01, max=1.0,
- default=0.25
- )
-bpy.types.Scene.cubester_weight_a = FloatProperty(
- name="Alpha",
- subtype="FACTOR",
- min=0.01, max=1.0,
- default=0.25
- )
+ del adv_obj.advanced_objects.cubester_vertex_colors[i]
class CubeSterPanel(Panel):
@@ -907,127 +706,123 @@ class CubeSterPanel(Panel):
def draw(self, context):
layout = self.layout.box()
scene = bpy.context.scene
+ adv_obj = scene.advanced_objects
images_found = 0
rows = 0
columns = 0
- layout.prop(scene, "cubester_audio_image", icon="IMAGE_COL")
- layout.separator()
+ layout.prop(adv_obj, "cubester_audio_image")
- if scene.cubester_audio_image == "image":
+ if adv_obj.cubester_audio_image == "image":
box = layout.box()
- box.prop(scene, "cubester_load_type")
+ box.prop(adv_obj, "cubester_load_type")
box.label("Image To Convert:")
- box.prop_search(scene, "cubester_image", bpy.data, "images")
- box.prop(scene, "cubester_load_image")
- layout.separator()
+ box.prop_search(adv_obj, "cubester_image", bpy.data, "images")
+ box.prop(adv_obj, "cubester_load_image")
# find number of approriate images if sequence
- if scene.cubester_load_type == "multiple":
+ if adv_obj.cubester_load_type == "multiple":
box = layout.box()
# display number of images found there
images = find_sequence_images(self, context)
- images_found = len(images[0]) if len(images[0]) <= scene.cubester_max_images \
- else scene.cubester_max_images
+ images_found = len(images[0]) if len(images[0]) <= adv_obj.cubester_max_images \
+ else adv_obj.cubester_max_images
if len(images[0]):
box.label(str(len(images[0])) + " Images Found", icon="PACKAGE")
- box.prop(scene, "cubester_max_images")
- box.prop(scene, "cubester_skip_images")
- box.prop(scene, "cubester_frame_step")
-
- layout.separator()
+ box.prop(adv_obj, "cubester_max_images")
+ box.prop(adv_obj, "cubester_skip_images")
+ box.prop(adv_obj, "cubester_frame_step")
box = layout.box()
- box.prop(scene, "cubester_skip_pixels")
- box.prop(scene, "cubester_size_per_hundred_pixels")
- box.prop(scene, "cubester_height_scale")
- box.prop(scene, "cubester_invert", icon="FILE_REFRESH")
+ col = box.column(align=True)
+ col.prop(adv_obj, "cubester_skip_pixels")
+ col.prop(adv_obj, "cubester_size_per_hundred_pixels")
+ col.prop(adv_obj, "cubester_height_scale")
+ box.prop(adv_obj, "cubester_invert", icon="FILE_REFRESH")
- layout.separator()
box = layout.box()
- box.prop(scene, "cubester_mesh_style", icon="MESH_GRID")
+ box.prop(adv_obj, "cubester_mesh_style", icon="MESH_GRID")
- if scene.cubester_mesh_style == "blocks":
- box.prop(scene, "cubester_block_style")
-
- # audio file
+ if adv_obj.cubester_mesh_style == "blocks":
+ box.prop(adv_obj, "cubester_block_style")
else:
- layout.prop(scene, "cubester_audio_path")
- layout.separator()
+ # audio file
+ layout.prop(adv_obj, "cubester_audio_path")
+
box = layout.box()
+ col = box.column(align=True)
+ col.prop(adv_obj, "cubester_audio_min_freq")
+ col.prop(adv_obj, "cubester_audio_max_freq")
- box.prop(scene, "cubester_audio_min_freq")
- box.prop(scene, "cubester_audio_max_freq")
box.separator()
- box.prop(scene, "cubester_audio_offset_type")
+ box.prop(adv_obj, "cubester_audio_offset_type")
- if scene.cubester_audio_offset_type == "frame":
- box.prop(scene, "cubester_audio_frame_offset")
+ if adv_obj.cubester_audio_offset_type == "frame":
+ box.prop(adv_obj, "cubester_audio_frame_offset")
+ box.prop(adv_obj, "cubester_audio_block_layout")
box.separator()
- box.prop(scene, "cubester_audio_block_layout")
- box.prop(scene, "cubester_audio_width_blocks")
- box.prop(scene, "cubester_audio_length_blocks")
+ col = box.column(align=True)
+ col.prop(adv_obj, "cubester_audio_width_blocks")
+ col.prop(adv_obj, "cubester_audio_length_blocks")
- rows = scene.cubester_audio_width_blocks
- columns = scene.cubester_audio_length_blocks
+ rows = adv_obj.cubester_audio_width_blocks
+ columns = adv_obj.cubester_audio_length_blocks
- box.prop(scene, "cubester_size_per_hundred_pixels")
+ col.prop(adv_obj, "cubester_size_per_hundred_pixels")
# materials
- layout.separator()
box = layout.box()
+ box.prop(adv_obj, "cubester_materials", icon="MATERIAL")
- box.prop(scene, "cubester_materials", icon="MATERIAL")
-
- if scene.cubester_materials == "image":
- box.prop(scene, "cubester_load_type")
+ if adv_obj.cubester_materials == "image":
+ box.prop(adv_obj, "cubester_load_type")
# find number of approriate images if sequence
- if scene.cubester_load_type == "multiple":
+ if adv_obj.cubester_load_type == "multiple":
# display number of images found there
images = find_sequence_images(self, context)
- images_found = len(images[0]) if len(images[0]) <= scene.cubester_max_images \
- else scene.cubester_max_images
+ images_found = len(images[0]) if len(images[0]) <= adv_obj.cubester_max_images \
+ else adv_obj.cubester_max_images
if len(images[0]):
box.label(str(len(images[0])) + " Images Found", icon="PACKAGE")
- box.prop(scene, "cubester_max_images")
- box.prop(scene, "cubester_skip_images")
- box.prop(scene, "cubester_frame_step")
+ box.prop(adv_obj, "cubester_max_images")
+ box.prop(adv_obj, "cubester_skip_images")
+ box.prop(adv_obj, "cubester_frame_step")
box.separator()
- if scene.cubester_audio_image == "image":
- box.prop(scene, "cubester_use_image_color", icon="COLOR")
+ if adv_obj.cubester_audio_image == "image":
+ box.prop(adv_obj, "cubester_use_image_color", icon="COLOR")
- if not scene.cubester_use_image_color or scene.cubester_audio_image == "audio":
+ if not adv_obj.cubester_use_image_color or adv_obj.cubester_audio_image == "audio":
box.label("Image To Use For Colors:")
- box.prop_search(scene, "cubester_color_image", bpy.data, "images")
- box.prop(scene, "cubester_load_color_image")
+ box.prop_search(adv_obj, "cubester_color_image", bpy.data, "images")
+ box.prop(adv_obj, "cubester_load_color_image")
- if scene.cubester_image in bpy.data.images:
- rows = int(bpy.data.images[scene.cubester_image].size[1] / (scene.cubester_skip_pixels + 1))
- columns = int(bpy.data.images[scene.cubester_image].size[0] / (scene.cubester_skip_pixels + 1))
+ if adv_obj.cubester_image in bpy.data.images:
+ rows = int(bpy.data.images[adv_obj.cubester_image].size[1] /
+ (adv_obj.cubester_skip_pixels + 1))
+ columns = int(bpy.data.images[adv_obj.cubester_image].size[0] /
+ (adv_obj.cubester_skip_pixels + 1))
- layout.separator()
box = layout.box()
- if scene.cubester_mesh_style == "blocks":
+ if adv_obj.cubester_mesh_style == "blocks":
box.label("Approximate Cube Count: " + str(rows * columns))
- box.label("Expected # Verts/Faces: " + str(rows * columns * 8) + " / " + str(rows * columns * 6))
+ box.label("Expected Verts/Faces: " + str(rows * columns * 8) + " / " + str(rows * columns * 6))
else:
box.label("Approximate Point Count: " + str(rows * columns))
- box.label("Expected # Verts/Faces: " + str(rows * columns) + " / " + str(rows * (columns - 1)))
+ box.label("Expected Verts/Faces: " + str(rows * columns) + " / " + str(rows * (columns - 1)))
# blocks and plane generation time values
- if scene.cubester_mesh_style == "blocks":
+ if adv_obj.cubester_mesh_style == "blocks":
slope = 0.0000876958
intercept = 0.02501
block_infl, frame_infl, intercept2 = 0.0025934, 0.38507, -0.5840189
-
else:
slope = 0.000017753
intercept = 0.04201
@@ -1035,21 +830,22 @@ class CubeSterPanel(Panel):
# if creating image based mesh
points = rows * columns
- if scene.cubester_audio_image == "image":
- if scene.cubester_load_type == "single":
+ if adv_obj.cubester_audio_image == "image":
+ if adv_obj.cubester_load_type == "single":
time = rows * columns * slope + intercept # approximate time count for mesh
else:
time = (points * slope) + intercept + (points * block_infl) + \
- (images_found / scene.cubester_skip_images * frame_infl) + intercept2
+ (images_found / adv_obj.cubester_skip_images * frame_infl) + intercept2
- box.label("Images To Be Used: " + str(int(images_found / scene.cubester_skip_images)))
-
- # audio based mesh
+ box.label("Images To Be Used: " + str(int(images_found / adv_obj.cubester_skip_images)))
else:
- box.label("Audio Track Length: " + scene.cubester_audio_file_length + " frames")
+ # audio based mesh
+ box.label("Audio Track Length: " + str(adv_obj.cubester_audio_file_length) + " frames")
block_infl, frame_infl, intercept = 0.0948, 0.0687566, -25.85985
- time = (points * block_infl) + (int(scene.cubester_audio_file_length) * frame_infl) + intercept
+ time = (points * block_infl) + (adv_obj.cubester_audio_file_length * frame_infl) + intercept
+ if time < 0.0: # usually no audio loaded
+ time = 0.0
time_mod = "s"
if time > 60: # convert to minutes if needed
@@ -1060,29 +856,31 @@ class CubeSterPanel(Panel):
box.label("Expected Time: " + str(time) + " " + time_mod)
# advanced
- if scene.cubester_audio_image == "image":
- layout.separator()
+ if adv_obj.cubester_audio_image == "image":
+ icon_1 = "TRIA_DOWN" if adv_obj.cubester_advanced else "TRIA_RIGHT"
+ # layout.separator()
box = layout.box()
- box.prop(scene, "cubester_advanced", icon="TRIA_DOWN")
- if bpy.context.scene.cubester_advanced:
- box.prop(scene, "cubester_random_weights", icon="RNDCURVE")
- box.separator()
+ box.prop(adv_obj, "cubester_advanced", icon=icon_1)
+
+ if adv_obj.cubester_advanced:
+ box.prop(adv_obj, "cubester_random_weights", icon="RNDCURVE")
- if not bpy.context.scene.cubester_random_weights:
+ if not adv_obj.cubester_random_weights:
box.label("RGBA Channel Weights", icon="COLOR")
- box.prop(scene, "cubester_weight_r")
- box.prop(scene, "cubester_weight_g")
- box.prop(scene, "cubester_weight_b")
- box.prop(scene, "cubester_weight_a")
+ col = box.column(align=True)
+ col.prop(adv_obj, "cubester_weight_r")
+ col.prop(adv_obj, "cubester_weight_g")
+ col.prop(adv_obj, "cubester_weight_b")
+ col.prop(adv_obj, "cubester_weight_a")
# generate mesh
- layout.separator()
layout.operator("mesh.cubester", icon="OBJECT_DATA")
class CubeSter(Operator):
bl_idname = "mesh.cubester"
bl_label = "Generate Mesh"
+ bl_description = "Generate a mesh from an Image or Sound File"
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
@@ -1090,18 +888,31 @@ class CubeSter(Operator):
start = timeit.default_timer()
scene = bpy.context.scene
+ adv_obj = scene.advanced_objects
- if scene.cubester_audio_image == "image":
- create_mesh_from_image(self, scene, verts, faces)
- frames = find_sequence_images(self, context)
- created = len(frames[0])
+ if adv_obj.cubester_audio_image == "image":
+ if adv_obj.cubester_image != "":
+ create_mesh_from_image(self, scene, verts, faces)
+ frames = find_sequence_images(self, context)
+ created = len(frames[0])
+ else:
+ self.report({'WARNING'},
+ "Please add an Image for Object generation. Operation Cancelled")
+ return {"CANCELLED"}
else:
- create_mesh_from_audio(self, scene, verts, faces)
- created = int(scene.cubester_audio_file_length)
+ if (adv_obj.cubester_audio_path != "" and
+ path.isfile(adv_obj.cubester_audio_path) and adv_obj.cubester_check_audio is True):
+
+ create_mesh_from_audio(self, scene, verts, faces)
+ created = adv_obj.cubester_audio_file_length
+ else:
+ self.report({'WARNING'},
+ "Please add an Sound File for Object generation. Operation Cancelled")
+ return {"CANCELLED"}
stop = timeit.default_timer()
- if scene.cubester_mesh_style == "blocks" or scene.cubester_audio_image == "audio":
+ if adv_obj.cubester_mesh_style == "blocks" or adv_obj.cubester_audio_image == "audio":
self.report({"INFO"},
"CubeSter: {} blocks and {} frame(s) "
"in {}s".format(str(int(len(verts) / 8)),
diff --git a/add_advanced_objects/delaunay_voronoi/DelaunayVoronoi.py b/add_advanced_objects/delaunay_voronoi/DelaunayVoronoi.py
index 18d7f38f..dcce7f68 100644
--- a/add_advanced_objects/delaunay_voronoi/DelaunayVoronoi.py
+++ b/add_advanced_objects/delaunay_voronoi/DelaunayVoronoi.py
@@ -61,13 +61,11 @@
import bpy
import math
-import sys
-import getopt
+
+# Globals
TOLERANCE = 1e-9
BIG_FLOAT = 1e38
-# TODO : Licence, prints, imports, autorship
-
class Context(object):
@@ -295,14 +293,14 @@ class Context(object):
def outTriple(self, s1, s2, s3):
self.triangles.append((s1.sitenum, s2.sitenum, s3.sitenum))
- if(self.debug):
+ if (self.debug):
print("circle through left=%d right=%d bottom=%d" % (s1.sitenum, s2.sitenum, s3.sitenum))
- elif(self.triangulate and self.doPrint):
+ elif (self.triangulate and self.doPrint):
print("%d %d %d" % (s1.sitenum, s2.sitenum, s3.sitenum))
def outBisector(self, edge):
self.lines.append((edge.a, edge.b, edge.c))
- if(self.debug):
+ if (self.debug):
print("line(%d) %gx+%gy=%g, bisecting %d %d" % (edge.edgenum, edge.a, edge.b,
edge.c, edge.reg[0].sitenum,
edge.reg[1].sitenum)
@@ -328,8 +326,8 @@ class Context(object):
self.edges.append((edge.edgenum, sitenumL, sitenumR))
- if(not self.triangulate):
- if(self.doPrint):
+ if (not self.triangulate):
+ if (self.doPrint):
print("e %d" % edge.edgenum)
print(" %d " % sitenumL)
print("%d" % sitenumR)
diff --git a/add_advanced_objects/delaunay_voronoi/__init__.py b/add_advanced_objects/delaunay_voronoi/__init__.py
index 1d210a2a..c32eb374 100644
--- a/add_advanced_objects/delaunay_voronoi/__init__.py
+++ b/add_advanced_objects/delaunay_voronoi/__init__.py
@@ -21,14 +21,13 @@
bl_info = {
"name": "Delaunay Voronoi",
"description": "Points cloud Delaunay triangulation in 2.5D "
- "(suitable for terrain modelling) or Voronoi diagram in 2D",
+ "(suitable for terrain modelling) or Voronoi diagram in 2D",
"author": "Domlysz, Oscurart",
"version": (1, 3),
"blender": (2, 7, 0),
"location": "View3D > Tools > GIS",
"warning": "",
"wiki_url": "https://github.com/domlysz/BlenderGIS/wiki",
- "tracker_url": "",
"category": ""
}
diff --git a/add_advanced_objects/delaunay_voronoi/delaunayVoronoiBlender.py b/add_advanced_objects/delaunay_voronoi/delaunayVoronoiBlender.py
index e937e7a1..707c45b4 100644
--- a/add_advanced_objects/delaunay_voronoi/delaunayVoronoiBlender.py
+++ b/add_advanced_objects/delaunay_voronoi/delaunayVoronoiBlender.py
@@ -2,9 +2,9 @@
import bpy
from .DelaunayVoronoi import (
- computeVoronoiDiagram,
- computeDelaunayTriangulation,
- )
+ computeVoronoiDiagram,
+ computeDelaunayTriangulation,
+ )
from bpy.types import (
Operator,
Panel,
@@ -12,6 +12,17 @@ from bpy.types import (
from bpy.props import EnumProperty
+# Globals
+# set to True to enable debug_prints
+DEBUG = False
+
+
+def debug_prints(text=""):
+ global DEBUG
+ if DEBUG and text:
+ print(text)
+
+
class Point:
def __init__(self, x, y, z):
self.x, self.y, self.z = x, y, z
@@ -56,45 +67,56 @@ class ToolsPanelDelaunay(Panel):
def draw(self, context):
layout = self.layout
- layout.label('Constellation')
- self.layout.operator("delaunay.triangulation")
- self.layout.operator("voronoi.tesselation")
- layout.label('Constellation')
- layout.operator("mesh.constellation", text="Cross Section")
+ adv_obj = context.scene.advanced_objects
+
+ box = layout.box()
+ col = box.column(align=True)
+ col.label("Point Cloud:")
+ col.operator("delaunay.triangulation")
+ col.operator("voronoi.tesselation")
+
+ box = layout.box()
+ col = box.column(align=True)
+ col.label("Constellation:")
+ col.operator("mesh.constellation", text="Cross Section")
+ col.prop(adv_obj, "constellation_limit")
class OBJECT_OT_TriangulateButton(Operator):
bl_idname = "delaunay.triangulation"
bl_label = "Triangulation"
- bl_description = "Terrain points cloud Delaunay triangulation in 2.5D"
- bl_options = {"UNDO"}
+ bl_description = ("Terrain points cloud Delaunay triangulation in 2.5D\n"
+ "Needs an existing Active Mesh Object")
+ bl_options = {"REGISTER", "UNDO"}
- def execute(self, context):
- # Get selected obj
- objs = bpy.context.selected_objects
- if len(objs) == 0 or len(objs) > 1:
- self.report({'INFO'}, "Selection is empty or too much object selected")
- return {'FINISHED'}
+ @classmethod
+ def poll(cls, context):
+ obj = context.active_object
+ return (obj is not None and obj.type == "MESH")
- obj = objs[0]
- if obj.type != 'MESH':
- self.report({'INFO'}, "Selection isn't a mesh")
- return {'FINISHED'}
+ def execute(self, context):
+ # move the check into the poll
+ obj = context.active_object
# Get points coodinates
r = obj.rotation_euler
s = obj.scale
mesh = obj.data
vertsPts = [vertex.co for vertex in mesh.vertices]
+
# Remove duplicate
verts = [[vert.x, vert.y, vert.z] for vert in vertsPts]
nDupli, nZcolinear = unique(verts)
nVerts = len(verts)
- print(str(nDupli) + " duplicates points ignored")
- print(str(nZcolinear) + " z colinear points excluded")
+
+ debug_prints(text=str(nDupli) + " duplicate points ignored")
+ debug_prints(str(nZcolinear) + " z colinear points excluded")
+
if nVerts < 3:
- self.report({'ERROR'}, "Not enough points")
- return {'FINISHED'}
+ self.report({"WARNING"},
+ "Not enough points to continue. Operation Cancelled")
+
+ return {"CANCELLED"}
# Check colinear
xValues = [pt[0] for pt in verts]
@@ -105,59 +127,63 @@ class OBJECT_OT_TriangulateButton(Operator):
return {'FINISHED'}
# Triangulate
- print("Triangulate " + str(nVerts) + " points...")
+ debug_prints(text="Triangulate " + str(nVerts) + " points...")
+
vertsPts = [Point(vert[0], vert[1], vert[2]) for vert in verts]
triangles = computeDelaunayTriangulation(vertsPts)
# reverse point order --> if all triangles are specified anticlockwise then all faces up
triangles = [tuple(reversed(tri)) for tri in triangles]
- print(str(len(triangles)) + " triangles")
+ debug_prints(text=str(len(triangles)) + " triangles")
# Create new mesh structure
- print("Create mesh...")
+ debug_prints(text="Create mesh...")
tinMesh = bpy.data.meshes.new("TIN") # create a new mesh
tinMesh.from_pydata(verts, [], triangles) # Fill the mesh with triangles
tinMesh.update(calc_edges=True) # Update mesh with new data
# Create an object with that mesh
tinObj = bpy.data.objects.new("TIN", tinMesh)
+
# Place object
tinObj.location = obj.location.copy()
tinObj.rotation_euler = r
tinObj.scale = s
+
# Update scene
bpy.context.scene.objects.link(tinObj) # Link object to scene
bpy.context.scene.objects.active = tinObj
tinObj.select = True
obj.select = False
- # Report
- self.report({'INFO'}, "Mesh created (" + str(len(triangles)) + " triangles)")
+
+ self.report({"INFO"},
+ "Mesh created (" + str(len(triangles)) + " triangles)")
+
return {'FINISHED'}
class OBJECT_OT_VoronoiButton(Operator):
bl_idname = "voronoi.tesselation"
bl_label = "Diagram"
- bl_description = "Points cloud Voronoi diagram in 2D"
+ bl_description = ("Points cloud Voronoi diagram in 2D\n"
+ "Needs an existing Active Mesh Object")
bl_options = {"REGISTER", "UNDO"}
meshType = EnumProperty(
- items=[("Edges", "Edges", ""), ("Faces", "Faces", "")],
- name="Mesh type",
- description=""
- )
+ items=[('Edges', "Edges", "Edges Only - do not fill Faces"),
+ ('Faces', "Faces", "Fill Faces in the new Object")],
+ name="Mesh type",
+ description="Type of geometry to generate"
+ )
- def execute(self, context):
- # Get selected obj
- objs = bpy.context.selected_objects
- if len(objs) == 0 or len(objs) > 1:
- self.report({'INFO'}, "Selection is empty or too much object selected")
- return {'FINISHED'}
+ @classmethod
+ def poll(cls, context):
+ obj = context.active_object
+ return (obj is not None and obj.type == "MESH")
- obj = objs[0]
- if obj.type != 'MESH':
- self.report({'INFO'}, "Selection isn't a mesh")
- return {'FINISHED'}
+ def execute(self, context):
+ # move the check into the poll
+ obj = context.active_object
# Get points coodinates
r = obj.rotation_euler
@@ -170,28 +196,36 @@ class OBJECT_OT_VoronoiButton(Operator):
nDupli, nZcolinear = unique(verts)
nVerts = len(verts)
- print(str(nDupli) + " duplicates points ignored")
- print(str(nZcolinear) + " z colinear points excluded")
+ debug_prints(text=str(nDupli) + " duplicates points ignored")
+ debug_prints(text=str(nZcolinear) + " z colinear points excluded")
if nVerts < 3:
- self.report({'ERROR'}, "Not enough points")
- return {'FINISHED'}
+ self.report({"WARNING"},
+ "Not enough points to continue. Operation Cancelled")
+
+ return {"CANCELLED"}
# Check colinear
xValues = [pt[0] for pt in verts]
yValues = [pt[1] for pt in verts]
+
if checkEqual(xValues) or checkEqual(yValues):
- self.report({'ERROR'}, "Points are colinear")
- return {'FINISHED'}
+ self.report({"WARNING"},
+ "Points are colinear. Operation Cancelled")
+
+ return {"CANCELLED"}
# Create diagram
- print("Tesselation... (" + str(nVerts) + " points)")
+ debug_prints(text="Tesselation... (" + str(nVerts) + " points)")
+
xbuff, ybuff = 5, 5
zPosition = 0
vertsPts = [Point(vert[0], vert[1], vert[2]) for vert in verts]
+
if self.meshType == "Edges":
pts, edgesIdx = computeVoronoiDiagram(
- vertsPts, xbuff, ybuff, polygonsOutput=False, formatOutput=True
+ vertsPts, xbuff, ybuff,
+ polygonsOutput=False, formatOutput=True
)
else:
pts, polyIdx = computeVoronoiDiagram(
@@ -227,8 +261,8 @@ class OBJECT_OT_VoronoiButton(Operator):
# Report
if self.meshType == "Edges":
- self.report({'INFO'}, "Mesh created (" + str(len(edgesIdx)) + " edges)")
+ self.report({"INFO"}, "Mesh created (" + str(len(edgesIdx)) + " edges)")
else:
- self.report({'INFO'}, "Mesh created (" + str(len(polyIdx)) + " polygons)")
+ self.report({"INFO"}, "Mesh created (" + str(len(polyIdx)) + " polygons)")
return {'FINISHED'}
diff --git a/add_advanced_objects/delaunay_voronoi/oscurart_constellation.py b/add_advanced_objects/delaunay_voronoi/oscurart_constellation.py
index babbfdc5..adde96c0 100644
--- a/add_advanced_objects/delaunay_voronoi/oscurart_constellation.py
+++ b/add_advanced_objects/delaunay_voronoi/oscurart_constellation.py
@@ -19,15 +19,17 @@
bl_info = {
"name": "Mesh: Constellation",
"author": "Oscurart",
- "version": (1, 0),
+ "version": (1, 1, 1),
"blender": (2, 67, 0),
"location": "Add > Mesh > Constellation",
- "description": "Adds a new Mesh From Selected",
+ "description": "Create a new Mesh From Selected",
"warning": "",
"wiki_url": "",
- "tracker_url": "",
"category": "Add Mesh"}
+# Note the setting is moved to __init__ search for
+# the adv_obj and advanced_objects patterns
+
import bpy
from bpy.types import Operator
from bpy.props import FloatProperty
@@ -56,51 +58,66 @@ def OscConstellation(limit):
edgei += 2
mesh = bpy.data.meshes.new("rsdata")
- object = bpy.data.objects.new("rsObject", mesh)
- bpy.context.scene.objects.link(object)
+ obj = bpy.data.objects.new("rsObject", mesh)
+ bpy.context.scene.objects.link(obj)
mesh.from_pydata(vertlist, edgelist, [])
-class Oscurart_Constellation (Operator):
+class Oscurart_Constellation(Operator):
bl_idname = "mesh.constellation"
bl_label = "Constellation"
- bl_description = "Create a Constellation Mesh"
+ bl_description = ("Create a Constellation Mesh - Cloud of Vertices\n"
+ "Note: can produce a lot of geometry\n"
+ "Needs an existing Active Mesh Object")
bl_options = {'REGISTER', 'UNDO'}
limit = FloatProperty(
- name='Limit',
- default=2,
- min=0
- )
+ name="Threshold",
+ description="Edges will be created only if the distance\n"
+ "between vertices is smaller than this value",
+ default=2,
+ min=0
+ )
@classmethod
def poll(cls, context):
- return(bpy.context.active_object.type == "MESH")
+ obj = context.active_object
+ return (obj and obj.type == "MESH")
+
+ def invoke(self, context, event):
+ adv_obj = context.scene.advanced_objects
+ self.limit = adv_obj.constellation_limit
+
+ return self.execute(context)
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.prop(self, "limit")
def execute(self, context):
- OscConstellation(self.limit)
+ try:
+ OscConstellation(self.limit)
+ except Exception as e:
+ print("\n[Add Advanced Objects]\nOperator: mesh.constellation\n{}".format(e))
- return {'FINISHED'}
+ self.report({"WARNING"},
+ "Constellation Operation could not be Completed (See Console for more Info)")
+ return {"CANCELLED"}
-# Register
+ return {'FINISHED'}
-def add_osc_constellation_button(self, context):
- self.layout.operator(
- Oscurart_Constellation.bl_idname,
- text="Constellation",
- icon="PLUGIN")
+# Register
def register():
bpy.utils.register_class(Oscurart_Constellation)
- bpy.types.INFO_MT_mesh_add.append(add_osc_constellation_button)
def unregister():
bpy.utils.unregister_class(Oscurart_Constellation)
- bpy.types.INFO_MT_mesh_add.remove(add_osc_constellation_button)
-if __name__ == '__main__':
+if __name__ == "__main__":
register()
diff --git a/add_advanced_objects/drop_to_ground.py b/add_advanced_objects/drop_to_ground.py
index 801b7e94..744a2d6b 100644
--- a/add_advanced_objects/drop_to_ground.py
+++ b/add_advanced_objects/drop_to_ground.py
@@ -19,14 +19,13 @@
bl_info = {
"name": "Drop to Ground1",
"author": "Unnikrishnan(kodemax), Florian Meyer(testscreenings)",
- "version": (1, 2),
+ "version": (1, 2, 1),
"blender": (2, 71, 0),
"location": "3D View > Toolshelf > Tools Tab",
"description": "Drop selected objects on active object",
"warning": "",
"wiki_url": "https://wiki.blender.org/index.php/Extensions:2.6/Py/"
"Scripts/Object/Drop_to_ground",
- "tracker_url": "https://developer.blender.org/maniphest/task/edit/form/2/",
"category": "Object"}
@@ -59,6 +58,7 @@ def transform_ground_to_world(sc, ground):
tmp_ground = bpy.data.objects.new('tmpGround', tmpMesh)
sc.objects.link(tmp_ground)
sc.update()
+
return tmp_ground
@@ -120,12 +120,16 @@ def drop_objectsall(self, context):
lowest_world_co = ob.location
else:
lowest_world_co = get_lowest_world_co(context, ob)
+
if not lowest_world_co:
- print(ob.type, 'is not supported. Failed to drop', ob.name)
+ message = "Type {} is not supported. Failed to drop {}".format(ob.type, ob.name)
+ self.reported.append(message)
continue
is_hit, hit_location, hit_normal, hit_index = tmp_ground.ray_cast(lowest_world_co, down)
+
if not is_hit:
- print(ob.name, 'didn\'t hit the ground')
+ message = ob.name + " did not hit the Ground"
+ self.reported.append(message)
continue
# simple drop down
@@ -169,12 +173,16 @@ def drop_objects(self, context):
lowest_world_co = ob.location
else:
lowest_world_co = get_lowest_world_co(context, ob)
+
if not lowest_world_co:
- print(ob.type, 'is not supported. Failed to drop', ob.name)
+ message = "Type {} is not supported. Failed to drop {}".format(ob.type, ob.name)
+ self.reported.append(message)
continue
+
is_hit, hit_location, hit_normal, hit_index = tmp_ground.ray_cast(lowest_world_co, down)
if not is_hit:
- print(ob.name, 'didn\'t hit the ground')
+ message = ob.name + " did not hit the Ground"
+ self.reported.append(message)
continue
# simple drop down
@@ -209,8 +217,8 @@ def drop_objects(self, context):
class OBJECT_OT_drop_to_ground(Operator):
bl_idname = "object.drop_on_active"
bl_label = "Drop to Ground"
+ bl_description = "Drop selected objects on the active object"
bl_options = {'REGISTER', 'UNDO'}
- bl_description = "Drop selected objects on active object"
align = BoolProperty(
name="Align to ground",
@@ -220,22 +228,31 @@ class OBJECT_OT_drop_to_ground(Operator):
name="Use Center",
description="Drop to objects origins",
default=False)
+ reported = []
@classmethod
def poll(cls, context):
return len(context.selected_objects) >= 2
def execute(self, context):
- print('\nDropping Objects')
drop_objects(self, context)
+
+ if self.reported:
+ self.report({"INFO"},
+ "Operation failed on some objects. See the Console for more Info")
+ report_items = " \n".join(self.reported)
+ print("\n[Drop to Ground Report]\n{}\n".format(report_items))
+
+ self.reported = []
+
return {'FINISHED'}
class OBJECT_OT_drop_all_ground(Operator):
bl_idname = "object.drop_all_active"
- bl_label = "Drop to Ground"
- bl_options = {'REGISTER', 'UNDO'}
+ bl_label = "Drop All to Ground (Active Object)"
bl_description = "Drop selected objects on active object"
+ bl_options = {'REGISTER', 'UNDO'}
align = BoolProperty(
name="Align to ground",
@@ -245,33 +262,45 @@ class OBJECT_OT_drop_all_ground(Operator):
name="Use Center",
description="Drop to objects origins",
default=False)
+ reported = []
+
+ @classmethod
+ def poll(cls, context):
+ return context.active_object is not None
def execute(self, context):
- print('\nDropping Objects')
drop_objectsall(self, context)
+ if self.reported:
+ self.report({"INFO"},
+ "Operation failed on some objects. See the Console for more Info")
+ report_items = " \n".join(self.reported)
+ print("\n[Drop All to Ground Report]\n{}\n".format(report_items))
+
+ self.reported = []
+
return {'FINISHED'}
-class drop_help(Operator):
+class Drop_help(Operator):
bl_idname = "help.drop"
bl_label = ""
+ is_all = BoolProperty(
+ default=True,
+ options={"HIDDEN"}
+ )
+
def draw(self, context):
layout = self.layout
layout.label("To use:")
- layout.label("___________________________")
- layout.label("Drop selected :-")
-
- layout.label("Name the base object 'Ground'")
- layout.label("Select the object/s to drop")
- layout.label("Then Shift Select 'Ground'")
- layout.label("___________________________")
-
- layout.label("Drop all :-")
-
- layout.label("select the ground mesh , and press Drop all")
+ if self.is_all is False:
+ layout.label("Name the base object 'Ground'")
+ layout.label("Select the object's to drop")
+ layout.label("Then Shift Select 'Ground'")
+ else:
+ layout.label("Select the ground mesh and press Drop all")
def execute(self, context):
return {'FINISHED'}
@@ -290,25 +319,31 @@ class Drop_Operator_Panel(Panel):
def draw(self, context):
layout = self.layout
- row = layout.row()
- row = layout.split(0.80)
+
+ row = layout.split(percentage=0.8, align=True)
row.operator(OBJECT_OT_drop_to_ground.bl_idname,
text="Drop Selected")
- row = layout.row()
+ row.operator("help.drop", icon="LAYER_USED").is_all = False
+
+ row = layout.split(percentage=0.8, align=True)
row.operator(OBJECT_OT_drop_all_ground.bl_idname,
text="Drop All")
- row.operator('help.drop', icon='INFO')
+ row.operator("help.drop", icon="LAYER_USED").is_all = True
# Register
def register():
- bpy.utils.register_module(__name__)
- pass
+ bpy.utils.register_class(OBJECT_OT_drop_all_ground)
+ bpy.utils.register_class(OBJECT_OT_drop_to_ground)
+ bpy.utils.register_class(Drop_Operator_Panel)
+ bpy.utils.register_class(Drop_help)
def unregister():
- bpy.utils.unregister_module(__name__)
- pass
+ bpy.utils.unregister_class(OBJECT_OT_drop_all_ground)
+ bpy.utils.unregister_class(OBJECT_OT_drop_to_ground)
+ bpy.utils.unregister_class(Drop_Operator_Panel)
+ bpy.utils.unregister_class(Drop_help)
if __name__ == "__main__":
diff --git a/add_advanced_objects/make_struts.py b/add_advanced_objects/make_struts.py
index 7f754ea8..58e149ab 100644
--- a/add_advanced_objects/make_struts.py
+++ b/add_advanced_objects/make_struts.py
@@ -21,22 +21,9 @@
# <pep8 compliant>
-"""
-bl_info = {
- "name": "Strut Generator",
- "author": "Bill Currie",
- "blender": (2, 6, 3),
- "api": 35622,
- "location": "View3D > Add > Mesh > Struts",
- "description": "Add struts meshes based on selected truss meshes",
- "warning": "can get very high-poly",
- "wiki_url": "",
- "tracker_url": "",
- "category": "Add Mesh"}
-"""
-
import bpy
import bmesh
+from bpy.types import Operator
from bpy.props import (
FloatProperty,
IntProperty,
@@ -48,8 +35,7 @@ from mathutils import (
Quaternion,
)
from math import (
- pi,
- cos,
+ pi, cos,
sin,
)
@@ -71,6 +57,7 @@ def build_cossin(n):
def select_up(axis):
+ # if axis.length != 0 and (abs(axis[0] / axis.length) < 1e-5 and abs(axis[1] / axis.length) < 1e-5):
if (abs(axis[0] / axis.length) < 1e-5 and abs(axis[1] / axis.length) < 1e-5):
up = Vector((-1, 0, 0))
else:
@@ -109,21 +96,21 @@ def select_up(axis):
# vertices for the created strut.
-def make_strut(v1, v2, id, od, n, solid, loops):
+def make_strut(v1, v2, ind, od, n, solid, loops):
v1 = Vector(v1)
v2 = Vector(v2)
axis = v2 - v1
pos = [(0, od / 2)]
if loops:
- pos += [((od - id) / 2, od / 2),
- (axis.length - (od - id) / 2, od / 2)]
+ pos += [((od - ind) / 2, od / 2),
+ (axis.length - (od - ind) / 2, od / 2)]
pos += [(axis.length, od / 2)]
if solid:
- pos += [(axis.length, id / 2)]
+ pos += [(axis.length, ind / 2)]
if loops:
- pos += [(axis.length - (od - id) / 2, id / 2),
- ((od - id) / 2, id / 2)]
- pos += [(0, id / 2)]
+ pos += [(axis.length - (od - ind) / 2, ind / 2),
+ ((od - ind) / 2, ind / 2)]
+ pos += [(0, ind / 2)]
vps = len(pos)
fps = vps
if not solid:
@@ -156,7 +143,7 @@ def make_strut(v1, v2, id, od, n, solid, loops):
for j in range(fps):
f = (i - 1) * fps + j
faces[f] = [base + j, j, (j + 1) % vps, base + (j + 1) % vps]
- # print(verts,faces)
+
return verts, faces
@@ -452,7 +439,7 @@ def make_manifold_struts(truss_obj, od, segments):
return verts, faces
-def make_simple_struts(truss_mesh, id, od, segments, solid, loops):
+def make_simple_struts(truss_mesh, ind, od, segments, solid, loops):
vps = 2
if solid:
vps *= 2
@@ -466,10 +453,11 @@ def make_simple_struts(truss_mesh, id, od, segments, solid, loops):
faces = [None] * len(truss_mesh.edges) * segments * fps
vbase = 0
fbase = 0
+
for e in truss_mesh.edges:
v1 = truss_mesh.vertices[e.vertices[0]]
v2 = truss_mesh.vertices[e.vertices[1]]
- v, f = make_strut(v1.co, v2.co, id, od, segments, solid, loops)
+ v, f = make_strut(v1.co, v2.co, ind, od, segments, solid, loops)
for fv in f:
for i in range(len(fv)):
fv[i] += vbase
@@ -481,14 +469,13 @@ def make_simple_struts(truss_mesh, id, od, segments, solid, loops):
# print (base * 100 / len(verts))
vbase += vps * segments
fbase += fps * segments
- # print(verts,faces)
+
return verts, faces
-def create_struts(self, context, id, od, segments, solid, loops, manifold):
+def create_struts(self, context, ind, od, segments, solid, loops, manifold):
build_cossin(segments)
- bpy.context.user_preferences.edit.use_global_undo = False
for truss_obj in bpy.context.scene.objects:
if not truss_obj.select:
continue
@@ -499,7 +486,7 @@ def create_struts(self, context, id, od, segments, solid, loops, manifold):
if manifold:
verts, faces = make_manifold_struts(truss_obj, od, segments)
else:
- verts, faces = make_simple_struts(truss_mesh, id, od, segments,
+ verts, faces = make_simple_struts(truss_mesh, ind, od, segments,
solid, loops)
mesh = bpy.data.meshes.new("Struts")
mesh.from_pydata(verts, [], faces)
@@ -509,58 +496,92 @@ def create_struts(self, context, id, od, segments, solid, loops, manifold):
obj.location = truss_obj.location
bpy.context.scene.objects.active = obj
mesh.update()
- bpy.context.user_preferences.edit.use_global_undo = True
- return {'FINISHED'}
-class Struts(bpy.types.Operator):
- """Add one or more struts meshes based on selected truss meshes"""
+class Struts(Operator):
bl_idname = "mesh.generate_struts"
bl_label = "Struts"
- bl_description = """Add one or more struts meshes based on selected truss meshes"""
+ bl_description = ("Add one or more struts meshes based on selected truss meshes \n"
+ "Note: can get very high poly\n"
+ "Needs an existing Active Mesh Object")
bl_options = {'REGISTER', 'UNDO'}
- id = FloatProperty(name="Inside Diameter",
- description="diameter of inner surface",
- min=0.0,
- soft_min=0.0,
- max=100,
- soft_max=100,
- default=0.04)
- od = FloatProperty(name="Outside Diameter",
- description="diameter of outer surface",
- min=0.001,
- soft_min=0.001,
- max=100,
- soft_max=100,
- default=0.05)
- manifold = BoolProperty(name="Manifold",
- description="Connect struts to form a single solid.",
- default=False)
- solid = BoolProperty(name="Solid",
- description="Create inner surface.",
- default=False)
- loops = BoolProperty(name="Loops",
- description="Create sub-surf friendly loops.",
- default=False)
- segments = IntProperty(name="Segments",
- description="Number of segments around strut",
- min=3, soft_min=3,
- max=64, soft_max=64,
- default=12)
+ ind = FloatProperty(
+ name="Inside Diameter",
+ description="Diameter of inner surface",
+ min=0.0, soft_min=0.0,
+ max=100, soft_max=100,
+ default=0.04
+ )
+ od = FloatProperty(
+ name="Outside Diameter",
+ description="Diameter of outer surface",
+ min=0.001, soft_min=0.001,
+ max=100, soft_max=100,
+ default=0.05
+ )
+ manifold = BoolProperty(
+ name="Manifold",
+ description="Connect struts to form a single solid",
+ default=False
+ )
+ solid = BoolProperty(
+ name="Solid",
+ description="Create inner surface",
+ default=False
+ )
+ loops = BoolProperty(
+ name="Loops",
+ description="Create sub-surf friendly loops",
+ default=False
+ )
+ segments = IntProperty(
+ name="Segments",
+ description="Number of segments around strut",
+ min=3, soft_min=3,
+ max=64, soft_max=64,
+ default=12
+ )
+
+ def draw(self, context):
+ layout = self.layout
+
+ col = layout.column(align=True)
+ col.prop(self, "ind")
+ col.prop(self, "od")
+ col.prop(self, "segments")
+ col.separator()
+
+ col.prop(self, "manifold")
+ col.prop(self, "solid")
+ col.prop(self, "loops")
+
+ @classmethod
+ def poll(cls, context):
+ obj = context.active_object
+ return obj is not None and obj.type == "MESH"
def execute(self, context):
+ store_undo = bpy.context.user_preferences.edit.use_global_undo
+ bpy.context.user_preferences.edit.use_global_undo = False
keywords = self.as_keywords()
- return create_struts(self, context, **keywords)
+ try:
+ create_struts(self, context, **keywords)
+ bpy.context.user_preferences.edit.use_global_undo = store_undo
+
+ return {"FINISHED"}
-def menu_func(self, context):
- self.layout.operator(Struts.bl_idname, text="Struts", icon='PLUGIN')
+ except Exception as e:
+ bpy.context.user_preferences.edit.use_global_undo = store_undo
+ self.report({"WARNING"},
+ "Make Struts could not be performed. Operation Cancelled")
+ print("\n[mesh.generate_struts]\n{}".format(e))
+ return {"CANCELLED"}
def register():
bpy.utils.register_module(__name__)
- bpy.types.INFO_MT_mesh_add.append(menu_func)
def unregister():
diff --git a/add_advanced_objects/mesh_easylattice.py b/add_advanced_objects/mesh_easylattice.py
index 13512adf..91a167dc 100644
--- a/add_advanced_objects/mesh_easylattice.py
+++ b/add_advanced_objects/mesh_easylattice.py
@@ -16,11 +16,12 @@
#
# ##### END GPL LICENSE BLOCK #####
+# TODO: find a better solution for allowing more than one lattice per scene
bl_info = {
"name": "Easy Lattice Object",
"author": "Kursad Karatas",
- "version": (0, 5),
+ "version": (0, 5, 1),
"blender": (2, 66, 0),
"location": "View3D > Easy Lattice",
"description": "Create a lattice for shape editing",
@@ -35,9 +36,11 @@ from mathutils import (
Matrix,
Vector,
)
+from bpy.types import Operator
from bpy.props import (
EnumProperty,
IntProperty,
+ StringProperty,
)
@@ -86,7 +89,8 @@ def createLattice(obj, size, pos, props):
# the size from bbox
ob.scale = size
- # the rotation comes from the combined obj world matrix which was converted to euler pairs
+ # the rotation comes from the combined obj world
+ # matrix which was converted to euler pairs
ob.rotation_euler = buildRot_World(obj)
ob.show_x_ray = True
@@ -263,10 +267,11 @@ def run(lat_props):
if obj.type == "MESH":
# set global property for the currently active latticed object
- bpy.types.Scene.activelatticeobject = bpy.props.StringProperty(
- name="currentlatticeobject",
- default=""
- )
+ # removed in __init__ on unregister if created
+ bpy.types.Scene.activelatticeobject = StringProperty(
+ name="currentlatticeobject",
+ default=""
+ )
bpy.types.Scene.activelatticeobject = obj.name
modifiersDelete(obj)
@@ -311,70 +316,85 @@ def main(context, latticeprops):
run(latticeprops)
-class EasyLattice(bpy.types.Operator):
- """Adds a Lattice modifier ready to edit"""
+class EasyLattice(Operator):
bl_idname = "object.easy_lattice"
bl_label = "Easy Lattice Creator"
- bl_space_type = "VIEW_3D"
- bl_region_type = "TOOLS"
+ bl_description = ("Create a Lattice modifier ready to edit\n"
+ "Needs an existing Active Mesh Object\n"
+ "Note: Works only with one lattice per scene")
lat_u = IntProperty(
- name="Lattice u",
- default=3
- )
+ name="Lattice u",
+ description="Points in u direction",
+ default=3
+ )
lat_w = IntProperty(
- name="Lattice w",
- default=3
- )
+ name="Lattice w",
+ description="Points in w direction",
+ default=3
+ )
lat_m = IntProperty(
- name="Lattice m",
- default=3
+ name="Lattice m",
+ description="Points in m direction",
+ default=3
+ )
+ lat_types = (('KEY_LINEAR', "Linear", "Linear Interpolation type"),
+ ('KEY_CARDINAL', "Cardinal", "Cardinal Interpolation type"),
+ ('KEY_BSPLINE', "BSpline", "Key BSpline Interpolation Type")
)
- lat_types = (('0', 'KEY_LINEAR', '0'),
- ('1', 'KEY_CARDINAL', '1'),
- ('2', 'KEY_BSPLINE', '2'))
lat_type = EnumProperty(
- name="Lattice Type",
- items=lat_types,
- default='0'
- )
+ name="Lattice Type",
+ description="Choose Lattice Type",
+ items=lat_types,
+ default='KEY_LINEAR'
+ )
@classmethod
def poll(cls, context):
- return context.active_object is not None
+ obj = context.active_object
+ return obj is not None and obj.type == "MESH"
+
+ def draw(self, context):
+ layout = self.layout
+
+ col = layout.column(align=True)
+ col.prop(self, "lat_u")
+ col.prop(self, "lat_w")
+ col.prop(self, "lat_m")
+
+ layout.prop(self, "lat_type")
def execute(self, context):
lat_u = self.lat_u
lat_w = self.lat_w
lat_m = self.lat_m
- # this is a reference to the "items" used to generate the
- # enum property
- lat_type = self.lat_types[int(self.lat_type)][1]
+ # enum property no need to complicate things
+ lat_type = self.lat_type
lat_props = [lat_u, lat_w, lat_m, lat_type]
+ try:
+ main(context, lat_props)
+
+ except Exception as e:
+ print("\n[Add Advanced Objects]\nOperator:object.easy_lattice\n{}\n".format(e))
+ self.report({'WARNING'},
+ "Easy Lattice Creator could not be completed (See Console for more info)")
- main(context, lat_props)
+ return {"CANCELLED"}
- return {'FINISHED'}
+ return {"FINISHED"}
def invoke(self, context, event):
wm = context.window_manager
return wm.invoke_props_dialog(self)
-def menu_draw(self, context):
- self.layout.operator_context = 'INVOKE_REGION_WIN'
- self.layout.operator(EasyLattice.bl_idname, "Easy Lattice")
-
-
def register():
bpy.utils.register_class(EasyLattice)
- bpy.types.VIEW3D_MT_edit_mesh_specials.append(menu_draw)
def unregister():
bpy.utils.unregister_class(EasyLattice)
- bpy.types.VIEW3D_MT_edit_mesh_specials.remove(menu_draw)
if __name__ == "__main__":
diff --git a/add_advanced_objects/object_add_chain.py b/add_advanced_objects/object_add_chain.py
index 57babfd6..8b182c82 100644
--- a/add_advanced_objects/object_add_chain.py
+++ b/add_advanced_objects/object_add_chain.py
@@ -30,20 +30,18 @@ bl_info = {
}
import bpy
-from bpy.types import (
- Operator,
- Panel,
- )
+from bpy.types import Operator
def Add_Chain():
# Adds Empty to scene
- bpy.ops.object.add(type='EMPTY',
- view_align=False,
- enter_editmode=False,
- location=(0, 0, 0),
- rotation=(0, 0, 0),
- )
+ bpy.ops.object.add(
+ type='EMPTY',
+ view_align=False,
+ enter_editmode=False,
+ location=(0, 0, 0),
+ rotation=(0, 0, 0),
+ )
# Changes name of Empty to rot_link adds variable emp
emp = bpy.context.object
@@ -53,24 +51,26 @@ def Add_Chain():
emp.rotation_euler = [1.570796, 0, 0]
# Adds Curve Path to scene
- bpy.ops.curve.primitive_nurbs_path_add(view_align=False,
- enter_editmode=False,
- location=(0, 0, 0),
- rotation=(0, 0, 0),
- )
+ bpy.ops.curve.primitive_nurbs_path_add(
+ view_align=False,
+ enter_editmode=False,
+ location=(0, 0, 0),
+ rotation=(0, 0, 0),
+ )
# Change Curve name to deform adds variable curv
curv = bpy.context.object
curv.name = "deform"
# Inserts Torus primitive
- bpy.ops.mesh.primitive_torus_add(major_radius=1,
- minor_radius=0.25,
- major_segments=12,
- minor_segments=4,
- abso_major_rad=1,
- abso_minor_rad=0.5,
- )
+ bpy.ops.mesh.primitive_torus_add(
+ major_radius=1,
+ minor_radius=0.25,
+ major_segments=12,
+ minor_segments=4,
+ abso_major_rad=1,
+ abso_minor_rad=0.5,
+ )
# Positions Torus primitive to center of scene
bpy.context.active_object.location = 0.0, 0.0, 0.0
@@ -98,22 +98,23 @@ def Add_Chain():
# Toggle into editmode
bpy.ops.object.editmode_toggle()
- # TODO, may be better to move objects directly.
+ # TODO, may be better to move objects directly
# Translate curve object
- bpy.ops.transform.translate(value=(2, 0, 0),
- constraint_axis=(True, False, False),
- constraint_orientation='GLOBAL',
- mirror=False,
- proportional='DISABLED',
- proportional_edit_falloff='SMOOTH',
- proportional_size=1,
- snap=False,
- snap_target='CLOSEST',
- snap_point=(0, 0, 0),
- snap_align=False,
- snap_normal=(0, 0, 0),
- release_confirm=False,
- )
+ bpy.ops.transform.translate(
+ value=(2, 0, 0),
+ constraint_axis=(True, False, False),
+ constraint_orientation='GLOBAL',
+ mirror=False,
+ proportional='DISABLED',
+ proportional_edit_falloff='SMOOTH',
+ proportional_size=1,
+ snap=False,
+ snap_target='CLOSEST',
+ snap_point=(0, 0, 0),
+ snap_align=False,
+ snap_normal=(0, 0, 0),
+ release_confirm=False,
+ )
# Toggle into objectmode
bpy.ops.object.editmode_toggle()
@@ -151,19 +152,27 @@ class AddChain(Operator):
bl_options = {'REGISTER', 'UNDO'}
def execute(self, context):
- Add_Chain()
+ try:
+ Add_Chain()
+
+ except Exception as e:
+ self.report({'WARNING'},
+ "Some operations could not be performed (See Console for more info)")
+
+ print("\n[Add Advanced Objects]\nOperator: "
+ "mesh.primitive_chain_add\nError: {}".format(e))
+
+ return {'CANCELLED'}
return {'FINISHED'}
def register():
- bpy.utils.register_module(__name__)
- pass
+ bpy.utils.register_class(AddChain)
def unregister():
- bpy.utils.unregister_module(__name__)
- pass
+ bpy.utils.unregister_class(AddChain)
if __name__ == "__main__":
diff --git a/add_advanced_objects/object_laplace_lightning.py b/add_advanced_objects/object_laplace_lightning.py
index ceaf6cd6..857682b0 100644
--- a/add_advanced_objects/object_laplace_lightning.py
+++ b/add_advanced_objects/object_laplace_lightning.py
@@ -16,18 +16,18 @@
#
# ##### END GPL LICENSE BLOCK #####
-# NOTE Needs cleanup, reorganizing, make prints optional
+# NOTE: moved the winmgr properties to __init__ and scene
+# search for context.scene.advanced_objects
bl_info = {
"name": "Laplacian Lightning",
"author": "teldredge",
- "version": (0, 2, 7),
- "blender": (2, 71, 0),
+ "version": (0, 2, 9),
+ "blender": (2, 78, 0),
"location": "View3D > Toolshelf > Create Tab",
"description": "Lightning mesh generator using laplacian growth algorithm",
- "warning": "Beta",
+ "warning": "",
"wiki_url": "http://www.funkboxing.com/wordpress/?p=301",
- "tracker_url": "https://developer.blender.org/maniphest/task/edit/form/2/",
"category": "Object"}
# BLENDER LAPLACIAN LIGHTNING
@@ -110,19 +110,43 @@ v0.x -
import bpy
import time
import random
-from math import sqrt
+from bpy.types import (
+ Operator,
+ Panel,
+ )
+# from math import sqrt
from mathutils import Vector
import struct
import bisect
import os.path
+
+# -- Globals --
notZero = 0.0000000001
-winmgr = bpy.context.window_manager
+# set to True to enable debug prints
+DEBUG = False
+
+
+# Utility Functions
+# func - function name, text - message, var - variable to print
+# it can have one variable to observe
+def debug_prints(func="", text="Message", var=None):
+ global DEBUG
+ if DEBUG:
+ print("\n[{}]\nmessage: {}".format(func, text))
+ if var:
+ print("variable: ", var)
+
+
+# pass variables just like for the regular prints
+def debug_print_vars(*args, **kwargs):
+ global DEBUG
+ if DEBUG:
+ print(*args, **kwargs)
-# UTILITY FXNS #
def within(x, y, d):
- # CHECK IF x-d <= y <= x+d
+ # CHECK IF x - d <= y <= x + d
if x - d <= y and x + d >= y:
return True
else:
@@ -196,7 +220,7 @@ def jitterCells(aList, jit):
def deDupe(seq, idfun=None):
- # THANKS TO THIS GUY - http://www.peterbe.com/plog/uniqifiers-benchmark
+ # Thanks to this guy - http://www.peterbe.com/plog/uniqifiers-benchmark
if idfun is None:
def idfun(x):
return x
@@ -211,7 +235,7 @@ def deDupe(seq, idfun=None):
return result
-# VISUALIZATION FXNS #
+# Visulization functions
def writeArrayToVoxel(arr, filename):
gridS = 64
@@ -222,7 +246,8 @@ def writeArrayToVoxel(arr, filename):
try:
aGrid[a[0] + half][a[1] + half][a[2] + half] = bitOn
except:
- print('Particle beyond voxel domain')
+ debug_prints(func="writeArrayToVoxel", text="Particle beyond voxel domain")
+
file = open(filename, "wb")
for z in range(gridS):
for y in range(gridS):
@@ -278,15 +303,12 @@ def makeMeshCube(msize):
# verts = [(0,0,0),(0,5,0),(5,5,0),(5,0,0),(0,0,5),(0,5,5),(5,5,5),(5,0,5)]
verts = [(-m2, -m2, -m2), (-m2, m2, -m2), (m2, m2, -m2), (m2, -m2, -m2),
(-m2, -m2, m2), (-m2, m2, m2), (m2, m2, m2), (m2, -m2, m2)]
- faces = [(0, 1, 2, 3), (4, 5, 6, 7), (0, 4, 5, 1), (1, 5, 6, 2), (2, 6, 7, 3), (3, 7, 4, 0)]
-
+ faces = [
+ (0, 1, 2, 3), (4, 5, 6, 7), (0, 4, 5, 1),
+ (1, 5, 6, 2), (2, 6, 7, 3), (3, 7, 4, 0)
+ ]
# Define mesh and object
mmesh = bpy.data.meshes.new("Cube")
- # mobject = bpy.data.objects.new("Cube", mmesh)
-
- # Set location and scene of object
- # mobject.location = bpy.context.scene.cursor_location
- # bpy.context.scene.objects.link(mobject)
# Create mesh
mmesh.from_pydata(verts, [], faces)
@@ -304,8 +326,9 @@ def writeArrayToCubes(arr, gridBU, orig, cBOOL=False, jBOOL=True):
ob.location.x = (x * gridBU) + orig[0]
ob.location.y = (y * gridBU) + orig[1]
ob.location.z = (z * gridBU) + orig[2]
- if cBOOL: # MOSTLY UNUSED
- # POS+BLUE, NEG-RED, ZERO:BLACK
+
+ if cBOOL: # mostly unused
+ # pos + blue, neg - red, zero: black
col = (1.0, 1.0, 1.0, 1.0)
if a[3] == 0:
col = (0.0, 0.0, 0.0, 1.0)
@@ -316,9 +339,10 @@ def writeArrayToCubes(arr, gridBU, orig, cBOOL=False, jBOOL=True):
ob.color = col
bpy.context.scene.objects.link(ob)
bpy.context.scene.update()
+
if jBOOL:
- # SELECTS ALL CUBES w/ ?bpy.ops.object.join() b/c
- # CAN'T JOIN ALL CUBES TO A SINGLE MESH RIGHT... ARGH...
+ # Selects all cubes w/ ?bpy.ops.object.join() b/c
+ # Can't join all cubes to a single mesh right... argh...
for q in bpy.context.scene.objects:
q.select = False
if q.name[0:5] == 'xCUBE':
@@ -365,7 +389,7 @@ def writeArrayToMesh(mname, arr, gridBU, rpt=None):
return mob
-# OUT OF ORDER - SOME PROBLEM WITH IT ADDING (0,0,0)
+# out of order - some problem with it adding (0,0,0)
def writeArrayToCurves(cname, arr, gridBU, bd=.05, rpt=None):
cur = bpy.data.curves.new('fslg_curve', 'CURVE')
cur.use_fill_front = False
@@ -374,12 +398,14 @@ def writeArrayToCurves(cname, arr, gridBU, bd=.05, rpt=None):
cur.bevel_resolution = 2
cob = bpy.data.objects.new(cname, cur)
cob.scale = (gridBU, gridBU, gridBU)
+
if rpt:
addReportProp(cob, rpt)
bpy.context.scene.objects.link(cob)
cur.splines.new('BEZIER')
cspline = cur.splines[0]
- div = 1 # SPACING FOR HANDLES (2 - 1/2 WAY, 1 - NEXT BEZIER)
+ div = 1 # spacing for handles (2 - 1/2 way, 1 - next bezier)
+
for a in range(len(arr)):
cspline.bezier_points.add(1)
bp = cspline.bezier_points[len(cspline.bezier_points) - 1]
@@ -418,17 +444,18 @@ def addMaterial(ob, matname):
def writeStokeToMesh(arr, jarr, MAINi, HORDERi, TIPSi, orig, gs, rpt=None):
- # MAIN BRANCH
- print(' WRITING MAIN BRANCH')
+ # main branch
+ debug_prints(func="writeStokeToMesh", text='Writing main branch')
llmain = []
+
for x in MAINi:
llmain.append(jarr[x])
mob = writeArrayToMesh('la0MAIN', llmain, gs)
mob.location = orig
- # hORDER BRANCHES
+ # horder branches
for hOi in range(len(HORDERi)):
- print(' WRITING ORDER', hOi)
+ debug_prints(func="writeStokeToMesh", text="Writing order", var=hOi)
hO = HORDERi[hOi]
hob = newMesh('la1H' + str(hOi))
@@ -440,8 +467,8 @@ def writeStokeToMesh(arr, jarr, MAINi, HORDERi, TIPSi, orig, gs, rpt=None):
hob.scale = (gs, gs, gs)
hob.location = orig
- # TIPS
- print(' WRITING TIP PATHS')
+ # tips
+ debug_prints(func="writeStokeToMesh", text="Writing tip paths")
tob = newMesh('la2TIPS')
for y in TIPSi:
llt = []
@@ -451,16 +478,17 @@ def writeStokeToMesh(arr, jarr, MAINi, HORDERi, TIPSi, orig, gs, rpt=None):
tob.scale = (gs, gs, gs)
tob.location = orig
- # ADD MATERIALS TO OBJECTS (IF THEY EXIST)
+ # add materials to objects (if they exist)
try:
addMaterial(mob, 'edgeMAT-h0')
addMaterial(hob, 'edgeMAT-h1')
addMaterial(tob, 'edgeMAT-h2')
- print(' ADDED MATERIALS')
+ debug_prints(func="writeStokeToMesh", text="Added materials")
+
except:
- print(' MATERIALS NOT FOUND')
+ debug_prints(func="writeStokeToMesh", text="Materials not found")
- # ADD GENERATION REPORT TO ALL MESHES
+ # add generation report to all meshes
if rpt:
addReportProp(mob, rpt)
addReportProp(hob, rpt)
@@ -486,62 +514,66 @@ def writeStokeToSingleMesh(arr, jarr, orig, gs, mct, rpt=None):
def visualizeArray(cg, oob, gs, vm, vs, vc, vv, rst):
+ winmgr = bpy.context.scene.advanced_objects
# IN: (cellgrid, origin, gridscale,
# mulimesh, single mesh, cubes, voxels, report sting)
origin = oob.location
- # DEAL WITH VERT MULTI-ORIGINS
+ # deal with vert multi-origins
oct = 2
if oob.type == 'MESH':
oct = len(oob.data.vertices)
- # JITTER CELLS
+ # jitter cells
if vm or vs:
cjarr = jitterCells(cg, 1)
- if vm: # WRITE ARRAY TO MULTI MESH
+ if vm: # write array to multi mesh
aMi, aHi, aTi = classifyStroke(cg, oct, winmgr.HORDER)
- print(':::WRITING TO MULTI-MESH')
+ debug_prints(func="visualizeArray", text="Writing to multi-mesh")
writeStokeToMesh(cg, cjarr, aMi, aHi, aTi, origin, gs, rst)
- print(':::MULTI-MESH WRITTEN')
+ debug_prints(func="visualizeArray", text="Multi-mesh written")
- if vs: # WRITE TO SINGLE MESH
- print(':::WRITING TO SINGLE MESH')
+ if vs: # write to single mesh
+ debug_prints(func="visualizeArray", text="Writing to single mesh")
writeStokeToSingleMesh(cg, cjarr, origin, gs, oct, rst)
- print(':::SINGLE MESH WRITTEN')
+ debug_prints(func="visualizeArray", text="Single mesh written")
- if vc: # WRITE ARRAY TO CUBE OBJECTS
- print(':::WRITING TO CUBES')
+ if vc: # write array to cube objects
+ debug_prints(func="visualizeArray", text="Writing to cubes")
writeArrayToCubes(cg, gs, origin)
- print(':::CUBES WRITTEN')
+ debug_prints(func="visualizeArray", text="Cubes written")
- if vv: # WRITE ARRAY TO VOXEL DATA FILE
- print(':::WRITING TO VOXELS')
+ if vv: # write array to voxel data file
+ debug_prints(func="visualizeArray", text="Writing to voxels")
fname = "FSLGvoxels.raw"
path = os.path.dirname(bpy.data.filepath)
writeArrayToVoxel(cg, path + "\\" + fname)
- print(':::VOXEL DATA WRITTEN TO - ', path + "\\" + fname)
- # READ/WRITE ARRAY TO FILE (MIGHT NOT BE NECESSARY)
+ debug_prints(func="visualizeArray",
+ text="Voxel data written to:", var=path + "\\" + fname)
+
+ # read/write array to file (might not be necessary)
# tfile = 'c:\\testarr.txt'
# writeArrayToFile(cg, tfile)
# cg = readArrayFromFile(tfile)
- # READ/WRITE ARRAY TO CURVES (OUT OF ORDER)
+ # read/write array to curves (out of order)
# writeArrayToCurves('laMAIN', llmain, .10, .25)
-# ALGORITHM FXNS #
-# FROM FALUAM PAPER #
-# PLUS SOME STUFF I MADE UP #
+# Algorithm functions
+# from faluam paper
+# plus some stuff i made up
def buildCPGraph(arr, sti=2):
- # IN -XYZ ARRAY AS BUILT BY GENERATOR
- # OUT -[(CHILDindex, PARENTindex)]
- # sti - start index, 2 for Empty, len(me.vertices) for Mesh
+ # in -xyz array as built by generator
+ # out -[(childindex, parentindex)]
+ # sti - start index, 2 for empty, len(me.vertices) for mesh
sgarr = []
sgarr.append((1, 0))
+
for ai in range(sti, len(arr)):
cs = arr[ai]
cpts = arr[0:ai]
@@ -552,13 +584,14 @@ def buildCPGraph(arr, sti=2):
if ct > 0:
cti = cpts.index(nc)
sgarr.append((ai, cti))
+
return sgarr
def buildCPGraph_WORKINPROGRESS(arr, sti=2):
- # IN -XYZ ARRAY AS BUILT BY GENERATOR
- # OUT -[(CHILDindex, PARENTindex)]
- # sti - start index, 2 for Empty, len(me.vertices) for Mesh
+ # in -xyz array as built by generator
+ # out -[(childindex, parentindex)]
+ # sti - start index, 2 for empty, len(me.vertices) for mesh
sgarr = []
sgarr.append((1, 0))
ctix = 0
@@ -575,13 +608,14 @@ def buildCPGraph_WORKINPROGRESS(arr, sti=2):
ctix = cpts.index(nc)
sgarr.append((ai, cti))
+
return sgarr
def findChargePath(oc, fc, ngraph, restrict=[], partial=True):
- # oc -ORIGIN CHARGE INDEX, fc -FINAL CHARGE INDEX
- # ngraph -NODE GRAPH, restrict- INDEX OF SITES CANNOT TRAVERSE
- # partial -RETURN PARTIAL PATH IF RESTRICTION ENCOUNTERD
+ # oc -origin charge index, fc -final charge index
+ # ngraph -node graph, restrict- index of sites cannot traverse
+ # partial -return partial path if restriction encounterd
cList = splitList(ngraph, 0)
pList = splitList(ngraph, 1)
aRi = []
@@ -591,13 +625,13 @@ def findChargePath(oc, fc, ngraph, restrict=[], partial=True):
aRi.append(cNODE)
cNODE = pNODE
npNODECOUNT = cList.count(pNODE)
- if cNODE == oc: # STOP IF ORIGIN FOUND
- aRi.append(cNODE) # RETURN PATH
+ if cNODE == oc: # stop if origin found
+ aRi.append(cNODE) # return path
return aRi
- if npNODECOUNT == 0: # STOP IF NO PARENTS
- return [] # RETURN []
- if pNODE in restrict: # STOP IF PARENT IS IN RESTRICTION
- if partial: # RETURN PARTIAL OR []
+ if npNODECOUNT == 0: # stop if no parents
+ return [] # return []
+ if pNODE in restrict: # stop if parent is in restriction
+ if partial: # return partial or []
aRi.append(cNODE)
return aRi
else:
@@ -615,6 +649,7 @@ def findTips(arr):
cCOUNT += 1
if cCOUNT == 0:
lt.append(a)
+
return lt
@@ -626,6 +661,7 @@ def findChannelRoots(path, ngraph, restrict=[]):
if par in path and chi not in path and chi not in restrict:
roots.append(par)
droots = deDupe(roots)
+
return droots
@@ -648,10 +684,14 @@ def findChannels(roots, tips, ngraph, restrict):
tTEMP = t
tiTEMP = ti
if len(sPATHi) > 0:
- print(' found path/idex from', ri, 'of',
- len(roots), 'possible | tips:', tTEMP, tiTEMP)
+ debug_print_vars(
+ "\n[findChannels]\n",
+ "found path/idex from", ri, 'of',
+ len(roots), "possible | tips:", tTEMP, tiTEMP
+ )
cPATHS.append(sPATHi)
tips.remove(tTEMP)
+
return cPATHS
@@ -662,13 +702,12 @@ def findChannels_WORKINPROGRESS(roots, ttips, ngraph, restrict):
r = roots[ri]
sL = 1
sPATHi = []
- tipREMOVE = [] # CHECKED TIP INDEXES, TO BE REMOVED FOR NEXT LOOP
+ tipREMOVE = [] # checked tip indexes, to be removed for next loop
for ti in range(len(tips)):
t = tips[ti]
- # print('-CHECKING RT/IDEX:', r, ri, 'AGAINST TIP', t, ti)
- # if t < r: continue
if ti < ri:
continue
+
tPATHi = findChargePath(r, t, ngraph, restrict, False)
tL = len(tPATHi)
if tL > sL:
@@ -680,9 +719,13 @@ def findChannels_WORKINPROGRESS(roots, ttips, ngraph, restrict):
if tL > 0:
tipREMOVE.append(t)
if len(sPATHi) > 0:
- print(' found path from root idex', ri, 'of',
- len(roots), 'possible roots | #oftips=', len(tips))
+ debug_print_vars(
+ "\n[findChannels_WORKINPROGRESS]\n",
+ "found path from root idex", ri, 'of',
+ len(roots), "possible roots | of tips= ", len(tips)
+ )
cPATHS.append(sPATHi)
+
for q in tipREMOVE:
tips.remove(q)
@@ -690,65 +733,72 @@ def findChannels_WORKINPROGRESS(roots, ttips, ngraph, restrict):
def countChildrenOnPath(aPath, ngraph, quick=True):
- # RETURN HOW MANY BRANCHES
- # COUNT WHEN NODE IS A PARENT >1 TIMES
- # quick -STOP AND RETURN AFTER FIRST
+ # return how many branches
+ # count when node is a parent >1 times
+ # quick -stop and return after first
cCOUNT = 0
pList = splitList(ngraph, 1)
+
for ai in range(len(aPath) - 1):
ap = aPath[ai]
pc = pList.count(ap)
+
if quick and pc > 1:
return pc
+
return cCOUNT
-# CLASSIFY CHANNELS INTO 'MAIN', 'hORDER/SECONDARY' and 'SIDE'
+# classify channels into 'main', 'hORDER/secondary' and 'side'
def classifyStroke(sarr, mct, hORDER=1):
- print(':::CLASSIFYING STROKE')
- # BUILD CHILD/PARENT GRAPH (INDEXES OF sarr)
+ debug_prints(func="classifyStroke", text="Classifying stroke")
+ # build child/parent graph (indexes of sarr)
sgarr = buildCPGraph(sarr, mct)
- # FIND MAIN CHANNEL
- print(' finding MAIN')
+ # find main channel
+ debug_prints(func="classifyStroke", text="Finding MAIN")
oCharge = sgarr[0][1]
fCharge = sgarr[len(sgarr) - 1][0]
aMAINi = findChargePath(oCharge, fCharge, sgarr)
- # FIND TIPS
- print(' finding TIPS')
+ # find tips
+ debug_prints(func="classifyStroke", text="Finding TIPS")
aTIPSi = findTips(sgarr)
- # FIND hORDER CHANNEL ROOTS
- # hCOUNT = ORDERS BEWTEEN MAIN and SIDE/TIPS
- # !!!STILL BUGGY!!!
- hRESTRICT = list(aMAINi) # ADD TO THIS AFTER EACH TIME
- allHPATHSi = [] # ALL hO PATHS: [[h0], [h1]...]
- curPATHSi = [aMAINi] # LIST OF PATHS FIND ROOTS ON
+ # find horder channel roots
+ # hcount = orders bewteen main and side/tips
+ # !!!still buggy!!!
+ hRESTRICT = list(aMAINi) # add to this after each time
+ allHPATHSi = [] # all ho paths: [[h0], [h1]...]
+ curPATHSi = [aMAINi] # list of paths find roots on
+
for h in range(hORDER):
allHPATHSi.append([])
- for pi in range(len(curPATHSi)): # LOOP THROUGH ALL PATHS IN THIS ORDER
+ for pi in range(len(curPATHSi)): # loop through all paths in this order
p = curPATHSi[pi]
- # GET ROOTS FOR THIS PATH
+ # get roots for this path
aHROOTSi = findChannelRoots(p, sgarr, hRESTRICT)
- print(' found', len(aHROOTSi), 'roots in ORDER', h, ':#paths:', len(curPATHSi))
- # GET CHANNELS FOR THESE ROOTS
+ debug_print_vars(
+ "\n[classifyStroke]\n",
+ "found", len(aHROOTSi), "roots in ORDER", h, ":paths:", len(curPATHSi)
+ )
+ # get channels for these roots
if len(aHROOTSi) == 0:
- print('NO ROOTS FOR FOUND FOR CHANNEL')
+ debug_prints(func="classifyStroke", text="No roots for found for channel")
aHPATHSi = []
continue
else:
aHPATHSiD = findChannels(aHROOTSi, aTIPSi, sgarr, hRESTRICT)
aHPATHSi = aHPATHSiD
allHPATHSi[h] += aHPATHSi
- # SET THESE CHANNELS AS RESTRICTIONS FOR NEXT ITERATIONS
+ # set these channels as restrictions for next iterations
for hri in aHPATHSi:
hRESTRICT += hri
curPATHSi = aHPATHSi
- # SIDE BRANCHES, FINAL ORDER OF HEIRARCHY
- # FROM TIPS THAT ARE NOT IN AN EXISTING PATH
- # BACK TO ANY OTHER POINT THAT IS ALREADY ON A PATH
+ # side branches, final order of heirarchy
+ # from tips that are not in an existing path
+ # back to any other point that is already on a path
aDRAWNi = []
aDRAWNi += aMAINi
for oH in allHPATHSi:
@@ -765,24 +815,25 @@ def classifyStroke(sarr, mct, hORDER=1):
def voxelByVertex(ob, gs):
- # 'VOXELIZES' VERTS IN A MESH TO LIST [(x,y,z),(x,y,z)]
- # W/ RESPECT GSCALE AND OB ORIGIN (B/C SHOULD BE ORIGIN OBJ)
- orig = ob.location
+ # 'voxelizes' verts in a mesh to list [(x,y,z),(x,y,z)]
+ # w/ respect gscale and ob origin (b/c should be origin obj)
+ # orig = ob.location
ll = []
for v in ob.data.vertices:
x = int(v.co.x / gs)
y = int(v.co.y / gs)
z = int(v.co.z / gs)
ll.append((x, y, z))
+
return ll
def voxelByRays(ob, orig, gs):
- # MESH INTO A 3DGRID W/ RESPECT GSCALE AND BOLT ORIGIN
- # -DOES NOT TAKE OBJECT ROTATION/SCALE INTO ACCOUNT
- # -THIS IS A HORRIBLE, INEFFICIENT FUNCTION
- # MAYBE THE RAYCAST/GRID THING ARE A BAD IDEA. BUT I
- # HAVE TO 'VOXELIZE THE OBJECT W/ RESCT TO GSCALE/ORIGIN
+ # mesh into a 3dgrid w/ respect gscale and bolt origin
+ # - does not take object rotation/scale into account
+ # - this is a horrible, inefficient function
+ # maybe the raycast/grid thing are a bad idea. but i
+ # have to 'voxelize the object w/ resct to gscale/origin
bbox = ob.bound_box
bbxL = bbox[0][0]
bbxR = bbox[4][0]
@@ -796,11 +847,17 @@ def voxelByRays(ob, orig, gs):
xs = int(xct / 2)
ys = int(yct / 2)
zs = int(zct / 2)
- print(' CASTING', xct, '/', yct, '/', zct, 'cells, total:', xct * yct * zct, 'in obj-', ob.name)
+
+ debug_print_vars(
+ "\n[voxelByRays]\n",
+ "Casting", xct, '/', yct, '/', zct, 'cells, total:',
+ xct * yct * zct, 'in obj-', ob.name
+ )
ll = []
- rc = 100 # DISTANCE TO CAST FROM
- # RAYCAST TOP/BOTTOM
- print(' RAYCASTING TOP/BOTTOM')
+ rc = 100 # distance to cast from
+ # raycast top/bottom
+ debug_prints(func="voxelByRays", text="Raycasting top/bottom")
+
for x in range(xct):
for y in range(yct):
xco = bbxL + (x * gs)
@@ -809,12 +866,20 @@ def voxelByRays(ob, orig, gs):
v2 = ((xco, yco, -rc))
vz1 = ob.ray_cast(v1, v2)
vz2 = ob.ray_cast(v2, v1)
- if vz1[2] != -1:
- ll.append((x - xs, y - ys, int(vz1[0][2] * (1 / gs))))
- if vz2[2] != -1:
- ll.append((x - xs, y - ys, int(vz2[0][2] * (1 / gs))))
- # RAYCAST FRONT/BACK
- print(' RAYCASTING FRONT/BACK')
+
+ debug_print_vars(
+ "\n[voxelByRays]\n", "vz1 is: ", vz1, "\nvz2 is: ", vz2
+ )
+ # Note: the API raycast return has changed now it is
+ # (result, location, normal, index) - result is a boolean
+ if vz1[0] is True:
+ ll.append((x - xs, y - ys, int(vz1[1][2] * (1 / gs))))
+ if vz2[0] is True:
+ ll.append((x - xs, y - ys, int(vz2[1][2] * (1 / gs))))
+
+ # raycast front/back
+ debug_prints(func="voxelByRays", text="Raycasting front/back")
+
for x in range(xct):
for z in range(zct):
xco = bbxL + (x * gs)
@@ -823,12 +888,14 @@ def voxelByRays(ob, orig, gs):
v2 = ((xco, -rc, zco))
vy1 = ob.ray_cast(v1, v2)
vy2 = ob.ray_cast(v2, v1)
- if vy1[2] != -1:
- ll.append((x - xs, int(vy1[0][1] * (1 / gs)), z - zs))
- if vy2[2] != -1:
- ll.append((x - xs, int(vy2[0][1] * (1 / gs)), z - zs))
- # RAYCAST LEFT/RIGHT
- print(' RAYCASTING LEFT/RIGHT')
+ if vy1[0] is True:
+ ll.append((x - xs, int(vy1[1][1] * (1 / gs)), z - zs))
+ if vy2[0] is True:
+ ll.append((x - xs, int(vy2[1][1] * (1 / gs)), z - zs))
+
+ # raycast left/right
+ debug_prints(func="voxelByRays", text="Raycasting left/right")
+
for y in range(yct):
for z in range(zct):
yco = bbyL + (y * gs)
@@ -837,24 +904,24 @@ def voxelByRays(ob, orig, gs):
v2 = ((-rc, yco, zco))
vx1 = ob.ray_cast(v1, v2)
vx2 = ob.ray_cast(v2, v1)
- if vx1[2] != -1:
- ll.append((int(vx1[0][0] * (1 / gs)), y - ys, z - zs))
- if vx2[2] != -1:
- ll.append((int(vx2[0][0] * (1 / gs)), y - ys, z - zs))
+ if vx1[0] is True:
+ ll.append((int(vx1[1][0] * (1 / gs)), y - ys, z - zs))
+ if vx2[0] is True:
+ ll.append((int(vx2[1][0] * (1 / gs)), y - ys, z - zs))
- # ADD IN NEIGHBORS SO BOLT WONT GO THRU
+ # add in neighbors so bolt wont go through
nlist = []
for l in ll:
nl = getStencil3D_26(l[0], l[1], l[2])
nlist += nl
- # DEDUPE
- print(' ADDED NEIGHBORS, DEDUPING...')
+ # dedupe
+ debug_prints(func="voxelByRays", text="Added neighbors, deduping...")
rlist = deDupe(ll + nlist)
qlist = []
- # RELOCATE GRID W/ RESPECT GSCALE AND BOLT ORIGIN
- # !!!NEED TO ADD IN OBJ ROT/SCALE HERE SOMEHOW...
+ # relocate grid w/ respect gscale and bolt origin
+ # !!!need to add in obj rot/scale here somehow...
od = Vector(
((ob.location[0] - orig[0]) / gs,
(ob.location[1] - orig[1]) / gs,
@@ -874,24 +941,25 @@ def fakeGroundChargePlane(z, charge):
eCL += [(0, xy, z, charge)]
eCL += [(-xy, 0, z, charge)]
eCL += [(0, -xy, z, charge)]
+
return eCL
def addCharges(ll, charge):
- # IN: ll - [(x,y,z), (x,y,z)], charge - w
- # OUT clist - [(x,y,z,w), (x,y,z,w)]
+ # in: ll - [(x,y,z), (x,y,z)], charge - w
+ # out clist - [(x,y,z,w), (x,y,z,w)]
clist = []
for l in ll:
clist.append((l[0], l[1], l[2], charge))
return clist
-# ALGORITHM FXNS #
-# FROM FSLG #
+# algorithm functions #
+# from fslg #
def getGrowthProbability_KEEPFORREFERENCE(uN, aList):
- # IN: uN -USER TERM, cList -CANDIDATE SITES, oList -CANDIDATE SITE CHARGES
- # OUT: LIST OF [(XYZ), POT, PROB]
+ # in: un -user term, clist -candidate sites, olist -candidate site charges
+ # out: list of [(xyz), pot, prob]
cList = splitList(aList, 0)
oList = splitList(aList, 1)
Omin, Omax = getLowHigh(oList)
@@ -900,20 +968,21 @@ def getGrowthProbability_KEEPFORREFERENCE(uN, aList):
Omin -= notZero
PdL = []
E = 0
- E = notZero # DIVISOR FOR (FSLG - Eqn. 12)
+ E = notZero # divisor for (fslg - eqn. 12)
for o in oList:
- Uj = (o - Omin) / (Omax - Omin) # (FSLG - Eqn. 13)
+ Uj = (o - Omin) / (Omax - Omin) # (fslg - eqn. 13)
E += pow(Uj, uN)
for oi in range(len(oList)):
o = oList[oi]
Ui = (o - Omin) / (Omax - Omin)
- Pd = (pow(Ui, uN)) / E # (FSLG - Eqn. 12)
+ Pd = (pow(Ui, uN)) / E # (fslg - eqn. 12)
PdINT = Pd * 100
PdL.append(Pd)
+
return PdL
-# WORK IN PROGRESS, TRYING TO SPEED THESE UP
+# work in progress, trying to speed these up
def fslg_e13(x, min, max, u):
return pow((x - min) / (max - min), u)
@@ -927,14 +996,16 @@ def fslg_e12(x, min, max, u, e):
def getGrowthProbability(uN, aList):
- # IN: uN -USER TERM, cList -CANDIDATE SITES, oList -CANDIDATE SITE CHARGES
- # OUT: LIST OF PROB
+ # In: uN - user_term, cList - candidate sites, oList - candidate site charges
+ # Out: list of prob
cList = splitList(aList, 0)
oList = splitList(aList, 1)
Omin, Omax = getLowHigh(oList)
+
if Omin == Omax:
Omax += notZero
Omin -= notZero
+
PdL = []
E = notZero
minL = [Omin for q in range(len(oList))]
@@ -943,15 +1014,17 @@ def getGrowthProbability(uN, aList):
E = sum(map(fslg_e13, oList, minL, maxL, uNL))
EL = [E for q in range(len(oList))]
mp = map(fslg_e12, oList, minL, maxL, uNL, EL)
+
for m in mp:
PdL.append(m)
+
return PdL
def updatePointCharges(p, cList, eList=[]):
- # IN: pNew -NEW GROWTH CELL
- # cList -OLD CANDIDATE SITES, eList -SAME
- # OUT: LIST OF NEW CHARGE AT CANDIDATE SITES
+ # In: pNew - new growth cell
+ # cList - old candidate sites, eList -SAME
+ # Out: list of new charge at candidate sites
r1 = 1 / 2 # (FSLG - Eqn. 10)
nOiL = []
for oi in range(len(cList)):
@@ -962,12 +1035,13 @@ def updatePointCharges(p, cList, eList=[]):
iOe += (1 - (r1 / rit))
Oit = o + iOe
nOiL.append((c, Oit))
+
return nOiL
def initialPointCharges(pList, cList, eList=[]):
- # IN: p -CHARGED CELL (XYZ), cList -CANDIDATE SITES (XYZ, POT, PROB)
- # OUT: cList -WITH POTENTIAL CALCULATED
+ # In: p -CHARGED CELL (XYZ), cList -candidate sites (XYZ, POT, PROB)
+ # Out: cList -with potential calculated
r1 = 1 / 2 # (FSLG - Eqn. 10)
npList = []
for p in pList:
@@ -980,15 +1054,15 @@ def initialPointCharges(pList, cList, eList=[]):
for j in npList:
if i != j[0]:
rij = dist(i[0], i[1], i[2], j[0][0], j[0][1], j[0][2])
- Oi += (1 - (r1 / rij)) * j[1] # CHARGE INFLUENCE
+ Oi += (1 - (r1 / rij)) * j[1] # charge influence
OiL.append(((i[0], i[1], i[2]), Oi))
+
return OiL
def getCandidateSites(aList, iList=[]):
- # IN: aList -(X,Y,Z) OF CHARGED CELL SITES, iList -insulator sites
- # OUT: CANDIDATE LIST OF GROWTH SITES [(X,Y,Z)]
- tt1 = time.clock()
+ # In: aList -(X,Y,Z) of charged cell sites, iList - insulator sites
+ # Out: candidate list of growth sites [(X,Y,Z)]
cList = []
for c in aList:
tempList = getStencil3D_26(c[0], c[1], c[2])
@@ -996,14 +1070,14 @@ def getCandidateSites(aList, iList=[]):
if t not in aList and t not in iList:
cList.append(t)
ncList = deDupe(cList)
- tt2 = time.clock()
return ncList
-# SETUP FXNS #
+# Setup functions
def setupObjects():
+ winmgr = bpy.context.scene.advanced_objects
oOB = bpy.data.objects.new('ELorigin', None)
oOB.location = ((0, 0, 10))
bpy.context.scene.objects.link(oOB)
@@ -1041,27 +1115,38 @@ def setupObjects():
def checkSettings():
check = True
+ winmgr = bpy.context.scene.advanced_objects
+ message = ""
if winmgr.OOB == "":
- print('ERROR: NO ORIGIN OBJECT SELECTED')
+ message = "Error: no origin object selected"
check = False
+
if winmgr.GROUNDBOOL and winmgr.GOB == "":
- print('ERROR: NO GROUND OBJECT SELECTED')
+ message = "Error: no ground object selected"
check = False
+
if winmgr.CLOUDBOOL and winmgr.COB == "":
- print('ERROR: NO CLOUD OBJECT SELECTED')
+ message = "Error: no cloud object selected"
check = False
+
if winmgr.IBOOL and winmgr.IOB == "":
- print('ERROR: NO INSULATOR OBJECT SELECTED')
+ message = "Error: no insulator object selected"
check = False
- # should make a popup here
- return check
+ if check is False:
+ debug_prints(func="checkSettings", text=message)
-# MAIN #
+ # return state and the message for the operator report
+ return check, message
+
+
+# Main
def FSLG():
- # FAST SIMULATION OF LAPLACIAN GROWTH #
- print('\n<<<<<<------GO GO GADGET: FAST SIMULATION OF LAPLACIAN GROWTH!')
+ winmgr = bpy.context.scene.advanced_objects
+ # fast simulation of laplacian growth
+ debug_prints(func="FSLG",
+ text="Go go gadget: fast simulation of laplacian growth")
tc1 = time.clock()
TSTEPS = winmgr.TSTEPS
@@ -1070,214 +1155,183 @@ def FSLG():
winmgr.ORIGIN = obORIGIN.location
winmgr.GROUNDZ = int((obGROUND.location[2] - winmgr.ORIGIN[2]) / winmgr.GSCALE)
- # 1) INSERT INTIAL CHARGE(S) POINT (USES VERTS IF MESH)
+ # 1) insert intial charge(s) point (uses verts if mesh)
cgrid = [(0, 0, 0)]
+
if obORIGIN.type == 'MESH':
- print("<<<<<<------ORIGIN OBJECT IS MESH, 'VOXELIZING' INTIAL CHARGES FROM VERTS")
+ debug_prints(
+ func="FSLG",
+ text="Origin object is mesh, 'voxelizing' intial charges from verts"
+ )
cgrid = voxelByVertex(obORIGIN, winmgr.GSCALE)
+
if winmgr.VMMESH:
- print("<<<<<<------CANNOT CLASSIFY STROKE FROM VERT ORIGINS YET, NO MULTI-MESH OUTPUT")
+ debug_prints(
+ func="FSLG",
+ text="Cannot classify stroke from vert origins yet, no multi-mesh output"
+ )
winmgr.VMMESH = False
winmgr.VSMESH = True
- # GROUND CHARGE CELL / INSULATOR LISTS (eChargeList/icList)
+ # ground charge cell / insulator lists (echargelist/iclist)
eChargeList = []
icList = []
if winmgr.GROUNDBOOL:
eChargeList = fakeGroundChargePlane(winmgr.GROUNDZ, winmgr.GROUNDC)
+
if winmgr.CLOUDBOOL:
- print("<<<<<<------'VOXELIZING' CLOUD OBJECT (COULD TAKE SOME TIME)")
+ debug_prints(
+ func="FSLG",
+ text="'Voxelizing' cloud object (could take some time)"
+ )
obCLOUD = bpy.context.scene.objects[winmgr.COB]
eChargeListQ = voxelByRays(obCLOUD, winmgr.ORIGIN, winmgr.GSCALE)
eChargeList = addCharges(eChargeListQ, winmgr.CLOUDC)
- print('<<<<<<------CLOUD OBJECT CELL COUNT = ', len(eChargeList))
+ debug_prints(
+ func="FSLG",
+ text="cloud object cell count", var=len(eChargeList)
+ )
+
if winmgr.IBOOL:
- print("<<<<<<------'VOXELIZING' INSULATOR OBJECT (COULD TAKE SOME TIME)")
+ debug_prints(
+ func="FSLG",
+ text="'Voxelizing' insulator object (could take some time)"
+ )
obINSULATOR = bpy.context.scene.objects[winmgr.IOB]
icList = voxelByRays(obINSULATOR, winmgr.ORIGIN, winmgr.GSCALE)
- print('<<<<<<------INSULATOR OBJECT CELL COUNT = ', len(icList))
- # 2) LOCATE CANDIDATE SITES AROUND CHARGE
+ debug_prints(
+ func="FSLG",
+ text="Insulator object cell count", var=len(icList)
+ )
+
+ # 2) locate candidate sites around charge
cSites = getCandidateSites(cgrid, icList)
- # 3) CALC POTENTIAL AT EACH SITE (Eqn. 10)
+ # 3) calc potential at each site (eqn. 10)
cSites = initialPointCharges(cgrid, cSites, eChargeList)
ts = 1
while ts <= TSTEPS:
- # 1) SELECT NEW GROWTH SITE (Eqn. 12)
- # GET PROBABILITIES AT CANDIDATE SITES
+ # 1) select new growth site (eqn. 12)
+ # get probabilities at candidate sites
gProbs = getGrowthProbability(winmgr.BIGVAR, cSites)
- # CHOOSE NEW GROWTH SITE BASED ON PROBABILITIES
+ # choose new growth site based on probabilities
gSitei = weightedRandomChoice(gProbs)
gsite = cSites[gSitei][0]
- # 2) ADD NEW POINT CHARGE AT GROWTH SITE
- # ADD NEW GROWTH CELL TO GRID
+ # 2) add new point charge at growth site
+ # add new growth cell to grid
cgrid.append(gsite)
- # REMOVE NEW GROWTH CELL FROM CANDIDATE SITES
+ # remove new growth cell from candidate sites
cSites.remove(cSites[gSitei])
- # 3) UPDATE POTENTIAL AT CANDIDATE SITES (Eqn. 11)
+ # 3) update potential at candidate sites (eqn. 11)
cSites = updatePointCharges(gsite, cSites, eChargeList)
- # 4) ADD NEW CANDIDATES SURROUNDING GROWTH SITE
- # GET CANDIDATE 'STENCIL'
+ # 4) add new candidates surrounding growth site
+ # get candidate 'stencil'
ncSitesT = getCandidateSites([gsite], icList)
- # REMOVE CANDIDATES ALREADY IN CANDIDATE LIST OR CHARGE GRID
+ # remove candidates already in candidate list or charge grid
ncSites = []
cSplit = splitList(cSites, 0)
for cn in ncSitesT:
if cn not in cSplit and cn not in cgrid:
ncSites.append((cn, 0))
- # 5) CALC POTENTIAL AT NEW CANDIDATE SITES (Eqn. 10)
+ # 5) calc potential at new candidate sites (eqn. 10)
ncSplit = splitList(ncSites, 0)
ncSites = initialPointCharges(cgrid, ncSplit, eChargeList)
- # ADD NEW CANDIDATE SITES TO CANDIDATE LIST
+ # add new candidate sites to candidate list
for ncs in ncSites:
cSites.append(ncs)
- # ITERATION COMPLETE
+ # iteration complete
istr1 = ':::T-STEP: ' + str(ts) + '/' + str(TSTEPS)
istr12 = ' | GROUNDZ: ' + str(winmgr.GROUNDZ) + ' | '
istr2 = 'CANDS: ' + str(len(cSites)) + ' | '
istr3 = 'GSITE: ' + str(gsite)
- print(istr1 + istr12 + istr2 + istr3)
+ debug_prints(
+ func="FSLG",
+ text="Iteration complete",
+ var=istr1 + istr12 + istr2 + istr3
+ )
ts += 1
- # EARLY TERMINATION FOR GROUND/CLOUD STRIKE
+ # early termination for ground/cloud strike
if winmgr.GROUNDBOOL:
if gsite[2] == winmgr.GROUNDZ:
ts = TSTEPS + 1
- print('<<<<<<------EARLY TERMINATION DUE TO GROUNDSTRIKE')
+ debug_prints(
+ func="FSLG",
+ text="Early termination due to groundstrike"
+ )
continue
+
if winmgr.CLOUDBOOL:
if gsite in splitListCo(eChargeList):
ts = TSTEPS + 1
- print('<<<<<<------EARLY TERMINATION DUE TO CLOUDSTRIKE')
+ debug_prints(
+ func="FSLG",
+ text="Early termination due to cloudstrike"
+ )
continue
tc2 = time.clock()
tcRUN = tc2 - tc1
- print('<<<<<<------LAPLACIAN GROWTH LOOP COMPLETED: ' + str(len(cgrid)) + ' / ' + str(tcRUN)[0:5] + ' SECONDS')
- print('<<<<<<------VISUALIZING DATA')
+ debug_prints(
+ func="FSLG",
+ text="Laplacian growth loop completed",
+ var=str(len(cgrid)) + " / " + str(tcRUN)[0:5] + " Seconds"
+ )
+ debug_prints(func="FSLG", text="Visualizing data")
reportSTRING = getReportString(tcRUN)
- # VISUALIZE ARRAY
- visualizeArray(
- cgrid, obORIGIN, winmgr.GSCALE,
- winmgr.VMMESH, winmgr.VSMESH,
- winmgr.VCUBE, winmgr.VVOX, reportSTRING
- )
- print('<<<<<<------COMPLETE')
-
-# GUI #
+ # Visualize array
+ visualizeArray(
+ cgrid, obORIGIN, winmgr.GSCALE,
+ winmgr.VMMESH, winmgr.VSMESH,
+ winmgr.VCUBE, winmgr.VVOX, reportSTRING
+ )
-# NOT IN UI
-bpy.types.WindowManager.ORIGIN = bpy.props.FloatVectorProperty(name="origin charge")
-bpy.types.WindowManager.GROUNDZ = bpy.props.IntProperty(name="ground Z coordinate")
-bpy.types.WindowManager.HORDER = bpy.props.IntProperty(name="secondary paths orders")
-# IN UI
-bpy.types.WindowManager.TSTEPS = bpy.props.IntProperty(
- name="iterations",
- description="number of cells to create, will end early if hits ground plane or cloud")
-bpy.types.WindowManager.GSCALE = bpy.props.FloatProperty(
- name="grid unit size",
- description="scale of cells, .25 = 4 cells per blenderUnit")
-bpy.types.WindowManager.BIGVAR = bpy.props.FloatProperty(
- name="straightness",
- description="straightness/branchiness of bolt, <2 is mush, >12 is staight line, 6.3 is good")
-bpy.types.WindowManager.GROUNDBOOL = bpy.props.BoolProperty(
- name="use ground object", description="use ground plane or not")
-bpy.types.WindowManager.GROUNDC = bpy.props.IntProperty(
- name="ground charge", description="charge of ground plane")
-bpy.types.WindowManager.CLOUDBOOL = bpy.props.BoolProperty(
- name="use cloud object",
- description="use cloud obj, attracts and terminates like ground but "
- "any obj instead of z plane, can slow down loop if obj is large, overrides ground")
-bpy.types.WindowManager.CLOUDC = bpy.props.IntProperty(
- name="cloud charge",
- description="charge of a cell in cloud object (so total charge also depends on obj size)")
-
-bpy.types.WindowManager.VMMESH = bpy.props.BoolProperty(
- name="multi mesh",
- description="output to multi-meshes for different materials on main/sec/side branches")
-bpy.types.WindowManager.VSMESH = bpy.props.BoolProperty(
- name="single mesh",
- description="output to single mesh for using build modifier and particles for effects")
-bpy.types.WindowManager.VCUBE = bpy.props.BoolProperty(
- name="cubes", description="CTRL-J after run to JOIN, outputs a bunch of cube objest, mostly for testing")
-bpy.types.WindowManager.VVOX = bpy.props.BoolProperty(
- name="voxel (experimental)",
- description="output to a voxel file to bpy.data.filepath\FSLGvoxels.raw - doesn't work well right now")
-bpy.types.WindowManager.IBOOL = bpy.props.BoolProperty(
- name="use insulator object", description="use insulator mesh object to prevent growth of bolt in areas")
-bpy.types.WindowManager.OOB = bpy.props.StringProperty(
- description="origin of bolt, can be an Empty, if obj is mesh will use all verts as charges")
-bpy.types.WindowManager.GOB = bpy.props.StringProperty(
- description="object to use as ground plane, uses z coord only")
-bpy.types.WindowManager.COB = bpy.props.StringProperty(
- description="object to use as cloud, best to use a cube")
-bpy.types.WindowManager.IOB = bpy.props.StringProperty(
- description="object to use as insulator, 'voxelized' before generating bolt, can be slow")
-
-# DEFAULT USER SETTINGS
-winmgr.TSTEPS = 350
-winmgr.HORDER = 1
-winmgr.GSCALE = 0.12
-winmgr.BIGVAR = 6.3
-winmgr.GROUNDBOOL = True
-winmgr.GROUNDC = -250
-winmgr.CLOUDBOOL = False
-winmgr.CLOUDC = -1
-winmgr.VMMESH = True
-winmgr.VSMESH = False
-winmgr.VCUBE = False
-winmgr.VVOX = False
-winmgr.IBOOL = False
-try:
- winmgr.OOB = "ELorigin"
- winmgr.GOB = "ELground"
- winmgr.COB = "ELcloud"
- winmgr.IOB = "ELinsulator"
-except:
- pass
+ debug_prints(func="FSLG", text="COMPLETE")
-# TESTING USER SETTINGS
-if False:
- winmgr.TSTEPS = 40
- winmgr.GROUNDBOOL = True
- winmgr.CLOUDBOOL = True
- winmgr.IBOOL = True
+# GUI #
-class runFSLGLoopOperator(bpy.types.Operator):
- '''By The Mighty Hammer Of Thor!!!'''
+class runFSLGLoopOperator(Operator):
bl_idname = "object.runfslg_operator"
bl_label = "run FSLG Loop Operator"
+ bl_description = "By The Mighty Hammer Of Thor!!!"
def execute(self, context):
- if checkSettings():
+ # tuple - state, report text
+ is_conditions, message = checkSettings()
+
+ if is_conditions:
FSLG()
else:
- pass
+ self.report({'WARNING'}, message + " Operation Cancelled")
+
+ return {'CANCELLED'}
+
return {'FINISHED'}
-class setupObjectsOperator(bpy.types.Operator):
- '''create origin/ground/cloud/insulator objects'''
+class setupObjectsOperator(Operator):
bl_idname = "object.setup_objects_operator"
bl_label = "Setup Objects Operator"
+ bl_description = "Create origin/ground/cloud/insulator objects"
def execute(self, context):
setupObjects()
+
return {'FINISHED'}
-class OBJECT_PT_fslg(bpy.types.Panel):
+class OBJECT_PT_fslg(Panel):
bl_label = "Laplacian Lightning"
bl_space_type = "VIEW_3D"
bl_region_type = "TOOLS"
@@ -1287,30 +1341,50 @@ class OBJECT_PT_fslg(bpy.types.Panel):
def draw(self, context):
layout = self.layout
- colR = layout.column()
- colR.label('-for progress open console-')
- colR.label('Help > Toggle System Console')
- colR.prop(winmgr, 'TSTEPS')
- colR.prop(winmgr, 'GSCALE')
- colR.prop(winmgr, 'BIGVAR')
- colR.operator('object.setup_objects_operator', text='create setup objects')
- colR.label('origin object')
- colR.prop_search(winmgr, "OOB", context.scene, "objects")
- colR.prop(winmgr, 'GROUNDBOOL')
- colR.prop_search(winmgr, "GOB", context.scene, "objects")
- colR.prop(winmgr, 'GROUNDC')
- colR.prop(winmgr, 'CLOUDBOOL')
- colR.prop_search(winmgr, "COB", context.scene, "objects")
- colR.prop(winmgr, 'CLOUDC')
- colR.prop(winmgr, 'IBOOL')
- colR.prop_search(winmgr, "IOB", context.scene, "objects")
- colR.operator('object.runfslg_operator', text='generate lightning')
- colR.prop(winmgr, 'VMMESH')
- colR.prop(winmgr, 'VSMESH')
- colR.prop(winmgr, 'VCUBE')
+ winmgr = context.scene.advanced_objects
+
+ col = layout.column(align=True)
+ col.prop(winmgr, "TSTEPS")
+ col.prop(winmgr, "GSCALE")
+ col.prop(winmgr, "BIGVAR")
+
+ col = layout.column()
+ col.operator("object.setup_objects_operator", text="Create Setup objects")
+ col.label("Origin object")
+ col.prop_search(winmgr, "OOB", context.scene, "objects")
+
+ box = layout.box()
+ col = box.column()
+ col.prop(winmgr, "GROUNDBOOL")
+ if winmgr.GROUNDBOOL:
+ col.prop_search(winmgr, "GOB", context.scene, "objects")
+ col.prop(winmgr, "GROUNDC")
+
+ box = layout.box()
+ col = box.column()
+ col.prop(winmgr, "CLOUDBOOL")
+ if winmgr.CLOUDBOOL:
+ col.prop_search(winmgr, "COB", context.scene, "objects")
+ col.prop(winmgr, "CLOUDC")
+
+ box = layout.box()
+ col = box.column()
+ col.prop(winmgr, "IBOOL")
+ if winmgr.IBOOL:
+ col.prop_search(winmgr, "IOB", context.scene, "objects")
+
+ col = layout.column()
+ col.operator("object.runfslg_operator",
+ text="Generate Lightning", icon="RNDCURVE")
+
+ row = layout.row(align=True)
+ row.prop(winmgr, "VMMESH", toggle=True)
+ row.prop(winmgr, "VSMESH", toggle=True)
+ row.prop(winmgr, "VCUBE", toggle=True)
def getReportString(rtime):
+ winmgr = bpy.context.scene.advanced_objects
rSTRING1 = 't:' + str(winmgr.TSTEPS) + ',sc:' + str(winmgr.GSCALE)[0:4] + ',uv:' + str(winmgr.BIGVAR)[0:4] + ','
rSTRING2 = 'ori:' + str(winmgr. ORIGIN[0]) + '/' + str(winmgr. ORIGIN[1]) + '/' + str(winmgr. ORIGIN[2]) + ','
rSTRING3 = 'gz:' + str(winmgr.GROUNDZ) + ',gc:' + str(winmgr.GROUNDC) + ',rtime:' + str(int(rtime))
@@ -1336,20 +1410,16 @@ def unregister():
if __name__ == "__main__":
- # RUN FOR TESTING
- # FSLG()
-
- # UI
register()
pass
-# FXN BENCHMARKS #
+# Benchmarks Function
def BENCH():
- print('\n\n\n--->BEGIN BENCHMARK')
+ debug_prints(func="BENCH", text="BEGIN BENCHMARK")
bt0 = time.clock()
- # MAKE A BIG LIST
+ # make a big list
tsize = 25
tlist = []
for x in range(tsize):
@@ -1358,13 +1428,15 @@ def BENCH():
tlist.append((x, y, z))
tlist.append((x, y, z))
- # FUNCTION TO TEST
+ # function to test
bt1 = time.clock()
- # print('LENS - ', len(tlist), len(ll))
-
bt2 = time.clock()
btRUNb = bt2 - bt1
btRUNa = bt1 - bt0
- print('--->SETUP TIME : ', btRUNa)
- print('--->BENCHMARK TIME: ', btRUNb)
- print('--->GRIDSIZE: ', tsize, ' - ', tsize * tsize * tsize)
+
+ debug_prints(func="BENCH", text="SETUP TIME", var=btRUNa)
+ debug_prints(func="BENCH", text="BENCHMARK TIME", var=btRUNb)
+ debug_print_vars(
+ "\n[BENCH]\n",
+ "GRIDSIZE: ", tsize, ' - ', tsize * tsize * tsize
+ )
diff --git a/add_advanced_objects/object_mangle_tools.py b/add_advanced_objects/object_mangle_tools.py
index 81110ad3..9f5b44ee 100644
--- a/add_advanced_objects/object_mangle_tools.py
+++ b/add_advanced_objects/object_mangle_tools.py
@@ -1,7 +1,6 @@
# mangle_tools.py (c) 2011 Phil Cote (cotejrp1)
-#
-# ***** BEGIN GPL LICENSE BLOCK *****
-#
+
+# ###### 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
@@ -10,36 +9,43 @@
#
# 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
+# 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 LICENCE BLOCK *****
+# ###### END GPL LICENCE BLOCK ######
+
+# Note: properties are moved into __init__
bl_info = {
"name": "Mangle Tools",
"author": "Phil Cote",
- "version": (0, 2),
+ "version": (0, 2, 2),
"blender": (2, 71, 0),
"location": "View3D > Toolshelf > Tools Tab",
"description": "Set of tools to mangle curves, meshes, and shape keys",
- "warning": "", # used for warning icon and text in addons panel
+ "warning": "",
"wiki_url": "",
- "tracker_url": "https://developer.blender.org/maniphest/task/edit/form/2/",
"category": "Object"}
import bpy
import random
+from bpy.types import (
+ Operator,
+ Panel,
+ )
import time
from math import pi
import bmesh
+
def move_coordinate(context, co, is_curve=False):
- xyz_const = context.scene.constraint_vector
+ advanced_objects = context.scene.advanced_objects
+ xyz_const = advanced_objects.mangle_constraint_vector
random.seed(time.time())
multiplier = 1
@@ -47,95 +53,100 @@ def move_coordinate(context, co, is_curve=False):
# This helps make curve changes more noticable.
if is_curve:
multiplier = 2 * pi
- random_mag = context.scene.random_magnitude
+ random_mag = advanced_objects.mangle_random_magnitude
if xyz_const[0]:
- co.x += .01 * random.randrange( -random_mag, random_mag ) * multiplier
+ co.x += .01 * random.randrange(-random_mag, random_mag) * multiplier
if xyz_const[1]:
- co.y += .01 * random.randrange( -random_mag, random_mag ) * multiplier
+ co.y += .01 * random.randrange(-random_mag, random_mag) * multiplier
if xyz_const[2]:
- co.z += .01 * random.randrange( -random_mag, random_mag ) * multiplier
+ co.z += .01 * random.randrange(-random_mag, random_mag) * multiplier
-class MeshManglerOperator(bpy.types.Operator):
- """Push vertices on the selected object around in random """ \
- """directions to create a crumpled look"""
+class MeshManglerOperator(Operator):
bl_idname = "ba.mesh_mangler"
bl_label = "Mangle Mesh"
- bl_options = { "REGISTER", "UNDO" }
+ bl_description = ("Push vertices on the selected object around in random\n"
+ "directions to create a crumpled look")
+ bl_options = {"REGISTER", "UNDO"}
@classmethod
def poll(cls, context):
ob = context.active_object
- return ob != None and ob.type == 'MESH'
+ return ob is not None and ob.type == 'MESH'
def execute(self, context):
mesh = context.active_object.data
bm = bmesh.new()
bm.from_mesh(mesh)
- verts, faces = bm.verts, bm.faces
- randomMag = context.scene.random_magnitude
- random.seed( time.time() )
-
- if mesh.shape_keys != None:
- self.report({'INFO'}, "Cannot mangle mesh: Shape keys present")
+ verts = bm.verts
+ advanced_objects = context.scene.advanced_objects
+ randomMag = advanced_objects.mangle_random_magnitude
+ random.seed(time.time())
+
+ if mesh.shape_keys is not None:
+ self.report({'INFO'},
+ "Cannot mangle mesh: Shape keys present. Operation Cancelled")
return {'CANCELLED'}
for vert in verts:
- xVal = .01 * random.randrange( -randomMag, randomMag )
- yVal = .01 * random.randrange( -randomMag, randomMag)
- zVal = .01 * random.randrange( -randomMag, randomMag )
+ xVal = .01 * random.randrange(-randomMag, randomMag)
+ yVal = .01 * random.randrange(-randomMag, randomMag)
+ zVal = .01 * random.randrange(-randomMag, randomMag)
+
vert.co.x = vert.co.x + xVal
vert.co.y = vert.co.y + yVal
vert.co.z = vert.co.z + zVal
+ del verts
+
bm.to_mesh(mesh)
mesh.update()
+
return {'FINISHED'}
-class AnimanglerOperator(bpy.types.Operator):
- """Make a shape key and pushes the verts around on it """ \
- """to set up for random pulsating animation"""
+class AnimanglerOperator(Operator):
bl_idname = "ba.ani_mangler"
bl_label = "Mangle Shape Key"
-
+ bl_description = ("Make a shape key and pushes the verts around on it\n"
+ "to set up for random pulsating animation")
@classmethod
def poll(cls, context):
ob = context.active_object
- return ob != None and ob.type in [ 'MESH', 'CURVE' ]
+ return ob is not None and ob.type in ['MESH', 'CURVE']
def execute(self, context):
- scn = context.scene
+ scn = context.scene.advanced_objects
mangleName = scn.mangle_name
ob = context.object
- shapeKey = ob.shape_key_add( name=mangleName )
+ shapeKey = ob.shape_key_add(name=mangleName)
verts = shapeKey.data
for vert in verts:
- move_coordinate(context, vert.co, is_curve=ob.type=='CURVE')
+ move_coordinate(context, vert.co, is_curve=ob.type == 'CURVE')
return {'FINISHED'}
-class CurveManglerOp(bpy.types.Operator):
- """Mangle a curve to the degree the user specifies"""
+class CurveManglerOp(Operator):
bl_idname = "ba.curve_mangler"
bl_label = "Mangle Curve"
- bl_options = { 'REGISTER', 'UNDO' }
+ bl_description = "Mangle a curve to the degree the user specifies"
+ bl_options = {'REGISTER', 'UNDO'}
@classmethod
def poll(cls, context):
ob = context.active_object
- return ob != None and ob.type == "CURVE"
-
+ return ob is not None and ob.type == "CURVE"
def execute(self, context):
-
ob = context.active_object
- if ob.data.shape_keys != None:
- self.report({'INFO'}, "Cannot mangle curve. Shape keys present")
+ if ob.data.shape_keys is not None:
+ self.report({'INFO'},
+ "Cannot mangle curve. Shape keys present. Operation Cancelled")
return {'CANCELLED'}
+
splines = context.object.data.splines
for spline in splines:
@@ -150,56 +161,43 @@ class CurveManglerOp(bpy.types.Operator):
return {'FINISHED'}
-class MangleToolsPanel(bpy.types.Panel):
+class MangleToolsPanel(Panel):
bl_label = "Mangle Tools"
bl_space_type = "VIEW_3D"
bl_context = "objectmode"
- bl_region_type="TOOLS"
+ bl_region_type = "TOOLS"
bl_category = "Create"
bl_options = {'DEFAULT_CLOSED'}
-
def draw(self, context):
- scn = context.scene
+ scn = context.scene.advanced_objects
obj = context.object
- if obj.type in ['MESH',]:
+
+ if obj and obj.type in ['MESH']:
layout = self.layout
+
+ row = layout.row(align=True)
+ row.prop(scn, "mangle_constraint_vector", toggle=True)
+
col = layout.column()
- col.prop(scn, "constraint_vector")
- col.prop(scn, "random_magnitude")
+ col.prop(scn, "mangle_random_magnitude")
col.operator("ba.mesh_mangler")
col.separator()
+
col.prop(scn, "mangle_name")
col.operator("ba.ani_mangler")
else:
layout = self.layout
- col = layout.column()
- col.label("Please Select Mesh Object")
+ layout.label(text="Please select a Mesh Object", icon="INFO")
-IntProperty = bpy.props.IntProperty
-StringProperty = bpy.props.StringProperty
-BoolVectorProperty = bpy.props.BoolVectorProperty
def register():
bpy.utils.register_class(AnimanglerOperator)
bpy.utils.register_class(MeshManglerOperator)
bpy.utils.register_class(CurveManglerOp)
bpy.utils.register_class(MangleToolsPanel)
- scnType = bpy.types.Scene
-
-
- scnType.constraint_vector = BoolVectorProperty(name="Mangle Constraint",
- default=(True,True,True),
- subtype='XYZ',
- description="Constrains Mangle Direction")
- scnType.random_magnitude = IntProperty( name = "Mangle Severity",
- default = 5, min = 1, max = 30,
- description = "Severity of mangling")
- scnType.mangle_name = StringProperty(name="Shape Key Name",
- default="mangle",
- description="Name given for mangled shape keys")
def unregister():
bpy.utils.unregister_class(AnimanglerOperator)
bpy.utils.unregister_class(MeshManglerOperator)
diff --git a/add_advanced_objects/oscurart_chain_maker.py b/add_advanced_objects/oscurart_chain_maker.py
index c336e44d..6dcd6f80 100644
--- a/add_advanced_objects/oscurart_chain_maker.py
+++ b/add_advanced_objects/oscurart_chain_maker.py
@@ -16,7 +16,7 @@
#
# ##### END GPL LICENSE BLOCK #####
-# TODO: translate the comments into English
+# TODO: find English versions of created object names
bl_info = {
"name": "Oscurart Chain Maker",
@@ -27,7 +27,6 @@ bl_info = {
"description": "Create chain links from armatures",
"warning": "",
"wiki_url": "oscurart.blogspot.com",
- "tracker_url": "",
"category": "Object"}
@@ -52,7 +51,7 @@ def makeChain(self, context, mult, curverig):
def creahuesocero(hueso):
# create data to link
mesh = bpy.data.meshes.new("objectData" + str(hueso.name))
- object = bpy.data.objects.new("EslabonCero" + str(hueso.name), mesh)
+ object = bpy.data.objects.new("HardLink" + str(hueso.name), mesh)
mesh.from_pydata(
[(-0.04986128956079483, -0.6918092370033264, -0.17846597731113434),
(-0.04986128956079483, -0.6918091773986816, 0.17846640944480896),
@@ -93,18 +92,18 @@ def makeChain(self, context, mult, curverig):
mesh.validate()
bpy.context.scene.objects.link(object)
# scale to the bone
- bpy.data.objects['EslabonCero' + str(hueso.name)].scale = (hueso.length * mult,
- hueso.length * mult,
- hueso.length * mult)
+ bpy.data.objects["HardLink" + str(hueso.name)].scale = (hueso.length * mult,
+ hueso.length * mult,
+ hueso.length * mult)
# Parent Objects
- bpy.data.objects['EslabonCero' + str(hueso.name)].parent = ARMATURE
- bpy.data.objects['EslabonCero' + str(hueso.name)].parent_type = 'BONE'
- bpy.data.objects['EslabonCero' + str(hueso.name)].parent_bone = hueso.name
+ bpy.data.objects["HardLink" + str(hueso.name)].parent = ARMATURE
+ bpy.data.objects["HardLink" + str(hueso.name)].parent_type = 'BONE'
+ bpy.data.objects["HardLink" + str(hueso.name)].parent_bone = hueso.name
def creahuesonoventa(hueso):
# create data to link
mesh = bpy.data.meshes.new("objectData" + str(hueso.name))
- object = bpy.data.objects.new("EslabonNov" + str(hueso.name), mesh)
+ object = bpy.data.objects.new("NewLink" + str(hueso.name), mesh)
mesh.from_pydata(
[(0.1784660965204239, -0.6918091773986816, -0.049861203879117966),
(-0.1784662902355194, -0.6918091773986816, -0.04986126348376274),
@@ -145,13 +144,13 @@ def makeChain(self, context, mult, curverig):
mesh.validate()
bpy.context.scene.objects.link(object)
# scale to the bone
- bpy.data.objects['EslabonNov' + str(hueso.name)].scale = (hueso.length * mult,
+ bpy.data.objects["NewLink" + str(hueso.name)].scale = (hueso.length * mult,
hueso.length * mult,
hueso.length * mult)
# Parent objects
- bpy.data.objects['EslabonNov' + str(hueso.name)].parent = ARMATURE
- bpy.data.objects['EslabonNov' + str(hueso.name)].parent_type = 'BONE'
- bpy.data.objects['EslabonNov' + str(hueso.name)].parent_bone = hueso.name
+ bpy.data.objects["NewLink" + str(hueso.name)].parent = ARMATURE
+ bpy.data.objects["NewLink" + str(hueso.name)].parent_type = 'BONE'
+ bpy.data.objects["NewLink" + str(hueso.name)].parent_bone = hueso.name
for hueso in bpy.context.active_object.pose.bones:
if VAR_SWITCH == 1:
@@ -182,18 +181,16 @@ def makeChain(self, context, mult, curverig):
# create the list of tail and head coordinates
LISTA_POINTC.append((
- ACTARM.data.bones[0].head_local[0],
- ACTARM.data.bones[0].head_local[1],
- ACTARM.data.bones[0].head_local[2],
- 1
- ))
+ ACTARM.data.bones[0].head_local[0],
+ ACTARM.data.bones[0].head_local[1],
+ ACTARM.data.bones[0].head_local[2], 1
+ ))
for hueso in ACTARM.data.bones:
LISTA_POINTC.append((
hueso.tail_local[0],
hueso.tail_local[1],
- hueso.tail_local[2],
- 1
+ hueso.tail_local[2], 1
))
# create the Spline
@@ -249,14 +246,14 @@ class MESH_OT_primitive_oscurart_chain_add(Operator):
bl_options = {'REGISTER', 'UNDO'}
curverig = BoolProperty(
- name="Curve Rig",
- default=False
- )
+ name="Curve Rig",
+ default=False
+ )
multiplier = FloatProperty(
- name="Scale",
- default=1,
- min=0.01, max=100.0
- )
+ name="Scale",
+ default=1,
+ min=0.01, max=100.0
+ )
@classmethod
def poll(cls, context):
@@ -264,7 +261,18 @@ class MESH_OT_primitive_oscurart_chain_add(Operator):
return (obj is not None and obj.type == "ARMATURE")
def execute(self, context):
- makeChain(self, context, self.multiplier, self.curverig)
+ try:
+ makeChain(self, context, self.multiplier, self.curverig)
+
+ except Exception as e:
+ self.report({'WARNING'},
+ "Some operations could not be performed (See Console for more info)")
+
+ print("\n[Add Advanced Objects]\nOperator: "
+ "mesh.primitive_oscurart_chain_add\nError: {}".format(e))
+
+ return {'CANCELLED'}
+
return {'FINISHED'}
diff --git a/add_advanced_objects/pixelate_3d.py b/add_advanced_objects/pixelate_3d.py
index 90e129da..d2b28971 100644
--- a/add_advanced_objects/pixelate_3d.py
+++ b/add_advanced_objects/pixelate_3d.py
@@ -1,28 +1,25 @@
-#######################################################
+# gpl author: liero
# very simple 'pixelization' or 'voxelization' engine #
-#######################################################
bl_info = {
- "name": "3D Pix",
+ "name": "3D Pixelate",
"author": "liero",
- "version": (0, 5, 1),
+ "version": (0, 5, 2),
"blender": (2, 74, 0),
"location": "View3D > Tool Shelf",
- "description": "Creates a 3d pixelated version of the object.",
+ "description": "Creates a 3d pixelated version of the object",
"category": "Object"}
-import bpy
-import mathutils
-from mathutils import Vector
+# Note: winmgr properties are moved into __init__
+# search for patterns advanced_objects and adv_obj
-bpy.types.WindowManager.size = bpy.props.FloatProperty(name='Size', min=.05, max=5, default=.25, description='Size of the cube / grid')
-bpy.types.WindowManager.gap = bpy.props.IntProperty(name='Gap', min=0, max=90, default=10, subtype='PERCENTAGE', description='Separation - percent of size')
-bpy.types.WindowManager.smooth = bpy.props.FloatProperty(name='Smooth', min=0, max=1, default=.0, description='Smooth factor when subdividing mesh')
+import bpy
+from bpy.types import Operator
def pix(obj):
sce = bpy.context.scene
- wm = bpy.context.window_manager
+ props = sce.advanced_objects
obj.hide = obj.hide_render = True
mes = obj.to_mesh(sce, True, 'RENDER')
mes.transform(obj.matrix_world)
@@ -37,12 +34,12 @@ def pix(obj):
fin = True
for i in dup.data.edges:
d = ver[i.vertices[0]].co - ver[i.vertices[1]].co
- if d.length > wm.size:
+ if d.length > props.pixelate_3d_size:
ver[i.vertices[0]].select = True
ver[i.vertices[1]].select = True
fin = False
bpy.ops.object.editmode_toggle()
- bpy.ops.mesh.subdivide(number_cuts=1, smoothness=wm.smooth)
+ bpy.ops.mesh.subdivide(number_cuts=1, smoothness=props.pixelate_3d_smooth)
bpy.ops.mesh.select_all(action='DESELECT')
bpy.ops.object.editmode_toggle()
if fin:
@@ -50,55 +47,68 @@ def pix(obj):
for i in ver:
for n in range(3):
- i.co[n] -= (.001 + i.co[n]) % wm.size
+ i.co[n] -= (.001 + i.co[n]) % props.pixelate_3d_size
bpy.ops.object.mode_set(mode='EDIT', toggle=False)
bpy.ops.mesh.select_all(action='SELECT')
bpy.ops.mesh.remove_doubles(threshold=0.0001)
bpy.ops.mesh.delete(type='EDGE_FACE')
bpy.ops.object.mode_set()
- sca = wm.size * (100 - wm.gap) * .005
+ sca = props.pixelate_3d_size * (100 - props.pixelate_3d_gap) * .005
bpy.ops.mesh.primitive_cube_add(layers=[True] + [False] * 19)
bpy.ops.transform.resize(value=[sca] * 3)
bpy.context.scene.objects.active = dup
bpy.ops.object.parent_set(type='OBJECT')
-class Pixelate(bpy.types.Operator):
- bl_idname = 'object.pixelate'
- bl_label = 'Pixelate Object'
- bl_description = 'Create a 3d pixelated version of the object.'
+class Pixelate(Operator):
+ bl_idname = "object.pixelate"
+ bl_label = "Pixelate Object"
+ bl_description = ("Create a 3d pixelated version of the object\n"
+ "using a Duplivert Box around each copied vertex\n"
+ "With high poly objects, it can take some time\n"
+ "Needs an existing Active Mesh Object")
bl_options = {'REGISTER', 'UNDO'}
@classmethod
def poll(cls, context):
- return (context.active_object and context.active_object.type == 'MESH' and context.mode == 'OBJECT')
+ return (context.active_object and
+ context.active_object.type == 'MESH' and
+ context.mode == 'OBJECT')
def draw(self, context):
layout = self.layout
+ adv_obj = context.scene.advanced_objects
- column = layout.column(align=True)
- column.prop(context.window_manager, "size")
- column.prop(context.window_manager, "gap")
- layout.prop(context.window_manager, "smooth")
+ col = layout.column(align=True)
+ col.prop(adv_obj, "pixelate_size")
+ col.prop(adv_obj, "pixelate_gap")
+ layout.prop(adv_obj, "pixelate_smooth")
def execute(self, context):
- objeto = bpy.context.object
- pix(objeto)
+ objeto = context.active_object
+ try:
+ pix(objeto)
+
+ except Exception as e:
+ self.report({'WARNING'},
+ "Some operations could not be performed (See Console for more info)")
+
+ print("\n[Add Advanced Objects]\nOperator: "
+ "object.pixelate\nError: {}".format(e))
+
+ return {'CANCELLED'}
+
return {'FINISHED'}
-classes = (
- Pixelate,
-)
def register():
- for cls in classes:
- bpy.utils.register_class(cls)
+ bpy.utils.register_class(Pixelate)
def unregister():
- for cls in classes:
- bpy.utils.unregister_class(cls)
+ bpy.utils.unregister_class(Pixelate)
+
if __name__ == '__main__':
register()
diff --git a/add_advanced_objects/random_box_structure.py b/add_advanced_objects/random_box_structure.py
index 5440b8b0..fa4b6497 100644
--- a/add_advanced_objects/random_box_structure.py
+++ b/add_advanced_objects/random_box_structure.py
@@ -1,9 +1,11 @@
+# gpl: author Dannyboy
+
bl_info = {
"name": "Add Random Box Structure",
"author": "Dannyboy",
- "version": (1, 0),
+ "version": (1, 0, 1),
"location": "View3D > Add > Make Box Structure",
- "description": "Fill selected box shaped meshes with randomly sized cubes.",
+ "description": "Fill selected box shaped meshes with randomly sized cubes",
"warning": "",
"wiki_url": "",
"tracker_url": "dannyboypython.blogspot.com",
@@ -23,45 +25,70 @@ from bpy.props import (
class makestructure(Operator):
bl_idname = "object.make_structure"
bl_label = "Add Random Box Structure"
+ bl_description = ("Create a randomized structure made of boxes\n"
+ "with various control parameters\n"
+ "Needs an existing Active Mesh Object")
bl_options = {'REGISTER', 'UNDO'}
dc = BoolProperty(
- name="Delete Base Mesh(s)?",
- default=True
- )
+ name="Delete Base Mesh(es)",
+ default=True
+ )
wh = BoolProperty(
- name="Stay Within Base Mesh(s)?",
- description="Keeps cubes from exceeding base mesh bounds",
- default=True
- )
+ name="Stay Within Bounds",
+ description="Keeps cubes from exceeding base mesh bounds",
+ default=True
+ )
uf = BoolProperty(
- name="Uniform Cube Quantity",
- default=False
- )
+ name="Uniform Cube Quantity",
+ default=False
+ )
qn = IntProperty(
- name="Cube Quantity",
- default=10,
- min=1, max=1500
- )
+ name="Cube Quantity",
+ default=10,
+ min=1, max=1500
+ )
mn = FloatVectorProperty(
- name="Min Scales",
- default=(0.1, 0.1, 0.1),
- subtype='XYZ'
- )
+ name="Min Scales",
+ default=(0.1, 0.1, 0.1),
+ subtype='XYZ'
+ )
mx = FloatVectorProperty(
- name="Max Scales",
- default=(2.0, 2.0, 2.0),
- subtype='XYZ'
- )
+ name="Max Scales",
+ default=(2.0, 2.0, 2.0),
+ subtype='XYZ'
+ )
lo = FloatVectorProperty(
- name="XYZ Offset",
- default=(0.0, 0.0, 0.0),
- subtype='XYZ'
- )
+ name="XYZ Offset",
+ default=(0.0, 0.0, 0.0),
+ subtype='XYZ'
+ )
rsd = FloatProperty(
- name="Random Seed",
- default=1
- )
+ name="Random Seed",
+ default=1
+ )
+
+ @classmethod
+ def poll(cls, context):
+ obj = context.active_object
+ return obj is not None and obj.type == "MESH" and obj.mode == "OBJECT"
+
+ def draw(self, context):
+ layout = self.layout
+
+ box = layout.box()
+ box.label(text="Options:")
+ box.prop(self, "dc")
+ box.prop(self, "wh")
+ box.prop(self, "uf")
+
+ box = layout.box()
+ box.label(text="Parameters:")
+ box.prop(self, "qn")
+ box.prop(self, "mn")
+ box.prop(self, "mx")
+ box.prop(self, "lo")
+ box.prop(self, "rsd")
def execute(self, context):
rsdchange = self.rsd
@@ -69,8 +96,10 @@ class makestructure(Operator):
uvyes = 0
bpy.ops.group.create(name='Cubagrouper')
bpy.ops.group.objects_remove()
+
for ob in bpy.context.selected_objects:
oblst.append(ob)
+
for obj in oblst:
bpy.ops.object.select_pattern(pattern=obj.name) # Select base mesh
bpy.context.scene.objects.active = obj
@@ -85,18 +114,19 @@ class makestructure(Operator):
area = dim.x * dim.y * dim.z
else:
area = 75
+
for cube in range(round((area / 75) * self.qn)):
random.seed(rsdchange)
pmn = self.mn # Proxy values
pmx = self.mx
if self.wh is True:
- if dim.x < pmx.x: # Keeping things from exceeding proper size.
+ if dim.x < pmx.x: # Keeping things from exceeding proper size
pmx.x = dim.x
if dim.y < pmx.y:
pmx.y = dim.y
if dim.z < pmx.z:
pmx.z = dim.z
- if 0.0 > pmn.x: # Keeping things from going under zero.
+ if 0.0 > pmn.x: # Keeping things from going under zero
pmn.x = 0.0
if 0.0 > pmn.y:
pmn.y = 0.0
@@ -105,7 +135,7 @@ class makestructure(Operator):
sx = (random.random() * (pmx.x - pmn.x)) + pmn.x # Just changed self.mx and .mn to pmx.
sy = (random.random() * (pmx.y - pmn.y)) + pmn.y
sz = (random.random() * (pmx.z - pmn.z)) + pmn.z
- if self.wh is True: # This keeps the cubes within the base mesh.
+ if self.wh is True: # This keeps the cubes within the base mesh
ex = (random.random() * (dim.x - sx)) - ((dim.x - sx) / 2) + obj.location.x
wy = (random.random() * (dim.y - sy)) - ((dim.y - sy) / 2) + obj.location.y
ze = (random.random() * (dim.z - sz)) - ((dim.z - sz) / 2) + obj.location.z
@@ -119,74 +149,52 @@ class makestructure(Operator):
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.select_all(action='SELECT')
bpy.ops.transform.resize(
- value=(sx, sy, sz), constraint_axis=(True, True, True),
- constraint_orientation='GLOBAL', mirror=False, proportional='DISABLED',
- proportional_edit_falloff='SMOOTH', proportional_size=1, release_confirm=True
- )
+ value=(sx, sy, sz), constraint_axis=(True, True, True),
+ constraint_orientation='GLOBAL', mirror=False, proportional='DISABLED',
+ proportional_edit_falloff='SMOOTH', proportional_size=1, release_confirm=True
+ )
bpy.ops.object.mode_set(mode='OBJECT')
- select = bpy.context.object # This is used to keep something selected for poll().
+ select = bpy.context.object # This is used to keep something selected for poll()
bpy.ops.object.group_link(group='Cubagrouper')
rsdchange += 3
bpy.ops.object.select_grouped(type='GROUP')
bpy.ops.transform.rotate(
- value=rot[0], axis=(1, 0, 0), constraint_axis=(False, False, False),
- constraint_orientation='GLOBAL', mirror=False, proportional='DISABLED',
- proportional_edit_falloff='SMOOTH', proportional_size=1, release_confirm=True
- )
+ value=rot[0], axis=(1, 0, 0), constraint_axis=(False, False, False),
+ constraint_orientation='GLOBAL', mirror=False, proportional='DISABLED',
+ proportional_edit_falloff='SMOOTH', proportional_size=1, release_confirm=True
+ )
bpy.ops.transform.rotate(
- value=rot[1], axis=(0, 1, 0), constraint_axis=(False, False, False),
- constraint_orientation='GLOBAL', mirror=False, proportional='DISABLED',
- proportional_edit_falloff='SMOOTH', proportional_size=1, release_confirm=True
- )
+ value=rot[1], axis=(0, 1, 0), constraint_axis=(False, False, False),
+ constraint_orientation='GLOBAL', mirror=False, proportional='DISABLED',
+ proportional_edit_falloff='SMOOTH', proportional_size=1, release_confirm=True
+ )
bpy.ops.transform.rotate(
- value=rot[2], axis=(0, 0, 1), constraint_axis=(False, False, False),
- constraint_orientation='GLOBAL', mirror=False, proportional='DISABLED',
- proportional_edit_falloff='SMOOTH', proportional_size=1, release_confirm=True
- )
- bpy.context.scene.objects.active = obj # Again needed to avoid poll() taking me down.
+ value=rot[2], axis=(0, 0, 1), constraint_axis=(False, False, False),
+ constraint_orientation='GLOBAL', mirror=False, proportional='DISABLED',
+ proportional_edit_falloff='SMOOTH', proportional_size=1, release_confirm=True
+ )
+ bpy.context.scene.objects.active = obj # Again needed to avoid poll() taking me down
bpy.ops.object.make_links_data(type='MODIFIERS')
bpy.ops.object.make_links_data(type='MATERIAL')
+
if uvyes == 1:
bpy.ops.object.join_uvs()
+
bpy.ops.group.objects_remove()
bpy.context.scene.objects.active = select
+
if self.dc is True:
bpy.context.scene.objects.unlink(obj)
- return {'FINISHED'}
-
- @classmethod
- def poll(cls, context):
- ob = context.active_object
- return ob is not None and ob.mode == 'OBJECT'
-
- def draw(self, context):
- layout = self.layout
- box = layout.box()
- box.label(text="Options")
- box.prop(self, "dc")
- box.prop(self, "wh")
- box.prop(self, "uf")
- box = layout.box()
- box.label(text="Parameters")
- box.prop(self, "qn")
- box.prop(self, "mn")
- box.prop(self, "mx")
- box.prop(self, "lo")
- box.prop(self, "rsd")
-
-def add_object_button(self, context):
- self.layout.operator(makestructure.bl_idname, text="Add Random Box structure", icon='PLUGIN')
+ return {'FINISHED'}
def register():
bpy.utils.register_class(makestructure)
- bpy.types.INFO_MT_add.append(add_object_button)
def unregister():
bpy.utils.unregister_class(makestructure)
- bpy.types.INFO_MT_add.remove(add_object_button)
if __name__ == "__main__":
diff --git a/add_advanced_objects/rope_alpha.py b/add_advanced_objects/rope_alpha.py
index f0406148..904168a1 100644
--- a/add_advanced_objects/rope_alpha.py
+++ b/add_advanced_objects/rope_alpha.py
@@ -18,18 +18,17 @@
#
# ##### END GPL LICENSE BLOCK #####
-# TODO : translate comments, prop names into English, add missing tooltips
+# TODO : prop names into English, add missing tooltips
bl_info = {
"name": "Rope Creator",
"description": "Dynamic rope (with cloth) creator",
"author": "Jorge Hernandez - Melenedez",
- "version": (0, 2),
+ "version": (0, 2, 2),
"blender": (2, 7, 3),
"location": "Left Toolbar > ClothRope",
"warning": "",
"wiki_url": "",
- "tracker_url": "",
"category": "Add Mesh"
}
@@ -60,29 +59,34 @@ def seleccionar_todo():
def salir_de_editmode():
- if bpy.context.mode == "EDIT" or bpy.context.mode == "EDIT_CURVE" or bpy.context.mode == "EDIT_MESH":
+ if bpy.context.mode in ["EDIT", "EDIT_MESH", "EDIT_CURVE"]:
bpy.ops.object.mode_set(mode='OBJECT')
-# Clear scene:
-
+# Clear scene:
def reset_scene():
desocultar("todo")
- # el play back al principio
+ # playback to the start
bpy.ops.screen.frame_jump(end=False)
try:
salir_de_editmode()
except:
pass
- area = bpy.context.area
- # en el outliner expando todo para poder seleccionar los emptys hijos
- old_type = area.type
- area.type = 'OUTLINER'
- bpy.ops.outliner.expanded_toggle()
- area.type = old_type
- # vuelvo al contexto donde estaba
- seleccionar_todo()
- bpy.ops.object.delete(use_global=False)
+ try:
+ area = bpy.context.area
+ # expand everything in the outliner to be able to select children
+ old_type = area.type
+ area.type = 'OUTLINER'
+ bpy.ops.outliner.expanded_toggle()
+
+ # restore the original context
+ area.type = old_type
+
+ seleccionar_todo()
+ bpy.ops.object.delete(use_global=False)
+
+ except Exception as e:
+ print("\n[rope_alpha]\nfunction: reset_scene\nError: %s" % e)
def entrar_en_editmode():
@@ -100,7 +104,6 @@ def select_all_in_edit_mode(ob):
if not v.select:
v.select = True
entrar_en_editmode()
- # bpy.ops.mesh.select_all(action="SELECT")
def deselect_all_in_edit_mode(ob):
@@ -119,17 +122,17 @@ def which_vertex_are_selected(ob):
for v in ob.data.vertices:
if v.select:
print(str(v.index))
- print("el vertice " + str(v.index) + " esta seleccionado")
+ print("Vertex " + str(v.index) + " is selected")
def seleccionar_por_nombre(nombre):
scn = bpy.context.scene
bpy.data.objects[nombre].select = True
+
scn.objects.active = bpy.data.objects[nombre]
def deseleccionar_por_nombre(nombre):
- # scn = bpy.context.scene
bpy.data.objects[nombre].select = False
@@ -143,14 +146,9 @@ def borrar_elementos_seleccionados(tipo):
bpy.ops.mesh.delete(type='VERT')
-def tab_editmode():
- bpy.ops.object.editmode_toggle()
-
-
def obtener_coords_vertex_seleccionados():
coordenadas_de_vertices = []
for ob in bpy.context.selected_objects:
- print(ob.name)
if ob.type == 'MESH':
for v in ob.data.vertices:
if v.select:
@@ -160,28 +158,28 @@ def obtener_coords_vertex_seleccionados():
def crear_locator(pos):
bpy.ops.object.empty_add(
- type='PLAIN_AXES', radius=1, view_align=False,
- location=(pos[0], pos[1], pos[2]),
- layers=(True, False, False, False, False, False, False,
- False, False, False, False, False, False, False,
- False, False, False, False, False, False)
- )
+ type='PLAIN_AXES', radius=1, view_align=False,
+ location=(pos[0], pos[1], pos[2]),
+ layers=(True, False, False, False, False, False, False,
+ False, False, False, False, False, False, False,
+ False, False, False, False, False, False)
+ )
def extruir_vertices(longitud, cuantos_segmentos):
bpy.ops.mesh.extrude_region_move(
- MESH_OT_extrude_region={"mirror": False},
- TRANSFORM_OT_translate={
- "value": (longitud / cuantos_segmentos, 0, 0),
- "constraint_axis": (True, False, False),
- "constraint_orientation": 'GLOBAL', "mirror": False,
- "proportional": 'DISABLED', "proportional_edit_falloff": 'SMOOTH',
- "proportional_size": 1, "snap": False, "snap_target": 'CLOSEST',
- "snap_point": (0, 0, 0), "snap_align": False, "snap_normal": (0, 0, 0),
- "gpencil_strokes": False, "texture_space": False,
- "remove_on_cancel": False, "release_confirm": False
- }
- )
+ MESH_OT_extrude_region={"mirror": False},
+ TRANSFORM_OT_translate={
+ "value": (longitud / cuantos_segmentos, 0, 0),
+ "constraint_axis": (True, False, False),
+ "constraint_orientation": 'GLOBAL', "mirror": False,
+ "proportional": 'DISABLED', "proportional_edit_falloff": 'SMOOTH',
+ "proportional_size": 1, "snap": False, "snap_target": 'CLOSEST',
+ "snap_point": (0, 0, 0), "snap_align": False, "snap_normal": (0, 0, 0),
+ "gpencil_strokes": False, "texture_space": False,
+ "remove_on_cancel": False, "release_confirm": False
+ }
+ )
def select_all_vertex_in_curve_bezier(bc):
@@ -203,135 +201,154 @@ def ocultar_relationships():
class ClothRope(Operator):
bl_idname = "clot.rope"
bl_label = "Rope Cloth"
+ bl_description = ("Create a new Scene with a Cloth modifier\n"
+ "Rope Simulation with hooked Helper Objects")
ropelenght = IntProperty(
- name="longitud",
- default=5
- )
+ name="Rope Length",
+ description="Length of the generated Rope",
+ default=5
+ )
ropesegments = IntProperty(
- name="rsegments",
- default=5
- )
+ name="Rope Segments",
+ description="Number of the Rope Segments",
+ default=5
+ )
qcr = IntProperty(
- name="qualcolr",
- min=1, max=20,
- default=20
- )
+ name="Collision Quality",
+ description="Rope's Cloth modifier collsion quality",
+ min=1, max=20,
+ default=20
+ )
substeps = IntProperty(
- name="rsubsteps",
- min=4, max=80,
- default=50
- )
+ name="Rope Substeps",
+ description="Rope's Cloth modifier quality",
+ min=4, max=80,
+ default=50
+ )
resrope = IntProperty(
- name="resr",
- default=5
- )
+ name="Rope Resolution",
+ description="Rope's Bevel resolution",
+ default=5
+ )
radiusrope = FloatProperty(
- name="radius",
- min=0.04, max=1,
- default=0.04
- )
+ name="Radius",
+ description="Rope's Radius",
+ min=0.04, max=1,
+ default=0.04
+ )
hide_emptys = BoolProperty(
- name="hemptys",
- default=False
- )
+ name="Hide Empties",
+ description="Hide Helper Objects",
+ default=False
+ )
def execute(self, context):
- # add new scene
+ # add a new scene
bpy.ops.scene.new(type="NEW")
scene = bpy.context.scene
scene.name = "Test Rope"
seleccionar_todo()
longitud = self.ropelenght
- # para que desde el primer punto hasta el ultimo, entre
- # medias tenga x segmentos debo sumarle 1 a la cantidad:
+
+ # For the middle to have x segments between the first and
+ # last point, must add 1 to the quantity:
cuantos_segmentos = self.ropesegments + 1
calidad_de_colision = self.qcr
substeps = self.substeps
deseleccionar_todo()
- # creamos el empty que sera el padre de todo
+ # collect the possible empties that already exist in the data
+ empties_prev = [obj.name for obj in bpy.data.objects if obj.type == "EMPTY"]
+
+ # create an empty that will be the parent of everything
bpy.ops.object.empty_add(
- type='SPHERE', radius=1, view_align=False, location=(0, 0, 0),
- layers=(True, False, False, False, False, False, False, False,
- False, False, False, False, False, False, False, False,
- False, False, False, False)
- )
+ type='SPHERE', radius=1, view_align=False, location=(0, 0, 0),
+ layers=(True, False, False, False, False, False, False, False,
+ False, False, False, False, False, False, False, False,
+ False, False, False, False)
+ )
ob = bpy.context.selected_objects[0]
ob.name = "Rope"
+ # .001 and friends
+ rope_name = ob.name
deseleccionar_todo()
- # creamos un plano y lo borramos
+
+ # create a plane and delete it
bpy.ops.mesh.primitive_plane_add(
- radius=1, view_align=False, enter_editmode=False, location=(0, 0, 0),
- layers=(True, False, False, False, False, False, False, False, False,
- False, False, False, False, False, False, False, False,
- False, False, False)
- )
+ radius=1, view_align=False, enter_editmode=False, location=(0, 0, 0),
+ layers=(True, False, False, False, False, False, False, False, False,
+ False, False, False, False, False, False, False, False,
+ False, False, False)
+ )
ob = bpy.context.selected_objects[0]
- # renombrar:
+ # rename:
ob.name = "cuerda"
- entrar_en_editmode() # entramos en edit mode
+ # .001 and friends
+ cuerda_1_name = ob.name
+
+ entrar_en_editmode() # enter edit mode
select_all_in_edit_mode(ob)
- # seleccionar_todo() # ya viene por default seleccionado
+
borrar_elementos_seleccionados("vertices")
- salir_de_editmode() # salimos de edit mode
- crear_vertices(ob) # creamos un vertex
- # creando el grupo Group para el PIN
- # Group contiene los vertices del pin y Group.001 contiene la linea unica principal
- entrar_en_editmode() # entramos en edit mode
- bpy.ops.object.vertex_group_add() # creamos un grupo
+ salir_de_editmode() # leave edit mode
+ crear_vertices(ob) # create a vertex
+
+ # Creating a Group for the PIN
+ # Group contains the vertices of the pin and the Group.001 contains the single main line
+ entrar_en_editmode() # enter edit mode
+ bpy.ops.object.vertex_group_add() # create a group
select_all_in_edit_mode(ob)
- bpy.ops.object.vertex_group_assign() # y lo asignamos
- # los hooks van a la curva no a la guia poligonal...
- # creo el primer hook sin necesidad de crear luego el locator a mano:
- # bpy.ops.object.hook_add_newob()
- salir_de_editmode() # salimos de edit mode
+ bpy.ops.object.vertex_group_assign() # assign it
+
+ salir_de_editmode() # leave edit mode
ob.vertex_groups[0].name = "Pin"
deseleccionar_todo()
- seleccionar_por_nombre("cuerda")
- # hago los extrudes del vertice:
+ seleccionar_por_nombre(cuerda_1_name)
+
+ # extrude vertices:
for i in range(cuantos_segmentos):
entrar_en_editmode()
extruir_vertices(longitud, cuantos_segmentos)
- # y los ELIMINO del grupo PIN
+ # delete the PIN group
bpy.ops.object.vertex_group_remove_from()
- # obtengo la direccion para lego crear el locator en su posicion
+ # get the direction to create the locator on it's position
pos = obtener_coords_vertex_seleccionados()
- # los hooks van a la curva no a la guia poligonal...
- # creo el hook sin necesidad de crear el locator a mano:
- # bpy.ops.object.hook_add_newob()
- salir_de_editmode() # salimos de edit mode
- # creo el locator en su sitio
+
+ salir_de_editmode() # leave edit mode
+ # create locator at position
crear_locator(pos)
deseleccionar_todo()
- seleccionar_por_nombre("cuerda")
+ seleccionar_por_nombre(cuerda_1_name)
deseleccionar_todo()
- seleccionar_por_nombre("cuerda")
- # vuelvo a seleccionar la cuerda
+
+ seleccionar_por_nombre(cuerda_1_name) # select the rope
entrar_en_editmode()
- pos = obtener_coords_vertex_seleccionados() # y obtenemos su posicion
+
+ pos = obtener_coords_vertex_seleccionados() # get their positions
salir_de_editmode()
- # creamos el ultimo locator
+ # create the last locator
crear_locator(pos)
deseleccionar_todo()
- seleccionar_por_nombre("cuerda")
- entrar_en_editmode() # entramos en edit mode
- bpy.ops.object.vertex_group_add() # CREANDO GRUPO GUIA MAESTRA
+ seleccionar_por_nombre(cuerda_1_name)
+ entrar_en_editmode() # enter edit mode
+ bpy.ops.object.vertex_group_add() # Creating Master guide group
select_all_in_edit_mode(ob)
- bpy.ops.object.vertex_group_assign() # y lo asignamos
+ bpy.ops.object.vertex_group_assign() # and assing it
ob.vertex_groups[1].name = "Guide_rope"
- # extruimos la curva para que tenga un minimo grosor para colisionar
+
+ # extrude the Curve so it has a minumum thickness for collide
bpy.ops.mesh.extrude_region_move(
- MESH_OT_extrude_region={"mirror": False},
- TRANSFORM_OT_translate={
- "value": (0, 0.005, 0), "constraint_axis": (False, True, False),
- "constraint_orientation": 'GLOBAL', "mirror": False,
- "proportional": 'DISABLED', "proportional_edit_falloff": 'SMOOTH',
- "proportional_size": 1, "snap": False, "snap_target": 'CLOSEST',
- "snap_point": (0, 0, 0), "snap_align": False, "snap_normal": (0, 0, 0),
- "gpencil_strokes": False, "texture_space": False,
- "remove_on_cancel": False, "release_confirm": False
- }
- )
+ MESH_OT_extrude_region={"mirror": False},
+ TRANSFORM_OT_translate={
+ "value": (0, 0.005, 0), "constraint_axis": (False, True, False),
+ "constraint_orientation": 'GLOBAL', "mirror": False,
+ "proportional": 'DISABLED', "proportional_edit_falloff": 'SMOOTH',
+ "proportional_size": 1, "snap": False, "snap_target": 'CLOSEST',
+ "snap_point": (0, 0, 0), "snap_align": False, "snap_normal": (0, 0, 0),
+ "gpencil_strokes": False, "texture_space": False,
+ "remove_on_cancel": False, "release_confirm": False
+ }
+ )
bpy.ops.object.vertex_group_remove_from()
deselect_all_in_edit_mode(ob)
salir_de_editmode()
@@ -340,54 +357,70 @@ class ClothRope(Operator):
bpy.context.object.modifiers["Cloth"].settings.vertex_group_mass = "Pin"
bpy.context.object.modifiers["Cloth"].collision_settings.collision_quality = calidad_de_colision
bpy.context.object.modifiers["Cloth"].settings.quality = substeps
- # DUPLICAMOS para convertir a curva:
- # selecciono los vertices que forman parte del grupo Group.001
- seleccionar_por_nombre("cuerda")
+
+ # Duplicate to convert into Curve:
+ # select the vertices that are the part of the Group.001
+ seleccionar_por_nombre(cuerda_1_name)
entrar_en_editmode()
bpy.ops.mesh.select_all(action="DESELECT")
bpy.context.tool_settings.mesh_select_mode = (True, False, False)
salir_de_editmode()
gi = ob.vertex_groups["Guide_rope"].index # get group index
+
for v in ob.data.vertices:
for g in v.groups:
if g.group == gi: # compare with index in VertexGroupElement
v.select = True
+
+ # now we have to make a table of names of cuerdas to see which one will be new
+ cuerda_names = [obj.name for obj in bpy.data.objects if "cuerda" in obj.name]
+
entrar_en_editmode()
- # ya tenemos la guia seleccionada:
- # la duplicamos:
+
+ # we already have the selected guide:
+ # duplicate it:
bpy.ops.mesh.duplicate_move(
- MESH_OT_duplicate={"mode": 1},
- TRANSFORM_OT_translate={
- "value": (0, 0, 0), "constraint_axis": (False, False, False),
- "constraint_orientation": 'GLOBAL', "mirror": False,
- "proportional": 'DISABLED', "proportional_edit_falloff": 'SMOOTH',
- "proportional_size": 1, "snap": False, "snap_target": 'CLOSEST',
- "snap_point": (0, 0, 0), "snap_align": False, "snap_normal": (0, 0, 0),
- "gpencil_strokes": False, "texture_space": False,
- "remove_on_cancel": False, "release_confirm": False
- }
- )
- # separamos por seleccion:
+ MESH_OT_duplicate={"mode": 1},
+ TRANSFORM_OT_translate={
+ "value": (0, 0, 0), "constraint_axis": (False, False, False),
+ "constraint_orientation": 'GLOBAL', "mirror": False,
+ "proportional": 'DISABLED', "proportional_edit_falloff": 'SMOOTH',
+ "proportional_size": 1, "snap": False, "snap_target": 'CLOSEST',
+ "snap_point": (0, 0, 0), "snap_align": False, "snap_normal": (0, 0, 0),
+ "gpencil_strokes": False, "texture_space": False,
+ "remove_on_cancel": False, "release_confirm": False
+ }
+ )
+ # separate the selections:
bpy.ops.mesh.separate(type='SELECTED')
salir_de_editmode()
deseleccionar_todo()
- seleccionar_por_nombre("cuerda.001")
- # a la nueva curva copiada le quitamos el cloth:
+
+ cuerda_2_name = "cuerda.001"
+ test = []
+ for obj in bpy.data.objects:
+ if "cuerda" in obj.name and obj.name not in cuerda_names:
+ cuerda_2_name = obj.name
+ test.append(obj.name)
+
+ seleccionar_por_nombre(cuerda_2_name)
+
+ # from the newly created curve remove the Cloth:
bpy.ops.object.modifier_remove(modifier="Cloth")
- # la convertimos en curva:
+ # convert the Curve:
bpy.ops.object.convert(target='CURVE')
- # todos los emptys:
+
+ # all Empties that are not previously present
emptys = []
for eo in bpy.data.objects:
- if eo.type == 'EMPTY':
- if eo.name != "Rope":
+ if eo.type == 'EMPTY' and eo.name not in empties_prev:
+ if eo.name != rope_name:
emptys.append(eo)
- # print(emptys)
- # cuantos puntos tiene la becier:
- # len(bpy.data.objects['cuerda.001'].data.splines[0].points)
- # seleccionar y deseleccionar:
- bc = bpy.data.objects['cuerda.001']
+
+ # select and deselect:
+ bc = bpy.data.objects[cuerda_2_name]
n = 0
+
for e in emptys:
deseleccionar_todo()
seleccionar_por_nombre(e.name)
@@ -398,9 +431,10 @@ class ClothRope(Operator):
bpy.ops.object.hook_add_selob(use_bone=False)
salir_de_editmode()
n = n + 1
- # entrar_en_editmode()
- ob = bpy.data.objects['cuerda']
+
+ ob = bpy.data.objects[cuerda_1_name]
n = 0
+
for e in emptys:
deseleccionar_todo()
seleccionar_por_nombre(e.name)
@@ -409,29 +443,32 @@ class ClothRope(Operator):
bpy.ops.mesh.select_all(action="DESELECT")
bpy.context.tool_settings.mesh_select_mode = (True, False, False)
salir_de_editmode()
+
for v in ob.data.vertices:
if v.select:
v.select = False
ob.data.vertices[n].select = True
entrar_en_editmode()
bpy.ops.object.vertex_parent_set()
- # deselect_all_in_edit_mode(ob)
+
salir_de_editmode()
n = n + 1
- # ocultar los emptys:
- # for e in emptys:
+ # hide the Empties:
deseleccionar_todo()
- # emparentando todo al empty esferico:
- seleccionar_por_nombre("cuerda.001")
- seleccionar_por_nombre("cuerda")
- seleccionar_por_nombre("Rope")
+
+ # all parented to the spherical empty:
+ seleccionar_por_nombre(cuerda_2_name)
+ seleccionar_por_nombre(cuerda_1_name)
+ seleccionar_por_nombre(rope_name)
bpy.ops.object.parent_set(type='OBJECT', keep_transform=True)
deseleccionar_todo()
- # display que no muestre las relaciones
+
+ # do not display the relations
ocultar_relationships()
- seleccionar_por_nombre("cuerda.001")
- # cuerda curva settings:
+ seleccionar_por_nombre(cuerda_2_name)
+
+ # curved rope settings:
bpy.context.object.data.fill_mode = 'FULL'
bpy.context.object.data.bevel_depth = self.radiusrope
bpy.context.object.data.bevel_resolution = self.resrope
@@ -439,82 +476,97 @@ class ClothRope(Operator):
return {'FINISHED'}
def invoke(self, context, event):
- return context.window_manager.invoke_props_dialog(self, width=310)
+ return context.window_manager.invoke_props_dialog(self, width=350)
def draw(self, context):
layout = self.layout
box = layout.box()
- col = box.column()
+ col = box.column(align=True)
+
col.label("Rope settings:")
rowsub0 = col.row()
- rowsub0.prop(self, "ropelenght", text='Length')
- rowsub0.prop(self, "ropesegments", text='Segments')
- rowsub0.prop(self, "radiusrope", text='Radius')
+ rowsub0.prop(self, "ropelenght", text="Length")
+ rowsub0.prop(self, "ropesegments", text="Segments")
+ rowsub0.prop(self, "radiusrope", text="Radius")
col.label("Quality Settings:")
- col.prop(self, "resrope", text='Resolution curve')
- col.prop(self, "qcr", text='Quality Collision')
- col.prop(self, "substeps", text='Substeps')
+ col.prop(self, "resrope", text="Resolution curve")
+ col.prop(self, "qcr", text="Quality Collision")
+ col.prop(self, "substeps", text="Substeps")
class BallRope(Operator):
bl_idname = "ball.rope"
- bl_label = "Rope Ball"
+ bl_label = "Wrecking Ball"
+ bl_description = ("Create a new Scene with a Rigid Body simulation of\n"
+ "Wrecking Ball on a rope")
# defaults rope ball
ropelenght2 = IntProperty(
- name="longitud",
- default=10
- )
+ name="Rope Length",
+ description="Length of the Wrecking Ball rope",
+ default=10
+ )
ropesegments2 = IntProperty(
- name="rsegments",
- min=0, max=999,
- default=6
- )
+ name="Rope Segments",
+ description="Number of the Wrecking Ball rope segments",
+ min=0, max=999,
+ default=6
+ )
radiuscubes = FloatProperty(
- name="radius",
- default=0.5
- )
+ name="Cube Radius",
+ description="Size of the Linked Cubes helpers",
+ default=0.5
+ )
radiusrope = FloatProperty(
- name="radius",
- default=0.4
- )
+ name="Rope Radius",
+ description="Radius of the Rope",
+ default=0.4
+ )
worldsteps = IntProperty(
- name="worldsteps",
- min=60, max=1000,
- default=250
- )
+ name="World Steps",
+ description="Rigid Body Solver world steps per second (update)",
+ min=60, max=1000,
+ default=250
+ )
solveriterations = IntProperty(
- name="solveriterations",
- min=10, max=100,
- default=50
- )
+ name="Solver Iterations",
+ description="How many times the Rigid Body Solver should run",
+ min=10, max=100,
+ default=50
+ )
massball = IntProperty(
- name="massball",
- default=1
- )
+ name="Ball Mass",
+ description="Mass of the Wrecking Ball",
+ default=1
+ )
resrope = IntProperty(
- name="resolucion",
- default=4
- )
+ name="Resolution",
+ description="Rope resolution",
+ default=4
+ )
grados = FloatProperty(
- name="grados",
- default=45
- )
+ name="Degrees",
+ description="Angle of the Wrecking Ball compared to the Ground Plane",
+ default=45
+ )
separacion = FloatProperty(
- name="separacion",
- default=0.1
- )
+ name="Link Cubes Gap",
+ description="Space between the Rope's Linked Cubes",
+ default=0.1
+ )
hidecubes = BoolProperty(
- name="hidecubes",
- default=False
- )
+ name="Hide Link Cubes",
+ description="Hide helper geometry for the Rope",
+ default=False
+ )
def execute(self, context):
world_steps = self.worldsteps
solver_iterations = self.solveriterations
longitud = self.ropelenght2
- # hago un + 2 para que los segmentos sean los que hay entre los dos extremos...
+
+ # make a + 2, so the segments will be between the two end points...
segmentos = self.ropesegments2 + 2
offset_del_suelo = 1
offset_del_suelo_real = (longitud / 2) + (segmentos / 2)
@@ -525,39 +577,48 @@ class BallRope(Operator):
rotrope = self.grados
separation = self.separacion
hidecubeslinks = self.hidecubes
+
# add new scene
bpy.ops.scene.new(type="NEW")
scene = bpy.context.scene
scene.name = "Test Ball"
- # suelo:
+
+ # collect the possible constraint empties that already exist in the data
+ constraint_prev = [obj.name for obj in bpy.data.objects if
+ obj.type == "EMPTY" and "Constraint" in obj.name]
+ # floor:
bpy.ops.mesh.primitive_cube_add(
- radius=1, view_align=False, enter_editmode=False, location=(0, 0, 0),
- layers=(True, False, False, False, False, False, False, False, False,
- False, False, False, False, False, False, False, False,
- False, False, False)
- )
+ radius=1, view_align=False, enter_editmode=False, location=(0, 0, 0),
+ layers=(True, False, False, False, False, False, False, False, False,
+ False, False, False, False, False, False, False, False,
+ False, False, False)
+ )
bpy.context.object.scale.x = 10 + longitud
bpy.context.object.scale.y = 10 + longitud
bpy.context.object.scale.z = 0.05
bpy.context.object.name = "groundplane"
+ # The secret agents .001, 002 etc.
+ groundplane_name = bpy.context.object.name
+
bpy.ops.rigidbody.objects_add(type='PASSIVE')
- # creamos el primer cubo:
+
+ # create the first cube:
cuboslink = []
n = 0
for i in range(segmentos):
- # si es 0 le digo que empieza desde 1
+ # if 0 start from 1
if i == 0:
i = offset_del_suelo
- else: # si no es 0 les tengo que sumar uno para que no se pisen al empezar el primero desde 1
+ else: # if it is not 0, add one so it doesn't step on the first one starting from 1
i = i + offset_del_suelo
- separacion = longitud * 2 / segmentos # distancia entre los cubos link
+ separacion = longitud * 2 / segmentos # distance between linked cubes
bpy.ops.mesh.primitive_cube_add(
- radius=1, view_align=False, enter_editmode=False,
- location=(0, 0, i * separacion),
- layers=(True, False, False, False, False, False, False, False,
- False, False, False, False, False, False, False, False,
- False, False, False, False)
- )
+ radius=1, view_align=False, enter_editmode=False,
+ location=(0, 0, i * separacion),
+ layers=(True, False, False, False, False, False, False, False,
+ False, False, False, False, False, False, False, False,
+ False, False, False, False)
+ )
bpy.ops.rigidbody.objects_add(type='ACTIVE')
bpy.context.object.name = "CubeLink"
if n != 0:
@@ -568,6 +629,7 @@ class BallRope(Operator):
bpy.context.object.scale.x = radio
bpy.context.object.scale.y = radio
cuboslink.append(bpy.context.object)
+
for i in range(len(cuboslink)):
deseleccionar_todo()
if i != len(cuboslink) - 1:
@@ -576,111 +638,115 @@ class BallRope(Operator):
seleccionar_por_nombre(nombre1.name)
seleccionar_por_nombre(nombre2.name)
bpy.ops.rigidbody.connect()
- seleccionar_por_nombre
- for i in range(segmentos - 1):
- if i == 0:
- seleccionar_por_nombre("Constraint")
- else:
- if i <= 9 and i > 0:
- seleccionar_por_nombre("Constraint.00" + str(i))
- else:
- if i <= 99 and i > 9:
- seleccionar_por_nombre("Constraint.0" + str(i))
- else:
- if i <= 999 and i > 99:
- seleccionar_por_nombre("Constraint." + str(i))
- for c in bpy.context.selected_objects:
- c.rigid_body_constraint.type = 'POINT'
+
+ # select by name
+ constraint_new = [
+ obj.name for obj in bpy.data.objects if
+ obj.type == "EMPTY" and "Constraint" in obj.name and
+ obj.name not in constraint_prev
+ ]
+
+ for names in constraint_new:
+ seleccionar_por_nombre(names)
+
+ for c in bpy.context.selected_objects:
+ c.rigid_body_constraint.type = 'POINT'
deseleccionar_todo()
- # creamos la curva bezier:
+ # create a Bezier curve:
bpy.ops.curve.primitive_bezier_curve_add(
- radius=1, view_align=False, enter_editmode=False, location=(0, 0, 0),
- layers=(True, False, False, False, False, False, False, False, False,
- False, False, False, False, False, False, False, False, False, False, False)
- )
+ radius=1, view_align=False, enter_editmode=False, location=(0, 0, 0),
+ layers=(True, False, False, False, False, False, False, False, False,
+ False, False, False, False, False, False, False, False, False, False, False)
+ )
bpy.context.object.name = "Cuerda"
+ # Blender will automatically append the .001
+ # if it is already in data
+ real_name = bpy.context.object.name
+
for i in range(len(cuboslink)):
cubonombre = cuboslink[i].name
seleccionar_por_nombre(cubonombre)
- seleccionar_por_nombre("Cuerda")
+ seleccionar_por_nombre(real_name)
x = cuboslink[i].location[0]
y = cuboslink[i].location[1]
z = cuboslink[i].location[2]
- # si es 0 le digo que empieza desde 1 es el offset desde el suelo...
+
+ # if it is 0 make it start from 1 as the offset from the ground...
if i == 0:
i = offset_del_suelo
- else: # si no es 0 les tengo que sumar uno para que no se pisen al empezar el primero desde 1
+ else: # if it is not 0, add one so it doesn't step on the first one starting from 1
i = i + offset_del_suelo
+
salir_de_editmode()
- # entrar_en_editmode()
- tab_editmode()
+ entrar_en_editmode()
+
if i == 1:
- # selecciono todos los vertices y los borro
- select_all_vertex_in_curve_bezier(bpy.data.objects["Cuerda"])
+ # select all the vertices and delete them
+ select_all_vertex_in_curve_bezier(bpy.data.objects[real_name])
bpy.ops.curve.delete(type='VERT')
- # creamos el primer vertice:
+ # create the first vertex:
bpy.ops.curve.vertex_add(location=(x, y, z))
else:
- # extruimos el resto:
+ # extrude the rest:
bpy.ops.curve.extrude_move(
- CURVE_OT_extrude={"mode": 'TRANSLATION'},
- TRANSFORM_OT_translate={
- "value": (0, 0, z / i),
- "constraint_axis": (False, False, True),
- "constraint_orientation": 'GLOBAL', "mirror": False,
- "proportional": 'DISABLED', "proportional_edit_falloff": 'SMOOTH',
- "proportional_size": 1, "snap": False, "snap_target": 'CLOSEST',
- "snap_point": (0, 0, 0), "snap_align": False, "snap_normal": (0, 0, 0),
- "gpencil_strokes": False, "texture_space": False,
- "remove_on_cancel": False, "release_confirm": False
- }
- )
+ CURVE_OT_extrude={"mode": 'TRANSLATION'},
+ TRANSFORM_OT_translate={
+ "value": (0, 0, z / i),
+ "constraint_axis": (False, False, True),
+ "constraint_orientation": 'GLOBAL', "mirror": False,
+ "proportional": 'DISABLED', "proportional_edit_falloff": 'SMOOTH',
+ "proportional_size": 1, "snap": False, "snap_target": 'CLOSEST',
+ "snap_point": (0, 0, 0), "snap_align": False, "snap_normal": (0, 0, 0),
+ "gpencil_strokes": False, "texture_space": False,
+ "remove_on_cancel": False, "release_confirm": False
+ }
+ )
bpy.ops.object.hook_add_selob(use_bone=False)
salir_de_editmode()
bpy.context.object.data.bevel_resolution = resolucion
deseleccionar_todo()
- # creando la esfera ball:
+ # create a sphere ball:
deseleccionar_todo()
seleccionar_por_nombre(cuboslink[0].name)
entrar_en_editmode()
z = cuboslink[0].scale.z + longitud / 2
bpy.ops.view3d.snap_cursor_to_selected()
bpy.ops.mesh.primitive_uv_sphere_add(
- view_align=False, enter_editmode=False,
- layers=(True, False, False, False, False, False, False,
- False, False, False, False, False, False, False,
- False, False, False, False, False, False)
- )
+ view_align=False, enter_editmode=False,
+ layers=(True, False, False, False, False, False, False,
+ False, False, False, False, False, False, False,
+ False, False, False, False, False, False)
+ )
bpy.ops.transform.translate(
- value=(0, 0, -z + 2), constraint_axis=(False, False, True),
- constraint_orientation='GLOBAL', mirror=False, proportional='DISABLED',
- proportional_edit_falloff='SMOOTH', proportional_size=1
- )
+ value=(0, 0, -z + 2), constraint_axis=(False, False, True),
+ constraint_orientation='GLOBAL', mirror=False, proportional='DISABLED',
+ proportional_edit_falloff='SMOOTH', proportional_size=1
+ )
bpy.ops.transform.resize(
- value=(longitud / 2, longitud / 2, longitud / 2),
- constraint_axis=(False, False, False),
- constraint_orientation='GLOBAL',
- mirror=False, proportional='DISABLED',
- proportional_edit_falloff='SMOOTH', proportional_size=1
- )
+ value=(longitud / 2, longitud / 2, longitud / 2),
+ constraint_axis=(False, False, False),
+ constraint_orientation='GLOBAL',
+ mirror=False, proportional='DISABLED',
+ proportional_edit_falloff='SMOOTH', proportional_size=1
+ )
deselect_all_in_edit_mode(cuboslink[0])
salir_de_editmode()
bpy.ops.object.shade_smooth()
bpy.context.object.rigid_body.mass = masa
bpy.ops.object.origin_set(type='ORIGIN_CENTER_OF_MASS')
- # lo subo todo para arriba un poco mas:
+ # move it all up a bit more:
seleccionar_todo()
- deseleccionar_por_nombre("groundplane")
+ deseleccionar_por_nombre(groundplane_name)
bpy.ops.transform.translate(
- value=(0, 0, offset_del_suelo_real),
- constraint_axis=(False, False, True),
- constraint_orientation='GLOBAL', mirror=False,
- proportional='DISABLED', proportional_edit_falloff='SMOOTH',
- proportional_size=1
- )
+ value=(0, 0, offset_del_suelo_real),
+ constraint_axis=(False, False, True),
+ constraint_orientation='GLOBAL', mirror=False,
+ proportional='DISABLED', proportional_edit_falloff='SMOOTH',
+ proportional_size=1
+ )
deseleccionar_todo()
seleccionar_por_nombre(cuboslink[-1].name)
@@ -689,25 +755,25 @@ class BallRope(Operator):
bpy.context.scene.rigidbody_world.steps_per_second = world_steps
bpy.context.scene.rigidbody_world.solver_iterations = solver_iterations
- # para mover todo desde el primero de arriba:
+ # move everything from the top one:
seleccionar_por_nombre(cuboslink[-1].name)
bpy.ops.view3d.snap_cursor_to_selected()
seleccionar_todo()
- deseleccionar_por_nombre("groundplane")
+ deseleccionar_por_nombre(groundplane_name)
deseleccionar_por_nombre(cuboslink[-1].name)
bpy.context.space_data.pivot_point = 'CURSOR'
bpy.ops.transform.rotate(
- value=rotrope, axis=(1, 0, 0),
- constraint_axis=(True, False, False),
- constraint_orientation='GLOBAL',
- mirror=False, proportional='DISABLED',
- proportional_edit_falloff='SMOOTH',
- proportional_size=1
- )
+ value=rotrope, axis=(1, 0, 0),
+ constraint_axis=(True, False, False),
+ constraint_orientation='GLOBAL',
+ mirror=False, proportional='DISABLED',
+ proportional_edit_falloff='SMOOTH',
+ proportional_size=1
+ )
bpy.context.space_data.pivot_point = 'MEDIAN_POINT'
deseleccionar_todo()
- seleccionar_por_nombre("Cuerda")
+ seleccionar_por_nombre(real_name)
bpy.context.object.data.fill_mode = 'FULL'
bpy.context.object.data.bevel_depth = radiorope
for ob in bpy.data.objects:
@@ -722,30 +788,34 @@ class BallRope(Operator):
return {'FINISHED'}
def invoke(self, context, event):
- return context.window_manager.invoke_props_dialog(self, width=310)
+ return context.window_manager.invoke_props_dialog(self, width=350)
def draw(self, context):
layout = self.layout
box = layout.box()
- col = box.column()
+ col = box.column(align=True)
+
col.label("Rope settings:")
rowsub0 = col.row()
- rowsub0.prop(self, "hidecubes", text='Hide Link Cubes')
- rowsub1 = col.row()
- rowsub1.prop(self, "ropelenght2", text='Length')
- rowsub1.prop(self, "ropesegments2", text='Segments')
- rowsub2 = col.row()
- rowsub2.prop(self, "radiuscubes", text='Radius Link Cubes')
- rowsub2.prop(self, "radiusrope", text='Radius Rope')
- rowsub3 = col.row()
- rowsub3.prop(self, "grados", text='Degrees')
- rowsub3.prop(self, "separacion", text='Separation Link Cubes')
+ rowsub0.prop(self, "hidecubes", text="Hide Link Cubes")
+
+ rowsub1 = col.row(align=True)
+ rowsub1.prop(self, "ropelenght2", text="Length")
+ rowsub1.prop(self, "ropesegments2", text="Segments")
+
+ rowsub2 = col.row(align=True)
+ rowsub2.prop(self, "radiuscubes", text="Radius Link Cubes")
+ rowsub2.prop(self, "radiusrope", text="Radius Rope")
+
+ rowsub3 = col.row(align=True)
+ rowsub3.prop(self, "grados", text="Degrees")
+ rowsub3.prop(self, "separacion", text="Separation Link Cubes")
col.label("Quality Settings:")
- col.prop(self, "resrope", text='Resolution Rope')
- col.prop(self, "massball", text='Ball Mass')
- col.prop(self, "worldsteps", text='World Steps')
- col.prop(self, "solveriterations", text='Solver Iterarions')
+ col.prop(self, "resrope", text="Resolution Rope")
+ col.prop(self, "massball", text="Ball Mass")
+ col.prop(self, "worldsteps", text="World Steps")
+ col.prop(self, "solveriterations", text="Solver Iterarions")
# Register
diff --git a/add_advanced_objects/scene_objects_bi.py b/add_advanced_objects/scene_objects_bi.py
index db3ec9cd..f189bb11 100644
--- a/add_advanced_objects/scene_objects_bi.py
+++ b/add_advanced_objects/scene_objects_bi.py
@@ -7,179 +7,189 @@ from bpy.types import Operator
class add_BI_scene(Operator):
bl_idname = "bi.add_scene"
bl_label = "Create test scene"
- bl_description = "BI Scene with Objects"
+ bl_description = "Blender Internal renderer Scene with Objects"
bl_options = {'REGISTER', 'UNDO'}
def execute(self, context):
- blend_data = context.blend_data
- # ob = bpy.context.active_object
-
- # add new scene
- bpy.ops.scene.new(type="NEW")
- scene = bpy.context.scene
- scene.name = "scene_materials"
-
- # render settings
- render = scene.render
- render.resolution_x = 1920
- render.resolution_y = 1080
- render.resolution_percentage = 50
-
- # add new world
- world = bpy.data.worlds.new("Materials_World")
- scene.world = world
- world.use_sky_blend = True
- world.use_sky_paper = True
- world.horizon_color = (0.004393, 0.02121, 0.050)
- world.zenith_color = (0.03335, 0.227, 0.359)
- world.light_settings.use_ambient_occlusion = True
- world.light_settings.ao_factor = 0.25
-
- # add camera
- bpy.ops.object.camera_add(
+ try:
+ blend_data = context.blend_data
+ # ob = bpy.context.active_object
+
+ # add new scene
+ bpy.ops.scene.new(type="NEW")
+ scene = bpy.context.scene
+ scene.name = "scene_materials"
+
+ # render settings
+ render = scene.render
+ render.resolution_x = 1920
+ render.resolution_y = 1080
+ render.resolution_percentage = 50
+
+ # add new world
+ world = bpy.data.worlds.new("Materials_World")
+ scene.world = world
+ world.use_sky_blend = True
+ world.use_sky_paper = True
+ world.horizon_color = (0.004393, 0.02121, 0.050)
+ world.zenith_color = (0.03335, 0.227, 0.359)
+ world.light_settings.use_ambient_occlusion = True
+ world.light_settings.ao_factor = 0.25
+
+ # add camera
+ bpy.ops.object.camera_add(
location=(7.48113, -6.50764, 5.34367),
rotation=(1.109319, 0.010817, 0.814928)
)
- cam = bpy.context.active_object.data
- cam.lens = 35
- cam.draw_size = 0.1
- bpy.ops.view3d.viewnumpad(type='CAMERA')
+ cam = bpy.context.active_object.data
+ cam.lens = 35
+ cam.draw_size = 0.1
+ bpy.ops.view3d.viewnumpad(type='CAMERA')
- # add point lamp
- bpy.ops.object.lamp_add(
+ # add point lamp
+ bpy.ops.object.lamp_add(
type="POINT", location=(4.07625, 1.00545, 5.90386),
rotation=(0.650328, 0.055217, 1.866391)
)
- lamp1 = bpy.context.active_object.data
- lamp1.name = "Point_Right"
- lamp1.energy = 1.0
- lamp1.distance = 30.0
- lamp1.shadow_method = "RAY_SHADOW"
- lamp1.use_sphere = True
-
- # add point lamp2
- bpy.ops.object.lamp_add(
+ lamp1 = bpy.context.active_object.data
+ lamp1.name = "Point_Right"
+ lamp1.energy = 1.0
+ lamp1.distance = 30.0
+ lamp1.shadow_method = "RAY_SHADOW"
+ lamp1.use_sphere = True
+
+ # add point lamp2
+ bpy.ops.object.lamp_add(
type="POINT", location=(-0.57101, -4.24586, 5.53674),
rotation=(1.571, 0, 0.785)
)
- lamp2 = bpy.context.active_object.data
- lamp2.name = "Point_Left"
- lamp2.energy = 1.0
- lamp2.distance = 30.0
-
- # Add cube
- bpy.ops.mesh.primitive_cube_add()
- bpy.ops.object.editmode_toggle()
- bpy.ops.mesh.subdivide(number_cuts=2)
- bpy.ops.uv.unwrap(method='CONFORMAL', margin=0.001)
- bpy.ops.object.editmode_toggle()
-
- cube = bpy.context.active_object
- # add new material
- cubeMaterial = blend_data.materials.new("Cube_Material")
- bpy.ops.object.material_slot_add()
- cube.material_slots[0].material = cubeMaterial
- # Diffuse
- cubeMaterial.preview_render_type = "CUBE"
- cubeMaterial.diffuse_color = (1.000, 0.373, 0.00)
- cubeMaterial.diffuse_shader = 'OREN_NAYAR'
- cubeMaterial.diffuse_intensity = 1.0
- cubeMaterial.roughness = 0.09002
- # Specular
- cubeMaterial.specular_color = (1.000, 0.800, 0.136)
- cubeMaterial.specular_shader = "PHONG"
- cubeMaterial.specular_intensity = 1.0
- cubeMaterial.specular_hardness = 511.0
- # Shading
- cubeMaterial.ambient = 1.00
- cubeMaterial.use_cubic = False
- # Transparency
- cubeMaterial.use_transparency = False
- cubeMaterial.alpha = 0
- # Mirror
- cubeMaterial.raytrace_mirror.use = True
- cubeMaterial.mirror_color = (1.000, 0.793, 0.0)
- cubeMaterial.raytrace_mirror.reflect_factor = 0.394
- cubeMaterial.raytrace_mirror.fresnel = 2.0
- cubeMaterial.raytrace_mirror.fresnel_factor = 1.641
- cubeMaterial.raytrace_mirror.fade_to = "FADE_TO_SKY"
- cubeMaterial.raytrace_mirror.gloss_anisotropic = 1.0
- # Shadow
- cubeMaterial.use_transparent_shadows = True
-
- # Add a texture
- cubetex = blend_data.textures.new("CloudTex", type='CLOUDS')
- cubetex.noise_type = 'SOFT_NOISE'
- cubetex.noise_scale = 0.25
- mtex = cubeMaterial.texture_slots.add()
- mtex.texture = cubetex
- mtex.texture_coords = 'ORCO'
- mtex.scale = (0.800, 0.800, 0.800)
- mtex.use_map_mirror = True
- mtex.mirror_factor = 0.156
- mtex.use_map_color_diffuse = True
- mtex.diffuse_color_factor = 0.156
- mtex.use_map_normal = True
- mtex.normal_factor = 0.010
- mtex.blend_type = "ADD"
- mtex.use_rgb_to_intensity = True
- mtex.color = (1.000, 0.207, 0.000)
-
- # Add monkey
- bpy.ops.mesh.primitive_monkey_add(location=(-0.1, 0.08901, 1.505))
- bpy.ops.transform.rotate(value=(1.15019), axis=(0, 0, 1))
- bpy.ops.transform.rotate(value=(-0.673882), axis=(0, 1, 0))
- bpy.ops.transform.rotate(value=-0.055, axis=(1, 0, 0))
- bpy.ops.object.modifier_add(type='SUBSURF')
- bpy.ops.object.shade_smooth()
- monkey = bpy.context.active_object
- # add new material
- monkeyMaterial = blend_data.materials.new("Monkey_Material")
- bpy.ops.object.material_slot_add()
- monkey.material_slots[0].material = monkeyMaterial
- # Material settings
- monkeyMaterial.preview_render_type = "MONKEY"
- monkeyMaterial.diffuse_color = (0.239, 0.288, 0.288)
- monkeyMaterial.specular_color = (0.604, 0.465, 0.136)
- monkeyMaterial.diffuse_shader = 'LAMBERT'
- monkeyMaterial.diffuse_intensity = 1.0
- monkeyMaterial.specular_intensity = 0.3
- monkeyMaterial.ambient = 0
- monkeyMaterial.type = 'SURFACE'
- monkeyMaterial.use_cubic = True
- monkeyMaterial.use_transparency = False
- monkeyMaterial.alpha = 0
- monkeyMaterial.use_transparent_shadows = True
- monkeyMaterial.raytrace_mirror.use = True
- monkeyMaterial.raytrace_mirror.reflect_factor = 0.65
- monkeyMaterial.raytrace_mirror.fade_to = "FADE_TO_MATERIAL"
-
- # Add plane
- bpy.ops.mesh.primitive_plane_add(
- radius=50, view_align=False, enter_editmode=False, location=(0, 0, -1)
- )
- bpy.ops.object.editmode_toggle()
- bpy.ops.transform.rotate(
- value=-0.8, axis=(0, 0, 1), constraint_axis=(False, False, True),
- constraint_orientation='GLOBAL', mirror=False, proportional='DISABLED',
- proportional_edit_falloff='SMOOTH', proportional_size=1
- )
- bpy.ops.uv.unwrap(method='CONFORMAL', margin=0.001)
- bpy.ops.object.editmode_toggle()
- plane = bpy.context.active_object
- # add new material
- planeMaterial = blend_data.materials.new("Plane_Material")
- bpy.ops.object.material_slot_add()
- plane.material_slots[0].material = planeMaterial
- # Material settings
- planeMaterial.preview_render_type = "CUBE"
- planeMaterial.diffuse_color = (0.2, 0.2, 0.2)
- planeMaterial.specular_color = (0.604, 0.465, 0.136)
- planeMaterial.specular_intensity = 0.3
- planeMaterial.ambient = 0
- planeMaterial.use_cubic = True
- planeMaterial.use_transparency = False
- planeMaterial.alpha = 0
- planeMaterial.use_transparent_shadows = True
+ lamp2 = bpy.context.active_object.data
+ lamp2.name = "Point_Left"
+ lamp2.energy = 1.0
+ lamp2.distance = 30.0
+
+ # Add cube
+ bpy.ops.mesh.primitive_cube_add()
+ bpy.ops.object.editmode_toggle()
+ bpy.ops.mesh.subdivide(number_cuts=2)
+ bpy.ops.uv.unwrap(method='CONFORMAL', margin=0.001)
+ bpy.ops.object.editmode_toggle()
+
+ cube = bpy.context.active_object
+ # add new material
+ cubeMaterial = blend_data.materials.new("Cube_Material")
+ bpy.ops.object.material_slot_add()
+ cube.material_slots[0].material = cubeMaterial
+ # Diffuse
+ cubeMaterial.preview_render_type = "CUBE"
+ cubeMaterial.diffuse_color = (1.000, 0.373, 0.00)
+ cubeMaterial.diffuse_shader = 'OREN_NAYAR'
+ cubeMaterial.diffuse_intensity = 1.0
+ cubeMaterial.roughness = 0.09002
+ # Specular
+ cubeMaterial.specular_color = (1.000, 0.800, 0.136)
+ cubeMaterial.specular_shader = "PHONG"
+ cubeMaterial.specular_intensity = 1.0
+ cubeMaterial.specular_hardness = 511.0
+ # Shading
+ cubeMaterial.ambient = 1.00
+ cubeMaterial.use_cubic = False
+ # Transparency
+ cubeMaterial.use_transparency = False
+ cubeMaterial.alpha = 0
+ # Mirror
+ cubeMaterial.raytrace_mirror.use = True
+ cubeMaterial.mirror_color = (1.000, 0.793, 0.0)
+ cubeMaterial.raytrace_mirror.reflect_factor = 0.394
+ cubeMaterial.raytrace_mirror.fresnel = 2.0
+ cubeMaterial.raytrace_mirror.fresnel_factor = 1.641
+ cubeMaterial.raytrace_mirror.fade_to = "FADE_TO_SKY"
+ cubeMaterial.raytrace_mirror.gloss_anisotropic = 1.0
+ # Shadow
+ cubeMaterial.use_transparent_shadows = True
+
+ # Add a texture
+ cubetex = blend_data.textures.new("CloudTex", type='CLOUDS')
+ cubetex.noise_type = 'SOFT_NOISE'
+ cubetex.noise_scale = 0.25
+ mtex = cubeMaterial.texture_slots.add()
+ mtex.texture = cubetex
+ mtex.texture_coords = 'ORCO'
+ mtex.scale = (0.800, 0.800, 0.800)
+ mtex.use_map_mirror = True
+ mtex.mirror_factor = 0.156
+ mtex.use_map_color_diffuse = True
+ mtex.diffuse_color_factor = 0.156
+ mtex.use_map_normal = True
+ mtex.normal_factor = 0.010
+ mtex.blend_type = "ADD"
+ mtex.use_rgb_to_intensity = True
+ mtex.color = (1.000, 0.207, 0.000)
+
+ # Add monkey
+ bpy.ops.mesh.primitive_monkey_add(location=(-0.1, 0.08901, 1.505))
+ bpy.ops.transform.rotate(value=(1.15019), axis=(0, 0, 1))
+ bpy.ops.transform.rotate(value=(-0.673882), axis=(0, 1, 0))
+ bpy.ops.transform.rotate(value=-0.055, axis=(1, 0, 0))
+ bpy.ops.object.modifier_add(type='SUBSURF')
+ bpy.ops.object.shade_smooth()
+ monkey = bpy.context.active_object
+ # add new material
+ monkeyMaterial = blend_data.materials.new("Monkey_Material")
+ bpy.ops.object.material_slot_add()
+ monkey.material_slots[0].material = monkeyMaterial
+ # Material settings
+ monkeyMaterial.preview_render_type = "MONKEY"
+ monkeyMaterial.diffuse_color = (0.239, 0.288, 0.288)
+ monkeyMaterial.specular_color = (0.604, 0.465, 0.136)
+ monkeyMaterial.diffuse_shader = 'LAMBERT'
+ monkeyMaterial.diffuse_intensity = 1.0
+ monkeyMaterial.specular_intensity = 0.3
+ monkeyMaterial.ambient = 0
+ monkeyMaterial.type = 'SURFACE'
+ monkeyMaterial.use_cubic = True
+ monkeyMaterial.use_transparency = False
+ monkeyMaterial.alpha = 0
+ monkeyMaterial.use_transparent_shadows = True
+ monkeyMaterial.raytrace_mirror.use = True
+ monkeyMaterial.raytrace_mirror.reflect_factor = 0.65
+ monkeyMaterial.raytrace_mirror.fade_to = "FADE_TO_MATERIAL"
+
+ # Add plane
+ bpy.ops.mesh.primitive_plane_add(
+ radius=50, view_align=False, enter_editmode=False, location=(0, 0, -1)
+ )
+ bpy.ops.object.editmode_toggle()
+ bpy.ops.transform.rotate(
+ value=-0.8, axis=(0, 0, 1), constraint_axis=(False, False, True),
+ constraint_orientation='GLOBAL', mirror=False, proportional='DISABLED',
+ proportional_edit_falloff='SMOOTH', proportional_size=1
+ )
+ bpy.ops.uv.unwrap(method='CONFORMAL', margin=0.001)
+ bpy.ops.object.editmode_toggle()
+ plane = bpy.context.active_object
+ # add new material
+ planeMaterial = blend_data.materials.new("Plane_Material")
+ bpy.ops.object.material_slot_add()
+ plane.material_slots[0].material = planeMaterial
+ # Material settings
+ planeMaterial.preview_render_type = "CUBE"
+ planeMaterial.diffuse_color = (0.2, 0.2, 0.2)
+ planeMaterial.specular_color = (0.604, 0.465, 0.136)
+ planeMaterial.specular_intensity = 0.3
+ planeMaterial.ambient = 0
+ planeMaterial.use_cubic = True
+ planeMaterial.use_transparency = False
+ planeMaterial.alpha = 0
+ planeMaterial.use_transparent_shadows = True
+
+ except Exception as e:
+ self.report({'WARNING'},
+ "Some operations could not be performed (See Console for more info)")
+
+ print("\n[Add Advanced Objects]\nOperator: "
+ "bi.add_scene\nError: {}".format(e))
+
+ return {'CANCELLED'}
return {"FINISHED"}
diff --git a/add_advanced_objects/scene_objects_cycles.py b/add_advanced_objects/scene_objects_cycles.py
index 1e07b3e5..85e85867 100644
--- a/add_advanced_objects/scene_objects_cycles.py
+++ b/add_advanced_objects/scene_objects_cycles.py
@@ -7,124 +7,136 @@ from bpy.types import Operator
class add_cycles_scene(Operator):
bl_idname = "objects_cycles.add_scene"
bl_label = "Create test scene"
- bl_description = "Cycles Scene with Objects"
+ bl_description = "Cycles renderer Scene with Objects"
bl_options = {'REGISTER'}
def execute(self, context):
- blend_data = context.blend_data
- # ob = bpy.context.active_object
-
- # add new scene
- bpy.ops.scene.new(type="NEW")
- scene = bpy.context.scene
- bpy.context.scene.render.engine = 'CYCLES'
- scene.name = "scene_object_cycles"
-
- # render settings
- render = scene.render
- render.resolution_x = 1920
- render.resolution_y = 1080
- render.resolution_percentage = 50
-
- # add new world
- world = bpy.data.worlds.new("Cycles_Object_World")
- scene.world = world
- world.use_sky_blend = True
- world.use_sky_paper = True
- world.horizon_color = (0.004393, 0.02121, 0.050)
- world.zenith_color = (0.03335, 0.227, 0.359)
- world.light_settings.use_ambient_occlusion = True
- world.light_settings.ao_factor = 0.25
-
- # add camera
- bpy.ops.object.camera_add(
- location=(7.48113, -6.50764, 5.34367),
- rotation=(1.109319, 0.010817, 0.814928)
- )
- cam = bpy.context.active_object.data
- cam.lens = 35
- cam.draw_size = 0.1
- bpy.ops.view3d.viewnumpad(type='CAMERA')
-
- # add point lamp
- bpy.ops.object.lamp_add(
- type="POINT", location=(4.07625, 1.00545, 5.90386),
- rotation=(0.650328, 0.055217, 1.866391)
- )
- lamp1 = bpy.context.active_object.data
- lamp1.name = "Point_Right"
- lamp1.energy = 1.0
- lamp1.distance = 30.0
- lamp1.shadow_method = "RAY_SHADOW"
- lamp1.use_sphere = True
-
- # add point lamp2
- bpy.ops.object.lamp_add(
- type="POINT", location=(-0.57101, -4.24586, 5.53674),
- rotation=(1.571, 0, 0.785)
- )
- lamp2 = bpy.context.active_object.data
- lamp2.name = "Point_Left"
- lamp2.energy = 1.0
- lamp2.distance = 30.0
-
- # Add cube
- bpy.ops.mesh.primitive_cube_add()
- bpy.ops.object.editmode_toggle()
- bpy.ops.mesh.subdivide(number_cuts=2)
- bpy.ops.uv.unwrap(method='CONFORMAL', margin=0.001)
- bpy.ops.object.editmode_toggle()
- cube = bpy.context.active_object
-
- # add cube material
- cubeMaterial = blend_data.materials.new("Cycles_Cube_Material")
- bpy.ops.object.material_slot_add()
- cube.material_slots[0].material = cubeMaterial
- # Diffuse
- cubeMaterial.preview_render_type = "CUBE"
- cubeMaterial.diffuse_color = (1.000, 0.373, 0.00)
- # Cycles
- cubeMaterial.use_nodes = True
-
- # Add monkey
- bpy.ops.mesh.primitive_monkey_add(location=(-0.1, 0.08901, 1.505))
- bpy.ops.transform.rotate(value=(1.15019), axis=(0, 0, 1))
- bpy.ops.transform.rotate(value=(-0.673882), axis=(0, 1, 0))
- bpy.ops.transform.rotate(value=-0.055, axis=(1, 0, 0))
-
- bpy.ops.object.modifier_add(type='SUBSURF')
- bpy.ops.object.shade_smooth()
- monkey = bpy.context.active_object
-
- # add monkey material
- monkeyMaterial = blend_data.materials.new("Cycles_Monkey_Material")
- bpy.ops.object.material_slot_add()
- monkey.material_slots[0].material = monkeyMaterial
- # Diffuse
- monkeyMaterial.preview_render_type = "MONKEY"
- monkeyMaterial.diffuse_color = (0.239, 0.288, 0.288)
- # Cycles
- monkeyMaterial.use_nodes = True
-
- # Add plane
- bpy.ops.mesh.primitive_plane_add(
- radius=50, view_align=False,
- enter_editmode=False, location=(0, 0, -1)
- )
- bpy.ops.object.editmode_toggle()
- bpy.ops.transform.rotate(value=-0.8, axis=(0, 0, 1), constraint_axis=(False, False, True))
- bpy.ops.uv.unwrap(method='CONFORMAL', margin=0.001)
- bpy.ops.object.editmode_toggle()
- plane = bpy.context.active_object
-
- # add plane material
- planeMaterial = blend_data.materials.new("Cycles_Plane_Material")
- bpy.ops.object.material_slot_add()
- plane.material_slots[0].material = planeMaterial
- # Diffuse
- planeMaterial.preview_render_type = "FLAT"
- planeMaterial.diffuse_color = (0.2, 0.2, 0.2)
- # Cycles
- planeMaterial.use_nodes = True
+ try:
+ blend_data = context.blend_data
+
+ # add new scene
+ bpy.ops.scene.new(type="NEW")
+ scene = bpy.context.scene
+ bpy.context.scene.render.engine = 'CYCLES'
+ scene.name = "scene_object_cycles"
+
+ # render settings
+ render = scene.render
+ render.resolution_x = 1920
+ render.resolution_y = 1080
+ render.resolution_percentage = 50
+
+ # add new world
+ world = bpy.data.worlds.new("Cycles_Object_World")
+ scene.world = world
+ world.use_sky_blend = True
+ world.use_sky_paper = True
+ world.horizon_color = (0.004393, 0.02121, 0.050)
+ world.zenith_color = (0.03335, 0.227, 0.359)
+ world.light_settings.use_ambient_occlusion = True
+ world.light_settings.ao_factor = 0.25
+
+ # add camera
+ bpy.ops.object.camera_add(
+ location=(7.48113, -6.50764, 5.34367),
+ rotation=(1.109319, 0.010817, 0.814928)
+ )
+ cam = bpy.context.active_object.data
+ cam.lens = 35
+ cam.draw_size = 0.1
+ bpy.ops.view3d.viewnumpad(type='CAMERA')
+
+ # add point lamp
+ bpy.ops.object.lamp_add(
+ type="POINT", location=(4.07625, 1.00545, 5.90386),
+ rotation=(0.650328, 0.055217, 1.866391)
+ )
+ lamp1 = bpy.context.active_object.data
+ lamp1.name = "Point_Right"
+ lamp1.energy = 1.0
+ lamp1.distance = 30.0
+ lamp1.shadow_method = "RAY_SHADOW"
+ lamp1.use_sphere = True
+
+ # add point lamp2
+ bpy.ops.object.lamp_add(
+ type="POINT", location=(-0.57101, -4.24586, 5.53674),
+ rotation=(1.571, 0, 0.785)
+ )
+ lamp2 = bpy.context.active_object.data
+ lamp2.name = "Point_Left"
+ lamp2.energy = 1.0
+ lamp2.distance = 30.0
+
+ # Add cube
+ bpy.ops.mesh.primitive_cube_add()
+ bpy.ops.object.editmode_toggle()
+ bpy.ops.mesh.subdivide(number_cuts=2)
+ bpy.ops.uv.unwrap(method='CONFORMAL', margin=0.001)
+ bpy.ops.object.editmode_toggle()
+ cube = bpy.context.active_object
+
+ # add cube material
+ cubeMaterial = blend_data.materials.new("Cycles_Cube_Material")
+ bpy.ops.object.material_slot_add()
+ cube.material_slots[0].material = cubeMaterial
+ # Diffuse
+ cubeMaterial.preview_render_type = "CUBE"
+ cubeMaterial.diffuse_color = (1.000, 0.373, 0.00)
+ # Cycles
+ cubeMaterial.use_nodes = True
+
+ # Add monkey
+ bpy.ops.mesh.primitive_monkey_add(location=(-0.1, 0.08901, 1.505))
+ bpy.ops.transform.rotate(value=(1.15019), axis=(0, 0, 1))
+ bpy.ops.transform.rotate(value=(-0.673882), axis=(0, 1, 0))
+ bpy.ops.transform.rotate(value=-0.055, axis=(1, 0, 0))
+
+ bpy.ops.object.modifier_add(type='SUBSURF')
+ bpy.ops.object.shade_smooth()
+ monkey = bpy.context.active_object
+
+ # add monkey material
+ monkeyMaterial = blend_data.materials.new("Cycles_Monkey_Material")
+ bpy.ops.object.material_slot_add()
+ monkey.material_slots[0].material = monkeyMaterial
+ # Diffuse
+ monkeyMaterial.preview_render_type = "MONKEY"
+ monkeyMaterial.diffuse_color = (0.239, 0.288, 0.288)
+ # Cycles
+ monkeyMaterial.use_nodes = True
+
+ # Add plane
+ bpy.ops.mesh.primitive_plane_add(
+ radius=50, view_align=False,
+ enter_editmode=False, location=(0, 0, -1)
+ )
+ bpy.ops.object.editmode_toggle()
+ bpy.ops.transform.rotate(
+ value=-0.8, axis=(0, 0, 1),
+ constraint_axis=(False, False, True)
+ )
+ bpy.ops.uv.unwrap(method='CONFORMAL', margin=0.001)
+ bpy.ops.object.editmode_toggle()
+ plane = bpy.context.active_object
+
+ # add plane material
+ planeMaterial = blend_data.materials.new("Cycles_Plane_Material")
+ bpy.ops.object.material_slot_add()
+ plane.material_slots[0].material = planeMaterial
+ # Diffuse
+ planeMaterial.preview_render_type = "FLAT"
+ planeMaterial.diffuse_color = (0.2, 0.2, 0.2)
+ # Cycles
+ planeMaterial.use_nodes = True
+
+ except Exception as e:
+ self.report({'WARNING'},
+ "Some operations could not be performed (See Console for more info)")
+
+ print("\n[Add Advanced Objects]\nOperator: "
+ "objects_cycles.add_scene\nError: {}".format(e))
+
+ return {'CANCELLED'}
return {'FINISHED'}
diff --git a/add_advanced_objects/scene_texture_render.py b/add_advanced_objects/scene_texture_render.py
index 2025b979..02d6490b 100644
--- a/add_advanced_objects/scene_texture_render.py
+++ b/add_advanced_objects/scene_texture_render.py
@@ -7,60 +7,72 @@ from bpy.types import Operator
class add_texture_scene(Operator):
bl_idname = "objects_texture.add_scene"
bl_label = "Create test scene"
- bl_description = "Cycles Scene: Camera aligned to plane"
+ bl_description = "Cycles renderer Scene: Camera aligned to a plane"
bl_options = {'REGISTER', 'UNDO'}
def execute(self, context):
- blend_data = context.blend_data
- # ob = bpy.context.active_object
+ try:
+ blend_data = context.blend_data
- # add new scene
- bpy.ops.scene.new(type="NEW")
- scene = bpy.context.scene
- bpy.context.scene.render.engine = 'CYCLES'
- scene.name = "scene_texture_cycles"
+ # add new scene
+ bpy.ops.scene.new(type="NEW")
+ scene = bpy.context.scene
+ bpy.context.scene.render.engine = 'CYCLES'
+ scene.name = "scene_texture_cycles"
- # render settings
- render = scene.render
- render.resolution_x = 1080
- render.resolution_y = 1080
- render.resolution_percentage = 100
+ # render settings
+ render = scene.render
+ render.resolution_x = 1080
+ render.resolution_y = 1080
+ render.resolution_percentage = 100
- # add new world
- world = bpy.data.worlds.new("Cycles_Textures_World")
- scene.world = world
- world.use_sky_blend = True
- world.use_sky_paper = True
- world.horizon_color = (0.004393, 0.02121, 0.050)
- world.zenith_color = (0.03335, 0.227, 0.359)
- world.light_settings.use_ambient_occlusion = True
- world.light_settings.ao_factor = 0.5
+ # add new world
+ world = bpy.data.worlds.new("Cycles_Textures_World")
+ scene.world = world
+ world.use_sky_blend = True
+ world.use_sky_paper = True
+ world.horizon_color = (0.004393, 0.02121, 0.050)
+ world.zenith_color = (0.03335, 0.227, 0.359)
+ world.light_settings.use_ambient_occlusion = True
+ world.light_settings.ao_factor = 0.5
- # add camera
- bpy.ops.view3d.viewnumpad(type='TOP')
- bpy.ops.object.camera_add(location=(0, 0, 2.1850), rotation=(0, 0, 0), view_align=True)
- cam = bpy.context.active_object.data
- cam.lens = 35
- cam.draw_size = 0.1
+ # add camera
+ bpy.ops.view3d.viewnumpad(type='TOP')
+ bpy.ops.object.camera_add(
+ location=(0, 0, 2.1850), rotation=(0, 0, 0), view_align=True
+ )
+ cam = bpy.context.active_object.data
+ cam.lens = 35
+ cam.draw_size = 0.1
- # add plane
- bpy.ops.mesh.primitive_plane_add(enter_editmode=True, location=(0, 0, 0))
- bpy.ops.mesh.subdivide(number_cuts=10, smoothness=0)
- bpy.ops.uv.unwrap(method='CONFORMAL', margin=0.001)
- bpy.ops.object.editmode_toggle()
- plane = bpy.context.active_object
+ # add plane
+ bpy.ops.mesh.primitive_plane_add(enter_editmode=True, location=(0, 0, 0))
+ bpy.ops.mesh.subdivide(number_cuts=10, smoothness=0)
+ bpy.ops.uv.unwrap(method='CONFORMAL', margin=0.001)
+ bpy.ops.object.editmode_toggle()
+ plane = bpy.context.active_object
- # add plane material
- planeMaterial = blend_data.materials.new("Cycles_Plane_Material")
- bpy.ops.object.material_slot_add()
- plane.material_slots[0].material = planeMaterial
- # Diffuse
- planeMaterial.preview_render_type = "FLAT"
- planeMaterial.diffuse_color = (0.2, 0.2, 0.2)
- # Cycles
- planeMaterial.use_nodes = True
+ # add plane material
+ planeMaterial = blend_data.materials.new("Cycles_Plane_Material")
+ bpy.ops.object.material_slot_add()
+ plane.material_slots[0].material = planeMaterial
+ # Diffuse
+ planeMaterial.preview_render_type = "FLAT"
+ planeMaterial.diffuse_color = (0.2, 0.2, 0.2)
+ # Cycles
+ planeMaterial.use_nodes = True
+
+ # Back to Scene
+ sc = bpy.context.scene
+ bpy.ops.view3d.viewnumpad(type='CAMERA')
+
+ except Exception as e:
+ self.report({'WARNING'},
+ "Some operations could not be performed (See Console for more info)")
+
+ print("\n[Add Advanced Objects]\nOperator: "
+ "objects_texture.add_scene\nError: {}".format(e))
+
+ return {'CANCELLED'}
- # Back to Scene
- sc = bpy.context.scene
- bpy.ops.view3d.viewnumpad(type='CAMERA')
return {'FINISHED'}
diff --git a/add_advanced_objects/trilighting.py b/add_advanced_objects/trilighting.py
index d23b4dbc..e0068e66 100644
--- a/add_advanced_objects/trilighting.py
+++ b/add_advanced_objects/trilighting.py
@@ -8,8 +8,7 @@ from bpy.props import (
IntProperty,
)
from math import (
- sin,
- cos,
+ sin, cos,
radians,
sqrt,
)
@@ -19,67 +18,69 @@ class TriLighting(Operator):
bl_idname = "object.trilighting"
bl_label = "Tri-Lighting Creator"
bl_description = ("Add 3 Point Lighting to Selected / Active Object\n"
- "Needs an active object in the scene")
+ "Needs an existing Active Object")
bl_options = {'REGISTER', 'UNDO'}
height = FloatProperty(
- name="Height",
- default=5
- )
+ name="Height",
+ default=5
+ )
distance = FloatProperty(
- name="Distance",
- default=5,
- min=0.1,
- subtype="DISTANCE"
- )
+ name="Distance",
+ default=5,
+ min=0.1,
+ subtype="DISTANCE"
+ )
energy = IntProperty(
- name="Base Energy",
- default=3,
- min=1
- )
+ name="Base Energy",
+ default=3,
+ min=1
+ )
contrast = IntProperty(
- name="Contrast",
- default=50,
- min=-100, max=100,
- subtype="PERCENTAGE"
- )
+ name="Contrast",
+ default=50,
+ min=-100, max=100,
+ subtype="PERCENTAGE"
+ )
leftangle = IntProperty(
- name="Left Angle",
- default=26,
- min=1, max=90,
- subtype="ANGLE"
- )
+ name="Left Angle",
+ default=26,
+ min=1, max=90,
+ subtype="ANGLE"
+ )
rightangle = IntProperty(
- name="Right Angle",
- default=45,
- min=1, max=90,
- subtype="ANGLE"
- )
+ name="Right Angle",
+ default=45,
+ min=1, max=90,
+ subtype="ANGLE"
+ )
backangle = IntProperty(
- name="Back Angle",
- default=235,
- min=90, max=270,
- subtype="ANGLE"
- )
- Light_Type_List = [('POINT', 'Point', 'Point Light'),
- ('SUN', 'Sun', 'Sun Light'),
- ('SPOT', 'Spot', 'Spot Light'),
- ('HEMI', 'Hemi', 'Hemi Light'),
- ('AREA', 'Area', 'Area Light')]
+ name="Back Angle",
+ default=235,
+ min=90, max=270,
+ subtype="ANGLE"
+ )
+ Light_Type_List = [
+ ('POINT', "Point", "Point Light"),
+ ('SUN', "Sun", "Sun Light"),
+ ('SPOT', "Spot", "Spot Light"),
+ ('HEMI', "Hemi", "Hemi Light"),
+ ('AREA', "Area", "Area Light")
+ ]
primarytype = EnumProperty(
- attr='tl_type',
- name="Key Type",
- description="Choose the type off Key Light you would like",
- items=Light_Type_List,
- default='HEMI'
- )
+ attr='tl_type',
+ name="Key Type",
+ description="Choose the types of Key Lights you would like",
+ items=Light_Type_List,
+ default='HEMI'
+ )
secondarytype = EnumProperty(
- attr='tl_type',
- name="Fill + Back Type",
- description="Choose the type off secondary Light you would like",
- items=Light_Type_List,
- default="POINT"
- )
+ attr='tl_type',
+ name="Fill + Back Type",
+ description="Choose the types of secondary Lights you would like",
+ items=Light_Type_List,
+ default="POINT"
+ )
@classmethod
def poll(cls, context):
@@ -111,115 +112,127 @@ class TriLighting(Operator):
col.prop(self, "secondarytype", text="")
def execute(self, context):
- scene = context.scene
- view = context.space_data
- if view.type == 'VIEW_3D' and not view.lock_camera_and_layers:
- camera = view.camera
- else:
- camera = scene.camera
-
- if (camera is None):
- cam_data = bpy.data.cameras.new(name='Camera')
- cam_obj = bpy.data.objects.new(name='Camera', object_data=cam_data)
- scene.objects.link(cam_obj)
- scene.camera = cam_obj
- bpy.ops.view3d.camera_to_view()
- camera = cam_obj
- bpy.ops.view3d.viewnumpad(type='TOP')
-
- obj = bpy.context.scene.objects.active
-
- # Calculate Energy for each Lamp
- if(self.contrast > 0):
- keyEnergy = self.energy
- backEnergy = (self.energy / 100) * abs(self.contrast)
- fillEnergy = (self.energy / 100) * abs(self.contrast)
- else:
- keyEnergy = (self.energy / 100) * abs(self.contrast)
- backEnergy = self.energy
- fillEnergy = self.energy
-
- # Calculate Direction for each Lamp
-
- # Calculate current Distance and get Delta
- obj_position = obj.location
- cam_position = camera.location
-
- delta_position = cam_position - obj_position
- vector_length = sqrt(
- (pow(delta_position.x, 2) +
- pow(delta_position.y, 2) +
- pow(delta_position.z, 2))
- )
- if not vector_length:
- # division by zero most likely
- self.report({'WARNING'}, "Operation Cancelled. No viable object in the scene")
- return {'CANCELLED'}
+ try:
+ scene = context.scene
+ view = context.space_data
+ if view.type == 'VIEW_3D' and not view.lock_camera_and_layers:
+ camera = view.camera
+ else:
+ camera = scene.camera
+
+ if (camera is None):
+ cam_data = bpy.data.cameras.new(name='Camera')
+ cam_obj = bpy.data.objects.new(name='Camera', object_data=cam_data)
+ scene.objects.link(cam_obj)
+ scene.camera = cam_obj
+ bpy.ops.view3d.camera_to_view()
+ camera = cam_obj
+ bpy.ops.view3d.viewnumpad(type='TOP')
+
+ obj = bpy.context.scene.objects.active
+
+ # Calculate Energy for each Lamp
+ if(self.contrast > 0):
+ keyEnergy = self.energy
+ backEnergy = (self.energy / 100) * abs(self.contrast)
+ fillEnergy = (self.energy / 100) * abs(self.contrast)
+ else:
+ keyEnergy = (self.energy / 100) * abs(self.contrast)
+ backEnergy = self.energy
+ fillEnergy = self.energy
+
+ # Calculate Direction for each Lamp
+
+ # Calculate current Distance and get Delta
+ obj_position = obj.location
+ cam_position = camera.location
+
+ delta_position = cam_position - obj_position
+ vector_length = sqrt(
+ (pow(delta_position.x, 2) +
+ pow(delta_position.y, 2) +
+ pow(delta_position.z, 2))
+ )
+ if not vector_length:
+ # division by zero most likely
+ self.report({'WARNING'},
+ "Operation Cancelled. No viable object in the scene")
+
+ return {'CANCELLED'}
+
+ single_vector = (1 / vector_length) * delta_position
+
+ # Calc back position
+ singleback_vector = single_vector.copy()
+ singleback_vector.x = cos(radians(self.backangle)) * single_vector.x + \
+ (-sin(radians(self.backangle)) * single_vector.y)
+
+ singleback_vector.y = sin(radians(self.backangle)) * single_vector.x + \
+ (cos(radians(self.backangle)) * single_vector.y)
+
+ backx = obj_position.x + self.distance * singleback_vector.x
+ backy = obj_position.y + self.distance * singleback_vector.y
+
+ backData = bpy.data.lamps.new(name="TriLamp-Back", type=self.secondarytype)
+ backData.energy = backEnergy
+
+ backLamp = bpy.data.objects.new(name="TriLamp-Back", object_data=backData)
+ scene.objects.link(backLamp)
+ backLamp.location = (backx, backy, self.height)
+
+ trackToBack = backLamp.constraints.new(type="TRACK_TO")
+ trackToBack.target = obj
+ trackToBack.track_axis = "TRACK_NEGATIVE_Z"
+ trackToBack.up_axis = "UP_Y"
+
+ # Calc right position
+ singleright_vector = single_vector.copy()
+ singleright_vector.x = cos(radians(self.rightangle)) * single_vector.x + \
+ (-sin(radians(self.rightangle)) * single_vector.y)
+
+ singleright_vector.y = sin(radians(self.rightangle)) * single_vector.x + \
+ (cos(radians(self.rightangle)) * single_vector.y)
+
+ rightx = obj_position.x + self.distance * singleright_vector.x
+ righty = obj_position.y + self.distance * singleright_vector.y
+
+ rightData = bpy.data.lamps.new(name="TriLamp-Fill", type=self.secondarytype)
+ rightData.energy = fillEnergy
+ rightLamp = bpy.data.objects.new(name="TriLamp-Fill", object_data=rightData)
+ scene.objects.link(rightLamp)
+ rightLamp.location = (rightx, righty, self.height)
+ trackToRight = rightLamp.constraints.new(type="TRACK_TO")
+ trackToRight.target = obj
+ trackToRight.track_axis = "TRACK_NEGATIVE_Z"
+ trackToRight.up_axis = "UP_Y"
+
+ # Calc left position
+ singleleft_vector = single_vector.copy()
+ singleleft_vector.x = cos(radians(-self.leftangle)) * single_vector.x + \
+ (-sin(radians(-self.leftangle)) * single_vector.y)
+ singleleft_vector.y = sin(radians(-self.leftangle)) * single_vector.x + \
+ (cos(radians(-self.leftangle)) * single_vector.y)
+ leftx = obj_position.x + self.distance * singleleft_vector.x
+ lefty = obj_position.y + self.distance * singleleft_vector.y
+
+ leftData = bpy.data.lamps.new(name="TriLamp-Key", type=self.primarytype)
+ leftData.energy = keyEnergy
+
+ leftLamp = bpy.data.objects.new(name="TriLamp-Key", object_data=leftData)
+ scene.objects.link(leftLamp)
+ leftLamp.location = (leftx, lefty, self.height)
+ trackToLeft = leftLamp.constraints.new(type="TRACK_TO")
+ trackToLeft.target = obj
+ trackToLeft.track_axis = "TRACK_NEGATIVE_Z"
+ trackToLeft.up_axis = "UP_Y"
+
+ except Exception as e:
+ self.report({'WARNING'},
+ "Some operations could not be performed (See Console for more info)")
+
+ print("\n[Add Advanced Objects]\nOperator: "
+ "object.trilighting\nError: {}".format(e))
- single_vector = (1 / vector_length) * delta_position
-
- # Calc back position
- singleback_vector = single_vector.copy()
- singleback_vector.x = cos(radians(self.backangle)) * single_vector.x + \
- (-sin(radians(self.backangle)) * single_vector.y)
-
- singleback_vector.y = sin(radians(self.backangle)) * single_vector.x + \
- (cos(radians(self.backangle)) * single_vector.y)
-
- backx = obj_position.x + self.distance * singleback_vector.x
- backy = obj_position.y + self.distance * singleback_vector.y
-
- backData = bpy.data.lamps.new(name="TriLamp-Back", type=self.secondarytype)
- backData.energy = backEnergy
-
- backLamp = bpy.data.objects.new(name="TriLamp-Back", object_data=backData)
- scene.objects.link(backLamp)
- backLamp.location = (backx, backy, self.height)
-
- trackToBack = backLamp.constraints.new(type="TRACK_TO")
- trackToBack.target = obj
- trackToBack.track_axis = "TRACK_NEGATIVE_Z"
- trackToBack.up_axis = "UP_Y"
-
- # Calc right position
- singleright_vector = single_vector.copy()
- singleright_vector.x = cos(radians(self.rightangle)) * single_vector.x + \
- (-sin(radians(self.rightangle)) * single_vector.y)
-
- singleright_vector.y = sin(radians(self.rightangle)) * single_vector.x + \
- (cos(radians(self.rightangle)) * single_vector.y)
-
- rightx = obj_position.x + self.distance * singleright_vector.x
- righty = obj_position.y + self.distance * singleright_vector.y
-
- rightData = bpy.data.lamps.new(name="TriLamp-Fill", type=self.secondarytype)
- rightData.energy = fillEnergy
- rightLamp = bpy.data.objects.new(name="TriLamp-Fill", object_data=rightData)
- scene.objects.link(rightLamp)
- rightLamp.location = (rightx, righty, self.height)
- trackToRight = rightLamp.constraints.new(type="TRACK_TO")
- trackToRight.target = obj
- trackToRight.track_axis = "TRACK_NEGATIVE_Z"
- trackToRight.up_axis = "UP_Y"
-
- # Calc left position
- singleleft_vector = single_vector.copy()
- singleleft_vector.x = cos(radians(-self.leftangle)) * single_vector.x + \
- (-sin(radians(-self.leftangle)) * single_vector.y)
- singleleft_vector.y = sin(radians(-self.leftangle)) * single_vector.x + \
- (cos(radians(-self.leftangle)) * single_vector.y)
- leftx = obj_position.x + self.distance * singleleft_vector.x
- lefty = obj_position.y + self.distance * singleleft_vector.y
-
- leftData = bpy.data.lamps.new(name="TriLamp-Key", type=self.primarytype)
- leftData.energy = keyEnergy
-
- leftLamp = bpy.data.objects.new(name="TriLamp-Key", object_data=leftData)
- scene.objects.link(leftLamp)
- leftLamp.location = (leftx, lefty, self.height)
- trackToLeft = leftLamp.constraints.new(type="TRACK_TO")
- trackToLeft.target = obj
- trackToLeft.track_axis = "TRACK_NEGATIVE_Z"
- trackToLeft.up_axis = "UP_Y"
+ return {'CANCELLED'}
return {'FINISHED'}
diff --git a/add_advanced_objects/unfold_transition.py b/add_advanced_objects/unfold_transition.py
index a621ca54..769386f5 100644
--- a/add_advanced_objects/unfold_transition.py
+++ b/add_advanced_objects/unfold_transition.py
@@ -1,18 +1,18 @@
+# gpl: authors Liero, Atom
+
bl_info = {
"name": "Unfold transition",
- "version": (0, 1, 0),
+ "author": "Liero, Atom",
+ "version": (0, 1, 2),
"location": "Tool bar > Animation tab > UnFold Transition",
- "description": "Simple unfold transition / animation, will separate faces and set up an armature",
+ "description": "Simple unfold transition / animation, will "
+ "separate faces and set up an armature",
"category": "Animation"}
+# Note the properties are moved to __init__
+# search for patterns advanced_objects, adv_obj
+
import bpy
-from bpy.props import (
- BoolProperty,
- EnumProperty,
- FloatProperty,
- IntProperty,
- # PointerProperty,
- )
from bpy.types import (
Operator,
Panel,
@@ -25,87 +25,22 @@ from mathutils import Vector
from mathutils.geometry import intersect_point_line
-bpy.types.WindowManager.modo = EnumProperty(
- name="",
- items=[("cursor", "3D Cursor", "Use the Distance to 3D Cursor"),
- ("weight", "Weight Map", "Use a Painted Weight map"),
- ("index", "Mesh Indices", "Use Faces and Vertices index")],
- description="How to Sort Bones for animation", default="cursor"
- )
-bpy.types.WindowManager.flip = BoolProperty(
- name="Flipping Faces",
- default=False,
- description="Rotate faces around the Center & skip Scaling - "
- "keep checked for both operators"
- )
-bpy.types.WindowManager.fold_duration = IntProperty(
- name="Total Time",
- min=5, soft_min=25,
- max=10000, soft_max=2500,
- default=200,
- description="Total animation length"
- )
-bpy.types.WindowManager.sca_time = IntProperty(
- name="Scale Time",
- min=1,
- max=5000, soft_max=500,
- default=10,
- description="Faces scaling time"
- )
-bpy.types.WindowManager.rot_time = IntProperty(
- name="Rotation Time",
- min=1, soft_min=5,
- max=5000, soft_max=500,
- default=15,
- description="Faces rotation time"
- )
-bpy.types.WindowManager.rot_max = IntProperty(
- name="Angle",
- min=-180,
- max=180,
- default=135,
- description="Faces rotation angle"
- )
-bpy.types.WindowManager.fold_noise = IntProperty(
- name="Noise",
- min=0,
- max=500, soft_max=50,
- default=0,
- description="Offset some faces animation"
- )
-bpy.types.WindowManager.bounce = FloatProperty(
- name="Bounce",
- min=0,
- max=10, soft_max=2.5,
- default=0,
- description="Add some bounce to rotation"
- )
-bpy.types.WindowManager.from_point = BoolProperty(
- name="Point",
- default=False,
- description="Scale faces from a Point instead of from an Edge"
- )
-bpy.types.WindowManager.wiggle_rot = BoolProperty(
- name="Wiggle",
- default=False,
- description="Use all Axis + Random Rotation instead of X Aligned"
- )
-
-
class Set_Up_Fold(Operator):
bl_idname = "object.set_up_fold"
bl_label = "Set Up Unfold"
- bl_description = "Set up Faces and Bones for animation"
+ bl_description = ("Set up Faces and Bones for animation\n"
+ "Needs an existing Active Mesh Object")
bl_options = {"REGISTER", "UNDO"}
@classmethod
def poll(cls, context):
- return (bpy.context.object.type == "MESH")
+ obj = context.active_object
+ return (obj is not None and obj.type == "MESH")
def execute(self, context):
bpy.ops.object.mode_set()
- wm = context.window_manager
scn = bpy.context.scene
+ adv_obj = scn.advanced_objects
obj = bpy.context.object
dat = obj.data
fac = dat.polygons
@@ -118,6 +53,7 @@ class Set_Up_Fold(Operator):
old_vg = [vg for vg in obj.vertex_groups if vg.name.startswith("bone.")]
for vg in old_vg:
obj.vertex_groups.remove(vg)
+
if "UnFold" in obj.modifiers:
arm = obj.modifiers["UnFold"].object
rig = arm.data
@@ -130,7 +66,7 @@ class Set_Up_Fold(Operator):
obj.modifiers.remove(obj.modifiers["UnFold"])
# try to obtain the face sequence from the vertex weights
- if wm.modo == "weight":
+ if adv_obj.unfold_modo == "weight":
if len(obj.vertex_groups):
i = obj.vertex_groups.active.index
W = []
@@ -154,6 +90,7 @@ class Set_Up_Fold(Operator):
S = [x[1:] for x in W]
else:
self.report({"INFO"}, "First paint a Weight Map for this object")
+
return {"FINISHED"}
# separate the faces and sort them
@@ -161,14 +98,17 @@ class Set_Up_Fold(Operator):
bpy.ops.mesh.select_all(action="SELECT")
bpy.ops.mesh.edge_split()
bpy.ops.mesh.select_all(action="SELECT")
- if wm.modo == "cursor":
+
+ if adv_obj.unfold_modo == "cursor":
bpy.context.tool_settings.mesh_select_mode = [True, True, True]
- bpy.ops.mesh.sort_elements(type="CURSOR_DISTANCE", elements={"VERT", "EDGE", "FACE"})
+ bpy.ops.mesh.sort_elements(
+ type="CURSOR_DISTANCE", elements={"VERT", "EDGE", "FACE"}
+ )
bpy.context.tool_settings.mesh_select_mode = [False, False, True]
bpy.ops.object.mode_set()
# Get sequence of faces and edges from the face / vertex indices
- if wm.modo != "weight":
+ if adv_obj.unfold_modo != "weight":
S = []
for f in fac:
E = list(f.edge_keys)
@@ -183,6 +123,9 @@ class Set_Up_Fold(Operator):
# create the armature and the modifier
arm = bpy.data.armatures.new("arm")
rig = bpy.data.objects.new("rig_" + obj.name, arm)
+
+ # store the name for checking the right rig
+ adv_obj.unfold_arm_name = rig.name
rig.matrix_world = obj.matrix_world
scn.objects.link(rig)
scn.objects.active = rig
@@ -203,10 +146,11 @@ class Set_Up_Fold(Operator):
for fb in S:
f = fac[fb[0]]
b = arm.edit_bones.new("bone.000")
- if wm.flip:
+ if adv_obj.unfold_flip:
b.tail, b.head = fb[2], fb[1]
else:
b.tail, b.head = fb[1], fb[2]
+
b.align_roll(f.normal)
b.select = False
b.layers = vis
@@ -215,7 +159,8 @@ class Set_Up_Fold(Operator):
vg.add(f.vertices, 1, "ADD")
bpy.ops.object.mode_set()
- if wm.modo == "weight":
+
+ if adv_obj.unfold_modo == "weight":
obj.vertex_groups.active_index = 0
scn.objects.active = rig
obj.select = False
@@ -226,66 +171,120 @@ class Set_Up_Fold(Operator):
class Animate_Fold(Operator):
bl_idname = "object.animate_fold"
bl_label = "Animate Unfold"
- bl_description = "Animate bones to simulate unfold... Starts on current frame"
+ bl_description = ("Animate bones to simulate unfold. Starts on current frame\n"
+ "Needs an existing Active Armature Object created in the previous step")
bl_options = {"REGISTER", "UNDO"}
+ is_not_undo = False
+
@classmethod
def poll(cls, context):
+ obj = context.active_object
+ return (obj is not None and obj.type == "ARMATURE" and obj.is_visible(bpy.context.scene))
+
+ def draw(self, context):
+ layout = self.layout
+ adv_obj = context.scene.advanced_objects
+
+ if self.is_not_undo is True:
+ layout.label(text="Warning:", icon="INFO")
+ layout.label(text="The generated Armature was not selected or it was renamed")
+ layout.label(text="The animation can fail if it is not generated by the previous step")
+ layout.separator()
+ layout.label(text="Expected Armature name:", icon="BONE_DATA")
+ layout.label(text=str(adv_obj.unfold_arm_name), icon="TRIA_RIGHT")
+ layout.label(text="To Continue press OK, to Cancel click Outside the Pop-up")
+ layout.separator()
+ else:
+ return
+
+ def invoke(self, context, event):
obj = bpy.context.object
- return (obj.type == "ARMATURE" and obj.is_visible(bpy.context.scene))
+ scn = bpy.context.scene
+ adv_obj = scn.advanced_objects
+
+ if obj.name != adv_obj.unfold_arm_name:
+ self.is_not_undo = True
+ return context.window_manager.invoke_props_dialog(self, width=400)
+ else:
+ return self.execute(context)
def execute(self, context):
obj = bpy.context.object
scn = bpy.context.scene
+ adv_obj = scn.advanced_objects
fra = scn.frame_current
- wm = context.window_manager
-
+ if obj.name != adv_obj.unfold_arm_name:
+ self.report({"INFO"},
+ "The generated rig was not selected or renamed. The animation can fail")
# clear the animation and get the list of bones
if obj.animation_data:
obj.animation_data_clear()
bpy.ops.object.mode_set(mode="POSE")
bones = obj.pose.bones[0].children_recursive
- if wm.flip:
+
+ if adv_obj.unfold_flip:
rot = -3.141592
else:
- rot = wm.rot_max / 57.3
- extra = wm.rot_time * wm.bounce
- ruido = max(wm.rot_time + extra, wm.sca_time) + wm.fold_noise
- vel = (wm.fold_duration - ruido) / len(bones)
+ rot = adv_obj.unfold_rot_max / 57.3
+
+ extra = adv_obj.unfold_rot_time * adv_obj.unfold_bounce
+ ruido = max(adv_obj.unfold_rot_time + extra,
+ adv_obj.unfold_sca_time) + adv_obj.unfold_fold_noise
+
+ len_bones = len(bones) if len(bones) != 0 else 1 # possible division by zero
+ vel = (adv_obj.unfold_fold_duration - ruido) / len_bones
# introduce scale and rotation keyframes
for a, b in enumerate(bones):
- t = fra + a * vel + randint(0, wm.fold_noise)
- if wm.flip:
+ t = fra + a * vel + randint(0, adv_obj.unfold_fold_noise)
+
+ if adv_obj.unfold_flip:
b.scale = (1, 1, 1)
- elif wm.from_point:
+ elif adv_obj.unfold_from_point:
b.scale = (0, 0, 0)
else:
b.scale = (1, 0, 0)
- if not wm.flip:
+
+ if not adv_obj.unfold_flip:
b.keyframe_insert("scale", frame=t)
b.scale = (1, 1, 1)
- b.keyframe_insert("scale", frame=t + wm.sca_time)
- if wm.rot_max:
+ b.keyframe_insert("scale", frame=t + adv_obj.unfold_sca_time)
+
+ if adv_obj.unfold_rot_max:
b.rotation_mode = "XYZ"
- if wm.wiggle_rot:
+ if adv_obj.unfold_wiggle_rot:
euler = (uniform(-rot, rot), uniform(-rot, rot), uniform(-rot, rot))
else:
euler = (rot, 0, 0)
+
b.rotation_euler = euler
b.keyframe_insert("rotation_euler", frame=t)
- if wm.bounce:
- val = wm.bounce * -.10
+
+ if adv_obj.unfold_bounce:
+ val = adv_obj.unfold_bounce * -.10
b.rotation_euler = (val * euler[0], val * euler[1], val * euler[2])
- b.keyframe_insert("rotation_euler", frame=t + wm.rot_time + .25 * extra)
- val = wm.bounce * .05
+ b.keyframe_insert(
+ "rotation_euler", frame=t + adv_obj.unfold_rot_time + .25 * extra
+ )
+
+ val = adv_obj.unfold_bounce * .05
b.rotation_euler = (val * euler[0], val * euler[1], val * euler[2])
- b.keyframe_insert("rotation_euler", frame=t + wm.rot_time + .50 * extra)
- val = wm.bounce * -.025
+ b.keyframe_insert(
+ "rotation_euler", frame=t + adv_obj.unfold_rot_time + .50 * extra
+ )
+
+ val = adv_obj.unfold_bounce * -.025
b.rotation_euler = (val * euler[0], val * euler[1], val * euler[2])
- b.keyframe_insert("rotation_euler", frame=t + wm.rot_time + .75 * extra)
+ b.keyframe_insert(
+ "rotation_euler", frame=t + adv_obj.unfold_rot_time + .75 * extra
+ )
+
b.rotation_euler = (0, 0, 0)
- b.keyframe_insert("rotation_euler", frame=t + wm.rot_time + extra)
+ b.keyframe_insert(
+ "rotation_euler", frame=t + adv_obj.unfold_rot_time + extra
+ )
+ self.is_not_undo = False
return {"FINISHED"}
@@ -299,26 +298,34 @@ class PanelFOLD(Panel):
bl_options = {"DEFAULT_CLOSED"}
def draw(self, context):
- wm = context.window_manager
layout = self.layout
- column = layout.column()
- column.operator("object.set_up_fold", text="1. Set Up Unfold")
- column.prop(wm, "modo")
- column.prop(wm, "flip")
- layout.separator()
- column = layout.column()
- column.operator("object.animate_fold", text="2. Animate Unfold")
- column.prop(wm, "fold_duration")
- column.prop(wm, "sca_time")
- column.prop(wm, "rot_time")
- column.prop(wm, "rot_max")
- row = column.row(align=True)
- row.prop(wm, "fold_noise")
- row.prop(wm, "bounce")
- row = column.row(align=True)
- row.prop(wm, "wiggle_rot")
- if not wm.flip:
- row.prop(wm, "from_point")
+ adv_obj = context.scene.advanced_objects
+
+ box = layout.box()
+ col = box.column()
+ col.operator("object.set_up_fold", text="1. Set Up Unfold")
+ col.separator()
+ col.label("Unfold Mode:")
+ col.prop(adv_obj, "unfold_modo")
+ col.prop(adv_obj, "unfold_flip")
+
+ box = layout.box()
+ col = box.column(align=True)
+ col.operator("object.animate_fold", text="2. Animate Unfold")
+ col.separator()
+ col.prop(adv_obj, "unfold_fold_duration")
+ col.prop(adv_obj, "unfold_sca_time")
+ col.prop(adv_obj, "unfold_rot_time")
+ col.prop(adv_obj, "unfold_rot_max")
+
+ row = col.row(align=True)
+ row.prop(adv_obj, "unfold_fold_noise")
+ row.prop(adv_obj, "unfold_bounce")
+ row = col.row(align=True)
+ row.prop(adv_obj, "unfold_wiggle_rot")
+
+ if not adv_obj.unfold_flip:
+ row.prop(adv_obj, "unfold_from_point")
def register():