4 from mathutils
import *
5 from gpu_extras
.batch
import batch_for_shader
8 "name":"Carve exporter",
9 "author": "Harry Godden (hgn)",
16 "category":"Import/Export",
19 class mdl_vert(Structure
):
21 _fields_
= [("co",c_float
*3),
26 class mdl_submesh(Structure
):
28 _fields_
= [("indice_start",c_uint32
),
29 ("indice_count",c_uint32
),
30 ("vertex_start",c_uint32
),
31 ("vertex_count",c_uint32
),
32 ("bbx",(c_float
*3)*2),
33 ("material_id",c_uint32
)] # index into the material array
35 class mdl_material(Structure
):
37 _fields_
= [("pstr_name",c_uint32
)]
39 class mdl_node(Structure
):
41 _fields_
= [("co",c_float
*3),
44 ("submesh_start",c_uint32
),
45 ("submesh_count",c_uint32
),
46 ("classtype",c_uint32
),
48 ("pstr_name",c_uint32
)]
50 class mdl_header(Structure
):
52 _fields_
= [("identifier",c_uint32
),
54 ("file_length",c_uint32
),
55 ("vertex_count",c_uint32
),
56 ("vertex_offset",c_uint32
),
58 ("indice_count",c_uint32
),
59 ("indice_offset",c_uint32
),
61 ("submesh_count",c_uint32
),
62 ("submesh_offset",c_uint32
),
64 ("material_count",c_uint32
),
65 ("material_offset",c_uint32
),
67 ("node_count",c_uint32
),
68 ("node_offset",c_uint32
),
70 ("strings_offset",c_uint32
),
71 ("entdata_offset",c_uint32
)
75 # ==========================================
77 class classtype_gate(Structure
):
79 _fields_
= [("target",c_uint32
),
82 class classtype_block(Structure
):
84 _fields_
= [("bbx",(c_float
*3)*2)]
86 class classtype_spawn(Structure
):
88 _fields_
= [("temp",c_uint32
)]
90 class classtype_water(Structure
):
92 _fields_
= [("temp",c_uint32
)]
94 class classtype_car_path(Structure
):
96 _fields_
= [("target",c_uint32
),
99 class classtype_instance(Structure
):
101 _fields_
= [("pstr_file",c_uint32
)]
103 class classtype_capsule(Structure
):
105 _fields_
= [("height",c_float
),
108 class classtype_route_node(Structure
):
110 _fields_
= [("target",c_uint32
),
111 ("target1",c_uint32
)]
113 class classtype_route(Structure
):
115 _fields_
= [("pstr_name",c_uint32
),
116 ("id_start",c_uint32
),
117 ("colour",c_float
*3)]
120 # ==============================================================================
122 def write_model(name
):
123 print( F
"Create mode {name}" )
125 header
= mdl_header()
126 header
.identifier
= 0xABCD0000
128 header
.vertex_count
= 0
129 header
.indice_count
= 0
130 header
.submesh_count
= 0
131 header
.node_count
= 0
132 header
.material_count
= 0
133 header
.file_length
= 0
149 def emplace_string( s
):
150 nonlocal string_cache
, strings_buffer
152 if s
in string_cache
:
153 return string_cache
[s
]
155 string_cache
[s
] = len( strings_buffer
)
156 strings_buffer
+= (s
+'\0').encode('utf-8')
157 return string_cache
[s
]
159 def emplace_material( mat
):
160 nonlocal material_cache
, material_buffer
162 if mat
.name
in material_cache
:
163 return material_cache
[mat
.name
]
165 material_cache
[mat
.name
] = header
.material_count
166 dest
= mdl_material()
167 dest
.pstr_name
= emplace_string( mat
.name
)
168 material_buffer
+= [dest
]
170 header
.material_count
+= 1
171 return material_cache
[mat
.name
]
173 # Create root or empty node and materials
175 none_material
= c_uint32(69)
176 none_material
.name
= ""
177 emplace_material( none_material
)
190 root
.pstr_name
= emplace_string('')
191 root
.submesh_start
= 0
192 root
.submesh_count
= 0
195 node_buffer
+= [root
]
199 print( " assigning ids" )
200 collection
= bpy
.data
.collections
[name
]
202 header
.node_count
= 1
203 for obj
in collection
.all_objects
:
204 obj
.cv_data
.uid
= header
.node_count
205 header
.node_count
+= 1
207 print( " compiling data" )
208 for obj
in collection
.all_objects
:
209 print( F
" [{obj.cv_data.uid}/{header.node_count-1}] {obj.name}" )
212 node
.co
[0] = obj
.location
[0]
213 node
.co
[1] = obj
.location
[2]
214 node
.co
[2] = -obj
.location
[1]
216 # Convert rotation quat to our space type
217 quat
= obj
.matrix_world
.to_quaternion()
223 node
.s
[0] = obj
.scale
[0]
224 node
.s
[1] = obj
.scale
[2]
225 node
.s
[2] = obj
.scale
[1]
226 node
.pstr_name
= emplace_string( obj
.name
)
228 # Process entity data
230 node
.offset
= entdata_length
231 classtype
= obj
.cv_data
.classtype
233 if classtype
== 'k_classtype_gate':
235 entdata_length
+= sizeof( classtype_gate
)
237 gate
= classtype_gate()
239 if obj
.cv_data
.target
!= None:
240 gate
.target
= obj
.cv_data
.target
.cv_data
.uid
242 if obj
.type == 'MESH':
243 gate
.dims
[0] = obj
.data
.cv_data
.v0
[0]
244 gate
.dims
[1] = obj
.data
.cv_data
.v0
[1]
245 gate
.dims
[2] = obj
.data
.cv_data
.v0
[2]
247 gate
.dims
[0] = obj
.cv_data
.v0
[0]
248 gate
.dims
[1] = obj
.cv_data
.v0
[1]
249 gate
.dims
[2] = obj
.cv_data
.v0
[2]
251 entdata_buffer
+= [gate
]
253 elif classtype
== 'k_classtype_block':
255 entdata_length
+= sizeof( classtype_block
)
257 source
= obj
.data
.cv_data
259 block
= classtype_block()
260 block
.bbx
[0][0] = source
.v0
[0]
261 block
.bbx
[0][1] = source
.v0
[2]
262 block
.bbx
[0][2] = -source
.v1
[1]
264 block
.bbx
[1][0] = source
.v1
[0]
265 block
.bbx
[1][1] = source
.v1
[2]
266 block
.bbx
[1][2] = -source
.v0
[1]
267 entdata_buffer
+= [block
]
269 elif classtype
== 'k_classtype_spawn':
272 elif classtype
== 'k_classtype_water':
274 elif classtype
== 'k_classtype_car_path':
276 entdata_length
+= sizeof( classtype_car_path
)
278 pn
= classtype_car_path()
282 if obj
.cv_data
.target
!= None:
283 pn
.target
= obj
.cv_data
.target
.cv_data
.uid
284 if obj
.cv_data
.target1
!= None:
285 pn
.target1
= obj
.cv_data
.target1
.cv_data
.uid
287 entdata_buffer
+= [pn
]
288 elif obj
.is_instancer
:
289 target
= obj
.instance_collection
292 entdata_length
+= sizeof( classtype_instance
)
294 inst
= classtype_instance()
295 inst
.pstr_file
= emplace_string( F
"models/{target.name}.mdl" )
296 entdata_buffer
+= [inst
]
297 elif classtype
== 'k_classtype_capsule':
299 elif classtype
== 'k_classtype_route_node':
301 entdata_length
+= sizeof( classtype_route_node
)
303 rn
= classtype_route_node()
304 if obj
.cv_data
.target
!= None:
305 rn
.target
= obj
.cv_data
.target
.cv_data
.uid
306 if obj
.cv_data
.target1
!= None:
307 rn
.target1
= obj
.cv_data
.target1
.cv_data
.uid
309 entdata_buffer
+= [rn
]
310 elif classtype
== 'k_classtype_route':
312 entdata_length
+= sizeof( classtype_route
)
313 r
= classtype_route()
314 r
.pstr_name
= emplace_string("not-implemented")
315 r
.colour
[0] = obj
.cv_data
.colour
[0]
316 r
.colour
[1] = obj
.cv_data
.colour
[1]
317 r
.colour
[2] = obj
.cv_data
.colour
[2]
319 if obj
.cv_data
.target
!= None:
320 r
.id_start
= obj
.cv_data
.target
.cv_data
.uid
322 entdata_buffer
+= [r
]
324 # classtype == 'k_classtype_none':
331 node
.submesh_start
= header
.submesh_count
332 node
.submesh_count
= 0
334 if obj
.type == 'MESH':
335 default_mat
= c_uint32(69)
336 default_mat
.name
= ""
338 # Dont use the cache if we have modifiers that affect the normals
341 for mod
in obj
.modifiers
:
342 if mod
.type == 'DATA_TRANSFER':
345 if use_cache
and obj
.data
.name
in mesh_cache
:
346 ref
= mesh_cache
[obj
.data
.name
]
347 node
.submesh_start
= ref
.submesh_start
348 node
.submesh_count
= ref
.submesh_count
349 node_buffer
+= [node
]
352 dgraph
= bpy
.context
.evaluated_depsgraph_get()
353 data
= obj
.evaluated_get(dgraph
).data
354 data
.calc_loop_triangles()
355 data
.calc_normals_split()
357 mat_list
= data
.materials
if len(data
.materials
) > 0 else [default_mat
]
358 for material_id
, mat
in enumerate(mat_list
):
362 sm
.indice_start
= header
.indice_count
363 sm
.vertex_start
= header
.vertex_count
366 sm
.material_id
= emplace_material( mat
)
369 sm
.bbx
[0][i
] = 999999
370 sm
.bbx
[1][i
] = -999999
374 # Write the vertex / indice data
376 for tri_index
, tri
in enumerate(data
.loop_triangles
):
377 if tri
.material_index
!= material_id
:
381 vert
= data
.vertices
[tri
.vertices
[j
]]
385 norm
= data
.loops
[li
].normal
389 uv
= data
.uv_layers
.active
.data
[li
].uv
390 if data
.vertex_colors
:
391 colour
= data
.vertex_colors
.active
.data
[li
].color
394 m
= float(10**TOLERENCE
)
396 key
= (int(co
[0]*m
+0.5),\
404 int(colour
[0]*m
+0.5),\
405 int(colour
[1]*m
+0.5),\
406 int(colour
[2]*m
+0.5),\
407 int(colour
[3]*m
+0.5))
410 indice_buffer
+= [boffa
[key
]]
412 index
= c_uint32(sm
.vertex_count
)
416 indice_buffer
+= [index
]
427 v
.colour
[0] = colour
[0]
428 v
.colour
[1] = colour
[1]
429 v
.colour
[2] = colour
[2]
430 v
.colour
[3] = colour
[3]
434 sm
.bbx
[0][i
] = min( sm
.bbx
[0][i
], v
.co
[i
] )
435 sm
.bbx
[1][i
] = max( sm
.bbx
[1][i
], v
.co
[i
] )
439 if sm
.vertex_count
== 0:
444 submesh_buffer
+= [sm
]
445 node
.submesh_count
+= 1
446 header
.submesh_count
+= 1
447 header
.vertex_count
+= sm
.vertex_count
448 header
.indice_count
+= sm
.indice_count
450 mesh_cache
[obj
.data
.name
] = node
451 node_buffer
+= [node
]
455 print( "Writing data" )
456 fpos
= sizeof(header
)
458 header
.node_offset
= fpos
459 fpos
+= sizeof(mdl_node
)*header
.node_count
461 header
.submesh_offset
= fpos
462 fpos
+= sizeof(mdl_submesh
)*header
.submesh_count
464 header
.material_offset
= fpos
465 fpos
+= sizeof(mdl_material
)*header
.material_count
467 header
.entdata_offset
= fpos
468 fpos
+= entdata_length
470 header
.vertex_offset
= fpos
471 fpos
+= sizeof(mdl_vert
)*header
.vertex_count
473 header
.indice_offset
= fpos
474 fpos
+= sizeof(c_uint32
)*header
.indice_count
476 header
.strings_offset
= fpos
477 fpos
+= len(strings_buffer
)
479 header
.file_length
= fpos
481 fp
= open(F
"/home/harry/Documents/carve/models/{name}.mdl", "wb")
482 fp
.write( bytearray( header
) )
484 for node
in node_buffer
:
485 fp
.write( bytearray(node
) )
486 for sm
in submesh_buffer
:
487 fp
.write( bytearray(sm
) )
488 for mat
in material_buffer
:
489 fp
.write( bytearray(mat
) )
490 for ed
in entdata_buffer
:
491 fp
.write( bytearray(ed
) )
492 for v
in vertex_buffer
:
493 fp
.write( bytearray(v
) )
494 for i
in indice_buffer
:
495 fp
.write( bytearray(i
) )
496 fp
.write( strings_buffer
)
499 print( F
"Completed {name}.mdl" )
502 # ------------------------------------------------------------------------------
504 cv_view_draw_handler
= None
505 cv_view_shader
= gpu
.shader
.from_builtin('3D_SMOOTH_COLOR')
508 global cv_view_shader
509 cv_view_shader
.bind()
510 gpu
.state
.depth_mask_set(False)
511 gpu
.state
.line_width_set(2.0)
512 gpu
.state
.face_culling_set('BACK')
513 gpu
.state
.depth_test_set('LESS')
514 gpu
.state
.blend_set('NONE')
519 #def drawbezier(p0,h0,p1,h1,c0,c1):
520 # nonlocal verts, colours
524 # colours += [(0.5,0.5,0.5,1.0),(0.5,0.5,0.5,1)]
527 # colours += [(1.0,1.0,1,1),(1,1,1,1)]
530 # for i in range(10):
536 # p=ttt*p1+(3*tt-3*ttt)*h1+(3*ttt-6*tt+3*t)*h0+(3*tt-ttt-3*t+1)*p0
537 # verts += [(last[0],last[1],last[2])]
538 # verts += [(p[0],p[1],p[2])]
539 # colours += [c0*a0+c1*(1-a0),c0*a0+c1*(1-a0)]
544 def drawbhandle(obj
, direction
, colour
):
545 nonlocal verts
, colours
547 h0
= obj
.matrix_world
@ Vector((0,direction
,0))
550 colours
+= [colour
,colour
]
552 def drawbezier(p0
,h0
,p1
,h1
,c0
,c1
):
553 nonlocal verts
, colours
562 p
=ttt
*p1
+(3*tt
-3*ttt
)*h1
+(3*ttt
-6*tt
+3*t
)*h0
+(3*tt
-ttt
-3*t
+1)*p0
563 verts
+= [(last
[0],last
[1],last
[2])]
564 verts
+= [(p
[0],p
[1],p
[2])]
565 colours
+= [c0
*a0
+c1
*(1-a0
),c0
*a0
+c1
*(1-a0
)]
568 def drawsbpath(o0
,o1
,c0
,c1
,s0
,s1
):
569 nonlocal course_count
571 offs
= ((course_count
% 2)*2-1) * course_count
* 0.02
573 p0
= o0
.matrix_world
@ Vector((offs
, 0,0))
574 h0
= o0
.matrix_world
@ Vector((offs
, s0
,0))
575 p1
= o1
.matrix_world
@ Vector((offs
, 0,0))
576 h1
= o1
.matrix_world
@ Vector((offs
,-s1
,0))
577 drawbezier(p0
,h0
,p1
,h1
,c0
,c1
)
579 def drawbpath(o0
,o1
,c0
,c1
):
580 drawsbpath(o0
,o1
,c0
,c1
,1.0,1.0)
582 def drawbline(p0
,p1
,c0
,c1
):
583 nonlocal verts
, colours
587 for obj
in bpy
.context
.collection
.objects
:
589 if obj
.cv_data
.classtype
== 'k_classtype_gate':
590 if obj
.type == 'MESH':
591 dims
= obj
.data
.cv_data
.v0
593 dims
= obj
.cv_data
.v0
596 c
= Vector((0,0,dims
[2]))
598 vs
[0] = obj
.matrix_world
@ Vector((-dims
[0],0.0,-dims
[1]+dims
[2]))
599 vs
[1] = obj
.matrix_world
@ Vector((-dims
[0],0.0, dims
[1]+dims
[2]))
600 vs
[2] = obj
.matrix_world
@ Vector(( dims
[0],0.0, dims
[1]+dims
[2]))
601 vs
[3] = obj
.matrix_world
@ Vector(( dims
[0],0.0,-dims
[1]+dims
[2]))
602 vs
[4] = obj
.matrix_world
@ (c
+Vector((-1,0,-2)))
603 vs
[5] = obj
.matrix_world
@ (c
+Vector((-1,0, 2)))
604 vs
[6] = obj
.matrix_world
@ (c
+Vector(( 1,0, 2)))
605 vs
[7] = obj
.matrix_world
@ (c
+Vector((-1,0, 0)))
606 vs
[8] = obj
.matrix_world
@ (c
+Vector(( 1,0, 0)))
608 indices
= [(0,1),(1,2),(2,3),(3,0),(4,5),(5,6),(7,8)]
613 verts
+= [(v0
[0],v0
[1],v0
[2])]
614 verts
+= [(v1
[0],v1
[1],v1
[2])]
615 colours
+= [(1,1,0,1),(1,1,0,1)]
617 sw
= (0.4,0.4,0.4,0.2)
618 if obj
.cv_data
.target
!= None:
619 drawbline( obj
.location
, obj
.cv_data
.target
.location
, sw
,sw
)
621 elif obj
.cv_data
.classtype
== 'k_classtype_route_node':
622 sw
= Vector((0.4,0.4,0.4,0.2))
623 sw2
= Vector((1.5,0.2,0.2,0.0))
624 if obj
.cv_data
.target
!= None:
625 drawbpath( obj
, obj
.cv_data
.target
, sw
, sw
)
626 if obj
.cv_data
.target1
!= None:
627 drawbpath( obj
, obj
.cv_data
.target1
, sw
, sw
)
629 drawbhandle( obj
, 1.0, (0.8,0.8,0.8,1.0) )
630 drawbhandle( obj
, -1.0, (0.4,0.4,0.4,1.0) )
633 obj
.matrix_world
.to_quaternion() @ Vector((0,0,-6+1.5))
634 drawbline( obj
.location
, p1
, sw
,sw2
)
637 elif obj
.cv_data
.classtype
== 'k_classtype_block':
638 a
= obj
.data
.cv_data
.v0
639 b
= obj
.data
.cv_data
.v1
642 vs
[0] = obj
.matrix_world
@ Vector((a
[0], a
[1], a
[2]))
643 vs
[1] = obj
.matrix_world
@ Vector((a
[0], b
[1], a
[2]))
644 vs
[2] = obj
.matrix_world
@ Vector((b
[0], b
[1], a
[2]))
645 vs
[3] = obj
.matrix_world
@ Vector((b
[0], a
[1], a
[2]))
646 vs
[4] = obj
.matrix_world
@ Vector((a
[0], a
[1], b
[2]))
647 vs
[5] = obj
.matrix_world
@ Vector((a
[0], b
[1], b
[2]))
648 vs
[6] = obj
.matrix_world
@ Vector((b
[0], b
[1], b
[2]))
649 vs
[7] = obj
.matrix_world
@ Vector((b
[0], a
[1], b
[2]))
651 indices
= [(0,1),(1,2),(2,3),(3,0),(4,5),(5,6),(6,7),(7,4),\
652 (0,4),(1,5),(2,6),(3,7)]
657 verts
+= [(v0
[0],v0
[1],v0
[2])]
658 verts
+= [(v1
[0],v1
[1],v1
[2])]
659 colours
+= [(1,1,0,1),(1,1,0,1)]
661 elif obj
.cv_data
.classtype
== 'k_classtype_capsule':
662 h
= obj
.data
.cv_data
.v0
[0]
663 r
= obj
.data
.cv_data
.v0
[1]
666 vs
[0] = obj
.matrix_world
@ Vector((0.0,0.0, h
*0.5 ))
667 vs
[1] = obj
.matrix_world
@ Vector((0.0,0.0,-h
*0.5 ))
668 vs
[2] = obj
.matrix_world
@ Vector(( r
,0.0, h
*0.5-r
))
669 vs
[3] = obj
.matrix_world
@ Vector(( -r
,0.0, h
*0.5-r
))
670 vs
[4] = obj
.matrix_world
@ Vector(( r
,0.0,-h
*0.5+r
))
671 vs
[5] = obj
.matrix_world
@ Vector(( -r
,0.0,-h
*0.5+r
))
672 vs
[6] = obj
.matrix_world
@ Vector((0.0, r
, h
*0.5-r
))
673 vs
[7] = obj
.matrix_world
@ Vector((0.0,-r
, h
*0.5-r
))
674 vs
[8] = obj
.matrix_world
@ Vector((0.0, r
,-h
*0.5+r
))
675 vs
[9] = obj
.matrix_world
@ Vector((0.0,-r
,-h
*0.5+r
))
677 indices
= [(0,1),(2,3),(4,5),(6,7),(8,9)]
682 verts
+= [(v0
[0],v0
[1],v0
[2])]
683 verts
+= [(v1
[0],v1
[1],v1
[2])]
684 colours
+= [(0.5,1,0,1),(0.5,1,0,1)]
686 elif obj
.cv_data
.classtype
== 'k_classtype_spawn':
688 vs
[0] = obj
.matrix_world
@ Vector((0,0,0))
689 vs
[1] = obj
.matrix_world
@ Vector((0,2,0))
690 vs
[2] = obj
.matrix_world
@ Vector((0.5,1,0))
691 vs
[3] = obj
.matrix_world
@ Vector((-0.5,1,0))
692 indices
= [(0,1),(1,2),(1,3)]
696 verts
+= [(v0
[0],v0
[1],v0
[2])]
697 verts
+= [(v1
[0],v1
[1],v1
[2])]
698 colours
+= [(0,1,1,1),(0,1,1,1)]
700 elif obj
.cv_data
.classtype
== 'k_classtype_route':
703 vs
[1] = obj
.cv_data
.target
.location
708 verts
+= [(v0
[0],v0
[1],v0
[2])]
709 verts
+= [(v1
[0],v1
[1],v1
[2])]
710 colours
+= [(0,1,1,1),(0,1,1,1)]
714 stack
[0] = obj
.cv_data
.target
716 loop_complete
= False
719 if stack_i
[si
-1] == 2:
723 if si
== 0: # Loop failed to complete
728 targets
= [None,None]
729 targets
[0] = node
.cv_data
.target
731 if node
.cv_data
.classtype
== 'k_classtype_route_node':
732 targets
[1] = node
.cv_data
.target1
734 nextnode
= targets
[stack_i
[si
-1]]
737 if nextnode
!= None: # branch
738 if nextnode
== stack
[0]: # Loop completed
744 if stack
[sj
] == nextnode
: # invalidated path
755 cc
= Vector((obj
.cv_data
.colour
[0],\
756 obj
.cv_data
.colour
[1],\
757 obj
.cv_data
.colour
[2],\
763 if stack
[sj
].cv_data
.classtype
== 'k_classtype_gate' and \
764 stack
[sk
].cv_data
.classtype
== 'k_classtype_gate':
765 dist
= (stack
[sj
].location
-stack
[sk
].location
).magnitude
766 drawsbpath( stack
[sj
], stack
[sk
], cc
*0.4, cc
, dist
, dist
)
769 drawbpath( stack
[sj
], stack
[sk
], cc
, cc
)
773 elif obj
.cv_data
.classtype
== 'k_classtype_car_path':
774 v0
= obj
.matrix_world
.to_quaternion() @ Vector((0,1,0))
775 c0
= Vector((v0
.x
*0.5+0.5, v0
.y
*0.5+0.5, 0.0, 1.0))
776 drawbhandle( obj
, 1.0, (0.9,0.9,0.9,1.0) )
778 if obj
.cv_data
.target
!= None:
779 v1
= obj
.cv_data
.target
.matrix_world
.to_quaternion()@Vector((0,1,0))
780 c1
= Vector((v1
.x
*0.5+0.5, v1
.y
*0.5+0.5, 0.0, 1.0))
782 drawbhandle( obj
.cv_data
.target
, -1.0, (0.5,0.5,0.5,1.0) )
783 drawbpath( obj
, obj
.cv_data
.target
, c0
, c1
)
785 if obj
.cv_data
.target1
!= None:
786 v1
= obj
.cv_data
.target1
.matrix_world
.to_quaternion()@Vector((0,1,0))
787 c1
= Vector((v1
.x
*0.5+0.5, v1
.y
*0.5+0.5, 0.0, 1.0))
789 drawbhandle( obj
.cv_data
.target1
, -1.0, (0.5,0.5,0.5,1.0) )
790 drawbpath( obj
, obj
.cv_data
.target1
, c0
, c1
)
792 lines
= batch_for_shader(\
793 cv_view_shader
, 'LINES', \
794 { "pos":verts
, "color":colours
})
796 lines
.draw( cv_view_shader
)
798 def cv_poll_target(scene
, obj
):
799 if obj
== bpy
.context
.active_object
:
801 if obj
.cv_data
.classtype
== 'k_classtype_none':
805 class CV_MESH_SETTINGS(bpy
.types
.PropertyGroup
):
806 v0
: bpy
.props
.FloatVectorProperty(name
="v0",size
=3)
807 v1
: bpy
.props
.FloatVectorProperty(name
="v1",size
=3)
808 v2
: bpy
.props
.FloatVectorProperty(name
="v2",size
=3)
809 v3
: bpy
.props
.FloatVectorProperty(name
="v3",size
=3)
811 class CV_OBJ_SETTINGS(bpy
.types
.PropertyGroup
):
812 uid
: bpy
.props
.IntProperty( name
="" )
814 target
: bpy
.props
.PointerProperty( type=bpy
.types
.Object
, name
="target", \
815 poll
=cv_poll_target
)
816 target1
: bpy
.props
.PointerProperty( type=bpy
.types
.Object
, name
="target1", \
817 poll
=cv_poll_target
)
819 colour
: bpy
.props
.FloatVectorProperty(name
="colour",subtype
='COLOR',\
822 classtype
: bpy
.props
.EnumProperty(
825 ('k_classtype_none', "k_classtype_none", "", 0),
826 ('k_classtype_gate', "k_classtype_gate", "", 1),
827 ('k_classtype_block', "k_classtype_block", "", 2),
828 ('k_classtype_spawn', "k_classtype_spawn", "", 3),
829 ('k_classtype_water', "k_classtype_water", "", 4),
830 ('k_classtype_car_path', "k_classtype_car_path", "", 5),
831 ('k_classtype_capsule', "k_classtype_capsule", "", 7 ),
832 ('k_classtype_route_node', "k_classtype_route_node", "", 8 ),
833 ('k_classtype_route', "k_classtype_route", "", 9 )
836 class CV_OBJ_PANEL(bpy
.types
.Panel
):
837 bl_label
="Entity Config"
838 bl_idname
="SCENE_PT_cv_entity"
839 bl_space_type
='PROPERTIES'
840 bl_region_type
='WINDOW'
844 active_object
= bpy
.context
.active_object
845 if active_object
== None: return
846 _
.layout
.prop( active_object
.cv_data
, "classtype" )
848 if active_object
.cv_data
.classtype
== 'k_classtype_gate':
849 _
.layout
.prop( active_object
.cv_data
, "target" )
851 mesh
= active_object
.data
852 _
.layout
.label( text
=F
"(i) Data is stored in {mesh.name}" )
853 _
.layout
.prop( mesh
.cv_data
, "v0" )
855 elif active_object
.cv_data
.classtype
== 'k_classtype_car_path' or \
856 active_object
.cv_data
.classtype
== 'k_classtype_route_node':
857 _
.layout
.prop( active_object
.cv_data
, "target" )
858 _
.layout
.prop( active_object
.cv_data
, "target1" )
860 elif active_object
.cv_data
.classtype
== 'k_classtype_route':
861 _
.layout
.prop( active_object
.cv_data
, "target" )
862 _
.layout
.prop( active_object
.cv_data
, "colour" )
864 elif active_object
.cv_data
.classtype
== 'k_classtype_block':
865 mesh
= active_object
.data
867 _
.layout
.label( text
=F
"(i) Data is stored in {mesh.name}" )
868 _
.layout
.prop( mesh
.cv_data
, "v0" )
869 _
.layout
.prop( mesh
.cv_data
, "v1" )
870 _
.layout
.prop( mesh
.cv_data
, "v2" )
871 _
.layout
.prop( mesh
.cv_data
, "v3" )
872 elif active_object
.cv_data
.classtype
== 'k_classtype_capsule':
873 mesh
= active_object
.data
874 _
.layout
.label( text
=F
"(i) Data is stored in {mesh.name}" )
875 _
.layout
.prop( mesh
.cv_data
, "v0" )
877 class CV_INTERFACE(bpy
.types
.Panel
):
878 bl_idname
= "VIEW3D_PT_carve"
880 bl_space_type
= 'VIEW_3D'
881 bl_region_type
= 'UI'
882 bl_category
= "Carve"
884 def draw(_
, context
):
886 layout
.operator( "carve.compile_all" )
889 for col
in bpy
.data
.collections
["export"].children
:
890 write_model( col
.name
)
892 class CV_COMPILE(bpy
.types
.Operator
):
893 bl_idname
="carve.compile_all"
894 bl_label
="Compile All"
896 def execute(_
,context
):
898 #cProfile.runctx("test_compile()",globals(),locals(),sort=1)
899 #for col in bpy.data.collections["export"].children:
900 # write_model( col.name )
904 classes
= [CV_OBJ_SETTINGS
,CV_OBJ_PANEL
,CV_COMPILE
,CV_INTERFACE
,\
908 global cv_view_draw_handler
911 bpy
.utils
.register_class(c
)
913 bpy
.types
.Object
.cv_data
= bpy
.props
.PointerProperty(type=CV_OBJ_SETTINGS
)
914 bpy
.types
.Mesh
.cv_data
= bpy
.props
.PointerProperty(type=CV_MESH_SETTINGS
)
916 cv_view_draw_handler
= bpy
.types
.SpaceView3D
.draw_handler_add(\
917 cv_draw
,(),'WINDOW','POST_VIEW')
920 global cv_view_draw_handler
923 bpy
.utils
.unregister_class(c
)
925 bpy
.types
.SpaceView3D
.draw_handler_remove(cv_view_draw_handler
,'WINDOW')