Add files via upload
This commit is contained in:
@@ -0,0 +1,164 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import bpy
|
||||
import math
|
||||
import random
|
||||
|
||||
from mathutils import Matrix
|
||||
from mathutils import Vector
|
||||
|
||||
from . import cfg
|
||||
|
||||
|
||||
def at_random_fill(min, max):
|
||||
first = random.uniform(min, max)
|
||||
second = random.uniform(min, max)
|
||||
if first <= second:
|
||||
return(first, second)
|
||||
else:
|
||||
return(second, first)
|
||||
|
||||
|
||||
def at_random(seed, totalc, totalr, mint, maxt, mins, maxs, minr, maxr, btr, bsc, brot, uniform,
|
||||
tr1, tr2, sc1, sc2, r1, r2, pivot, varia, valign):
|
||||
"""Random function for translation, scale and rotation,
|
||||
seed : seed for random
|
||||
totalc : number of elements in column
|
||||
totalr : number of elements in row
|
||||
mint : minimum for translation
|
||||
maxt : maximum for translation
|
||||
mins : minimum for scale
|
||||
maxs : maximum for scale
|
||||
minr : minimum for rotation
|
||||
maxr : maximun for rotation
|
||||
btr : (boolean) use translation or not
|
||||
bsc : (boolean) use scale or not
|
||||
brot : (boolean) use rotation or not
|
||||
uniform : (boolean) use uniform scale or not
|
||||
tr1 : translation offset of the column
|
||||
tr2 : translation offset of the row
|
||||
sc1 : scale offset of the column
|
||||
sc2 : scale offset of the row
|
||||
r1 : rotation offset of the column
|
||||
r2 : rotation offset of the row
|
||||
pivot : pivot
|
||||
varia : variation of rows
|
||||
valign : Vector of align of rows
|
||||
"""
|
||||
random.seed(seed)
|
||||
tr, sc, rot = [0, 0, 0], [0, 0, 0], [0, 0, 0]
|
||||
xyz_vec = (x_axis(), y_axis(), z_axis())
|
||||
ref_name = cfg.atools_objs[0][0]
|
||||
for j in range(totalr):
|
||||
for k in range(totalc + j*varia):
|
||||
elem_name = cfg.atools_objs[j][k]
|
||||
if elem_name == ref_name:
|
||||
continue
|
||||
elem = bpy.data.objects[elem_name]
|
||||
for i in range(3):
|
||||
tr[i] = random.uniform(mint[i], maxt[i])
|
||||
sc[i] = random.uniform(mins[i]/100, maxs[i]/100)
|
||||
rot[i] = random.uniform(minr[i], maxr[i])
|
||||
if uniform:
|
||||
sc[0] = sc[1] = sc[2]
|
||||
mt = Matrix.Translation(tr)
|
||||
ms = Matrix.Scale(sc[0], 4, (1, 0, 0)) @ Matrix.Scale(sc[1], 4, (0, 1, 0)) @ Matrix.Scale(sc[2], 4, (0, 0, 1))
|
||||
mr = Matrix.Rotation(rot[0], 4, (1, 0, 0)) @ Matrix.Rotation(rot[1], 4, (0, 1, 0)) @ Matrix.Rotation(rot[2], 4, (0, 0, 1))
|
||||
|
||||
# recalculate the position...
|
||||
vt, vs, vr = tsr(cfg.ref_mtx, k, j, tr1, tr2, sc1, sc2, Vector(r1), Vector(r2), valign)
|
||||
|
||||
if pivot is not None:
|
||||
emat = at_all_in_one(cfg.ref_mtx, vr, xyz_vec, vt, vs, pivot.location)
|
||||
else:
|
||||
emat = at_all_in_one(cfg.ref_mtx, vr, xyz_vec, vt, vs, cfg.ref_mtx.translation)
|
||||
elem.matrix_world = emat
|
||||
if btr:
|
||||
elem.matrix_world @= mt
|
||||
if bsc:
|
||||
elem.matrix_world @= ms
|
||||
if brot:
|
||||
elem.matrix_world @= mr
|
||||
|
||||
def x_axis():
|
||||
"""Get the x axis"""
|
||||
return Vector((1.0, 0.0, 0.0))
|
||||
|
||||
|
||||
def y_axis():
|
||||
"""Get the y axis"""
|
||||
return Vector((0.0, 1.0, 0.0))
|
||||
|
||||
|
||||
def z_axis():
|
||||
"""Get the z axis"""
|
||||
return Vector((0.0, 0.0, 1.0))
|
||||
|
||||
|
||||
def xyz_axis():
|
||||
"""Get the xyz axis"""
|
||||
return Vector((1.0, 1.0, 1.0))
|
||||
|
||||
|
||||
def at_all_in_one(ref, angle, vecxyz, vec_tr, vec_sc, pivot):
|
||||
"""Return the matrix of transformations"""
|
||||
# Matrix is composed by location @ rotation @ scale
|
||||
loc_ref, rot_ref, sc_ref = ref.decompose()
|
||||
# ref_location = bpy.data.objects[cfg.atools_objs[0][0]].location
|
||||
|
||||
loc_ma = Matrix.Translation(loc_ref)
|
||||
rot_ma = rot_ref.to_matrix().to_4x4()
|
||||
sc_ma = Matrix.Scale(sc_ref[0], 4, (1, 0, 0)) @ Matrix.Scale(sc_ref[1], 4, (0, 1, 0)) @ Matrix.Scale(sc_ref[2], 4, (0, 0, 1))
|
||||
|
||||
mt = Matrix.Translation(pivot - loc_ref)
|
||||
mr = Matrix.Rotation(angle[0], 4, vecxyz[0]) @ Matrix.Rotation(angle[1], 4, vecxyz[1]) @ Matrix.Rotation(angle[2], 4, vecxyz[2])
|
||||
mra = mt @ mr @ mt.inverted()
|
||||
|
||||
trm = Matrix.Translation(vec_tr)
|
||||
scm = Matrix.Scale(vec_sc[0], 4, (1, 0, 0)) @ Matrix.Scale(vec_sc[1], 4, (0, 1, 0)) @ Matrix.Scale(vec_sc[2], 4, (0, 0, 1))
|
||||
|
||||
if pivot == loc_ref:
|
||||
mw = loc_ma @ rot_ma @ trm @ scm @ sc_ma @ mr
|
||||
else:
|
||||
mw = loc_ma @ mra @ rot_ma @ trm @ scm @ sc_ma
|
||||
return mw
|
||||
|
||||
|
||||
def fill_rotation(context):
|
||||
prop = context.scene.arraytools_prop
|
||||
offset = prop.rot_offset
|
||||
|
||||
for i in range(3):
|
||||
if offset[i] == 0.0:
|
||||
prop.rot_min[i], prop.rot_max[i] = at_random_fill(-math.pi, math.pi)
|
||||
else:
|
||||
prop.rot_min[i], prop.rot_max[i] = at_random_fill(-offset[i]*2, offset[i]*2)
|
||||
|
||||
|
||||
def sum_serie(n, factor):
|
||||
"""Return the sum of the serie 1+2+3+4+...+n
|
||||
with a factor
|
||||
"""
|
||||
return ((n * (n - 1)) / 2) * factor
|
||||
|
||||
|
||||
# (T)ranslate (S)cale (R)otation vector
|
||||
def tsr(mat, col, row, tcol, trow, scol, srow, rcol, rrow, ralign):
|
||||
"""Retrieve the translation, scale and rotation vector according
|
||||
to the position in the array
|
||||
mat : matrix of the reference object
|
||||
col : position in column
|
||||
row : position in row
|
||||
tcol : translate offset in column
|
||||
trow : translate offset in row
|
||||
scol : scale offset in column
|
||||
srow : scale offset in row
|
||||
rcol : rotation offset in column
|
||||
rrow : rotation offset in row
|
||||
ralign : row align
|
||||
"""
|
||||
translate = col * tcol + row * trow + row * ralign
|
||||
rotate = col * Vector(rcol) + row * Vector(rrow)
|
||||
s1 = col * (mat.to_scale() - (scol/100))
|
||||
s2 = row * (mat.to_scale() - (srow/100))
|
||||
scale = xyz_axis() - s1 - s2
|
||||
return translate, scale, rotate
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,219 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# ---------------------------- Operators ------------------------
|
||||
import bpy
|
||||
import math
|
||||
|
||||
from mathutils import Vector
|
||||
|
||||
from . import cfg
|
||||
from . import at_interface
|
||||
from . at_calc_func import at_random_fill, fill_rotation
|
||||
|
||||
|
||||
class OBJECT_OT_at_start(bpy.types.Operator):
|
||||
"""Start and init the addon"""
|
||||
bl_idname = 'scene.at_op'
|
||||
bl_label = "Start array"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return not context.scene.arraytools_prop.already_start
|
||||
|
||||
def execute(self, context):
|
||||
cfg.init_array_tool(context)
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
class OBJECT_OT_at_done(bpy.types.Operator):
|
||||
"""Apply the settings"""
|
||||
bl_idname = 'scene.at_done'
|
||||
bl_label = "Done !"
|
||||
|
||||
def execute(self, context):
|
||||
cfg.atools_objs.clear()
|
||||
#cfg.at_mtx_list.clear()
|
||||
array_col = bpy.data.collections.get(cfg.col_name)
|
||||
cfg.col_name = "Array_collection"
|
||||
context.scene.arraytools_prop.up_ui_reset()
|
||||
context.scene.arraytools_prop.already_start = False
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
class OBJECT_OT_at_cancel(bpy.types.Operator):
|
||||
"""Cancel the settings"""
|
||||
bl_idname = 'scene.at_cancel'
|
||||
bl_label = "Cancel"
|
||||
|
||||
def execute(self, context):
|
||||
scn = context.scene
|
||||
scn.arraytools_prop.at_del_all(True)
|
||||
scn.arraytools_prop.up_ui_reset()
|
||||
scn.arraytools_prop.already_start = False
|
||||
cfg.col_name = "Array_collection"
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
class OBJECT_OT_fill_tr(bpy.types.Operator):
|
||||
"""Fill the random translation fields"""
|
||||
bl_idname = 'scene.fill_tr'
|
||||
bl_label = "Fill"
|
||||
|
||||
def execute(self, context):
|
||||
prop = context.scene.arraytools_prop
|
||||
offset = prop.tr_offset
|
||||
|
||||
for i in range(3):
|
||||
if offset[i] == 0.0:
|
||||
prop.tr_min[i], prop.tr_max[i] = at_random_fill(-3.0, 3.0)
|
||||
else:
|
||||
prop.tr_min[i], prop.tr_max[i] = at_random_fill(-offset[i]/2, offset[i]/2)
|
||||
return{'FINISHED'}
|
||||
|
||||
|
||||
class OBJECT_OT_fill_sc(bpy.types.Operator):
|
||||
"""Fill the random scale fields"""
|
||||
bl_idname = 'scene.fill_sc'
|
||||
bl_label = "Fill"
|
||||
|
||||
def execute(self, context):
|
||||
prop = context.scene.arraytools_prop
|
||||
offset = prop.sc_offset
|
||||
|
||||
if 100 in [offset[0], offset[1], offset[2]]:
|
||||
prop.sc_min_x, prop.sc_max_x = at_random_fill(40.0, 120.0)
|
||||
prop.sc_min_y, prop.sc_max_y = at_random_fill(40.0, 120.0)
|
||||
prop.sc_min_z, prop.sc_max_z = at_random_fill(40.0, 120.0)
|
||||
else:
|
||||
rand = [(100 - offset[i]) / 2 for i in range(3)]
|
||||
print(rand)
|
||||
prop.sc_min_x, prop.sc_max_x = at_random_fill(offset[0]-rand[0], offset[0]+rand[0])
|
||||
prop.sc_min_y, prop.sc_max_y = at_random_fill(offset[1]-rand[1], offset[1]+rand[1])
|
||||
prop.sc_min_z, prop.sc_max_z = at_random_fill(offset[2]-rand[2], offset[2]+rand[2])
|
||||
if prop.sc_all:
|
||||
prop.sc_min_x = prop.sc_min_y = prop.sc_min_z
|
||||
prop.sc_max_x = prop.sc_max_y = prop.sc_max_z
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
class OBJECT_OT_fill_rot(bpy.types.Operator):
|
||||
"""Fill the random rotation fields"""
|
||||
bl_idname = 'scene.fill_rot'
|
||||
bl_label = "Fill"
|
||||
|
||||
def execute(self, context):
|
||||
fill_rotation(context)
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
class OBJECT_OT_x360(bpy.types.Operator):
|
||||
"""Quick 360 degrees on X axis"""
|
||||
bl_idname = 'scene.x360'
|
||||
bl_label = "360"
|
||||
|
||||
def execute(self, context):
|
||||
prop = context.scene.arraytools_prop
|
||||
prop.tr_offset = Vector((0.0, 0.0, 0.0))
|
||||
prop.rot_global = Vector((math.pi/180*360, 0.0, 0.0))
|
||||
return{'FINISHED'}
|
||||
|
||||
|
||||
class OBJECT_OT_y360(bpy.types.Operator):
|
||||
"""Quick 360 degrees on Y axis"""
|
||||
bl_idname = 'scene.y360'
|
||||
bl_label = "360"
|
||||
|
||||
def execute(self, context):
|
||||
prop = context.scene.arraytools_prop
|
||||
prop.tr_offset = Vector((0.0, 0.0, 0.0))
|
||||
prop.rot_global = Vector((0.0, math.pi/180*360, 0.0))
|
||||
return{'FINISHED'}
|
||||
|
||||
|
||||
class OBJECT_OT_z360(bpy.types.Operator):
|
||||
"""Quick 360 degrees on Z axis"""
|
||||
bl_idname = 'scene.z360'
|
||||
bl_label = "360"
|
||||
|
||||
def execute(self, context):
|
||||
prop = context.scene.arraytools_prop
|
||||
prop.tr_offset = Vector((0.0, 0.0, 0.0))
|
||||
prop.rot_global = Vector((0.0, 0.0, math.pi/180*360))
|
||||
return{'FINISHED'}
|
||||
|
||||
|
||||
class OBJECT_OT_reset_tr(bpy.types.Operator):
|
||||
"""Reset the settings of random translation"""
|
||||
bl_idname = 'scene.at_reset_tr'
|
||||
bl_label = 'Reset'
|
||||
|
||||
def execute(self, context):
|
||||
prop = context.scene.arraytools_prop
|
||||
prop.tr_min[0], prop.tr_min[1], prop.tr_min[2] = 0.0, 0.0, 0.0
|
||||
prop.tr_max[0], prop.tr_max[1], prop.tr_max[2] = 0.0, 0.0, 0.0
|
||||
|
||||
# if operator is used many times
|
||||
# get weird result != 0 with vector
|
||||
# prop.tr_max = Vector((0.0, 0.0, 0.0))
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
class OBJECT_OT_reset_sc(bpy.types.Operator):
|
||||
"""Reset the settings of random scale"""
|
||||
bl_idname = 'scene.at_reset_sc'
|
||||
bl_label = 'Reset'
|
||||
|
||||
def execute(self, context):
|
||||
prop = context.scene.arraytools_prop
|
||||
prop.sc_min_x, prop.sc_min_y, prop.sc_min_z = 100, 100, 100
|
||||
prop.sc_max_x, prop.sc_max_y, prop.sc_max_z = 100, 100, 100
|
||||
return{'FINISHED'}
|
||||
|
||||
|
||||
class OBJECT_OT_reset_rot(bpy.types.Operator):
|
||||
"""Reset the settings of random rotation"""
|
||||
bl_idname = 'scene.at_reset_rot'
|
||||
bl_label = 'Reset'
|
||||
|
||||
def execute(self, context):
|
||||
prop = context.scene.arraytools_prop
|
||||
prop.rot_min[0], prop.rot_min[1], prop.rot_min[2] = 0.0, 0.0, 0.0
|
||||
prop.rot_max[0], prop.rot_max[1], prop.rot_max[2] = 0.0, 0.0, 0.0
|
||||
return{'FINISHED'}
|
||||
|
||||
|
||||
class OBJECT_OT_reset_second(bpy.types.Operator):
|
||||
"""Reset the settings of row options"""
|
||||
bl_idname = 'scene.at_reset_second'
|
||||
bl_label = 'Reset'
|
||||
|
||||
def execute(self, context):
|
||||
prop = context.scene.arraytools_prop
|
||||
prop.tr_second = (0,0,0)
|
||||
prop.sc_second = (100,100,100)
|
||||
prop.rot_second = (0,0,0)
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
class OBJECT_OT_error(bpy.types.Operator):
|
||||
"""Draw a message box to display error"""
|
||||
bl_idname = "info.at_error"
|
||||
bl_label = "Message info"
|
||||
|
||||
info: bpy.props.StringProperty(
|
||||
name = "Message",
|
||||
description = "Display a message",
|
||||
default = ''
|
||||
)
|
||||
|
||||
def execute(self, context):
|
||||
self.report({'INFO'}, self.info)
|
||||
print(self.info)
|
||||
return {'FINISHED'}
|
||||
|
||||
def invoke(self, context, event):
|
||||
return context.window_manager.invoke_props_dialog(self)
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.label(text=self.info)
|
||||
layout.label(text="")
|
||||
@@ -0,0 +1,210 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from bpy.types import Panel
|
||||
|
||||
from . import cfg
|
||||
|
||||
# ---------------------------- Panel --------------------------------
|
||||
class UIPANEL_PT_def(Panel):
|
||||
bl_space_type = "VIEW_3D"
|
||||
bl_region_type = "UI"
|
||||
bl_category = "Array Tools"
|
||||
|
||||
|
||||
class UIPANEL_PT_trans(UIPANEL_PT_def):
|
||||
"""Panel containing the settings for translation, scale and rotation array"""
|
||||
bl_label = "Array Tools"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return (len(context.selected_objects) > 0 and (context.object.mode == 'OBJECT'))
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
scn = context.scene
|
||||
my_prop = scn.arraytools_prop
|
||||
|
||||
row = layout.row()
|
||||
row.operator('scene.at_op')
|
||||
row = layout.row()
|
||||
if not my_prop.already_start:
|
||||
row.alignment = 'CENTER'
|
||||
row.label(text="~ Click to begin ~")
|
||||
else:
|
||||
row.prop(my_prop, 'is_copy')
|
||||
row.prop(my_prop, 'count')
|
||||
box = layout.box()
|
||||
box.label(text="Translation")
|
||||
col = box.column()
|
||||
split = col.split()
|
||||
split.prop(my_prop, 'tr_offset')
|
||||
split.prop(my_prop, 'tr_global')
|
||||
|
||||
row = layout.row()
|
||||
row.prop(my_prop, 'at_pivot')
|
||||
|
||||
box = layout.box()
|
||||
box.label(text="Scaling (%)")
|
||||
col = box.column()
|
||||
split = col.split()
|
||||
split.prop(my_prop, 'sc_offset')
|
||||
split.prop(my_prop, 'sc_global')
|
||||
|
||||
box = layout.box()
|
||||
if scn.unit_settings.system_rotation == 'DEGREES':
|
||||
box.label(text="Rotation (degrees)")
|
||||
else:
|
||||
box.label(text="Rotation (radians)")
|
||||
split = box.split(factor=0.08)
|
||||
|
||||
col = split.column(align=True)
|
||||
col.label(text='')
|
||||
col.operator('scene.x360', text='X')
|
||||
col.operator('scene.y360', text='Y')
|
||||
col.operator('scene.z360', text='Z')
|
||||
|
||||
col = split.column()
|
||||
col.prop(my_prop, 'rot_offset')
|
||||
col = split.column()
|
||||
col.prop(my_prop, 'rot_global')
|
||||
|
||||
box = layout.box()
|
||||
row = box.row()
|
||||
row.scale_y = 1.5
|
||||
row.operator('scene.at_done')
|
||||
row.operator('scene.at_cancel')
|
||||
|
||||
row = box.row()
|
||||
row.scale_y = 0.3
|
||||
row.alignment = 'CENTER'
|
||||
row.label(text="~ Tansforms are NOT applied ~")
|
||||
|
||||
|
||||
class UIPANEL_PT_rows(UIPANEL_PT_def):
|
||||
"""Panel containing the row options"""
|
||||
bl_parent_id = 'UIPANEL_PT_trans'
|
||||
bl_label = 'Rows options'
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
my_prop = context.scene.arraytools_prop
|
||||
|
||||
if my_prop.already_start:
|
||||
row = layout.row()
|
||||
row.prop(my_prop, 'count')
|
||||
row.prop(my_prop, 'row')
|
||||
row = layout.row()
|
||||
|
||||
row.scale_y = 0.8
|
||||
row.prop(my_prop, 'align', icon_only=True, expand=True)
|
||||
row.prop(my_prop, 'alter')
|
||||
row = layout.row()
|
||||
|
||||
row.alignment = 'CENTER'
|
||||
row.scale_x = 1.5
|
||||
row.scale_y = 0.6
|
||||
row.label(text=" - Offset settings -")
|
||||
row.scale_x = 0.8
|
||||
row.operator('scene.at_reset_second')
|
||||
|
||||
layout.use_property_split = True
|
||||
|
||||
col = layout.column()
|
||||
row = col.row(align=True)
|
||||
row.prop(my_prop, 'tr_second')
|
||||
col = layout.column()
|
||||
row = col.row(align=True)
|
||||
row.prop(my_prop, 'sc_second')
|
||||
col = layout.column()
|
||||
row = col.row(align=True)
|
||||
row.prop(my_prop, 'rot_second')
|
||||
|
||||
row = layout.row()
|
||||
row.scale_y = 0.5
|
||||
row.label(text="Total : " + my_prop.total + " | current row : " + my_prop.erow)
|
||||
"""
|
||||
box = layout.box()
|
||||
box.prop(my_prop, 'tr_second')
|
||||
#row = layout.row()
|
||||
box.prop(my_prop, 'sc_second')
|
||||
#row = layout.row()
|
||||
box.prop(my_prop, 'rot_second')
|
||||
"""
|
||||
|
||||
|
||||
class UIPANEL_PT_options(UIPANEL_PT_def):
|
||||
"""Panel containing the random options"""
|
||||
bl_parent_id = 'UIPANEL_PT_trans'
|
||||
bl_label = 'Random options'
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
my_prop = context.scene.arraytools_prop
|
||||
|
||||
layout.enabled = my_prop.already_start
|
||||
row = layout.row()
|
||||
row.alignment = 'CENTER'
|
||||
row.prop(my_prop, 'at_seed')
|
||||
row = layout.row()
|
||||
row.prop(my_prop, 'at_mode', expand=True)
|
||||
row = layout.row()
|
||||
if my_prop.at_mode == 'SIM':
|
||||
row.prop(my_prop, 'at_is_tr')
|
||||
row = layout.row()
|
||||
row.prop(my_prop, 'tr_rand')
|
||||
row = layout.row()
|
||||
row.prop(my_prop, 'at_is_sc')
|
||||
row = layout.row()
|
||||
row.prop(my_prop, 'sc_rand')
|
||||
row = layout.row()
|
||||
row.prop(my_prop, 'at_is_rot')
|
||||
row = layout.row()
|
||||
row.prop(my_prop, 'rot_rand')
|
||||
else:
|
||||
row.label(text=' ')
|
||||
row.label(text='X')
|
||||
row.label(text='Y')
|
||||
row.label(text='Z')
|
||||
row = layout.row()
|
||||
row.prop(my_prop, 'at_is_tr')
|
||||
row.scale_x = 0.5
|
||||
row.scale_y = 0.7
|
||||
row.operator('scene.at_reset_tr')
|
||||
row.operator('scene.fill_tr')
|
||||
row = layout.row()
|
||||
row.prop(my_prop, 'tr_min')
|
||||
row = layout.row()
|
||||
row.prop(my_prop, 'tr_max')
|
||||
row = layout.row()
|
||||
|
||||
row.prop(my_prop, 'at_is_sc')
|
||||
row.scale_x = 0.5
|
||||
row.scale_y = 0.7
|
||||
row.operator('scene.at_reset_sc')
|
||||
row.operator('scene.fill_sc')
|
||||
row = layout.row()
|
||||
row.alignment = "CENTER"
|
||||
row.scale_y = 0.7
|
||||
row.prop(my_prop, 'sc_all')
|
||||
row = layout.row(align=True)
|
||||
row.label(text='min:')
|
||||
row.prop(my_prop, 'sc_min_x', text='')
|
||||
row.prop(my_prop, 'sc_min_y', text='')
|
||||
row.prop(my_prop, 'sc_min_z', text='')
|
||||
row = layout.row(align=True)
|
||||
row.label(text='max:')
|
||||
row.prop(my_prop, 'sc_max_x', text='')
|
||||
row.prop(my_prop, 'sc_max_y', text='')
|
||||
row.prop(my_prop, 'sc_max_z', text='')
|
||||
|
||||
row = layout.row()
|
||||
row.prop(my_prop, "at_is_rot")
|
||||
row.scale_x = 0.5
|
||||
row.scale_y = 0.7
|
||||
row.operator('scene.at_reset_rot')
|
||||
row.operator('scene.fill_rot')
|
||||
row = layout.row()
|
||||
row.prop(my_prop, 'rot_min')
|
||||
row = layout.row()
|
||||
row.prop(my_prop, 'rot_max')
|
||||
@@ -0,0 +1,103 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import bpy
|
||||
|
||||
# count values, contains only 2 values : old count and current
|
||||
at_count_values = []
|
||||
# row value, contains old row and current
|
||||
at_row_values = []
|
||||
# alter values, contains old and current
|
||||
at_alter = []
|
||||
# maximun row according to column and alter
|
||||
maxrow = 1
|
||||
# list of the copies / list of lists
|
||||
atools_objs = []
|
||||
ref_mtx = [] # reference matrix
|
||||
# collection name
|
||||
col_name = "Array_collection"
|
||||
|
||||
|
||||
def init_array_tool(context):
|
||||
"""Initialisation of the array tools"""
|
||||
global at_count_values
|
||||
global at_row_values
|
||||
global at_alter
|
||||
global atools_objs
|
||||
global ref_mtx
|
||||
global col_name
|
||||
|
||||
prop = context.scene.arraytools_prop
|
||||
name = col_name
|
||||
i = 1
|
||||
collect = bpy.data.collections.get(col_name)
|
||||
# create and link the new collection
|
||||
if collect is None:
|
||||
array_col = bpy.data.collections.new(col_name)
|
||||
bpy.context.scene.collection.children.link(array_col)
|
||||
else:
|
||||
# if a collection already exist, create a new one
|
||||
while bpy.data.collections.get(name) is not None:
|
||||
name = col_name + str(i)
|
||||
i += 1
|
||||
array_col = bpy.data.collections.new(name)
|
||||
bpy.context.scene.collection.children.link(array_col)
|
||||
col_name = name
|
||||
|
||||
if not prop.already_start:
|
||||
at_count_values = [1, 2]
|
||||
at_row_values = [0, 1]
|
||||
at_alter = [0, 0]
|
||||
active = context.active_object
|
||||
prop.already_start = True
|
||||
prop.is_tr_off_last = True
|
||||
if active is not None:
|
||||
atools_objs.append([active.name])
|
||||
ref_mtx = active.matrix_world.copy()
|
||||
del active
|
||||
prop.add_in_column(prop.row)
|
||||
# no need anymore
|
||||
else:
|
||||
print("No object selected")
|
||||
else:
|
||||
print("Already started!")
|
||||
|
||||
|
||||
def add_count(value):
|
||||
"""Save the current count"""
|
||||
global at_count_values
|
||||
at_count_values.append(value)
|
||||
|
||||
|
||||
def del_count():
|
||||
"""Del the previous count"""
|
||||
global at_count_values
|
||||
del at_count_values[0]
|
||||
|
||||
|
||||
def add_row(value):
|
||||
"""Save the current row"""
|
||||
global at_row_values
|
||||
at_row_values.append(value)
|
||||
|
||||
|
||||
def del_row():
|
||||
""" Del the previous row value"""
|
||||
global at_row_values
|
||||
del at_row_values[0]
|
||||
|
||||
|
||||
def add_alter(value):
|
||||
"""save the current variation"""
|
||||
global at_alter
|
||||
at_alter.append(value)
|
||||
|
||||
|
||||
def del_alter():
|
||||
"""Remove previous variation"""
|
||||
global at_alter
|
||||
del at_alter[0]
|
||||
|
||||
|
||||
def display_error(msg):
|
||||
"""Call the operator to display an error message"""
|
||||
bpy.ops.info.at_error('INVOKE_DEFAULT', info = msg)
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTIBILITY 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, see <http://www.gnu.org/licenses/>.
|
||||
import bpy
|
||||
|
||||
from . import cfg
|
||||
from . import at_interface
|
||||
|
||||
bl_info = {
|
||||
"name": "Array_tools",
|
||||
"author": "Elreenys",
|
||||
"description": "Tools to create array of objects",
|
||||
"blender": (2, 80, 0),
|
||||
"version": (1, 2, 1),
|
||||
"location": "View3D > sidebar > array tools tab",
|
||||
"category": "Object"
|
||||
}
|
||||
|
||||
classes = (
|
||||
at_operators.OBJECT_OT_at_start,
|
||||
at_operators.OBJECT_OT_at_cancel,
|
||||
at_operators.OBJECT_OT_at_done,
|
||||
at_operators.OBJECT_OT_fill_tr,
|
||||
at_operators.OBJECT_OT_fill_sc,
|
||||
at_operators.OBJECT_OT_fill_rot,
|
||||
at_operators.OBJECT_OT_x360,
|
||||
at_operators.OBJECT_OT_y360,
|
||||
at_operators.OBJECT_OT_z360,
|
||||
at_operators.OBJECT_OT_reset_tr,
|
||||
at_operators.OBJECT_OT_reset_sc,
|
||||
at_operators.OBJECT_OT_reset_rot,
|
||||
at_operators.OBJECT_OT_reset_second,
|
||||
at_operators.OBJECT_OT_error,
|
||||
at_panel.UIPANEL_PT_trans,
|
||||
at_panel.UIPANEL_PT_rows,
|
||||
at_panel.UIPANEL_PT_options,
|
||||
at_interface.ArrayTools_props
|
||||
)
|
||||
|
||||
|
||||
def register():
|
||||
scene = bpy.types.Scene
|
||||
pp = bpy.props.PointerProperty
|
||||
|
||||
for cls in classes:
|
||||
bpy.utils.register_class(cls)
|
||||
scene.arraytools_prop = pp(type=at_interface.ArrayTools_props)
|
||||
|
||||
|
||||
def unregister():
|
||||
del bpy.types.Scene.arraytools_prop
|
||||
for cls in reversed(classes):
|
||||
bpy.utils.unregister_class(cls)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
register()
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user