Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJean-Luc Peurière <jlp@nerim.net>2007-06-03 01:42:54 +0400
committerJean-Luc Peurière <jlp@nerim.net>2007-06-03 01:42:54 +0400
commit6cc1269d976641e6fdac59d1c1afbc96ae3aab8b (patch)
tree02bc32f07419e48a1492bc09609d5186fc095df6
parent16340dfe1235391bb675a633a099c17af3a731c7 (diff)
parentc6158b9293d6c5ea15c323fea44138d3563d1a12 (diff)
merge from trunk up to rev [10858]
WIP in the NDOF part, dont work yet
-rw-r--r--SConstruct228
-rw-r--r--intern/ghost/GHOST_Types.h1
-rw-r--r--intern/ghost/intern/GHOST_NDOFManager.cpp7
-rw-r--r--intern/ghost/intern/GHOST_WindowCarbon.cpp14
-rw-r--r--release/scripts/DirectX8Importer.py178
-rw-r--r--release/scripts/export_m3g.py3047
-rw-r--r--release/windows/installer/00.sconsblender.nsi15
-rw-r--r--source/blender/blenkernel/BKE_blender.h2
-rw-r--r--source/blender/blenkernel/BKE_node.h11
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c2
-rw-r--r--source/blender/blenkernel/intern/mesh.c2
-rw-r--r--source/blender/blenkernel/intern/nla.c5
-rw-r--r--source/blender/blenkernel/intern/node.c8
-rw-r--r--source/blender/blenloader/intern/readfile.c23
-rw-r--r--source/blender/blenloader/intern/writefile.c6
-rw-r--r--source/blender/imbuf/intern/util.c26
-rw-r--r--source/blender/include/BIF_editaction.h1
-rw-r--r--source/blender/include/BIF_editdeform.h3
-rw-r--r--source/blender/include/multires.h2
-rw-r--r--source/blender/makesdna/DNA_meshdata_types.h6
-rw-r--r--source/blender/nodes/CMP_node.h6
-rw-r--r--source/blender/nodes/SHD_node.h2
-rw-r--r--source/blender/nodes/intern/CMP_nodes/CMP_alphaOver.c4
-rw-r--r--source/blender/nodes/intern/CMP_nodes/CMP_curves.c6
-rw-r--r--source/blender/nodes/intern/CMP_nodes/CMP_invert.c134
-rw-r--r--source/blender/nodes/intern/CMP_nodes/CMP_mixrgb.c2
-rw-r--r--source/blender/nodes/intern/CMP_nodes/CMP_setalpha.c4
-rw-r--r--source/blender/nodes/intern/SHD_nodes/SHD_geom.c11
-rw-r--r--source/blender/nodes/intern/SHD_nodes/SHD_invert.c83
-rw-r--r--source/blender/nodes/intern/SHD_nodes/SHD_material.c79
-rw-r--r--source/blender/nodes/intern/SHD_util.c30
-rw-r--r--source/blender/nodes/intern/SHD_util.h18
-rw-r--r--source/blender/python/api2_2x/Blender.c9
-rw-r--r--source/blender/python/api2_2x/Key.c2
-rw-r--r--source/blender/python/api2_2x/Mesh.c39
-rw-r--r--source/blender/python/api2_2x/NMesh.c88
-rw-r--r--source/blender/python/api2_2x/Scene.c6
-rw-r--r--source/blender/python/api2_2x/doc/Render.py2
-rw-r--r--source/blender/python/api2_2x/doc/Scene.py2
-rw-r--r--source/blender/render/extern/include/RE_shader_ext.h5
-rw-r--r--source/blender/render/intern/source/shadeinput.c5
-rw-r--r--source/blender/src/SConscript18
-rw-r--r--source/blender/src/buttons_editing.c2
-rw-r--r--source/blender/src/buttons_object.c15
-rw-r--r--source/blender/src/drawmesh.c1
-rw-r--r--source/blender/src/drawnode.c19
-rw-r--r--source/blender/src/editaction.c98
-rw-r--r--source/blender/src/editdeform.c97
-rw-r--r--source/blender/src/editipo.c3
-rw-r--r--source/blender/src/editnla.c6
-rw-r--r--source/blender/src/ghostwinlay.c4
-rw-r--r--source/blender/src/multires-firstlevel.c37
-rw-r--r--source/blender/src/multires.c370
-rw-r--r--source/blender/src/space.c17
-rw-r--r--source/blender/src/transform_manipulator.c18
-rw-r--r--source/gameengine/Converter/BL_ArmatureObject.cpp5
-rw-r--r--source/gameengine/Ketsji/BL_Shader.cpp3
-rwxr-xr-xtools/btools.py239
58 files changed, 4371 insertions, 705 deletions
diff --git a/SConstruct b/SConstruct
index 2a8adac2338..7e9e0344c3a 100644
--- a/SConstruct
+++ b/SConstruct
@@ -74,8 +74,8 @@ if not use_color=='1':
#on defaut white Os X terminal, some colors are totally unlegible
if platform=='darwin':
- B.bc.OKGREEN = '\033[34m'
- B.bc.WARNING = '\033[36m'
+ B.bc.OKGREEN = '\033[34m'
+ B.bc.WARNING = '\033[36m'
# arguments
print B.bc.HEADER+'Command-line arguments'+B.bc.ENDC
@@ -115,6 +115,8 @@ if toolset:
env.Tool('mstoolkit', ['tools'])
else:
env = BlenderEnvironment(tools=[toolset], ENV = os.environ)
+ if env:
+ btools.SetupSpawn(env)
else:
env = BlenderEnvironment(ENV = os.environ)
@@ -122,7 +124,7 @@ if not env:
print "Could not create a build environment"
Exit()
-env.SConscriptChdir(0)
+
cc = B.arguments.get('CC', None)
cxx = B.arguments.get('CXX', None)
if cc:
@@ -135,53 +137,7 @@ if env['CC'] in ['cl', 'cl.exe'] and sys.platform=='win32':
elif env['CC'] in ['gcc'] and sys.platform=='win32':
platform = 'win32-mingw'
-# Fix me!
-#if platform == 'win32-mingw':
-if 0:
- try:
- import win32file
- import win32event
- import win32process
- import win32security
- import string
-
- slash= re.compile(r"\\")
-
- def myesc(b):
- if b[0]!= "-":
- b = slash.sub(r"\\\\", b[1:-1])
- return "\"" + b + "\""
- else:
- return b
-
- def my_spawn(sh, escape, cmd, args, spawnenv):
- for var in spawnenv:
- spawnenv[var] = spawnenv[var].encode('ascii', 'replace')
-
- sAttrs = win32security.SECURITY_ATTRIBUTES()
- StartupInfo = win32process.STARTUPINFO()
- if cmd=='ar' and args[1]=='r':
- args[1] = '-r'
- newargs = string.join(map(myesc, args[1:]), ' ')
- cmdline = cmd + " " + newargs
-
- # check for any special operating system commands
- if cmd == 'del':
- for arg in args[1:]:
- win32file.DeleteFile(arg)
- exit_code = 0
- else:
- # otherwise execute the command.
- hProcess, hThread, dwPid, dwTid = win32process.CreateProcess(None, cmdline, None, None, 1, 0, spawnenv, None, StartupInfo)
- win32event.WaitForSingleObject(hProcess, win32event.INFINITE)
- exit_code = win32process.GetExitCodeProcess(hProcess)
- win32file.CloseHandle(hProcess);
- win32file.CloseHandle(hThread);
- return exit_code
-
- env['SPAWN'] = my_spawn
- except:
- print "install win32all from http://sourceforge.net/project/showfiles.php?group_id=78018"
+env.SConscriptChdir(0)
crossbuild = B.arguments.get('BF_CROSS', None)
if crossbuild and platform!='win32':
@@ -278,170 +234,6 @@ env['BUILDDIR'] = B.root_build_dir
if not B.root_build_dir[-1]==os.sep:
B.root_build_dir += os.sep
-def NSIS_Installer():
-
- if env['OURPLATFORM'] != 'win32-vc' and env['OURPLATFORM'] != 'win32-mingw':
- print "NSIS installer is only available on Windows."
- Exit()
-
- install_base_dir = os.getcwd() + "\\"
-
- if not os.path.exists(install_base_dir+env['BF_INSTALLDIR']+'/plugins/include'):
- os.mkdir(install_base_dir+env['BF_INSTALLDIR']+'/plugins/include')
-
- for f in glob.glob('source/blender/blenpluginapi/*.h'):
- shutil.copy(f,install_base_dir+env['BF_INSTALLDIR']+'/plugins/include')
-
- shutil.copy('source/blender/blenpluginapi/plugin.def',install_base_dir+env['BF_INSTALLDIR']+'/plugins/include/')
-
- os.chdir("release")
- v = open("VERSION")
- version = v.read()[:-1]
- shortver = version.split('.')[0] + version.split('.')[1]
- v.close()
-
- #### change to suit install dir ####
- inst_dir = install_base_dir + env['BF_INSTALLDIR']
-
- os.chdir("windows/installer")
-
- ns = open("00.sconsblender.nsi","r")
-
- ns_cnt = str(ns.read())
- ns.close()
-
- # do root
- rootlist = []
- rootdir = os.listdir(inst_dir+"\\")
- for rootitem in rootdir:
- if os.path.isdir(inst_dir+"\\"+ rootitem) == 0:
- rootlist.append("File " + inst_dir + "\\" + rootitem)
- rootstring = string.join(rootlist, "\n ")
- rootstring += "\n\n"
- ns_cnt = string.replace(ns_cnt, "[ROOTDIRCONTS]", rootstring)
-
- # do delete items
- delrootlist = []
- for rootitem in rootdir:
- if os.path.isdir(inst_dir + rootitem) == 0:
- delrootlist.append("Delete $INSTDIR\\" + rootitem)
- delrootstring = string.join(delrootlist, "\n ")
- delrootstring += "\n"
- ns_cnt = string.replace(ns_cnt, "[DELROOTDIRCONTS]", delrootstring)
-
- # do scripts
- scriptlist = []
- scriptpath = "%s%s" % (inst_dir, "\\.blender\\scripts")
- scriptdir = os.listdir(scriptpath)
- for scriptitem in scriptdir:
- scriptfile = "%s\\%s" % (scriptpath, scriptitem)
- if os.path.isdir(scriptfile) == 0:
- scriptlist.append("File %s" % scriptfile)
- scriptstring = string.join(scriptlist, "\n ")
- scriptstring += "\n\n"
- ns_cnt = string.replace(ns_cnt, "[SCRIPTCONTS]", scriptstring)
-
- # do scripts\bpymodules
- bpymodlist = []
- bpymodpath = "%s%s" % (inst_dir, "\\.blender\\scripts\\bpymodules")
- bpymoddir = os.listdir(bpymodpath)
-
- for bpymoditem in bpymoddir:
- bpymodfile = "%s\\%s" % (bpymodpath, bpymoditem)
- if os.path.isdir(bpymodfile) == 0:
- bpymodlist.append("File %s" % bpymodfile)
- bpymodstring = string.join(bpymodlist, "\n ")
- bpymodstring += "\n\n"
- ns_cnt = string.replace(ns_cnt, "[SCRIPTMODCONTS]", bpymodstring)
-
- # do scripts\bpymodules\colladaimex
- colladalist = []
- bpymodpath = "%s%s" % (inst_dir, "\\.blender\\scripts\\bpymodules\\ColladaImEx")
- bpymoddir = os.listdir(bpymodpath)
-
- for bpymoditem in bpymoddir:
- bpymodfile = "%s\\%s" % (bpymodpath, bpymoditem)
- if os.path.isdir(bpymodfile) == 0:
- colladalist.append("File %s" % bpymodfile)
- bpymodstring = string.join(colladalist, "\n ")
- bpymodstring += "\n\n"
- ns_cnt = string.replace(ns_cnt, "[SCRIPTMODCOLLADACONT]", bpymodstring)
-
- # do scripts\bpydata
- bpydatalist = []
- bpydatapath = "%s%s" % (inst_dir, "\\.blender\\scripts\\bpydata")
- bpydatadir = os.listdir(bpydatapath)
- for bpydataitem in bpydatadir:
- bpydatafile = "%s\\%s" % (bpydatapath, bpydataitem)
- if os.path.isdir(bpydatafile) == 0:
- bpydatalist.append("File %s" % bpydatafile)
- bpydatastring = string.join(bpydatalist, "\n ")
- bpydatastring += "\n\n"
- ns_cnt = string.replace(ns_cnt, "[SCRIPTDATACONTS]", bpydatastring)
-
- # do plugins\include
- plugincludelist = []
- plugincludepath = "%s%s" % (inst_dir, "\\plugins\\include")
- plugincludedir = os.listdir(plugincludepath)
- for plugincludeitem in plugincludedir:
- plugincludefile = "%s\\%s" % (plugincludepath, plugincludeitem)
- if os.path.isdir(plugincludefile) == 0:
- if plugincludefile.find('.h') or plugincludefile.find('.DEF'):
- plugincludelist.append("File %s" % plugincludefile)
- plugincludestring = string.join(plugincludelist, "\n ")
- plugincludestring += "\n\n"
- ns_cnt = string.replace(ns_cnt, "[PLUGINCONTS]", plugincludestring)
-
- # do scripts\bpydata\config
- cfglist = []
- cfgpath = "%s%s" % (inst_dir, "\\.blender\\scripts\\bpydata\\config")
- cfgdir = os.listdir(cfgpath)
- for cfgitem in cfgdir:
- cfgfile = "%s\\%s" % (cfgpath, cfgitem)
- if os.path.isdir(cfgfile) == 0:
- cfglist.append("File %s" % cfgfile)
- cfgstring = string.join(cfglist, "\n ")
- cfgstring += "\n\n"
- ns_cnt = string.replace(ns_cnt, "[SCRIPTDATACFGCONTS]", cfgstring)
-
- # do dotblender
- dotblendlist = []
- dotblenddir = os.listdir(inst_dir+"\\.blender")
- for dotblenditem in dotblenddir:
- if os.path.isdir(inst_dir + "\\.blender\\" + dotblenditem) == 0:
- dotblendlist.append("File " + inst_dir + "\\.blender\\" + dotblenditem)
- dotblendstring = string.join(dotblendlist, "\n ")
- dotblendstring += "\n\n"
- ns_cnt = string.replace(ns_cnt, "[DOTBLENDERCONTS]", dotblendstring)
-
- # do language files
- langlist = []
- langfiles = []
- langdir = os.listdir(inst_dir + "\\.blender\\locale")
- for langitem in langdir:
- if os.path.isdir(inst_dir + "\\.blender\\locale\\" + langitem) == 1:
- langfiles.append("SetOutPath $BLENDERHOME\\.blender\\locale\\" + langitem + "\\LC_MESSAGES")
- langfiles.append("File " + inst_dir + "\\.blender\\locale\\" + langitem + "\\LC_MESSAGES\\blender.mo")
- langstring = string.join(langfiles, "\n ")
- langstring += "\n\n"
- ns_cnt = string.replace(ns_cnt, "[LANGUAGECONTS]", langstring)
-
- # var replacements
- ns_cnt = string.replace(ns_cnt, "DISTDIR", inst_dir+"\\")
- ns_cnt = string.replace(ns_cnt, "SHORTVER", shortver)
- ns_cnt = string.replace(ns_cnt, "VERSION", version)
-
- new_nsis = open("00.blender_tmp.nsi", 'w')
- new_nsis.write(ns_cnt)
- new_nsis.close()
-
- sys.stdout = os.popen("makensis 00.blender_tmp.nsi", 'w')
-
-nsis_build = None
-if 'nsis' in B.targets:
- NSIS_Installer()
- Exit()
-
# We do a shortcut for clean when no quicklist is given: just delete
# builddir without reading in SConscripts
do_clean = None
@@ -484,8 +276,6 @@ B.init_lib_dict()
##### END SETUP ##########
Export('env')
-#Export('root_build_dir') # this one is still needed for makesdna
-##TODO: improve makesdna usage
BuildDir(B.root_build_dir+'/intern', 'intern', duplicate=0)
SConscript(B.root_build_dir+'/intern/SConscript')
@@ -624,6 +414,10 @@ if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw'):
installtarget = env.Alias('install', allinstall)
bininstalltarget = env.Alias('install-bin', blenderinstall)
+nsisaction = env.Action(btools.NSIS_Installer, btools.NSIS_print)
+nsiscmd = env.Command('nsisinstaller', None, nsisaction)
+nsisalias = env.Alias('nsis', nsiscmd)
+
if env['WITH_BF_PLAYER']:
blenderplayer = env.Alias('blenderplayer', B.program_list)
Depends(blenderplayer,installtarget)
@@ -632,6 +426,8 @@ if not env['WITH_BF_GAMEENGINE']:
blendernogame = env.Alias('blendernogame', B.program_list)
Depends(blendernogame,installtarget)
+Depends(nsiscmd, allinstall)
+
Default(B.program_list)
Default(installtarget)
diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h
index c0f7245eff1..f8f9a8d4735 100644
--- a/intern/ghost/GHOST_Types.h
+++ b/intern/ghost/GHOST_Types.h
@@ -343,6 +343,7 @@ typedef void (*GHOST_NDOFLibraryShutdown_fp)(void* deviceHandle);
typedef void* (*GHOST_NDOFDeviceOpen_fp)(void* platformData);
typedef int (*GHOST_NDOFEventHandler_fp)(float* result7, void* deviceHandle, unsigned int message, unsigned int* wParam, unsigned long* lParam);
+/* original patch used floats, but the driver return ints and uns. We will calibrate in view, no sense on doing conversions twice */
typedef struct {
/** N-degree of freedom device data */
float tx, ty, tz; /** -x left, +y up, +z forward */
diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp
index 86a9b56c7cc..3ac3d483d18 100644
--- a/intern/ghost/intern/GHOST_NDOFManager.cpp
+++ b/intern/ghost/intern/GHOST_NDOFManager.cpp
@@ -46,6 +46,7 @@ GHOST_NDOFManager::GHOST_NDOFManager()
ndofLibraryShutdown = 0;
ndofDeviceOpen = 0;
ndofEventHandler = 0;
+ // available = 0;
}
GHOST_NDOFManager::~GHOST_NDOFManager()
@@ -69,9 +70,9 @@ GHOST_NDOFManager::deviceOpen(GHOST_IWindow* window,
ndofDeviceOpen = setNdofDeviceOpen;
ndofEventHandler = setNdofEventHandler;
- if (ndofLibraryInit)
+ if (ndofLibraryInit && ndofDeviceOpen)
{
- ndofLibraryInit();
+ printf("%i client \n", ndofLibraryInit());
}
/*
if (ndofDeviceOpen)
@@ -96,6 +97,7 @@ GHOST_NDOFManager::handle(unsigned int message, unsigned int* wParam, unsigned l
{
handled = ndofEventHandler(&sbdata.tx, m_DeviceHandle, message, wParam, lParam);
}
+ printf("handled %i\n", handled);
return handled ? &sbdata : 0;
}
@@ -105,3 +107,4 @@ GHOST_NDOFManager::available()
{
return m_DeviceHandle != 0;
}
+
diff --git a/intern/ghost/intern/GHOST_WindowCarbon.cpp b/intern/ghost/intern/GHOST_WindowCarbon.cpp
index 9b0ccf37ef0..04debe36191 100644
--- a/intern/ghost/intern/GHOST_WindowCarbon.cpp
+++ b/intern/ghost/intern/GHOST_WindowCarbon.cpp
@@ -49,20 +49,22 @@ AGLContext GHOST_WindowCarbon::s_firstaglCtx = NULL;
const GHOST_TInt32 GHOST_WindowCarbon::s_sizeRectSize = 16;
#endif //GHOST_DRAW_CARBON_GUTTER
-static const GLint sPreferredFormatWindow[9] = {
-AGL_RGBA, GL_TRUE,
-AGL_DOUBLEBUFFER, GL_TRUE,
-AGL_DEPTH_SIZE, 16,
+static const GLint sPreferredFormatWindow[8] = {
+AGL_RGBA,
+AGL_DOUBLEBUFFER,
+AGL_ACCELERATED,
+AGL_DEPTH_SIZE, 32,
AGL_AUX_BUFFERS, 1,
AGL_NONE,
};
-static const GLint sPreferredFormatFullScreen[7] = {
+static const GLint sPreferredFormatFullScreen[9] = {
AGL_RGBA,
AGL_DOUBLEBUFFER,
AGL_ACCELERATED,
AGL_FULLSCREEN,
-AGL_DEPTH_SIZE, 16,
+AGL_DEPTH_SIZE, 32,
+AGL_AUX_BUFFERS, 1,
AGL_NONE,
};
diff --git a/release/scripts/DirectX8Importer.py b/release/scripts/DirectX8Importer.py
index 61ae12e8a7e..7e6a8429759 100644
--- a/release/scripts/DirectX8Importer.py
+++ b/release/scripts/DirectX8Importer.py
@@ -23,7 +23,7 @@ Tip: 'Import from DirectX text file format format.'
# This script import meshes from DirectX text file format
# Grab the latest version here :www.omariben.too.it
-
+import bpy
import Blender
from Blender import NMesh,Object,Material,Texture,Image,Draw
@@ -33,123 +33,102 @@ class xImport:
global my_path
self.file = open(filename, "r")
my_path = Blender.sys.dirname(filename)
- self.lines = self.file.readlines()
+
+ #
+ self.lines = [l_split for l in self.file.readlines() for l_split in (' '.join(l.split()),) if l_split]
def Import(self):
lines = self.lines
print "importing into Blender ..."
- scene = Blender.Scene.getCurrent()
+ scene = bpy.data.scenes.active
mesh = NMesh.GetRaw()
#Get the line of Texture Coords
nr_uv_ind = 0
- for line_uv in lines:
- l = line_uv.strip()
- words = line_uv.split()
- if l and words[0] == "MeshTextureCoords" :
- nr_uv_ind = lines.index(line_uv)
-
-
-
- #Get Materials
+
+ #Get Materials
+ nr_fac_mat = 0
idx = 0
i = -1
mat_list = []
tex_list = []
- for line_mat in lines:
- i += 1
- l = line_mat.strip()
- words = line_mat.split()
- if l and words[0] == "Material" :
- idx += 1
- self.writeMaterials(i, idx, mat_list, tex_list)
-
-
-
- nr_fac_mat = 0
- #Assign Materials
- for line_m in lines:
- l = line_m.strip()
- words = line_m.split()
- if l and words[0] == "MeshMaterialList" :
- nr_fac_mat = lines.index(line_m) + 2
-
- #Create The Mesh
- for line in lines:
+ mesh_line_indicies = []
+ for j, line in enumerate(lines):
l = line.strip()
- words = line.split()
- if l and words[0] == "Mesh" :
- nr_vr_ind = lines.index(line)
- self.writeVertices(nr_vr_ind, mesh, nr_uv_ind, nr_fac_mat, tex_list)
-
-
- NMesh.PutRaw(mesh,"Mesh",1)
+ words = line.split()
+ if words[0] == "Material" :
+ idx += 1
+ self.writeMaterials(j, idx, mat_list, tex_list)
+ elif words[0] == "MeshTextureCoords" :
+ nr_uv_ind = j
+ elif words[0] == "MeshMaterialList" :
+ nr_fac_mat = j + 2
+ elif words[0] == "Mesh": # Avoid a second loop
+ mesh_line_indicies.append(j)
+
+ #Create The Mesh
+ for nr_vr_ind in mesh_line_indicies:
+ self.writeVertices(nr_vr_ind, mesh, nr_uv_ind, nr_fac_mat, tex_list)
+
mesh.setMaterials(mat_list)
- mesh.update()
-
- if nr_fac_mat :
+ if nr_fac_mat:
self.writeMeshMaterials(nr_fac_mat, mesh)
-
+ NMesh.PutRaw(mesh,"Mesh",1)
+
self.file.close()
print "... finished"
-
+
#------------------------------------------------------------------------------
# CREATE THE MESH
#------------------------------------------------------------------------------
def writeVertices(self, nr_vr_ind, mesh, nr_uv, nr_fac_mat, tex_list):
-
- lin = self.lines[nr_vr_ind + 1]
+ v_ind = nr_vr_ind + 1
+ lin = self.lines[v_ind]
if lin :
- lin_c = self.CleanLine(lin)
+ lin_c = self.CleanLine(lin)
nr_vert = int((lin_c.split()[0]))
- v_ind = self.lines.index(lin)
else :
- lin = self.lines.index(nr_vr_ind + 2)
- lin_c = self.CleanLine(lin)
+ v_ind = nr_vr_ind + 2
+ lin = self.lines[v_ind]
+ lin_c = self.CleanLine(lin)
nr_vert = int((lin_c.split()[0]))
- v_ind = self.lines.index(lin)
-
+
vx_array = range(v_ind + 1, (v_ind + nr_vert +1))
#--------------------------------------------------
- lin_f = self.lines[v_ind + nr_vert +1]
+ nr_fac_li = v_ind + nr_vert +1
+ lin_f = self.lines[nr_fac_li]
if lin_f :
- lin_fc = self.CleanLine(lin_f)
+ lin_fc = self.CleanLine(lin_f)
nr_face = int((lin_fc.split()[0]))
- nr_fac_li = self.lines.index(lin_f)
else :
- lin_f = self.lines[v_ind + nr_vert +1]
- lin_fc = self.CleanLine(lin_f)
+ nr_fac_li = v_ind + nr_vert +1
+ lin_f = self.lines[nr_fac_li]
+ lin_fc = self.CleanLine(lin_f)
nr_face = int((lin_fc.split()[0]))
- nr_fac_li = self.lines.index(lin_f)
-
-
- fac_array = range(nr_fac_li + 1, (nr_fac_li + nr_face + 1))
- #Get Coordinates
+
+ fac_array = range(nr_fac_li + 1, (nr_fac_li + nr_face + 1))
+ #Get Coordinates
for l in vx_array:
line_v = self.lines[l]
lin_v = self.CleanLine(line_v)
- words = lin_v.split()
+ words = lin_v.split()
if len(words)==3:
- co_vert_x = float(words[0])
- co_vert_y = float(words[1])
- co_vert_z = float(words[2])
- v=NMesh.Vert(co_vert_x,co_vert_y,co_vert_z)
- mesh.verts.append(v)
-
-
-
+ mesh.verts.append(NMesh.Vert(float(words[0]),float(words[1]),float(words[2])))
+
#Make Faces
i = 0
+ mesh_verts = mesh.verts
for f in fac_array:
i += 1
line_f = self.lines[f]
lin_f = self.CleanLine(line_f)
- words = lin_f.split()
- if len(words) == 5:
- f=NMesh.Face()
- f.v.append(mesh.verts[int(words[1])])
- f.v.append(mesh.verts[int(words[2])])
- f.v.append(mesh.verts[int(words[3])])
- f.v.append(mesh.verts[int(words[4])])
+ words = lin_f.split()
+ if len(words) == 5:
+ f= NMesh.Face([\
+ mesh_verts[int(words[1])],
+ mesh_verts[int(words[2])],
+ mesh_verts[int(words[3])],
+ mesh_verts[int(words[4])]])
+
mesh.faces.append(f)
if nr_uv :
uv = []
@@ -193,12 +172,13 @@ class xImport:
#Draw.PupMenu("No image to load")
#print "No image " + name_tex + " to load"
pass
-
- elif len(words) == 4:
- f=NMesh.Face()
- f.v.append(mesh.verts[int(words[1])])
- f.v.append(mesh.verts[int(words[2])])
- f.v.append(mesh.verts[int(words[3])])
+
+ elif len(words) == 4:
+ f=NMesh.Face([\
+ mesh_verts[int(words[1])],\
+ mesh_verts[int(words[2])],\
+ mesh_verts[int(words[3])]])
+
mesh.faces.append(f)
if nr_uv :
uv = []
@@ -236,10 +216,10 @@ class xImport:
#Draw.PupMenu("No image to load")
#print "No image " + name_tex + " to load"
pass
-
-
-
-
+
+
+
+
def CleanLine(self,line):
fix_line = line.replace(";", " ")
fix_1_line = fix_line.replace('"', ' ')
@@ -248,7 +228,7 @@ class xImport:
fix_4_line = fix_3_line.replace(",", " ")
fix_5_line = fix_4_line.replace("'", " ")
return fix_5_line
-
+
#------------------------------------------------------------------
# CREATE MATERIALS
#------------------------------------------------------------------
@@ -257,21 +237,21 @@ class xImport:
mat = Material.New(name)
line = self.lines[nr_mat + 1]
fixed_line = self.CleanLine(line)
- words = fixed_line.split()
+ words = fixed_line.split()
mat.rgbCol = [float(words[0]),float(words[1]),float(words[2])]
mat.setAlpha(float(words[3]))
mat_list.append(mat)
l = self.lines[nr_mat + 5]
fix_3_line = self.CleanLine(l)
tex_n = fix_3_line.split()
-
+
if tex_n and tex_n[0] == "TextureFilename" :
-
+
if len(tex_n) > 1:
tex_list.append(tex_n[1])
-
+
if len(tex_n) <= 1 :
-
+
l_succ = self.lines[nr_mat + 6]
fix_3_succ = self.CleanLine(l_succ)
tex_n_succ = fix_3_succ.split()
@@ -279,7 +259,7 @@ class xImport:
else :
tex_name = None
tex_list.append(tex_name)
-
+
return mat_list, tex_list
#------------------------------------------------------------------
# SET MATERIALS
@@ -292,10 +272,8 @@ class xImport:
wrd = fixed_line.split()
mat_idx = int(wrd[0])
face.materialIndex = mat_idx
- mesh.update()
-
-
-
+
+
#------------------------------------------------------------------
# MAIN
#------------------------------------------------------------------
@@ -308,4 +286,4 @@ arg = __script__['arg']
if __name__ == '__main__':
Blender.Window.FileSelector(my_callback, "Import DirectX", "*.x")
- \ No newline at end of file
+# my_callback('/directxterrain.x')
diff --git a/release/scripts/export_m3g.py b/release/scripts/export_m3g.py
new file mode 100644
index 00000000000..afb019fcc1e
--- /dev/null
+++ b/release/scripts/export_m3g.py
@@ -0,0 +1,3047 @@
+#!BPY
+""" Registration info for Blender menus:
+Name: 'M3G (.m3g, .java)...'
+Blender: 244
+Group: 'Export'
+Tooltip: 'Export to M3G'
+"""
+#------------------------------------------------------------------------
+# M3G exporter for blender 2.37 or above
+#
+# Source: http://www.nelson-games.de/bl2m3g/source
+#
+# $Id: m3g_export.py,v 0.1 2005/04/19 12:25 gerhardv Exp gerhardv $
+#
+# Author: Gerhard Völkl
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# Copyright (C) 2005: gerhard völkl gkvoelkl@yahoo.de
+#
+# 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 *****
+#
+# To use script:
+# 1.) load this file in the text window.
+# (press SHIFT+F11, Open New via Datablock button)
+# 2.) make sure your mouse is over the text edit window and
+# run this script. (press ALT+P)
+# Or:
+# copy to the scripts directory and it will appear in the
+# export list. (Needs 2.32 or higher)
+#
+# Based on informations from:
+# wrl2export.py from Rick Kimball and others
+# --------------------------------------------------------------------------#
+# History 0.2
+# * maximal Precision in VertexArray (with algorithms from Kalle Raita)
+# * IPO Animation with mesh: Rotation, Translation and Size
+# History 0.3
+# * to find a 3d object in your java programm you can assign a userID
+# your blender object has name 'cube#01' your 3d object will have ID 01
+# the number after '#' is taken
+# * more than one material per mesh can be used
+# * uv texture support (implemented by Aki Koskinen and Juha Laitinen)
+# The image which is bound to the faces will be exportet within m3g-file
+# Limitations by M3G-API:
+# The width and height of the image must be non-negative powers of two,
+# but they need not to be equal. Maximum value is 256.
+# *.java export: Only PNG images can be used.
+# History 0.4
+# * check limitation of texture images (credit to MASTER_ZION for Brasil)
+# * Better light: The light modeles of Blender and M3G are naturally
+# different. So the export script trys to translate as much as possible
+#
+# M3G Light type Blender Light type
+# --------------------------------------------------------------
+# AMIENT Light Not available as light type in Blender
+# DIRECTIONAL Light SUN
+# OMNIdirectional light LAMP
+# SPOT light SPOT
+# not translated HEMI
+# not translated AREA
+#
+# Attributs of M3G Lights:
+#
+# Attenuation (OMNI,SPOT):
+# Intensity of light changes with distance
+# The attenuation factor is 1 / (c + l d + q d2)
+# where d is the distance between the light and the vertex being lighted
+# and c, l, q are the constant, linear, and quadratic coefficients.
+# In Blender exists much complex posibilies. To simplify exporter uses
+# only button Dist: distance at which the light intensity is half
+# the Energy
+# Color (ALL)
+# Color of light
+# Intensity (ALL)
+# The RGB color of this Light is multiplied component-wise with the
+# intensity. In Blender : energy
+# SpotAngle (SPOT)
+# the spot cone angle for this Light
+# In Blender: spotSize
+# SpotExponent (SPOT)
+# The spot exponent controls the distribution of the intensity of
+# this Light within the spot cone, such that larger values yield
+# a more concentrated cone. In Blender: SpotBl
+#
+# * Some GUI for options
+# First prototype of GUI was created using RipSting's Blender-Python
+# GUI designer. Download at Http://oregonstate.edu/~dennisa/Blender/BPG/
+#
+# * Ambiente light
+# Information is taken by world ambiente attribute
+#
+# * Parenting Part 1
+# In Blender the Empty object is used to group objects. All objects
+# which have the same empty as parent are the member of the same group.
+#
+# empty <-- Parent of -- element 1
+# <-- Parent of -- element 2
+#
+# is translated in M3G
+#
+# group-Node -- Member --> element 1
+# -- Member --> element 2
+#
+# In Blender every object can be the parent of every other object
+# In M3G that is not possible. Only a group object can be parent.
+# (Or the world object which is derived from group).
+# That will come later as Parenting Part 2
+#
+# * Backface Culling
+# you can use backface culling, if option "use backface culloing" is on.
+# Culling will be set in PolygonMode object of every mesh. The correct
+# winding is controlled.
+# History 0.5
+#* Bone Animation - Armature (Part 1)
+#
+# Armature is the skeleton for skinned meshes. It stores the bones in
+# rest position (more information http://www.blender.org/cms/How_Armatures_work.634.0.html)
+# You can work in Blender with bones and meshes in different ways. In
+# this first attempt only the use of vertex groups is assisted.
+#
+# Blender-Objekts translated into M3G-Objects
+#
+# MESH SkinnedMesh
+# | |
+# v v
+# ARMATURE Group
+# | |
+# v v
+# BONE_1 Group
+# Group_second
+# | |
+# V v
+# BONE_2 Group
+# Group_secound
+#
+# Every bone is translated into two groups at the moment, because
+# the second bone is needed to do the animation in an easy way.
+#
+# The animations in Blender for meshes are stored in action objects.
+#
+# Blender Objects translated into M3G-Objects
+#
+# ARMATURE
+# | activ
+# v
+# ACTION ANIMATIONCONTROLLER
+# | 1..n ^
+# v ANIMATIONTRACK --> Group_second
+# IPOs |
+# v
+# KEYSEQUENZE
+#
+# One action is translated into one animationcontroller. One IPO is
+# translated in one KEYSEQUENZE and one ANIMATIONTRACK.
+#
+# At the moment only the active action of the armature object is translated.
+#
+#* Print Info, if type of light is used that is not supported
+#
+# History 0.5
+#
+#* New Option exportAllAction (default value: false)
+# If that option is true, all actions will be exported - not only the active
+# action.
+# At the moment you can only assign one action to one armature.
+# To know which action is used with which armature the action
+# needs a special name :
+# <Action Name>#A<M3G ID of Armature>E<End Frame>#<ID of Action>
+
+# Example: Name of action : walk#A10E250#02
+# Name of armature : man#10
+# End Frame: 250
+#
+# History 0.6
+# Include the same image only one time into the m3g-file
+#
+# All the following changes of this version was made by Claus Hoefele
+#
+#* Until now all vertices of the faces was been written.
+# Now the vertices will be used again if possible:
+# normal and texture coordinates of to vertices have to be the same
+#
+#* Smooth/solid shading can now be defined for every single material:
+# in Editing panel (F9)>Link and Materials
+#
+#* This script uses now correctly the TexFace and Shadless Buttons in
+# Shading panel (F5)>Material buttons>Material box.
+# TexFace switches on/off the Export of texture coordinates.
+# Shadeless does the some with the normal coordinates
+#
+#* The GUI was redesigned in a PupBlock
+#
+#* Options:
+#
+#** Texturing Enabled: Switches on/off export of textures and texture
+# coordinates. Attention: the TextFace button switches only
+# for one mesh
+#** Texturing External: the textures will be included it mg3-file or
+# exported in seperate file
+#** Lighting Enabled: turns on/off export of lights and normal completly
+# Attention: Shadeless only for one mesh
+#** Persp. Correction: turns on/off perspective correction in PolygonMode.
+#** Smooth Shading: turns on/off smooth shading in PolygonMode.
+#
+#* Textures in external references are used again (with ImageFactory)
+#
+#* Blender function: Double Sided button in Editing Context
+# (F9)>Mesh panel)
+# turn on/off PolygonMode.CULL_BACK anzuschalten.
+#
+#* Script ingnores meshes that have no faces
+#
+# History 0.7
+#
+# * Exporter can work with texture coordinates greater 1 and smaller 0
+#
+# * Adler32 did not work always correct. New implementation made.
+#
+# * Modul shutil is not needed any longer. Exporter has its own copy_file.
+# (realized and inspired by ideasman_42 and Martin Neumann)
+# --------------------------------------------------------------------------#
+# TODO: Export only selected mesh
+# TODO: Optimize Bones <--> Vertex Group mapping
+# TODO: Compressed File
+# TODO: MTex - Support
+# TODO: By Rotating use SQUAD instead of Beziere. It's smoother
+import Blender
+from Blender import Types,Lamp,Material,Texture,Window,Registry,Draw
+from Blender.BGL import *
+from Blender.Object import *
+from Blender.Camera import *
+from Blender.Mesh import *
+from array import array
+import sys, struct, zlib
+from inspect import *
+from types import *
+from Blender.Mathutils import *
+from os.path import *
+#import rpdb2
+
+# ---- Helper Functions -------------------------------------------------------#
+def copy_file(source, dest):
+ file = open(source, 'rb')
+ data = file.read()
+ file.close()
+
+ file = open(dest, 'wb')
+ file.write(data)
+ file.close()
+
+def tracer(frame, event, arg):
+ '''Global trace function'''
+ if event=='call':
+ tmp = getargvalues(frame)
+ print event, frame.f_code.co_name, frame.f_lineno, \
+ formatargvalues(tmp[0],tmp[1],tmp[2],tmp[3])
+ elif event=='line':
+ print event, frame.f_code.co_name, frame.f_lineno
+ #print event, frame.f_code.co_name, frame.f_lineno, \
+ # getsourcelines(frame.f_code)[frame.f_lineno]
+ elif event=='return':
+ print event, frame.f_code.co_name, frame.f_lineno, "->", arg
+ return tracer
+
+def doSearchDeep(inList,outList):
+ '''Does deepsearch for all elements in inList'''
+ for element in inList:
+ if element != None : outList = element.searchDeep(outList)
+ return outList
+
+
+def getId(aObject):
+ ''' returns 0 if Object is None: M3G value for null'''
+ if aObject == None: return 0
+ return aObject.id
+
+def toJavaBoolean(aValue):
+ ''' returns java equivalent to boolean'''
+ if aValue:
+ return 'true'
+ else :
+ return 'false'
+
+def sign(a):
+ if a<0 : return -1
+ elif a>0 : return 1
+ else : return 0
+
+def isOrderClockWise(v,normal):
+ ''' returns true, if order of vertices is clockwise. Important for
+ culling '''
+ # (v2-v0)x(v2-v1)=surface_normal
+ #
+ if type(v[0]) is Types.MVertType:
+ mNormal = TriangleNormal(Vector(v[0].co),Vector(v[1].co),Vector(v[2].co))
+ else:
+ mNormal = TriangleNormal(Vector(v[0]),Vectot(v[1]),Vector(v[2]))
+ #print "normal ",mNormal.normalize()
+ #print "BNormal ",normal.normalize()
+
+ # Do not use any longer. Blender does it correct
+
+ result = (sign(normal.x)==sign(mNormal.x) and
+ sign(normal.y)==sign(mNormal.y) and
+ sign(normal.z)==sign(mNormal.z))
+ #print "Result ",result
+
+ return True
+
+
+# ---- M3G Types --------------------------------------------------------------#
+class M3GVertexList:
+ def __init__(self, wrapList):
+ self.mlist = wrapList
+
+ def __getitem__(self, key):
+ item = self.mlist[key]
+ if type(item) is Types.MVertType:
+ result =(item.co[0],item.co[1],item.co[2])
+ else:
+ result = item
+ return result
+
+class M3GBoneReference:
+ def __init__(self,first,count):
+ self.firstVertex=first #UInt32
+ self.vertexCount=count #UInt32
+
+
+class M3GBone:
+ def __init__(self):
+ self.verts=[] #List of influenced verts
+ self.transformNode=None #ObjectIndex
+ self.references = [] #References to Verts that are needed
+ self.weight=0 #Int32
+
+
+ def setVerts(self,aVerts):
+ self.verts = aVerts
+ self.createReferences()
+
+ def createReferences(self):
+ #print "createReference::len(verts) ",len(self.verts)
+ if len(self.verts)==0: return #No Verts available
+ self.verts.sort()
+ ref = []
+ list = []
+ last = self.verts[0]-1
+ count = 0
+ for vert in self.verts:
+ #print "vert ",vert
+ if vert==last+1:
+ list.append(vert)
+ else:
+ ref.append(M3GBoneReference(list[0],len(list)))
+ #print list[0],len(list)
+ list=[vert]
+ last=vert
+ #print "list ",list
+ if len(list)>0:
+ ref.append(M3GBoneReference(list[0],len(list)))
+ self.references = ref
+
+
+class M3GVector3D:
+ def __init__(self,ax=0.0,ay=0.0,az=0.0):
+ self.x = ax #Float32
+ self.y = ay #Float32
+ self.z = az #Float32
+
+ def writeJava(self):
+ return str(self.x)+"f, "+str(self.y)+"f, "+str(self.z)+"f"
+
+ def getData(self):
+ return struct.pack("<3f",self.x,self.y,self.z)
+
+ def getDataLength(self):
+ return struct.calcsize("<3f")
+
+class M3GMatrix:
+ """ A 4x4 generalized matrix. The 16 elements of the
+ matrix are output in the same order as they are
+ retrieved using the API Transform.get method. In
+ other words, in this order:
+ 0 1 2 3
+ 4 5 6 7
+ 8 9 10 11
+ 12 13 14 15 """
+ def __init__(self):
+ self.elements=16 * [0.0] #Float32
+
+ def identity(self):
+ self.elements[ 0] = 1.0
+ self.elements[ 5] = 1.0
+ self.elements[10] = 1.0
+ self.elements[15] = 1.0
+
+ def getData(self):
+ return struct.pack('<16f',self.elements[0],self.elements[1],
+ self.elements[2],self.elements[3],
+ self.elements[4],self.elements[5],
+ self.elements[6],self.elements[7],
+ self.elements[8],self.elements[9],
+ self.elements[10],self.elements[11],
+ self.elements[12],self.elements[13],
+ self.elements[14],self.elements[15])
+
+ def getDataLength(self):
+ return struct.calcsize('<16f')
+
+
+class M3GColorRGB:
+ """ A color, with no alpha information. Each compo-
+ nent is scaled so that 0x00 is 0.0, and 0xFF is 1.0.
+ """
+ def __init__(self,ared=0,agreen=0,ablue=0):
+ self.red = ared #Byte
+ self.green = agreen #Byte
+ self.blue = ablue #Byte
+
+ def writeJava(self):
+ return "0x"+("%02X%02X%02X%02X" % (0.0, self.red, self.green, self.blue))
+
+ def getData(self):
+ return struct.pack('3B',self.red,self.green,self.blue)
+
+ def getDataLength(self):
+ return struct.calcsize('3B')
+
+
+class M3GColorRGBA:
+ """ A color, with alpha information. Each component
+ is scaled so that 0x00 is 0.0, and 0xFF is 1.0. The
+ alpha value is scaled so that 0x00 is completely
+ transparent, and 0xFF is completely opaque.
+ """
+ def __init__(self,ared=0,agreen=0,ablue=0,aalpha=0):
+ self.red = ared #Byte
+ self.green = agreen #Byte
+ self.blue = ablue #Byte
+ self.alpha = aalpha #Byte
+
+ def writeJava(self):
+ return "0x"+("%02X%02X%02X%02X" % (self.alpha, self.red, self.green, self.blue))
+
+ def getData(self):
+ return struct.pack('4B',self.red,self.green,self.blue,self.alpha)
+
+ def getDataLength(self):
+ return struct.calcsize('4B')
+
+
+#ObjectIndex
+#The index of a previously encountered object in
+#the file. Although this is serialized as a single
+#unsigned integer, it is included in the compound
+#type list because of the additional semantic infor-
+#mation embodied in its type. A value of 0 is
+#reserved to indicate a null reference; actual object indices start from 1. Object indices must refer
+#only to null or to an object which has already been
+#created during the input deserialization of a file -
+#they must be less than or equal to the index of the
+#object in which they appear. Other values are dis-
+#allowed and must be treated as errors.
+#UInt32
+#index;
+
+# ---- M3G Proxy --------------------------------------------------------------- #
+class M3GProxy:
+ def __init__(self):
+ self.name = ""
+ self.id=0
+ self.ObjectType=0
+ self.binaryFormat=''
+
+ def __repr__(self):
+ return "<"+str(self.__class__)[9:] + ":" + str(self.name) + ":" + str(self.id) + ">"
+
+
+class M3GHeaderObject(M3GProxy):
+ def __init__(self):
+ M3GProxy.__init__(self)
+ self.M3GHeaderObject_binaryFormat = '<BBBII'
+ self.ObjectType=0
+ self.id = 1 #Special Object: always 1
+ self.VersionNumber=[1,0] #Byte[2]
+ self.hasExternalReferences=False #Boolean External Files needed? eg. Textures
+ self.TotalFileSize=0 #UInt32
+ self.ApproximateContentSize=0 #UInt32 Only a hint! External sources included
+ self.AuthoringField='Blender M3G Export' #String
+
+ def getData(self):
+ data = struct.pack(self.M3GHeaderObject_binaryFormat,
+ self.VersionNumber[0],
+ self.VersionNumber[1],
+ self.hasExternalReferences,
+ self.TotalFileSize,
+ self.ApproximateContentSize)
+ data += struct.pack(str(len(self.AuthoringField)+1)+'s',self.AuthoringField)
+ return data
+
+ def getDataLength(self):
+ value = struct.calcsize(self.M3GHeaderObject_binaryFormat)
+ return value + struct.calcsize(str(len(self.AuthoringField)+1)+'s')
+
+class M3GExternalReference(M3GProxy):
+ def __init__(self):
+ M3GProxy.__init__(self)
+ self.ObjectType=0xFF
+ self.URI='' #reference URI
+
+ def getData(self):
+ data = struct.pack(str(len(self.URI)+1) + 's', self.URI)
+ return data
+
+ def getDataLength(self):
+ return struct.calcsize(str(len(self.URI)+1)+'s')
+
+ def searchDeep(self,alist):
+ if not(self in alist): alist.append(self)
+ return alist
+
+ def __repr__(self):
+ return M3GProxy.__repr__(self) + " (" + self.URI + ")"
+
+
+class M3GObject3D(M3GProxy):
+ def __init__(self):
+ M3GProxy.__init__(self)
+ self.userID=0 #UInt32 - field may be any value
+ self.animationTracks=[] #ObjectIndex[]
+ self.userParameterCount=0 #UInt32 - No user parameter used
+
+ def searchDeep(self,alist):
+ alist = doSearchDeep(self.animationTracks,alist)
+ if not(self in alist): alist.append(self)
+ return alist
+
+ def getData(self):
+ data = struct.pack('<I',self.userID)
+ print "write userID",self.userID,self.name,str(self), self.getDataLength()
+ data += struct.pack('<I',len(self.animationTracks))
+ for element in self.animationTracks:
+ data += struct.pack('<I',getId(element))
+ data += struct.pack('<I',self.userParameterCount)
+ return data
+
+ def getDataLength(self):
+ value = struct.calcsize('<3I')
+ if len(self.animationTracks) > 0:
+ value += struct.calcsize('<'+str(len(self.animationTracks))+'I')
+ return value
+
+ def writeJava(self,aWriter,aCreate):
+ if aCreate : pass #Abstract! Could not be created
+ if len(self.animationTracks) > 0 :
+ aWriter.write(2)
+ for iTrack in self.animationTracks:
+ aWriter.write(2,"BL%i.addAnimationTrack(BL%i);" % (self.id,iTrack.id))
+
+
+class M3GTransformable(M3GObject3D):
+ def __init__(self):
+ M3GObject3D.__init__(self)
+ self.hasComponentTransform=False #Boolean
+ #IF hasComponentTransform==TRUE, THEN
+ self.translation=M3GVector3D(0,0,0) #Vector3D
+ self.scale=M3GVector3D(1,1,1) #Vector3D
+ self.orientationAngle=0 #Float32
+ self.orientationAxis=M3GVector3D(0,0,0) #Vector3D undefined
+ #END
+ self.hasGeneralTransform=False #Boolean
+ #IF hasGeneralTransform==TRUE, THEN
+ self.transform = M3GMatrix() #Matrix identity
+ self.transform.identity()
+ #END
+ #If either hasComponentTransform or hasGeneralTransform is false, the omitted fields will be
+ #initialized to their default values (equivalent to an identity transform in both cases).
+
+ def writeJava(self,aWriter,aCreate):
+ if aCreate: pass #Abstract Base Class! Cant't be created
+ M3GObject3D.writeJava(self,aWriter,False)
+ if self.hasGeneralTransform :
+ aWriter.write(2,"float[] BL%i_matrix = {" % (self.id))
+ aWriter.writeList(self.transform.elements,4,"f")
+ aWriter.write(2,"};")
+ aWriter.write(2)
+ aWriter.write(2,"Transform BL%i_transform = new Transform();" % (self.id))
+ aWriter.write(2,"BL%i_transform.set(BL%i_matrix);" % (self.id,self.id))
+ aWriter.write(2,"BL%i.setTransform(BL%i_transform);" % (self.id,self.id))
+ aWriter.write(2)
+ if self.hasComponentTransform:
+ aWriter.write(2,("BL%i.setTranslation("+self.translation.writeJava()+");")
+ %(self.id))
+
+ def getData(self):
+ data = M3GObject3D.getData(self)
+ data += struct.pack("<B",self.hasComponentTransform)
+ if self.hasComponentTransform==True:
+ data += self.translation.getData()
+ data += self.scale.getData()
+ data += struct.pack('<f',self.orientationAngle)
+ data += self.orientationAxis.getData()
+ data += struct.pack("<B",self.hasGeneralTransform)
+ if self.hasGeneralTransform==True:
+ data += self.transform.getData()
+ return data
+
+ def getDataLength(self):
+ value = M3GObject3D.getDataLength(self)
+ value += struct.calcsize("<B")
+ if self.hasComponentTransform==True:
+ value += self.translation.getDataLength()
+ value += self.scale.getDataLength()
+ value += struct.calcsize('<f')
+ value += self.orientationAxis.getDataLength()
+ value += struct.calcsize("<B")
+ if self.hasGeneralTransform==True:
+ value += self.transform.getDataLength()
+ return value
+
+
+class M3GNode(M3GTransformable):
+ def __init__(self):
+ M3GTransformable.__init__(self)
+ self.blenderObj = None #Pointer to corrsponding BlenderObj
+ self.parentBlenderObj = None #Pointer to Parent in Blender
+ self.blenderMatrixWorld = None #BlenderObj matrixWorld
+ self.M3GNode_binaryFormat = '<BBBIB'
+ self.enableRendering=True #Boolean
+ self.enablePicking=True #Boolean
+ self.alphaFactor=255 #Byte 0x00 is equivalent to 0.0 (fully transparent), and 255 is equivalent to 1.0 (fully opaque);
+ self.scope=4294967295 #-1 #UInt32
+ self.hasAlignment = False #Boolean
+ #IF hasAlignment==TRUE, THEN
+ self.M3GNode_binaryFormat_2 = '<BBII'
+ self.zTarget=0 #Byte The zTarget and yTarget fields must each hold a valid enumerated value,
+ self.yTarget=0 #Byte as specified in the class definition. Other values must be treated as errors.
+ self.zReference=None #ObjectIndex
+ self.yReference=None #ObjectIndex
+ #END
+ #If the hasAlignment field is false, the omitted fields are initialized to their default values.
+
+
+ def getData(self):
+ data = M3GTransformable.getData(self)
+ #print "Binary ",self.binaryFormat
+ data += struct.pack(self.M3GNode_binaryFormat,
+ self.enableRendering,
+ self.enablePicking,
+ self.alphaFactor,
+ self.scope,
+ self.hasAlignment)
+
+ if self.hasAlignment:
+ data += pack(self.M3GNode_binaryFormat_2,
+ self.zTarget,
+ self.yTarget,
+ getId(self.zReference),
+ getId(self.yReference))
+ return data
+
+ def getDataLength(self):
+ value = M3GTransformable.getDataLength(self) + \
+ struct.calcsize(self.M3GNode_binaryFormat)
+ if self.hasAlignment:
+ value += struct.calcsize(self.M3GNode_binaryFormat_2)
+ return value
+
+ def writeJava(self,aWriter,aCreate):
+ if aCreate: pass #Abstract Base Class! Cant't be created
+ M3GTransformable.writeJava(self,aWriter,False)
+
+class M3GGroup(M3GNode):
+ def __init__(self):
+ M3GNode.__init__(self)
+ self.ObjectType=9
+ self.children = [] #ObjectIndex[]
+
+ def searchDeep(self,alist):
+ for element in self.children:
+ alist = element.searchDeep(alist)
+ return M3GNode.searchDeep(self,alist)
+
+ def writeJava(self,aWriter,aCreate):
+ if aCreate:
+ aWriter.write(2,"//Group:"+self.name )
+ aWriter.write(2,"Group BL"+str(self.id)+" = new Group();")
+ M3GNode.writeJava(self,aWriter,False)
+ for element in self.children:
+ aWriter.write(2,"BL%i.addChild(BL%i);" % (self.id,element.id))
+
+ def getData(self):
+ data = M3GNode.getData(self)
+ data = data + struct.pack("<I",len(self.children))
+ for element in self.children:
+ data += struct.pack("<I",getId(element))
+ return data
+
+ def getDataLength(self):
+ return M3GNode.getDataLength(self)+ \
+ struct.calcsize("<"+str(len(self.children)+1)+"I")
+
+
+class M3GWorld(M3GGroup):
+ def __init__(self):
+ M3GGroup.__init__(self)
+ self.ObjectType=22
+ self.activeCamera=None #ObjectIndex
+ self.background=None #ObjectIndex UInt32 0=None
+ self.M3GWorld_binaryFormat='<II'
+
+ def searchDeep(self,alist):
+ alist = doSearchDeep([self.activeCamera, self.background],alist)
+ return M3GGroup.searchDeep(self,alist)
+
+
+ def writeJava(self,aWriter,aCreate):
+ if aCreate:
+ aWriter.write(2,"//World:"+self.name )
+ aWriter.write(2,"World BL"+str(self.id)+" = new World();")
+ M3GGroup.writeJava(self,aWriter,False)
+ if self.background != None:
+ aWriter.write(2,"BL"+str(self.id)+".setBackground(BL"+str(self.background.id)+");")
+ if self.activeCamera != None:
+ aWriter.write(2,"BL%i.setActiveCamera(BL%i);" %
+ (self.id,self.activeCamera.id))
+ aWriter.write(2)
+
+
+ def getData(self):
+ data = M3GGroup.getData(self)
+ return data + \
+ struct.pack(self.M3GWorld_binaryFormat,getId(self.activeCamera),getId(self.background))
+
+
+ def getDataLength(self):
+ return M3GGroup.getDataLength(self) + struct.calcsize(self.M3GWorld_binaryFormat)
+
+
+class M3GBackground(M3GObject3D):
+ def __init__(self):
+ M3GObject3D.__init__(self)
+ self.ObjectType=4
+ self.M3GBackground_binaryFormat = '<BBiiiiBB'
+ self.backgroundColor=M3GColorRGBA(0,0,0,0) #ColorRGBA 0x00000000 (black, transparent)
+ self.backgroundImage=None #ObjectIndex null (use the background color only)
+ self.backgroundImageModeX=32; #Byte BORDER=32 REPEAT=33
+ self.backgroundImageModeY=32; #Byte BORDER
+ self.cropX = 0; #Int32
+ self.cropY = 0 #Int32 ;
+ self.cropWidth = 0 #Int32 ;
+ self.cropHeight = 0;#Int32
+ self.depthClearEnabled = True #Boolean
+ self.colorClearEnabled = True #Boolean
+
+ def writeJava(self,aWriter,aCreate):
+ if aCreate:
+ aWriter.write(2,"//Background:"+self.name )
+ aWriter.write(2,"Background BL"+str(self.id)+" = new Background();")
+ M3GObject3D.writeJava(self,aWriter,False)
+ aWriter.write(2,"BL"+str(self.id)+".setColor("+self.backgroundColor.writeJava()+");")
+ aWriter.write(2,"")
+
+ def getData(self):
+ data = M3GObject3D.getData(self)
+ data += self.backgroundColor.getData()
+ data += struct.pack('<I',getId(self.backgroundImage))
+ data += struct.pack(self.M3GBackground_binaryFormat, self.backgroundImageModeX,
+ self.backgroundImageModeY,
+ self.cropX,
+ self.cropY,
+ self.cropWidth,
+ self.cropHeight,
+ self.depthClearEnabled,
+ self.colorClearEnabled)
+ return data
+
+ def getDataLength(self):
+ value=M3GObject3D.getDataLength(self)
+ value += self.backgroundColor.getDataLength()
+ value += struct.calcsize('<I')
+ value += struct.calcsize(self.M3GBackground_binaryFormat)
+ return value
+
+
+class M3GCamera(M3GNode):
+ GENERIC=48 #Projection-Types
+ PARALLEL=49
+ PERSPECTIVE=50
+
+ def __init__(self):
+ M3GNode.__init__(self)
+ self.ObjectType=5
+ self.projectionType=M3GCamera.PARALLEL #Byte
+ #IF projectionType==GENERIC, THEN
+ self.projectionMatrix=M3GMatrix() #Matrix •view volume : opposite corners at (-1 -1 -1) and (1 1 1)
+ # TODO: Set right matrix
+ #ELSE
+ self.fovy=0.0 #Float32
+ self.AspectRatio=0.0#Float32
+ self.near=0.0#Float32
+ self.far=0.0#Float32
+ #END
+
+ def writeJava(self,aWriter,aCreate):
+ if aCreate:
+ aWriter.write(2,"//Camera " + self.name)
+ aWriter.write(2,"Camera BL%i = new Camera();" % (self.id))
+ M3GNode.writeJava(self,aWriter,False)
+ aWriter.write(2,"BL%i.setPerspective(%ff, //Field of View" % \
+ (self.id,self.fovy))
+ aWriter.write(4,"(float)aCanvas.getWidth()/(float)aCanvas.getHeight(),")
+ aWriter.write(4,str(self.near)+"f, //Near Clipping Plane")
+ aWriter.write(4,str(self.far)+"f); //Far Clipping Plane")
+
+ def getData(self):
+ data = M3GNode.getData(self)
+ data += struct.pack("B",self.projectionType)
+ if self.projectionType == self.GENERIC:
+ data += self.projectionMatrix.getData()
+ else:
+ data += struct.pack("<4f",self.fovy,self.AspectRatio,self.near,self.far)
+ return data
+
+ def getDataLength(self):
+ value = M3GNode.getDataLength(self)
+ value += struct.calcsize("B")
+ if self.projectionType == self.GENERIC:
+ value += self.projectionMatrix.getDataLength()
+ else:
+ value += struct.calcsize("<4f")
+ return value
+
+
+class M3GMesh(M3GNode):
+ def __init__(self,aVertexBuffer=None, aIndexBuffer=[], aAppearance=[]):
+ M3GNode.__init__(self)
+ self.ObjectType=14
+ self.vertexBuffer = aVertexBuffer #ObjectIndex
+ self.submeshCount=len(aIndexBuffer) #UInt32
+ #FOR each submesh...
+ self.indexBuffer=aIndexBuffer #ObjectIndex
+ self.appearance=aAppearance #;ObjectIndex
+ #END
+
+ def getData(self):
+ data = M3GNode.getData(self)
+ data += struct.pack('<2I', getId(self.vertexBuffer),
+ self.submeshCount)
+ for i in range(len(self.indexBuffer)):
+ data += struct.pack('<2I',getId(self.indexBuffer[i]),
+ getId(self.appearance[i]))
+ return data
+
+ def getDataLength(self):
+ value = M3GNode.getDataLength(self)
+ value += struct.calcsize('<2I')
+ for i in range(len(self.indexBuffer)):
+ value += struct.calcsize('<2I')
+ return value
+
+ def searchDeep(self,alist):
+ alist = doSearchDeep([self.vertexBuffer] +self.indexBuffer
+ + self.appearance ,alist)
+ return M3GNode.searchDeep(self,alist)
+
+ def writeJava(self,aWriter,aCreate):
+ self.writeBaseJava(aWriter,aCreate,"Mesh","")
+
+ def writeBaseJava(self,aWriter,aCreate,aClassName,aExtension):
+ if aCreate:
+ aWriter.writeClass(aClassName,self)
+ if self.submeshCount > 1:
+ aWriter.write(2,"IndexBuffer[] BL%i_indexArray = {" % (self.id))
+ aWriter.write(4,",".join(["BL%i" %(i.id) for i in self.indexBuffer ]))
+ aWriter.write(2," };")
+ aWriter.write(2)
+ aWriter.write(2,"Appearance[] BL%i_appearanceArray = {" % (self.id))
+ aWriter.write(4,",".join(["BL%i" %(i.id) for i in self.appearance ]))
+ aWriter.write(2," };")
+ aWriter.write(2)
+ aWriter.write(2,"%s BL%i = new %s(BL%i,BL%i_indexArray,BL%i_appearanceArray%s);" % \
+ (aClassName,self.id,aClassName,self.vertexBuffer.id, self.id,self.id,aExtension))
+ else:
+ #print "indexBuffer", len(self.indexBuffer)
+ #print "appearance", len(self.appearance)
+ aWriter.write(2,"%s BL%i = new %s(BL%i,BL%i,BL%i%s);" % \
+ (aClassName,
+ self.id,
+ aClassName,
+ self.vertexBuffer.id,
+ self.indexBuffer[0].id,
+ self.appearance[0].id,
+ aExtension))
+ M3GNode.writeJava(self,aWriter,False)
+ aWriter.write(2)
+
+
+class M3GSkinnedMesh(M3GMesh):
+ def __init__(self,aVertexBuffer=None, aIndexBuffer=[], aAppearance=[]):
+ M3GMesh.__init__(self,aVertexBuffer, aIndexBuffer, aAppearance)
+ self.ObjectType=16
+ self.skeleton=None #ObjectIndex
+ self.bones={}
+ #print"M3GSkinnedMesh.__init__::self.vertexBuffer:",self.vertexBuffer
+ ##ObjectIndex skeleton;
+ ##UInt32 transformReferenceCount;
+ ##FOR each bone reference...
+ ## ObjectIndex transformNode;
+ ## UInt32 firstVertex;
+ ## UInt32 vertexCount;
+ ## Int32 weight;
+ ##END
+
+ def searchDeep(self,alist):
+ alist = doSearchDeep([self.skeleton],alist)
+ return M3GMesh.searchDeep(self,alist)
+
+ def addSecondBone(self):
+ secondBones = {}
+ for bone in self.bones.values():
+ bone2 = M3GBone()
+ bone2.verts=bone.verts
+ bone.verts=[]
+ mGroup = M3GGroup()
+ mGroup.name=bone.transformNode.name+"_second"
+ bone2.transformNode=mGroup
+ bone2.references = bone.references
+ bone.references = []
+ bone2.weight = bone.weight
+ bone.weight=0
+ mGroup.children = bone.transformNode.children
+ bone.transformNode.children = [mGroup]
+ mGroup.animationTracks=bone.transformNode.animationTracks
+ bone.transformNode.animationTracks = []
+ secondBones[bone.transformNode.name+"_second"]=bone2
+ for bone in secondBones.values():
+ self.bones[bone.transformNode.name] = bone
+
+ def getBlenderIndexes(self):
+ #print "M3GSkinnedMesh.vertexBuffer:",self.vertexBuffer
+ return self.vertexBuffer.positions.blenderIndexes
+
+ def writeJava(self,aWriter,aCreate):
+ self.writeBaseJava(aWriter,aCreate,"SkinnedMesh",
+ (",BL%i" % (self.skeleton.id)))
+ aWriter.write(2,"//Transforms")
+ for bone in self.bones.values():
+ #print "bone: ", bone
+ #print "bone.references: ", bone.references
+ for ref in bone.references:
+ aWriter.write(2,"BL%i.addTransform(BL%i,%i,%i,%i);" %
+ (self.id,
+ bone.transformNode.id,bone.weight,
+ ref.firstVertex, ref.vertexCount))
+ aWriter.write(2)
+
+ def getDataLength(self):
+ value = M3GMesh.getDataLength(self)
+ value += struct.calcsize('<I') #skeleton
+ value += struct.calcsize('<I') #transformReferenceCount
+ for bone in self.bones.values():
+ for ref in bone.references:
+ value += struct.calcsize('<3Ii')
+ return value
+
+ def getData(self):
+ data = M3GMesh.getData(self)
+ data += struct.pack('<I', getId(self.skeleton))
+ count = 0
+ for bone in self.bones.values(): count+=len(bone.references)
+ data += struct.pack('<I',count)
+ for bone in self.bones.values():
+ for ref in bone.references:
+ data += struct.pack('<I',getId(bone.transformNode))
+ data += struct.pack('<2I',ref.firstVertex,ref.vertexCount)
+ data += struct.pack('<i',bone.weight)
+ return data
+
+class M3GLight(M3GNode):
+ def __init__(self):
+ M3GNode.__init__(self)
+ self.ObjectType=12
+ self.modes = {'AMBIENT':128,
+ 'DIRECTIONAL':129,
+ 'OMNI':130,
+ 'SPOT':131}
+ self.attenuationConstant = 1.0 #Float32
+ self.attenuationLinear = 0.0 #Float32
+ self.attenuationQuadratic = 0.0 #Float32
+ self.color = M3GColorRGB(1.0, 1.0, 1.0) #ColorRGB
+ self.mode = self.modes['DIRECTIONAL'] #Byte Enumurator mode: DIRECTIONAL
+ self.intensity = 1.0 #Float32
+ self.spotAngle = 45 #Float32
+ self.spotExponent = 0.0 #Float32
+
+ def writeJava(self,aWriter,aCreate):
+ if aCreate:
+ aWriter.write(2,"//Light: " + self.name)
+ aWriter.write(2,"Light BL%i = new Light();" % (self.id))
+ aWriter.write(2,"BL%i.setMode(%i);" % (self.id,self.mode)) #Light.OMNI
+ if self.mode in [self.modes['OMNI'],self.modes['SPOT']]:#Attenuation
+ aWriter.write(2,"BL%i.setAttenuation(%ff, %ff,%ff);"
+ % (self.id,
+ self.attenuationConstant,
+ self.attenuationLinear,
+ self.attenuationQuadratic))
+ aWriter.write(2,("BL%i.setColor("+self.color.writeJava()+");")
+ % (self.id))
+ aWriter.write(2,"BL%i.setIntensity(%ff);"
+ % (self.id,self.intensity))
+ if self.mode == self.modes['SPOT']:
+ aWriter.write(2,"BL%i.setSpotAngle(%ff);"
+ % (self.id,self.spotAngle))
+ aWriter.write(2,"BL%i.setSpotExponent(%ff);"
+ % (self.id,self.spotExponent))
+ M3GNode.writeJava(self,aWriter,False)
+ aWriter.write(2)
+
+
+ def getData(self):
+ data = M3GNode.getData(self)
+ data += struct.pack("<fff", self.attenuationConstant,
+ self.attenuationLinear,
+ self.attenuationQuadratic)
+ data += self.color.getData()
+ data += struct.pack("<Bfff", self.mode,
+ self.intensity,
+ self.spotAngle,
+ self.spotExponent)
+ return data
+
+ def getDataLength(self):
+ value = M3GNode.getDataLength(self)
+ value += self.color.getDataLength()
+ value += struct.calcsize('<B6f')
+ return value
+
+class M3GMaterial(M3GObject3D):
+ def __init__(self):
+ M3GObject3D.__init__(self)
+ self.ObjectType=13
+ self.ambientColor=M3GColorRGB(0.2, 0.2, 0.2) #ColorRGB
+ self.diffuseColor=M3GColorRGBA(0.8, 0.8, 0.8, 1.0) #ColorRGBA
+ self.emissiveColor=M3GColorRGB(0.0, 0.0, 0.0) #ColorRGB
+ self.specularColor=M3GColorRGB(0.0, 0.0, 0.0) #ColorRGB
+ self.shininess=0.0 #Float32
+ self.vertexColorTrackingEnabled=False #Boolean
+
+ def writeJava(self,aWriter,aCreate):
+ if aCreate :
+ aWriter.write(2,"//Material: "+self.name )
+ aWriter.write(2,"Material BL%i = new Material();" % (self.id))
+ aWriter.write(2,("BL%i.setColor(Material.AMBIENT," +
+ self.ambientColor.writeJava()+");") % (self.id) )
+ aWriter.write(2,("BL%i.setColor(Material.SPECULAR," +
+ self.specularColor.writeJava()+");") % (self.id) )
+ aWriter.write(2,("BL%i.setColor(Material.DIFFUSE," +
+ self.diffuseColor.writeJava()+");") % (self.id))
+ aWriter.write(2,("BL%i.setColor(Material.EMISSIVE," +
+ self.emissiveColor.writeJava()+");") % (self.id))
+ aWriter.write(2,("BL%i.setShininess(%ff);") % (self.id,self.shininess))
+ aWriter.write(2,("BL%i.setVertexColorTrackingEnable(" +
+ toJavaBoolean(self.vertexColorTrackingEnabled) + ");") %
+ (self.id))
+ M3GObject3D.writeJava(self,aWriter,False)
+
+ def getData(self):
+ data = M3GObject3D.getData(self)
+ data += self.ambientColor.getData()
+ data += self.diffuseColor.getData()
+ data += self.emissiveColor.getData()
+ data += self.specularColor.getData()
+ data += struct.pack('<fB',self.shininess,
+ self.vertexColorTrackingEnabled)
+ return data
+
+
+ def getDataLength(self):
+ value = M3GObject3D.getDataLength(self)
+ value += self.ambientColor.getDataLength()
+ value += self.diffuseColor.getDataLength()
+ value += self.emissiveColor.getDataLength()
+ value += self.specularColor.getDataLength()
+ value += struct.calcsize('<fB')
+ return value
+
+
+class M3GVertexArray(M3GObject3D):
+ def __init__(self,aNumComponents,aComponentSize,aAutoScaling=False,aUVMapping=False):
+ M3GObject3D.__init__(self)
+ self.ObjectType=20
+ self.blenderIndexes={} #Translation-Table from Blender index to m3g index
+ self.autoscaling = aAutoScaling #bias and scale should be computed internal
+ self.uvmapping=aUVMapping #Change coordinates from blender uv to uv-m3g
+ self.bias = [0.0,0.0,0.0]
+ self.scale = 1.0
+ self.componentSize=aComponentSize #Byte number of bytes per component; must be [1, 2]
+ self.componentCount=aNumComponents #Byte number of components per vertex; must be [2, 4]
+ self.encoding=0 #Byte 0="raw" as bytes or 16 bit integers.
+ self.vertexCount=0 #UInt16 number of vertices in this VertexArray; must be [1, 65535]
+ if self.autoscaling==True:
+ self.components = array('f')
+ else:
+ self.components = self.createComponentArray()
+ #FOR each vertex...
+ # IF componentSize==1, THEN
+ # IF encoding==0, THEN
+ # Byte[componentCount]
+ # ELSE IF encoding==1, THEN
+ # Byte[componentCount]
+ # END
+ # ELSE
+ # IF encoding==0, THEN
+ # Int16[componentCount]
+ # ELSE IF encoding==1, THEN
+ # Int16[componentCount]
+ # END
+ # END
+ #END
+
+ def createComponentArray(self):
+ if self.componentSize == 1:
+ return array('b') #Byte-Array
+ else:
+ return array('h') #Short-Array
+
+ def useMaxPrecision(self,aBoundingBox):
+ """With Bias and Scale you can maximize the precision of the array"""
+ #print "useMaxPrecision"
+ vertexList = M3GVertexList(aBoundingBox)
+ first = vertexList[0]
+ minimum =[first[0],first[1],first[2]]
+ maximum = [first[0],first[1],first[2]] #Search maximal Dimension
+ for element in vertexList:
+ for i in range(3):
+ if minimum[i] > element[i] : minimum[i] = element[i]
+ if maximum[i] < element[i] : maximum[i] = element[i]
+ #print i, maximum[i],element[i]
+ lrange=[0,0,0]
+ maxRange=0.0
+ maxDimension=-1
+ for i in range(3): #set bias
+ lrange[i] = maximum[i]-minimum[i]
+ self.bias[i] = minimum[i]*0.5+maximum[i]*0.5
+ #print "Bias",i,self.bias[i],"min-max",minimum[i],maximum[i],"lrang",lrange[i]
+ if lrange[i] > maxRange:
+ maxRange = lrange[i]
+ maxDimension=i
+ self.scale = maxRange/65533.0
+ #print "MaxRange ",maxRange
+ #print "scale",self.scale
+
+
+ def internalAutoScaling(self):
+ print "internalAutoScaling"
+ #Already done?
+ print self.components.typecode
+ if not self.autoscaling or self.components.typecode!="f":return
+ #Find bais and scale
+ minimum=[]
+ maximum=[]
+ for i in range(self.componentCount):
+ minimum.append(self.components[i])
+ maximum.append(self.components[i])
+ for i in range(0,len(self.components),self.componentCount):
+ for j in range(self.componentCount):
+ if minimum[j] > self.components[i+j] : minimum[j] = self.components[i+j]
+ if maximum[j] < self.components[i+j] : maximum[j] = self.components[i+j]
+ #print "i+j=",i+j,"min=",minimum[j],"max=",maximum[j],"elem=",self.components[i+j]
+ #print "min=", minimum
+ #print "max=", maximum
+ lrange=[0] * self.componentCount
+ maxRange=0.0
+ maxDimension=-1
+ for i in range(self.componentCount): #set bias
+ lrange[i] = maximum[i]-minimum[i]
+ self.bias[i] = minimum[i]*0.5+maximum[i]*0.5
+ #print "Bias",i,self.bias[i],"min-max",minimum[i],maximum[i],"lrang",lrange[i]
+ if lrange[i] > maxRange:
+ maxRange = lrange[i]
+ maxDimension=i
+ maxValue=(2**(8*self.componentSize)*1.0)-2.0
+ #print "MaxValue=",maxValue
+ self.scale = maxRange/maxValue
+ #print "MaxRange ",maxRange
+ #print "scale",self.scale
+ #Copy Components
+ oldArray=self.components
+ self.components=self.createComponentArray()
+ for i in range(0,len(oldArray),self.componentCount):
+ for j in range(self.componentCount):
+ element=int((oldArray[i+j]-self.bias[j])/self.scale)
+ #print "element",element
+ self.components.append(element)
+ # Reverse t coordinate because M3G uses a different 2D coordinate system than Blender.
+ if self.uvmapping:
+ for i in range(0,len(self.components),2):
+ self.components[i]= int(self.components[i]*(-1))
+ for i in range(len(self.components)):
+ if abs(self.components[i])>maxValue:raise Exception( i+". element too great/small!")
+
+ def writeJava(self,aWriter,aCreate):
+ self.internalAutoScaling()
+ if aCreate:
+ aWriter.write(2,"// VertexArray " + self.name)
+ if self.componentSize == 1:
+ aWriter.write(2,"byte[] BL%i_array = {" % (self.id))
+ else:
+ aWriter.write(2,"short[] BL%i_array = {" % (self.id))
+ aWriter.writeList(self.components)
+ aWriter.write(2,"};")
+ aWriter.write(2)
+ aWriter.write(2,"VertexArray BL%i = new VertexArray(BL%i_array.length/%i,%i,%i);" %
+ (self.id,self.id,
+ self.componentCount,self.componentCount,self.componentSize))
+ aWriter.write(2,"BL%i.set(0,BL%i_array.length/%i,BL%i_array);" %
+ (self.id,self.id,self.componentCount,self.id))
+ M3GObject3D.writeJava(self,aWriter,False)
+ aWriter.write(2)
+
+
+ def getData(self):
+ self.internalAutoScaling()
+ self.vertexCount = len(self.components)/self.componentCount
+ data = M3GObject3D.getData(self)
+ data += struct.pack('<3BH',self.componentSize,
+ self.componentCount,
+ self.encoding,
+ self.vertexCount)
+ componentType = ""
+ if self.componentSize == 1:
+ componentType = "b"
+ else:
+ componentType = "h"
+ for element in self.components:
+ data += struct.pack('<'+componentType,element)
+ return data
+
+ def getDataLength(self):
+ self.internalAutoScaling()
+ value = M3GObject3D.getDataLength(self)
+ value += struct.calcsize('<3BH')
+ componentType = ""
+ if self.componentSize == 1:
+ componentType = "b"
+ else:
+ componentType = "h"
+ value += struct.calcsize('<'+str(len(self.components))+componentType)
+ return value
+
+ def append(self,element,index=None):
+ #print "type(element):",type(element)
+ if type(element) is Types.vectorType :
+ for i in range(3):
+ value = int((element[i]-self.bias[i])/self.scale)
+ #print "append:",i,element[i],(element[i]-self.bias[i]),value
+ self.components.append(value)
+ elif type(element) is Types.MVertType:
+ for i in range(3):
+ value = int((element.co[i]-self.bias[i])/self.scale)
+ #print "append:",i,element[i],(element[i]-self.bias[i]),value
+ self.components.append(value)
+ if index!=None:
+ key=str(len(self.blenderIndexes))
+ #print"key,index:",key,index
+ self.blenderIndexes[key]=index
+ #print"blenderIndexes",self.blenderIndexes
+ else:
+ # print "VertexArray.append: element=",element
+ self.components.append(element)
+
+class M3GVertexBuffer(M3GObject3D):
+ def __init__(self):
+ M3GObject3D.__init__(self)
+ self.ObjectType=21
+ self.defaultColor=M3GColorRGBA(255,255,255) #ColorRGBA 0xFFFFFFFF (opaque white).
+ self.positions = None #ObjectIndex
+ self.positionBias = [0.0,0.0,0.0] #Float32[3]
+ self.positionScale = 1.0 #Float32
+ self.normals = None #ObjectIndex
+ self.colors = None #ObjectIndex
+ self.texCoordArrays = []
+ self.texcoordArrayCount = 0 #UInt32
+## #FOR each texture coordinate array...
+## self.texCoords = [] #ObjectIndex
+## self.texCoordBias=[] #Float32[3]
+## self.texCoordScale=[] #;Float32
+## #END
+## #If a texture coordinate array has only two components, the corresponding texCoordBias[2] element
+## #must be 0.0.
+## #Null texture coordinate arrays are never serialized, regardless of their position. A single texture
+## #coordinate array will therefore always be serialized as belonging to texturing unit 0, regardless of
+## #its original unit it was assigned to.
+## #There are as many references in the texture coordinates array as there are active texture units for
+## #this geometry. The texture coordinate references are loaded sequentially from texture unit 0. If the
+## #implementation supports more texture units than are specified, these are left in their default, inactive
+## #state, with a null texture coordinate reference and an undefined bias and scale.
+## #If more texture coordinate references are specified than are supported by the implementation, then
+## #this must be treated as an error, as it would be in the API. The application can then decide on an
+## #appropriate course of action to handle this case.
+
+ def searchDeep(self,alist):
+ if self.positions!=None: alist = self.positions.searchDeep(alist)
+ if self.normals != None: alist = self.normals.searchDeep(alist)
+ if self.colors!= None: alist = self.colors.searchDeep(alist)
+ alist = doSearchDeep(self.texCoordArrays, alist)
+ return M3GObject3D.searchDeep(self,alist)
+
+ def setPositions(self,aVertexArray):
+ self.positions = aVertexArray
+ self.positionBias = aVertexArray.bias
+ self.positionScale = aVertexArray.scale
+
+ def writeJava(self,aWriter,aCreate):
+ if aCreate:
+ aWriter.write(2,"//VertexBuffer"+self.name )
+ aWriter.write(2,"VertexBuffer BL%i = new VertexBuffer();" % (self.id))
+ aWriter.write(2,"float BL%i_Bias[] = { %ff, %ff, %ff};" %
+ (self.id,self.positionBias[0],
+ self.positionBias[1],self.positionBias[2]))
+ aWriter.write(2,"BL%i.setPositions(BL%i,%ff,BL%i_Bias);" %
+ (self.id, self.positions.id,
+ self.positionScale,self.id))
+ aWriter.write(2,"BL%i.setNormals(BL%i);" % (self.id,self.normals.id))
+ #if self.colors != None: aWriter.write(2,"BL%i.setTexCoords(0,BL%i,1.0f,null);" %
+ # (self.id,self.colors.id))
+ lIndex = 0
+ for iTexCoord in self.texCoordArrays:
+ aWriter.write(2,"float BL%i_%i_TexBias[] = { %ff, %ff, %ff};" %
+ (self.id,lIndex, iTexCoord.bias[0],
+ iTexCoord.bias[1],iTexCoord.bias[2]))
+ #int index, javax.microedition.m3g.VertexArray194 texCoords, float scale, float[] bias
+ aWriter.write(2,"BL%i.setTexCoords(%i,BL%i,%ff,BL%i_%i_TexBias);" %
+ (self.id, lIndex, iTexCoord.id, iTexCoord.scale,self.id,lIndex))
+ lIndex += 1
+
+ M3GObject3D.writeJava(self,aWriter,False)
+
+
+ def getData(self):
+ self.texcoordArrayCount = len(self.texCoordArrays)
+ data = M3GObject3D.getData(self)
+ data += self.defaultColor.getData()
+ data += struct.pack('<I4f3I',getId(self.positions),
+ self.positionBias[0],
+ self.positionBias[1],
+ self.positionBias[2],
+ self.positionScale,
+ getId(self.normals),
+ getId(self.colors),
+ self.texcoordArrayCount)
+ for iTexCoord in self.texCoordArrays:
+ data += struct.pack('<I', getId(iTexCoord))
+ data += struct.pack('<ffff', iTexCoord.bias[0],
+ iTexCoord.bias[1],
+ iTexCoord.bias[2],
+ iTexCoord.scale)
+ return data
+
+
+ def getDataLength(self):
+ value = M3GObject3D.getDataLength(self)
+ value += self.defaultColor.getDataLength()
+ value += struct.calcsize('<I4f3I')
+ value += struct.calcsize('<Iffff') * len(self.texCoordArrays)
+ return value
+
+
+class M3GPolygonMode(M3GObject3D):
+ CULL_BACK=160
+ CULL_NONE=162
+ SHADE_FLAT=164
+ SHADE_SMOOTH=165
+ WINDING_CCW=168
+ WINDING_CW=169
+
+ def __init__(self):
+ M3GObject3D.__init__(self)
+ self.ObjectType=8
+ self.culling=M3GPolygonMode.CULL_BACK #Byte
+ self.shading=M3GPolygonMode.SHADE_SMOOTH #Byte
+ self.winding=M3GPolygonMode.WINDING_CCW #Byte
+ self.twoSidedLightingEnabled = False #Boolean
+ self.localCameraLightingEnabled = False #Boolean
+ self.perspectiveCorrectionEnabled = False #Boolean
+
+ def writeJava(self,aWriter,aCreate):
+ if aCreate:
+ aWriter.write(2,"PolygonMode BL%i = new PolygonMode();" % (self.id))
+ aWriter.write(2,"BL%i.setCulling(%i);" % (self.id,self.culling))
+ aWriter.write(2,"BL%i.setShading(%i);" % (self.id,self.shading))
+ aWriter.write(2,"BL%i.setWinding(%i);" % (self.id,self.winding))
+ aWriter.write(2,("BL%i.setTwoSidedLightingEnable(" +
+ toJavaBoolean(self.twoSidedLightingEnabled) + ");") %
+ (self.id))
+ aWriter.write(2,("BL%i.setLocalCameraLightingEnable(" +
+ toJavaBoolean(self.localCameraLightingEnabled) + ");") %
+ (self.id))
+ aWriter.write(2,("BL%i.setPerspectiveCorrectionEnable(" +
+ toJavaBoolean(self.perspectiveCorrectionEnabled) + ");") %
+ (self.id))
+ aWriter.write(2)
+ M3GObject3D.writeJava(self,aWriter,False)
+
+ def getData(self):
+ data = M3GObject3D.getData(self)
+ data += struct.pack('6B',self.culling,
+ self.shading,
+ self.winding,
+ self.twoSidedLightingEnabled,
+ self.localCameraLightingEnabled,
+ self.perspectiveCorrectionEnabled)
+ return data
+
+ def getDataLength(self):
+ value = M3GObject3D.getDataLength(self)
+ value += struct.calcsize('6B')
+ return value
+
+class M3GIndexBuffer(M3GObject3D):
+ def __init__(self):
+ M3GObject3D.__init__(self)
+
+ def getData(self):
+ return M3GObject3D.getData(self)
+
+ def getDataLength(self):
+ return M3GObject3D.getDataLength(self)
+
+ def writeJava(self,aWriter,aCreate):
+ M3GObject3D.writeJava(self,aWriter,False)
+
+
+class M3GTriangleStripArray(M3GIndexBuffer):
+ def __init__(self):
+ M3GIndexBuffer.__init__(self)
+ self.ObjectType=11
+ self.encoding=128 #Byte Bit 7: 1 = explicit property on index buffer true
+ #Bit 1 .. 6: 0 = "raw" integer values 1= a single byte will suffice
+ #2 = a 16 bit integer is suffi to hold all the given index values
+ #IF encoding == 0, THEN
+ #self.startIndex = 0 #;UInt32
+ #ELSE IF encoding == 1, THEN
+ #Byte startIndex;
+ #ELSE IF encoding == 2, THEN
+ #UInt16 startIndex;
+ #ELSE IF encoding == 128, THEN
+ self.indices = [] #;UInt32[]
+ #ELSE IF encoding == 129, THEN
+ #Byte[] indices;
+ #ELSE IF encoding == 130, THEN
+ #UInt16[] indices;
+ #END
+ self.stripLengths = [] #;UInt32[]
+
+ def writeJava(self,aWriter,aCreate):
+ if aCreate:
+ aWriter.write(2,"//length of TriangleStrips")
+ aWriter.write(2,"int[] BL"+str(self.id)+"_stripLength ={"+
+ ",".join([str(element) for element in self.stripLengths])+"};")
+ aWriter.write(2)
+ aWriter.write(2,"//IndexBuffer")
+ aWriter.write(2,"int[] BL%i_Indices = {" % (self.id))
+ aWriter.write(2,",".join([str(element) for element in self.indices])+"};")
+ aWriter.write(2)
+ aWriter.write(2,"IndexBuffer BL%i=new TriangleStripArray(BL%i_Indices,BL%i_stripLength);" %
+ (self.id, self.id, self.id))
+ M3GIndexBuffer.writeJava(self,aWriter,False)
+ aWriter.write(2)
+
+
+ def getData(self):
+ data = M3GIndexBuffer.getData(self)
+ data += struct.pack('<BI',self.encoding,
+ len(self.indices))
+ for element in self.indices:
+ data += struct.pack('<I',element)
+ data += struct.pack('<I',len(self.stripLengths))
+ for element in self.stripLengths:
+ data += struct.pack('<I',element)
+ return data
+
+ def getDataLength(self):
+ value = M3GIndexBuffer.getDataLength(self)
+ value += struct.calcsize('<BI')
+ if len(self.indices) > 0 :
+ value += struct.calcsize('<' + str(len(self.indices)) + 'I')
+ value += struct.calcsize('<I')
+ if len(self.stripLengths) > 0:
+ value+= struct.calcsize('<'+str(len(self.stripLengths))+'I')
+ return value
+
+
+class M3GAppearance(M3GObject3D):
+ def __init__(self):
+ M3GObject3D.__init__(self)
+ self.ObjectType=3
+ self.layer=0 #Byte
+ self.compositingMode=None #ObjectIndex
+ self.fog=None #ObjectIndex
+ self.polygonMode=None #ObjectIndex
+ self.material=None #ObjectIndex
+ self.textures=[] #;ObjectIndex[]
+
+ def searchDeep(self,alist):
+ alist = doSearchDeep([self.compositingMode,self.fog,
+ self.polygonMode,self.material]
+ + self.textures,alist)
+ return M3GObject3D.searchDeep(self,alist)
+
+ def getData(self):
+ data = M3GObject3D.getData(self)
+ data += struct.pack("<B5I", self.layer,
+ getId(self.compositingMode),
+ getId(self.fog),
+ getId(self.polygonMode),
+ getId(self.material),
+ len(self.textures))
+ for element in self.textures:
+ data += struct.pack("<I",getId(element))
+ return data
+
+ def getDataLength(self):
+ value = M3GObject3D.getDataLength(self)
+ value += struct.calcsize("<B5I")
+ if len(self.textures) > 0 :
+ value += struct.calcsize("<"+str(len(self.textures))+'I')
+ return value
+
+
+ def writeJava(self,aWriter,aCreate):
+ if aCreate:
+ aWriter.write(2,"//Appearance")
+ aWriter.write(2,"Appearance BL%i = new Appearance();" % (self.id))
+ if self.compositingMode!= None:
+ aWriter.write(2,"BL%i.setPolygonMode(BL%i);" %
+ (self.id,self.compositingMode.id))
+ if self.fog!=None:
+ aWriter.write(2,"BL%i.setFog(BL%i);" %
+ (self.id,self.fog.id))
+ if self.polygonMode!=None:
+ aWriter.write(2,"BL%i.setPolygonMode(BL%i);" %
+ (self.id,self.polygonMode.id))
+ if self.material!=None:
+ aWriter.write(2,"BL%i.setMaterial(BL%i);" %
+ (self.id,self.material.id))
+ i=0
+ for itexture in self.textures:
+ aWriter.write(2,"BL%i.setTexture(%i,BL%i);" %
+ (self.id,i,itexture.id))
+ i =+ 1
+ M3GObject3D.writeJava(self,aWriter,False)
+ aWriter.write(2)
+
+class M3GTexture2D(M3GTransformable):
+ #M3G imposes the following restrictions when assigning textures to a model:
+ #The dimensions must be powers of two (4, 8, 16, 32, 64, 128...).
+
+ WRAP_REPEAT = 241
+ WRAP_CLAMP = 240
+ FILTER_BASE_LEVEL=208
+ FILTER_LINEAR=209
+ FILTER_NEAREST=210
+ FUNC_ADD=224
+ FUNC_BLEND=225
+ FUNC_DECAL=226
+ FUNC_MODULATE=227
+ FUNC_REPLACE=228
+
+ def __init__(self,aImage):
+ M3GTransformable.__init__(self)
+ self.ObjectType=17
+ self.Image = aImage #ObjectIndex
+ self.blendColor=M3GColorRGB(0,0,0)
+ self.blending=M3GTexture2D.FUNC_MODULATE #Byte
+ self.wrappingS=M3GTexture2D.WRAP_REPEAT #Byte
+ self.wrappingT=M3GTexture2D.WRAP_REPEAT #Byte
+ self.levelFilter=M3GTexture2D.FILTER_BASE_LEVEL #Byte
+ self.imageFilter=M3GTexture2D.FILTER_NEAREST #Byte
+
+ def searchDeep(self,alist):
+ alist = doSearchDeep([self.Image],alist)
+ return M3GTransformable.searchDeep(self,alist)
+
+ def getData(self):
+ data = M3GTransformable.getData(self)
+ data += struct.pack('<I', getId(self.Image))
+ data += self.blendColor.getData()
+ data += struct.pack('5B',self.blending,
+ self.wrappingS,
+ self.wrappingT,
+ self.levelFilter,
+ self.imageFilter)
+ return data
+
+ def getDataLength(self):
+ value = M3GTransformable.getDataLength(self)
+ value += struct.calcsize('<I')
+ value += self.blendColor.getDataLength()
+ value += struct.calcsize('5B')
+ return value
+
+ def writeJava(self,aWriter,aCreate):
+ if aCreate:
+ aWriter.write(2,"//Texture")
+ aWriter.write(2,"Texture2D BL%i = new Texture2D(BL%i);" % (self.id,
+ self.Image.id))
+ aWriter.write(2,"BL%i.setFiltering(%i,%i);" % (self.id,
+ self.levelFilter,
+ self.imageFilter))
+ aWriter.write(2,"BL%i.setWrapping(%i,%i);" % (self.id,
+ self.wrappingS,
+ self.wrappingT))
+ aWriter.write(2,"BL%i.setBlending(%i);" % (self.id,self.blending))
+ aWriter.write(2)
+ M3GTransformable.writeJava(self,aWriter,False)
+
+class ImageFactory:
+ images={}
+ def getImage(self, image, externalReference):
+ # It's important to use getFilename() because getName() returns a
+ # truncated string depending on the length of the file name.
+ filename = Blender.sys.expandpath(image.getFilename())
+
+ if self.images.has_key(filename):
+ image = self.images[filename]
+ elif externalReference:
+ # Check for file ending (only relevant for external images). The M3G specification
+ # mandates only PNG support, but some devices might also support additional image types.
+ [path,ext] = splitext(filename)
+ if ext != ".png":
+ print "Warning: image file ends with " + ext + ". M3G specification only mandates PNG support."
+
+ image = M3GExternalReference()
+ image.URI = Blender.sys.basename(filename)
+ self.images[filename] = image
+ else:
+ image = M3GImage2D(image)
+ self.images[filename] = image
+ return image
+
+ getImage = classmethod(getImage)
+
+
+class M3GImage2D(M3GObject3D):
+ ALPHA=96 #a single byte per pixel, representing pixel opacity
+ LUMINANCE=97 #a single byte per pixel, representing pixel luminance.
+ LUMINANCE_ALPHA=98 #two bytes per pixel. The first: luminance, the second: alpha.
+ RGB=99 #three bytes per pixel, representing red, green and blue
+ RGBA=100 #four bytes per pixel, representing red, green, blue and alpha
+
+ def __init__(self, aImage, aFormat=RGBA):
+ M3GObject3D.__init__(self)
+ self.ObjectType=10
+ self.image=aImage #Blender Image
+ self.format=aFormat #Byte
+ self.isMutable=False #Boolean changable or not
+ [self.width, self.height] = aImage.getSize()
+
+ #IF isMutable==false, THEN
+ self.palette=0 #Byte[]
+ self.pixels = array('B') #Byte[]
+ self.extractPixelsFromImage()
+ #END
+#For a palettised format, the pixels array contains a single palette
+#index per pixel, and the palette array will contain up to 256 entries,
+#each consisting of a pixel specifier appropriate to the format chosen.
+
+#For a non-palettised format, the palette array will be empty,
+#and the pixels array contains a pixel specifier appropriate to the format
+#chosen.
+#In a pixel specifier, each byte is scaled such that 0 represents the
+#value 0.0 and 255 represents the value 1.0. The different formats
+#require different data to be serialized, as follows:
+
+#The width and height of the image must be non-negative powers of two, but they need not be equal.
+
+ def getData(self):
+ data = M3GObject3D.getData(self)
+ data += struct.pack('2B', self.format, self.isMutable)
+ data += struct.pack('<2I', self.width, self.height)
+ if self.isMutable == False:
+ # TODO: support palettised formats also
+ # export palette data
+ data += struct.pack('<I', 0)
+
+ # export pixel data
+ if self.format == M3GImage2D.RGBA:
+ #print "len pixels",len(self.pixels)
+ data += struct.pack('<I', len(self.pixels))
+ for pixel in self.pixels:
+ data += struct.pack('B', pixel)
+ #elif...
+ return data
+
+ def getDataLength(self):
+ value = M3GObject3D.getDataLength(self)
+ value += struct.calcsize('2B')
+ value += struct.calcsize('<2I')
+ if self.isMutable == False:
+ # TODO: support palettised formats also
+ value+= struct.calcsize('<I')
+
+ # pixel data size
+ if self.format == M3GImage2D.RGBA:
+ value += struct.calcsize('<I')
+ value += struct.calcsize(str(len(self.pixels))+'B')
+ return value
+
+ def writeJava(self,aWriter,aCreate):
+ if aCreate:
+ lFileName = self.image.filename
+ if not Blender.sys.exists(lFileName) :
+ lFileName = Blender.sys.join(dirname(Blender.Get('filename')),
+ basename(self.image.filename))
+ elif not Blender.sys.exists(lFileName):
+ raise FileError, 'Image file not found!'
+ lTargetFile = Blender.sys.join(Blender.sys.dirname(aWriter.filename),
+ Blender.sys.basename(self.image.filename))
+ copy_file(lFileName,lTargetFile)
+ #shutil.copyfile(lFileName,lTargetFile)
+ aWriter.write(2,"//Image2D")
+ aWriter.write(2,"Image BL%i_Image = null;" % (self.id))
+ aWriter.write(2,"try {")
+ aWriter.write(3,"BL%i_Image = Image.createImage(\"/%s\");" %
+ (self.id,basename(self.image.filename)))
+ aWriter.write(2,"} catch (IOException e) {")
+ aWriter.write(3,"e.printStackTrace();")
+ aWriter.write(2,"}")
+ aWriter.write(2,"Image2D BL%i = new Image2D(Image2D.RGBA,BL%i_Image);" %
+ (self.id,self.id))
+ aWriter.write(2)
+ M3GObject3D.writeJava(self,aWriter,False)
+ aWriter.write(2)
+
+ def extractPixelsFromImage(self):
+ # Reverse t coordiante because M3G uses a different 2D coordinate system than OpenGL.
+ for y in range(self.height):
+ for x in range(self.width):
+ [r, g, b, a] = self.image.getPixelI(x, self.height-1-y)
+ self.pixels.append(r)
+ self.pixels.append(g)
+ self.pixels.append(b)
+ self.pixels.append(a)
+
+class M3GAnimationController(M3GObject3D):
+ def __init__(self):
+ M3GObject3D.__init__(self)
+ self.ObjectType=1
+ self.speed = 1.0 #Float32
+ self.weight = 1.0 #Float32
+ self.activeIntervalStart = 0 #Int32 - (always active)
+ self.activeIntervalEnd = 0 #Int32
+ self.referenceSequenceTime = 0.0 #Float32
+ self.referenceWorldTime = 0 #Int32
+
+ def writeJava(self,aWriter,aCreate):
+ if aCreate:
+ aWriter.writeClass("AnimationController",self)
+ aWriter.write(2,"AnimationController BL%i = new AnimationController();" %
+ (self.id))
+ aWriter.write(2,"BL%i.setActiveInterval(%i, %i);" %
+ (self.id,self.activeIntervalStart,self.activeIntervalEnd))
+ #lightAnim.setPosition(0, 2000);(2) Applying the animation during rendering
+ M3GObject3D.writeJava(self,aWriter,False)
+
+ def getData(self):
+ data = M3GObject3D.getData(self)
+ data += struct.pack("<ffiifi", self.speed,
+ self.weight,
+ self.activeIntervalStart,
+ self.activeIntervalEnd,
+ self.referenceSequenceTime,
+ self.referenceWorldTime)
+ return data
+
+ def getDataLength(self):
+ value = M3GObject3D.getDataLength(self)
+ return value + struct.calcsize("<ffiifi")
+
+class M3GAnimationTrack(M3GObject3D):
+ ALPHA=256
+ AMBIENT_COLOR=257
+ COLOR=258
+ CROP=259
+ DENSITY=260
+ DIFFUSE_COLOR=261
+ EMISSIVE_COLOR=262
+ FAR_DISTANCE=263
+ FIELD_OF_VIEW=264
+ INTENSITY=265
+ MORPH_WEIGHTS=266
+ NEAR_DISTANCE=267
+ ORIENTATION=268
+ PICKABILITY=269
+ SCALE=270
+ SHININESS=271
+ SPECULAR_COLOR=272
+ SPOT_ANGLE=273
+ SPOT_EXPONENT=274
+ TRANSLATION=275
+ VISIBILITY=276
+
+ def __init__(self,aSequence,aProperty):
+ M3GObject3D.__init__(self)
+ self.ObjectType = 2
+ self.keyframeSequence = aSequence #ObjectIndex
+ self.animationController = None #ObjectIndex
+ self.propertyID = aProperty #UInt32
+
+ def getData(self):
+ data = M3GObject3D.getData(self)
+ data += struct.pack("<3I", getId(self.keyframeSequence),
+ getId(self.animationController),
+ self.propertyID)
+ return data
+
+ def getDataLength(self):
+ value = M3GObject3D.getDataLength(self)
+ return value + struct.calcsize("<3I")
+
+ def writeJava(self,aWriter,aCreate):
+ if aCreate:
+ aWriter.writeClass("AnimationTrack",self)
+ #print "self.id,self.keyframeSequence,self.propertyID",self.id,self.keyframeSequence,self.propertyID
+ aWriter.write(2,"AnimationTrack BL%i = new AnimationTrack(BL%i,%i);" %
+ (self.id,self.keyframeSequence.id,self.propertyID))
+ aWriter.write(2,"BL%i.setController(BL%i);" %
+ (self.id,self.animationController.id))
+ M3GObject3D.writeJava(self,aWriter,False)
+
+ def searchDeep(self,alist):
+ alist = doSearchDeep([self.keyframeSequence, self.animationController],alist)
+ return M3GObject3D.searchDeep(self,alist)
+
+class M3GKeyframeSequence(M3GObject3D):
+ CONSTANT=192
+ LINEAR=176
+ LOOP=193
+ SLERP=177
+ SPLINE=178
+ SQUAD=179
+ STEP=180
+
+ def __init__(self,aNumKeyframes, aNumComponents,aBlenderInterpolation,
+ aM3GInterpolation=None):
+ M3GObject3D.__init__(self)
+ self.ObjectType = 19
+ if aM3GInterpolation!=None:
+ self.interpolation = aM3GInterpolation
+ else:
+ if aBlenderInterpolation == "Constant":
+ self.interpolation = self.STEP #Byte
+ elif aBlenderInterpolation == "Bezier":
+ self.interpolation = self.SPLINE #Byte
+ elif aBlenderInterpolation == "Linear":
+ self.interpolation = self.LINEAR #Byte
+ else:
+ pass # TODO : Throw Error
+ self.repeatMode = self.CONSTANT #Byte CONSTANT or LOOP
+ self.encoding = 0 #Byte 0=raw
+ # TODO: Other encodings
+ self.duration = 0 #UInt32
+ self.validRangeFirst = 0 #UInt32
+ self.validRangeLast = 0 #UInt32
+ self.componentCount = aNumComponents #UInt32
+ self.keyframeCount = aNumKeyframes #UInt32
+ #IF encoding == 0
+ #FOR each key frame...
+ self.time = [] #Int32
+ self.vectorValue = [] # Float32[componentCount]
+ #END
+ #ELSE IF encoding == 1
+ #Float32[componentCount] vectorBias;
+ #Float32[componentCount] vectorScale;
+ #FOR each key frame...
+ #Int32 time;
+ #Byte[componentCount] vectorValue;
+ #END
+ #ELSE IF encoding == 2
+ #Float32[componentCount] vectorBias;
+ #Float32[componentCount] vectorScale;
+ #FOR each key frame...
+ #Int32 time;
+ #UInt16[componentCount] vectorValue;
+ #END
+ #END
+
+#All of the vectorValue arrays are the same size, so a separate count is stored outside the individual
+#keyframe's data rather than with each array. The encoding field indicates the encoding scheme to be used for the keyframe data. Only the
+#nominated values above are allowed. Other values must be treated as errors.
+
+#•Encoding 0 indicates that the values are stored "raw" as floats.
+#•Encodings 1 and 2 indicate that the values are quantized to 1 or 2 bytes. For each component,
+#a bias and scale are calculated from the sequence of values for that component. The bias is the
+#mimimum value, the scale is the maximum value minus the minimum value. The raw values
+#are then converted to a value 0..1 by subtracting the bias and dividing by the scale. These raw
+#values are then quantized into the range of a Byte or UInt16 by multiplying by 255 or 65535
+#respectively. The converse operation restores the original value from the quantized values.
+
+ def beforeExport(self):
+ #M3G can not work with negative zero
+ #print"beforeExport ID= ",self.id
+ for i in range(self.keyframeCount):
+ for j in range(self.componentCount):
+ x = struct.pack("<f",self.vectorValue[i][j])
+ y = struct.unpack("<f",x)
+ #print "beforeExport i,j ",i,j,self.vectorValue[i][j],y
+ if abs(self.vectorValue[i][j]) < 0.000001 :
+ #print "Negative Zero found!",self.vectorValue[i][j]
+ self.vectorValue[i][j]=0.0
+ #print "zero ",self.vectorValue[i][j]
+
+ def getData(self):
+ self.beforeExport()
+ data = M3GObject3D.getData(self)
+ data += struct.pack("<3B5I",self.interpolation,
+ self.repeatMode,
+ self.encoding,
+ self.duration,
+ self.validRangeFirst,
+ self.validRangeLast,
+ self.componentCount,
+ self.keyframeCount)
+ #FOR each key frame...
+ for i in range(self.keyframeCount):
+ data += struct.pack("<i",self.time[i]) #Int32
+ for j in range(self.componentCount):
+ data += struct.pack("<f",self.vectorValue[i][j]) # Float32[componentCount]
+ return data
+
+ def getDataLength(self):
+ value = M3GObject3D.getDataLength(self)
+ value += struct.calcsize("<3B5I")
+ value += struct.calcsize("<i") * self.keyframeCount
+ value += struct.calcsize("<f") * self.keyframeCount * self.componentCount
+ return value
+
+ def setRepeatMode(self,aBlenderMode):
+ if aBlenderMode == "Constant" :
+ self.repeatMode = self.CONSTANT
+ elif aBlenderMode == "Cyclic":
+ self.repeatMode = self.LOOP
+ else:
+ print "In IPO: Mode " + aBlenderMode + " is not assisted!"
+
+ def setKeyframe(self, aIndex, aTime, aVector):
+ self.time.append(aTime)
+ self.vectorValue.append(aVector)
+
+ def writeJava(self,aWriter,aCreate):
+ self.beforeExport()
+ if aCreate:
+ aWriter.writeClass("KeyframeSequence",self)
+ aWriter.write(2,"KeyframeSequence BL%i = new KeyframeSequence(%i, %i, %i);" %
+ (self.id,self.keyframeCount,self.componentCount,self.interpolation))
+ for i in range(len(self.time)):
+ lLine = "BL%i.setKeyframe(%i,%i, new float[] { %ff, %ff, %ff" % \
+ (self.id,i,self.time[i],self.vectorValue[i][0], \
+ self.vectorValue[i][1],self.vectorValue[i][2])
+ if self.componentCount == 4:
+ lLine += ", %ff" % (self.vectorValue[i][3])
+ lLine += "});"
+ aWriter.write(2,lLine)
+ # TODO : Works only with componentCount = 3
+ aWriter.write(2,"BL%i.setDuration(%i);" % (self.id, self.duration))
+ aWriter.write(2,"BL%i.setRepeatMode(%i);" % (self.id,self.repeatMode))
+ M3GObject3D.writeJava(self,aWriter,False)
+
+# ---- Translator -------------------------------------------------------------- #
+
+class M3GTranslator:
+ "Trys to translate a blender scene into a mg3 World"
+
+ def __init__(self):
+ self.world = None
+ self.scene = None
+ self.nodes = []
+
+ def start(self):
+ print "Translate started ..."
+
+ self.scene = Blender.Scene.GetCurrent()
+ self.world = self.translateWorld(self.scene)
+
+ for obj in self.scene.objects:
+ if obj.getType()=='Camera': # older Version: isinstance(obj.getData(),Types.CameraType)
+ self.translateCamera(obj)
+ elif obj.getType()=='Mesh':
+ self.translateMesh(obj)
+ elif obj.getType()=='Lamp' and mOptions.lightingEnabled: # older Version: isinstance(obj.getData(),Types.LampType)
+ self.translateLamp(obj)
+ elif obj.getType()=='Empty':
+ self.translateEmpty(obj)
+ else:
+ print "Warning: could not translate" + str(obj) + ". Try to convert object to mesh using Alt-C"
+
+ self.translateParenting()
+
+ print "Translate finished."
+ return self.world
+
+ def translateParenting(self):
+ for iNode in self.nodes:
+ if iNode.parentBlenderObj == None:
+ self.world.children.append(iNode)
+ else:
+ for jNode in self.nodes:
+ if iNode.parentBlenderObj == jNode.blenderObj:
+ #TODO : Every object can be parent
+ jNode.children.append(iNode)
+ #lMatrix = Matrix(iNode.blenderMatrixWorld) * Matrix(jNode.blenderMatrixWorld).invert()
+ lMatrix = self.calculateChildMatrix(iNode.blenderMatrixWorld,jNode.blenderMatrixWorld)
+ iNode.transform = self.translateMatrix(lMatrix)
+ iNode.hasGeneralTransform=True
+ break
+
+ def calculateChildMatrix(self,child,parent):
+ return Matrix(child) * Matrix(parent).invert()
+
+ def translateArmature(self,obj,meshObj,aSkinnedMesh):
+ print "translate Armature ..."
+ #print "translateArmature::aSkinnedMesh.vertexBuffer:",aSkinnedMesh.vertexBuffer
+ armature = obj.getData()
+
+ #Pose
+ #pose = obj.getPose()
+ #print "pose ",pose
+ #for bone in pose.bones.values():
+ # print "bone local",bone.localMatrix
+ # print "bone pose",bone.poseMatrix
+
+ #Skeleton
+ mGroup = M3GGroup()
+ self.translateCore(obj,mGroup)
+ aSkinnedMesh.skeleton = mGroup
+ mGroup.transform = self.translateMatrix(
+ self.calculateChildMatrix(obj.matrixWorld,
+ meshObj.matrixWorld))
+
+ #Bones
+ #print "armature:",armature.bones
+ for bone in armature.bones.values(): #Copy Bones
+ mBone = M3GBone()
+ mBone.transformNode = M3GGroup()
+ self.translateCore(bone, mBone.transformNode)
+ #mBone.transformNode.transform = self.translateMatrix(pose.bones[bone.name].poseMatrix)#Test!!!!
+ #print "node transform", mBone.transformNode.transform
+ #mBone.transformNode.transform=self.translateMatrix(self.calculateChildMatrix(bone.matrix['ARMATURESPACE'],meshObj.matrixWorld))
+ if bone.hasParent():
+ mBone.transformNode.transform = self.translateMatrix(
+ self.calculateChildMatrix(bone.matrix['ARMATURESPACE'],
+ bone.parent.matrix['ARMATURESPACE']))
+ mBone.weight = bone.weight
+ aSkinnedMesh.bones[bone.name]=mBone
+
+ rootBone = [] #Copy Child-Parent-Structure
+ for bone in armature.bones.values():
+ mBone = aSkinnedMesh.bones[bone.name]
+ if not bone.hasParent():
+ rootBone.append(mBone)
+ if bone.hasChildren():
+ for childBone in bone.children:
+ mChildBone = aSkinnedMesh.bones[childBone.name]
+ mBone.transformNode.children.append(mChildBone.transformNode)
+ for rbone in rootBone:
+ aSkinnedMesh.skeleton.children.append(rbone.transformNode)
+
+ #VertexGroups - Skinning
+ if armature.vertexGroups:
+ for boneName in aSkinnedMesh.bones.keys():
+ aSkinnedMesh.bones[boneName].setVerts(self.translateVertsGroup(meshObj.getData(False,True).getVertsFromGroup(boneName),
+ aSkinnedMesh))
+ #Envelope - Skinning
+ if armature.envelopes:
+ pass #TODO
+
+ #Action
+ self.translateAction(obj,aSkinnedMesh)
+ aSkinnedMesh.addSecondBone()
+
+
+ def translateVertsGroup(self,group,aSkinnedMesh):
+ #print "group: ",group
+ #print "items: ",aSkinnedMesh.getBlenderIndexes().items()
+ ergebnis = [int(k) for k,v in aSkinnedMesh.getBlenderIndexes().items() if v in group]
+ #print "ergebnis: ",ergebnis
+ return ergebnis
+
+ def translateAction(self,armatureObj,aSkinnedMesh):
+ action = armatureObj.getAction()
+ if action==None: return
+
+ print "tranlating Action ..."
+ if mOptions.exportAllActions:
+ lArmatureID = self.translateUserID(armatureObj.getData().name)
+ print "armatureID ", lArmatureID, armatureObj
+ for a in Blender.Armature.NLA.GetActions().values():
+ (lArmatureActionID,lEndFrame,lActionID) = self.translateActionName(a.name)
+ #print "action", a
+ #print "lArmatureID", lArmatureActionID
+ #print "lEndFrame", lEndFrame
+ #print "lActionID", lActionID
+ if lArmatureActionID == lArmatureID:
+ #print "Action found"
+ mController = self.translateActionIPOs(a,aSkinnedMesh,lEndFrame)
+ mController.userID = lActionID
+ #print "mController.userID ",mController.userID
+
+ #print "getActionScripts() ", Blender.Armature.NLA.getActionStrips()
+ else:
+ self.translateActionIPOs(action,aSkinnedMesh)
+
+
+ def translateActionIPOs(self,aAction,aSkinnedMesh,aEndFrame=0):
+ ipos = aAction.getAllChannelIpos()
+ mController=None
+ for boneName in aSkinnedMesh.bones.keys():
+ if ipos.has_key(boneName):
+ ipo = ipos[boneName]
+ if mController==None: mController = M3GAnimationController()
+ self.translateIpo(ipo,aSkinnedMesh.bones[boneName].transformNode,mController,aEndFrame)
+ return mController
+
+ def translateActionName(self,name):
+ # <Action Name>#A<M3G ID of Armature>E<End Frame>#<ID of Action>
+ lError = "Armature name " + name + " is not ok. Perhaps you should set option 'ExportAllAction' to false."
+ #print "name ", name
+ lLetter = name.find("#")
+ if lLetter == -1 :raise Exception(lError)
+ if name[lLetter+1]!='A': raise Exception(lError)
+ lName = name[lLetter+2:]
+ #print "lName ", lName
+ lLetter = lName.find("E")
+ #print "lLetter ", lLetter
+ if lLetter == -1 :raise Exception(lError)
+ #print "lName[:]", lName[:0]
+ lArmatureID = int(lName[:lLetter])
+ lName = lName[lLetter+1:]
+ lLetter = lName.find("#")
+ if lLetter == -1:raise Exception(lError)
+ lEndFrame = int(lName[:lLetter])
+ lActionID = int(lName[lLetter+1:])
+ return (lArmatureID,lEndFrame,lActionID)
+
+
+ def translateWorld(self,scene):
+ "creates world object"
+ world = M3GWorld()
+
+ #Background
+ world.background = M3GBackground()
+ blWorld= scene.world
+ #AllWorlds = Blender.World.Get() # Set Color
+ #if len(AllWorlds)>=1: # world object available
+ if blWorld != None:
+ world.background.backgroundColor=self.translateRGBA(blWorld.getHor(),0) # horizon color of the first world
+ if mOptions.createAmbientLight & mOptions.lightingEnabled:
+ lLight = M3GLight()
+ lLight.mode = lLight.modes['AMBIENT']
+ lLight.color = self.translateRGB(AllWorlds[0].getAmb())
+ self.nodes.append(lLight)
+
+ #TODO: Set background picture from world
+
+ return world
+
+ def translateEmpty(self,obj):
+ print "translate empty ..."
+ mGroup = M3GGroup()
+ self.translateToNode(obj,mGroup)
+
+ def translateCamera(self,obj):
+ print "translate camera ..."
+ camera = obj.getData()
+ if camera.getType()!=0:
+ print "Only perscpectiv cameras will work korrekt"
+ return #Type=0 'perspectiv' Camera will be translated
+ mCamera = M3GCamera()
+ mCamera.projectionType=mCamera.PERSPECTIVE
+ mCamera.fovy=60.0 # TODO: Calculate fovy from Blender.lens
+ mCamera.AspectRatio=4.0/3.0 # TODO: different in every device
+ mCamera.near=camera.getClipStart()
+ mCamera.far=camera.getClipEnd()
+ self.translateToNode(obj,mCamera)
+ self.world.activeCamera = mCamera # Last one is always the active one
+
+
+ def translateMaterials(self, aMaterial, aMesh, aMatIndex, createNormals, createUvs):
+ print "translate materials ..."
+
+ mAppearance = M3GAppearance()
+
+ if createNormals:
+ mMaterial = M3GMaterial()
+ mMaterial.name = aMaterial.name
+ mMaterial.diffuseColor = self.translateRGBA(aMaterial.rgbCol,1.0) #ColorRGBA
+ #material.specularColor= self.translateRGB(mat.specCol) #ColorRGB
+ mAppearance.material = mMaterial
+
+ if createUvs:
+ # Search file name in mesh face.
+ lImage = None
+ for iface in aMesh.faces:
+ if iface.mat==aMatIndex:
+ if iface.image != None:
+ lImage = iface.image
+ break
+ if lImage==None:
+ raise Exception("Mesh " + aMesh.name + ": No image found for uv-texture! Perhaps no uv-coordinates ?")
+
+ # M3G requires textures to have power-of-two dimensions.
+ [width, height] = lImage.getSize()
+ powerWidth = 1
+ while (powerWidth < width):
+ powerWidth *= 2
+ powerHeight = 1
+ while (powerHeight < height):
+ powerHeight *= 2
+ if powerWidth != width or powerHeight != height:
+ raise Exception("Image " + lImage.filename + ": width and height must be power-of-two!")
+
+ # ImageFactory reuses existing images.
+ mImage = ImageFactory.getImage(lImage, mOptions.textureExternal)
+ mTexture = M3GTexture2D(mImage)
+ mAppearance.textures.append(mTexture)
+
+ mPolygonMode=M3GPolygonMode()
+ mPolygonMode.perspectiveCorrectionEnabled = mOptions.perspectiveCorrection
+ if not aMesh.mode & Modes.TWOSIDED:
+ mPolygonMode.culling=M3GPolygonMode.CULL_BACK
+ else:
+ mPolygonMode.culling=M3GPolygonMode.CULL_NONE
+ if mOptions.smoothShading:
+ mPolygonMode.shading=M3GPolygonMode.SHADE_SMOOTH
+ else:
+ mPolygonMode.shading=M3GPolygonMode.SHADE_FLAT
+
+ mAppearance.polygonMode = mPolygonMode
+
+ return mAppearance
+
+
+ def translateMesh(self,obj):
+ print "translate mesh ..." + str(obj)
+
+ # Mesh data.
+ mesh = obj.getData(False, True) # get Mesh not NMesh object
+ if len(mesh.faces) <= 0: # no need to process empty meshes
+ print "Empty mesh " + str(obj) + " not processed."
+ return
+
+ vertexBuffer = M3GVertexBuffer()
+ positions = M3GVertexArray(3, 2) # 3 coordinates - 2 bytes
+ if mOptions.autoscaling: positions.useMaxPrecision(mesh.verts)
+ indexBuffers = []
+ appearances = []
+ print str(len(mesh.materials)) + " material(s) found."
+
+ # Texture coordinates.
+ createUvs = False
+ if mOptions.textureEnabled & mesh.faceUV:
+ for material in mesh.materials:
+ if material.getMode() & Material.Modes.TEXFACE: createUvs = True;
+
+ if createUvs:
+ if mOptions.autoscaling:
+ uvCoordinates = M3GVertexArray(2,2,True,True) #2 coordinates - 2 bytes - autoscaling
+ else:
+ uvCoordinates = M3GVertexArray(2, 2) #2 coordinates - 2 bytes
+ uvCoordinates.bias[0] = 0.5
+ uvCoordinates.bias[1] = 0.5
+ uvCoordinates.bias[2] = 0.5
+ uvCoordinates.scale = 1.0/65535.0
+ else:
+ uvCoordinates = None
+
+ # Normals.
+ createNormals = False
+ if mOptions.lightingEnabled:
+ for material in mesh.materials:
+ if not (material.getMode() & Material.Modes.SHADELESS): createNormals = True;
+
+ if createNormals:
+ normals = M3GVertexArray(3, 1) # 3 coordinates - 1 byte
+ else:
+ normals = None
+
+ # Create a submesh for each material.
+ for materialIndex, material in enumerate(mesh.materials):
+ faces = [face for face in mesh.faces if face.mat == materialIndex]
+ if len(faces) >= 0:
+ indexBuffers.append(self.translateFaces(faces, positions, normals, uvCoordinates, createNormals, createUvs))
+ appearances.append(self.translateMaterials(material, mesh, materialIndex, createNormals, createUvs))
+
+ # If the above didn't result in any IndexBuffer (e.g. there's no material), write a single IndexBuffer
+ # with all faces and a default Appearance.
+ if len(indexBuffers) == 0:
+ indexBuffers.append(self.translateFaces(mesh.faces, positions, normals, uvCoordinates, createNormals, createUvs))
+ appearances.append(M3GAppearance())
+
+ vertexBuffer.setPositions(positions)
+ if createNormals: vertexBuffer.normals = normals
+ if createUvs: vertexBuffer.texCoordArrays.append(uvCoordinates)
+
+ parent = obj.getParent()
+ if parent!=None and parent.getType()=='Armature': #Armatures ?
+ mMesh = M3GSkinnedMesh(vertexBuffer,indexBuffers,appearances)
+ #print"vertexBuffer.positions:",vertexBuffer.positions
+ print"mMesh.vertexBuffer:",mMesh.vertexBuffer
+ self.translateArmature(parent,obj,mMesh)
+ else:
+ mMesh = M3GMesh(vertexBuffer,indexBuffers,appearances)
+
+ self.translateToNode(obj,mMesh)
+
+ #Do Animation
+ self.translateObjectIpo(obj,mMesh)
+
+ def translateFaces(self, faces, positions, normals, uvCoordinates, createNormals, createUvs):
+ """Translates a list of faces into vertex data and triangle strips."""
+
+ # Create vertices and triangle strips.
+ indices = [0, 0, 0, 0]
+ triangleStrips = M3GTriangleStripArray()
+
+ for face in faces:
+ for vertexIndex, vertex in enumerate(face.verts):
+ # Find candidates for sharing (vertices with same Blender ID).
+ vertexCandidateIds = [int(k) for k, v in positions.blenderIndexes.items() if v == vertex.index]
+
+ # Check normal.
+ if createNormals and not face.smooth:
+ # For solid faces, a vertex can only be shared if the the face normal is
+ # the same as the normal of the shared vertex.
+ for candidateId in vertexCandidateIds[:]:
+ for j in range(3):
+ if face.no[j]*127 != normals.components[candidateId*3 + j]:
+ vertexCandidateIds.remove(candidateId)
+ break
+
+ # Check texture coordinates.
+ if createUvs:
+ # If texture coordinates are required, a vertex can only be shared if the
+ # texture coordinates match.
+ for candidateId in vertexCandidateIds[:]:
+ s = int((face.uv[vertexIndex][0]-0.5)*65535)
+ t = int((0.5-face.uv[vertexIndex][1])*65535)
+ if (s != uvCoordinates.components[candidateId*2 + 0]) or (t != uvCoordinates.components[candidateId*2 + 1]):
+ vertexCandidateIds.remove(candidateId)
+
+ if len(vertexCandidateIds) > 0:
+ # Share the vertex.
+ indices[vertexIndex] = vertexCandidateIds[0]
+ else:
+ # Create new vertex.
+ positions.append(vertex, vertex.index)
+ indices[vertexIndex] = len(positions.components)/3 - 1
+
+ # Normal.
+ if createNormals:
+ for j in range(3):
+ if face.smooth:
+ normals.append(int(vertex.no[j]*127)) # vertex normal
+ else:
+ normals.append(int(face.no[j]*127)) # face normal
+
+ # Texture coordinates.
+ if createUvs:
+ lUvCoordinatesFound = True
+ print "face.uv[vertexIndex][0]:",face.uv[vertexIndex][0]
+ print "face.uv[vertexIndex][1]:",face.uv[vertexIndex][1]
+ if mOptions.autoscaling:
+ uvCoordinates.append(face.uv[vertexIndex][0])
+ uvCoordinates.append(face.uv[vertexIndex][1])
+ else:
+ uvCoordinates.append(int((face.uv[vertexIndex][0]-0.5)*65535))
+ # Reverse t coordinate because M3G uses a different 2D coordinate system than Blender.
+ uvCoordinates.append(int((0.5-face.uv[vertexIndex][1])*65535))
+
+ # IndexBuffer.
+ triangleStrips.stripLengths.append(len(face.verts))
+ if len(face.verts) > 3 :
+ triangleStrips.indices += [indices[1], indices[2], indices[0], indices[3]] # quad
+ else :
+ triangleStrips.indices += [indices[0], indices[1], indices[2]] # tri
+
+ return triangleStrips
+
+
+ def translateObjectIpo(self,obj,aM3GObject):
+ if obj.getIpo() == None : return #No Ipo available
+ print "translate Ipo ..."
+
+ lIpo = obj.getIpo()
+ self.translateIpo(lIpo,aM3GObject)
+
+
+ def translateIpo(self,aIpo,aM3GObject,aM3GAnimContr=None,aEndFrame=0):
+ #Print info about curves
+ #for iCurve in lIpo.getCurves():
+ # print "Extrapolation",iCurve.getExtrapolation() #Constant, Extrapolation, Cyclic or Cyclic_extrapolation
+ # print "Interpolation",iCurve.getInterpolation() #Constant, Bezier, or Linear
+ # print "Name",iCurve.getName()
+ # for iPoint in iCurve.getPoints():
+ # print "Knode points",iPoint.getPoints()
+ types = ['Loc','Rot','Size','Quat']
+
+ for type in types:
+ if aIpo.getCurve(type+'X'):
+ self.translateIpoCurve(aIpo,aM3GObject,type,aM3GAnimContr,aEndFrame)
+
+
+ def translateIpoCurve(self,aIpo,aM3GObject,aCurveType,aM3GAnimContr,aEndFrame=0):
+
+ lContext = self.scene.getRenderingContext()
+ if aEndFrame==0:
+ lEndFrame = lContext.endFrame()
+ else:
+ lEndFrame = aEndFrame
+
+ lTimePerFrame = 1.0 / lContext.framesPerSec() * 1000
+
+ lCurveX = aIpo.getCurve(aCurveType+'X')
+ lCurveY = aIpo.getCurve(aCurveType+'Y')
+ lCurveZ = aIpo.getCurve(aCurveType+'Z')
+ if aCurveType=='Quat': lCurveW = aIpo.getCurve(aCurveType+'W')
+
+ lInterpolation = None
+ if aCurveType == 'Rot' or aCurveType == 'Quat':
+ lTrackType = M3GAnimationTrack.ORIENTATION
+ lNumComponents=4
+ lCurveFactor= 10 #45 Degrees = 4,5
+ if aCurveType == 'Quat':
+ lTrackType = M3GAnimationTrack.ORIENTATION
+ lNumComponents=4
+ lCurveFactor= 1
+ lInterpolation = M3GKeyframeSequence.SLERP
+ #lInterpolation = M3GKeyframeSequence.SQUAD
+ elif aCurveType == 'Size':
+ lTrackType = M3GAnimationTrack.SCALE
+ lNumComponents=3
+ lCurveFactor=1
+ else:
+ lTrackType = M3GAnimationTrack.TRANSLATION
+ lNumComponents=3
+ lCurveFactor=1
+
+ mSequence = M3GKeyframeSequence(len(lCurveX.getPoints()),
+ lNumComponents,
+ lCurveX.getInterpolation(),
+ lInterpolation)
+
+ #print 'ComponentCount',mSequence.componentCount
+
+ mSequence.duration = lEndFrame * lTimePerFrame
+ mSequence.setRepeatMode(lCurveX.getExtrapolation())
+
+ lIndex = 0
+ for iPoint in lCurveX.getPoints():
+ lPoint = iPoint.getPoints()
+
+ lPointList = [(lPoint[1]*lCurveFactor),
+ (lCurveY.evaluate(lPoint[0])*lCurveFactor),
+ (lCurveZ.evaluate(lPoint[0])*lCurveFactor)]
+
+ #print "aCurveType ", aCurveType
+
+ if aCurveType == 'Loc':
+ #print "PointList ", lPointList
+ #lorgTransVector = aM3GObject.blenderTransformMatrix.translationPart()
+ #ltrans = TranslationMatrix(Vector(lPointList))
+ #ltrans2 = self.calculateChildMatrix(ltrans,aM3GObject.blenderTransformMatrix)
+ #lVector = ltrans2.translationPart() + lorgTransVector
+ #lPointList = [lVector.x, lVector.y,lVector.z]
+ #print "PointList ", lPointList
+ pass
+
+ if aCurveType == 'Quat':
+ lPointList.append(lCurveW.evaluate(lPoint[0])*lCurveFactor)
+ #lQuat = Quaternion([lPointList[3],lPointList[0],lPointList[1],lPointList[2]])
+ #print "Quat ", lQuat
+ #print "Quat.angel ", lQuat.angle
+ #print "Quat.axis ", lQuat.axis
+ #print "PointList ", lPointList
+
+ #print "PointList",lPointList
+
+ if aCurveType =='Rot':
+ lQuat = Euler(lPointList).toQuat()
+ #lPointList = [lQuat.w,lQuat.x,lQuat.y,lQuat.z]
+ lPointList = [lQuat.x,lQuat.y,lQuat.z,lQuat.w]
+ #print " Quat=", lPointList
+
+ mSequence.setKeyframe(lIndex,
+ lPoint[0]*lTimePerFrame,
+ lPointList)
+ lIndex += 1
+ mSequence.validRangeFirst = 0
+ mSequence.validRangeLast = lIndex - 1
+
+ mTrack = M3GAnimationTrack(mSequence,lTrackType)
+ aM3GObject.animationTracks.append(mTrack)
+ if aM3GAnimContr==None: aM3GAnimContr = M3GAnimationController()
+ mTrack.animationController = aM3GAnimContr
+
+
+ def translateLamp(self,obj):
+ print "translate lamp ..."
+ lamp = obj.getData()
+
+ #Type
+ lampType=lamp.getType()
+ if not lampType in [Lamp.Types.Lamp,Lamp.Types.Spot,Lamp.Types.Sun]:
+ print "INFO: Type of light is not supported. See documentation"
+ return #create not light; type not supported
+ mLight = M3GLight()
+ if lampType == Lamp.Types.Lamp:
+ mLight.mode = mLight.modes['OMNI']
+ elif lampType == Lamp.Types.Spot:
+ mLight.mode = mLight.modes['SPOT']
+ elif lampType == Lamp.Types.Sun:
+ mLight.mode = mLight.modes['DIRECTIONAL']
+ #Attenuation (OMNI,SPOT):
+ if lampType in [Lamp.Types.Lamp,Lamp.Types.Spot]:
+ mLight.attenuationConstant = 0.0
+ mLight.attenuationLinear = 2.0/lamp.dist
+ mLight.attenuationQuadratic = 0.0
+ #Color
+ mLight.color = self.translateRGB(lamp.col)
+ #Energy
+ mLight.intensity = lamp.energy
+ #SpotAngle, SpotExponent (SPOT)
+ if lampType == Lamp.Types.Spot:
+ mLight.spotAngle = lamp.spotSize
+ mLight.spotExponent = lamp.spotBlend
+ self.translateToNode(obj,mLight)
+
+
+ def translateCore(self,obj,node):
+ #Name
+ node.name = obj.name
+ node.userID = self.translateUserID(obj.name)
+ #Location
+ #node.translation=self.translateLoc(obj.LocX,obj.LocY,obj.LocZ
+ #node.hasComponentTransform=True
+ #Transform
+ #node.transform = self.translateMatrix(obj.getMatrix('localspace'))
+ if type(obj) is Types.BoneType:
+ #print "BoneMatrix ",obj.matrix['BONESPACE']
+ node.transform = self.translateMatrix(obj.matrix['ARMATURESPACE'])
+ #'ARMATURESPACE' - this matrix of the bone in relation to the armature
+ #'BONESPACE' - the matrix of the bone in relation to itself
+ else:
+ node.transform = self.translateMatrix(obj.matrixWorld)
+ node.hasGeneralTransform=True
+
+
+ def translateToNode(self,obj,node):
+ self.translateCore(obj,node)
+ #Nodes
+ self.nodes.append(node)
+ #Link to Blender Object
+ node.blenderObj = obj
+ node.blenderMatrixWorld = obj.matrixWorld
+ lparent = None
+ if obj.getParent()!=None:
+ if obj.getParent().getType()!='Armature':
+ lparent = obj.getParent()
+ else:
+ if obj.getParent().getParent()!=None and obj.getParent().getParent().getType()!='Armature':
+ lparent = obj.getParent().getParent()
+ node.parentBlenderObj = lparent
+
+
+ def translateUserID(self, name):
+ id = 0
+ start = name.find('#')
+
+ # Use digits that follow the # sign for id.
+ if start != -1:
+ start += 1
+ end = start
+ for char in name[start:]:
+ if char.isdigit():
+ end += 1
+ else:
+ break
+
+ if end > start:
+ id = int(name[start:end])
+
+ return id
+
+ def translateLoc(self,aLocX,aLocY,aLocZ):
+ return M3GVector3D(aLocX,aLocY,aLocZ)
+
+ def translateRGB(self,color):
+ return M3GColorRGB(int(color[0]*255),
+ int(color[1]*255),
+ int(color[2]*255))
+
+ def translateRGBA(self,color,alpha):
+ return M3GColorRGBA(int(color[0]*255),
+ int(color[1]*255),
+ int(color[2]*255),
+ int(alpha*255))
+
+ def translateMatrix(self,aPyMatrix):
+ """
+  0   1   2   3 
+ 4   5   6   7 
+ 8   9  10  11
+ 12  13  14  15 """
+ #print "Matrix:", aPyMatrix
+ lMatrix = M3GMatrix()
+ lMatrix.elements[0] = aPyMatrix[0][0]
+ lMatrix.elements[1] = aPyMatrix[1][0]
+ lMatrix.elements[2] = aPyMatrix[2][0]
+ lMatrix.elements[3] = aPyMatrix[3][0]
+ lMatrix.elements[4] = aPyMatrix[0][1]
+ lMatrix.elements[5] = aPyMatrix[1][1]
+ lMatrix.elements[6] = aPyMatrix[2][1]
+ lMatrix.elements[7] = aPyMatrix[3][1]
+ lMatrix.elements[8] = aPyMatrix[0][2]
+ lMatrix.elements[9] = aPyMatrix[1][2]
+ lMatrix.elements[10] = aPyMatrix[2][2]
+ lMatrix.elements[11] = aPyMatrix[3][2]
+ lMatrix.elements[12] = aPyMatrix[0][3]
+ lMatrix.elements[13] = aPyMatrix[1][3]
+ lMatrix.elements[14] = aPyMatrix[2][3]
+ lMatrix.elements[15] = aPyMatrix[3][3]
+ return lMatrix
+
+
+# ---- Exporter ---------------------------------------------------------------- #
+
+class M3GExporter:
+ "Exports Blender-Scene to M3D"
+ def __init__(self, aWriter):
+ self.writer = aWriter
+
+
+ def start(self):
+ print "Info: starting export ..."
+ #rpdb2.start_embedded_debugger("t",True)
+ Translator = M3GTranslator()
+ world = Translator.start()
+
+ #sys.settrace(tracer)
+ exportList = self.createDeepSearchList(world)
+ externalReferences = [element for element in exportList if element.__class__ is M3GExternalReference]
+ exportList = [element for element in exportList if element.__class__ is not M3GExternalReference]
+ #sys.settrace(None)
+
+ # 1 is reservated for HeaderObject.
+ i=1
+
+ # Next are the external references.
+ for element in externalReferences:
+ i += 1
+ element.id = i
+ print "object ",element.id, element
+
+ # And the standard scene objects.
+ for element in exportList:
+ i += 1
+ element.id = i
+ print "object ",element.id, element
+
+ self.writer.writeFile(world, exportList, externalReferences)
+
+ print("Ready!")
+
+
+ def createDeepSearchList(self,aWorld):
+ "creates the right order for saving m3g : leafs first"
+ return aWorld.searchDeep([])
+
+
+
+# ---- Writer ---------------------------------------------------------------- #
+class JavaWriter:
+ "writes a java class which creates m3g-Scene in a j2me programm"
+ def __init__(self,aFilename):
+ self.filename = aFilename
+ self.classname = Blender.sys.basename(aFilename)
+ self.classname = self.classname[:-5] #without extention ".java"
+ self.outFile = file(aFilename,"w")
+
+ def write(self, tab, zeile=""):
+ "writes to file"
+ #print "\t" * tab + zeile
+ print >>self.outFile, "\t" * tab + zeile
+
+ def writeFile(self,aWorld,aExportList,externalReferences):
+ self.world = aWorld
+ self.writeHeader()
+ for element in aExportList:
+ element.writeJava(self,True)
+ self.writeFooter()
+ self.outFile.close()
+
+ def writeHeader(self):
+ "writes class header"
+ self.write(0,"import javax.microedition.lcdui.Image;")
+ self.write(0,"import javax.microedition.m3g.*;")
+ self.write(0,"public final class "+self.classname+" {")
+ self.write(1,"public static World getRoot(Canvas3D aCanvas) {")
+
+ def writeFooter(self):
+ self.write(1)
+ self.write(1,"return BL"+str(self.world.id)+";")
+ self.write(0,"}}")
+
+ def writeList(self,alist,numberOfElementsPerLine=12,aType=""):
+ '''Writes numberOfElementsPerLine'''
+ line=""
+ lastLine=""
+ counter=0
+ for element in alist:
+ if counter!=0:
+ line = line + "," + str(element) + aType
+ else:
+ line = str(element) + aType
+ counter = counter + 1
+ if counter == numberOfElementsPerLine:
+ if len(lastLine)>0:
+ self.write(3,lastLine+",")
+ lastLine=line
+ line=""
+ counter = 0
+ if len(lastLine)>0:
+ if len(line)>0:
+ self.write(3,lastLine+",")
+ else:
+ self.write(3,lastLine)
+ if len(line) > 0: self.write(3,line)
+
+ def writeClass(self,aName,aM3GObject):
+ self.write(2)
+ self.write(2,"//"+aName+":"+aM3GObject.name)
+
+
+class M3GSectionObject:
+ def __init__(self,aObject):
+ """Object Structure
+ Each object in the file represents one object in the
+ scene graph tree, and is stored in a chunk. The
+ structure of an object chunk is as follows:
+ Byte ObjectType
+ UInt32 Length
+ Byte[] Data"""
+ #ObjectType
+ #This field describes what type of object has been serialized.
+ #The values 0 and 0xFF are special: 0 represents the header object,
+ #and 0xFF represents an external reference.
+ #Example: Byte ObjectType = 14
+ self.ObjectType = aObject.ObjectType
+ self.data = aObject.getData()
+ self.length = aObject.getDataLength()
+
+ def getData(self):
+ data = struct.pack('<BI',self.ObjectType,self.length)
+ data += self.data
+ return data
+
+ def getDataLength(self):
+ return struct.calcsize('<BI') + self.length
+
+class M3GSection:
+ '''Part of a M3G binary file'
+ Section Structur
+ Byte CompressionScheme
+ UInt32 TotalSectionLength
+ UInt32 UncompressedLength
+ Byte[] Objects
+ UInt32 Checksum '''
+ def __init__(self,aObjectList,compressed=False):
+ self.CompressionScheme=0
+ self.TotalSectionLength=0 #including the CompressionScheme,
+ #TotalSectionLength, UncompressedLength,
+ #Objects and Checksum fields,
+ self.UncompressedLength=0 #Length of Objects uncompresses
+ self.Objects = ''
+ for element in aObjectList:
+ lObject = M3GSectionObject(element)
+ #print "Obj:", lObject, lObject.getDataLength(), len(lObject.getData())
+ self.Objects += lObject.getData()
+ self.UncompressedLength += lObject.getDataLength()
+ self.TotalSectionLength=struct.calcsize('<BIII')+self.UncompressedLength
+
+ def getData(self):
+ data = struct.pack('<BII',self.CompressionScheme,
+ self.TotalSectionLength,
+ self.UncompressedLength)
+ data += self.Objects
+ #self.Checksum = zlib.adler32(data)
+ self.Checksum = self.ownAdler32(data)
+ print "Checksum",self.Checksum
+ #print "Own Checksum",self.ownAdler32(data)
+ return data + struct.pack('<I',self.Checksum)
+
+ def ownAdler32(self,data):
+ s1 = int(1) #uint32_t
+ s2 = int(0) #uint32_t
+ for n in data:
+ s1 = (s1 + int(struct.unpack("B",n)[0])) % 65521
+ s2 = (s2 + s1) % 65521
+ return (s2 << 16) + s1
+
+ def getLength(self):
+ return self.TotalSectionLength
+
+ def write(self,aFile):
+ print "Write Section.."
+ print "TotalSectionLength:", str(self.TotalSectionLength)
+ aFile.write(self.getData())
+
+ #CompressionScheme
+ #Example Byte CompressionScheme = 1;
+ #0 Uncompressed, Adler32 Checksum
+ #1 ZLib compression, 32 k buffer size, Adler32 Checksum
+ #2...255 Reserved
+ #TotalSectionLength: total length of the section in bytes
+ #Example: UInt32 TotalSectionLength = 2056
+ #UncompressedLength
+ #contains the length of the Objects field after decompression.
+ #If no compression is specified for this section,
+ #this equals the actual number of bytes serialized in the Objects array.
+ #CompressionScheme
+ #Currently, only the Adler32 checksum is mandatory.
+ #The checksum is calculated using all preceding bytes in
+ #the section, i.e. the CompressionScheme,TotalSectionLength,
+ #UncompressedLength, and the actual serialized data in the
+ #Objects field (i.e. in its compressed form if compression is speci-
+ #fied).
+ #Example: UInt32 Checksum = 0xffe806a3
+
+
+
+
+class M3GFileIdentifier:
+ def __init__(self):
+ '''Byte[12] FileIdentifier = { 0xAB, 0x4A, 0x53, 0x52, 0x31, 0x38, 0x34,
+ 0xBB, 0x0D, 0x0A, 0x1A, 0x0A }
+ This can also be expressed using C-style character definitions as:
+ Byte[12] FileIdentifier = { '«', 'J', 'S', 'R', '1', '8', '4', '»', '\r',
+ '\n', '\x1A', '\n' }'''
+ self.data = [ 0xAB, 0x4A, 0x53, 0x52, 0x31, 0x38, 0x34,
+ 0xBB, 0x0D, 0x0A, 0x1A, 0x0A ]
+
+ def write(self,aFile):
+ for element in self.data:
+ aFile.write(struct.pack('B',element))
+
+ def getLength(self):
+ return len(self.data)
+
+
+class M3GWriter:
+ """writes a m3g binary file
+ File Structur
+ File Identifier
+ Section 0 File Header Object
+ Section 1 External Reference Objects
+ Section 2 Scene Objects
+ Section 3 Scene Objects
+ ... ...
+ Section n Scene Objects"""
+
+ def __init__(self,aFilename):
+ self.FileName = aFilename
+
+
+ def writeFile(self,aWorld,aExportList,externalReferences):
+ '''Called after translation
+ first atempt: all objects in one section'''
+ print "M3G file writing .."
+
+ fileIdentifier = M3GFileIdentifier()
+
+ fileHeaderObject = M3GHeaderObject()
+ section0 = M3GSection([fileHeaderObject])
+ sectionN = M3GSection(aExportList)
+
+ length = fileIdentifier.getLength()
+ length += section0.getLength()
+ length += sectionN.getLength()
+
+ if len(externalReferences) != 0:
+ section1 = M3GSection(externalReferences)
+ length += section1.getLength()
+ fileHeaderObject.hasExternalReferences = True
+
+ fileHeaderObject.TotalFileSize=length
+ fileHeaderObject.ApproximateContentSize=length
+ section0 = M3GSection([fileHeaderObject])
+
+ output = open(self.FileName, mode='wb')
+
+ fileIdentifier.write(output)
+ section0.write(output)
+ if len(externalReferences) != 0:
+ section1.write(output)
+ sectionN.write(output)
+
+ output.close()
+
+ print "M3G file written."
+
+
+class OptionMgr:
+ """Reads and saves options """
+
+ def __init__(self):
+ self.setDefault()
+ rdict = Registry.GetKey('M3GExport', True) # True to check on disk as well
+ if rdict: # if found, get the values saved there
+ try:
+ self.textureEnabled = rdict['textureEnabled']
+ self.textureExternal = rdict['textureExternal']
+ self.lightingEnabled = rdict['lightingEnabled']
+ self.createAmbientLight = rdict['createAmbientLight']
+ self.exportAllActions = rdict['exportAllActions']
+ self.autoscaling = rdict['autoscaling']
+ self.perspectiveCorrection = rdict['perspectiveCorrection']
+ self.smoothShading = rdict['smoothShading']
+ self.exportAsJava = rdict['exportAsJava']
+
+ except: self.save() # if data isn't valid, rewrite it
+
+ def setDefault(self):
+ self.textureEnabled = True
+ self.textureExternal = False
+ self.lightingEnabled = True
+ self.createAmbientLight = False
+ self.exportAllActions = False
+ self.autoscaling = True
+ self.perspectiveCorrection = False
+ self.smoothShading = True
+ self.exportAsJava = False
+
+ def save(self):
+ d = {}
+ d['textureEnabled'] = self.textureEnabled
+ d['textureExternal'] = self.textureExternal
+ d['lightingEnabled'] = self.lightingEnabled
+ d['createAmbientLight'] = self.createAmbientLight
+ d['exportAllActions'] = self.exportAllActions
+ d['autoscaling'] = self.autoscaling
+ d['perspectiveCorrection'] = self.perspectiveCorrection
+ d['smoothShading'] = self.smoothShading
+ d['exportAsJava'] = self.exportAsJava
+
+ Blender.Registry.SetKey('M3GExport', d, True)
+
+
+# ---- User Interface -------------------------------------------------------- #
+mOptions = OptionMgr()
+
+def gui():
+ """Draws the options menu."""
+ # Flush events.
+ for s in Window.GetScreenInfo():
+ Window.QHandle(s['id'])
+
+ # Display options.
+ textureEnabled = Draw.Create(mOptions.textureEnabled)
+ textureExternal = Draw.Create(mOptions.textureExternal)
+ lightingEnabled = Draw.Create(mOptions.lightingEnabled)
+ createAmbientLight = Draw.Create(mOptions.createAmbientLight)
+ exportAllActions = Draw.Create(mOptions.exportAllActions)
+ autoscaling = Draw.Create(mOptions.autoscaling)
+ perspectiveCorrection = Draw.Create(mOptions.perspectiveCorrection)
+ smoothShading = Draw.Create(mOptions.smoothShading)
+ exportAsJava = Draw.Create(mOptions.exportAsJava)
+
+ pupBlock = [\
+ ('Texturing'),\
+ ('Enabled', textureEnabled, 'Enables texture export'),\
+ ('External', textureExternal, 'References external files for textures'),\
+ ('Lighting'),\
+ ('Enabled', lightingEnabled, 'Enables light export'),\
+ ('Ambient Light', createAmbientLight, 'Inserts an extra light object for ambient light'),\
+ ('Mesh Options'),\
+ ('Autoscaling', autoscaling, 'Uses maximum precision for vertex positions'),\
+ ('Persp. Correction', perspectiveCorrection, 'Sets perspective correction flag'),\
+ ('Smooth Shading', smoothShading, 'Sets smooth shading flag'),\
+ ('Posing'),\
+ ('All Armature Actions', exportAllActions, 'Exports all actions for armatures'),\
+ ('Export'),\
+ ('As Java Source', exportAsJava, 'Exports scene as Java source code')
+ ]
+
+ # Only execute if use didn't quit (ESC).
+ if Draw.PupBlock('M3G Export', pupBlock):
+ mOptions.textureEnabled = textureEnabled.val
+ mOptions.textureExternal = textureExternal.val
+ mOptions.lightingEnabled = lightingEnabled.val
+ mOptions.createAmbientLight = createAmbientLight.val
+ mOptions.exportAllActions = exportAllActions.val
+ mOptions.autoscaling = autoscaling.val
+ mOptions.perspectiveCorrection = perspectiveCorrection.val
+ mOptions.smoothShading = smoothShading.val
+ mOptions.exportAsJava = exportAsJava.val
+ mOptions.save()
+
+ if mOptions.exportAsJava:
+ Window.FileSelector(file_callback_java, 'Export M3G as Java', Blender.sys.makename(ext='.java'))
+ else:
+ Window.FileSelector(file_callback_m3g, 'Export M3G Binary', Blender.sys.makename(ext='.m3g'))
+
+def file_callback_java(filename):
+ Window.WaitCursor(1) # Blender will automatically remove wait cursor in case of an exception
+ exporter=M3GExporter(JavaWriter(filename))
+ exporter.start()
+ Window.WaitCursor(0)
+ Window.RedrawAll()
+
+def file_callback_m3g(filename):
+ Window.WaitCursor(1)
+ exporter=M3GExporter(M3GWriter(filename))
+ exporter.start()
+ Window.WaitCursor(0)
+ Window.RedrawAll()
+
+if __name__ == '__main__':
+ gui() \ No newline at end of file
diff --git a/release/windows/installer/00.sconsblender.nsi b/release/windows/installer/00.sconsblender.nsi
index cd68312e69f..ff7a198d0b9 100644
--- a/release/windows/installer/00.sconsblender.nsi
+++ b/release/windows/installer/00.sconsblender.nsi
@@ -8,17 +8,19 @@
!include "FileFunc.nsh"
!include "WordFunc.nsh"
+SetCompressor /SOLID lzma
+
Name "Blender VERSION"
!define MUI_ABORTWARNING
!define MUI_WELCOMEPAGE_TEXT "This wizard will guide you through the installation of Blender.\r\n\r\nIt is recommended that you close all other applications before starting Setup.\r\n\r\nNote to Win2k/XP users: You may require administrator privileges to install Blender successfully."
-!define MUI_WELCOMEFINISHPAGE_BITMAP "01.installer.bmp"
+!define MUI_WELCOMEFINISHPAGE_BITMAP "RELDIR\01.installer.bmp"
!define MUI_HEADERIMAGE
-!define MUI_HEADERIMAGE_BITMAP "00.header.bmp"
+!define MUI_HEADERIMAGE_BITMAP "RELDIR\00.header.bmp"
!define MUI_COMPONENTSPAGE_SMALLDESC
!define MUI_FINISHPAGE_RUN "$INSTDIR\blender.exe"
-!define MUI_CHECKBITMAP "00.checked.bmp"
+!define MUI_CHECKBITMAP "RELDIR\00.checked.bmp"
!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_LICENSE "DISTDIR\Copyright.txt"
@@ -38,8 +40,8 @@ Page custom DataLocation
!insertmacro VersionCompare
-Icon "00.installer.ico"
-UninstallIcon "00.installer.ico"
+Icon "RELDIR\00.installer.ico"
+UninstallIcon "RELDIR\00.installer.ico"
;--------------------------------
;Languages
@@ -60,7 +62,6 @@ UninstallIcon "00.installer.ico"
Caption "Blender VERSION Installer"
OutFile "DISTDIR\..\blender-VERSION-windows.exe"
-
InstallDir "$PROGRAMFILES\Blender Foundation\Blender"
BrandingText "http://www.blender.org/bf"
@@ -208,7 +209,7 @@ Function .onInit
Call GetWindowsVersion
Pop $R0
Strcpy $winversion $R0
- !insertmacro MUI_INSTALLOPTIONS_EXTRACT "data.ini"
+ !insertmacro MUI_INSTALLOPTIONS_EXTRACT "RELDIR\data.ini"
FunctionEnd
!define DLL_VER "8.00.50727.42"
diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h
index bf3e25b1c5a..4b9e10651cf 100644
--- a/source/blender/blenkernel/BKE_blender.h
+++ b/source/blender/blenkernel/BKE_blender.h
@@ -44,7 +44,7 @@ struct ListBase;
struct MemFile;
#define BLENDER_VERSION 244
-#define BLENDER_SUBVERSION 1
+#define BLENDER_SUBVERSION 2
#define BLENDER_MINVERSION 240
#define BLENDER_MINSUBVERSION 0
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index bace38651ea..44266a1c854 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -204,6 +204,8 @@ struct ShadeResult;
#define SH_NODE_MATH 115
#define SH_NODE_VECT_MATH 116
#define SH_NODE_SQUEEZE 117
+#define SH_NODE_MATERIAL_EXT 118
+#define SH_NODE_INVERT 119
/* custom defines options for Material node */
@@ -293,9 +295,16 @@ void set_node_shader_lamp_loop(void (*lamp_loop_func)(struct ShadeInput *, str
#define CMP_NODE_COMBHSVA 246
#define CMP_NODE_MATH 247
#define CMP_NODE_LUMA_MATTE 248
-
#define CMP_NODE_BRIGHTCONTRAST 249
#define CMP_NODE_GAMMA 250
+#define CMP_NODE_INVERT 251
+
+/* channel toggles */
+#define CMP_CHAN_RGB 1
+#define CMP_CHAN_A 2
+#define CMP_CHAN_R 4
+#define CMP_CHAN_G 8
+#define CMP_CHAN_B 16
/* filter types */
#define CMP_FILT_SOFT 0
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index dc54fc7c1f0..5f8e9c7b207 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -2272,7 +2272,7 @@ float *multires_render_pin(Object *ob, Mesh *me, int *orig_lvl)
lvl= multires_level_n(me->mr, BLI_countlist(&me->mr->levels));
vert_copy= MEM_callocN(sizeof(float)*3*lvl->totvert, "multires vert_copy");
for(i=0; i<lvl->totvert; ++i)
- VecCopyf(&vert_copy[i*3], lvl->verts[i].co);
+ VecCopyf(&vert_copy[i*3], me->mr->verts[i].co);
/* Goto the pin level for multires */
me->mr->newlvl= me->mr->pinlvl;
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index 278d49e2198..4c6bfda1517 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -504,7 +504,7 @@ static float *make_orco_mesh_internal(Object *ob, int render)
if(me->mr) {
lvl = multires_level_n(me->mr, me->mr->pinlvl);
vcos = MEM_callocN(sizeof(*vcos)*lvl->totvert, "orco mr mesh");
- mvert = lvl->verts;
+ mvert = me->mr->verts;
totvert = lvl->totvert;
}
else {
diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c
index a348aef0399..961ea21d088 100644
--- a/source/blender/blenkernel/intern/nla.c
+++ b/source/blender/blenkernel/intern/nla.c
@@ -141,7 +141,10 @@ bActionStrip *convert_action_to_strip (Object *ob)
//set_active_strip(ob, nstrip); /* is in editnla as does UI calls */
nstrip->repeat = 1.0;
-
+
+ if(ob->nlastrips.first == NULL)
+ ob->nlaflag |= OB_NLA_OVERRIDE;
+
BLI_addtail(&ob->nlastrips, nstrip);
return nstrip; /* is created, malloced etc. here so is safe to just return the pointer?
this is needed for setting this active in UI, and probably useful for API too */
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index 842e07cebe7..e7b7b36aaa4 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -2322,6 +2322,9 @@ static void registerCompositNodes(ListBase *ntypelist)
nodeRegisterType(ntypelist, &cmp_node_curve_rgb);
nodeRegisterType(ntypelist, &cmp_node_mix_rgb);
nodeRegisterType(ntypelist, &cmp_node_hue_sat);
+ nodeRegisterType(ntypelist, &cmp_node_brightcontrast);
+ nodeRegisterType(ntypelist, &cmp_node_gamma);
+ nodeRegisterType(ntypelist, &cmp_node_invert);
nodeRegisterType(ntypelist, &cmp_node_alphaover);
nodeRegisterType(ntypelist, &cmp_node_zcombine);
@@ -2361,9 +2364,6 @@ static void registerCompositNodes(ListBase *ntypelist)
nodeRegisterType(ntypelist, &cmp_node_flip);
nodeRegisterType(ntypelist, &cmp_node_displace);
nodeRegisterType(ntypelist, &cmp_node_mapuv);
-
- nodeRegisterType(ntypelist, &cmp_node_brightcontrast);
- nodeRegisterType(ntypelist, &cmp_node_gamma);
}
static void registerShaderNodes(ListBase *ntypelist)
@@ -2383,9 +2383,11 @@ static void registerShaderNodes(ListBase *ntypelist)
nodeRegisterType(ntypelist, &sh_node_squeeze);
nodeRegisterType(ntypelist, &sh_node_camera);
nodeRegisterType(ntypelist, &sh_node_material);
+ nodeRegisterType(ntypelist, &sh_node_material_ext);
nodeRegisterType(ntypelist, &sh_node_value);
nodeRegisterType(ntypelist, &sh_node_rgb);
nodeRegisterType(ntypelist, &sh_node_texture);
+ nodeRegisterType(ntypelist, &sh_node_invert);
}
void init_nodesystem(void)
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 118c2779ac0..1b595b1e3fc 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -2554,6 +2554,8 @@ static void direct_link_mesh(FileData *fd, Mesh *mesh)
mesh->mr->edge_flags= MEM_callocN(sizeof(short)*lvl->totedge, "Multires Edge Flags");
if(!mesh->mr->edge_creases)
mesh->mr->edge_creases= MEM_callocN(sizeof(char)*lvl->totedge, "Multires Edge Creases");
+
+ mesh->mr->verts = newdataadr(fd, mesh->mr->verts);
for(; lvl; lvl= lvl->next) {
lvl->verts= newdataadr(fd, lvl->verts);
@@ -6465,9 +6467,28 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
if(main->versionfile <= 244) {
Scene *sce;
- if(main->subversionfile < 1) {
+ if(main->versionfile != 244 || main->subversionfile < 2) {
+ Mesh *me;
for(sce= main->scene.first; sce; sce= sce->id.next)
sce->r.mode |= R_SSS;
+
+ /* Copy over old per-level multires vertex data
+ into a single vertex array in struct Multires */
+
+ for(me = main->mesh.first; me; me=me->id.next) {
+ if(me->mr) {
+ MultiresLevel *lvl = me->mr->levels.last;
+ if(lvl) {
+ me->mr->verts = lvl->verts;
+ lvl->verts = NULL;
+ /* Don't need the other vert arrays */
+ for(lvl = lvl->prev; lvl; lvl = lvl->prev) {
+ MEM_freeN(lvl->verts);
+ lvl->verts = NULL;
+ }
+ }
+ }
+ }
}
}
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index 0d4d9d82ee1..226561ab97b 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -1156,13 +1156,17 @@ static void write_meshs(WriteData *wd, ListBase *idbase)
writedata(wd, DATA, sizeof(short)*lvl->totedge, mesh->mr->edge_flags);
writedata(wd, DATA, sizeof(char)*lvl->totedge, mesh->mr->edge_creases);
}
+
for(; lvl; lvl= lvl->next) {
writestruct(wd, DATA, "MultiresLevel", 1, lvl);
- writestruct(wd, DATA, "MVert", lvl->totvert, lvl->verts);
writestruct(wd, DATA, "MultiresFace", lvl->totface, lvl->faces);
writestruct(wd, DATA, "MultiresEdge", lvl->totedge, lvl->edges);
writestruct(wd, DATA, "MultiresColFace", lvl->totface, lvl->colfaces);
}
+
+ lvl= mesh->mr->levels.last;
+ if(lvl)
+ writestruct(wd, DATA, "MVert", lvl->totvert, mesh->mr->verts);
}
/* PMV data */
diff --git a/source/blender/imbuf/intern/util.c b/source/blender/imbuf/intern/util.c
index fccb3aba7fc..69390951a25 100644
--- a/source/blender/imbuf/intern/util.c
+++ b/source/blender/imbuf/intern/util.c
@@ -258,17 +258,17 @@ static int isffmpeg (char *filename) {
BLI_testextensie(filename, ".wav")) return 0;
if(av_open_input_file(&pFormatCtx, filename, NULL, 0, NULL)!=0) {
- fprintf(stderr, "isffmpeg: av_open_input_file failed\n");
+ if(UTIL_DEBUG) fprintf(stderr, "isffmpeg: av_open_input_file failed\n");
return 0;
}
if(av_find_stream_info(pFormatCtx)<0) {
- fprintf(stderr, "isffmpeg: av_find_stream_info failed\n");
+ if(UTIL_DEBUG) fprintf(stderr, "isffmpeg: av_find_stream_info failed\n");
av_close_input_file(pFormatCtx);
return 0;
}
- dump_format(pFormatCtx, 0, filename, 0);
+ if(UTIL_DEBUG) dump_format(pFormatCtx, 0, filename, 0);
/* Find the first video stream */
@@ -315,19 +315,33 @@ int imb_get_anim_type(char * name) {
if(UTIL_DEBUG) printf("in getanimtype: %s\n", name);
-#ifdef WITH_FFMPEG
+#ifndef _WIN32
+# ifdef WITH_FFMPEG
/* stat test below fails on large files > 4GB */
if (isffmpeg(name)) return (ANIM_FFMPEG);
-#endif
+# endif
+ if (ib_stat(name,&st) == -1) return(0);
+ if (((st.st_mode) & S_IFMT) != S_IFREG) return(0);
+
+ if (isavi(name)) return (ANIM_AVI);
+ if (ismovie(name)) return (ANIM_MOVIE);
+# ifdef WITH_QUICKTIME
+ if (isqtime(name)) return (ANIM_QTIME);
+# endif
+#else
if (ib_stat(name,&st) == -1) return(0);
if (((st.st_mode) & S_IFMT) != S_IFREG) return(0);
if (isavi(name)) return (ANIM_AVI);
if (ismovie(name)) return (ANIM_MOVIE);
-#ifdef WITH_QUICKTIME
+# ifdef WITH_QUICKTIME
if (isqtime(name)) return (ANIM_QTIME);
+# endif
+# ifdef WITH_FFMPEG
+ if (isffmpeg(name)) return (ANIM_FFMPEG);
+# endif
#endif
type = IMB_ispic(name);
if (type == ANIM) return (ANIM_ANIM5);
diff --git a/source/blender/include/BIF_editaction.h b/source/blender/include/BIF_editaction.h
index 2d92b120b9a..6e180418cd8 100644
--- a/source/blender/include/BIF_editaction.h
+++ b/source/blender/include/BIF_editaction.h
@@ -92,6 +92,7 @@ void snap_keys_to_frame(int snap_mode);
void mirror_action_keys(short mirror_mode);
void clean_shapekeys(struct Key *key);
void clean_actionchannels(struct bAction *act);
+void insertkey_action(void);
/* Marker Operations */
void column_select_shapekeys(struct Key *key, int mode);
diff --git a/source/blender/include/BIF_editdeform.h b/source/blender/include/BIF_editdeform.h
index 69f03652887..2a8f43c14e7 100644
--- a/source/blender/include/BIF_editdeform.h
+++ b/source/blender/include/BIF_editdeform.h
@@ -67,5 +67,8 @@ void vertexgroup_select_by_name(struct Object *ob, char *name);
extern void object_apply_deform(struct Object *ob);
+void vgroup_assign_with_menu(void);
+void vgroup_operation_with_menu(void);
+
#endif
diff --git a/source/blender/include/multires.h b/source/blender/include/multires.h
index 6c33af2d5e3..069dbee802f 100644
--- a/source/blender/include/multires.h
+++ b/source/blender/include/multires.h
@@ -31,6 +31,7 @@
#define MULTIRES_H
struct CustomData;
+struct EditMesh;
struct Object;
struct MDeformVert;
struct Mesh;
@@ -65,6 +66,7 @@ int multires_modifier_warning();
/* multires-firstlevel.c */
/* Generic */
+void multires_update_first_level(struct Mesh *me, struct EditMesh *em);
void multires_update_customdata(struct MultiresLevel *lvl1, struct CustomData *src,
struct CustomData *dst, const int type);
void multires_customdata_to_mesh(struct Mesh *me, struct EditMesh *em, struct MultiresLevel *lvl,
diff --git a/source/blender/makesdna/DNA_meshdata_types.h b/source/blender/makesdna/DNA_meshdata_types.h
index 4d78f577137..af9c1ae629d 100644
--- a/source/blender/makesdna/DNA_meshdata_types.h
+++ b/source/blender/makesdna/DNA_meshdata_types.h
@@ -109,7 +109,6 @@ struct MultiresMapNode;
typedef struct MultiresLevel {
struct MultiresLevel *next, *prev;
- MVert *verts;
MultiresFace *faces;
MultiresColFace *colfaces;
MultiresEdge *edges;
@@ -118,10 +117,15 @@ typedef struct MultiresLevel {
struct MultiresMapNode *map_mem;
unsigned int totvert, totface, totedge, pad;
+
+ /* Kept for compatibility with older files */
+ MVert *verts;
} MultiresLevel;
typedef struct Multires {
ListBase levels;
+ MVert *verts;
+
unsigned char level_count, current, newlvl, edgelvl, pinlvl, renderlvl;
unsigned char use_col, pad;
diff --git a/source/blender/nodes/CMP_node.h b/source/blender/nodes/CMP_node.h
index ea15d4dbe73..3410238c0a2 100644
--- a/source/blender/nodes/CMP_node.h
+++ b/source/blender/nodes/CMP_node.h
@@ -53,6 +53,9 @@ extern bNodeType cmp_node_output_file;
extern bNodeType cmp_node_curve_rgb;
extern bNodeType cmp_node_mix_rgb;
extern bNodeType cmp_node_hue_sat;
+extern bNodeType cmp_node_brightcontrast;
+extern bNodeType cmp_node_gamma;
+extern bNodeType cmp_node_invert;
extern bNodeType cmp_node_alphaover;
extern bNodeType cmp_node_zcombine;
@@ -93,9 +96,6 @@ extern bNodeType cmp_node_flip;
extern bNodeType cmp_node_displace;
extern bNodeType cmp_node_mapuv;
-extern bNodeType cmp_node_brightcontrast;
-extern bNodeType cmp_node_gamma;
-
#endif
diff --git a/source/blender/nodes/SHD_node.h b/source/blender/nodes/SHD_node.h
index b443a39624b..688494d6de5 100644
--- a/source/blender/nodes/SHD_node.h
+++ b/source/blender/nodes/SHD_node.h
@@ -56,6 +56,8 @@ extern bNodeType sh_node_curve_rgb;
extern bNodeType sh_node_math;
extern bNodeType sh_node_vect_math;
extern bNodeType sh_node_squeeze;
+extern bNodeType sh_node_material_ext;
+extern bNodeType sh_node_invert;
#endif
diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_alphaOver.c b/source/blender/nodes/intern/CMP_nodes/CMP_alphaOver.c
index aedaa036d67..f108098750c 100644
--- a/source/blender/nodes/intern/CMP_nodes/CMP_alphaOver.c
+++ b/source/blender/nodes/intern/CMP_nodes/CMP_alphaOver.c
@@ -90,12 +90,12 @@ static void node_composit_exec_alphaover(void *data, bNode *node, bNodeStack **i
return;
/* input no image? then only color operation */
- if(in[1]->data==NULL) {
+ if(in[1]->data==NULL && in[2]->data==NULL) {
do_alphaover_premul(node, out[0]->vec, in[1]->vec, in[2]->vec, in[0]->vec);
}
else {
/* make output size of input image */
- CompBuf *cbuf= in[1]->data;
+ CompBuf *cbuf= in[1]->data?in[1]->data:in[2]->data;
CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* allocs */
if(node->custom1)
diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_curves.c b/source/blender/nodes/intern/CMP_nodes/CMP_curves.c
index 754d016fb25..17d9821a5ef 100644
--- a/source/blender/nodes/intern/CMP_nodes/CMP_curves.c
+++ b/source/blender/nodes/intern/CMP_nodes/CMP_curves.c
@@ -172,10 +172,10 @@ static void node_composit_exec_curve_rgb(void *data, bNode *node, bNodeStack **i
CompBuf *cbuf= in[1]->data;
CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* allocs */
- if(in[0]->data)
- composit2_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, in[0]->data, in[0]->vec, do_curves_fac, CB_RGBA, CB_VAL);
- else
+ if(in[0]->vec[0] == 1.0)
composit1_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, do_curves, CB_RGBA);
+ else
+ composit2_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, in[0]->data, in[0]->vec, do_curves_fac, CB_RGBA, CB_VAL);
out[0]->data= stackbuf;
}
diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_invert.c b/source/blender/nodes/intern/CMP_nodes/CMP_invert.c
new file mode 100644
index 00000000000..1d4be2bc09f
--- /dev/null
+++ b/source/blender/nodes/intern/CMP_nodes/CMP_invert.c
@@ -0,0 +1,134 @@
+/**
+ * $Id: CMP_mixrgb.c,v 1.4 2007/04/04 13:58:10 jesterking Exp $
+ *
+ * ***** BEGIN 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 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.
+ *
+ * The Original Code is Copyright (C) 2006 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#include "../CMP_util.h"
+
+/* **************** INVERT ******************** */
+static bNodeSocketType cmp_node_invert_in[]= {
+ { SOCK_VALUE, 1, "Fac", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_RGBA, 1, "Color", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+ { -1, 0, "" }
+};
+
+static bNodeSocketType cmp_node_invert_out[]= {
+ { SOCK_RGBA, 0, "Color", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+ { -1, 0, "" }
+};
+
+static void do_invert(bNode *node, float *out, float *in)
+{
+ if(node->custom1 & CMP_CHAN_RGB) {
+ out[0] = 1.0f - in[0];
+ out[1] = 1.0f - in[1];
+ out[2] = 1.0f - in[2];
+ } else
+ VECCOPY(out, in);
+
+ if(node->custom1 & CMP_CHAN_A)
+ out[3] = 1.0f - in[3];
+ else
+ out[3] = in[3];
+}
+
+static void do_invert_fac(bNode *node, float *out, float *in, float *fac)
+{
+ float col[4], facm;
+
+ do_invert(node, col, in);
+
+ /* blend inverted result against original input with fac */
+ facm = 1.0 - fac[0];
+
+ if(node->custom1 & CMP_CHAN_RGB) {
+ col[0] = fac[0]*col[0] + (facm*in[0]);
+ col[1] = fac[0]*col[1] + (facm*in[1]);
+ col[2] = fac[0]*col[2] + (facm*in[2]);
+ }
+ if(node->custom1 & CMP_CHAN_A)
+ col[3] = fac[0]*col[3] + (facm*in[3]);
+
+ QUATCOPY(out, col);
+}
+
+static void node_composit_exec_invert(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+ /* stack order in: fac, Image, Image */
+ /* stack order out: Image */
+ float *fac= in[0]->vec;
+
+ if(out[0]->hasoutput==0) return;
+
+ /* input no image? then only color operation */
+ if(in[1]->data==NULL && in[0]->data==NULL) {
+ do_invert_fac(node, out[0]->vec, in[1]->vec, fac);
+ }
+ else {
+ /* make output size of first available input image, or then size of fac */
+ CompBuf *cbuf= in[1]->data?in[1]->data:in[0]->data;
+
+ /* if neither RGB or A toggled on, pass through */
+ if (node->custom1 != 0) {
+ CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* allocs */
+
+ if (fac[0] < 1.0f || in[0]->data!=NULL)
+ composit2_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, in[0]->data, fac, do_invert_fac, CB_RGBA, CB_VAL);
+ else
+ composit1_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, do_invert, CB_RGBA);
+ out[0]->data= stackbuf;
+ return;
+
+ } else {
+ out[0]->data = pass_on_compbuf(cbuf);
+ return;
+ }
+ }
+}
+
+static void node_composit_init_invert(bNode *node)
+{
+ node->custom1 |= CMP_CHAN_RGB;
+}
+
+/* custom1 = mix type */
+bNodeType cmp_node_invert= {
+ /* *next,*prev */ NULL, NULL,
+ /* type code */ CMP_NODE_INVERT,
+ /* name */ "Invert",
+ /* width+range */ 120, 120, 140,
+ /* class+opts */ NODE_CLASS_OP_COLOR, NODE_OPTIONS,
+ /* input sock */ cmp_node_invert_in,
+ /* output sock */ cmp_node_invert_out,
+ /* storage */ "",
+ /* execfunc */ node_composit_exec_invert,
+ /* butfunc */ NULL,
+ /* initfunc */ node_composit_init_invert,
+ /* freestoragefunc */ NULL,
+ /* copystoragefunc */ NULL,
+ /* id */ NULL
+
+};
diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_mixrgb.c b/source/blender/nodes/intern/CMP_nodes/CMP_mixrgb.c
index 790b24a105a..6a4916b3fac 100644
--- a/source/blender/nodes/intern/CMP_nodes/CMP_mixrgb.c
+++ b/source/blender/nodes/intern/CMP_nodes/CMP_mixrgb.c
@@ -81,7 +81,7 @@ bNodeType cmp_node_mix_rgb= {
/* *next,*prev */ NULL, NULL,
/* type code */ CMP_NODE_MIX_RGB,
/* name */ "Mix",
- /* width+range */ 80, 60, 120,
+ /* width+range */ 110, 60, 120,
/* class+opts */ NODE_CLASS_OP_COLOR, NODE_OPTIONS,
/* input sock */ cmp_node_mix_rgb_in,
/* output sock */ cmp_node_mix_rgb_out,
diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_setalpha.c b/source/blender/nodes/intern/CMP_nodes/CMP_setalpha.c
index d56baecb587..a7e0e28989b 100644
--- a/source/blender/nodes/intern/CMP_nodes/CMP_setalpha.c
+++ b/source/blender/nodes/intern/CMP_nodes/CMP_setalpha.c
@@ -46,7 +46,7 @@ static void node_composit_exec_setalpha(void *data, bNode *node, bNodeStack **in
/* stack order in: col, alpha */
/* input no image? then only color operation */
- if(in[0]->data==NULL) {
+ if(in[0]->data==NULL && in[1]->data==NULL) {
out[0]->vec[0] = in[0]->vec[0];
out[0]->vec[1] = in[0]->vec[1];
out[0]->vec[2] = in[0]->vec[2];
@@ -54,7 +54,7 @@ static void node_composit_exec_setalpha(void *data, bNode *node, bNodeStack **in
}
else {
/* make output size of input image */
- CompBuf *cbuf= in[0]->data;
+ CompBuf *cbuf= in[0]->data?in[0]->data:in[1]->data;
CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* allocs */
if(in[1]->data==NULL && in[1]->vec[0]==1.0f) {
diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_geom.c b/source/blender/nodes/intern/SHD_nodes/SHD_geom.c
index 3875dead2b0..b15aa6802f3 100644
--- a/source/blender/nodes/intern/SHD_nodes/SHD_geom.c
+++ b/source/blender/nodes/intern/SHD_nodes/SHD_geom.c
@@ -41,6 +41,7 @@ static bNodeSocketType sh_node_geom_out[]= {
{ SOCK_VECTOR, 0, "UV", 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f},
{ SOCK_VECTOR, 0, "Normal", 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f},
{ SOCK_RGBA, 0, "Vertex Color", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+ { SOCK_VALUE, 0, "Front/Back", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
{ -1, 0, "" }
};
@@ -52,6 +53,7 @@ static void node_shader_exec_geom(void *data, bNode *node, bNodeStack **in, bNod
NodeGeometry *ngeo= (NodeGeometry*)node->storage;
ShadeInputUV *suv= &shi->uv[0];
static float defaultvcol[4] = {1.0f, 1.0f, 1.0f, 1.0f};
+ static float front= 0.0;
int i;
if(ngeo->uvname[0]) {
@@ -105,6 +107,15 @@ static void node_shader_exec_geom(void *data, bNode *node, bNodeStack **in, bNod
out[GEOM_OUT_NORMAL]->data= shi->dxno;
out[GEOM_OUT_NORMAL]->datatype= NS_OSA_VECTORS;
}
+
+ /* front/back
+ * check the original un-flipped normals to determine front or back side */
+ if (shi->orignor[2] < FLT_EPSILON) {
+ front= 1.0f;
+ } else {
+ front = 0.0f;
+ }
+ out[GEOM_OUT_FRONTBACK]->vec[0]= front;
}
}
diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_invert.c b/source/blender/nodes/intern/SHD_nodes/SHD_invert.c
new file mode 100644
index 00000000000..4d1ce282fce
--- /dev/null
+++ b/source/blender/nodes/intern/SHD_nodes/SHD_invert.c
@@ -0,0 +1,83 @@
+/**
+ * $Id: SHD_math.c,v 1.4 2007/04/04 13:58:12 jesterking Exp $
+ *
+ * ***** BEGIN 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 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.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "../SHD_util.h"
+
+
+
+/* **************** INVERT ******************** */
+static bNodeSocketType sh_node_invert_in[]= {
+ { SOCK_VALUE, 1, "Fac", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_RGBA, 1, "Color", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+ { -1, 0, "" }
+};
+
+static bNodeSocketType sh_node_invert_out[]= {
+ { SOCK_RGBA, 0, "Color", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+ { -1, 0, "" }
+};
+
+static void node_shader_exec_invert(void *data, bNode *node, bNodeStack **in,
+bNodeStack **out)
+{
+ float col[3], facm;
+
+ col[0] = 1.0f - in[1]->vec[0];
+ col[1] = 1.0f - in[1]->vec[1];
+ col[2] = 1.0f - in[1]->vec[2];
+
+ /* if fac, blend result against original input */
+ if (in[0]->vec[0] < 1.0f) {
+ facm = 1.0 - in[0]->vec[0];
+
+ col[0] = in[0]->vec[0]*col[0] + (facm*in[1]->vec[0]);
+ col[1] = in[0]->vec[0]*col[1] + (facm*in[1]->vec[1]);
+ col[2] = in[0]->vec[0]*col[2] + (facm*in[1]->vec[2]);
+ }
+
+ VECCOPY(out[0]->vec, col);
+}
+
+bNodeType sh_node_invert= {
+ /* *next,*prev */ NULL, NULL,
+ /* type code */ SH_NODE_INVERT,
+ /* name */ "Invert",
+ /* width+range */ 90, 80, 100,
+ /* class+opts */ NODE_CLASS_OP_COLOR, NODE_OPTIONS,
+ /* input sock */ sh_node_invert_in,
+ /* output sock */ sh_node_invert_out,
+ /* storage */ "",
+ /* execfunc */ node_shader_exec_invert,
+ /* butfunc */ NULL,
+ /* initfunc */ NULL,
+ /* freestoragefunc */ NULL,
+ /* copystoragefunc */ NULL,
+ /* id */ NULL
+};
+
diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_material.c b/source/blender/nodes/intern/SHD_nodes/SHD_material.c
index 1dc18f97496..bdceb134c0d 100644
--- a/source/blender/nodes/intern/SHD_nodes/SHD_material.c
+++ b/source/blender/nodes/intern/SHD_nodes/SHD_material.c
@@ -39,11 +39,6 @@ static bNodeSocketType sh_node_material_in[]= {
{ -1, 0, "" }
};
-/* output socket defines */
-#define MAT_OUT_COLOR 0
-#define MAT_OUT_ALPHA 1
-#define MAT_OUT_NORMAL 2
-
static bNodeSocketType sh_node_material_out[]= {
{ SOCK_RGBA, 0, "Color", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
{ SOCK_VALUE, 0, "Alpha", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
@@ -51,6 +46,34 @@ static bNodeSocketType sh_node_material_out[]= {
{ -1, 0, "" }
};
+/* **************** EXTENDED MATERIAL ******************** */
+
+static bNodeSocketType sh_node_material_ext_in[]= {
+ { SOCK_RGBA, 1, "Color", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+ { SOCK_RGBA, 1, "Spec", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+ { SOCK_VALUE, 1, "Refl", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+ { SOCK_VECTOR, 1, "Normal", 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f},
+ { SOCK_RGBA, 1, "Mirror", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+ { SOCK_RGBA, 1, "AmbCol", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+ { SOCK_VALUE, 1, "Ambient", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+ { SOCK_VALUE, 1, "Emit", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+ { SOCK_VALUE, 1, "SpecTra", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+ { SOCK_VALUE, 1, "Ray Mirror", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_VALUE, 1, "Alpha", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+ { SOCK_VALUE, 1, "Translucency", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+ { -1, 0, "" }
+};
+
+static bNodeSocketType sh_node_material_ext_out[]= {
+ { SOCK_RGBA, 0, "Color", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+ { SOCK_VALUE, 0, "Alpha", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_VECTOR, 0, "Normal", 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f},
+ { SOCK_RGBA, 0, "Diffuse", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+ { SOCK_RGBA, 0, "Spec", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+ { SOCK_RGBA, 0, "AO", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+ { -1, 0, "" }
+};
+
static void node_shader_exec_material(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
{
if(data && node->id) {
@@ -91,6 +114,25 @@ static void node_shader_exec_material(void *data, bNode *node, bNodeStack **in,
shi->vn[2]= -shi->vn[2];
}
+ if (node->type == SH_NODE_MATERIAL_EXT) {
+ if(in[MAT_IN_MIR]->hasinput)
+ nodestack_get_vec(&shi->mirr, SOCK_VECTOR, in[MAT_IN_MIR]);
+ if(in[MAT_IN_AMBCOL]->hasinput)
+ nodestack_get_vec(&shi->ambr, SOCK_VECTOR, in[MAT_IN_AMBCOL]);
+ if(in[MAT_IN_AMB]->hasinput)
+ nodestack_get_vec(&shi->amb, SOCK_VALUE, in[MAT_IN_AMB]);
+ if(in[MAT_IN_EMIT]->hasinput)
+ nodestack_get_vec(&shi->emit, SOCK_VALUE, in[MAT_IN_EMIT]);
+ if(in[MAT_IN_SPECTRA]->hasinput)
+ nodestack_get_vec(&shi->spectra, SOCK_VALUE, in[MAT_IN_SPECTRA]);
+ if(in[MAT_IN_RAY_MIRROR]->hasinput)
+ nodestack_get_vec(&shi->ray_mirror, SOCK_VALUE, in[MAT_IN_RAY_MIRROR]);
+ if(in[MAT_IN_ALPHA]->hasinput)
+ nodestack_get_vec(&shi->alpha, SOCK_VALUE, in[MAT_IN_ALPHA]);
+ if(in[MAT_IN_TRANSLUCENCY]->hasinput)
+ nodestack_get_vec(&shi->translucency, SOCK_VALUE, in[MAT_IN_TRANSLUCENCY]);
+ }
+
node_shader_lamp_loop(shi, &shrnode); /* clears shrnode */
/* write to outputs */
@@ -122,6 +164,15 @@ static void node_shader_exec_material(void *data, bNode *node, bNodeStack **in,
VECCOPY(out[MAT_OUT_NORMAL]->vec, shi->vn);
+ /* Extended material options */
+ if (node->type == SH_NODE_MATERIAL_EXT) {
+ /* Shadow, Reflect, Refract, Radiosity, Speed seem to cause problems inside
+ * a node tree :( */
+ VECCOPY(out[MAT_OUT_DIFFUSE]->vec, shrnode.diff);
+ VECCOPY(out[MAT_OUT_SPEC]->vec, shrnode.spec);
+ VECCOPY(out[MAT_OUT_AO]->vec, shrnode.ao);
+ }
+
/* copy passes, now just active node */
if(node->flag & NODE_ACTIVE_ID)
*(shcd->shr)= shrnode;
@@ -153,3 +204,21 @@ bNodeType sh_node_material= {
};
+bNodeType sh_node_material_ext= {
+ /* *next,*prev */ NULL, NULL,
+ /* type code */ SH_NODE_MATERIAL_EXT,
+ /* name */ "Extended Material",
+ /* width+range */ 120, 80, 240,
+ /* class+opts */ NODE_CLASS_INPUT, NODE_OPTIONS|NODE_PREVIEW,
+ /* input sock */ sh_node_material_ext_in,
+ /* output sock */ sh_node_material_ext_out,
+ /* storage */ "",
+ /* execfunc */ node_shader_exec_material,
+ /* butfunc */ NULL,
+ /* initfunc */ node_shader_init_material,
+ /* freestoragefunc */ NULL,
+ /* copystoragefunc */ NULL,
+ /* id */ NULL
+
+};
+
diff --git a/source/blender/nodes/intern/SHD_util.c b/source/blender/nodes/intern/SHD_util.c
index 8401c302386..c9f58fbce49 100644
--- a/source/blender/nodes/intern/SHD_util.c
+++ b/source/blender/nodes/intern/SHD_util.c
@@ -145,7 +145,7 @@ void nodeShaderSynchronizeID(bNode *node, int copyto)
{
if(node->id==NULL) return;
- if(node->type==SH_NODE_MATERIAL) {
+ if(ELEM(node->type, SH_NODE_MATERIAL, SH_NODE_MATERIAL_EXT)) {
bNodeSocket *sock;
Material *ma= (Material *)node->id;
int a;
@@ -161,6 +161,20 @@ void nodeShaderSynchronizeID(bNode *node, int copyto)
VECCOPY(&ma->specr, sock->ns.vec); break;
case MAT_IN_REFL:
ma->ref= sock->ns.vec[0]; break;
+ case MAT_IN_MIR:
+ VECCOPY(&ma->mirr, sock->ns.vec); break;
+ case MAT_IN_AMB:
+ VECCOPY(&ma->ambr, sock->ns.vec); break;
+ case MAT_IN_EMIT:
+ ma->emit= sock->ns.vec[0]; break;
+ case MAT_IN_SPECTRA:
+ ma->spectra= sock->ns.vec[0]; break;
+ case MAT_IN_RAY_MIRROR:
+ ma->ray_mirror= sock->ns.vec[0]; break;
+ case MAT_IN_ALPHA:
+ ma->alpha= sock->ns.vec[0]; break;
+ case MAT_IN_TRANSLUCENCY:
+ ma->translucency= sock->ns.vec[0]; break;
}
}
else {
@@ -171,6 +185,20 @@ void nodeShaderSynchronizeID(bNode *node, int copyto)
VECCOPY(sock->ns.vec, &ma->specr); break;
case MAT_IN_REFL:
sock->ns.vec[0]= ma->ref; break;
+ case MAT_IN_MIR:
+ VECCOPY(sock->ns.vec, &ma->mirr); break;
+ case MAT_IN_AMB:
+ VECCOPY(sock->ns.vec, &ma->ambr); break;
+ case MAT_IN_EMIT:
+ sock->ns.vec[0]= ma->emit; break;
+ case MAT_IN_SPECTRA:
+ sock->ns.vec[0]= ma->spectra; break;
+ case MAT_IN_RAY_MIRROR:
+ sock->ns.vec[0]= ma->ray_mirror; break;
+ case MAT_IN_ALPHA:
+ sock->ns.vec[0]= ma->alpha; break;
+ case MAT_IN_TRANSLUCENCY:
+ sock->ns.vec[0]= ma->translucency; break;
}
}
}
diff --git a/source/blender/nodes/intern/SHD_util.h b/source/blender/nodes/intern/SHD_util.h
index 6b9a26de350..f75802b7c15 100644
--- a/source/blender/nodes/intern/SHD_util.h
+++ b/source/blender/nodes/intern/SHD_util.h
@@ -108,12 +108,30 @@ typedef struct ShaderCallData {
#define GEOM_OUT_UV 4
#define GEOM_OUT_NORMAL 5
#define GEOM_OUT_VCOL 6
+#define GEOM_OUT_FRONTBACK 7
+
/* input socket defines */
#define MAT_IN_COLOR 0
#define MAT_IN_SPEC 1
#define MAT_IN_REFL 2
#define MAT_IN_NORMAL 3
+#define MAT_IN_MIR 4
+#define MAT_IN_AMBCOL 5
+#define MAT_IN_AMB 6
+#define MAT_IN_EMIT 7
+#define MAT_IN_SPECTRA 8
+#define MAT_IN_RAY_MIRROR 9
+#define MAT_IN_ALPHA 10
+#define MAT_IN_TRANSLUCENCY 11
+
+/* output socket defines */
+#define MAT_OUT_COLOR 0
+#define MAT_OUT_ALPHA 1
+#define MAT_OUT_NORMAL 2
+#define MAT_OUT_DIFFUSE 3
+#define MAT_OUT_SPEC 4
+#define MAT_OUT_AO 5
extern void node_ID_title_cb(void *node_v, void *unused_v);
diff --git a/source/blender/python/api2_2x/Blender.c b/source/blender/python/api2_2x/Blender.c
index 174c2be95a7..9a5163022ff 100644
--- a/source/blender/python/api2_2x/Blender.c
+++ b/source/blender/python/api2_2x/Blender.c
@@ -521,14 +521,7 @@ static PyObject *Blender_Get( PyObject * self, PyObject * args )
/*****************************************************************************/
static PyObject *Blender_Redraw( PyObject * self, PyObject * args )
{
- int wintype = SPACE_VIEW3D;
-
- if( !PyArg_ParseTuple( args, "|i", &wintype ) ) {
- return EXPP_ReturnPyObjError( PyExc_TypeError,
- "expected int argument (or nothing)" );
- }
-
- return M_Window_Redraw( self, PyInt_FromLong( (long)wintype ) );
+ return M_Window_Redraw( self, args );
}
/*****************************************************************************/
diff --git a/source/blender/python/api2_2x/Key.c b/source/blender/python/api2_2x/Key.c
index 49fd55ed5c2..4e5d4278fd3 100644
--- a/source/blender/python/api2_2x/Key.c
+++ b/source/blender/python/api2_2x/Key.c
@@ -315,7 +315,7 @@ static PyObject *Key_repr( BPy_Key * self )
static PyObject *Key_getIpo( BPy_Key * self )
{
if (self->key->ipo)
- Ipo_CreatePyObject( self->key->ipo );
+ return Ipo_CreatePyObject( self->key->ipo );
Py_RETURN_NONE;
}
diff --git a/source/blender/python/api2_2x/Mesh.c b/source/blender/python/api2_2x/Mesh.c
index b64259553bf..bd78900f625 100644
--- a/source/blender/python/api2_2x/Mesh.c
+++ b/source/blender/python/api2_2x/Mesh.c
@@ -6922,45 +6922,26 @@ static PyObject *Mesh_fill( BPy_Mesh * self )
/*
* "pointInside" function
*/
-
+#define SIDE_OF_LINE(pa,pb,pp) ((pa[0]-pp[0])*(pb[1]-pp[1]))-((pb[0]-pp[0])*(pa[1]-pp[1]))
+#define POINT_IN_TRI(p0,p1,p2,p3) ((SIDE_OF_LINE(p1,p2,p0)>=0) && (SIDE_OF_LINE(p2,p3,p0)>=0) && (SIDE_OF_LINE(p3,p1,p0)>=0))
static short pointInside_internal(float *vec, float *v1, float *v2, float *v3 )
{
- float a,a1,a2,a3, /*areas, used for point in tri test */
- z,w1,w2,w3,wtot;
- float bounds[5];
+ float z,w1,w2,w3,wtot;
- /*min,max*/
- bounds[0] = MIN3(v1[0], v2[0], v3[0]);
- bounds[1] = MAX3(v1[0], v2[0], v3[0]);
- bounds[2] = MIN3(v1[1], v2[1], v3[1]);
- bounds[3] = MAX3(v1[1], v2[1], v3[1]);
- /*bounds[4] = MIN3(v1[2], v2[2], v3[2]); - ZMIN isnt used*/
- bounds[4] = MAX3(v1[2], v2[2], v3[2]); /* reuse 4 index as the max */
+ if (!POINT_IN_TRI(vec, v1,v2,v3))
+ return 0;
- if ( /* is the vertex in the bounds of the face? */
- (bounds[0] < vec[0] && vec[0] < bounds[1]) &&
- (bounds[2] < vec[1] && vec[1] < bounds[3]) &&
- (bounds[4] < vec[2]) /* the vector must be above the face on the Z axis */
- )
- {
- /* these areas are used for calculating the Z value where the vector is over the face */
- a = AreaF2Dfl(v1, v2, v3);
- w1=a1= AreaF2Dfl(vec, v2, v3);
- if (a1>a) return 0; /*outside*/
- w2=a2= AreaF2Dfl(v1, vec, v3);
- if (a1+a2>a) return 0; /*outside*/
- w3=a3= AreaF2Dfl(v1, v2, vec);
- if ((a1+a2+a3) - 0.000001 > a) return 0; /*outside*/
-
+ if (vec[2] < MAX3(v1[2], v2[2], v3[2])) {
+ w1= AreaF2Dfl(vec, v2, v3);
+ w2= AreaF2Dfl(v1, vec, v3);
+ w3= AreaF2Dfl(v1, v2, vec);
wtot = w1+w2+w3;
- if (!wtot) return 0;
w1/=wtot; w2/=wtot; w3/=wtot;
z =((v1[2] * (w2+w3)) +
(v2[2] * (w1+w3)) +
(v3[2] * (w1+w2))) * 0.5;
-
/* only return true if the face is above vec*/
- if (vec[2] > z )
+ if (vec[2] < z )
return 1;
}
return 0;
diff --git a/source/blender/python/api2_2x/NMesh.c b/source/blender/python/api2_2x/NMesh.c
index 5c86a344896..0a4e8b50406 100644
--- a/source/blender/python/api2_2x/NMesh.c
+++ b/source/blender/python/api2_2x/NMesh.c
@@ -524,16 +524,18 @@ static PyObject *new_NMFace( PyObject * vertexlist )
vlcopy = PyList_New( len );
- if( !vlcopy )
+ if( !vlcopy ) {
+ Py_DECREF(mf);
return EXPP_ReturnPyObjError( PyExc_MemoryError,
"couldn't create PyList" );
-
+ }
for( i = 0; i < len; i++ ) {
item = PySequence_GetItem( vertexlist, i ); /* PySequence increfs */
if( item )
PyList_SET_ITEM( vlcopy, i, item );
else {
+ Py_DECREF(mf);
Py_DECREF(vlcopy);
return EXPP_ReturnPyObjError
( PyExc_RuntimeError,
@@ -582,7 +584,7 @@ static PyObject *NMFace_append( PyObject * self, PyObject * args )
PyList_Append( f->v, vert );
- return EXPP_incr_ret( Py_None );
+ Py_RETURN_NONE;
}
#undef MethodDef
@@ -616,7 +618,7 @@ static PyObject *NMFace_getattr( PyObject * self, char *name )
if( mf->image )
return Image_CreatePyObject( mf->image );
else
- return EXPP_incr_ret( Py_None );
+ Py_RETURN_NONE;
}
else if( strcmp( name, "mode" ) == 0 )
@@ -1169,7 +1171,7 @@ static PyObject *NMesh_setMaterials( PyObject * self, PyObject * args )
Py_DECREF( me->materials );
me->materials = EXPP_incr_ret( pymats );
- return EXPP_incr_ret( Py_None );
+ Py_RETURN_NONE;
}
static PyObject *NMesh_addMaterial( PyObject * self, PyObject * args )
@@ -1200,7 +1202,7 @@ static PyObject *NMesh_addMaterial( PyObject * self, PyObject * args )
PyList_Append( me->materials, ( PyObject * ) pymat );
- return EXPP_incr_ret( Py_None );
+ Py_RETURN_NONE;
}
static PyObject *NMesh_getKey( BPy_NMesh * self )
@@ -1269,40 +1271,38 @@ static PyObject *NMesh_insertKey( PyObject * self, PyObject * args )
if( fra > 0 )
G.scene->r.cfra = (int)oldfra;
- return EXPP_incr_ret( Py_None );
+ Py_RETURN_NONE;
}
static PyObject *NMesh_getSelectedFaces( PyObject * self, PyObject * args )
{
BPy_NMesh *nm = ( BPy_NMesh * ) self;
Mesh *me = nm->mesh;
- int flag = 0;
-
- MTFace *tf;
- int i;
- PyObject *l = PyList_New( 0 ), *pyval;
-
- if( me == NULL )
- return NULL;
-
- tf = me->mtface;
- if( tf == 0 )
- return l;
+ int i, totfaces, flag = 0;
+ PyObject *l, *pyval;
if( !PyArg_ParseTuple( args, "|i", &flag ) )
- return NULL;
-
+ return EXPP_ReturnPyObjError( PyExc_ValueError,
+ "expected int argument (or nothing)" );
+
+ l = PyList_New( 0 );
+ if( me == NULL || me->mface == NULL)
+ return l;
+
+ /* make sure not to write more faces then we have */
+ totfaces= MIN2(me->totface, PySequence_Length(nm->faces));
+
if( flag ) {
- for( i = 0; i < me->totface; i++ ) {
- if( tf[i].flag & TF_SELECT ) {
+ for( i = 0; i < totfaces; i++ ) {
+ if( me->mface[i].flag & ME_FACE_SEL ) {
pyval = PyInt_FromLong( i );
PyList_Append( l, pyval );
Py_DECREF(pyval);
}
}
} else {
- for( i = 0; i < me->totface; i++ ) {
- if( tf[i].flag & TF_SELECT )
+ for( i = 0; i < totfaces; i++ ) {
+ if( me->mface[i].flag & ME_FACE_SEL )
PyList_Append( l, PyList_GetItem( nm->faces, i ) );
}
}
@@ -1312,7 +1312,7 @@ static PyObject *NMesh_getSelectedFaces( PyObject * self, PyObject * args )
static PyObject *NMesh_getActiveFace( PyObject * self )
{
if( ( ( BPy_NMesh * ) self )->sel_face < 0 )
- return EXPP_incr_ret( Py_None );
+ Py_RETURN_NONE;
return Py_BuildValue( "i", ( ( BPy_NMesh * ) self )->sel_face );
}
@@ -1576,8 +1576,7 @@ static PyObject *NMesh_setMaxSmoothAngle( PyObject * self, PyObject * args )
( short ) EXPP_ClampInt( value, NMESH_SMOOTHRESH_MIN,
NMESH_SMOOTHRESH_MAX );
- Py_INCREF( Py_None );
- return Py_None;
+ Py_RETURN_NONE;
}
static PyObject *NMesh_getSubDivLevels( BPy_NMesh * self )
@@ -1609,8 +1608,7 @@ static PyObject *NMesh_setSubDivLevels( PyObject * self, PyObject * args )
( short ) EXPP_ClampInt( render, NMESH_SUBDIV_MIN,
NMESH_SUBDIV_MAX );
- Py_INCREF( Py_None );
- return Py_None;
+ Py_RETURN_NONE;
}
static PyObject *NMesh_getMode( BPy_NMesh * self )
@@ -1662,8 +1660,7 @@ static PyObject *NMesh_setMode( PyObject * self, PyObject * args )
nmesh->mode = mode;
- Py_INCREF( Py_None );
- return Py_None;
+ Py_RETURN_NONE;
}
/* METH_VARARGS: function(PyObject *self, PyObject *args) */
@@ -2827,7 +2824,7 @@ PyObject *NMesh_assignMaterials_toObject( BPy_NMesh * nmesh, Object * ob )
ob->colbits = old_matmask; /*@ HACK */
ob->actcol = 1;
- return EXPP_incr_ret( Py_None );
+ Py_RETURN_NONE;
}
static void fill_medge_from_nmesh(Mesh * mesh, BPy_NMesh * nmesh)
@@ -3193,7 +3190,7 @@ static PyObject *M_NMesh_PutRaw( PyObject * self, PyObject * args )
EXPP_newMaterialList_fromPyList( nmesh->materials );
EXPP_incr_mats_us( mesh->mat,
PyList_Size( nmesh->materials ) );
- return EXPP_incr_ret( Py_None );
+ Py_RETURN_NONE;
}
}
@@ -3421,7 +3418,7 @@ static PyObject *findEdge( BPy_NMesh *nmesh, BPy_NMVert *v1, BPy_NMVert *v2, int
return newEdge;
}
else
- return EXPP_incr_ret( Py_None );
+ Py_RETURN_NONE;
}
static void removeEdge( BPy_NMesh *nmesh, BPy_NMVert *v1, BPy_NMVert *v2, int ununsedOnly)
@@ -3526,7 +3523,7 @@ static PyObject *NMesh_removeEdge( PyObject * self, PyObject * args )
"vertices must be different" );
removeEdge(bmesh, v1, v2, 0);
- return EXPP_incr_ret( Py_None );
+ Py_RETURN_NONE;
}
@@ -3579,7 +3576,7 @@ static PyObject *NMesh_addFace( PyObject * self, PyObject * args )
return edges;
}
- return EXPP_incr_ret( Py_None );
+ Py_RETURN_NONE;
}
static PyObject *NMesh_removeFace( PyObject * self, PyObject * args )
@@ -3626,7 +3623,7 @@ static PyObject *NMesh_removeFace( PyObject * self, PyObject * args )
}
}
- return EXPP_incr_ret( Py_None );
+ Py_RETURN_NONE;
}
static PyObject *NMesh_printDebug( PyObject * self )
@@ -3675,7 +3672,7 @@ static PyObject *NMesh_printDebug( PyObject * self )
}
}
- return EXPP_incr_ret( Py_None );
+ Py_RETURN_NONE;
}
static PyObject *NMesh_addVertGroup( PyObject * self, PyObject * args )
@@ -3702,7 +3699,7 @@ static PyObject *NMesh_addVertGroup( PyObject * self, PyObject * args )
EXPP_allqueue( REDRAWBUTSALL, 1 );
- return EXPP_incr_ret( Py_None );
+ Py_RETURN_NONE;
}
static PyObject *NMesh_removeVertGroup( PyObject * self, PyObject * args )
@@ -3738,7 +3735,7 @@ static PyObject *NMesh_removeVertGroup( PyObject * self, PyObject * args )
EXPP_allqueue( REDRAWBUTSALL, 1 );
- return EXPP_incr_ret( Py_None );
+ Py_RETURN_NONE;
}
static PyObject *NMesh_assignVertsToGroup( PyObject * self, PyObject * args )
@@ -3824,7 +3821,7 @@ static PyObject *NMesh_assignVertsToGroup( PyObject * self, PyObject * args )
add_vert_defnr( object, nIndex, tempInt, weight, assignmode );
}
- return EXPP_incr_ret( Py_None );
+ Py_RETURN_NONE;
}
static PyObject *NMesh_removeVertsFromGroup( PyObject * self, PyObject * args )
@@ -3910,7 +3907,7 @@ static PyObject *NMesh_removeVertsFromGroup( PyObject * self, PyObject * args )
}
}
- return EXPP_incr_ret( Py_None );
+ Py_RETURN_NONE;
}
static PyObject *NMesh_getVertsFromGroup( PyObject * self, PyObject * args )
@@ -4098,7 +4095,7 @@ static PyObject *NMesh_renameVertGroup( PyObject * self, PyObject * args )
PyOS_snprintf( defGroup->name, 32, newGr );
unique_vertexgroup_name( defGroup, ( ( BPy_NMesh * ) self )->object );
- return EXPP_incr_ret( Py_None );
+ Py_RETURN_NONE;
}
static PyObject *NMesh_getVertGroupNames( PyObject * self )
@@ -4191,6 +4188,5 @@ static PyObject *NMesh_transform (PyObject *self, PyObject *args)
/* should we alternatively return a list of changed verts (and preserve
* the original ones) ? */
- Py_INCREF( Py_None );
- return Py_None;
+ Py_RETURN_NONE;
}
diff --git a/source/blender/python/api2_2x/Scene.c b/source/blender/python/api2_2x/Scene.c
index 39a7f0d77f4..fd139c4fe6e 100644
--- a/source/blender/python/api2_2x/Scene.c
+++ b/source/blender/python/api2_2x/Scene.c
@@ -1343,16 +1343,18 @@ static PyObject *SceneObSeq_item( BPy_SceneObSeq * self, int i )
if (self->mode==EXPP_OBSEQ_NORMAL)
for (base= scene->base.first; base && i!=index; base= base->next, index++) {}
/* selected */
- else if (self->mode==EXPP_OBSEQ_SELECTED)
+ else if (self->mode==EXPP_OBSEQ_SELECTED) {
for (base= scene->base.first; base && i!=index; base= base->next)
if (base->flag & SELECT)
index++;
+ }
/* context */
- else if (self->mode==EXPP_OBSEQ_CONTEXT)
+ else if (self->mode==EXPP_OBSEQ_CONTEXT) {
if (G.vd)
for (base= scene->base.first; base && i!=index; base= base->next)
if TESTBASE(base)
index++;
+ }
if (!(base))
return EXPP_ReturnPyObjError( PyExc_IndexError,
diff --git a/source/blender/python/api2_2x/doc/Render.py b/source/blender/python/api2_2x/doc/Render.py
index adadf54c488..9c9f58f6074 100644
--- a/source/blender/python/api2_2x/doc/Render.py
+++ b/source/blender/python/api2_2x/doc/Render.py
@@ -498,7 +498,7 @@ class RenderData:
def setOversamplingLevel(level):
"""
- Set the edge color for toon shading.
+ Set the level of over-sampling (anti-aliasing).
@type level: int
@param level: can be either 5, 8, 11, or 16
"""
diff --git a/source/blender/python/api2_2x/doc/Scene.py b/source/blender/python/api2_2x/doc/Scene.py
index fb852f2aa49..93d3e7d830e 100644
--- a/source/blender/python/api2_2x/doc/Scene.py
+++ b/source/blender/python/api2_2x/doc/Scene.py
@@ -107,6 +107,8 @@ class Scene:
@ivar objects: The scene's objects. The sequence supports the methods .link(ob), .unlink(ob), and .new(obdata), and can be iterated over.
@type cursor: Vector (wrapped)
@ivar cursor: the 3d cursor location for this scene.
+ @type camera: Camera or None
+ @ivar camera: The active camera for this scene (can be set)
@type world: World or None
@ivar world: The world that this scene uses (if any)
@type timeline: Timeline
diff --git a/source/blender/render/extern/include/RE_shader_ext.h b/source/blender/render/extern/include/RE_shader_ext.h
index c1b20da53b7..364535736ae 100644
--- a/source/blender/render/extern/include/RE_shader_ext.h
+++ b/source/blender/render/extern/include/RE_shader_ext.h
@@ -151,6 +151,10 @@ typedef struct ShadeInput
int samplenr; /* sample counter, to detect if we should do shadow again */
int depth; /* 1 or larger on raytrace shading */
+ /* stored copy of original face normal (facenor)
+ * before flipping. Used in Front/back output on geometry node */
+ float orignor[3];
+
/* from initialize, part or renderlayer */
short do_preview; /* for nodes, in previewrender */
short thread, sample; /* sample: ShadeSample array index */
@@ -158,6 +162,7 @@ typedef struct ShadeInput
int layflag, passflag, combinedflag;
struct Group *light_override;
struct Material *mat_override;
+
} ShadeInput;
diff --git a/source/blender/render/intern/source/shadeinput.c b/source/blender/render/intern/source/shadeinput.c
index 51157cb83f4..ca661469b36 100644
--- a/source/blender/render/intern/source/shadeinput.c
+++ b/source/blender/render/intern/source/shadeinput.c
@@ -259,6 +259,11 @@ void shade_input_set_triangle_i(ShadeInput *shi, VlakRen *vlr, short i1, short i
/* facenormal copy, can get flipped */
VECCOPY(shi->facenor, vlr->n);
+ /* copy of original pre-flipped normal, for geometry->front/back node output */
+ VECCOPY(shi->orignor, vlr->n);
+ if (vlr->noflag & R_FLIPPED_NO) {
+ VECMUL(shi->orignor, -1.0f);
+ }
}
/* note, facenr declared volatile due to over-eager -O2 optimizations
diff --git a/source/blender/src/SConscript b/source/blender/src/SConscript
index 815cf532c88..729e79dcb6f 100644
--- a/source/blender/src/SConscript
+++ b/source/blender/src/SConscript
@@ -4,18 +4,6 @@ Import ('env')
# TODO: src_env.Append (CCFLAGS = user_options_dict['SDL_CFLAGS'])
sources = env.Glob('*.c')
-numobj = len(sources)
-maxobj = 30
-
-numlibs = numobj / maxobj
-if (numobj % maxobj):
- numlibs = numlibs + 1
-subsources = []
-
-if (env['OURPLATFORM'] == 'win32-mingw'):
- for i in range(numlibs - 1):
- subsources.append(sources[i*maxobj:(i+1)*maxobj])
- subsources.append(sources[(numlibs-1)*maxobj:])
incs = ' #/intern/guardedalloc #/intern/memutil'
incs += ' ../blenlib ../makesdna ../blenkernel'
@@ -67,8 +55,4 @@ if env['WITH_BF_VERSE']:
if env['BF_BUILDINFO'] == 1:
defs.append('NAN_BUILDINFO')
-if (env['OURPLATFORM'] == 'win32-mingw'):
- for i in range(numlibs):
- env.BlenderLib ( libname = 'src%d' % (i), sources = subsources[i], includes = Split(incs), defines = defs, libtype=['core', 'intern'], priority = [5, 25] )
-else:
- env.BlenderLib ( libname = 'src', sources = sources, includes = Split(incs), defines = defs, libtype=['core', 'intern'], priority = [5, 25] )
+env.BlenderLib ( libname = 'src', sources = sources, includes = Split(incs), defines = defs, libtype=['core', 'intern'], priority = [5, 25] )
diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c
index 3760b17f039..ec2b7b3b274 100644
--- a/source/blender/src/buttons_editing.c
+++ b/source/blender/src/buttons_editing.c
@@ -4447,7 +4447,7 @@ static void editing_panel_links(Object *ob)
block= uiNewBlock(&curarea->uiblocks, "editing_panel_links", UI_EMBOSS, UI_HELV, curarea->win);
if(uiNewPanel(curarea, block, "Link and Materials", "Editing", 0, 0, 318, 204)==0) return;
- uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
+ uiSetButLock((ob && ob->id.lib), ERROR_LIBDATA_MESSAGE);
buttons_active_id(&id, &idfrom);
diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c
index e47a80fe9fa..bb5ac2ba682 100644
--- a/source/blender/src/buttons_object.c
+++ b/source/blender/src/buttons_object.c
@@ -2462,11 +2462,22 @@ static void object_softbodies__enable(void *ob_v, void *arg2)
allqueue(REDRAWBUTSEDIT, 0);
}
+static int _can_softbodies_at_all(Object *ob)
+{
+ // list of Yes
+ if ((ob->type==OB_MESH)
+ || (ob->type==OB_CURVE)
+ || (ob->type==OB_LATTICE)
+ || (ob->type==OB_SURF)
+ ) return 1;
+ // else deny
+ return 0;
+}
static void object_softbodies_II(Object *ob)
{
uiBlock *block;
static int val;
-
+ if(!_can_softbodies_at_all(ob)) return;
block= uiNewBlock(&curarea->uiblocks, "object_softbodies_II", UI_EMBOSS, UI_HELV, curarea->win);
uiNewPanelTabbed("Soft Body", "Physics");
if(uiNewPanel(curarea, block, "Soft Body Collision", "Physics", 651, 0, 318, 204)==0) return;
@@ -2545,9 +2556,9 @@ static void object_softbodies(Object *ob)
uiBlock *block;
static int val;
uiBut *but;
+ if(!_can_softbodies_at_all(ob)) return;
block= uiNewBlock(&curarea->uiblocks, "object_softbodies", UI_EMBOSS, UI_HELV, curarea->win);
if(uiNewPanel(curarea, block, "Soft Body", "Physics", 640, 0, 318, 204)==0) return;
-
uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
val = modifiers_isSoftbodyEnabled(ob);
diff --git a/source/blender/src/drawmesh.c b/source/blender/src/drawmesh.c
index b1ce86dd045..6307307345b 100644
--- a/source/blender/src/drawmesh.c
+++ b/source/blender/src/drawmesh.c
@@ -320,7 +320,6 @@ int set_tpage(MTFace *tface)
else fCurtile= tface->tile;
if(tilemode) {
-
if(ima->repbind==0) make_repbind(ima);
if(fCurtile>=ima->totbind) fCurtile= 0;
diff --git a/source/blender/src/drawnode.c b/source/blender/src/drawnode.c
index e1cab659171..883fd05909f 100644
--- a/source/blender/src/drawnode.c
+++ b/source/blender/src/drawnode.c
@@ -622,6 +622,7 @@ static void node_shader_set_butfunc(bNodeType *ntype)
/* case NODE_GROUP: note, typeinfo for group is generated... see "XXX ugly hack" */
case SH_NODE_MATERIAL:
+ case SH_NODE_MATERIAL_EXT:
ntype->butfunc= node_shader_buts_material;
break;
case SH_NODE_TEXTURE:
@@ -1508,6 +1509,21 @@ static int node_composit_buts_scale(uiBlock *block, bNodeTree *ntree, bNode *nod
return 20;
}
+static int node_composit_buts_invert(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+ if(block) {
+ uiBlockBeginAlign(block);
+ uiDefButBitS(block, TOG, CMP_CHAN_RGB, B_NODE_EXEC+node->nr, "RGB",
+ butr->xmin, butr->ymin, (butr->xmax-butr->xmin)/2, 20,
+ &node->custom1, 0, 0, 0, 0, "");
+ uiDefButBitS(block, TOG, CMP_CHAN_A, B_NODE_EXEC+node->nr, "A",
+ butr->xmin+(butr->xmax-butr->xmin)/2, butr->ymin, (butr->xmax-butr->xmin)/2, 20,
+ &node->custom1, 0, 0, 0, 0, "");
+ uiBlockEndAlign(block);
+ }
+ return 20;
+}
+
/* only once called */
static void node_composit_set_butfunc(bNodeType *ntype)
{
@@ -1609,6 +1625,9 @@ static void node_composit_set_butfunc(bNodeType *ntype)
case CMP_NODE_MATH:
ntype->butfunc= node_buts_math;
break;
+ case CMP_NODE_INVERT:
+ ntype->butfunc= node_composit_buts_invert;
+ break;
default:
ntype->butfunc= NULL;
}
diff --git a/source/blender/src/editaction.c b/source/blender/src/editaction.c
index 4c698674bbf..1b0429abda2 100644
--- a/source/blender/src/editaction.c
+++ b/source/blender/src/editaction.c
@@ -2568,6 +2568,9 @@ void snap_keys_to_frame(int snap_mode)
else if (key) {
set_snap_meshchannels(key, snap_mode);
}
+ else {
+ return;
+ }
BIF_undo_push(str);
allspace(REMAKEIPO, 0);
@@ -2670,6 +2673,9 @@ void mirror_action_keys(short mirror_mode)
else if (key) {
mirror_meshchannels(key, mirror_mode);
}
+ else {
+ return;
+ }
BIF_undo_push(str);
allspace(REMAKEIPO, 0);
@@ -2678,6 +2684,82 @@ void mirror_action_keys(short mirror_mode)
allqueue(REDRAWNLA, 0);
}
+/* This function allows the user to insert keyframes on the current
+ * frame from the Action Editor, using the current values of the channels
+ * to be keyframed.
+ */
+void insertkey_action(void)
+{
+ bAction *act;
+ Key *key;
+ Object *ob= OBACT;
+ IpoCurve *icu;
+ short mode;
+ float cfra;
+
+ /* get data */
+ act = G.saction->action;
+ key = get_action_mesh_key();
+ cfra = frame_to_float(CFRA);
+
+ if (act) {
+ bActionChannel *achan;
+ bConstraintChannel *conchan;
+
+ /* ask user what to keyframe */
+ mode = pupmenu("Insert Key%t|All Channels%x1|Only Selected Channels%x2");
+ if (mode == 0) return;
+
+ for (achan= act->chanbase.first; achan; achan=achan->next) {
+ if (EDITABLE_ACHAN(achan)) {
+ if (achan->ipo && (SEL_ACHAN(achan) || (mode == 1))) {
+ for (icu= achan->ipo->curve.first; icu; icu=icu->next) {
+ if (ob)
+ insertkey((ID *)ob, icu->blocktype, achan->name, NULL, icu->adrcode);
+ else
+ insert_vert_ipo(icu, cfra, icu->curval);
+ }
+ }
+
+ if (EXPANDED_ACHAN(achan) && FILTER_CON_ACHAN(achan)) {
+ for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) {
+ if (EDITABLE_CONCHAN(conchan)) {
+ if (conchan->ipo && (SEL_ACHAN(conchan) || (mode == 1))) {
+ for (icu= conchan->ipo->curve.first; icu; icu=icu->next) {
+ /* // commented out as this doesn't seem to work right for some reason
+ if (ob)
+ insertkey((ID *)ob, ID_CO, achan->name, conchan->name, CO_ENFORCE);
+ else
+ insert_vert_ipo(icu, cfra, icu->curval);
+ */
+ insert_vert_ipo(icu, cfra, icu->curval);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (key) {
+ /* ask user if they want to insert a keyframe */
+ mode = okee("Insert Keyframe?");
+ if (mode == 0) return;
+
+ if (key->ipo) {
+ for (icu= key->ipo->curve.first; icu; icu=icu->next) {
+ insert_vert_ipo(icu, cfra, icu->curval);
+ }
+ }
+ }
+
+ BIF_undo_push("Insert Key");
+ allspace(REMAKEIPO, 0);
+ allqueue(REDRAWACTION, 0);
+ allqueue(REDRAWIPO, 0);
+ allqueue(REDRAWNLA, 0);
+}
+
static void select_all_keys_frames(bAction *act, short *mval,
short *mvalo, int selectmode)
{
@@ -2886,7 +2968,7 @@ static void borderselect_function(void (*select_func)(bAction *act,
select_func(act, mval, mvalo, SELECT_SUBTRACT);
}
- BIF_undo_push("Border select Action");
+ BIF_undo_push("Border Select Action");
}
static void clever_keyblock_names(Key *key, short* mval){
@@ -3255,7 +3337,7 @@ void winqreadactionspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
}
}
break;
-
+
case KKEY:
if (G.qual & LR_CTRLKEY) {
markers_selectkeys_between();
@@ -3278,8 +3360,10 @@ void winqreadactionspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
case MKEY:
if (G.qual & LR_SHIFTKEY) {
/* mirror keyframes */
- val = pupmenu("Mirror Keys Over%t|Current Frame%x1|Vertical Axis%x2|Horizontal Axis %x3|Selected Marker %x4");
- mirror_action_keys(val);
+ if (act || key) {
+ val = pupmenu("Mirror Keys Over%t|Current Frame%x1|Vertical Axis%x2|Horizontal Axis %x3|Selected Marker %x4");
+ mirror_action_keys(val);
+ }
}
else {
/* marker operations */
@@ -3329,8 +3413,10 @@ void winqreadactionspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
case SKEY:
if (mval[0]>=ACTWIDTH) {
if(G.qual & LR_SHIFTKEY) {
- val = pupmenu("Snap Keys To%t|Nearest Frame%x1|Current Frame%x2|Nearest Marker %x3");
- snap_keys_to_frame(val);
+ if (act || key) {
+ val = pupmenu("Snap Keys To%t|Nearest Frame%x1|Current Frame%x2|Nearest Marker %x3");
+ snap_keys_to_frame(val);
+ }
}
else {
if (act)
diff --git a/source/blender/src/editdeform.c b/source/blender/src/editdeform.c
index 305d01a8aea..7a086ed5be3 100644
--- a/source/blender/src/editdeform.c
+++ b/source/blender/src/editdeform.c
@@ -55,12 +55,16 @@
#include "BKE_mesh.h"
#include "BKE_utildefines.h"
+#include "BIF_interface.h"
#include "BIF_editdeform.h"
#include "BIF_editmesh.h"
+#include "BIF_space.h"
#include "BIF_toolbox.h"
#include "BSE_edit.h"
+#include "butspace.h"
+#include "mydevice.h"
#include "editmesh.h"
#include "multires.h"
@@ -788,6 +792,99 @@ void vertexgroup_select_by_name(Object *ob, char *name)
ob->actdef=0; // this signals on painting to create a new one, if a bone in posemode is selected */
}
+/* This function provides a shortcut for adding/removing verts from
+ * vertex groups. It is called by the Ctrl-G hotkey in EditMode for Meshes
+ * and Lattices. (currently only restricted to those two)
+ * It is only responsible for
+ */
+void vgroup_assign_with_menu(void)
+{
+ Object *ob= G.obedit;
+ int defCount;
+ int mode;
+
+ /* prevent crashes */
+ if (ob==NULL) return;
+
+ defCount= BLI_countlist(&ob->defbase);
+
+ /* give user choices of adding to current/new or removing from current */
+ if (defCount && ob->actdef)
+ mode = pupmenu("Vertex Groups %t|Add Selected to New Group %x1|Add Selected to Active Group %x2|Remove Selected from Active Group %x3");
+ else
+ mode= pupmenu("Vertex Groups %t|Add Selected to New Group %x1");
+
+ /* handle choices */
+ switch (mode) {
+ case 1: /* add to new group */
+ add_defgroup(ob);
+ assign_verts_defgroup();
+ allqueue(REDRAWVIEW3D, 1);
+ BIF_undo_push("Assign to vertex group");
+ break;
+ case 2: /* add to current group */
+ assign_verts_defgroup();
+ allqueue(REDRAWVIEW3D, 1);
+ BIF_undo_push("Assign to vertex group");
+ break;
+ case 3: /* remove from current group */
+ remove_verts_defgroup(0);
+ allqueue(REDRAWVIEW3D, 1);
+ BIF_undo_push("Remove from vertex group");
+ break;
+ }
+}
+
+/* This function provides a shortcut for commonly used vertex group
+ * functions - change weight (not implemented), change active group, delete active group,
+ * when Ctrl-Shift-G is used in EditMode, for Meshes and Lattices (only for now).
+ */
+void vgroup_operation_with_menu(void)
+{
+ Object *ob= G.obedit;
+ int defCount;
+ int mode;
+
+ /* prevent crashes and useless cases */
+ if (ob==NULL) return;
+
+ defCount= BLI_countlist(&ob->defbase);
+ if (defCount == 0) return;
+
+ /* give user choices of adding to current/new or removing from current */
+ if (ob->actdef)
+ mode = pupmenu("Vertex Groups %t|Change Active Group%x1|Delete Active Group%x2");
+ else
+ mode= pupmenu("Vertex Groups %t|Change Active Group%x1");
+
+ /* handle choices */
+ switch (mode) {
+ case 1: /* change active group*/
+ {
+ char *menustr= get_vertexgroup_menustr(ob);
+ short nr;
+
+ if (menustr) {
+ nr= pupmenu(menustr);
+
+ if ((nr >= 1) && (nr <= defCount))
+ ob->actdef= nr;
+
+ MEM_freeN(menustr);
+ }
+ allqueue(REDRAWBUTSALL, 0);
+ }
+ break;
+ case 2: /* delete active group */
+ {
+ del_defgroup(ob);
+ allqueue (REDRAWVIEW3D, 1);
+ allqueue(REDRAWOOPS, 0);
+ BIF_undo_push("Delete vertex group");
+ }
+ break;
+ }
+}
/* ******************* other deform edit stuff ********** */
diff --git a/source/blender/src/editipo.c b/source/blender/src/editipo.c
index 95e998d3496..ad5ffacf103 100644
--- a/source/blender/src/editipo.c
+++ b/source/blender/src/editipo.c
@@ -2426,6 +2426,9 @@ void common_insertkey(void)
if(curarea->spacetype==SPACE_IPO) {
insertkey_editipo();
}
+ else if(curarea->spacetype==SPACE_ACTION) {
+ insertkey_action();
+ }
else if(curarea->spacetype==SPACE_BUTS) {
if(G.buts->mainb==CONTEXT_SHADING) {
int tab= G.buts->tab[CONTEXT_SHADING];
diff --git a/source/blender/src/editnla.c b/source/blender/src/editnla.c
index d204fa2b703..73eea2b5aa4 100644
--- a/source/blender/src/editnla.c
+++ b/source/blender/src/editnla.c
@@ -526,6 +526,9 @@ static void add_nla_block(short event)
if(strip->object)
id_lib_extern(&strip->object->id); /* checks lib data, sets correct flag for saving then */
+ if(ob->nlastrips.first == NULL)
+ ob->nlaflag |= OB_NLA_OVERRIDE;
+
BLI_addtail(&ob->nlastrips, strip);
BIF_undo_push("Add NLA strip");
@@ -580,6 +583,9 @@ static void add_nla_block_by_name(char name[32], Object *ob, short hold, short a
act->id.us++;
+ if(ob->nlastrips.first == NULL)
+ ob->nlaflag |= OB_NLA_OVERRIDE;
+
BLI_addtail(&ob->nlastrips, strip);
}
diff --git a/source/blender/src/ghostwinlay.c b/source/blender/src/ghostwinlay.c
index 9df293a0fda..19e858a9f59 100644
--- a/source/blender/src/ghostwinlay.c
+++ b/source/blender/src/ghostwinlay.c
@@ -881,10 +881,8 @@ Window *winlay_get_active_window(void) {
void window_open_ndof(Window* win)
{
- PILdynlib* ndofLib = PIL_dynlib_open("NDOFPlugin.plug");
- printf("passing here \n");
+ PILdynlib* ndofLib = PIL_dynlib_open("spaceplug.plug");
if (ndofLib) {
- printf("and here \n");
GHOST_OpenNDOF(g_system, win->ghostwin,
PIL_dynlib_find_symbol(ndofLib, "ndofInit"),
diff --git a/source/blender/src/multires-firstlevel.c b/source/blender/src/multires-firstlevel.c
index db39a429c22..2be867b5db0 100644
--- a/source/blender/src/multires-firstlevel.c
+++ b/source/blender/src/multires-firstlevel.c
@@ -55,6 +55,8 @@
MDeformVert *subdivide_dverts(MDeformVert *src, MultiresLevel *lvl);
MTFace *subdivide_mtfaces(MTFace *src, MultiresLevel *lvl);
+void multires_update_edge_flags(Mesh *me, EditMesh *em);
+void eed_to_medge_flag(EditEdge *eed, short *flag, char *crease);
/*********** Generic ***********/
@@ -221,6 +223,41 @@ void multires_del_lower_customdata(Multires *mr, MultiresLevel *cr_lvl)
mr->fdata= cdf;
}
+/* Update all special first-level data, if the first-level is active */
+void multires_update_first_level(Mesh *me, EditMesh *em)
+{
+ if(me && me->mr && me->mr->current == 1) {
+ multires_update_customdata(me->mr->levels.first, em ? &em->vdata : &me->vdata,
+ &me->mr->vdata, CD_MDEFORMVERT);
+ multires_update_customdata(me->mr->levels.first, em ? &em->fdata : &me->fdata,
+ &me->mr->fdata, CD_MTFACE);
+ multires_update_edge_flags(me, em);
+ }
+}
+
+/*********** Multires.edge_flags ***********/
+void multires_update_edge_flags(Mesh *me, EditMesh *em)
+{
+ MultiresLevel *lvl= me->mr->levels.first;
+ EditEdge *eed= NULL;
+ int i;
+
+ if(em) eed= em->edges.first;
+ for(i=0; i<lvl->totedge; ++i) {
+ if(em) {
+ me->mr->edge_flags[i]= 0;
+ eed_to_medge_flag(eed, &me->mr->edge_flags[i], &me->mr->edge_creases[i]);
+ eed= eed->next;
+ }
+ else {
+ me->mr->edge_flags[i]= me->medge[i].flag;
+ me->mr->edge_creases[i]= me->medge[i].crease;
+ }
+ }
+}
+
+
+
/*********** Multires.vdata ***********/
/* MDeformVert */
diff --git a/source/blender/src/multires.c b/source/blender/src/multires.c
index d1ae24e73a8..33b85bd27b6 100644
--- a/source/blender/src/multires.c
+++ b/source/blender/src/multires.c
@@ -52,6 +52,7 @@
#include "BKE_key.h"
#include "BKE_mesh.h"
#include "BKE_modifier.h"
+#include "BKE_object.h"
#include "BIF_editmesh.h"
#include "BIF_screen.h"
@@ -483,13 +484,14 @@ void multires_get_face(MultiresFace *f, EditFace *efa, MFace *m)
tmp.v3= efa->v3->tmp.l;
tmp.v4= 0;
if(efa->v4) tmp.v4= efa->v4->tmp.l;
- tmp.flag= efa->flag;
- if(efa->f & 1) tmp.flag |= ME_FACE_SEL;
- else f->flag &= ~ME_FACE_SEL;
- if(efa->h) tmp.flag |= ME_HIDE;
test_index_face(&tmp, NULL, 0, efa->v4?4:3);
for(j=0; j<4; ++j) f->v[j]= (&tmp.v1)[j];
- f->flag= tmp.flag;
+
+ /* Flags */
+ f->flag= efa->flag;
+ if(efa->f & 1) f->flag |= ME_FACE_SEL;
+ else f->flag &= ~ME_FACE_SEL;
+ if(efa->h) f->flag |= ME_HIDE;
f->mat_nr= efa->mat_nr;
} else {
f->v[0]= m->v1;
@@ -574,12 +576,12 @@ void multires_make(void *ob, void *me_v)
/* Load vertices and vdata (MDeformVerts) */
lvl->totvert= em ? BLI_countlist(&em->verts) : me->totvert;
- lvl->verts= MEM_callocN(sizeof(MVert)*lvl->totvert,"multires verts");
+ me->mr->verts= MEM_callocN(sizeof(MVert)*lvl->totvert,"multires verts");
multires_update_customdata(me->mr->levels.first, em ? &em->vdata : &me->vdata,
&me->mr->vdata, CD_MDEFORMVERT);
if(em) eve= em->verts.first;
for(i=0; i<lvl->totvert; ++i) {
- multires_get_vert(&lvl->verts[i], eve, &me->mvert[i], i);
+ multires_get_vert(&me->mr->verts[i], eve, &me->mvert[i], i);
if(em) eve= eve->next;
}
@@ -635,7 +637,6 @@ MultiresLevel *multires_level_copy(MultiresLevel *orig)
MultiresLevel *lvl= MEM_dupallocN(orig);
lvl->next= lvl->prev= NULL;
- lvl->verts= MEM_dupallocN(orig->verts);
lvl->faces= MEM_dupallocN(orig->faces);
lvl->colfaces= MEM_dupallocN(orig->colfaces);
lvl->edges= MEM_dupallocN(orig->edges);
@@ -657,6 +658,8 @@ Multires *multires_copy(Multires *orig)
for(lvl= orig->levels.first; lvl; lvl= lvl->next)
BLI_addtail(&mr->levels, multires_level_copy(lvl));
+
+ mr->verts= MEM_dupallocN(orig->verts);
lvl= mr->levels.first;
if(lvl) {
@@ -689,6 +692,8 @@ void multires_free(Multires *mr)
lvl= lvl->next;
}
+ MEM_freeN(mr->verts);
+
BLI_freelistN(&mr->levels);
MEM_freeN(mr);
@@ -699,7 +704,6 @@ void multires_free(Multires *mr)
void multires_free_level(MultiresLevel *lvl)
{
if(lvl) {
- if(lvl->verts) MEM_freeN(lvl->verts);
if(lvl->faces) MEM_freeN(lvl->faces);
if(lvl->edges) MEM_freeN(lvl->edges);
if(lvl->colfaces) MEM_freeN(lvl->colfaces);
@@ -843,6 +847,7 @@ void multires_add_level(void *ob, void *me_v)
Mesh *me= me_v;
MultiresLevel *lvl= MEM_callocN(sizeof(MultiresLevel), "multireslevel");
MultiApplyData data;
+ MVert *oldverts= NULL;
multires_check_state();
@@ -858,15 +863,16 @@ void multires_add_level(void *ob, void *me_v)
/* Create vertices
=============== */
lvl->totvert= lvl->prev->totvert + lvl->prev->totedge + lvl->prev->totface;
- lvl->verts= MEM_callocN(sizeof(MVert)*lvl->totvert,"multires verts");
- /* Copy previous level's verts */
+ oldverts= me->mr->verts;
+ me->mr->verts= MEM_callocN(sizeof(MVert)*lvl->totvert, "multitres verts");
+ /* Copy old verts */
for(i=0; i<lvl->prev->totvert; ++i)
- lvl->verts[i]= lvl->prev->verts[i];
+ me->mr->verts[i]= oldverts[i];
/* Create new edge verts */
for(i=0; i<lvl->prev->totedge; ++i) {
- VecMidf(lvl->verts[lvl->prev->totvert + i].co,
- lvl->prev->verts[lvl->prev->edges[i].v[0]].co,
- lvl->prev->verts[lvl->prev->edges[i].v[1]].co);
+ VecMidf(me->mr->verts[lvl->prev->totvert + i].co,
+ oldverts[lvl->prev->edges[i].v[0]].co,
+ oldverts[lvl->prev->edges[i].v[1]].co);
lvl->prev->edges[i].mid= lvl->prev->totvert + i;
}
/* Create new face verts */
@@ -936,38 +942,42 @@ void multires_add_level(void *ob, void *me_v)
=============== */
for(i=0; i<lvl->prev->totface; ++i) {
const MultiresFace *f= &lvl->prev->faces[i];
- data.corner1= lvl->prev->verts[f->v[0]].co;
- data.corner2= lvl->prev->verts[f->v[1]].co;
- data.corner3= lvl->prev->verts[f->v[2]].co;
- data.corner4= lvl->prev->verts[f->v[3]].co;
+ data.corner1= oldverts[f->v[0]].co;
+ data.corner2= oldverts[f->v[1]].co;
+ data.corner3= oldverts[f->v[2]].co;
+ data.corner4= oldverts[f->v[3]].co;
data.quad= f->v[3] ? 1 : 0;
- multi_apply(lvl->verts[f->mid].co, &data, 3, catmullclark_smooth_face);
+ multi_apply(me->mr->verts[f->mid].co, &data, 3, catmullclark_smooth_face);
}
if(G.scene->toolsettings->multires_subdiv_type == 0) {
for(i=0; i<lvl->prev->totedge; ++i) {
const MultiresEdge *e= &lvl->prev->edges[i];
data.boundary= multires_edge_is_boundary(lvl->prev,i);
- edge_face_neighbor_midpoints_accum(&data,lvl->prev,lvl->verts,sizeof(MVert),e);
- data.endpoint1= lvl->prev->verts[e->v[0]].co;
- data.endpoint2= lvl->prev->verts[e->v[1]].co;
- multi_apply(lvl->verts[e->mid].co, &data, 3, catmullclark_smooth_edge);
+ edge_face_neighbor_midpoints_accum(&data,lvl->prev, me->mr->verts, sizeof(MVert),e);
+ data.endpoint1= oldverts[e->v[0]].co;
+ data.endpoint2= oldverts[e->v[1]].co;
+ multi_apply(me->mr->verts[e->mid].co, &data, 3, catmullclark_smooth_edge);
}
for(i=0; i<lvl->prev->totvert; ++i) {
data.boundary= multires_vert_is_boundary(lvl->prev,i);
- data.original= lvl->verts[i].co;
+ data.original= oldverts[i].co;
data.edge_count= BLI_countlist(&lvl->prev->vert_edge_map[i]);
if(data.boundary)
- boundary_edges_average(&data,lvl->prev,lvl->prev->verts,sizeof(MVert),i);
+ boundary_edges_average(&data,lvl->prev, oldverts, sizeof(MVert),i);
else {
- vert_face_neighbor_midpoints_average(&data,lvl->prev,lvl->verts,sizeof(MVert),i);
- vert_edge_neighbor_midpoints_average(&data,lvl->prev,lvl->prev->verts,sizeof(MVert),i);
+ vert_face_neighbor_midpoints_average(&data,lvl->prev, me->mr->verts,
+ sizeof(MVert),i);
+ vert_edge_neighbor_midpoints_average(&data,lvl->prev, oldverts,
+ sizeof(MVert),i);
}
- multi_apply(lvl->verts[i].co, &data, 3, catmullclark_smooth_vert);
+ multi_apply(me->mr->verts[i].co, &data, 3, catmullclark_smooth_vert);
}
}
+ MEM_freeN(oldverts);
+
/* Vertex Colors
============= */
curf= 0;
@@ -1093,13 +1103,13 @@ void multires_level_to_mesh(Object *ob, Mesh *me, const int render)
for(i=0; i<lvl->totvert; ++i) {
if(em) {
- eves[i]= addvertlist(lvl->verts[i].co, NULL); /* TODO */
- if(lvl->verts[i].flag & 1) eves[i]->f |= SELECT;
- if(lvl->verts[i].flag & ME_HIDE) eves[i]->h= 1;
+ eves[i]= addvertlist(me->mr->verts[i].co, NULL);
+ if(me->mr->verts[i].flag & 1) eves[i]->f |= SELECT;
+ if(me->mr->verts[i].flag & ME_HIDE) eves[i]->h= 1;
eves[i]->data= NULL;
}
else
- me->mvert[i]= lvl->verts[i];
+ me->mvert[i]= me->mr->verts[i];
}
for(i=0; i<lvl->totedge; ++i) {
if(em) {
@@ -1114,9 +1124,12 @@ void multires_level_to_mesh(Object *ob, Mesh *me, const int render)
if(em) {
EditVert *eve4= lvl->faces[i].v[3] ? eves[lvl->faces[i].v[3]] : NULL;
EditFace *efa= addfacelist(eves[lvl->faces[i].v[0]], eves[lvl->faces[i].v[1]],
- eves[lvl->faces[i].v[2]], eve4, NULL, NULL); /* TODO */
- efa->flag= lvl->faces[i].flag;
+ eves[lvl->faces[i].v[2]], eve4, NULL, NULL);
+ efa->flag= lvl->faces[i].flag & ~ME_HIDE;
efa->mat_nr= lvl->faces[i].mat_nr;
+ if(lvl->faces[i].flag & ME_FACE_SEL)
+ efa->f |= SELECT;
+ if(lvl->faces[i].flag & ME_HIDE) efa->h= 1;
efa->data= NULL;
}
else {
@@ -1159,6 +1172,14 @@ void multires_level_to_mesh(Object *ob, Mesh *me, const int render)
}
}
}
+
+ if(em) {
+ eed= em->edges.first;
+ for(i=0, eed= em->edges.first; i<lvl->totedge; ++i, eed= eed->next) {
+ eed->h= me->mr->verts[lvl->edges[i].v[0]].flag & ME_HIDE ||
+ me->mr->verts[lvl->edges[i].v[1]].flag & ME_HIDE;
+ }
+ }
EM_select_flush();
@@ -1205,6 +1226,7 @@ void multires_level_to_mesh(Object *ob, Mesh *me, const int render)
/* friendly check for background render */
if(G.background==0) {
+ object_handle_update(ob);
countall();
if(G.vd && G.vd->depths) G.vd->depths->damaged= 1;
@@ -1311,108 +1333,65 @@ void multires_update_colors(Mesh *me)
}
}
-void multires_update_edge_flags(Multires *mr, Mesh *me, EditMesh *em)
-{
- MultiresLevel *lvl= current_level(mr);
- EditEdge *eed= NULL;
- int i;
-
- if(em) eed= em->edges.first;
- for(i=0; i<lvl->totedge; ++i) {
- if(em) {
- mr->edge_flags[i]= 0;
- eed_to_medge_flag(eed, &mr->edge_flags[i], &mr->edge_creases[i]);
- eed= eed->next;
- }
- else {
- mr->edge_flags[i]= me->medge[i].flag;
- mr->edge_creases[i]= me->medge[i].crease;
- }
- }
-}
-
-void multires_update_levels(Mesh *me, const int render)
+/* Update vertex locations and vertex flags */
+void multires_update_vertices(Mesh *me, EditMesh *em)
{
- /* cr=current, pr=previous, or=original */
- MultiresLevel *cr_lvl= current_level(me->mr), *pr_lvl;
- MultiresLevel *or_lvl= cr_lvl;
- vec3f *pr_deltas= NULL, *cr_deltas= NULL;
- char *pr_flag_damaged= NULL, *cr_flag_damaged= NULL, *pr_mat_damaged= NULL, *cr_mat_damaged= NULL;
- char *or_flag_damaged= NULL, *or_mat_damaged= NULL;
- EditMesh *em= (!render && G.obedit) ? G.editMesh : NULL;
+ MultiresLevel *cr_lvl= current_level(me->mr), *pr_lvl= NULL,
+ *last_lvl= me->mr->levels.last;
+ vec3f *pr_deltas= NULL, *cr_deltas= NULL, *swap_deltas= NULL;
EditVert *eve= NULL;
- EditFace *efa= NULL;
MultiApplyData data;
- unsigned i,j,curf;
-
- /* Update special first-level data */
- if(cr_lvl==me->mr->levels.first) {
- multires_update_customdata(me->mr->levels.first, em ? &em->vdata : &me->vdata,
- &me->mr->vdata, CD_MDEFORMVERT);
- multires_update_customdata(me->mr->levels.first, em ? &em->fdata : &me->fdata,
- &me->mr->fdata, CD_MTFACE);
- multires_update_edge_flags(me->mr, me, em);
- }
+ int i, j;
/* Prepare deltas */
- cr_deltas= MEM_callocN(sizeof(vec3f)*cr_lvl->totvert,"initial deltas");
+ pr_deltas= MEM_callocN(sizeof(vec3f)*last_lvl->totvert, "multires deltas 1");
+ cr_deltas= MEM_callocN(sizeof(vec3f)*last_lvl->totvert, "multires deltas 2");
/* Calculate initial deltas -- current mesh subtracted from current level*/
if(em) eve= em->verts.first;
for(i=0; i<cr_lvl->totvert; ++i) {
if(em) {
- VecSubf(&cr_deltas[i].x, eve->co, cr_lvl->verts[i].co);
+ VecSubf(&cr_deltas[i].x, eve->co, me->mr->verts[i].co);
eve= eve->next;
} else
- VecSubf(&cr_deltas[i].x, me->mvert[i].co, cr_lvl->verts[i].co);
- }
-
- /* Faces -- find whether flag/mat has changed */
- cr_flag_damaged= MEM_callocN(sizeof(char)*cr_lvl->totface, "flag_damaged 1");
- cr_mat_damaged= MEM_callocN(sizeof(char)*cr_lvl->totface, "mat_damaged 1");
- if(em) efa= em->faces.first;
- for(i=0; i<cr_lvl->totface; ++i) {
- if(cr_lvl->faces[i].flag != (em ? efa->flag : me->mface[i].flag))
- cr_flag_damaged[i]= 1;
- if(cr_lvl->faces[i].mat_nr != (em ? efa->mat_nr : me->mface[i].mat_nr))
- cr_mat_damaged[i]= 1;
- if(em) efa= efa->next;
+ VecSubf(&cr_deltas[i].x, me->mvert[i].co, me->mr->verts[i].co);
}
- or_flag_damaged= MEM_dupallocN(cr_flag_damaged);
- or_mat_damaged= MEM_dupallocN(cr_mat_damaged);
- /* Update current level -- copy current mesh into current level */
- if(em) {
- eve= em->verts.first;
- efa= em->faces.first;
- }
- for(i=0; i<cr_lvl->totvert; ++i) {
- multires_get_vert(&cr_lvl->verts[i], eve, &me->mvert[i], i);
- if(em) eve= eve->next;
+
+ /* Copy current level's vertex flags and clear the rest */
+ if(em) eve= em->verts.first;
+ for(i=0; i < last_lvl->totvert; ++i) {
+ if(i < cr_lvl->totvert) {
+ MVert mvflag;
+ multires_get_vert(&mvflag, eve, &me->mvert[i], i);
+ if(em) eve= eve->next;
+ me->mr->verts[i].flag= mvflag.flag;
+ }
+ else
+ me->mr->verts[i].flag= 0;
}
- for(i=0; i<cr_lvl->totface; ++i) {
- cr_lvl->faces[i].flag= em ? efa->flag : me->mface[i].flag;
- cr_lvl->faces[i].mat_nr= em ? efa->mat_nr : me->mface[i].mat_nr;
- if(em) efa= efa->next;
+
+ /* If already on the highest level, copy current verts (including flags) into current level */
+ if(cr_lvl == last_lvl) {
+ if(em)
+ eve= em->verts.first;
+ for(i=0; i<cr_lvl->totvert; ++i) {
+ multires_get_vert(&me->mr->verts[i], eve, &me->mvert[i], i);
+ if(em) eve= eve->next;
+ }
}
/* Update higher levels */
pr_lvl= BLI_findlink(&me->mr->levels,me->mr->current-1);
cr_lvl= pr_lvl->next;
while(cr_lvl) {
- /* Set up new deltas, but keep the ones from the previous level */
- if(pr_deltas) MEM_freeN(pr_deltas);
+ /* Swap the old/new deltas */
+ swap_deltas= pr_deltas;
pr_deltas= cr_deltas;
- cr_deltas= MEM_callocN(sizeof(vec3f)*cr_lvl->totvert,"deltas");
- if(pr_flag_damaged) MEM_freeN(pr_flag_damaged);
- pr_flag_damaged= cr_flag_damaged;
- cr_flag_damaged= MEM_callocN(sizeof(char)*cr_lvl->totface,"flag_damaged 2");
- if(pr_mat_damaged) MEM_freeN(pr_mat_damaged);
- pr_mat_damaged= cr_mat_damaged;
- cr_mat_damaged= MEM_callocN(sizeof(char)*cr_lvl->totface,"mat_damaged 2");
+ cr_deltas= swap_deltas;
/* Calculate and add new deltas
- ============================*/
+ ============================ */
for(i=0; i<pr_lvl->totface; ++i) {
const MultiresFace *f= &pr_lvl->faces[i];
data.corner1= &pr_deltas[f->v[0]].x;
@@ -1421,18 +1400,9 @@ void multires_update_levels(Mesh *me, const int render)
data.corner4= &pr_deltas[f->v[3]].x;
data.quad= f->v[3] ? 1 : 0;
multi_apply(&cr_deltas[f->mid].x, &data, 3, catmullclark_smooth_face);
-
- VecAddf(cr_lvl->verts[f->mid].co,
- cr_lvl->verts[f->mid].co,
- &cr_deltas[f->mid].x);
- cr_lvl->verts[f->mid].flag= 0;
- for(j=0; j<(data.quad?4:3); ++j) {
- if(pr_lvl->verts[f->v[j]].flag & 1)
- cr_lvl->verts[f->mid].flag |= 1;
- if(pr_lvl->verts[f->v[j]].flag & ME_HIDE)
- cr_lvl->verts[f->mid].flag |= ME_HIDE;
- }
+ for(j=0; j<(data.quad?4:3); ++j)
+ me->mr->verts[f->mid].flag |= me->mr->verts[f->v[j]].flag;
}
for(i=0; i<pr_lvl->totedge; ++i) {
@@ -1442,20 +1412,9 @@ void multires_update_levels(Mesh *me, const int render)
data.endpoint1= &pr_deltas[e->v[0]].x;
data.endpoint2= &pr_deltas[e->v[1]].x;
multi_apply(&cr_deltas[e->mid].x, &data, 3, catmullclark_smooth_edge);
-
- cr_lvl->verts[e->mid].flag= 0;
- for(j=0; j<2; ++j) {
- if(pr_lvl->verts[e->v[j]].flag & 1)
- cr_lvl->verts[e->mid].flag |= 1;
- if(pr_lvl->verts[e->v[j]].flag & ME_HIDE)
- cr_lvl->verts[e->mid].flag |= ME_HIDE;
- }
- }
- for(i=0; i<pr_lvl->totedge; ++i) {
- const unsigned ndx= pr_lvl->edges[i].mid;
- VecAddf(cr_lvl->verts[ndx].co,
- cr_lvl->verts[ndx].co,
- &cr_deltas[ndx].x);
+
+ for(j=0; j<2; ++j)
+ me->mr->verts[e->mid].flag |= me->mr->verts[e->v[j]].flag;
}
for(i=0; i<pr_lvl->totvert; ++i) {
@@ -1469,31 +1428,13 @@ void multires_update_levels(Mesh *me, const int render)
vert_edge_neighbor_midpoints_average(&data,pr_lvl,pr_deltas,sizeof(vec3f),i);
}
multi_apply(&cr_deltas[i].x, &data, 3, catmullclark_smooth_vert);
- cr_lvl->verts[i].flag= 0;
- if(pr_lvl->verts[i].flag & 1) cr_lvl->verts[i].flag |= 1;
- if(pr_lvl->verts[i].flag & ME_HIDE) cr_lvl->verts[i].flag |= ME_HIDE;
- }
- for(i=0; i<pr_lvl->totvert; ++i) {
- VecAddf(cr_lvl->verts[i].co,
- cr_lvl->verts[i].co,
- &cr_deltas[i].x);
}
- /* Update faces */
- curf= 0;
- for(i=0; i<pr_lvl->totface; ++i) {
- const int sides= cr_lvl->prev->faces[i].v[3] ? 4 : 3;
- for(j=0; j<sides; ++j) {
- if(pr_flag_damaged[i]) {
- cr_lvl->faces[curf].flag= pr_lvl->faces[i].flag;
- cr_flag_damaged[curf]= 1;
- }
- if(pr_mat_damaged[i]) {
- cr_lvl->faces[curf].mat_nr= pr_lvl->faces[i].mat_nr;
- cr_mat_damaged[curf]= 1;
- }
- ++curf;
- }
+ /* Apply deltas to vertex locations */
+ for(i=0; (cr_lvl == last_lvl) && (i < cr_lvl->totvert); ++i) {
+ VecAddf(me->mr->verts[i].co,
+ me->mr->verts[i].co,
+ &cr_deltas[i].x);
}
pr_lvl= pr_lvl->next;
@@ -1502,34 +1443,51 @@ void multires_update_levels(Mesh *me, const int render)
if(pr_deltas) MEM_freeN(pr_deltas);
if(cr_deltas) MEM_freeN(cr_deltas);
+}
+
+void multires_update_faces(Mesh *me, EditMesh *em)
+{
+ MultiresLevel *cr_lvl= current_level(me->mr), *pr_lvl= NULL,
+ *last_lvl= me->mr->levels.last;
+ char *pr_flag_damaged= NULL, *cr_flag_damaged= NULL, *or_flag_damaged= NULL,
+ *pr_mat_damaged= NULL, *cr_mat_damaged= NULL, *or_mat_damaged= NULL, *swap= NULL;
+ EditFace *efa= NULL;
+ unsigned i,j,curf;
+
+ /* Find for each face whether flag/mat has changed */
+ pr_flag_damaged= MEM_callocN(sizeof(char) * last_lvl->totface, "flag_damaged 1");
+ cr_flag_damaged= MEM_callocN(sizeof(char) * last_lvl->totface, "flag_damaged 1");
+ pr_mat_damaged= MEM_callocN(sizeof(char) * last_lvl->totface, "mat_damaged 1");
+ cr_mat_damaged= MEM_callocN(sizeof(char) * last_lvl->totface, "mat_damaged 1");
+ if(em) efa= em->faces.first;
+ for(i=0; i<cr_lvl->totface; ++i) {
+ MultiresFace mftmp;
+ multires_get_face(&mftmp, efa, &me->mface[i]);
+ if(cr_lvl->faces[i].flag != mftmp.flag)
+ cr_flag_damaged[i]= 1;
+ if(cr_lvl->faces[i].mat_nr != mftmp.mat_nr)
+ cr_mat_damaged[i]= 1;
+
+ /* Update current level */
+ cr_lvl->faces[i].flag= mftmp.flag;
+ cr_lvl->faces[i].mat_nr= mftmp.mat_nr;
+
+ if(em) efa= efa->next;
+ }
+ or_flag_damaged= MEM_dupallocN(cr_flag_damaged);
+ or_mat_damaged= MEM_dupallocN(cr_mat_damaged);
+
/* Update lower levels */
- cr_lvl= me->mr->levels.last;
cr_lvl= cr_lvl->prev;
- /* Update Verts */
- while(cr_lvl) {
- for(i=0; i<cr_lvl->totvert; ++i)
- cr_lvl->verts[i]= cr_lvl->next->verts[i];
- cr_lvl= cr_lvl->prev;
- }
-
- /* Update Faces */
-
- /* Clear to original damages */
- if(cr_flag_damaged) MEM_freeN(cr_flag_damaged);
- if(cr_mat_damaged) MEM_freeN(cr_mat_damaged);
- cr_flag_damaged= or_flag_damaged;
- cr_mat_damaged= or_mat_damaged;
-
- cr_lvl= or_lvl->prev;
while(cr_lvl) {
- if(pr_flag_damaged) MEM_freeN(pr_flag_damaged);
+ swap= pr_flag_damaged;
pr_flag_damaged= cr_flag_damaged;
- cr_flag_damaged= MEM_callocN(sizeof(char)*cr_lvl->totface,"flag_damaged 3");
- if(pr_mat_damaged) MEM_freeN(pr_mat_damaged);
+ cr_flag_damaged= swap;
+
+ swap= pr_mat_damaged;
pr_mat_damaged= cr_mat_damaged;
- cr_mat_damaged= MEM_callocN(sizeof(char)*cr_lvl->totface,"mat_damaged 3");
+ cr_mat_damaged= swap;
- /* Update faces */
curf= 0;
for(i=0; i<cr_lvl->totface; ++i) {
const int sides= cr_lvl->faces[i].v[3] ? 4 : 3;
@@ -1549,14 +1507,58 @@ void multires_update_levels(Mesh *me, const int render)
cr_lvl= cr_lvl->prev;
}
+
+ /* Clear to original damages */
+ if(cr_flag_damaged) MEM_freeN(cr_flag_damaged);
+ if(cr_mat_damaged) MEM_freeN(cr_mat_damaged);
+ cr_flag_damaged= or_flag_damaged;
+ cr_mat_damaged= or_mat_damaged;
+
+ /* Update higher levels */
+ pr_lvl= current_level(me->mr);
+ cr_lvl= pr_lvl->next;
+ while(cr_lvl) {
+ swap= pr_flag_damaged;
+ pr_flag_damaged= cr_flag_damaged;
+ cr_flag_damaged= swap;
+
+ swap= pr_mat_damaged;
+ pr_mat_damaged= cr_mat_damaged;
+ cr_mat_damaged= swap;
+
+ /* Update faces */
+ for(i=0, curf= 0; i<pr_lvl->totface; ++i) {
+ const int sides= cr_lvl->prev->faces[i].v[3] ? 4 : 3;
+ for(j=0; j<sides; ++j, ++curf) {
+ if(pr_flag_damaged[i]) {
+ cr_lvl->faces[curf].flag= pr_lvl->faces[i].flag;
+ cr_flag_damaged[curf]= 1;
+ }
+ if(pr_mat_damaged[i]) {
+ cr_lvl->faces[curf].mat_nr= pr_lvl->faces[i].mat_nr;
+ cr_mat_damaged[curf]= 1;
+ }
+ }
+ }
+
+ pr_lvl= pr_lvl->next;
+ cr_lvl= cr_lvl->next;
+ }
if(pr_flag_damaged) MEM_freeN(pr_flag_damaged);
if(cr_flag_damaged) MEM_freeN(cr_flag_damaged);
if(pr_mat_damaged) MEM_freeN(pr_mat_damaged);
if(cr_mat_damaged) MEM_freeN(cr_mat_damaged);
+}
- multires_update_colors(me);
+void multires_update_levels(Mesh *me, const int render)
+{
+ EditMesh *em= (!render && G.obedit) ? G.editMesh : NULL;
+ multires_update_first_level(me, em);
+ multires_update_vertices(me, em);
+ multires_update_faces(me, em);
+ multires_update_colors(me);
}
void multires_calc_level_maps(MultiresLevel *lvl)
diff --git a/source/blender/src/space.c b/source/blender/src/space.c
index c5a485b67cf..bcb3a2784d6 100644
--- a/source/blender/src/space.c
+++ b/source/blender/src/space.c
@@ -97,6 +97,7 @@
#include "BIF_drawscript.h"
#include "BIF_editarmature.h"
#include "BIF_editconstraint.h"
+#include "BIF_editdeform.h"
#include "BIF_editfont.h"
#include "BIF_editgroup.h"
#include "BIF_editkey.h"
@@ -1839,8 +1840,20 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
break;
case GKEY:
- if(G.qual == LR_CTRLKEY)
- group_operation_with_menu();
+ if((G.qual == LR_CTRLKEY)) {
+ if(G.obedit) {
+ if(ELEM(G.obedit->type, OB_MESH, OB_LATTICE))
+ vgroup_assign_with_menu();
+ }
+ else
+ group_operation_with_menu();
+ }
+ else if((G.qual == (LR_CTRLKEY|LR_SHIFTKEY))) {
+ if(G.obedit) {
+ if(ELEM(G.obedit->type, OB_MESH, OB_LATTICE))
+ vgroup_operation_with_menu();
+ }
+ }
else if((G.qual==LR_SHIFTKEY))
if(G.obedit) {
if(G.obedit->type==OB_MESH)
diff --git a/source/blender/src/transform_manipulator.c b/source/blender/src/transform_manipulator.c
index 765c74461f2..773ae3d17ec 100644
--- a/source/blender/src/transform_manipulator.c
+++ b/source/blender/src/transform_manipulator.c
@@ -697,11 +697,13 @@ static void draw_manipulator_axes(int colcode, int flagx, int flagy, int flagz)
/* only called while G.moving */
static void draw_manipulator_rotate_ghost(float mat[][4], int drawflags)
{
- GLUquadricObj *qobj= gluNewQuadric();
+ GLUquadricObj *qobj;
float size, phi, startphi, vec[3], svec[3], matt[4][4], cross[3], tmat[3][3];
int arcs= (G.rt!=2);
glDisable(GL_DEPTH_TEST);
+
+ qobj= gluNewQuadric();
gluQuadricDrawStyle(qobj, GLU_FILL);
glColor4ub(0,0,0,64);
@@ -832,7 +834,7 @@ static void draw_manipulator_rotate_ghost(float mat[][4], int drawflags)
static void draw_manipulator_rotate(float mat[][4], int moving, int drawflags, int combo)
{
- GLUquadricObj *qobj= gluNewQuadric();
+ GLUquadricObj *qobj;
double plane[4];
float size, vec[3], unitmat[4][4];
float cywid= 0.33f*0.01f*(float)U.tw_handlesize;
@@ -849,6 +851,8 @@ static void draw_manipulator_rotate(float mat[][4], int moving, int drawflags, i
/* Init stuff */
glDisable(GL_DEPTH_TEST);
Mat4One(unitmat);
+
+ qobj= gluNewQuadric();
gluQuadricDrawStyle(qobj, GLU_FILL);
/* prepare for screen aligned draw */
@@ -1153,7 +1157,7 @@ static void draw_cylinder(GLUquadricObj *qobj, float len, float width)
static void draw_manipulator_translate(float mat[][4], int moving, int drawflags, int combo, int colcode)
{
- GLUquadricObj *qobj = gluNewQuadric();
+ GLUquadricObj *qobj;
float cylen= 0.01f*(float)U.tw_handlesize;
float cywid= 0.25f*cylen, dz, size;
float unitmat[4][4];
@@ -1163,6 +1167,8 @@ static void draw_manipulator_translate(float mat[][4], int moving, int drawflags
if(moving) glTranslatef(Trans.vec[0], Trans.vec[1], Trans.vec[2]);
glDisable(GL_DEPTH_TEST);
+
+ qobj= gluNewQuadric();
gluQuadricDrawStyle(qobj, GLU_FILL);
/* center circle, do not add to selection when shift is pressed (planar constraint) */
@@ -1225,19 +1231,21 @@ static void draw_manipulator_translate(float mat[][4], int moving, int drawflags
static void draw_manipulator_rotate_cyl(float mat[][4], int moving, int drawflags, int combo, int colcode)
{
- GLUquadricObj *qobj = gluNewQuadric();
+ GLUquadricObj *qobj;
float size;
float cylen= 0.01f*(float)U.tw_handlesize;
float cywid= 0.25f*cylen;
/* when called while moving in mixed mode, do not draw when... */
if((drawflags & MAN_ROT_C)==0) return;
-
+
/* prepare for screen aligned draw */
glPushMatrix();
size= screen_aligned(mat);
glDisable(GL_DEPTH_TEST);
+
+ qobj= gluNewQuadric();
/* Screen aligned view rot circle */
if(drawflags & MAN_ROT_V) {
diff --git a/source/gameengine/Converter/BL_ArmatureObject.cpp b/source/gameengine/Converter/BL_ArmatureObject.cpp
index 91c527f1980..4bf13a09fb4 100644
--- a/source/gameengine/Converter/BL_ArmatureObject.cpp
+++ b/source/gameengine/Converter/BL_ArmatureObject.cpp
@@ -190,8 +190,9 @@ double BL_ArmatureObject::GetLastFrame()
bool BL_ArmatureObject::GetBoneMatrix(Bone* bone, MT_Matrix4x4& matrix) const
{
- // ton hack
- bPoseChannel *pchan= get_pose_channel(m_pose, bone->name);
+ Object* par_arma = m_objArma;
+ where_is_pose(par_arma);
+ bPoseChannel *pchan= get_pose_channel(par_arma->pose, bone->name);
if(pchan) {
matrix.setValue(&pchan->pose_mat[0][0]);
diff --git a/source/gameengine/Ketsji/BL_Shader.cpp b/source/gameengine/Ketsji/BL_Shader.cpp
index 4e32d2cced9..ab0479eb88b 100644
--- a/source/gameengine/Ketsji/BL_Shader.cpp
+++ b/source/gameengine/Ketsji/BL_Shader.cpp
@@ -1,4 +1,5 @@
-// ------------------------------------
+
+
#ifdef WIN32
#include <windows.h>
#endif // WIN32
diff --git a/tools/btools.py b/tools/btools.py
index fba884ed09b..1dc35bb7248 100755
--- a/tools/btools.py
+++ b/tools/btools.py
@@ -1,7 +1,12 @@
-import sys
-import StringIO
+import os
+import os.path
import SCons.Options
import SCons.Options.BoolOption
+import subprocess
+import string
+import glob
+import shutil
+import sys
Options = SCons.Options
BoolOption = SCons.Options.BoolOption
@@ -84,33 +89,26 @@ def validate_targets(targs, bc):
print '\t'+bc.WARNING+'Invalid target: '+bc.ENDC+t
return oklist
-
-
-class idBuffering:
- def buffered_spawn( self, sh, escape, cmd, args, env ):
- stderr = StringIO.StringIO()
- stdout = StringIO.StringIO()
- command_string = ''
- for i in args:
- if ( len( command_string ) ):
- command_string += ' '
- command_string += i
- try:
- retval = self.env['PSPAWN']( sh, escape, cmd, args, env, stdout, stderr )
- except OSError, x:
- if x.errno != 10:
- raise x
- print 'OSError ignored on command: %s' % command_string
- retval = 0
- sys.stdout.write( stdout.getvalue() )
- sys.stderr.write( stderr.getvalue() )
- return retval
-
-# get a clean error output when running multiple jobs
-def SetupBufferedOutput( env ):
- buf = idBuffering()
- buf.env = env
- env['SPAWN'] = buf.buffered_spawn
+class ourSpawn:
+ def ourspawn(self, sh, escape, cmd, args, env):
+ newargs = string.join(args[1:], ' ')
+ cmdline = cmd + " " + newargs
+ startupinfo = subprocess.STARTUPINFO()
+ startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
+ proc = subprocess.Popen(cmdline, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE, startupinfo=startupinfo, shell = False)
+ data, err = proc.communicate()
+ rv = proc.wait()
+ if rv:
+ print "====="
+ print err
+ print "====="
+ return rv
+
+def SetupSpawn( env ):
+ buf = ourSpawn()
+ buf.ourenv = env
+ env['SPAWN'] = buf.ourspawn
def read_opts(cfg, args):
@@ -297,3 +295,186 @@ def read_opts(cfg, args):
return localopts
+def NSIS_print(target, source, env):
+ return "Creating NSIS installer for Blender 3D"
+
+def NSIS_Installer(target=None, source=None, env=None):
+
+ if env['OURPLATFORM'] != 'win32-vc' and env['OURPLATFORM'] != 'win32-mingw':
+ print "NSIS installer is only available on Windows."
+ Exit()
+
+ start_dir = os.getcwd()
+ rel_dir = start_dir + "\\release\\windows\\installer\\"
+ install_base_dir = start_dir + "\\"
+
+ if not os.path.exists(install_base_dir+env['BF_INSTALLDIR']+'/plugins/include'):
+ os.mkdir(install_base_dir+env['BF_INSTALLDIR']+'/plugins/include')
+
+ for f in glob.glob('source/blender/blenpluginapi/*.h'):
+ shutil.copy(f,install_base_dir+env['BF_INSTALLDIR']+'/plugins/include')
+
+ shutil.copy('source/blender/blenpluginapi/plugin.def',install_base_dir+env['BF_INSTALLDIR']+'/plugins/include/')
+
+ os.chdir("release")
+ v = open("VERSION")
+ version = v.read()[:-1]
+ shortver = version.split('.')[0] + version.split('.')[1]
+ v.close()
+
+ #### change to suit install dir ####
+ inst_dir = install_base_dir + env['BF_INSTALLDIR']
+
+ os.chdir("windows/installer")
+
+ ns = open("00.sconsblender.nsi","r")
+
+ ns_cnt = str(ns.read())
+ ns.close()
+
+ # do root
+ rootlist = []
+ rootdir = os.listdir(inst_dir+"\\")
+ for rootitem in rootdir:
+ if os.path.isdir(inst_dir+"\\"+ rootitem) == 0:
+ rootlist.append("File \"" + os.path.normpath(inst_dir) + "\\" + rootitem+"\"")
+ rootstring = string.join(rootlist, "\n ")
+ rootstring += "\n\n"
+ ns_cnt = string.replace(ns_cnt, "[ROOTDIRCONTS]", rootstring)
+
+ # do delete items
+ delrootlist = []
+ for rootitem in rootdir:
+ if os.path.isdir(inst_dir + rootitem) == 0:
+ delrootlist.append("Delete $INSTDIR\\" + rootitem)
+ delrootstring = string.join(delrootlist, "\n ")
+ delrootstring += "\n"
+ ns_cnt = string.replace(ns_cnt, "[DELROOTDIRCONTS]", delrootstring)
+
+ # do scripts
+ scriptlist = []
+ scriptpath = "%s%s" % (inst_dir, "\\.blender\\scripts")
+ scriptdir = os.listdir(scriptpath)
+ for scriptitem in scriptdir:
+ scriptfile = "%s\\%s" % (scriptpath, scriptitem)
+ if os.path.isdir(scriptfile) == 0:
+ scriptfile = os.path.normpath(scriptfile)
+ scriptlist.append("File \"%s\"" % scriptfile)
+ scriptstring = string.join(scriptlist, "\n ")
+ scriptstring += "\n\n"
+ ns_cnt = string.replace(ns_cnt, "[SCRIPTCONTS]", scriptstring)
+
+ # do scripts\bpymodules
+ bpymodlist = []
+ bpymodpath = "%s%s" % (inst_dir, "\\.blender\\scripts\\bpymodules")
+ bpymoddir = os.listdir(bpymodpath)
+
+ for bpymoditem in bpymoddir:
+ bpymodfile = "%s\\%s" % (bpymodpath, bpymoditem)
+ if os.path.isdir(bpymodfile) == 0:
+ bpymodfile = os.path.normpath(bpymodfile)
+ bpymodlist.append("File \"%s\"" % bpymodfile)
+ bpymodstring = string.join(bpymodlist, "\n ")
+ bpymodstring += "\n\n"
+ ns_cnt = string.replace(ns_cnt, "[SCRIPTMODCONTS]", bpymodstring)
+
+ # do scripts\bpymodules\colladaimex
+ colladalist = []
+ bpymodpath = "%s%s" % (inst_dir, "\\.blender\\scripts\\bpymodules\\ColladaImEx")
+ bpymoddir = os.listdir(bpymodpath)
+
+ for bpymoditem in bpymoddir:
+ bpymodfile = "%s\\%s" % (bpymodpath, bpymoditem)
+ if os.path.isdir(bpymodfile) == 0:
+ bpymodfile=os.path.normpath(bpymodfile)
+ colladalist.append("File \"%s\"" % bpymodfile)
+ bpymodstring = string.join(colladalist, "\n ")
+ bpymodstring += "\n\n"
+ ns_cnt = string.replace(ns_cnt, "[SCRIPTMODCOLLADACONT]", bpymodstring)
+
+ # do scripts\bpydata
+ bpydatalist = []
+ bpydatapath = "%s%s" % (inst_dir, "\\.blender\\scripts\\bpydata")
+ bpydatadir = os.listdir(bpydatapath)
+ for bpydataitem in bpydatadir:
+ bpydatafile = "%s\\%s" % (bpydatapath, bpydataitem)
+ if os.path.isdir(bpydatafile) == 0:
+ bpydatalist.append("File \"%s\"" % bpydatafile)
+ bpydatastring = string.join(bpydatalist, "\n ")
+ bpydatastring += "\n\n"
+ ns_cnt = string.replace(ns_cnt, "[SCRIPTDATACONTS]", bpydatastring)
+
+ # do plugins\include
+ plugincludelist = []
+ plugincludepath = "%s%s" % (inst_dir, "\\plugins\\include")
+ plugincludedir = os.listdir(plugincludepath)
+ for plugincludeitem in plugincludedir:
+ plugincludefile = "%s\\%s" % (plugincludepath, plugincludeitem)
+ if os.path.isdir(plugincludefile) == 0:
+ if plugincludefile.find('.h') or plugincludefile.find('.DEF'):
+ plugincludefile = os.path.normpath(plugincludefile)
+ plugincludelist.append("File \"%s\"" % plugincludefile)
+ plugincludestring = string.join(plugincludelist, "\n ")
+ plugincludestring += "\n\n"
+ ns_cnt = string.replace(ns_cnt, "[PLUGINCONTS]", plugincludestring)
+
+ # do scripts\bpydata\config
+ cfglist = []
+ cfgpath = "%s%s" % (inst_dir, "\\.blender\\scripts\\bpydata\\config")
+ cfgdir = os.listdir(cfgpath)
+ for cfgitem in cfgdir:
+ cfgfile = "%s\\%s" % (cfgpath, cfgitem)
+ if os.path.isdir(cfgfile) == 0:
+ cfglist.append("File \"%s\"" % cfgfile)
+ cfgstring = string.join(cfglist, "\n ")
+ cfgstring += "\n\n"
+ ns_cnt = string.replace(ns_cnt, "[SCRIPTDATACFGCONTS]", cfgstring)
+
+ # do dotblender
+ dotblendlist = []
+ dotblenddir = os.listdir(inst_dir+"\\.blender")
+ for dotblenditem in dotblenddir:
+ if os.path.isdir(inst_dir + "\\.blender\\" + dotblenditem) == 0:
+ dotblendlist.append("File \"" + os.path.normpath(inst_dir) + "\\.blender\\" +
+ dotblenditem+"\"")
+ dotblendstring = string.join(dotblendlist, "\n ")
+ dotblendstring += "\n\n"
+ ns_cnt = string.replace(ns_cnt, "[DOTBLENDERCONTS]", dotblendstring)
+
+ # do language files
+ langlist = []
+ langfiles = []
+ langdir = os.listdir(inst_dir + "\\.blender\\locale")
+ for langitem in langdir:
+ if os.path.isdir(inst_dir + "\\.blender\\locale\\" + langitem) == 1:
+ langfiles.append("SetOutPath $BLENDERHOME\\.blender\\locale\\" + langitem + "\\LC_MESSAGES")
+ langfiles.append("File \"" + os.path.normpath(inst_dir) + "\\.blender\\locale\\"
+ + langitem + "\\LC_MESSAGES\\blender.mo\"")
+ langstring = string.join(langfiles, "\n ")
+ langstring += "\n\n"
+ ns_cnt = string.replace(ns_cnt, "[LANGUAGECONTS]", langstring)
+
+ # var replacements
+ ns_cnt = string.replace(ns_cnt, "DISTDIR", os.path.normpath(inst_dir+"\\"))
+ ns_cnt = string.replace(ns_cnt, "SHORTVER", shortver)
+ ns_cnt = string.replace(ns_cnt, "VERSION", version)
+ ns_cnt = string.replace(ns_cnt, "RELDIR", os.path.normpath(rel_dir))
+
+ tmpnsi = os.path.normpath(install_base_dir+os.sep+env['BF_BUILDDIR']+os.sep+"00.blender_tmp.nsi")
+ new_nsis = open(tmpnsi, 'w')
+ new_nsis.write(ns_cnt)
+ new_nsis.close()
+
+ os.chdir(start_dir)
+
+ cmdline = "makensis " + "\""+tmpnsi+"\""
+
+ startupinfo = subprocess.STARTUPINFO()
+ startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
+ proc = subprocess.Popen(cmdline, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE, startupinfo=startupinfo, shell = True)
+ data, err = proc.communicate()
+ rv = proc.wait()
+
+ return 0
+