Initial text support implementation, pt. II.
Switch from fixed-function pipeline to shaders.
10
ENNTool.py
@ -10,7 +10,7 @@
|
|||||||
# 3) -s: effects: rotate, smash into bricks, swirl, wave, ...
|
# 3) -s: effects: rotate, smash into bricks, swirl, wave, ...
|
||||||
# 4) XXX autodetect video width from widest mircart
|
# 4) XXX autodetect video width from widest mircart
|
||||||
# 5) XXX convert TTF to texture PNG & coords TXT, render accordingly
|
# 5) XXX convert TTF to texture PNG & coords TXT, render accordingly
|
||||||
# 6) XXX dont stall GPU w/ glReadPixels(), switch to asynchronous model w/ PBOs
|
# 6) XXX dont stall GPU w/ glReadPixels(), switch to asynchronous model w/ FBO or PBO (http://www.songho.ca/opengl/gl_fbo.html, http://www.songho.ca/opengl/gl_pbo.html)
|
||||||
# 7) XXX render mircart as 3D blocks vs flat surface
|
# 7) XXX render mircart as 3D blocks vs flat surface
|
||||||
#
|
#
|
||||||
|
|
||||||
@ -91,8 +91,8 @@ class ENNToolApp(object):
|
|||||||
MiRCART += ENNToolMiRCARTImporter(inFile).outMap
|
MiRCART += ENNToolMiRCARTImporter(inFile).outMap
|
||||||
|
|
||||||
curY, rotateX, rotateY, translateY = 0, 0, 0, scrollRate
|
curY, rotateX, rotateY, translateY = 0, 0, 0, scrollRate
|
||||||
artTextureId = panelGLCanvas.initTexture(texturePathName)
|
artTextureId, artInfo = panelGLCanvas.initTexture(texturePathName)
|
||||||
artVbo, artVboLen, lastY, numVertices = panelGLCanvas.renderMiRCART(MiRCART, cubeSize=optdict["-R"])
|
artVbo, artVboLen, lastY, numVertices = panelGLCanvas.renderMiRCART(artInfo, MiRCART, cubeSize=optdict["-R"])
|
||||||
if "-v" in optdict:
|
if "-v" in optdict:
|
||||||
print("{} vertices".format(numVertices))
|
print("{} vertices".format(numVertices))
|
||||||
w, h = panelGLCanvas.GetClientSize(); w, h = max(w, 1.0), max(h, 1.0);
|
w, h = panelGLCanvas.GetClientSize(); w, h = max(w, 1.0), max(h, 1.0);
|
||||||
@ -121,7 +121,9 @@ class ENNToolApp(object):
|
|||||||
|
|
||||||
videoFps, videoPath = int(optdict["-f"]), optdict["-o"]
|
videoFps, videoPath = int(optdict["-f"]), optdict["-o"]
|
||||||
panelGLCanvas = ENNToolGLCanvasPanel(appPanelSkin, size=appFrameSize, videoPath=videoPath)
|
panelGLCanvas = ENNToolGLCanvasPanel(appPanelSkin, size=appFrameSize, videoPath=videoPath)
|
||||||
panelGLCanvas.initOpenGL(); panelGLCanvas.initVideoWriter(fps=videoFps)
|
panelGLCanvas.initOpenGL()
|
||||||
|
panelGLCanvas.initShaders()
|
||||||
|
panelGLCanvas.initVideoWriter(fps=videoFps)
|
||||||
|
|
||||||
if "-v" in optdict:
|
if "-v" in optdict:
|
||||||
time0 = time.time()
|
time0 = time.time()
|
||||||
|
@ -10,13 +10,20 @@
|
|||||||
# Wed, 27 Jun 2018 16:02:12 +0200 [3] <https://www.khronos.org/opengl/wiki/How_lighting_works#Good_Settings.>
|
# Wed, 27 Jun 2018 16:02:12 +0200 [3] <https://www.khronos.org/opengl/wiki/How_lighting_works#Good_Settings.>
|
||||||
# Wed, 27 Jun 2018 16:02:13 +0200 [4] <https://www.khronos.org/opengl/wiki/Common_Mistakes>
|
# Wed, 27 Jun 2018 16:02:13 +0200 [4] <https://www.khronos.org/opengl/wiki/Common_Mistakes>
|
||||||
# Wed, 27 Jun 2018 16:02:14 +0200 [5] <https://www.khronos.org/opengl/wiki/Pixel_Transfer#Pixel_layout>
|
# Wed, 27 Jun 2018 16:02:14 +0200 [5] <https://www.khronos.org/opengl/wiki/Pixel_Transfer#Pixel_layout>
|
||||||
|
# Thu, 28 Jun 2018 17:03:16 +0200 [6] <https://stackoverflow.com/questions/384759/how-to-convert-a-pil-image-into-a-numpy-array>
|
||||||
|
# Thu, 28 Jun 2018 17:04:59 +0200 [7] <https://www.khronos.org/opengl/wiki/Common_Mistakes#y-axis>
|
||||||
|
# Thu, 28 Jun 2018 18:32:50 +0200 [8] <https://stackoverflow.com/questions/18935203/shader-position-vec4-or-vec3>
|
||||||
#
|
#
|
||||||
|
|
||||||
from OpenGL.GL import *
|
from OpenGL.GL import *
|
||||||
|
from OpenGL.GL import shaders
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
import cv2, numpy
|
import cv2, numpy
|
||||||
import ctypes, sys
|
import ctypes, os, sys, time
|
||||||
import wx, wx.glcanvas
|
import wx, wx.glcanvas
|
||||||
|
import yaml
|
||||||
|
|
||||||
|
from ENNToolMiRCARTColours import ENNToolMiRCARTColoursFloat
|
||||||
|
|
||||||
class ENNToolGLCanvasPanel(wx.glcanvas.GLCanvas, wx.Panel):
|
class ENNToolGLCanvasPanel(wx.glcanvas.GLCanvas, wx.Panel):
|
||||||
"""XXX"""
|
"""XXX"""
|
||||||
@ -34,22 +41,56 @@ class ENNToolGLCanvasPanel(wx.glcanvas.GLCanvas, wx.Panel):
|
|||||||
glEnable(GL_DEPTH_TEST)
|
glEnable(GL_DEPTH_TEST)
|
||||||
glClearColor(0, 0, 0, 1); glClearDepth(1);
|
glClearColor(0, 0, 0, 1); glClearDepth(1);
|
||||||
glTranslatef(-5.0, 3.0, -5)
|
glTranslatef(-5.0, 3.0, -5)
|
||||||
|
|
||||||
# [3]
|
|
||||||
glLight(GL_LIGHT0, GL_AMBIENT, (0, 0, 0, 1))
|
|
||||||
glLight(GL_LIGHT0, GL_DIFFUSE, (1, 1, 1, 1))
|
|
||||||
glLight(GL_LIGHT0, GL_POSITION, (1, 1, 0+2, 0))
|
|
||||||
glLight(GL_LIGHT0, GL_SPECULAR, (1, 1, 1, 1))
|
|
||||||
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, (0.2, 0.2, 0.2, 1))
|
|
||||||
glEnable(GL_LIGHTING); glEnable(GL_LIGHT0);
|
|
||||||
glEnable(GL_COLOR_MATERIAL)
|
|
||||||
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE)
|
|
||||||
# }}}
|
# }}}
|
||||||
# {{{ initTexture(self, pathName): XXX
|
# {{{ initShaders(self): XXX
|
||||||
def initTexture(self, pathName):
|
def initShaders(self):
|
||||||
|
fs = shaders.compileShader("""
|
||||||
|
#version 330 core
|
||||||
|
|
||||||
|
in vec4 bgColour;
|
||||||
|
in vec2 fgTexCoord;
|
||||||
|
uniform sampler2D texture;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec4 texel = texture2D(texture, fgTexCoord);
|
||||||
|
if (texel.a > 0.0) {
|
||||||
|
gl_FragColor = vec4(texel.r, texel.g, texel.b, 1.0);
|
||||||
|
} else {
|
||||||
|
gl_FragColor = bgColour;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""", GL_FRAGMENT_SHADER)
|
||||||
|
vs = shaders.compileShader("""
|
||||||
|
#version 330 core
|
||||||
|
|
||||||
|
layout(location = 0) in vec4 vertex;
|
||||||
|
layout(location = 1) in vec3 normal;
|
||||||
|
layout(location = 2) in vec4 colour;
|
||||||
|
layout(location = 3) in vec2 texcoord;
|
||||||
|
|
||||||
|
out vec4 bgColour;
|
||||||
|
out vec2 fgTexCoord;
|
||||||
|
|
||||||
|
uniform mat4 model;
|
||||||
|
uniform mat4 projection;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
gl_Position = projection * model * vertex;
|
||||||
|
bgColour = colour;
|
||||||
|
fgTexCoord = texcoord;
|
||||||
|
}
|
||||||
|
""", GL_VERTEX_SHADER)
|
||||||
|
self.shader = shaders.compileProgram(vs, fs)
|
||||||
|
# }}}
|
||||||
|
# {{{ initTexture(self, pathName, infoPathName=os.path.join("assets", "textures.yaml")): XXX
|
||||||
|
def initTexture(self, pathName, infoPathName=os.path.join("assets", "textures.yaml")):
|
||||||
|
with open(infoPathName, "r") as fileObject:
|
||||||
|
artInfo = yaml.load(fileObject)
|
||||||
|
|
||||||
|
# [6], [7]
|
||||||
artTextureId = glGenTextures(1)
|
artTextureId = glGenTextures(1)
|
||||||
artTextureImage = Image.open(pathName)
|
artTextureImage = Image.open(pathName).transpose(Image.FLIP_TOP_BOTTOM)
|
||||||
artTextureImageData = numpy.array(list(artTextureImage.getdata()), numpy.uint8)
|
artTextureImageData = numpy.array(artTextureImage)
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, artTextureId)
|
glBindTexture(GL_TEXTURE_2D, artTextureId)
|
||||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1)
|
glPixelStorei(GL_UNPACK_ALIGNMENT, 1)
|
||||||
@ -61,11 +102,11 @@ class ENNToolGLCanvasPanel(wx.glcanvas.GLCanvas, wx.Panel):
|
|||||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
|
||||||
|
|
||||||
# [4][5]
|
# [4][5]
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
|
||||||
artTextureImage.size[0], artTextureImage.size[1],
|
artTextureImage.size[0], artTextureImage.size[1],
|
||||||
0, GL_RGBA, GL_UNSIGNED_BYTE, artTextureImageData)
|
0, GL_RGBA, GL_UNSIGNED_BYTE, artTextureImageData)
|
||||||
glBindTexture(GL_TEXTURE_2D, artTextureId)
|
glBindTexture(GL_TEXTURE_2D, artTextureId)
|
||||||
return artTextureId
|
return artTextureId, artInfo
|
||||||
# }}}
|
# }}}
|
||||||
# {{{ initVideoWriter(self): XXX
|
# {{{ initVideoWriter(self): XXX
|
||||||
def initVideoWriter(self, fourcc="XVID", fps=25):
|
def initVideoWriter(self, fourcc="XVID", fps=25):
|
||||||
@ -76,54 +117,94 @@ class ENNToolGLCanvasPanel(wx.glcanvas.GLCanvas, wx.Panel):
|
|||||||
def renderFrame(self, artTextureId, artVbo, artVboLen):
|
def renderFrame(self, artTextureId, artVbo, artVboLen):
|
||||||
glEnableClientState(GL_VERTEX_ARRAY)
|
glEnableClientState(GL_VERTEX_ARRAY)
|
||||||
glEnableClientState(GL_NORMAL_ARRAY)
|
glEnableClientState(GL_NORMAL_ARRAY)
|
||||||
|
glEnableClientState(GL_COLOR_ARRAY)
|
||||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY)
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY)
|
||||||
glEnable(GL_TEXTURE_2D)
|
glEnable(GL_TEXTURE_2D)
|
||||||
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
|
glEnable(GL_BLEND)
|
||||||
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, artTextureId)
|
glBindTexture(GL_TEXTURE_2D, artTextureId)
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, artVbo)
|
glBindBuffer(GL_ARRAY_BUFFER, artVbo)
|
||||||
glVertexPointer(3, GL_FLOAT, 32, ctypes.c_void_p(0))
|
|
||||||
glNormalPointer(GL_FLOAT, 32, ctypes.c_void_p(12))
|
glUseProgram(self.shader)
|
||||||
glTexCoordPointer(2, GL_FLOAT, 32, ctypes.c_void_p(24))
|
model = (GLfloat * 16)()
|
||||||
|
glGetFloatv(GL_MODELVIEW_MATRIX, model)
|
||||||
|
projection = (GLfloat * 16)()
|
||||||
|
glGetFloatv(GL_PROJECTION_MATRIX, projection)
|
||||||
|
glUniformMatrix4fv(glGetUniformLocation(self.shader, "model"), 1, GL_FALSE, model)
|
||||||
|
glUniformMatrix4fv(glGetUniformLocation(self.shader, "projection"), 1, GL_FALSE, projection)
|
||||||
|
glUniform1i(glGetUniformLocation(self.shader, "texture"), 0)
|
||||||
|
|
||||||
|
# [8]
|
||||||
|
glEnableVertexAttribArray(0)
|
||||||
|
glVertexAttribPointer(0, 3, GL_FLOAT, False, 48, ctypes.c_void_p(0))
|
||||||
|
glEnableVertexAttribArray(1)
|
||||||
|
glVertexAttribPointer(1, 3, GL_FLOAT, False, 48, ctypes.c_void_p(12))
|
||||||
|
glEnableVertexAttribArray(2)
|
||||||
|
glVertexAttribPointer(2, 4, GL_FLOAT, False, 48, ctypes.c_void_p(24))
|
||||||
|
glEnableVertexAttribArray(3)
|
||||||
|
glVertexAttribPointer(3, 2, GL_FLOAT, False, 48, ctypes.c_void_p(40))
|
||||||
|
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
|
||||||
|
glVertexPointer(3, GL_FLOAT, 48, ctypes.c_void_p(0))
|
||||||
|
glNormalPointer(GL_FLOAT, 48, ctypes.c_void_p(12))
|
||||||
|
glColorPointer(4, GL_FLOAT, 48, ctypes.c_void_p(24))
|
||||||
|
glTexCoordPointer(2, GL_FLOAT, 48, ctypes.c_void_p(40))
|
||||||
glDrawArrays(GL_QUADS, 0, artVboLen)
|
glDrawArrays(GL_QUADS, 0, artVboLen)
|
||||||
|
|
||||||
|
glDisableVertexAttribArray(0)
|
||||||
|
glDisable(GL_BLEND)
|
||||||
glDisable(GL_TEXTURE_2D)
|
glDisable(GL_TEXTURE_2D)
|
||||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY)
|
glDisableClientState(GL_TEXTURE_COORD_ARRAY)
|
||||||
|
glDisableClientState(GL_COLOR_ARRAY)
|
||||||
glDisableClientState(GL_NORMAL_ARRAY)
|
glDisableClientState(GL_NORMAL_ARRAY)
|
||||||
glDisableClientState(GL_VERTEX_ARRAY)
|
glDisableClientState(GL_VERTEX_ARRAY)
|
||||||
# }}}
|
# }}}
|
||||||
# {{{ renderMiRCART(self, artMap, centre=True, canvasCols=100, cubeSize=(0.1, 0.2), texelHeight=0.0625, texelWidth=0.0625): XXX
|
# {{{ renderMiRCART(self, artInfo, artMap, centre=True, canvasCols=100, cubeSize=(0.1, 0.2)): XXX
|
||||||
def renderMiRCART(self, artMap, centre=True, canvasCols=100, cubeSize=(0.1, 0.2), texelHeight=0.0625, texelWidth=0.0625):
|
def renderMiRCART(self, artInfo, artMap, centre=True, canvasCols=100, cubeSize=(0.1, 0.2)):
|
||||||
curPos = [0, 0, 0]; vertices = []; numVertices = 0;
|
curPos = [0, 0, 0]; vertices = []; numVertices = 0;
|
||||||
for numRow in range(len(artMap)):
|
for numRow in range(len(artMap)):
|
||||||
if centre and (len(artMap[numRow]) < canvasCols):
|
if centre and (len(artMap[numRow]) < canvasCols):
|
||||||
curPos[0] += (((canvasCols - len(artMap[numRow])) * cubeSize[0]) / 2)
|
curPos[0] += (((canvasCols - len(artMap[numRow])) * cubeSize[0]) / 2)
|
||||||
for numCol in range(len(artMap[numRow])):
|
for numCol in range(len(artMap[numRow])):
|
||||||
cubeColour = artMap[numRow][numCol][1] * texelWidth
|
cubeColour = [*ENNToolMiRCARTColoursFloat[artMap[numRow][numCol][1]], 1.0]
|
||||||
|
if artMap[numRow][numCol][0] != artMap[numRow][numCol][1]:
|
||||||
|
colColour = artMap[numRow][numCol][0]
|
||||||
|
cubeChar = artMap[numRow][numCol][3]
|
||||||
|
if ord(cubeChar) >= 128:
|
||||||
|
print("dont have {}".format(cubeChar))
|
||||||
|
cubeChar = " "
|
||||||
|
else:
|
||||||
|
colColour = artMap[numRow][numCol][1]
|
||||||
|
cubeChar = " "
|
||||||
|
|
||||||
# Top Right
|
# Top Right
|
||||||
vertices += curPos
|
vertices += curPos
|
||||||
vertices += [0.0, 0.0, 1.0]
|
vertices += [0.0, 0.0, 1.0]
|
||||||
vertices += [cubeColour+texelWidth, texelHeight]
|
vertices += cubeColour
|
||||||
|
vertices += [float(((ord(cubeChar) + 1) * artInfo["rowWidth"]) / artInfo["texWidth"]), ((colColour + 1) * artInfo["rowHeight"]) / float(artInfo["texHeight"])]
|
||||||
numVertices += 1
|
numVertices += 1
|
||||||
|
|
||||||
# Top Left
|
# Top Left
|
||||||
vertices += [curPos[0]-cubeSize[0], curPos[1], curPos[2]]
|
vertices += [curPos[0]-cubeSize[0], curPos[1], curPos[2]]
|
||||||
vertices += [0.0, 0.0, 1.0]
|
vertices += [0.0, 0.0, 1.0]
|
||||||
vertices += [cubeColour, texelHeight]
|
vertices += cubeColour
|
||||||
|
vertices += [float(((ord(cubeChar) + 0) * artInfo["rowWidth"]) / artInfo["texWidth"]), ((colColour + 1) * artInfo["rowHeight"]) / float(artInfo["texHeight"])]
|
||||||
numVertices += 1
|
numVertices += 1
|
||||||
|
|
||||||
# Bottom Left
|
# Bottom Left
|
||||||
vertices += [curPos[0]-cubeSize[0], curPos[1]-cubeSize[1], curPos[2]]
|
vertices += [curPos[0]-cubeSize[0], curPos[1]-cubeSize[1], curPos[2]]
|
||||||
vertices += [0.0, 0.0, 1.0]
|
vertices += [0.0, 0.0, 1.0]
|
||||||
vertices += [cubeColour, 0.0]
|
vertices += cubeColour
|
||||||
|
vertices += [float(((ord(cubeChar) + 0) * artInfo["rowWidth"]) / artInfo["texWidth"]), ((colColour) * artInfo["rowHeight"]) / float(artInfo["texHeight"])]
|
||||||
numVertices += 1
|
numVertices += 1
|
||||||
|
|
||||||
# Bottom Right
|
# Bottom Right
|
||||||
vertices += [curPos[0], curPos[1]-cubeSize[1], curPos[2]]
|
vertices += [curPos[0], curPos[1]-cubeSize[1], curPos[2]]
|
||||||
vertices += [0.0, 0.0, 1.0]
|
vertices += [0.0, 0.0, 1.0]
|
||||||
vertices += [cubeColour+texelWidth, 0.0]
|
vertices += cubeColour
|
||||||
|
vertices += [float(((ord(cubeChar) + 1) * artInfo["rowWidth"]) / artInfo["texWidth"]), ((colColour) * artInfo["rowHeight"]) / float(artInfo["texHeight"])]
|
||||||
numVertices += 1
|
numVertices += 1
|
||||||
|
|
||||||
curPos[0] += cubeSize[0]
|
curPos[0] += cubeSize[0]
|
||||||
|
@ -16,75 +16,61 @@ from ENNToolMiRCARTImporter import ENNToolMiRCARTImporter
|
|||||||
def main(*argv):
|
def main(*argv):
|
||||||
fontNormalPathName = os.path.join("assets", "DejaVuSansMono.ttf")
|
fontNormalPathName = os.path.join("assets", "DejaVuSansMono.ttf")
|
||||||
fontBoldPathName = os.path.join("assets", "DejaVuSansMono-Bold.ttf")
|
fontBoldPathName = os.path.join("assets", "DejaVuSansMono-Bold.ttf")
|
||||||
fontSize = int("11")
|
fontSize = int("26")
|
||||||
outInfoFileName = os.path.join("assets", "textures.yaml")
|
outInfoFileName = os.path.join("assets", "textures.yaml")
|
||||||
outPathName = os.path.join("assets", "textures")
|
outFileName = os.path.join("assets", "DejaVuSansMono.png")
|
||||||
if not os.path.exists(os.path.dirname(outInfoFileName)):
|
if not os.path.exists(os.path.dirname(outInfoFileName)):
|
||||||
os.makedirs(os.path.dirname(outInfoFileName))
|
os.makedirs(os.path.dirname(outInfoFileName))
|
||||||
if not os.path.exists(outPathName):
|
if not os.path.exists(os.path.dirname(outFileName)):
|
||||||
os.makedirs(outPathName)
|
os.makedirs(os.path.dirname(outFileName))
|
||||||
|
|
||||||
pilFontNormal = ImageFont.truetype(fontNormalPathName, fontSize)
|
pilFontNormal = ImageFont.truetype(fontNormalPathName, fontSize)
|
||||||
pilFontBold = ImageFont.truetype(fontBoldPathName, fontSize)
|
pilFontBold = ImageFont.truetype(fontBoldPathName, fontSize)
|
||||||
pilFontSize = list(pilFontNormal.getsize(" "))
|
pilFontSize = list(pilFontNormal.getsize(" "))
|
||||||
pilFontSize[0] += (8 - (pilFontSize[0] % 8))
|
pilFontSize[0] += (8 - (pilFontSize[0] % 8))
|
||||||
pilFontSize[1] = pilFontSize[0] * 2
|
pilFontSize[1] = pilFontSize[0] * 2
|
||||||
pilImageSize = (pilFontSize[0] * 128, pilFontSize[1])
|
pilImageSize = (pilFontSize[0] * 128, (pilFontSize[1] * 16 * 4))
|
||||||
print("font size: {}, image size: {}".format(pilFontSize, pilImageSize))
|
print("font size: {}, image size: {}".format(pilFontSize, pilImageSize))
|
||||||
|
|
||||||
charMap = {}
|
|
||||||
for fontAttrs in [[ENNToolMiRCARTImporter._CellState.CS_NONE],
|
|
||||||
[ENNToolMiRCARTImporter._CellState.CS_BOLD],
|
|
||||||
[ENNToolMiRCARTImporter._CellState.CS_UNDERLINE],
|
|
||||||
[ENNToolMiRCARTImporter._CellState.CS_BOLD, ENNToolMiRCARTImporter._CellState.CS_UNDERLINE]]:
|
|
||||||
for fontColour in range(16):
|
|
||||||
curPos = [0, 0]
|
curPos = [0, 0]
|
||||||
pilImage = Image.new("RGBA", pilImageSize, (0, 0, 0, 0))
|
pilImage = Image.new("RGBA", pilImageSize, (0, 0, 0, 0))
|
||||||
pilImageDraw = ImageDraw.Draw(pilImage)
|
pilImageDraw = ImageDraw.Draw(pilImage)
|
||||||
|
|
||||||
|
pilImageTmp = Image.new("RGBA", pilFontSize, (0, 0, 0, 0))
|
||||||
|
pilImageTmpDraw = ImageDraw.Draw(pilImageTmp)
|
||||||
|
|
||||||
|
for fontAttr in [ENNToolMiRCARTImporter._CellState.CS_BOLD | ENNToolMiRCARTImporter._CellState.CS_UNDERLINE,
|
||||||
|
ENNToolMiRCARTImporter._CellState.CS_UNDERLINE,
|
||||||
|
ENNToolMiRCARTImporter._CellState.CS_BOLD,
|
||||||
|
ENNToolMiRCARTImporter._CellState.CS_NONE]:
|
||||||
|
for fontColour in reversed(range(16)):
|
||||||
for fontChar in [chr(n) for n in range(128)]:
|
for fontChar in [chr(n) for n in range(128)]:
|
||||||
pilFont, underLine = None, False
|
pilFont, underLine = pilFontNormal, False
|
||||||
for fontAttr in fontAttrs:
|
if fontAttr & ENNToolMiRCARTImporter._CellState.CS_BOLD:
|
||||||
if fontAttr == ENNToolMiRCARTImporter._CellState.CS_NONE:
|
|
||||||
pilFont = pilFontNormal
|
|
||||||
elif fontAttr == ENNToolMiRCARTImporter._CellState.CS_BOLD:
|
|
||||||
pilFont = pilFontBold
|
pilFont = pilFontBold
|
||||||
elif fontAttr == ENNToolMiRCARTImporter._CellState.CS_UNDERLINE:
|
if fontAttr & ENNToolMiRCARTImporter._CellState.CS_UNDERLINE:
|
||||||
underLine = True
|
underLine = True
|
||||||
else:
|
|
||||||
raise ValueError
|
|
||||||
if fontChar in string.printable:
|
if fontChar in string.printable:
|
||||||
pilImageDraw.text(curPos, fontChar,
|
pilImageTmpDraw.text((0, 0), fontChar,
|
||||||
(*ENNToolMiRCARTColours[fontColour], 255), pilFont)
|
(*ENNToolMiRCARTColours[fontColour], 255), pilFont)
|
||||||
|
pilImage.paste(pilImageTmp, tuple(curPos))
|
||||||
|
pilImageTmpDraw.rectangle((0, 0, pilFontSize[0], pilFontSize[1]),
|
||||||
|
fill=(0, 0, 0, 0))
|
||||||
if underLine:
|
if underLine:
|
||||||
pilImageDraw.line(
|
pilImageDraw.line(
|
||||||
xy=(curPos[0], curPos[1] + (pilFontSize[1] - 2),
|
xy=(curPos[0], curPos[1] + (pilFontSize[1] - 2),
|
||||||
curPos[0] + pilFontSize[0], curPos[1] + (pilFontSize[1] - 2)),
|
curPos[0] + pilFontSize[0], curPos[1] + (pilFontSize[1] - 2)),
|
||||||
fill=(*ENNToolMiRCARTColours[fontColour], 255))
|
fill=(*ENNToolMiRCARTColours[fontColour], 255))
|
||||||
if not fontChar in charMap:
|
|
||||||
charMap[fontChar] = {}
|
|
||||||
if not fontColour in charMap[fontChar]:
|
|
||||||
charMap[fontChar][fontColour] = []
|
|
||||||
charMap[fontChar][fontColour] \
|
|
||||||
+= [{"attrs":fontAttrs,
|
|
||||||
"bl":[float((curPos[0])/pilImageSize[0]), float((curPos[1])/pilImageSize[1])],
|
|
||||||
"br":[float((curPos[0] + pilFontSize[0])/pilImageSize[0]), float((curPos[1])/pilImageSize[1])],
|
|
||||||
"tl":[float((curPos[0])/pilImageSize[0]), float((curPos[1] + pilFontSize[1])/pilImageSize[1])],
|
|
||||||
"tr":[float((curPos[0] + pilFontSize[0])/pilImageSize[0]), float((curPos[1] + pilFontSize[1])/pilImageSize[1])]}]
|
|
||||||
curPos[0] += pilFontSize[0]
|
curPos[0] += pilFontSize[0]
|
||||||
fontAttrName = ""
|
curPos[0], curPos[1] = 0, curPos[1] + pilFontSize[1]
|
||||||
for fontAttr in fontAttrs:
|
pilImage.save(outFileName)
|
||||||
if fontAttr == ENNToolMiRCARTImporter._CellState.CS_NONE:
|
artInfo = {}
|
||||||
fontAttrName += "Normal"
|
artInfo["rowHeight"] = pilFontSize[1]
|
||||||
elif fontAttr == ENNToolMiRCARTImporter._CellState.CS_BOLD:
|
artInfo["rowWidth"] = pilFontSize[0]
|
||||||
fontAttrName += "Bold"
|
artInfo["texHeight"] = pilImageSize[1]
|
||||||
elif fontAttr == ENNToolMiRCARTImporter._CellState.CS_UNDERLINE:
|
artInfo["texWidth"] = pilImageSize[0]
|
||||||
fontAttrName += "Underline"
|
|
||||||
else:
|
|
||||||
raise ValueError
|
|
||||||
pilImage.save(os.path.join(outPathName, "{}Fg{:02d}.png".format(fontAttrName, fontColour)))
|
|
||||||
|
|
||||||
with open(outInfoFileName, "w") as fileObject:
|
with open(outInfoFileName, "w") as fileObject:
|
||||||
yaml.dump(charMap, fileObject)
|
yaml.dump(artInfo, fileObject)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main(*sys.argv)
|
main(*sys.argv)
|
||||||
|
BIN
assets/DejaVuSansMono.png
Normal file
After Width: | Height: | Size: 1.5 MiB |
Before Width: | Height: | Size: 270 B After Width: | Height: | Size: 18 B |
1
assets/texture.png
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
DejaVuSansMono.png
|
Before Width: | Height: | Size: 270 B After Width: | Height: | Size: 18 B |
33703
assets/textures.yaml
Before Width: | Height: | Size: 7.0 KiB |
Before Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 5.6 KiB |
Before Width: | Height: | Size: 6.1 KiB |
Before Width: | Height: | Size: 8.5 KiB |
Before Width: | Height: | Size: 6.2 KiB |
Before Width: | Height: | Size: 7.5 KiB |
Before Width: | Height: | Size: 7.5 KiB |
Before Width: | Height: | Size: 7.9 KiB |
Before Width: | Height: | Size: 8.5 KiB |
Before Width: | Height: | Size: 7.4 KiB |
Before Width: | Height: | Size: 7.7 KiB |
Before Width: | Height: | Size: 8.3 KiB |
Before Width: | Height: | Size: 7.8 KiB |
Before Width: | Height: | Size: 8.5 KiB |
Before Width: | Height: | Size: 8.6 KiB |
Before Width: | Height: | Size: 7.1 KiB |
Before Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 5.7 KiB |
Before Width: | Height: | Size: 6.1 KiB |
Before Width: | Height: | Size: 8.5 KiB |
Before Width: | Height: | Size: 6.2 KiB |
Before Width: | Height: | Size: 7.5 KiB |
Before Width: | Height: | Size: 7.5 KiB |
Before Width: | Height: | Size: 7.9 KiB |
Before Width: | Height: | Size: 8.5 KiB |
Before Width: | Height: | Size: 7.4 KiB |
Before Width: | Height: | Size: 7.8 KiB |
Before Width: | Height: | Size: 8.4 KiB |
Before Width: | Height: | Size: 7.8 KiB |
Before Width: | Height: | Size: 8.5 KiB |
Before Width: | Height: | Size: 8.6 KiB |
Before Width: | Height: | Size: 7.1 KiB |
Before Width: | Height: | Size: 4.2 KiB |
Before Width: | Height: | Size: 5.1 KiB |
Before Width: | Height: | Size: 5.6 KiB |
Before Width: | Height: | Size: 8.4 KiB |
Before Width: | Height: | Size: 5.7 KiB |
Before Width: | Height: | Size: 7.5 KiB |
Before Width: | Height: | Size: 7.5 KiB |
Before Width: | Height: | Size: 7.1 KiB |
Before Width: | Height: | Size: 8.3 KiB |
Before Width: | Height: | Size: 7.4 KiB |
Before Width: | Height: | Size: 7.1 KiB |
Before Width: | Height: | Size: 8.3 KiB |
Before Width: | Height: | Size: 7.1 KiB |
Before Width: | Height: | Size: 8.5 KiB |
Before Width: | Height: | Size: 8.5 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.3 KiB |