You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
180 lines
8.7 KiB
180 lines
8.7 KiB
|
2 weeks ago
|
import bpy
|
||
|
|
import bmesh
|
||
|
|
import os
|
||
|
|
import sys
|
||
|
|
import json
|
||
|
|
import numpy as np
|
||
|
|
from mathutils import Vector
|
||
|
|
from ..project_config import PROJECT_CONFIG
|
||
|
|
sys.path.append(PROJECT_CONFIG.executable_dir_path)
|
||
|
|
sys.path.append(PROJECT_CONFIG.library_dir_path)
|
||
|
|
import datetime
|
||
|
|
|
||
|
|
class LoginOperator(bpy.types.Operator):
|
||
|
|
bl_idname = "wm.login_operator"
|
||
|
|
bl_label = "Login"
|
||
|
|
|
||
|
|
username: bpy.props.StringProperty(name="Username")
|
||
|
|
password: bpy.props.StringProperty(name="Password", subtype='PASSWORD')
|
||
|
|
credentials_path = os.path.join(PROJECT_CONFIG.workplace_dir_path, "parameters", "credentials.json")
|
||
|
|
login_status_path = os.path.join(PROJECT_CONFIG.workplace_dir_path, "parameters", "login_status.json")
|
||
|
|
|
||
|
|
def execute(self, context):
|
||
|
|
with open(self.credentials_path, 'r') as f:
|
||
|
|
credentials = json.load(f)
|
||
|
|
|
||
|
|
if self.username in credentials and self.password == credentials[self.username]:
|
||
|
|
print("Login successful")
|
||
|
|
with open(self.login_status_path, 'w') as f:
|
||
|
|
json.dump({'logged_in': True, 'login_time': str(datetime.datetime.now())}, f)
|
||
|
|
return {'FINISHED'}
|
||
|
|
else:
|
||
|
|
print("Login failed")
|
||
|
|
bpy.ops.wm.quit_blender()
|
||
|
|
return {'CANCELLED'}
|
||
|
|
|
||
|
|
|
||
|
|
class SurfaceHoleOperator(bpy.types.Operator):
|
||
|
|
bl_idname: str = "designauto.texture_3d_surface_hole"
|
||
|
|
bl_label: str = "表面打孔纹理"
|
||
|
|
bl_options = {"REGISTER", "UNDO"}
|
||
|
|
|
||
|
|
single_parameter_file_path=os.path.join(PROJECT_CONFIG.workplace_dir_path, "parameters", "single.txt")
|
||
|
|
with open(single_parameter_file_path, 'r') as param_file:
|
||
|
|
lines = param_file.readlines()
|
||
|
|
for line in lines:
|
||
|
|
parts = line.strip().split(':')
|
||
|
|
if len(parts) == 2:
|
||
|
|
param_name = parts[0].strip()
|
||
|
|
param_value = parts[1].strip()
|
||
|
|
# 根据参数名称设置相应的属性值
|
||
|
|
if param_name == "Hole Height":
|
||
|
|
hole_height_arg = float(param_value)
|
||
|
|
elif param_name == "Hole Radius":
|
||
|
|
hole_radius_arg = float(param_value)
|
||
|
|
elif param_name == "Use Honeycomb Type":
|
||
|
|
use_honeycomb_type_arg = param_value.lower() == "true"
|
||
|
|
elif param_name == "Is Bridge":
|
||
|
|
is_bridge_arg = param_value.lower() == "true"
|
||
|
|
elif param_name == "Hole Distance":
|
||
|
|
hole_distance_arg = float(param_value)
|
||
|
|
elif param_name == "Texture Style":
|
||
|
|
texture_style_arg = str(param_value)
|
||
|
|
elif param_name == "Use_sharp_edge":
|
||
|
|
use_sharp_edge_arg = param_value.lower() == "true"
|
||
|
|
elif param_name == "Angle_of_se":
|
||
|
|
angle_of_se_arg = float(param_value)
|
||
|
|
elif param_name == "Area_threshold":
|
||
|
|
area_threshold_arg = int(param_value)
|
||
|
|
elif param_name == "Boundary_Margin":
|
||
|
|
boundary_margin_arg = float(param_value)
|
||
|
|
elif param_name == "Number ID":
|
||
|
|
number_id_arg = int(param_value)
|
||
|
|
|
||
|
|
style_items = [
|
||
|
|
('圆台1', '圆台1', ''),
|
||
|
|
('圆台2', '圆台2', ''),
|
||
|
|
('圆柱', '圆柱', ''),
|
||
|
|
('方形', '方形', ''),
|
||
|
|
('三角形', '三角形', ''),
|
||
|
|
('六边形', '六边形', ''),
|
||
|
|
('八边形', '八边形', '')
|
||
|
|
]
|
||
|
|
hole_height: bpy.props.FloatProperty(name="孔洞深度", default=hole_height_arg)
|
||
|
|
hole_radius: bpy.props.FloatProperty(name="孔洞半径", default=hole_radius_arg)
|
||
|
|
use_honeycomb_type:bpy.props.BoolProperty(name="蜂窝型", default=use_honeycomb_type_arg)
|
||
|
|
is_bridge:bpy.props.BoolProperty(name="桥", default=is_bridge_arg)
|
||
|
|
hole_distance: bpy.props.FloatProperty(name="孔洞间距", default=hole_distance_arg)
|
||
|
|
texture_style:bpy.props.EnumProperty(name="纹理样式",items=style_items,
|
||
|
|
description="Choose the style of texture", default="圆柱")
|
||
|
|
use_sharp_edge: bpy.props.BoolProperty(name="使用锐边算法", default=use_sharp_edge_arg)
|
||
|
|
angle_of_se:bpy.props.FloatProperty(name="锐边阈值", default=angle_of_se_arg)
|
||
|
|
area_threshold:bpy.props.IntProperty(name="面积阈值", default=area_threshold_arg)
|
||
|
|
boundary_margin:bpy.props.FloatProperty(name="边缘距离",
|
||
|
|
description="边缘距离", default=boundary_margin_arg)
|
||
|
|
number_id:bpy.props.IntProperty(name="数字id",
|
||
|
|
description="ID", default=number_id_arg)
|
||
|
|
save:bpy.props.BoolProperty(name="保存参数",
|
||
|
|
description="save", default=True)
|
||
|
|
|
||
|
|
|
||
|
|
def execute(self, context):
|
||
|
|
|
||
|
|
working_object = context.active_object
|
||
|
|
bpyscene = bpy.context.scene
|
||
|
|
|
||
|
|
workplace = PROJECT_CONFIG.workplace_dir_path
|
||
|
|
executable_path = PROJECT_CONFIG.executable_dir_path
|
||
|
|
tri_mesh_path = os.path.join(workplace, "assets", "model.obj")
|
||
|
|
|
||
|
|
bpy.ops.export_scene.obj(filepath=tri_mesh_path, use_selection=True, axis_forward='Y', axis_up='Z', use_edges=False, use_animation=False, use_materials=False, use_uvs=False, use_normals=False,
|
||
|
|
use_mesh_modifiers=False, use_nurbs=False, use_smooth_groups=False, use_vertex_groups=False, use_blen_objects=False, use_smooth_groups_bitflags=False)
|
||
|
|
|
||
|
|
import dapy_t3d_surface_hole
|
||
|
|
os.chdir(executable_path)
|
||
|
|
sample_distance = 2.0*self.hole_radius+self.hole_distance
|
||
|
|
hole_factor = 2.0*self.hole_radius / sample_distance
|
||
|
|
texture_num = 0
|
||
|
|
if self.texture_style == "圆台1":
|
||
|
|
texture_num=1
|
||
|
|
elif self.texture_style == "圆台2":
|
||
|
|
texture_num=2
|
||
|
|
elif self.texture_style == "圆柱":
|
||
|
|
texture_num=3
|
||
|
|
elif self.texture_style == "方形":
|
||
|
|
texture_num=4
|
||
|
|
elif self.texture_style == "三角形":
|
||
|
|
texture_num=5
|
||
|
|
elif self.texture_style == "六边形":
|
||
|
|
texture_num=6
|
||
|
|
elif self.texture_style == "八边形":
|
||
|
|
texture_num=7
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
if self.is_bridge == True:
|
||
|
|
mesh_with_hole = dapy_t3d_surface_hole.GenerateSurfaceHoles( self.hole_height, hole_factor,self.use_honeycomb_type,
|
||
|
|
sample_distance,texture_num,self.use_sharp_edge,self.angle_of_se,self.area_threshold,self.boundary_margin,self.number_id,False,True)
|
||
|
|
else :
|
||
|
|
mesh_with_hole = dapy_t3d_surface_hole.GenerateSurfaceHoles( self.hole_height, hole_factor,self.use_honeycomb_type,
|
||
|
|
sample_distance, texture_num,self.use_sharp_edge,self.angle_of_se,self.area_threshold,self.boundary_margin,self.number_id,False,False)
|
||
|
|
|
||
|
|
working_object.hide_set(True)
|
||
|
|
new_mesh = bpy.data.meshes.new("mesh-" + working_object.name + "-hole")
|
||
|
|
new_mesh.from_pydata(mesh_with_hole.mat_coordinates.tolist(), [], mesh_with_hole.mat_faces.tolist())
|
||
|
|
new_mesh.update()
|
||
|
|
new_object = bpy.data.objects.new(working_object.name + "-hole", new_mesh)
|
||
|
|
found = False
|
||
|
|
for c in bpy.data.collections:
|
||
|
|
if c.name == 'designauto':
|
||
|
|
found = True
|
||
|
|
new_collection = c
|
||
|
|
if not found:
|
||
|
|
new_collection = bpy.data.collections.new('designauto')
|
||
|
|
bpy.context.scene.collection.children.link(new_collection)
|
||
|
|
new_collection.objects.link(new_object)
|
||
|
|
|
||
|
|
working_object.select_set(True)
|
||
|
|
|
||
|
|
if self.save == True:
|
||
|
|
with open(self.single_parameter_file_path, 'w') as param_file:
|
||
|
|
param_file.write(f"Hole Height: {self.hole_height}\n")
|
||
|
|
param_file.write(f"Hole Radius: {self.hole_radius}\n")
|
||
|
|
param_file.write(f"Use Honeycomb Type: {self.use_honeycomb_type}\n")
|
||
|
|
param_file.write(f"Is Bridge: {self.is_bridge}\n")
|
||
|
|
param_file.write(f"Hole Distance: {self.hole_distance}\n")
|
||
|
|
param_file.write(f"Texture Style: {self.texture_style}\n")
|
||
|
|
param_file.write(f"Use_sharp_edge: {self.use_sharp_edge}\n")
|
||
|
|
param_file.write(f"Angle_of_se: {self.angle_of_se}\n")
|
||
|
|
param_file.write(f"Area_threshold: {self.area_threshold_arg}\n")
|
||
|
|
param_file.write(f"Boundary_Margin: {self.boundary_margin}\n")
|
||
|
|
param_file.write(f"Number ID: {self.number_id}\n")
|
||
|
|
return {'FINISHED'}
|
||
|
|
|
||
|
|
def invoke(self, context, event):
|
||
|
|
if context.active_object.type == 'MESH':
|
||
|
|
return context.window_manager.invoke_props_dialog(self)
|
||
|
|
else:
|
||
|
|
self.report({'ERROR'}, "Selected object is not a mesh!")
|
||
|
|
return {'CANCELLED'}
|