Blender Python Script to combine materials with the same diffuse texture map and the same diffuse color
for all the selected objects
This was done very quickly and may be improved in the future
namely the "signature" of each material needs to include things like opacity
if bad luck has it, all your skin materials may be replaced by the one skin material which happens to be fully transparent
In Blender, following the Import of an .obj file
change one of the Blender panels to a Text Editor
do a Text / Load Text
load mcjMergeSelectedObjectsMats
select objects in the scenes for which you want materials to be combined
click in the Run Script button
Grosso modo
first it collects all the materials for the selected objects
then
for each material in that list, ( which we will call the reference mat )
for each object,
for each material slot
if that slot has the same diffuse texture and the same diffuse color as the reference mat
it makes this material slot share the reference material
note that this is based on the premise that the diffuse_color texture map is prefixed with “kd”
which is the case for objects imported from .obj files
one nice feature is that it should work for non-node-based materials too ( blender internal etc )
when i select Aiko3, most of the skin materials were made to share the ‘SkinHands’ material
import bpy
materials = []
#---------- getMap ----------
def getMap( mat, key, keydot ):
texSlots = mat.texture_slots
for t in texSlots:
if t:
if ( t.name == key ) or ( t.name.startswith(keydot) ):
return( t.texture )
return 0
#---------- getImage ----------
def getMaterialUID( mat ):
KdMap = getMap( mat, 'Kd', 'Kd.' )
im = 0;
if KdMap:
im = KdMap.image.filepath
return( [im, mat.diffuse_color] )
#---------- getMap ----------
def swapDuplicates( refmat, slots, refUID ):
for slot in slots:
myUID = getMaterialUID( slot.material )
if ( myUID[0] == refUID[0] ):
if ( myUID[1] == refUID[1] ):
slot.material = refmat
#---------- mergeSelectedObjectsMats ----------
def collectMats( o ):
for slot in o.material_slots:
materials.append( slot.material )
#---------- mergeSelectedObjectsMats ----------
def mergeSelectedObjectsMats( o ):
slots = []
for slot in o.material_slots:
slots.append( slot )
for mat in materials:
myUID = getMaterialUID( mat )
swapDuplicates( mat, slots, myUID )
objects = bpy.context.selected_objects
for obj in objects:
collectMats( obj )
for obj in objects:
mergeSelectedObjectsMats( obj )
by mCasual/Jacques
You can use this software freely for personal or commercial use.
You may not resell, sub-license or rent this software in any way.
You may credit this software to mCasual/Jacques
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.