本文整理汇总了Python中srctools.Vec.as_tuple方法的典型用法代码示例。如果您正苦于以下问题:Python Vec.as_tuple方法的具体用法?Python Vec.as_tuple怎么用?Python Vec.as_tuple使用的例子?那么恭喜您, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类srctools.Vec
的用法示例。
在下文中一共展示了Vec.as_tuple方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的Python代码示例。
示例1: join_markers
# 需要导入模块: from srctools import Vec [as 别名]
# 或者: from srctools.Vec import as_tuple [as 别名]
def join_markers(inst_a, inst_b, is_start=False):
"""Join two marker ents together with corners.
This returns a list of solids used for the vphysics_motion trigger.
"""
origin_a = Vec.from_str(inst_a['ent']['origin'])
origin_b = Vec.from_str(inst_b['ent']['origin'])
norm_a = Vec(-1, 0, 0).rotate_by_str(inst_a['ent']['angles'])
norm_b = Vec(-1, 0, 0).rotate_by_str(inst_b['ent']['angles'])
config = inst_a['conf']
if norm_a == norm_b:
# Either straight-line, or s-bend.
dist = (origin_a - origin_b).mag()
if origin_a + (norm_a * dist) == origin_b:
make_straight(
origin_a,
norm_a,
dist,
config,
is_start,
)
# else: S-bend, we don't do the geometry for this..
return
if norm_a == -norm_b:
# U-shape bend..
make_ubend(
origin_a,
origin_b,
norm_a,
config,
max_size=inst_a['size'],
)
return
try:
corner_ang, flat_angle = CORNER_ANG[norm_a.as_tuple(), norm_b.as_tuple()]
if origin_a[flat_angle] != origin_b[flat_angle]:
# It needs to be flat in this angle!
raise ValueError
except ValueError:
# The tubes need two corners to join together - abort for that.
return
else:
make_bend(
origin_a,
origin_b,
norm_a,
norm_b,
corner_ang,
config,
max_size=inst_a['size'],
)
示例2: res_glass_hole
# 需要导入模块: from srctools import Vec [as 别名]
# 或者: from srctools.Vec import as_tuple [as 别名]
def res_glass_hole(inst: Entity, res: Property):
"""Add Glass/grating holes. The value should be 'large' or 'small'."""
hole_type = HoleType(res.value)
normal = Vec(z=-1).rotate_by_str(inst['angles'])
origin = Vec.from_str(inst['origin']) // 128 * 128 + 64
if test_hole_spot(origin, normal, hole_type):
HOLES[origin.as_tuple(), normal.as_tuple()] = hole_type
inst['origin'] = origin
inst['angles'] = normal.to_angle()
return
# Test the opposite side of the glass too.
inv_origin = origin + 128 * normal
inv_normal = -normal
if test_hole_spot(inv_origin, inv_normal, hole_type):
HOLES[inv_origin.as_tuple(), inv_normal.as_tuple()] = hole_type
inst['origin'] = inv_origin
inst['angles'] = inv_normal.to_angle()
else:
# Remove the instance, so this does nothing.
inst.remove()
示例3: make_straight
# 需要导入模块: from srctools import Vec [as 别名]
# 或者: from srctools.Vec import as_tuple [as 别名]
def make_straight(
origin: Vec,
normal: Vec,
dist: int,
config: dict,
is_start=False,
):
"""Make a straight line of instances from one point to another."""
# 32 added to the other directions, plus extended dist in the direction
# of the normal - 1
p1 = origin + (normal * ((dist // 128 * 128) - 96))
# The starting brush needs to
# stick out a bit further, to cover the
# point_push entity.
p2 = origin - (normal * (96 if is_start else 32))
# bbox before +- 32 to ensure the above doesn't wipe it out
p1, p2 = Vec.bbox(p1, p2)
solid = vbsp.VMF.make_prism(
# Expand to 64x64 in the other two directions
p1 - 32, p2 + 32,
mat='tools/toolstrigger',
).solid
motion_trigger(solid.copy())
push_trigger(origin, normal, [solid])
angles = normal.to_angle()
support_file = config['support']
straight_file = config['straight']
support_positions = (
SUPPORT_POS[normal.as_tuple()]
if support_file else
[]
)
for off in range(0, int(dist), 128):
position = origin + off * normal
vbsp.VMF.create_ent(
classname='func_instance',
origin=position,
angles=angles,
file=straight_file,
)
for supp_ang, supp_off in support_positions:
if (position + supp_off).as_tuple() in SOLIDS:
vbsp.VMF.create_ent(
classname='func_instance',
origin=position,
angles=supp_ang,
file=support_file,
)
示例4: test_hole_spot
# 需要导入模块: from srctools import Vec [as 别名]
# 或者: from srctools.Vec import as_tuple [as 别名]
def test_hole_spot(origin: Vec, normal: Vec, hole_type: HoleType):
"""Check if the given position is valid for holes.
We need to check that it's actually placed on glass/grating, and that
all the parts are the same. Otherwise it'd collide with the borders.
"""
try:
center_type = BARRIERS[origin.as_tuple(), normal.as_tuple()]
except KeyError:
LOGGER.warning('No center barrier at {}, {}', origin, normal)
return False
if hole_type is HoleType.SMALL:
return True
u, v = Vec.INV_AXIS[normal.axis()]
# The corners don't matter, but all 4 neighbours must be there.
for u_off, v_off in [
(-128, 0),
(0, -128),
(128, 0),
(0, 128),
]:
pos = origin + Vec.with_axes(u, u_off, v, v_off)
try:
off_type = BARRIERS[pos.as_tuple(), normal.as_tuple()]
except KeyError:
# No side
LOGGER.warning('No offset barrier at {}, {}', pos, normal)
return False
if off_type is not center_type:
# Different type.
LOGGER.warning('Wrong barrier type at {}, {}', pos, normal)
return False
return True
示例5: mon_remove_bullseyes
# 需要导入模块: from srctools import Vec [as 别名]
# 或者: from srctools.Vec import as_tuple [as 别名]
def mon_remove_bullseyes(inst: Entity) -> Optional[object]:
"""Remove bullsyes used for cameras."""
if not BULLSYE_LOCS:
return RES_EXHAUSTED
if inst['file'].casefold() not in instanceLocs.resolve('<ITEM_CATAPULT_TARGET>'):
return
origin = Vec(0, 0, -64)
origin.localise(Vec.from_str(inst['origin']), Vec.from_str(inst['angles']))
origin = origin.as_tuple()
LOGGER.info('Pos: {} -> ', origin, BULLSYE_LOCS[origin])
if BULLSYE_LOCS[origin]:
BULLSYE_LOCS[origin] -= 1
inst.remove()
示例6: res_hollow_brush
# 需要导入模块: from srctools import Vec [as 别名]
# 或者: from srctools.Vec import as_tuple [as 别名]
def res_hollow_brush(inst: Entity, res: Property):
"""Hollow out the attached brush, as if EmbeddedVoxel was set.
This just removes the surface if it's already an embeddedVoxel. This allows
multiple items to embed thinly in the same block without affecting each
other.
"""
loc = Vec(0, 0, -64).rotate_by_str(inst['angles'])
loc += Vec.from_str(inst['origin'])
try:
group = SOLIDS[loc.as_tuple()]
except KeyError:
LOGGER.warning('No brush for hollowing at ({})', loc)
return # No brush here?
conditions.hollow_block(
group,
remove_orig_face=srctools.conv_bool(res['RemoveFace', False])
)
示例7: make_barriers
# 需要导入模块: from srctools import Vec [as 别名]
# 或者: from srctools.Vec import as_tuple [as 别名]
def make_barriers(vmf: VMF, get_tex: Callable[[str], str]):
"""Make barrier entities. get_tex is vbsp.get_tex."""
glass_temp = template_brush.get_scaling_template(
vbsp_options.get(str, "glass_template")
)
grate_temp = template_brush.get_scaling_template(
vbsp_options.get(str, "grating_template")
)
# Avoid error without this package.
if HOLES:
# Grab the template solids we need.
hole_temp = template_brush.get_template(
vbsp_options.get(str, 'glass_hole_temp')
)
hole_world, hole_detail, _ = hole_temp.visgrouped({'small'})
hole_temp_small = hole_world + hole_detail
hole_world, hole_detail, _ = hole_temp.visgrouped({'large'})
hole_temp_large = hole_world + hole_detail
hole_world, hole_detail, _ = hole_temp.visgrouped({'large_corner'})
hole_temp_corner = hole_world + hole_detail
else:
hole_temp_small = hole_temp_large = hole_temp_corner = None
floorbeam_temp = vbsp_options.get(str, 'glass_floorbeam_temp')
if vbsp_options.get_itemconf('BEE_PELLET:PelletGrating', False):
# Merge together these existing filters in global_pti_ents
vmf.create_ent(
origin=vbsp_options.get(Vec, 'global_pti_ents_loc'),
targetname='@grating_filter',
classname='filter_multi',
filtertype=0,
negated=0,
filter01='@not_pellet',
filter02='@not_paint_bomb',
)
else:
# Just skip paint bombs.
vmf.create_ent(
origin=vbsp_options.get(Vec, 'global_pti_ents_loc'),
targetname='@grating_filter',
classname='filter_activator_class',
negated=1,
filterclass='prop_paint_bomb',
)
# Group the positions by planes in each orientation.
# This makes them 2D grids which we can optimise.
# (normal_dist, positive_axis, type) -> [(x, y)]
slices = defaultdict(set) # type: Dict[Tuple[Tuple[float, float, float], bool, BarrierType], Set[Tuple[float, float]]]
# We have this on the 32-grid so we can cut squares for holes.
for (origin, normal), barr_type in BARRIERS.items():
origin = Vec(origin)
normal = Vec(normal)
norm_axis = normal.axis()
u, v = origin.other_axes(norm_axis)
norm_pos = Vec.with_axes(norm_axis, origin)
slice_plane = slices[
norm_pos.as_tuple(), # distance from origin to this plane.
normal[norm_axis] > 0,
barr_type,
]
for u_off in [-48, -16, 16, 48]:
for v_off in [-48, -16, 16, 48]:
slice_plane.add((
(u + u_off) // 32,
(v + v_off) // 32,
))
# Remove pane sections where the holes are. We then generate those with
# templates for slanted parts.
for (origin, normal), hole_type in HOLES.items():
barr_type = BARRIERS[origin, normal]
origin = Vec(origin)
normal = Vec(normal)
norm_axis = normal.axis()
u, v = origin.other_axes(norm_axis)
norm_pos = Vec.with_axes(norm_axis, origin)
slice_plane = slices[
norm_pos.as_tuple(),
normal[norm_axis] > 0,
barr_type,
]
if hole_type is HoleType.LARGE:
offsets = (-80, -48, -16, 16, 48, 80)
hole_temp = hole_temp_large.copy()
else:
offsets = (-16, 16)
hole_temp = hole_temp_small.copy()
for u_off in offsets:
for v_off in offsets:
# Skip the corners on large holes.
# Those aren't actually used, so skip them. That way
# we can have them diagonally or without glass in the corner.
if u_off in (-80, 80) and v_off in (-80, 80):
continue
slice_plane.discard((
#.........这里部分代码省略.........
示例8: make_ubend
# 需要导入模块: from srctools import Vec [as 别名]
# 或者: from srctools.Vec import as_tuple [as 别名]
#.........这里部分代码省略.........
3,
max_size,
side_dist // (128 * 2),
)
first_straight = second_straight = 0
side_straight = side_dist - 2 * 128 * first_size
elif out_off > 0:
# The second tube is further away than the first - the first bend
# should be largest.
# We need 1 spot for the second bend.
first_size = min(
3,
max_size,
side_dist // 128 - 1,
out_off,
)
second_size = min(3, side_dist // 128 - first_size, max_size)
first_straight = (out_off + 128) - 128 * second_size
second_straight = (first_size - second_size) * 128
side_straight = (side_dist / 128 - first_size - second_size) * 128
elif out_off < 0:
# The first tube is further away than the second - the second bend
# should be largest.
second_size = min(
3,
max_size,
side_dist // 128 - 1,
-out_off # -out = abs()
)
first_size = min(3, side_dist // 128 - second_size, max_size)
first_straight = (second_size - first_size) * 128
second_straight = (-out_off + 128) - 128 * second_size
side_straight = (side_dist / 128 - first_size - second_size) * 128
else:
return [] # Not possible..
# We always have a straight segment at the first marker point - move
# everything up slightly.
first_straight += 128
LOGGER.info(
'Ubend {}: {}, c={}, {}, c={}, {}',
out_off,
first_straight,
first_size,
side_straight,
second_size,
second_straight,
)
make_straight(
origin_a,
normal,
first_straight,
config,
is_start,
)
first_corner_loc = origin_a + (normal * first_straight)
make_corner(
first_corner_loc,
CORNER_ANG[normal.as_tuple(), side_norm.as_tuple()].ang,
first_size,
config,
)
off_straight_loc = first_corner_loc + normal * (128 * (first_size - 1))
off_straight_loc += side_norm * (128 * first_size)
if side_straight > 0:
make_straight(
off_straight_loc,
side_norm,
side_straight,
config,
)
sec_corner_loc = off_straight_loc + side_norm * side_straight
make_corner(
sec_corner_loc,
CORNER_ANG[side_norm.as_tuple(), (-normal).as_tuple()].ang,
second_size,
config,
)
if second_straight > 0:
make_straight(
sec_corner_loc - normal * (128 * second_size),
-normal,
second_straight,
config,
)
示例9: res_insert_overlay
# 需要导入模块: from srctools import Vec [as 别名]
# 或者: from srctools.Vec import as_tuple [as 别名]
def res_insert_overlay(inst: Entity, res: Property):
"""Use a template to insert one or more overlays on a surface.
Options:
- ID: The template ID. Brushes will be ignored.
- Replace: old -> new material replacements.
- Face_pos: The offset of the brush face.
- Normal: The direction of the brush face.
- Offset: An offset to move the overlays by.
"""
(
temp_id,
replace,
face,
norm,
offset,
) = res.value
if temp_id[:1] == '$':
temp_id = inst.fixup[temp_id]
origin = Vec.from_str(inst['origin']) # type: Vec
angles = Vec.from_str(inst['angles', '0 0 0'])
face_pos = Vec(face).rotate(*angles)
face_pos += origin
normal = Vec(norm).rotate(*angles)
# Don't make offset change the face_pos value..
origin += offset.copy().rotate_by_str(
inst['angles', '0 0 0']
)
for axis, norm in enumerate(normal):
# Align to the center of the block grid. The normal direction is
# already correct.
if norm == 0:
face_pos[axis] = face_pos[axis] // 128 * 128 + 64
try:
face_id = SOLIDS[face_pos.as_tuple()].face.id
except KeyError:
LOGGER.warning(
'Overlay brush position is not valid: {}',
face_pos,
)
return
temp = template_brush.import_template(
temp_id,
origin,
angles,
targetname=inst['targetname', ''],
force_type=TEMP_TYPES.detail,
)
for over in temp.overlay: # type: Entity
random.seed('TEMP_OVERLAY_' + over['basisorigin'])
mat = random.choice(replace.get(
over['material'],
(over['material'], ),
))
if mat[:1] == '$':
mat = inst.fixup[mat]
if mat.startswith('<') or mat.endswith('>'):
# Lookup in the style data.
import vbsp
LOGGER.info('Tex: {}', vbsp.settings['textures'].keys())
mat = vbsp.get_tex(mat[1:-1])
over['material'] = mat
over['sides'] = str(face_id)
# Wipe the brushes from the map.
if temp.detail is not None:
temp.detail.remove()
LOGGER.info(
'Overlay template "{}" could set keep_brushes=0.',
temp_id,
)
示例10: res_make_tag_fizzler
# 需要导入模块: from srctools import Vec [as 别名]
# 或者: from srctools.Vec import as_tuple [as 别名]
#.........这里部分代码省略.........
# smallest magnitude.
sign_dir = min(
sign_floor_loc - Vec.with_axes(
axis,side_min,
other_axis, normal,
),
sign_floor_loc - Vec.with_axes(
axis, side_max,
other_axis, normal,
),
key=Vec.mag,
)
else:
# Align just based on whether we're in front or behind.
sign_dir = Vec()
sign_dir[other_axis] = sign_floor_loc[other_axis] - normal
sign_angle = math.degrees(
math.atan2(sign_dir.y, sign_dir.x)
)
# Round to nearest 90 degrees
# Add 45 so the switchover point is at the diagonals
sign_angle = (sign_angle + 45) // 90 * 90
# Rotate to fit the instances - south is down
sign_angle = int(sign_angle + 90) % 360
if inst_normal.z > 0:
sign_angle = '0 {} 0'.format(sign_angle)
elif inst_normal.z < 0:
# Flip upside-down for ceilings
sign_angle = '0 {} 180'.format(sign_angle)
else:
# On a wall, face upright
sign_angle = PETI_INST_ANGLE[inst_normal.as_tuple()]
# If disable_other, we show off signs. Otherwise we don't use that sign.
blue_sign = blue_sign_on if blue_enabled else blue_sign_off if disable_other else None
oran_sign = oran_sign_on if oran_enabled else oran_sign_off if disable_other else None
if blue_sign:
vmf.create_ent(
classname='func_instance',
file=blue_sign,
targetname=inst['targetname'],
angles=sign_angle,
origin=blue_loc.join(' '),
)
if oran_sign:
vmf.create_ent(
classname='func_instance',
file=oran_sign,
targetname=inst['targetname'],
angles=sign_angle,
origin=oran_loc.join(' '),
)
# Now modify the fizzler...
# Subtract the sign from the list of connections, but don't go below
# zero
fizzler.base_inst.fixup['$connectioncount'] = str(max(
0,
srctools.conv_int(fizzler.base_inst.fixup['$connectioncount', '']) - 1
))
示例11: res_make_catwalk
# 需要导入模块: from srctools import Vec [as 别名]
# 或者: from srctools.Vec import as_tuple [as 别名]
#.........这里部分代码省略.........
LOGGER.info('Connections: {}', links)
LOGGER.info('Markers: {}', markers)
# First loop through all the markers, adding connecting sections
for marker_name, inst in markers.items():
mark_item = ITEMS[marker_name]
mark_item.delete_antlines()
for conn in list(mark_item.outputs):
try:
inst2 = markers[conn.to_item.name]
except KeyError:
LOGGER.warning('Catwalk connected to non-catwalk!')
conn.remove()
origin1 = Vec.from_str(inst['origin'])
origin2 = Vec.from_str(inst2['origin'])
if origin1.x != origin2.x and origin1.y != origin2.y:
LOGGER.warning('Instances not aligned!')
continue
y_dir = origin1.x == origin2.x # Which way the connection is
if y_dir:
dist = abs(origin1.y - origin2.y)
else:
dist = abs(origin1.x - origin2.x)
vert_dist = origin1.z - origin2.z
if (dist - 128) // 2 < abs(vert_dist):
# The stairs are 2 long, 1 high. Check there's enough room
# Subtract the last block though, since that's a corner.
LOGGER.warning('Not enough room for stairs!')
continue
if dist > 128:
# add straight sections in between
place_catwalk_connections(vmf, instances, origin1, origin2)
# Update the lists based on the directions that were set
conn_lst1 = links[inst]
conn_lst2 = links[inst2]
if origin1.x < origin2.x:
conn_lst1.E = conn_lst2.W = True
elif origin2.x < origin1.x:
conn_lst1.W = conn_lst2.E = True
if origin1.y < origin2.y:
conn_lst1.N = conn_lst2.S = True
elif origin2.y < origin1.y:
conn_lst1.S = conn_lst2.N = True
for inst, dir_mask in links.items():
# Set the marker instances based on the attached walkways.
normal = Vec(0, 0, 1).rotate_by_str(inst['angles'])
new_type, inst['angles'] = utils.CONN_LOOKUP[dir_mask.as_tuple()]
inst['file'] = instances[CATWALK_TYPES[new_type]]
if new_type is utils.CONN_TYPES.side:
# If the end piece is pointing at a wall, switch the instance.
if normal.z == 0:
if normal == dir_mask.conn_dir():
inst['file'] = instances['end_wall']
continue # We never have normal supports on end pieces
elif new_type is utils.CONN_TYPES.none:
# Unconnected catwalks on the wall switch to a special instance.
# This lets players stand next to a portal surface on the wall.
if normal.z == 0:
inst['file'] = instances['single_wall']
inst['angles'] = INST_ANGLE[normal.as_tuple()]
else:
inst.remove()
continue # These don't get supports otherwise
# Add regular supports
supp = None
if normal == (0, 0, 1):
# If in goo, use different supports!
origin = Vec.from_str(inst['origin'])
origin.z -= 128
if brushLoc.POS['world': origin].is_goo:
supp = instances['support_goo']
else:
supp = instances['support_floor']
elif normal == (0, 0, -1):
supp = instances['support_ceil']
else:
supp = instances['support_wall']
if supp:
vmf.create_ent(
classname='func_instance',
origin=inst['origin'],
angles=INST_ANGLE[normal.as_tuple()],
file=supp,
)
LOGGER.info('Finished catwalk generation!')
return RES_EXHAUSTED
示例12: res_import_template
# 需要导入模块: from srctools import Vec [as 别名]
# 或者: from srctools.Vec import as_tuple [as 别名]
#.........这里部分代码省略.........
'"{}" is not a valid template!',
temp_name
)
# We don't want an error, just quit.
return
if color_var.casefold() == '<editor>':
# Check traits for the colour it should be.
traits = instance_traits.get(inst)
if 'white' in traits:
force_colour = template_brush.MAT_TYPES.white
elif 'black' in traits:
force_colour = template_brush.MAT_TYPES.black
else:
LOGGER.warning(
'"{}": Instance "{}" '
"isn't one with inherent color!",
temp_id,
inst['file'],
)
elif color_var:
color_val = conditions.resolve_value(inst, color_var).casefold()
if color_val == 'white':
force_colour = template_brush.MAT_TYPES.white
elif color_val == 'black':
force_colour = template_brush.MAT_TYPES.black
# else: no color var
if srctools.conv_bool(conditions.resolve_value(inst, invert_var)):
force_colour = template_brush.TEMP_COLOUR_INVERT[force_colour]
# else: False value, no invert.
origin = Vec.from_str(inst['origin'])
angles = Vec.from_str(inst['angles', '0 0 0'])
temp_data = template_brush.import_template(
template,
origin,
angles,
targetname=inst['targetname', ''],
force_type=force_type,
visgroup_choose=visgroup_func,
add_to_map=True,
additional_visgroups=visgroups,
)
if key_block is not None:
conditions.set_ent_keys(temp_data.detail, inst, key_block)
br_origin = Vec.from_str(key_block.find_key('keys')['origin'])
br_origin.localise(origin, angles)
temp_data.detail['origin'] = br_origin
move_dir = temp_data.detail['movedir', '']
if move_dir.startswith('<') and move_dir.endswith('>'):
move_dir = Vec.from_str(move_dir).rotate(*angles)
temp_data.detail['movedir'] = move_dir.to_angle()
for out in outputs: # type: Output
out = out.copy()
out.target = conditions.local_name(inst, out.target)
temp_data.detail.add_out(out)
# Add it to the list of ignored brushes, so vbsp.change_brush() doesn't
# modify it.
vbsp.IGNORED_BRUSH_ENTS.add(temp_data.detail)
try:
# This is the original brush the template is replacing. We fix overlay
# face IDs, so this brush is replaced by the faces in the template
# pointing
# the same way.
if replace_brush_pos is None:
raise KeyError # Not set, raise to jump out of the try block
pos = Vec(replace_brush_pos).rotate(angles.x, angles.y, angles.z)
pos += origin
brush_group = SOLIDS[pos.as_tuple()]
except KeyError:
# Not set or solid group doesn't exist, skip..
pass
else:
LOGGER.info('IDS: {}', additional_replace_ids | template.overlay_faces)
conditions.steal_from_brush(
temp_data,
brush_group,
rem_replace_brush,
map(int, additional_replace_ids | template.overlay_faces),
conv_bool(conditions.resolve_value(inst, transfer_overlays), True),
)
template_brush.retexture_template(
temp_data,
origin,
inst.fixup,
replace_tex,
force_colour,
force_grid,
# Don't allow clumping if using custom keyvalues - then it won't be edited.
no_clumping=key_block is not None,
)
示例13: add_glass_floorbeams
# 需要导入模块: from srctools import Vec [as 别名]
# 或者: from srctools.Vec import as_tuple [as 别名]
def add_glass_floorbeams(vmf: VMF, temp_name: str):
"""Add beams to separate large glass panels.
The texture is assumed to match plasticwall004a's shape.
"""
template = template_brush.get_template(temp_name)
temp_world, temp_detail, temp_over = template.visgrouped()
try:
[beam_template] = temp_world + temp_detail # type: Solid
except ValueError:
raise ValueError('Bad Glass Floorbeam template!')
# Grab the 'end' side, which we move around.
for side in beam_template.sides:
if side.normal() == (-1, 0, 0):
beam_end_face = side
break
else:
raise ValueError('Not aligned to world...')
separation = vbsp_options.get(int, 'glass_floorbeam_sep') + 1
separation *= 128
# First we want to find all the groups of contiguous glass sections.
# This is a mapping from some glass piece to its group list.
groups = {}
for (origin, normal), barr_type in BARRIERS.items():
# Grating doesn't use it.
if barr_type is not BarrierType.GLASS:
continue
normal = Vec(normal)
if not normal.z:
# Not walls.
continue
pos = Vec(origin) + normal * 62
groups[pos.as_tuple()] = [pos]
# Loop over every pos and check in the +x/y directions for another glass
# piece. If there, merge the two lists and set every pos in the group to
# point to the new list.
# Once done, every unique list = a group.
for pos_tup in groups.keys():
pos = Vec(pos_tup)
for off in ((128, 0, 0), (0, 128, 0)):
neighbour = (pos + off).as_tuple()
if neighbour in groups:
our_group = groups[pos_tup]
neigh_group = groups[neighbour]
if our_group is neigh_group:
continue
# Now merge the two lists. We then need to update all dict locs
# to point to the new list.
if len(neigh_group) > len(our_group):
small_group, large_group = our_group, neigh_group
else:
small_group, large_group = neigh_group, our_group
large_group.extend(small_group)
for pos in small_group:
groups[pos.as_tuple()] = large_group
# Remove duplicates objects by using the ID as key..
groups = list({
id(group): group
for group in groups.values()
}.values())
# Side -> u, v or None
for group in groups:
bbox_min, bbox_max = Vec.bbox(group)
dimensions = bbox_max - bbox_min
LOGGER.info('Size = {}', dimensions)
# Our beams align to the smallest axis.
if dimensions.y > dimensions.x:
beam_ax = 'x'
side_ax = 'y'
rot = Vec(0, 0, 0)
else:
beam_ax = 'y'
side_ax = 'x'
rot = Vec(0, 90, 0)
# Build min, max tuples for each axis in the other direction.
# This tells us where the beams will be.
beams = {} # type: Dict[int, Tuple[int, int]]
# Add 128 so the first pos isn't a beam.
offset = bbox_min[side_ax] + 128
#.........这里部分代码省略.........
示例14: convert_floor
# 需要导入模块: from srctools import Vec [as 别名]
# 或者: from srctools.Vec import as_tuple [as 别名]
def convert_floor(
vmf: VMF,
loc: Vec,
overlay_ids,
mats,
settings,
signage_loc,
detail,
noise_weight,
noise_func: SimplexNoise,
):
"""Cut out tiles at the specified location."""
# We pop it, so the face isn't detected by other logic - otherwise it'll
# be retextured and whatnot, which we don't want.
try:
brush = conditions.SOLIDS.pop(loc.as_tuple())
except KeyError:
return False # No tile here!
if brush.normal == (0, 0, 1):
# This is a pillar block - there isn't actually tiles here!
# We need to generate a squarebeams brush to fill this gap.
brush.face.mat = 'tools/toolsnodraw' # It won't be visible
temp_data = template_brush.import_template(
temp_name=FLOOR_TEMP_PILLAR,
origin=loc,
)
template_brush.retexture_template(
temp_data,
loc,
# Switch to use the configured squarebeams texture
replace_tex={
consts.Special.SQUAREBEAMS: random.choice(
MATS['squarebeams']
),
}
)
return False
# The new brush IDs overlays need to use
# NOTE: strings, not ints!
ant_locs = overlay_ids[str(brush.face.id)] = []
# Move the floor brush down and switch to the floorbase texture.
for plane in brush.face.planes:
plane.z -= FLOOR_DEPTH
brush.face.mat = random.choice(mats['floorbase'])
loc.x -= 64
loc.y -= 64
for x, y in utils.iter_grid(max_x=4, max_y=4):
tile_loc = loc + (x * 32 + 16, y * 32 + 16, 0)
if tile_loc.as_tuple() in signage_loc:
# Force the tile to be present under signage..
should_make_tile = True
rand = 100
# We don't need to check this again in future!
signage_loc.remove(tile_loc.as_tuple())
else:
# Create a number between 0-100
rand = 100 * get_noise(tile_loc // 32, noise_func) + 10
# Adjust based on the noise_weight value, so boundries have more tiles
rand *= 0.1 + 0.9 * (1 - noise_weight)
should_make_tile = rand < settings['floor_chance']
if random.randint(0, 7) == 0:
# Sometimes there'll be random holes/extra tiles
should_make_tile = not should_make_tile
if should_make_tile:
# Full tile
tile = make_tile(
vmf,
p1=tile_loc - (16, 16, 0),
p2=tile_loc + (16, 16, -2),
top_mat=vbsp.get_tex(str(brush.color) + '.floor'),
bottom_mat='tools/toolsnodraw',
beam_mat=random.choice(mats['squarebeams']),
)
detail.solids.append(tile.solid)
ant_locs.append(str(tile.top.id))
elif rand < settings['floor_glue_chance']:
# 'Glue' tile - this chance should be higher, making these appear
# bordering the full tiles.
tile = make_tile(
vmf,
p1=tile_loc - (16, 16, 1),
p2=tile_loc + (16, 16, -2),
top_mat=random.choice(mats['tile_glue']),
bottom_mat='tools/toolsnodraw',
beam_mat=random.choice(mats['squarebeams']),
)
detail.solids.append(tile.solid)
else:
# No tile at this loc!
pass
#.........这里部分代码省略.........
示例15: parse_map
# 需要导入模块: from srctools import Vec [as 别名]
# 或者: from srctools.Vec import as_tuple [as 别名]
def parse_map(vmf: VMF, voice_attrs: Dict[str, bool]) -> None:
"""Analyse fizzler instances to assign fizzler types.
Instance traits are required.
The model instances and brushes will be removed from the map.
Needs connections to be parsed.
"""
# Item ID and model skin -> fizzler type
fizz_types = {} # type: Dict[Tuple[str, int], FizzlerType]
for fizz_type in FIZZ_TYPES.values():
for item_id in fizz_type.item_ids:
if ':' in item_id:
item_id, barrier_type = item_id.split(':')
if barrier_type == 'laserfield':
barrier_skin = 2
elif barrier_type == 'fizzler':
barrier_skin = 0
else:
LOGGER.error('Invalid barrier type ({}) for "{}"!', barrier_type, item_id)
fizz_types[item_id, 0] = fizz_type
fizz_types[item_id, 2] = fizz_type
continue
fizz_types[item_id, barrier_skin] = fizz_type
else:
fizz_types[item_id, 0] = fizz_type
fizz_types[item_id, 2] = fizz_type
fizz_bases = {} # type: Dict[str, Entity]
fizz_models = defaultdict(list) # type: Dict[str, List[Entity]]
# Position and normal -> name, for output relays.
fizz_pos = {} # type: Dict[Tuple[Tuple[float, float, float], Tuple[float, float, float]], str]
# First use traits to gather up all the instances.
for inst in vmf.by_class['func_instance']:
traits = instance_traits.get(inst)
if 'fizzler' not in traits:
continue
name = inst['targetname']
if 'fizzler_model' in traits:
name = name.rsplit('_model', 1)[0]
fizz_models[name].append(inst)
inst.remove()
elif 'fizzler_base' in traits:
fizz_bases[name] = inst
else:
LOGGER.warning('Fizzler "{}" has non-base, non-model instance?', name)
continue
origin = Vec.from_str(inst['origin'])
normal = Vec(z=1).rotate_by_str(inst['angles'])
fizz_pos[origin.as_tuple(), normal.as_tuple()] = name
for name, base_inst in fizz_bases.items():
models = fizz_models[name]
up_axis = Vec(y=1).rotate_by_str(base_inst['angles'])
# If upside-down, make it face upright.
if up_axis == (0, 0, -1):
up_axis = Vec(z=1)
base_inst.outputs.clear()
# Now match the pairs of models to each other.
# The length axis is the line between them.
# We don't care about the instances after this, so don't keep track.
length_axis = Vec(z=1).rotate_by_str(base_inst['angles']).axis()
emitters = [] # type: List[Tuple[Vec, Vec]]
model_pairs = {} # type: Dict[Tuple[float, float], Vec]
model_skin = models[0].fixup.int('$skin')
try:
item_id, item_subtype = instanceLocs.ITEM_FOR_FILE[base_inst['file'].casefold()]
fizz_type = fizz_types[item_id, model_skin]
except KeyError:
LOGGER.warning('Fizzler types: {}', fizz_types.keys())
raise ValueError('No fizzler type for "{}"!'.format(
base_inst['file'],
)) from None
for attr_name in fizz_type.voice_attrs:
voice_attrs[attr_name] = True
for model in models:
pos = Vec.from_str(model['origin'])
try:
other_pos = model_pairs.pop(pos.other_axes(length_axis))
except KeyError:
# No other position yet, we need to find that.
model_pairs[pos.other_axes(length_axis)] = pos
continue
min_pos, max_pos = Vec.bbox(pos, other_pos)
#.........这里部分代码省略.........