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
This commit is contained in:
parent
97bf32a8b8
commit
331f2982d7
|
@ -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__":
|
||||
|
|
|
@ -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.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.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.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.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'
|
||||
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
|
||||
|
||||
except Exception as e:
|
||||
self.report({'WARNING'},
|
||||
"Some operations could not be performed (See Console for more info)")
|
||||
if self.camera_constraint and self.camera is not None and \
|
||||
self.camera.type == "CAMERA":
|
||||
|
||||
print("\n[object.add_light_template]\nError: {}".format(e))
|
||||
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
|
||||
try:
|
||||
objects = context.selected_objects
|
||||
|
||||
if len(objects) == 2:
|
||||
for ob in objects:
|
||||
if ob.type == 'CAMERA':
|
||||
self.camera = ob
|
||||
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'}
|
||||
|
||||
|
|
|
@ -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()
|
||||
register()
|
||||
|
|
|
@ -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__":
|
||||
|
|
|
@ -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__":
|
||||
|
|
|
@ -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
|
||||
from bpy.types import Operator
|
||||
from bpy.props import (
|
||||
BoolProperty,
|
||||
EnumProperty,
|
||||
FloatProperty,
|
||||
)
|
||||
from mathutils import (
|
||||
Vector,
|
||||
Matrix,
|
||||
)
|
||||
|
||||
|
||||
class Copy2(bpy.types.Operator):
|
||||
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')
|
||||
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,
|
||||
)
|
||||
|
||||
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')
|
||||
@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
|
||||
|
||||
|
||||
#-----------------------------------------------------------------
|
||||
|
||||
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__":
|
||||
|
|
|
@ -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 not bpy.context.scene.cubester_random_weights:
|
||||
if adv_obj.cubester_advanced:
|
||||
box.prop(adv_obj, "cubester_random_weights", icon="RNDCURVE")
|
||||
|
||||
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)),
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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": ""
|
||||
}
|
||||
|
||||
|
|
|
@ -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"}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
obj = context.active_object
|
||||
return (obj is not None and obj.type == "MESH")
|
||||
|
||||
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'}
|
||||
|
||||
obj = objs[0]
|
||||
if obj.type != 'MESH':
|
||||
self.report({'INFO'}, "Selection isn't a mesh")
|
||||
return {'FINISHED'}
|
||||
# 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"
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
obj = context.active_object
|
||||
return (obj is not None and obj.type == "MESH")
|
||||
|
||||
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'}
|
||||
|
||||
obj = objs[0]
|
||||
if obj.type != 'MESH':
|
||||
self.report({'INFO'}, "Selection isn't a mesh")
|
||||
return {'FINISHED'}
|
||||
# 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'}
|
||||
|
|
|
@ -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))
|
||||
|
||||
self.report({"WARNING"},
|
||||
"Constellation Operation could not be Completed (See Console for more Info)")
|
||||
|
||||
return {"CANCELLED"}
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
# Register
|
||||
|
||||
def add_osc_constellation_button(self, context):
|
||||
self.layout.operator(
|
||||
Oscurart_Constellation.bl_idname,
|
||||
text="Constellation",
|
||||
icon="PLUGIN")
|
||||
|
||||
|
||||
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()
|
||||
|
|
|
@ -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__":
|
||||
|
|
|
@ -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
|
||||
|
||||
def menu_func(self, context):
|
||||
self.layout.operator(Struts.bl_idname, text="Struts", icon='PLUGIN')
|
||||
return {"FINISHED"}
|
||||
|
||||
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():
|
||||
|
|
|
@ -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)
|
||||
|
||||
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)")
|
||||
|
||||
return {'FINISHED'}
|
||||
return {"CANCELLED"}
|
||||
|
||||
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__":
|
||||
|
|
|
@ -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__":
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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() )
|
||||
verts = bm.verts
|
||||
advanced_objects = context.scene.advanced_objects
|
||||
randomMag = advanced_objects.mangle_random_magnitude
|
||||
random.seed(time.time())
|
||||
|
||||
if mesh.shape_keys != None:
|
||||
self.report({'INFO'}, "Cannot mangle mesh: Shape keys present")
|
||||
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)
|
||||
|
|
|
@ -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'}
|
||||
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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')
|
||||
|
||||
|
||||
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__":
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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
|
||||
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"
|
||||
# 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
|
||||
# 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 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(
|
||||
# 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
|
||||
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(
|
||||
# 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
|
||||
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()
|
||||
# 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
|
||||
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 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 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
|
||||
# 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"}
|
||||
|
|
|
@ -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
|
||||
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"
|
||||
# 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
|
||||
# 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 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 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 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 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
|
||||
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 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))
|
||||
# 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
|
||||
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 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
|
||||
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
|
||||
# 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'}
|
||||
|
|
|
@ -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'}
|
||||
|
|
|
@ -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
|
||||
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')
|
||||
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
|
||||
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 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 Direction for each Lamp
|
||||
|
||||
# Calculate current Distance and get Delta
|
||||
obj_position = obj.location
|
||||
cam_position = camera.location
|
||||
# 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))
|
||||
|
||||
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"
|
||||
|
||||
return {'FINISHED'}
|
||||
|
|
|
@ -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():
|
||||
|
|
Loading…
Reference in New Issue