The REZN8 Productions MAXScript Control and Function Library
	rezn8mxs.dlx version 1.34
	Copyright 2006, REZN8 Productions
	Developed by Simon Feltman
	Thanks to Bill Dahlinger for many ideas and testing.
	For bugs, comments, or suggestions email: support@rezn8.com

USE AT YOUR OWN RISK.

You are given the rights to use and distribute this extension provided
	credit is given to the author either in source or about box.


Version History:

1.34
	- All window related functions now accept an HWND, Control, Rollout, Dialog, or RolloutFloater.
		These are now described as <Window> in the help below and can be interchanged.
	- Added more functions.
		(dialogs.setAlphaAndColorKey, windows.getHWnd, windows.getWindowRect, windows.mapWindowPoint)

	- Fixed cool button so that when the button is pressed and the mouse is moved outside
		of the button area and release, button pressed events are no longer fired.

1.33
	- Added more coolbutton event handlers.
	(mouse up and down's for all mouse buttons)

1.32
	- Fixed GDI leak for coolbuttons when using images.

1.31
	- Bugfix for coolbutton's. Windows was getting a refresh call on creation
	   with images.

1.30
	- Added a ton of new Coolbutton properties.
	- Added CheckMAXMessages function for processing the 3dsmax windows 
	   message loop at any point in time during script execution.
	- Added DynamicPopupMenu to create a popup menu from a list of strings.

1.29
	- Fixed control de-allocation bug by recompiling with VC6 and the maxsdk6.
	- Added a bunch of new properties to the coolbutton.
	  backColor, textColor, alwaysDrawBorder, borderColor1, and borderColor2
	- Updated some errors in this help file. tabctrl.addPages never existed,
	   use <tabctrl.pages = #(<page1>,...) instead. Splitter control handlers
	   do not pass the position, get this from <splitter>.pos
	  
1.28
	- Added saveAppData and loadAppData for attaching file's to max objects.
	- Added getStructContext for getting the current struct context during
		script execution.
	- Addition of Dialog struct for wrapping rollouts.

1.27
	- Added dialogs.setAlpha for setting a dialogs windows transparency
	- Added dialogs.setColorKey for setting a transparent color key 

1.26
	- Fixed problem with multi-line tab control to properly resize tab pages.
	- Fixed bug with coolbutton's where disabled buttons would draw text black,
		it now draws disabled text.

1.25
	- Moved selchanged handler in tabctrl back to get called after the page is switched.
	  This was causing a problem with the selection index being incorrect.

1.24
	- Fixed refresh problem with coolbutton when going from hidden to visible state.
	- Fixed doubled text with coolbutton in text mode.
	- Move selchanged handler in tabctrl to get called before the page is switched.
	- Added new destroypages property to the tabctrl.

1.23
	- Fixed the splitter control to properly use .border and .handles properties.
		Previous documentation said the splitter had a .style property, this was incorrect
		and never worked.

1.22 
	- Fixed a bug in the coolbutton where buttons that created modal dialogs
		would not gain focus correctly.

	- Added tooltips to the coolbutton control.

1.21
	- Added mousein and mouseout events to the coolbutton control.

1.20
	- Added pixelsToTwips and twipsToPixels conversion functions.



System Variables

	rezn8mxs.version
		This variable is the current number release of the extension.

	rezn8mxs.copyright
		The extensions copyright information as a string.

Global Functions

	consoleCommand <String> [to:<stream>]
		Run a command through a console, stdout will get redirected into the listener 
		or the stream specified by 'to'.
		Example: consoleCommand "cmd /c dir"

	dialogs.setAlpha <Window> <Integer value>
		Sets a dialog to layered mode with a alpha value of 0 to 255

	dialogs.setColorKey <Window> <Color value>
		Sets a color key of a dialog in which pixels of the color will be completely transparent.

	dialogs.setAlphaAndColorKey <Window> <Integer alpha> <Color key>
		Sets the alpha and color key of a window.

	dialogs.setParent <child Window> <parent Window>
		This method will set a dialog as a child of another dialog or rollout
		floater. This gives a dialog the ability to stay on top of the dialog
		you set as the parent. The problem with this is the child dialogs will
		get clipped to the parents edges, not what I wanted. oh well. still is
		might be useful for someone.

	dialogs.setClipChildren <Window> <Boolean>
		Setting a dialog to clip its children means: when a dialog is redrawn by
		Windows, the child windows (Controls) will be clipped from the redraw area
		making for faster flicker free redraws. This function has not been tested
		with all controls but in general when you have a resizing dialog with some
		text boxes or large controls that also get resized it will look much nicer.

	dialogs.getState <Window>
		Returns the state of the dialog, can be one of the following:
			#restored
			#maximized
			#minimized

	dialogs.getPos <Window>
		Returns the screen space position of the given window or control.
	
	dialogs.getSize <Window>
		Returns the size of a dialog.

	dialogs.setSize <Window>
		Sets the size of a dialog.

	dialogs.getTitle <Window>
		Returns the dialog or rollout floaters window title as a String.

	dialogs.setTitle <Window> <String title>
		Returns the dialog or rollout floaters window title as a String.

	<Integer> windows.getHWnd <Window>
		Return the window handle (HWND) for the given Dialog, Rollout, RolloutFloater, or Control.

	<#(left,top,right,bottom)> windows.getWindowRect <Window>
		Return the screen space rectangle of the given HWND, Dialog, Rollout, RolloutFloater, or Control.

	<Point2> windows.mapWindowPoint <from Window> <to Window> <point2>
		Return a point2 value mapped from one window space onto another.
		Passing 0 for a window means to use the desktop screen space.

	Doh! the following clipboard functions were added before I new they
	were in Larry's avgaurd.dlx extension. 

		clipboard.get <#bitmap or #string>
			Retrives either a bitmap or text string from the windows clipboard.

		clipboard.set <String clipboardText>
			This method copies the given text string into the windows clipboard.

	isParityNegative <Node or Matrix3>
		Returns true if the given matrix has been negatively scaled.
		Matrices get negative scaling applied after mirror operations
		and can cause problems with maxscript exporters. If a node is
		being exported and it has a negatively scaled TM, you will
		generally need to flip the normal and re-order a faces vertices
		in the opposite order. For instance, a mirrored object with a 
		faces vertex order of 1-2-3 might be drawn incorrectly in a 
		Realtime engine. When exporting geometry of negatively scaled
		nodes simply check if the parity is negative with this method
		and re-order all faces vertex indexing to the opposite. The above
		example would be fixed with an ording of 3-2-1. Note this will 
		also need to be done for all corresponding texture and color vertex
		channels as well.

	getObjectOffsetTM <Node>
		Returns a Matrix3 value of the object offset. This is the combined result
		of the nodes object offset components (translation, rotation, and scale)
		The object offset is the pivot point offset from the node transformation 
		matrix. This can be multiplied by mesh geometry when exporting to get 
		correctly behavied animated objects with a pivot point that was modified.
		Generally the Matrix returned by this function will be the Identity matrix
		unless the object pivot point was moved by the artist.

	pixelsToTwips <Point2>
		Converts the given point from pixels to twips returning the converted value.
		Twips are a resolution independent format so thing can get scaled properly 
		for different resolutions.
		This is very useful for some activeX controls that require twips,
		the activeX TreeControl uses twips for hit testing...

	twipsToPixels <Point2>
		Converts the given point from twips to pixels returning the converted value.
		
	saveAppData <MaxObject> <id> <filename>
		Save the given objects app data out to the specified filename.
	
	loadAppData <MaxObject> <id> <filename>
		Load the specified file as a binary stream into the given objects app data.
	
	getStructContext()
		This function will return the currently executing structure. You can do 
		some very powerfull structured programming with this. For instance, you could have
		a self variable within a struct:
			struct MyStruct ( self = getStructContext() )
	
	CheckMAXMessages()
		Function for checking the 3dsmax windows message loop at any point in time during script execution.
		This can aid in usage of the 'execute' function within a menu or dialog handler.
		See usage example in 'plugins/rezn8/DynamicPopupMenu.ms'
	
	DynamicPopupMenu <#("menuItem1","menuitemX...")> pos:undefined useRollout:undefined align:#align_topleft
		This will dynamically generate a flat popup menu from a list of strings.
		Returns the selected string.

Rollout Controls

	TABCTRL
		This uses the standard windows Tab widget. The advantage however is automatic
		showing and hiding of the tab pages and items within each tab. The way this
		works is each tab page is defined by a seperate Rollout definition and then
		pushed into the tab control.
		When a rollout is added to the tabctrl either by using the 'pages' array or
		the addPage method, CreateDialog is automatically called on the Rollout. 
		DestroyDialog is also called on the rollout when the control is destroyed.
		Since the rollouts added to a tab control are handled the same as any other
		rollout all standard rollout handlers are called on them, 'on open', 'on close'...
		Note however that 'on oktoclose' does not get called for the pages, use the 
		parent container Rollouts 'oktoclose' handler.

		Creation Parameters:
			multiline:<boolean>  -- allows tabs to be shown over multiple lines. (default=false)

		Properties:
			<tabctrl>.style      -- location of tab strip, can be #top or #bottom
								    this parameter is only allowable on creation.
			<tabctrl>.padding    -- point2 of the spacing around the image and text of a tab (write only).
			<tabctrl>.selection  -- index of the currently selected page.
			<tabctrl>.selected   -- the currently selected Rollout page.
			<tabctrl>.pages      -- array of Rollout's for each page
			<tabctrl>.images     -- image array, the first two items are bitmap values or filnames
									the third is the number of images in the bitmaps, 4th and on
									are the indices into the images corresponding to each page.
									#( <Bitmap>, <Bitmap>, <Count>, <Index>, ... )
			<tabctrl>.page<n>    -- Rollout page <n> where <n> is any valid page index (read only).
			<tabctrl>.image<n>   -- image index of page <n> where <n> is any valid page index.
			<tabctrl>.title<n>   -- title of page <n> where <n> is any valid page index.
			<tabctrl>.destroypages  -- when set to false tabs pages do not get destroyed when
			                           they are removed from the tabctrl they do however when the containing
									   dialog gets destroyed, this can greatly increase speed for pages that
									   have alot of controls and are added and removed frequently.
			

		Methods:
			<Index> tabctrl.addPage <TabCtrl> <Rollout>
				Adds a dialog as a tab page. The dialog must first be created
				with the CreateDialog maxscript function. This function returns
				the index of the added tab page.

			tabctrl.removePage <TabCtrl> <Index or Rollout>
				Removes a tab page from the tab control.
			
			<Index> tabctrl.getPageIndex <TabCtrl> <Rollout>
				Returns the index of the given Rollout in the list of pages.
			
			tabctrl.setPageTitle <TabCtrl> <Index> <String Title>
				Sets the given pages string title.
			
			<String> tabctrl.getPageTitle <TabCtrl> <Index>
				Returns the given pages string title.
				
		Handlers:
			on <tabctrl> selected <tabindex>
				This event is fired when the user selects a tab.
			
			on <tabctrl> countchanged <count>
				When the number of pages in the control changes this will get fired with the
				new number of pages. This can be from setting the actual 'pages' property
				or calling the addPage or removePage methods.
				
			on <tabctrl> rightclick <Index>
				Fired when the right mouse button is clicked over the tab control passing
				the index of the tab the mouse was over.
				
			on <tabctrl> leftclick <Index>
				Fired when the left mouse button is clicked over the tab control passing
				the index of the tab the mouse was over.

	SPLITTER
		The Splitter control for dividing controls on a dialog or rollout. When the 
		splitter is moving or moved a callback is fired and your script can update
		the position and sizes of other controls in the dialog.

		Properties:
			<splitter>.border   -- tells the control to draw a border

			<splitter>.handles  -- tells the control to draw drag handles using the border1 and border2 colors.
				
			<splitter>.allow   -- allow draggin in this direction, can be:
									#drag_horz for horizontal
									#drag_vert for vertical
									#drag_horz_vert for both
			<splitter>.clipto   -- clips dragging to the specified rollout or dialog
			<splitter>.backColor -- background color of the control, should be the same as the dialog.
			<splitter>.borderColor1  -- left and top border color
			<splitter>.borderColor2  -- right and bottom border color
			<splitter>.realtime -- boolean, if true the control moves around
									in realtime with the mouse, otherwise
									an inverted tracker will be draw with the
									mouse.
		Handlers:
			on <splitter> dragging do	-- called while dragging the splitter and
												when realtime is set to true.
			on <splitter> dragdone do	-- called once the left mouse button has been
												let up and the dragging has finished.
	
	COOLBUTTON
		The CoolButton control is just like a regular button control but allows 
		mouse over bitmap's.

		Properties:
			<coolbutton>.images  -- image array identified as follows
									#( <bitmap file or value>,
									   <mask bitmap file or value>,
									   <number of images in bitmaps>,
									   <up index>,
									   <down index>,
									   <mouse over index>,
									   <down and out index>,
									   <disabled index> )

			<coolbutton>.tooltip		-- tooltip text, this is write only, can be used when control is defined.
			<coolbutton>.backColor		-- The buttons background color. Default to what 3dsmax uses.
			<coolbutton>.textColor		-- The buttons text color. Default to what 3dsmax uses.
			<coolbutton>.alwaysShowBorder -- Show the button border even when the mouse is not over.
			<coolbutton>.checkButton    -- Turn the coolbutton into a check button.
			<coolbutton>.checked        -- Checked state when in check button mode.
			<coolbutton>.state          -- Checked state when in check button mode.
			<coolbutton>.borderColor1	-- Color for the upper left border rectangle. Default to what 3dsmax uses.
			<coolbutton>.borderColor2	-- Color for the lower right border rectangle. Default to what 3dsmax uses.
			<coolbutton>.backColorOver  -- Backgound color when the mouse is over the button.
			<coolbutton>.textColorOver  -- Text color when the mouse is over the button.
			<coolbutton>.backColorDisabled  -- Background color when the button is disabled.
			<coolbutton>.textColorDisabled1 -- Topmost text color when the button is disabled.
			<coolbutton>.textColorDisabled2 -- Dropshadow text color when the button is disabled.
			<coolbutton>.backColorDown  -- Background color when the button is down or checked.
			<coolbutton>.textColorDown  -- Text color when the button is down or checked.
			<coolbutton>.horizontalAlignment -- Alignment can be: #align_left, #align_center, or #align_right
			<coolbutton>.verticalAlignment   -- Alignemnt can be: #align_top, #align_center, or #align_bottom
			<coolbutton>.textPadding    -- Padding offset for when alignment is set to edges (default:[4,4])
			<coolbutton>.textOffset     -- Offset in pixels after alignment (default:[0,0])
			<coolbutton>.textDownOffset -- Text offset when the button is pressed (default:[1,1])

		Handlers:
			on <coolbutton> pressed do    -- called when the left mouse button is depressed.
			on <coolbutton> mousein do    -- called when the mouse has entered the buttons area.
			on <coolbutton> mouseout do   -- called when the mouse has left the buttons area.
			on <coolbutton> leftButtonDown do    -- called when left mouse button is down.
			on <coolbutton> leftButtonUp do      -- called when left mouse button is released.
			on <coolbutton> middleButtonDown do  -- called when middle mouse button is down.
			on <coolbutton> middleButtonDown do  -- called when middle mouse button is released.
			on <coolbutton> rightButtonDown do   -- called when right mouse button is down.
			on <coolbutton> rightButtonUp do     -- called when right mouse button is released.
			on <coolbutton> changed <arg> do
				Called when in check button mode and the user clicks the check button to change its state.
				The <arg> argument will contain the new state of the check button,
				on (true) or off (false). 


	DIALOG (rollout wrapper)

	This structure allows wrapping of standard rollouts with usage to create
	modal and non-modal dialogs via the 'createDialog' MAXScript function.
	Automatic support for docking is added when the 'dockable' property is set to true.
	
	This is a genaral purpose wrapper that automatically saves and loads dialog
	state (position, size, docking, and min/maximized info).
	
	With minimal hooks placed in your rollout you get all the features described above.
	Most of the construction parameters are the same as 'createDialog' uses.
	See 'createDialog' documentation for more information on construction parameters.
	
	Construction:
	
	Dialog
		theRollout:<rollout>		-- The rollout this structure will wrap.
		pos:<Point2>				-- Position of the dialog. default:center or 3dsmax
		width:<Integer>				-- Width of the dialog. default: dialog width
		height:<Integer>			-- Height of the dialog. default: dialog height
		placement:<#minimized|#maximized|#normal>	-- This gets loaded and saved to the ini.
		bgcolor:<Color>				-- Dialog background color. default: standard background color.
		fgcolor:<Color>				-- Dialog text color. default: standard text color
		bitmap:<Bitmap>				-- Background bitmap for the dialog.
		bmpstyle:<Name>				-- default: #bmp_center
		menu:<RCMenu>				-- Menu definition to use as a dialog menu.
		style:<StyleArray>			-- default: #( #style_titlebar, #style_border, #style_sysmenu )
		escapeEnable:<Boolean>		-- Allow escape key to stop MAXScript execution: default: true
		lockHeight:<Boolean>		-- Lock the dialog height. default: false
		lockWidth:<Boolean>			-- Lock the dialog width. default: false
		clipChildren:<Boolean>		-- Clip dialog controls from the redraw area. default: false
		
		-- Dockable dialog bar params. See cui.RegisterDialogBar for more information.
		dockable:<Boolean>			-- Allow this dialog to be docked. default: false
		dockState:<Name>			-- The state the dockable dialog will be opened.
		dockStyle:<StyleArray>		-- Array of docking styles. default: #(#cui_dock_all, #cui_floatable, #cui_handles)
		dockMinSize:<Point2>		-- Minimum size the docking dialog can be. default: dialog size
		dockMaxSize:<Point2>		-- Maximum size the docking dialog can be. default: dialog size
		
		configFile:<Filename>		-- Full path name to the INI file in which settings are saved and loaded.
	
	Usage: A simple example
		The following example creates a simple resizing dialog that saves and loads
		the position and size each time it's loaded. It also returns the currently
		selected item in the list when closed.
	
	>>
		rollout TestRoll "Dialog Test" width:160 height:280
		(
			listBox theList "" pos:[8,8] width:144 height:20
			
			local theDlg = undefined
			
			on TestRoll open do
			(
				-- Get the struct that is wrapping this rollout.
				theDlg = getStructContext()		
				
				-- Get the params passed into the Dialog wrapper
				theList.items = theDlg.params
				
				-- Load dialog states
				theDlg.OnOpen()
			)
			on TestRoll close do
			(
				-- Set the result of this dialog
				theDlg.result = theList.selected
				
				-- Save dialog states
				theDlg.OnClose()
			)
		)

		dlg = Dialog theRollout:TestRoll style:#(#style_titlebar,#style_resizing,#style_sysmenu)
		dlg.DoModal params:#("Item one", "Item 2", "3")
	<<
