- add model import via blender - add support dor 3ds, dae to SDK git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@10237 75d07b2b-3a1a-0410-a2c5-0572b91ccdca3.0
parent
f158717981
commit
74eccc7c8f
@ -0,0 +1,91 @@ |
||||
/* |
||||
* To change this template, choose Tools | Templates |
||||
* and open the template in the editor. |
||||
*/ |
||||
package com.jme3.gde.blender.filetypes; |
||||
|
||||
import com.jme3.gde.blender.BlenderTool; |
||||
import com.jme3.gde.core.assets.ProjectAssetManager; |
||||
import com.jme3.gde.core.assets.SpatialAssetDataObject; |
||||
import com.jme3.scene.Spatial; |
||||
import java.io.IOException; |
||||
import java.util.ArrayList; |
||||
import java.util.Iterator; |
||||
import java.util.List; |
||||
import java.util.logging.Level; |
||||
import org.openide.DialogDisplayer; |
||||
import org.openide.NotifyDescriptor; |
||||
import org.openide.filesystems.FileLock; |
||||
import org.openide.filesystems.FileObject; |
||||
import org.openide.filesystems.FileUtil; |
||||
import org.openide.loaders.DataObjectExistsException; |
||||
import org.openide.loaders.MultiFileLoader; |
||||
import org.openide.util.Exceptions; |
||||
|
||||
/** |
||||
* |
||||
* @author normenhansen |
||||
*/ |
||||
public abstract class AbstractBlenderAssetDataObject extends SpatialAssetDataObject { |
||||
|
||||
protected String SUFFIX; |
||||
|
||||
public AbstractBlenderAssetDataObject(FileObject pf, MultiFileLoader loader) throws DataObjectExistsException, IOException { |
||||
super(pf, loader); |
||||
} |
||||
|
||||
@Override |
||||
public Spatial loadAsset() { |
||||
if (SUFFIX == null) { |
||||
throw new IllegalStateException("Suffix for blender filetype is null! Set SUFFIX = \"sfx\" in constructor!"); |
||||
} |
||||
ProjectAssetManager mgr = getLookup().lookup(ProjectAssetManager.class); |
||||
if (mgr == null) { |
||||
DialogDisplayer.getDefault().notifyLater(new NotifyDescriptor.Message("File is not part of a project!\nCannot load without ProjectAssetManager.")); |
||||
return null; |
||||
} |
||||
FileObject mainFile = getPrimaryFile(); |
||||
BlenderTool.runConversionScript(SUFFIX, mainFile); |
||||
FileObject outFile = FileUtil.findBrother(mainFile, BlenderTool.TEMP_SUFFIX); |
||||
if (outFile == null) { |
||||
logger.log(Level.SEVERE, "Failed to create model, blend file cannot be found"); |
||||
return null; |
||||
} |
||||
String assetKey = mgr.getRelativeAssetPath(outFile.getPath()); |
||||
FileLock lock = null; |
||||
try { |
||||
lock = getPrimaryFile().lock(); |
||||
listListener.start(); |
||||
Spatial spatial = mgr.loadModel(assetKey); |
||||
replaceFiles(); |
||||
listListener.stop(); |
||||
savable = spatial; |
||||
return spatial; |
||||
} catch (IOException ex) { |
||||
Exceptions.printStackTrace(ex); |
||||
} finally { |
||||
if (lock != null) { |
||||
lock.releaseLock(); |
||||
} |
||||
try { |
||||
outFile.delete(); |
||||
} catch (IOException ex) { |
||||
Exceptions.printStackTrace(ex); |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
protected void replaceFiles() { |
||||
for (int i = 0; i < assetList.size(); i++) { |
||||
FileObject fileObject = assetList.get(i); |
||||
if (fileObject.hasExt(BlenderTool.TEMP_SUFFIX)) { |
||||
assetList.remove(i); |
||||
assetKeyList.remove(i); |
||||
assetList.add(i, getPrimaryFile()); |
||||
assetKeyList.add(getAssetKey()); |
||||
return; |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,89 @@ |
||||
/* |
||||
* To change this template, choose Tools | Templates |
||||
* and open the template in the editor. |
||||
*/ |
||||
package com.jme3.gde.blender.filetypes; |
||||
|
||||
import com.jme3.gde.core.assets.SpatialAssetDataObject; |
||||
import java.io.IOException; |
||||
import org.openide.awt.ActionID; |
||||
import org.openide.awt.ActionReference; |
||||
import org.openide.awt.ActionReferences; |
||||
import org.openide.filesystems.FileObject; |
||||
import org.openide.filesystems.MIMEResolver; |
||||
import org.openide.loaders.DataObject; |
||||
import org.openide.loaders.DataObjectExistsException; |
||||
import org.openide.loaders.MultiFileLoader; |
||||
import org.openide.util.NbBundle.Messages; |
||||
|
||||
@Messages({ |
||||
"LBL_Blender3ds_LOADER=3DS Files (via Blender)" |
||||
}) |
||||
@MIMEResolver.ExtensionRegistration( |
||||
displayName = "#LBL_Blender3ds_LOADER", |
||||
mimeType = "application/x-3ds", |
||||
extension = {"3ds", "3DS"}) |
||||
@DataObject.Registration( |
||||
mimeType = "application/x-3ds", |
||||
iconBase = "com/jme3/gde/blender/blender.png", |
||||
displayName = "#LBL_Blender3ds_LOADER", |
||||
position = 300) |
||||
@ActionReferences({ |
||||
@ActionReference( |
||||
path = "Loaders/application/x-3ds/Actions", |
||||
id = |
||||
@ActionID(category = "System", id = "org.openide.actions.OpenAction"), |
||||
position = 100, |
||||
separatorAfter = 200), |
||||
@ActionReference( |
||||
path = "Loaders/application/x-3ds/Actions", |
||||
id = |
||||
@ActionID(category = "Edit", id = "org.openide.actions.CutAction"), |
||||
position = 300), |
||||
@ActionReference( |
||||
path = "Loaders/application/x-3ds/Actions", |
||||
id = |
||||
@ActionID(category = "Edit", id = "org.openide.actions.CopyAction"), |
||||
position = 400, |
||||
separatorAfter = 500), |
||||
@ActionReference( |
||||
path = "Loaders/application/x-3ds/Actions", |
||||
id = |
||||
@ActionID(category = "Edit", id = "org.openide.actions.DeleteAction"), |
||||
position = 600), |
||||
@ActionReference( |
||||
path = "Loaders/application/x-3ds/Actions", |
||||
id = |
||||
@ActionID(category = "System", id = "org.openide.actions.RenameAction"), |
||||
position = 700, |
||||
separatorAfter = 800), |
||||
@ActionReference( |
||||
path = "Loaders/application/x-3ds/Actions", |
||||
id = |
||||
@ActionID(category = "System", id = "org.openide.actions.SaveAsTemplateAction"), |
||||
position = 900, |
||||
separatorAfter = 1000), |
||||
@ActionReference( |
||||
path = "Loaders/application/x-3ds/Actions", |
||||
id = |
||||
@ActionID(category = "System", id = "org.openide.actions.FileSystemAction"), |
||||
position = 1100, |
||||
separatorAfter = 1200), |
||||
@ActionReference( |
||||
path = "Loaders/application/x-3ds/Actions", |
||||
id = |
||||
@ActionID(category = "System", id = "org.openide.actions.ToolsAction"), |
||||
position = 1300), |
||||
@ActionReference( |
||||
path = "Loaders/application/x-3ds/Actions", |
||||
id = |
||||
@ActionID(category = "System", id = "org.openide.actions.PropertiesAction"), |
||||
position = 1400) |
||||
}) |
||||
public class Blender3dsDataObject extends AbstractBlenderAssetDataObject { |
||||
|
||||
public Blender3dsDataObject(FileObject pf, MultiFileLoader loader) throws DataObjectExistsException, IOException { |
||||
super(pf, loader); |
||||
SUFFIX = "3ds"; |
||||
} |
||||
} |
@ -0,0 +1,92 @@ |
||||
/* |
||||
* To change this template, choose Tools | Templates |
||||
* and open the template in the editor. |
||||
*/ |
||||
package com.jme3.gde.blender.filetypes; |
||||
|
||||
import java.io.IOException; |
||||
import org.openide.awt.ActionID; |
||||
import org.openide.awt.ActionReference; |
||||
import org.openide.awt.ActionReferences; |
||||
import org.openide.filesystems.FileObject; |
||||
import org.openide.filesystems.MIMEResolver; |
||||
import org.openide.loaders.DataObject; |
||||
import org.openide.loaders.DataObjectExistsException; |
||||
import org.openide.loaders.MultiFileLoader; |
||||
import org.openide.util.NbBundle.Messages; |
||||
|
||||
/** |
||||
* |
||||
* @author normenhansen |
||||
*/ |
||||
@Messages({ |
||||
"LBL_BlenderDae_LOADER=Collada Files (via Blender)" |
||||
}) |
||||
@MIMEResolver.ExtensionRegistration( |
||||
displayName = "#LBL_BlenderDae_LOADER", |
||||
mimeType = "model/vnd.collada+xml", |
||||
extension = {"dae", "DAE"}) |
||||
@DataObject.Registration( |
||||
mimeType = "model/vnd.collada+xml", |
||||
iconBase = "com/jme3/gde/blender/blender.png", |
||||
displayName = "#LBL_BlenderDae_LOADER", |
||||
position = 300) |
||||
@ActionReferences({ |
||||
@ActionReference( |
||||
path = "Loaders/model/vnd.collada+xml/Actions", |
||||
id = |
||||
@ActionID(category = "System", id = "org.openide.actions.OpenAction"), |
||||
position = 100, |
||||
separatorAfter = 200), |
||||
@ActionReference( |
||||
path = "Loaders/model/vnd.collada+xml/Actions", |
||||
id = |
||||
@ActionID(category = "Edit", id = "org.openide.actions.CutAction"), |
||||
position = 300), |
||||
@ActionReference( |
||||
path = "Loaders/model/vnd.collada+xml/Actions", |
||||
id = |
||||
@ActionID(category = "Edit", id = "org.openide.actions.CopyAction"), |
||||
position = 400, |
||||
separatorAfter = 500), |
||||
@ActionReference( |
||||
path = "Loaders/model/vnd.collada+xml/Actions", |
||||
id = |
||||
@ActionID(category = "Edit", id = "org.openide.actions.DeleteAction"), |
||||
position = 600), |
||||
@ActionReference( |
||||
path = "Loaders/model/vnd.collada+xml/Actions", |
||||
id = |
||||
@ActionID(category = "System", id = "org.openide.actions.RenameAction"), |
||||
position = 700, |
||||
separatorAfter = 800), |
||||
@ActionReference( |
||||
path = "Loaders/model/vnd.collada+xml/Actions", |
||||
id = |
||||
@ActionID(category = "System", id = "org.openide.actions.SaveAsTemplateAction"), |
||||
position = 900, |
||||
separatorAfter = 1000), |
||||
@ActionReference( |
||||
path = "Loaders/model/vnd.collada+xml/Actions", |
||||
id = |
||||
@ActionID(category = "System", id = "org.openide.actions.FileSystemAction"), |
||||
position = 1100, |
||||
separatorAfter = 1200), |
||||
@ActionReference( |
||||
path = "Loaders/model/vnd.collada+xml/Actions", |
||||
id = |
||||
@ActionID(category = "System", id = "org.openide.actions.ToolsAction"), |
||||
position = 1300), |
||||
@ActionReference( |
||||
path = "Loaders/model/vnd.collada+xml/Actions", |
||||
id = |
||||
@ActionID(category = "System", id = "org.openide.actions.PropertiesAction"), |
||||
position = 1400) |
||||
}) |
||||
public class BlenderDaeDataObject extends AbstractBlenderAssetDataObject { |
||||
|
||||
public BlenderDaeDataObject(FileObject pf, MultiFileLoader loader) throws DataObjectExistsException, IOException { |
||||
super(pf, loader); |
||||
SUFFIX = "dae"; |
||||
} |
||||
} |
@ -0,0 +1,64 @@ |
||||
/* |
||||
* To change this template, choose Tools | Templates |
||||
* and open the template in the editor. |
||||
*/ |
||||
package com.jme3.gde.blender.scripts; |
||||
|
||||
import java.io.IOException; |
||||
import java.io.InputStream; |
||||
import java.io.OutputStream; |
||||
import java.net.URL; |
||||
import java.util.logging.Level; |
||||
import java.util.logging.Logger; |
||||
import org.openide.filesystems.FileObject; |
||||
import org.openide.filesystems.FileUtil; |
||||
import org.openide.util.Exceptions; |
||||
|
||||
/** |
||||
* |
||||
* @author normenhansen |
||||
*/ |
||||
public class Scripts { |
||||
|
||||
private static final Logger logger = Logger.getLogger(Scripts.class.getName()); |
||||
private final static String root = "com/jme3/gde/blender/scripts/"; |
||||
|
||||
public static void copyToFolder(FileObject folder) { |
||||
if (folder == null) { |
||||
logger.log(Level.WARNING, "Got null folder for scripts check"); |
||||
return; |
||||
} |
||||
checkScript(folder, "import_3ds.py"); |
||||
checkScript(folder, "import_dae.py"); |
||||
} |
||||
|
||||
private static void checkScript(FileObject folder, String name) { |
||||
FileObject file = folder.getFileObject(name); |
||||
//TODO:check version!
|
||||
if (file == null) { |
||||
try { |
||||
InputStream in = null; |
||||
OutputStream out = null; |
||||
try { |
||||
URL url = new URL("nbres:" + root + name); |
||||
file = FileUtil.createData(folder, name); |
||||
in = url.openStream(); |
||||
out = file.getOutputStream(); |
||||
FileUtil.copy(in, out); |
||||
} catch (IOException e) { |
||||
Exceptions.printStackTrace(e); |
||||
} finally { |
||||
if (in != null) { |
||||
in.close(); |
||||
} |
||||
if (out != null) { |
||||
out.close(); |
||||
} |
||||
} |
||||
logger.log(Level.INFO, "Extracted script {0}", file.getPath()); |
||||
} catch (IOException ex) { |
||||
Exceptions.printStackTrace(ex); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,86 @@ |
||||
# This script is an example of how you can run blender from the command line |
||||
# (in background mode with no interface) to automate tasks, in this example it |
||||
# creates a text object, camera and light, then renders and/or saves it. |
||||
# This example also shows how you can parse command line options to scripts. |
||||
# |
||||
# Example usage for this test. |
||||
# blender --background --factory-startup --python $HOME/background_job.py -- \ |
||||
# --text="Hello World" \ |
||||
# --render="/tmp/hello" \ |
||||
# --save="/tmp/hello.blend" |
||||
# |
||||
# Notice: |
||||
# '--factory-startup' is used to avoid the user default settings from |
||||
# interfearing with automated scene generation. |
||||
# |
||||
# '--' causes blender to ignore all following arguments so python can use them. |
||||
# |
||||
# See blender --help for details. |
||||
|
||||
import bpy |
||||
|
||||
|
||||
def convert_file(file_path, save_path): |
||||
bpy.ops.import_scene.autodesk_3ds(filepath = file_path) |
||||
|
||||
scene = bpy.context.scene |
||||
|
||||
try: |
||||
f = open(save_path, 'w') |
||||
f.close() |
||||
ok = True |
||||
except: |
||||
print("Cannot save to path %r" % save_path) |
||||
|
||||
import traceback |
||||
traceback.print_exc() |
||||
|
||||
if ok: |
||||
bpy.ops.wm.save_as_mainfile(filepath=save_path) |
||||
|
||||
def main(): |
||||
import sys # to get command line args |
||||
import argparse # to parse options for us and print a nice help message |
||||
|
||||
# get the args passed to blender after "--", all of which are ignored by |
||||
# blender so scripts may receive their own arguments |
||||
argv = sys.argv |
||||
|
||||
if "--" not in argv: |
||||
argv = [] # as if no args are passed |
||||
else: |
||||
argv = argv[argv.index("--") + 1:] # get all args after "--" |
||||
|
||||
# When --help or no args are given, print this help |
||||
usage_text = \ |
||||
"Run blender in background mode with this script:" |
||||
" blender --background --factory-startup --python " + __file__ + " -- [options]" |
||||
|
||||
parser = argparse.ArgumentParser(description=usage_text) |
||||
|
||||
# Possible types are: string, int, long, choice, float and complex. |
||||
parser.add_argument("-i", "--input", dest="file_path", metavar='FILE', |
||||
help="Import the specified file") |
||||
parser.add_argument("-o", "--output", dest="save_path", metavar='FILE', |
||||
help="Save the generated file to the specified path") |
||||
|
||||
args = parser.parse_args(argv) # In this example we wont use the args |
||||
|
||||
if not argv: |
||||
parser.print_help() |
||||
return |
||||
|
||||
# Clear existing objects. |
||||
scene = bpy.context.scene |
||||
scene.camera = None |
||||
for obj in scene.objects: |
||||
scene.objects.unlink(obj) |
||||
|
||||
# Run the conversion |
||||
convert_file(args.file_path, args.save_path) |
||||
|
||||
print("batch job finished, exiting") |
||||
|
||||
|
||||
if __name__ == "__main__": |
||||
main() |
@ -0,0 +1,86 @@ |
||||
# This script is an example of how you can run blender from the command line |
||||
# (in background mode with no interface) to automate tasks, in this example it |
||||
# creates a text object, camera and light, then renders and/or saves it. |
||||
# This example also shows how you can parse command line options to scripts. |
||||
# |
||||
# Example usage for this test. |
||||
# blender --background --factory-startup --python $HOME/background_job.py -- \ |
||||
# --text="Hello World" \ |
||||
# --render="/tmp/hello" \ |
||||
# --save="/tmp/hello.blend" |
||||
# |
||||
# Notice: |
||||
# '--factory-startup' is used to avoid the user default settings from |
||||
# interfearing with automated scene generation. |
||||
# |
||||
# '--' causes blender to ignore all following arguments so python can use them. |
||||
# |
||||
# See blender --help for details. |
||||
|
||||
import bpy |
||||
|
||||
|
||||
def convert_file(file_path, save_path): |
||||
bpy.ops.wm.collada_import(filepath = file_path) |
||||
|
||||
scene = bpy.context.scene |
||||
|
||||
try: |
||||
f = open(save_path, 'w') |
||||
f.close() |
||||
ok = True |
||||
except: |
||||
print("Cannot save to path %r" % save_path) |
||||
|
||||
import traceback |
||||
traceback.print_exc() |
||||
|
||||
if ok: |
||||
bpy.ops.wm.save_as_mainfile(filepath=save_path) |
||||
|
||||
def main(): |
||||
import sys # to get command line args |
||||
import argparse # to parse options for us and print a nice help message |
||||
|
||||
# get the args passed to blender after "--", all of which are ignored by |
||||
# blender so scripts may receive their own arguments |
||||
argv = sys.argv |
||||
|
||||
if "--" not in argv: |
||||
argv = [] # as if no args are passed |
||||
else: |
||||
argv = argv[argv.index("--") + 1:] # get all args after "--" |
||||
|
||||
# When --help or no args are given, print this help |
||||
usage_text = \ |
||||
"Run blender in background mode with this script:" |
||||
" blender --background --python " + __file__ + " -- [options]" |
||||
|
||||
parser = argparse.ArgumentParser(description=usage_text) |
||||
|
||||
# Possible types are: string, int, long, choice, float and complex. |
||||
parser.add_argument("-i", "--input", dest="file_path", metavar='FILE', |
||||
help="Import the specified file") |
||||
parser.add_argument("-o", "--output", dest="save_path", metavar='FILE', |
||||
help="Save the generated file to the specified path") |
||||
|
||||
args = parser.parse_args(argv) # In this example we wont use the args |
||||
|
||||
if not argv: |
||||
parser.print_help() |
||||
return |
||||
|
||||
# Clear existing objects. |
||||
scene = bpy.context.scene |
||||
scene.camera = None |
||||
for obj in scene.objects: |
||||
scene.objects.unlink(obj) |
||||
|
||||
# Run the conversion |
||||
convert_file(args.file_path, args.save_path) |
||||
|
||||
print("batch job finished, exiting") |
||||
|
||||
|
||||
if __name__ == "__main__": |
||||
main() |
Loading…
Reference in new issue