[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [17797] trunk/blender/release/scripts: VRML/X3D
Campbell Barton
ideasman42 at gmail.com
Fri Dec 12 06:46:08 CET 2008
Revision: 17797
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=17797
Author: campbellbarton
Date: 2008-12-12 06:46:07 +0100 (Fri, 12 Dec 2008)
Log Message:
-----------
VRML/X3D
* Improved compatibility with VRML files
* Extract strings so they dont get modified for parsing, filename URL's with {} [] dont break importing anymore.
* Cameras were rotated incorrectly
* inline files were not opened with GZip
* Animation Support - currently only loc/scale/rot (scale untested)
* Lists of image URLs now use the first image from the list since there is no support for dynamic switching.
* use imagemagick to convert GIF's so they load in linux. (WIP - could be extended, At least it should not break anything)
BPyMathutils angle2ToLength function could be simplified (pointed out by brecht)
Modified Paths:
--------------
trunk/blender/release/scripts/bpymodules/BPyMathutils.py
trunk/blender/release/scripts/import_web3d.py
Modified: trunk/blender/release/scripts/bpymodules/BPyMathutils.py
===================================================================
--- trunk/blender/release/scripts/bpymodules/BPyMathutils.py 2008-12-12 05:32:15 UTC (rev 17796)
+++ trunk/blender/release/scripts/bpymodules/BPyMathutils.py 2008-12-12 05:46:07 UTC (rev 17797)
@@ -225,15 +225,5 @@
def angleToLength(angle):
# Alredy accounted for
- if angle < 0.000001:
- return 1.0
-
- angle = 2*pi*angle/360
- x,y = cos(angle), sin(angle)
- # print "YX", x,y
- # 0 d is hoz to the right.
- # 90d is vert upward.
- fac=1/x
- x=x*fac
- y=y*fac
- return sqrt((x*x)+(y*y))
+ if angle < 0.000001: return 1.0
+ else: return abs(1.0 / cos(pi*angle/180));
Modified: trunk/blender/release/scripts/import_web3d.py
===================================================================
--- trunk/blender/release/scripts/import_web3d.py 2008-12-12 05:32:15 UTC (rev 17796)
+++ trunk/blender/release/scripts/import_web3d.py 2008-12-12 05:46:07 UTC (rev 17797)
@@ -48,6 +48,27 @@
def dirName(path):
return path[:-len(baseName(path))]
+def imageConvertCompat(path):
+
+ try: import os
+ except:
+ return path
+
+ if path.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
@@ -78,6 +99,7 @@
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
@@ -96,7 +118,40 @@
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#')
@@ -108,6 +163,27 @@
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)
+
+ if i != -1:
+ start = i + len(search) # first char after end of search
+ item = string_ls.pop(0)
+ data = data[:start] + item + data[start:]
+
+ last_i = start + len(item)
+
+ 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 ')
@@ -199,21 +275,46 @@
'''
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(' ') # comma's always have a space before them
+ 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_end]) # works for a float or int
+ float(l[line_start:line_end]) # works for a float or int
return True
except:
return False
+
class vrmlNode(object):
- __slots__ = 'id', 'fields', 'node_type', 'parent', 'children', 'parent', 'array_data', 'reference', 'lineno', 'filename', 'blendObject', 'DEF_NAMESPACE', 'FIELD_NAMESPACE', 'x3dNode'
+ __slots__ = 'id', 'fields', 'node_type', 'parent', 'children', 'parent', 'array_data', 'reference', 'lineno', 'filename', 'blendObject', 'DEF_NAMESPACE', 'ROUTE_IPO_NAMESPACE', 'FIELD_NAMESPACE', 'x3dNode'
def __init__(self, parent, node_type, lineno):
self.id = None
self.node_type = node_type
@@ -231,6 +332,7 @@
# 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.reference = None
@@ -257,12 +359,25 @@
return self.DEF_NAMESPACE
else:
return self.parent.getDefDict()
+
+ def getRouteIpoDict(self):
+ if self.ROUTE_IPO_NAMESPACE != None:
+ return self.ROUTE_IPO_NAMESPACE
+ else:
+ return self.parent.getRouteIpoDict()
def setRoot(self, filename):
self.filename = filename
- self.FIELD_NAMESPACE = {}
- self.DEF_NAMESPACE= {}
-
+ self.FIELD_NAMESPACE = {}
+ self.DEF_NAMESPACE = {}
+ self.ROUTE_IPO_NAMESPACE = {}
+
+ def isRoot(self):
+ if self.filename == None:
+ return False
+ else:
+ return True
+
def getFilename(self):
if self.filename:
return self.filename
@@ -284,6 +399,11 @@
except:
return None
+ def getPrefix(self):
+ if self.id:
+ return self.id[0]
+ return None
+
def getDefName(self):
self_real = self.getRealNode()
@@ -464,11 +584,13 @@
child_array = None
for child in self_real.children:
+ # print "ID IS", child.id
if child.id and len(child.id) == 1 and child.id[0] == field:
child_array = child
break
if child_array==None:
+
# For x3d, should work ok with vrml too
# for x3d arrays are fields, vrml they are nodes, annoying but not tooo bad.
data_split = self.getFieldName(field)
@@ -489,10 +611,13 @@
print '\tWarning, could not parse array data from field'
array_data = []
else:
-
+ # print child_array
# Normal vrml
array_data = child_array.array_data
+
+ # print 'array_data', array_data
+
if group==-1 or len(array_data)==0:
return array_data
@@ -520,8 +645,6 @@
# We requested a flat array
if group == 0:
return flat_array
-
-
new_array = []
sub_array = []
@@ -537,6 +660,30 @@
return new_array
+ def getFieldAsStringArray(self, field):
+ '''
+ Get a list of strings
+ '''
+ self_real = self.getRealNode() # incase we're an instance
+
+ child_array = None
+ for child in self_real.children:
+ if child.id and len(child.id) == 1 and child.id[0] == field:
+ child_array = child
+ break
+ if not child_array:
+ return []
+
+ # each string gets its own list, remove ""'s
+ try:
+ new_array = [f[0][1:-1] for f in child_array.fields]
+ except:
+ print '\twarning, string array could not be made'
+ new_array = []
+
+ return new_array
+
+
def getLevel(self):
# Ignore self_real
level = 0
@@ -564,19 +711,24 @@
else:
text = ''
- text += ind + 'ID: ' + str(self.id) + ' ' + str(level) + ('lineno %d\n' % self.lineno)
+ text += ind + 'ID: ' + str(self.id) + ' ' + str(level) + (' lineno %d\n' % self.lineno)
if self.node_type==NODE_REFERENCE:
+ text += ind + "(reference node)\n"
return text
- for item in self.fields:
+ text += ind + 'FIELDS:\n'
+
+ for i,item in enumerate(self.fields):
+ text += ind + 'FIELD:\n'
text += ind + str(item) +'\n'
#text += ind + 'ARRAY: ' + str(len(self.array_data)) + ' ' + str(self.array_data) + '\n'
text += ind + 'ARRAY: ' + str(len(self.array_data)) + '[...] \n'
text += ind + 'CHILDREN: ' + str(len(self.children)) + '\n'
- for child in self.children:
+ for i, child in enumerate(self.children):
+ text += ind + ('CHILD%d:\n' % i)
text += str(child)
text += '\n' + ind + brackets[1]
@@ -590,12 +742,24 @@
# If we were an inline then try load the file
if self.node_type == NODE_NORMAL and self.getSpec() == 'Inline':
+
url = self.getFieldAsString('url', None)
if url != None:
- if not exists(url):
- url = dirName(self.getFilename()) + baseName(url)
- if not exists(url):
+ urls = []
+ urls.append( url )
+ urls.append( BPySys.caseInsensitivePath(urls[-1]) )
+
+ urls.append( dirName(self.getFilename()) + baseName(url) )
+ urls.append( BPySys.caseInsensitivePath(urls[-1]) )
+
+ try:
+ url = [url for url in urls if exists(url)][0]
+ url_found = True
+ except:
+ url_found = False
+
+ if not url_found:
print '\tWarning: Inline URL could not be found:', url
else:
if url==self.getFilename():
@@ -603,12 +767,12 @@
else:
try:
- f = open(url, 'rU')
+ data = gzipOpen(url)
except:
print '\tWarning: cant open the file:', url
- f = None
+ data = None
- if f:
+ if data:
# Tricky - inline another VRML
print '\tLoading Inline:"%s"...' % url
@@ -616,12 +780,15 @@
lines_old = lines[:]
- lines[:] = vrmlFormat( f.read() )
- f.close()
+ lines[:] = vrmlFormat( data )
lines.insert(0, '{')
lines.insert(0, 'root_node____')
lines.append('}')
+ '''
+ ff = open('/test.txt', 'w')
+ ff.writelines([l+'\n' for l in lines])
+ '''
child = vrmlNode(self, NODE_NORMAL, -1)
child.setRoot(url) # initialized dicts
@@ -723,7 +890,9 @@
values = l_split
# This should not extend over multiple lines however it is possible
- self.array_data.extend( values )
+ # print self.array_data
+ if values:
+ self.array_data.extend( values )
i+=1
else:
words = l.split()
@@ -843,13 +1012,13 @@
lines.insert(0, '{')
lines.insert(0, 'dymmy_node')
lines.append('}')
-
# Use for testing our parsed output, so we can check on line numbers.
- ## ff = open('m:\\test.txt', 'w')
- ## ff.writelines([l+'\n' for l in lines])
+ '''
+ ff = open('/test.txt', 'w')
+ ff.writelines([l+'\n' for l in lines])
+ '''
-
# Now evaluate it
node_type, new_i = is_nodeline(0, [])
if not node_type:
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list