7
$\begingroup$

So I'm trying to import some actual ascii art into the scripting window's txt editor, aiming to convert it into an extruded 3d mesh to create the basis for some quick mazes.

But upon conversion despite the looking fine in the text editor, the formatting is completely thrown off when it turns into a 3d Object, and messing with the alignment didn't help much.

I feel there is a logical answer to this problem, but have found no way to resolve my issue, any feedback on this would be nice

I feel there is a logical answer to this problem, but have found no way to resolve my issue, any feedback on this would be nice

$\endgroup$
1
  • 1
    $\begingroup$ I don't really know what you're doing there, that thing on the left is a text object or what? To me it looks like the decades old problem of trying to do something with a proportional font what needs an anti-proportional font. I mean, go into word, put this line art there and format it with Courier New font. I guess it would look okay. Then format it with Arial or Times New Roman and all is broken. Maybe you should choose a different font for the text object? $\endgroup$ May 21, 2021 at 8:53

2 Answers 2

10
$\begingroup$

You need to set the font to a monospaced font. BFont is proportional and so the characters are different sizes.

enter image description here

I used Consolas which is a monospaced font, and the text is exactly as it looks in the editor. I believe Consolas ships with Windows.

enter image description here

This is with the default BFont:

enter image description here

$\endgroup$
5
$\begingroup$

Here is a script which turns ASCII art into fully connected geometry:

enter image description here

It supports the characters "|_/\", and variable font size. By default, it replace the geometry of the active mesh object.

Run it with bpy.MazeGen.ASCIIGrid(D.texts["Maze"], run=True) in the console panel.

import bpy, bmesh

class ASCIIGrid():
    def __init__(self, text, chardims=(0.6, 1.0), run=False, ctx=None):
        self.text = "\n".join(l.body for l in text.lines) if isinstance(text, bpy.types.Text) else text
        self.chardims = tuple(chardims)
        self.ctx = ctx or bpy.context
        if run:
            self.Run()
    def MakeBMesh(self):
        self.bm = bmesh.new()
        self.lines = self.text.split("\n")
        self.height, self.width = len(self.lines)+1, (max(len(l) for l in self.lines)+1)*2
        self.grid = [[self.bm.verts.new((c/2*self.chardims[0], -r*self.chardims[1], 0)) for c in range(self.width)] for r in range(self.height)]
        return self
    def ConnectBMesh(self):
        for r, li in enumerate(self.lines):
            for c, ch in enumerate(li):
                if ch == "|":
                    self.bm.edges.new((self.grid[r][c*2+1], self.grid[r+1][c*2+1]))
                elif ch == "_":
                    self.bm.edges.new((self.grid[r+1][c*2], self.grid[r+1][c*2+1]))
                    self.bm.edges.new((self.grid[r+1][c*2+1], self.grid[r+1][c*2+2]))
                elif ch == "/":
                    self.bm.edges.new((self.grid[r+1][c*2], self.grid[r][c*2+2]))
                elif ch == "\\":
                    self.bm.edges.new((self.grid[r][c*2], self.grid[r+1][c*2+2]))
        return self
    def FillBMesh(self):
        for r, ro in enumerate(self.grid):
            for c, ve in enumerate(ro):
                if {self.grid[r+1][c] if r < self.height-1 else ..., self.grid[r-1][c] if r else ...}.intersection({v for e in ve.link_edges for v in e.verts}):
                    left, right = self.grid[r][c-1] if c else ..., self.grid[r][c+1] if c < self.width-1 else ...
                    for side in (left, right):
                        if side is ...:
                            continue
                        if side.link_edges:
                            self.bm.edges.new((ve, side))
        return self
    def CleanBMesh(self):
        used = {v for e in self.bm.edges for v in e.verts}
        for v in self.bm.verts:
            if v not in used:
                self.bm.verts.remove(v)
    def InjectToMesh(self, mesh=None):
        if mesh is None:
            mesh = self.ctx.object.data
        self.bm.to_mesh(mesh)
        return self
    def Run(self, mesh=None):
        self.MakeBMesh()
        self.ConnectBMesh()
        self.FillBMesh()
        self.CleanBMesh()
        self.InjectToMesh(mesh=mesh)
        return self     
        


class O:
    def __init__(self, d):
        self.__dict__ = d

bpy.MazeGen = O(globals())
$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .