Newer
Older
"version": (2, 0, 1),
"blender": (2, 77, 3),
"wiki_url": "http://wiki.blender.org/index.php/Extensions:2.6/Py/Scripts/3D_interaction/bprojection",
"tracker_url": "https://developer.blender.org/maniphest/task/edit/form/2/",
from bpy.app.handlers import persistent
from bpy.types import (
Panel,
Operator,
PropertyGroup,
AddonPreferences,
)
from bpy.props import (
IntProperty,
FloatProperty,
BoolProperty,
StringProperty,
FloatVectorProperty,
CollectionProperty,
)
from math import (
radians,
sqrt,
pi,
)
from mathutils import (
Quaternion,
Vector,
)
BProjection_Empty = 'Empty for BProjection'
BProjection_Material = 'Material for BProjection'
BProjection_Texture = 'Texture for BProjection'
# Main function for align the plan to view
def align_to_view(context):
last_mouse = Vector((0, 0))
CoDEmanX
committed
em = bpy.data.objects[BProjection_Empty]
rotation = em.custom_rotation
scale = em.custom_scale
z = em.custom_location.z
pos = [em.custom_location.x, em.custom_location.y]
CoDEmanX
committed
sd = context.space_data
r3d = sd.region_3d
r3d.update()
vr = r3d.view_rotation
quat = Quaternion((0.0, 0.0, 1.0), radians(float(rotation)))
v = Vector((pos[0], pos[1], z))
v.rotate(vr)
em = bpy.data.objects[BProjection_Empty]
img = bpy.data.textures[BProjection_Texture].image
if img and img.size[1] != 0:
prop = img.size[0] / img.size[1]
else:
prop = 1
CoDEmanX
committed
if em.custom_linkscale:
em.scale = Vector((prop * scale[0], scale[0], 1))
em.scale = Vector((prop * scale[0], scale[1], 1))
pos_cur = em.location - sd.cursor_location
rot_cur1 = em.rotation_euler.to_quaternion()
em.location = v + ob.location
em.rotation_euler = Quaternion.to_euler(vr * quat)
if em.custom_c3d:
if em.custom_old_scale != em.custom_scale:
CoDEmanX
committed
pos_cur = em.location - sd.cursor_location
rot_cur2 = em.rotation_euler.to_quaternion()
rot_cur1.invert()
pos_cur.rotate(rot_cur1)
pos_cur.rotate(rot_cur2)
v = em.location - pos_cur
sd.cursor_location = v
CoDEmanX
committed
def applyimage(context):
img = bpy.data.textures[BProjection_Texture].image
ob = context.object
CoDEmanX
committed
face = ob.data.polygons
uvdata = ob.data.uv_textures.active.data
CoDEmanX
committed
for f, d in zip(face, uvdata):
if f.select:
d.image = img
align_to_view(context)
ob.data.update()
CoDEmanX
committed
# Function to update the properties
CoDEmanX
committed
def update_Location(self, context):
def find_uv(context):
obj = context.object
me = obj.data.vertices
vg = obj.vertex_groups
CoDEmanX
committed
index_uv = 0
for face in obj.data.polygons:
x = len(face.vertices)
for vertex in face.vertices:
if (len(me[vertex]. groups) > 0):
for g in me[vertex].groups:
if vg[g.group].name == 'texture plane':
CoDEmanX
committed
l.append([index_uv, len(face. vertices)])
index_uv += len(face.vertices)
return l
# Function to update the scaleUV
def update_UVScale(self, context):
ob = context.object
em = bpy.data.objects[BProjection_Empty]
v = Vector((em.custom_offsetuv[0] / 10 + 0.5, em.custom_offsetuv[1] / 10 + 0.5))
l = Vector((0.0, 0.0))
CoDEmanX
committed
os = em.custom_old_scaleuv
for i, j in l:
d = ob.data.uv_layers.active.data[i + t]
vres = v - d.uv
d.uv.x = v.x - vres.x / os[0] * s[0]
d.uv.y = v.y - vres.y / os[1] * s[1]
CoDEmanX
committed
em.custom_old_scaleuv = s
def update_PropUVScale(self, context):
em = bpy.data.objects[BProjection_Empty]
if em.custom_linkscaleuv:
em.custom_scaleuv = [em.custom_propscaleuv, em.custom_propscaleuv]
def update_LinkUVScale(self, context):
em = bpy.data.objects[BProjection_Empty]
if em.custom_linkscaleuv:
em.custom_propscaleuv = em.custom_scaleuv.x
update_PropUVScale(self, context)
else:
CoDEmanX
committed
update_UVScale(self, context)
# Function to update the offsetUV
def update_UVOffset(self, context):
ob = context.object
em = bpy.data.objects[BProjection_Empty]
o = em.custom_offsetuv
CoDEmanX
committed
oo = em.custom_old_offsetuv
for i, j in l:
d = ob.data.uv_layers.active.data[i + t]
d.uv = [d.uv[0] - oo[0] / 10 + o[0] / 10, d.uv[1] - oo[1] / 10 + o[1] / 10]
CoDEmanX
committed
# Function to update the flip horizontal
def update_FlipUVX(self, context):
l = find_uv(context)
for i, j in l:
d = context.object.data.uv_layers.active.data[i + t]
x = d.uv.x
d.uv.x = 1 - x
CoDEmanX
committed
# Function to update the flip vertical
def update_FlipUVY(self, context):
l = find_uv(context)
for i, j in l:
d = context.object.data.uv_layers.active.data[i + t]
y = d.uv[1]
d.uv[1] = 1 - y
CoDEmanX
committed
CoDEmanX
committed
def update_Rotation(self, context):
ob = context.object
em = bpy.data.objects[BProjection_Empty]
if em.custom_rotc3d:
angle = em.custom_rotation - em.custom_old_rotation
sd = context.space_data
CoDEmanX
committed
vr = sd.region_3d.view_rotation.copy()
c = sd.cursor_location - ob.location
e = bpy.data.objects[BProjection_Empty].location - ob.location
vo = Vector((0.0, 0.0, 1.0))
vo.rotate(vr)
quat = Quaternion(vo, radians(angle))
v = e - c
v.rotate(quat)
vr.invert()
v.rotate(vr)
c.rotate(vr)
em.custom_location = c + v
CoDEmanX
committed
else:
CoDEmanX
committed
em.custom_old_rotation = em.custom_rotation
CoDEmanX
committed
def update_Scale(self, context):
ob = context.object
em = bpy.data.objects[BProjection_Empty]
CoDEmanX
committed
if em.custom_scac3d:
sd = context.space_data
r3d = sd.region_3d
vr = r3d.view_rotation.copy()
vr.invert()
e = em.location - ob.location
c = sd.cursor_location - ob.location
ce = e - c
CoDEmanX
committed
s = em.custom_scale
os = em.custom_old_scale
c.rotate(vr)
ce.rotate(vr)
CoDEmanX
committed
v = Vector((s.x * ce.x / os.x, s.y * ce.y / os.y, 0.0))
em.custom_location = c + v
CoDEmanX
committed
else:
CoDEmanX
committed
em.custom_old_scale = em.custom_scale
def update_PropScale(self, context):
em = bpy.data.objects[BProjection_Empty]
if em.custom_linkscale:
em.custom_scale = [em.custom_propscale, em.custom_propscale]
CoDEmanX
committed
def update_LinkScale(self, context):
em = bpy.data.objects[BProjection_Empty]
if em.custom_linkscale:
em.custom_propscale = em.custom_scale.x
update_PropScale(self, context)
else:
CoDEmanX
committed
update_Scale(self, context)
def update_activeviewname(self, context):
em = bpy.data.objects[BProjection_Empty]
if self.custom_active:
em.custom_active_view = self.custom_active_view
CoDEmanX
committed
def update_style_clone(self, context):
km = context.window_manager.keyconfigs.default.keymaps['Image Paint']
for kmi in km.keymap_items:
CoDEmanX
committed
if self.custom_style_clone:
if kmi.idname == 'paint.image_paint':
kmi.idname = 'paint.bp_paint'
else:
if kmi.idname == 'paint.bp_paint':
CoDEmanX
committed
kmi.idname = 'paint.image_paint'
CoDEmanX
committed
class custom_props(PropertyGroup):
custom_fnlevel: IntProperty(
name="Fast navigate level",
description="Increase or decrease the SubSurf level, decrease make navigation faster",
default=0,
)
custom_location: FloatVectorProperty(
name="Location",
description="Location of the plane",
default=(1.0, 0, -1.0),
subtype='XYZ',
soft_min=-10,
soft_max=10,
step=0.1,
size=3,
)
custom_rotation: FloatProperty(
name="Rotation",
description="Rotate the plane",
min=-180, max=180,
default=0
)
custom_scale: FloatVectorProperty(
name="Scales",
description="Scale the planes",
default=(1.0, 1.0),
subtype='XYZ',
min=0.1,
max=10,
soft_min=0.1,
soft_max=10,
step=0.1,
size=2,
)
custom_propscale: FloatProperty(
name="PropScale",
description="Scale the Plane",
default=1.0,
min=0.1,
max=10,
soft_min=0.1,
soft_max=10,
step=0.1
)
custom_linkscale: BoolProperty(
name="linkscale",
default=True
)
custom_scaleuv: FloatVectorProperty(
name="ScaleUV",
description="Scale the texture's UV",
default=(1.0, 1.0),
min=0.01,
subtype='XYZ',
size=2
)
custom_propscaleuv: FloatProperty(
name="PropScaleUV",
description="Scale the texture's UV",
default=1.0,
min=0.01
)
custom_offsetuv: FloatVectorProperty(
name="OffsetUV",
description="Decal the texture's UV",
default=(0.0, 0.0),
subtype='XYZ',
size=2
)
custom_linkscaleuv: BoolProperty(
name="linkscaleUV",
default=True)
custom_flipuvx: BoolProperty(
name="flipuvx",
default=False
)
custom_flipuvy: BoolProperty(
name="flipuvy",
default=False
)
custom_active: BoolProperty(
name="custom_active",
default=True
)
custom_expand: BoolProperty(
name="expand",
default=False
)
custom_style_clone: BoolProperty(
name="custom_style_clone",
default=False
)
custom_active_view: StringProperty(
name="custom_active_view",
default="View",
update=update_activeviewname
)
custom_image: StringProperty(
name="custom_image",
default=""
)
custom_index: IntProperty()
# Function to create custom properties
def createcustomprops(context):
Ob = bpy.types.Object
CoDEmanX
committed
Ob.custom_fnlevel = IntProperty(
name="Fast navigate level",
description="Increase or decrease the SubSurf level, decrease make navigation faster",
default=0
)
CoDEmanX
committed
# plane properties
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
Ob.custom_location = FloatVectorProperty(
name="Location",
description="Location of the plane",
default=(1.0, 0, -1.0),
subtype='XYZ',
size=3,
step=0.5,
soft_min=-10,
soft_max=10,
update=update_Location
)
Ob.custom_rotation = FloatProperty(
name="Rotation",
description="Rotate the plane",
min=-180,
max=180,
default=0,
update=update_Rotation
)
Ob.custom_old_rotation = FloatProperty(
name="old_Rotation",
description="Old Rotate the plane",
min=-180,
max=180,
default=0
)
Ob.custom_scale = FloatVectorProperty(
name="Scales",
description="Scale the planes",
subtype='XYZ',
default=(1.0, 1.0),
min=0.1,
max=10,
soft_min=0.1,
soft_max=10,
size=2,
step=0.5,
update=update_Scale
)
Ob.custom_propscale = FloatProperty(
name="PropScale",
description="Scale the Plane",
default=1.0,
min=0.1,
soft_min=0.1,
soft_max=10,
step=0.5,
update=update_PropScale
)
Ob.custom_old_scale = FloatVectorProperty(
name="old_Scales",
description="Old Scale the planes",
subtype='XYZ',
default=(1.0, 1.0),
min=0.1,
size=2
)
Ob.custom_linkscale = BoolProperty(
name="linkscale",
default=True,
update=update_LinkScale
)
Ob.custom_sub = IntProperty(
name="Subdivide",
description="Number of subdivision of the plane",
min=0,
max=20,
default=0
)
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
Ob.custom_scaleuv = FloatVectorProperty(
name="ScaleUV",
description="Scale the texture's UV",
default=(1.0, 1.0),
soft_min=0.01,
soft_max=100,
min=0.01,
subtype='XYZ',
size=2,
update=update_UVScale
)
Ob.custom_propscaleuv = FloatProperty(
name="PropScaleUV",
description="Scale the texture's UV",
default=1.0,
soft_min=0.01,
soft_max=100,
min=0.01,
update=update_PropUVScale
)
Ob.custom_old_scaleuv = FloatVectorProperty(
name="old_ScaleUV",
description="Scale the texture's UV",
default=(1.0, 1.0),
min=0.01,
subtype='XYZ',
size=2
)
Ob.custom_offsetuv = FloatVectorProperty(
name="OffsetUV",
description="Decal the texture's UV",
default=(0.0, 0.0),
subtype='XYZ',
size=2,
update=update_UVOffset
)
Ob.custom_old_offsetuv = FloatVectorProperty(
name="old_OffsetUV",
description="Decal the texture's UV",
default=(0.0, 0.0),
subtype='XYZ',
size=2
)
Ob.custom_linkscaleuv = BoolProperty(
name="linkscaleUV",
default=True,
update=update_LinkUVScale
)
Ob.custom_flipuvx = BoolProperty(
name="flipuvx",
default=False,
update=update_FlipUVX
)
Ob.custom_flipuvy = BoolProperty(
name="flipuvy",
default=False,
update=update_FlipUVY
)
CoDEmanX
committed
# other properties
Ob.custom_c3d = BoolProperty(
name="c3d",
default=True
)
Ob.custom_rotc3d = BoolProperty(
name="rotc3d",
default=False
)
Ob.custom_scac3d = BoolProperty(
name="scac3d",
default=False
)
Ob.custom_expand = BoolProperty(
name="expand",
default=True
)
Ob.custom_style_clone = BoolProperty(
name="custom_style_clone",
default=False,
update=update_style_clone
)
Ob.custom_active_view = StringProperty(
name="custom_active_view",
default="View"
)
Ob.custom_active_object = StringProperty(
name="custom_active_object",
default=context.object.name
)
Ob.custom_active_object = StringProperty(
name="custom_active_object",
default='debut'
)
Ob.custom_props = CollectionProperty(type=custom_props)
# Function to remove custom properties
CoDEmanX
committed
def removecustomprops():
list_prop = ['custom_location', 'custom_rotation',
'custom_old_rotation', 'custom_scale',
'custom_old_scale', 'custom_c3d',
'custom_rotc3d', 'custom_scaleuv',
'custom_flipuvx', 'custom_flipuvy',
'custom_linkscale', 'custom_linkscaleuv',
'custom_old_scaleuv', 'custom_offsetuv',
'custom_old_offsetuv', 'custom_scac3d',
'custom_sub', 'custom_expand',
'custom_style_clone', 'custom_active_view',
'custom_propscaleuv', 'custom_props', 'custom_propscale']
for prop in list_prop:
try:
del bpy.data.objects[BProjection_Empty][prop]
except:
pass
CoDEmanX
committed
CoDEmanX
committed
em = bpy.data.objects[BProjection_Empty]
em.custom_scale = [1, 1]
em.custom_scaleuv = [1.0, 1.0]
em.custom_offsetuv = [0.0, 0.0]
em.custom_propscaleuv = 1.0
em.custom_propscale = 1.0
if em.custom_flipuvx is True:
if em.custom_flipuvy is True:
em.custom_flipuvy = False
# Operator Class to create view
class CreateView(Operator):
bl_idname = "object.create_view"
bl_label = "Create a new view"
CoDEmanX
committed
def execute(self, context):
ob = context.object
em = bpy.data.objects[BProjection_Empty]
CoDEmanX
committed
new_props = em.custom_props.add()
em.custom_active_view = new_props.custom_active_view
ob.data.shape_keys.key_blocks[ob.active_shape_key_index].mute = True
bpy.ops.object.shape_key_add(from_mix=False)
ob.data.shape_keys.key_blocks[ob.active_shape_key_index].value = 1.0
new_props.custom_index = len(em.custom_props) - 1
bpy.ops.object.active_view(index=new_props.custom_index)
# Operator Class to copy view
class SaveView(Operator):
bl_idname = "object.save_view"
bl_label = "copy the view"
CoDEmanX
committed
index: IntProperty(default=0)
CoDEmanX
committed
def execute(self, context):
em = bpy.data.objects[BProjection_Empty]
CoDEmanX
committed
prop = em.custom_props[self.index]
prop.custom_rotation = em.custom_rotation
prop.custom_scale = em.custom_scale
prop.custom_linkscale = em.custom_linkscale
prop.custom_scaleuv = em.custom_scaleuv
prop.custom_propscale = em.custom_propscale
prop.custom_offsetuv = em.custom_offsetuv
prop.custom_linkscaleuv = em.custom_linkscaleuv
prop.custom_propscaleuv = em.custom_propscaleuv
prop.custom_flipuvx = em.custom_flipuvx
prop.custom_flipuvy = em.custom_flipuvy
try:
prop.custom_image = bpy.data.textures[BProjection_Texture].image.name
except:
pass
CoDEmanX
committed
# Operator Class to copy view
class PasteView(Operator):
bl_idname = "object.paste_view"
bl_label = "paste the view"
CoDEmanX
committed
index: IntProperty(default=0)
CoDEmanX
committed
def execute(self, context):
em = bpy.data.objects[BProjection_Empty]
tmp_scac3d = em.custom_scac3d
tmp_rotc3d = em.custom_rotc3d
em.custom_scac3d = False
em.custom_rotc3d = False
prop = em.custom_props[self.index]
em.custom_linkscale = prop.custom_linkscale
em.custom_offsetuv = prop.custom_offsetuv
em.custom_linkscaleuv = prop.custom_linkscaleuv
em.custom_scaleuv = prop.custom_scaleuv
CoDEmanX
committed
em.custom_propscaleuv = prop.custom_propscaleuv
em.custom_rotation = prop.custom_rotation
em.custom_scale = prop.custom_scale
CoDEmanX
committed
em.custom_propscale = prop.custom_propscale
if prop.custom_image != '':
if bpy.data.textures[BProjection_Texture].image.name != prop.custom_image:
bpy.data.textures[BProjection_Texture].image = bpy.data.images[prop.custom_image]
applyimage(context)
if em.custom_flipuvx != prop.custom_flipuvx:
em.custom_flipuvx = prop.custom_flipuvx
if em.custom_flipuvy != prop.custom_flipuvy:
em.custom_flipuvy = prop.custom_flipuvy
em.custom_scac3d = tmp_scac3d
CoDEmanX
committed
em.custom_rotc3d = tmp_rotc3d
# Operator Class to remove view
class RemoveView(Operator):
bl_idname = "object.remove_view"
bl_label = "Rmeove the view"
CoDEmanX
committed
index: IntProperty(default=0)
CoDEmanX
committed
def execute(self, context):
ob = context.object
em = bpy.data.objects[BProjection_Empty]
CoDEmanX
committed
ob.active_shape_key_index = self.index + 1
bpy.ops.object.shape_key_remove()
CoDEmanX
committed
if em.custom_props[self.index].custom_active:
if len(em.custom_props) > 0:
bpy.ops.object.active_view(index=self.index - 1)
if self.index == 0 and len(em.custom_props) > 1:
bpy.ops.object.active_view(index=1)
CoDEmanX
committed
em.custom_props.remove(self.index)
CoDEmanX
committed
if len(em.custom_props) == 0:
clear_props(context)
CoDEmanX
committed
bpy.ops.object.create_view()
for item in em.custom_props:
CoDEmanX
committed
item.custom_index = i
for item in (item for item in em.custom_props if item.custom_active):
ob.active_shape_key_index = item.custom_index + 1
CoDEmanX
committed
# Operator Class to copy view
class ActiveView(Operator):
bl_idname = "object.active_view"
bl_label = "Active the view"
CoDEmanX
committed
index: IntProperty(default=0)
CoDEmanX
committed
def execute(self, context):
ob = context.object
em = bpy.data.objects[BProjection_Empty]
for item in (item for item in em.custom_props if item.custom_active is True):
bpy.ops.object.save_view(index=item.custom_index)
em.custom_props[self.index].custom_active = True
CoDEmanX
committed
em.custom_active_view = em.custom_props[self.index].custom_active_view
ob.active_shape_key_index = self.index + 1
CoDEmanX
committed
for i in ob.data.shape_keys.key_blocks:
i.mute = True
CoDEmanX
committed
ob.data.shape_keys.key_blocks[ob.active_shape_key_index].mute = False
CoDEmanX
committed
bpy.ops.object.paste_view(index=self.index)
CoDEmanX
committed
# Draw Class to show the panel
class BProjection(Panel):
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
bl_label = "BProjection"
@classmethod
def poll(cls, context):
return (context.image_paint_object or context.sculpt_object)
def draw(self, context):
CoDEmanX
committed
layout = self.layout
if BProjection_Empty in [ob.name for ob in bpy.data.objects]:
tex = bpy.data.textures[BProjection_Texture]
ob = context.object
em = bpy.data.objects[BProjection_Empty]
CoDEmanX
committed
if ob == bpy.data.objects[em.custom_active_object]:
col = layout.column(align=True)
CoDEmanX
committed
col.operator("object.removebprojectionplane", text="Remove BProjection plane")
try:
matBProjection = bpy.data.materials[BProjection_Material]
except:
matBProjection = None
CoDEmanX
committed
box = layout.box()
row = box.row()
if not em.custom_expand:
row.prop(em, "custom_expand", text="", icon="TRIA_RIGHT", emboss=False)
row.label(text='Paint Object: ' + ob.name)
row.prop(em, "custom_expand", text="", icon="TRIA_DOWN", emboss=False)
row.label(text='Paint Object: ' + ob.name)
CoDEmanX
committed
if ob == bpy.data.objects[em.custom_active_object]:
col = box.column(align=True)
col.template_ID(tex, "image", open="image.open")
row = box.row(align=True)
row.operator('object.applyimage', text="Apply image", icon='FILE_TICK')
row.prop(em, "custom_c3d", text="", icon='PIVOT_CURSOR')
row = box.row(align=True)
row.label(text="Location:")
row = box.row(align=True)
row.prop(em, 'custom_location', text='')
row = box.row(align=True)
row.prop(em, 'custom_rotation')
row.prop(em, 'custom_rotc3d', text="", icon='MANIPUL')
row = box.row(align=True)
row = box.row(align=True)
if em.custom_linkscale:
row.prop(em, "custom_propscale", text="")
row.prop(em, "custom_linkscale", text="", icon='LINKED')
CoDEmanX
committed
else:
row.prop(em, 'custom_scale', text='')
row.prop(em, "custom_linkscale", text="", icon='UNLINKED')
row.prop(em, 'custom_scac3d', text="", icon='MANIPUL')
row = box.row(align=True)
row.label(text="UV's Offset:")
row = box.row(align=True)
row.prop(em, 'custom_offsetuv', text='')
row.prop(em, "custom_flipuvx", text="", icon='ARROW_LEFTRIGHT')
row.prop(em, "custom_flipuvy", text="", icon='FULLSCREEN_ENTER')
row = box.row(align=True)
row.label(text="UV's Scale:")
row = box.row(align=True)
row.prop(em, 'custom_propscaleuv', text='')
row.prop(em, "custom_linkscaleuv", text="", icon='LINKED')
CoDEmanX
committed
else:
row.prop(em, 'custom_scaleuv', text='')
row.prop(em, "custom_linkscaleuv", text="", icon='UNLINKED')
CoDEmanX
committed
if (context.scene.game_settings.material_mode == 'GLSL' and
context.space_data.viewport_shade == 'TEXTURED'):
row = box.column(align=True)
row.prop(matBProjection, 'alpha', slider=True)
row = box.column(align=True)
row.prop(ob, "custom_fnlevel")
row = box.column(align=True)
row.prop(em, "custom_style_clone", text="Style Clone Normal", icon='RENDERLAYERS')
row.prop(em, "custom_style_clone", text="Style Clone New", icon='RENDERLAYERS')
row = box.column(align=True)
CoDEmanX
committed
if ob == bpy.data.objects[em.custom_active_object]:
for item in em.custom_props:
box = layout.box()
row = box.row()
if item.custom_active:
row.operator("object.active_view", text="",
icon='RADIOBUT_ON', emboss=False).index = item.custom_index
row.operator("object.active_view", text="",
icon='RADIOBUT_OFF', emboss=False).index = item.custom_index
CoDEmanX
committed
row.prop(item, "custom_active_view", text="")
row.operator('object.remove_view', text="",
icon='PANEL_CLOSE', emboss=False).index = item.custom_index
row.operator('object.create_view', text="Create View", icon='RENDER_STILL')
col = box.column(align=True)
CoDEmanX
committed
col.operator("object.change_object", text="Change Object")
else:
ob = context.object
col = layout.column(align=True)
CoDEmanX
committed
if ob.active_material is None:
col.label(text="Add a material first!", icon="ERROR")
elif ob.data.uv_textures.active is None:
col.label(text="Create UVMap first!!", icon="ERROR")
else:
col.operator("object.addbprojectionplane", text="Add BProjection plane")
col = layout.column(align=True)
col.prop(ob, "custom_sub", text="Subdivision level")
CoDEmanX
committed
# Operator Class to apply the image to the plane
class ApplyImageOB(Operator):
bl_idname = "object.applyimage"
bl_label = "Apply image"
CoDEmanX
committed
def execute(self, context):
CoDEmanX
committed
# Operator Class to make the 4 or 6 point and scale the plan
class IntuitiveScale(Operator):
bl_idname = "object.intuitivescale"
bl_label = "Draw lines"
def invoke(self, context, event):
ob = context.object
em = bpy.data.objects[BProjection_Empty]
x = event.mouse_region_x
CoDEmanX
committed
y = event.mouse_region_y
draw_stroke = {"name": "", "pen_flip": False,
"is_start": True, "location": (0, 0, 0),
"mouse": (x, y), "pressure": 1,
"size": 0.5, "time": 0}
CoDEmanX
committed
if len(ob.grease_pencil.layers.active.frames) == 0:
bpy.ops.gpencil.draw(mode='DRAW', stroke=[draw_stroke])
else:
if em.custom_linkscale:
nb_point = 4
else:
nb_point = 6
CoDEmanX
committed
if len(ob.grease_pencil.layers.active.frames[0].strokes) < nb_point:
bpy.ops.gpencil.draw(mode='DRAW', stroke=[draw_stroke])
CoDEmanX
committed
if len(ob.grease_pencil.layers.active.frames[0].strokes) == nb_point:
s = ob.grease_pencil.layers.active.frames[0]
v1 = s.strokes[1].points[0].co - s.strokes[0].points[0].co
if not em.custom_linkscale:
v2 = s.strokes[4].points[0].co - s.strokes[3].points[0].co
else:
v2 = s.strokes[3].points[0].co - s.strokes[2].points[0].co
if (v1.x and v2.x) != 0:
propx = v1.x / v2.x
em.custom_scale[0] *= abs(propx)
CoDEmanX
committed
if not em.custom_linkscale:
v1 = s.strokes[2].points[0].co - s.strokes[0].points[0].co
v2 = s.strokes[5].points[0].co - s.strokes[3].points[0].co
if (v1.y and v2.y) != 0:
propy = v1.y / v2.y
em.custom_scale[1] *= abs(propy)
bpy.ops.gpencil.active_frame_delete()
CoDEmanX
committed
# Operator Class to configure all what's needed
class AddBProjectionPlane(Operator):
bl_idname = "object.addbprojectionplane"
bl_label = "Configure"
CoDEmanX
committed
def creatematerial(self, context):
if 'Material for BProjection' not in [mat.name for mat in bpy.data.materials]:
bpy.data.textures.new(name='Texture for BProjection', type='IMAGE')
CoDEmanX
committed
bpy.data.materials.new(name='Material for BProjection')
CoDEmanX
committed
matBProjection = bpy.data.materials['Material for BProjection']
matBProjection.texture_slots.add()
matBProjection.use_shadeless = True
matBProjection.use_transparency = True
matBProjection.active_texture = bpy.data.textures['Texture for BProjection']
CoDEmanX
committed
index = matBProjection.active_texture_index
matBProjection.texture_slots[index].texture_coords = 'UV'
CoDEmanX
committed
ob = context.object
old_index = ob.active_material_index
bpy.ops.object.material_slot_add()
index = ob.active_material_index
ob.material_slots[index].material = bpy.data.materials['Material for BProjection']
bpy.ops.object.material_slot_assign()
ob.active_material_index = old_index
ob.data.update()
CoDEmanX
committed
def execute(self, context):
if BProjection_Empty not in [ob.name for ob in bpy.data.objects]:
CoDEmanX
committed
cm = bpy.context.object.mode
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
CoDEmanX
committed
context.space_data.show_relationship_lines = False
CoDEmanX
committed
CoDEmanX
committed
bpy.ops.object.add()
em = context.object
em.name = BProjection_Empty
CoDEmanX
committed
context.view_layer.objects.active = ob
CoDEmanX
committed
bpy.ops.object.editmode_toggle()
CoDEmanX
committed
bpy.ops.mesh.primitive_plane_add()
# fix the vertex group creation
bpy.ops.object.vertex_group_assign_new()
CoDEmanX
committed
ob.vertex_groups.active.name = 'texture plane'
CoDEmanX
committed
bpy.ops.mesh.select_all(action='DESELECT')
bpy.ops.object.vertex_group_select()
CoDEmanX
committed
bpy.ops.object.editmode_toggle()
for i in range(4):