refactor model things
authorhgn <hgodden00@gmail.com>
Fri, 28 Oct 2022 02:15:02 +0000 (03:15 +0100)
committerhgn <hgodden00@gmail.com>
Fri, 28 Oct 2022 02:15:02 +0000 (03:15 +0100)
audio.h
blender_export.py
build.sh
main.c
model.h
models_src/mp_dev.mdl
player.h
server.c
world.h
world_gen.h

diff --git a/audio.h b/audio.h
index 34ebb3a4ad3a7866468654fcc932a898d4337d76..26c1a35ca3b69152c2a0b2f99c556e63567c7247 100644 (file)
--- a/audio.h
+++ b/audio.h
@@ -9,10 +9,10 @@
 
 #include "world.h"
 
-static float audio_occlusion_current = 0.0f,
+VG_STATIC float audio_occlusion_current = 0.0f,
              k_audio_occlusion_rate  = 1.0f;
 
-static int   k_audio_debug_soundscape = 0;
+VG_STATIC int   k_audio_debug_soundscape = 0;
 
 audio_clip audio_board[] =
 {
@@ -141,7 +141,7 @@ audio_player audio_player_gate =
    .name = "Gate"
 };
 
-static void audio_init(void)
+VG_STATIC void audio_init(void)
 {
    audio_player_init( &audio_player0 );
    audio_player_init( &audio_player1 );
@@ -156,19 +156,19 @@ static void audio_init(void)
    audio_player_init( &audio_player_extra );
    audio_player_init( &audio_rewind_player );
 
-   audio_clip_loadn( audio_board, vg_list_size(audio_board) );
-   audio_clip_loadn( audio_ambience, vg_list_size(audio_ambience) );
-   audio_clip_loadn( &audio_splash, 1 );
-   audio_clip_loadn( &audio_gate_pass, 1 );
-   audio_clip_loadn( &audio_gate_lap, 1 );
-   audio_clip_loadn( &audio_gate_ambient, 1 );
-   audio_clip_loadn( audio_jumps, vg_list_size(audio_jumps) );
-   audio_clip_loadn( audio_lands, vg_list_size(audio_lands) );
-   audio_clip_loadn( audio_water, vg_list_size(audio_water) );
-   audio_clip_loadn( audio_grass, vg_list_size(audio_grass) );
-   audio_clip_loadn( audio_footsteps, vg_list_size(audio_footsteps) );
-   audio_clip_loadn( audio_rewind, vg_list_size(audio_rewind) );
-   audio_clip_loadn( audio_ui, vg_list_size(audio_ui) );
+   audio_clip_loadn( audio_board, vg_list_size(audio_board), NULL );
+   audio_clip_loadn( audio_ambience, vg_list_size(audio_ambience), NULL );
+   audio_clip_loadn( &audio_splash, 1, NULL );
+   audio_clip_loadn( &audio_gate_pass, 1, NULL );
+   audio_clip_loadn( &audio_gate_lap, 1, NULL );
+   audio_clip_loadn( &audio_gate_ambient, 1, NULL );
+   audio_clip_loadn( audio_jumps, vg_list_size(audio_jumps), NULL );
+   audio_clip_loadn( audio_lands, vg_list_size(audio_lands), NULL );
+   audio_clip_loadn( audio_water, vg_list_size(audio_water), NULL );
+   audio_clip_loadn( audio_grass, vg_list_size(audio_grass), NULL );
+   audio_clip_loadn( audio_footsteps, vg_list_size(audio_footsteps), NULL );
+   audio_clip_loadn( audio_rewind, vg_list_size(audio_rewind), NULL );
+   audio_clip_loadn( audio_ui, vg_list_size(audio_ui), NULL );
 
    audio_lock();
    u32 flags = AUDIO_FLAG_LOOP|AUDIO_FLAG_SPACIAL_3D;
@@ -215,13 +215,13 @@ static void audio_init(void)
    });
 }
 
-static void audio_free(void*_)
+VG_STATIC void audio_free(void*_)
 {
    /* TODO! */
    vg_warn( "UNIMPLEMENTED: audio_free()\n" );
 }
 
-static void audio_sample_occlusion( v3f origin )
+VG_STATIC void audio_sample_occlusion( v3f origin )
 {
    float d = 0.0f,
          sample_dist = 880.0f;
@@ -280,7 +280,7 @@ enum audio_sprite_type
 /*
  * Trace out a random point, near the player to try and determine water areas
  */
-static enum audio_sprite_type audio_sample_sprite_random( v3f origin, 
+VG_STATIC enum audio_sprite_type audio_sample_sprite_random( v3f origin, 
                                                           v3f output )
 {
    v3f chance = { (vg_randf()-0.5f) * 30.0f, 
@@ -314,7 +314,7 @@ static enum audio_sprite_type audio_sample_sprite_random( v3f origin,
    return k_audio_sprite_type_water;
 }
 
-static void audio_debug_soundscapes(void)
+VG_STATIC void audio_debug_soundscapes(void)
 {
    if( !k_audio_debug_soundscape ) return;
 
index a7e714c2fae4a76661b19f7a9fcfa0e1f9412be1..ce4e8264af2fb32dfcdb3efbf73c98fd6733fb7c 100644 (file)
@@ -1,5 +1,20 @@
+# 
+# =============================================================================
+# 
+# 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
@@ -116,17 +131,29 @@ class mdl_keyframe(Structure):
                ("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
@@ -155,8 +182,62 @@ class classtype_gate(Structure):
          _.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
@@ -167,8 +248,41 @@ class classtype_spawn(Structure):
       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
@@ -181,6 +295,10 @@ class classtype_water(Structure):
    #}
 #}
 
+# Classtype 8
+#
+#  Purpose: Defines a route node and links to up to two more nodes
+#
 class classtype_route_node(Structure):
 #{
    _pack_ = 1
@@ -197,12 +315,44 @@ class classtype_route_node(Structure):
       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):
@@ -213,12 +363,118 @@ class classtype_route(Structure):
       _.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
@@ -233,6 +489,10 @@ class classtype_skin(Structure):
    #}
 #}
 
+# Classtype 11
+#
+#  Purpose: defines the allocation requirements for a skeleton
+#
 class classtype_skeleton(Structure):
 #{
    _pack_ = 1
@@ -254,6 +514,11 @@ class classtype_skeleton(Structure):
    #}
 #}
 
+
+# Classtype 10
+#
+#  Purpose: intrinsic bone type, stores collision information and limits too
+#
 class classtype_bone(Structure):
 #{
    _pack_ = 1
@@ -306,21 +571,127 @@ class classtype_bone(Structure):
    #}
 #}
 
+# 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
@@ -335,29 +706,45 @@ class classtype_audio(Structure):
       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():
@@ -585,7 +972,6 @@ def encoder_build_scene_graph( collection ):
             for b in n.data.bones:
                if not b.parent:
                   _extendb( tree, b, d+1 )
-            #}
          #}
          
          # Recurse into children of this object
@@ -1279,459 +1665,439 @@ def write_model(collection_name):
    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)
@@ -1739,8 +2105,10 @@ class CV_BONE_SETTINGS(bpy.types.PropertyGroup):
    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'
@@ -1748,6 +2116,7 @@ class CV_BONE_PANEL(bpy.types.Panel):
    bl_context='bone'
 
    def draw(_,context):
+   #{
       active_object = context.active_object
       if active_object == None: return
 
@@ -1762,11 +2131,16 @@ class CV_BONE_PANEL(bpy.types.Panel):
       _.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'
@@ -1774,6 +2148,7 @@ class CV_OBJ_PANEL(bpy.types.Panel):
    bl_context="object"
    
    def draw(_,context):
+   #{
       active_object = bpy.context.active_object
       if active_object == None: return
       if active_object.type == 'ARMATURE':
@@ -1786,43 +2161,22 @@ class CV_OBJ_PANEL(bpy.types.Panel):
 
       _.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'
@@ -1830,33 +2184,43 @@ class CV_INTERFACE(bpy.types.Panel):
    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:
@@ -1869,11 +2233,14 @@ def register():
 
    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')
+#}
index 0228534080bc83d6aee13c56acbaa198e065ba1d..eb741bfdba289a4dd1400616cb1aad027be955a5 100755 (executable)
--- a/build.sh
+++ b/build.sh
@@ -29,7 +29,7 @@ _options_release="-O3 -DVG_RELEASE"
 # Compiler lines
 # ==============================================================================
 
-_warnings="-Wall -Wno-unused-function -Wno-unused-variable"
+_warnings="-Wall -Wno-unused-function -Wno-unused-variable -Wno-unused-command-line-argument -Wno-unused-but-set-variable"
 _include="-I. -I./vg/dep -I./vg/src"
 _library="-L. -L./vg/dep/glfw -L./vg/dep/steam"
 _epilogue="-Wl,-rpath=./"
diff --git a/main.c b/main.c
index 119be9e0f5f62219e4f347a075ef3dd8a5d95e53..0e5a2fc66f850c513afb3feed100633e06b647c1 100644 (file)
--- a/main.c
+++ b/main.c
@@ -40,26 +40,8 @@ static int cl_ui     = 1;
 
 int main( int argc, char *argv[] )
 {
-   vg_mem.use_libc_malloc = 1;
-#if 0
-   vg_prealloc_quota( 128*1024*1024 );
-   void *test_allocator = vg_create_linear_allocator( NULL, 2048 );
-
-   for( int i=0; i<8; i++ )
-   {
-      u64 *items = vg_linear_alloc( test_allocator, sizeof(u64) );
-      items = vg_linear_extend( test_allocator, items, sizeof(u64));
-      items[0] = 43;
-      items[1] = 12445;
-
-      vg_info( "%lu %lu\n", items[0], items[1] );
-   }
-   
-   vg_linear_clear( test_allocator );
-   return 0;
-#endif
-
-   vg_prealloc_quota( 128*1024*1024 );
+   vg_mem.use_libc_malloc = 0;
+   vg_set_mem_quota( 128*1024*1024 );
    vg_enter( argc, argv, "Voyager Game Engine" ); 
 }
 
@@ -109,6 +91,7 @@ VG_STATIC void vg_load(void)
 
    vg_bake_shaders();
    vg_loader_highwater( audio_init, audio_free, NULL );
+   world_audio_init();
 
    /* 'systems' are completely loaded now */
    strcpy( world.world_name, "models/mp_test.mdl" );
diff --git a/model.h b/model.h
index 957001c40a193ad2b0e7be2d86472e81e7047baa..fb33e0bbad88bbaa45f7c1f61e708148c8a95d0b 100644 (file)
--- a/model.h
+++ b/model.h
@@ -37,12 +37,12 @@ enum classtype
    k_classtype_bone = 10,
    k_classtype_skeleton = 11,
    k_classtype_skin = 12,
-   k_classtype_achievement_box = 13,
    k_classtype_audio = 14,
-   k_classtype_trigger = 15
+   k_classtype_trigger = 100,
+   k_classtype_logic_achievement = 101,
+   k_classtype_logic_relay = 102
 };
 
-
 #pragma pack(push,1)
 
 struct mdl_vert
@@ -149,6 +149,7 @@ struct classtype_route_node
 struct classtype_route
 {
    u32 id_start;
+   u32 pstr_name;
    v3f colour;
 };
 
@@ -178,10 +179,19 @@ struct classtype_skin
    u32 skeleton;
 };
 
-struct classtype_achievement_box
+struct classtype_trigger
 {
-   u32 pstr_name,
-       trigger;
+   u32 target;
+};
+
+struct classtype_logic_relay
+{
+   u32 targets[4];
+};
+
+struct classtype_logic_achievement
+{
+   u32 pstr_name;
 };
 
 struct classtype_audio
index e2ffeb52859cf6e56bc9cb07e0b345a9dbfd7fc0..00eb7e81f7fdea67b776f194609e424b7945e2f3 100644 (file)
Binary files a/models_src/mp_dev.mdl and b/models_src/mp_dev.mdl differ
index 0b6db882031480bbd9a803f33649955b96c732c2..e119ffcffaac33ee553f5e3f99076324f8bf6dbf 100644 (file)
--- a/player.h
+++ b/player.h
@@ -472,17 +472,6 @@ VG_STATIC void player_update_post(void)
             budget -= advt;
          }
 
-#if 0
-         if( player.dist_accum >= 5.0f )
-         {
-            audio_lock();
-            audio_player_playclip( &audio_rewind_player, &audio_rewind[4] );
-            audio_unlock();
-
-            player.dist_accum -= 5.0f;
-         }
-#endif
-
          player.rewind_time = vg_maxf( 0.0f, player.rewind_time );
 
          float current_time = vg.time - player.diag_rewind_start,
index dfe8be870a25ad55f0ac084c7d92709391b0b3c3..4b088c17f404b6a5da2025b09720f8e72083a2bd 100644 (file)
--- a/server.c
+++ b/server.c
@@ -337,7 +337,9 @@ int main( int argc, char *argv[] )
    
    /* TODO: Options to override, ammend, remove etc */
 
-   vg_prealloc_quota( 80*1024*1024 );
+   vg_set_mem_quota( 80*1024*1024 );
+   vg_alloc_quota();
+
    highscores_init( 250000, 10000 );
    
    if( !highscores_read() )
diff --git a/world.h b/world.h
index 7b265cd96d1513ea47452fbacd91841d64fe91a8..8b650a5e0c169d336cd0b2a872fe640408c7d29d 100644 (file)
--- a/world.h
+++ b/world.h
@@ -110,6 +110,7 @@ VG_STATIC struct gworld
 
    v3f render_gate_pos;
    int active_route_board;
+   int in_trigger;
 
    /* This is a small flag we use to changelevel.
     * It will not be cleared until all sounds stop playing 
@@ -126,7 +127,8 @@ VG_STATIC struct gworld
     * (world_gen.h)
     * --------------------------------------------------------------------------
     */
-   void *dynamic_vgl;
+   void *dynamic_vgl, 
+        *audio_vgl;  /* sub buffer of the audio buffer */
 
    /*
     * Main world .mdl 
@@ -161,42 +163,46 @@ VG_STATIC struct gworld
    u32 audio_things_count;
 
    /*
-    * Relays, random, etc
+    * Relays
     */
-   struct logic_entity
+   struct logic_relay
    {
       v3f pos;
-      enum logic_type logic_type;
-      int enabled;
 
-      /* indexes the action array */
-      u32 action_start, action_count;
+      struct relay_target
+      {
+         u32 sub_id;
+         enum classtype classtype;
+      }
+      targets[4];
+      u32 target_count;
    }
-   * logic_entities;
-   u32 logic_entity_count;
+   * logic_relays;
+   u32 relay_count;
 
    /*
-    * Action array
+    * Box trigger entities
     */
-   struct logic_action
+   struct trigger_zone
    {
-      u32 event,     /* on trigger, on enable, etc (TODO: Enum) */
-          target_id; /* thing to target, 0: self */
+      m4x3f transform, inv_transform;
 
+      struct relay_target target;
    }
-   * logic_actions;
-   u32 logic_action_count;
+   * triggers;
+   u32 trigger_count;
 
    /*
-    * Box trigger entities
+    * Achievements
     */
-   struct trigger_zone
+   struct logic_achievement
    {
-      m4x3f transform, inv_transform;
-      u32   trigger_entity;
+      v3f pos;
+      const char *achievement_id;
+      u32 achieved;
    }
-   * triggers;
-   u32 trigger_count;
+   * logic_achievements;
+   u32 achievement_count;
 
 
    /*
@@ -431,6 +437,77 @@ VG_STATIC void world_init(void)
                                                    VG_MEMORY_SYSTEM );
 }
 
+VG_STATIC void world_audio_init(void)
+{
+   u32 size = vg_linear_remaining( vg_audio.audio_pool ) 
+               - sizeof(vg_linear_allocator);
+
+   world.audio_vgl = vg_create_linear_allocator( vg_audio.audio_pool, 
+                                                 size, VG_MEMORY_SYSTEM );
+}
+
+VG_STATIC void world_trigger_achievement( u32 uid )
+{
+   struct logic_achievement *ach = &world.logic_achievements[ uid ];
+
+   if( ach->achieved )
+      return;
+
+   steam_set_achievement( ach->achievement_id );
+   steam_store_achievements();
+
+   ach->achieved = 1;
+}
+
+VG_STATIC void world_run_relay( struct relay_target *rt );
+VG_STATIC void world_trigger_relay( u32 uid )
+{
+   struct logic_relay *relay = &world.logic_relays[ uid ];
+
+   for( int i=0; i<relay->target_count; i++ )
+   {
+      world_run_relay( &relay->targets[i] );
+   }
+}
+
+VG_STATIC void world_trigger_audio( u32 uid )
+{
+   struct world_audio_thing *wat = &world.audio_things[ uid ];
+
+   audio_lock();
+   audio_player_playclip( &wat->player, 
+                          &wat->temp_embedded_clip );
+   audio_unlock();
+}
+
+VG_STATIC void world_run_relay( struct relay_target *rt )
+{
+   struct entity_instruction
+   {
+      enum classtype classtype;
+      void (*p_trigger)( u32 uid );
+   }
+   entity_instructions[] =
+   {
+      { k_classtype_logic_achievement, world_trigger_achievement },
+      { k_classtype_logic_relay, world_trigger_relay },
+      { k_classtype_audio, world_trigger_audio }
+   };
+
+   for( int i=0; i<vg_list_size(entity_instructions); i++ )
+   {
+      struct entity_instruction *instr = &entity_instructions[i];
+
+      if( instr->classtype == rt->classtype )
+      {
+         instr->p_trigger( rt->sub_id );
+         return;
+      }
+   }
+
+   vg_error( "Don't know how to trigger classtype %d\n", rt->classtype );
+}
+
 VG_STATIC void world_update( v3f pos )
 {
    if( world.switching_to_new_world )
@@ -502,14 +579,10 @@ VG_STATIC void world_update( v3f pos )
       }
    }
 
-#if 0
-   VG_STATIC int in_zone = 0;
-
-   int in_zone_this_time = 0;
-
-   for( int i=0; i<world.achievement_zones_count; i++ )
+   int in_trigger = 0;
+   for( int i=0; i<world.trigger_count; i++ )
    {
-      struct achievement_zone *zone = &world.achievement_zones[i];
+      struct trigger_zone *zone = &world.triggers[i];
 
       v3f local;
       m4x3_mulv( zone->inv_transform, pos, local );
@@ -518,23 +591,12 @@ VG_STATIC void world_update( v3f pos )
           (fabsf(local[1]) <= 1.0f) &&
           (fabsf(local[2]) <= 1.0f) )
       {
-         in_zone_this_time = 1;
-
-         if( !in_zone && zone->ptarget )
-         {
-            audio_lock();
-            audio_player_playclip( &zone->ptarget->player, 
-                                   &zone->ptarget->temp_embedded_clip );
-            audio_unlock();
-         }
+         in_trigger = 1;
 
-         if( !zone->triggered )
+         if( !world.in_trigger )
          {
-            steam_set_achievement( zone->name );
-            steam_store_achievements();
+            world_run_relay( &zone->target );
          }
-
-         zone->triggered = 1;
       }
 
       vg_line_boxf_transformed( zone->transform, (boxf){{-1.0f,-1.0f,-1.0f},
@@ -542,9 +604,7 @@ VG_STATIC void world_update( v3f pos )
                                                         0xff00ff00 );
    }
 
-   in_zone = in_zone_this_time;
-#endif
-   
+   world.in_trigger = in_trigger;
    sfd_update();
 }
 
index 4605adf662a6107c0a02b0b12c037a39f48f205d..16d64fdefdf8a53af2a1cbb98b28eed71d43702a 100644 (file)
@@ -115,6 +115,16 @@ VG_STATIC void world_ents_allocate(void)
          k_classtype_trigger,
          (void*)&world.triggers,
          sizeof(struct trigger_zone)
+      },
+      {
+         k_classtype_logic_relay,
+         (void*)&world.logic_relays,
+         sizeof(struct logic_relay)
+      },
+      {
+         k_classtype_logic_achievement,
+         (void*)&world.logic_achievements,
+         sizeof(struct logic_achievement)
       }
    };
 
@@ -129,6 +139,7 @@ VG_STATIC void world_ents_allocate(void)
       {
          if( pnode->classtype == entity_counts[j].ct )
          {
+            pnode->sub_uid = entity_counts[j].count;
             entity_counts[j].count ++;
             break;
          }
@@ -199,7 +210,7 @@ VG_STATIC void world_pct_audio( mdl_node *pnode )
    thing->temp_embedded_clip.path = mdl_pstr( world.meta, aud->pstr_file );
    thing->temp_embedded_clip.source_mode = k_audio_source_mono;
 
-   audio_clip_load( &thing->temp_embedded_clip );
+   audio_clip_load( &thing->temp_embedded_clip, world.audio_vgl );
    thing->player.name = mdl_pstr( world.meta, pnode->pstr_name );
    thing->player.enqued = 0;
 
@@ -207,6 +218,71 @@ VG_STATIC void world_pct_audio( mdl_node *pnode )
    world.audio_things_count ++;
 }
 
+
+VG_STATIC void world_pct_trigger( mdl_node *pnode )
+{
+   struct trigger_zone *trigger = &world.triggers[ world.trigger_count ];
+   struct classtype_trigger *inf = mdl_get_entdata( world.meta, pnode );
+   
+   if( inf->target )
+   {
+      mdl_node *target_node = mdl_node_from_id( world.meta, inf->target );
+
+      trigger->target.sub_id = target_node->sub_uid;
+      trigger->target.classtype = target_node->classtype;
+   }
+   else
+   {
+      vg_warn( "Trigger with no target...\n" );
+      return;
+   }
+
+   mdl_node_transform( pnode, trigger->transform );
+   m4x3_invert_full( trigger->transform, trigger->inv_transform );
+
+   world.trigger_count ++;
+}
+
+
+VG_STATIC void world_pct_relay( mdl_node *pnode )
+{
+   struct logic_relay *relay = &world.logic_relays[ world.relay_count ];
+   struct classtype_logic_relay *inf = mdl_get_entdata( world.meta, pnode );
+
+   relay->target_count = 0;
+
+   for( int i=0; i<vg_list_size(relay->targets); i++ )
+   {
+      if( inf->targets[i] )
+      {
+         struct relay_target *target = &relay->targets[relay->target_count ++];
+         mdl_node *other = mdl_node_from_id( world.meta, inf->targets[i] );
+         
+         target->classtype = other->classtype;
+         target->sub_id = other->sub_uid;
+      }
+   }
+
+   v3_copy( pnode->co, relay->pos );
+   world.relay_count ++;
+}
+
+
+VG_STATIC void world_pct_achievement( mdl_node *pnode )
+{
+   struct logic_achievement *ach = 
+      &world.logic_achievements[ world.achievement_count ];
+   struct classtype_logic_achievement *inf = 
+      mdl_get_entdata( world.meta, pnode );
+
+   v3_copy( pnode->co, ach->pos );
+   ach->achievement_id = mdl_pstr( world.meta, inf->pstr_name );
+   ach->achieved = 0;
+
+   world.achievement_count ++;
+}
+
+
 VG_STATIC void world_entities_process(void)
 {
    struct entity_instruction
@@ -219,6 +295,9 @@ VG_STATIC void world_entities_process(void)
       { k_classtype_spawn,    world_pct_spawn },
       { k_classtype_water,    world_pct_water },
       { k_classtype_audio,    world_pct_audio },
+      { k_classtype_trigger,  world_pct_trigger },
+      { k_classtype_logic_relay, world_pct_relay },
+      { k_classtype_logic_achievement, world_pct_achievement }
    };
 
    for( int i=0; i<world.meta->info.node_count; i++ )
@@ -235,50 +314,7 @@ VG_STATIC void world_entities_process(void)
             break;
          }
       }
-      
-#if 0
-      else if( pnode->classtype == k_classtype_achievement_box )
-      {
-         world.achievement_zones = 
-            buffer_reserve( world.achievement_zones,
-                            world.achievement_zones_count,
-                            &world.achievement_zones_cap, 1, 
-                            sizeof(struct achievement_zone) );
-
-         struct achievement_zone *zone = &world.achievement_zones[ 
-                                          world.achievement_zones_count ++ ];
-
-
-         struct classtype_achievement_box *box = mdl_get_entdata(mworld,pnode);
-
-         mdl_node_transform( pnode, zone->transform );
-         m4x3_invert_full( zone->transform, zone->inv_transform );
-         vg_strncpy( mdl_pstr(mworld, box->pstr_name), zone->name, 31 );
-         zone->name[31] = 0x00;
-         zone->triggered = 0;
-
-         if( box->trigger )
-            zone->ptarget_delegated = mdl_node_from_id( mworld, box->trigger );
-         else
-            zone->ptarget_delegated = NULL;
-      }
-#endif
    }
-
-#if 0
-   /* fixup links */
-   for( int i=0; i<world.achievement_zones_count; i ++ )
-   {
-      struct achievement_zone *ach = &world.achievement_zones[ i ];
-      if( ach->ptarget_delegated )
-      {
-         u32 id = ach->ptarget_delegated->sub_uid;
-         ach->ptarget = &world.audio_things[ id ];
-      }
-      else
-         ach->ptarget = NULL;
-   }
-#endif
 }
 
 VG_STATIC void world_generate(void)
@@ -413,6 +449,7 @@ VG_STATIC void world_generate(void)
    world.scene_no_collide = NULL;
 }
 
+VG_STATIC int reset_player( int argc, char const *argv[] );
 VG_STATIC void world_post_process(void)
 {
    /* initialize audio if need be */
@@ -505,6 +542,8 @@ VG_STATIC void world_post_process(void)
    /*
     * Setup scene collider 
     */
+
+   reset_player( 1, (const char *[]){"start"} );
 }
 
 
@@ -538,6 +577,7 @@ VG_STATIC void world_unload(void)
 
    /* delete the entire block of memory */
    vg_linear_clear( world.dynamic_vgl );
+   vg_linear_clear( world.audio_vgl );
 
    /* clean dangling pointers */
    world.meta = NULL;
@@ -556,15 +596,15 @@ VG_STATIC void world_unload(void)
    world.audio_things = NULL;
    world.audio_things_count = 0;
 
-   world.logic_entities = NULL;
-   world.logic_entity_count = 0;
-
-   world.logic_actions = NULL;
-   world.logic_action_count = 0;
-
    world.triggers = NULL;
    world.trigger_count = 0;
 
+   world.logic_relays = NULL;
+   world.relay_count = 0;
+
+   world.logic_achievements = NULL;
+   world.achievement_count = 0;
+
    world.nodes = NULL;
    world.node_count = 0;