Skip to content

Instantly share code, notes, and snippets.

@cecilemuller
Created January 3, 2019 14:35
Show Gist options
  • Save cecilemuller/057d5ccdcbe8964d9babc6b339986bf5 to your computer and use it in GitHub Desktop.
Save cecilemuller/057d5ccdcbe8964d9babc6b339986bf5 to your computer and use it in GitHub Desktop.
Maxscript: get the Material Editor thumbnail for an arbitrary material
-- Reads the 88x88 thumbnail from Material Editor for an arbitrary material.
-- Note that it renders faster when the material editor is closed,
-- so you could call `MatEditor.Close()` first.
--
-- Parameters:
-- mat: a material instance (StandardMaterial, Universal_Material, etc..)
--
-- Returns:
-- a Bitmap or `undefined`
--
fn getMaterialThumbnail mat = (
local thumb = undefined
local iGlobal = (dotnetClass "Autodesk.Max.GlobalInterface").Instance
if iGlobal != undefined then (
local IntPtr = dotnetClass "System.IntPtr"
local pStampSize = (dotnetclass "Autodesk.Max.PostageStampSize").Large
local backupMat = meditMaterials[1]
meditMaterials[1] = mat
local matRef = iGlobal.CoreInterface.GetMtlSlot 0
local pStamp = matRef.CreatePStamp pStampSize true
local bytes = pStamp.Image
local size = pStamp.Width
thumb = bitmap size size gamma:0.5
local step = size * 3
for y = 1 to bytes.count by step do (
local row = for x = y to (y + step - 1) by 3 collect [bytes[x + 2], bytes[x + 1], bytes[x]]
setpixels thumb [0, size -= 1] row
)
pStamp.Dispose()
matRef.Dispose()
meditMaterials[1] = backupMat
)
return thumb
)
@RafalZera
Copy link

That's actually great, works flawlessly. Seems that by using dotnet you can do anything in max. Maybe it's time to grasp the basics.

@theacb
Copy link

theacb commented Nov 28, 2023

I converted this to python, if that is useful to anyone.

import pymxs

rt = pymxs.runtime

def get_material_thumbnail(mat):
    """
    Reads the 88x88 thumbnail from Material Editor for an arbitrary material.
    Note that it renders faster when the material editor is closed,
    so you could call `rt.MatEditor.Close()` first.

    Originally written (in Maxscript) by Cecile Muller
    https://github.com/cecilemuller

    :param mat: a material instance (StandardMaterial, Universal_Material, etc..)
    :return: a Bitmap or None
    """
    thumb = None
    iGlobal = (rt.dotnetClass("Autodesk.Max.GlobalInterface")).Instance

    if iGlobal is not None:
        pStampSize = (rt.dotnetclass("Autodesk.Max.PostageStampSize")).Large

        backupMat = rt.meditMaterials[0]
        rt.meditMaterials[0] = mat
        matRef = iGlobal.CoreInterface.GetMtlSlot(0)

        pStamp = matRef.CreatePStamp(pStampSize, True)
        i_dat = pStamp.Image
        size = pStamp.Width
        thumb = rt.bitmap(size, size, gamma=0.5)

        step = size * 3

        row_ind = size - 1
        for y in range(0, i_dat.count, step):
            row = []
            for x in range(y, y + step - 1, 3):
                row.append(rt.color(i_dat[x + 2], i_dat[x + 1], i_dat[x]))
            rt.setpixels(thumb, rt.point2(0, row_ind), row)
            row_ind -= 1

        pStamp.Dispose()
        matRef.Dispose()
        rt.meditMaterials[0] = backupMat

    return thumb

@andriypogribniy
Copy link

andriypogribniy commented Jun 23, 2024

Any way to generate larger bitmaps?
88x88 is kind of useless

@theacb
Copy link

theacb commented Jun 23, 2024

No, 88x88 is a hard limit imposed by this interface. Most people seem to instead set up background rendering in this situation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment