+#
+# =============================================================================
+#
+# Copyright . . . -----, ,----- ,---. .---.
+# 2021-2022 |\ /| | / | | | | /|
+# | \ / | +-- / +----- +---' | / |
+# | \ / | | / | | \ | / |
+# | \/ | | / | | \ | / |
+# ' ' '--' [] '----- '----- ' ' '---' SOFTWARE
+#
+# =============================================================================
+#
+# Python exporter for Blender, compiles .mdl format for Skate Rift.
#
-# Copyright (C) 2021-2022 Mt.ZERO Software, Harry Godden - All Rights Reserved
+# Its really slow, sorry, I don't know how to speed it up.
+# Also not sure why you need to put # before {} in code blocks, there is errors
+# otherwise
#
import bpy, math, gpu
("s",c_float*3)]
#}
-# Entity types
-# ==========================================
+# ---------------------------------------------------------------------------- #
+# #
+# Entity definitions #
+# #
+# ---------------------------------------------------------------------------- #
#
# ctypes _fields_ defines the data which is filled in by:
# def encode_obj( _, node, node_def ):
#
# gizmos get drawn into the viewport via:
# @staticmethod
-# def editor_interface( object ):
+# def draw_scene_helpers( obj ):
+#
+# editor enterface, simiraliy:
+# @staticmethod
+# def editor_interface( layout, obj ):
#
+# Classtype 1
+#
+# Purpose: A rift. must target another gate, the target gate can not have more
+# than one target nodes of its own.
+#
class classtype_gate(Structure):
#{
_pack_ = 1
_.dims[2] = obj.cv_data.v0[2]
#}
#}
+
+ @staticmethod
+ def draw_scene_helpers( obj ):
+ #{
+ global cv_view_verts, cv_view_colours
+
+ if obj.type == 'MESH':
+ dims = obj.data.cv_data.v0
+ else:
+ dims = obj.cv_data.v0
+
+ vs = [None]*9
+ c = Vector((0,0,dims[2]))
+
+ vs[0] = obj.matrix_world @ Vector((-dims[0],0.0,-dims[1]+dims[2]))
+ vs[1] = obj.matrix_world @ Vector((-dims[0],0.0, dims[1]+dims[2]))
+ vs[2] = obj.matrix_world @ Vector(( dims[0],0.0, dims[1]+dims[2]))
+ vs[3] = obj.matrix_world @ Vector(( dims[0],0.0,-dims[1]+dims[2]))
+ vs[4] = obj.matrix_world @ (c+Vector((-1,0,-2)))
+ vs[5] = obj.matrix_world @ (c+Vector((-1,0, 2)))
+ vs[6] = obj.matrix_world @ (c+Vector(( 1,0, 2)))
+ vs[7] = obj.matrix_world @ (c+Vector((-1,0, 0)))
+ vs[8] = obj.matrix_world @ (c+Vector(( 1,0, 0)))
+
+ indices = [(0,1),(1,2),(2,3),(3,0),(4,5),(5,6),(7,8)]
+
+ for l in indices:
+ v0 = vs[l[0]]
+ v1 = vs[l[1]]
+ cv_view_verts += [(v0[0],v0[1],v0[2])]
+ cv_view_verts += [(v1[0],v1[1],v1[2])]
+ cv_view_colours += [(1,1,0,1),(1,1,0,1)]
+
+ sw = (0.4,0.4,0.4,0.2)
+ if obj.cv_data.target != None:
+ cv_draw_arrow( obj.location, obj.cv_data.target.location, sw )
+ #}
+
+ @staticmethod
+ def editor_interface( layout, obj ):
+ #{
+ layout.prop( obj.cv_data, "target" )
+
+ mesh = obj.data
+ layout.label( text=F"(i) Data is stored in {mesh.name}" )
+ layout.prop( mesh.cv_data, "v0", text="Gate dimensions" )
+ #}
#}
+# Classtype 3
+#
+# Purpose: player can reset here, its a safe place
+# spawns can share the same name, the closest one will be picked
+#
+# when the world loads it will pick the one named 'start' first.
+#
class classtype_spawn(Structure):
#{
_pack_ = 1
node.classtype = 3
_.pstr_alias = encoder_process_pstr( node_def['obj'].cv_data.strp )
#}
+
+ @staticmethod
+ def draw_scene_helpers( obj ):
+ #{
+ global cv_view_verts, cv_view_colours
+
+ vs = [None]*4
+ vs[0] = obj.matrix_world @ Vector((0,0,0))
+ vs[1] = obj.matrix_world @ Vector((0,2,0))
+ vs[2] = obj.matrix_world @ Vector((0.5,1,0))
+ vs[3] = obj.matrix_world @ Vector((-0.5,1,0))
+ indices = [(0,1),(1,2),(1,3)]
+
+ for l in indices:
+ #{
+ v0 = vs[l[0]]
+ v1 = vs[l[1]]
+
+ cv_view_verts += [(v0[0],v0[1],v0[2])]
+ cv_view_verts += [(v1[0],v1[1],v1[2])]
+ cv_view_colours += [(0,1,1,1),(0,1,1,1)]
+ #}
+ #}
+
+ @staticmethod
+ def editor_interface( layout, obj ):
+ #{
+ layout.prop( obj.cv_data, "strp", text="Alias" )
+ #}
#}
+# Classtype 4
+#
+# Purpose: Tells the game to draw water HERE, at this entity.
+#
class classtype_water(Structure):
#{
_pack_ = 1
#}
#}
+# Classtype 8
+#
+# Purpose: Defines a route node and links to up to two more nodes
+#
class classtype_route_node(Structure):
#{
_pack_ = 1
if obj.cv_data.target1 != None:
_.target1 = obj.cv_data.target1.cv_data.uid
#}
+
+ @staticmethod
+ def draw_scene_helpers( obj ):
+ #{
+ global cv_view_verts, cv_view_colours
+
+ sw = Vector((0.4,0.4,0.4,0.2))
+ sw2 = Vector((1.5,0.2,0.2,0.0))
+ if obj.cv_data.target != None:
+ cv_draw_bpath( obj, obj.cv_data.target, sw, sw )
+ if obj.cv_data.target1 != None:
+ cv_draw_bpath( obj, obj.cv_data.target1, sw, sw )
+
+ cv_draw_bhandle( obj, 1.0, (0.8,0.8,0.8,1.0) )
+ cv_draw_bhandle( obj, -1.0, (0.4,0.4,0.4,1.0) )
+
+ p1 = obj.location+ \
+ obj.matrix_world.to_quaternion() @ Vector((0,0,-6+1.5))
+ cv_draw_arrow( obj.location, p1, sw )
+ #}
+
+ @staticmethod
+ def editor_interface( layout, obj ):
+ #{
+ layout.prop( obj.cv_data, "target", text="Left" )
+ layout.prop( obj.cv_data, "target1", text="Right" )
+ #}
#}
+# Classtype 9
+#
+# Purpose: Defines a route, its 'starting' point, and the colour to use for it
+#
class classtype_route(Structure):
#{
_pack_ = 1
_fields_ = [("id_start",c_uint32),
+ ("pstr_name",c_uint32),
("colour",c_float*3)]
def encode_obj(_, node,node_def):
_.colour[0] = obj.cv_data.colour[0]
_.colour[1] = obj.cv_data.colour[1]
_.colour[2] = obj.cv_data.colour[2]
+ _.pstr_name = encoder_process_pstr( obj.cv_data.strp )
if obj.cv_data.target != None:
_.id_start = obj.cv_data.target.cv_data.uid
#}
+
+ @staticmethod
+ def draw_scene_helpers( obj ):
+ #{
+ global cv_view_verts, cv_view_colours, cv_view_course_i
+
+ if obj.cv_data.target:
+ cv_draw_arrow( obj.location, obj.cv_data.target.location, [1,1,1,1] )
+
+ # Tries to simulate how we do it in the game
+ #
+ stack = [None]*64
+ stack_i = [0]*64
+ stack[0] = obj.cv_data.target
+ si = 1
+ loop_complete = False
+
+ while si > 0:
+ #{
+ if stack_i[si-1] == 2:
+ #{
+ si -= 1
+ continue
+
+ if si == 0: # Loop failed to complete
+ break
+ #}
+
+ node = stack[si-1]
+
+ targets = [None,None]
+ targets[0] = node.cv_data.target
+
+ if node.cv_data.classtype == 'classtype_route_node':
+ #{
+ targets[1] = node.cv_data.target1
+ #}
+
+ nextnode = targets[stack_i[si-1]]
+ stack_i[si-1] += 1
+
+ if nextnode != None: # branch
+ #{
+ if nextnode == stack[0]: # Loop completed
+ #{
+ loop_complete = True
+ break
+ #}
+
+ valid=True
+ for sj in range(si):
+ #{
+ if stack[sj] == nextnode: # invalidated path
+ #{
+ valid=False
+ break
+ #}
+ #}
+
+ if valid:
+ #{
+ stack_i[si] = 0
+ stack[si] = nextnode
+ si += 1
+ continue
+ #}
+ #}
+ #}
+
+ if loop_complete:
+ #{
+ cc = Vector((obj.cv_data.colour[0],\
+ obj.cv_data.colour[1],\
+ obj.cv_data.colour[2],\
+ 1.0))
+
+ for sj in range(si):
+ #{
+ sk = (sj+1)%si
+
+ if stack[sj].cv_data.classtype == 'classtype_gate' and \
+ stack[sk].cv_data.classtype == 'classtype_gate':
+ #{
+ dist = (stack[sj].location-stack[sk].location).magnitude
+ cv_draw_sbpath( stack[sj], stack[sk], cc*0.4, cc, dist, dist )
+ #}
+ else:
+ cv_draw_bpath( stack[sj], stack[sk], cc, cc )
+ #}
+
+ cv_view_course_i += 1
+ #}
+ #}
+
+ @staticmethod
+ def editor_interface( layout, obj ):
+ #{
+ layout.prop( obj.cv_data, "target", text="'Start' from" )
+ layout.prop( obj.cv_data, "colour" )
+ layout.prop( obj.cv_data, "strp", text="Name" )
+ #}
#}
+# Classtype 12
+#
+# Purpose: links an mesh node to a type 11
+#
class classtype_skin(Structure):
#{
_pack_ = 1
#}
#}
+# Classtype 11
+#
+# Purpose: defines the allocation requirements for a skeleton
+#
class classtype_skeleton(Structure):
#{
_pack_ = 1
#}
#}
+
+# Classtype 10
+#
+# Purpose: intrinsic bone type, stores collision information and limits too
+#
class classtype_bone(Structure):
#{
_pack_ = 1
#}
#}
+# Classtype 100
+#
+# Purpose: sends a signal to another entity
+#
+class classtype_trigger(Structure):
+#{
+ _pack_ = 1
+ _fields_ = [("target",c_uint32)]
+
+ def encode_obj(_, node,node_def ):
+ #{
+ node.classtype = 100
+ if node_def['obj'].cv_data.target:
+ _.target = node_def['obj'].cv_data.target.cv_data.uid
+ #}
+
+ @staticmethod
+ def draw_scene_helpers( obj ):
+ #{
+ global cv_view_verts, cv_view_colours
+ cv_draw_ucube( obj.matrix_world, [0,1,0,1] )
+
+ if obj.cv_data.target:
+ cv_draw_arrow( obj.location, obj.cv_data.target.location, [1,1,1,1] )
+ #}
+
+ @staticmethod
+ def editor_interface( layout, obj ):
+ #{
+ layout.prop( obj.cv_data, "target", text="Triggers" )
+ #}
+#}
-# TO BE REPLACED
+# Classtype 101
+#
+# Purpose: Gives the player an achievement.
+# No cheating! You shouldn't use this entity anyway, since only ME can
+# add achievements to the steam ;)
#
-class classtype_achievement_box(Structure):
+class classtype_logic_achievement(Structure):
#{
_pack_ = 1
- _fields_ = [("pstr_name",c_uint32),
- ("trigger",c_uint32)]
+ _fields_ = [("pstr_name",c_uint32)]
def encode_obj(_, node,node_def ):
#{
- node.classtype = 0
+ node.classtype = 101
+ _.pstr_name = encoder_process_pstr( node_def['obj'].cv_data.strp )
+ #}
+
+ @staticmethod
+ def editor_interface( layout, obj ):
+ #{
+ layout.prop( obj.cv_data, "strp", text="Achievement ID" )
#}
#}
+# Classtype 102
+#
+# Purpose: sends a signal to another entity
+#
+class classtype_logic_relay(Structure):
+#{
+ _pack_ = 1
+ _fields_ = [("targets",c_uint32*4)]
+
+ def encode_obj(_, node,node_def ):
+ #{
+ node.classtype = 102
+ obj = node_def['obj']
+ if obj.cv_data.target:
+ _.targets[0] = obj.cv_data.target.cv_data.uid
+ if obj.cv_data.target1:
+ _.targets[1] = obj.cv_data.target1.cv_data.uid
+ if obj.cv_data.target2:
+ _.targets[2] = obj.cv_data.target2.cv_data.uid
+ if obj.cv_data.target3:
+ _.targets[3] = obj.cv_data.target3.cv_data.uid
+ #}
+
+ @staticmethod
+ def draw_scene_helpers( obj ):
+ #{
+ global cv_view_verts, cv_view_colours
+
+ if obj.cv_data.target:
+ cv_draw_arrow( obj.location, obj.cv_data.target.location, [1,1,1,1] )
+ if obj.cv_data.target1:
+ cv_draw_arrow( obj.location, obj.cv_data.target1.location, [1,1,1,1] )
+ if obj.cv_data.target2:
+ cv_draw_arrow( obj.location, obj.cv_data.target2.location, [1,1,1,1] )
+ if obj.cv_data.target3:
+ cv_draw_arrow( obj.location, obj.cv_data.target3.location, [1,1,1,1] )
+ #}
+
+ @staticmethod
+ def editor_interface( layout, obj ):
+ #{
+ layout.prop( obj.cv_data, "target", text="Triggers" )
+ layout.prop( obj.cv_data, "target1", text="Triggers" )
+ layout.prop( obj.cv_data, "target2", text="Triggers" )
+ layout.prop( obj.cv_data, "target3", text="Triggers" )
+ #}
+#}
+
+# Classtype 14
+#
+# Purpose: Plays some audio (44100hz .ogg vorbis only)
+# NOTE: There is a 32mb limit on the audio buffer, world audio is
+# decompressed and stored in signed 16 bit integers (2 bytes)
+# per sample.
+#
+# volume: not used if has 3D flag
+# flags:
+# AUDIO_FLAG_LOOP 0x1
+# AUDIO_FLAG_ONESHOT 0x2 (DONT USE THIS, it breaks semaphores)
+# AUDIO_FLAG_SPACIAL_3D 0x4 (Probably what you want)
+# AUDIO_FLAG_AUTO_START 0x8 (Play when the world starts)
+# ......
+# the rest are just internal flags, only use the above 3.
+#
class classtype_audio(Structure):
#{
_pack_ = 1
obj = node_def['obj']
_.pstr_file = encoder_process_pstr( obj.cv_data.strp )
- _.flags = obj.cv_data.intp
+
+ flags = 0x00
+ if obj.cv_data.bp0: flags |= 0x1
+ if obj.cv_data.bp1: flags |= 0x4
+ if obj.cv_data.bp2: flags |= 0x8
+
+ _.flags = flags
_.volume = obj.cv_data.fltp
#}
@staticmethod
- def editor_interface(yada):
+ def editor_interface( layout, obj ):
#{
- pass
+ layout.prop( obj.cv_data, "strp" )
+
+ layout.prop( obj.cv_data, "bp0", text = "Looping" )
+ layout.prop( obj.cv_data, "bp1", text = "3D Audio" )
+ layout.prop( obj.cv_data, "bp2", text = "Auto Start" )
#}
@staticmethod
- def draw_scene_helpers(yada):
+ def draw_scene_helpers( obj ):
#{
- pass
+ global cv_view_verts, cv_view_colours
+
+ cv_draw_sphere( obj.location, obj.scale[0], [1,1,0,1] )
#}
#}
+# ---------------------------------------------------------------------------- #
+# #
+# Compiler section #
+# #
+# ---------------------------------------------------------------------------- #
# Current encoder state
#
g_encoder = None
-
# Reset encoder
#
def encoder_init():
for b in n.data.bones:
if not b.parent:
_extendb( tree, b, d+1 )
- #}
#}
# Recurse into children of this object
print( F"Completed {collection_name}.mdl" )
#}
-
-# Clicky clicky GUI
-# ------------------------------------------------------------------------------
+# ---------------------------------------------------------------------------- #
+# #
+# GUI section #
+# #
+# ---------------------------------------------------------------------------- #
cv_view_draw_handler = None
cv_view_shader = gpu.shader.from_builtin('3D_SMOOTH_COLOR')
+cv_view_verts = []
+cv_view_colours = []
+cv_view_course_i = 0
-def cv_draw():
- global cv_view_shader
- cv_view_shader.bind()
- gpu.state.depth_mask_set(False)
- gpu.state.line_width_set(2.0)
- gpu.state.face_culling_set('BACK')
- gpu.state.depth_test_set('LESS')
- gpu.state.blend_set('NONE')
-
- verts = []
- colours = []
-
- #def drawbezier(p0,h0,p1,h1,c0,c1):
- # nonlocal verts, colours
-
- # verts += [p0]
- # verts += [h0]
- # colours += [(0.5,0.5,0.5,1.0),(0.5,0.5,0.5,1)]
- # verts += [p1]
- # verts += [h1]
- # colours += [(1.0,1.0,1,1),(1,1,1,1)]
- #
- # last = p0
- # for i in range(10):
- # t = (i+1)/10
- # a0 = 1-t
-
- # tt = t*t
- # ttt = tt*t
- # p=ttt*p1+(3*tt-3*ttt)*h1+(3*ttt-6*tt+3*t)*h0+(3*tt-ttt-3*t+1)*p0
- # verts += [(last[0],last[1],last[2])]
- # verts += [(p[0],p[1],p[2])]
- # colours += [c0*a0+c1*(1-a0),c0*a0+c1*(1-a0)]
- # last = p
-
- course_count = 0
-
- def drawbhandle(obj, direction, colour):
- nonlocal verts, colours
- p0 = obj.location
- h0 = obj.matrix_world @ Vector((0,direction,0))
- verts += [p0]
- verts += [h0]
- colours += [colour,colour]
-
- def drawbezier(p0,h0,p1,h1,c0,c1):
- nonlocal verts, colours
-
- last = p0
- for i in range(10):
- t = (i+1)/10
- a0 = 1-t
-
- tt = t*t
- ttt = tt*t
- p=ttt*p1+(3*tt-3*ttt)*h1+(3*ttt-6*tt+3*t)*h0+(3*tt-ttt-3*t+1)*p0
- verts += [(last[0],last[1],last[2])]
- verts += [(p[0],p[1],p[2])]
- colours += [c0*a0+c1*(1-a0),c0*a0+c1*(1-a0)]
- last = p
-
- def drawsbpath(o0,o1,c0,c1,s0,s1):
- nonlocal course_count
-
- offs = ((course_count % 2)*2-1) * course_count * 0.02
-
- p0 = o0.matrix_world @ Vector((offs, 0,0))
- h0 = o0.matrix_world @ Vector((offs, s0,0))
- p1 = o1.matrix_world @ Vector((offs, 0,0))
- h1 = o1.matrix_world @ Vector((offs,-s1,0))
- drawbezier(p0,h0,p1,h1,c0,c1)
-
- def drawbpath(o0,o1,c0,c1):
- drawsbpath(o0,o1,c0,c1,1.0,1.0)
+# Draw axis alligned sphere at position with radius
+#
+def cv_draw_sphere( pos, radius, colour ):
+#{
+ global cv_view_verts, cv_view_colours
+
+ ly = pos + Vector((0,0,radius))
+ lx = pos + Vector((0,radius,0))
+ lz = pos + Vector((0,0,radius))
+
+ pi = 3.14159265358979323846264
- def drawbline(p0,p1,c0,c1):
- nonlocal verts, colours
- verts += [p0,p1]
- colours += [c0,c1]
+ for i in range(16):
+ #{
+ t = ((i+1.0) * 1.0/16.0) * pi * 2.0
+ s = math.sin(t)
+ c = math.cos(t)
- for obj in bpy.context.collection.objects:
- if obj.type == 'ARMATURE':
- for bone in obj.data.bones:
- if bone.cv_data.collider and obj.data.pose_position == 'REST':
- c = bone.head_local
- a = bone.cv_data.v0
- b = bone.cv_data.v1
-
- vs = [None]*8
- vs[0]=obj.matrix_world@Vector((c[0]+a[0],c[1]+a[1],c[2]+a[2]))
- vs[1]=obj.matrix_world@Vector((c[0]+a[0],c[1]+b[1],c[2]+a[2]))
- vs[2]=obj.matrix_world@Vector((c[0]+b[0],c[1]+b[1],c[2]+a[2]))
- vs[3]=obj.matrix_world@Vector((c[0]+b[0],c[1]+a[1],c[2]+a[2]))
- vs[4]=obj.matrix_world@Vector((c[0]+a[0],c[1]+a[1],c[2]+b[2]))
- vs[5]=obj.matrix_world@Vector((c[0]+a[0],c[1]+b[1],c[2]+b[2]))
- vs[6]=obj.matrix_world@Vector((c[0]+b[0],c[1]+b[1],c[2]+b[2]))
- vs[7]=obj.matrix_world@Vector((c[0]+b[0],c[1]+a[1],c[2]+b[2]))
-
- indices = [(0,1),(1,2),(2,3),(3,0),(4,5),(5,6),(6,7),(7,4),\
- (0,4),(1,5),(2,6),(3,7)]
-
- for l in indices:
- v0 = vs[l[0]]
- v1 = vs[l[1]]
- verts += [(v0[0],v0[1],v0[2])]
- verts += [(v1[0],v1[1],v1[2])]
- colours += [(0.5,0.5,0.5,0.5),(0.5,0.5,0.5,0.5)]
-
- center=obj.matrix_world@c
-
- def _angle_lim( major, minor, amin, amax, colour ):
- nonlocal verts, colours
- f = 0.05
- ay = major*f
- ax = minor*f
-
- for x in range(16):
- t0 = x/16
- t1 = (x+1)/16
- a0 = amin*(1.0-t0)+amax*t0
- a1 = amin*(1.0-t1)+amax*t1
-
- p0 = c + major*f*math.cos(a0) + minor*f*math.sin(a0)
- p1 = c + major*f*math.cos(a1) + minor*f*math.sin(a1)
-
- p0=obj.matrix_world @ p0
- p1=obj.matrix_world @ p1
- verts += [p0,p1]
- colours += [colour,colour]
-
- if x == 0:
- verts += [p0,c]
- colours += [colour,colour]
- if x == 15:
- verts += [p1,c]
- colours += [colour,colour]
-
- verts += [c+major*1.2*f,c+major*f*0.8]
- colours += [colour,colour]
-
- if bone.cv_data.con0:
- _angle_lim( Vector((0,1,0)),Vector((0,0,1)), \
- bone.cv_data.mins[0], bone.cv_data.maxs[0], \
- (1,0,0,1))
- _angle_lim( Vector((0,0,1)),Vector((1,0,0)), \
- bone.cv_data.mins[1], bone.cv_data.maxs[1], \
- (0,1,0,1))
- _angle_lim( Vector((1,0,0)),Vector((0,1,0)), \
- bone.cv_data.mins[2], bone.cv_data.maxs[2], \
- (0,0,1,1))
-
+ py = pos + Vector((s*radius,0.0,c*radius))
+ px = pos + Vector((s*radius,c*radius,0.0))
+ pz = pos + Vector((0.0,s*radius,c*radius))
- if obj.cv_data.classtype == 'classtype_gate':
- if obj.type == 'MESH':
- dims = obj.data.cv_data.v0
- else:
- dims = obj.cv_data.v0
+ cv_view_verts += [ px, lx ]
+ cv_view_verts += [ py, ly ]
+ cv_view_verts += [ pz, lz ]
- vs = [None]*9
- c = Vector((0,0,dims[2]))
+ cv_view_colours += [ colour, colour, colour, colour, colour, colour ]
- vs[0] = obj.matrix_world @ Vector((-dims[0],0.0,-dims[1]+dims[2]))
- vs[1] = obj.matrix_world @ Vector((-dims[0],0.0, dims[1]+dims[2]))
- vs[2] = obj.matrix_world @ Vector(( dims[0],0.0, dims[1]+dims[2]))
- vs[3] = obj.matrix_world @ Vector(( dims[0],0.0,-dims[1]+dims[2]))
- vs[4] = obj.matrix_world @ (c+Vector((-1,0,-2)))
- vs[5] = obj.matrix_world @ (c+Vector((-1,0, 2)))
- vs[6] = obj.matrix_world @ (c+Vector(( 1,0, 2)))
- vs[7] = obj.matrix_world @ (c+Vector((-1,0, 0)))
- vs[8] = obj.matrix_world @ (c+Vector(( 1,0, 0)))
+ ly = py
+ lx = px
+ lz = pz
+ #}
+ cv_draw_lines()
+#}
- indices = [(0,1),(1,2),(2,3),(3,0),(4,5),(5,6),(7,8)]
+# Draw transformed -1 -> 1 cube
+#
+def cv_draw_ucube( transform, colour ):
+#{
+ global cv_view_verts, cv_view_colours
- for l in indices:
- v0 = vs[l[0]]
- v1 = vs[l[1]]
- verts += [(v0[0],v0[1],v0[2])]
- verts += [(v1[0],v1[1],v1[2])]
- colours += [(1,1,0,1),(1,1,0,1)]
-
- sw = (0.4,0.4,0.4,0.2)
- if obj.cv_data.target != None:
- drawbline( obj.location, obj.cv_data.target.location, sw,sw )
-
- elif obj.cv_data.classtype == 'classtype_route_node':
- sw = Vector((0.4,0.4,0.4,0.2))
- sw2 = Vector((1.5,0.2,0.2,0.0))
- if obj.cv_data.target != None:
- drawbpath( obj, obj.cv_data.target, sw, sw )
- if obj.cv_data.target1 != None:
- drawbpath( obj, obj.cv_data.target1, sw, sw )
-
- drawbhandle( obj, 1.0, (0.8,0.8,0.8,1.0) )
- drawbhandle( obj, -1.0, (0.4,0.4,0.4,1.0) )
-
- p1 = obj.location+ \
- obj.matrix_world.to_quaternion() @ Vector((0,0,-6+1.5))
- drawbline( obj.location, p1, sw,sw2 )
-
- elif obj.cv_data.classtype == 'classtype_achievement_box':
- a = Vector((-1,-1,-1))
- b = Vector((1,1,1))
-
- vs = [None]*8
- vs[0] = obj.matrix_world @ Vector((a[0], a[1], a[2]))
- vs[1] = obj.matrix_world @ Vector((a[0], b[1], a[2]))
- vs[2] = obj.matrix_world @ Vector((b[0], b[1], a[2]))
- vs[3] = obj.matrix_world @ Vector((b[0], a[1], a[2]))
- vs[4] = obj.matrix_world @ Vector((a[0], a[1], b[2]))
- vs[5] = obj.matrix_world @ Vector((a[0], b[1], b[2]))
- vs[6] = obj.matrix_world @ Vector((b[0], b[1], b[2]))
- vs[7] = obj.matrix_world @ Vector((b[0], a[1], b[2]))
+ a = Vector((-1,-1,-1))
+ b = Vector((1,1,1))
+
+ vs = [None]*8
+ vs[0] = transform @ Vector((a[0], a[1], a[2]))
+ vs[1] = transform @ Vector((a[0], b[1], a[2]))
+ vs[2] = transform @ Vector((b[0], b[1], a[2]))
+ vs[3] = transform @ Vector((b[0], a[1], a[2]))
+ vs[4] = transform @ Vector((a[0], a[1], b[2]))
+ vs[5] = transform @ Vector((a[0], b[1], b[2]))
+ vs[6] = transform @ Vector((b[0], b[1], b[2]))
+ vs[7] = transform @ Vector((b[0], a[1], b[2]))
+
+ indices = [(0,1),(1,2),(2,3),(3,0),(4,5),(5,6),(6,7),(7,4),\
+ (0,4),(1,5),(2,6),(3,7)]
+
+ for l in indices:
+ #{
+ v0 = vs[l[0]]
+ v1 = vs[l[1]]
+ cv_view_verts += [(v0[0],v0[1],v0[2])]
+ cv_view_verts += [(v1[0],v1[1],v1[2])]
+ cv_view_colours += [(0,1,0,1),(0,1,0,1)]
+ #}
+ cv_draw_lines()
+#}
- indices = [(0,1),(1,2),(2,3),(3,0),(4,5),(5,6),(6,7),(7,4),\
- (0,4),(1,5),(2,6),(3,7)]
+# Draw line with colour
+#
+def cv_draw_line( p0, p1, colour ):
+#{
+ global cv_view_verts, cv_view_colours
- for l in indices:
- v0 = vs[l[0]]
- v1 = vs[l[1]]
- verts += [(v0[0],v0[1],v0[2])]
- verts += [(v1[0],v1[1],v1[2])]
- colours += [(0,1,0,1),(0,1,0,1)]
-
- if obj.cv_data.target != None:
- vs = [None]*2
- vs[0] = obj.location
- vs[1] = obj.cv_data.target.location
- indices = [(0,1)]
- for l in indices:
- v0 = vs[l[0]]
- v1 = vs[l[1]]
- verts += [(v0[0],v0[1],v0[2])]
- verts += [(v1[0],v1[1],v1[2])]
- colours += [(0,1,1,1),(0,1,1,1)]
-
-
- elif obj.cv_data.classtype == 'classtype_block':
- a = obj.data.cv_data.v0
- b = obj.data.cv_data.v1
-
- vs = [None]*8
- vs[0] = obj.matrix_world @ Vector((a[0], a[1], a[2]))
- vs[1] = obj.matrix_world @ Vector((a[0], b[1], a[2]))
- vs[2] = obj.matrix_world @ Vector((b[0], b[1], a[2]))
- vs[3] = obj.matrix_world @ Vector((b[0], a[1], a[2]))
- vs[4] = obj.matrix_world @ Vector((a[0], a[1], b[2]))
- vs[5] = obj.matrix_world @ Vector((a[0], b[1], b[2]))
- vs[6] = obj.matrix_world @ Vector((b[0], b[1], b[2]))
- vs[7] = obj.matrix_world @ Vector((b[0], a[1], b[2]))
+ cv_view_verts += [p0,p1]
+ cv_view_colours += [colour, colour]
+ cv_draw_lines()
+#}
- indices = [(0,1),(1,2),(2,3),(3,0),(4,5),(5,6),(6,7),(7,4),\
- (0,4),(1,5),(2,6),(3,7)]
+# Draw line with colour(s)
+#
+def cv_draw_line2( p0, p1, c0, c1 ):
+#{
+ global cv_view_verts, cv_view_colours
- for l in indices:
- v0 = vs[l[0]]
- v1 = vs[l[1]]
- verts += [(v0[0],v0[1],v0[2])]
- verts += [(v1[0],v1[1],v1[2])]
- colours += [(1,1,0,1),(1,1,0,1)]
-
- elif obj.cv_data.classtype == 'classtype_capsule':
- h = obj.data.cv_data.v0[0]
- r = obj.data.cv_data.v0[1]
-
- vs = [None]*10
- vs[0] = obj.matrix_world @ Vector((0.0,0.0, h*0.5 ))
- vs[1] = obj.matrix_world @ Vector((0.0,0.0,-h*0.5 ))
- vs[2] = obj.matrix_world @ Vector(( r,0.0, h*0.5-r))
- vs[3] = obj.matrix_world @ Vector(( -r,0.0, h*0.5-r))
- vs[4] = obj.matrix_world @ Vector(( r,0.0,-h*0.5+r))
- vs[5] = obj.matrix_world @ Vector(( -r,0.0,-h*0.5+r))
- vs[6] = obj.matrix_world @ Vector((0.0, r , h*0.5-r))
- vs[7] = obj.matrix_world @ Vector((0.0,-r , h*0.5-r))
- vs[8] = obj.matrix_world @ Vector((0.0, r ,-h*0.5+r))
- vs[9] = obj.matrix_world @ Vector((0.0,-r ,-h*0.5+r))
-
- indices = [(0,1),(2,3),(4,5),(6,7),(8,9)]
+ cv_view_verts += [p0,p1]
+ cv_view_colours += [c0,c1]
+ cv_draw_lines()
+#}
- for l in indices:
- v0 = vs[l[0]]
- v1 = vs[l[1]]
- verts += [(v0[0],v0[1],v0[2])]
- verts += [(v1[0],v1[1],v1[2])]
- colours += [(0.5,1,0,1),(0.5,1,0,1)]
-
- elif obj.cv_data.classtype == 'classtype_spawn':
- vs = [None]*4
- vs[0] = obj.matrix_world @ Vector((0,0,0))
- vs[1] = obj.matrix_world @ Vector((0,2,0))
- vs[2] = obj.matrix_world @ Vector((0.5,1,0))
- vs[3] = obj.matrix_world @ Vector((-0.5,1,0))
- indices = [(0,1),(1,2),(1,3)]
- for l in indices:
- v0 = vs[l[0]]
- v1 = vs[l[1]]
- verts += [(v0[0],v0[1],v0[2])]
- verts += [(v1[0],v1[1],v1[2])]
- colours += [(0,1,1,1),(0,1,1,1)]
-
- elif obj.cv_data.classtype == 'classtype_route':
- vs = [None]*2
- vs[0] = obj.location
- vs[1] = obj.cv_data.target.location
- indices = [(0,1)]
- for l in indices:
- v0 = vs[l[0]]
- v1 = vs[l[1]]
- verts += [(v0[0],v0[1],v0[2])]
- verts += [(v1[0],v1[1],v1[2])]
- colours += [(0,1,1,1),(0,1,1,1)]
-
- stack = [None]*64
- stack_i = [0]*64
- stack[0] = obj.cv_data.target
- si = 1
- loop_complete = False
-
- while si > 0:
- if stack_i[si-1] == 2:
- si -= 1
- continue
+# Just the tx because we dont really need ty for this app
+#
+def cv_tangent_basis_tx( n, tx ):
+#{
+ if abs( n[0] ) >= 0.57735027:
+ #{
+ tx[0] = n[1]
+ tx[1] = -n[0]
+ tx[2] = 0.0
+ #}
+ else:
+ #{
+ tx[0] = 0.0
+ tx[1] = n[2]
+ tx[2] = -n[1]
+ #}
- if si == 0: # Loop failed to complete
- break
+ tx.normalize()
+#}
- node = stack[si-1]
+# Draw coloured arrow
+#
+def cv_draw_arrow( p0, p1, c0 ):
+#{
+ global cv_view_verts, cv_view_colours
- targets = [None,None]
- targets[0] = node.cv_data.target
+ n = p1-p0
+ midpt = p0 + n*0.5
+ n.normalize()
- if node.cv_data.classtype == 'classtype_route_node':
- targets[1] = node.cv_data.target1
-
- nextnode = targets[stack_i[si-1]]
- stack_i[si-1] += 1
+ tx = Vector((1,0,0))
+ cv_tangent_basis_tx( n, tx )
+
+ cv_view_verts += [p0,p1, midpt+(tx-n)*0.15,midpt, midpt+(-tx-n)*0.15,midpt ]
+ cv_view_colours += [c0,c0,c0,c0,c0,c0]
+ cv_draw_lines()
+#}
- if nextnode != None: # branch
- if nextnode == stack[0]: # Loop completed
- loop_complete = True
- break
+# Drawhandles of a bezier control point
+#
+def cv_draw_bhandle( obj, direction, colour ):
+#{
+ global cv_view_verts, cv_view_colours
- valid=True
- for sj in range(si):
- if stack[sj] == nextnode: # invalidated path
- valid=False
- break
+ p0 = obj.location
+ h0 = obj.matrix_world @ Vector((0,direction,0))
- if valid:
- stack_i[si] = 0
- stack[si] = nextnode
- si += 1
- continue
+ cv_view_verts += [p0]
+ cv_view_verts += [h0]
+ cv_view_colours += [colour,colour]
+ cv_draw_lines()
+#}
- if loop_complete:
- cc = Vector((obj.cv_data.colour[0],\
- obj.cv_data.colour[1],\
- obj.cv_data.colour[2],\
- 1.0))
+# Draw a bezier curve (at fixed resolution 10)
+#
+def cv_draw_bezier( p0,h0,p1,h1,c0,c1 ):
+#{
+ global cv_view_verts, cv_view_colours
- for sj in range(si):
- sk = (sj+1)%si
+ last = p0
+ for i in range(10):
+ #{
+ t = (i+1)/10
+ a0 = 1-t
- if stack[sj].cv_data.classtype == 'classtype_gate' and \
- stack[sk].cv_data.classtype == 'classtype_gate':
- dist = (stack[sj].location-stack[sk].location).magnitude
- drawsbpath( stack[sj], stack[sk], cc*0.4, cc, dist, dist )
+ tt = t*t
+ ttt = tt*t
+ p=ttt*p1+(3*tt-3*ttt)*h1+(3*ttt-6*tt+3*t)*h0+(3*tt-ttt-3*t+1)*p0
- else:
- drawbpath( stack[sj], stack[sk], cc, cc )
+ cv_view_verts += [(last[0],last[1],last[2])]
+ cv_view_verts += [(p[0],p[1],p[2])]
+ cv_view_colours += [c0*a0+c1*(1-a0),c0*a0+c1*(1-a0)]
- course_count += 1
+ last = p
+ #}
+ cv_draw_lines()
+#}
- elif obj.cv_data.classtype == 'classtype_car_path':
- v0 = obj.matrix_world.to_quaternion() @ Vector((0,1,0))
- c0 = Vector((v0.x*0.5+0.5, v0.y*0.5+0.5, 0.0, 1.0))
- drawbhandle( obj, 1.0, (0.9,0.9,0.9,1.0) )
+# I think this one extends the handles of the bezier otwards......
+#
+def cv_draw_sbpath( o0,o1,c0,c1,s0,s1 ):
+#{
+ global cv_view_course_i
+
+ offs = ((cv_view_course_i % 2)*2-1) * cv_view_course_i * 0.02
- if obj.cv_data.target != None:
- v1 = obj.cv_data.target.matrix_world.to_quaternion()@Vector((0,1,0))
- c1 = Vector((v1.x*0.5+0.5, v1.y*0.5+0.5, 0.0, 1.0))
+ p0 = o0.matrix_world @ Vector((offs, 0,0))
+ h0 = o0.matrix_world @ Vector((offs, s0,0))
+ p1 = o1.matrix_world @ Vector((offs, 0,0))
+ h1 = o1.matrix_world @ Vector((offs,-s1,0))
- drawbhandle( obj.cv_data.target, -1.0, (0.5,0.5,0.5,1.0) )
- drawbpath( obj, obj.cv_data.target, c0, c1 )
+ cv_draw_bezier( p0,h0,p1,h1,c0,c1 )
+ cv_draw_lines()
+#}
- if obj.cv_data.target1 != None:
- v1 = obj.cv_data.target1.matrix_world.to_quaternion()@Vector((0,1,0))
- c1 = Vector((v1.x*0.5+0.5, v1.y*0.5+0.5, 0.0, 1.0))
+# Flush the lines buffers. This is called often because god help you if you want
+# to do fixed, fast buffers in this catastrophic programming language.
+#
+def cv_draw_lines():
+#{
+ global cv_view_shader, cv_view_verts, cv_view_colours
- drawbhandle( obj.cv_data.target1, -1.0, (0.5,0.5,0.5,1.0) )
- drawbpath( obj, obj.cv_data.target1, c0, c1 )
+ if len(cv_view_verts) < 2:
+ return
lines = batch_for_shader(\
cv_view_shader, 'LINES', \
- { "pos":verts, "color":colours })
+ { "pos":cv_view_verts, "color":cv_view_colours })
lines.draw( cv_view_shader )
+ cv_view_verts = []
+ cv_view_colours = []
+#}
+
+# I dont remember what this does exactly
+#
+def cv_draw_bpath( o0,o1,c0,c1 ):
+#{
+ cv_draw_sbpath( o0,o1,c0,c1,1.0,1.0 )
+#}
+
+# Semi circle to show the limit. and some lines
+#
+def draw_limit( obj, center, major, minor, amin, amax, colour ):
+#{
+ global cv_view_verts, cv_view_colours
+ f = 0.05
+ ay = major*f
+ ax = minor*f
+
+ for x in range(16):
+ #{
+ t0 = x/16
+ t1 = (x+1)/16
+ a0 = amin*(1.0-t0)+amax*t0
+ a1 = amin*(1.0-t1)+amax*t1
+
+ p0 = center + major*f*math.cos(a0) + minor*f*math.sin(a0)
+ p1 = center + major*f*math.cos(a1) + minor*f*math.sin(a1)
+
+ p0=obj.matrix_world @ p0
+ p1=obj.matrix_world @ p1
+ cv_view_verts += [p0,p1]
+ cv_view_colours += [colour,colour]
+
+ if x == 0:
+ #{
+ cv_view_verts += [p0,center]
+ cv_view_colours += [colour,colour]
+ #}
+ if x == 15:
+ #{
+ cv_view_verts += [p1,center]
+ cv_view_colours += [colour,colour]
+ #}
+ #}
+
+ cv_view_verts += [center+major*1.2*f,center+major*f*0.8]
+ cv_view_colours += [colour,colour]
+
+ cv_draw_lines()
+#}
+
+# Draws constraints and stuff for the skeleton. This isnt documented and wont be
+#
+def draw_skeleton_helpers( obj ):
+#{
+ global cv_view_verts, cv_view_colours
+
+ for bone in obj.data.bones:
+ #{
+ if bone.cv_data.collider and (obj.data.pose_position == 'REST'):
+ #{
+ c = bone.head_local
+ a = bone.cv_data.v0
+ b = bone.cv_data.v1
+
+ vs = [None]*8
+ vs[0]=obj.matrix_world@Vector((c[0]+a[0],c[1]+a[1],c[2]+a[2]))
+ vs[1]=obj.matrix_world@Vector((c[0]+a[0],c[1]+b[1],c[2]+a[2]))
+ vs[2]=obj.matrix_world@Vector((c[0]+b[0],c[1]+b[1],c[2]+a[2]))
+ vs[3]=obj.matrix_world@Vector((c[0]+b[0],c[1]+a[1],c[2]+a[2]))
+ vs[4]=obj.matrix_world@Vector((c[0]+a[0],c[1]+a[1],c[2]+b[2]))
+ vs[5]=obj.matrix_world@Vector((c[0]+a[0],c[1]+b[1],c[2]+b[2]))
+ vs[6]=obj.matrix_world@Vector((c[0]+b[0],c[1]+b[1],c[2]+b[2]))
+ vs[7]=obj.matrix_world@Vector((c[0]+b[0],c[1]+a[1],c[2]+b[2]))
+
+ indices = [(0,1),(1,2),(2,3),(3,0),(4,5),(5,6),(6,7),(7,4),\
+ (0,4),(1,5),(2,6),(3,7)]
+
+ for l in indices:
+ #{
+ v0 = vs[l[0]]
+ v1 = vs[l[1]]
+
+ cv_view_verts += [(v0[0],v0[1],v0[2])]
+ cv_view_verts += [(v1[0],v1[1],v1[2])]
+ cv_view_colours += [(0.5,0.5,0.5,0.5),(0.5,0.5,0.5,0.5)]
+ #}
+
+ center = obj.matrix_world @ c
+ if bone.cv_data.con0:
+ #{
+ draw_limit( obj, c, Vector((0,1,0)),Vector((0,0,1)), \
+ bone.cv_data.mins[0], bone.cv_data.maxs[0], \
+ (1,0,0,1))
+ draw_limit( obj, c, Vector((0,0,1)),Vector((1,0,0)), \
+ bone.cv_data.mins[1], bone.cv_data.maxs[1], \
+ (0,1,0,1))
+ draw_limit( obj, c, Vector((1,0,0)),Vector((0,1,0)), \
+ bone.cv_data.mins[2], bone.cv_data.maxs[2], \
+ (0,0,1,1))
+ #}
+ #}
+ #}
+#}
+
+def cv_draw():
+#{
+ global cv_view_shader
+ global cv_view_verts
+ global cv_view_colours
+ global cv_view_course_i
+
+ cv_view_course_i = 0
+ cv_view_verts = []
+ cv_view_colours = []
+
+ cv_view_shader.bind()
+ gpu.state.depth_mask_set(False)
+ gpu.state.line_width_set(2.0)
+ gpu.state.face_culling_set('BACK')
+ gpu.state.depth_test_set('LESS')
+ gpu.state.blend_set('NONE')
+
+ for obj in bpy.context.collection.objects:
+ #{
+ if obj.type == 'ARMATURE':
+ #{
+ if obj.data.pose_position == 'REST':
+ draw_skeleton_helpers( obj )
+ #}
+ else:
+ #{
+ classtype = obj.cv_data.classtype
+ if (classtype != 'classtype_none') and (classtype in globals()):
+ #{
+ cl = globals()[ classtype ]
+
+ if getattr( cl, "draw_scene_helpers", None ):
+ #{
+ cl.draw_scene_helpers( obj )
+ #}
+ #}
+ #}
+ #}
+
+ cv_draw_lines()
+ return
+#}
+
+
+# ---------------------------------------------------------------------------- #
+# #
+# Blender #
+# #
+# ---------------------------------------------------------------------------- #
+
+# Checks whether this object has a classtype assigned. we can only target other
+# classes
def cv_poll_target(scene, obj):
+#{
if obj == bpy.context.active_object:
return False
if obj.cv_data.classtype == 'classtype_none':
return False
+
return True
+#}
class CV_MESH_SETTINGS(bpy.types.PropertyGroup):
+#{
v0: bpy.props.FloatVectorProperty(name="v0",size=3)
v1: bpy.props.FloatVectorProperty(name="v1",size=3)
v2: bpy.props.FloatVectorProperty(name="v2",size=3)
v3: bpy.props.FloatVectorProperty(name="v3",size=3)
+#}
class CV_OBJ_SETTINGS(bpy.types.PropertyGroup):
+#{
uid: bpy.props.IntProperty( name="" )
strp: bpy.props.StringProperty( name="strp" )
intp: bpy.props.IntProperty( name="intp" )
fltp: bpy.props.FloatProperty( name="fltp" )
+ bp0: bpy.props.BoolProperty( name="bp0" )
+ bp1: bpy.props.BoolProperty( name="bp1" )
+ bp2: bpy.props.BoolProperty( name="bp2" )
+ bp3: bpy.props.BoolProperty( name="bp3" )
target: bpy.props.PointerProperty( type=bpy.types.Object, name="target", \
poll=cv_poll_target )
target1: bpy.props.PointerProperty( type=bpy.types.Object, name="target1", \
poll=cv_poll_target )
+ target2: bpy.props.PointerProperty( type=bpy.types.Object, name="target2", \
+ poll=cv_poll_target )
+ target3: bpy.props.PointerProperty( type=bpy.types.Object, name="target3", \
+ poll=cv_poll_target )
- colour: bpy.props.FloatVectorProperty(name="colour",subtype='COLOR',\
- min=0.0,max=1.0)
+ colour: bpy.props.FloatVectorProperty( name="colour",subtype='COLOR',\
+ min=0.0,max=1.0)
classtype: bpy.props.EnumProperty(
name="Format",
items = [
('classtype_none', "classtype_none", "", 0),
('classtype_gate', "classtype_gate", "", 1),
- ('classtype_block', "classtype_block", "", 2),
('classtype_spawn', "classtype_spawn", "", 3),
('classtype_water', "classtype_water", "", 4),
- ('classtype_car_path', "classtype_car_path", "", 5),
- ('classtype_INSTANCE', "","", 6 ),
- ('classtype_capsule', "classtype_capsule", "", 7 ),
('classtype_route_node', "classtype_route_node", "", 8 ),
('classtype_route', "classtype_route", "", 9 ),
- ('classtype_bone',"classtype_bone","",10),
- ('classtype_SKELETON', "","", 11 ),
- ('classtype_SKIN',"","",12),
- ('classtype_achievement_box',"classtype_achievement_box","",13),
('classtype_audio',"classtype_audio","",14),
+ ('classtype_trigger',"classtype_trigger","",100),
+ ('classtype_logic_achievement',"classtype_logic_achievement","",101),
+ ('classtype_logic_relay',"classtype_logic_relay","",102),
])
+#}
class CV_BONE_SETTINGS(bpy.types.PropertyGroup):
+#{
collider: bpy.props.BoolProperty(name="Collider",default=False)
v0: bpy.props.FloatVectorProperty(name="v0",size=3)
v1: bpy.props.FloatVectorProperty(name="v1",size=3)
con0: bpy.props.BoolProperty(name="Constriant 0",default=False)
mins: bpy.props.FloatVectorProperty(name="mins",size=3)
maxs: bpy.props.FloatVectorProperty(name="maxs",size=3)
+#}
class CV_BONE_PANEL(bpy.types.Panel):
+#{
bl_label="Bone Config"
bl_idname="SCENE_PT_cv_bone"
bl_space_type='PROPERTIES'
bl_context='bone'
def draw(_,context):
+ #{
active_object = context.active_object
if active_object == None: return
_.layout.prop( bone.cv_data, "con0" )
_.layout.prop( bone.cv_data, "mins" )
_.layout.prop( bone.cv_data, "maxs" )
+ #}
+#}
class CV_SCENE_SETTINGS(bpy.types.PropertyGroup):
+#{
use_hidden: bpy.props.BoolProperty( name="use hidden", default=False )
+#}
class CV_OBJ_PANEL(bpy.types.Panel):
+#{
bl_label="Entity Config"
bl_idname="SCENE_PT_cv_entity"
bl_space_type='PROPERTIES'
bl_context="object"
def draw(_,context):
+ #{
active_object = bpy.context.active_object
if active_object == None: return
if active_object.type == 'ARMATURE':
_.layout.prop( active_object.cv_data, "classtype" )
- if active_object.cv_data.classtype == 'classtype_gate':
- _.layout.prop( active_object.cv_data, "target" )
-
- mesh = active_object.data
- _.layout.label( text=F"(i) Data is stored in {mesh.name}" )
- _.layout.prop( mesh.cv_data, "v0" )
-
- elif active_object.cv_data.classtype == 'classtype_car_path' or \
- active_object.cv_data.classtype == 'classtype_route_node':
- _.layout.prop( active_object.cv_data, "target" )
- _.layout.prop( active_object.cv_data, "target1" )
-
- elif active_object.cv_data.classtype == 'classtype_route':
- _.layout.prop( active_object.cv_data, "target" )
- _.layout.prop( active_object.cv_data, "colour" )
-
- elif active_object.cv_data.classtype == 'classtype_block':
- mesh = active_object.data
-
- _.layout.label( text=F"(i) Data is stored in {mesh.name}" )
- _.layout.prop( mesh.cv_data, "v0" )
- _.layout.prop( mesh.cv_data, "v1" )
- _.layout.prop( mesh.cv_data, "v2" )
- _.layout.prop( mesh.cv_data, "v3" )
- elif active_object.cv_data.classtype == 'classtype_capsule':
- mesh = active_object.data
- _.layout.label( text=F"(i) Data is stored in {mesh.name}" )
- _.layout.prop( mesh.cv_data, "v0" )
- elif active_object.cv_data.classtype == 'classtype_achievement_box':
- _.layout.prop( active_object.cv_data, "strp" )
- _.layout.prop( active_object.cv_data, "target" )
- elif active_object.cv_data.classtype == 'classtype_audio':
- _.layout.prop( active_object.cv_data, "strp" )
- _.layout.prop( active_object.cv_data, "intp" )
- _.layout.prop( active_object.cv_data, "fltp" )
+ classtype = active_object.cv_data.classtype
+
+ if (classtype != 'classtype_none') and (classtype in globals()):
+ #{
+ cl = globals()[ classtype ]
+
+ if getattr( cl, "editor_interface", None ):
+ #{
+ cl.editor_interface( _.layout, active_object )
+ #}
+ #}
+ #}
+#}
class CV_INTERFACE(bpy.types.Panel):
+#{
bl_idname = "VIEW3D_PT_carve"
bl_label = "Carve"
bl_space_type = 'VIEW_3D'
bl_category = "Carve"
def draw(_, context):
+ #{
layout = _.layout
layout.prop( context.scene.cv_data, "use_hidden")
layout.operator( "carve.compile_all" )
+ #}
+#}
def test_compile():
+#{
view_layer = bpy.context.view_layer
for col in view_layer.layer_collection.children["export"].children:
if not col.hide_viewport or bpy.context.scene.cv_data.use_hidden:
write_model( col.name )
+#}
class CV_COMPILE(bpy.types.Operator):
+#{
bl_idname="carve.compile_all"
bl_label="Compile All"
def execute(_,context):
+ #{
test_compile()
#cProfile.runctx("test_compile()",globals(),locals(),sort=1)
#for col in bpy.data.collections["export"].children:
# write_model( col.name )
return {'FINISHED'}
+ #}
+#}
classes = [CV_OBJ_SETTINGS,CV_OBJ_PANEL,CV_COMPILE,CV_INTERFACE,\
CV_MESH_SETTINGS, CV_SCENE_SETTINGS, CV_BONE_SETTINGS,\
CV_BONE_PANEL]
def register():
+#{
global cv_view_draw_handler
for c in classes:
cv_view_draw_handler = bpy.types.SpaceView3D.draw_handler_add(\
cv_draw,(),'WINDOW','POST_VIEW')
+#}
def unregister():
+#{
global cv_view_draw_handler
for c in classes:
bpy.utils.unregister_class(c)
bpy.types.SpaceView3D.draw_handler_remove(cv_view_draw_handler,'WINDOW')
+#}