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
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)
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
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)
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