[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [34228] trunk/blender/release/scripts/op/ io_scene_x3d/import_x3d.py: copy x3d/vrml importer from blender 2.4x.
Campbell Barton
ideasman42 at gmail.com
Mon Jan 10 14:11:56 CET 2011
Revision: 34228
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=34228
Author: campbellbarton
Date: 2011-01-10 13:11:56 +0000 (Mon, 10 Jan 2011)
Log Message:
-----------
copy x3d/vrml importer from blender 2.4x.
svn cp https://svn.blender.org/svnroot/bf-blender/branches/blender2.4/release/scripts/import_web3d.py release/scripts/op/io_scene_x3d/import_x3d.py
Added Paths:
-----------
trunk/blender/release/scripts/op/io_scene_x3d/import_x3d.py
Copied: trunk/blender/release/scripts/op/io_scene_x3d/import_x3d.py (from rev 34227, branches/blender2.4/release/scripts/import_web3d.py)
===================================================================
--- trunk/blender/release/scripts/op/io_scene_x3d/import_x3d.py (rev 0)
+++ trunk/blender/release/scripts/op/io_scene_x3d/import_x3d.py 2011-01-10 13:11:56 UTC (rev 34228)
@@ -0,0 +1,2594 @@
+#!BPY
+"""
+Name: 'X3D & VRML97 (.x3d / wrl)...'
+Blender: 248
+Group: 'Import'
+Tooltip: 'Load an X3D or VRML97 file'
+"""
+
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# (C) Copyright 2008 Paravizion
+# Written by Campbell Barton aka Ideasman42
+#
+# 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 2
+# 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, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# ***** END GPL LICENCE BLOCK *****
+# --------------------------------------------------------------------------
+
+__author__ = "Campbell Barton"
+__url__ = ['www.blender.org', 'blenderartists.org', 'http://wiki.blender.org/index.php/Scripts/Manual/Import/X3D_VRML97']
+__version__ = "0.1"
+
+__bpydoc__ = """\
+This script is an importer for the X3D and VRML97 file formats.
+"""
+
+DEBUG = False
+
+# This should work without a blender at all
+try:
+ from Blender.sys import exists
+except:
+ from os.path import exists
+
+def baseName(path):
+ return path.split('/')[-1].split('\\')[-1]
+
+def dirName(path):
+ return path[:-len(baseName(path))]
+
+def imageConvertCompat(path):
+
+ try: import os
+ except: return path
+ if os.sep=='\\': return path # assime win32 has quicktime, dont convert
+
+ if path.lower().endswith('.gif'):
+ path_to = path[:-3] + 'png'
+
+ '''
+ if exists(path_to):
+ return path_to
+ '''
+ # print '\n'+path+'\n'+path_to+'\n'
+ os.system('convert "%s" "%s"' % (path, path_to)) # for now just hope we have image magick
+
+ if exists(path_to):
+ return path_to
+
+ return path
+
+# notes
+# transform are relative
+# order dosnt matter for loc/size/rot
+# right handed rotation
+# angles are in radians
+# rotation first defines axis then ammount in radians
+
+
+
+# =============================== VRML Spesific
+
+
+def vrmlFormat(data):
+ '''
+ Keep this as a valid vrml file, but format in a way we can predict.
+ '''
+ # Strip all commends - # not in strings - warning multiline strings are ignored.
+ def strip_comment(l):
+ #l = ' '.join(l.split())
+ l = l.strip()
+
+ if l.startswith('#'):
+ return ''
+
+ i = l.find('#')
+
+ if i==-1:
+ return l
+
+ # Most cases accounted for! if we have a comment at the end of the line do this...
+ #j = l.find('url "')
+ j = l.find('"')
+
+ if j == -1: # simple no strings
+ return l[:i].strip()
+
+ q = False
+ for i,c in enumerate(l):
+ if c == '"':
+ q = not q # invert
+
+ elif c == '#':
+ if q==False:
+ return l[:i-1]
+
+ return l
+
+ data = '\n'.join([strip_comment(l) for l in data.split('\n') ]) # remove all whitespace
+
+ EXTRACT_STRINGS = True # only needed when strings or filesnames containe ,[]{} chars :/
+
+ if EXTRACT_STRINGS:
+
+ # We need this so we can detect URL's
+ data = '\n'.join([' '.join(l.split()) for l in data.split('\n')]) # remove all whitespace
+
+ string_ls = []
+
+ #search = 'url "'
+ search = '"'
+
+ ok = True
+ last_i = 0
+ while ok:
+ ok = False
+ i = data.find(search, last_i)
+ if i != -1:
+
+ start = i + len(search) # first char after end of search
+ end = data.find('"', start)
+ if end != -1:
+ item = data[start:end]
+ string_ls.append( item )
+ data = data[:start] + data[end:]
+ ok = True # keep looking
+
+ last_i = (end - len(item)) + 1
+ # print last_i, item, '|' + data[last_i] + '|'
+
+ # done with messy extracting strings part
+
+
+ # Bad, dont take strings into account
+ '''
+ data = data.replace('#', '\n#')
+ data = '\n'.join([ll for l in data.split('\n') for ll in (l.strip(),) if not ll.startswith('#')]) # remove all whitespace
+ '''
+ data = data.replace('{', '\n{\n')
+ data = data.replace('}', '\n}\n')
+ data = data.replace('[', '\n[\n')
+ data = data.replace(']', '\n]\n')
+ data = data.replace(',', ' , ') # make sure comma's seperate
+
+ if EXTRACT_STRINGS:
+ # add strings back in
+
+ search = '"' # fill in these empty strings
+
+ ok = True
+ last_i = 0
+ while ok:
+ ok = False
+ i = data.find(search + '"', last_i)
+ # print i
+ if i != -1:
+ start = i + len(search) # first char after end of search
+ item = string_ls.pop(0)
+ # print item
+ data = data[:start] + item + data[start:]
+
+ last_i = start + len(item) + 1
+
+ ok = True
+
+
+ # More annoying obscure cases where USE or DEF are placed on a newline
+ # data = data.replace('\nDEF ', ' DEF ')
+ # data = data.replace('\nUSE ', ' USE ')
+
+ data = '\n'.join([' '.join(l.split()) for l in data.split('\n')]) # remove all whitespace
+
+ # Better to parse the file accounting for multiline arrays
+ '''
+ data = data.replace(',\n', ' , ') # remove line endings with commas
+ data = data.replace(']', '\n]\n') # very very annoying - but some comma's are at the end of the list, must run this again.
+ '''
+
+ return [l for l in data.split('\n') if l]
+
+NODE_NORMAL = 1 # {}
+NODE_ARRAY = 2 # []
+NODE_REFERENCE = 3 # USE foobar
+# NODE_PROTO = 4 #
+
+lines = []
+
+def getNodePreText(i, words):
+ # print lines[i]
+ use_node = False
+ while len(words) < 5:
+
+ if i>=len(lines):
+ break
+ '''
+ elif lines[i].startswith('PROTO'):
+ return NODE_PROTO, i+1
+ '''
+ elif lines[i]=='{':
+ # words.append(lines[i]) # no need
+ # print "OK"
+ return NODE_NORMAL, i+1
+ elif lines[i].count('"') % 2 != 0: # odd number of quotes? - part of a string.
+ # print 'ISSTRING'
+ break
+ else:
+ new_words = lines[i].split()
+ if 'USE' in new_words:
+ use_node = True
+
+ words.extend(new_words)
+ i += 1
+
+ # Check for USE node - no {
+ # USE #id - should always be on the same line.
+ if use_node:
+ # print 'LINE', i, words[:words.index('USE')+2]
+ words[:] = words[:words.index('USE')+2]
+ if lines[i] == '{' and lines[i+1] == '}':
+ # USE sometimes has {} after it anyway
+ i+=2
+ return NODE_REFERENCE, i
+
+ # print "error value!!!", words
+ return 0, -1
+
+def is_nodeline(i, words):
+
+ if not lines[i][0].isalpha():
+ return 0, 0
+
+ #if lines[i].startswith('field'):
+ # return 0, 0
+
+ # Is this a prototype??
+ if lines[i].startswith('PROTO'):
+ words[:] = lines[i].split()
+ return NODE_NORMAL, i+1 # TODO - assumes the next line is a '[\n', skip that
+ if lines[i].startswith('EXTERNPROTO'):
+ words[:] = lines[i].split()
+ return NODE_ARRAY, i+1 # TODO - assumes the next line is a '[\n', skip that
+
+ '''
+ proto_type, new_i = is_protoline(i, words, proto_field_defs)
+ if new_i != -1:
+ return proto_type, new_i
+ '''
+
+ # Simple "var [" type
+ if lines[i+1] == '[':
+ if lines[i].count('"') % 2 == 0:
+ words[:] = lines[i].split()
+ return NODE_ARRAY, i+2
+
+ node_type, new_i = getNodePreText(i, words)
+
+ if not node_type:
+ if DEBUG: print "not node_type", lines[i]
+ return 0, 0
+
+ # Ok, we have a { after some values
+ # Check the values are not fields
+ for i, val in enumerate(words):
+ if i != 0 and words[i-1] in ('DEF', 'USE'):
+ # ignore anything after DEF, it is a ID and can contain any chars.
+ pass
+ elif val[0].isalpha() and val not in ('TRUE', 'FALSE'):
+ pass
+ else:
+ # There is a number in one of the values, therefor we are not a node.
+ return 0, 0
+
+ #if node_type==NODE_REFERENCE:
+ # print words, "REF_!!!!!!!"
+ return node_type, new_i
+
+def is_numline(i):
+ '''
+ Does this line start with a number?
+ '''
+
+ # Works but too slow.
+ '''
+ l = lines[i]
+ for w in l.split():
+ if w==',':
+ pass
+ else:
+ try:
+ float(w)
+ return True
+
+ except:
+ return False
+
+ return False
+ '''
+
+ l = lines[i]
+
+ line_start = 0
+
+ if l.startswith(', '):
+ line_start += 2
+
+ line_end = len(l)-1
+ line_end_new = l.find(' ', line_start) # comma's always have a space before them
+
+ if line_end_new != -1:
+ line_end = line_end_new
+
+ try:
+ float(l[line_start:line_end]) # works for a float or int
+ return True
+ except:
+ return False
+
+
+class vrmlNode(object):
+ __slots__ = 'id', 'fields', 'proto_node', 'proto_field_defs', 'proto_fields', 'node_type', 'parent', 'children', 'parent', 'array_data', 'reference', 'lineno', 'filename', 'blendObject', 'DEF_NAMESPACE', 'ROUTE_IPO_NAMESPACE', 'PROTO_NAMESPACE', 'x3dNode'
+ def __init__(self, parent, node_type, lineno):
+ self.id = None
+ self.node_type = node_type
+ self.parent = parent
+ self.blendObject = None
+ self.x3dNode = None # for x3d import only
+ if parent:
+ parent.children.append(self)
+
+ self.lineno = lineno
+
+ # This is only set from the root nodes.
+ # Having a filename also denotes a root node
+ self.filename = None
+ self.proto_node = None # proto field definition eg: "field SFColor seatColor .6 .6 .1"
+
+ # Store in the root node because each inline file needs its own root node and its own namespace
+ self.DEF_NAMESPACE = None
+ self.ROUTE_IPO_NAMESPACE = None
+ '''
+ self.FIELD_NAMESPACE = None
+ '''
+
+
+ self.PROTO_NAMESPACE = None
+
+ self.reference = None
+
+ if node_type==NODE_REFERENCE:
+ # For references, only the parent and ID are needed
+ # the reference its self is assigned on parsing
+ return
+
+ self.fields = [] # fields have no order, in some cases rool level values are not unique so dont use a dict
+
+ self.proto_field_defs = [] # proto field definition eg: "field SFColor seatColor .6 .6 .1"
+ self.proto_fields = [] # proto field usage "diffuseColor IS seatColor"
+ self.children = []
+ self.array_data = [] # use for arrays of data - should only be for NODE_ARRAY types
+
+
+ # Only available from the root node
+ '''
+ def getFieldDict(self):
+ if self.FIELD_NAMESPACE != None:
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list