Пример #1
0
    def _make_lights_core(self, style, id, type, bounds):
        '''Make lights in this around the walls only.'''
        lights = []
        xoffs = styleFetcher.getLightingSetOffset(style, id, type, dims.X)
        yoffs = styleFetcher.getLightingSetOffset(style, id, type, dims.Y)
        zoffs = styleFetcher.getLightingSetOffset(style, id, type, dims.Z)
        xmin = styleFetcher.getLightingSetMindist(style, id, type, dims.X)
        ymin = styleFetcher.getLightingSetMindist(style, id, type, dims.Y)
        zmin = styleFetcher.getLightingSetMindist(style, id, type, dims.Z)
        entity = styleFetcher.getLightingSetEntity(style, id, type)
        light = styleFetcher.getLightingSetLevel(style, id, type)
        sound = styleFetcher.getLightingSetSound(style, id, type)

        # Lights must go in the corners.
        #   i.e. xoffs,             yoffs,             zoffs
        #        xoffs,             bounds.y - yoffs,  zoffs
        #        bounds.x - xoffs,  yoffs,             zoffs
        #        bounds.x - xoffs,  bounds.y - yoffs,  zoffs
        # Work out how many to go inbetween the corners (along walls).
        # That may be repeated vertically according to zstep.
        # Do we have them in middle of room?

        xgap = bounds.x  # - 2*xoffs
        ygap = bounds.y  # - 2*yoffs
        zgap = bounds.z  # - 2*yoffs

        # How many lights in xgap?
        # We need a ``smallest gap'' metric.
        # This can be used to work out how many lights we can fit in between
        # these two.
        # Now find a gap size >= smallest_gap that will give us an integer
        # number of lights...
        xmin = self._get_gap(xmin, xgap)
        ymin = self._get_gap(ymin, ygap)
        zmin = self._get_gap(zmin, zgap)

        for i in range(xoffs, int(bounds.x), xmin):
            for j in range(yoffs, int(bounds.y), ymin):
                for k in range(zoffs, int(bounds.z), zmin):
                    # Do a test that the lights are near the perimeter of the room,
                    # if we are in perimeter mode...

                    # If the spot is near the walls then use it...
                    xclose = self._check_proximity(bounds.x, i, xoffs * 1.5)
                    yclose = self._check_proximity(bounds.y, j, yoffs * 1.5)
                    # If any test passed, then it's near one of the walls...
                    close_to_perimeter = xclose or yclose  # or zclose

                    if type == lightingstyle.PERIMETER:
                        if close_to_perimeter:
                            drawlight = True
                        else:
                            drawlight = False
                    elif type == lightingstyle.CENTRE:
                        if close_to_perimeter:
                            drawlight = False
                        else:
                            drawlight = True
                    else:
                        utils.error('invalid lighting subscheme type ' + type +
                                    ' specified.')

                    # Now to render the light to XML...
                    if drawlight:
                        super().startElement('entity', {})

                        super().startElement('property', {
                            'name': 'classname',
                            'value': entity
                        })
                        super().endElement('property')

                        super().startElement(
                            'property', {
                                'name': 'origin',
                                'value': str(i) + ' ' + str(j) + ' ' + str(k)
                            })
                        super().endElement('property')

                        super().startElement('property', {
                            'name': 'light',
                            'value': str(light)
                        })
                        super().endElement('property')

                        if sound:
                            super().startElement('property', {
                                'name': 'classname',
                                'value': sound
                            })
                            super().endElement('property')

                        super().endElement('entity')
                    else:
                        pass
        return lights
Пример #2
0
    def macro_stairs(self, bi, si):
        '''Make some stairs

		we see this as a 2D problem then add the missing dimension later
		(width/depth) dir tells us in which dir the steps go up length is the
		distance from start of lowest to end of heighest step height is the
		height of the highest step'''
        # FIXME cope with being able to make a hole through (under) the stairs
        origin = utils.getPoint(bi['origin'])
        size = utils.getPoint(bi['extent'])
        dir = si['dir']
        texture = ''
        if 'texture' in bi:
            texture = bi['texture']
        slength = 0
        sheight = float(si['stepheight'])
        parts = []
        parts3d = []

        # FIXME repeated code: n/e == s/w -- collapse into 2?

        # Work out which dimension is which
        if dir == dcp.NORTH:
            # use X and Y; Z rising with increasing Y
            length = size.y
            height = size.z
            width = size.x
            flip = False
            parts = self._macro_stairs_core(length, height, width, flip,
                                            slength, sheight, texture)
            for part in parts:
                part3d = utils.Region3D(
                    Point(0, part.origin.x, part.origin.y) + origin,
                    Point(width, part.extent.x, part.extent.y))
                parts3d.append(part3d)
        elif dir == dcp.SOUTH:
            # use X and Y; Z falling with increasing Y
            length = size.y
            height = size.z
            width = size.x
            flip = True
            parts = self._macro_stairs_core(length, height, width, flip,
                                            slength, sheight, texture)
            for part in parts:
                part3d = utils.Region3D(
                    Point(0, part.origin.x, part.origin.y) + origin,
                    Point(width, part.extent.x, part.extent.y))
                parts3d.append(part3d)
        elif dir == dcp.EAST:
            # use X and Y; Z rising with increasing X
            length = size.x
            height = size.z
            width = size.y
            flip = False
            parts = self._macro_stairs_core(length, height, width, flip,
                                            slength, sheight, texture)
            for part in parts:
                part3d = utils.Region3D(
                    Point(part.origin.x, 0, part.origin.y) + origin,
                    Point(part.extent.x, width, part.extent.y))
                parts3d.append(part3d)
        elif dir == dcp.WEST:
            # use X and y; Z falling with increasing X
            length = size.x
            height = size.z
            width = size.y
            flip = True
            parts = self._macro_stairs_core(length, height, width, flip,
                                            slength, sheight, texture)
            for part in parts:
                part3d = utils.Region3D(
                    Point(part.origin.x, 0, part.origin.y) + origin,
                    Point(part.extent.x, width, part.extent.y))
                parts3d.append(part3d)
        else:
            utils.error(
                'invalid direction specified for stairs (up and down are currently '
                'unsupported)')

        for part3d in parts3d:
            super().startElement(
                'solid', {
                    'origin': str(part3d.origin),
                    'extent': str(part3d.extent),
                    'texture': texture,
                    'type': 'step'
                })
            super().endElement('solid')
Пример #3
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(
                utils.Chunk2D(
                    chunk.origin,
                    utils.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(
                utils.Chunk2D(
                    utils.Point2D(hole.end.x, chunk.origin.y),
                    utils.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(
                    utils.Chunk2D(
                        chunk.origin,
                        utils.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(
                    utils.Chunk2D(
                        chunk.origin +
                        utils.Point2D(0, hole.origin.y - chunk.origin.y),
                        utils.Point2D(hole.origin.x - chunk.origin.x,
                                      hole.extent.y)))
            # Above hole
            if (chunk.end.y - hole.end.y) > 0:
                parts.append(
                    utils.Chunk2D(
                        chunk.origin +
                        utils.Point2D(0, hole.end.y - chunk.origin.y),
                        utils.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(
                utils.Chunk2D(
                    chunk.origin,
                    utils.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(
                utils.Chunk2D(
                    utils.Point2D(holeA.end.x, chunk.origin.y),
                    utils.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(
                    utils.Chunk2D(
                        chunk.origin,
                        utils.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(
                    utils.Chunk2D(
                        utils.Point2D(chunk.origin.x, upper.origin.y),
                        utils.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(
                    utils.Chunk2D(chunk.origin,
                                  utils.Point2D(xcutoff, upper.origin.y)),
                    [lower])
                for ap in addparts:
                    parts.append(ap)
                paddedPrint('sWC: n. Y.  more holes.  UPPER.')
                addparts = splitWallCore(
                    utils.Chunk2D(
                        utils.Point2D(chunk.origin.x, upper.origin.y),
                        utils.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(
                    utils.Chunk2D(
                        utils.Point2D(chunk.origin.x + xcutoff,
                                      chunk.origin.y),
                        utils.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.
            utils.error(
                "Oh dear: the segmentation algorithm can't cope with holes that overlap "
                'both x- and y-wise!')
    splitWallCoreLevel = splitWallCoreLevel - 1
    return parts
Пример #4
0
def processSolid(doc, parent, worldtype, worldspawn, sf, offset, solid):
    style = parent.getAttribute('style')
    o = utils.getPoint(solid.getAttribute('origin')) + offset
    e = utils.getPoint(solid.getAttribute('extent'))
    type = solid.getAttribute('type')
    if not type:
        utils.error('solid with no type')
    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 == connector.DOOR:
                props['key'] = hole.getAttribute('key')
            else:
                utils.warning(
                    'only doors allowed as hole types; not plats or others.')
            # FIXME deal with other types
            holes.append(
                utils.Hole2D(utils.Point2D(float(ho_x), float(ho_y)),
                             utils.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 == dcp.NORTH:
            parts = split.splitWall(
                utils.Region2D(utils.Point2D(o.x, o.z),
                               utils.Point2D(e.x, e.z)), holes)
            for part in parts:
                part3d = utils.addDim(part, dims.Y, o.y, e.y)
                utils.makeBrush(doc, worldtype, worldspawn, sf, style, part3d,
                                f)
        elif f == dcp.UP:
            parts = split.splitWall(
                utils.Region2D(utils.Point2D(o.x, o.y),
                               utils.Point2D(e.x, e.y)), holes)
            for part in parts:
                part3d = utils.addDim(part, dims.Z, o.z + prog.lip_small,
                                      e.z - prog.lip_small * 2)
                utils.makeBrush(doc, worldtype, worldspawn, sf, style, part3d,
                                f)
            else:
                utils.error('Unsupported holeface ' + f +
                            ' requested for hole in solid.')
    else:
        # Doesn't have child nodes...
        if not type or type == connector.STEP:
            pass  # no properties to set
        elif type == connector.DOOR:
            props['key'] = solid.getAttribute('key')
        elif type == connector.PLAT:
            props['position'] = solid.getAttribute('position')
        else:
            utils.warning('unknown type ' + type + ' specifed.')

        brush = utils.Region3D(Point(o.x, o.y, o.z), Point(e.x, e.y, e.z),
                               type, props)
        utils.makeBrush(doc, worldtype, worldspawn, sf, style, brush, type)
    # We can't remove the child or we screw over tree traversal (urgh)...
    utils.insertPlaceholder(doc, parent, solid)