switch to entity list
[carveJwlIkooP6JGAAIwe30JlM.git] / blender_export.py
index ede1106b484ec22db611381473a47cb9cb501395..820c49ac05e6f721af4ca38ab7f02e200bb5e616 100644 (file)
@@ -33,7 +33,10 @@ sr_entity_list = [
    ('ent_skateshop',    'Skate Shop',     '', 12 ),
    ('ent_camera',       'Camera',         '', 13 ),
    ('ent_swspreview', 'Workshop Preview', '', 14 ),
-   ('ent_menuitem',     'Menu Item',      '', 15 )
+   ('ent_menuitem',     'Menu Item',      '', 15 ),
+   ('ent_worldinfo',    'World Info',     '', 16 ),
+   ('ent_ccmd',         'CCmd',           '', 17 ),
+   ('ent_challenge',    'Challenge',      '', 18 )
 ]
 
 def get_entity_enum_id( alias ):
@@ -185,6 +188,7 @@ class ent_gate(Structure):
 #{
    _fields_ = [("type",c_uint32),
                ("target", c_uint32),
+               ("key",c_uint32),
                ("dimensions", c_float*3),
                ("co", (c_float*3)*2),
                ("q", (c_float*4)*2),
@@ -340,13 +344,35 @@ class ent_traffic(Structure):
                ("index",c_uint32)]
 #}
 
-class ent_skateshop(Structure):
+# Skateshop
+# ---------------------------------------------------------------
+class ent_skateshop_characters(Structure):
 #{
-   _fields_ = [("transform",mdl_transform),
-               ("id_display",c_uint32),
+   _fields_ = [("id_display",c_uint32),
+               ("id_info",c_uint32)]
+#}
+class ent_skateshop_boards(Structure):
+#{
+   _fields_ = [("id_display",c_uint32),
                ("id_info",c_uint32),
-               ("id_rack",c_uint32),
-               ("id_camera",c_uint32)]
+               ("id_rack",c_uint32)]
+#}  
+class ent_skateshop_worlds(Structure):
+#{
+   _fields_ = [("id_display",c_uint32),
+               ("id_info",c_uint32)]
+#}
+class ent_skateshop_anon_union(Union):
+#{
+   _fields_ = [("boards",ent_skateshop_boards),
+               ("character",ent_skateshop_characters),
+               ("worlds",ent_skateshop_worlds)]
+#}
+class ent_skateshop(Structure):
+#{
+   _fields_ = [("transform",mdl_transform), ("type",c_uint32),
+               ("id_camera",c_uint32), 
+               ("_anonymous_union",ent_skateshop_anon_union)]
 #}
 
 class ent_swspreview(Structure):
@@ -356,6 +382,8 @@ class ent_swspreview(Structure):
                ("id_display1",c_uint32)]
 #}
 
+# Menu
+# -----------------------------------------------------------------
 class ent_menuitem_slider(Structure):
 #{
    _fields_ = [("id_min",c_uint32),
@@ -363,25 +391,22 @@ class ent_menuitem_slider(Structure):
                ("id_handle",c_uint32),
                ("pstr_data",c_uint32)]
 #}
-
 class ent_menuitem_button(Structure):
 #{
    _fields_ = [("pstr",c_uint32)]
 #}
-
 class ent_menuitem_checkmark(Structure):
 #{
    _fields_ = [("id_check",c_uint32),
-               ("pstr_data",c_uint32)]
+               ("pstr_data",c_uint32),
+               ("offset",c_float*3)]
 #}
-
 class ent_menuitem_page(Structure):
 #{
    _fields_ = [("pstr_name",c_uint32),
                ("id_entrypoint",c_uint32),
                ("id_viewpoint",c_uint32)]
 #}
-
 class ent_menuitem_anon_union(Union):
 #{
    _fields_ = [("slider",ent_menuitem_slider),
@@ -389,14 +414,15 @@ class ent_menuitem_anon_union(Union):
                ("checkmark",ent_menuitem_checkmark),
                ("page",ent_menuitem_page)]
 #}
-
 class ent_menuitem(Structure):
 #{
    _fields_ = [("type",c_uint32), ("groups",c_uint32),
-               ("id_links",c_uint32*4),
+               ("id_links",c_uint32*4), 
+               ("factive",c_float), ("fvisible",c_float),
                #-- TODO: Refactor this into a simple mesh structure
                ("transform",mdl_transform),
                ("submesh_start",c_uint32),("submesh_count",c_uint32),
+               ("_u64",c_uint64),
                #-- end
                ("_anonymous_union", ent_menuitem_anon_union)]
 #}
@@ -407,6 +433,30 @@ class ent_camera(Structure):
                ("fov",c_float)]
 #}
 
+class ent_worldinfo(Structure):
+#{
+   _fields_ = [("pstr_name",c_uint32),
+               ("pstr_author",c_uint32),    # unused
+               ("pstr_desc",c_uint32),      # unused
+               ("timezone",c_float)]
+#}
+
+class ent_ccmd(Structure):
+#{
+   _fields_ = [("pstr_command",c_uint32)]
+#}
+
+class ent_challenge(Structure):#{
+   _fields_ = [("transform",mdl_transform),
+               ("submesh_start",c_uint32), ("submesh_count",c_uint32),
+               ("id_next",c_uint32),
+               ("filter",c_uint32),
+               ("time_limit",c_float)]
+
+   sr_functions = { 0: 'trigger',
+                    1: 'start_challenge' }
+#}
+
 def obj_ent_type( obj ):
 #{
    if obj.type == 'ARMATURE': return 'mdl_armature'
@@ -430,6 +480,31 @@ def sr_filter_ent_type( obj, ent_types ):
    return False
 #}
 
+def v4_dot( a, b ):#{
+   return a[0]*b[0] + a[1]*b[1] + a[2]*b[2] + a[3]*b[3]
+#}
+
+def q_identity( q ):#{
+   q[0] = 0.0
+   q[1] = 0.0
+   q[2] = 0.0
+   q[3] = 1.0
+#}
+
+def q_normalize( q ):#{
+   l2 = v4_dot(q,q)
+   if( l2 < 0.00001 ):#{
+      q_identity( q )
+   #}
+   else:#{
+      s = 1.0/math.sqrt(l2)
+      q[0] *= s
+      q[1] *= s
+      q[2] *= s
+      q[3] *= s
+   #}
+#}
+
 def compile_obj_transform( obj, transform ):
 #{
    co = obj.matrix_world @ Vector((0,0,0))
@@ -437,6 +512,7 @@ def compile_obj_transform( obj, transform ):
    # This was changed from matrix_local on 09.05.23
    q = obj.matrix_world.to_quaternion() 
    s = obj.scale
+   q_normalize( q )
    
    # Setup transform
    #
@@ -671,6 +747,7 @@ def sr_compile_material( mat ):
          if mat.SR_data.skate_surface: flags |= 0x1
          if mat.SR_data.grow_grass: flags |= 0x4
          if mat.SR_data.grind_surface: flags |= 0x8
+         if mat.SR_data.preview_visibile: flags |= 0x40
       #}
       if mat.SR_data.shader == 'invisible': flags |= 0x10
       if mat.SR_data.shader == 'boundary': flags |= (0x10|0x20)
@@ -721,14 +798,18 @@ def sr_compile_material( mat ):
    if mat.SR_data.shader == 'boundary':#{
       m.shader = 6
    #}
+
+   if mat.SR_data.shader == 'fxglow':#{
+      m.shader = 7
+   #}
    
    inf = material_info( mat )
 
    if mat.SR_data.shader == 'standard' or \
       mat.SR_data.shader == 'standard_cutout' or \
       mat.SR_data.shader == 'terrain_blend' or \
-      mat.SR_data.shader == 'vertex_blend':
-   #{
+      mat.SR_data.shader == 'vertex_blend' or \
+      mat.SR_data.shader == 'fxglow': #{
       if 'tex_diffuse' in inf: 
          m.tex_diffuse = sr_compile_texture(inf['tex_diffuse'])
    #}
@@ -750,8 +831,9 @@ def sr_armature_bones( armature ):
          yield from _recurse_bone( b )
 #}
 
-def sr_entity_id( obj ):
-#{
+def sr_entity_id( obj ):#{
+   if not obj: return 0
+   
    tipo = get_entity_enum_id( obj_ent_type(obj) )
    index = sr_compile.entity_ids[ obj.name ]
 
@@ -1149,7 +1231,7 @@ def sr_compile_fonts( collection ):
 
 def sr_compile_menus( collection ):
 #{
-   print( "[SR] Compiling menus" )
+   print( "[SR1] Compiling menus" )
    groups = []
 
    for obj in collection.all_objects:#{
@@ -1176,18 +1258,23 @@ def sr_compile_menus( collection ):
 
       if item.type == 1 or item.type == 2:#{
          item_button = item._anonymous_union.button
-         item_button.string = sr_compile_string( obj_data.string )
+         item_button.pstr = sr_compile_string( obj_data.string )
       #}
       elif item.type == 3:#{
          item_checkmark = item._anonymous_union.checkmark
          item_checkmark.pstr_data = sr_compile_string( obj_data.string )
          item_checkmark.id_check = sr_entity_id( obj_data.checkmark )
+         delta = obj_data.checkmark.location - obj.location
+         item_checkmark.offset[0] =  delta[0]
+         item_checkmark.offset[1] =  delta[2]
+         item_checkmark.offset[2] = -delta[1]
       #}
       elif item.type == 4:#{
          item_slider = item._anonymous_union.slider
          item_slider.id_min = sr_entity_id( obj_data.slider_minloc )
          item_slider.id_max = sr_entity_id( obj_data.slider_maxloc )
          item_slider.id_handle = sr_entity_id( obj_data.slider_handle )
+         item_slider.pstr_data = sr_compile_string( obj_data.string )
       #}
       elif item.type == 5:#{
          item_page = item._anonymous_union.page
@@ -1340,6 +1427,7 @@ def sr_compile_armature( obj ):
                      lc_m = smtx.inverted() @ lc_m
                   #}
                   rq = lc_m.to_quaternion()
+                  q_normalize( rq )
 
                   kf = mdl_transform()
                   kf.co[0] =  loc[0]
@@ -1483,6 +1571,7 @@ def sr_compile( collection ):
          if ent_type == 'ent_font': continue
          if ent_type == 'ent_font_variant': continue
          if ent_type == 'ent_menuitem': continue
+         if ent_type == 'ent_challenge': continue
          #--------------------------
 
          print( F'[SR] {i: 3}/{mesh_count} {obj.name:<40}', end='\r' )
@@ -1537,7 +1626,8 @@ def sr_compile( collection ):
                #}
             #}
             elif obj_data.tipo == 'nonlocal':#{
-               gate.target = sr_compile_string(obj_data.key)
+               gate.target = 0
+               gate.key = sr_compile_string(obj_data.key)
                gate.type = 2
             #}
             else: gate.type = 0
@@ -1637,6 +1727,7 @@ def sr_compile( collection ):
 
             if obj_data.target:#{
                volume.target = sr_entity_id( obj_data.target )
+               volume._anon.trigger.event = obj_data.event
             #}
 
             sr_ent_push(volume)
@@ -1650,9 +1741,23 @@ def sr_compile( collection ):
          elif ent_type == 'ent_skateshop':#{
             skateshop = ent_skateshop()
             obj_data = obj.SR_data.ent_skateshop[0]
-            skateshop.id_display = sr_entity_id( obj_data.mark_display )
-            skateshop.id_info = sr_entity_id( obj_data.mark_info )
-            skateshop.id_rack = sr_entity_id( obj_data.mark_rack )
+            skateshop.type = int(obj_data.tipo)
+            if skateshop.type == 0:#{
+               boardshop = skateshop._anonymous_union.boards
+               boardshop.id_display = sr_entity_id( obj_data.mark_display )
+               boardshop.id_info = sr_entity_id( obj_data.mark_info )
+               boardshop.id_rack = sr_entity_id( obj_data.mark_rack )
+            #}
+            elif skateshop.type == 1:#{
+               charshop = skateshop._anonymous_union.character
+               charshop.id_display = sr_entity_id( obj_data.mark_display )
+               charshop.id_info = sr_entity_id( obj_data.mark_info )
+            #}
+            elif skateshop.type == 2:#{
+               worldshop = skateshop._anonymous_union.worlds
+               worldshop.id_display = sr_entity_id( obj_data.mark_display )
+               worldshop.id_info = sr_entity_id( obj_data.mark_info )
+            #}
             skateshop.id_camera = sr_entity_id( obj_data.cam )
             compile_obj_transform( obj, skateshop.transform )
             sr_ent_push(skateshop)
@@ -1665,6 +1770,34 @@ def sr_compile( collection ):
             workshop_preview.id_camera = sr_entity_id( obj_data.cam )
             sr_ent_push( workshop_preview )
          #}
+         elif ent_type == 'ent_worldinfo':#{
+            worldinfo = ent_worldinfo()
+            obj_data = obj.SR_data.ent_worldinfo[0]
+            worldinfo.pstr_name = sr_compile_string( obj_data.name )
+            worldinfo.pstr_author = sr_compile_string( obj_data.author )
+            worldinfo.pstr_desc = sr_compile_string( obj_data.desc )
+            worldinfo.timezone = obj_data.timezone
+            sr_ent_push( worldinfo )
+         #}
+         elif ent_type == 'ent_ccmd':#{
+            ccmd = ent_ccmd()
+            obj_data = obj.SR_data.ent_ccmd[0]
+            ccmd.pstr_command = sr_compile_string( obj_data.command )
+            sr_ent_push( ccmd )
+         #}
+         elif ent_type == 'ent_challenge':#{
+            challenge = ent_challenge()
+            obj_data = obj.SR_data.ent_challenge[0]
+            challenge.id_next = sr_entity_id( obj_data.proxima )
+            challenge.filter = 0
+            challenge.time_limit = obj_data.time_limit
+
+            compile_obj_transform( obj, challenge.transform )
+            challenge.submesh_start, challenge.submesh_count, _ = \
+                  sr_compile_mesh_internal( obj )
+
+            sr_ent_push( challenge )
+         #}
       #}
    #}
 
@@ -1860,6 +1993,7 @@ def sr_compile( collection ):
    path = F"{folder}{collection.name}.mdl"
    print( path )
 
+   os.makedirs(os.path.dirname(path),exist_ok=True)
    fp = open( path, "wb" )
    header = mdl_header()
    header.version = 101
@@ -2176,6 +2310,7 @@ class SR_MATERIAL_PANEL(bpy.types.Panel):
             row.prop( active_mat.SR_data, "skate_surface" )
             row.prop( active_mat.SR_data, "grind_surface" )
             row.prop( active_mat.SR_data, "grow_grass" )
+            row.prop( active_mat.SR_data, "preview_visibile" )
          #}
       #}
 
@@ -2602,8 +2737,7 @@ class SR_OBJECT_ENT_ROUTE(bpy.types.PropertyGroup):
    #}
 #}
 
-class SR_OBJECT_ENT_VOLUME(bpy.types.PropertyGroup):
-#{
+class SR_OBJECT_ENT_VOLUME(bpy.types.PropertyGroup):#{
    subtype: bpy.props.EnumProperty(
       name="Subtype",
       items=[('0','Trigger',''),
@@ -2613,14 +2747,33 @@ class SR_OBJECT_ENT_VOLUME(bpy.types.PropertyGroup):
    target: bpy.props.PointerProperty( \
            type=bpy.types.Object, name="Target", \
            poll=lambda self,obj: sr_filter_ent_type(obj,\
-                                    ['ent_audio','ent_skateshop']))
+                                    ['ent_audio','ent_skateshop','ent_ccmd',\
+                                     'ent_challenge']))
+
+   event: bpy.props.IntProperty( name="Event/Method" )
 
    @staticmethod
-   def sr_inspector( layout, data ):
-   #{
-      data = data[0]
-      layout.prop( data, 'subtype' )
-      layout.prop( data, 'target' )
+   def sr_inspector( layout, data ):#{
+      layout.prop( data[0], 'subtype' )
+      layout.prop( data[0], 'target' )
+
+      row = layout.row()
+      row.prop( data[0], 'event' )
+
+      if data[0].target:#{
+         tipo = data[0].target.SR_data.ent_type
+         cls = globals()[ tipo ]
+
+         table = getattr( cls, 'sr_functions', None )
+         if table:#{
+            if data[0].event in table:#{
+               row.label( text=table[data[0].event] )
+            #}
+            else:#{
+               row.label( text="undefined function" )
+            #}
+         #}
+      #}
    #}
 #}
 
@@ -2684,16 +2837,15 @@ class SR_OBJECT_ENT_AUDIO(bpy.types.PropertyGroup):
       box.prop( data[0], 'flag_loop' )
       box.prop( data[0], 'flag_auto' )
 
+      layout.prop( data[0], 'probability_curve' )
+
       split = layout.split(factor=0.7)
       c = split.column()
       c.label( text='Filepath' )
       c = split.column()
-      c.label( text='Chance (0.1s)' )
-
-      layout.prop( data[0], 'probability_curve' )
-
+      c.label( text='Chance' )
       layout.template_list('SR_UL_AUDIO_LIST', 'Files', \
-                            data[0], 'files', data[0], 'file_index', rows=5)
+                            data[0], 'files', data[0], 'files_index', rows=5)
 
       row = layout.row()
       row.operator( 'skaterift.al_new_entry', text='Add' )
@@ -2766,6 +2918,10 @@ class SR_OBJECT_ENT_TRAFFIC(bpy.types.PropertyGroup):
 
 class SR_OBJECT_ENT_SKATESHOP(bpy.types.PropertyGroup):
 #{
+   tipo: bpy.props.EnumProperty( name='Type',
+                                 items=[('0','boards',''),
+                                        ('1','character',''),
+                                        ('2','world','')] )
    mark_rack: bpy.props.PointerProperty( \
            type=bpy.types.Object, name="Board Rack", \
            poll=lambda self,obj: sr_filter_ent_type(obj,['ent_marker']))
@@ -2886,6 +3042,31 @@ class SR_OBJECT_ENT_MENU_ITEM(bpy.types.PropertyGroup):
    #}
 #}
 
+class SR_OBJECT_ENT_WORLD_INFO(bpy.types.PropertyGroup):
+#{
+   name: bpy.props.StringProperty(name="Name")
+   desc: bpy.props.StringProperty(name="Description")
+   author: bpy.props.StringProperty(name="Author")
+   timezone: bpy.props.FloatProperty(name="Timezone(hrs) (UTC0 +hrs)")
+#}
+
+class SR_OBJECT_ENT_CCMD(bpy.types.PropertyGroup):
+#{
+   command: bpy.props.StringProperty(name="Command Line")
+#}
+
+class SR_OBJECT_ENT_CHALLENGE(bpy.types.PropertyGroup):#{
+   proxima: bpy.props.PointerProperty( \
+            type=bpy.types.Object, name="Next", \
+            poll=lambda self,obj: sr_filter_ent_type(obj,['ent_challenge']))
+   target: bpy.props.PointerProperty( \
+           type=bpy.types.Object, name="Target", \
+           poll=lambda self,obj: sr_filter_ent_type(obj,\
+                                    ['ent_audio','ent_ccmd']))
+   event: bpy.props.IntProperty( name="Event/Method" )
+   time_limit: bpy.props.FloatProperty( name="Time Limit", default=1.0 )
+#}
+
 class SR_OBJECT_PROPERTIES(bpy.types.PropertyGroup):
 #{
    ent_gate: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_GATE)
@@ -2901,6 +3082,9 @@ class SR_OBJECT_PROPERTIES(bpy.types.PropertyGroup):
    ent_swspreview: \
          bpy.props.CollectionProperty(type=SR_OBJECT_ENT_WORKSHOP_PREVIEW)
    ent_menuitem: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_MENU_ITEM)
+   ent_worldinfo: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_WORLD_INFO)
+   ent_ccmd: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_CCMD)
+   ent_challenge: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_CHALLENGE)
 
    ent_type: bpy.props.EnumProperty(
       name="Type",
@@ -2975,7 +3159,8 @@ class SR_MATERIAL_PROPERTIES(bpy.types.PropertyGroup):
       ('vertex_blend', "vertex_blend", ''),
       ('water',"water",''),
       ('invisible','Invisible',''),
-      ('boundary','Boundary','')
+      ('boundary','Boundary',''),
+      ('fxglow','FX Glow',''),
       ])
 
    surface_prop: bpy.props.EnumProperty(
@@ -3008,6 +3193,11 @@ class SR_MATERIAL_PROPERTIES(bpy.types.PropertyGroup):
          default=False,\
          description = "Spawn grass sprites on this surface?" \
    )
+   preview_visibile: bpy.props.BoolProperty( \
+         name="Preview visibile", \
+         default=True,\
+         description = "Show this material in preview models?" \
+   )
    blend_offset: bpy.props.FloatVectorProperty( \
          name="Blend Offset", \
          size=2, \
@@ -3304,7 +3494,8 @@ def cv_draw_lines():
          cv_view_shader, 'LINES', \
          { "pos":cv_view_verts, "color":cv_view_colours })
 
-   lines.draw( cv_view_shader )
+   if bpy.context.scene.SR_data.gizmos:
+      lines.draw( cv_view_shader )
 
    cv_view_verts = []
    cv_view_colours = []
@@ -3381,8 +3572,8 @@ def draw_cone_twist( center, vx, vy, va ):
       p0 = center + (axis + vx*c0 + vy*s0).normalized() * size
       p1 = center + (axis + vx*c1 + vy*s1).normalized() * size
 
-      col0 = ( abs(c0), abs(s0), 0.0, 1.0 )
-      col1 = ( abs(c1), abs(s1), 0.0, 1.0 )
+      col0 = ( abs(c0), abs(s0), 0.0 )
+      col1 = ( abs(c1), abs(s1), 0.0 )
 
       cv_view_verts += [center, p0, p0, p1]
       cv_view_colours += [ (0,0,0), col0, col0, col1 ]
@@ -3539,14 +3730,14 @@ def cv_ent_volume( obj ):
       cv_draw_ucube( obj.matrix_world, (0,1,0) )
 
       if data.target:#{
-         cv_draw_line( obj.location, data.target.location, (0,1,0) )
+         cv_draw_arrow( obj.location, data.target.location, (0,1,0) )
       #}
    #}
    elif data.subtype == '1':#{
       cv_draw_ucube( obj.matrix_world, (1,1,0) )
 
       if data.target:#{
-         cv_draw_line( obj.location, data.target.location, (1,1,0) )
+         cv_draw_arrow( obj.location, data.target.location, (1,1,0) )
       #}
    #}
 #}
@@ -3825,6 +4016,12 @@ def cv_draw():
          elif ent_type == 'ent_volume':#{
             cv_ent_volume( obj )
          #}
+         elif ent_type == 'ent_challenge':#{
+            data = obj.SR_data.ent_challenge[0]
+            if data.proxima:#{
+               cv_draw_arrow( obj.location, data.proxima.location, (0,0.2,1.0) )
+            #}
+         #}
          elif ent_type == 'ent_audio':#{
             if obj.SR_data.ent_audio[0].flag_3d:
                cv_draw_sphere( obj.location, obj.scale[0], (1,1,0) )
@@ -3853,21 +4050,42 @@ def cv_draw():
             #}
          #}
          elif ent_type == 'ent_skateshop':#{
-            cc = (0.0,0.9,0.6)
-            cc1 = (0.4,0.9,0.2)
-            cc2 = (0.9,0.6,0.1)
-
             data = obj.SR_data.ent_skateshop[0]
             display = data.mark_display
             info = data.mark_info
-            rack = data.mark_rack
 
-            rack_cu = Vector((3.15,2.0,0.1))*0.5
-            rack_co = Vector((0.0,0.0,0.0))
-            display_cu = Vector((0.3,1.2,0.1))*0.5
-            display_co = Vector((0.0,0.0,0.1))*0.5
-            info_cu = Vector((1.2,0.01,0.3))*0.5
-            info_co = Vector((0.0,0.0,0.0))*0.5
+            if data.tipo == '0':#{
+               cc = (0.0,0.9,0.6)
+               cc1 = (0.4,0.9,0.2)
+               cc2 = (0.9,0.6,0.1)
+
+               rack = data.mark_rack
+
+               rack_cu = Vector((3.15,2.0,0.1))*0.5
+               rack_co = Vector((0.0,0.0,0.0))
+               display_cu = Vector((0.3,1.2,0.1))*0.5
+               display_co = Vector((0.0,0.0,0.1))*0.5
+               info_cu = Vector((1.2,0.01,0.3))*0.5
+               info_co = Vector((0.0,0.0,0.0))*0.5
+            #}
+            elif data.tipo == '1':#{
+               rack = None
+               cc1 = (1.0,0.0,0.0)
+               cc2 = (1.0,0.5,0.0)
+               display_cu = Vector((0.4,0.4,2.0))*0.5
+               display_co = Vector((0.0,0.0,1.0))*0.5
+               info_cu = Vector((1.2,0.01,0.3))*0.5
+               info_co = Vector((0.0,0.0,0.0))*0.5
+            #}
+            elif data.tipo == '2':#{
+               rack = None
+               cc1 = (1.0,0.0,0.0)
+               cc2 = (1.0,0.5,0.0)
+               display_cu = Vector((1.0,1.0,0.5))*0.5
+               display_co = Vector((0.0,0.0,0.5))*0.5
+               info_cu = Vector((1.2,0.01,0.3))*0.5
+               info_co = Vector((0.0,0.0,0.0))*0.5
+            #}
 
             if rack:
                cv_draw_ucube( rack.matrix_world, cc, rack_cu, rack_co )
@@ -3994,6 +4212,8 @@ classes = [ SR_INTERFACE, SR_MATERIAL_PANEL,\
             SR_UL_FONT_VARIANT_LIST,SR_UL_FONT_GLYPH_LIST,\
             SR_OBJECT_ENT_FONT,SR_OBJECT_ENT_TRAFFIC,SR_OBJECT_ENT_SKATESHOP,\
             SR_OBJECT_ENT_WORKSHOP_PREVIEW,SR_OBJECT_ENT_MENU_ITEM,\
+            SR_OBJECT_ENT_WORLD_INFO,SR_OBJECT_ENT_CCMD,\
+            SR_OBJECT_ENT_CHALLENGE,\
             \
             SR_OBJECT_PROPERTIES, SR_LIGHT_PROPERTIES, SR_BONE_PROPERTIES, 
             SR_MESH_PROPERTIES, SR_MATERIAL_PROPERTIES \