Module igeCore.devtool

indi game engine offline develop tools

convert 3d assets convert images to platform dipend format make ige package upload package to devserver

Expand source code
"""
indi game engine offline develop tools

convert 3d assets
convert images to platform dipend format
make ige package
upload package to devserver

"""

import py_compile
import shutil
import glob
import os.path
import igeCore as core
from igeCore import apputil
from igeCore.devtool._igeTools import *
from igeCore import apputil
from igeCore.apputil import launch_server
import hashlib
import tokenize

def isHiddenFolder(path):
    if path.find('/.') != -1 or path.find('\\.') != -1 :
        return True
    return False

def findFiles(path, exts = ['.*']):
    list = []
    for root, dirs, files in os.walk(path):
        if isHiddenFolder(root): continue
        for fname in files:
            name, ext = os.path.splitext(fname)
            for e in exts:
                if e == '.*' or e == ext:
                    list.append(os.path.join(root, fname))
                    break
    return list

def findImageFiles(path):
    list = []
    for root, dirs, files in os.walk(path):
        if isHiddenFolder(root): continue
        for fname in files:
            name, ext = os.path.splitext(fname)
            extl = ext.lower()
            if extl == '.png' or extl == '.dds' or extl == '.tga' or extl == '.psd' or extl == '.jpg':
                list.append(os.path.join(root, fname))
    return list

def find3DSceneFiles(path):
    dict = {}
    for root, dirs, files in os.walk(path):
        if root.find('\.') != -1: continue
        folder = os.path.basename(root)

        folderRule = False
        for f in files:
            name, ext = os.path.splitext(f)
            if name == folder:
                folderRule = True
                baseFile = f
                break

        if folderRule:
            daes = [os.path.join(root, baseFile)]
            for f2 in files:
                f2_name, f2_ext = os.path.splitext(f2)
                if (f2_ext.lower() == '.dae' or f2_ext.lower() == '.fbx') and f2_name != folder:
                    daes.append(os.path.join(root, f2))
            dict[folder] = daes
        else:
            for f2 in files:
                f2_name, f2_ext = os.path.splitext(f2)
                if f2_ext.lower() == '.dae' or f2_ext.lower() == '.fbx':
                    dict[f2_name] = [os.path.join(root, f2)]
    return dict

def createDirectoryTree(filelist, root):
    imageDirectory = dict()
    for img in filelist:
        while True:
            img, file = os.path.split(img)
            if img not in imageDirectory:
                imageDirectory[img] = {file: 0};
            elif file not in imageDirectory[img]:
                imageDirectory[img][file] = 0
            if img == root: break
    return imageDirectory

def findFileFromDiorectoryTree(imageDirectory, file, dir):
    files = imageDirectory.get(dir)
    if files is None: return None
    if file in files:
        return os.path.join(dir, file)
    for d in files:
        _, ext = os.path.splitext(d)
        if ext == '':
            rv = findFileFromDiorectoryTree(imageDirectory, file, os.path.join(dir, d))
            if rv: return rv
    return None

def removeRoot(path, root):
    newpath = path.replace(root, '', 1)
    if len(newpath) >0:
        if newpath[0] == '/' or newpath[0] == '\\':
            newpath = newpath[1:]
    else:
        newpath = ""
    return newpath

def replaceExt(file, ext):
    name, extold = os.path.splitext(file)
    return name + ext

def readAndCalcHash(srcfile, dstfile, hashfile):
    hashcode = '00000000000000000000000000000000'
    newhash  = 'ffffffffffffffffffffffffffffffff'
    if os.path.exists(dstfile):
        try:
            with open(hashfile, 'r') as f:
                hashcode = f.read()
        except : None

    with open(srcfile, 'rb') as f:
        fileDataBinary = f.read()
        if len(fileDataBinary) != 0:
            hash = hashlib.md5()
            hash.update(fileDataBinary)
            newhash = hash.hexdigest()
    return hashcode,newhash

def saveHash(hashfile, newhash):
    if newhash != 'ffffffffffffffffffffffffffffffff':
        apputil.makeDirectories(hashfile)
        with open(hashfile, 'w') as f:
            f.write(newhash)

def readFigureConf(path):
    mode = 0
    label = ''
    keyvalue = {}
    with open(path, 'rb') as f:
        for token in tokenize.tokenize(f.readline):
            if token.type is tokenize.ENDMARKER:
                break
            elif token.type is tokenize.NAME:
                if mode == 0:
                    label = token.string
                else:
                    keyvalue[label] = token.string
                    mode = 0
            elif token.type is tokenize.OP:
                mode = 1
            elif token.type is tokenize.NUMBER:
                if mode == 1:
                    try:
                        keyvalue[label] = int(token.string)
                    except ValueError:
                        keyvalue[label] = float(token.string)
                    mode = 0
    return keyvalue

def createFigureConfTree(path, unit=1.0):
    path = os.path.abspath(path)
    filelist = []
    for root, dirs, files in os.walk(path):
        if root.find('\.') != -1: continue
        for fname in files:
            if fname == 'figure.conf':
                filelist.append(os.path.join(root, fname))
    figureConfTree = dict()
    for filepath in filelist:
        conf = readFigureConf(filepath)
        dir, file = os.path.split(filepath)
        figureConfTree[dir] = conf

    for dir, val in figureConfTree.items():
        while True:
            dir, _ = os.path.split(dir)
            if dir == os.path.abspath('.').split(os.path.sep)[0]+os.path.sep:
                break
            parent = figureConfTree.get(dir)
            if parent is not None:
                for parentkey, parentval in parent.items():
                    if val.get(parentkey) is None:
                        val[parentkey] = parentval

    if len(figureConfTree) == 0:
        figureConfTree[path] = {}

    for conf in figureConfTree.values():
        if conf.get('BASE_SCALE') is None:
           conf['BASE_SCALE'] = unit
        #if conf.get('OPTIMIZE_MESH') is None:
        #   conf['OPTIMIZE_MESH'] = True

    return figureConfTree

def findFigureConf(dir: str, tree: dict):
    dir = os.path.abspath(dir)
    while True:
        dir, _ = os.path.split(dir)
        if dir == os.path.abspath('.').split(os.path.sep)[0]+os.path.sep:
            break
        conf = tree.get(dir)
        if conf is not None:
            return conf
    return dict()

def load3DScene(tmpfig, files, conf):
    loadModel(files[0], tmpfig, conf)
    for i in range(1, len(files)):
        loadAnimation(files[i], tmpfig, conf)

def replaceTexturePath(tmpfig, imageDirectory, startPath, endPath, allTextures, subFolder):
    texs = tmpfig.getTextureSource()
    for tex in texs:
        filename = os.path.basename(tex['path'])
        current = startPath
        inputimage = None
        while True:
            inputimage = findFileFromDiorectoryTree(imageDirectory, filename, current)
            if inputimage is not None: break
            if current == endPath: break
            current, _ = os.path.split(current)
        if inputimage is None:
            print('file not found ' + tex['path'])
        else:
            allTextures[inputimage] = tex;
            inputimage = removeRoot(inputimage, endPath);
            inputimage, ext = os.path.splitext(inputimage)
            inputimage = os.path.join(subFolder, inputimage)
            inputimage = inputimage.replace('\\', '/')
            newTex = {'path': inputimage, 'normal': tex['normal'], 'wrap': tex['wrap']}
            tmpfig.replaceTextureSource(tex, newTex)

def setMaterialAlpha(tmpfig, imageDirectory, startPath, endPath):
    texs = tmpfig.getTextureSource()
    for tex in texs:
        filename = os.path.basename(tex['path'])
        current = startPath
        inputimage = None
        while True:
            inputimage = findFileFromDiorectoryTree(imageDirectory, filename, current)
            if inputimage is not None: break
            if current == endPath: break
            current, _ = os.path.split(current)
        if inputimage is not None:
            if isAlpha(inputimage):
                tmpfig.enableAlphaModeByTexture(tex['path'])

def getHashPath(root, source, platform):
    abspath = os.path.abspath(source)
    if abspath[0]=='/' or abspath[0]=='\\':
       abspath = abspath[1:]
    elif abspath[2]=='\\':
        abspath = abspath[3:]
    return os.path.join(os.path.join(root, apputil.targetFolderName(platform)), abspath)

def convertImages(allTextures, sourceDir, destDir, platform):
    print('----------------------')
    print('Convert image files')
    print('----------------------')
    for key, val in allTextures.items():
        outfile = os.path.normpath(key.replace(sourceDir, destDir, 1))
        outfile = replaceExt(outfile, '.pyxi')
        hashfile = getHashPath('.tmp/hash', key, platform)
        hashcode, newhash = readAndCalcHash(key, outfile, hashfile)
        if hashcode != newhash:
            print("convert {} for {}".format(key,apputil.targetFolderName(platform)))
            apputil.makeDirectories(outfile)
            convertTextureToPlatform(key, outfile, platform, val['normal'], val['wrap'])
            saveHash(hashfile, newhash)
        else:
            print("skip {} ".format(key))

def copyFiles(src, dst, exts=['.*']):
    for root, dirs, files in os.walk(src):
        if isHiddenFolder(root): continue
        for fname in files:
            name, ext = os.path.splitext(fname)
            for e in exts:
                if e == '.*' or ext == e:
                    srcPath = os.path.join(root, fname)
                    dstPath = os.path.join(dst, removeRoot(srcPath, src))
                    apputil.makeDirectories(dstPath)
                    shutil.copy2(srcPath, dstPath)
                    print("copy {}".format(dstPath))
                    break

def compilePrograms(src, dst):
    list = findFiles(src, ['.py'])
    for infile in list:
        outfile = os.path.normpath(infile.replace(src, dst, 1))
        apputil.makeDirectories(outfile)
        if os.path.basename(infile) == 'root.py':
            shutil.copy(infile, outfile)
        else:
            outfile = replaceExt(outfile, '.pyc')
            apputil.makeDirectories(outfile)
            print('compile : '+infile)
            py_compile.compile(infile, outfile)

def hashCheck(files, outfile, platform):
    changed = False
    for file in files:
        hashfile = getHashPath('.tmp/hash', file, platform)
        hashcode, newhash = readAndCalcHash(file, outfile, hashfile)
        if hashcode != newhash:
            changed = True
            saveHash(hashfile, newhash)
    return changed

def buildAppPackage(src, dest):
    apputil.makeDirectories(dest)
    list =glob.glob(os.path.join(src,'*' ))
    for dir in list:
        if os.path.isdir(dir):
            outpath = os.path.join(dest,os.path.basename(dir))

            list = findFiles(dir)
            if hashCheck(list, outpath+'.pyxd', 0):
                print("build asset database {}.pyxd".format(outpath))
                compressFolder(dir, outpath)
            else:
                print("skip asset database {}.pyxd".format(outpath))
        else:
            print("copy {}".format(dir))
            shutil.copy2(dir, dest)


def findConvertReplaceTextures(fig : core.editableFigure, sourceRoot, destRoot, platform=core.TARGET_PLATFORM_PC, figurePath=""):
    """
    Find and convert the texture file linked from editableFigure.

    :param sourceRoot: Root folder to search for texture files
    :param destRoot: Root folder to save the textures
    :param editableFigure: The location where the editableFigure was saved (optional). It must be included under sourceRoot.
    :param platform: Formats to convert textures to. TARGET_PLATFORM_PC or TARGET_PLATFORM_MOBILE

    :return: None

    The figurePath must always be under the sourceRoot.
    The specified folder hierarchy may contain multiple texture files with the same name.
    When figurePath is specified, the texture file closest to it will be selected.

    Example.
        ・File path saved in editableFigure
            D:/aaa/bbb/ccc/test.png
        ・Location of the actual file
            C:/user/input/images/test.png
        ・sourceRoot
            C:/user/input
        ・destRoot
            C:/user/output
        ・The actual output file
            C:/user/output/images/test.pyxi
        ・New file path to be saved in editableFigure
            images/test
    """
    sourceRoot = os.path.abspath(sourceRoot).replace('\\', '/')
    destRoot = os.path.abspath(destRoot).replace('\\', '/')

    if figurePath == "":
        daepath = figurePath = sourceRoot
    else:
        figurePath = os.path.abspath(figurePath).replace('\\', '/')
        daepath, _ = os.path.split(figurePath)
        if len(daepath) == 0 : daepath = os.path.abspath(".").replace('\\', '/')


    imageList = findImageFiles(sourceRoot)
    imageDirectoryTree = createDirectoryTree(imageList, sourceRoot)
    setMaterialAlpha(fig, imageDirectoryTree, daepath, sourceRoot)

    allTextures = dict()
    replaceTexturePath(fig, imageDirectoryTree, daepath, sourceRoot, allTextures, removeRoot(destRoot,sourceRoot))
    convertImages(allTextures, sourceRoot, destRoot, platform)


def convertAssets(sourceDir, destDir, platform, unit=1.0, rootDir=None):
    """
    Convert model and image data to ige format
    model(.dae) -> .pyxf
    image(.png .dds .tga .psd ) -> .pyxi

    If model data with the same name as the folder name is found,
    it is regarded as base model data, and other model data in the
    same folder are regarded as motion files, and all are packed
    into one file
    If there is no model data with the same name as the folder name,
    Each model data as base model data and convert separately

    :param sourceDir: source root folder
    :param destDir: destination root folder
    :param platform: target platform (core.TARGET_PLATFORM_XX)
    :param unit: scale unit size of 3d model
    :return: None
    """
    if rootDir is None: rootDir = destDir

    imageList = findImageFiles(sourceDir)
    sceneList = find3DSceneFiles(sourceDir)
    imageDirectoryTree = createDirectoryTree(imageList, sourceDir)
    confTree = createFigureConfTree(sourceDir, unit)
    allTextures = dict()
    tmpfig = core.editableFigure("tmpfigure", True)

    print('----------------------')
    print('Convert 3d scene files')
    print('----------------------')

    for files in sceneList.values():
        tmpfig.clear()
        conf = findFigureConf(files[0], confTree)
        load3DScene(tmpfig, files, conf)

        daepath, _ = os.path.split(files[0])
        setMaterialAlpha(tmpfig, imageDirectoryTree, daepath, sourceDir)
        replaceTexturePath(tmpfig, imageDirectoryTree, daepath, sourceDir, allTextures, removeRoot(destDir,rootDir))

        outfile = os.path.normpath(files[0].replace(sourceDir, destDir, 1))
        outfile = replaceExt(outfile, '.pyxf')

        if hashCheck(files, outfile, platform):
            print("convert {}".format(files[0]))
            apputil.makeDirectories(outfile)

            if 'OPTIMIZE_VERTEX' in conf.keys() and conf['OPTIMIZE_VERTEX']:
                tmpfig.removeUnreferencedVertices()
            if 'OPTIMIZE_MESH' in conf.keys() and conf['OPTIMIZE_MESH']:
                tmpfig.mergeSameMaterialMesh()

            tmpfig.saveFigure(outfile)
        else:
            print("skip {}".format(files[0]))

    for img in imageList:
        if img not in allTextures:
            allTextures[img] = {'path': removeRoot(img,sourceDir), 'normal': False, 'wrap': False}
    convertImages(allTextures, sourceDir, destDir, platform)

    return allTextures


def deploy(projectFolder, userID, appName, appVersion, unit = 1.0, assetSource=None, assetDestination=None):
    if assetSource == None: assetSource = projectFolder
    if assetDestination == None: assetDestination = projectFolder
    allTextures = convertAssets(assetSource, assetDestination, core.TARGET_PLATFORM_PC, unit, projectFolder)

    deployTmp = '.tmp/deploy/'+appName+'/'+appVersion+'/'

    print('----------------------')
    print('Create non pack app image')
    print('----------------------')
    print('--- PC ---')
    copyFiles(projectFolder, deployTmp+'unpackimage/pc', ['.pyxf', '.json', '.pyxa', '.pyxb', '.pickle', '.zip', '.txt', '.db', '.ttf'])
    compilePrograms(projectFolder, deployTmp+'unpackimage/pc')
    convertImages(allTextures, assetSource, os.path.join(deployTmp+'unpackimage/pc',removeRoot(assetDestination, projectFolder)), core.TARGET_PLATFORM_PC)
    print('--- Mobile ---')
    copyFiles(projectFolder, deployTmp+'unpackimage/mobile', ['.pyxf', '.json', '.pyxa', '.pyxb', '.pickle', '.zip', '.txt', '.db', '.ttf'])
    compilePrograms(projectFolder, deployTmp+'unpackimage/mobile')
    convertImages(allTextures, assetSource, os.path.join(deployTmp+'unpackimage/mobile',removeRoot(assetDestination, projectFolder)), core.TARGET_PLATFORM_MOBILE)

    print('----------------------')
    print('Create packed app image')
    print('----------------------')
    print('--- PC ---')
    buildAppPackage(deployTmp+'unpackimage/pc', deployTmp+'packimage/pc')
    print('--- Mobile ---')
    buildAppPackage(deployTmp+'unpackimage/mobile', deployTmp+'packimage/mobile')

    print('----------------------')
    print('Upload app image to the server')
    print('----------------------')
    print('--- PC ---')
    launch_server.makeProjectDir(userID, appName, appVersion, "pc")
    launch_server.upload_files(deployTmp+'packimage/pc', '/'+userID+'/'+appName+'/'+appVersion+'/pc')
    print('--- Mobile ---')
    launch_server.makeProjectDir(userID, appName, appVersion, "mobile")
    launch_server.upload_files(deployTmp+'packimage/mobile',  '/'+userID+'/'+appName+'/'+appVersion+'/mobile')

Functions

def buildAppPackage(src, dest)
Expand source code
def buildAppPackage(src, dest):
    apputil.makeDirectories(dest)
    list =glob.glob(os.path.join(src,'*' ))
    for dir in list:
        if os.path.isdir(dir):
            outpath = os.path.join(dest,os.path.basename(dir))

            list = findFiles(dir)
            if hashCheck(list, outpath+'.pyxd', 0):
                print("build asset database {}.pyxd".format(outpath))
                compressFolder(dir, outpath)
            else:
                print("skip asset database {}.pyxd".format(outpath))
        else:
            print("copy {}".format(dir))
            shutil.copy2(dir, dest)
def compilePrograms(src, dst)
Expand source code
def compilePrograms(src, dst):
    list = findFiles(src, ['.py'])
    for infile in list:
        outfile = os.path.normpath(infile.replace(src, dst, 1))
        apputil.makeDirectories(outfile)
        if os.path.basename(infile) == 'root.py':
            shutil.copy(infile, outfile)
        else:
            outfile = replaceExt(outfile, '.pyc')
            apputil.makeDirectories(outfile)
            print('compile : '+infile)
            py_compile.compile(infile, outfile)
def compressFolder(...)
def convertAssets(sourceDir, destDir, platform, unit=1.0, rootDir=None)

Convert model and image data to ige format model(.dae) -> .pyxf image(.png .dds .tga .psd ) -> .pyxi

If model data with the same name as the folder name is found, it is regarded as base model data, and other model data in the same folder are regarded as motion files, and all are packed into one file If there is no model data with the same name as the folder name, Each model data as base model data and convert separately

:param sourceDir: source root folder :param destDir: destination root folder :param platform: target platform (core.TARGET_PLATFORM_XX) :param unit: scale unit size of 3d model :return: None

Expand source code
def convertAssets(sourceDir, destDir, platform, unit=1.0, rootDir=None):
    """
    Convert model and image data to ige format
    model(.dae) -> .pyxf
    image(.png .dds .tga .psd ) -> .pyxi

    If model data with the same name as the folder name is found,
    it is regarded as base model data, and other model data in the
    same folder are regarded as motion files, and all are packed
    into one file
    If there is no model data with the same name as the folder name,
    Each model data as base model data and convert separately

    :param sourceDir: source root folder
    :param destDir: destination root folder
    :param platform: target platform (core.TARGET_PLATFORM_XX)
    :param unit: scale unit size of 3d model
    :return: None
    """
    if rootDir is None: rootDir = destDir

    imageList = findImageFiles(sourceDir)
    sceneList = find3DSceneFiles(sourceDir)
    imageDirectoryTree = createDirectoryTree(imageList, sourceDir)
    confTree = createFigureConfTree(sourceDir, unit)
    allTextures = dict()
    tmpfig = core.editableFigure("tmpfigure", True)

    print('----------------------')
    print('Convert 3d scene files')
    print('----------------------')

    for files in sceneList.values():
        tmpfig.clear()
        conf = findFigureConf(files[0], confTree)
        load3DScene(tmpfig, files, conf)

        daepath, _ = os.path.split(files[0])
        setMaterialAlpha(tmpfig, imageDirectoryTree, daepath, sourceDir)
        replaceTexturePath(tmpfig, imageDirectoryTree, daepath, sourceDir, allTextures, removeRoot(destDir,rootDir))

        outfile = os.path.normpath(files[0].replace(sourceDir, destDir, 1))
        outfile = replaceExt(outfile, '.pyxf')

        if hashCheck(files, outfile, platform):
            print("convert {}".format(files[0]))
            apputil.makeDirectories(outfile)

            if 'OPTIMIZE_VERTEX' in conf.keys() and conf['OPTIMIZE_VERTEX']:
                tmpfig.removeUnreferencedVertices()
            if 'OPTIMIZE_MESH' in conf.keys() and conf['OPTIMIZE_MESH']:
                tmpfig.mergeSameMaterialMesh()

            tmpfig.saveFigure(outfile)
        else:
            print("skip {}".format(files[0]))

    for img in imageList:
        if img not in allTextures:
            allTextures[img] = {'path': removeRoot(img,sourceDir), 'normal': False, 'wrap': False}
    convertImages(allTextures, sourceDir, destDir, platform)

    return allTextures
def convertImages(allTextures, sourceDir, destDir, platform)
Expand source code
def convertImages(allTextures, sourceDir, destDir, platform):
    print('----------------------')
    print('Convert image files')
    print('----------------------')
    for key, val in allTextures.items():
        outfile = os.path.normpath(key.replace(sourceDir, destDir, 1))
        outfile = replaceExt(outfile, '.pyxi')
        hashfile = getHashPath('.tmp/hash', key, platform)
        hashcode, newhash = readAndCalcHash(key, outfile, hashfile)
        if hashcode != newhash:
            print("convert {} for {}".format(key,apputil.targetFolderName(platform)))
            apputil.makeDirectories(outfile)
            convertTextureToPlatform(key, outfile, platform, val['normal'], val['wrap'])
            saveHash(hashfile, newhash)
        else:
            print("skip {} ".format(key))
def convertTextureToPlatform(...)
def copyFiles(src, dst, exts=['.*'])
Expand source code
def copyFiles(src, dst, exts=['.*']):
    for root, dirs, files in os.walk(src):
        if isHiddenFolder(root): continue
        for fname in files:
            name, ext = os.path.splitext(fname)
            for e in exts:
                if e == '.*' or ext == e:
                    srcPath = os.path.join(root, fname)
                    dstPath = os.path.join(dst, removeRoot(srcPath, src))
                    apputil.makeDirectories(dstPath)
                    shutil.copy2(srcPath, dstPath)
                    print("copy {}".format(dstPath))
                    break
def createDirectoryTree(filelist, root)
Expand source code
def createDirectoryTree(filelist, root):
    imageDirectory = dict()
    for img in filelist:
        while True:
            img, file = os.path.split(img)
            if img not in imageDirectory:
                imageDirectory[img] = {file: 0};
            elif file not in imageDirectory[img]:
                imageDirectory[img][file] = 0
            if img == root: break
    return imageDirectory
def createFigureConfTree(path, unit=1.0)
Expand source code
def createFigureConfTree(path, unit=1.0):
    path = os.path.abspath(path)
    filelist = []
    for root, dirs, files in os.walk(path):
        if root.find('\.') != -1: continue
        for fname in files:
            if fname == 'figure.conf':
                filelist.append(os.path.join(root, fname))
    figureConfTree = dict()
    for filepath in filelist:
        conf = readFigureConf(filepath)
        dir, file = os.path.split(filepath)
        figureConfTree[dir] = conf

    for dir, val in figureConfTree.items():
        while True:
            dir, _ = os.path.split(dir)
            if dir == os.path.abspath('.').split(os.path.sep)[0]+os.path.sep:
                break
            parent = figureConfTree.get(dir)
            if parent is not None:
                for parentkey, parentval in parent.items():
                    if val.get(parentkey) is None:
                        val[parentkey] = parentval

    if len(figureConfTree) == 0:
        figureConfTree[path] = {}

    for conf in figureConfTree.values():
        if conf.get('BASE_SCALE') is None:
           conf['BASE_SCALE'] = unit
        #if conf.get('OPTIMIZE_MESH') is None:
        #   conf['OPTIMIZE_MESH'] = True

    return figureConfTree
def deploy(projectFolder, userID, appName, appVersion, unit=1.0, assetSource=None, assetDestination=None)
Expand source code
def deploy(projectFolder, userID, appName, appVersion, unit = 1.0, assetSource=None, assetDestination=None):
    if assetSource == None: assetSource = projectFolder
    if assetDestination == None: assetDestination = projectFolder
    allTextures = convertAssets(assetSource, assetDestination, core.TARGET_PLATFORM_PC, unit, projectFolder)

    deployTmp = '.tmp/deploy/'+appName+'/'+appVersion+'/'

    print('----------------------')
    print('Create non pack app image')
    print('----------------------')
    print('--- PC ---')
    copyFiles(projectFolder, deployTmp+'unpackimage/pc', ['.pyxf', '.json', '.pyxa', '.pyxb', '.pickle', '.zip', '.txt', '.db', '.ttf'])
    compilePrograms(projectFolder, deployTmp+'unpackimage/pc')
    convertImages(allTextures, assetSource, os.path.join(deployTmp+'unpackimage/pc',removeRoot(assetDestination, projectFolder)), core.TARGET_PLATFORM_PC)
    print('--- Mobile ---')
    copyFiles(projectFolder, deployTmp+'unpackimage/mobile', ['.pyxf', '.json', '.pyxa', '.pyxb', '.pickle', '.zip', '.txt', '.db', '.ttf'])
    compilePrograms(projectFolder, deployTmp+'unpackimage/mobile')
    convertImages(allTextures, assetSource, os.path.join(deployTmp+'unpackimage/mobile',removeRoot(assetDestination, projectFolder)), core.TARGET_PLATFORM_MOBILE)

    print('----------------------')
    print('Create packed app image')
    print('----------------------')
    print('--- PC ---')
    buildAppPackage(deployTmp+'unpackimage/pc', deployTmp+'packimage/pc')
    print('--- Mobile ---')
    buildAppPackage(deployTmp+'unpackimage/mobile', deployTmp+'packimage/mobile')

    print('----------------------')
    print('Upload app image to the server')
    print('----------------------')
    print('--- PC ---')
    launch_server.makeProjectDir(userID, appName, appVersion, "pc")
    launch_server.upload_files(deployTmp+'packimage/pc', '/'+userID+'/'+appName+'/'+appVersion+'/pc')
    print('--- Mobile ---')
    launch_server.makeProjectDir(userID, appName, appVersion, "mobile")
    launch_server.upload_files(deployTmp+'packimage/mobile',  '/'+userID+'/'+appName+'/'+appVersion+'/mobile')
def find3DSceneFiles(path)
Expand source code
def find3DSceneFiles(path):
    dict = {}
    for root, dirs, files in os.walk(path):
        if root.find('\.') != -1: continue
        folder = os.path.basename(root)

        folderRule = False
        for f in files:
            name, ext = os.path.splitext(f)
            if name == folder:
                folderRule = True
                baseFile = f
                break

        if folderRule:
            daes = [os.path.join(root, baseFile)]
            for f2 in files:
                f2_name, f2_ext = os.path.splitext(f2)
                if (f2_ext.lower() == '.dae' or f2_ext.lower() == '.fbx') and f2_name != folder:
                    daes.append(os.path.join(root, f2))
            dict[folder] = daes
        else:
            for f2 in files:
                f2_name, f2_ext = os.path.splitext(f2)
                if f2_ext.lower() == '.dae' or f2_ext.lower() == '.fbx':
                    dict[f2_name] = [os.path.join(root, f2)]
    return dict
def findConvertReplaceTextures(fig: editableFigure, sourceRoot, destRoot, platform=0, figurePath='')

Find and convert the texture file linked from editableFigure.

:param sourceRoot: Root folder to search for texture files :param destRoot: Root folder to save the textures :param editableFigure: The location where the editableFigure was saved (optional). It must be included under sourceRoot. :param platform: Formats to convert textures to. TARGET_PLATFORM_PC or TARGET_PLATFORM_MOBILE

:return: None

The figurePath must always be under the sourceRoot. The specified folder hierarchy may contain multiple texture files with the same name. When figurePath is specified, the texture file closest to it will be selected.

Example. ・File path saved in editableFigure D:/aaa/bbb/ccc/test.png ・Location of the actual file C:/user/input/images/test.png ・sourceRoot C:/user/input ・destRoot C:/user/output ・The actual output file C:/user/output/images/test.pyxi ・New file path to be saved in editableFigure images/test

Expand source code
def findConvertReplaceTextures(fig : core.editableFigure, sourceRoot, destRoot, platform=core.TARGET_PLATFORM_PC, figurePath=""):
    """
    Find and convert the texture file linked from editableFigure.

    :param sourceRoot: Root folder to search for texture files
    :param destRoot: Root folder to save the textures
    :param editableFigure: The location where the editableFigure was saved (optional). It must be included under sourceRoot.
    :param platform: Formats to convert textures to. TARGET_PLATFORM_PC or TARGET_PLATFORM_MOBILE

    :return: None

    The figurePath must always be under the sourceRoot.
    The specified folder hierarchy may contain multiple texture files with the same name.
    When figurePath is specified, the texture file closest to it will be selected.

    Example.
        ・File path saved in editableFigure
            D:/aaa/bbb/ccc/test.png
        ・Location of the actual file
            C:/user/input/images/test.png
        ・sourceRoot
            C:/user/input
        ・destRoot
            C:/user/output
        ・The actual output file
            C:/user/output/images/test.pyxi
        ・New file path to be saved in editableFigure
            images/test
    """
    sourceRoot = os.path.abspath(sourceRoot).replace('\\', '/')
    destRoot = os.path.abspath(destRoot).replace('\\', '/')

    if figurePath == "":
        daepath = figurePath = sourceRoot
    else:
        figurePath = os.path.abspath(figurePath).replace('\\', '/')
        daepath, _ = os.path.split(figurePath)
        if len(daepath) == 0 : daepath = os.path.abspath(".").replace('\\', '/')


    imageList = findImageFiles(sourceRoot)
    imageDirectoryTree = createDirectoryTree(imageList, sourceRoot)
    setMaterialAlpha(fig, imageDirectoryTree, daepath, sourceRoot)

    allTextures = dict()
    replaceTexturePath(fig, imageDirectoryTree, daepath, sourceRoot, allTextures, removeRoot(destRoot,sourceRoot))
    convertImages(allTextures, sourceRoot, destRoot, platform)
def findFigureConf(dir: str, tree: dict)
Expand source code
def findFigureConf(dir: str, tree: dict):
    dir = os.path.abspath(dir)
    while True:
        dir, _ = os.path.split(dir)
        if dir == os.path.abspath('.').split(os.path.sep)[0]+os.path.sep:
            break
        conf = tree.get(dir)
        if conf is not None:
            return conf
    return dict()
def findFileFromDiorectoryTree(imageDirectory, file, dir)
Expand source code
def findFileFromDiorectoryTree(imageDirectory, file, dir):
    files = imageDirectory.get(dir)
    if files is None: return None
    if file in files:
        return os.path.join(dir, file)
    for d in files:
        _, ext = os.path.splitext(d)
        if ext == '':
            rv = findFileFromDiorectoryTree(imageDirectory, file, os.path.join(dir, d))
            if rv: return rv
    return None
def findFiles(path, exts=['.*'])
Expand source code
def findFiles(path, exts = ['.*']):
    list = []
    for root, dirs, files in os.walk(path):
        if isHiddenFolder(root): continue
        for fname in files:
            name, ext = os.path.splitext(fname)
            for e in exts:
                if e == '.*' or e == ext:
                    list.append(os.path.join(root, fname))
                    break
    return list
def findImageFiles(path)
Expand source code
def findImageFiles(path):
    list = []
    for root, dirs, files in os.walk(path):
        if isHiddenFolder(root): continue
        for fname in files:
            name, ext = os.path.splitext(fname)
            extl = ext.lower()
            if extl == '.png' or extl == '.dds' or extl == '.tga' or extl == '.psd' or extl == '.jpg':
                list.append(os.path.join(root, fname))
    return list
def getHashPath(root, source, platform)
Expand source code
def getHashPath(root, source, platform):
    abspath = os.path.abspath(source)
    if abspath[0]=='/' or abspath[0]=='\\':
       abspath = abspath[1:]
    elif abspath[2]=='\\':
        abspath = abspath[3:]
    return os.path.join(os.path.join(root, apputil.targetFolderName(platform)), abspath)
def hashCheck(files, outfile, platform)
Expand source code
def hashCheck(files, outfile, platform):
    changed = False
    for file in files:
        hashfile = getHashPath('.tmp/hash', file, platform)
        hashcode, newhash = readAndCalcHash(file, outfile, hashfile)
        if hashcode != newhash:
            changed = True
            saveHash(hashfile, newhash)
    return changed
def isAlpha(...)
def isHiddenFolder(path)
Expand source code
def isHiddenFolder(path):
    if path.find('/.') != -1 or path.find('\\.') != -1 :
        return True
    return False
def load3DScene(tmpfig, files, conf)
Expand source code
def load3DScene(tmpfig, files, conf):
    loadModel(files[0], tmpfig, conf)
    for i in range(1, len(files)):
        loadAnimation(files[i], tmpfig, conf)
def loadAnimation(...)

Import 3D animation scene to editableFigure

igeTools.loadAnimation(filePath, editableFigure, options)

Parameters

filePath : string
    dae or fbx file path to read
editableFigure : igeCore.editableFigure
    The editableFigure object to which the Collada file is read
options : dict
    Various options to specify when converting data 
        {BASE_SCALE:1.0,    
         EXPORT_NAMES:1,    
         TRIANGLE_STRIP:1,  
         INHERIT_JOINT_NAME:1,      
         CLOP_JOINT:1,      
         GEN_MIPMAP:1,      
         KILL_MIPMAP:1,     
         FREEZE_GEOMETORY:1,        
         COMPUTE_PERIOD:1}
def loadCollada(...)

Load collada file to editableFigure

igeTools.loadCollada(filePath, editableFigure, options)

Parameters

filePath : string
    collada file path to read
editableFigure : igeCore.editableFigure
    The editableFigure object to which the Collada file is read
options : dict
    Various options to specify when converting data 
        {BASE_SCALE:1.0,    
         EXPORT_NAMES:1,    
         TRIANGLE_STRIP:1,  
         INHERIT_JOINT_NAME:1,      
         CLOP_JOINT:1,      
         GEN_MIPMAP:1,      
         KILL_MIPMAP:1,     
         FREEZE_GEOMETORY:1,        
         COMPUTE_PERIOD:1}
def loadColladaAnimation(...)
def loadModel(...)

Import 3D model scene to editableFigure

igeTools.loadModel(filePath, editableFigure, options)

Parameters

filePath : string
    dae or fbx file path to read
editableFigure : igeCore.editableFigure
    The editableFigure object to which the Collada file is read
options : dict
    Various options to specify when converting data 
        {BASE_SCALE:1.0,    
         EXPORT_NAMES:1,    
         TRIANGLE_STRIP:1,  
         INHERIT_JOINT_NAME:1,      
         CLOP_JOINT:1,      
         GEN_MIPMAP:1,      
         KILL_MIPMAP:1,     
         FREEZE_GEOMETORY:1,        
         COMPUTE_PERIOD:1}
def readAndCalcHash(srcfile, dstfile, hashfile)
Expand source code
def readAndCalcHash(srcfile, dstfile, hashfile):
    hashcode = '00000000000000000000000000000000'
    newhash  = 'ffffffffffffffffffffffffffffffff'
    if os.path.exists(dstfile):
        try:
            with open(hashfile, 'r') as f:
                hashcode = f.read()
        except : None

    with open(srcfile, 'rb') as f:
        fileDataBinary = f.read()
        if len(fileDataBinary) != 0:
            hash = hashlib.md5()
            hash.update(fileDataBinary)
            newhash = hash.hexdigest()
    return hashcode,newhash
def readFigureConf(path)
Expand source code
def readFigureConf(path):
    mode = 0
    label = ''
    keyvalue = {}
    with open(path, 'rb') as f:
        for token in tokenize.tokenize(f.readline):
            if token.type is tokenize.ENDMARKER:
                break
            elif token.type is tokenize.NAME:
                if mode == 0:
                    label = token.string
                else:
                    keyvalue[label] = token.string
                    mode = 0
            elif token.type is tokenize.OP:
                mode = 1
            elif token.type is tokenize.NUMBER:
                if mode == 1:
                    try:
                        keyvalue[label] = int(token.string)
                    except ValueError:
                        keyvalue[label] = float(token.string)
                    mode = 0
    return keyvalue
def removeRoot(path, root)
Expand source code
def removeRoot(path, root):
    newpath = path.replace(root, '', 1)
    if len(newpath) >0:
        if newpath[0] == '/' or newpath[0] == '\\':
            newpath = newpath[1:]
    else:
        newpath = ""
    return newpath
def replaceExt(file, ext)
Expand source code
def replaceExt(file, ext):
    name, extold = os.path.splitext(file)
    return name + ext
def replaceTexturePath(tmpfig, imageDirectory, startPath, endPath, allTextures, subFolder)
Expand source code
def replaceTexturePath(tmpfig, imageDirectory, startPath, endPath, allTextures, subFolder):
    texs = tmpfig.getTextureSource()
    for tex in texs:
        filename = os.path.basename(tex['path'])
        current = startPath
        inputimage = None
        while True:
            inputimage = findFileFromDiorectoryTree(imageDirectory, filename, current)
            if inputimage is not None: break
            if current == endPath: break
            current, _ = os.path.split(current)
        if inputimage is None:
            print('file not found ' + tex['path'])
        else:
            allTextures[inputimage] = tex;
            inputimage = removeRoot(inputimage, endPath);
            inputimage, ext = os.path.splitext(inputimage)
            inputimage = os.path.join(subFolder, inputimage)
            inputimage = inputimage.replace('\\', '/')
            newTex = {'path': inputimage, 'normal': tex['normal'], 'wrap': tex['wrap']}
            tmpfig.replaceTextureSource(tex, newTex)
def saveHash(hashfile, newhash)
Expand source code
def saveHash(hashfile, newhash):
    if newhash != 'ffffffffffffffffffffffffffffffff':
        apputil.makeDirectories(hashfile)
        with open(hashfile, 'w') as f:
            f.write(newhash)
def setMaterialAlpha(tmpfig, imageDirectory, startPath, endPath)
Expand source code
def setMaterialAlpha(tmpfig, imageDirectory, startPath, endPath):
    texs = tmpfig.getTextureSource()
    for tex in texs:
        filename = os.path.basename(tex['path'])
        current = startPath
        inputimage = None
        while True:
            inputimage = findFileFromDiorectoryTree(imageDirectory, filename, current)
            if inputimage is not None: break
            if current == endPath: break
            current, _ = os.path.split(current)
        if inputimage is not None:
            if isAlpha(inputimage):
                tmpfig.enableAlphaModeByTexture(tex['path'])