From 189d8b8d287b0dd88c3d2d9642dcfd9f10dad913 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Tue, 29 May 2007 06:30:33 +0000 Subject: [PATCH 01/30] == PY-API Docs == Fixed bad description for a function. As reported here: http://www.blender.org/forum/viewtopic.php?t=11752 --- source/blender/python/api2_2x/doc/Render.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 """ From d597bff7d3896d5f5b074c448bad951fa9e1f899 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Tue, 29 May 2007 06:42:10 +0000 Subject: [PATCH 02/30] == Multires == Fixed bug [#6737] facecount is reported incorrectly when using multires * Added a call to update the derivedmesh after updating a multires mesh. --- source/blender/src/multires.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/blender/src/multires.c b/source/blender/src/multires.c index d1ae24e73a8..a249b6b408b 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" @@ -1205,6 +1206,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; From 92f1d59b44f67c5ccbe020f0fb484da3d147f52d Mon Sep 17 00:00:00 2001 From: Charlie Carley Date: Tue, 29 May 2007 07:46:07 +0000 Subject: [PATCH 03/30] Test commit... --- source/gameengine/Ketsji/BL_Shader.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 #endif // WIN32 From 044607a450e8b8d230d52155e19541f8e9473f78 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Tue, 29 May 2007 10:28:19 +0000 Subject: [PATCH 04/30] == PY API == Added some braces to silence gcc warnings about scene.c --- source/blender/python/api2_2x/Scene.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) 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, From 7585adc8cce519773dd775d611f661ca22e7dc27 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 29 May 2007 21:39:29 +0000 Subject: [PATCH 05/30] Script from Gerhard for exporting blender to m3g and java source, see website for examples http://www.nelson-games.de/bl2m3g/default.html --- release/scripts/export_m3g.py | 3047 +++++++++++++++++++++++++++++++++ 1 file changed, 3047 insertions(+) create mode 100644 release/scripts/export_m3g.py 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 : +# #AE# + +# 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 = ' 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(" 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(' 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(' 0 : + value += struct.calcsize('<' + str(len(self.indices)) + 'I') + value += struct.calcsize(' 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(" 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('#AE# + 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(' Date: Wed, 30 May 2007 06:11:25 +0000 Subject: [PATCH 06/30] * Fix for #6707 This fix is windows specific. AVIs are now evaluated by the pre-FFMPEG code first, failing that only by FFMPEG. Adding the 200 frame testfile from the bugreport http://projects.blender.org/tracker/?func=detail&aid=6707&group_id=9&atid=125 now goes fine with Add>Movie. Add>Movie+Audio will complain about the fail first, but it will be added anyway. --- source/blender/imbuf/intern/util.c | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) 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 +# 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 + 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); From 024485b9b8a1ad6a4e5e72665537b826f73ee86a Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Wed, 30 May 2007 10:36:17 +0000 Subject: [PATCH 07/30] Patch #6759: this speeds up the vertex group editing workflow a bit. The hotkey Ctrl-G in EditMode for Meshes and Lattices, brings up a menu giving the user options to assign/remove selected vertices to a new/the active Vertex Group. The hotkey Ctrl-Shift-G in EditMode for Meshes and Lattices, brings up a menu giving the user options to change the active Vertex Group and delete the current Vertex Group. --- source/blender/include/BIF_editdeform.h | 3 + source/blender/src/editdeform.c | 97 +++++++++++++++++++++++++ source/blender/src/space.c | 17 ++++- 3 files changed, 115 insertions(+), 2 deletions(-) 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/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/space.c b/source/blender/src/space.c index a528fd260ff..ec43d55a2bd 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" @@ -1835,8 +1836,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) From 6e716521f8a06b6d8161e72a63cc7e5c4379cba5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Luc=20Peuri=C3=A8re?= Date: Wed, 30 May 2007 21:34:21 +0000 Subject: [PATCH 08/30] **blush** I never committed the depth buffer changes from 16 to 32 thanks to meestaplu for spotting it --- intern/ghost/intern/GHOST_WindowCarbon.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) 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, }; From 6057ab05f0b4d4ab7a84a142bcdeee65fffe97d9 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 31 May 2007 06:12:09 +0000 Subject: [PATCH 09/30] Updated this script not to choke on some blank lines (example file from Lekane) Also removed the use of list.index() all over the place where the index was known. (saves searching the file and the possibility of duplicates messing it up) --- release/scripts/DirectX8Importer.py | 178 ++++++++++++---------------- 1 file changed, 78 insertions(+), 100 deletions(-) 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') From 17a219e3c0af09d682179f3e087472dbd27b6540 Mon Sep 17 00:00:00 2001 From: Matt Ebb Date: Thu, 31 May 2007 06:55:02 +0000 Subject: [PATCH 10/30] == Shader nodes == * Geometry node: Front/back output This is used as a mask for determining whether you're looking at the front side or back side of a mesh, useful for blending materials, my practical need was giving different materials to the pages of a magazine: http://mke3.net/blender/etc/frontback-h264.mov Give 1.0 if it's the front side, and 0.0 if it's the back side. * Extended material node This is the same as the material node, but gives more available inputs and outputs, (basically just connecting up more of ShadeInput and ShadeResult to the node). I didn't want to add it to the normal simple Material node since you don't always need all that stuff, and it would make the node huge, but when you do need it, it's nice to have it. == Comp nodes == * Invert node Inverting is something that happens all the time in a node setup, and this makes it easier. It's been possible to invert previously by adding a mix node and subtracting the input from 1.0, but it's not the best way of doing it. This node: - makes it a lot faster to set up, rather than all the clicking required with the mix node - is a lot more usable amidst a complex comp setup, when you're looking at a node tree, it's very helpful to be able to see at a glance what's going on. Using subtract for inverting is easily mixed up with other nodes in which you are actually subtracting, not inverting, and looks very similar to all the other mix nodes that usually litter a comp tree. - has options to invert the RGB channels, the Alpha channel, or both. This saves adding lots of extra nodes (separate RGBA, subtract, set alpha) when you want to do something simple like invert an alpha channel. I'd like to add this option to other nodes too. There's also a shader node version too. * Also a few fixes that I committed ages ago, but seems to have been overwritten in Bob's node refactor: - adding new compbufs to the set alpha and alphaover nodes when you have only one noodle connected to the lower input - making the fac value on RGB curves still work when there's nothing connected to it --- source/blender/blenkernel/BKE_node.h | 11 +- source/blender/blenkernel/intern/node.c | 8 +- source/blender/nodes/CMP_node.h | 6 +- source/blender/nodes/SHD_node.h | 2 + .../nodes/intern/CMP_nodes/CMP_alphaOver.c | 4 +- .../nodes/intern/CMP_nodes/CMP_curves.c | 6 +- .../nodes/intern/CMP_nodes/CMP_invert.c | 131 ++++++++++++++++++ .../nodes/intern/CMP_nodes/CMP_mixrgb.c | 2 +- .../nodes/intern/CMP_nodes/CMP_setalpha.c | 4 +- .../blender/nodes/intern/SHD_nodes/SHD_geom.c | 11 ++ .../nodes/intern/SHD_nodes/SHD_invert.c | 83 +++++++++++ .../nodes/intern/SHD_nodes/SHD_material.c | 79 ++++++++++- source/blender/nodes/intern/SHD_util.c | 30 +++- source/blender/nodes/intern/SHD_util.h | 18 +++ .../render/extern/include/RE_shader_ext.h | 5 + .../blender/render/intern/source/shadeinput.c | 5 + source/blender/src/drawnode.c | 19 +++ 17 files changed, 403 insertions(+), 21 deletions(-) create mode 100644 source/blender/nodes/intern/CMP_nodes/CMP_invert.c create mode 100644 source/blender/nodes/intern/SHD_nodes/SHD_invert.c 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/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/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..4bc026302dd --- /dev/null +++ b/source/blender/nodes/intern/CMP_nodes/CMP_invert.c @@ -0,0 +1,131 @@ +/** + * $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; + CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* allocs */ + + /* if neither RGB or A toggled on, pass through */ + if (node->custom1 == 0) { + out[0]->data = pass_on_compbuf(cbuf); + return; + } + + 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; + } +} + +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/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/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; } From 270ab2fe18889616355a6c69e1905c32cf11df7f Mon Sep 17 00:00:00 2001 From: Matt Ebb Date: Thu, 31 May 2007 07:33:18 +0000 Subject: [PATCH 11/30] Fix for invert comp node, was allocating a compbuf unnecessarily. --- .../nodes/intern/CMP_nodes/CMP_invert.c | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_invert.c b/source/blender/nodes/intern/CMP_nodes/CMP_invert.c index 4bc026302dd..1d4be2bc09f 100644 --- a/source/blender/nodes/intern/CMP_nodes/CMP_invert.c +++ b/source/blender/nodes/intern/CMP_nodes/CMP_invert.c @@ -90,19 +90,22 @@ static void node_composit_exec_invert(void *data, bNode *node, bNodeStack **in, 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; - CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* allocs */ - + /* if neither RGB or A toggled on, pass through */ - if (node->custom1 == 0) { + 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; } - - 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; } } From 1badf04923cfbe0007a7497ee9085ca732d19d4e Mon Sep 17 00:00:00 2001 From: Nathan Letwory Date: Thu, 31 May 2007 07:42:54 +0000 Subject: [PATCH 12/30] === SCons === FINALLY! With this commit command-length problems are History. Thanks go to xuru from #scons for giving the nice pointer. src is now again one lib, and further libsplitting should be rather unnecessary, unless we somehow reach the 37K limit (for internally used CreateProcess, by subprocess module) --- SConstruct | 60 ++++------------------------------- source/blender/src/SConscript | 18 +---------- tools/btools.py | 51 ++++++++++++++--------------- 3 files changed, 31 insertions(+), 98 deletions(-) diff --git a/SConstruct b/SConstruct index 2a8adac2338..8f1ab1d2529 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': @@ -285,7 +241,7 @@ def NSIS_Installer(): 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') @@ -484,8 +440,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') 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/tools/btools.py b/tools/btools.py index fba884ed09b..cf936a95e26 100755 --- a/tools/btools.py +++ b/tools/btools.py @@ -1,7 +1,9 @@ -import sys -import StringIO +import os +import os.path import SCons.Options import SCons.Options.BoolOption +import subprocess +import string Options = SCons.Options BoolOption = SCons.Options.BoolOption @@ -84,33 +86,26 @@ def validate_targets(targs, bc): print '\t'+bc.WARNING+'Invalid target: '+bc.ENDC+t return oklist - +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 -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 +def SetupSpawn( env ): + buf = ourSpawn() + buf.ourenv = env + env['SPAWN'] = buf.ourspawn def read_opts(cfg, args): From 8b2a129294a8b389072728d6384cd89c11208a9c Mon Sep 17 00:00:00 2001 From: Nathan Letwory Date: Thu, 31 May 2007 11:15:47 +0000 Subject: [PATCH 13/30] === SCons === * Finally cleaned up the NSIS installer creation process This is now a proper action and command, with simple printout The 'nsis' target (only on Windows) now properly depends on all the build process, and will be done as very last. * Make LZMA (Solid) default compressor for installer (= the best) --- SConstruct | 170 +--------------- release/windows/installer/00.sconsblender.nsi | 15 +- tools/btools.py | 186 ++++++++++++++++++ 3 files changed, 200 insertions(+), 171 deletions(-) diff --git a/SConstruct b/SConstruct index 8f1ab1d2529..7e9e0344c3a 100644 --- a/SConstruct +++ b/SConstruct @@ -234,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 @@ -578,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) @@ -586,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/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/tools/btools.py b/tools/btools.py index cf936a95e26..1dc35bb7248 100755 --- a/tools/btools.py +++ b/tools/btools.py @@ -4,6 +4,9 @@ import SCons.Options import SCons.Options.BoolOption import subprocess import string +import glob +import shutil +import sys Options = SCons.Options BoolOption = SCons.Options.BoolOption @@ -292,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 + From 57a91d7659a60933e76a761c1eb7000f9496773a Mon Sep 17 00:00:00 2001 From: Mal Duffin Date: Thu, 31 May 2007 11:20:35 +0000 Subject: [PATCH 14/30] Test commit by myself ( whitespace ), just spreading my new Blender commit wings! --- source/blender/src/drawmesh.c | 1 - 1 file changed, 1 deletion(-) 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; From 2d8dd194ccd2aec3b27f145c488354fbc81b41fa Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Thu, 31 May 2007 11:47:04 +0000 Subject: [PATCH 15/30] == Action Editor == Small Action Editor feature to hopefully make keyframing quicker. Just press the IKEY in the Action Editor. Feedback on the (annoyance factor of the) popups welcome. --- source/blender/include/BIF_editaction.h | 1 + source/blender/src/editaction.c | 91 +++++++++++++++++++++++-- source/blender/src/editipo.c | 3 + 3 files changed, 89 insertions(+), 6 deletions(-) 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/src/editaction.c b/source/blender/src/editaction.c index 4c698674bbf..e9b0e43b410 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,75 @@ 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; + IpoCurve *icu; + short mode; + float cfra, val; + + /* 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) { + val = icu->curval; + insert_vert_ipo(icu, cfra, val); + } + } + + 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) { + val = icu->curval; + insert_vert_ipo(icu, cfra, val); + } + } + } + } + } + } + } + } + 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) { + val = icu->curval; + insert_vert_ipo(icu, cfra, val); + } + } + } + + 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 +2961,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 +3330,7 @@ void winqreadactionspace(ScrArea *sa, void *spacedata, BWinEvent *evt) } } break; - + case KKEY: if (G.qual & LR_CTRLKEY) { markers_selectkeys_between(); @@ -3278,8 +3353,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 +3406,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/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]; From 0ea46073085676ed4dc5c0d0e18420205c80c86b Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 31 May 2007 13:48:16 +0000 Subject: [PATCH 16/30] scene.camera was missing from docs bad bad mistake- key wasnt returning IPO's --- source/blender/python/api2_2x/Key.c | 2 +- source/blender/python/api2_2x/doc/Scene.py | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) 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/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 From 134739106023f3f7635ad1a128c7f77044b40884 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Thu, 31 May 2007 14:02:43 +0000 Subject: [PATCH 17/30] Fix for memory leak: Manipulator drawing, enabled or disabled, with the exception of the combo manipulator, was leaking a GLU quadric on every redraw. I don't think this caused trouble in practical situations though, it leaked about 1 MB when running Alt+A for 20 minutes here. --- source/blender/src/transform_manipulator.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) 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) { From a9640819ffbad25f2730bb89e47ee94c1d89786e Mon Sep 17 00:00:00 2001 From: Charlie Carley Date: Thu, 31 May 2007 20:40:59 +0000 Subject: [PATCH 18/30] Applied patch [#5795] Parent to bone - Supplied by Monster. --- source/gameengine/Converter/BL_ArmatureObject.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) 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]); From 9d0f74658001947781cd65d28fb7982b36acd1fd Mon Sep 17 00:00:00 2001 From: Jens Ole Wund Date: Fri, 1 Jun 2007 00:40:52 +0000 Subject: [PATCH 19/30] test commit knit picking users complained about available options with non softbody able objects --- source/blender/src/buttons_object.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index e47a80fe9fa..ed9b2043924 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -2462,11 +2462,21 @@ 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) + ) 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 +2555,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); From 1a9f0e692acc3d5b2b9111e781d5e4a018c811d5 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Fri, 1 Jun 2007 02:21:11 +0000 Subject: [PATCH 20/30] == Multires == * Moved the multires vertex data from struct MultiresLevel to struct Multires. There's no longer any reason to store data seperately for each level; it was just taking up extra memory. * Incremented the subversion to 2 and adjusted do_versions to correctly load older files. * Refactored the multires update process (which handles propagating changes to other levels) --- source/blender/blenkernel/BKE_blender.h | 2 +- .../blender/blenkernel/intern/DerivedMesh.c | 2 +- source/blender/blenkernel/intern/mesh.c | 2 +- source/blender/blenloader/intern/readfile.c | 21 + source/blender/blenloader/intern/writefile.c | 6 +- source/blender/include/multires.h | 2 + source/blender/makesdna/DNA_meshdata_types.h | 6 +- source/blender/src/multires-firstlevel.c | 37 ++ source/blender/src/multires.c | 378 +++++++++--------- 9 files changed, 262 insertions(+), 194 deletions(-) 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/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; itotvert; ++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/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 118c2779ac0..4bbcfab74ae 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); @@ -6469,6 +6471,25 @@ static void do_versions(FileData *fd, Library *lib, Main *main) for(sce= main->scene.first; sce; sce= sce->id.next) sce->r.mode |= R_SSS; } + if(main->versionfile != 244 || main->subversionfile < 2) { + /* Copy over old per-level multires vertex data + into a single vertex array in struct Multires */ + Mesh *me; + 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; + } + } + } + } + } } /* WATCH IT!!!: pointers from libdata have not been converted yet here! */ 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/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/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; itotedge; ++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 a249b6b408b..33b85bd27b6 100644 --- a/source/blender/src/multires.c +++ b/source/blender/src/multires.c @@ -484,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; @@ -575,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; itotvert; ++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; } @@ -636,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); @@ -658,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) { @@ -690,6 +692,8 @@ void multires_free(Multires *mr) lvl= lvl->next; } + MEM_freeN(mr->verts); + BLI_freelistN(&mr->levels); MEM_freeN(mr); @@ -700,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); @@ -844,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(); @@ -859,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; iprev->totvert; ++i) - lvl->verts[i]= lvl->prev->verts[i]; + me->mr->verts[i]= oldverts[i]; /* Create new edge verts */ for(i=0; iprev->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 */ @@ -937,38 +942,42 @@ void multires_add_level(void *ob, void *me_v) =============== */ for(i=0; iprev->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; iprev->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; iprev->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; @@ -1094,13 +1103,13 @@ void multires_level_to_mesh(Object *ob, Mesh *me, const int render) for(i=0; itotvert; ++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; itotedge; ++i) { if(em) { @@ -1115,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 { @@ -1160,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; itotedge; ++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(); @@ -1313,108 +1333,65 @@ void multires_update_colors(Mesh *me) } } -void multires_update_edge_flags(Multires *mr, Mesh *me, EditMesh *em) +/* Update vertex locations and vertex flags */ +void multires_update_vertices(Mesh *me, EditMesh *em) { - MultiresLevel *lvl= current_level(mr); - EditEdge *eed= NULL; - int i; - - if(em) eed= em->edges.first; - for(i=0; itotedge; ++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) -{ - /* 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; itotvert; ++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); + VecSubf(&cr_deltas[i].x, me->mvert[i].co, me->mr->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; itotface; ++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; - } - 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; + + /* 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; itotvert; ++i) { - multires_get_vert(&cr_lvl->verts[i], eve, &me->mvert[i], i); - if(em) eve= eve->next; - } - for(i=0; itotface; ++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; itotvert; ++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; itotface; ++i) { const MultiresFace *f= &pr_lvl->faces[i]; data.corner1= &pr_deltas[f->v[0]].x; @@ -1423,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; itotedge; ++i) { @@ -1444,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; itotedge; ++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; itotvert; ++i) { @@ -1471,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; itotvert; ++i) { - VecAddf(cr_lvl->verts[i].co, - cr_lvl->verts[i].co, - &cr_deltas[i].x); } - /* Update faces */ - curf= 0; - for(i=0; itotface; ++i) { - const int sides= cr_lvl->prev->faces[i].v[3] ? 4 : 3; - for(j=0; jfaces[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; @@ -1504,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); - /* Update lower levels */ - cr_lvl= me->mr->levels.last; - cr_lvl= cr_lvl->prev; - /* Update Verts */ - while(cr_lvl) { - for(i=0; itotvert; ++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); - 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); - pr_mat_damaged= cr_mat_damaged; - cr_mat_damaged= MEM_callocN(sizeof(char)*cr_lvl->totface,"mat_damaged 3"); +} + +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; itotface; ++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= cr_lvl->prev; + 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 */ curf= 0; for(i=0; itotface; ++i) { const int sides= cr_lvl->faces[i].v[3] ? 4 : 3; @@ -1551,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; itotface; ++i) { + const int sides= cr_lvl->prev->faces[i].v[3] ? 4 : 3; + for(j=0; jfaces[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); +} +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) From f19b56a541c1c8923fc64adefd7e250c5b55b965 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 1 Jun 2007 02:33:23 +0000 Subject: [PATCH 21/30] When converting from TF_SELECT to use the mfaces selection flag only I missed getSelectedFaces. This broke theeths UV-Exportscript. updated and added 2 missing decref's, as well as a check not to write a list of faces greater then the size of the NMesh (mesh and NMesh face lengths can differ) --- source/blender/python/api2_2x/NMesh.c | 28 ++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/source/blender/python/api2_2x/NMesh.c b/source/blender/python/api2_2x/NMesh.c index 5c86a344896..b0ab64a6249 100644 --- a/source/blender/python/api2_2x/NMesh.c +++ b/source/blender/python/api2_2x/NMesh.c @@ -1278,23 +1278,33 @@ static PyObject *NMesh_getSelectedFaces( PyObject * self, PyObject * args ) Mesh *me = nm->mesh; int flag = 0; - MTFace *tf; + MFace *mf; int i; PyObject *l = PyList_New( 0 ), *pyval; - if( me == NULL ) + /* dont allow returning more then the NMesh's number of faces */ + int totfaces = PySequence_Length(nm->faces); + + if( me == NULL ) { + Py_DECREF(l); return NULL; - - tf = me->mtface; - if( tf == 0 ) + } + mf = me->mface; + if( mf == NULL ) return l; - if( !PyArg_ParseTuple( args, "|i", &flag ) ) + if( !PyArg_ParseTuple( args, "|i", &flag ) ) { + Py_DECREF(l); return NULL; - + } + + /* make sure not to write more faces then we have */ + if (totfaces > me->totface) + totfaces= me->totface; + if( flag ) { for( i = 0; i < me->totface; i++ ) { - if( tf[i].flag & TF_SELECT ) { + if( mf[i].flag & ME_FACE_SEL ) { pyval = PyInt_FromLong( i ); PyList_Append( l, pyval ); Py_DECREF(pyval); @@ -1302,7 +1312,7 @@ static PyObject *NMesh_getSelectedFaces( PyObject * self, PyObject * args ) } } else { for( i = 0; i < me->totface; i++ ) { - if( tf[i].flag & TF_SELECT ) + if( mf[i].flag & ME_FACE_SEL ) PyList_Append( l, PyList_GetItem( nm->faces, i ) ); } } From 3d6f9b804fce3779a10ecdcdfeed46c75f9adef4 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 1 Jun 2007 02:48:36 +0000 Subject: [PATCH 22/30] buttons editing didnt let lib-obdata to changed once set (thanks for the report broken) NMesh (error in last commit). --- source/blender/python/api2_2x/NMesh.c | 4 ++-- source/blender/src/buttons_editing.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/source/blender/python/api2_2x/NMesh.c b/source/blender/python/api2_2x/NMesh.c index b0ab64a6249..3c7a15a537a 100644 --- a/source/blender/python/api2_2x/NMesh.c +++ b/source/blender/python/api2_2x/NMesh.c @@ -1303,7 +1303,7 @@ static PyObject *NMesh_getSelectedFaces( PyObject * self, PyObject * args ) totfaces= me->totface; if( flag ) { - for( i = 0; i < me->totface; i++ ) { + for( i = 0; i < totfaces; i++ ) { if( mf[i].flag & ME_FACE_SEL ) { pyval = PyInt_FromLong( i ); PyList_Append( l, pyval ); @@ -1311,7 +1311,7 @@ static PyObject *NMesh_getSelectedFaces( PyObject * self, PyObject * args ) } } } else { - for( i = 0; i < me->totface; i++ ) { + for( i = 0; i < totfaces; i++ ) { if( mf[i].flag & ME_FACE_SEL ) PyList_Append( l, PyList_GetItem( nm->faces, i ) ); } 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); From f0fe6833dbdf3742d0036a2ca545e91ba7cc5727 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 1 Jun 2007 05:54:16 +0000 Subject: [PATCH 23/30] when removing py_build value I removed this but shouldnt have, however theres no need to parse the value in Blender_Redraw since its done in the Window module. --- source/blender/python/api2_2x/Blender.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) 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 ); } /*****************************************************************************/ From 16f49532300630e3015a28c7f4b6874cb61ddb8c Mon Sep 17 00:00:00 2001 From: Jens Ole Wund Date: Fri, 1 Jun 2007 09:20:46 +0000 Subject: [PATCH 24/30] surface objects are allowed to be softbodies too --- source/blender/src/buttons_object.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index ed9b2043924..bb5ac2ba682 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -2468,6 +2468,7 @@ static int _can_softbodies_at_all(Object *ob) if ((ob->type==OB_MESH) || (ob->type==OB_CURVE) || (ob->type==OB_LATTICE) + || (ob->type==OB_SURF) ) return 1; // else deny return 0; From 84ec2711ace386284b7305ef345051d7572a8678 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 1 Jun 2007 10:38:17 +0000 Subject: [PATCH 25/30] == NLA Editor == When adding a new Action Strip to an Object which didn't have any Action Strips previously, NLA-override mode is turned on by default for that object (the Action/NLA-icon beside the expand/collapse triangle). --- source/blender/blenkernel/intern/nla.c | 5 ++++- source/blender/src/editnla.c | 6 ++++++ 2 files changed, 10 insertions(+), 1 deletion(-) 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/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); } From b726b64ead355e73f096510aeefd4d8c4408194f Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Fri, 1 Jun 2007 16:53:55 +0000 Subject: [PATCH 26/30] Fix error in the version patch for the SSS scene flag. --- source/blender/blenloader/intern/readfile.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 4bbcfab74ae..fd6b5837d15 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -6467,11 +6467,10 @@ 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) { for(sce= main->scene.first; sce; sce= sce->id.next) sce->r.mode |= R_SSS; - } - if(main->versionfile != 244 || main->subversionfile < 2) { + /* Copy over old per-level multires vertex data into a single vertex array in struct Multires */ Mesh *me; From 228e927c0450e2290ab980df2e2ad9303e528c58 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 2 Jun 2007 00:31:20 +0000 Subject: [PATCH 27/30] pointInside wasnt working properly (did work with the examples I was using with many small faces) --- source/blender/python/api2_2x/Mesh.c | 38 ++++++++-------------------- 1 file changed, 10 insertions(+), 28 deletions(-) diff --git a/source/blender/python/api2_2x/Mesh.c b/source/blender/python/api2_2x/Mesh.c index b64259553bf..15175c0beef 100644 --- a/source/blender/python/api2_2x/Mesh.c +++ b/source/blender/python/api2_2x/Mesh.c @@ -6922,45 +6922,27 @@ 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; From f579a66d7b731a61a1e45cb22b21373390b770ec Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 2 Jun 2007 02:02:33 +0000 Subject: [PATCH 28/30] made change to NMesh decrefing suggested by theeth, and added 2 more missing decrefs in new_NMFace --- source/blender/python/api2_2x/Mesh.c | 1 - source/blender/python/api2_2x/NMesh.c | 86 +++++++++++---------------- 2 files changed, 36 insertions(+), 51 deletions(-) diff --git a/source/blender/python/api2_2x/Mesh.c b/source/blender/python/api2_2x/Mesh.c index 15175c0beef..bd78900f625 100644 --- a/source/blender/python/api2_2x/Mesh.c +++ b/source/blender/python/api2_2x/Mesh.c @@ -6928,7 +6928,6 @@ static short pointInside_internal(float *vec, float *v1, float *v2, float *v3 ) { float z,w1,w2,w3,wtot; - /*min,max*/ if (!POINT_IN_TRI(vec, v1,v2,v3)) return 0; diff --git a/source/blender/python/api2_2x/NMesh.c b/source/blender/python/api2_2x/NMesh.c index 3c7a15a537a..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,42 +1271,30 @@ 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; - - MFace *mf; - int i; - PyObject *l = PyList_New( 0 ), *pyval; + int i, totfaces, flag = 0; + PyObject *l, *pyval; - /* dont allow returning more then the NMesh's number of faces */ - int totfaces = PySequence_Length(nm->faces); + if( !PyArg_ParseTuple( args, "|i", &flag ) ) + return EXPP_ReturnPyObjError( PyExc_ValueError, + "expected int argument (or nothing)" ); - if( me == NULL ) { - Py_DECREF(l); - return NULL; - } - mf = me->mface; - if( mf == NULL ) + l = PyList_New( 0 ); + if( me == NULL || me->mface == NULL) return l; - - if( !PyArg_ParseTuple( args, "|i", &flag ) ) { - Py_DECREF(l); - return NULL; - } /* make sure not to write more faces then we have */ - if (totfaces > me->totface) - totfaces= me->totface; + totfaces= MIN2(me->totface, PySequence_Length(nm->faces)); if( flag ) { for( i = 0; i < totfaces; i++ ) { - if( mf[i].flag & ME_FACE_SEL ) { + if( me->mface[i].flag & ME_FACE_SEL ) { pyval = PyInt_FromLong( i ); PyList_Append( l, pyval ); Py_DECREF(pyval); @@ -1312,7 +1302,7 @@ static PyObject *NMesh_getSelectedFaces( PyObject * self, PyObject * args ) } } else { for( i = 0; i < totfaces; i++ ) { - if( mf[i].flag & ME_FACE_SEL ) + if( me->mface[i].flag & ME_FACE_SEL ) PyList_Append( l, PyList_GetItem( nm->faces, i ) ); } } @@ -1322,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 ); } @@ -1586,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 ) @@ -1619,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 ) @@ -1672,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) */ @@ -2837,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) @@ -3203,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; } } @@ -3431,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) @@ -3536,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; } @@ -3589,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 ) @@ -3636,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 ) @@ -3685,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 ) @@ -3712,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 ) @@ -3748,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 ) @@ -3834,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 ) @@ -3920,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 ) @@ -4108,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 ) @@ -4201,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; } From aad39edee7dec4abed99967c2c2cd196f753cdf2 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sat, 2 Jun 2007 04:09:10 +0000 Subject: [PATCH 29/30] == Action Editor - IKEY == Modified behaviour of IKEY in Action Editor a bit, so that the keyframes added have been updated to reflect the current state of an object/bone. Previously, it only used the current values of the ipo-curves they were being keyframed (maintained as fallback method now). --- source/blender/src/editaction.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/source/blender/src/editaction.c b/source/blender/src/editaction.c index e9b0e43b410..1b0429abda2 100644 --- a/source/blender/src/editaction.c +++ b/source/blender/src/editaction.c @@ -2692,9 +2692,10 @@ void insertkey_action(void) { bAction *act; Key *key; + Object *ob= OBACT; IpoCurve *icu; short mode; - float cfra, val; + float cfra; /* get data */ act = G.saction->action; @@ -2713,8 +2714,10 @@ void insertkey_action(void) if (EDITABLE_ACHAN(achan)) { if (achan->ipo && (SEL_ACHAN(achan) || (mode == 1))) { for (icu= achan->ipo->curve.first; icu; icu=icu->next) { - val = icu->curval; - insert_vert_ipo(icu, cfra, val); + if (ob) + insertkey((ID *)ob, icu->blocktype, achan->name, NULL, icu->adrcode); + else + insert_vert_ipo(icu, cfra, icu->curval); } } @@ -2723,8 +2726,13 @@ void insertkey_action(void) if (EDITABLE_CONCHAN(conchan)) { if (conchan->ipo && (SEL_ACHAN(conchan) || (mode == 1))) { for (icu= conchan->ipo->curve.first; icu; icu=icu->next) { - val = icu->curval; - insert_vert_ipo(icu, cfra, val); + /* // 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); } } } @@ -2740,8 +2748,7 @@ void insertkey_action(void) if (key->ipo) { for (icu= key->ipo->curve.first; icu; icu=icu->next) { - val = icu->curval; - insert_vert_ipo(icu, cfra, val); + insert_vert_ipo(icu, cfra, icu->curval); } } } From c6158b9293d6c5ea15c323fea44138d3563d1a12 Mon Sep 17 00:00:00 2001 From: Johnny Matthews Date: Sat, 2 Jun 2007 13:46:16 +0000 Subject: [PATCH 30/30] Put declarations at the top of the block to save some compile problems. --- source/blender/blenloader/intern/readfile.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index fd6b5837d15..1b595b1e3fc 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -6468,12 +6468,13 @@ static void do_versions(FileData *fd, Library *lib, Main *main) Scene *sce; 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 */ - Mesh *me; + for(me = main->mesh.first; me; me=me->id.next) { if(me->mr) { MultiresLevel *lvl = me->mr->levels.last;