-import bpy, math, gpu, os
+import bpy, blf, math, gpu, os
import cProfile
from ctypes import *
from mathutils import *
from gpu_extras.batch import batch_for_shader
from bpy_extras import mesh_utils
+from bpy_extras import view3d_utils
bl_info = {
"name":"Skaterift .mdl exporter",
"category":"Import/Export",
}
-sr_entity_alias = {
- 'ent_gate': 1,
- 'ent_spawn': 2,
- 'ent_route_node': 3,
- 'ent_route': 4,
- 'ent_water': 5,
- 'ent_volume': 6,
- 'ent_audio': 7,
- 'ent_marker': 8,
- 'ent_glyph': 9
-}
+sr_entity_list = [
+ ('none', 'None', '', 0 ),
+ ('ent_gate', 'Gate', '', 1 ),
+ ('ent_spawn', 'Spawn Point', '', 2 ),
+ ('ent_route_node', 'Routing Path', '', 3 ),
+ ('ent_route', 'Skate Course', '', 4 ),
+ ('ent_water', 'Water Surface', '', 5 ),
+ ('ent_volume', 'Volume/Trigger', '', 6 ),
+ ('ent_audio', 'Audio', '', 7 ),
+ ('ent_marker', 'Marker', '', 8 ),
+ ('ent_font', 'Font', '', 9 ),
+ ('ent_font_variant', 'Font:Variant', '', 10 ),
+ ('ent_traffic', 'Traffic Model', '', 11 ),
+ ('ent_skateshop', 'Skate Shop', '', 12 ),
+ ('ent_camera', 'Camera', '', 13 ),
+ ('ent_swspreview', 'Workshop Preview', '', 14 ),
+ ('ent_menuitem', 'Menu Item', '', 15 ),
+ ('ent_worldinfo', 'World Info', '', 16 ),
+ ('ent_ccmd', 'CCmd', '', 17 ),
+ ('ent_objective', 'Objective', '', 18 ),
+ ('ent_challenge', 'Challenge', '', 19 ),
+ ('ent_relay', 'Relay', '', 20 ),
+ ('ent_miniworld', 'Mini World', '', 22 ),
+ ('ent_prop', 'Prop', '', 23 ),
+ ('ent_list', 'Entity List', '', 24 ),
+ ('ent_region', 'Region', '', 25 )
+]
+
+MDL_VERSION_NR = 104
+SR_TRIGGERABLE = [ 'ent_audio', 'ent_ccmd', 'ent_gate', 'ent_challenge', \
+ 'ent_relay', 'ent_skateshop', 'ent_objective', 'ent_route',\
+ 'ent_miniworld', 'ent_region' ]
+
+def get_entity_enum_id( alias ):
+#{
+ for et in sr_entity_list:#{
+ if et[0] == alias:#{
+ return et[3]
+ #}
+ #}
+
+ if alias == 'ent_cubemap': return 21
+
+ return 0
+#}
class mdl_vert(Structure): # 48 bytes. Quite large. Could compress
#{ # the normals and uvs to i16s. Not an
("vertex_start",c_uint32),
("vertex_count",c_uint32),
("bbx",(c_float*3)*2),
- ("material_id",c_uint32)] # index into the material array
+ ("material_id",c_uint16), # index into the material array
+ ("flags",c_uint16)]
#}
class mdl_material(Structure):
("submesh_start",c_uint32),
("submesh_count",c_uint32),
("pstr_name",c_uint32),
- ("flags",c_uint32),
+ ("entity_id",c_uint32),
("armature_id",c_uint32)]
#}
class mdl_texture(Structure):
#{
_fields_ = [("file",mdl_file),
- ("type",c_uint32)]
+ ("glname",c_uint32)]
#}
class mdl_array(Structure):
class ent_gate(Structure):
#{
- _fields_ = [("type",c_uint32),
+ _fields_ = [("flags",c_uint32),
("target", c_uint32),
+ ("key",c_uint32),
("dimensions", c_float*3),
("co", (c_float*3)*2),
("q", (c_float*4)*2),
("_anonymous_union",version_refcount_union),
("timing_time",c_double),
("routes",c_uint16*4),
- ("route_count",c_uint8)]
+ ("route_count",c_uint8),
+ ("submesh_start",c_uint32), # v102+
+ ("submesh_count",c_uint32), # v102+ (can be 0)
+ ]
+ sr_functions = { 0: 'unlock' }
#}
class ent_route_node(Structure):
("factive",c_float),
("board_transform",(c_float*3)*4),
("sm",mdl_submesh),
- ("latest_pass",c_double)]
+ ("latest_pass",c_double),
+ ("id_camera",c_uint32), # v103+
+ ]
+
+ sr_functions = { 0: 'view' }
+#}
+
+class ent_list(Structure):#{
+ _fields_ = [("start",c_uint16),("count",c_uint16)]
#}
class ent_water(Structure):
class volume_trigger(Structure):
#{
_fields_ = [("event",c_uint32),
- ("blank",c_uint32)]
+ ("event_leave",c_uint32)]
#}
class volume_particles(Structure):
("particles",volume_particles)]
#}
-class ent_index(Structure):
-#{
- _fields_ = [("type",c_uint32),
- ("index",c_uint32)]
-#}
-
class ent_volume(Structure):
#{
_fields_ = [("transform",mdl_transform),
("to_world",(c_float*3)*4),
("to_local",(c_float*3)*4),
("type",c_uint32),
- ("target",ent_index),
+ ("target",c_uint32),
("_anon",volume_union)]
#}
("glyph_utf32_base",c_uint32)]
#}
+class ent_traffic(Structure):
+#{
+ _fields_ = [("transform",mdl_transform),
+ ("submesh_start",c_uint32),
+ ("submesh_count",c_uint32),
+ ("start_node",c_uint32),
+ ("node_count",c_uint32),
+ ("speed",c_float),
+ ("t",c_float),
+ ("index",c_uint32)]
+#}
+
+# Skateshop
+# ---------------------------------------------------------------
+class ent_skateshop_characters(Structure):
+#{
+ _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)]
+#}
+class ent_skateshop_worlds(Structure):
+#{
+ _fields_ = [("id_display",c_uint32),
+ ("id_info",c_uint32)]
+#}
+class ent_skateshop_server(Structure):
+#{
+ _fields_ = [("id_lever",c_uint32)]
+#}
+class ent_skateshop_anon_union(Union):
+#{
+ _fields_ = [("boards",ent_skateshop_boards),
+ ("character",ent_skateshop_characters),
+ ("worlds",ent_skateshop_worlds),
+ ("server",ent_skateshop_server)]
+#}
+class ent_skateshop(Structure):
+#{
+ _fields_ = [("transform",mdl_transform), ("type",c_uint32),
+ ("id_camera",c_uint32),
+ ("_anonymous_union",ent_skateshop_anon_union)]
+
+ sr_functions = { 0: 'trigger' }
+#}
+
+class ent_swspreview(Structure):
+#{
+ _fields_ = [("id_camera",c_uint32),
+ ("id_display",c_uint32),
+ ("id_display1",c_uint32)]
+#}
+
+# Menu
+# -----------------------------------------------------------------
+class ent_menuitem_visual(Structure):
+#{
+ _fields_ = [("pstr_name",c_uint32)]
+#}
+class ent_menuitem_slider(Structure):
+#{
+ _fields_ = [("id_min",c_uint32),
+ ("id_max",c_uint32),
+ ("id_handle",c_uint32),
+ ("pstr_data",c_uint32)]
+#}
+class ent_menuitem_button(Structure):
+#{
+ _fields_ = [("pstr",c_uint32),
+ ("stack_behaviour",c_uint32)]
+#}
+class ent_menuitem_checkmark(Structure):
+#{
+ _fields_ = [("id_check",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_binding(Structure):
+#{
+ _fields_ = [("pstr_bind",c_uint32),
+ ("font_variant",c_uint32)]
+#}
+class ent_menuitem_anon_union(Union):
+#{
+ _fields_ = [("slider",ent_menuitem_slider),
+ ("button",ent_menuitem_button),
+ ("checkmark",ent_menuitem_checkmark),
+ ("page",ent_menuitem_page),
+ ("visual",ent_menuitem_visual),
+ ("binding",ent_menuitem_binding)]
+#}
+class ent_menuitem(Structure):
+#{
+ _fields_ = [("type",c_uint32), ("groups",c_uint32),
+ ("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)]
+#}
+
+class ent_camera(Structure):
+#{
+ _fields_ = [("transform",mdl_transform),
+ ("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),
+ ("pstr_skybox",c_uint32),
+ ("flags",c_uint32)]
+#}
+
+class ent_ccmd(Structure):
+#{
+ _fields_ = [("pstr_command",c_uint32)]
+#}
+
+class ent_objective(Structure):#{
+ _fields_ = [("transform",mdl_transform),
+ ("submesh_start",c_uint32), ("submesh_count",c_uint32),
+ ("flags",c_uint32),
+ ("id_next",c_uint32),
+ ("filter",c_uint32),("filter2",c_uint32),
+ ("id_win",c_uint32),
+ ("win_event",c_uint32),
+ ("time_limit",c_float)]
+
+ sr_functions = { 0: 'trigger',
+ 2: 'show',
+ 3: 'hide' }
+#}
+
+class ent_challenge(Structure):#{
+ _fields_ = [("transform",mdl_transform),
+ ("pstr_alias",c_uint32),
+ ("flags",c_uint32),
+ ("target",c_uint32),
+ ("target_event",c_uint32),
+ ("reset",c_uint32),
+ ("reset_event",c_uint32),
+ ("first",c_uint32),
+ ("camera",c_uint32),
+ ("status",c_uint32)] #runtime
+ sr_functions = { 0: 'unlock',
+ 1: 'view/reset' }
+#}
+
+class ent_region(Structure):#{
+ _fields_ = [("transform",mdl_transform),
+ ("submesh_start",c_uint32), ("submesh_count",c_uint32),
+ ("pstr_title",c_uint32),
+ ("flags",c_uint32),
+ ("zone_volume",c_uint32)]
+ sr_functions = { 0: 'enter', 1: 'leave' }
+#}
+
+class ent_relay(Structure):#{
+ _fields_ = [("targets",(c_uint32*2)*4),
+ ("targets_events",c_uint32*4)]
+ sr_functions = { 0: 'trigger' }
+#}
+
+class ent_cubemap(Structure):#{
+ _fields_ = [("co",c_float*3),
+ ("resolution",c_uint32), #placeholder
+ ("live",c_uint32), #placeholder
+ ("texture_id",c_uint32), #engine
+ ("framebuffer_id",c_uint32),#engine
+ ("renderbuffer_id",c_uint32),#engine
+ ("placeholder",c_uint32*2)]
+#}
+
+print( sizeof(ent_cubemap) )
+
+class ent_miniworld(Structure):#{
+ _fields_ = [("transform",mdl_transform),
+ ("pstr_world",c_uint32),
+ ("camera",c_uint32),
+ ("proxy",c_uint32)]
+
+ sr_functions = { 0: 'zone', 1: 'leave' }
+#}
+
+class ent_prop(Structure):#{
+ _fields_ = [("transform",mdl_transform),
+ ("submesh_start",c_uint32),
+ ("submesh_count",c_uint32),
+ ("flags",c_uint32),
+ ("pstr_alias",c_uint32)]
+#}
+
def obj_ent_type( obj ):
#{
if obj.type == 'ARMATURE': return 'mdl_armature'
elif obj.type == 'LIGHT': return 'ent_light'
+ elif obj.type == 'CAMERA': return 'ent_camera'
+ elif obj.type == 'LIGHT_PROBE' and obj.data.type == 'CUBEMAP':
+ return 'ent_cubemap'
else: return obj.SR_data.ent_type
#}
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))
- q = obj.matrix_local.to_quaternion()
+
+ # This was changed from matrix_local on 09.05.23
+ q = obj.matrix_world.to_quaternion()
s = obj.scale
+ q_normalize( q )
# Setup transform
#
index = len( sr_compile.string_data )
sr_compile.string_cache[s] = index
+ sr_compile.string_data.extend( c_uint32(hash_djb2(s)) )
sr_compile.string_data.extend( s.encode('utf-8') )
sr_compile.string_data.extend( b'\0' )
"Color": material_tex_image("tex_normal")
}
}
+ },
+ "Emission":
+ {
+ "Color": material_tex_image("tex_diffuse")
}
}
texture_index = (len(sr_compile.texture_data)//sizeof(mdl_texture)) +1
tex = mdl_texture()
- tex.type = 0
+ tex.glname = 0
if sr_compile.pack_textures:#{
filedata = qoi_encode( img )
return texture_index
#}
-def sr_compile_material( mat ):
-#{
+def sr_compile_material( mat ):#{
if mat == None:
return 0
if mat.name in sr_compile.material_cache:
flags = 0x00
if mat.SR_data.collision:#{
- flags |= 0x2
- if mat.SR_data.skate_surface: flags |= 0x1
- if mat.SR_data.grind_surface: flags |= (0x8|0x1)
+ flags |= 0x2 # collision flag
+ if (mat.SR_data.shader != 'invisible') and \
+ (mat.SR_data.shader != 'boundary'):#{
+ 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)
+ if mat.SR_data.shader == 'walking': flags |= (0x10|0x80)
#}
- if mat.SR_data.grow_grass: flags |= 0x4
m.flags = flags
m.surface_prop = int(mat.SR_data.surface_prop)
+ inf = material_info( mat )
if mat.SR_data.shader == 'standard': m.shader = 0
if mat.SR_data.shader == 'standard_cutout': m.shader = 1
m.colour1[2] = pow( mat.SR_data.ocean_colour[2], 1.0/2.2 )
m.colour1[3] = 1.0
#}
-
- 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':
- #{
+ if mat.SR_data.shader == 'invisible':#{
+ m.shader = 5
+ #}
+
+ if mat.SR_data.shader == 'boundary':#{
+ m.shader = 6
+ #}
+
+ if mat.SR_data.shader == 'fxglow':#{
+ m.shader = 7
+ #}
+
+ if mat.SR_data.shader == 'cubemap':#{
+ m.shader = 8
+ m.tex_none0 = sr_entity_id( mat.SR_data.cubemap )
+
+ m.colour[0] = pow( mat.SR_data.tint[0], 1.0/2.2 )
+ m.colour[1] = pow( mat.SR_data.tint[1], 1.0/2.2 )
+ m.colour[2] = pow( mat.SR_data.tint[2], 1.0/2.2 )
+ m.colour[3] = pow( mat.SR_data.tint[3], 1.0/2.2 )
+ #}
+
+ if mat.SR_data.shader == 'walking':#{
+ m.shader = 9
+ #}
+
+ if mat.SR_data.shader in ['standard', 'standard_cutout', 'terrain_blend', \
+ 'vertex_blend', 'fxglow', 'cubemap' ]: #{
if 'tex_diffuse' in inf:
m.tex_diffuse = sr_compile_texture(inf['tex_diffuse'])
#}
+ if mat.SR_data.tex_diffuse_rt >= 0:#{
+ m.tex_diffuse = 0x80000000 | mat.SR_data.tex_diffuse_rt
+ #}
+
sr_compile.material_data.extend( bytearray(m) )
return index
#}
yield from _recurse_bone( b )
#}
-def sr_compile_mesh( obj ):
-#{
- node=mdl_mesh()
- compile_obj_transform(obj, node.transform)
- node.pstr_name = sr_compile_string(obj.name)
- node.flags = 0
+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 ]
+
+ return (tipo&0xffff)<<16 | (index&0xffff)
+#}
+# Returns submesh_start,count and armature_id
+def sr_compile_mesh_internal( obj ):
+#{
can_use_cache = True
armature = None
+ submesh_start = 0
+ submesh_count = 0
+ armature_id = 0
+
for mod in obj.modifiers:#{
if mod.type == 'DATA_TRANSFER' or mod.type == 'SHRINKWRAP' or \
mod.type == 'BOOLEAN' or mod.type == 'CURVE' or \
#}
if mod.type == 'ARMATURE': #{
- node.flags = 1
armature = mod.object
rig_weight_groups = \
['0 [ROOT]']+[_.name for _ in sr_armature_bones(mod.object)]
- node.armature_id = sr_compile.entity_ids[armature.name]
+ armature_id = sr_compile.entity_ids[armature.name]
POSE_OR_REST_CACHE = armature.data.pose_position
armature.data.pose_position = 'REST'
#
if can_use_cache and (obj.data.name in sr_compile.mesh_cache):#{
ref = sr_compile.mesh_cache[obj.data.name]
- node.submesh_start = ref[0]
- node.submesh_count = ref[1]
- sr_compile.mesh_data.extend(bytearray(node))
- return
+ submesh_start = ref[0]
+ submesh_count = ref[1]
+ return (submesh_start,submesh_count,armature_id)
#}
# Compile a whole new mesh
#
- node.submesh_start = len(sr_compile.submesh_data)//sizeof(mdl_submesh)
- node.submesh_count = 0
+ submesh_start = len(sr_compile.submesh_data)//sizeof(mdl_submesh)
+ submesh_count = 0
dgraph = bpy.context.evaluated_depsgraph_get()
data = obj.evaluated_get(dgraph).data
# Add submesh to encoder
#
sr_compile.submesh_data.extend( bytearray(sm) )
- node.submesh_count += 1
+ submesh_count += 1
#}
if armature:#{
armature.data.pose_position = POSE_OR_REST_CACHE
#}
- # Save a reference to this node since we want to reuse the submesh indices
+ # Save a reference to this mesh since we want to reuse the submesh indices
# later.
- sr_compile.mesh_cache[obj.data.name]=(node.submesh_start,node.submesh_count)
+ sr_compile.mesh_cache[obj.data.name]=(submesh_start,submesh_count)
+ return (submesh_start,submesh_count,armature_id)
+#}
+
+def sr_compile_mesh( obj ):
+#{
+ node=mdl_mesh()
+ compile_obj_transform(obj, node.transform)
+ node.pstr_name = sr_compile_string(obj.name)
+ ent_type = obj_ent_type( obj )
+
+ node.entity_id = 0
+
+ if ent_type != 'none':#{
+ ent_id_lwr = sr_compile.entity_ids[obj.name]
+ ent_id_upr = get_entity_enum_id( obj_ent_type(obj) )
+ node.entity_id = (ent_id_upr << 16) | ent_id_lwr
+ #}
+
+ node.submesh_start, node.submesh_count, node.armature_id = \
+ sr_compile_mesh_internal( obj )
+
sr_compile.mesh_data.extend(bytearray(node))
#}
font.glyph_start = glyph_count
glyph_base = data.glyphs[0].utf32
- glyph_range = data.glyphs[-1].utf32 - glyph_base
+ glyph_range = data.glyphs[-1].utf32+1 - glyph_base
font.glyph_utf32_base = glyph_base
font.glyph_count = glyph_range
#}
#}
+def sr_compile_menus( collection ):
+#{
+ print( "[SR1] Compiling menus" )
+ groups = []
+
+ for obj in collection.all_objects:#{
+ if obj_ent_type(obj) != 'ent_menuitem': continue
+ obj_data = obj.SR_data.ent_menuitem[0]
+
+ bitmask = 0x00000000
+
+ for col in obj.users_collection:#{
+ name = col.name
+ if name not in groups: groups.append( name )
+ bitmask |= (0x1 << groups.index(name))
+ #}
+
+ item = ent_menuitem()
+ item.type = int( obj_data.tipo )
+ item.groups = bitmask
+
+ compile_obj_transform( obj, item.transform )
+ if obj.type == 'MESH':#{
+ item.submesh_start, item.submesh_count, _ = \
+ sr_compile_mesh_internal( obj )
+ #}
+
+ if item.type == 1 or item.type == 2 or item.type == 7:#{
+ item_button = item._anonymous_union.button
+ item_button.pstr = sr_compile_string( obj_data.string )
+ item_button.stack_behaviour = int( obj_data.stack_behaviour )
+ #}
+ elif item.type == 0:#{
+ item_visual = item._anonymous_union.visual
+ item_visual.pstr_name = 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
+ item_page.pstr_name = sr_compile_string( obj_data.string )
+ item_page.id_entrypoint = sr_entity_id( obj_data.newloc )
+ item_page.id_viewpoint = sr_entity_id( obj_data.camera )
+ #}
+ elif item.type == 6:#{
+ item_binding = item._anonymous_union.binding
+ item_binding.pstr_bind = sr_compile_string( obj_data.string )
+ item_binding.font_variant = obj_data.font_variant
+ #}
+
+ if obj_data.link0:
+ item.id_links[0] = sr_entity_id( obj_data.link0 )
+ if obj_data.link1:
+ item.id_links[1] = sr_entity_id( obj_data.link1 )
+ if item.type != 4:#{
+ if obj_data.link2:
+ item.id_links[2] = sr_entity_id( obj_data.link2 )
+ if obj_data.link3:
+ item.id_links[3] = sr_entity_id( obj_data.link3 )
+ #}
+
+ sr_ent_push( item )
+ #}
+#}
+
def sr_compile_armature( obj ):
#{
node = mdl_armature()
lc_m = smtx.inverted() @ lc_m
#}
rq = lc_m.to_quaternion()
+ q_normalize( rq )
kf = mdl_transform()
kf.co[0] = loc[0]
arr.item_size = size
#}
+def hash_djb2(s):
+#{
+ picadillo = 5381
+ for x in s:#{
+ picadillo = (((picadillo << 5) + picadillo) + ord(x)) & 0xFFFFFFFF
+ #}
+ return picadillo
+#}
+
def sr_compile( collection ):
#{
print( F"[SR] compiler begin ({collection.name}.mdl)" )
sr_compile.entities = {}
sr_compile.entity_ids = {}
+ # begin
+ # -------------------------------------------------------
+
+ sr_compile_string( "null" )
+
mesh_count = 0
for obj in collection.all_objects: #{
- if obj.type == 'MESH': mesh_count += 1
+ if obj.type == 'MESH':#{
+ mesh_count += 1
+ #}
ent_type = obj_ent_type( obj )
if ent_type == 'none': continue
for obj in collection.all_objects:#{
if obj.type == 'MESH':#{
i+=1
- print( F'[SR] {i: 3}/{mesh_count} {obj.name:<40}', end='\r' )
+
+ ent_type = obj_ent_type( obj )
+
+ # entity ignore mesh list
+ #
+ if ent_type == 'ent_traffic': continue
+ if ent_type == 'ent_prop': continue
+ if ent_type == 'ent_font': continue
+ if ent_type == 'ent_font_variant': continue
+ if ent_type == 'ent_menuitem': continue
+ if ent_type == 'ent_objective': continue
+ if ent_type == 'ent_region': continue
+
+ #TODO: This is messy.
+ if ent_type == 'ent_gate':#{
+ obj_data = obj.SR_data.ent_gate[0]
+ if obj_data.custom: continue
+ #}
+ #--------------------------
+
+ print( F'[SR] {i: 3}/{mesh_count} {obj.name:<40}' )
sr_compile_mesh( obj )
#}
#}
light.colour[3] = obj.data.energy
sr_ent_push( light )
#}
+ elif ent_type == 'ent_camera': #{
+ cam = ent_camera()
+ compile_obj_transform( obj, cam.transform )
+ cam.fov = obj.data.angle * 45.0
+ sr_ent_push(cam)
+ #}
elif ent_type == 'ent_gate': #{
gate = ent_gate()
- gate.type = 0
obj_data = obj.SR_data.ent_gate[0]
mesh_data = obj.data.SR_data.ent_gate[0]
- if obj_data.target:#{
- gate.target = sr_compile.entity_ids[obj_data.target.name]
- gate.type = 1
+
+ flags = 0x0000
+
+ if obj_data.tipo == 'default':#{
+ if obj_data.target:#{
+ gate.target = sr_compile.entity_ids[obj_data.target.name]
+ flags |= 0x0001
+ #}
#}
+ elif obj_data.tipo == 'nonlocal':#{
+ gate.target = 0
+ gate.key = sr_compile_string(obj_data.key)
+ flags |= 0x0002
+ #}
+
+ if obj_data.flip: flags |= 0x0004
+ if obj_data.custom:#{
+ flags |= 0x0008
+ gate.submesh_start, gate.submesh_count, _ = \
+ sr_compile_mesh_internal( obj )
+ #}
+ if obj_data.locked: flags |= 0x0010
+ gate.flags = flags
+
gate.dimensions[0] = mesh_data.dimensions[0]
gate.dimensions[1] = mesh_data.dimensions[1]
gate.dimensions[2] = mesh_data.dimensions[2]
compile_obj_transform( obj, volume.transform )
if obj_data.target:#{
- target = obj_data.target
- volume.target.type = sr_entity_alias[obj_ent_type(target)]
- volume.target.index = sr_compile.entity_ids[ target.name ]
+ volume.target = sr_entity_id( obj_data.target )
+ volume._anon.trigger.event = obj_data.target_event
+
+ ev = 0xffffffff if obj_data.target_event_leave < 0 else \
+ obj_data.target_event_leave
+ volume._anon.trigger.event_leave = ev
#}
sr_ent_push(volume)
compile_obj_transform( obj, marker.transform )
sr_ent_push(marker)
#}
+ elif ent_type == 'ent_skateshop':#{
+ skateshop = ent_skateshop()
+ obj_data = obj.SR_data.ent_skateshop[0]
+ 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 )
+ #}
+ elif skateshop.type == 3:#{
+ server = skateshop._anonymous_union.server
+ server.id_lever = sr_entity_id( obj_data.mark_display )
+ #}
+ skateshop.id_camera = sr_entity_id( obj_data.cam )
+ compile_obj_transform( obj, skateshop.transform )
+ sr_ent_push(skateshop)
+ #}
+ elif ent_type == 'ent_swspreview':#{
+ workshop_preview = ent_swspreview()
+ obj_data = obj.SR_data.ent_swspreview[0]
+ workshop_preview.id_display = sr_entity_id( obj_data.mark_display )
+ workshop_preview.id_display1 = sr_entity_id( obj_data.mark_display1)
+ 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 )
+
+ flags = 0x00
+
+ if obj_data.fix_time:#{
+ worldinfo.timezone = obj_data.fixed_time
+ flags |= 0x1
+ #}
+ else:
+ worldinfo.timezone = obj_data.timezone
+
+ worldinfo.flags = flags
+ worldinfo.pstr_skybox = sr_compile_string( obj_data.skybox )
+ 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_objective':#{
+ objective = ent_objective()
+ obj_data = obj.SR_data.ent_objective[0]
+ objective.id_next = sr_entity_id( obj_data.proxima )
+ objective.id_win = sr_entity_id( obj_data.target )
+ objective.win_event = obj_data.target_event
+ objective.filter = int(obj_data.filtrar)
+ objective.filter2 = 0
+ objective.time_limit = obj_data.time_limit
+
+ compile_obj_transform( obj, objective.transform )
+ objective.submesh_start, objective.submesh_count, _ = \
+ sr_compile_mesh_internal( obj )
+
+ sr_ent_push( objective )
+ #}
+ elif ent_type == 'ent_challenge':#{
+ challenge = ent_challenge()
+ obj_data = obj.SR_data.ent_challenge[0]
+ compile_obj_transform( obj, challenge.transform )
+ challenge.pstr_alias = sr_compile_string( obj_data.alias )
+ challenge.target = sr_entity_id( obj_data.target )
+ challenge.target_event = obj_data.target_event
+ challenge.reset = sr_entity_id( obj_data.reset )
+ challenge.reset_event = obj_data.reset_event
+ challenge.first = sr_entity_id( obj_data.first )
+ challenge.flags = 0x00
+ challenge.camera = sr_entity_id( obj_data.camera )
+ if obj_data.time_limit: challenge.flags |= 0x01
+ challenge.status = 0
+ sr_ent_push( challenge )
+ #}
+ elif ent_type == 'ent_region':#{
+ region = ent_region()
+ obj_data = obj.SR_data.ent_region[0]
+ compile_obj_transform( obj, region.transform )
+ region.submesh_start, region.submesh_count, _ = \
+ sr_compile_mesh_internal( obj )
+ region.pstr_title = sr_compile_string( obj_data.title )
+ region.zone_volume = sr_entity_id( obj_data.zone_volume )
+ sr_ent_push( region )
+ #}
+ elif ent_type == 'ent_relay':#{
+ relay = ent_relay()
+ obj_data = obj.SR_data.ent_relay[0]
+ relay.targets[0][0] = sr_entity_id( obj_data.target0 )
+ relay.targets[1][0] = sr_entity_id( obj_data.target1 )
+ relay.targets[2][0] = sr_entity_id( obj_data.target2 )
+ relay.targets[3][0] = sr_entity_id( obj_data.target3 )
+ relay.targets[0][1] = obj_data.target0_event
+ relay.targets[1][1] = obj_data.target1_event
+ relay.targets[2][1] = obj_data.target2_event
+ relay.targets[3][1] = obj_data.target3_event
+ sr_ent_push( relay )
+ #}
+ elif ent_type == 'ent_cubemap':#{
+ cubemap = ent_cubemap()
+ co = obj.matrix_world @ Vector((0,0,0))
+ cubemap.co[0] = co[0]
+ cubemap.co[1] = co[2]
+ cubemap.co[2] = -co[1]
+ cubemap.resolution = 0
+ cubemap.live = 60
+ sr_ent_push( cubemap )
+ #}
+ elif ent_type == 'ent_miniworld':#{
+ miniworld = ent_miniworld()
+ obj_data = obj.SR_data.ent_miniworld[0]
+
+ compile_obj_transform( obj, miniworld.transform )
+ miniworld.pstr_world = sr_compile_string( obj_data.world )
+ miniworld.proxy = sr_entity_id( obj_data.proxy )
+ miniworld.camera = sr_entity_id( obj_data.camera )
+ sr_ent_push( miniworld )
+ #}
+ elif ent_type == 'ent_prop':#{
+ prop = ent_prop()
+ obj_data = obj.SR_data.ent_prop[0]
+ compile_obj_transform( obj, prop.transform )
+ prop.submesh_start, prop.submesh_count, _ = \
+ sr_compile_mesh_internal( obj )
+ prop.flags = obj_data.flags
+ prop.pstr_alias = sr_compile_string( obj_data.alias )
+ sr_ent_push( prop )
+ #}
#}
#}
- sr_compile_fonts(collection)
+ sr_compile_menus( collection )
+ sr_compile_fonts( collection )
def _children( col ):#{
yield col
route_gates = []
route_curves = []
routes = []
+ traffics = []
for obj in col.objects:#{
if obj.type == 'ARMATURE': pass
#}
elif ent_type == 'ent_route':
routes += [obj]
+ elif ent_type == 'ent_traffic':
+ traffics += [obj]
#}
#}
route.pstr_name = sr_compile_string( obj_data.alias )
route.checkpoints_start = checkpoint_count
route.checkpoints_count = 0
+ route.id_camera = sr_entity_id( obj_data.cam )
for ci in range(3):
route.colour[ci] = obj_data.colour[ci]
sr_ent_push( route )
#}
+ for obj in traffics:#{
+ traffic = ent_traffic()
+ compile_obj_transform( obj, traffic.transform )
+ traffic.submesh_start, traffic.submesh_count, _ = \
+ sr_compile_mesh_internal( obj )
+
+ # find best subsection
+
+ graph_keys = list(dij.graph)
+ min_dist = 100.0
+ best_point = 0
+
+ for j in range(len(dij.points)):#{
+ point = dij.points[j]
+ dist = (point-obj.location).magnitude
+
+ if dist < min_dist:#{
+ min_dist = dist
+ best_point = j
+ #}
+ #}
+
+ # scan to each edge
+ best_begin = best_point
+ best_end = best_point
+
+ while True:#{
+ map0 = dij.subsections[best_begin]
+ if map0[1] == -1: break
+ best_begin = map0[1]
+ #}
+ while True:#{
+ map1 = dij.subsections[best_end]
+ if map1[2] == -1: break
+ best_end = map1[2]
+ #}
+
+ traffic.start_node = routenode_count + best_begin
+ traffic.node_count = best_end - best_begin
+ traffic.index = best_point - best_begin
+ traffic.speed = obj.SR_data.ent_traffic[0].speed
+ traffic.t = 0.0
+
+ sr_ent_push(traffic)
+ #}
+
for point in dij.points:#{
rn = ent_route_node()
rn.co[0] = point[0]
routenode_count += len(dij.points)
#}
-
print( F"[SR] Writing file" )
file_array_instructions = {}
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 = 40
+ header.version = MDL_VERSION_NR
sr_array_title( header.arrays, \
'index', len(file_array_instructions), \
sizeof(mdl_array), header_size )
#{
use_hidden: bpy.props.BoolProperty( name="use hidden", default=False )
export_dir: bpy.props.StringProperty( name="Export Dir", subtype='DIR_PATH' )
- gizmos: bpy.props.BoolProperty( name="Draw Gizmos", default=True )
+ gizmos: bpy.props.BoolProperty( name="Draw Gizmos", default=False )
panel: bpy.props.EnumProperty(
name='Panel',
active_object = context.active_object
if not active_object: return
- _.layout.operator( 'skaterift.copy_entity_data', \
- text=F'Copy entity data to {len(context.selected_objects)-1} '+\
- F'other objects' )
+ amount = max( 0, len(context.selected_objects)-1 )
+
+ row = _.layout.row()
+ row.operator( 'skaterift.copy_entity_data', \
+ text=F'Copy entity data to {amount} other objects' )
+ if amount == 0: row.enabled=False
box = _.layout.box()
row = box.row()
row.label( text=active_object.name )
row.scale_y = 1.5
- def _draw_prop_collection( data ): #{
+ def _draw_prop_collection( source, data ): #{
nonlocal box
row = box.row()
row.alignment = 'CENTER'
row.enabled = False
row.scale_y = 1.5
- row.label( text=F'{data[0]}' )
+ row.label( text=F'{source}' )
if hasattr(type(data[0]),'sr_inspector'):#{
type(data[0]).sr_inspector( box, data )
text=F'Mirror attributes to {mb.name}' )
#}
- _draw_prop_collection( [bones.active.SR_data ] )
+ _draw_prop_collection( \
+ F'bpy.types.Bone["{bones.active.name}"].SR_data',\
+ [bones.active.SR_data ] )
#}
else: #{
row = box.row()
#}
#}
elif active_object.type == 'LIGHT': #{
- _draw_prop_collection( [active_object.data.SR_data] )
+ _draw_prop_collection( \
+ F'bpy.types.Light["{active_object.data.name}"].SR_data', \
+ [active_object.data.SR_data] )
#}
elif active_object.type in ['EMPTY','CURVE','MESH']:#{
box.prop( active_object.SR_data, "ent_type" )
ent_type = active_object.SR_data.ent_type
col = getattr( active_object.SR_data, ent_type, None )
- if col != None and len(col)!=0: _draw_prop_collection( col )
+ if col != None and len(col)!=0:
+ _draw_prop_collection( \
+ F'bpy.types.Object["{active_object.name}"].SR_data.{ent_type}[0]', \
+ col )
if active_object.type == 'MESH':#{
col = getattr( active_object.data.SR_data, ent_type, None )
- if col != None and len(col)!=0: _draw_prop_collection( col )
+ if col != None and len(col)!=0:
+ _draw_prop_collection( \
+ F'bpy.types.Mesh["{active_object.data.name}"].SR_data.{ent_type}[0]', \
+ col )
#}
#}
#}
_.layout.prop( active_mat.SR_data, "shader" )
_.layout.prop( active_mat.SR_data, "surface_prop" )
_.layout.prop( active_mat.SR_data, "collision" )
+ _.layout.prop( active_mat.SR_data, "tex_diffuse_rt" )
if active_mat.SR_data.collision:#{
- _.layout.prop( active_mat.SR_data, "skate_surface" )
- _.layout.prop( active_mat.SR_data, "grind_surface" )
- _.layout.prop( active_mat.SR_data, "grow_grass" )
+ box = _.layout.box()
+ row = box.row()
+
+ if (active_mat.SR_data.shader != 'invisible') and \
+ (active_mat.SR_data.shader != 'boundary') and \
+ (active_mat.SR_data.shader != 'walking'):#{
+ 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" )
+ #}
#}
if active_mat.SR_data.shader == "terrain_blend":#{
box.prop( active_mat.SR_data, "shore_colour" )
box.prop( active_mat.SR_data, "ocean_colour" )
#}
+ elif active_mat.SR_data.shader == "cubemap":#{
+ box = _.layout.box()
+ box.prop( active_mat.SR_data, "cubemap" )
+ box.prop( active_mat.SR_data, "tint" )
+ #}
#}
#}
target: bpy.props.PointerProperty( \
type=bpy.types.Object, name="destination", \
poll=lambda self,obj: sr_filter_ent_type(obj,['ent_gate']))
+
+ key: bpy.props.StringProperty()
+ tipo: bpy.props.EnumProperty(items=(('default', 'Default', ""),
+ ('nonlocal', 'Non-Local', "")))
+
+ flip: bpy.props.BoolProperty( name="Flip exit", default=False )
+ custom: bpy.props.BoolProperty( name="Mesh is surface", default=False )
+ locked: bpy.props.BoolProperty( name="Start Locked", default=False )
+
+ @staticmethod
+ def sr_inspector( layout, data ):
+ #{
+ box = layout.box()
+ box.prop( data[0], 'tipo', text="subtype" )
+
+ if data[0].tipo == 'default': box.prop( data[0], 'target' )
+ elif data[0].tipo == 'nonlocal': box.prop( data[0], 'key' )
+
+ flags = box.box()
+ flags.prop( data[0], 'flip' )
+ flags.prop( data[0], 'custom' )
+ flags.prop( data[0], 'locked' )
+ #}
#}
class SR_MESH_ENT_GATE(bpy.types.PropertyGroup):
poll=lambda self,obj: sr_filter_ent_type(obj,['ent_gate']))
#}
+class SR_OBJECT_ENT_MINIWORLD(bpy.types.PropertyGroup):
+#{
+ world: bpy.props.StringProperty( name='world UID' )
+ proxy: bpy.props.PointerProperty( \
+ type=bpy.types.Object, name='proxy', \
+ poll=lambda self,obj: sr_filter_ent_type(obj,['ent_prop']))
+ camera: bpy.props.PointerProperty( \
+ type=bpy.types.Object, name="Camera", \
+ poll=lambda self,obj: sr_filter_ent_type(obj,['ent_camera']))
+#}
+
class SR_UL_ROUTE_NODE_LIST(bpy.types.UIList):
#{
bl_idname = 'SR_UL_ROUTE_NODE_LIST'
@classmethod
def poll(cls, context):#{
active_object = context.active_object
- if obj_ent_type(active_object) == 'ent_gate':#{
+ if obj_ent_type(active_object) == 'ent_route':#{
return active_object.SR_data.ent_route[0].gates
#}
else: return False
s1 = c.split(factor=0.3)
c = s1.column()
row = c.row()
- lbl = chr(item.utf32) if item.utf32 >= 32 and item.utf32 <= 126 else 'ERR'
+ lbl = chr(item.utf32) if item.utf32 >= 32 and item.utf32 <= 126 else \
+ f'x{item.utf32:x}'
row.label(text=lbl)
c = s1.column()
c.prop( item, 'utf32', text='', emboss=True )
name="Alias",\
default="Untitled Course")
+ cam: bpy.props.PointerProperty( \
+ type=bpy.types.Object, name="Viewpoint", \
+ poll=lambda self,obj: sr_filter_ent_type(obj,['ent_camera']))
+
@staticmethod
def sr_inspector( layout, data ):
#{
layout.prop( data[0], 'alias' )
layout.prop( data[0], 'colour' )
+ layout.prop( data[0], 'cam' )
layout.label( text='Checkpoints' )
layout.template_list('SR_UL_ROUTE_NODE_LIST', 'Checkpoints', \
#}
#}
-class SR_OBJECT_ENT_VOLUME(bpy.types.PropertyGroup):
+
+class SR_OT_ENT_LIST_NEW_ITEM(bpy.types.Operator):#{
+ bl_idname = "skaterift.ent_list_new_entry"
+ bl_label = "Add entity"
+
+ def execute(self, context):#{
+ return internal_listadd_execute(self,context,'ent_list','entities')
+ #}
+#}
+
+class SR_OT_ENT_LIST_DEL_ITEM(bpy.types.Operator):#{
+ bl_idname = "skaterift.ent_list_del_entry"
+ bl_label = "Remove entity"
+
+ @classmethod
+ def poll(cls, context):#{
+ active_object = context.active_object
+ if obj_ent_type(active_object) == 'ent_list':#{
+ return active_object.SR_data.ent_list[0].entities
+ #}
+ else: return False
+ #}
+
+ def execute(self, context):#{
+ return internal_listdel_execute(self,context,'ent_list','entities')
+ #}
+#}
+
+class SR_OBJECT_ENT_LIST_ENTRY(bpy.types.PropertyGroup):
#{
+ target: bpy.props.PointerProperty( \
+ type=bpy.types.Object, name='target' )
+#}
+
+class SR_UL_ENT_LIST(bpy.types.UIList):#{
+ bl_idname = 'SR_UL_ENT_LIST'
+
+ def draw_item(_,context,layout,data,item,icon,active_data,active_propname):#{
+ layout.prop( item, 'target', text='', emboss=False )
+ #}
+#}
+
+class SR_OBJECT_ENT_LIST(bpy.types.PropertyGroup):#{
+ entities: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_LIST_ENTRY)
+ entities_index: bpy.props.IntProperty()
+
+ @staticmethod
+ def sr_inspector( layout, data ):#{
+ layout.label( text='Entities' )
+ layout.template_list('SR_UL_ENT_LIST', 'Entities', \
+ data[0], 'entities', data[0], \
+ 'entities_index', rows=5)
+
+ row = layout.row()
+ row.operator( 'skaterift.ent_list_new_entry', text='Add' )
+ row.operator( 'skaterift.ent_list_del_entry', text='Remove' )
+ #}
+#}
+
+
+class SR_OBJECT_ENT_VOLUME(bpy.types.PropertyGroup):#{
subtype: bpy.props.EnumProperty(
name="Subtype",
items=[('0','Trigger',''),
target: bpy.props.PointerProperty( \
type=bpy.types.Object, name="Target", \
- poll=lambda self,obj: sr_filter_ent_type(obj,['ent_audio']))
+ poll=lambda self,obj: sr_filter_ent_type(obj,SR_TRIGGERABLE))
+ target_event: bpy.props.IntProperty( name="Enter Ev" )
+ target_event_leave: bpy.props.IntProperty( name="Leave Ev", default=-1 )
@staticmethod
- def sr_inspector( layout, data ):
- #{
- data = data[0]
- layout.prop( data, 'subtype' )
- layout.prop( data, 'target' )
+ def inspect_target( layout, data, propname, evs = ['_event'] ):#{
+ box = layout.box()
+ box.prop( data[0], propname )
+
+ for evname in evs:#{
+ row = box.row()
+ row.prop( data[0], propname + evname )
+
+ target = getattr( data[0], propname )
+ if target:#{
+ tipo = target.SR_data.ent_type
+ cls = globals()[ tipo ]
+
+ table = getattr( cls, 'sr_functions', None )
+ if table:#{
+ index = getattr( data[0], propname + evname )
+ if index in table:
+ row.label( text=table[index] )
+ else:
+ row.label( text="undefined function" )
+ #}
+ #}
+ else:#{
+ row.label( text="..." )
+ row.enabled=False
+ #}
+ #}
+ #}
+
+ @staticmethod
+ def sr_inspector( layout, data ):#{
+ layout.prop( data[0], 'subtype' )
+ SR_OBJECT_ENT_VOLUME.inspect_target( layout, data, 'target', \
+ ['_event','_event_leave'] )
#}
#}
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' )
class SR_OBJECT_ENT_MARKER(bpy.types.PropertyGroup):
#{
alias: bpy.props.StringProperty()
+ flags: bpy.props.IntProperty()
#}
class SR_OBJECT_ENT_GLYPH(bpy.types.PropertyGroup):
#}
#}
+class SR_OBJECT_ENT_TRAFFIC(bpy.types.PropertyGroup):
+#{
+ speed: bpy.props.FloatProperty(default=1.0)
+#}
+
+class SR_OBJECT_ENT_SKATESHOP(bpy.types.PropertyGroup):
+#{
+ tipo: bpy.props.EnumProperty( name='Type',
+ items=[('0','boards',''),
+ ('1','character',''),
+ ('2','world',''),
+ ('4','server','')] )
+ mark_rack: bpy.props.PointerProperty( \
+ type=bpy.types.Object, name="Board Rack", \
+ poll=lambda self,obj: sr_filter_ent_type(obj,['ent_marker']))
+ mark_display: bpy.props.PointerProperty( \
+ type=bpy.types.Object, name="Selected Board Display", \
+ poll=lambda self,obj: sr_filter_ent_type(obj,['ent_marker']))
+ mark_info: bpy.props.PointerProperty( \
+ type=bpy.types.Object, name="Selected Board Info", \
+ poll=lambda self,obj: sr_filter_ent_type(obj,\
+ ['ent_marker','ent_prop']))
+ cam: bpy.props.PointerProperty( \
+ type=bpy.types.Object, name="Viewpoint", \
+ poll=lambda self,obj: sr_filter_ent_type(obj,['ent_camera']))
+#}
+
+class SR_OBJECT_ENT_WORKSHOP_PREVIEW(bpy.types.PropertyGroup):
+#{
+ mark_display: bpy.props.PointerProperty( \
+ type=bpy.types.Object, name="Board Display", \
+ poll=lambda self,obj: sr_filter_ent_type(obj,['ent_marker']))
+ mark_display1: bpy.props.PointerProperty( \
+ type=bpy.types.Object, name="Board Display (other side)", \
+ poll=lambda self,obj: sr_filter_ent_type(obj,['ent_marker']))
+ cam: bpy.props.PointerProperty( \
+ type=bpy.types.Object, name="Viewpoint", \
+ poll=lambda self,obj: sr_filter_ent_type(obj,['ent_camera']))
+#}
+
+class SR_OBJECT_ENT_MENU_ITEM(bpy.types.PropertyGroup):
+#{
+ link0: bpy.props.PointerProperty( \
+ type=bpy.types.Object, name="Link 0", \
+ poll=lambda self,obj: sr_filter_ent_type(obj,['ent_menuitem']))
+ link1: bpy.props.PointerProperty( \
+ type=bpy.types.Object, name="Link 1", \
+ poll=lambda self,obj: sr_filter_ent_type(obj,['ent_menuitem']))
+ link2: bpy.props.PointerProperty( \
+ type=bpy.types.Object, name="Link 2", \
+ poll=lambda self,obj: sr_filter_ent_type(obj,['ent_menuitem']))
+ link3: bpy.props.PointerProperty( \
+ type=bpy.types.Object, name="Link 3", \
+ poll=lambda self,obj: sr_filter_ent_type(obj,['ent_menuitem']))
+
+ newloc: bpy.props.PointerProperty( \
+ type=bpy.types.Object, name="New location", \
+ poll=lambda self,obj: sr_filter_ent_type(obj,['ent_menuitem']))
+ stack_behaviour: bpy.props.EnumProperty( name='Stack Behaviour',
+ items=[('0','append',''),
+ ('1','replace','')])
+
+ camera: bpy.props.PointerProperty( \
+ type=bpy.types.Object, name="Camera", \
+ poll=lambda self,obj: sr_filter_ent_type(obj,['ent_camera']))
+
+ slider_minloc: bpy.props.PointerProperty( \
+ type=bpy.types.Object, name="Slider min", \
+ poll=lambda self,obj: sr_filter_ent_type(obj,['ent_marker']))
+ slider_maxloc: bpy.props.PointerProperty( \
+ type=bpy.types.Object, name="Slider max", \
+ poll=lambda self,obj: sr_filter_ent_type(obj,['ent_marker']))
+ slider_handle: bpy.props.PointerProperty( \
+ type=bpy.types.Object, name="Slider handle", \
+ poll=lambda self,obj: sr_filter_ent_type(obj,['ent_menuitem']))
+
+ checkmark: bpy.props.PointerProperty( \
+ type=bpy.types.Object, name="Checked", \
+ poll=lambda self,obj: sr_filter_ent_type(obj,['ent_menuitem']))
+
+ font_variant: bpy.props.IntProperty( name="Font Variant" )
+
+ string: bpy.props.StringProperty( name="String" )
+ tipo: bpy.props.EnumProperty( name='Type',
+ items=[('0','visual',''),
+ ('1','event button',''),
+ ('2','page button',''),
+ ('3','toggle', ''),
+ ('4','slider',''),
+ ('5','page',''),
+ ('6','binding',''),
+ ('7','visual(no colourize)','')])
+
+ @staticmethod
+ def sr_inspector( layout, data ):
+ #{
+ data = data[0]
+ box = layout.box()
+ box.prop( data, 'tipo' )
+
+ if data.tipo == '0' or data.tipo == '7':#{
+ box.prop( data, 'string', text='Name' )
+ return
+ #}
+ elif data.tipo == '1':#{
+ box.prop( data, 'string', text='Event' )
+ #}
+ elif data.tipo == '2':#{
+ box.prop( data, 'string', text='Page' )
+ box.prop( data, 'stack_behaviour' )
+ #}
+ elif data.tipo == '3':#{
+ box.prop( data, 'string', text='Data (i32)' )
+ box.prop( data, 'checkmark' )
+ #}
+ elif data.tipo == '4':#{
+ box.prop( data, 'string', text='Data (f32)' )
+ box.prop( data, 'slider_minloc' )
+ box.prop( data, 'slider_maxloc' )
+ box.prop( data, 'slider_handle' )
+ box = box.box()
+ box.label( text="Links" )
+ box.prop( data, 'link0', text='v0' )
+ box.prop( data, 'link1', text='v1' )
+ return
+ #}
+ elif data.tipo == '5':#{
+ box.prop( data, 'string', text='Page Name' )
+ box.prop( data, 'newloc', text='Entry Point' )
+ box.prop( data, 'camera', text='Viewpoint' )
+ return
+ #}
+ elif data.tipo == '6':#{
+ box.prop( data, 'string', text='ID' )
+ box.prop( data, 'font_variant' )
+ return
+ #}
+
+ box = box.box()
+ box.label( text="Links" )
+ box.prop( data, 'link0' )
+ box.prop( data, 'link1' )
+ box.prop( data, 'link2' )
+ box.prop( data, 'link3' )
+ #}
+#}
+
+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")
+ skybox: bpy.props.StringProperty(name="Skybox")
+
+ fix_time: bpy.props.BoolProperty(name="Fix Time")
+ timezone: bpy.props.FloatProperty(name="Timezone(hrs) (UTC0 +hrs)")
+ fixed_time: bpy.props.FloatProperty(name="Fixed Time (0-1)")
+
+ @staticmethod
+ def sr_inspector( layout, data ):#{
+ layout.prop( data[0], 'name' )
+ layout.prop( data[0], 'desc' )
+ layout.prop( data[0], 'author' )
+
+ layout.prop( data[0], 'fix_time' )
+ if data[0].fix_time:
+ layout.prop( data[0], 'fixed_time' )
+ else:
+ layout.prop( data[0], 'timezone' )
+ #}
+#}
+
+class SR_OBJECT_ENT_CCMD(bpy.types.PropertyGroup):
+#{
+ command: bpy.props.StringProperty(name="Command Line")
+#}
+
+class SR_OBJECT_ENT_OBJECTIVE(bpy.types.PropertyGroup):#{
+ proxima: bpy.props.PointerProperty( \
+ type=bpy.types.Object, name="Next", \
+ poll=lambda self,obj: sr_filter_ent_type(obj,['ent_objective']))
+ target: bpy.props.PointerProperty( \
+ type=bpy.types.Object, name="Win", \
+ poll=lambda self,obj: sr_filter_ent_type(obj,SR_TRIGGERABLE))
+ target_event: bpy.props.IntProperty( name="Event/Method" )
+ time_limit: bpy.props.FloatProperty( name="Time Limit", default=1.0 )
+ filtrar: bpy.props.EnumProperty( name='Filter',\
+ items=[('0','none',''),
+ (str(0x1),'trick_shuvit',''),
+ (str(0x2),'trick_kickflip',''),
+ (str(0x4),'trick_treflip',''),
+ (str(0x1|0x2|0x4),'trick_any',''),
+ (str(0x8),'flip_back',''),
+ (str(0x10),'flip_front',''),
+ (str(0x8|0x10),'flip_any',''),
+ (str(0x20),'grind_truck_any',''),
+ (str(0x40),'grind_board_any',''),
+ (str(0x20|0x40),'grind_any',''),
+ (str(0x80),'footplant',''),
+ (str(0x100),'passthrough',''),
+ ])
+
+ @staticmethod
+ def sr_inspector( layout, data ):#{
+ layout.prop( data[0], 'proxima' )
+ layout.prop( data[0], 'time_limit' )
+ layout.prop( data[0], 'filtrar' )
+ SR_OBJECT_ENT_VOLUME.inspect_target( layout, data, 'target' )
+ #}
+#}
+
+class SR_OBJECT_ENT_CHALLENGE(bpy.types.PropertyGroup):#{
+ alias: bpy.props.StringProperty( name="Alias" )
+
+ target: bpy.props.PointerProperty( \
+ type=bpy.types.Object, name="On Complete", \
+ poll=lambda self,obj: sr_filter_ent_type(obj,SR_TRIGGERABLE))
+ target_event: bpy.props.IntProperty( name="Event/Method" )
+ reset: bpy.props.PointerProperty( \
+ type=bpy.types.Object, name="On Reset", \
+ poll=lambda self,obj: sr_filter_ent_type(obj,SR_TRIGGERABLE))
+ reset_event: bpy.props.IntProperty( name="Event/Method" )
+
+ time_limit: bpy.props.BoolProperty( name="Time Limit" )
+
+ first: bpy.props.PointerProperty( \
+ type=bpy.types.Object, name="First Objective", \
+ poll=lambda self,obj: sr_filter_ent_type(obj,['ent_objective']))
+
+ camera: bpy.props.PointerProperty( \
+ type=bpy.types.Object, name="Camera", \
+ poll=lambda self,obj: sr_filter_ent_type(obj,['ent_camera']))
+
+
+ @staticmethod
+ def sr_inspector( layout, data ):#{
+ layout.prop( data[0], 'alias' )
+ layout.prop( data[0], 'camera' )
+ layout.prop( data[0], 'first' )
+ layout.prop( data[0], 'time_limit' )
+ SR_OBJECT_ENT_VOLUME.inspect_target( layout, data, 'target' )
+ SR_OBJECT_ENT_VOLUME.inspect_target( layout, data, 'reset' )
+ #}
+#}
+
+class SR_OBJECT_ENT_REGION(bpy.types.PropertyGroup):#{
+ title: bpy.props.StringProperty( name="Title" )
+ zone_volume: bpy.props.PointerProperty(
+ type=bpy.types.Object, name="Zone Volume", \
+ poll=lambda self,obj: sr_filter_ent_type(obj,['ent_volume']))
+#}
+
+class SR_OBJECT_ENT_RELAY(bpy.types.PropertyGroup):#{
+ target0: bpy.props.PointerProperty( \
+ type=bpy.types.Object, name="Target 0", \
+ poll=lambda self,obj: sr_filter_ent_type(obj,SR_TRIGGERABLE))
+ target1: bpy.props.PointerProperty( \
+ type=bpy.types.Object, name="Target 1", \
+ poll=lambda self,obj: sr_filter_ent_type(obj,SR_TRIGGERABLE))
+ target2: bpy.props.PointerProperty( \
+ type=bpy.types.Object, name="Target 2", \
+ poll=lambda self,obj: sr_filter_ent_type(obj,SR_TRIGGERABLE))
+ target3: bpy.props.PointerProperty( \
+ type=bpy.types.Object, name="Target 3", \
+ poll=lambda self,obj: sr_filter_ent_type(obj,SR_TRIGGERABLE))
+
+ target0_event: bpy.props.IntProperty( name="Event" )
+ target1_event: bpy.props.IntProperty( name="Event" )
+ target2_event: bpy.props.IntProperty( name="Event" )
+ target3_event: bpy.props.IntProperty( name="Event" )
+
+ @staticmethod
+ def sr_inspector( layout, data ):#{
+ SR_OBJECT_ENT_VOLUME.inspect_target( layout, data, 'target0' )
+ SR_OBJECT_ENT_VOLUME.inspect_target( layout, data, 'target1' )
+ SR_OBJECT_ENT_VOLUME.inspect_target( layout, data, 'target2' )
+ SR_OBJECT_ENT_VOLUME.inspect_target( layout, data, 'target3' )
+ #}
+#}
+
class SR_OBJECT_PROPERTIES(bpy.types.PropertyGroup):
#{
ent_gate: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_GATE)
ent_volume: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_VOLUME)
ent_audio: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_AUDIO)
ent_marker: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_MARKER)
+ ent_prop: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_MARKER)
ent_glyph: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_GLYPH)
ent_font: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_FONT)
+ ent_traffic: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_TRAFFIC)
+ ent_skateshop: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_SKATESHOP)
+ 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_objective: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_OBJECTIVE)
+ ent_challenge: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_CHALLENGE)
+ ent_region: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_REGION)
+ ent_relay: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_RELAY)
+ ent_miniworld: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_MINIWORLD)
+ ent_list: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_LIST)
+
ent_type: bpy.props.EnumProperty(
name="Type",
- items=[('none', 'None', '', 0),
- ('ent_gate','Gate','', 1),
- ('ent_spawn','Spawn','', 2),
- ('ent_route_node', 'Route Node', '', 3 ),
- ('ent_route', 'Route', '', 4),
- ('ent_water', 'Water Surface', '', 5),
- ('ent_volume', 'Volume', '', 6 ),
- ('ent_audio', 'Audio Files', '', 7),
- ('ent_marker', 'Marker', '', 8),
- ('ent_font', 'Font', '', 9),
- ('ent_font_variant','Font variant','',10)],
+ items=sr_entity_list,
update=sr_on_type_change
)
#}
('standard_cutout', "standard_cutout", ''),
('terrain_blend', "terrain_blend", ''),
('vertex_blend', "vertex_blend", ''),
- ('water',"water",'')
+ ('water',"water",''),
+ ('invisible','Invisible',''),
+ ('boundary','Boundary',''),
+ ('fxglow','FX Glow',''),
+ ('cubemap','Cubemap',''),
+ ('walking','Walking','')
])
surface_prop: bpy.props.EnumProperty(
collision: bpy.props.BoolProperty( \
name="Collisions Enabled",\
default=True,\
- description = "Can the player collide with this material"\
+ description = "Can the player collide with this material?"\
)
skate_surface: bpy.props.BoolProperty( \
- name="Skate Surface", \
+ name="Skate Target", \
default=True,\
description = "Should the game try to target this surface?" \
)
grind_surface: bpy.props.BoolProperty( \
- name="Grind Surface", \
- default=False,\
- description = "Grind face?" \
+ name="Grindable", \
+ default=True,\
+ description = "Can you grind on this surface?" \
)
grow_grass: bpy.props.BoolProperty( \
name="Grow Grass", \
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, \
default=Vector((0.0,0.006,0.03)),\
description="Water colour in the deep bits"\
)
+ tint: bpy.props.FloatVectorProperty( \
+ name="Tint",\
+ subtype='COLOR',\
+ min=0.0,max=1.0,\
+ size=4,\
+ default=Vector((1.0,1.0,1.0,1.0)),\
+ description="Reflection tint"\
+ )
+
+ cubemap: bpy.props.PointerProperty( \
+ type=bpy.types.Object, name="cubemap", \
+ poll=lambda self,obj: sr_filter_ent_type(obj,['ent_cubemap']))
+
+ tex_diffuse_rt: bpy.props.IntProperty( name="diffuse: RT index", default=-1 )
#}
# ---------------------------------------------------------------------------- #
# ---------------------------------------------------------------------------- #
cv_view_draw_handler = None
+cv_view_pixel_handler = None
cv_view_shader = gpu.shader.from_builtin('3D_SMOOTH_COLOR')
cv_view_verts = []
cv_view_colours = []
# Draw coloured arrow
#
-def cv_draw_arrow( p0, p1, c0, size=0.15 ):
+def cv_draw_arrow( p0, p1, c0, size=0.25, outline=True ):
#{
global cv_view_verts, cv_view_colours
tx = Vector((1,0,0))
ty = Vector((1,0,0))
cv_tangent_basis( n, tx, ty )
-
+ tx *= 0.5
+ ty *= 0.5
+
+ if outline:#{
+ cv_draw_lines()
+ gpu.state.line_width_set(1.0)
+ #}
+
cv_view_verts += [p0,p1, midpt+(tx-n)*size,midpt, midpt+(-tx-n)*size,midpt ]
cv_view_colours += [c0,c0,c0,c0,c0,c0]
- #cv_draw_lines()
+ cv_draw_lines()
+
+ if outline:#{
+ gpu.state.line_width_set(3.0)
+ cv_view_verts += [p0,p1,midpt+(tx-n)*size,midpt,midpt+(-tx-n)*size,midpt]
+ b0 = (0,0,0)
+ cv_view_colours += [b0,b0,b0,b0,b0,b0]
+ cv_draw_lines()
+ gpu.state.line_width_set(2.0)
+ #}
#}
def cv_draw_line_dotted( p0, p1, c0, dots=10 ):
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 = []
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 ]
data = obj.SR_data.ent_volume[0]
if data.subtype == '0':#{
- cv_draw_ucube( obj.matrix_world, (0,1,0) )
+ cv_draw_ucube( obj.matrix_world, (0,1,0), Vector((0.99,0.99,0.99)) )
if data.target:#{
- cv_draw_line( obj.location, data.target.location, (0,1,0) )
+ cv_draw_arrow( obj.location, data.target.location, (1,1,1) )
#}
#}
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,1) )
#}
#}
#}
path = solve_graph( dij, gi.name, gj.name )
if path:#{
- cv_draw_arrow(gi.location,dij.points[path[0]],cc,1.5)
- cv_draw_arrow(dij.points[path[len(path)-1]],gj.location,cc,1.5)
+ cv_draw_arrow(gi.location,dij.points[path[0]],cc,1.5,False)
+ cv_draw_arrow(dij.points[path[len(path)-1]],gj.location,cc,1.5,False)
for j in range(len(path)-1):#{
i0 = path[j]
i1 = path[j+1]
o0 = dij.points[ i0 ]
o1 = dij.points[ i1 ]
- cv_draw_arrow(o0,o1,cc,1.5)
+ cv_draw_arrow(o0,o1,cc,1.5,False)
#}
#}
else:#{
#}
#}
-def cv_draw():
-#{
+def cv_draw():#{
global cv_view_shader
global cv_view_verts
global cv_view_colours
cv_view_colours = []
cv_view_shader.bind()
- gpu.state.depth_mask_set(False)
+ gpu.state.depth_mask_set(True)
gpu.state.line_width_set(2.0)
gpu.state.face_culling_set('BACK')
gpu.state.depth_test_set('LESS')
elif ent_type == 'ent_volume':#{
cv_ent_volume( obj )
#}
+ elif ent_type == 'ent_objective':#{
+ data = obj.SR_data.ent_objective[0]
+ if data.proxima:#{
+ cv_draw_arrow( obj.location, data.proxima.location, (1,0.6,0.2) )
+ #}
+ if data.target:
+ cv_draw_arrow( obj.location, data.target.location, (1,1,1) )
+ #}
+ elif ent_type == 'ent_relay':#{
+ data = obj.SR_data.ent_relay[0]
+ if data.target0:
+ cv_draw_arrow( obj.location, data.target0.location, (1,1,1) )
+ if data.target1:
+ cv_draw_arrow( obj.location, data.target1.location, (1,1,1) )
+ if data.target2:
+ cv_draw_arrow( obj.location, data.target2.location, (1,1,1) )
+ if data.target3:
+ cv_draw_arrow( obj.location, data.target3.location, (1,1,1) )
+ #}
+ elif ent_type == 'ent_challenge':#{
+ data = obj.SR_data.ent_challenge[0]
+ if data.target:
+ cv_draw_arrow( obj.location, data.target.location, (1,1,1) )
+ if data.reset:
+ cv_draw_arrow( obj.location, data.reset.location, (0.9,0,0) )
+ if data.first:
+ cv_draw_arrow( obj.location, data.first.location, (1,0.6,0.2) )
+
+ cc1 = (0.4,0.3,0.2)
+ info_cu = Vector((1.2,0.01,0.72))*0.5
+ info_co = Vector((0.0,0.0,0.72))*0.5
+ cv_draw_ucube( obj.matrix_world, cc1, info_cu, info_co)
+ if data.camera:
+ cv_draw_line_dotted( obj.location, data.camera.location, (1,1,1))
+
+ vs = [Vector((-0.2,0.0,0.10)),Vector((-0.2,0.0,0.62)),\
+ Vector(( 0.2,0.0,0.62)),Vector((-0.2,0.0,0.30)),\
+ Vector(( 0.1,0.0,0.30))]
+ for v in range(len(vs)):#{
+ vs[v] = obj.matrix_world @ vs[v]
+ #}
+
+ cv_view_verts += [vs[0],vs[1],vs[1],vs[2],vs[3],vs[4]]
+ cv_view_colours += [cc1,cc1,cc1,cc1,cc1,cc1]
+ #}
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) )
#}
#}
#}
+ elif ent_type == 'ent_skateshop':#{
+ data = obj.SR_data.ent_skateshop[0]
+ display = data.mark_display
+ info = data.mark_info
+
+ 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
+ #}
+ elif data.tipo == '3':#{
+ rack = None
+ display = None
+ info = None
+ #}
+ elif data.tipo == '4':#{
+ rack = None
+ display = None
+ info = None
+ #}
+
+ if rack:
+ cv_draw_ucube( rack.matrix_world, cc, rack_cu, rack_co )
+ if display:
+ cv_draw_ucube( display.matrix_world, cc1, display_cu, display_co)
+ if info:
+ cv_draw_ucube( info.matrix_world, cc2, info_cu, info_co )
+ #}
+ elif ent_type == 'ent_swspreview':#{
+ cc1 = (0.4,0.9,0.2)
+ data = obj.SR_data.ent_swspreview[0]
+ display = data.mark_display
+ display1 = data.mark_display1
+ display_cu = Vector((0.3,1.2,0.1))*0.5
+ display_co = Vector((0.0,0.0,0.1))*0.5
+ if display:
+ cv_draw_ucube( display.matrix_world, cc1, display_cu, display_co)
+ if display1:
+ cv_draw_ucube(display1.matrix_world, cc1, display_cu, display_co)
+ #}
+ elif ent_type == 'ent_menuitem':#{
+ for i,col in enumerate(obj.users_collection):#{
+ colour32 = hash_djb2( col.name )
+ r = pow(((colour32 ) & 0xff) / 255.0, 2.2 )
+ g = pow(((colour32>>8 ) & 0xff) / 255.0, 2.2 )
+ b = pow(((colour32>>16) & 0xff) / 255.0, 2.2 )
+ cc = (r,g,b)
+ vs = [None for _ in range(8)]
+ scale = i*0.02
+ for j in range(8):#{
+ v0 = Vector([(obj.bound_box[j][z]+\
+ ((-1.0 if obj.bound_box[j][z]<0.0 else 1.0)*scale)) \
+ for z in range(3)])
+ vs[j] = obj.matrix_world @ v0
+ #}
+ 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 += [cc,cc]
+ #}
+ #}
+ cv_draw_lines()
+ cc = (1.0,1.0,1.0)
+ data = obj.SR_data.ent_menuitem[0]
+ if data.tipo == '4':#{
+ if data.slider_minloc and data.slider_maxloc:#{
+ v0 = data.slider_minloc.location
+ v1 = data.slider_maxloc.location
+ cv_draw_line( v0, v1, cc )
+ #}
+ #}
+
+ colour32 = hash_djb2(obj.name)
+ r = ((colour32 ) & 0xff) / 255.0
+ g = ((colour32>>8 ) & 0xff) / 255.0
+ b = ((colour32>>16) & 0xff) / 255.0
+ cc = (r,g,b)
+ origin = obj.location + (Vector((r,g,b))*2.0-Vector((1.0,1.0,1.0)))\
+ * 0.04
+
+ size = 0.01
+
+ if data.tipo != '0':#{
+ if data.tipo == '4':#{
+ if data.link0:#{
+ cv_draw_arrow( origin, data.link0.location, cc, size )
+ #}
+ if data.link1:#{
+ cv_draw_arrow( origin, data.link1.location, cc, size )
+ #}
+ #}
+ else:#{
+ if data.link0:#{
+ cv_draw_arrow( origin, data.link0.location, cc, size )
+ #}
+ if data.link1:#{
+ cv_draw_arrow( origin, data.link1.location, cc, size )
+ #}
+ if data.link2:#{
+ cv_draw_arrow( origin, data.link2.location, cc, size )
+ #}
+ if data.link3:#{
+ cv_draw_arrow( origin, data.link3.location, cc, size )
+ #}
+ #}
+ #}
+ #}
#}
#}
#}
cv_draw_lines()
- return
+#}
+
+def pos3d_to_2d( pos ):#{
+ return view3d_utils.location_3d_to_region_2d( \
+ bpy.context.region, \
+ bpy.context.space_data.region_3d, pos )
+#}
+
+def cv_draw_pixel():#{
+ if not bpy.context.scene.SR_data.gizmos: return
+ blf.size(0,10)
+ blf.color(0, 1.0,1.0,1.0,0.9)
+ blf.enable(0,blf.SHADOW)
+ blf.shadow(0,3,0.0,0.0,0.0,1.0)
+ for obj in bpy.context.collection.objects:#{
+ ent_type = obj_ent_type( obj )
+
+ if ent_type != 'none':#{
+ co = pos3d_to_2d( obj.location )
+
+ if not co: continue
+ blf.position(0,co[0],co[1],0)
+ blf.draw(0,ent_type)
+ #}
+ #}
#}
classes = [ SR_INTERFACE, SR_MATERIAL_PANEL,\
SR_OBJECT_ENT_FONT_VARIANT,
SR_OBJECT_ENT_GLYPH_ENTRY,\
SR_UL_FONT_VARIANT_LIST,SR_UL_FONT_GLYPH_LIST,\
- SR_OBJECT_ENT_FONT,\
+ 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_OBJECTIVE,SR_OBJECT_ENT_CHALLENGE,\
+ SR_OBJECT_ENT_REGION,\
+ SR_OBJECT_ENT_RELAY,SR_OBJECT_ENT_MINIWORLD,\
+ SR_OBJECT_ENT_LIST_ENTRY, SR_UL_ENT_LIST, SR_OBJECT_ENT_LIST, \
+ SR_OT_ENT_LIST_NEW_ITEM, SR_OT_ENT_LIST_DEL_ITEM,\
\
SR_OBJECT_PROPERTIES, SR_LIGHT_PROPERTIES, SR_BONE_PROPERTIES,
SR_MESH_PROPERTIES, SR_MATERIAL_PROPERTIES \
bpy.types.Material.SR_data = \
bpy.props.PointerProperty(type=SR_MATERIAL_PROPERTIES)
- global cv_view_draw_handler
+ global cv_view_draw_handler, cv_view_pixel_handler
cv_view_draw_handler = bpy.types.SpaceView3D.draw_handler_add(\
cv_draw,(),'WINDOW','POST_VIEW')
+ cv_view_pixel_handler = bpy.types.SpaceView3D.draw_handler_add(\
+ cv_draw_pixel,(),'WINDOW','POST_PIXEL')
#}
def unregister():
for c in classes:
bpy.utils.unregister_class(c)
- global cv_view_draw_handler
+ global cv_view_draw_handler, cv_view_pixel_handler
bpy.types.SpaceView3D.draw_handler_remove(cv_view_draw_handler,'WINDOW')
+ bpy.types.SpaceView3D.draw_handler_remove(cv_view_pixel_handler,'WINDOW')
#}
# ---------------------------------------------------------------------------- #