[Closed] Grabbing The Material Preview
Hey All,
I just wrote a new post detailing my method for capturing the preview from the material editor. I thought I’d share as it’s something I’ve wanted to do for years but have not been able to figure out until now. What it does is allow high-res thumbnails to be generated to file from the material editor window. It’s also disgustingly hacky, so avert your eyes if you are of a nervous scripting disposition. :surprised
I wrote it so that I can begin writing a shader database system for work, but since I wrote this part in my spare time, I can share it with you peeps. Hopefully it will be useful for any similar material based asset tracking scripts you might want to write.
I’ve got another slightly hacky way of doing it.
Install Kees’s Helium plugin, and you can use the function to get the shader ball as a bitmap value. It’s not quite as good as the real preview but it’s a lot less lines of code than yours
Wow, great! I don’t know why Autodesk doesn’t give access to this part directly. It would be really great to have the option to have our own material preview window inside our scripts/plugins…
Thank you!
Ha, that’s because someone else did the hard work for you, Dave
Good to know that helium can do this too though – thanks.
this will do it
//********************************************************************************************
// MtlPreviewToBitmap
def_visible_primitive(MtlPreviewToBitmap, "MtlPreviewToBitmap");
Value* MtlPreviewToBitmap_cf(Value** arg_list, int count)
{
check_arg_count(MtlPreviewToBitmap, 2, count);
MtlBase* mb = arg_list[0]->to_mtlbase();
int sz = arg_list[1]->to_int();
PStamp *ps = mb->CreatePStamp(sz,1);
if(ps)
{
int d = PSDIM(sz);
int scanw = ByteWidth(d);
int nb = scanw*d;
UBYTE *buf = new UBYTE[nb + sizeof(BITMAPINFOHEADER)];
if(!buf)
&undefined;
// get the image data
ps->GetImage(&buf[sizeof(BITMAPINFOHEADER)]);
// and create the header info
BITMAPINFOHEADER* bih = (BITMAPINFOHEADER*)buf;
bih->biSize = sizeof(BITMAPINFOHEADER);
bih->biWidth = d;
bih->biHeight = d;
bih->biPlanes = 1;
bih->biBitCount = 24;
bih->biCompression = BI_RGB;
bih->biSizeImage = 0;
Bitmap *map = TheManager->Create((PBITMAPINFO)buf);
delete [] buf;
if(map)
{
one_typed_value_local(MAXBitMap* mbm);
vl.mbm = new MAXBitMap();
vl.mbm->bi.CopyImageInfo(&map->Storage()->bi);
vl.mbm->bi.SetFirstFrame(0);
vl.mbm->bi.SetLastFrame(0);
vl.mbm->bi.SetName("");
vl.mbm->bi.SetDevice("");
if(vl.mbm->bi.Type() > BMM_TRUE_64)
vl.mbm->bi.SetType(BMM_TRUE_64);
vl.mbm->bm = map;
return_value(vl.mbm);
}
}
return &undefined;
}
sz = 0 -> 3232
sz = 1-> 8888
sz > 1 -> 24*24
display (MtlPreviewToBitmap (getMeditMaterial 1) 0)
edited to remove memcpy
Is it possible to do the other way around?
Meaning – sending in a custom bitmap as a ‘material preview’?
The reason why I ask is because in a exporter I’ve been working on for a long time has it’s own ‘preview tab’ in the material, which then shows the external rendered preview image.
It would be very nice to send that image back into the material slot directly instead.
The exporter calls on a external renderer, that’s why it works with the current setup – we render a preview scene externally, save to a file named the same as material, then when you open that material in the editor it just shows that image.
yes but I think it would need a custom mtl plugin which overides the mtlbase pstamp routines.
it might be possible without the use of a custom mtl, as the PStamp object has a setimage method.
very nice! could you post it on “useful mxs extensions” thread, please?
Thank you guys for sharing this.
@Pete:
There is a action that opens the preview (“Magnify”) window. Perhaps you may want to check it out and see if that could replace the double click hack?
actionMan.executeAction 2 "40296"
Can anyone verify if this works? I’ve tried this call in 2013, 2014 and 2015 and it returns false with no material window magnified.
I’d +1 for a SDK heads up if anyone was kind enough to do it.
Ack, my bad – its just a focus issue, you need to call MatEditor.Open() before you run the actionman item.
it’s a Material Editor action. it means the editor has to be in focus when you execute this action.
edited
oops. you already answered your question
Hi Chaps,
thanks for all your input.
Klunk – For those of us not clear about how to approach the SDK, is this method easily usable? My limit is that I’ve built an SDK maxscript extension before, is this a case of adding this and re-compiling? Many thanks for your solution
PolyTools3d – Thanks a million, anything to remove some of my hacky steps is awesome, I’ll change the code and update the article, I’m sure that will work much better.