+ 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
+ _fields_ = [("skeleton",c_uint32)]
+
+ def encode_obj(_, node,node_def):
+ #{
+ node.classtype = 12
+
+ armature_def = node_def['linked_armature']
+ _.skeleton = armature_def['obj'].cv_data.uid
+ #}
+#}
+
+# Classtype 11
+#
+# Purpose: defines the allocation requirements for a skeleton
+#
+class classtype_skeleton(Structure):
+#{
+ _pack_ = 1
+ _fields_ = [("channels",c_uint32),
+ ("ik_count",c_uint32),
+ ("collider_count",c_uint32),
+ ("anim_start",c_uint32),
+ ("anim_count",c_uint32)]
+
+ def encode_obj(_, node,node_def):
+ #{
+ node.classtype = 11
+
+ _.channels = len( node_def['bones'] )
+ _.ik_count = node_def['ik_count']
+ _.collider_count = node_def['collider_count']
+ _.anim_start = node_def['anim_start']
+ _.anim_count = node_def['anim_count']
+ #}
+#}
+
+
+# Classtype 10
+#
+# Purpose: intrinsic bone type, stores collision information and limits too
+#
+class classtype_bone(Structure):
+#{
+ _pack_ = 1
+ _fields_ = [("deform",c_uint32),
+ ("ik_target",c_uint32),
+ ("ik_pole",c_uint32),
+ ("collider",c_uint32),
+ ("use_limits",c_uint32),
+ ("angle_limits",(c_float*3)*2),
+ ("hitbox",(c_float*3)*2)]
+
+ def encode_obj(_, node,node_def):
+ #{
+ node.classtype = 10
+
+ armature_def = node_def['linked_armature']
+ obj = node_def['bone']
+
+ _.deform = node_def['deform']
+
+ if 'ik_target' in node_def:
+ #{
+ _.ik_target = armature_def['bones'].index( node_def['ik_target'] )
+ _.ik_pole = armature_def['bones'].index( node_def['ik_pole'] )
+ #}
+
+ # For ragdolls
+ #
+ if obj.cv_data.collider:
+ #{
+ _.collider = 1
+ _.hitbox[0][0] = obj.cv_data.v0[0]
+ _.hitbox[0][1] = obj.cv_data.v0[2]
+ _.hitbox[0][2] = -obj.cv_data.v1[1]
+ _.hitbox[1][0] = obj.cv_data.v1[0]
+ _.hitbox[1][1] = obj.cv_data.v1[2]
+ _.hitbox[1][2] = -obj.cv_data.v0[1]
+ #}
+
+ if obj.cv_data.con0:
+ #{
+ _.use_limits = 1
+ _.angle_limits[0][0] = obj.cv_data.mins[0]
+ _.angle_limits[0][1] = obj.cv_data.mins[2]
+ _.angle_limits[0][2] = -obj.cv_data.maxs[1]
+ _.angle_limits[1][0] = obj.cv_data.maxs[0]
+ _.angle_limits[1][1] = obj.cv_data.maxs[2]
+ _.angle_limits[1][2] = -obj.cv_data.mins[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" )
+ #}
+#}
+
+# 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_logic_achievement(Structure):
+#{
+ _pack_ = 1
+ _fields_ = [("pstr_name",c_uint32)]
+
+ def encode_obj(_, node,node_def ):
+ #{
+ 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
+ _fields_ = [("pstr_file",c_uint32),
+ ("flags",c_uint32),
+ ("volume",c_float)]
+
+ def encode_obj(_, node,node_def ):
+ #{
+ node.classtype = 14
+
+ obj = node_def['obj']
+
+ _.pstr_file = encoder_process_pstr( obj.cv_data.strp )
+
+ 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( layout, obj ):
+ #{
+ 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( obj ):
+ #{
+ 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( collection ):
+#{
+ global g_encoder
+
+ g_encoder = \
+ {
+ # The actual file header
+ #
+ 'header': mdl_header(),
+
+ # Options
+ #
+ 'pack_textures': collection.cv_data.pack_textures,
+
+ # Compiled data chunks (each can be read optionally by the client)
+ #
+ 'data':
+ {
+ #1---------------------------------
+ 'node': [], # Metadata 'chunk'
+ 'submesh': [],
+ 'material': [],
+ 'texture': [],
+ 'anim': [],
+ 'entdata': bytearray(), # variable width
+ 'strings': bytearray(), # .
+ #2---------------------------------
+ 'keyframe': [], # Animations
+ #3---------------------------------
+ 'vertex': [], # Mesh data
+ 'indice': [],
+ #4---------------------------------
+ 'pack': bytearray() # Other generic packed data
+ },
+
+ # All objects of the model in their final heirachy
+ #
+ "uid_count": 1,
+ "scene_graph":{},
+ "graph_lookup":{},
+
+ # Allows us to reuse definitions
+ #
+ 'string_cache':{},
+ 'mesh_cache': {},
+ 'material_cache': {},
+ 'texture_cache': {}
+ }