X-Git-Url: https://harrygodden.com/git/?a=blobdiff_plain;f=blender_export.py;h=091718d15d5b660c240d4b8017197832dbbfba1c;hb=2e4531dfd7bd0d9a0776fda1a62653806d85eb3b;hp=d0a1c8aa50932b67a7cd4389865dedc983aed23c;hpb=26bde92c7084971f13352b37fd4d1ea528b45dcf;p=carveJwlIkooP6JGAAIwe30JlM.git diff --git a/blender_export.py b/blender_export.py index d0a1c8a..091718d 100644 --- a/blender_export.py +++ b/blender_export.py @@ -171,8 +171,161 @@ class mdl_keyframe(Structure): # def editor_interface( layout, obj ): # -# Classtype 1 +# 000: Intrinsic +# ---------------------------------------------------------------------------- # + +# Purpose: intrinsic bone type, stores collision information and limits too +# +class classtype_bone(Structure): +#{ + _pack_ = 1 + _fields_ = [("flags",c_uint32), + ("ik_target",c_uint32), + ("ik_pole",c_uint32), + ("hitbox",(c_float*3)*2), + ("conevx",c_float*3), + ("conevy",c_float*3), + ("coneva",c_float*3), + ("conet",c_float)] + + def encode_obj(_, node,node_def): + #{ + node.classtype = 1 + + armature_def = node_def['linked_armature'] + obj = node_def['bone'] + + _.flags = node_def['deform'] + + if 'ik_target' in node_def: + #{ + _.flags |= 0x2 + _.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_none': + #{ + if obj.cv_data.collider == 'collider_box': + _.flags |= 0x4 + else: + _.flags |= 0x8 + + _.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: + #{ + _.flags |= 0x100 + _.conevx[0] = obj.cv_data.conevx[0] + _.conevx[1] = obj.cv_data.conevx[2] + _.conevx[2] = -obj.cv_data.conevx[1] + _.conevy[0] = obj.cv_data.conevy[0] + _.conevy[1] = obj.cv_data.conevy[2] + _.conevy[2] = -obj.cv_data.conevy[1] + _.coneva[0] = obj.cv_data.coneva[0] + _.coneva[1] = obj.cv_data.coneva[2] + _.coneva[2] = -obj.cv_data.coneva[1] + _.conet = obj.cv_data.conet + #} + #} +#} + +# 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 = 2 + + _.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'] + #} +#} + +# 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 = 3 + + armature_def = node_def['linked_armature'] + _.skeleton = armature_def['obj'].cv_data.uid + #} +#} + +# Purpose: world light # +class classtype_world_light( Structure ): +#{ + _pack_ = 1 + _fields_ = [("type",c_uint32), + ("colour",c_float*4), + ("angle",c_float), + ("range",c_float)] + + def encode_obj(_, node, node_def): + #{ + node.classtype = 4 + + obj = node_def['obj'] + data = obj.data + _.colour[0] = data.color[0] + _.colour[1] = data.color[1] + _.colour[2] = data.color[2] + _.colour[3] = data.energy + _.range = data.cutoff_distance # this has to be manually set + # TODO: At some point, automate a min + # threshold value + + if obj.data.type == 'POINT': + #{ + _.type = 0 + _.angle = 0.0 + #} + elif obj.data.type == 'SPOT': + #{ + _.type = 1 + _.angle = data.spot_size*0.5 + #} + + if data.cv_data.bp0: + _.type += 2 + #} + + @staticmethod + def editor_interface( layout, obj ): + #{ + pass + #} +#} + +# 100: Gates +# ---------------------------------------------------------------------------- # + # Purpose: A rift. must target another gate, the target gate can not have more # than one target nodes of its own. # @@ -184,7 +337,7 @@ class classtype_gate(Structure): def encode_obj(_, node,node_def): #{ - node.classtype = 1 + node.classtype = 100 obj = node_def['obj'] @@ -259,7 +412,7 @@ class classtype_nonlocal_gate(classtype_gate): #{ def encode_obj(_,node,node_def): #{ - node.classtype = 300 + node.classtype = 101 obj = node_def['obj'] _.target = encoder_process_pstr( node_def['obj'].cv_data.strp ) @@ -289,8 +442,9 @@ class classtype_nonlocal_gate(classtype_gate): #} #} -# Classtype 3 -# +# 200: Spawns/Waypoints +# ---------------------------------------------------------------------------- # + # Purpose: player can reset here, its a safe place # spawns can share the same name, the closest one will be picked # @@ -303,7 +457,7 @@ class classtype_spawn(Structure): def encode_obj(_, node,node_def): #{ - node.classtype = 3 + node.classtype = 200 _.pstr_alias = encoder_process_pstr( node_def['obj'].cv_data.strp ) #} @@ -339,8 +493,9 @@ class classtype_spawn(Structure): #} #} -# Classtype 4 -# +# 300: Water +# ---------------------------------------------------------------------------- # + # Purpose: Tells the game to draw water HERE, at this entity. # class classtype_water(Structure): @@ -350,710 +505,156 @@ class classtype_water(Structure): def encode_obj(_, node,node_def): #{ - node.classtype = 4 + node.classtype = 300 # no data, spooky #} #} -# Classtype 8 -# -# Purpose: Defines a route node and links to up to two more nodes -# -class classtype_route_node(Structure): -#{ - _pack_ = 1 - _fields_ = [("target",c_uint32), - ("target1",c_uint32)] - - def encode_obj(_, node,node_def): - #{ - node.classtype = 8 - obj = node_def['obj'] - - if obj.cv_data.target != None: - _.target = obj.cv_data.target.cv_data.uid - 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): - #{ - node.classtype = 9 - obj = node_def['obj'] - - _.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 - _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_ = [("flags",c_uint32), - ("ik_target",c_uint32), - ("ik_pole",c_uint32), - ("hitbox",(c_float*3)*2), - ("conevx",c_float*3), - ("conevy",c_float*3), - ("coneva",c_float*3), - ("conet",c_float)] - - def encode_obj(_, node,node_def): - #{ - node.classtype = 10 - - armature_def = node_def['linked_armature'] - obj = node_def['bone'] - - _.flags = node_def['deform'] - - if 'ik_target' in node_def: - #{ - _.flags |= 0x2 - _.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_none': - #{ - if obj.cv_data.collider == 'collider_box': - _.flags |= 0x4 - else: - _.flags |= 0x8 - - _.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: - #{ - _.flags |= 0x100 - _.conevx[0] = obj.cv_data.conevx[0] - _.conevx[1] = obj.cv_data.conevx[2] - _.conevx[2] = -obj.cv_data.conevx[1] - _.conevy[0] = obj.cv_data.conevy[0] - _.conevy[1] = obj.cv_data.conevy[2] - _.conevy[2] = -obj.cv_data.conevy[1] - _.coneva[0] = obj.cv_data.coneva[0] - _.coneva[1] = obj.cv_data.coneva[2] - _.coneva[2] = -obj.cv_data.coneva[1] - _.conet = obj.cv_data.conet - #} - #} -#} - -# 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] ) - - white = (1,1,1,1) - - if obj.cv_data.target: - cv_draw_arrow( obj.location, obj.cv_data.target.location, white, 0.7 ) - #} - - @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" ) - #} -#} - -class union_128bit_data(Union): -#{ - _pack_ = 1 - _fields_ = [("f32",c_float), - ("u32",c_uint32), - ("i32",c_int32), - ("v4f",c_float*4)] -#} - -# Class type 105 -# -# Purpose: -# -class classtype_logic_wire(Structure): -#{ - _pack_ = 1 - _fields_ = [("next",c_uint32), - ("function",c_uint32), - ("data",union_128bit_data), - ("data_type",c_uint32), - ("enabled",c_uint32)] - - function_enum = [('0',"pass along",""), - ('1',"enable",""), - ('2',"disable",""), - ('3',"","")] - - def encode_obj(_,node,node_def): - #{ - node.classtype = 105 - - obj = node_def['obj'] - - if obj.cv_data.target: _.next = obj.cv_data.target.cv_data.uid - - _.data_type = obj.cv_data.intp1 - _.function = int(obj.cv_data.function) - _.enabled = obj.cv_data.bp0 - - if _.data_type == 1: # an integer - _.data.i32 = obj.cv_data.intp - elif _.data_type == 2: # a number - _.data.f32 = obj.cv_data.fltp - elif _.data_type == 3: # a target - if obj.cv_data.target2: - _.data.u32 = obj.cv_data.target2.cv_data.uid - elif _.data_type == 4: # a string - _.data.u32 = encoder_process_pstr( obj.cv_data.strp ) - #} - - @staticmethod - def editor_interface( layout, obj ): - #{ - layout.prop( obj.cv_data, "bp0", text="Start disabled" ) - box = layout.box() - box.label( text="Target" ) - box.prop( obj.cv_data, "target", text="connection" ) - - row = box.row() - if not obj.cv_data.target: - row.enabled=False - row.prop( obj.cv_data, "function", text="function" ) - - box = layout.box() - box.label( text="Data packet" ) - box.prop( obj.cv_data, "intp1", text="type" ) - - if obj.cv_data.intp1 == 1: - box.prop( obj.cv_data, "intp", text="Signed Integer" ) - elif obj.cv_data.intp1 == 2: - box.prop( obj.cv_data, "fltp", text="Float" ) - elif obj.cv_data.intp1 == 3: - box.prop( obj.cv_data, "target2", text="Object reference" ) - elif obj.cv_data.intp1 == 4: - box.prop( obj.cv_data, "strp", text="String" ) - else: - #{ - row = box.row() - row.enabled=False - row.label( text="this wire will not impart any data" ) - #} - #} - - @staticmethod - def draw_scene_helpers( obj ): - #{ - global cv_view_verts, cv_view_colours - - white = (1,1,1,1) - purple = (0.5,0.2,1,1) - - if obj.cv_data.target: - cv_draw_arrow( obj.location, obj.cv_data.target.location, white, 0.7 ) - if (obj.cv_data.target2) and (obj.cv_data.intp1 == 3): - cv_draw_arrow( obj.cv_data.target2.location, obj.location,purple, 0.7 ) - #} - - @staticmethod - def get_targeted_methods( scene, context ): - #{ - obj = context.object - invalid = [('0',"",""), - ('1',"",""), - ('2',"",""), - ('3',"","")] - - if obj.cv_data.target: - #{ - classtype = obj.cv_data.target.cv_data.classtype - if classtype == 'classtype_none' or classtype not in globals(): - #{ - return invalid - #} - else: - #{ - cl = globals()[ classtype ] - if getattr( cl, "function_enum", None ): - #{ - return cl.function_enum - #} - else: - #{ - return invalid - #} - #} - #} - else: - #{ - return invalid - #} - #} -#} - -# Class type 108 -# -# Purpose: -# -class classtype_particle_box(Structure): -#{ - _pack_ = 1 - _fields_ = [("target",c_uint32), - ("rate",c_float)] - - function_enum = [('0',"set rate",""), - ('1',"",""), - ('2',"",""), - ('3',"","")] - - def encode_obj(_, node,node_def ): - #{ - node.classtype = 108 - - obj = node_def['obj'] - - _.rate = obj.cv_data.fltp - if obj.cv_data.target: - _.target = 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, [1,0.8,0,1] ) - - white = (1,1,1,1) - if obj.cv_data.target: - cv_draw_arrow( obj.location, obj.cv_data.target.location, white, 0.7 ) - #} - - @staticmethod - def editor_interface( layout, obj ): - #{ - layout.prop( obj.cv_data, "target", text="Triggers" ) - layout.prop( obj.cv_data, "fltp", text="count per second" ) - #} -#} - -# Class type 109 -# -# Purpose: -# -class classtype_signal_splitter(Structure): -#{ - _pack_ = 1 - _fields_ = [("next",c_uint32*4)] - - function_enum = [('0',"pass along",""), - ('1',"",""), - ('2',"",""), - ('3',"","")] - - def encode_obj(_,node,node_def): - #{ - node.classtype = 109 - - obj = node_def['obj'] - - if obj.cv_data.target: _.next[0] = obj.cv_data.target.cv_data.uid - if obj.cv_data.target1: _.next[1] = obj.cv_data.target1.cv_data.uid - if obj.cv_data.target2: _.next[2] = obj.cv_data.target2.cv_data.uid - if obj.cv_data.target3: _.next[3] = obj.cv_data.target3.cv_data.uid - #} - - @staticmethod - def editor_interface( layout, obj ): - #{ - layout.label( text="The split signals will run in order" ) - layout.prop( obj.cv_data, "target", text="#0" ) - layout.prop( obj.cv_data, "target1", text="#1" ) - layout.prop( obj.cv_data, "target2", text="#2" ) - layout.prop( obj.cv_data, "target3", text="#3" ) - #} - - @staticmethod - def draw_scene_helpers( obj ): - #{ - global cv_view_verts, cv_view_colours - - c0 = (1,0.5,0.2,1) - c1 = (0.8,1,0.1,1) - c2 = (0.3,0.9,0.4,1) - c3 = (0.1,0.4,1.0,1) - - if obj.cv_data.target: - cv_draw_arrow( obj.location, obj.cv_data.target.location, c0, 0.7 ) - if obj.cv_data.target1: - cv_draw_arrow( obj.location, obj.cv_data.target1.location, c1, 0.7 ) - if obj.cv_data.target2: - cv_draw_arrow( obj.location, obj.cv_data.target2.location, c2, 0.7 ) - if obj.cv_data.target3: - cv_draw_arrow( obj.location, obj.cv_data.target3.location, c3, 0.7 ) - #} -#} +# 400: Routes +# ---------------------------------------------------------------------------- # -# Class type 106 -# -# Purpose: +# Purpose: Defines a route, its 'starting' point, and the colour to use for it # -class classtype_soundscape(Structure): +class classtype_route(Structure): #{ _pack_ = 1 - _fields_ = [("max_instances",c_uint32), - ("allow_transitions",c_uint32), - ("transition_duration",c_float), - ("label",c_uint32)] - - function_enum = [('0',"play",""), - ('1',"set position",""), - ('2',"",""), - ('3',"","")] + _fields_ = [("id_start",c_uint32), + ("pstr_name",c_uint32), + ("colour",c_float*3)] - def encode_obj(_,node,node_def): + def encode_obj(_, node,node_def): #{ - node.classtype = 106 - + node.classtype = 400 obj = node_def['obj'] - _.max_instances = obj.cv_data.intp - _.allow_transitions = obj.cv_data.bp0 - _.transition_duration = obj.cv_data.fltp - _.label = encoder_process_pstr( obj.cv_data.strp ) + _.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 editor_interface( layout, obj ): + def draw_scene_helpers( obj ): #{ - layout.prop( obj.cv_data, "intp", text="max instances" ) - layout.prop( obj.cv_data, "strp", text="label" ) + global cv_view_verts, cv_view_colours, cv_view_course_i - box = layout.box() - box.label( text="If its a 3d sound, where can it spawn?" ) - box.prop( obj.cv_data, "bp1", text="Only in water" ) - box.prop( obj.cv_data, "bp2", text="Only on grass" ) - box.prop( obj.cv_data, "bp3", text="Only on wood" ) + 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 - box = layout.box() - box.prop( obj.cv_data, "bp0", text="allow transitions" ) + while si > 0: + #{ + if stack_i[si-1] == 2: + #{ + si -= 1 + continue - row = box.row() - if not obj.cv_data.bp0: - row.enabled=False - row.prop( obj.cv_data, "fltp", text="transition duration" ) - #} -#} + if si == 0: # Loop failed to complete + break + #} -class classtype_logic_chances(Structure): -#{ - _pack_ = 1 - _fields_ = [("targets",c_uint32*2), - ("p",c_float)] + node = stack[si-1] - function_enum = [('0',"pass along",""), - ('1',"set ratio",""), - ('2',"",""), - ('3',"","")] + targets = [None,None] + targets[0] = node.cv_data.target - def encode_obj(_,node,node_def): - #{ - node.classtype = 107 + 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 - obj = node_def['obj'] + if nextnode != None: # branch + #{ + if nextnode == stack[0]: # Loop completed + #{ + loop_complete = True + break + #} - 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 - - _.p = obj.cv_data.fltp - #} + valid=True + for sj in range(si): + #{ + if stack[sj] == nextnode: # invalidated path + #{ + valid=False + break + #} + #} - @staticmethod - def editor_interface( layout, obj ): - #{ - box = layout.box() - box.prop( obj.cv_data, "target", text="red" ) - box.prop( obj.cv_data, "target1", text="black" ) - box.prop( obj.cv_data, "fltp", text="p(red)" ) + 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 draw_scene_helpers( obj ): + def editor_interface( layout, obj ): #{ - global cv_view_verts, cv_view_colours - - red = (1,0,0,1) - black = (0,0,0,1) - - if obj.cv_data.target: - cv_draw_arrow( obj.location, obj.cv_data.target.location, red, 0.7 ) - if obj.cv_data.target1: - cv_draw_arrow( obj.location, obj.cv_data.target1.location, black, 0.7 ) + layout.prop( obj.cv_data, "target", text="'Start' from" ) + layout.prop( obj.cv_data, "colour" ) + layout.prop( obj.cv_data, "strp", text="Name" ) #} #} -# Classtype 102 [ DEPRECATED ] -# -# Purpose: sends a signal to another entity +# Purpose: Defines a route node and links to up to two more nodes # -class classtype_logic_relay(Structure): +class classtype_route_node(Structure): #{ _pack_ = 1 - _fields_ = [("targets",c_uint32*4)] + _fields_ = [("target",c_uint32), + ("target1",c_uint32)] - def encode_obj(_, node,node_def ): + def encode_obj(_, node,node_def): #{ - node.classtype = 102 + node.classtype = 401 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 + + if obj.cv_data.target != None: + _.target = obj.cv_data.target.cv_data.uid + if obj.cv_data.target1 != None: + _.target1 = obj.cv_data.target1.cv_data.uid #} @staticmethod @@ -1061,40 +662,45 @@ class classtype_logic_relay(Structure): #{ 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] ) + 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="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" ) + layout.prop( obj.cv_data, "target", text="Left" ) + layout.prop( obj.cv_data, "target1", text="Right" ) #} #} -# 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 + +# 500: Audio +# ---------------------------------------------------------------------------- # + +AUDIO_SPRITE_CATEGORIES_ENUM = [ + ('0', "Bird", ""), + ('1', "Nocturnal Bird", ""), + ('2', "Grass", ""), + ('3', "Wave",""), + ('4', "Wind",""), + ('5', "Wood Creaks", ""), + ] + # flags: # AUDIO_FLAG_LOOP 0x1 # 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): #{ @@ -1103,9 +709,16 @@ class classtype_audio(Structure): ("flags",c_uint32), ("volume",c_float)] + dynamic_enum = [ + ('0', "mono", ""), + ('1', "stereo", ""), + ('2', "remain compressed", ""), + ('3', "synthetic bird",""), + ] + def encode_obj(_, node,node_def ): #{ - node.classtype = 14 + node.classtype = 500 obj = node_def['obj'] @@ -1116,12 +729,9 @@ class classtype_audio(Structure): if obj.cv_data.bp1: flags |= 0x4 if obj.cv_data.bp2: flags |= 0x8 - if obj.cv_data.audio_format == 'stereo': - flags |= 0x200 - if obj.cv_data.audio_format == 'remain compressed': - flags |= 0x400 - if obj.cv_data.audio_format == 'synthetic bird': - flags |= 0x1000 + if obj.cv_data.dynamic_enum == '1': flags |= 0x200 + if obj.cv_data.dynamic_enum == '2': flags |= 0x400 + if obj.cv_data.dynamic_enum == '3': flags |= 0x1000 _.flags = flags _.volume = obj.cv_data.fltp @@ -1130,12 +740,12 @@ class classtype_audio(Structure): @staticmethod def editor_interface( layout, obj ): #{ - layout.prop( obj.cv_data, "strp", text = "File (.ogg)" ) + layout.prop( obj.cv_data, "strp", text = "File (.ogg/DATA)" ) 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" ) - layout.prop( obj.cv_data, "audio_format" ) + layout.prop( obj.cv_data, "bp2", text = "Play here" ) + layout.prop( obj.cv_data, "dynamic_enum" ) layout.prop( obj.cv_data, "fltp", text = "Volume (0-1)" ) #} @@ -1145,127 +755,101 @@ class classtype_audio(Structure): #{ global cv_view_verts, cv_view_colours - cv_draw_sphere( obj.location, obj.scale[0], [1,1,0,1] ) + if bpy.context.active_object == obj: + cv_draw_sphere( obj.location, obj.scale[0], [1,1,0,1] ) #} #} - -# Classtype 200 -# -# Purpose: world light -# -class classtype_world_light( Structure ): +class classtype_audio_sprite(Structure): #{ _pack_ = 1 - _fields_ = [("type",c_uint32), - ("colour",c_float*4), - ("angle",c_float), - ("range",c_float)] + _fields_ = [("audio",c_uint32), + ("category",c_uint32), + ("probability",c_float)] - def encode_obj(_, node, node_def): - #{ - node.classtype = 200 + dynamic_enum = AUDIO_SPRITE_CATEGORIES_ENUM - obj = node_def['obj'] - data = obj.data - _.colour[0] = data.color[0] - _.colour[1] = data.color[1] - _.colour[2] = data.color[2] - _.colour[3] = data.energy - _.range = data.cutoff_distance # this has to be manually set - # TODO: At some point, automate a min - # threshold value + def encode_obj(_, node,node_def ): + #{ + node.classtype = 501 + obj = node_def['obj'] - if obj.data.type == 'POINT': - #{ - _.type = 0 - _.angle = 0.0 - #} - elif obj.data.type == 'SPOT': - #{ - _.type = 1 - _.angle = data.spot_size*0.5 - #} + _.category = int( obj.cv_data.dynamic_enum ) + _.probability = obj.cv_data.fltp - if data.cv_data.bp0: - _.type += 2 + if obj.cv_data.target: + _.audio = obj.cv_data.target.cv_data.uid #} @staticmethod def editor_interface( layout, obj ): #{ - pass + layout.prop( obj.cv_data, "dynamic_enum", text="Category" ) + layout.prop( obj.cv_data, "target", text="Sound" ) + layout.prop( obj.cv_data, "fltp", text="Probability" ) + #} + + @staticmethod + def draw_scene_helpers( obj ): + #{ + global cv_view_verts, cv_view_colours + + purple = (0.5,0.2,1,1) + if obj.cv_data.target: + cv_draw_arrow( obj.location, obj.cv_data.target.location, purple, 0.1 ) #} #} -# Classtype 201 -# -# Purpose: lighting settings for world -# -class classtype_lighting_info(Structure): + +# 600: Volumes +# ---------------------------------------------------------------------------- # + +class classtype_volume_audio(Structure): #{ _pack_ = 1 - _fields_ = [("colours",(c_float*3)*3), - ("directions",(c_float*2)*3), - ("states",c_uint32*3), - ("shadow_spread",c_float), - ("shadow_length",c_float), - ("ambient",c_float*3)] + _fields_ = [("category",c_uint32)] - def encode_obj(_, node, node_def): + dynamic_enum = AUDIO_SPRITE_CATEGORIES_ENUM + + def encode_obj(_, node,node_def ): #{ - node.classtype = 201 + node.classtype = 600 + + obj = node_def['obj'] + _.category = int(obj.cv_data.dynamic_enum) + #} - # TODO + @staticmethod + def draw_scene_helpers( obj ): + #{ + global cv_view_verts, cv_view_colours + cv_draw_ucube( obj.matrix_world, [1,0.8,0,1] ) #} @staticmethod def editor_interface( layout, obj ): #{ - pass + layout.prop( obj.cv_data, "dynamic_enum", text="Category" ) #} #} -class classtype_spawn_link(Structure): +class classtype_volume_event(Structure): #{ _pack_ = 1 - _fields_ = [("connections",c_uint32*4)] + _fields_ = [("event",c_uint32)] def encode_obj(_, node,node_def ): #{ - node.classtype = 0 - #} - - @staticmethod - def editor_interface( layout, obj ): - #{ - pass + node.classtype = 601 + obj = node_def['obj'] + _.event = encoder_process_pstr( obj.cv_data.strp ) #} @staticmethod def draw_scene_helpers( obj ): #{ global cv_view_verts, cv_view_colours - - count = 0 - - for obj1 in bpy.context.collection.objects: - #{ - if (obj1.cv_data.classtype != 'classtype_spawn_link') and \ - (obj1.cv_data.classtype != 'classtype_spawn') : - continue - - if (obj1.location - obj.location).length < 40.0: - #{ - cv_draw_line( obj.location, obj1.location, [1,1,1,1] ) - count +=1 - #} - - if count == 4: - break - #} - - cv_draw_sphere( obj.location, 20.0, [0.5,0,0.2,0.4] ) + cv_draw_ucube( obj.matrix_world, [0.0,1.0,0,1] ) #} #} @@ -3020,6 +2604,33 @@ class CV_LIGHT_PANEL(bpy.types.Panel): #} #} +def cv_variable_enum( scene, context ): +#{ + obj = context.object + invalid = [('0',"",""), + ('1',"",""), + ('2',"",""), + ('3',"",""), + ('4',"",""), + ('5',"",""), + ('6',"",""), + ('7',"",""), + ('8',"",""), + ('9',"","")] + + classtype = obj.cv_data.classtype + + if classtype in globals(): + #{ + cl = globals()[ classtype ] + if getattr( cl, "dynamic_enum", None ): + if len(cl.dynamic_enum)>0: + return cl.dynamic_enum + #} + + return invalid +#} + class CV_OBJ_SETTINGS(bpy.types.PropertyGroup): #{ uid: bpy.props.IntProperty( name="" ) @@ -3045,40 +2656,28 @@ class CV_OBJ_SETTINGS(bpy.types.PropertyGroup): colour: bpy.props.FloatVectorProperty( name="colour",subtype='COLOR',\ min=0.0,max=1.0) - function: bpy.props.EnumProperty( - name="Function", - items= classtype_logic_wire.get_targeted_methods + dynamic_enum: bpy.props.EnumProperty( + name="", + items = cv_variable_enum ) classtype: bpy.props.EnumProperty( - name="Format", - items = [ - ('classtype_none', "classtype_none", "", 0), - ('classtype_gate', "classtype_gate", "", 1), - ('classtype_spawn', "classtype_spawn", "", 3), - ('classtype_water', "classtype_water", "", 4), - ('classtype_route_node', "classtype_route_node", "", 8 ), - ('classtype_route', "classtype_route", "", 9 ), - ('classtype_audio',"classtype_audio","",14), - ('classtype_trigger',"classtype_trigger","",100), - ('classtype_logic_achievement',"classtype_logic_achievement","",101), - ('classtype_logic_relay',"classtype_logic_relay","",102), - ('classtype_logic_wire',"classtype_logic_wire","",105), - ('classtype_soundscape',"classtype_soundscape","",106), - ('classtype_logic_chances',"classtype_logic_chances","",107), - ('classtype_particle_box',"classtype_particle_box","",108), - ('classtype_signal_splitter',"classtype_signal_splitter","",109), - ('classtype_spawn_link',"classtype_spawn_link","",150), - ('classtype_nonlocal_gate', "classtype_nonlocal_gate", "", 300) - ]) - - audio_format: bpy.props.EnumProperty( - name="Loaded format", + name="Class", items = [ - ('mono', "mono", "", 0), - ('stereo', "stereo", "", 1), - ('remain compressed', "remain compressed", "", 2), - ('synthetic bird',"synthetic bird","",3) + ('classtype_none', "None", ""), #000 + ('classtype_gate', "Gate", ""), #100 + ('classtype_nonlocal_gate', "Gate:NonLocal", ""), #101 + ('classtype_spawn', "Spawn", ""), #200 + ('classtype_water', "Water Surface", ""), #300 + ('classtype_route', "Route", ""), #400 + ('classtype_route_node', "Route:Node", ""), #401 + ('classtype_audio', "Audio:File", ""), #500 + ('classtype_audio_player', "Audio:Player", ""), #501 + ('classtype_audio_sprite', "Audio:Sprite", ""), #502 + ('classtype_volume_audio', "Volume:Audio", ""), #600 + ('classtype_volume_event', "Volume:Event", ""), #601 + + ('300', "ERROR", "",300) ]) #}