diff --git a/.gitignore b/ENNTool/.gitignore similarity index 100% rename from .gitignore rename to ENNTool/.gitignore diff --git a/ENNTool.py b/ENNTool/ENNTool.py similarity index 60% rename from ENNTool.py rename to ENNTool/ENNTool.py index a593868..907a794 100755 --- a/ENNTool.py +++ b/ENNTool/ENNTool.py @@ -5,13 +5,20 @@ # This project is licensed under the terms of the MIT license. # # TODO: -# 1) -A: render frame #1, render frame #2, ... -# 2) -s: effects: rotate, smash into bricks, swirl, wave, ... -# 3) Feature: include ETA @ progress bar -# 4) Feature: autodetect video width from widest mircart -# 5) Feature: render mircart as 3D blocks vs flat surface -# 6) OpenGL: use VAOs + glVertexAttribFormat + glVertexAttribBinding -# 7) use names @ optdict[] + set from optdefaults +# 1) -A, -S: replace w/ -s, implement animation script: render frame #1, render frame #2, ...; scrolling script; effects: rotate, smash into bricks, swirl, wave, ... +# 2) Feature: include ETA(s) @ progress bar(s) +# 3) Feature: autodetect video width from widest mircart +# 4) Feature: render mircart as 3D blocks vs flat surface + +# +# 1) Optimisation: speed up ENNToolMiRCARTImporter +# 2) Cleanup: use names @ optdict + set from optdefaults +# 3) Feature: scrolling speed as x +# 4) Cleanup: use VAOs + glVertexAttribFormat + glVertexAttribBinding +# 5) Optimisation: split mIRC art into separate VBOs & implement rudimentary culling +# 6) Optimisation: only call glReadPixels() when changes were made relative to the last call +# 7) Split video output into separate module, switch to GUI +# 8) FBOs http://www.songho.ca/opengl/gl_fbo.html # from getopt import getopt, GetoptError @@ -20,7 +27,7 @@ from OpenGL.GL import * import os, sys, time import wx -from ENNToolGLCanvasPanel import ENNToolGLCanvasPanel +from ENNToolGLCanvasPanel import ENNToolGLCanvas, ENNToolGLPanel from ENNToolGLTTFTexture import ENNToolGLTTFTexture from ENNToolGLVideoWriter import ENNToolGLVideoWriter from ENNToolMiRCARTImporter import ENNToolMiRCARTImporter @@ -52,8 +59,6 @@ class ENNToolApp(object): if "-h" in optdict: usage(sys.argv[0]); exit(0); - elif not "-o" in optdict: - raise GetoptError("-o fname must be specified") elif not len(argv): raise GetoptError("at least one MiRCART input fname must be specified") @@ -82,8 +87,8 @@ class ENNToolApp(object): print("\r[{:<50}] {}%".format( ("=" * int(progressDiv * 50)), int(progressDiv * 100)), end=endChar) # }}} - # {{{ modeScroll(self, argv, optdict, GLVideoWriter, panelGLCanvas, fps=25, scrollRate=0.25): XXX - def modeScroll(self, argv, optdict, GLVideoWriter, panelGLCanvas, fps=25, scrollRate=0.25): + # {{{ modeScroll(self, argv, optdict, GLVideoWriter, GLpanel, GLpanel, fps=25, scrollRate=0.1): XXX + def modeScroll(self, argv, optdict, GLVideoWriter, GLcanvas, GLpanel, fps=25, scrollRate=0.1): MiRCART = [] if "-v" in optdict: time0 = time.time() @@ -93,53 +98,74 @@ class ENNToolApp(object): if "-v" in optdict: print("mIRC art import delta {:.3f}ms".format((time.time() - time0) * 1000)) - curY, rotateX, rotateY, translateY = 0, 0, 0, scrollRate if "-v" in optdict: time0 = time.time() artTextureId, artInfo = ENNToolGLTTFTexture(MiRCART, optdict["-R"], optdict["-r"]).getParams() if "-v" in optdict: print("TTF texture generation delta {:.3f}ms".format((time.time() - time0) * 1000)) - artVbo, artVboLen, lastY, numVertices = panelGLCanvas.renderMiRCART(artInfo, MiRCART, cubeSize=optdict["-R"]) + artVbo, artVboLen, lastY, numVertices = GLcanvas.renderMiRCART(artInfo, MiRCART, cubeSize=optdict["-R"]) if "-v" in optdict: print("{} vertices".format(numVertices)) - w, h = panelGLCanvas.GetClientSize(); w, h = max(w, 1.0), max(h, 1.0); - - while True: - self.printProgress(curY, lastY) - for numFrame in range(fps): - panelGLCanvas.renderFrame(artTextureId, artVbo, artVboLen) + def scrollFrameFun(): + curY, rotateX, rotateY, translateY = 0, 0, 0, scrollRate + w, h = GLcanvas.GetClientSize(); w, h = max(w, 1.0), max(h, 1.0); + def scrollFrame(): + nonlocal curY + self.printProgress(curY, lastY) + GLcanvas.renderFrame(artTextureId, artVbo, artVboLen) if translateY: glTranslatef(0, translateY, 0); curY += translateY if rotateX: glRotatef(rotateX * (180.0/w), 0.0, 1.0, 0.0) if rotateY: glRotatef(rotateY * (180.0/h), 1.0, 0.0, 0.0) - GLVideoWriter.saveFrame() - if curY >= lastY: - self.printProgress(curY, lastY); break; - - GLVideoWriter.saveVideo() + if "-o" in optdict: + GLVideoWriter.saveFrame() + else: + GLcanvas.SwapBuffers() + if curY >= lastY: + self.printProgress(curY, lastY) + if "-o" in optdict: + GLVideoWriter.saveVideo() + return False + return True + return scrollFrame + if "-o" in optdict: + frameFun = scrollFrameFun() + while True: + if not frameFun(): + break + else: + GLpanel.frameFun = scrollFrameFun() + self.wxApp.MainLoop() # }}} # {{{ __init__(self, argv): XXX def __init__(self, argv): argv, optdict = self.parseArgv(argv) - wxApp = wx.App(False) - appFrameSize = optdict["-r"] - appFrame = wx.Frame(None, size=appFrameSize); appFrame.Hide(); - appPanelSkin = wx.Panel(appFrame, wx.ID_ANY) + self.wxApp = wx.App(False) + appFrameSize = [c + 128 for c in optdict["-r"]] + self.appFrame = wx.Frame(None, size=appFrameSize) + appPanelSkin = wx.Panel(self.appFrame, wx.ID_ANY) - videoFps, videoPath = int(optdict["-f"]), optdict["-o"] - panelGLCanvas = ENNToolGLCanvasPanel(appPanelSkin, size=appFrameSize) - panelGLCanvas.initOpenGL() - panelGLCanvas.initShaders() - GLVideoWriter = ENNToolGLVideoWriter(videoPath, panelGLCanvas.GetClientSize(), videoFps=videoFps) + videoFps, videoPath = int(optdict["-f"]), optdict["-o"] if "-o" in optdict else None + GLpanel = ENNToolGLPanel(appPanelSkin, size=optdict["-r"], parentFrame=self.appFrame) + GLcanvas = ENNToolGLCanvas(GLpanel, optdict["-r"]) + GLcanvas.initOpenGL() + GLcanvas.initShaders() + GLVideoWriter = ENNToolGLVideoWriter(videoPath, GLpanel.GetClientSize(), videoFps=videoFps) + + if "-o" in optdict: + self.appFrame.Hide() + else: + self.appFrame.Show(); self.appFrame.SetFocus(); if "-v" in optdict: time0 = time.time() - self.modeScroll(argv, optdict, GLVideoWriter, panelGLCanvas, fps=videoFps) + self.modeScroll(argv, optdict, GLVideoWriter, GLcanvas, GLpanel, fps=videoFps) if "-v" in optdict: print("delta {}s".format(time.time() - time0)) - if "-p" in optdict: + if "-o" in optdict \ + and "-p" in optdict: os.startfile(videoPath) # }}} diff --git a/ENNToolGLCanvasPanel.py b/ENNTool/ENNToolGLCanvasPanel.py similarity index 61% rename from ENNToolGLCanvasPanel.py rename to ENNTool/ENNToolGLCanvasPanel.py index d26f0b6..63d8c4e 100644 --- a/ENNToolGLCanvasPanel.py +++ b/ENNTool/ENNToolGLCanvasPanel.py @@ -14,13 +14,12 @@ # Tue, 03 Jul 2018 14:34:57 +0200 [7] # +from ENNToolMiRCARTColours import ENNToolMiRCARTColoursFloat from OpenGL.GL import * from OpenGL.GL import shaders import ctypes, wx, wx.glcanvas -class ENNToolGLCanvasPanel(wx.glcanvas.GLCanvas, wx.Panel): - """XXX""" - +class ENNToolGLCanvas(wx.glcanvas.GLCanvas): # {{{ initOpenGL(self): XXX def initOpenGL(self): self.glContext = wx.glcanvas.GLContext(self) @@ -32,7 +31,6 @@ class ENNToolGLCanvasPanel(wx.glcanvas.GLCanvas, wx.Panel): glLoadIdentity(); glFrustum(-1, 1, -1, 1, 1, 100); glMatrixMode(GL_MODELVIEW) glEnable(GL_DEPTH_TEST) - glClearColor(0, 0, 0, 1); glClearDepth(1); glTranslatef(-5.0, 3.0, -5) # }}} # {{{ initShaders(self): XXX @@ -41,12 +39,20 @@ class ENNToolGLCanvasPanel(wx.glcanvas.GLCanvas, wx.Panel): fs = shaders.compileShader(""" #version 330 core - in vec2 fgTexCoord; + in vec2 frgTexCoord; + in vec3 frgFgColour; + in vec3 frgBgColour; uniform sampler2D texture; + layout(location = 0) out vec4 fragColour; + void main() { - vec4 texel = texture2D(texture, fgTexCoord); - gl_FragColor = vec4(texel.r, texel.g, texel.b, 1.0); + vec4 texel = texture2D(texture, frgTexCoord); + if (texel.r == 0.0 && texel.g == 0.0 && texel.b == 0.0 && texel.a == 0.0) { + fragColour = vec4(frgBgColour.r, frgBgColour.g, frgBgColour.b, 1.0); + } else { + fragColour = vec4(frgFgColour.r, frgFgColour.g, frgFgColour.b, 1.0); + } } """, GL_FRAGMENT_SHADER) @@ -56,15 +62,21 @@ class ENNToolGLCanvasPanel(wx.glcanvas.GLCanvas, wx.Panel): layout(location = 0) in vec4 vertex; layout(location = 1) in vec2 texcoord; + layout(location = 2) in vec3 vexFgColour; + layout(location = 3) in vec3 vexBgColour; - out vec2 fgTexCoord; + out vec2 frgTexCoord; + out vec3 frgFgColour; + out vec3 frgBgColour; uniform mat4 modelview; uniform mat4 projection; void main() { gl_Position = projection * modelview * vertex; - fgTexCoord = texcoord; + frgTexCoord = texcoord; + frgFgColour = vexFgColour; + frgBgColour = vexBgColour; } """, GL_VERTEX_SHADER) self.shader = shaders.compileProgram(vs, fs) @@ -86,13 +98,23 @@ class ENNToolGLCanvasPanel(wx.glcanvas.GLCanvas, wx.Panel): # VBO vertices location glEnableVertexAttribArray(0) - glVertexAttribPointer(0, 3, GL_FLOAT, False, 20, ctypes.c_void_p(0)) - glVertexPointer(3, GL_FLOAT, 20, ctypes.c_void_p(0)) + glVertexAttribPointer(0, 3, GL_FLOAT, False, 44, ctypes.c_void_p(0)) + glVertexPointer(3, GL_FLOAT, 44, ctypes.c_void_p(0)) # VBO texture coordinates glEnableVertexAttribArray(1) - glVertexAttribPointer(1, 2, GL_FLOAT, False, 20, ctypes.c_void_p(12)) - glTexCoordPointer(2, GL_FLOAT, 20, ctypes.c_void_p(12)) + glVertexAttribPointer(1, 2, GL_FLOAT, False, 44, ctypes.c_void_p(12)) + glTexCoordPointer(2, GL_FLOAT, 44, ctypes.c_void_p(12)) + + # VBO foreground colours + glEnableVertexAttribArray(2) + glVertexAttribPointer(2, 3, GL_FLOAT, False, 44, ctypes.c_void_p(20)) + glTexCoordPointer(3, GL_FLOAT, 44, ctypes.c_void_p(20)) + + # VBO background colours + glEnableVertexAttribArray(3) + glVertexAttribPointer(3, 3, GL_FLOAT, False, 44, ctypes.c_void_p(32)) + glTexCoordPointer(3, GL_FLOAT, 44, ctypes.c_void_p(32)) # Clear colour and depth buffer, draw quads from VBO & clear state glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) @@ -111,19 +133,27 @@ class ENNToolGLCanvasPanel(wx.glcanvas.GLCanvas, wx.Panel): cubeBg = artMap[numRow][numCol][1] cubeAttrs = artMap[numRow][numCol][2] cubeChar = artMap[numRow][numCol][3] - artCell = artInfo[cubeFg][cubeBg][cubeAttrs][cubeChar] + artCell = artInfo[cubeAttrs][cubeChar] # Top Right, Top Left vertices += curPos vertices += artCell[0:2] + vertices += [*ENNToolMiRCARTColoursFloat[cubeFg]] + vertices += [*ENNToolMiRCARTColoursFloat[cubeBg]] vertices += [curPos[0] - cubeSize[0], curPos[1], curPos[2]] vertices += artCell[2:4] + vertices += ENNToolMiRCARTColoursFloat[cubeFg] + vertices += ENNToolMiRCARTColoursFloat[cubeBg] # Bottom Left, Bottom Right vertices += [curPos[0] - cubeSize[0], curPos[1] - cubeSize[1], curPos[2]] vertices += artCell[4:6] + vertices += [*ENNToolMiRCARTColoursFloat[cubeFg]] + vertices += [*ENNToolMiRCARTColoursFloat[cubeBg]] vertices += [curPos[0], curPos[1] - cubeSize[1], curPos[2]] vertices += artCell[6:8] + vertices += ENNToolMiRCARTColoursFloat[cubeFg] + vertices += ENNToolMiRCARTColoursFloat[cubeBg] curPos[0], numVertices = curPos[0] + cubeSize[0], numVertices + 4 curPos[0], curPos[1] = 0, curPos[1] - cubeSize[1] @@ -135,10 +165,40 @@ class ENNToolGLCanvasPanel(wx.glcanvas.GLCanvas, wx.Panel): GL_STATIC_DRAW) return artVbo, len(vertices), -curPos[1], numVertices # }}} - # {{{ __init__(self, parent, size, defaultPos=(24,24)): initialisation method - def __init__(self, parent, size, defaultPos=(24,24)): + # {{{ __init__(self, parentCanvas, size): initialisation method + def __init__(self, parentCanvas, size): + super().__init__(parentCanvas, size=size) + self.curSize = list(size) + self.parentCanvas = parentCanvas + # }}} + +class ENNToolGLPanel(wx.Panel): + """XXX""" + + # {{{ onPaint(self, event): XXX + def onPaint(self, event): + eventDc = wx.PaintDC(self) + eventUpdates = wx.RegionIterator(self.GetUpdateRegion()) + paintFlag = True if eventUpdates.HaveRects() else False + if self.frameFun != None: + self.frameFun() + # }}} + # {{{ onTimer(self, event): XXX + def onTimer(self, event): + if self.frameFun != None: + if not self.frameFun(): + event.GetTimer().Stop() + event.GetTimer().Destroy() + # }}} + # {{{ __init__(self, parent, size, defaultPos=(24,24), parentFrame=None): initialisation method + def __init__(self, parent, size, defaultPos=(24,24), parentFrame=None): super().__init__(parent, pos=defaultPos, size=size) self.curPos = list(defaultPos); self.curSize = list(size); + self.Bind(wx.EVT_PAINT, self.onPaint) + self.frameFun = None + self.timerTimer = wx.Timer(self, 1) + self.timerTimer.Start(40) + self.Bind(wx.EVT_TIMER, self.onTimer, self.timerTimer) # }}} # vim:expandtab foldmethod=marker sw=4 ts=4 tw=120 diff --git a/ENNToolGLTTFTexture.py b/ENNTool/ENNToolGLTTFTexture.py similarity index 63% rename from ENNToolGLTTFTexture.py rename to ENNTool/ENNToolGLTTFTexture.py index c2ef112..e56c838 100644 --- a/ENNToolGLTTFTexture.py +++ b/ENNTool/ENNToolGLTTFTexture.py @@ -10,6 +10,7 @@ # Wed, 27 Jun 2018 16:02:12 +0200 [3] # Wed, 27 Jun 2018 16:02:13 +0200 [4] # Wed, 27 Jun 2018 16:02:14 +0200 [5] +# Wed, 04 Jul 2018 10:57:09 +0200 [6] # from collections import defaultdict @@ -33,33 +34,38 @@ class ENNToolGLTTFTexture(object): def _nestedDict(): return defaultdict(ENNToolGLTTFTexture._nestedDict) # }}} - # {{{ _drawCharList(self, artInfo, charList, pilFontBold, pilFontNormal, pilFontSize, pilImageDraw, pilImageSize): XXX - def _drawCharList(self, artInfo, charList, pilFontBold, pilFontNormal, pilFontSize, pilImageDraw, pilImageSize): + # {{{ _drawCharList(self, artInfo, charList, pilFontBold, pilFontNormal, pilImageDraw, pilImageSize): XXX + def _drawCharList(self, artInfo, charList, pilFontBold, pilFontNormal, pilImageDraw, pilImageSize): curPos = [0, 0] for newChar in charList: - pilFont, underLine = pilFontNormal, False if newChar[2] & ENNToolMiRCARTImporter._CellState.CS_BOLD: - pilFont = pilFontBold + pilFont, pilFontSize = pilFontBold, [pilFontBold.getsize(newChar[3])[0], pilFontBold.getsize(newChar[3])[1]] + else: + pilFont, pilFontSize = pilFontNormal, [pilFontNormal.getsize(newChar[3])[0], pilFontNormal.getsize(newChar[3])[1]] if newChar[2] & ENNToolMiRCARTImporter._CellState.CS_UNDERLINE: underLine = True - pilImageDraw.rectangle((*curPos, curPos[0] + pilFontSize[0], curPos[1] + pilFontSize[1] - 1), - fill=(*ENNToolMiRCARTColours[newChar[1]], 255)) - pilImageDraw.text(curPos, newChar[3], (*ENNToolMiRCARTColours[newChar[0]], 255), pilFont) - if underLine: + else: + underLine = False + if newChar[3] != " ": + pilImageDraw.text(curPos, newChar[3], (255, 255, 255, 255), pilFont) + elif newChar[0] == newChar[1]: + pilImageDraw.rectangle((*curPos, curPos[0] + pilFontSize[0], curPos[1] + pilFontSize[1] - 1), + fill=(255, 255, 255, 255)) + if underLine and False: pilImageDraw.line( xy=(curPos[0], curPos[1] + (pilFontSize[1] - 2), curPos[0] + pilFontSize[0], curPos[1] + pilFontSize[1]), fill=(*ENNToolMiRCARTColours[newChar[0]], 255)) - artInfo[newChar[0]][newChar[1]][newChar[2]][newChar[3]] = [] + artInfo[newChar[2]][newChar[3]] = [] # Top Right - artInfo[newChar[0]][newChar[1]][newChar[2]][newChar[3]] += [float(curPos[0] + pilFontSize[0]) / pilImageSize[0], 0.0] + artInfo[newChar[2]][newChar[3]] += [float(curPos[0] + pilFontSize[0]) / pilImageSize[0], 0.0] # Top Left - artInfo[newChar[0]][newChar[1]][newChar[2]][newChar[3]] += [float(curPos[0]) / pilImageSize[0], 0.0] + artInfo[newChar[2]][newChar[3]] += [float(curPos[0]) / pilImageSize[0], 0.0] # Bottom Left - artInfo[newChar[0]][newChar[1]][newChar[2]][newChar[3]] += [float(curPos[0]) / pilImageSize[0], float(pilFontSize[1]) / pilImageSize[1]] + artInfo[newChar[2]][newChar[3]] += [float(curPos[0]) / pilImageSize[0], float(pilFontSize[1]) / pilImageSize[1]] # Bottom Right - artInfo[newChar[0]][newChar[1]][newChar[2]][newChar[3]] += [float(curPos[0] + pilFontSize[0]) / pilImageSize[0], float(pilFontSize[1]) / pilImageSize[1]] + artInfo[newChar[2]][newChar[3]] += [float(curPos[0] + pilFontSize[0]) / pilImageSize[0], float(pilFontSize[1]) / pilImageSize[1]] curPos[0] += pilFontSize[0] return artInfo @@ -73,24 +79,33 @@ class ENNToolGLTTFTexture(object): artBg = artMap[numRow][numCol][1] artAttrs = artMap[numRow][numCol][2] artChar = artMap[numRow][numCol][3] - if artInfo[artFg][artBg][artAttrs][artChar] == {}: - artInfo[artFg][artBg][artAttrs][artChar] = None + if artInfo[artAttrs][artChar] == {}: + artInfo[artAttrs][artChar] = None charList += [[artFg, artBg, artAttrs, artChar]] return artInfo, charList # }}} - # {{{ _initFonts(self): XXX - def _initFonts(self): + # {{{ _initFonts(self, charMap): XXX + def _initFonts(self, charMap): fontBoldPathName = os.path.join("assets", "DejaVuSansMono-Bold.ttf") fontNormalPathName = os.path.join("assets", "DejaVuSansMono.ttf") fontSize = int("26") pilFontBold = ImageFont.truetype(fontBoldPathName, fontSize) + pilFontMaxSize = [16, 32] # TODO pilFontNormal = ImageFont.truetype(fontNormalPathName, fontSize) - pilFontSize = list(pilFontNormal.getsize("_")) # XXX - return pilFontBold, pilFontNormal, pilFontSize + return pilFontBold, pilFontMaxSize, pilFontNormal # }}} - # {{{ _initImage(self, charList, pilFontSize): XXX - def _initImage(self, charList, pilFontSize): - pilImageSize = (pilFontSize[0] * len(charList), pilFontSize[1]) + # {{{ _initImage(self, charList, pilFontMaxSize): XXX + def _initImage(self, charList, pilFontMaxSize): + pilImageSize = [pilFontMaxSize[0] * len(charList), pilFontMaxSize[1]] + for numDim in range(len(pilImageSize)): + if (pilImageSize[numDim] & (pilImageSize[numDim] - 1)) != 0: + pilImageSize[numDim] -= 1 + pilImageSize[numDim] |= pilImageSize[numDim] >> 1 + pilImageSize[numDim] |= pilImageSize[numDim] >> 2 + pilImageSize[numDim] |= pilImageSize[numDim] >> 4 + pilImageSize[numDim] |= pilImageSize[numDim] >> 8 + pilImageSize[numDim] |= pilImageSize[numDim] >> 16 + pilImageSize[numDim] += 1 pilImage = Image.new("RGBA", pilImageSize, (0, 0, 0, 0)) pilImageDraw = ImageDraw.Draw(pilImage) return pilImage, pilImageDraw, pilImageSize @@ -115,7 +130,6 @@ class ENNToolGLTTFTexture(object): glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, artTextureImage.size[0], artTextureImage.size[1], 0, GL_RGBA, GL_UNSIGNED_BYTE, artTextureImageData) - glGenerateMipmap(GL_TEXTURE_2D) glBindTexture(GL_TEXTURE_2D, 0) return artTextureId @@ -127,11 +141,9 @@ class ENNToolGLTTFTexture(object): # {{{ __init__(self): initialisation method def __init__(self, artMap, cubeSize, videoSize): artInfo, charList = self._initArtInfoCharList(artMap) - pilFontBold, pilFontNormal, pilFontSize = self._initFonts() - pilImage, pilImageDraw, pilImageSize = self._initImage(charList, pilFontSize) - artInfo = self._drawCharList(artInfo, charList, - pilFontBold, pilFontNormal, pilFontSize, - pilImageDraw, pilImageSize) + pilFontBold, pilFontMaxSize, pilFontNormal = self._initFonts(charList) + pilImage, pilImageDraw, pilImageSize = self._initImage(charList, pilFontMaxSize) + artInfo = self._drawCharList(artInfo, charList, pilFontBold, pilFontNormal, pilImageDraw, pilImageSize) artTextureId = self._initTexture(pilImage) self.artTextureId = artTextureId self.artInfo = artInfo diff --git a/ENNToolGLVideoWriter.py b/ENNTool/ENNToolGLVideoWriter.py similarity index 100% rename from ENNToolGLVideoWriter.py rename to ENNTool/ENNToolGLVideoWriter.py diff --git a/ENNToolMiRCARTColours.py b/ENNTool/ENNToolMiRCARTColours.py similarity index 100% rename from ENNToolMiRCARTColours.py rename to ENNTool/ENNToolMiRCARTColours.py diff --git a/ENNToolMiRCARTImporter.py b/ENNTool/ENNToolMiRCARTImporter.py similarity index 100% rename from ENNToolMiRCARTImporter.py rename to ENNTool/ENNToolMiRCARTImporter.py diff --git a/LICENCE b/ENNTool/LICENCE similarity index 100% rename from LICENCE rename to ENNTool/LICENCE diff --git a/README.md b/ENNTool/README.md similarity index 100% rename from README.md rename to ENNTool/README.md diff --git a/assets/DejaVuSansMono-Bold.ttf b/ENNTool/assets/DejaVuSansMono-Bold.ttf similarity index 100% rename from assets/DejaVuSansMono-Bold.ttf rename to ENNTool/assets/DejaVuSansMono-Bold.ttf diff --git a/assets/DejaVuSansMono.png b/ENNTool/assets/DejaVuSansMono.png similarity index 100% rename from assets/DejaVuSansMono.png rename to ENNTool/assets/DejaVuSansMono.png diff --git a/assets/DejaVuSansMono.ttf b/ENNTool/assets/DejaVuSansMono.ttf similarity index 100% rename from assets/DejaVuSansMono.ttf rename to ENNTool/assets/DejaVuSansMono.ttf diff --git a/assets/puke.txt b/ENNTool/assets/puke.txt similarity index 100% rename from assets/puke.txt rename to ENNTool/assets/puke.txt diff --git a/openh264-1.7.0-win32.dll b/ENNTool/openh264-1.7.0-win32.dll similarity index 100% rename from openh264-1.7.0-win32.dll rename to ENNTool/openh264-1.7.0-win32.dll diff --git a/ENNTool/openh264-1.7.0-win64.dll b/ENNTool/openh264-1.7.0-win64.dll new file mode 100755 index 0000000..ba98295 Binary files /dev/null and b/ENNTool/openh264-1.7.0-win64.dll differ diff --git a/openh264-1.7.0-win32_LICENSE.txt b/ENNTool/openh264-1.7.0_LICENSE.txt similarity index 100% rename from openh264-1.7.0-win32_LICENSE.txt rename to ENNTool/openh264-1.7.0_LICENSE.txt