Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/工单文件优化
# Conflicts: # sf_manufacturing/models/mrp_workorder.py
This commit is contained in:
@@ -10,7 +10,7 @@
|
||||
""",
|
||||
'category': 'sf',
|
||||
'website': 'https://www.sf.jikimo.com',
|
||||
'depends': ['mrp', 'base', 'sf_manufacturing', 'purchase', 'mrp_subcontracting'],
|
||||
'depends': ['mrp', 'base', 'sf_manufacturing'],
|
||||
'data': [
|
||||
'data/product_data.xml',
|
||||
'views/product_template_view.xml'
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<field name="type">原材料</field>
|
||||
</record>
|
||||
|
||||
<record id="product_template_sf" model="product.template">
|
||||
<record id="product_template_sf" model="product.product">
|
||||
<field name="name">CNC加工产品模板</field>
|
||||
<field name="active" eval="False"/>
|
||||
<field name="categ_id" ref="product_category_finished_sf"/>
|
||||
@@ -31,7 +31,7 @@
|
||||
<field name="tracking">serial</field>
|
||||
|
||||
</record>
|
||||
<record id="product_embryo_sf_self_machining" model="product.template">
|
||||
<record id="product_embryo_sf_self_machining" model="product.product">
|
||||
<field name="name">胚料自加工模板</field>
|
||||
<field name="active" eval="False"/>
|
||||
<field name="categ_id" ref="product_category_embryo_sf"/>
|
||||
@@ -48,7 +48,7 @@
|
||||
<!-- <field name="active" eval="False"/>-->
|
||||
</record>
|
||||
|
||||
<record id="product_embryo_sf_outsource" model="product.template">
|
||||
<record id="product_embryo_sf_outsource" model="product.product">
|
||||
<field name="name">胚料外协加工模板</field>
|
||||
<field name="active" eval="False"/>
|
||||
<field name="categ_id" ref="product_category_embryo_sf"/>
|
||||
@@ -63,7 +63,7 @@
|
||||
<field name="tracking">serial</field>
|
||||
<!-- <field name="active" eval="False"/>-->
|
||||
</record>
|
||||
<record id="product_embryo_sf_purchase" model="product.template">
|
||||
<record id="product_embryo_sf_purchase" model="product.product">
|
||||
<field name="name">胚料采购模板</field>
|
||||
<field name="active" eval="False"/>
|
||||
<field name="categ_id" ref="product_category_embryo_sf"/>
|
||||
|
||||
11
sf_dlm/data/uom_data.xml
Normal file
11
sf_dlm/data/uom_data.xml
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo noupdate="1">
|
||||
<!-- UOM.UOM -->
|
||||
<!-- VOLUME -->
|
||||
<record id="product_uom_cubic_millimeter" model="uom.uom">
|
||||
<field name="name">立方毫米</field>
|
||||
<field name="category_id" ref="uom.product_uom_categ_vol"/>
|
||||
<field name="factor_inv">1000</field>
|
||||
<field name="uom_type">bigger</field>
|
||||
</record>
|
||||
</odoo>
|
||||
@@ -1,12 +1,17 @@
|
||||
from odoo import models, fields, api
|
||||
from odoo.exceptions import ValidationError
|
||||
import logging
|
||||
import base64
|
||||
import os
|
||||
# from OCC.Extend.DataExchange import read_step_file, write_stl_file
|
||||
from odoo.modules import get_resource_path
|
||||
|
||||
|
||||
class ResProductTemplate(models.Model):
|
||||
_inherit = 'product.template'
|
||||
|
||||
# 模型的长,宽,高,体积,精度,材料
|
||||
model_name = fields.Char('模型名称')
|
||||
model_long = fields.Float('模型长[mm]', digits=(16, 3))
|
||||
model_width = fields.Float('模型宽[mm]', digits=(16, 3))
|
||||
model_height = fields.Float('模型高[mm]', digits=(16, 3))
|
||||
@@ -29,6 +34,17 @@ class ResProductTemplate(models.Model):
|
||||
materials_id = fields.Many2one('sf.production.materials', string='材料')
|
||||
materials_type_id = fields.Many2one('sf.materials.model', string='材料型号')
|
||||
single_manufacturing = fields.Boolean(string="单个制造")
|
||||
upload_model_file = fields.Many2many('ir.attachment', 'upload_model_file_attachment_ref', string='上传模型文件')
|
||||
model_code = fields.Char('模型编码')
|
||||
|
||||
def _get_volume_uom_id_from_ir_config_parameter(self):
|
||||
product_length_in_feet_param = self.env['ir.config_parameter'].sudo().get_param('product.volume_in_cubic_feet')
|
||||
if product_length_in_feet_param == '1':
|
||||
return self.env.ref('uom.product_uom_cubic_foot')
|
||||
else:
|
||||
return self.env.ref('sf_dlm.product_uom_cubic_millimeter')
|
||||
|
||||
# model_file = fields.Binary('模型文件')
|
||||
|
||||
# 胚料的库存路线设置
|
||||
# def _get_routes(self, route_type):
|
||||
@@ -53,59 +69,82 @@ class ResProductTemplate(models.Model):
|
||||
# 业务平台分配工厂后在智能工厂先创建销售订单再创建该产品
|
||||
def product_create(self, product_id, item, order_id, order_number, i):
|
||||
copy_product_id = product_id.with_user(self.env.ref("base.user_admin")).copy()
|
||||
# copy_product_id.product_tmpl_id.active = True
|
||||
copy_product_id.product_tmpl_id.active = True
|
||||
model_type = self.env['sf.model.type'].search([], limit=1)
|
||||
attachment = self.attachment_create(item['model_name'], item['model_data'])
|
||||
vals = {
|
||||
'name': '%s-%s' % (order_id.name, i),
|
||||
'model_long': item['model_long'],
|
||||
'model_width': item['model_width'],
|
||||
'model_height': item['model_height'],
|
||||
'model_long': item['model_long'] + model_type.embryo_tolerance,
|
||||
'model_width': item['model_width'] + model_type.embryo_tolerance,
|
||||
'model_height': item['model_height'] + model_type.embryo_tolerance,
|
||||
'model_volume': (item['model_long'] + model_type.embryo_tolerance) * (
|
||||
item['model_width'] + model_type.embryo_tolerance) * (
|
||||
item['model_height'] + model_type.embryo_tolerance),
|
||||
'model_type_id': 1,
|
||||
'model_machining_precision': item['model_machining_precision'],
|
||||
'model_processing_panel': 'R,U',
|
||||
# 'model_machining_precision': item['model_machining_precision'],
|
||||
'model_processing_panel': 'R',
|
||||
'model_machining_precision': '±0.10mm',
|
||||
'model_code': item['barcode'],
|
||||
'length': item['model_long'],
|
||||
'width': item['model_width'],
|
||||
'height': item['model_height'],
|
||||
'volume': (item['model_long'] * item['model_width'] * item['model_height']),
|
||||
# 'model_price': item['price'],
|
||||
'volume': item['model_long'] * item['model_width'] * item['model_height'],
|
||||
'model_file': '' if not item['model_file'] else base64.b64decode(item['model_file']),
|
||||
'model_name': attachment.name,
|
||||
'upload_model_file': [(6, 0, [attachment.id])],
|
||||
# 'single_manufacturing': True,
|
||||
'tracking': 'serial',
|
||||
'list_price': item['price'],
|
||||
# 'categ_id': self.env.ref('sf_dlm.product_category_finished_sf').id,
|
||||
'materials_id': self.env['sf.production.materials'].search(
|
||||
[('materials_no', '=', item['texture_code'])]).id,
|
||||
'materials_type_id': self.env['sf.materials.model'].search(
|
||||
[('materials_no', '=', item['texture_type_code'])]).id,
|
||||
# 'model_surface_process_id': self.env['sf.production.process'].search(
|
||||
# [('process_encode', '=', item['surface_process_code'])]).id,
|
||||
'model_surface_process_id': self.env['sf.production.process'].search(
|
||||
[('process_encode', '=', item['surface_process_code'])]).id,
|
||||
# 'model_process_parameters_id': self.env['sf.processing.technology'].search(
|
||||
# [('process_encode', '=', item['process_parameters_code'])]).id,
|
||||
'model_remark': item['remark'],
|
||||
'default_code': '%s-%s' % (order_number, i),
|
||||
'barcode': item['barcode'],
|
||||
# 'barcode': item['barcode'],
|
||||
'active': True,
|
||||
# 'route_ids': self._get_routes('')
|
||||
}
|
||||
copy_product_id.sudo().write(vals)
|
||||
# product_id.active = False
|
||||
# product_id.product_tmpl_id.active = False
|
||||
return copy_product_id
|
||||
|
||||
def attachment_create(self, name, data):
|
||||
attachment = self.env['ir.attachment'].create({
|
||||
'datas': base64.b64decode(data),
|
||||
'type': 'binary',
|
||||
'description': '模型文件',
|
||||
'name': name
|
||||
})
|
||||
return attachment
|
||||
|
||||
# 创建胚料
|
||||
def no_bom_product_create(self, product_id, item, order_id, route_type):
|
||||
def no_bom_product_create(self, product_id, item, order_id, route_type, i):
|
||||
no_bom_copy_product_id = product_id.with_user(self.env.ref("base.user_admin")).copy()
|
||||
# no_bom_copy_product_id.product_tmpl_id.active = True
|
||||
no_bom_copy_product_id.product_tmpl_id.active = True
|
||||
materials_id = self.env['sf.production.materials'].search(
|
||||
[('materials_no', '=', item['texture_code'])])
|
||||
materials_type_id = self.env['sf.materials.model'].search(
|
||||
[('materials_no', '=', item['texture_type_code'])])
|
||||
model_type = self.env['sf.model.type'].search([], limit=1)
|
||||
supplier = self.env['mrp.bom'].get_supplier(materials_type_id)
|
||||
logging.info('no_bom_copy_product_supplier-vals:%s' % supplier)
|
||||
vals = {
|
||||
'name': '%s %s %s %s * %s * %s' % (
|
||||
order_id.name, materials_id.name, materials_type_id.name, item['model_long'], item['model_width'],
|
||||
item['model_height']),
|
||||
'length': item['model_long'],
|
||||
'width': item['model_width'],
|
||||
'height': item['model_height'],
|
||||
'volume': item['model_long'] * item['model_width'] * item['model_height'],
|
||||
'name': '%s-%s %s %s %s * %s * %s' % (
|
||||
order_id.name, i, materials_id.name, materials_type_id.name,
|
||||
item['model_long'] + model_type.embryo_tolerance, item['model_width'] + model_type.embryo_tolerance,
|
||||
item['model_height'] + model_type.embryo_tolerance),
|
||||
'length': item['model_long'] + model_type.embryo_tolerance,
|
||||
'width': item['model_width'] + model_type.embryo_tolerance,
|
||||
'height': item['model_height'] + model_type.embryo_tolerance,
|
||||
'volume': (item['model_long'] + model_type.embryo_tolerance) * (
|
||||
item['model_width'] + model_type.embryo_tolerance) * (
|
||||
item['model_height'] + model_type.embryo_tolerance),
|
||||
# 'model_price': item['price'],
|
||||
'list_price': item['price'],
|
||||
'materials_id': materials_id.id,
|
||||
@@ -131,22 +170,32 @@ class ResProductTemplate(models.Model):
|
||||
logging.info('no_bom_copy_product_id-seller_ids-vals:%s' % no_bom_copy_product_id.seller_ids)
|
||||
no_bom_copy_product_id.write(vals)
|
||||
logging.info('no_bom_copy_product_id-vals:%s' % vals)
|
||||
# product_id.active = False
|
||||
# product_id.product_tmpl_id.active = False
|
||||
return no_bom_copy_product_id
|
||||
|
||||
# 根据模型类型默认给模型的长高宽加配置的长度;
|
||||
@api.onchange('model_type_id')
|
||||
def add_product_size(self):
|
||||
if not self.model_type_id:
|
||||
return
|
||||
model_type = self.env['sf.model.type'].search(
|
||||
[('id', '=', self.model_type_id.id), ('embryo_tolerance', '=', True)])
|
||||
if model_type:
|
||||
self.model_long = self.model_long + 1
|
||||
self.model_width = self.model_width + 1
|
||||
self.model_height = self.model_width + 1
|
||||
else:
|
||||
return
|
||||
# @api.onchange('upload_model_file')
|
||||
# def onchange_model_file(self):
|
||||
# for item in self:
|
||||
# if len(item.upload_model_file) > 1:
|
||||
# raise ValidationError('只允许上传一个文件')
|
||||
# if item.upload_model_file:
|
||||
# file_attachment_id = item.upload_model_file[0]
|
||||
# item.model_name = file_attachment_id.name
|
||||
# # 附件路径
|
||||
# report_path = file_attachment_id._full_path(file_attachment_id.store_fname)
|
||||
# shapes = read_step_file(report_path)
|
||||
# output_file = get_resource_path('sf_dlm', 'static/file', 'out.stl')
|
||||
# write_stl_file(shapes, output_file, 'binary', 0.03, 0.5)
|
||||
# # 转化为glb
|
||||
# output_glb_file = get_resource_path('sf_dlm', 'static/file', 'out.glb')
|
||||
# util_path = get_resource_path('sf_dlm', 'static/util')
|
||||
# cmd = 'python %s/stl2gltf.py %s %s -b' % (util_path, output_file, output_glb_file)
|
||||
# os.system(cmd)
|
||||
# # 转base64
|
||||
# with open(output_glb_file, 'rb') as fileObj:
|
||||
# image_data = fileObj.read()
|
||||
# base64_data = base64.b64encode(image_data)
|
||||
# item.model_file = base64_data
|
||||
|
||||
|
||||
class ResMrpBom(models.Model):
|
||||
@@ -207,8 +256,6 @@ class ResMrpBom(models.Model):
|
||||
|
||||
# 匹配bom
|
||||
def get_bom(self, product):
|
||||
logging.info('get_bom-product:%s' % product)
|
||||
logging.info('get_bom-product:%s' % product.materials_type_id.id)
|
||||
embryo_has = self.env['product.product'].search(
|
||||
[('categ_id.type', '=', '胚料'), ('materials_type_id', '=', product.materials_type_id.id),
|
||||
('length', '>', product.length), ('width', '>', product.width),
|
||||
@@ -220,7 +267,7 @@ class ResMrpBom(models.Model):
|
||||
logging.info('get_bom-vals:%s' % embryo_has)
|
||||
if embryo_has:
|
||||
rate_of_waste = ((embryo_has.volume - product.model_volume) % embryo_has.volume) * 100
|
||||
if rate_of_waste >= 20:
|
||||
if rate_of_waste <= 20:
|
||||
return embryo_has
|
||||
else:
|
||||
return
|
||||
|
||||
BIN
sf_dlm/static/file/out.glb
Normal file
BIN
sf_dlm/static/file/out.glb
Normal file
Binary file not shown.
BIN
sf_dlm/static/file/out.stl
Normal file
BIN
sf_dlm/static/file/out.stl
Normal file
Binary file not shown.
277
sf_dlm/static/util/stl2gltf.py
Normal file
277
sf_dlm/static/util/stl2gltf.py
Normal file
@@ -0,0 +1,277 @@
|
||||
import os
|
||||
|
||||
def stl_to_gltf(binary_stl_path, out_path, is_binary):
|
||||
import struct
|
||||
|
||||
gltf2 = '''
|
||||
{
|
||||
"scenes" : [
|
||||
{
|
||||
"nodes" : [ 0 ]
|
||||
}
|
||||
],
|
||||
"nodes" : [
|
||||
{
|
||||
"mesh" : 0
|
||||
}
|
||||
],
|
||||
"meshes" : [
|
||||
{
|
||||
"primitives" : [ {
|
||||
"attributes" : {
|
||||
"POSITION" : 1
|
||||
},
|
||||
"indices" : 0
|
||||
} ]
|
||||
}
|
||||
],
|
||||
"buffers" : [
|
||||
{
|
||||
%s
|
||||
"byteLength" : %d
|
||||
}
|
||||
],
|
||||
"bufferViews" : [
|
||||
{
|
||||
"buffer" : 0,
|
||||
"byteOffset" : 0,
|
||||
"byteLength" : %d,
|
||||
"target" : 34963
|
||||
},
|
||||
{
|
||||
"buffer" : 0,
|
||||
"byteOffset" : %d,
|
||||
"byteLength" : %d,
|
||||
"target" : 34962
|
||||
}
|
||||
],
|
||||
"accessors" : [
|
||||
{
|
||||
"bufferView" : 0,
|
||||
"byteOffset" : 0,
|
||||
"componentType" : 5125,
|
||||
"count" : %d,
|
||||
"type" : "SCALAR",
|
||||
"max" : [ %d ],
|
||||
"min" : [ 0 ]
|
||||
},
|
||||
{
|
||||
"bufferView" : 1,
|
||||
"byteOffset" : 0,
|
||||
"componentType" : 5126,
|
||||
"count" : %d,
|
||||
"type" : "VEC3",
|
||||
"min" : [%f, %f, %f],
|
||||
"max" : [%f, %f, %f]
|
||||
}
|
||||
],
|
||||
"asset" : {
|
||||
"version" : "2.0"
|
||||
}
|
||||
}
|
||||
'''
|
||||
|
||||
header_bytes = 80
|
||||
unsigned_long_int_bytes = 4
|
||||
float_bytes = 4
|
||||
vec3_bytes = 4 * 3
|
||||
spacer_bytes = 2
|
||||
num_vertices_in_face = 3
|
||||
|
||||
vertices = {}
|
||||
indices = []
|
||||
|
||||
if not is_binary:
|
||||
out_bin = os.path.join(out_path, "out.bin")
|
||||
out_gltf = os.path.join(out_path, "out.gltf")
|
||||
else:
|
||||
out_bin = out_path
|
||||
|
||||
unpack_face = struct.Struct("<12fH").unpack
|
||||
face_bytes = float_bytes*12 + 2
|
||||
|
||||
with open(path_to_stl, "rb") as f:
|
||||
f.seek(header_bytes) # skip 80 bytes headers
|
||||
|
||||
num_faces_bytes = f.read(unsigned_long_int_bytes)
|
||||
number_faces = struct.unpack("<I", num_faces_bytes)[0]
|
||||
|
||||
# the vec3_bytes is for normal
|
||||
stl_assume_bytes = header_bytes + unsigned_long_int_bytes + number_faces * (vec3_bytes*3 + spacer_bytes + vec3_bytes)
|
||||
assert stl_assume_bytes == os.path.getsize(path_to_stl), "stl is not binary or ill formatted"
|
||||
|
||||
minx, maxx = [9999999, -9999999]
|
||||
miny, maxy = [9999999, -9999999]
|
||||
minz, maxz = [9999999, -9999999]
|
||||
|
||||
vertices_length_counter = 0
|
||||
|
||||
data = struct.unpack("<" + "12fH"*number_faces, f.read())
|
||||
len_data = len(data)
|
||||
|
||||
for i in range(0, len_data, 13):
|
||||
for j in range(3, 12, 3):
|
||||
x, y, z = data[i+j:i+j+3]
|
||||
|
||||
x = int(x*100000)/100000
|
||||
y = int(y*100000)/100000
|
||||
z = int(z*100000)/100000
|
||||
|
||||
tuple_xyz = (x, y, z);
|
||||
|
||||
try:
|
||||
indices.append(vertices[tuple_xyz])
|
||||
except KeyError:
|
||||
vertices[tuple_xyz] = vertices_length_counter
|
||||
vertices_length_counter += 1
|
||||
indices.append(vertices[tuple_xyz])
|
||||
|
||||
|
||||
|
||||
if x < minx: minx = x
|
||||
if x > maxx: maxx = x
|
||||
if y < miny: miny = y
|
||||
if y > maxy: maxy = y
|
||||
if z < minz: minz = z
|
||||
if z > maxz: maxz = z
|
||||
|
||||
# f.seek(spacer_bytes, 1) # skip the spacer
|
||||
|
||||
number_vertices = len(vertices)
|
||||
vertices_bytelength = number_vertices * vec3_bytes # each vec3 has 3 floats, each float is 4 bytes
|
||||
unpadded_indices_bytelength = number_vertices * unsigned_long_int_bytes
|
||||
|
||||
out_number_vertices = len(vertices)
|
||||
out_number_indices = len(indices)
|
||||
|
||||
unpadded_indices_bytelength = out_number_indices * unsigned_long_int_bytes
|
||||
indices_bytelength = (unpadded_indices_bytelength + 3) & ~3
|
||||
|
||||
out_bin_bytelength = vertices_bytelength + indices_bytelength
|
||||
|
||||
if is_binary:
|
||||
out_bin_uir = ""
|
||||
else:
|
||||
out_bin_uir = '"uri": "out.bin",'
|
||||
|
||||
gltf2 = gltf2 % ( out_bin_uir,
|
||||
#buffer
|
||||
out_bin_bytelength,
|
||||
|
||||
# bufferViews[0]
|
||||
indices_bytelength,
|
||||
|
||||
# bufferViews[1]
|
||||
indices_bytelength,
|
||||
vertices_bytelength,
|
||||
|
||||
# accessors[0]
|
||||
out_number_indices,
|
||||
out_number_vertices - 1,
|
||||
|
||||
# accessors[1]
|
||||
out_number_vertices,
|
||||
minx, miny, minz,
|
||||
maxx, maxy, maxz
|
||||
)
|
||||
|
||||
glb_out = bytearray()
|
||||
if is_binary:
|
||||
gltf2 = gltf2.replace(" ", "")
|
||||
gltf2 = gltf2.replace("\n", "")
|
||||
|
||||
scene = bytearray(gltf2.encode())
|
||||
|
||||
scene_len = len(scene)
|
||||
padded_scene_len = (scene_len + 3) & ~3
|
||||
body_offset = padded_scene_len + 12 + 8
|
||||
|
||||
file_len = body_offset + out_bin_bytelength + 8
|
||||
|
||||
# 12-byte header
|
||||
glb_out.extend(struct.pack('<I', 0x46546C67)) # magic number for glTF
|
||||
glb_out.extend(struct.pack('<I', 2))
|
||||
glb_out.extend(struct.pack('<I', file_len))
|
||||
|
||||
# chunk 0
|
||||
glb_out.extend(struct.pack('<I', padded_scene_len))
|
||||
glb_out.extend(struct.pack('<I', 0x4E4F534A)) # magic number for JSON
|
||||
glb_out.extend(scene)
|
||||
|
||||
while len(glb_out) < body_offset:
|
||||
glb_out.extend(b' ')
|
||||
|
||||
# chunk 1
|
||||
glb_out.extend(struct.pack('<I', out_bin_bytelength))
|
||||
glb_out.extend(struct.pack('<I', 0x004E4942)) # magin number for BIN
|
||||
|
||||
# print('<%dI' % len(indices))
|
||||
# print(struct.pack('<%dI' % len(indices), *indices))
|
||||
glb_out.extend(struct.pack('<%dI' % len(indices), *indices))
|
||||
|
||||
for i in range(indices_bytelength - unpadded_indices_bytelength):
|
||||
glb_out.extend(b' ')
|
||||
|
||||
vertices = dict((v, k) for k,v in vertices.items())
|
||||
|
||||
# glb_out.extend(struct.pack('f',
|
||||
# print([each_v for vertices[v_counter] for v_counter in range(number_vertices)]) # magin number for BIN
|
||||
vertices = [vertices[i] for i in range(number_vertices)]
|
||||
flatten = lambda l: [item for sublist in l for item in sublist]
|
||||
|
||||
# for v_counter in :
|
||||
# v_3f = vertices[v_counter]
|
||||
# all_floats_in_vertices.append(v_3f[0])
|
||||
# all_floats_in_vertices.append(v_3f[1])
|
||||
# all_floats_in_vertices.append(v_3f[2])
|
||||
|
||||
# for v_counter in range(number_vertices):
|
||||
glb_out.extend(struct.pack('%df' % number_vertices*3, *flatten(vertices))) # magin number for BIN
|
||||
|
||||
# for v_counter in range(number_vertices):
|
||||
# glb_out.extend(struct.pack('3f', *vertices[v_counter])) # magin number for BIN
|
||||
|
||||
# for (v_x, v_y, v_z), _ in sorted(vertices.items(), key=lambda x: x[1]):
|
||||
# glb_out.extend(struct.pack('3f', v_x, v_y, v_z)) # magin number for BIN
|
||||
# # glb_out.extend(struct.pack('f', v_y)) # magin number for BIN
|
||||
# # glb_out.extend(struct.pack('f', v_z)) # magin number for BIN
|
||||
|
||||
with open(out_bin, "wb") as out:
|
||||
out.write(glb_out)
|
||||
|
||||
if not is_binary:
|
||||
with open(out_gltf, "w") as out:
|
||||
out.write(gltf2)
|
||||
|
||||
print("Done! Exported to %s" %out_path)
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
|
||||
if len(sys.argv) < 3:
|
||||
print("use it like python3 stl_to_gltf.py /path/to/stl /path/to/gltf/folder")
|
||||
print("or python3 stl_to_gltf.py /path/to/stl /path/to/glb/file -b")
|
||||
sys.exit(1)
|
||||
|
||||
path_to_stl = sys.argv[1]
|
||||
out_path = sys.argv[2]
|
||||
if len(sys.argv) > 3:
|
||||
is_binary = True
|
||||
else:
|
||||
is_binary = False
|
||||
|
||||
if out_path.lower().endswith(".glb"):
|
||||
print("Use binary mode since output file has glb extension")
|
||||
is_binary = True
|
||||
else:
|
||||
if is_binary:
|
||||
print("output file should have glb extension but not %s", out_path)
|
||||
|
||||
if not os.path.exists(path_to_stl):
|
||||
print("stl file does not exists %s" % path_to_stl)
|
||||
|
||||
if not is_binary:
|
||||
if not os.path.isdir(out_path):
|
||||
os.mkdir(out_path)
|
||||
|
||||
stl_to_gltf(path_to_stl, out_path, is_binary)
|
||||
@@ -6,7 +6,13 @@
|
||||
<field name="model">product.template</field>
|
||||
<field name="inherit_id" ref="product.product_template_only_form_view"/>
|
||||
<field name="arch" type="xml">
|
||||
<!-- <field name="image_1920" position="replace">-->
|
||||
<!-- <field name="upload_model_file" required="True"-->
|
||||
<!-- widget='many2many_binary'/>-->
|
||||
<!-- </field>-->
|
||||
|
||||
<field name="invoice_policy" position="after">
|
||||
<field name="model_file" required="True" widget="model_viewer"/>
|
||||
<field name="materials_id" string="材料"/>
|
||||
<field name="materials_type_id" string="型号"
|
||||
domain="[('materials_id', '=', materials_id)]"/>
|
||||
@@ -101,8 +107,8 @@
|
||||
<field name="inherit_id" ref="mrp.mrp_bom_form_view"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="subcontractor_ids" position="replace">
|
||||
<field name="subcontractor_id" widget="many2one_tags" readonly="1"
|
||||
attrs="{'invisible':[('type', 'in', ['normal','phantom'])]}"/>
|
||||
<field name="subcontractor_id"
|
||||
attrs="{'invisible': [('type', '!=', 'subcontract')], 'required': [('type', '=', 'subcontract')]}"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
Reference in New Issue
Block a user