[Bf-extensions-cvs] SVN commit: /data/svn/bf-extensions [3049] contrib/py/scripts/addons/ io_export_marmalade.py: Marmalade Exporter, initial version in Contrib

Campbell Barton ideasman42 at gmail.com
Fri Mar 2 14:46:49 CET 2012


Hi Benoit, great to see your script in contrib - had a quick look over
it and some suggestions.

---
Rather then relying on "convert.exe" - blender could do the
conversion, you can load, save and free and image, would be nice one
to add to bpy_extras.image_utils module.
- will make the script more portable too since it looks like the
script assumes windows at the moment.


---
Notice you transform the mesh multiple times:
                Mesh.transform(Object.matrix_world)
                Mesh.transform(SCALE_MAT)
                Mesh.transform(X_ROT)

Better multiply the mat's together and transform once.

---

For classes with many instances - CGeoIndexList, CGeoPoly - suggest
using __slots__ to save some memory. (also I find this better practice
and prevents assigning invalid values).

---
if len(self.vnList) > 0:
 can be:
if self.vnList:
---

        matList = list()
        for matName in self.MaterialsDict.keys():
            matList.append(matName)
        return matList

can be
   return list(self.MaterialsDict.keys())
---
Looks like a typo in GetMaterialByName :
            return none

----

lines over 200 length in WriteMeshPoly() could be broken up, just
style preference.

---

(MatSpecularColor[0] * 255, MatSpecularColor[1] * 255,
MatSpecularColor[2] * 255)

can be...
(MatSpecularColor * 255)[:]

---

Large multiline comments in WriteKeyedAnimationSet(), nicer to use """
"""'s (again personal preference).

---

in WriteKeyedAnimationSet - better to store scene as a var rather then
access as bpy.context.scene.

---
                # Exports all frames
                for i in
range(bpy.context.scene.frame_start,bpy.context.scene.frame_end + 1,
1):
                    keyframeTimes.add(i)

Can be...

keyframeTimes.update(range(scene.frame_start, scene.frame_end + 1, 1))

---

when calling MarmaladeExporterSettings() looks like you could use
operator method:

  self.as_keywords()
... since theres a 1:1 mapping from settings to keyword args.

---

Regards

- Campbell

On Fri, Mar 2, 2012 at 6:39 PM, Benoit Muller <benoit.muller at laposte.net> wrote:
> Revision: 3049
>          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-extensions&revision=3049
> Author:   benoitmuller
> Date:     2012-03-02 07:38:55 +0000 (Fri, 02 Mar 2012)
> Log Message:
> -----------
> Marmalade Exporter, initial version in Contrib
> Allows to export animated characters and Scene For Marmalade SDK.
> Marmalade allows to build IPhone, Android, BlackBerry, Badda Applications/Games in C++.
>
> Added Paths:
> -----------
>    contrib/py/scripts/addons/io_export_marmalade.py
>
> Added: contrib/py/scripts/addons/io_export_marmalade.py
> ===================================================================
> --- contrib/py/scripts/addons/io_export_marmalade.py                            (rev 0)
> +++ contrib/py/scripts/addons/io_export_marmalade.py    2012-03-02 07:38:55 UTC (rev 3049)
> @@ -0,0 +1,1733 @@
> +# ***** GPL LICENSE BLOCK *****
> +#
> +# This program is free software: you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License as published by
> +# the Free Software Foundation, either version 3 of the License, or
> +# (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program.  If not, see <http://www.gnu.org/licenses/>.
> +# All rights reserved.
> +# ***** GPL LICENSE BLOCK *****
> +
> +# Marmalade SDK is not responsible in any case of the following code.
> +# This Blender add-on is freely shared for the Blender and Marmalade user communities.
> +
> +
> +bl_info = {
> +    "name": "Marmalade Cross-platform Apps (.group)",
> +    "author": "Benoit Muller",
> +    "version": (0, 5, 0),
> +    "blender": (2, 6, 0),
> +    "api": 37702,
> +    "location": "File > Export > Marmalade cross-platform Apps (.group)",
> +    "description": "Export Marmalade Format files (.group)",
> +    "warning": "",
> +    "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.6/Py/"\
> +        "Scripts/Import-Export/Marmalade_Exporter",
> +    "tracker_url": "https://projects.blender.org/tracker/index.php?"\
> +        "",
> +    "category": "Import-Export"}
> +
> +import os
> +import shutil
> +from math import radians
> +
> +import bpy
> +from mathutils import Matrix
> +
> +import mathutils
> +import math
> +
> +import datetime
> +
> +import subprocess
> +
> +
> +#Container for the exporter settings
> +class MarmaladeExporterSettings:
> +
> +    def __init__(self,
> +                 context,
> +                 FilePath,
> +                 Optimized=True,
> +                 CoordinateSystem=1,
> +                 FlipNormals=False,
> +                 ApplyModifiers=False,
> +                 Scale=100,
> +                 AnimFPS=30,
> +                 ExportVertexColors=True,
> +                 ExportMaterialColors=True,
> +                 ExportTextures=True,
> +                 CopyTextureFiles=True,
> +                 ExportArmatures=False,
> +                 ExportAnimation=0,
> +                 ExportMode=1,
> +                 MergeModes=0,
> +                 Verbose=False):
> +        self.context = context
> +        self.FilePath = FilePath
> +        self.Optimized = Optimized
> +        self.CoordinateSystem = int(CoordinateSystem)
> +        self.FlipNormals = FlipNormals
> +        self.ApplyModifiers = ApplyModifiers
> +        self.Scale = Scale
> +        self.AnimFPS = AnimFPS
> +        self.ExportVertexColors = ExportVertexColors
> +        self.ExportMaterialColors = ExportMaterialColors
> +        self.ExportTextures = ExportTextures
> +        self.CopyTextureFiles = CopyTextureFiles
> +        self.ExportArmatures = ExportArmatures
> +        self.ExportAnimation = int(ExportAnimation)
> +        self.ExportMode = int(ExportMode)
> +        self.MergeModes = int(MergeModes)
> +        self.Verbose = Verbose
> +        self.WarningList = list()
> +
> +
> +def ExportMadeWithMarmaladeGroup(Config):
> +    print("----------\nExporting to {}".format(Config.FilePath))
> +    if Config.Verbose:
> +        print("Opening File...")
> +    Config.File = open(Config.FilePath, "w")
> +
> +    if Config.Verbose:
> +        print("Done")
> +
> +    if Config.MergeModes > 0:
> +        # Merge mode only work with Optimised setting
> +        Config.Optimized = True
> +
> +    if Config.Verbose:
> +        print("writing group header")
> +
> +    Config.File.write('// Marmalade group file exported from : %s\n' % bpy.data.filepath)
> +    Config.File.write('// Exported %s\n' % str(datetime.datetime.now()))
> +    Config.File.write("CIwResGroup\n{\n\tname \"%s\"\n" % bpy.path.display_name_from_filepath(Config.FilePath))
> +
> +    if Config.Verbose:
> +        print("Generating Object list for export... (Root parents only)")
> +    if Config.ExportMode == 1:
> +        Config.ExportList = [Object for Object in Config.context.scene.objects
> +                             if Object.type in {'ARMATURE', 'EMPTY', 'MESH'}
> +                             and Object.parent is None]
> +    else:
> +        ExportList = [Object for Object in Config.context.selected_objects
> +                      if Object.type in {'ARMATURE', 'EMPTY', 'MESH'}]
> +        Config.ExportList = [Object for Object in ExportList
> +                             if Object.parent not in ExportList]
> +    if Config.Verbose:
> +        print("  List: {}\nDone".format(Config.ExportList))
> +
> +    if Config.Verbose:
> +        print("Setting up...")
> +
> +    if Config.ExportAnimation:
> +        if Config.Verbose:
> +            print(bpy.context.scene)
> +            print(bpy.context.scene.frame_current)
> +        CurrentFrame = bpy.context.scene.frame_current
> +        #comment because it crashes Blender on some old blend file: bpy.context.scene.frame_current = bpy.context.scene.frame_current
> +    if Config.Verbose:
> +        print("Done")
> +
> +    Config.ObjectList = []
> +    if Config.Verbose:
> +        print("Writing Objects...")
> +    WriteObjects(Config, Config.ExportList)
> +    if Config.Verbose:
> +        print("Done")
> +
> +    if Config.Verbose:
> +        print("Objects Exported: {}".format(Config.ExportList))
> +
> +    if Config.ExportAnimation:
> +        if Config.Verbose:
> +            print("Writing Animation...")
> +        WriteKeyedAnimationSet(Config)
> +        bpy.context.scene.frame_current = CurrentFrame
> +        if Config.Verbose:
> +            print("Done")
> +    Config.File.write("}\n")
> +    CloseFile(Config)
> +    print("Finished")
> +
> +
> +def GetObjectChildren(Parent):
> +    return [Object for Object in Parent.children
> +            if Object.type in {'ARMATURE', 'EMPTY', 'MESH'}]
> +
> +
> +#Returns the vertex count of Mesh in not optimized version, counting each vertex for every face.
> +def GetNonOptimizedMeshVertexCount(Mesh):
> +    VertexCount = 0
> +    for Face in Mesh.faces:
> +        VertexCount += len(Face.vertices)
> +    return VertexCount
> +
> +
> +#Returns the file path of first image texture from Material.
> +def GetMaterialTextureFullPath(Config, Material):
> +    if Material:
> +        #Create a list of Textures that have type "IMAGE"
> +        ImageTextures = [Material.texture_slots[TextureSlot].texture for TextureSlot in Material.texture_slots.keys() if Material.texture_slots[TextureSlot].texture.type == "IMAGE"]
> +        #Refine a new list with only image textures that have a file source
> +        TexImages = [Texture.image for Texture in ImageTextures if getattr(Texture.image, "source", "") == "FILE"]
> +        ImageFiles = [Texture.image.filepath for Texture in ImageTextures if getattr(Texture.image, "source", "") == "FILE"]
> +        if TexImages:
> +            filepath = TexImages[0].filepath
> +            if TexImages[0].packed_file:
> +                TexImages[0].unpack()
> +            if not os.path.exists(filepath):
> +                #try relative path to the blend file
> +                filepath = os.path.dirname(bpy.data.filepath) + filepath
> +            #Marmalade doesn't like jpeg/tif so try to convert in png on the fly
> +            if (TexImages[0].file_format == 'JPEG' or TexImages[0].file_format == 'TIFF') and os.path.exists(filepath):
> +                marmaladeConvert = os.path.expandvars("%S3E_DIR%\\..\\tools\\ImageMagick\\win32\\convert.exe")
> +                if (os.path.exists(marmaladeConvert)):
> +                    srcImagefilepath = filepath
> +                    filepath = os.path.splitext(filepath)[0] + '.png'
> +                    if Config.Verbose:
> +                        print("  /!\\ Converting Texture %s in PNG: %s{}..." % (TexImages[0].file_format, filepath))
> +                        print('"%s" "%s" "%s"' % (marmaladeConvert, srcImagefilepath, filepath))
> +                    subprocess.call([marmaladeConvert, srcImagefilepath, filepath])
> +            return filepath
> +    return None
> +
> +
> +def WriteObjects(Config, ObjectList, geoFile=None, mtlFile=None, GeoModel=None,  bChildObjects=False):
> +    Config.ObjectList += ObjectList
> +
> +    if bChildObjects == False and Config.MergeModes > 0:
> +        if geoFile == None:
> +            #we merge objects, so use name of group file for the name of Geo
> +            geoFile, mtlFile = CreateGeoMtlFiles(Config, bpy.path.display_name_from_filepath(Config.FilePath))
> +            GeoModel = CGeoModel(bpy.path.display_name_from_filepath(Config.FilePath))
> +
> +    for Object in ObjectList:
> +        if Config.Verbose:
> +            print("  Writing Object: {}...".format(Object.name))
> +
> +        if Config.ExportArmatures and Object.type == "ARMATURE":
> +            Armature = Object.data
> +            ParentList = [Bone for Bone in Armature.bones if Bone.parent is None]
> +            if Config.Verbose:
> +                print("    Writing Armature Bones...")
> +            #Create the skel file
> +            skelfullname = os.path.dirname(Config.FilePath) + "\models\%s.skel" % (StripName(Object.name))
> +            ensure_dir(skelfullname)
> +            if Config.Verbose:
> +                print("      Creating skel file %s" % (skelfullname))
> +
> +            skelFile = open(skelfullname, "w")
> +            skelFile.write('// skel file exported from : %r\n' % os.path.basename(bpy.data.filepath))
> +            skelFile.write("CIwAnimSkel\n")
> +            skelFile.write("{\n")
> +            skelFile.write("\tnumBones %d\n" % (len(Armature.bones)))
> +            Config.File.write("\t\".\models\%s.skel\"\n" % (StripName(Object.name)))
> +
> +            WriteArmatureParentRootBones(Config, Object, ParentList, skelFile)
> +
> +            skelFile.write("}\n")
> +            skelFile.close()
> +            if Config.Verbose:
> +                print("    Done")
> +
> +        ChildList = GetObjectChildren(Object)
> +        if Config.ExportMode == 2:  # Selected Objects Only
> +            ChildList = [Child for Child in ChildList
> +                         if Child in Config.context.selected_objects]
> +        if Config.Verbose:
> +            print("    Writing Children...")
> +        WriteObjects(Config, ChildList, geoFile, mtlFile, GeoModel, True)
>
> @@ Diff output truncated at 10240 characters. @@
> _______________________________________________
> Bf-extensions-cvs mailing list
> Bf-extensions-cvs at blender.org
> http://lists.blender.org/mailman/listinfo/bf-extensions-cvs



-- 
- Campbell


More information about the Bf-extensions-cvs mailing list