Home Technical Talk

misc. maxscript UV scripts/tools

13456714
sublime tool
Offline / Send Message
renderhjs sublime tool
this thread has become bloody big :D

What it is all about?

A plugin or script collection if you will that boosts the 3dsmax tasks of UV Unwrapping and Texture related stuff. This includes handy align, relax and transformation tools for UV editing but also nifty single button scripts for baking AO, Lighttracer maps or blockout maps directly to your clipboard.
All of that super easy to install (just drag the download file into the max viewport),- and if you are interested in the scripting part or contribution you can look into the code as well.

TexTools_2.90_splash.jpg

For a full overview head over to:
http://www.renderhjs.net/textools
it has lots of GIF animations of each tool explaining them without the need of much text- though some of the text might explain some more background info for each tool. Here is a excerpt of some of the things you can do:

texTools_ani_transform_align.giftexTools_ani_mirror.gif
texTools_ani_swapuvw.giftexTools_ani_iron.gif
texTools_ani_texel_pick.giftexTools_ani_transform_basic.gif

and here is the original first message:

just a thread to dumb my UV-related scripts into, some of these scripts will be eventually ported in a GUI so they are more in a usefull collection.

some of my goals:
- should run in max9+
- no xtra plugins required
- reduce tasks that are usually required


1.) render UV- template to clipboard
(does not require the avg_dlx.dlx extention!!! nor any other third party xtra plugin)
render_uv2clipboard.gif
lets you render a UV-template directly into the windows clipboard so you can paste it directly into photoshop. Nor Framebuffer is displayed,- you dont even need to open the UV-editor- it requires though a UV-unwrap modifier.
--render uv to clipboard
_size = 512;
$.modifiers[#unwrap_uvw].renderuv_width =  _size;
$.modifiers[#unwrap_uvw].renderuv_height = _size;
$.modifiers[#unwrap_uvw].renderuv_fillmode = 0;--solid
$.modifiers[#unwrap_uvw].renderuv_seamColor = color 255 255 255;
$.modifiers[#unwrap_uvw].renderuv_showframebuffer = false;

clipboardClass = dotNetClass "System.Windows.Forms.Clipboard" --create a Clipboard dotNetClass

theFileName = GetDir #image + "_renderToClipboard.bmp" --define a temp.file name
$.modifiers[#unwrap_uvw].unwrap5.renderUV theFileName;--save UV layout to the temp folder

theImage = dotNetClass "System.Drawing.Image" --create an Image dotNetClass
theBitmap = theImage.FromFile theFileName --get the saved image from file as bitmap
clipboardClass.setImage theBitmap --copy the image to clipboard
theBitmap.Dispose() --release the bitmap 
deleteFile theFileName --delete the temp. file
clipboardClass.ContainsImage() --return true if the clipboard contains image

$.modifiers[#unwrap_uvw].renderuv_showframebuffer = true;--reset defaults
at first I found this great thread:
http://forums.cgsociety.org/showthread.php?t=677106
but its to much of a hassle and it requires some extra steps like photopshop scripts to be manually activated. With my script now all I need to do in photoshop once pasted is to select either a color range or use the magic wad or invert and set the layer mode to multiply.
Used this reference for the setClipboard part:
http://www.scriptspot.com/bobo/mxs9/dotNet/UsingTheClipboard.html


comming next is a align tool that aligns vertex UV`s on a real line and not like all the lazy scripts out there only horizontal or vertical. A angle snap determinces if they should be aligned vertical or horizontal e.g if all the points in a line are +- 5° apart from 90°. It should help up aligning verts from the faces of block type objects.

Replies

  • renderhjs
    Options
    Offline / Send Message
    renderhjs sublime tool
    I have some good progress on my vertice align script

    it works like this, you select your verts and hit the script, it automaticly detects the flow and will align the verts between the 2 end points on that line.
    example usage:
    align_verts_script_01.gif
    or
    align_verts_script_02.gif
    what I still plan is a angle snap value (e.g within 2° or 5°) where it detects to snap to either 45° angles or most common 90° angles which would be the same as the rest of the scripts that can only snap vertical or horizontal.

    this is how it works:
    align_verts_script_03.gif

    draft script (requires a uv-unwrap modifier a opened UV-editor + at least 3 selected UV-verts
    --uv-align script draft
    function align_uv_verts =(
    	_uvBase = $.modifiers[#unwrap_uvw];
    	_uv1 = $.modifiers[#unwrap_uvw].unwrap;
    	_uv5 = $.modifiers[#unwrap_uvw].unwrap5;
    	
    	_array = _uv1.getSelectedVertices();
    	_selection = #();--new array
    	_maxX;_maxY;_minX;_minY;
    	
    	_nr=1;
    	for i in _array do (
    		local _pt = _uvBase.getVertexPosition 1 i;
    		
    		if (_nr > 1) then(
    			local _pt2 = _uvBase.getVertexPosition 1 _maxX;
    			if (_pt.x > _pt2.x)then(
    				_maxX = i;
    			)
    			_pt2 = _uvBase.getVertexPosition 1 _minX;
    			if (_pt.x < _pt2.x)then(
    				_minX = i;
    			)
    			
    			_pt2 = _uvBase.getVertexPosition 1 _maxY;
    			if (_pt.y > _pt2.y)then(
    				_maxY = i;
    			)
    			_pt2 = _uvBase.getVertexPosition 1 _minY;
    			if (_pt.y < _pt2.y)then(
    				_minY = i;
    			)
    		)else(
    			_maxX = i;
    			_maxY = i;
    			_minX = i;
    			_minY = i;
    		)
    		_selection[_nr] = i;
    		_nr+=1;
    	)
    
    	--determine if horizontal or vertical flow
    	local _a = _uvBase.getVertexPosition 1 _minX;
    	local _b = _uvBase.getVertexPosition 1 _maxX;
    	local _w = (_b.x - _a.x);
    	_a = _uvBase.getVertexPosition 1 _minY;
    	_b = _uvBase.getVertexPosition 1 _maxY;
    	local _h = (_b.y - _a.y);
    	
    	local A=1;
    	local B=1;
    
    	_sel = #{};
    	if (_w > _h )then(
    		A = _minX;
    		B = _maxX;
    	)else(
    		A = _minY;
    		B = _maxY;
    	)
    	_sel = #{};
    	_sel[A] = true;
    	_sel[B] = true;
    	_uv1.selectVertices _sel;
    
    	
    	if (_selection.count > 2)then(
    		local ptA = _uvBase.getVertexPosition 1 A;
    		local ptB = _uvBase.getVertexPosition 1 B;
    
    		for i = 1 to _selection.count do(
    			if (_selection[i] != A and _selection[i] != B)then(
    				local _pt = _uvBase.getVertexPosition 1 _selection[i];
    				
    				if(_w > _h )then(
    					local _m = (ptB.y - ptA.y) / (ptB.x - ptA.x);
    					local _x = _pt.x - ptA.x;
    					_pt.y = _x * _m + ptA.y; 
    				)else(
    					local _m = (ptB.x - ptA.x) / (ptB.y - ptA.y);
    					local _y = _pt.y - ptA.y;
    					_pt.x = _y * _m + ptA.x; 
    				)
    				_uvBase.SetVertexPosition 1 _selection[i] _pt;
    			)
    		)
    	)else(
    		print("select at least 3 vertecies!");
    	)
    )
    align_uv_verts();
    
  • Yozora
    Options
    Offline / Send Message
    Yozora polycounter lvl 11
    problem with the first one is its restricted to one resolution only unless you make a macro for each resolution you use.

    2nd one looks interesting but I dont see that much use diagonally aligning things, at least I've never personally felt the need to do it for any reason

    but thanks for sharing, I'll keep an eye on this thread!
  • renderhjs
    Options
    Offline / Send Message
    renderhjs sublime tool
    Yozora:
    1st one will most likely end up in a rollout dialogue with a dropdown menu and or input text box.
    Alternativly one could predict the size for example based on the associated material and its difuse texture bitmap size - if one is applied. Or the units of the 3d poly and some math guessing the size where 1 max units in 3d space is 1 pixel or something like that. Or... a popup window appears asking you to verify the resolution - that should be possible with a macroscript

    2nd script:
    One main Idea was not to align vertecies diagonally but foremost having just ONE simple button that alligns things for you- like a smart button that detects automaticly if things should be aligned horizontal, vertical diagonal or snapped to the border. Depending on the vertex positions it will the automaticly determine the smartest move. To me its bothersome having 2 buttons to align horizontal and vertical,- it might be even the case that I want to align in 45°.

    as for further ideas:
    I am thinking of a distribute scripts that works similar to the align script as it ditributes evenly along a line in any direction- or perhaps ease to a line.

    Another script I have in mind is to auto-rotate shells based on their z-axis flow or topXY alignment. I find myself often finding the right edges in the 3d view in order to know how to rotate certain islands and faces because I prefer not having flipped UV-layouts- or weired rotated ones. I think the easiest approach will be by selecting 1 edge and letting the script gess if its a side, bottom or top side on the 3d model and align the UV- shells occordingly.

    yet another idea is to smart rotate shells because often my shells are +- 0.05 ° rotated and not perfectly aligned to the axis. This script should analyze the vert points and snap to the most matching 90° related vertexes. If it would go well it would simply align the rototation to the base axis in the UV view in the most suited manner.

    another one:
    render only selected faces/shells with a random block/face color to the clipboard. That way I could faster block out a mesh by its base elements. And quickly paste it in my existing photoshop texture.
  • Rob Galanakis
    Options
    Offline / Send Message
    renderhjs wrote: »
    some of my goals:
    - should run in max9+
    - no xtra plugins required
    - reduce tasks that are usually required

    I have to say your second goal is foolish. If you can leverage something, such as avg, or libraries you find on the net, you should, without a doubt. Otherwise you are duplicating code by writing it yourself, or copying and pasting (I'm not sure which is worse).

    One of the greatest obstacles of tech art development is that there is no mentality or infrastructure for good tool distribution. Developers and scripters are both to blame- the first for not creating any good frameworks or systems in their programs, the second for not fostering a collaborative mentality even when there are some available.

    Real programmers have long known the benefit of modular, reusable code, between individuals and companies both. One of the great benefits of .NET has been the utterly successful ability to share classes between users and languages, via things such as codeproject.

    I'd urge you, and everyone else, to reconsider "no extra things required" as something good, and instead considering "leveraging other code but distributing it in a sensible way".

    If you write your scripts in such a way as they are modular and reusable, I'm sure many, many people will have good use for your code and put it to many other tools and applications inside Max.
  • Funky Bunnies
    Options
    Offline / Send Message
    Funky Bunnies polycounter lvl 17
    these look awesome, renderhjs. I'm looking forward to your progression

    that's definitely true Rob, and I think in actual production where you have a little more control over who's using it that's stellar - but the majority of users for these free scripts probably don't know enough about it to put everything into place correctly.
    So for them, the fewer pieces they have to worry about the better.

    over all we'd probably be able to create way superior stuff, but that runs the risk of leaving some people behind - the people who know the least about the technical aspects. I think that'd be unfair because that might be the group that relies on them most.
    But I'm teh noobzorz, so I don't mind being told I'm wrong. :poly142:

    the community scripts project you guys have been working towards sounds wonderous, btw :D
  • Yozora
    Options
    Offline / Send Message
    Yozora polycounter lvl 11
    ah if this can combine vertical and horizontal aligning into 1 button then it is indeed very useful!

    I just tried it and I cant undo/redo once I've used it.... which pretty much makes it useless for now :/
  • Michael Knubben
    Options
    Offline / Send Message
    One thing I've been looking for is a script that takes an edge (or selection of verts) and rotates the entire uv-island so that this edge/selection is alligned flat on the horizontal or vertical axis. Does anyone know if that's possible?
  • renderhjs
    Options
    Offline / Send Message
    renderhjs sublime tool
    Rob Galanakis: my simple reason for that is that I have plenty of computers here on the University on which I am not allowed to copy any data in the 3dsmax directory.
    The other reason is that I can go anytime with those xtras but:
    - what happens if those plugins are not updated for a newer max relese?
    - what if the download url should vanish
    - what if autodesk no longer supports parts of it
    ...
    surely someone like you is in a different position,- maybe I need to discover more advantages of others classes for now Id rather avoid them if possible.
  • dejawolf
    Options
    Offline / Send Message
    dejawolf polycounter lvl 18
    ghostpainter bitches.
    selected UVs straight into photoshop with 1 key press of F2.
    its expensive though, especially since the only function i actually use is the send UVs into photoshop part, and select marked polygons in photoshop. plus its vector UVs.
  • MoP
    Options
    Offline / Send Message
    MoP polycounter lvl 18
    btw something awesome i found out (and I think Per mentioned this too a while back) is that if you're using maxscript to physically set the position of a UV vertex, you will not get any undo info on that.
    The only way I found to make it correctly behave with undo is put a relative move of 0,0,0 in before the actual setVertexPosition. Then the undo clause worked correctly.

    Good idea to put the functionality for aligning all into one button.

    I might take this idea for my UV Line Relax script so that it falls back to default align behaviour if it doesn't find a contiguous line to relax along.
  • MoP
    Options
    Offline / Send Message
    MoP polycounter lvl 18
    Here's what I had to hack in to get it working:
            undo "Align V" on (
                uv.unwrap2.MoveSelected [0.0,0.0,0.0]
                uv.moveY mid
            )
    
    Where "mid" is the averaged value calculated from the selected verts' Y positions. If you try this undo clause without the MoveSelected command, Undo does nothing. Stupid Max.

    You probably don't need the ".unwrap2" in there, I think you can just point it to your unwrap modifier object (in this case mine's called "uv" ).
  • MoP
    Options
    Offline / Send Message
    MoP polycounter lvl 18
    Ouch heh, yeah that does something horrible... when I tried it stitching one selected vertex, on undo it created an extra floating UV at the original position but kept the face stitched... no idea what's going on there!
  • Rob Galanakis
    Options
    Offline / Send Message
    that's definitely true Rob, and I think in actual production where you have a little more control over who's using it that's stellar - but the majority of users for these free scripts probably don't know enough about it to put everything into place correctly.
    So for them, the fewer pieces they have to worry about the better.
    Yes but you are missing the point about framework and infrastructure. Good collaborative/sharing or distribution mechanisms do not exist. As long as you think there is no need for them they will not exist- this is an issue of us having to take the initiative. No one is going to build something there is no use for, and no one is going to support and improve it if it isn't used. If you are a scripter, you need to demand a collaborative and distribution infrastructure and help incubate what people are doing. These systems, when developed correctly, are only beneficial for the user.

    It is very inconvenient to have to install a bunch of extra stuff to run a program. But few programs develop everything themselves, they have external libraries they depend on. The difference is, they are better about how they are distributed and they understand the need for them. We haven't figured out a distribution mechanism (part of this is because how our shitty scripting languages and programs work), but much of it, and what we can change, is the part about understanding the need for them. Once we understand and demand the need, we can develop the systems- and once the systems are developed it will be trivial/assumed/usual to distribute external code as part of a tool or app.
    renderhjs wrote:
    my simple reason for that is that I have plenty of computers here on the University on which I am not allowed to copy any data in the 3dsmax directory.
    So what? That is an issue with how you are installing scripts, nothing more.
    The other reason is that I can go anytime with those xtras but:
    - what happens if those plugins are not updated for a newer max relese?
    Feel free to recompile them if they are plugins or rewrite them if they are scripts. But it is always better and faster to refactor someone else's working code than it is to write that code from scratch (and if you think it isn't always faster- unless the code is real shite which you shouldn't be using in the first place- then you haven't been developing enough, because it unequivocally and 100% is).
    - what if the download url should vanish
    You are distributing the needed stuff with your script.
    - what if autodesk no longer supports parts of it
    See response to your second point.
    surely someone like you is in a different position,- maybe I need to discover more advantages of others classes for now Id rather avoid them if possible.
    No I'm not in a different position, at all. I have a different perspective and I probably need to explain better, but my position is the same.

    So I have this program, called 'ProgramX' that installs to 'C:\\Program Files\\ProgramX\\'. Inside I have something like 'ProgramX.exe', 'dx9.dll', 'openal.dll', 'Ionic.Zip.Utils.dll', 'DesktopDecorator.dll'. Each of these dll's are essentially someone else's code you are using.
    dx9.dll- You are using DirectX, which is an API (key word is 'interface')
    openal.dll- A sound library, instead of having to write all your sound stuff in C++, you can just call stuff from openal, it is also an API.
    Ionic.Zip.Utils.dll and DesktopDecorator.dll- These are two C# classes. The first is for dealing with zip files, the second is for changing wallpaper.

    You could, of course, write all of this stuff from scratch (assuming you had the requisite skills). But programmers don't, why? Because they have a rich library of available, good (sometimes not so good, in the case of the last dll) code they can reuse. That they don't have to update. That they don't have to maintain. But they still have the ability to extend classes and fix bugs (this is one of the infrastructure issues in our scripting languages we cannot do easily right now).

    So for example I'll take chuggnut's functionally-excellent but structurally-shit UV plugin (I dont' blame him, this was made years ago when this sort of scripting was the norm and pretty usual). Great, it works, end of story, right? No. Because if the tool were written in a sensible way, the user experience wouldn't be the end of the story. Other devs would be able to take the methods and utilities chuggnut wrote and do tons of other things with them. They'd also be much better able to expand/replace/enhance functionality within the tool itself.

    You should be able to use an existing script library, expand it, and others should be able to take yours (depending on license, of course, which if anything but open-source is selfish) and expand and distribute it. To the user, they are just downloading and installing stuff as usual. The problem is with few people writing extensible scripts and libraries, and fewer people participating in the discussion about how to best distribute and what systems are needed, there are still substantial issues to be solved. But simply giving up is no way to behave, as there is a solution there if we discuss and collaborate and we all acknowledge the end result will be exponentially better than what we put in (which is the entire idea behind developing tools, isn't it?).

    There was something else I wanted to say but my brother called and I can't catch my train of thought a half hour later. I hope that explains my perspective more clearly.
  • zOffTy
    Options
    Offline / Send Message
    zOffTy polycounter lvl 16
    I used your renderUV script and mixed with one of mine.
    Now the script count black pixel on the uv map, and drop a percentage of "wast uv space" depending on the wanted size of the map.
    result just below

    my code is perhaps not very optimised, but its working well on editpoly object

    just select an editObj and run the script :)
    (
    rollout SizeMapDialog "Map Size"
    (
    	editText sixze "X :" pos:[15,24] width:88 height:20
    	editText siyze "Y :" pos:[110,24] width:88 height:20
    	button btnok "OK" pos:[218,24] width:50 height:20
    	groupBox grp1 "Size Map" pos:[8,5] width:280 height:51
    		
    	on btnok pressed do
    	(
    		destroyDialog SizeMapDialog
    		st = timestamp()
    		a = 0
    		pxBlack = 0
    		stat = 0
    		modPanel.addModToSelection (Unwrap_UVW ()) ui:on
    	--------------------------	
    	$.modifiers[#unwrap_uvw].renderuv_width =  sixze.text as integer;
    	$.modifiers[#unwrap_uvw].renderuv_height = siyze.text as integer;
    	$.modifiers[#unwrap_uvw].renderuv_fillmode = 1;--solid
    	$.modifiers[#unwrap_uvw].renderuv_seamColor = color 255 255 255;
    	$.modifiers[#unwrap_uvw].renderuv_showframebuffer = false;
    
    	boularaw = GetDir #image + "_renderTlibad.bmp" --define a temp.file name
    	$.modifiers[#unwrap_uvw].unwrap5.renderUV boularaw;--save UV layout to the temp folder
    	$.modifiers[#unwrap_uvw].renderuv_showframebuffer = true;--reset defaults		
    	---------------------------
    		boula= openBitmap(boularaw as string)
    		progressstart "Are you a good UV mapper??..."
    			oldEscapeEnable = escapeEnable
    			escapeEnable = true	
    			print coin2
    			for y = 1 to boula.height do
    			(
    				progressupdate (100.0 * y / boula.height)
    				g = getpixels boula [0,y-1] boula.width
    				for x = 1 to boula.width do
    			(
    				
    			if g[x] ==  (color 0 0 0) do (pxBlack +=1)
    		)
    	)
    	et = timestamp()
    	progressend ()
    	escapeEnable = oldEscapeEnable
    
    	pxBlack
    	d = boula.width * boula.height
    	stat =int ((pxBlack/d as float) *100)
    	if stat < 10 then
    	(
    		messageBox ("You are an UV Killer!! Only " + (stat as string) + " %" + " of free space!") 
    	)
    	else
    	(
    		messageBox ("You have " + (stat as string) + " %" + " of free space! Woot!") 
    	)
    -------------------------------------------------------
    $.modifiers[#unwrap_uvw].renderuv_width =  sixze.text as integer;
    $.modifiers[#unwrap_uvw].renderuv_height = siyze.text as integer;
    $.modifiers[#unwrap_uvw].renderuv_fillmode = 0;--solid
    $.modifiers[#unwrap_uvw].renderuv_seamColor = color 255 255 255;
    $.modifiers[#unwrap_uvw].renderuv_showframebuffer = false;
    
    clipboardClass = dotNetClass "System.Windows.Forms.Clipboard" --create a Clipboard dotNetClass
    
    theFileName = GetDir #image + "_renderToClipboard.png" --define a temp.file name
    $.modifiers[#unwrap_uvw].unwrap5.renderUV theFileName;--save UV layout to the temp folder
    
    theImage = dotNetClass "System.Drawing.Image" --create an Image dotNetClass
    theBitmap = theImage.FromFile theFileName --get the saved image from file as bitmap
    clipboardClass.setImage theBitmap --copy the image to clipboard
    theBitmap.Dispose() --release the bitmap 
    deleteFile theFileName --delete the temp. file
    clipboardClass.ContainsImage() --return true if the clipboard contains image
    
    $.modifiers[#unwrap_uvw].renderuv_showframebuffer = true;--reset defaults	
    print "UV copy to clipboard OK"
    -------------------------------------------------------	
    )
    )
    createDialog SizeMapDialog width:296 height:64
    )
    

    Maybe it's completely useless, but it was a challenge for me :\


    I saw too, on your post, that you want to make a uv face selection 3ds==>photoshop?
    like this?
    http://www.zortech.de/uv2psScript.xhtml
    I find that very useful

    hope you like it :)
  • renderhjs
    Options
    Offline / Send Message
    renderhjs sublime tool
    @zOffTy
    I got this error in max9
    Surface Area 300829.781250 bounds area 329609.718750  per used 0.912685
    Edge Height 1541.482056 Edge Width 1286.267456
    Initial Clusters 6 finalClusters 6
    undefined
    -- Error occurred in ü8LT¸&#732;à
    --  Frame:
    >> MAXScript Rollout Handler Exception: -- Unknown system exception <<
    
    I saw too, on your post, that you want to make a uv face selection 3ds==>photoshop?
    like this?
    http://www.zortech.de/uv2psScript.xhtml
    I find that very useful
    thats propably the result from that thread- I just dont like the PS script part. But its a nice script to learn from.
  • zOffTy
    Options
    Offline / Send Message
    zOffTy polycounter lvl 16
    on max 11 it's works well.
    but on max 9 sp1 I sometimes have the same error
    I'll try to see where the problem may come


    is copy to clipboard limited in size?
    a 1024x1024 works well, but not 2048x2048?!
  • Mark Dygert
    Options
    Offline / Send Message
    MoP wrote: »
    btw something awesome i found out (and I think Per mentioned this too a while back) is that if you're using maxscript to physically set the position of a UV vertex, you will not get any undo info on that.
    The only way I found to make it correctly behave with undo is put a relative move of 0,0,0 in before the actual setVertexPosition. Then the undo clause worked correctly.

    Good idea to put the functionality for aligning all into one button.

    I might take this idea for my UV Line Relax script so that it falls back to default align behaviour if it doesn't find a contiguous line to relax along.
    son of a b!tch... that had me stumped on a vert/edge flatten script I was working on. Drove me batty until now. Thanks a bunch I might actually have something usable, that mimics all the other 19 UV vert flatten scripts already floating around. But consider it was a learning experience, I learned a lot. Thanks for helping me make it usable!

    Renderhjs, you have some sweet stuff going, don't stop!
  • renderhjs
    Options
    Offline / Send Message
    renderhjs sublime tool
    got another script :D

    render ambient occlusion map to clipboard

    render_ao_script.jpg
    you will see a render progress bar so you know when max is done rendering the map and when its in your clipboard - but you dont see the framebuffer or renderwindow.

    still prototype but here is the code:
    fn bake_AO_2_clipboard _size _quality=
    (
    	tex_size = _size;
    	obj = selection[1];
    	obj.removeAllBakeElements();
    
    	ao_bake = AmbientOcclusionBakeElement();	
    	ao_bake.outputSzX    =    tex_size;
    	ao_bake.outputSzY    =    tex_size;
    	ao_bake.autoSzOn              = false;
    	ao_bake.bright                      = color 255 255 255 0;
    	ao_bake.dark                      = color 0 0 0 0;
    	ao_bake.backgroundColor		= color 0 0 0 0;
    	ao_bake.elementName          = "Ambient Occlusion";
    	ao_bake.falloff                      = 1.0;
    	ao_bake.maxDistance          = 0.0 ;
    	ao_bake.samples                  = 2+_quality*120;--16
    	ao_bake.spread                  = 40.1 - _quality*40;--0.8
    	ao_bake.enabled                  = true;
    	ao_bake.fileType = GetDir #image + "_renderToClipboard3.bmp";--appearently the target filename/path
    	
    	-- Baking job
    	bake = obj.INodeBakeProperties;
    	bake.bakeChannel = 1;
    	bake.nDilations         = 2; -- (Pading)
    	bake.flags             = 1; --bit 1 of flag will be set to signify map channel conflict
    	bake.bakeEnabled     = true;
    	bake.addBakeElement ao_bake;
    	--select obj
    	render rendertype:#bakeSelected outputwidth:tex_size outputheight:tex_size vfb:false;
    
    	--copy to clipoard and delete temp image
    	theFileName = ao_bake.fileType --define a temp.file name
    	clipboardClass = dotNetClass "System.Windows.Forms.Clipboard" --create a Clipboard dotNetClass
    	theImage = dotNetClass "System.Drawing.Image" --create an Image dotNetClass
    	theBitmap = theImage.FromFile theFileName --get the saved image from file as bitmap
    	clipboardClass.setImage theBitmap --copy the image to clipboard
    	theBitmap.Dispose() --release the bitmap 
    	deleteFile theFileName --delete the temp. file
    	clipboardClass.ContainsImage() --return true if the clipboard contains image
    	
    	--remove traces
    	bake.removeAllBakeElements();
    	bake.bakeEnabled = false;
    	obj.removeAllBakeElements();
    )
    bake_AO_2_clipboard 320 0.8;
    
    I am still figuring out how to use as less parameters as possible to reduce complexity in the interface or usage. But in the end it might end up with textureSize², samples/qulity, spread/softness

    the next thing I started roughly is a GUI for all these scripts (texture/UV stuff) though I plan designing most functions in a way so that they can used as well on keys and single buttons - so that they can survive as well without parameters somehow

    texturing_gui_start.jpg
  • renderhjs
    Options
    Offline / Send Message
    renderhjs sublime tool
    bigger update:

    polycount_uv_scripts_verts_gui1.gif

    I crossed the buttons that have no functions yet - those are planned atm. but not yet added. Be carefull though as open UV-editor overwrites color settings of your UV-editor such as background color and edge color. I have not yet tried it on other computers here but those should be the only settings that change things in your uv-unwrap editor in case you might edit your UV`s the regular way.

    script as download (source view at the bottom)
    http://www.renderhjs.net/bbs/polycount/texture_maxscript_tools/renderhjs_texture_tools_05.ms


    more in detail:

    the vertex align script:
    polycount_uv_scripts_verts_align1.gif
    changes:
    - can handle face or edge selections as well
    - spinner for the snap angle that defines within what 90° offset angle it should snap to the axis.

    align edge-shell to axis
    polycount_uv_scripts_edge_align1.gifpolycount_uv_scripts_edge_align2.gif
    features:
    - detects automaticly the closest axis to the edge slected
    - aligns the associated shell around the center of the selected edge
    - align shells to each other based on a edge- pair (similar to Modo or uvLayout)


    future ideas:

    - align face selection to 3d space equivalent orientation. Often when automatic unwrapping shells get rotated or flipped in the wrong direction - I want to get rid of that.
    - render selected faces to quicker block out textures in photoshop (inking base shapes of certain model shapes)
    - render convex/concave map (convexity map) based on vertex color script I found. This will be a alternative dirt map. maybe some material stuff with difuse-RTT output might be another nice idea, or a difuse-RTT of a falloff map with world-z direction (dust map).


    script code (in case my url gets offline or you want to dig specific code)
    fl_textureHelper;
    rl_textureMain;
    
    fn pack_uv _space = (
    	if classof (modPanel.getCurrentObject()) == Unwrap_UVW then(
    		selection[1].modifiers[1].unwrap2.pack 0 _space false false false;
    	)
    )
    
    fn open_uv_editor = (
    	try(
    		disableSceneRedraw()
    		
    		modPanel.addModToSelection (Unwrap_UVW ()) ui:on
    		
    		$.modifiers[#unwrap_uvw].unwrap5.setShowMapSeams off
    		$.modifiers[#unwrap_uvw].unwrap5.setPeltAlwaysShowSeams off
    		
    		subobjectLevel = 3;
    		modPanel.setCurrentObject $.modifiers[#Unwrap_UVW]
    		
    		$.modifiers[#unwrap_uvw].unwrap2.setFreeFormMode on
    		$.modifiers[#unwrap_uvw].unwrap.edit ()
    		
    		subobjectLevel = 3
    		$.modifiers[#unwrap_uvw].unwrap.DisplayMap off
    		$.modifiers[#unwrap_uvw].unwrap.edit ()-- to maximize
    		$.modifiers[#unwrap_uvw].unwrap.edit ()-- to maximize
    		
    		$.unwrap_uvw.unwrap2.setGeomSelectElementMode(true); -- select viewport 
    		--$.unwrap_uvw.unwrap2.setTVElementMode(true);--select element UV view
    		$.unwrap_uvw.unwrap2.setTVSubObjectMode(3);--face selection more
    		$.unwrap_uvw.unwrap2.setShowMap(false);--disable tex view
    		
    		--$.modifiers[#unwrap_uvw].unwrap2.renderuv_seamColor = color ;
    		--
    		$.modifiers[#unwrap_uvw].unwrap2.setOpenEdgeColor [256-190,256-230,256-119];
    		$.modifiers[#unwrap_uvw].unwrap2.setSharedColor [256-255,256-132,256-255];
    		$.modifiers[#unwrap_uvw].unwrap.setLineColor [256-255,256-132,256-0];
    		
    		$.modifiers[#unwrap_uvw].unwrap.setSelectionColor [256-255, 256-108, 256-0];
    
    		-- new stuff
    		$.modifiers[#unwrap_uvw].unwrap2.setFillMode 2;
    		$.modifiers[#unwrap_uvw].unwrap2.setBackgroundColor [256-44,256-52,256-43];
    
    		--grid colors
    		$.modifiers[#unwrap_uvw].unwrap2.setGridVisible true;
    		$.modifiers[#unwrap_uvw].unwrap2.setGridSize 1;
    		$.modifiers[#unwrap_uvw].unwrap2.setGridColor [82,79,69];
    
    		--fl_textureHelper.pos = point2 96 64;
    		--clearlistener();
    		
    		local _x = (fl_textureHelper.pos.x + 160+200) as integer;
    		local _y = (fl_textureHelper.pos.y + 16)  as integer;
    		
    		$.modifiers[#unwrap_uvw].unwrap5.setWindowXOffset 640;
    		
    		print("pos x "+5 as string);
    		
    		--$.modifiers[#unwrap_uvw].unwrap5.setWindowYOffset _y;
    		--setWindowXOffset
    		enableSceneRedraw();
    		completeRedraw();
    		
    		print("any?"+2 as string);--$.modifiers[#unwrap_uvw].unwrap.pos
    		
    	)catch(
    		enableSceneRedraw()
    		completeRedraw();
    	)
    )
    
    
    
    fn align_uv_edge_to_axis =(
    	local obj = selection[1];
    	if classof (modPanel.getCurrentObject()) == Unwrap_UVW then(
    		local _mode = obj.modifiers[#unwrap_uvw].unwrap2.getTVSubObjectMode();
    		if (_mode == 2)then(
    
    			local _array = obj.modifiers[#unwrap_uvw].unwrap2.getSelectedEdges();
    			
    			if (_array.numberSet == 1)then(
    				
    				local _edge = (_array as array)[1] as integer;
    
    				--get the transformation info
    				obj.modifiers[#unwrap_uvw].unwrap2.edgeToVertSelect();
    				_points = obj.modifiers[#unwrap_uvw].unwrap.getSelectedVertices() as array;
    				local ptA = obj.modifiers[#unwrap_uvw].getVertexPosition 1 _points[1];
    				local ptB = obj.modifiers[#unwrap_uvw].getVertexPosition 1 _points[2];
    				
    				
    				local dx = ptB.x - ptA.x;
    				local dy = ptB.y - ptA.y;
    				
    				
    				/*
    				local dx = amax #(ptB.x, ptA.x) - amin #(ptB.x, ptA.x);
    				local dy = amax #(ptB.y, ptA.y) - amin #(ptB.y, ptA.y);
    				*/
    				
    				
    				
    				local _a_abs = mod ((atan2 dy dx)+4*360) 360;--the angle in closed 360 degrees
    				local _a_off = (mod _a_abs 90);--angle offset
    				if (_a_off > 45)then(
    					_a_off = -(90 - _a_off);
    				)
    				--was it last time already snapped to this value? - in that case flip the axis
    				/*local _res1 = (floor (_a_abs)) as integer;
    				local _res2 = (floor (_a_abs + _a_off)) as integer;
    				if (_res1 == _res2)then(
    					_a_off = _a_off+90;
    				)
    				print("angle offset "+_a_off as string+" = "+_res1 as string);
    				*/
    				
    				obj.modifiers[#unwrap_uvw].unwrap2.selectElement();
    				obj.modifiers[#unwrap_uvw].unwrap2.RotateSelected (-_a_off  * PI/180) [(ptA.x + dx/2),(ptA.y + dy/2),0]
    				obj.modifiers[#unwrap_uvw].unwrap6.selectEdgesByNode #{_edge} $;
    
    			)else(
    				print("select just 1 edge!");
    			)
    		)
    	)
    )
    
    
    
    
    fn align_uv_verts _angleSnap =(
    	if classof (modPanel.getCurrentObject()) == Unwrap_UVW then(
    		-- check if vertex points are selected. otherwise convert
    		
    		_uvBase = $.modifiers[#unwrap_uvw];
    		_uv1 = $.modifiers[#unwrap_uvw].unwrap;
    		_uv2 = $.modifiers[#unwrap_uvw].unwrap2;
    		_uv5 = $.modifiers[#unwrap_uvw].unwrap5;
    		
    		local _mode = _uv2.getTVSubObjectMode();
    		if (_mode == 2)then(
    			_uv2.edgeToVertSelect();
    		)else if (_mode == 3)then(
    			_uv2.faceToVertSelect();
    		)
    
    		
    		_array = _uv1.getSelectedVertices();
    		_selection = #();--new array
    		_maxX;_maxY;_minX;_minY;
    		
    		_nr=1;
    		for i in _array do (
    			local _pt = _uvBase.getVertexPosition 1 i;
    			
    			if (_nr > 1) then(
    				local _pt2 = _uvBase.getVertexPosition 1 _maxX;
    				if (_pt.x > _pt2.x)then(
    					_maxX = i;
    				)
    				_pt2 = _uvBase.getVertexPosition 1 _minX;
    				if (_pt.x < _pt2.x)then(
    					_minX = i;
    				)
    				
    				_pt2 = _uvBase.getVertexPosition 1 _maxY;
    				if (_pt.y > _pt2.y)then(
    					_maxY = i;
    				)
    				_pt2 = _uvBase.getVertexPosition 1 _minY;
    				if (_pt.y < _pt2.y)then(
    					_minY = i;
    				)
    			)else(
    				_maxX = i;
    				_maxY = i;
    				_minX = i;
    				_minY = i;
    			)
    			_selection[_nr] = i;
    			_nr+=1;
    		)
    
    		if (_nr > 1)then(
    			--determine if horizontal or vertical flow
    			local _a = _uvBase.getVertexPosition 1 _minX;
    			local _b = _uvBase.getVertexPosition 1 _maxX;
    			local _w = (_b.x - _a.x);
    			_a = _uvBase.getVertexPosition 1 _minY;
    			_b = _uvBase.getVertexPosition 1 _maxY;
    			local _h = (_b.y - _a.y);
    			
    			local A=1;
    			local B=1;
    
    			_sel = #{};
    			if (_w > _h )then(
    				A = _minX;
    				B = _maxX;
    			)else(
    				A = _minY;
    				B = _maxY;
    			)
    			_sel = #{};
    			_sel[A] = true;
    			_sel[b] = true;
    			--_uv1.selectVertices _sel;
    
    			
    			if (_selection.count > 2)then(
    				local ptA = _uvBase.getVertexPosition 1 A;
    				local ptB = _uvBase.getVertexPosition 1 B;
    				
    				local dx = ptB.x - ptA.x;
    				local dy = ptB.y - ptA.y;
    				local _a = mod ((atan2 dy dx)+4*360) 360;--the angle in degrees
    				local _snap = (mod _a 90) as integer;
    				if (_snap > 45)then(
    					_snap = 90 - _snap;
    				)
    				if (_snap <= _angleSnap)then(
    					--snap to axis
    					if(_w > _h )then(
    						ptA.y = ptA.y + dy/2;
    						ptB.y = ptA.y;
    					)else(
    						ptA.x = ptA.x + dx/2;
    						ptB.x = ptA.x;
    					)
    					_uvBase.SetVertexPosition 1 A ptA;
    					_uvBase.SetVertexPosition 1 B ptB;
    				)
    				--_angleSnap
    				print("angle "+_a as string+" %90= ("+_snap as string+")");
    
    				for i = 1 to _selection.count do(
    					if (_selection[i] != A and _selection[i] != B)then(
    						local _pt = _uvBase.getVertexPosition 1 _selection[i];
    						
    						if(_w > _h )then(
    							local _m = (ptB.y - ptA.y) / (ptB.x - ptA.x);
    							local _x = _pt.x - ptA.x;
    							_pt.y = _x * _m + ptA.y; 
    						)else(
    							local _m = (ptB.x - ptA.x) / (ptB.y - ptA.y);
    							local _y = _pt.y - ptA.y;
    							_pt.x = _y * _m + ptA.x; 
    						)
    						_uvBase.SetVertexPosition 1 _selection[i] _pt;
    					)
    				)
    			)else if (_selection.count == 2) then(
    				--align just 2 verts
    				local ptA = _uvBase.getVertexPosition 1 A;
    				local ptB = _uvBase.getVertexPosition 1 B;
    				
    				local dx = ptB.x - ptA.x;
    				local dy = ptB.y - ptA.y;
    				local _a = mod ((atan2 dy dx)+4*360) 360;--the angle in degrees
    				local _snap = (mod _a 90) as integer;
    				if (_snap > 45)then(
    					_snap = 90 - _snap;
    				)
    				if (_snap <= _angleSnap)then(
    					--snap to axis
    					if(_w > _h )then(
    						ptA.y = ptA.y + dy/2;
    						ptB.y = ptA.y;
    					)else(
    						ptA.x = ptA.x + dx/2;
    						ptB.x = ptA.x;
    					)
    					_uvBase.SetVertexPosition 1 A ptA;
    					_uvBase.SetVertexPosition 1 B ptB;
    				)
    			)
    		)
    	)else(
    		print("you are not in UV-edit mode!");
    	)
    )
    
    
    fn get_tex_size_auto = (
    	local _w;
    	local _h;
    	local _result;
    
    	if (selection[1].material != undefined)then(--the object material difuse bitmap width
    		_w = selection[1].material.maps[2].bitmap.width;
    		_h = selection[1].material.maps[2].bitmap.height;
    		_result = amax #(_w, _h);
    	)else(
    		if classof (modPanel.getCurrentObject()) == Unwrap_UVW then(
    			_w = selection[1].modifiers[1].unwrap.getRenderWidth();
    			_h = selection[1].modifiers[1].unwrap.getRenderHeight();
    			_result = amax #(_w, _h);
    		)else(
    			_result = 512;
    		)
    	)
    	return _result;
    )
    
    fn bake_ao_2_clipboard _size _samples _spread=(
    	tex_size = _size;
    	obj = selection[1];
    	obj.removeAllBakeElements();
    
    	ao_bake = AmbientOcclusionBakeElement();	
    	ao_bake.outputSzX    =    tex_size;
    	ao_bake.outputSzY    =    tex_size;
    	ao_bake.autoSzOn              = false;
    	ao_bake.bright                      = color 255 255 255 0;
    	ao_bake.dark                      = color 0 0 0 0;
    	ao_bake.backgroundColor		= color 0 0 0 0;
    	ao_bake.elementName          = "Ambient Occlusion";
    	ao_bake.falloff                      = 1.0;
    	ao_bake.maxDistance          = 0.0 ;
    	ao_bake.samples                  = _samples;--16
    	ao_bake.spread                  = _spread;--0.8
    	ao_bake.enabled                  = true;
    	ao_bake.fileType = GetDir #image + "_renderToClipboard3.bmp";--appearently the target filename/path
    	
    	-- Baking job
    	bake = obj.INodeBakeProperties;
    	bake.bakeChannel = 1;
    	bake.nDilations         = 2; -- (Pading)
    	bake.flags             = 1; --bit 1 of flag will be set to signify map channel conflict
    	bake.bakeEnabled     = true;
    	bake.addBakeElement ao_bake;
    	--select obj
    	render rendertype:#bakeSelected outputwidth:tex_size outputheight:tex_size vfb:false;
    
    	--copy to clipoard and delete temp image
    	theFileName = ao_bake.fileType --define a temp.file name
    	clipboardClass = dotNetClass "System.Windows.Forms.Clipboard" --create a Clipboard dotNetClass
    	theImage = dotNetClass "System.Drawing.Image" --create an Image dotNetClass
    	theBitmap = theImage.FromFile theFileName --get the saved image from file as bitmap
    	clipboardClass.setImage theBitmap --copy the image to clipboard
    	theBitmap.Dispose() --release the bitmap 
    	deleteFile theFileName --delete the temp. file
    	clipboardClass.ContainsImage() --return true if the clipboard contains image
    	
    	--remove traces
    	bake.removeAllBakeElements();
    	bake.bakeEnabled = false;
    	obj.removeAllBakeElements();
    )
    
    
    function bake_uv_2_clipboard _size = (
    	
    	--check if UV- modifier is present...
    	
    	local obj = selection[1];
    	local del_uvModifier = false;
    	if classof (modPanel.getCurrentObject()) != Unwrap_UVW then(--add a UVW unwrap modifier
    		modPanel.addModToSelection (Unwrap_UVW ()) ui:on;
    		del_uvModifier = true;
    	)
    	--_size = 512;
    	obj.modifiers[#unwrap_uvw].renderuv_width =  _size;
    	obj.modifiers[#unwrap_uvw].renderuv_height = _size;
    	obj.modifiers[#unwrap_uvw].renderuv_fillmode = 0;--solid
    	obj.modifiers[#unwrap_uvw].renderuv_seamColor = color 255 255 255;
    	obj.modifiers[#unwrap_uvw].renderuv_showframebuffer = false;
    
    	
    	clipboardClass = dotNetClass "System.Windows.Forms.Clipboard" --create a Clipboard dotNetClass
    
    	theFileName = GetDir #image + "_renderToClipboard.bmp" --define a temp.file name
    	obj.modifiers[#unwrap_uvw].unwrap5.renderUV theFileName;--save UV layout to the temp folder
    
    	theImage = dotNetClass "System.Drawing.Image" --create an Image dotNetClass
    	theBitmap = theImage.FromFile theFileName --get the saved image from file as bitmap
    	clipboardClass.setImage theBitmap --copy the image to clipboard
    	theBitmap.Dispose() --release the bitmap 
    	deleteFile theFileName --delete the temp. file
    	clipboardClass.ContainsImage() --return true if the clipboard contains image
    
    	obj.modifiers[#unwrap_uvw].renderuv_showframebuffer = true;--reset defaults
    	
    	if (del_uvModifier == true)then(
    		deleteModifier obj 1;
    		print("modifier has been deleted!!!");
    	)
    	
    )
    
    
    
    
    
    
    
    rollout rl_textureMain "general" width:128 height:353
    (
    
    	label lbl1 "res:" pos:[2,6] width:31 height:14
    
    	button btn_bake_uv "bake UV wire" pos:[2,26] width:124 height:20
    	button btn_bake_ao "bake AO" pos:[2,75] width:124 height:20
    	spinner spn_ao_samples "smpl" pos:[9,96] width:56 height:16 range:[0,800,64] scale:1
    	spinner spn_ao_spread "sprd" pos:[71,96] width:56 height:16 range:[0,100,50] scale:1
    
    	
    	button btn_align_verts "align verts" pos:[2,189] width:78 height:28
    	spinner spn_snap_align "" pos:[79,200] width:40 height:16 range:[0,45,45] scale:1
    	label lbl_degrees "°" pos:[121,201] width:4 height:14
    	
    	
    	button btn_res_guess "get" pos:[55,3] width:25 height:21
    	edittext edt_tex_size "" pos:[18,3] width:37 height:21
    	dropdownList ddl_uvChannel "" pos:[92,3] width:37 height:21 items:#("1", "2", "3", "4") selection:1
    
    	
    	button btn_bake_faces "bake UV sel. faces" pos:[2,46] width:124 height:20
    	
    	
    	label lbl_channel "#" pos:[83,6] width:9 height:14
    
    	button btn_align_edge_shell_axis "align edge-shell to axis" pos:[2,222] width:124 height:20
    	button btn_align_shell_3d "align shell to 3d-space" pos:[2,265] width:124 height:20
    	button btn_align_edge_neighbor "align edge to neighbor" pos:[2,242] width:124 height:20
    	label lbl_uv_tools "UV alinging tools" pos:[23,126] width:82 height:14
    	label lbl9 "axis snap" pos:[81,186] width:45 height:14
    	button btn_open_uv_editor "open UV editor" pos:[2,142] width:124 height:30
    	
    	button btn_pack_uv "pack UV" pos:[2,292] width:87 height:30
    	spinner spn_btn_pack_uv_space "" pos:[88,305] width:39 height:16 range:[0,100,0] scale:1
    	label lbl_btn_pack_uv_space "pix spc" pos:[89,291] width:37 height:14
    	
    	-------------------------------------------------
    
    	
    	
    	
    	
    
    	
    
    	on btn_bake_uv pressed do
    	(
    			bake_uv_2_clipboard (edt_tex_size.text as integer);
    		)
    	on btn_bake_ao pressed do
    	(
    			bake_ao_2_clipboard (edt_tex_size.text as integer ) (spn_ao_samples.value/100) (spn_ao_spread.value/100);
    		)
    	on btn_align_verts pressed do
    	(
    		align_uv_verts spn_snap_align.value;
    	)
    	on btn_res_guess pressed do
    	(
    			edt_tex_size.text = get_tex_size_auto() as string;
    		)
    	on btn_bake_faces pressed do
    	(
    		--render selected faces
    	)
    	
    	on btn_align_shell_3d pressed do
    	(
    		--
    	)
    	on btn_align_edge_neighbor pressed do
    	(
    		--
    	)
    	on btn_align_edge_shell_axis pressed do
    	(
    		align_uv_edge_to_axis();
    	)
    	
    	on btn_open_uv_editor pressed do
    	(
    		open_uv_editor();
    	)
    	on btn_pack_uv pressed do
    	(
    		pack_uv (spn_btn_pack_uv_space.value/(rl_textureMain.edt_tex_size.text as integer));
    	)
    )
    
    
    
    
    function _init = (
    
    	try (-- close existing rolloutFloater
    		closeRolloutFloater fl_textureHelper; 
    	) catch();
    	fl_textureHelper = newRolloutFloater "texture tools" 142 370;
    	addrollout rl_textureMain fl_textureHelper;
    	
    	rl_textureMain.edt_tex_size.text ="512";
    	fl_textureHelper.pos = point2 96 64;
    )
    
    _init();
    
  • Yozora
    Options
    Offline / Send Message
    Yozora polycounter lvl 11
    just played around with it...

    Thanks for the idea to change the colours of the uv window, I was always annoyed at that background grid thing and how the lines were not visible in the black squares, cant believe changing the colours didnt occur to me until now -.-
    btw you can make the uv window pop up by default by enabling the "always bring up the edit window"under options and then saving preferences.

    The features are awesome, I really like that shell aligning idea and the copy-uv-wire. But a few things I dont like;

    First I cant hotkey the UV aligning tools, this is really important because I dont want to be clicking on a 2nd window to do this. Actually I'd like to put all of this stuff in a quad menu or hotkeyed instead of a clicking interface, but I guess it will be impossible to do with the ones that require a number input box.

    Secondly when undoing the UV aligning, it undos each vertex individually instead of the whole process. So If I align 20 UVs, it will have to go through 20 undos to get back to the previous state whereas with chuggnuts (or mops tools), you can undo the whole thing.


    And I realize I can rip your script to make a hotkeyable version of the alignment tool, I just felt like suggesting you to put it in there by default :p
  • renderhjs
    Options
    Offline / Send Message
    renderhjs sublime tool
    First I cant hotkey the UV aligning tools, th...
    defenitly planned once its all cleaned up- I need as well to assign stuff to hotkeys later.
    That is also why I mentioned in the beginning to try to design functions to be useable even witout parameters (e.g angle snap value - would then be hard coded i the function and each time come with the same value). Another goal was to reduce the amount of functions or keys one use (by smartly determining between horizontal or vertical align for example).

    but thx for the try and feedback
  • Tumerboy
    Options
    Offline / Send Message
    Tumerboy polycounter lvl 17
    awesome, I'll try and mess with it later!
  • Farfarer
    Options
    Offline / Send Message
    Woop, after writing my UV island edge align script for modo I wanted it in Max, but ain't got the Maxscript skills to make it happen.

    Cheers, dude :)
  • renderhjs
    Options
    Offline / Send Message
    renderhjs sublime tool
    been playing with a new interface (the middle one), its inspired by the phtoshop/Flash/ Illustrator tool palette. That way it will be less in the way and easier to arrange next to the UV-editor
    uv_script_interface_v2.gif

    functions added meanwhile (will post code later)
    - render selected UV faces as mask into clipboard
    - edge-loop align (aligns a edge loop based on a edge selection)

    I had some smal success writing the align selection to 3d space (so you dont have flipped or 180° rotated shells) but its not yet working quite right yet.
    Another idea I have is to distribute vertecies along a line with a kind of relax behaviour which could work great on pelt-mappings that need to be straighten on the borders but remain relaxed to the connected vertecies.
  • Japhir
    Options
    Offline / Send Message
    Japhir polycounter lvl 16
    wow this is looking really promising! if you could (once it's all done) make it so that you can assign each script to a hotkey/button whater individually it would be great!

    feature request:
    could you make a script that relaxes the selection, but constrains some edges/verts to either their uv position, or just the u or v position? so you could create straight edges, yet still relax it so that you get the smallest amount of distortion? (so you select the top edges of an island, make sure they are aligned in the v direction, then constrain them to that axis so they can only move in the other direction.
    hard to explain, but it'd be an amazing feature, and if you could pull it off i'd be worshipping you for the rest of your life until you get so annoyed of me you wish you never wrote the script in the first place! haha.
  • renderhjs
    Options
    Offline / Send Message
    renderhjs sublime tool
    could you make a script that relaxes the selection, but constrains some edges/verts to either their uv position, or just the u or v position? so you could create straight edges, yet still relax it so that you get the smallest amount of distortion? (so you select the top edges of an island, make sure they are aligned in the v direction, then constrain them to that axis so they can only move in the other direction.

    at the bottom of my last message:
    renderhjs wrote:
    Another idea I have is to distribute vertecies along a line with a kind of relax behaviour which could work great on pelt-mappings that need to be straighten on the borders but remain relaxed to the connected vertecies.
    I think that is what you mean or at least close related,- here is a picture of what I had in mind:
    pc_uvscripts_distribute_idea.gif
    is dat wat jij bedoelt ? :D
    note the equal distribution at the end, the same of course could be applied to a snapped axis (just U or V). My idea was to have a version of that script or button that eases step by step (always 1/2 of the distance to its perfect position from its current) so the transition would not be that rough and adjustable in steps (like the old relax behaviour in max except that this one can align on line flows)
  • Michael Knubben
    Options
    Offline / Send Message
    I get this error when using the 'Bake AO' button: maxscript_texturetools_error.jpg
    Any idea what causes it?
  • renderhjs
    Options
    Offline / Send Message
    renderhjs sublime tool
    which max version?

    seems like it cant find a path,- got the same when rendering the UV ?
    c:\documents and settings\ ???? \..

    or maybe you removed that part in the screenshot in that case perhaps you dont have write access at that location.

    that code line that is highlighted refers to a string ao_bake.fileType which is the path of the image to be saved it gets declared here:
    ao_bake.fileType = GetDir #image + "_renderToClipboard3.bmp";--appearently the target filename/path
    

    so if you paste just
    (GetDir #image + "_renderToClipboard3.bmp")
    
    in your listener what does it puke? a path that does not exist?
  • renderhjs
    Options
    Offline / Send Message
    renderhjs sublime tool
    little progress on the GUI design
    uv_scripts_gui_v3.gif
    I wanted to go with grey styled icons only just like in PS but compared to PS I do not simply need to visualize tools but rather actions and affection which becomes difficult.

    if you could (once it's all done) make it so that you can assign each script to a hotkey/button whater individually it would be great!
    that would be certainly nice perhaps in the style of silo where you hover over the button with the mouse and hit a key on your keyboard. Unfortunately scripting access to keys is from my understanding very limited- macroscripts though will be added once I have this all running nice and smooth without puking errors.
  • Michael Knubben
    Options
    Offline / Send Message
    Nope. The part I painted out in that picture consists of only lowercase letters.
    I sent some info to Renderhjs, though, so let's hope he figures it out. Not that I really needed the ao-bake, I just clicked buttons to see if they'd work and found one that didn't :)
  • renderhjs
    Options
    Offline / Send Message
    renderhjs sublime tool
    I noticed that you have a 64-bit version of max,- propably vista as well maybe between the 2 lies the problem.
    It worked here with 3dsmax 9 32 bit and with 3dsmax 2009 Design 32 bit on Windows Xp 32 bit so I almost believe that the problem is somewhat because of that.

    It might be that the path`s in vista are not present, write-able (in that case maxscript returned the wrong url for the #image url), or that 64 bit has different access or whatever to dotNet either way cant reproduce and thereby debug the problem here- sorry.
  • Yozora
    Options
    Offline / Send Message
    Yozora polycounter lvl 11
    im also using vista and 3d max 64 bit and got same error as pea. After the AO Bake button causes the error, all the buttons in the whole script no longer work.
  • renderhjs
    Options
    Offline / Send Message
    renderhjs sublime tool
    there is a fucked up typo in maxscript
    [php]ao_bake.fileType = GetDir #image + "_renderToClipboard3.bmp";--appearently the target filename/path[/php] its the part of the script that tells the RTT job of the AO pass where to save the file.
    Appearently it defines the filename instead of the extention. There is a attribute for the filename as well but its something else or is ignored. I got this glitch from a forum where people freaked out because maxscript would simply not save the AO render pass. It could be that autodesk fixed that only in the 64-bit version in vista - maybe I could test things out based on this assumption and define the path where one would assume it for Vista64bit users - propably some try()catch() thing. Will test it out this weekend
  • Michael Knubben
    Options
    Offline / Send Message
    Xp64 (sorry for not mentioning that before) and max 2009 64-bit here.
  • renderhjs
    Options
    Offline / Send Message
    renderhjs sublime tool
    so that might nail it closer to 64 bit,- will post a new code later (with new GUI) this evening hopefully fixing the issue although its more a guess
  • Mark Dygert
    Options
    Offline / Send Message
    renderhjs wrote: »
    there is a fucked up typo in maxscript
    [php]ao_bake.fileType = GetDir #image + "_renderToClipboard3.bmp";--appearently the target filename/path[/php] its the part of the script that tells the RTT job of the AO pass where to save the file.
    Appearently it defines the filename instead of the extention. There is a attribute for the filename as well but its something else or is ignored. I got this glitch from a forum where people freaked out because maxscript would simply not save the AO render pass. It could be that autodesk fixed that only in the 64-bit version in vista - maybe I could test things out based on this assumption and define the path where one would assume it for Vista64bit users - propably some try()catch() thing. Will test it out this weekend
    Its something they admit to being broken and even make a special note of it in their maxscript help files, but don't tell you how to work around it... Drove me bat shit nuts for a few days.

    It pulls the actual file format from what is defined in the "Render Setup > Render Output" window "rendOutputFilename" to be exact. If this is blank (like any new scene is) then it will not save anything, which is why it fails for some people. If they picked a file path and type, (and possible rendered once with those settings) it would save something. The sad thing is lets say you have it set to .mov but the script names it .png you get a .mov with a renamed extension to png.

    You have to set "rendOutputFilename" first, in order to set the file format correctly. Kind of a pain and not very well documented... I remember there being one more hickup/roadblock to outputting renders but can't think of it... Hopefully that will get you moving in the right direction?
  • renderhjs
    Options
    Offline / Send Message
    renderhjs sublime tool
    maxscript is actually very powerfull and its nice how easy often you can get into every little tool max has to offer - mixing it with your own flavour. But yes sometimes its kind of chaos how they did things.

    But isnt't rendOutputFilename somethiing that is rather close to render in general not the RTT stuff? Its odd as when throwing the render job using:
    render rendertype:#bakeSelected outputwidth:tex_size outputheight:tex_size vfb:false;
    
    you can pass through an additional parameter of where the framebuffer should be stored (though obviously not what I want). I will give your hint a in depth shot if my current version should still fail on 64-bit max versions - as I changed some variables where it crashed before for 64bit users.


    so here is the update, this time however you need a additional bitmap to run the script it holds the icons of my buttons - so copy booth to the scripts/statup folder

    interface
    uv_scripts_gui_v4_tools.gif
    crossed buttons are not yet available or finished

    a quick video showing some of the features
    uv_scripts_gui_v4.gif

    download
    www.renderhjs.net/bbs/polycount/texture_maxscript_tools/uv_toolbox_0.6.zip

    so if some 64 bit users could give esspecially this code fraction another shot (copy it and run it in the maxscript listener) that would be fine (you need to select a object to render the AO map)
    (
    _samples = 100;
    _spread = 60;
    _size = 256;
    tex_size = _size;
    	obj = selection[1];
    	obj.removeAllBakeElements();
    
    	
    	
    	local url_save_path = GetDir #image + "_renderToClipboard3.bmp"
    	
    	ao_bake = AmbientOcclusionBakeElement();	
    	ao_bake.outputSzX    =    tex_size;
    	ao_bake.outputSzY    =    tex_size;
    	ao_bake.autoSzOn              = false;
    	ao_bake.bright                      = color 255 255 255 0;
    	ao_bake.dark                      = color 0 0 0 0;
    	ao_bake.backgroundColor		= color 0 0 0 0;
    	ao_bake.elementName          = "Ambient Occlusion";
    	ao_bake.falloff                      = 1.0;
    	ao_bake.maxDistance          = 0.0 ;
    	ao_bake.samples                  = _samples;--16
    	ao_bake.spread                  = _spread;--0.8
    	ao_bake.enabled                  = true;
    	
    	ao_bake.fileName = url_save_path;--just in case for 64-bit machines
    	ao_bake.fileType = url_save_path;--appearently the target filename/path
    	
    	
    	-- Baking job
    	bake = obj.INodeBakeProperties;
    	bake.bakeChannel = 1;
    	bake.nDilations         = 2; -- (Pading)
    	bake.flags             = 1; --bit 1 of flag will be set to signify map channel conflict
    	bake.bakeEnabled     = true;
    	bake.addBakeElement ao_bake;
    	--select obj
    	render rendertype:#bakeSelected outputwidth:tex_size outputheight:tex_size vfb:false;
    
    	--copy to clipoard and delete temp image
    	clipboardClass = dotNetClass "System.Windows.Forms.Clipboard" --create a Clipboard dotNetClass
    	theImage = dotNetClass "System.Drawing.Image" --create an Image dotNetClass
    	theBitmap = theImage.FromFile url_save_path --get the saved image from file as bitmap
    	clipboardClass.setImage theBitmap --copy the image to clipboard
    	theBitmap.Dispose() --release the bitmap 
    	deleteFile url_save_path; --delete the temp. file
    	clipboardClass.ContainsImage() --return true if the clipboard contains image
    	
    	--remove traces
    	bake.removeAllBakeElements();
    	bake.bakeEnabled = false;
    	obj.removeAllBakeElements();
    )
    
  • Mark Dygert
    Options
    Offline / Send Message
    That might be true, RTT might be separate from the render or batch render. I ran into that problem setting up the file output path/type when I was working with the batch render. It won't surprise me if they handle RTT the same way...
  • Yozora
    Options
    Offline / Send Message
    Yozora polycounter lvl 11
    AO button still causes the same error, copying that part of the script alone does this;

    -- Syntax error: at ), expected <factor>
    -- In line: )


    Whats the purpose of the 3 icons at the top that arent buttons? Is it meant to be some logo for this script? I think they're a waste of space :/
  • renderhjs
    Options
    Offline / Send Message
    renderhjs sublime tool
    At least it tells you a syntax error - not anymore this
    runtime error: dotNet runtime exception ....
    
    so it means max 64 thinks there is some syntax typo in my script. hmm guess I am going to ask some people here to install me a 64bit windows with max 64bit to digg into that.

    yes a smal logo or caption for the tool itself will be placed there because the initial window title is hardly readable - I am working atm. on that so that some GUI parts will work propper. Its just 20 pixels in height If you dont like it you can remove it later its just 1 line of code.
  • renderhjs
    Options
    Offline / Send Message
    renderhjs sublime tool
    I might have catched the problem though I am not 100% sure- I got the same error today with a different scene. It turned out that having the renderer not set to MentalRay caused the same errors posted by others here. It should be obvious that mental Ray is a requirement for AO anyway I will build in a detection that will otherwise set the renderer to mentalRay and back to what it was before- hopefully that will fix everything.
  • Mark Dygert
    Options
    Offline / Send Message
    You can cause some lighting problems and scene insatiability if you're switching the rendering engine back and forth, which they would no doubt blame on your script. Problems like normal lights in the scene becoming overly bright, or causing shadow errors because MR adds shadow parameters to lights which are left on after it switches back to scan line.

    You might want to warn the user that their render-er is not set correctly and offer three options.
    1) Set it to MR and leave it.
    2) Set it to MR and switch it back, another prompt comes up warning them about instability and make sure to blame MR/AD so you don't unfairly get blamed.
    3) Do nothing and let them set switch it over, ie cancel.
  • Titus
    Options
    Offline / Send Message
    Titus polycounter lvl 14
    renderhjs - this is awesome script !! Very useful but i get an error when i run it (ver 0.6) when i run old version 0.5 it works fine for me

    here is error screen
    Uv_tools_err_01.jpg

    PS: 3dsmax 2009 32 bit , WinXP Pro x86 SP3

    Please help:poly122:
  • renderhjs
    Options
    Offline / Send Message
    renderhjs sublime tool
    EDIT

    Titus: fixed it,- thanks for your feedback - remove the older files and now simply use this single file
    http://www.renderhjs.net/bbs/polycount/texture_maxscript_tools/uv_toolbox_0.7.mzp
    again just copy this single file into your 3dsmax/scripts/startup folder so that it runs at each launch,- or simply start the script from the maxscript listener.

    Vig: thanks for the input,- you are right I guess I will stay with a warn message so that the user has to switch by himself instead of me hacking around the system.

    btw. I addded the script at scriptspot some time ago
    http://www.scriptspot.com/3ds-max/uv-toolbox-for-the-texture-artist-set-of-uv-texture-maps-rendering-tools
    though this thread will be my main update/inspiration thread regarding this project
  • Titus
    Options
    Offline / Send Message
    Titus polycounter lvl 14
    Many thanks !! For quick reply :)
  • Tumerboy
    Options
    Offline / Send Message
    Tumerboy polycounter lvl 17
    Been playing with it, (no, not THAT) and it's quite useful. Render, is there a way to tell the edge/shell align thing to ignore angle snap? I usually work with angle snap on. If I do an unwrap, and then relax, lets say my island is off kilter 7.62 deg. If I have angle snap on when I run the shell align script, it will attempt to move it to 0, but angle snap will only let it move in 5 deg increments, so now it's at 2.62, or -2.38.
  • renderhjs
    Options
    Offline / Send Message
    renderhjs sublime tool
    hi tumberboy, thx for testing
    the command that is responsible for the rotation there is:
    [php]obj.modifiers[#unwrap_uvw].unwrap2.RotateSelected (-_a_off * PI/180) [(ptA.x + dx/2),(ptA.y + dy/2),0][/php]
    the way it seems (havent tested yet) is that max takes even within single maxscript commands the snap value into consideration. I found a command that toggles the ratation snap but not a variables that tells me the current state - which I need in order to detect when to switch,
    [php]max angle snap toggle[/php]
    maybe I can trick abit and do a temporary rotation and calculate the result of that rotation transformation - if it fits within the default 5° snap value toggle the autoSnap.

    thx for letting me know
  • Tumerboy
    Options
    Offline / Send Message
    Tumerboy polycounter lvl 17
    ya, not a big deal, just something I noticed.
  • renderhjs
    Options
    Offline / Send Message
    renderhjs sublime tool
    update v 0.8
    - 3 new functions: assign checker map; set "flat" view mode; normalize UV shells (thx to MoP)

    uv_tex_tools_ui_0.8.gif
    changes/updates:
    (1.) ask's the user in case mental Ray is not assigned as the renderer if the script should assign it and continue the script.
    uv_tex_tools_ui_0.8_dialogue.gif
    If mentalRay is already the scene renderer everything should work right away and nothing gets changed at all.

    (2.) high and low presets (not yet tuned values,- some recomendations? - sets spread and falloff value for AO)

    (3.) Assigns a checker map (greyish with 8*8 tiling) to the selected object with visibility inside set the viewport. This has nothing to do with the material instance editor (the 3dsmax material editor) as each object node in max can (has) have its own material.

    (4.) set self illujmination viewmode in the active viewport. Its a bit hidden in the default 3dsmax interface but this button does not at all modify the material - instead it sets the viewport mode to 'flat' which basicly means no shading and 100 difuse view.

    (5.) thx to tumberboy I fixed the auto-align button thingy my script can actually DETECT angle snap mode :D . If it is active it will temporarily disable it- align rotate again and enable back your angle snap toggle.

    (6.) included the normalize UV-shells script from MoP
    http://boards.polycount.net/showthread.php?t=52415
    which normalizes all uv-shells without hardly changing their position. This often results into equal pixel space density over all shells, thx MoP for the great script

    ... and some minor enhacements like the get Size button that better detects if a bitmap material is assigned to the selected object- and use its width or height value ect. It would be nice if some of those former 64-bit users could give the AO-bake part another spin to see if it was actually rather not because in their cases MR was not assigned as the renderer.


    download:
    uv_toolbox_0.8.mzp
    remove prior versions and copy this into your startup folder
  • Yozora
    Options
    Offline / Send Message
    Yozora polycounter lvl 11
    Something wrong with the .mzp, it asks this when dragged into max;

    renderjhs1.jpg

    click yes and it applys your icons as a hugely stretched viewport background, click cancel and it does nothing (no script box, nothing)
13456714
Sign In or Register to comment.