Пример #1
0
	def _macro_stairs_core(self, full_length, full_height, full_depth, flip, step_length, step_height, t):
		'''Create stairs by iteration.'''
		parts = []
		#ldl.uprint('create steps:\n\tstaircase length: ' + str(full_length) + '\n\tstaircase height: ' + str(full_height) + '\n\tstaircase depth: ' + str(full_depth) + '\n\tflip: ' + str(flip) + '\n\tstep length: ' + str(step_length) + '\n\tstep height: ' + str(step_height) + '\n\ttexture: ' + t)
		# Find closest match for step length and height...
		step_height = self._macro_stairs_match(full_height, step_height)
		num_steps = full_height/step_height
		step_length = full_length/num_steps
		#ldl.uprint('\tnum_steps: ' + str(num_steps) + '\n\tstep_length: ' + str(step_length) + '\n\tstep_height: ' + str(step_height))
		# Create parts...
		length_iter = int(full_length/step_length)
		if flip:
			for i in range(length_iter):
				parts.append(
					ldl.Region3D(
						ldl.Point2D(step_length*i,0),
						ldl.Point2D( step_length,step_height*(length_iter-i) )
					)
				)
		else:
			for i in range(length_iter):
				parts.append(
					ldl.Region3D(
						ldl.Point2D(step_length*i,0),
						ldl.Point2D( step_length,step_height*(i+1) )
					)
				)
		return parts
Пример #2
0
def processHollow(doc, parent, worldspawn, s, offset, hollow):
    '''Note: sets global style var.'''
    global style
    o = ldl.getPoint(hollow.getAttribute('origin')) + offset
    e = ldl.getPoint(hollow.getAttribute('extent'))
    style = hollow.getAttribute('style')
    holes = {}
    absentwalls = []
    # FIXME the following is where we see if this hollow contains an absentwalls element and a holes element before proceeding.  It's implemented in a bit of a hacky way; we ought to be using SAX but then it would be a *lot* more work to create the output XML.  This way we can just change what's there a bit.
    for hollowChild in hollow.childNodes:
        if hollowChild.localName == 'absentwalls':
            # Get absent walls info...
            for absentwall in hollowChild.childNodes:
                wall = absentwall.getAttribute('value')
                absentwalls.append(wall)
            ldl.insertPlaceholder(doc, hollow, hollowChild)
        elif hollowChild.localName == 'holes':
            # Get holes info...
            for hole in hollowChild.childNodes:
                wall = hole.getAttribute('wall')
                # If we've not added a hole to this wall yet then set up an empty array...
                if not holes.has_key(wall):
                    holes[wall] = []
                o_x, o_y = hole.getAttribute('origin').split()
                e_x, e_y = hole.getAttribute('extent').split()
                type = hole.getAttribute('type')
                if type == ldl.RT_DOOR:
                    key = hole.getAttribute('key')
                    button = hole.getAttribute('button')
                else:
                    key = button = None
                # FIXME deal with other types
                holes[wall].append(
                    ldl.Hole2D(ldl.Point2D(float(o_x), float(o_y)),
                               ldl.Point2D(float(e_x), float(e_y)), type,
                               {ldl.PROPS_K_KEY: key}))
            # FIXME we shouldn't need to detect overlapping holes here because they'll be detected higher up (by overlapping connected hollows)
            ldl.insertPlaceholder(doc, hollow, hollowChild)

    # Now we have the required structural info (absent walls and holes), we can turn this hollow into a series of textured brushes...
    io, ie = ldl.makeHollow(doc, worldspawn, s, o, e, absentwalls, holes,
                            style)
    # Contained solids, hollows and entities...
    for node in hollow.childNodes:
        processNode(doc, hollow, worldspawn, s, io, node)
    # We can't remove the child or we screw over tree traversal (urgh)...
    ldl.insertPlaceholder(doc, parent, hollow)
Пример #3
0
def splitWall(brush, holes):
    '''Splits a brush up in 2D so that it appears to have a hole in it.  This is achieved by taking the full brush size and the holes list and splitting the brush up into multiple parts.'''
    if not holes:
        return [brush]
        parts = []  # stores 2D parts returned by the main function
    finalparts = []  # stores expanded 3D parts
    extent2d = ldl.Point2D(brush.extent.x, brush.extent.y)
    # Sort holes by x start coord, then width...
    sortedholes = qsortHoles(holes)
    # Check for errors and add doors into the returned list of parts, as they need to be built...
    for hole in sortedholes:
        # FIXME check for other errors -- backtrack?
        if hole.origin.y + hole.extent.y > extent2d.y:
            #ldl.error('Hole is taller than containing wall.\n\thole.origin.y: ' + str(hole.origin.y) + '\n\thole.extent.y: ' + str(hole.extent.y) + '\n\textent2d.y: ' + str(extent2d.y))
            ldl.error('Hole is taller than containing wall.\n\thole: ' +
                      str(hole) + '\n\textent2d: ' + str(extent2d))
        if hole.type == ldl.RT_DOOR:
            finalparts.append(
                ldl.Region2D(
                    ldl.Point2D(brush.origin.x + hole.origin.x,
                                brush.origin.y + hole.origin.y),
                    ldl.Point2D(hole.extent.x, hole.extent.y), hole.type,
                    hole.props))
    # Go to main function...
    # FIXME this should not assume the origin is (0,0) but it doesn't work if we don't make this true...
    parts = splitWallCore(ldl.Chunk2D(ldl.Point2D(0, 0), extent2d),
                          sortedholes)
    # Take list of brushes and add the z coord back on...
    for p in parts:
        finalparts.append(
            ldl.Region2D(
                ldl.Point2D(brush.origin.x + p.origin.x,
                            brush.origin.y + p.origin.y),
                ldl.Point2D(p.extent.x, p.extent.y), p.type, p.props))
    # Now we can return them...
    return finalparts
Пример #4
0
def processSolid(doc, parent, worldspawn, sf, offset, solid):
    '''Note: uses style set in parent hollow.'''
    global style
    o = ldl.getPoint(solid.getAttribute('origin')) + offset
    e = ldl.getPoint(solid.getAttribute('extent'))
    t = solid.getAttribute('texture')
    type = solid.getAttribute('type')
    if not t:
        if not type:
            ldl.error('solid with no type also has no texture attribute set')
    f = solid.getAttribute('holeface')
    # Get holes info...
    # FIXME this is repeated code from the hollow one -- any way we can refactor it?
    props = {}
    holes = []
    # Check if the solid has children (holes).
    # If so, split it up.
    # If not, just add it.
    if solid.hasChildNodes():
        for hole in solid.childNodes:
            ho_x, ho_y = hole.getAttribute('origin').split()
            he_x, he_y = hole.getAttribute('extent').split()
            type = hole.getAttribute('type')
            if not type:
                pass
            elif type == ldl.RT_DOOR:
                props[ldl.PROPS_K_KEY] = hole.getAttribute('key')
            else:
                ldl.warning(
                    'only doors allowed as hole types; not plats or others.')
            # FIXME deal with other types
            holes.append(
                ldl.Hole2D(ldl.Point2D(float(ho_x), float(ho_y)),
                           ldl.Point2D(float(he_x), float(he_y)), type, props))
        # Built split (2D) parts into 3D brushes; mapping of coords to 3D depends on which direction/face the hole was constructed in.
        if f == ldl.DCP_NORTH:
            parts = split.splitWall(
                ldl.Region2D(ldl.Point2D(o.x, o.z), ldl.Point2D(e.x, e.z)),
                holes)
            for part in parts:
                part3d = ldl.addDim(part, ldl.DIM_Y, o.y, e.y)
                #ldl.uprint('Part:   ' + str(part) + '\nPart3D: ' + str(part3d))
                ldl.makeBrush(doc, worldspawn, sf, style, part3d, f, t)
        elif f == ldl.DCP_UP:
            parts = split.splitWall(
                ldl.Region2D(ldl.Point2D(o.x, o.y), ldl.Point2D(e.x, e.y)),
                holes)
            for part in parts:
                part3d = ldl.addDim(part, ldl.DIM_Z, o.z + ldl.lip_small,
                                    e.z - ldl.lip_small * 2)
                #ldl.uprint('Part:   ' + str(part) + '\nPart3D: ' + str(part3d))
                ldl.makeBrush(doc, worldspawn, sf, style, part3d, f, t)
            else:
                ldl.error('Unsupported holeface ' + f +
                          ' requested for hole in solid.')
    else:
        # Doesn't have child nodes...
        if not type or type == ldl.RT_STEP:
            pass  # no properties to set
        elif type == ldl.RT_DOOR:
            props[ldl.PROPS_K_KEY] = solid.getAttribute('key')
        elif type == ldl.RT_PLAT:
            props[ldl.PROPS_K_POS] = solid.getAttribute('position')
        else:
            ldl.warning('unknown type ' + type + ' specifed.')

        brush = ldl.Region3D(Point(o.x, o.y, o.z), Point(e.x, e.y, e.z), type,
                             props)
        ldl.makeBrush(doc, worldspawn, sf, style, brush, type, t)
    # We can't remove the child or we screw over tree traversal (urgh)...
    ldl.insertPlaceholder(doc, parent, solid)
Пример #5
0
def splitWallCore(chunk, holes):
    '''Take a given area of the face to be split and split it.'''
    global splitWallCoreLevel
    splitWallCoreLevel = splitWallCoreLevel + 1
    parts = []
    if len(holes) == 0:
        paddedPrint('sWC: 0. chunk:' + str(chunk))
        parts.append(chunk)
    elif len(holes) == 1:
        hole = holes.pop()
        paddedPrint('sWC: 1. chunk: ' + str(chunk) + ' holes: ' + str(hole))
        if hole.end.x < chunk.end.x:
            # The hole is not flush with one side of this chunk; split the chunk so it is.
            # We do this by splitting the chunk so that the hole touches its east side.
            # Anything left over after the east side is a single whole chunk.
            paddedPrint('sWC: 1. hole.end.x (' + str(hole.end.x) +
                        ') < chunk.end.x (' + str(chunk.end.x) + ').')
            # Process part of chunk with hole in it...
            paddedPrint('sWC: 1. hole.end.x < chunk.end.x.  HOLE CHUNK')
            addparts = splitWallCore(
                ldl.Chunk2D(
                    chunk.origin,
                    ldl.Point2D(hole.end.x - chunk.origin.x, chunk.extent.y)),
                [hole])
            for ap in addparts:
                parts.append(ap)
            # Process the bit left at the east side...
            paddedPrint('sWC: 1. hole.end.x < chunk.end.x.  SOLID CHUNK')
            addparts = splitWallCore(
                ldl.Chunk2D(
                    ldl.Point2D(hole.end.x, chunk.origin.y),
                    ldl.Point2D(chunk.end.x - hole.end.x, chunk.extent.y)), [])
            for ap in addparts:
                parts.append(ap)
        else:
            # The end x-points of hole and chunk must be equal.
            # Add some parts around the hole...
            paddedPrint('sWC: 1. split flush.')
            # Under hole
            if (hole.origin.y - chunk.origin.y) > 0:
                parts.append(
                    ldl.Chunk2D(
                        chunk.origin,
                        ldl.Point2D(hole.end.x - chunk.origin.x,
                                    hole.origin.y - chunk.origin.y)))
            # Left of hole
            if (hole.origin.x - chunk.origin.x) > 0:
                parts.append(
                    ldl.Chunk2D(
                        chunk.origin +
                        ldl.Point2D(0, hole.origin.y - chunk.origin.y),
                        ldl.Point2D(hole.origin.x - chunk.origin.x,
                                    hole.extent.y)))
            # Above hole
            if (chunk.end.y - hole.end.y) > 0:
                parts.append(
                    ldl.Chunk2D(
                        chunk.origin +
                        ldl.Point2D(0, hole.end.y - chunk.origin.y),
                        ldl.Point2D(hole.end.x - chunk.origin.x,
                                    chunk.end.y - hole.end.y)))
            paddedPrint('sWC: 1. split flush.  results: ' +
                        str([str(p) for p in parts]))
    else:  # len(holes) > 1
        paddedPrint('sWC: n. chunk: ' + str(chunk) + ' holes: ' +
                    str([str(h) for h in holes]))
        '''Compare first two holes.
        If they do not overlap x-wise, split the chunk at the x value that represents the end of the first hole.
        If they do overlap x-wise, see if they overlap y-wise too.
            If they do, we're screwed (can't handle this yet).
            If they overlap y-wise
                See if there are any more nodes.
                    If no, then we can just split this chunk at a given y-value to keep the holes seperate.
                    If yes, then we need to see if we can split this chunk into two:
                        one split vertically (at an x-value just after the 2nd hole) to seperate our two x-overlapping holes from the next one.
                        and one split horizontally (at a y-value) to separate our overlapping holes
        '''
        holeA = holes[0]
        holeB = holes[1]
        if holeA.end.x < holeB.origin.x:
            paddedPrint('sWC: n. holeA.end.x (' + str(holeA.end.x) +
                        ') < holeB.origin.x (' + str(holeB.origin.x) + ')')
            # Our holes do not overlap x-wise;
            # split our chunk into two:
            #   one chunk containing the first hole (flush to the edge)
            #   another chunk containing all the other holes
            paddedPrint('sWC: n. holeA.end.x < holeB.origin.x.  singleton')
            addparts = splitWallCore(
                ldl.Chunk2D(
                    chunk.origin,
                    ldl.Point2D(holeA.end.x - chunk.origin.x, chunk.extent.y)),
                [holeA])
            for ap in addparts:
                parts.append(ap)
            paddedPrint('sWC: n. holeA.end.x < holeB.origin.x.  the rest')
            addparts = splitWallCore(
                ldl.Chunk2D(
                    ldl.Point2D(holeA.end.x, chunk.origin.y),
                    ldl.Point2D(chunk.end.x - holeA.end.x, chunk.extent.y)),
                holes[1:])
            for ap in addparts:
                parts.append(ap)
        elif holeA.origin.y >= holeB.end.y or holeB.origin.y >= holeA.end.y:
            paddedPrint('sWC: n. Y.  holeA.origin.y (' + str(holeA.origin.y) +
                        ' >= holeB.end.y (' + str(holeB.end.y) + ')')
            # Our holes overlap x-wise, but they don't overlap y-wise.
            # Which one is on top?
            if holeA.origin.y >= holeB.origin.y:
                upper = holeA
                lower = holeB
            else:
                upper = holeB
                lower = holeA
            # Are there more holes?
            if not len(holes) > 2:
                paddedPrint('sWC: n. Y.  no more holes')
                # No more holes; just split this chunk y-wise...
                paddedPrint('sWC: n. Y.  no more holes.  LOWER.')
                addparts = splitWallCore(
                    ldl.Chunk2D(chunk.origin,
                                ldl.Point2D(chunk.extent.x, upper.origin.y)),
                    [lower])
                for ap in addparts:
                    parts.append(ap)
                paddedPrint('sWC: n. Y.  no more holes.  UPPER.')
                addparts = splitWallCore(
                    ldl.Chunk2D(
                        ldl.Point2D(chunk.origin.x, upper.origin.y),
                        ldl.Point2D(chunk.extent.x,
                                    chunk.extent.y - upper.origin.y)), [upper])
                for ap in addparts:
                    parts.append(ap)
            else:
                # There are more holes; split both y- and x-wise.
                # Use the x-value of the next hole (FIXME could break things?)
                xcutoff = holes[2].origin.x - chunk.origin.x
                paddedPrint('sWC: n. Y.  more holes; xcutoff = ' +
                            str(xcutoff))
                paddedPrint('sWC: n. Y.  more holes.  LOWER.')
                addparts = splitWallCore(
                    ldl.Chunk2D(chunk.origin,
                                ldl.Point2D(xcutoff, upper.origin.y)), [lower])
                for ap in addparts:
                    parts.append(ap)
                paddedPrint('sWC: n. Y.  more holes.  UPPER.')
                addparts = splitWallCore(
                    ldl.Chunk2D(
                        ldl.Point2D(chunk.origin.x, upper.origin.y),
                        ldl.Point2D(xcutoff, chunk.extent.y - upper.origin.y)),
                    [upper])
                for ap in addparts:
                    parts.append(ap)
                paddedPrint('sWC: n. Y.  more holes.  REST-OF-X.')
                addparts = splitWallCore(
                    ldl.Chunk2D(
                        ldl.Point2D(chunk.origin.x + xcutoff, chunk.origin.y),
                        ldl.Point2D(chunk.extent.x - xcutoff, chunk.extent.y)),
                    holes[2:])
                for ap in addparts:
                    parts.append(ap)
        else:
            # Our holes overlap both x- and y-wise; for now, we're screwed.
            ldl.error(
                'Oh dear: the segmentation algorithm can\'t cope with holes that overlap both x- and y-wise!'
            )
    splitWallCoreLevel = splitWallCoreLevel - 1
    return parts