1

What I have:

select two points then click “First” (get length between), then other two points - click “Second” (get length between), and then click “Scale” and get value “Second / First”.

Am I right with code, or somewhere it can be simplified? enter image description here

import bpy

import bmesh from bpy.types import Operator, Panel, PropertyGroup

def get_float1(self): return self["l1"]

def set_float1(self, value): self["l1"] = value

def get_float2(self): return self["l2"]

def set_float2(self, value): self["l2"] = value

def length_first(): obj = bpy.context.edit_object me = obj.data bm = bmesh.from_edit_mesh(me)

elem_list1 = []

for g in bm.select_history:
    elem_list1.append(g)

lf1 = elem_list1[0].co
lf2 = elem_list1[1].co

length1 = (lf2 - lf1).length
print("First value =", length1)
return length1

def length_second():
obj = bpy.context.edit_object me = obj.data bm = bmesh.from_edit_mesh(me)

elem_list2 = []

for g in bm.select_history:
    elem_list2.append(g)

ls1 = elem_list2[0].co
ls2 = elem_list2[1].co

length2 = (ls2 - ls1).length    
print("Second value =", length2)    
return length2  


class VERTS_OT_length (Operator): bl_idname = "verts.length" bl_label = "l" bl_description = ""

action: bpy.props.EnumProperty (
    items=[('first','first',''),
           ('second','second',''),
           ('scale','scale','')])

def execute(self, context):
    props  = context.scene.LENGTH_PG_main
    if self.action == "first":            
        props.l1 = length_first()            
    if self.action == "second":
        props.l2 = length_second()
    if self.action == "scale":
        scale = props.l2 / props.l1
        print("----------------------")
        #print(props.l1)
        #print(props.l2)
        print("Scale =", scale)
    return {'FINISHED'}


class LENGTH_PG_main (PropertyGroup):

l1: bpy.props.FloatProperty(
    name="Get",
    subtype="DISTANCE",
    get=get_float1,
    set=set_float1
)

l2: bpy.props.FloatProperty(
    name="Set",
    subtype="DISTANCE",
    get=get_float2,
    set=set_float2
)


class TEST_PT_main(Panel): bl_label = "TEST" bl_space_type = 'VIEW_3D' bl_region_type = 'UI' bl_category = 'TEST'

def draw(self, context):
    layout = self.layout
    col = layout.column(align = True)
    row1 = col.row(align = True)        
    props  = context.scene.LENGTH_PG_main
    row1.prop(props, "l1", text="")
    row1.operator("verts.length", text="First").action = "first"

    col = layout.column(align = True)
    row2 = col.row(align = True)        
    props  = context.scene.LENGTH_PG_main
    row2.prop(props, "l2", text="")
    row2.operator("verts.length", text="Second").action = "second"

    col = layout.column()
    col.operator("verts.length", text="Scale").action = "scale"


classes = ( VERTS_OT_length, LENGTH_PG_main, TEST_PT_main, )

register, unregister = bpy.utils.register_classes_factory(classes)

def register():
for c in classes: bpy.utils.register_class(c)

bpy.types.Scene.LENGTH_PG_main = bpy.props.PointerProperty(type = LENGTH_PG_main)

def unregister(): for c in classes: bpy.utils.unregister_class(c)

del bpy.types.Scene.LENGTH_PG_main

if name == "main": register()

APEC
  • 570
  • 3
  • 12

1 Answers1

1

so answer is:

  1. def length_first() and def length_second() can be merged in one def length()
def length():
    obj = bpy.context.edit_object
    me = obj.data
    bm = bmesh.from_edit_mesh(me)
elem_list1 = []

for g in bm.select_history:
    elem_list1.append(g)

lf1 = elem_list1[0].co
lf2 = elem_list1[1].co

distance = (lf2 - lf1).length
return length

  1. as @batFINGER sugested
def get_float1(self):
    return self["l1"]

def set_float1(self, value): self["l1"] = value

def get_float2(self): return self["l2"]

def set_float2(self, value): self["l2"] = value

need to replace with own properties to not get error like KeyError: 'bpy_struct[key]: key "l1" not found'

The final code for me look like this:

import bpy

import bmesh from bpy.types import Operator, Panel, PropertyGroup

def get_float1(self): props = bpy.context.scene.LENGTH_PG_main return props.dist1

def set_float1(self, value): props = bpy.context.scene.LENGTH_PG_main props.dist1 = value

def get_float2(self): props = bpy.context.scene.LENGTH_PG_main return props.dist2

def set_float2(self, value): props = bpy.context.scene.LENGTH_PG_main props.dist2 = value

def length():
obj = bpy.context.edit_object me = obj.data bm = bmesh.from_edit_mesh(me)

elem_list2 = []

for g in bm.select_history:
    elem_list2.append(g)

ls1 = elem_list2[0].co
ls2 = elem_list2[1].co

length = (ls2 - ls1).length    
print("Second value =", length)    
return length  


class VERTS_OT_length (Operator): bl_idname = "verts.length" bl_label = "l" bl_description = ""

action: bpy.props.EnumProperty (
    items=[('first','first',''),
           ('second','second',''),
           ('scale','scale','')])

def execute(self, context):
    props  = context.scene.LENGTH_PG_main
    if self.action == "first":            
        props.l1 = length()            
    if self.action == "second":
        props.l2 = length()
    if self.action == "scale":
        scale = props.l2 / props.l1
        print("----------------------")
        #print(props.l1)
        #print(props.l2)
        print("Scale =", scale)
    return {'FINISHED'}


class LENGTH_PG_main (PropertyGroup):

dist1: bpy.props.FloatProperty(default=1)
dist2: bpy.props.FloatProperty(default=1)

l1: bpy.props.FloatProperty(
    name="Get",
    subtype="DISTANCE",
    get=get_float1,
    set=set_float1
)

l2: bpy.props.FloatProperty(
    name="Set",
    subtype="DISTANCE",
    get=get_float2,
    set=set_float2
)    

class TEST_PT_main(Panel): bl_label = "TEST" bl_space_type = 'VIEW_3D' bl_region_type = 'UI' bl_category = 'TEST'

def draw(self, context):
    layout = self.layout
    col = layout.column(align = True)
    row1 = col.row(align = True)        
    props  = context.scene.LENGTH_PG_main
    row1.prop(props, "l1", text="")
    row1.operator("verts.length", text="First").action = "first"

    col = layout.column(align = True)
    row2 = col.row(align = True)        
    props  = context.scene.LENGTH_PG_main
    row2.prop(props, "l2", text="")
    row2.operator("verts.length", text="Second").action = "second"

    col = layout.column()
    col.operator("verts.length", text="Scale").action = "scale"


classes = ( VERTS_OT_length, LENGTH_PG_main, TEST_PT_main, )

register, unregister = bpy.utils.register_classes_factory(classes)

def register():
for c in classes: bpy.utils.register_class(c)

bpy.types.Scene.LENGTH_PG_main = bpy.props.PointerProperty(type = LENGTH_PG_main)

def unregister(): for c in classes: bpy.utils.unregister_class(c)

del bpy.types.Scene.LENGTH_PG_main

if name == "main": register()

Hope it will be useful.

APEC
  • 570
  • 3
  • 12