├── .gitignore ├── .vscode └── tasks.json ├── MCG ├── HyperClone │ ├── HyperClone_v2.0.495.mcg │ ├── Hyperclone_rollout.jpg │ ├── hyperClone.jpg │ └── old_version │ │ └── HyperClone.mcg └── SphereClone │ ├── SphereClone.jpg │ ├── SphereClone.mcg │ └── SphereClone_rolout.png ├── Max UI └── BUMP_maxcolors.clrx ├── README.md ├── Snippets ├── Send_Mail.ms └── Snippets.ms ├── assets ├── Hyperclone_rollout.jpg ├── SphereClone.jpg ├── SphereClone_rolout.png ├── advman.png ├── camtool.PNG ├── hyperClone.jpg ├── panel_cuts_intro.png ├── panel_cuts_logo.png ├── panel_cuts_ui.png └── random_detach.jpg ├── encryptFile.ms ├── libs ├── easing.ms ├── goldenProportions.ms └── menu_manager_api │ ├── menu_man_example.ms │ └── menu_manager.ms ├── release ├── Adv_path_manager.zip ├── Panel_cuts.zip ├── Photographic_composition_guides.zip ├── Random_detach.zip ├── Viewport_composition_guides.zip ├── align_assets.zip ├── arch_scaler.zip ├── audit_materials.zip ├── cam_manager.zip ├── gamma_adjustment.zip ├── mat_tools.zip ├── plugin │ └── BUMP_resizer.zip ├── random_select.zip ├── sunblind_cage_calc.zip ├── usericons │ ├── extratools_16a.bmp │ ├── extratools_16i.bmp │ ├── extratools_24a.bmp │ └── extratools_24i.bmp ├── vertex_scrambler.zip ├── vraymat_populate.zip └── xref_replace.zip └── src ├── Adv_path_manager ├── BUMP_AdvPathMngr.mcr └── BUMP_AdvPathMngr.ms ├── BUMP_ArchScaler.mcr ├── BUMP_Mat_Tools.mcr ├── BUMP_Random_select.mcr ├── BUMP_align_assets.mcr ├── BUMP_audit-materials.ms ├── BUMP_camManager.mcr ├── BUMP_gamma_adjustment.ms ├── BUMP_sunblind_cage_calc.ms ├── BUMP_vertexScrambler.mcr ├── BUMP_viewPortCompositionGuides-v1.mcr ├── BUMP_xref_replace.mcr ├── Panel_cuts ├── example │ ├── cuts_CUTS REPORT.csv │ └── panel_cuts_test.max └── src │ ├── psd │ ├── panel_cuts.psd │ ├── panel_cuts_intro.psd │ └── panel_cuts_ui.psd │ ├── scripts │ └── BUMP_panelCuts.ms │ ├── usericons │ ├── panel_cuts_16a.bmp │ ├── panel_cuts_16i.bmp │ ├── panel_cuts_24a.bmp │ └── panel_cuts_24i.bmp │ └── usermacros │ └── BUMP_pcuts.mcr ├── Photographic_composition_guides ├── Icons │ ├── vcomp_24.png │ ├── vcomp_32.png │ ├── vcomp_36.png │ └── vcomp_48.png ├── MacroScripts │ ├── BUMP_CompositionGuides.mcr │ └── BUMP_CompositionGuides_DEBUG.mcr └── Scripts │ └── vpCompositionGuides.mse ├── Random_detach ├── BUMP_Random_detach.mcr ├── BUMP_Random_detach.ms └── min │ └── min_BUMP_Random_detach.ms ├── VrayMtlPopulate ├── BUMP_VrayMtlPopulate.mcr └── BUMP_VrayMtlPopulate.ms └── plugin └── BUMP_resizer.ms /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | #ignore thumbnails created by windows 3 | Thumbs.db 4 | #Ignore files build by vscode and binaries 5 | *.exe 6 | **/min -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "label": "Encrypt file", 8 | "type": "shell", 9 | "command": "3dsmaxbatch.exe", 10 | "args": [ 11 | "'${workspaceFolder}\\encryptFile.ms'", 12 | "-mxsString", 13 | "in:'@\"${file}\"'" 14 | ], 15 | "problemMatcher": [] 16 | } 17 | ] 18 | } -------------------------------------------------------------------------------- /MCG/HyperClone/HyperClone_v2.0.495.mcg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HAG87/maxscript-assorted/962c5c5a67dac1201e0878e7f536395d815cd817/MCG/HyperClone/HyperClone_v2.0.495.mcg -------------------------------------------------------------------------------- /MCG/HyperClone/Hyperclone_rollout.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HAG87/maxscript-assorted/962c5c5a67dac1201e0878e7f536395d815cd817/MCG/HyperClone/Hyperclone_rollout.jpg -------------------------------------------------------------------------------- /MCG/HyperClone/hyperClone.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HAG87/maxscript-assorted/962c5c5a67dac1201e0878e7f536395d815cd817/MCG/HyperClone/hyperClone.jpg -------------------------------------------------------------------------------- /MCG/HyperClone/old_version/HyperClone.mcg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HAG87/maxscript-assorted/962c5c5a67dac1201e0878e7f536395d815cd817/MCG/HyperClone/old_version/HyperClone.mcg -------------------------------------------------------------------------------- /MCG/SphereClone/SphereClone.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HAG87/maxscript-assorted/962c5c5a67dac1201e0878e7f536395d815cd817/MCG/SphereClone/SphereClone.jpg -------------------------------------------------------------------------------- /MCG/SphereClone/SphereClone.mcg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HAG87/maxscript-assorted/962c5c5a67dac1201e0878e7f536395d815cd817/MCG/SphereClone/SphereClone.mcg -------------------------------------------------------------------------------- /MCG/SphereClone/SphereClone_rolout.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HAG87/maxscript-assorted/962c5c5a67dac1201e0878e7f536395d815cd817/MCG/SphereClone/SphereClone_rolout.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Free 3ds Max Tools 2 | 3 | ## MaxScript tools 4 | 5 | | File | Name | Description | 6 | | ---- | ---- | ----------- | 7 | | ../Max UI | | 3Ds Max custom dark UI scheme. | 8 | | ./usericons | UI Icons for some of the scripts | Change node XYZ dimensions. | 9 | | adv_path_manager | Advanced Paths Manager | Utility for managing user paths (beta) | 10 | | align_assets | Align assets | Rearrange nodes in a row. | 11 | | arch_scaler | Architecture Scale | Small utility to rescale nodes using an architectural scale factor. | 12 | | Audit_materials | Audit Materials | Filter objects by material | 13 | | cam_manager | Camera tools | Compact interface to manage, review, select cameras. It also can add batch render views, change resolution and aspect ratio per camera. Comes with presets for common aspect ratios. | 14 | | gamma_adjustment | | Convert Normal Maps gamma | 15 | | mat_tools | bumpTo100 | (V-ray) material Bump value to 100.0 | 16 | | mat_tools | FaceSel | Select faces with same material ID | 17 | | mat_tools | FnameToBMap | Change the names of Bitmap Textures to the name of the loaded files. | 18 | | mat_tools | MapLoader | Load multiple bitmapTextures to the slate material editor | 19 | | mat_tools | ObjIDbyCAM | Set objects ID for current camera view | 20 | | mat_tools | QIDSet | Set material IDs for selected faces | 21 | | mat_tools | Remove_mats | Remove material from selection | 22 | | mat_tools | RndIDSet | Set random material IDs for selected faces | 23 | | mat_tools | SelNoMat | Filter nodes without material in current selection. | 24 | | panel_cuts | Panel cuts | Tool for creating panel cuts reports. Useful for furniture or cabinets design. | 25 | | photographic_composition_guides | | Display photographic composition guides overlay in viewport. | 26 | | random_detach | Random Detach | Random detach **editable poly** elements. | 27 | | random_select | Random Select | Random nodes selection. | 28 | | plugin/BUMP_resizer | Resize modifier | Change node XYZ dimensions. | 29 | | vertex_scrambler | Vertex scrambler | Random shift vertex positions in a mesh. | 30 | | vraymat_populate | | Populate material editor slots with VRayMtl | 31 | | xref_replace | Replace with Xref | Replace selected node with Xref Record. | 32 | 33 | ## MCG solutions 34 | 35 | * **HyperClone**: Advanced cloning tool. 36 | * **SphereClone**: Instance objects on a spherical space or in a convex closed mesh. 37 | 38 | --- 39 | 40 | ## Install notes 41 | 42 | 1. Locate **3ds Max user folder**. Usually at: *C:\Users\USER_NAME\AppData\Local\Autodesk\3dsMax\20XX - 64bit\ENU* 43 | 2. Copy **.ms** and **.mse** to *scripts*, *.mcr* files to *usermacros* and Icons (.bmp) to *usericons* 44 | 3. Restart Max if opened 45 | 4. Add the macro to a toolbar. Found under the category "BUMP tools" 46 | 47 | --- 48 | 49 | ## Advanced path manager 50 | 51 | ![advman1](./assets/advman.png) 52 | 53 | Listview for managing External files User Paths. Listview for managing External files User Paths. 54 | It has several advantages over the the default Max´s dialog, some are: 55 | More useful UI with colors and font effects to indicate directories status, display only invalid paths, remove empty folders paths and more... 56 | 57 | ### Reference 58 | 59 | * Paths to be deleted : Marked by strikeout text. 60 | * Paths to be added : Showed on bold text. 61 | * Paths modified: Text marked with underline. 62 | * Changes are only applied when pressing "Done". 63 | 64 | --- 65 | 66 | ## Panel Cuts 67 | 68 | ![panelcuts id](./assets/panel_cuts_intro.png) 69 | 70 | Tool for creating panel cuts reports. Useful for furniture or kitchen cabinets design. 71 | 72 | ### features 73 | 74 | * Material finish, part type, description, grain orientation properties. 75 | * Sheet use report. 76 | * Export a .csv file with Part quantity, dimensions, finish, grain direction, part and description values; Import the file in a spreadsheet or cut optimization software. 77 | 78 | ### How to use 79 | 80 | ![panelcuts ui](./assets/panel_cuts_ui.png) 81 | 82 | >*In order to effectively use the tool, you will need a clean, real scale model, composed of individual objects for each piece of the model.* 83 | 84 | 1. Select the parts (individual objects making a kitchen cabinet, for example) of the model that you want to add the properties that will be used to generate the report. Press the "SELECTION" button to make all the selected objects active in the tool. Alternatively, activate the "Viewport select" toggle button if you want to pick each object alone in the Viewport. 85 | 86 | 2. Start adding properties. Grain direction will swap the piece height and width, in order to accommodate the cuts to the sheet face texture direction. "Finish" indicates the material color, skin, etc. "Part" can be used as indicative of the piece position/function (i.e. Kitchen Module 1 - Lateral stand). Once you are done, press the "commit" Button. Note: Right-click on "Commit" will apply the properties to the entire objects collection. Values entered in the textbox will be added to the below listbox. Double click on an item in the listbox to reutilize it. 87 | 88 | 3. Navigate through the objects in the collection with the previous ("<<") and next (">>") buttons. 89 | * The tool has a visual feedback, displaying as wireframe the objects in the collection and shading the current active one, also a viewport label shows the selected object dimensions. 90 | * Right click on prev. or next buttons to commit properties. 91 | 92 | 4. Utilities. 93 | * Scale units: objects are measured in current Max's active units system and scale. Use the units factor to convert stored dimensions between units. I.e: If the system scale is configured in centimeters, use a factor of 10.0 and scale up to change the measurements to millimeters. 94 | * Sheet dimensions: Generate a report of how much sheets (or sheet area) the pieces will require. Account for wastage. 95 | 96 | 5. Save to file. This is the main functionality of this tool. Export a list of the parts to a .csv file. It can be later imported in a Spreadsheet or cut optimization program. 97 | 98 | --- 99 | 100 | ## Random Detach 101 | 102 | ![Help image](./assets/random_detach.jpg) 103 | 104 | --- 105 | 106 | ## Random Select 107 | 108 | Random node selection. By percent of the selected nodes or "Dot-Gap" pattern. 109 | 110 | ### Modes 111 | 112 | * Percent: Keep a random percentage of the total quantity of nodes in the current selection. 113 | * Step: Performs a skip pattern in the selection. 114 | * Subtract: Same as percent, but inverse: deselect a random percentage within selection. 115 | * Pattern: Not a random mode; Instead it wil unselect nodes following a pattern. 116 | 117 | ### Values 118 | 119 | * Percent: Percentage of nodes quantity to be selected 120 | * Step: Quantity of objects to skip in the selection 121 | * Subtract percent: Percentage of nodes quantity to be un-selected 122 | 123 | >Note: The tool will respect the selection pick order. 124 | 125 | ### Pattern 126 | 127 | * Keep: How much objects the pattern will keep 128 | * Quit: Quantity of objects that will be deselected. 129 | 130 | >Example: 131 | >Keep: 3; Quit: 2 132 | 133 | --- 134 | -------------------------------------------------------------------------------- /Snippets/Send_Mail.ms: -------------------------------------------------------------------------------- 1 | ( 2 | -- WEBMAIL PROTOCOL 3 | struct _comSrv 4 | ( 5 | public 6 | fn composeMail body sub FromAdress ToAdress AttachFile:undefined = 7 | ( 8 | local MailMessage = dotNetObject "System.Net.Mail.MailMessage" 9 | local MailMessageFrom = dotNetObject "System.Net.Mail.MailAddress" FromAdress 10 | MailMessage.From = (dotNetObject "System.Net.Mail.MailAddress" MAIL_TO) 11 | local MailAdressTo = (dotNet.ValueToDotNetObject ToAdress (dotNetClass "System.String")) 12 | MailMessage.To.Add MailAdressTo 13 | MailMessage.CC.Add FromAdress 14 | MailMessage.Subject = if sub != undefined then sub else "no subject" 15 | MailMessage.Body = if body != undefined then body else " " 16 | if AttachFile != undefined then ( 17 | local MailAttachment = dotNetObject "System.Net.Mail.Attachment" AttachFile 18 | MailMessage.Attachments.Add(MailAttachment) 19 | ) 20 | return MailMessage 21 | ), 22 | fn MailSender MailMessage Username Password Host port ssl:true = 23 | ( 24 | Client = dotNetObject "System.Net.Mail.SmtpClient" --Host Port 25 | NetworkCred = dotNetObject "System.Net.NetworkCredential" 26 | NetworkCred.UserName = Username 27 | NetworkCred.Password = Password 28 | Client.Credentials = NetworkCred 29 | Client.Host = Host 30 | Client.Port = port --25 --587; 31 | Client.EnableSsl = ssl 32 | Client.Send MailMessage 33 | ) 34 | ) 35 | -- EXAMPLE FORM 36 | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 37 | rollout roll_email "Send Email" width:450 38 | ( 39 | fn fullWidth div:1 th:10 = 40 | ( 41 | if div > 1 then ( 42 | ( (roll_email.width - th) / div ) - (th / div) 43 | ) else ( 44 | ( (roll_email.width - th) / div ) 45 | ) 46 | ) 47 | editText txt_dest "Adress" text:"" labelOnTop:true fieldWidth:(fullWidth()-15) align:#left 48 | editText txt_cpt "Caption" text:"Send Email" labelOnTop:true fieldWidth:(fullWidth()-15) align:#left 49 | editText txt_c1 "Email text" text:("Example email body.\n" + localTime) labelOnTop:true fieldWidth:(fullWidth()-15) height:150 align:#left 50 | imgTag sep1 width:(fullWidth()) height:1 bitmap:(bitmap 1 2 color: (color 5 5 5)) align:#center 51 | label lbl_c1 "Email" align:#left across:2 52 | label lbl_c2 "Password" align:#left 53 | editText txt_c3 "" text:"mail@gmail.com" labelOnTop:true align:#left fieldWidth:200 height:20 across:2 54 | dotNetControl txt_c4 "TextBox" text:"PASSWORD" width:200 55 | imgTag sep2 width:(fullWidth()) height:1 bitmap:(bitmap 1 2 color: (color 5 5 5)) align:#center 56 | editText txt_c5 "SMTP Server" labelOnTop:true align:#left fieldWidth:220 offset:[0,5] across:3 57 | editText txt_c6 "Port" text:"587" labelOnTop:true align:#left width:35 offset:[80,5] 58 | CheckBox chk_c1 "USE SSL CONECTION" checked:true offset:[-30,24] align:#right 59 | imgTag sep3 width:(fullWidth()) height:1 bitmap:(bitmap 1 2 color: (color 5 5 5)) align:#center 60 | dotNetControl txt_c7 "label" width:220 height:16 offset:[0,5] across:2 61 | button btn_c1 "SEND" width:120 height:30 align:#right offset:[10,0] enabled:false 62 | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 63 | local SMTP = #("smtp.gmail", "smtp-mail.outlook", "smtp.live", "smtp.mail.yahoo", "smtp.btconnect", "mail.o2online", "outgoing.verizon", "smtp.zoho", "smtp.mail", "smtp.aol", "smtp.gmx") 64 | local fSMTP = for i in SMTP collect (filterString i ".") 65 | local SMTP = "smtp.gmail.com" 66 | local PORT = #("587","25") 67 | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 68 | local compose = StringStream "" 69 | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 70 | 71 | -- Automated HTML email template example. 72 | fn load_data var1 var2 var3 var5 var5 = 73 | ( 74 | format "
75 |

Hi;
EXAMPLE TEXT!

76 |
77 |

MORE EXAMPLE TEXT

78 |

VAR1: %

79 |

CONTENT TEXT:
80 | VAR2: %
81 | VAR3: %
82 | VAR4: %
83 | VAR5: %

84 |
85 |
86 |

Regards;

87 |
" VAR1 VAR2 VAR3 VAR4 VAR5 to:compose 88 | txt_c1.text = compose as string 89 | btn_c1.enabled = true 90 | ) 91 | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 92 | on roll_email open do ( 93 | -- Password of the email account 94 | txt_c4.PasswordChar = "x"; txt_c4.MaxLength = 16 95 | txt_c5.TEXT = SMTP 96 | ) 97 | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 98 | -- SSL connection option 99 | on chk_c1 changed state do (if state then txt_c6.text = PORT[1] else txt_c6.text = PORT[2]) 100 | 101 | -- email of the sender 102 | on txt_c3 changed args do ( 103 | if (MatchPattern args pattern:"*@*") == true then ( 104 | local members = filterString args "@" 105 | if members[2] != undefined then ( 106 | local 107 | provider = filterString members[2] ".", 108 | lk = _cm.arFind fSMTP (if provider[1] == "hotmail" then "live" else provider[1]), 109 | serv = if lk !=undefined then SMTP[lk], 110 | dom = if serv != undefined then substituteString members[2] provider[1] serv 111 | txt_c5.text = if dom != undefined then dom else "" 112 | ) 113 | ) 114 | ) 115 | -- compose and send the email 116 | on btn_c1 pressed do ( 117 | try ( 118 | local mailbody = _comSrv.composeMail txt_c1.text txt_cpt.text txt_c3.text txt_dest.text --AttachFile:file_attach --> you can attach a file.... 119 | 120 | _comSrv.MailSender mailbody txt_c3.text txt_c4.text txt_c5.text (execute txt_c6.text) ssl:chk_c1.state 121 | 122 | txt_c7.text = "MAIL SENT" 123 | txt_c7.BackColor = ((dotNetClass "System.Drawing.Color").Lightgreen) 124 | 125 | ) catch ( 126 | txt_c7.text = getCurrentException() 127 | txt_c7.BackColor = ((dotNetClass "System.Drawing.Color").IndianRed) 128 | ) 129 | ) 130 | ) -- END ROLLOUT -- 131 | 132 | -- load a bunch of values in the template 133 | roll_email.load_data "ONE" "TWO" "THREE" "FOUR" "FIVE" 134 | -- show the dialog 135 | CreateDialog roll_email 136 | ) -------------------------------------------------------------------------------- /Snippets/Snippets.ms: -------------------------------------------------------------------------------- 1 | /* https://atelierbump.com ~ MaxScript Snippets */ 2 | -------------------------------------------------------------------------------- 3 | /* GET A RAY PERPENDICULAR TO THE CURRENT VIEW */ 4 | fn getViewDirectionRay = 5 | ( 6 | -- The affine TM transforms from world coords to view coords 7 | -- so we need the inverse of this matrix 8 | local coordSysTM = Inverse(getViewTM()) 9 | -- The Z axis of this matrix is the view direction. 10 | local viewDir = -coordSysTM.row3 11 | -- get the view position from this matrix 12 | local viewPt = coordSysTM.row4 13 | return ray viewPt viewDir 14 | ) 15 | 16 | -------------------------------------------------------------------------------- 17 | /* SELECT ALL NODES INSIDE AN OPEN CONTAINER*/ 18 | fn cont_content c = 19 | ( 20 | if isKindOf c Container then ( 21 | local nd 22 | c.GetContentNodes true &nd 23 | selectMore nd 24 | ) 25 | ) 26 | 27 | -------------------------------------------------------------------------------- 28 | /* LIST NODE PROPERTIES */ 29 | fn props_lister obj = 30 | ( 31 | ClearListener() 32 | p_names = getPropNames obj 33 | p_str = for i in p_names collect (i as string) 34 | for i in p_str do (format "%\n" i) 35 | ) 36 | 37 | -------------------------------------------------------------------------------- 38 | /* add new layer and set options */ 39 | fn addLay obj layerName:"layer_test_" = 40 | ( 41 | if not(LayerManager.getLayerFromName layerName) then 42 | ( 43 | local refLay = LayerManager.newLayerFromName layerName 44 | refLay.showFrozenInGray=false 45 | refLay.renderable =false 46 | refLay.lock=true 47 | try (refLay.addNode obj) catch () 48 | ) 49 | ) 50 | 51 | -------------------------------------------------------------------------------- 52 | /* MATRIX FROM 3 POINTS */ 53 | fn getMatrix p1 p2 p3 = ( 54 | v1 = normalize (p2 - p1) 55 | v3 = normalize (cross v1 (normalize (p3 - p1))) 56 | v2 = normalize (cross v3 v1) 57 | return matrix3 v1 v2 v3 p1 58 | ) 59 | -------------------------------------------------------------------------------- 60 | /* RESET ROTATION */ 61 | fn resetAxisRot obj axis:x = ( 62 | local objTM = obj.transform 63 | local objTR = obj.position 64 | local objRot = objTM.rotationpart 65 | local deg = objRot as EulerAngles 66 | case axis of ( 67 | x: deg.x = 0 68 | y: deg.y = 0 69 | z: deg.z = 0 70 | ) 71 | local rm = (deg as Quat) as Matrix3 72 | local newTM = rm 73 | newTM.row4 = objTR 74 | obj.transform = newTM 75 | ) 76 | 77 | -------------------------------------------------------------------------------- 78 | /* set Obj ID relative to camera distance */ 79 | fn setObjID = 80 | ( 81 | local cam = getActiveCamera() 82 | if cam != undefined then ( 83 | local bbx = box2 [0,0] [gw.getWinSizeX(),gw.getWinSizeY()] 84 | local objsel = boxPickNode bbx 85 | local campos = cam.pos 86 | fn compareFN v1 v2 ref: = 87 | ( 88 | local a = distance ref v1.pos 89 | local b = distance ref v2.pos 90 | local d = a - b 91 | case of 92 | ( 93 | (d < 0.): -1 94 | (d > 0.): 1 95 | default: 0 96 | ) 97 | ) 98 | qsort objsel compareFN ref:campos 99 | for i=1 to objsel.count do ( 100 | objsel[i].gbufferChannel = i 101 | ) 102 | 103 | ) 104 | ) 105 | 106 | -------------------------------------------------------------------------------- 107 | /* SELECT ALL NODES WITHOUT MATERIAL*/ 108 | fn sel_nomat = 109 | ( 110 | local sel = getCurrentSelection() 111 | local nomat = for i in sel where (i.material == undefined and not (isgrouphead i)) collect i 112 | select nomat 113 | ) 114 | 115 | -------------------------------------------------------------------------------- 116 | /* QUICK ALIGN TO CURRENT COORDINATE SYSTEM */ 117 | mapped fn alignToCPTM obj = 118 | ( 119 | if isValidNode obj then 120 | ( 121 | local tm = obj.transform 122 | local stm = getCPTM() 123 | local irot = ( tm * (inverse stm) ).rotationpart 124 | -- transform 125 | obj.transform = preRotate tm (inverse irot) 126 | --node.transform *= xformmat (scalematrix sc) (inverse spaceTM) 127 | --obj.transform = obj.transform * (inverse spaceTM) * (scalematrix sc) * spaceTM 128 | ) 129 | ) 130 | 131 | -------------------------------------------------------------------------------- 132 | -------------------------------------------------------------------------------- /assets/Hyperclone_rollout.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HAG87/maxscript-assorted/962c5c5a67dac1201e0878e7f536395d815cd817/assets/Hyperclone_rollout.jpg -------------------------------------------------------------------------------- /assets/SphereClone.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HAG87/maxscript-assorted/962c5c5a67dac1201e0878e7f536395d815cd817/assets/SphereClone.jpg -------------------------------------------------------------------------------- /assets/SphereClone_rolout.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HAG87/maxscript-assorted/962c5c5a67dac1201e0878e7f536395d815cd817/assets/SphereClone_rolout.png -------------------------------------------------------------------------------- /assets/advman.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HAG87/maxscript-assorted/962c5c5a67dac1201e0878e7f536395d815cd817/assets/advman.png -------------------------------------------------------------------------------- /assets/camtool.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HAG87/maxscript-assorted/962c5c5a67dac1201e0878e7f536395d815cd817/assets/camtool.PNG -------------------------------------------------------------------------------- /assets/hyperClone.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HAG87/maxscript-assorted/962c5c5a67dac1201e0878e7f536395d815cd817/assets/hyperClone.jpg -------------------------------------------------------------------------------- /assets/panel_cuts_intro.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HAG87/maxscript-assorted/962c5c5a67dac1201e0878e7f536395d815cd817/assets/panel_cuts_intro.png -------------------------------------------------------------------------------- /assets/panel_cuts_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HAG87/maxscript-assorted/962c5c5a67dac1201e0878e7f536395d815cd817/assets/panel_cuts_logo.png -------------------------------------------------------------------------------- /assets/panel_cuts_ui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HAG87/maxscript-assorted/962c5c5a67dac1201e0878e7f536395d815cd817/assets/panel_cuts_ui.png -------------------------------------------------------------------------------- /assets/random_detach.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HAG87/maxscript-assorted/962c5c5a67dac1201e0878e7f536395d815cd817/assets/random_detach.jpg -------------------------------------------------------------------------------- /encryptFile.ms: -------------------------------------------------------------------------------- 1 | (encryptScript maxOps.mxsCmdLineArgs[#in]) -------------------------------------------------------------------------------- /libs/easing.ms: -------------------------------------------------------------------------------- 1 | -- Ease-In Algorithm in MaxScript 2 | ( 3 | struct easing 4 | ( 5 | -- Function to calculate ease-in based on a cubic function 6 | fn easeInCubic t = t^3, 7 | 8 | -- Function to calculate ease-in based on a quadratic function 9 | fn easeInQuad t = t^2, 10 | 11 | -- Function to calculate ease-in based on a sinusoidal function 12 | fn easeInSine t = 13 | ( 14 | 1 - cos (t * pi / 2.0) 15 | ), 16 | 17 | -- Function to calculate ease-in based on an exponential function 18 | fn easeInExpo t = 19 | ( 20 | if t == 0 then 0 else (2.0 ^ (10 * (t - 1))) 21 | ), 22 | 23 | -- Function to calculate ease-in based on a circular function 24 | fn easeInCirc t = 25 | ( 26 | if t == (t as integer == 1) then 1 else 1 - sqrt (1 - t * t) 27 | t 28 | ), 29 | 30 | -- Function to calculate ease-in based on a back function 31 | fn easeInBack t s:1.70158 = 32 | ( 33 | t^2 * ((s + 1) * t - s) 34 | ), 35 | -- Function to calculate ease-out based on a bounce function (used for ease-in bounce) 36 | fn easeOutBounce t = 37 | ( 38 | if t < (1 / 2.75) then 39 | 7.5625 * t^2 40 | else if t < (2 / 2.75) then 41 | ( 42 | t = t - (1.5 / 2.75) 43 | 7.5625 * t^2 + 0.75 44 | ) 45 | else if t < (2.5 / 2.75) then 46 | ( 47 | t = t - (2.25 / 2.75) 48 | 7.5625 * t^2 + 0.9375 49 | ) 50 | else 51 | ( 52 | t = t - (2.625 / 2.75) 53 | 7.5625 * t^2 + 0.984375 54 | ) 55 | ), 56 | -- Function to calculate ease-in based on a bounce function 57 | fn easeInBounce t = 58 | ( 59 | 1 - easeOutBounce (1 - t) 60 | ), 61 | -- Function to interpolate between two values using an easing function 62 | fn interpolateEase startValue endValue t easingFunction = 63 | ( 64 | local delta = endValue - startValue 65 | local easedT = easingFunction t 66 | startValue + delta * easedT 67 | ) 68 | 69 | ) 70 | ) 71 | ea = easing() 72 | -- Test the ease-in functions 73 | /* 74 | for t = 0.0 to 1.0 by 0.1 do 75 | ( 76 | -- format "t: % - EaseInCubic: %\n" t (ea.easeInCubic t) 77 | -- format "t: % - EaseInQuad: %\n" t (ea.easeInQuad t) 78 | -- format "t: % - EaseInSine: %\n" t (ea.easeInSine t) 79 | -- format "t: % - EaseInExpo: %\n" t (ea.easeInExpo t) 80 | -- format "t: % - EaseInCirc: %\n" t (ea.easeInCirc t) 81 | -- format "t: % - EaseInBack: %\n" t (ea.easeInBack t) 82 | -- format "t: % - EaseInBounce: %\n" t (ea.easeInBounce t) 83 | ea.interpolateEase 0.0 1.0 t easeInBounce 84 | ) 85 | */ -------------------------------------------------------------------------------- /libs/goldenProportions.ms: -------------------------------------------------------------------------------- 1 | struct goldenProportions 2 | ( 3 | private 4 | fn phivalue = phi = (1 + sqrt 5) / 2.0, 5 | rects, 6 | public 7 | phi = phivalue(), 8 | private 9 | -- PhiRectangles bounds: the golden ratio rectangle 10 | fn goldenRectangleBounds viewSize margin_vertical:0.0 margin_horizontal:0.0 = 11 | ( 12 | -- the rectangle 13 | local rec = boxmodel() 14 | -- rectangle size 15 | if (viewSize.w > viewSize.h) then 16 | ( 17 | -- horizontal rectangle 18 | rec.orient = 0 19 | 20 | if (viewSize.w / viewSize.h as float) > phi then 21 | ( 22 | rec.h = viewSize.h 23 | rec.w = viewSize.h * phi 24 | ) else ( 25 | rec.w = viewSize.w 26 | rec.h = viewSize.w / phi 27 | ) 28 | ) else ( 29 | -- vertical rectangle 30 | rec.orient = 1 31 | 32 | if (viewSize.h / viewSize.w as float) > phi then 33 | ( 34 | rec.w = viewSize.w 35 | rec.h = viewSize.w * phi 36 | ) else ( 37 | rec.h = viewSize.h 38 | rec.w = viewSize.h / phi 39 | ) 40 | ) 41 | -- margins 42 | rec.h += margin_vertical 43 | rec.w += margin_horizontal 44 | -- center the Rectangle 45 | rec.x = (viewSize.x + (viewSize.w - rec.w) / 2.0) as integer 46 | rec.y = (viewSize.y + (viewSize.h - rec.h) / 2.0) as integer 47 | -- other values 48 | rec.refPoint = [rec.x, rec.y, 0] 49 | rec.basepoint = rec.refPoint 50 | -- the rectangle object 51 | rec 52 | ), 53 | -- PhiRectangles iterator. 54 | fn PhiRectangles &rects limit:1.0 = 55 | ( 56 | -- draw the rectangle here ? 57 | -- last value 58 | local last = rects[rects.count] 59 | -- proceed until the rectangle is 1x1px in size... 60 | if (last.w > limit) OR (last.h > limit) then ( 61 | local curr = deepCopy last 62 | 63 | case last.orient of ( 64 | 0: 65 | ( 66 | curr.refpoint = [last.x, last.y + last.h, 0] 67 | curr.x += last.h 68 | curr.w -= last.h 69 | curr.basePoint = [curr.x, curr.y + curr.h,0] 70 | curr.orient = 1 71 | ) 72 | 1: 73 | ( 74 | curr.refpoint = [last.x, last.y, 0] 75 | curr.y += last.w 76 | curr.h -= last.w 77 | curr.basePoint = [curr.x, curr.y,0] 78 | curr.orient = 2 79 | ) 80 | 2: 81 | ( 82 | curr.refpoint = [last.x + last.w, last.y, 0] 83 | curr.w -= last.h 84 | curr.basePoint = [curr.x + curr.w, curr.y,0] 85 | curr.orient = 3 86 | ) 87 | 3: 88 | ( 89 | curr.refpoint = [last.x + last.w, last.y + last.h, 0] 90 | curr.h -= last.w 91 | curr.basePoint = [curr.x+last.w, curr.y+curr.h,0] 92 | curr.orient = 0 93 | ) 94 | ) 95 | -- add to collection 96 | append rects curr 97 | -- ITERATE 98 | PhiRectangles &rects limit:limit 99 | ) 100 | ), 101 | -- interpolate arc points 102 | fn arcGen bp radius start:0 end:360 res:1 = 103 | ( 104 | for i=start to end by res collect [(cos i), (sin i), 0.0] * radius + bp 105 | ), 106 | public 107 | -- generate the golden rectangles collection 108 | fn goldenRectangles sizebox margin_vertical:0.0 margin_horizontal:0.0 = 109 | ( 110 | if classOf sizebox == Box2 then ( 111 | -- start 112 | local rects = #( goldenRectangleBounds sizebox margin_vertical:margin_vertical margin_horizontal:margin_horizontal ) 113 | -- iterate 114 | PhiRectangles &rects 115 | -- return 116 | rects 117 | ) else undefined 118 | ), 119 | -- draw rectilinear spiral 120 | fn sqSpiral golden_rects = 121 | ( 122 | for r=2 to golden_rects.count collect golden_rects[r].refPoint 123 | ), 124 | -- draw quasi-spiral conformed by arcs 125 | fn arcSpiral golden_rects res:1 = 126 | ( 127 | local res = #() 128 | for r=2 to golden_rects.count do ( 129 | local radius = distance golden_rects[r].basePoint golden_rects[r].refPoint 130 | local arcpoints = 131 | case golden_rects[r].orient of ( 132 | 0:( arcGen (golden_rects[r].basePoint) radius start:90 end:180 ) 133 | 1:( arcGen (golden_rects[r].basePoint) radius start:180 end:270 ) 134 | 2:( arcGen (golden_rects[r].basePoint) radius start:270 end:360 ) 135 | 3:( arcGen (golden_rects[r].basePoint) radius start:0 end:90 ) 136 | ) 137 | join res arcpoints 138 | ) 139 | res 140 | ) 141 | ) -------------------------------------------------------------------------------- /libs/menu_manager_api/menu_man_example.ms: -------------------------------------------------------------------------------- 1 | dstlbxMenu = menu_man.generate_menu "DesignToolBox" classid:0x6cc645b8 2 | if dstlbxMenu != undefined then ( 3 | --------- refGuides 4 | menu_man.item_create_add dstlbxMenu "BUMP_refGuides_noUI_free_cont" "BUMP refGuides" title:"Reference guide - free space" 5 | menu_man.item_create_add dstlbxMenu "BUMP_refGuides_noUI_ortho_cont" "BUMP refGuides" title:"Reference guide - orhtogonal" 6 | menu_man.item_create_add dstlbxMenu "BUMP_refGuides_noUI_polar_cont" "BUMP refGuides" title:"Reference guide - polar" 7 | menu_man.menu_separator dstlbxMenu 8 | menu_man.item_create_add dstlbxMenu "BUMP_refGuides_Li2" "BUMP refGuides" title:"Display ref. guides units" 9 | menu_man.item_create_add dstlbxMenu "BUMP_refGuides_delete" "BUMP refGuides" title:"Delete all reference objects" 10 | menu_man.menu_separator dstlbxMenu 11 | --------- 12 | local Rg_mnu = menu_man.item_submenu_create "refGuides tools" 13 | menu_man.item_create_add Rg_mnu "BUMP_refGuides_prot_free" "BUMP refGuides" title:"Reference protractor - free space" 14 | menu_man.item_create_add Rg_mnu "BUMP_refGuides_prot_ortho" "BUMP refGuides" title:"Reference protractor - orthogonal" 15 | menu_man.item_create_add Rg_mnu "BUMP_refGuides_prot_polar" "BUMP refGuides" title:"Reference protractor - polar" 16 | menu_man.menu_separator Rg_mnu 17 | menu_man.item_create_add Rg_mnu "BUMP_refGuides_UI_free" "BUMP refGuides" title:"Reference guide - free space - UI" 18 | menu_man.item_create_add Rg_mnu "BUMP_refGuides_UI_ortho" "BUMP refGuides" title:"Reference guide - orthogonal - UI" 19 | menu_man.item_create_add Rg_mnu "BUMP_refGuides_UI_polar" "BUMP refGuides" title:"Reference guide - polar - UI" 20 | menu_man.menu_separator Rg_mnu 21 | menu_man.item_create_add Rg_mnu "rG_ribbon_intPoints" "BUMP refGuides" title:"Enlable intersection points" 22 | menu_man.item_create_add Rg_mnu "rG_ribbon_Prot" "BUMP refGuides" title:"Enable protractor creation" 23 | menu_man.item_create_add Rg_mnu "rG_ribbon_LkGuides" "BUMP refGuides" title:"Lock reference objects" 24 | menu_man.item_create_add Rg_mnu "rG_ribbon_pGrid" "BUMP refGuides" title:"Enable working grid from polar" 25 | menu_man.item_create_add Rg_mnu "rG_ribbon_IntMode" "BUMP refGuides" title:"Intersection points - All vs Current" 26 | menu_man.menu_separator Rg_mnu 27 | menu_man.item_create_add Rg_mnu "BUMP_refGuides_Li" "BUMP refGuides" title:"Display units for selected guide" 28 | menu_man.menu_separator Rg_mnu 29 | menu_man.item_create_add Rg_mnu "BUMP_HGScale" "BUMP refGuides" title:"Display Home Grid units" 30 | menu_man.item_create_add Rg_mnu "BUMP_infotool" "BUMP refGuides" title:"Spatial Info tool" 31 | menu_man.item_create_add Rg_mnu "BUMP_Zpos" "BUMP refGuides" title:"Node Z position Info tool" 32 | menu_man.menu_add_submenu dstlbxMenu Rg_mnu 33 | --------- 34 | menu_man.menu_separator dstlbxMenu 35 | --------- Transform 36 | menu_man.item_create_add dstlbxMenu "BUMP_Lrotator" "BUMP DesignToolbox" title:"Rotation - local reference" 37 | menu_man.item_create_add dstlbxMenu "BUMP_rotator" "BUMP DesignToolbox" title:"Rotation - 3 axis mode" 38 | menu_man.item_create_add dstlbxMenu "BUMP_scale" "BUMP DesignToolbox" title:"Reference scale" 39 | menu_man.item_create_add dstlbxMenu "BUMP_scale_distance" "BUMP DesignToolbox" title:"Scale by dimension" 40 | menu_man.item_create_add dstlbxMenu "BUMP_offset" "BUMP DesignToolbox" title:"Adv. Position Offset" 41 | menu_man.menu_separator dstlbxMenu 42 | --------- 43 | local Tr_mnu = menu_man.item_submenu_create "Transform tools" 44 | menu_man.item_create_add Tr_mnu "BUMP_scale_xform" "BUMP DesignToolbox" title:"Reference scale - xForm mod." 45 | menu_man.item_create_add Tr_mnu "BUMP_moveAround" "BUMP DesignToolbox" title:"Move around and clone" 46 | menu_man.item_create_add Tr_mnu "BUMP_rndTrs" "BUMP tools" title:"Random transform" 47 | menu_man.menu_add_submenu dstlbxMenu Tr_mnu 48 | --------- 49 | menu_man.menu_separator dstlbxMenu 50 | --------- Measure 51 | menu_man.item_create_add dstlbxMenu "BUMP_Qmeasure" "BUMP DesignToolbox" title:"Measure units" 52 | menu_man.item_create_add dstlbxMenu "BUMP_Qmeasure_mult" "BUMP DesignToolbox" title:"Chain measure" 53 | menu_man.menu_separator dstlbxMenu 54 | menu_man.item_create_add dstlbxMenu "BUMP_Divider" "BUMP DesignToolbox" title:"Distance divider" 55 | menu_man.menu_separator dstlbxMenu 56 | --------- 57 | local Ms_mnu = menu_man.item_submenu_create "Measure tools" 58 | menu_man.item_create_add Ms_mnu "BUMP_Qangle" "BUMP DesignToolbox" title:"Angle measure" 59 | menu_man.item_create_add Ms_mnu "BUMP_Qarea" "BUMP DesignToolbox" title:"2D Area measure" 60 | menu_man.item_create_add Ms_mnu "BUMP_Qvolume" "BUMP DesignToolbox" title:"Cubic volume" 61 | menu_man.menu_separator Ms_mnu 62 | menu_man.item_create_add Ms_mnu "BUMP_clonebtwn" "BUMP DesignToolbox" title:"Clone between" 63 | menu_man.item_create_add Ms_mnu "BUMP_Divider_imput" "BUMP DesignToolbox" title:"Distance divider - imput" 64 | menu_man.menu_add_submenu dstlbxMenu Ms_mnu 65 | --------- 66 | menu_man.menu_separator dstlbxMenu 67 | menu_man.item_create_add dstlbxMenu "BUMP_distListener" "BUMP DesignToolbox" title:"Measure listener" 68 | menu_man.menu_separator dstlbxMenu 69 | --------- Eyedropper 70 | menu_man.item_create_add dstlbxMenu "BUMP_replicator" "BUMP DesignToolbox" title:"Replicator" 71 | menu_man.item_create_add dstlbxMenu "BUMP_edrpAll" "BUMP DesignToolbox" title:"Eyedropper" 72 | menu_man.item_create_add dstlbxMenu "BUMP_edrp_flt" "BUMP DesignToolbox" title:"Eyedropper filters" 73 | menu_man.menu_separator dstlbxMenu 74 | --------- 75 | local Rep_mnu = menu_man.item_submenu_create "Replicators" 76 | menu_man.item_create_add Rep_mnu "BUMP_edrpTr" "BUMP DesignToolbox" title:"Eyedropper - Transform" 77 | menu_man.item_create_add Rep_mnu "BUMP_edrpMt" "BUMP DesignToolbox" title:"Eyedropper - Material" 78 | menu_man.item_create_add Rep_mnu "BUMP_edrpMd" "BUMP DesignToolbox" title:"Eyedropper - Modifiers" 79 | menu_man.item_create_add Rep_mnu "BUMP_edrpUV" "BUMP DesignToolbox" title:"Eyedropper - UVW data or modifiers" 80 | menu_man.item_create_add Rep_mnu "BUMP_edrpVis" "BUMP DesignToolbox" title:"Eyedropper - Visual properties" 81 | menu_man.menu_separator Rep_mnu 82 | menu_man.item_create_add Rep_mnu "BUMP_rep_mt" "BUMP DesignToolbox" title:"Replicator - multi target" 83 | menu_man.item_create_add Rep_mnu "BUMP_rep_grp" "BUMP DesignToolbox" title:"Replicator - group replace mode" 84 | menu_man.item_create_add Rep_mnu "BUMP_rep_tm" "BUMP DesignToolbox" title:"Replicate transform" 85 | menu_man.item_create_add Rep_mnu "BUMP_rep_inst" "BUMP DesignToolbox" title:"Propagate instances" 86 | menu_man.item_create_add Rep_mnu "BUMP_edrp_mt" "BUMP DesignToolbox" title:"Eyedropper - multi target" 87 | menu_man.menu_add_submenu dstlbxMenu Rep_mnu 88 | --------- 89 | menu_man.menu_separator dstlbxMenu 90 | --------- Tools 91 | menu_man.item_create_add dstlbxMenu "BUMP_PARR" "BUMP DesignToolbox" title:"Patern array" 92 | menu_man.item_create_add dstlbxMenu "BUMP_IARR" "BUMP DesignToolbox" title:"3D Array" 93 | menu_man.menu_separator dstlbxMenu 94 | menu_man.item_create_add dstlbxMenu "BUMP_unhider" "BUMP DesignToolbox" title:"Unhide by selection" 95 | menu_man.item_create_add dstlbxMenu "BUMP_unfrozer" "BUMP DesignToolbox" title:"Unfreeze by selection" 96 | menu_man.item_create_add dstlbxMenu "BUMP_refIsolate" "BUMP DesignToolbox" title:"Local coords. Isolation" 97 | menu_man.menu_separator dstlbxMenu 98 | --------- Pivot 99 | local Pivot_mnu = menu_man.item_submenu_create "Pivot tools" 100 | menu_man.item_create_add Pivot_mnu "BUMP_QPVT" "BUMP DesignToolbox" title:"Quick pivot UI" 101 | menu_man.menu_separator Pivot_mnu 102 | -- menu_man.item_create_add Pivot_mnu "BUMP_QPVT_pnt" "BUMP DesignToolbox" title:"Pivot to point" 103 | menu_man.item_create_add Pivot_mnu "BUMP_QPVT_btn" "BUMP DesignToolbox" title:"Pivot to bottom" 104 | menu_man.item_create_add Pivot_mnu "BUMP_QPVT_3p" "BUMP DesignToolbox" title:"Pivot from 3 points" 105 | menu_man.item_create_add Pivot_mnu "BUMP_QPVT_3pWP" "BUMP DesignToolbox" title:"Working pivot from 3 points" 106 | menu_man.item_create_add Pivot_mnu "BUMP_QPVT_sf" "BUMP DesignToolbox" title:"Pivot from selected faces" 107 | menu_man.menu_add_submenu dstlbxMenu Pivot_mnu 108 | --------- 109 | menu_man.menu_separator dstlbxMenu 110 | --------- Objects 111 | menu_man.item_create_add dstlbxMenu "BUMP_PN" "BUMP DesignToolbox" title:"Paneling tool" 112 | menu_man.item_create_add dstlbxMenu "BUMP_MMap" "BUMP DesignToolbox" title:"UVW map tool" 113 | --------- 114 | local Util_mnu = menu_man.item_submenu_create "Utilities" 115 | menu_man.item_create_add Util_mnu "BUMP_PNDT" "BUMP DesignToolbox" title:"Add details tool" 116 | menu_man.item_create_add Util_mnu "BUMP_mapTools" "BUMP DesignToolbox" title:"UVW gizmo tools" 117 | menu_man.item_create_add Util_mnu "BUMP_snapSets" "BUMP tools" title:"Save snap states" 118 | menu_man.item_create_add Util_mnu "BUMP_cclp" "BUMP tools" title:"Color clipboard" 119 | menu_man.item_create_add Util_mnu "BUMP_rndTrs" "BUMP tools" title:"Random Transformations" 120 | menu_man.menu_add_submenu dstlbxMenu Util_mnu 121 | --------- 122 | menu_man.menu_separator dstlbxMenu 123 | --------- 124 | local Lks_mnu = menu_man.item_submenu_create "Transform locks" 125 | menu_man.item_create_add Lks_mnu "BUMP_Locks_all" "BUMP DesignToolbox" title:"Lock All" 126 | menu_man.item_create_add Lks_mnu "BUMP_Locks_pos" "BUMP DesignToolbox" title:"Lock position" 127 | menu_man.item_create_add Lks_mnu "BUMP_Locks_rot" "BUMP DesignToolbox" title:"Lock rotation" 128 | menu_man.item_create_add Lks_mnu "BUMP_Locks_scale" "BUMP DesignToolbox" title:"Lock scale" 129 | menu_man.menu_add_submenu dstlbxMenu Lks_mnu 130 | --------- 131 | menu_man.menu_separator dstlbxMenu 132 | --------- Layers 133 | local Layers_mnu = menu_man.item_submenu_create "Layer tools" 134 | menu_man.item_create_add Layers_mnu "BUMP_layIso" "BUMP DesignToolbox" title:"Isolate layer" 135 | menu_man.menu_separator Layers_mnu 136 | menu_man.item_create_add Layers_mnu "BUMP_layProp1" "BUMP DesignToolbox" title:"Layer lock" 137 | menu_man.item_create_add Layers_mnu "BUMP_layProp2" "BUMP DesignToolbox" title:"layer ON/OFF" 138 | menu_man.item_create_add Layers_mnu "BUMP_layProp3" "BUMP DesignToolbox" title:"Layer box mode" 139 | menu_man.item_create_add Layers_mnu "BUMP_layProp4" "BUMP DesignToolbox" title:"Layer backface cull" 140 | menu_man.menu_add_submenu dstlbxMenu Layers_mnu 141 | --------- 142 | menu_man.menu_separator dstlbxMenu 143 | ---------- 144 | local cfg_mnu = menu_man.item_submenu_create "Configuration" 145 | menu_man.item_create_add cfg_mnu "BUMP_cfg" "BUMP DesignToolbox" title:"DesignToolBox settings" 146 | menu_man.item_create_add cfg_mnu "BUMP_refGuides_config" "BUMP refGuides" title:"refGuides settings" 147 | menu_man.menu_add_submenu dstlbxMenu cfg_mnu 148 | --------- 149 | menu_man.menu_separator dstlbxMenu 150 | --------- 151 | local help_mnu = menu_man.item_submenu_create "Help" 152 | menu_man.item_create_add help_mnu "DTLBX_ACT" "BUMP DesignToolbox" 153 | menu_man.item_create_add help_mnu "DTLBX_DOCS" "BUMP DesignToolbox" 154 | menu_man.item_create_add help_mnu "DTLBX_ABOUT" "BUMP DesignToolbox" 155 | menu_man.menu_add_submenu dstlbxMenu help_mnu 156 | --------- 157 | -- */ 158 | 159 | /* 160 | local flt_mnu = menuMan.createMenu "UI Floaters" 161 | create_add flt_mnu "BUMP_rG_fltUI" "BUMP refGuides" title:"refGuides floater" 162 | create_add flt_mnu "BUMP_dS_fltUI" "BUMP DesignToolbox" title:"DesignToolBox floater" 163 | add_mnu dstlbxMenu ( menuMan.createSubMenuItem "UI Floaters" flt_mnu) 164 | */ 165 | ------------------------------------- 166 | -- redraw the menu bar with the new item 167 | menuMan.updateMenuBar() 168 | ) 169 | -------------------------------------------------------------------------------- /libs/menu_manager_api/menu_manager.ms: -------------------------------------------------------------------------------- 1 | /* 2 | ------------------------------------------------------------------------------------------------------------- 3 | http://help.autodesk.com/view/3DSMAX/2018/ENU/?guid=__files_GUID_258F6015_6B45_4A87_A7F5_BB091A2AE065_htm 4 | 5 | MENU STRUCTURE 6 | --------------- 7 | mainMenubar 8 | -Menu-registered 9 | - Item-action 10 | - Item-action 11 | - Item-submenu 12 | - Item-action 13 | - Item-submenu 14 | - Item-action 15 | - ... 16 | - ... 17 | - ... 18 | ------------------------------------------------------------------------------------------------------------- 19 | */ 20 | ( 21 | struct menuMan_api 22 | ( 23 | /* 24 | - if is sucessfull... you can register a new menu in that context 25 | - if fails, either the context can't be registered or has already been defined 26 | - The context is unique for each menu 27 | - Use (genClassID())[1] to genereate a classID 28 | */ 29 | fn register_menu_context classid: = 30 | ( 31 | local res = false 32 | try ( 33 | res = menuMan.registerMenuContext classid 34 | ) catch ( 35 | format "%\n" (getCurrentException()) 36 | return false 37 | ) 38 | res 39 | ), 40 | -- Menu needs to be created to be able to add items to it 41 | fn menu_create_main title = 42 | ( 43 | local mainMenuBar = menuMan.getMainMenuBar() 44 | local m = menuMan.createMenu title 45 | -- menu needs to be registered as submenu of the mainMenuBar 46 | local subMenuItem = menuMan.createSubMenuItem title m 47 | local subMenuIndex = mainMenuBar.numItems() - 1 48 | mainMenuBar.addItem subMenuItem subMenuIndex 49 | menuMan.updateMenuBar() 50 | m 51 | ), 52 | fn item_submenu_create title = 53 | ( 54 | if title != "" then menuMan.createMenu title 55 | ), 56 | fn item_action_create ms_name ms_cat title: = 57 | ( 58 | local item = menuMan.createActionItem ms_name ms_cat 59 | if title != unsupplied and title != "" then ( 60 | item.setTitle title 61 | item.setUseCustomTitle true 62 | ) 63 | item 64 | ), 65 | -- Items can be either an or a 66 | fn menu_add_item menu item = 67 | ( 68 | menu.addItem item (-1) 69 | item 70 | ), 71 | fn menu_add_submenu menu submenu title: = 72 | ( 73 | local the_title = if title == unsupplied then submenu.getTitle() else title 74 | this.menu_add_item menu (menuMan.createSubMenuItem the_title submenu) 75 | ), 76 | fn item_create_add menu ms_name ms_cat title: = 77 | ( 78 | local item = this.item_action_create ms_name ms_cat title:title 79 | this.menu_add_item menu item 80 | item 81 | ), 82 | fn menu_separator menu = 83 | ( 84 | menu.addItem (menuMan.createSeparatorItem()) (-1) 85 | ), 86 | fn menu_find_in_bar title = 87 | ( 88 | local mainMenuBar = menuMan.getMainMenuBar() 89 | local counter = mainMenuBar.numItems() 90 | local mnu_in_bar = false 91 | do ( 92 | local item = mainMenuBar.getItem counter 93 | local t = item.getTitle() 94 | if t == title then ( 95 | mnu_in_bar = true 96 | counter = 0 97 | ) else counter -= 1 98 | ) while (counter > 1) 99 | mnu_in_bar 100 | ), 101 | fn menu_register menu title = 102 | ( 103 | -- check if exist in the MainMenu, if not, add it 104 | local menu_in_bar = this.menu_find_in_bar title 105 | if not mnu_in_bar then ( 106 | local subMenuItem = menuMan.createSubMenuItem title menu 107 | -- compute the index of the next-to-last menu item in the main menu bar 108 | local subMenuIndex = mainMenuBar.numItems() - 1 109 | -- Add the sub-menu just at the second to last slot 110 | mainMenuBar.addItem subMenuItem subMenuIndex 111 | menuMan.updateMenuBar() 112 | ) 113 | mnu_in_bar 114 | ), 115 | fn menu_reset title = 116 | ( 117 | local the_menu = menuMan.findMenu title 118 | if the_menu != undefined then ( 119 | local menu_itemcount = the_menu.numItems(); 120 | if menu_itemcount > 0 then ( 121 | -- Remove menu items 122 | for i = menu_itemcount to 1 by -1 do ( 123 | local item = the_menu.getItem i 124 | -- if is a submenu... unimplemented 125 | -- local submenu = item.getSubMenu() 126 | the_menu.removeItem item 127 | ) 128 | menuMan.updateMenuBar() 129 | ) 130 | ) 131 | ), 132 | fn menu_remove title = 133 | ( 134 | local res = false 135 | local the_menu = menuMan.findMenu title 136 | if the_menu != undefined then 137 | ( 138 | local menu_itemcount = the_menu.numItems(); 139 | if menu_itemcount > 0 then ( 140 | -- Remove menu items 141 | for i = menu_itemcount to 1 by -1 do ( 142 | local item = the_menu.getItem i 143 | -- if is a submenu... unimplemented 144 | -- local submenu = item.getSubMenu() 145 | the_menu.removeItem item 146 | ) 147 | -- unregister the menu 148 | -- This method allows you to remove a menu form the mananger. Returns false if the menu was not registered, true if successfully unregistered. 149 | -- menu: Points to the menu to unregister. 150 | -- menuMan.unRegisterMenu menu 151 | res = menuMan.unRegisterMenu the_menu 152 | menuMan.updateMenuBar() 153 | ) 154 | ) 155 | res 156 | ), 157 | fn generate_menu title classid: = 158 | ( 159 | local try_to_register = this.register_menu_context classid:classid 160 | local the_menu 161 | if try_to_register then ( 162 | -- if context successful... 163 | the_menu = this.menu_create_main title 164 | ) else ( 165 | -- context can exist but the menu can be deleted so... 166 | -- Check if menu exists 167 | the_menu = menuMan.findMenu title 168 | if (the_menu != undefined) then ( 169 | -- reset the menu or remove the menu 170 | -- this.menu_reset title 171 | this.menu_remove title 172 | -- register menu again 173 | this.register_menu_context classid:classid 174 | the_menu = this.menu_create_main title 175 | ) else ( 176 | the_menu = this.menu_create_main title 177 | ) 178 | ) 179 | menuMan.updateMenuBar() 180 | the_menu 181 | ) 182 | ) 183 | -- END STRUCT -- 184 | menuMan_api() 185 | ) -------------------------------------------------------------------------------- /release/Adv_path_manager.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HAG87/maxscript-assorted/962c5c5a67dac1201e0878e7f536395d815cd817/release/Adv_path_manager.zip -------------------------------------------------------------------------------- /release/Panel_cuts.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HAG87/maxscript-assorted/962c5c5a67dac1201e0878e7f536395d815cd817/release/Panel_cuts.zip -------------------------------------------------------------------------------- /release/Photographic_composition_guides.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HAG87/maxscript-assorted/962c5c5a67dac1201e0878e7f536395d815cd817/release/Photographic_composition_guides.zip -------------------------------------------------------------------------------- /release/Random_detach.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HAG87/maxscript-assorted/962c5c5a67dac1201e0878e7f536395d815cd817/release/Random_detach.zip -------------------------------------------------------------------------------- /release/Viewport_composition_guides.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HAG87/maxscript-assorted/962c5c5a67dac1201e0878e7f536395d815cd817/release/Viewport_composition_guides.zip -------------------------------------------------------------------------------- /release/align_assets.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HAG87/maxscript-assorted/962c5c5a67dac1201e0878e7f536395d815cd817/release/align_assets.zip -------------------------------------------------------------------------------- /release/arch_scaler.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HAG87/maxscript-assorted/962c5c5a67dac1201e0878e7f536395d815cd817/release/arch_scaler.zip -------------------------------------------------------------------------------- /release/audit_materials.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HAG87/maxscript-assorted/962c5c5a67dac1201e0878e7f536395d815cd817/release/audit_materials.zip -------------------------------------------------------------------------------- /release/cam_manager.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HAG87/maxscript-assorted/962c5c5a67dac1201e0878e7f536395d815cd817/release/cam_manager.zip -------------------------------------------------------------------------------- /release/gamma_adjustment.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HAG87/maxscript-assorted/962c5c5a67dac1201e0878e7f536395d815cd817/release/gamma_adjustment.zip -------------------------------------------------------------------------------- /release/mat_tools.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HAG87/maxscript-assorted/962c5c5a67dac1201e0878e7f536395d815cd817/release/mat_tools.zip -------------------------------------------------------------------------------- /release/plugin/BUMP_resizer.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HAG87/maxscript-assorted/962c5c5a67dac1201e0878e7f536395d815cd817/release/plugin/BUMP_resizer.zip -------------------------------------------------------------------------------- /release/random_select.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HAG87/maxscript-assorted/962c5c5a67dac1201e0878e7f536395d815cd817/release/random_select.zip -------------------------------------------------------------------------------- /release/sunblind_cage_calc.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HAG87/maxscript-assorted/962c5c5a67dac1201e0878e7f536395d815cd817/release/sunblind_cage_calc.zip -------------------------------------------------------------------------------- /release/usericons/extratools_16a.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HAG87/maxscript-assorted/962c5c5a67dac1201e0878e7f536395d815cd817/release/usericons/extratools_16a.bmp -------------------------------------------------------------------------------- /release/usericons/extratools_16i.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HAG87/maxscript-assorted/962c5c5a67dac1201e0878e7f536395d815cd817/release/usericons/extratools_16i.bmp -------------------------------------------------------------------------------- /release/usericons/extratools_24a.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HAG87/maxscript-assorted/962c5c5a67dac1201e0878e7f536395d815cd817/release/usericons/extratools_24a.bmp -------------------------------------------------------------------------------- /release/usericons/extratools_24i.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HAG87/maxscript-assorted/962c5c5a67dac1201e0878e7f536395d815cd817/release/usericons/extratools_24i.bmp -------------------------------------------------------------------------------- /release/vertex_scrambler.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HAG87/maxscript-assorted/962c5c5a67dac1201e0878e7f536395d815cd817/release/vertex_scrambler.zip -------------------------------------------------------------------------------- /release/vraymat_populate.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HAG87/maxscript-assorted/962c5c5a67dac1201e0878e7f536395d815cd817/release/vraymat_populate.zip -------------------------------------------------------------------------------- /release/xref_replace.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HAG87/maxscript-assorted/962c5c5a67dac1201e0878e7f536395d815cd817/release/xref_replace.zip -------------------------------------------------------------------------------- /src/Adv_path_manager/BUMP_AdvPathMngr.mcr: -------------------------------------------------------------------------------- 1 | macroScript BUMP_AdvPathMngr 2 | category:"BUMP tools" 3 | ButtonText:"APM" 4 | toolTip:"Advanced User Paths manager" 5 | ( 6 | 7 | local path_a = "$UserScripts/BUMP_AdvPathMngr.ms" 8 | local path_b = "$scripts/BUMP_AdvPathMngr.ms" 9 | 10 | -- safe execution. Check if script is present in either scripts or userScripts folder 11 | on execute do ( 12 | if doesFileExist path_a then 13 | filein path_a 14 | else if doesFileExist path_b then 15 | filein path_b 16 | else 17 | messageBox "Script file missing!" 18 | ) 19 | ) 20 | -------------------------------------------------------------------------------- /src/Adv_path_manager/BUMP_AdvPathMngr.ms: -------------------------------------------------------------------------------- 1 | ( 2 | 3 | rollout roll_PathEdit "Add Paths" width:500 height:300 4 | ( 5 | local owner = if owner != undefined then owner 6 | local stored_values 7 | label lbl1 "Enter a list of paths separated by semicolons (;) or New Lines (\n). Paths can be quoted" 8 | edittext txt1 height:230 9 | button btn1 "Commit" width:150 height:30 10 | fn stringparser str = 11 | ( 12 | local stream = str as StringStream 13 | seek stream 0 14 | --readValue stream ignoreStringEscapes:true 15 | local pathsCol = #() 16 | try ( 17 | while not eof stream do ( 18 | local the_path = readDelimitedString stream ";\n" 19 | -- print the_path 20 | -- sanitize the strings 21 | -- deal with \"\" and "\n"s 22 | --if matchPattern the_path pattern:"\"" 23 | if pathConfig.isLegalPath the_path then ( 24 | append pathsCol the_path 25 | ) else ( 26 | the_path = substituteString the_path "\"" "" 27 | the_path = substituteString the_path "'" "" 28 | -- just in case 29 | the_path = substituteString the_path "\n" "" 30 | -- attemp to validate the path 31 | local resolved_path = pathConfig.resolvePathSymbols the_path 32 | if pathConfig.isLegalPath resolved_path then ( 33 | append pathsCol the_path 34 | ) 35 | ) 36 | ) 37 | -- ensure unique paths 38 | pathsCol = makeUniqueArray pathsCol 39 | ) catch (messageBox "Invalid entries!") 40 | -- return the paths 41 | pathsCol 42 | ) 43 | on btn1 pressed do ( 44 | -- commit paths 45 | local paths = stringparser txt1.text 46 | if paths.count > 0 then stored_values = paths 47 | -- exit dialog 48 | DestroyDialog roll_pathEdit 49 | ) 50 | ) 51 | 52 | rollout roll_mPath "Advanced External Files (User Paths) Manager" width:1000 --height:400 53 | ( 54 | dotNetControl lst_mPath "ListView" height:300 55 | button btn_1 "Change / Resolve" width:150 align:#left across:5 56 | button btn_3 "Brownse..." width:150 align:#left 57 | button btn_8 "Paste..." width:150 align:#left 58 | button btn_2 "Remove" width:150 align:#left 59 | checkbutton btn_4 "Show Only Invalids" align:#right 60 | 61 | checkBox chk_sb "Sub-Directories search filter" align:#left checked:true across:2 62 | editText txt_filter "Pattern: " Text:"#(\"map*\",\"texture*\")" align:#right 63 | 64 | imgTag sep1 width:(roll_mPath.width) height:1 bitmap:(bitmap 1 2 color: (color 5 5 5)) align:#center offset:[0,10] 65 | button btn_7 "Remove ..." width:150 align:#left across:7 66 | checkbox chk_1 "Empty folders" checked:true width:80 align:#right 67 | checkbox chk_dupes "Duplicates" checked:true width:80 align:#right 68 | checkbox chk_2 "Not Images" width:80 align:#right 69 | checkbox chk_3 "Not Models" width:80 align:#right 70 | checkbox chk_4 "Other (specify):" align:#right 71 | editText txt_1 text:"#(\".ies\",\".svg\")" align:#left 72 | imgTag sep2 width:(roll_mPath.width) height:1 bitmap:(bitmap 1 2 color: (color 5 5 5)) align:#center offset:[0,10] 73 | button btn_open "Explore selected" height:30 align:#left across:3 74 | button btn_5 "Done" width:150 height:30 align:#right offset:[160,0] 75 | button btn_6 "Cancel" width:150 height:30 align:#right 76 | ---------------------------------------------------------------------------------------------------------------------------------------------------- 77 | local only_invalid = false 78 | -- 79 | local 80 | TEMP_PATHS = #(), 81 | ADD_PATHS = #(), 82 | REMOVE_PATHS = #() 83 | -- 84 | local temp_listItemsCol 85 | ---------------------------------------------------------------------------------------------------------------------------------------------------- 86 | -- file extensions, add as needed 87 | local 88 | img_ext = #(".jpg",".jpeg",".png",".tif",".tiff",".tga",".bmp",".exr",".gif", ".hdr", ".hdri"), 89 | md_ext = #(".3ds",".max",".obj",".fbx",".iges",".dwg",".dxf",".rvt",".skp") 90 | ---------------------------------------------------------------------------------------------------------------------------------------------------- 91 | local 92 | alignLeft = (dotNetClass "HorizontalAlignment").Left, 93 | resizeToContent = (dotNetClass "ColumnHeaderAutoResizeStyle").ColumnContent, 94 | resizeToHeader = (dotNetClass "ColumnHeaderAutoResizeStyle").HeaderSize, 95 | dotNetLstViewItemClass = dotNetClass "System.Windows.Forms.ListViewItem", 96 | dotNetLstViewClass = dotNetClass "System.Windows.Forms.ListView", 97 | dotNetColor = dotNetClass "System.Drawing.Color", 98 | dotNetFont = dotNetClass "System.Drawing.Font", 99 | font_underline = (dotNetClass "System.Drawing.FontStyle").Underline, 100 | font_bold = (dotNetClass "System.Drawing.FontStyle").Bold, 101 | font_strk = (dotNetClass "System.Drawing.FontStyle").Strikeout, 102 | font_reg = (dotNetClass "System.Drawing.FontStyle").Regular, 103 | folder_dialog = dotnetobject "FolderBrowserDialog", 104 | dotNetDirectory = dotnetclass "System.IO.Directory", 105 | DirectorySearch = (dotNetClass"System.IO.SearchOption").AllDirectories, 106 | dotNetSort = dotNetClass "System.Windows.Forms.SortOrder" 107 | ---------------------------------------------------------------------------------------------------------------------------------------------------- 108 | local 109 | validPathColor = dotNetColor.seagreen, 110 | invalidPathColor = dotNetColor.Crimson, 111 | removedPathColor = dotNetColor.Goldenrod 112 | -- local dotNetContextMenuClass = dotNetClass "System.Windows.Forms.ContextMenu" 113 | ---------------------------------------------------------------------------------------------------------------------------------------------------- 114 | -- Compare function used by bsearch: 115 | fn extComparator a b = 116 | ( 117 | if a > (toLower b) then 1 118 | else if a < (toLower b) then -1 119 | else 0 120 | ) 121 | fn invSort a b = 122 | ( 123 | case of ( 124 | (a > b):-1 125 | (a < b):1 126 | default:0 127 | ) 128 | ) 129 | fn ArrayComparator a b = 130 | ( 131 | if a > b then 1 132 | else if a < b then -1 133 | else 0 134 | ) 135 | -- Retrieve subdirectorries 136 | fn GetAllSubDirs MyDirectory _filter:#("map*","texture*") = 137 | ( 138 | local curr_folder = 139 | if _filter != unsupplied then ( 140 | local temp = #() 141 | for i in _filter do ( join temp (dotNetDirectory.GetDirectories MyDirectory i DirectorySearch) ) 142 | temp 143 | ) else ( dotNetDirectory.GetDirectories MyDirectory "*" DirectorySearch ) 144 | curr_folder 145 | /* 146 | local 147 | temp = #(), 148 | s = 1, 149 | folders = getDirectories (MyDirectory + "/*"), 150 | t = folders.count 151 | while s < t do 152 | ( 153 | for i = s to t do ( 154 | temp = getDirectories (folders[i]+"*") 155 | -- apply filter 156 | for j = 1 to temp.count do folders[folders.count+1] = temp[j] 157 | ) 158 | s = t 159 | t = folders.count 160 | ) 161 | sort folders 162 | for i=1 to folders.count do (folders[i] = trimRight folders[i] "\\") 163 | folders 164 | -- */ 165 | ) 166 | ---------------------------------------------------------------------------------------------------------------------------------------------------- 167 | -- Re-apply style 168 | fn lst_restyle = 169 | ( 170 | local list_items = lst_mPath.Items 171 | for f=0 to (list_items.count) - 1 do ( 172 | list_items.Item[f].BackColor = if (bit.get f 1) then dotNetColor.Transparent else dotNetColor.LightGray 173 | ) 174 | ) 175 | -- Add columns to listView 176 | fn lstV_addColumns lst itms autosize:false = 177 | ( 178 | local w = if not autosize then ( (lst.width/itms.count)-1 ) else -2 179 | for x in itms do ( lst.columns.add x w alignLeft ) 180 | ) 181 | -- Add items to listView 182 | fn lstV_addItem lst itmCol = 183 | ( 184 | lst.BeginUpdate() 185 | lst.Items.AddRange itmCol 186 | lst.AutoResizeColumns resizeToContent 187 | lst.AutoResizeColumns resizeToHeader 188 | lst_restyle() 189 | lst.EndUpdate() 190 | ) 191 | -- Process paths into ListView items 192 | fn parse_items mP_list font: listView:lst_mPath = 193 | ( 194 | local res_list = #() 195 | if mP_list != undefined then ( 196 | local ForeColor 197 | local currpath 198 | local subitems 199 | local res_list = 200 | for i=1 to mP_list.count collect ( 201 | currpath = mP_list[i] 202 | subitems = #() 203 | subitems[5] = if (pathConfig.isAbsolutePath currpath) then "Absolute" else if (pathConfig.isUncPath currpath) then "UNC" else "-" 204 | subitems[1] = pathConfig.stripPathToLeaf currpath 205 | subitems[2] = currpath 206 | subitems[3] = (getFiles (pathConfig.appendPath currpath "*.*")).count as string 207 | subitems[4] = if (dotNetDirectory.exists currpath) then (ForeColor = validPathColor; "OK") else (ForeColor = invalidPathColor;"MISSING") 208 | -- Initialize Item 209 | local item = dotNetObject dotNetLstViewItemClass subitems 210 | item.tag = currpath 211 | item.ForeColor = ForeColor 212 | item.BackColor = if (bit.get i 1) then dotNetColor.Transparent else dotNetColor.LightGray 213 | if font != unsupplied then item.Font = (dotNetObject dotNetFont (listView.Font) font) 214 | item 215 | ) 216 | ) 217 | res_list 218 | ) 219 | -- Update listView Item 220 | fn update_item the_item new_path = 221 | ( 222 | local the_subitems = the_item.subitems 223 | the_item.text = pathConfig.stripPathToLeaf new_path 224 | the_subitems.item[1].text = new_path 225 | the_subitems.item[2].text = (getFiles (pathConfig.appendPath new_path "*.*")).count as string 226 | the_subitems.item[3].text = 227 | if (dotNetDirectory.exists new_path) then ( 228 | the_item.ForeColor = validpathColor 229 | "OK" 230 | ) else ( 231 | the_item.ForeColor = invalidPathColor 232 | "MISSING" 233 | ) 234 | the_subitems.item[4].text = if (pathConfig.isAbsolutePath new_path) then "Absolute" else if (pathConfig.isUncPath new_path) then "UNC" else "-" 235 | ) 236 | -- Initialize Collection 237 | fn Init = 238 | ( 239 | -- Collect user paths 240 | TEMP_PATHS = for i=1 to (mapPaths.count()) collect (mapPaths.get i) 241 | -- Process paths into ListView items 242 | lstV_addItem lst_mPath (parse_items TEMP_PATHS) 243 | ) 244 | ----------------------------------------------------------------------------------------------- 245 | -- Commit changes to Paths 246 | fn commit = 247 | ( 248 | -- format "%\n" REMOVE_PATHS 249 | -- format "%\n" ADD_PATHS 250 | 251 | if not (queryBox "Commit changes ?. This could take a while to process.") then return false 252 | 253 | -- remove any dupes 254 | REMOVE_PATHS = makeUniqueArray REMOVE_PATHS 255 | ADD_PATHS = makeUniqueArray ADD_PATHS 256 | 257 | -- remove possible delete entry from add entry.. 258 | ADD_PATHS = for i=1 to ADD_PATHS.count where (findItem REMOVE_PATHS ADD_PATHS[i] == 0) collect ADD_PATHS[i] 259 | 260 | -- delete entry 261 | format "Removing paths from External files list...\n" 262 | try ( 263 | -- collect the indexes to be removed 264 | local rem_idx = for p in REMOVE_PATHS collect findItem TEMP_PATHS p 265 | -- descending sort 266 | qsort rem_idx invSort 267 | -- remove the paths 268 | for i in rem_idx where i != 0 do ( 269 | mapPaths.delete i 270 | format "-> %\n" TEMP_PATHS[i] 271 | ) 272 | ) catch (messageBox "Unable to remove some paths."; format "%\n" (getCurrentException()) ) 273 | 274 | -- add entry 275 | -- /* 276 | format "Adding paths to External files list...\n" 277 | try ( 278 | -- progressStart "Adding user paths" 279 | -- do not add duplicated entries 280 | for p in ADD_PATHS where (findItem TEMP_PATHS p) == 0 do ( 281 | mapPaths.add p 282 | format "-> %\n" p 283 | ) 284 | ) catch (messageBox "unable to add some paths"; format "%\n" (getCurrentException()) ) 285 | -- */ 286 | -- update the tool 287 | -- Init() 288 | ) 289 | ----------------------------------------------------------------------------------------------- 290 | -- open explorer 291 | fn openDir = 292 | ( 293 | local itms = lst_mPath.SelectedItems.Item 294 | DOSCommand ("explorer " + "\"" + (itms[0].Subitems.Item[1].text) + "\"") 295 | ) 296 | -- Add to list 297 | fn path_adder paths = 298 | ( 299 | local the_paths = deepcopy paths 300 | local the_filter = if chk_sb.state then (execute txt_filter.text) else unsupplied 301 | if (queryBox "Add subfolders too?") then ( 302 | for the_path in paths do ( 303 | join the_paths (GetAllSubDirs the_path _filter:the_filter) 304 | ) 305 | ) 306 | -- add to temp results 307 | join ADD_PATHS the_paths 308 | -- add to list 309 | lstV_addItem lst_mPath (parse_items the_paths font:font_Bold) 310 | silentValue 311 | ) 312 | ---------------------------------------------------------------------------------------------------------------------------------------------------- 313 | -- Initialize 314 | on roll_mPath open do 315 | ( 316 | local HZ = (dotNetClass "HorizontalAlignment").Left 317 | -------------------------------------------------------------------------------------------------------------------------------- 318 | --Setup the forms view 319 | lst_mPath.view = (dotNetClass "system.windows.forms.view").details 320 | --Set so full width of listView is selected and not just first column. 321 | lst_mPath.FullRowSelect = true 322 | --Show lines between the items. 323 | lst_mPath.GridLines = true 324 | --Allow for multiple selections. 325 | lst_mPath.MultiSelect = true 326 | -- Allow Label Edit 327 | lst_mPath.LabelEdit = True 328 | -- Allow Column order change 329 | lst_mPath.AllowColumnReorder = True 330 | -- Columns Header additonal options 331 | lst_mPath.HeaderStyle = lst_mPath.HeaderStyle.Nonclickable 332 | -- turn off the grid lines 333 | lst_mPath.gridLines = false 334 | -- When this ListView loses the focus, it will still show what's selected 335 | lst_mPath.HideSelection = false 336 | -- make the border a flat solid color instead of the Windows 3D look 337 | lst_mPath.BorderStyle = lst_mPath.BorderStyle.FixedSingle 338 | -- required in order to implement DotNet drag and drop functionality 339 | lst_mPath.allowDrop = true 340 | -- Items Sort 341 | lst_mPath.Sorting = dotNetSort.Ascending 342 | -------------------------------------------------------------------------------------------------------------------------------- 343 | -- Add Columns 344 | lstV_addColumns lst_mPath #("Folder name", "Full path", "Files", "Status", "Type") autosize:True 345 | -- Add Items 346 | Init() 347 | -- lst_mPath.Items.Clear() 348 | ) 349 | -- close 350 | on roll_mPath close do ( lst_mPath.Dispose(); gc()) 351 | ---------------------------------------------------------------------------------------------------------------------------------------------------- Event handlers 352 | -- Change entry 353 | on btn_1 pressed do 354 | ( 355 | local underline = dotNetObject dotNetFont (lst_mPath.Font) font_underline 356 | -- get items list 357 | local itms = lst_mPath.SelectedItems.Item 358 | local itms_count = lst_mPath.SelectedItems.count 359 | for i=0 to itms_count-1 do ( 360 | local the_item = itms[i] 361 | folder_dialog.showDialog() 362 | local new_path = folder_dialog.SelectedPath 363 | if new_path != "" then ( 364 | -- add old to remove list 365 | appendIfUnique REMOVE_PATHS (the_item.Subitems.Item[1].text) 366 | -- add new to add list 367 | appendIfUnique ADD_PATHS new_path 368 | -- update listview 369 | the_item.Font = underline 370 | update_item the_item new_path 371 | ) 372 | ) 373 | ) 374 | -- Remove entry 375 | on btn_2 pressed do 376 | ( 377 | local strikeout = dotNetObject dotNetFont (lst_mPath.Font) font_strk 378 | local regular = dotNetObject dotNetFont (lst_mPath.Font) font_reg 379 | local itms = lst_mPath.SelectedItems.Item 380 | local itms_count = lst_mPath.SelectedItems.count 381 | 382 | for i=0 to itms_count-1 do ( 383 | local the_item = itms[i] 384 | local item_path = the_item.Subitems.Item[1].Text 385 | local f_d = findItem REMOVE_PATHS item_path 386 | 387 | local save_color = the_item.ForeColor 388 | local save_Font = the_item.Font 389 | if f_d == 0 then ( 390 | the_item.Font = strikeout 391 | the_item.ForeColor = removedPathColor 392 | appendIfUnique REMOVE_PATHS item_path 393 | 394 | ) else ( 395 | the_item.Font = save_Font 396 | the_item.ForeColor = save_color 397 | deleteItem REMOVE_PATHS f_d 398 | ) 399 | ) 400 | -- format "%\n" REMOVE_PATHS 401 | ) 402 | -- paste paths string 403 | on btn_8 pressed do ( 404 | local roll = roll_PathEdit 405 | createDialog roll modal:true 406 | local response = roll.stored_values 407 | -- print response 408 | if isKindOf response Array then ( 409 | -- commit the paths 410 | path_adder response 411 | ) 412 | ) 413 | -- add entry 414 | on btn_3 pressed do 415 | ( 416 | local res = folder_dialog.showDialog() 417 | local the_path = folder_dialog.SelectedPath 418 | 419 | if the_path != "" then path_adder #(the_path) 420 | ) 421 | -- invalid paths filter 422 | on btn_4 changed state do 423 | ( 424 | if state then ( 425 | items_col = lst_mPath.Items 426 | temp_listItemsCol = for i= 0 to (items_col.count)-1 where (items_col.Item[i].Subitems.Item[3].text == "OK") collect items_col.Item[i] 427 | local temp_items = 428 | for i = (items_col.count)-1 to 0 by -1 where (items_col.Item[i].Subitems.Item[3].text != "OK") collect (items_col.Item[i].Clone()) 429 | lst_mPath.Items.Clear() 430 | lstV_addItem lst_mPath temp_items 431 | ) else ( 432 | lstV_addItem lst_mPath temp_listItemsCol 433 | lst_mPath.Sort() 434 | ) 435 | ) 436 | -- remove unwanted WIP 437 | on btn_7 pressed do 438 | ( 439 | local strikeout = dotNetObject dotNetFont (lst_mPath.Font) font_strk 440 | -- collect filenames 441 | -- local proc_array = TEMP_PATHS + ADD_PATHS REPLACE TEMP PATHS 442 | local origin_paths = deepcopy TEMP_PATHS 443 | join origin_paths ADD_PATHS 444 | -- search for files in folders 445 | local filenames = 446 | for f=1 to origin_paths.count collect ( 447 | local temp = getfiles (origin_paths[f] + "\\*.*") 448 | local ext = #() 449 | if temp.count != 0 then ( 450 | ext = for i=1 to temp.count where (getFilenameType temp[i]) != ".db" collect (getFilenameType temp[i]) 451 | ) 452 | ext 453 | ) 454 | -- marked will contain indexes 455 | local marked = #() 456 | -- dupes will contain paths 457 | local dupes = #() 458 | -- empty folders 459 | if chk_1.checked then ( 460 | local empty_folders = #() 461 | empty_folders = for a=1 to filenames.count where filenames[a].count == 0 collect a 462 | join marked empty_folders 463 | ) 464 | -- not images 465 | if chk_2.checked then ( 466 | local not_images = #() 467 | not_images = for b=1 to filenames.count collect ( 468 | local res = 0 469 | local cnt = 1 470 | do ( 471 | bsearch img_ext[cnt] filenames[b] extComparator index:&res 472 | cnt += 1 473 | ) while ((cnt < img_ext.count) and (res == 0)) 474 | if res == 0 then b else continue 475 | ) 476 | join marked not_images 477 | ) 478 | -- not models 479 | if chk_3.checked then ( 480 | local not_models = #() 481 | not_models = for c=1 to filenames.count collect ( 482 | local res = 0 483 | local cnt = 1 484 | do ( 485 | bsearch md_ext[cnt] filenames[c] extComparator index:&res 486 | cnt += 1 487 | ) while ((cnt < md_ext.count) and (res == 0)) 488 | if res == 0 then c else continue 489 | ) 490 | join marked not_models 491 | ) 492 | -- other 493 | if chk_4.checked then ( 494 | local ext = execute txt_1.text 495 | if isKindOf ext Array then ( 496 | local other_files = #() 497 | other_files = for d=1 to filenames.count collect ( 498 | local res = 0 499 | local cnt = 1 500 | do ( 501 | bsearch ext[cnt] filenames[d] extComparator index:&res 502 | cnt += 1 503 | ) while ((cnt < ext.count) and (res == 0)) 504 | if res == 0 then d else continue 505 | ) 506 | join marked other_files 507 | ) 508 | ) 509 | -- duplicates 510 | if chk_dupes.checked then ( 511 | local suspects = deepCopy origin_paths 512 | sort suspects 513 | -- format "suspects: %\n" suspects 514 | dupes = for i=1 to (suspects.count - 1) where (suspects[i] == suspects[i+1]) collect suspects[i] 515 | ) 516 | -- process list 517 | -- get paths using collected indexes 518 | local str = dotnetclass "system.string" 519 | 520 | local temp_marked = makeUniqueArray marked 521 | local paths_list = for g=1 to temp_marked.count collect origin_paths[temp_marked[g]] 522 | -- add dupes 523 | join paths_list dupes 524 | -- find item in list, change item font 525 | for i=1 to paths_list.count do ( 526 | local f_i = lst_mPath.FindItemWithText (dotNet.ValueToDotNetObject paths_list[i] str) true 0 false 527 | 528 | if f_i != undefined then ( 529 | -- format "% || %\n" paths_list[i] f_i.Tag 530 | f_i.Font = strikeout 531 | f_i.ForeColor = removedPathColor 532 | ) 533 | ) 534 | -- add to deletion array 535 | join REMOVE_PATHS paths_list 536 | ) 537 | -- accept 538 | on btn_5 pressed do (commit(); DestroyDialog roll_mPath) 539 | on btn_6 pressed do (DestroyDialog roll_mPath) 540 | on btn_open pressed do (openDir()) 541 | ) 542 | CreateDialog roll_mPath 543 | ) -------------------------------------------------------------------------------- /src/BUMP_ArchScaler.mcr: -------------------------------------------------------------------------------- 1 | /* 2 | ------------------------------------------------------------------------------------------------------------------------------------ 3 | https://atelierbump.com 4 | Small utility to rescale nodes using an architectural scale factor. 5 | 20-22-2020 6 | ------------------------------------------------------------------------------------------------------------------------------------ 7 | */ 8 | 9 | macroScript BUMP_units 10 | category:"BUMP tools" 11 | buttontext:"ArchScaler" 12 | tooltip:"Small utility to rescale nodes using an architectural scale factor." 13 | ( 14 | rollout roll_archsc "ArchScale" 15 | ( 16 | group "Units" 17 | ( 18 | spinner spn_1 "" range:[1,1000,10] type:#float fieldwidth:50 align:#left across:2 19 | radiobuttons rd_1 labels:#("cm", "inches") 20 | spinner spn_2 "" range:[1,1000,1] type:#float fieldwidth:50 align:#left across:2 21 | label lbl_u "Max units" 22 | button btn_1 "Apply" width:140 height:25 23 | ) 24 | group "Factor" 25 | ( 26 | spinner spn_3 "" range:[1,1000,1] type:#integer fieldwidth:50 align:#left across:3 27 | label lbl_s1 " : " align:#center 28 | spinner spn_4 "" range:[1,1000,100] type:#integer fieldwidth:50 align:#right 29 | button btn_2 "Apply" width:140 height:25 30 | ) 31 | -- Decode a float value to the specified units. Note the extra steps to overcome different decimal separators than "." in wich case, the units.decodeValue will fail. 32 | fn valToUnits n unit = 33 | ( 34 | local res = 1 35 | local nrType = ClassOf n 36 | if ((nrType == integer OR nrType == Float) AND ClassOf unit == string) then 37 | ( 38 | local nstr = n as string 39 | 40 | if (matchPattern nstr pattern:"*.*") then ( 41 | -- get the system decimal separator 42 | local sep = (dotNetClass "System.Threading.Thread").CurrentThread.CurrentCulture.NumberFormat.NumberDecimalSeparator 43 | if sep != "." then nstr = substituteString nstr "." sep 44 | ) 45 | res = units.decodeValue (nstr + unit) 46 | ) 47 | res 48 | ) 49 | -- re-scale funtion. scale is applied relative to the node current scale 50 | fn scaler f = 51 | ( 52 | local theScaleTM = ScaleMatrix [f, f, f] 53 | local nodes = getCurrentSelection() 54 | undo "ArchScaler" on ( 55 | if nodes.count > 0 then ( 56 | for i in nodes do ( 57 | -- uncomment this line to reset the scale of the nodes 58 | -- i.scale = [f, f, f] 59 | i.transform = PreScale i.transform [f, f, f] 60 | ) 61 | ) 62 | ) 63 | ) 64 | 65 | on btn_1 pressed do ( 66 | local unit = 67 | case rd_1.state of 68 | ( 69 | 1:"cm" 70 | 2:"\"" 71 | ) 72 | a = (valToUnits spn_1.value unit ) 73 | b = (valToUnits spn_2.value "" ) 74 | f = a / b 75 | 76 | scaler (a / b) 77 | ) 78 | on btn_2 pressed do ( 79 | scaler ( spn_3.value / spn_4.value as float ) 80 | ) 81 | ) 82 | on isEnabled do not roll_archsc.open 83 | on execute do CreateDialog roll_archsc 84 | ) 85 | -------------------------------------------------------------------------------- /src/BUMP_Mat_Tools.mcr: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * https://atelierbump.com 4 | * Category: "BUMP tools" 5 | * last updated: 01-05-2023 6 | * MODIFY AT YOUR OWN RISK 7 | * ------------------------------------------------------------------------------------------------------- 8 | * BUMP_mapLoader | Load multiple bitmapTextures to the slate material editor 9 | * BUMP_fnameToBMap | Change the names of Bitmap Textures to the name of the loaded files. 10 | * BUMP_remove_mats | Remove material from selection 11 | * BUMP_selNoMat | Filter nodes without material in current selection. 12 | * BUMP_ObjIDbyCAM | Set objects ID for current camera view 13 | * BUMP_faceSel | Select faces with same material ID 14 | * BUMP_RndIDSet | Set random material IDs for selected faces 15 | * BUMP_qIDSet | Set material IDs for selected faces 16 | * BUMP_listMtl | List materials in selection 17 | * BUMP_selByMat | Select objects with the same material as the current selection 18 | */ 19 | /* Change mtl bump value */ 20 | macroScript DSTLBX_bumpToOneHundred 21 | category: "BUMP tools" 22 | ButtonText: "bumpTo100" 23 | toolTip: "Material Bump value to 100" 24 | ( 25 | on execute do ( 26 | local warning = messageBox "Warning! this will change the bump amount value of scene materials. Works only with Vray materials for now" 27 | if warning AND VRayMtl != undefined then ( 28 | -- for Vray materials only! 29 | -- TODO: Implement physical, standard, Arnold, Corona... 30 | local mats = getClassInstances VRayMtl 31 | mats = makeUniqueArray mats 32 | for m in mats where classOf (m.texmap_bump) == VRayNormalMap do m.texmap_bump_multiplier = 100.0 33 | ) 34 | ) 35 | ) 36 | /* Load texture maps */ 37 | macroScript BUMP_mapLoader 38 | category: "BUMP tools" 39 | ButtonText: "Bitmap multi-loader" 40 | toolTip: "Load multiple bitmapTextures to the slate material editor" 41 | ( 42 | -- open files dialog 43 | fn GetMultiOpenFilenames caption:"Open" filename:"" types:"image Files (*.*)|*.*" default:1 = 44 | ( 45 | local dlg = DotNetObject "System.Windows.Forms.OpenFileDialog" 46 | dlg.multiSelect = true 47 | dlg.title = caption 48 | local p = getFilenamePath filename 49 | if doesFileExist p then dlg.initialDirectory = p 50 | dlg.filter = types 51 | dlg.filterIndex = default 52 | local result = dlg.ShowDialog() 53 | if (result.Equals result.OK) then dlg.filenames else undefined 54 | ) 55 | -- load TextureMaps 56 | fn loadTextureMaps files _gamma _basename = 57 | ( 58 | for i=1 to files.count do ( 59 | 60 | local _path = files[i] 61 | local tx = openBitMap _path gamma:_gamma 62 | 63 | if tx != undefined then ( 64 | local map = Bitmaptexture() 65 | map.bitmap = tx 66 | map.name = _basename + (try (getFilenameFile _path ) catch ( uniqueName (getFilenameFile _path) )) 67 | 68 | local smeView = sme.GetView(SME.activeView) 69 | smeView.CreateNode map (smeView.position + [0, 0 + (40 * i - 1)]) 70 | ) 71 | ) 72 | ) 73 | rollout roll_loadbitmaps "Load bitmaps" 74 | ( 75 | Group "Gamma" 76 | ( 77 | radiobuttons rd_1 labels:#("Auto", "Override") 78 | spinner spn_1 "Gamma value:" range:[1.0, 100.0, 1.0] units:#float 79 | ) 80 | edittext txt_1 "Name Prefix:" text:"Map_" labelOnTop:true 81 | button btn_1 "Load Maps" width:150 height:30 offset:[0,5] 82 | 83 | local 84 | _gamma, _basename 85 | 86 | on roll_loadbitmaps open do 87 | ( 88 | _gamma = #Auto 89 | _basename = "Map_" 90 | ) 91 | on roll_loadbitmaps close do updateToolbarButtons() 92 | 93 | on rd_1 changed index do 94 | ( 95 | case index of 96 | ( 97 | 1: (_gamma = #Auto) 98 | 2: ( _gamma = spn_1.value) 99 | ) 100 | ) 101 | on spn_1 changed val do 102 | ( 103 | if _gamma != #Auto then ( 104 | _gamma = val 105 | ) 106 | ) 107 | on btn_1 pressed do 108 | ( 109 | local paths 110 | if (paths = GetMultiOpenFilenames()) != undefined then 111 | ( 112 | print paths 113 | loadTextureMaps paths _gamma _basename 114 | ) 115 | ) 116 | ) 117 | on isChecked do roll_loadbitmaps.open 118 | on execute do CreateDialog roll_loadbitmaps style:#(#style_toolwindow,#style_sysmenu) 119 | on CloseDialogs do DestroyDialog roll_loadbitmaps 120 | ) 121 | /* Map - Material related tools */ 122 | macroScript BUMP_fnameToBMap 123 | category: "BUMP tools" 124 | buttonText: "Map name from file" 125 | toolTip: "Change the names of Bitmap Textures to the name of the loaded files." 126 | ( 127 | local msg = "This will rename all Bitmap maps to the filename of the source. Are you sure to continue?" 128 | 129 | fn renameTxtMapFromFileName = 130 | ( 131 | undo "Map name from file" on ( 132 | for i in (getClassInstances BitmapTexture) do ( 133 | i.name = (getFilenameFile i.filename + getFilenameType i.filename) 134 | ) 135 | ) 136 | ) 137 | on execute do 138 | ( 139 | if queryBox msg then renameTxtMapFromFileName() 140 | ) 141 | ) 142 | /* Remove material from selection */ 143 | macroScript BUMP_remove_mats 144 | category: "BUMP tools" 145 | buttonText: "Remove materials" 146 | toolTip: "Remove material from selection" 147 | ( 148 | on execute do 149 | ( 150 | local msg = "This will remove the materials assigned to the node selection. Are you sure to continue?" 151 | if queryBox msg then ( 152 | undo "Remove materials" on ( 153 | for i in selection where (isValidNode i) do i.material = undefined 154 | CompleteRedraw() 155 | ) 156 | ) 157 | ) 158 | ) 159 | /* Filter nodes without material in current selection. */ 160 | macroScript BUMP_selNoMat 161 | category: "BUMP tools" 162 | buttonText: "Select nodes without material" 163 | toolTip: "Filter nodes without material in current selection." 164 | ( 165 | fn SelectNoMaterial = 166 | ( 167 | max create mode 168 | with redraw off 169 | ( 170 | local objs = getCurrentSelection() 171 | ClearSelection() 172 | for i in objs where (i.material == undefined) do selectMore i 173 | ) 174 | ) 175 | on execute do SelectNoMaterial() 176 | ) 177 | -- Poly - Node Id related tools 178 | macroScript BUMP_ObjIDbyCAM 179 | category: "BUMP tools" 180 | buttonText: "ID from camera" 181 | toolTip: "Set objects ID for current camera view" 182 | icon: #("Material_Modifiers",2) 183 | ( 184 | fn setObjID = 185 | ( 186 | local cam = getActiveCamera() 187 | if cam != undefined then ( 188 | local bbx = box2 [0,0] [gw.getWinSizeX(),gw.getWinSizeY()] 189 | local objsel = boxPickNode bbx 190 | local campos = cam.pos 191 | fn compareFN v1 v2 ref: = 192 | ( 193 | local a = distance ref v1.pos 194 | local b = distance ref v2.pos 195 | local d = a - b 196 | case of 197 | ( 198 | (d < 0.): -1 199 | (d > 0.): 1 200 | default: 0 201 | ) 202 | ) 203 | qsort objsel compareFN ref:campos 204 | for i=1 to objsel.count do ( 205 | objsel[i].gbufferChannel = i 206 | ) 207 | 208 | ) 209 | ) 210 | on execute do setObjID() 211 | ) 212 | /* Select faces with same material ID */ 213 | macroScript BUMP_faceSel 214 | category: "BUMP tools" 215 | buttonText: "Face ID" 216 | toolTip: "Select faces with same material ID" 217 | icon: #("UVWUnwrapSelection",12) 218 | ( 219 | fn EPOLY_selectMatID obj = 220 | ( 221 | if obj != undefined then ( 222 | if ((isKindOf obj Editable_Poly) and (subObjectLevel == 4)) then ( 223 | 224 | local faceCount = polyop.getNumFaces obj 225 | local currFace = polyop.getFaceSelection obj 226 | local currFaceArr = currFace as Array 227 | 228 | if currFaceArr[1] != undefined then ( 229 | local faceID = polyop.getFaceMatID obj currFaceArr[1] 230 | local tempFaces = for i=1 to faceCount where (polyop.getFaceMatID obj i == faceID) collect i 231 | polyop.setFaceSelection obj tempFaces 232 | redrawViews() 233 | ) 234 | ) 235 | ) 236 | ) 237 | On IsEnabled do Filters.Is_EditPoly() 238 | -- On IsVisible do Filters.Is_EditPoly() 239 | on execute do 240 | ( 241 | local theObj = if selection[1] != undefined then selection[1] else undefined 242 | EPOLY_selectMatID theObj 243 | ) 244 | ) 245 | /* Set random material IDs for selected faces */ 246 | macroScript BUMP_RndIDSet 247 | category: "BUMP tools" 248 | ButtonText: "Random ID Set" 249 | tooltip: "Set random material IDs for selected faces" 250 | silentErrors: true 251 | ( 252 | fn randMatID obj min:1 max:5 = 253 | ( 254 | if obj !=undefined then ( 255 | if ((isKindOf obj Editable_Poly) and (subObjectLevel == 4)) then ( 256 | local faceCount = polyop.getNumFaces obj 257 | local currFace = polyop.getFaceSelection obj 258 | local currFaceArr = currFace as Array 259 | if currFaceArr[1] != undefined then ( 260 | for i in currFaceArr do polyop.setFaceMatID obj i (abs (floor (random min max))) 261 | redrawViews() 262 | ) 263 | ) 264 | ) 265 | ) 266 | on execute do try (randMatID $) catch () 267 | ) 268 | /* Set material IDs for selected faces */ 269 | macroScript BUMP_qIDSet 270 | category: "BUMP tools" 271 | ButtonText: "Quick material ID Set" 272 | tooltip: "Set material IDs for selected faces" 273 | silentErrors: true 274 | ( 275 | local roll_qID 276 | rollout roll_qID "Quick polygon ID set" width:200 --*height:300 277 | ( 278 | -- label lblCurr "Current ID: " align:#left height:25 across:2 279 | -- label lblCurrID "10" align:#right height:25 offset:[-10,0] 280 | checkbutton utl1 "Set / Select" height:25 align:#left across:2 281 | label lbl1 "SET MODE" offset:[0,5]-- align:#right 282 | button btn1 "1" width:32 height:32 across:5 283 | button btn2 "2" width:32 height:32 284 | button btn3 "3" width:32 height:32 285 | button btn4 "4" width:32 height:32 286 | button btn5 "5" width:32 height:32 287 | button btn6 "6" width:32 height:32 across:5 288 | button btn7 "7" width:32 height:32 289 | button btn8 "8" width:32 height:32 290 | button btn9 "9" width:32 height:32 291 | button btn10 "10" width:32 height:32 292 | button btn11 "Sel. Selected face ID" width:170 height:32 align:#left offset:[0,5] enabled:false 293 | 294 | -- local str1 = "Sel. Selected face ID" 295 | 296 | mapped fn polyID obj id:1 = 297 | ( 298 | if obj != undefined then ( 299 | if ((isKindOf obj Editable_Poly) and (subObjectLevel == 4 OR subObjectLevel == 5)) then ( 300 | local faceCount = polyop.getNumFaces obj 301 | local currFace= polyop.getFaceSelection obj 302 | local currFaceArr = currFace as Array 303 | if currFaceArr[1] != undefined then ( 304 | with redraw off for i in currFaceArr do polyop.setFaceMatID obj i id 305 | redrawViews() 306 | ) 307 | ) 308 | ) 309 | ) 310 | mapped fn selectMatID obj id:1 = 311 | ( 312 | if obj != undefined then ( 313 | if ((isKindOf obj Editable_Poly) and (subObjectLevel == 4 OR subObjectLevel == 5)) then ( 314 | local faceCount = polyop.getNumFaces obj 315 | local currFace = polyop.getFaceSelection obj 316 | -- accelerator 317 | local _getID = polyop.getFaceMatID 318 | local tempFaces = for i=1 to faceCount where (_getID obj i == id) collect i 319 | polyop.setFaceSelection obj tempFaces 320 | redrawViews() 321 | ) 322 | ) 323 | ) 324 | 325 | fn currFaceMatID obj &faceID = 326 | ( 327 | if obj != undefined then ( 328 | if ((isKindOf obj Editable_Poly) and (subObjectLevel == 4)) then ( 329 | local faceCount = polyop.getNumFaces obj 330 | local currFace = polyop.getFaceSelection obj 331 | local currFaceArr = currFace as Array 332 | 333 | if currFaceArr[1] != undefined then ( 334 | faceID = polyop.getFaceMatID obj currFaceArr[1] 335 | local tempFaces = for i=1 to faceCount where (polyop.getFaceMatID obj i == faceID) collect i 336 | polyop.setFaceSelection obj tempFaces 337 | redrawViews() 338 | ) 339 | ) 340 | ) 341 | ) 342 | 343 | on utl1 changed state do ( 344 | if state then ( 345 | lbl1.text = "SELECT MODE" 346 | btn11.enabled = true 347 | ) else ( 348 | lbl1.text = "SET MODE" 349 | btn11.enabled = false 350 | ) 351 | -- lbl1.text = if state then "SELECT MODE" else "SET MODE" 352 | ) 353 | on btn1 pressed do if utl1.checked then selectMatID $ id:1 else polyID $ id:1 354 | on btn2 pressed do if utl1.checked then selectMatID $ id:2 else polyID $ id:2 355 | on btn3 pressed do if utl1.checked then selectMatID $ id:3 else polyID $ id:3 356 | on btn4 pressed do if utl1.checked then selectMatID $ id:4 else polyID $ id:4 357 | on btn5 pressed do if utl1.checked then selectMatID $ id:5 else polyID $ id:5 358 | on btn6 pressed do if utl1.checked then selectMatID $ id:6 else polyID $ id:6 359 | on btn7 pressed do if utl1.checked then selectMatID $ id:7 else polyID $ id:7 360 | on btn8 pressed do if utl1.checked then selectMatID $ id:8 else polyID $ id:8 361 | on btn9 pressed do if utl1.checked then selectMatID $ id:9 else polyID $ id:9 362 | on btn10 pressed do if utl1.checked then selectMatID $ id:10 else polyID $ id:10 363 | on btn11 pressed do currFaceMatID $ &faceID 364 | ) 365 | 366 | on isChecked do if roll_qID != undefined then roll_qID.open else false 367 | on execute do ( 368 | try ( 369 | if not roll_qID.open then CreateDialog roll_qID 370 | ) catch ( 371 | DestroyDialog roll_qID 372 | CreateDialog roll_qID 373 | ) 374 | ) 375 | ) 376 | /* Select by material */ 377 | macroScript BUMP_selByMat 378 | category: "BUMP tools" 379 | ButtonText: "Select by Material" 380 | tooltip: "Select objects with the same material as the current selection." 381 | silentErrors: true 382 | ( 383 | on execute do 384 | ( 385 | -- current selection material 386 | local mats = for i in (getCurrentSelection()) where i.material != undefined collect i.material 387 | -- unique array of materials 388 | makeuniquearray mats 389 | -- look for objects with the same material 390 | local sim = for i in objects where findItem mats i.material collect i 391 | -- select the resul 392 | if sim.count > 0 then select sim 393 | ) 394 | ) 395 | /* List materials in selection */ 396 | macroScript BUMP_listMtl 397 | category: "BUMP tools" 398 | ButtonText: "List Materials" 399 | tooltip: "List materials of selected nodes" 400 | silentErrors: true 401 | ( 402 | fn listMats sel = 403 | ( 404 | local mats = #() 405 | local undef = #() 406 | for i in sel do 407 | ( 408 | if i.material != undefined then ( 409 | appendIfUnique mats i.material 410 | ) else ( 411 | -- print (classof i) 412 | append undef i 413 | ) 414 | ) 415 | for m in mats do format "% :: %\n" m.name (classof m) 416 | if undef.count > 0 then ( 417 | format "Undefined Materials at:\n" 418 | for u in undef do format "% :: %\n" u.name (classof u) 419 | select undef 420 | ) 421 | OK 422 | ) 423 | 424 | on execute do 425 | ( 426 | listMats $ 427 | ) 428 | ) 429 | /* 430 | -- Max UI related tools 431 | macroScript TrackbarToggle 432 | category: "BUMP tools" 433 | buttonText: "Toggle Trackbar" 434 | toolTip: "Toggle Timeslider and Trackbar" 435 | Icon: #("TrackViewStatus",11) 436 | ( 437 | on isChecked do not (timeslider.isVisible()) 438 | on execute do 439 | ( 440 | timeslider.setvisible (not timeslider.isVisible()) 441 | ) 442 | ) 443 | */ -------------------------------------------------------------------------------- /src/BUMP_Random_select.mcr: -------------------------------------------------------------------------------- 1 | /* 2 | ------------------------------------------------------------------------------------------------------------------ 3 | Random object selection 4 | ------------------------------------------------------------------------------------------------------------------ 5 | */ 6 | macroScript BUMP_RndSel 7 | category: "BUMP tools" 8 | ButtonText: "Random Select" 9 | toolTip: "Select random nodes" 10 | silentErrors: true 11 | ( 12 | -- Percent: Keep a random percentage of the total quantity of nodes in the current selection. 13 | fn rndItemsPercent c p = 14 | ( 15 | local itms_count = floor (c * p) as integer 16 | local res = #() 17 | for i = 1 to itms_count do ( 18 | local r = random 1 c 19 | if ((findItem res r) != 0) then 20 | ( 21 | do ( r = random 1 c ) while ((findItem res d) != 0) 22 | ) 23 | append res r 24 | ) 25 | sort res 26 | res 27 | ) 28 | -- Subtract: Same as percent, but inverse: deselect a random percentage within selection. 29 | fn rndItemsSubstr c p = 30 | ( 31 | local itms_count = c - ( ceil (c * p) as integer ) 32 | local res = #() 33 | if ( itms_count > 0) then ( 34 | for i = 1 to itms_count do ( 35 | local r = random 1 c 36 | if ((findItem res r) != 0) then 37 | ( 38 | do ( r = random 1 c ) while ((findItem res d) != 0) 39 | ) 40 | append res r 41 | ) 42 | ) 43 | sort res 44 | res 45 | ) 46 | -- Step: Performs a skip pattern in the selection. 47 | fn rndItemsStep c s = 48 | ( 49 | local res 50 | if s < (c/2) then ( 51 | local bits = #{1..c} 52 | for i = 1 to bits.count by s where ((random 0 1) == 1) do bits[i] = false 53 | res = bits as Array 54 | sort res 55 | ) else ( res = #() ) 56 | res 57 | ) 58 | -- Pattern: Not a random mode; Instead it wil unselect nodes following a pattern. 59 | fn selPattern sel c st qn = 60 | ( 61 | local res = #() 62 | local delta = st + qn 63 | if delta < c then ( 64 | for i=1 to (c - delta) by delta do ( 65 | local tmp = for f = 1 to st collect sel[i+f] 66 | join res tmp 67 | ) 68 | ) 69 | res 70 | ) 71 | -- main UI 72 | rollout roll_rndSel "Random selection" 73 | ( 74 | group "Mode" 75 | ( 76 | radioButtons rd_1 labels:#("Percent","Step", "Subtract", "Pattern") columns:2 77 | ) 78 | group "Values" 79 | ( 80 | spinner spn_1 "Percent" range:[1,100,50] type:#integer fieldWidth:(roll_rndSel.width/2) align:#right 81 | spinner spn_2 "Step" range:[1,1000,1] type:#integer fieldWidth:(roll_rndSel.width/2) align:#right enabled:false 82 | spinner spn_3 "Subtr. %" range:[0,99,50] type:#integer fieldWidth:(roll_rndSel.width/2) align:#right enabled:false 83 | ) 84 | group "Pattern" 85 | ( 86 | spinner spn_4 "Keep" range:[1,100,1] type:#integer fieldWidth:(roll_rndSel.width/2) align:#right enabled:false 87 | spinner spn_5 "Quit" range:[1,1000,1] type:#integer fieldWidth:(roll_rndSel.width/2) align:#right enabled:false 88 | ) 89 | button btn_1 "Select Random" height:30 width:(roll_rndSel.width - 25) 90 | button btn_2 "Re-Select" height:30 width:(roll_rndSel.width - 25) 91 | -- button btn_2 "Done" height:30 width:(roll_rndSel.width - 25) 92 | ----------------------------------------- 93 | local mode = 1, 94 | sel, sel_count 95 | ----------------------------------------- 96 | fn rndSel s c x mode:1 = 97 | ( 98 | local rnd, res 99 | rnd = case mode of 100 | ( 101 | 1: ( rndItemsPercent c (x * 0.01) ) 102 | 2: ( rndItemsStep c x ) 103 | 3: ( rndItemsSubstr c (x * 0.01) ) 104 | ) 105 | if rnd.count > 0 then ( 106 | res = for i = 1 to rnd.count where (isValidNode s[rnd[i]]) collect s[rnd[i]] 107 | ) else ( 108 | res = for i = 1 to s.count where (isValidNode s[i]) collect s[i] 109 | ) 110 | res 111 | ) 112 | fn test_sel = 113 | ( 114 | sel = getCurrentSelection() 115 | if sel.count != 0 then 116 | sel_count = sel.count 117 | else 118 | messageBox "Select some nodes!" 119 | OK 120 | ) 121 | ----------------------------------------- 122 | on roll_rndSel open do ( 123 | max create mode 124 | test_sel() 125 | ) 126 | on rd_1 changed state do 127 | ( 128 | mode = state 129 | case state of ( 130 | 1: ( 131 | spn_1.enabled = true 132 | spn_2.enabled = false 133 | spn_3.enabled = false 134 | spn_4.enabled = false 135 | spn_5.enabled = false 136 | ) 137 | 2: ( 138 | spn_1.enabled = false 139 | spn_2.enabled = true 140 | spn_3.enabled = false 141 | spn_4.enabled = false 142 | spn_5.enabled = false 143 | ) 144 | 3: ( 145 | spn_1.enabled = false 146 | spn_2.enabled = false 147 | spn_3.enabled = true 148 | spn_4.enabled = false 149 | spn_5.enabled = false 150 | ) 151 | 4: ( 152 | spn_1.enabled = false 153 | spn_2.enabled = false 154 | spn_3.enabled = false 155 | spn_4.enabled = true 156 | spn_5.enabled = true 157 | ) 158 | ) 159 | ) 160 | on spn_1 changed val do 161 | ( 162 | if sel.count == 0 then test_sel() else select (rndSel sel sel_count val mode:1) 163 | ) 164 | on spn_2 changed val do 165 | ( 166 | if sel.count == 0 then test_sel() else select (rndSel sel sel_count val mode:2) 167 | ) 168 | on spn_3 changed val do 169 | ( 170 | if sel.count == 0 then test_sel() else select (rndSel sel sel_count val mode:3) 171 | ) 172 | on spn_4 changed val do 173 | ( 174 | if sel.count == 0 then test_sel() else select (selPattern sel sel_count val spn_5.value) 175 | ) 176 | on spn_5 changed val do 177 | ( 178 | if sel.count == 0 then test_sel() else select (selPattern sel sel_count spn_4.value val) 179 | ) 180 | on btn_1 pressed do 181 | ( 182 | if sel.count == 0 then test_sel() 183 | else 184 | ( 185 | case mode of ( 186 | 1: ( select (rndSel sel sel_count spn_1.value mode:1) ) 187 | 2: ( select (rndSel sel sel_count spn_2.value mode:2) ) 188 | 3: ( select (rndSel sel sel_count spn_3.value mode:3) ) 189 | 4: ( select selPattern sel sel_count spn_4.value spn_5.value ) 190 | ) 191 | ) 192 | ) 193 | on btn_2 pressed do ( 194 | -- DestroyDialog roll_rndSel 195 | test_sel() 196 | 197 | ) 198 | ) 199 | 200 | on execute do ( 201 | CreateDialog roll_rndSel 202 | ) 203 | ) -------------------------------------------------------------------------------- /src/BUMP_align_assets.mcr: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------------------- 3 | * Align Assets 4 | * MODIFY AT YOUR OWN RISK 5 | * atelierbump@gmail.com 6 | * Category: "BUMP tools" 7 | * 11-3-2018 - Fixed repostion of Groups and Parented Nodes 8 | * ------------------------------------------------------------------------------------------------------- 9 | */ 10 | macroscript BUMP_line_assets 11 | category:"BUMP tools" 12 | buttonText:"ALN" 13 | tooltip:"Put assets in line" 14 | Icon:#("AutoGrid",2) 15 | ( 16 | fn lineAssets objs gap:20.0 axis:x_axis = 17 | ( 18 | if objs != undefined then ( 19 | local baseP = pickPoint promt:"Pick reference point" 20 | if isKindOf baseP point3 then ( 21 | local wrld_TM = matrix3 1 22 | local prevPoint = [0.0,0.0,0.0] 23 | -- Filter Objs Parent 24 | local obj_col = #() 25 | 26 | for i=1 to objs.count where ( isValidNode objs[i] ) do ( 27 | local curr = objs[i] 28 | appendIfUnique obj_col (if curr.parent != undefined then curr.parent else curr) 29 | ) 30 | 31 | for i=1 to obj_col.count do ( 32 | local 33 | _obj = obj_col[i], 34 | objTM = _obj.objecttransform, 35 | savepivot = _obj.pivot * inverse objTM, 36 | bx = in coordsys _obj nodeLocalBoundingBox _obj, 37 | bx1_abs = [abs bx[1].x, abs bx[1].y, abs bx[1].z], 38 | bx2_abs = [abs bx[2].x, abs bx[2].y, abs bx[2].z] 39 | /* 40 | bx1_abs = [objs[i].min.x, objs[i].min.y, objs[i].min.z], 41 | bx2_abs = [objs[i].max.x, objs[i].max.y, objs[i].max.z] 42 | */ 43 | _obj.pivot = [_obj.center.x, _obj.center.y, _obj.min.z] 44 | if i < 2 then ( 45 | _obj.pos = baseP 46 | local objNewTM = _obj.objecttransform 47 | _obj.pivot = (savepivot * objNewTM) 48 | prevPoint = bx2_abs + gap 49 | ) else ( 50 | local p = baseP + ((prevPoint + bx1_abs) * axis) 51 | _obj.pos = p 52 | local objNewTM = _obj.objecttransform 53 | _obj.pivot = (savepivot * objNewTM) 54 | prevPoint += (bx1_abs + bx2_abs) + gap 55 | ) 56 | ) 57 | ) 58 | ) 59 | ) 60 | rollout roll_aline "Put assets in line" 61 | ( 62 | spinner spn_gap "Separation: " type:#Worldunits range:[-1000000.0,1000000.0,20.0] width:(roll_aline.width - 10.0) align:#center 63 | imgTag sep1 width:(roll_aline.width) height:1 bitmap:(bitmap 1 2 color: (color 5 5 5)) offset:[0,5] align:#center 64 | radiobuttons rd_ax "Direction:" labels:#("X axis","Y axis") width:(roll_aline.width - 10.0) align:#left 65 | imgTag sep2 width:(roll_aline.width) height:1 bitmap:(bitmap 1 2 color: (color 5 5 5)) offset:[0,5] align:#center 66 | button btn_ok "Apply" height:30 width:(roll_aline.width - 10.0) align:#center 67 | on btn_ok pressed do ( 68 | if $ != undefined then ( 69 | local the_ax = case (rd_ax.state) of 70 | ( 71 | 1: x_axis 72 | 2: y_axis 73 | ) 74 | undo on ( lineAssets $ axis:the_ax gap:(spn_gap.value) ) 75 | ) 76 | ) 77 | ) 78 | on execute do ( createDialog roll_aline ) 79 | ) -------------------------------------------------------------------------------- /src/BUMP_audit-materials.ms: -------------------------------------------------------------------------------- 1 | ( 2 | /* 3 | FILTER SELECTION BY MATERIAL CLASS 4 | The algortihm will look 1-level deep in MultiMaterials 5 | 1 - Start by selecting the nodes you want to filter 6 | */ 7 | clearListener() 8 | local mtlClass = VRayMtl ---> 2 - THE TYPE OF MATERIAL YOU WANT TO EXCLUDE IN THE SEARCH 9 | local listOfObjs = #() 10 | for o in selection where ClassOf o.material != mtlClass do ( 11 | if ClassOf o.material == MultiMaterial then ( 12 | local hasinvalidMtl = false 13 | for m in o.Material.materialList while ClassOf m != mtlClass do hasinvalidMtl = true 14 | if hasinvalidMtl then ( 15 | format "% || %\n" o.name o.material 16 | append listOfObjs o 17 | ) 18 | ) else ( 19 | format "% || %\n" o.name o.material 20 | append listOfObjs o 21 | ) 22 | ) 23 | clearSelection() 24 | select listOfObjs 25 | ) 26 | -------------------------------------------------------------------------------- /src/BUMP_camManager.mcr: -------------------------------------------------------------------------------- 1 | /* 2 | * ------------------------------------------------------------------------------------------- 3 | * Camera Manager - FREE VERSION. COMPLETE VERSION IS PART OF DESIGTOOLBOX 4 | * htpps://atelierbump.com 5 | * Bump 2019-2022 6 | * rev 1.5 03/06/2019 7 | * 02-2021 8 | * 01-2022 9 | * Added Shutter parameters, reordered parameters, changed presets to common aspect ratios 10 | * ------------------------------------------------------------------------------------------- 11 | */ 12 | macroScript BUMP_CamMngr 13 | category: "BUMP tools" 14 | ButtonText: "Camera manager" 15 | tooltip: "Manage Cameras and render batch views" 16 | silentErrors: false 17 | icon: #("extratools", 1) 18 | ( 19 | struct camManagerTool 20 | ( 21 | CamFloater, 22 | dialog_width = 250, 23 | Active_preview = false, 24 | roll_Cams, 25 | roll_Batch, 26 | roll_active, 27 | private 28 | /* CAMS ROLLOUT */ 29 | fn ui_cams = 30 | ( 31 | rollout roll_Cams "Camera Manager" 32 | ( 33 | local roll_w = 250 --roll_Cams.width 34 | local owner = if owner != undefined then owner 35 | -------------------------------- 36 | group "Active Camera" 37 | ( 38 | label lbl_cam "" align:#left height:25 offset:[0,5] 39 | ) 40 | 41 | group "Scene cameras" 42 | ( 43 | listbox lst_cams "" height:8 44 | button btn_prev_cam "<<" width:60 align:#left across:3 45 | tooltip:"Previous camera" 46 | button btn_s "Select" width:80 align:#center 47 | tooltip:"Select active camera" 48 | button btn_next_cam ">>" width:60 align:#right 49 | tooltip: "Nex camera" 50 | ) 51 | 52 | button btn_1 "Refresh" height:25 width:(roll_w - 25) 53 | tooltip:"Update scene cameras list" 54 | 55 | group "Parameters" 56 | ( 57 | --LENS 58 | label lbl_fl "Focal length" align:#left across:2 59 | spinner spn_fl "mm" fieldWidth:70 align:#right 60 | checkbox chk_fov "Use FOV" align:#left across:2 61 | spinner spn_fov "FOV" fieldWidth:70 align:#right 62 | -- APERTURE 63 | checkbox chk_dof "Enable DOF" across:2 64 | spinner spn_f "f-" align:#right fieldWidth:70 align:#right 65 | checkbox chk_tilt "Perspective: Auto Vertical Tilt" 66 | -- EV 67 | label lbl_ex "Exposure:" align:#left 68 | radiobuttons rd_ex labels:#("Manual", "Target") align:#left offsets:#([0,0], [80,0]) 69 | -- SHUTTER 70 | dropdownList drp_ev "Shutter" items:#("1 / seconds", "seconds", "degrees", "frames") width:112 align:#left across:2 71 | -- EV 72 | spinner spn_ev "EV" range:[0,1.0E6,6] fieldWidth:80 align:#right offset:[0,20] 73 | -- SHUTTER 74 | spinner spn_sh "Duration" range:[0,1.0E6,100] fieldWidth:60 align:#left 75 | -- SENSOR 76 | spinner spn_iso "ISO" range:[0,1.0E6,100] fieldWidth:60 align:#left offset:[23,0] 77 | ) 78 | 79 | group "Output size" 80 | ( 81 | spinner spn_w "Width" type:#integer range:[1,1000000,100] fieldwidth:65 align:#right across:2 82 | spinner spn_r "Ratio" type:#float range:[0.0,6.0,1.33] fieldwidth:65 align:#right 83 | spinner spn_h "Height" type:#integer range:[1,1000000,100] fieldwidth:65 align:#right across:2 84 | checkButton chk_ratio "LOCK" height:18 width:75 align:#right 85 | label lbl_presets "Presets" align:#left 86 | 87 | button p1 "9:16" width:40 across:5 88 | button p2 "2:3" width:40 89 | button p3 "4:5" width:40 90 | button p4 "3:4" width:40 91 | button p5 "1:1" width:40 92 | button p6 "4:3" width:40 across:5 93 | button p7 "16:10" width:40 94 | button p8 "16:9" width:40 95 | button p9 "2:1" width:40 96 | button p10 "21:9" width:40 97 | ) 98 | -------------------------------- 99 | local active_cam 100 | local list_cam 101 | local curr_itm = 1 102 | local ratios = #(0.5625, 0.666667, 0.8, 0.75, 1.0, 1.33333, 1.6, 1.77778, 2.0, 2.37037) 103 | -------------------------------- 104 | /* Store Resolution settings in camera */ 105 | fn set_cam_res cam w h r = 106 | ( 107 | if isValidNode cam then ( 108 | setUserProp cam "w_res" w 109 | setUserProp cam "h_res" h 110 | setUserProp cam "aspect_ratio" r 111 | ) 112 | ) 113 | /* Set default aspect ratio */ 114 | -- fn set_def_aspect cam r = () 115 | 116 | /* Get stored cam resolution */ 117 | fn get_cam_res cam &width &height &ratio = 118 | ( 119 | if isValidNode cam then ( 120 | 121 | local 122 | w = getUserProp cam "w_res", 123 | h = getUserProp cam "h_res", 124 | r = getUserProp cam "aspect_ratio" 125 | 126 | width = if w != undefined then w as integer --else undefined 127 | height = if h != undefined then h as integer --else undefined 128 | ratio = if r != undefined then r as float --else undefined 129 | ) 130 | ) 131 | /* Physical camera PROPERTIES */ 132 | fn shutterType2Values cam = 133 | ( 134 | case drp_ev.selection of ( 135 | 1: (spn_sh.value = 1.0 / cam.shutter_length_seconds) 136 | 2: (spn_sh.value = cam.shutter_length_seconds) 137 | 3: (spn_sh.value = cam.shutter_length_frames * 360) 138 | 4: (spn_sh.value = cam.shutter_length_frames) 139 | ) 140 | ) 141 | fn shutterValue cam val = 142 | ( 143 | case drp_ev.selection of ( 144 | 1: (cam.shutter_length_seconds = val / 1.0) 145 | 2: (cam.shutter_length_seconds = val) 146 | 3: (cam.shutter_length_frames = val / 360) 147 | 4: (cam.shutter_length_frames = val) 148 | ) 149 | ) 150 | fn get_camprops cam = 151 | ( 152 | if classOf cam == Physical then 153 | ( 154 | -- Lens 155 | spn_fl.enabled = NOT cam.specify_fov 156 | spn_fov.enabled = cam.specify_fov 157 | 158 | spn_fl.value = cam.focal_length_mm 159 | spn_fov.value = cam.fov 160 | chk_fov.state = cam.specify_fov 161 | 162 | chk_dof.state = cam.use_dof 163 | spn_f.value = cam.f_number 164 | chk_tilt.state = cam.auto_vertical_tilt_correction 165 | --shutter 166 | drp_ev.selection = cam.shutter_unit_type + 1 167 | shutterType2Values cam 168 | -- EV 169 | rd_ex.state = cam.exposure_gain_type + 1 170 | case cam.exposure_gain_type of 171 | ( 172 | 0:(spn_iso.enabled = true; spn_ev.enabled = false) 173 | 1:(spn_iso.enabled = false; spn_ev.enabled = true) 174 | ) 175 | spn_iso.value = cam.iso 176 | spn_ev.value = cam.exposure_value 177 | ) 178 | ) 179 | /* DEPRECATED */ 180 | fn set_camprops cam = 181 | ( 182 | if classOf cam == Physical then 183 | ( 184 | -- Lens 185 | cam.specify_fov = chk_fov.state 186 | cam.focal_length_mm = spn_fl.value 187 | cam.fov = spn_fov.value 188 | 189 | cam.use_dof = chk_dof.state 190 | cam.f_number = spn_f.value 191 | cam.auto_vertical_tilt_correction = chk_tilt.state 192 | 193 | -- shutter 194 | cam.shutter_unit_type = drp_ev.selection - 1 195 | shutterValue cam spn_sh.value 196 | -- EV 197 | cam.exposure_gain_type = rd_ex.state - 1 198 | case cam.exposure_gain_type of 199 | ( 200 | 0: (cam.iso = spn_iso.value) 201 | 1: (cam.exposure_value = spn_ev.value) 202 | ) 203 | spn_iso.value = cam.iso 204 | spn_ev.value = cam.exposure_value 205 | ) 206 | ) 207 | fn set_camprop cam prop val = 208 | ( 209 | if classOf cam == Physical AND isProperty cam prop then ( 210 | setProperty cam prop val 211 | ) 212 | ) 213 | /* GET RENDER RES VALUES */ 214 | fn get_output_values = 215 | ( 216 | spn_w.value = renderWidth 217 | spn_h.value = renderHeight 218 | spn_r.value = rendImageAspectRatio 219 | ) 220 | /* CHANGE RENDER RATIO */ 221 | fn set_output_ratio val = 222 | ( 223 | if renderSceneDialog.isOpen() then renderSceneDialog.close() 224 | rendImageAspectRatio = val 225 | spn_w.value = renderWidth 226 | spn_h.value = renderHeight 227 | CompleteRedraw() 228 | ) 229 | /* CHANGE RENDER RESOLUTION */ 230 | fn set_output_res w h = 231 | ( 232 | if renderSceneDialog.isOpen() then renderSceneDialog.close() 233 | if w != undefined then renderWidth = w 234 | if h != undefined then renderHeight = h 235 | spn_r.value = rendImageAspectRatio 236 | redrawViews() 237 | ) 238 | /* SELECT ACTIVE CAMERA */ 239 | fn selCam n = 240 | ( 241 | max modify mode 242 | if isValidNode n then select n 243 | ) 244 | /* LIST CAMERAS IN SCENE */ 245 | fn listCameras = 246 | ( 247 | for cam in cameras collect #(cam, cam.name) 248 | ) 249 | /* UPDATE CAMERA LIST */ 250 | fn relist_cams = 251 | ( 252 | list_cam = listCameras() 253 | lst_cams.items = for i in list_cam where (isKindOf i[1] camera) collect i[2] 254 | -- local only_names = for i in list_cam where (isKindOf i[1] camera) collect i[2] 255 | -- local only_cams = for i in list_cam where (isKindOf i[1] camera) collect i[1] 256 | -- lst_cams.items = only_names 257 | ) 258 | /* GET THE ACTIVE CAMERA */ 259 | fn change_active = 260 | ( 261 | if active_cam == undefined then active_cam = getActiveCamera() 262 | --active_cam = getActiveCamera() 263 | if active_cam != undefined then ( 264 | -- camera properties 265 | get_camprops active_cam 266 | -- load camera custom resolution AND assign to render settings 267 | get_cam_res active_cam &w &h &r 268 | 269 | if w != undefined AND h != undefined then ( 270 | -- Check if active preview is enabled 271 | if NOT owner.Active_preview then ( 272 | set_output_res w h 273 | get_output_values() 274 | ) 275 | lbl_cam.text = active_cam.name + "(" + w as string + "x" + h as string + ")" + "@" + r as string 276 | ) else ( 277 | lbl_cam.text = active_cam.name 278 | ) 279 | ) else ( 280 | lbl_cam.text = "None" 281 | ) 282 | RedrawViews() 283 | ) 284 | /* SET ACTIVE CAMERA IN VIEWPORT */ 285 | fn setActiveCam n = 286 | ( 287 | if n != undefined then ( 288 | local cam = if (isKindOf n string) then ( getNodeByName n) else n 289 | 290 | if isValidNode cam AND (isKindOf cam camera) then ( 291 | if viewport.CanSetToViewport cam then viewport.SetCamera cam 292 | active_cam = cam 293 | -- update 294 | change_active() 295 | ) 296 | ) 297 | ) 298 | -------------------------------- 299 | on roll_Cams open do 300 | ( 301 | change_active() 302 | relist_cams() 303 | get_output_values() 304 | chk_ratio.checked = rendLockImageAspectRatio 305 | ) 306 | on roll_Cams close do updateToolbarButtons() 307 | /* SELECT CAMERA */ 308 | on btn_s pressed do ( selCam active_cam ) 309 | /* PREVIOUS CAMERA */ 310 | on btn_prev_cam pressed do 311 | ( 312 | if curr_itm > 1 then curr_itm -=1 313 | lst_cams.selection = curr_itm 314 | setActiveCam lst_cams.selected 315 | 316 | owner.roll_batch.view_settings() 317 | ) 318 | /* NEXT CAMERA */ 319 | on btn_next_cam pressed do 320 | ( 321 | if curr_itm < lst_cams.items.count then curr_itm +=1 322 | lst_cams.selection = curr_itm 323 | setActiveCam lst_cams.selected 324 | 325 | owner.roll_batch.view_settings() 326 | ) 327 | /* CHANGE ACTIVE CAMERA */ 328 | on lst_cams selected item do 329 | ( 330 | curr_itm = item 331 | setActiveCam lst_cams.selected 332 | 333 | owner.roll_batch.view_settings() 334 | ) 335 | /* CAMERA PARAMETERS*/ 336 | -- Lens 337 | on chk_fov changed state do 338 | ( 339 | spn_fl.enabled = NOT state 340 | spn_fov.enabled = state 341 | set_camprop active_cam #specify_fov state 342 | ) 343 | on spn_lf changed val do set_camprop active_cam #focal_length_mm val 344 | on spn_fov changed val do set_camprop active_cam #fov val 345 | on chk_dof changed state do set_camprop active_cam #use_dof state 346 | on chk_tilt changed state do set_camprop active_cam #auto_vertical_tilt_correction state 347 | -- Shutter 348 | on drp_ev selected idx do ( 349 | shutterType2Values active_cam 350 | set_camprop active_cam #shutter_unit_type (idx - 1) 351 | ) 352 | on spn_sh changed val do shutterValue active_cam val 353 | -- EV 354 | on rd_ex changed state do 355 | ( 356 | case state of 357 | ( 358 | 1:(spn_iso.enabled = true; spn_ev.enabled = false) 359 | 2:(spn_iso.enabled = false; spn_ev.enabled = true) 360 | ) 361 | set_camprop active_cam #exposure_gain_type (state - 1) 362 | ) 363 | on spn_iso changed val do set_camprop active_cam #iso val 364 | on spn_ev changed val do set_camprop active_cam #exposure_value val 365 | /* REFRESH CAM LIST */ 366 | on btn_1 pressed do ( 367 | change_active() 368 | relist_cams() 369 | ) 370 | /* LOCK STATUS OF RENDER RATIO */ 371 | on chk_ratio changed status do ( 372 | rendLockImageAspectRatio = status 373 | ) 374 | /* CHANGE RENDER OUTPUT */ 375 | on spn_w changed val do ( 376 | 377 | if chk_ratio.checked then spn_h.value = floor(val/spn_r.value) 378 | -- set_output_res val undefined 379 | set_output_res val spn_h.value 380 | -- save values in camera 381 | set_cam_res active_cam val spn_h.value spn_r.value 382 | -- change_active() 383 | ) 384 | /* CHANGE RENDER HEIGHT */ 385 | on spn_h changed val do ( 386 | if chk_ratio.checked then spn_w.value = floor(val*spn_r.value) 387 | set_output_res spn_w.value val 388 | -- save values to camera 389 | set_cam_res active_cam spn_w.value val spn_r.value 390 | -- change_active() 391 | ) 392 | /* CHANGE RENDER WIDTH */ 393 | on spn_r changed val do ( 394 | set_output_ratio val 395 | -- save values to camera 396 | set_cam_res active_cam spn_w.value spn_h.value val 397 | -- change_active() 398 | ) 399 | /* IMAGE RATIO PRESETS */ 400 | fn preset val = 401 | ( 402 | set_output_ratio (spn_r.value = val) 403 | -- save values to camera 404 | set_cam_res active_cam spn_w.value spn_h.value spn_r.value 405 | change_active() 406 | ) 407 | /* PRESETS */ 408 | on p1 pressed do preset ratios[1] 409 | on p2 pressed do preset ratios[2] 410 | on p3 pressed do preset ratios[3] 411 | on p4 pressed do preset ratios[4] 412 | on p5 pressed do preset ratios[5] 413 | on p6 pressed do preset ratios[6] 414 | on p7 pressed do preset ratios[7] 415 | on p8 pressed do preset ratios[8] 416 | on p9 pressed do preset ratios[9] 417 | on p10 pressed do preset ratios[10] 418 | /*------------------------------ ROLLOUT END ------------------------------*/ 419 | ) 420 | roll_Cams 421 | ), 422 | /* BATCH ROLLOUT */ 423 | fn ui_batch = 424 | ( 425 | rollout roll_batch "Batch Render" 426 | ( 427 | local roll_w = 250 428 | local owner = if owner != undefined then owner 429 | -------------------------------- 430 | group "Batch views" 431 | ( 432 | listbox lst_views "Batch Views" height:5 433 | edittext txt_1 "View name" fieldWidth:(roll_w - 25) bold:true labelOnTop:true 434 | edittext txt_3 "File name" fieldWidth:(roll_w - 25) labelOnTop:true 435 | edittext txt_2 "Output" fieldWidth:(roll_w - 60) labelOnTop:true across:2 436 | button btn_p "..." align:#right offset:[0,15] tooltip:"Change path" 437 | checkbox chk_1 "Override output size in view" align:#left \ 438 | tooltip:"Set active render output size as view override" 439 | button btn_v "Add View to batch" width:(roll_w - 80) height:25 align:#left across:2 440 | button btn_rem "Delete" height:25 align:#right 441 | ) 442 | button btn_bup "Refresh" width:(roll_w - 70) height:25 align:#left 443 | tooltip:"Update the views list" 444 | button btn_b "Open Batch window" width:(roll_w - 70) height:25 align:#left 445 | -------------------------------- 446 | local batch_view 447 | local view_name = "" 448 | local view_path = undefined 449 | local active_view = undefined 450 | -------------------------------- 451 | /* FIND ITEM IN LIST */ 452 | fn findItemInList item lst = 453 | ( 454 | local idx = FindItem lst.Items item 455 | if idx != 0 then lst.selection = idx 456 | ) 457 | /* SET VIEW OUT PATH */ 458 | fn SetViewPath the_view = 459 | ( 460 | if view_path != undefined then the_view.outputFilename = view_path 461 | ) 462 | /* UPDATE BITMAP FILENAME */ 463 | fn update_Path cam: = 464 | ( 465 | if view_path != undefined then ( 466 | txt_2.text = getFilenamePath view_path 467 | txt_3.text = filenameFromPath view_path 468 | ) else ( 469 | txt_2.text = "" 470 | txt_3.text = "" 471 | ) 472 | ) 473 | /* LIST BATCH VIEWS */ 474 | fn list_views = 475 | ( 476 | local gv = batchRenderMgr.GetView 477 | local num = batchRenderMgr.numViews 478 | local col = for i=1 to num collect ( 479 | local the_view = gv i 480 | local st = if the_view.enabled then "[x] " else "[o] " 481 | st+the_view.name 482 | ) 483 | lst_views.items = col 484 | ) 485 | /* LOAD VIEW PROPS */ 486 | fn get_view_params index = 487 | ( 488 | local the_view = try (batchRenderMgr.GetView index) catch undefined 489 | if the_view != undefined then ( 490 | txt_1.text = the_view.name 491 | local cam = the_view.camera 492 | if isValidNode cam then ( 493 | owner.roll_Cams.setActiveCam cam 494 | -- SET CAM IN LIST 495 | findItemInList cam.name owner.roll_Cams.lst_cams 496 | -- Get the view Path 497 | if the_view.outputFilename != undefined then ( 498 | txt_2.text = getFilenamePath the_view.outputFilename 499 | txt_3.text = filenameFromPath the_view.outputFilename 500 | ) 501 | ) 502 | -- SET RENDER OUTPUT TO THE VIEW OVERRIDE, USEFUL TO SEE THE CROP FRAME ETC... 503 | if the_view.overridePreset then ( 504 | renderWidth = the_view.width 505 | renderHeight = the_view.height 506 | owner.roll_Cams.get_output_values() 507 | ) 508 | CompleteRedraw() 509 | ) 510 | the_view 511 | ) 512 | /* LOAD VIEW PROPS */ 513 | fn view_settings = 514 | ( 515 | local temp_cam = owner.roll_Cams.active_cam 516 | if (temp_cam != undefined) then ( 517 | txt_1.text = temp_cam.name + "-" + (rendImageAspectRatio as string) 518 | if (view_path != undefined) then ( 519 | local root = getFilenamePath view_path 520 | local type = getFilenameType view_path 521 | local filename = filenameFromPath view_path 522 | 523 | local comp_filename = temp_cam.name + type 524 | for i in owner.roll_Cams.list_cam do ( 525 | local n = i[2] 526 | local f = matchPattern filename pattern:("*"+n+"*") 527 | if f then ( 528 | local filename_parse = findString filename n 529 | comp_filename = replace filename filename_parse (n.count) temp_cam.name 530 | exit 531 | ) 532 | ) 533 | -- compose Path 534 | view_path = pathConfig.appendPath root comp_filename 535 | ) 536 | update_Path() 537 | ) 538 | ) 539 | /* ADD VIEW */ 540 | fn view_add = 541 | ( 542 | local temp_cam = owner.roll_Cams.active_cam 543 | if temp_cam != undefined then ( 544 | if (batchRenderMgr.FindView txt_1.text) == 0 then ( 545 | local new_view = batchRenderMgr.CreateView temp_cam 546 | if (new_view.overridePreset = chk_1.state) then ( 547 | new_view.width = renderWidth 548 | new_view.height = renderHeight 549 | ) 550 | new_view.name = txt_1.text 551 | new_view.outputFilename = view_path 552 | list_views() 553 | ) else messageBox "View Already exist.\nChange name AND try again." 554 | ) 555 | ) 556 | -------------------------------- 557 | on roll_batch open do 558 | ( 559 | view_settings() 560 | list_views() 561 | ) 562 | 563 | on roll_batch rolledUp state do ( 564 | if NOT state then ( 565 | owner.CamFloater.size.y -= roll_batch.height 566 | ) else ( 567 | owner.CamFloater.size.y += roll_batch.height 568 | ) 569 | ) 570 | -------------------------------- 571 | /* GET BATCH VIEW PARAMS */ 572 | on lst_views selected item do ( active_view = get_view_params item ) 573 | /* SET VIEW OUTPUT */ 574 | on btn_p pressed do 575 | ( 576 | if (view_path = getBitmapSaveFileName()) != undefined then ( 577 | update_Path() 578 | if active_view != undefined then ( 579 | SetViewPath active_view 580 | ) 581 | ) 582 | ) 583 | /* ADD VIEW */ 584 | on btn_v pressed do ( view_add() ) 585 | /* DELETE VIEW */ 586 | on btn_rem pressed do 587 | ( 588 | if (queryBox "Confirm view Deletion?") then ( 589 | if active_view != undefined then ( 590 | batchRenderMgr.DeleteView lst_views.selection 591 | -- refresh list 592 | batch_view = undefined 593 | view_name = "" 594 | -- view_path = undefined 595 | active_view = undefined 596 | list_views() 597 | ) 598 | ) 599 | ) 600 | /* UPDATE BATCH VIEWS LIST */ 601 | on btn_bup pressed do 602 | ( 603 | batch_view = undefined 604 | view_name = "" 605 | -- view_path = undefined 606 | active_view = undefined 607 | list_views() 608 | ) 609 | /* OPEN RENDER BATCH */ 610 | on btn_b pressed do (actionMan.executeAction -43434444 "4096") 611 | /*------------------------------ ROLLOUT END ------------------------------*/ 612 | ) 613 | roll_batch 614 | ), 615 | public 616 | /* TOOL MAIN UI */ 617 | fn showUI = 618 | ( 619 | local res = false 620 | -- TODO: LICENSING! 621 | if (CamFloater != undefined AND CamFloater.open) then ( 622 | try (closeRolloutFloater CamFloater) catch () 623 | CamFloater = undefined 624 | updateToolbarButtons() 625 | ) else ( 626 | roll_Cams = ui_cams() 627 | roll_Batch = ui_batch() 628 | 629 | roll_Cams.owner = this 630 | roll_Batch.owner = this 631 | 632 | CamFloater = newRolloutFloater "Camera Manager" 270 663 50 50 lockHeight:true lockWidth:true 633 | addRollout roll_Cams CamFloater border:false 634 | addRollout roll_Batch CamFloater 635 | res = true 636 | ) 637 | res 638 | ) 639 | ) 640 | ------------------------------------------------------ 641 | cmt = camManagerTool() 642 | ------------------------------------------------------ 643 | on execute do ( 644 | if cmt == undefined then cmt = camManagerTool() 645 | cmt.showUI() 646 | ) 647 | ) -------------------------------------------------------------------------------- /src/BUMP_gamma_adjustment.ms: -------------------------------------------------------------------------------- 1 | /* 2 | Utility for changing the gamma value of bitmap texture maps. Intended to be use on Normal Maps 3 | Note: this is a work-in-progress 4 | 2020 - https://atelierbump.com 5 | */ 6 | ( 7 | -------------------------------------------------CONFIGURATION 8 | -- RENDERER PRESETS. ADD YOUR OWN FOLOWING THE SAME PATTERN 9 | struct _std 10 | ( 11 | mat_filter_class = PhysicalMaterial, 12 | bitmap_filter = #bump_map, 13 | renderer_normalmap = #(#(Normal_Bump, #normal_map)), 14 | rndrBitmapTexture = #() 15 | ) 16 | struct _Arnold 17 | ( 18 | mat_filter_class = ai_standard_surface, 19 | bitmap_filter = #normal_shader, 20 | renderer_normalmap = #( 21 | #(ai_normal_map, #normal_shader), 22 | #(ai_bump2d, #normal_shader), 23 | #(ai_bump3d, #normal_shader) 24 | ), 25 | rndrBitmapTexture = #() 26 | ) 27 | struct _Vray 28 | ( 29 | mat_filter_class = VRayMtl, 30 | bitmap_filter = #texmap_bump, 31 | renderer_normalmap = #(#(VRayNormalMap, #normal_map)), 32 | rndrBitmapTexture = #(VRayHDRI, #gamma) 33 | ) 34 | struct _Corona 35 | ( 36 | mat_filter_class = CoronaMtl, 37 | bitmap_filter = #texmapBump, 38 | renderer_normalmap = #(#(CoronaNormal, #normalMap)), 39 | rndrBitmapTexture = #(CoronaBitmap, #gamma) 40 | ) 41 | /* 42 | -- EXAMPLE: ADD SUPPORT FOR OTHER RENDERER 43 | struct _Your_own 44 | ( 45 | -- Class of the shader 46 | mat_filter_class = Material_Class, 47 | -- Shader bump/normal property name 48 | bitmap_filter = #texmap_Bump_Property, 49 | -- renderer specific bump/normal map class and property for the normal texturemap. 50 | -- this can be more than one. i.e: look for Arnold implementation 51 | renderer_normalmap = #(#(Shader_Normal_Map, #normal_Map_Property)), 52 | -- renderer specific textureMap implementation and gamma property. Must be a float value 53 | rndrBitmapTexture = #(Renderer_Bitmap, #gamma_property_float) 54 | ) 55 | -- */ 56 | -- ENABLE - DISABLE RENDER ENGINES, ADD YOUR OWN HERE 57 | local RENDER_ENGINES_OPT = 58 | #( 59 | -- #("Your_own", _Your_own), 60 | #("Physical Material", _std), 61 | #("Arnold", _Arnold), 62 | #("Vray", _Vray), 63 | #("Corona", _Corona) 64 | ) 65 | ----------------------------------------------------------------- 66 | -- MAIN CODE -- DO NOT MODIFY! 67 | -- change bitmap gamma 68 | fn changeBmpGamma bmpTxt gammavalue:1.0 = 69 | ( 70 | try ( 71 | local curr_bitmap = bmpTxt.bitmap 72 | local new_bitmap = openBitMap curr_bitmap.filename gamma:gammavalue channels:curr_bitmap.channels 73 | setproperty bmpTxt #bitmap new_bitmap 74 | ) catch ( 75 | format "Conversion error: %\m" (getCurrentException()) 76 | ) 77 | ) 78 | -- search function. 79 | -- src parameter is the struct with the render engine parameters 80 | -- if "mats" is unsupplied it defaults to scene materials 81 | fn reassignMaps src _gamma:1.0 mats:unsupplied = 82 | ( 83 | -- format "%\n" src 84 | -- get the material collection 85 | local mat_loop = if mats == unsupplied then sceneMaterials else mats 86 | -- handle Multimaterial and filter collection to valid material class 87 | local actual_mat_list = #() 88 | 89 | for mat in mat_loop do ( 90 | -- single materials 91 | if (isKindOf mat src.mat_filter_class) then ( 92 | append actual_mat_list mat 93 | ) else if (isKindOf mat Multimaterial) then ( 94 | local multimat_childerns = 95 | for i in mat where (isKindOf i src.mat_filter_class) collect i 96 | join actual_mat_list multimat_childerns 97 | ) 98 | ) 99 | -- cleanup 100 | makeUniqueArray actual_mat_list 101 | 102 | -- change the properties 103 | for mat in actual_mat_list where (isKindOf mat src.mat_filter_class) do ( 104 | 105 | format "material: %\n" mat 106 | 107 | -- check for shader bitmap 108 | if (isProperty mat src.bitmap_filter) then ( 109 | local texturenode = getProperty mat src.bitmap_filter 110 | 111 | format "property: %\n" texturenode 112 | 113 | -- property must not be undefined 114 | if (texturenode != undefined) then ( 115 | -- check for Bitmaptexture 116 | if (ClassOf texturenode == Bitmaptexture) then 117 | ( 118 | -- CASE_A: standard bitmaptexture 119 | changeBmpGamma texturenode gammavalue:_gamma 120 | ) 121 | else 122 | ( 123 | -- CASE_B: renderer-specific normalMap. This generally implements some sort of a direct gamma property 124 | for i in src.renderer_normalmap do ( 125 | if ClassOf texturenode == i[1] then ( 126 | -- get the normalMap property 127 | local thebitmap = getProperty texturenode i[2] 128 | if ClassOf thebitmap == Bitmaptexture then ( 129 | -- CASE_B_1: standard bitmap 130 | changeBmpGamma thebitmap gammavalue:_gamma 131 | ) else ( 132 | -- CASE_B_2: render specific bitmap 133 | if src.rndrBitmapTexture.count > 1 then ( 134 | if ClassOf thebitmap == src.rndrBitmapTexture[1] then ( 135 | -- set the new gamma value 136 | -- this works only for float values 137 | if (isKindOf (getProperty thebitmap src.rndrBitmapTexture[2]) float) then ( 138 | setProperty thebitmap src.rndrBitmapTexture[2] _gamma 139 | ) 140 | ) 141 | ) 142 | ) 143 | ) 144 | ) 145 | ) 146 | ) 147 | ) 148 | -- format "-----------\n" 149 | ) 150 | ) 151 | -------------------------------------------------UI 152 | rollout roll_normalGamma "Change Normal Maps gamma" 153 | ( 154 | group "Operate on" 155 | ( 156 | radiobuttons rd_1 "" labels:#("Scene materials", "Material editor slots", "Selection") align:#left 157 | ) 158 | spinner spn_1 "Gamma value: " type:#float range:[-100.0,100.0,1.0] align:#left 159 | label lbl_1 "Render engine" align:#left 160 | Dropdownlist cb_renders "" 161 | label lbl_2 "WARNING!!!\nTHIS OPERATION\nCAN'T BE UNDONE" height:40 align:#left 162 | button btn_change "Change values" height:30 163 | on roll_normalGamma open do 164 | ( 165 | -- load render engines 166 | cb_renders.items = for i in RENDER_ENGINES_OPT collect i[1] 167 | -- tooltip 168 | btn_change.tooltip = "If you know some scripting,\nyou can edit this script to add more render engine options.\nLook for the file: "+(getThisScriptFilename()) 169 | ) 170 | on btn_change pressed do ( 171 | -- material collection 172 | local mats_col = 173 | case rd_1.state of 174 | ( 175 | 0: (unsupplied) 176 | 1: (unsupplied) 177 | 2: (meditMaterials) 178 | 3: (for i in (getCurrentSelection()) where i.material != undefined collect i.material) 179 | ) 180 | -- renderer 181 | local selected_renderer = RENDER_ENGINES_OPT[cb_renders.selection][2] 182 | selected_renderer = selected_renderer() 183 | -- execute 184 | -- single materials 185 | reassignMaps selected_renderer _gamma:spn_1.value mats:mats_col 186 | -- multi-materials? 187 | ) 188 | ) 189 | -------------------------------------------------EXECUTION - MAUNAL - AUTOMATED IMPLEMENTATION 190 | -- default gamma value to apply 191 | local _gamma_ = 1.0 -- 2.2 192 | ----------------------------------------------------------------- 193 | -- change maps gamma on scene materials 194 | -- set the render engine preset. 195 | /* 196 | reassignMaps _Corona _gamma:_gamma_ 197 | -- */ 198 | ------------------------------------------------- 199 | -- change maps in node selection material's 200 | /* 201 | local selection_materials = 202 | ( 203 | local sel = getCurrentSelection() 204 | for i in sel where i.material != undefined collect i.material 205 | ) 206 | -- set the render engine preset. 207 | reassignMaps _Corona mats:selection_materials _gamma:_gamma_ 208 | -- */ 209 | ------------------------------------------------- UI IMPLEMENTATION 210 | -- /* 211 | try (DestroyDialog roll_normalGamma) catch () 212 | CreateDialog roll_normalGamma 213 | -- */ 214 | ) -------------------------------------------------------------------------------- /src/BUMP_sunblind_cage_calc.ms: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------- 2 | /* https://atelierbump.com */ 3 | ---------------------------------------------------- 4 | -- Units in Centimeters 5 | ( 6 | -- Input data 7 | ---------------------------------------------------- 8 | -- Reel axis radius 9 | local r_eje = 5 10 | -- courtain length 11 | local l_total = 230 12 | -- courtain tickness 13 | local esp_cortina = 2 14 | ---------------------------------------------------- 15 | 16 | fn sunBlindCageCalc r_eje l_total esp_cortina = 17 | ( 18 | -- calc - do not modify 19 | local cant_vueltas = 0 20 | local r_calculo = 0 21 | while l_total > 0 do ( 22 | r_calculo = r_eje + ((esp_cortina * cant_vueltas)/2) 23 | perim = (2 * pi * r_calculo) 24 | cant_vueltas += 1 25 | l_total -= perim 26 | ) 27 | #(r_calculo, perim, cant_vueltas, l_total) 28 | ) 29 | 30 | rollout roll_ui "SunBlindCage" width:300 31 | ( 32 | spinner spn_1 "Reel radius" type:#float align:#left 33 | spinner spn_2 "Courtain length" type:#float align:#left 34 | spinner spn_3 "Courtain thickness" type:#float align:#left 35 | 36 | button btn_1 "Calc" width:150 37 | editText txt_1 "" heigth:300 38 | 39 | on btn_1 pressed do ( 40 | 41 | local res = sunBlindCageCalc spn_1.value spn_2.value spn_3.length 42 | local res_str = "" as StringStream 43 | -- output 44 | format "-----------DIMENSIONS - IN CM-----------\n" to:res_str 45 | format "FULL REEL DIAMETER: %\n" ((r_calculo*2) as String) to:res_str 46 | format "COURTAIN REVOLUTIONS: %\n" (cant_vueltas as String) to:res_str 47 | format "SQUARE CAGE SIDE: %\n" ((r_calculo * 2 + 10) as String) to:res_str 48 | txt_1.text = res_str as string 49 | ) 50 | ) 51 | ) 52 | -------------------------------------------------------------------------------- /src/BUMP_vertexScrambler.mcr: -------------------------------------------------------------------------------- 1 | /* 2 | BUMP 2016 3 | 22-05-16 4 | Vertex Scrambler 5 | v. 1.0.0 6 | http://www.scriptspot.com/users/ariel-g 7 | */ 8 | macroScript BUMP_vrtxScr 9 | category:"BUMP tools" 10 | ButtonText:"VSC" 11 | toolTip:"Vertex Scrambler" 12 | ( 13 | rollout roll_vertScramble "Vertex Scramble" width:200 14 | ( 15 | label lbl_1 "OFFSET" align:#left 16 | group "" 17 | ( 18 | spinner spn_dwX "X: " type:#worldunits range:[-1000000.0,1000000.0,0.0] fieldWidth:50 across:2 19 | spinner spn_upX "< " type:#worldunits range:[-1000000.0,1000000.0,0.0] fieldWidth:50 20 | spinner spn_dwY "Y: " type:#worldunits range:[-1000000.0,1000000.0,0.0] fieldWidth:50 across:2 21 | spinner spn_upY "< " type:#worldunits range:[-1000000.0,1000000.0,0.0] fieldWidth:50 22 | spinner spn_dwZ "Z: " type:#worldunits range:[-1000000.0,1000000.0,0.0] fieldWidth:50 across:2 23 | spinner spn_upZ "< " type:#worldunits range:[-1000000.0,1000000.0,0.0] fieldWidth:50 24 | checkbox chk_sfts "Use soft selection" 25 | ) 26 | button btn_Sc "Scramble" width:190 height:30 27 | button btn_unS "UnScramble" width:190 height:30 28 | checkButton chk_live "Live" width:190 height:20 29 | 30 | local 31 | downlimit, 32 | uplimit, 33 | obj, 34 | vert_sel, 35 | vert_pos 36 | 37 | fn vertScramble o vs d_l u_l soft_s:false = 38 | ( 39 | local vc = for i in vs collect random d_l u_l 40 | polyop.moveVert obj vs vc useSoftSel:soft_s 41 | ) 42 | 43 | fn vertUnScramble o vs vo = 44 | ( 45 | polyop.setVert o vs vo 46 | ) 47 | 48 | fn scrambler = 49 | ( 50 | undo "vertex scramble" on ( 51 | vertUnScramble obj vert_sel vert_pos 52 | vertScramble obj vert_sel downlimit uplimit soft_s:(chk_sfts.state) 53 | ) 54 | ) 55 | fn vert_sc = 56 | ( 57 | obj = $ 58 | if isKindOf tempsel Editable_Poly then ( 59 | if not (polyop.getVertSelection obj).isEmpty then ( 60 | vert_sel = polyop.getVertSelection obj 61 | vert_pos = for i in vert_sel collect ( polyop.getVert obj i) 62 | ) else (messageBox "Select some Vertex!"; DestroyDialog roll_vertScramble) 63 | 64 | ) else (messageBox "Select EditPoly Object!"; DestroyDialog roll_vertScramble) 65 | ) 66 | 67 | on roll_vertScramble open do ( 68 | vert_sc() 69 | 70 | downlimit = [spn_dwX.value, spn_dwY.value, spn_dwZ.value] 71 | uplimit = [spn_upX.value, spn_upY.value, spn_upZ.value] 72 | 73 | ) 74 | 75 | on spn_dwX changed val do (downlimit.x = val; if chk_live.state then ( scrambler() )) 76 | on spn_dwY changed val do (downlimit.y = val; if chk_live.state then ( scrambler() )) 77 | on spn_dwZ changed val do (downlimit.z = val; if chk_live.state then ( scrambler() )) 78 | on spn_upX changed val do (uplimit.x = val; if chk_live.state then ( scrambler() )) 79 | on spn_upY changed val do (uplimit.y = val; if chk_live.state then ( scrambler() )) 80 | on spn_upZ changed val do (uplimit.z = val; if chk_live.state then ( scrambler() )) 81 | on btn_Sc pressed do ( scrambler() ) 82 | on btn_unS pressed do ( vertUnScramble obj vert_sel vert_pos ) 83 | ) 84 | on isEnabled do roll_vertScramble.open 85 | on execute do CreateDialog roll_vertScramble 86 | ) -------------------------------------------------------------------------------- /src/BUMP_viewPortCompositionGuides-v1.mcr: -------------------------------------------------------------------------------- 1 | /* 2 | VIEWPORT COMPOSITION GUIDES 3 | 2020 4 | */ 5 | macroscript BUMP_vpComp 6 | category: "BUMP tools" 7 | buttontext: "viewport Composition guides" 8 | tooltip: "viewport Composition guides" 9 | ( 10 | rollout compGuide "Composition guides" 11 | ( 12 | group "Grid presets" 13 | ( 14 | checkbutton p1 "2 x 2" width:65 height:40 across:2 15 | checkbutton p2 "3 x 3" width:65 height:40 16 | ) 17 | group "Position Guides" 18 | ( 19 | button place1 "Horizontal" width:65 height:40 across:2 20 | button place2 "Vertical" width:65 height:40 21 | button place3 "Cross" width:65 height:40 across:2 22 | button place4 "From Pt" width:65 height:40 \ 23 | toolTip: "Position multiple aligned lines from a common base point. Useful to draw perspective lines from a vanishing point" 24 | ) 25 | colorPicker c1 "Guides Color" height:20 fieldwidth:30 align:#right default:yellow 26 | ------------------------------ 27 | -- store values 28 | local 29 | Guide_Lines, drawingLines, 30 | Grid_Lines, drawingGirds, 31 | Store_Point, Track_point, 32 | guideLine 33 | ------------------------------ 34 | /* VIEWPORT INFORMATION FUNCTIONS */ 35 | -- viewport data 36 | fn getViewportSafeFrameSize UIScaling:true = 37 | ( 38 | local viewSize_x = gw.getWinSizeX applyUIScaling:UIScaling 39 | local viewSize_y = gw.getWinSizeY applyUIScaling:UIScaling 40 | 41 | local viewAspect = viewSize_x as float / viewSize_y 42 | local renderAspect = renderWidth as float / renderHeight 43 | 44 | local x, y, w, h 45 | if (viewAspect > renderAspect) then 46 | ( 47 | h = viewSize_y 48 | w = (h * renderAspect) as integer 49 | y = 0 50 | x = (viewSize_x - w) / 2 51 | ) 52 | else 53 | ( 54 | w = viewSize_x 55 | h = (w / renderAspect) as integer 56 | x = 0 57 | y = (viewSize_y - h) / 2 58 | ) 59 | return box2 x y w h 60 | ) 61 | -- viewport diagonal size 62 | fn getViewPortDiagonalSize UIScaling:true = 63 | ( 64 | (length [gw.getWinSizeX applyUIScaling:UIScaling, gw.getWinSizeY applyUIScaling:UIScaling]) as integer 65 | ) 66 | ------------------------------ 67 | /* UTILITY FUNCTIONS */ 68 | -- get axes from mouse position 69 | fn tracker p2 ref axis:#x = 70 | ( 71 | local res 72 | if axis == #x then ( 73 | res = #( 74 | #( [p2.x, 0, 0], [p2.x, ref.y, 0] ), 75 | #() 76 | ) 77 | ) else if axis == #y then ( 78 | res = #( 79 | #(), 80 | #( [0, p2.y, 0], [ref.x , p2.y, 0] ) 81 | ) 82 | ) else ( 83 | res = #( 84 | #( [p2.x, 0, 0], [p2.x, ref.y, 0] ), 85 | #( [0, p2.y, 0], [ref.x , p2.y, 0] ) 86 | ) 87 | ) 88 | res 89 | ) 90 | -- construct grid 91 | fn viewPortGrid h v UIScaling:true = 92 | ( 93 | local 94 | Hdiv, Vdiv, 95 | resH, resV, 96 | dx, dy, 97 | fx, fy 98 | --local vpSize = 99 | if displaySafeFrames then ( 100 | local vpSize = getViewportSafeFrameSize UIScaling:UIScaling 101 | -- Hdiv = floor ((vpSize.h + vpSize.y) / h as float) 102 | -- Vdiv = floor ((vpSize.w + vpSize.x) / v as float) 103 | dx = vpSize.w 104 | dy = vpSize.h 105 | fx = vpSize.x 106 | fy = vpSize.y 107 | ) else ( 108 | -- Hdiv = floor (gw.getWinSizeX applyUIScaling:UIScaling / h as float) 109 | -- Vdiv = floor (gw.getWinSizeY applyUIScaling:UIScaling / v as float) 110 | dx = gw.getWinSizeX applyUIScaling:UIScaling 111 | dy = gw.getWinSizeY applyUIScaling:UIScaling 112 | fx = 0 113 | fy = 0 114 | ) 115 | Hdiv = floor ( dy / h ) 116 | Vdiv = floor ( dx / v ) 117 | 118 | resH = for ih=1 to (h - 1) collect ( 119 | #( 120 | -- mapScreenToView [0, Hdiv * ih] 1 applyUIScaling:UIScaling, 121 | -- mapScreenToView [dx, Hdiv * ih] 1 applyUIScaling:UIScaling 122 | [0, Hdiv * ih, 0] + [fx, fy, 0], 123 | [dx, Hdiv * ih, 0] + [fx, fy, 0] 124 | ) 125 | ) 126 | resV = for iv=1 to (v - 1) collect ( 127 | #( 128 | -- mapScreenToView [Vdiv * iv, 0] 1 applyUIScaling:UIScaling, 129 | -- mapScreenToView [Vdiv * iv, dy] 1 applyUIScaling:UIScaling 130 | [Vdiv * iv, 0, 0] + [fx, fy, 0], 131 | [Vdiv * iv, dy, 0] + [fx, fy, 0] 132 | ) 133 | ) 134 | join resH resV 135 | ) 136 | ------------------------------ 137 | /* MOUSE TRACK FUNCTIONS */ 138 | fn TraceMouse msg ir obj faceNum shift ctrl alt args = 139 | ( 140 | -- mouse.posUnscaled 141 | Track_point = tracker mouse.pos Store_Point axis:args 142 | redrawViews() 143 | 144 | case msg of 145 | ( 146 | #mouseAbort: undefined 147 | #freeMove: #continue 148 | #mouseMove: #continue 149 | #mousePoint: mouse.pos 150 | -- #mousePoint: mouse.posUnscaled 151 | default: msg 152 | ) 153 | ) 154 | ------------------------------ 155 | /* GRAPHIC FUNCTIONS */ 156 | fn GW_hline col RGBColor:yellow = 157 | ( 158 | if (isKindOf col Array) AND col.count > 0 then ( 159 | gw.setTransform (Matrix3 1) 160 | gw.setColor #line RGBColor 161 | 162 | for i in col do gw.hPolyline i false 163 | 164 | gw.enlargeUpdateRect #whole 165 | gw.updateScreen() 166 | ) 167 | ) 168 | fn GW_wline col RGBColor:yellow = 169 | ( 170 | if (isKindOf col Array) AND col.count > 0 then ( 171 | gw.setTransform (Matrix3 1) 172 | gw.setColor #line RGBColor 173 | 174 | for i in col do gw.wPolyline i false 175 | 176 | gw.enlargeUpdateRect #whole 177 | gw.updateScreen() 178 | ) 179 | ) 180 | -- gw callbacks 181 | fn GW_tracker = GW_wline Track_point RGBColor:c1.color 182 | fn GW_GridCallback = GW_hline Grid_Lines RGBColor:c1.color 183 | fn GW_LinesCallback = GW_wline Guide_Lines RGBColor:c1.color 184 | fn GW_GuideCallback = GW_wline guideLine RGBColor:c1.color 185 | ------------------------------ 186 | -- utility functions 187 | fn placeGuide axis:#x = 188 | ( 189 | local mPoint 190 | local res 191 | -- save resources: store the wp size 192 | Store_Point = [gw.getWinSizeX applyUIScaling:UIScaling, gw.getWinSizeY applyUIScaling:UIScaling] 193 | -- register line track gw 194 | unregisterRedrawViewsCallback GW_tracker 195 | registerRedrawViewsCallback GW_tracker 196 | -- track line 197 | if ( mPoint = mouseTrack snap:#3d trackCallback:#(TraceMouse, axis)) != undefined then 198 | ( 199 | -- just return the point 200 | res = Track_point 201 | ) 202 | -- unregister the tracker 203 | unregisterRedrawViewsCallback GW_tracker 204 | res 205 | ) 206 | fn drawGrids state h v = 207 | ( 208 | if state then ( 209 | try ( 210 | Grid_Lines = viewPortGrid h v 211 | unregisterRedrawViewsCallback GW_GridCallback 212 | registerRedrawViewsCallback GW_GridCallback 213 | redrawViews() 214 | ) 215 | catch ( 216 | unregisterRedrawViewsCallback GW_GridCallback 217 | format (getCurrentException()) 218 | ) 219 | ) else ( 220 | unregisterRedrawViewsCallback GW_GridCallback 221 | redrawViews() 222 | ) 223 | ) 224 | fn drawLines theGuide = 225 | ( 226 | if not drawingLines then ( 227 | drawingLines = true 228 | unregisterRedrawViewsCallback GW_LinesCallback 229 | registerRedrawViewsCallback GW_LinesCallback 230 | ) 231 | local res 232 | try ( 233 | if (res = theGuide) != undefined then ( 234 | -- add to lines collection 235 | join Guide_Lines res 236 | redrawViews() 237 | ) 238 | ) catch ( 239 | -- unregister gw 240 | unregisterRedrawViewsCallback GW_LinesCallback 241 | format (getCurrentException()) 242 | ) 243 | ) 244 | fn drawRays = 245 | ( 246 | -- implemented as a mouseTool 247 | tool raysTool 248 | ( 249 | -- base point 250 | local bp 251 | local vpDiagSize = getViewPortDiagonalSize() 252 | -- line function 253 | fn compline p1 p2 ext:1000 = 254 | ( 255 | local v = (normalize (p2 - p1)) * ext 256 | #(-v + p1, v + p1) 257 | ) 258 | -- events 259 | on start do ( 260 | registerRedrawViewsCallback GW_GuideCallback 261 | ) 262 | on stop do ( 263 | unRegisterRedrawViewsCallback GW_GuideCallback 264 | guideLine = #() 265 | ) 266 | -- click event 267 | on mousePoint clickno do ( 268 | if clickno == 1 then ( 269 | bp = [viewPoint.x, viewPoint.y, 0] 270 | ) else if clickno != 2 then ( 271 | -- add guide to display collection 272 | if guideLine[1] != undefined then drawLines guideLine 273 | ) 274 | ) 275 | -- mouse track event 276 | on mouseMove clickno do ( 277 | if bp != undefined then ( 278 | guideLine = #(compline bp [viewPoint.x, viewPoint.y, 0] ext:vpDiagSize) 279 | ) 280 | redrawViews() 281 | ) 282 | -- on mouseAbort ckickno do (...) 283 | ) 284 | -- start the tool 285 | startTool raysTool 286 | ) 287 | ------------------------------ 288 | -- open event 289 | on compGuide open do 290 | ( 291 | -- initialize values 292 | Guide_Lines = #() 293 | Grid_Lines = #() 294 | drawingLines = false 295 | 296 | Store_Point = [0, 0, 0] 297 | Track_point = [0, 0, 0] 298 | 299 | guideLine = #() 300 | ) 301 | -- close event 302 | on compGuide close do 303 | ( 304 | unregisterRedrawViewsCallback GW_tracker 305 | unregisterRedrawViewsCallback GW_GridCallback 306 | unregisterRedrawViewsCallback GW_LinesCallback 307 | unregisterRedrawViewsCallback GW_GuideCallback 308 | redrawViews() 309 | ) 310 | ------------------------------ 311 | -- draw 2x2 grid 312 | on p1 changed state do (drawGrids state 2 2; if p2.checked then p2.checked = false) 313 | -- draw 3x3 grid 314 | on p2 changed state do (drawGrids state 3 3; if p1.checked then p1.checked = false) 315 | ------------------------------ 316 | -- draw horiz lines 317 | on place1 pressed do drawLines (placeGuide axis:#y) 318 | -- draw vert lines 319 | on place2 pressed do drawLines (placeGuide axis:#x) 320 | -- draw cross lines 321 | on place3 pressed do drawLines (placeGuide axis:#xy) 322 | -- draw free position guide 323 | on place4 pressed do drawRays() 324 | ) 325 | 326 | on isChecked do if compGuide != undefined then compGuide.open else false 327 | 328 | on execute do ( 329 | try ( 330 | if not compGuide.open then CreateDialog compGuide 331 | ) catch ( 332 | DestroyDialog compGuide 333 | CreateDialog compGuide 334 | ) 335 | ) 336 | ) -------------------------------------------------------------------------------- /src/BUMP_xref_replace.mcr: -------------------------------------------------------------------------------- 1 | /* 2 | ------------------------------------------------------------------------------------------------------------------ 3 | https://atelierbump.com 4 | Xref Object Utilities 5 | ------------------------------------------------------------------------------------------------------------------ 6 | */ 7 | macroScript BUMP_toXref 8 | category: "BUMP tools" 9 | buttonText: "Replace with Xref" 10 | toolTip: "Replace selected node with Xref Record" 11 | ( 12 | fn centroid objs = 13 | ( 14 | local sumpoints = [0.0f,0.0f,0.0f] 15 | for i in objs do ( 16 | sumpoints += i.pos 17 | ) 18 | sumpoints /= objs.count 19 | ) 20 | ----------------------------------------- 21 | fn place objs ref = 22 | ( 23 | local cent = centroid objs 24 | for i in objs where (i.parent == undefined) do ( 25 | i.pos = (cent - i.pos) + ref 26 | ) 27 | ) 28 | ----------------------------------------- 29 | fn setXrefRecord obj filename deleteRef:true = 30 | ( 31 | if (not (isValidNode obj)) AND (not (doesFileExist filename)) then return false 32 | 33 | local xrefRecord 34 | local the_nodes = #() 35 | 36 | with redraw off ( 37 | -- load XrefObject 38 | xrefRecord = objXRefMgr.AddXRefItemsFromFile filename xrefOptions:#(#selectnodes) 39 | if xrefRecord == undefined then return false 40 | -- check for xref existence ? 41 | if (xrefRecord.Update()) then ( 42 | format "RECORD LOADED\n" 43 | -- get items 44 | xrefRecord.GetItems #XRefObjectType &xrefItems 45 | if xrefItems == undefined then return false 46 | -- get nodes 47 | for itm in xrefItems where (isKindOf itm XRefObject) do ( 48 | itm.getNodes &nodelist 49 | join the_nodes nodelist 50 | ) 51 | place the_nodes obj.pos 52 | ) 53 | -- delete refnode 54 | if deleteRef then delete obj 55 | ) 56 | -- update xrefs 57 | objXRefMgr.UpdateAllRecords() 58 | true 59 | ) 60 | ----------------------------------------- 61 | fn XrefReplace = 62 | ( 63 | local file = getOpenFileName caption:"Xref Object file" types:"Max files (*.max)|*.max" historyCategory:"XREFOPEN" 64 | local obj = (getCurrentSelection())[1] 65 | setXrefRecord obj file 66 | ) 67 | ----------------------------------------- 68 | on execute do XrefReplace() 69 | ----------------------------------------- 70 | ) -------------------------------------------------------------------------------- /src/Panel_cuts/example/cuts_CUTS REPORT.csv: -------------------------------------------------------------------------------- 1 | CUTS REPORT 2 | "QUANT.","HEIGHT","LENGTH","THICKNESS","ORIENTATION","FINISH","PART","DESCRIPTION" 3 | "2","160.0","60.0","1.8","H","MDF PANEL - white finish (melamine)","BODY - roof","" 4 | "2","101.3","52.8333","1.8","H","MDF PANEL - wood texture","Ddoor 2","" 5 | "4","98.2","60.0","1.8","H","MDF PANEL - white finish (melamine)","Body - vert. Divider","" 6 | "1","60.0","50.3333","1.8","H","MDF PANEL - white finish (melamine)","Horiz - Divider","" 7 | "1","60.0","52.1333","1.8","H","MDF PANEL - white finish (melamine)","Horiz - Divider","" 8 | "1","60.0","50.3333","1.8","H","MDF PANEL - white finish (melamine)","Horiz - Divider","" 9 | "1","52.8333","50.5437","1.8","H","MDF PANEL - wood texture","Door 3","" 10 | "1","52.8333","50.3791","1.8","H","MDF PANEL - wood texture","Door 1","" 11 | -------------------------------------------------------------------------------- /src/Panel_cuts/example/panel_cuts_test.max: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HAG87/maxscript-assorted/962c5c5a67dac1201e0878e7f536395d815cd817/src/Panel_cuts/example/panel_cuts_test.max -------------------------------------------------------------------------------- /src/Panel_cuts/src/psd/panel_cuts.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HAG87/maxscript-assorted/962c5c5a67dac1201e0878e7f536395d815cd817/src/Panel_cuts/src/psd/panel_cuts.psd -------------------------------------------------------------------------------- /src/Panel_cuts/src/psd/panel_cuts_intro.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HAG87/maxscript-assorted/962c5c5a67dac1201e0878e7f536395d815cd817/src/Panel_cuts/src/psd/panel_cuts_intro.psd -------------------------------------------------------------------------------- /src/Panel_cuts/src/psd/panel_cuts_ui.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HAG87/maxscript-assorted/962c5c5a67dac1201e0878e7f536395d815cd817/src/Panel_cuts/src/psd/panel_cuts_ui.psd -------------------------------------------------------------------------------- /src/Panel_cuts/src/scripts/BUMP_panelCuts.ms: -------------------------------------------------------------------------------- 1 | ( 2 | /* 3 | ------------------------------------------------------------------------------------------------------- 4 | BUMP Panel Cuts 5 | BUMP 2016 6 | version 1.0 - 12-16 7 | ------------------------------------------------------------------------------------------------------- 8 | */ 9 | ---- STRINGS 10 | Local 11 | r_title = "PANEL CUTS", 12 | c_name = "Name:", 13 | c_h = "Height: ", 14 | c_l = "Length: ", 15 | c_w = "Thickness: ", 16 | c_ck_h = "HEIGHT", 17 | c_ck_l = "LENGTH", 18 | c_f = "Finish: ", 19 | c_t = "Part: ", 20 | c_c = "Caption: ", 21 | c_d = "Description: ", 22 | c_ss = "SELECTION", 23 | c_s = "Selected", 24 | c_ps = " > SAVE TO FILE - Current Selection", 25 | c_pa = " > SAVE TO FILE - All Objects", 26 | c_i = "REPORT ", 27 | l_o = "Grain Direction", 28 | l_cp = "-------------- SHEET QNT --------------", 29 | l_dm = "Sheet dimensions: ", 30 | sc_u = "Scale Up", 31 | sc_d = "Scale Down", 32 | ---- 33 | drp_itms = #("Vertical","Horizontal"), 34 | ---- 35 | strf_p1 = "Estimated Sheets quantity with a wastage of ", 36 | strf_p2 = "taking into account the selected objects", 37 | str_q1 = "This operation will scale up computed dimensions on x% factor. Are you sure?", 38 | str_q2 = "This operation will scale down computed dimensions on x% factor. Are you sure?", 39 | str_cap = "CUTS REPORT", 40 | ---- 41 | str_titles = "\"HEIGHT\",\"LENGTH\",\"THICKNESS\",\"ORIENTATION\",\"FINISH\",\"PART\",\"DESCRIPTION\"\n", 42 | str_titles_2 = "\"QUANT.\",\"HEIGHT\",\"LENGTH\",\"THICKNESS\",\"ORIENTATION\",\"FINISH\",\"PART\",\"DESCRIPTION\"\n", 43 | ---- 44 | str_ok = "COMMIT", 45 | ---- TOOLTIPS 46 | t1 = "Commit changes, right click on button to change all objects in selection.", 47 | t2 = "Set selected objects as active object collection. Use previous and next buttons to navigate through the object collection.", 48 | t3 = "Previuos object. Right click to commit parameter changes.", 49 | t4 = "Next object. Right click to commit parameter changes.", 50 | t5 = "Pick object in viewport and set it as active.", 51 | t6 = "Scale measured object units (not reflected in geometry).", 52 | t7 = "Compute sheet area use.", 53 | t8 = "Conversion factor for units." 54 | ---- DEFAULT VALUES 55 | local vals_to_file = #("h","l","w","orientation","mat","part","description") 56 | ---- 57 | struct _props 58 | ( 59 | obj, 60 | l,w,h, 61 | orientation, 62 | _name, part, description, 63 | mat 64 | ) 65 | struct _gw 66 | ( 67 | fn GW_text p txt RGBcolor:(color 8 180 150) = 68 | ( 69 | if (p != undefined and txt != undefined) then ( 70 | gw.setTransform (matrix3 1) 71 | local _p = gw.hTransPoint p 72 | gw.hText _p txt color:black 73 | local pr = gw.getTextExtent txt 74 | p1 = [_p.x,_p.y] - [2.5,0.0] 75 | p2 = pr + p1 + 5.0 76 | local bx = Box2 p1 p2 77 | gw.hRect bx RGBcolor 78 | gw.enlargeUpdateRect #whole 79 | gw.updateScreen() 80 | ) 81 | ) 82 | ) 83 | struct _cm 84 | ( 85 | ------------------------------------------------------------------------------------ Object checking 86 | fn check_obj obj = (if (obj != undefined) and (superClassOf obj == GeometryClass) then obj else undefined), 87 | fn getObjSelect = 88 | ( 89 | local tmp = (selection as Array) 90 | local validObjs = 91 | if tmp[1] != undefined then ( 92 | for i in tmp where (superClassOf i == GeometryClass) collect i 93 | ) else undefined 94 | ), 95 | fn selector objs indx: = 96 | ( 97 | for i in objs do ( 98 | if isValidNode i then ( 99 | if i.displayByLayer then i.displayByLayer = false 100 | i.boxmode = true 101 | ) 102 | ) 103 | if indx != unsupplied then objs[indx].boxmode = false 104 | objs[indx] 105 | ), 106 | fn unselector objs = 107 | ( 108 | if objs != undefined then ( 109 | for i in objs do ( 110 | if isValidNode i then ( 111 | i.boxmode = false 112 | ) 113 | ) 114 | ) 115 | ), 116 | ------------------------------------------------------------------------------------ Math functions 117 | fn CalculateVolumeAndCenterOfMass obj = 118 | ( 119 | if (superclassof obj) == geometryclass then ( 120 | local Volume= 0.0 121 | local Center= [0.0, 0.0, 0.0] 122 | local theMesh = snapshotasmesh obj 123 | local numFaces = theMesh.numfaces 124 | for i = 1 to numFaces do 125 | ( 126 | local Face= getFace theMesh i 127 | local vert2 = getVert theMesh Face.z 128 | local vert1 = getVert theMesh Face.y 129 | local vert0 = getVert theMesh Face.x 130 | local dV = Dot (Cross (vert1 - vert0) (vert2 - vert0)) vert0 131 | Volume+= dV 132 | Center+= (vert0 + vert1 + vert2) * dV 133 | ) 134 | delete theMesh 135 | Volume /= 6 136 | Center /= 24 137 | Center /= Volume 138 | #(Volume,Center) 139 | ) else #(undefined, undefined) 140 | ), 141 | fn changeUnits _objs up:true factor:10.0 = 142 | ( 143 | if _objs != undefined then ( 144 | for o in _objs do ( 145 | local h = getUserProp o "h" 146 | local l = getUserProp o "l" 147 | local w = getUserProp o "w" 148 | --- 149 | if isKindOf h float then setUserProp o "h" (if up then h*factor else h/factor) 150 | if isKindOf l float then setUserProp o "l" (if up then l*factor else l/factor) 151 | if isKindOf w float then setUserProp o "w" (if up then w*factor else w/factor) 152 | ) 153 | ) 154 | ), 155 | fn ReverseArray arr = (for i=arr.count to 1 by -1 collect arr[i]), 156 | fn sortMax arr1 arr2 maxtomin:true = 157 | ( 158 | local first = arr1[1], 159 | second = arr2[1] 160 | if (isKindOf first float) and (isKindOf second float) then ( 161 | case of ( 162 | (first < second): if maxtomin then 1 else -1 163 | (first > second): if maxtomin then -1 else 1 164 | default:0 165 | ) 166 | ) else 0 167 | ), 168 | fn getDims obj = 169 | ( 170 | if (obj != undefined) and (superClassOf obj == GeometryClass) then ( 171 | local bbx = in coordsys local nodeLocalBoundingBox obj 172 | local dim = bbx[2] - bbx[1] 173 | local coords = _cm.ReverseArray (sort #(dim.x, dim.y, dim.z)) 174 | ) else undefined 175 | ), 176 | ------------------------------------------------------------------------------------ userProps functions 177 | fn setUserProps obj getFrom = 178 | ( 179 | try( 180 | local prop = getPropNames getFrom 181 | for i in prop do ( 182 | local p = getProperty getFrom i 183 | if (getHashValue p 10) != undefined then ( 184 | setUserProp obj (toLower (i as string) ) p 185 | ) 186 | ) 187 | ) catch (displayTempPrompt (getCurrentException()) 6000 ) 188 | ), 189 | ------------------------------------------------------------------------------------ file functions 190 | fn saveFile str fname = 191 | ( 192 | local fnArr = filterString fname "*.*" 193 | try ( 194 | local out_name = GetSaveFileName filename:fname types:("*."+fnArr[2]) 195 | if out_name != undefined then ( 196 | local out_file = createfile out_name 197 | format (str as String) to:out_file 198 | close out_file 199 | ) 200 | return out_name 201 | ) catch (return undefined) 202 | ), 203 | ------------------------------------------------------------------------------------ Save UserProps to file 204 | fn prop_str _objs caption: titles:"" vals:#("h","l","w","orientation","finish","part","description") = 205 | ( 206 | if titles != unsupplied and vals != unsupplied then ( 207 | -- rows 208 | local obj_v = #() 209 | for o in _objs do ( 210 | local temp_v = for i=1 to vals.count collect 211 | ( 212 | local v = getUserProp o vals[i] 213 | v = if v != undefined then v else "-" 214 | ) 215 | append obj_v temp_v 216 | ) 217 | -- sort array 218 | qsort obj_v _cm.sortMax 219 | -- /* 220 | -- add row number 221 | for i in obj_v do ( insertItem 1 i 1 ) 222 | -- group similars 223 | local del_sim = deepCopy obj_v 224 | for i = del_sim.count to 2 by -1 do ( 225 | if ( (del_sim[i][2] == del_sim[i-1][2]) and (del_sim[i][3] == del_sim[i-1][3]) ) and (del_sim[i][5] == del_sim[i-1][5]) then ( 226 | del_sim[i-1][1] += del_sim[i][1] 227 | deleteItem del_sim i 228 | ) 229 | ) 230 | -- generate file 231 | local theFile = StringStream "" 232 | if caption != unsupplied do ( append theFile (caption + "\n") ) 233 | append theFile titles 234 | for i in del_sim do ( 235 | for f=1 to i.count do ( 236 | if f < i.count then ( 237 | format "\"%\"," i[f] to:theFile 238 | ) else ( 239 | format "\"%\"\n" i[f] to:theFile 240 | ) 241 | ) 242 | ) 243 | free obj_v 244 | free del_sim 245 | theFile 246 | -- */ 247 | ) 248 | ) 249 | ) 250 | fn PanelCuts = 251 | ( 252 | rollout roll_props r_title width:270 253 | ( 254 | EditText txt_1 c_name fieldWidth:(roll_props.width - 20) readOnly:true align:#right labelOnTop:true 255 | EditText txt_2_1 c_h fieldWidth:180 readOnly:true align:#right 256 | EditText txt_2_2 c_l fieldWidth:180 readOnly:true align:#right 257 | EditText txt_2_3 c_w fieldWidth:180 readOnly:true align:#right 258 | imgTag sep3 width:(roll_props.width - 30) height:1 bitmap:(bitmap 1 2 color: (color 5 5 5)) offset:[0,5] align:#center 259 | label lbl_sep1 "PROPERTIES" align:#center 260 | dropdownlist drp_1 l_o items:drp_itms 261 | checkBox ck_o1 c_ck_h checked:true across:2 align:#left enabled:false 262 | checkBox ck_o2 c_ck_l align:#left enabled:false 263 | imgTag sep2 width:(roll_props.width - 30) height:1 bitmap:(bitmap 1 2 color: (color 5 5 5)) offset:[0,5] align:#center 264 | editText txt_m c_f fieldWidth:245 labelOnTop:true 265 | listbox lst_m "" height:3 width:245 266 | editText txt_3 c_t fieldWidth:245 labelOnTop:true 267 | listbox lst_t height:5 width:245 268 | editText txt_4 c_d height:50 fieldWidth:245 labelOnTop:true 269 | button btn_1 str_ok height:30 width: 245 tooltip:t1 270 | imgTag sep4 width:(roll_props.width - 30) height:1 bitmap:(bitmap 1 2 color: (color 5 5 5)) offset:[0,5] align:#center 271 | label lbl_sep2 "SELECT PARTS" align:#center 272 | button btn_p "<<" align:#left height:30 across:3 tooltip:t3 273 | button btn_sg c_ss height:30 width:170 tooltip:t2 274 | button btn_n ">>" height:30 align:#right tooltip:t4 275 | checkbutton btn_a "Viewport select" highlightColor:(color 80 120 30) height:25 width:240 align:#center offset:[0,10] tooltip:t5 276 | 277 | 278 | group "UTILITIES" 279 | ( 280 | label lbl_sep4 "Scale Units" align:#left offset:[0,10] 281 | imgTag sep6 width:(roll_props.width - 30) height:1 bitmap:(bitmap 1 2 color: (color 5 5 5)) offset:[0,0] align:#center 282 | spinner spn_f "Factor:" type:#float range:[1.0,1000000.0,10.0] width:150 align:#left across:2 283 | button btn_m1 sc_u width:80 align:#right tooltip:t6 284 | button btn_m2 sc_d width:80 align:#right tooltip:t6 285 | 286 | label lbl_sep5 "Sheet use" align:#left 287 | imgTag sep7 width:(roll_props.width - 30) height:1 bitmap:(bitmap 1 2 color: (color 5 5 5)) offset:[0,0] align:#center 288 | label l_dmns l_dm align:#left 289 | spinner spn_p1 "W: " type:#worldunits range:[1.0,1000000.0,183.0] fieldwidth:70 align:#right across:2 290 | spinner spn_p2 "H: " type:#worldunits range:[1.0,1000000.0,260.0] fieldwidth:70 align:#right 291 | spinner spn_p3 "Waste %: " type:#float range:[1.0,100.0,20.0] fieldwidth:70 offset:[0,10] align:#right 292 | spinner spn_p4 "Unit conversion: " type:#float range:[1.0,100.0,1.0] fieldwidth:70 align:#right tooltip:t8 293 | button btn_p1 c_i width:240 height:25 align:#center offset:[0,10] tooltip:t7 294 | 295 | label lbl_sep6 "Save to file" align:#left 296 | imgTag sep8 width:(roll_props.width - 30) height:1 bitmap:(bitmap 1 2 color: (color 5 5 5)) offset:[0,0] align:#center 297 | editText txt_c c_c text:str_cap fieldwidth:240 labelonTop:true 298 | button btn_lst_s c_ps width:240 height:30 align:#center offset:[0,10] 299 | button btn_lst_a c_pa width:240 height:30 align:#center offset:[0,10] 300 | ) 301 | ------------------------------------------------------------------------------------ UI VALUES 302 | local dimTxt = #(txt_2_2, txt_2_1, txt_2_3) 303 | local propsTxt = #(txt_3, txt_4) 304 | ------------------------------------------------------------------------------------ COMMON VALUES 305 | local props 306 | local obj 307 | local objs 308 | local index 309 | local tempSel 310 | local callbackItem 311 | local tempPoint, tempText 312 | ------------------------------------------------------------------------------------ Graphic functions 313 | fn GW_txt_callback = (_gw.GW_text tempPoint tempText) 314 | ------------------------------------------------------------------------------------ selection functions 315 | fn startSelector &item call = ( item = NodeEventCallback mouseup:true delay:1000 selectionChanged:call ) 316 | fn stopSelector &item = ( item = undefined; gc light:true ) 317 | ------------------------------------------------------------------------------------ 318 | -- rewrite 319 | fn getValues obj &props = 320 | ( 321 | if (obj != undefined) and (superClassOf obj == GeometryClass) then ( 322 | props.obj = obj.name 323 | local coords = _cm.getDims obj 324 | props.L = coords[2]; props.H = coords[1]; props.W = coords[3] 325 | 326 | props.orientation = getUserProp obj "orientation" 327 | props.part = getUserProp obj "part" 328 | props.description = getUserProp obj "description" 329 | props.mat = getUserProp obj "mat" 330 | ) 331 | ) 332 | fn setValues &props val: _props:#("_name","Lenght","Width","Height","Orient","Part","Description","mat") = 333 | ( 334 | props.obj = _props[1] 335 | props.orientation = _props[5] 336 | props.part = _props[6] 337 | props.description = _props[7] 338 | props.mat = _props[8] 339 | ) 340 | fn set_val_toObj obj objs _update_all:false = 341 | ( 342 | if obj != undefined then ( 343 | local d = #("V","H") 344 | if _update_all then ( 345 | for i in objs do ( 346 | getValues i &props 347 | setValues &props _props:#(txt_1.text,"Lenght","Width","Height",d[drp_1.selection],txt_3.text ,txt_4.text,txt_m.text) 348 | _cm.setUserProps i props 349 | ) 350 | ) else ( 351 | setValues &props _props:#(txt_1.text,"Lenght","Width","Height",d[drp_1.selection],txt_3.text ,txt_4.text,txt_m.text) 352 | _cm.setUserProps obj props 353 | ) 354 | ) 355 | ) 356 | -- UI update 357 | fn loadToUI props = 358 | ( 359 | try ( 360 | txt_1.text = props.obj 361 | txt_2_1.text = units.formatValue props.H 362 | txt_2_2.text = units.formatValue props.L 363 | txt_2_3.text = units.formatValue props.W 364 | ) catch() 365 | 366 | if props.orientation == "V" then ( 367 | drp_1.selection = 1 368 | ck_o1.checked = true; ck_o2.checked = false 369 | ) else ( 370 | drp_1.selection = 2 371 | ck_o1.checked = false; ck_o2.checked = true 372 | ) 373 | ck_o1.caption = c_ck_h + ": " + txt_2_1.text 374 | ck_o2.caption = c_ck_l + ": " + txt_2_2.text 375 | 376 | txt_3.text = if props.part != undefined then (props.part as string) else "" 377 | txt_4.text = if props.description != undefined then (props.description as string) else "" 378 | txt_m.text = if props.mat != undefined then props.mat else "" 379 | ) 380 | fn validate = ( getValues obj &props; loadToUI props ) 381 | fn sel_shuffle &i _t _to:#up = 382 | ( 383 | case _to of ( 384 | #up:(if i < objs.count do i +=1) 385 | #down:(if i > 1 do i -=1) 386 | ) 387 | _cm.selector objs indx:i 388 | obj = objs[i] 389 | validate() 390 | tempPoint = (_cm.CalculateVolumeAndCenterOfMass obj)[2] 391 | tempText = (props.l as string)+"x"+(props.h as string)+"x"+(props.w as string) 392 | ) 393 | ------------------------------------------------------------------------------------ selector Callback 394 | fn CallBackSel ev nd = 395 | ( 396 | obj = _cm.check_obj (selection[1]) 397 | if obj != undefined then validate() 398 | tempPoint = (_cm.CalculateVolumeAndCenterOfMass obj)[2] 399 | tempText = (props.l as string)+"x"+(props.h as string)+"x"+(props.w as string) 400 | ) 401 | ------------------------------------------------------------------------------------ EVENTS 402 | on roll_props open do ( props = _props() ) 403 | on roll_props close do 404 | ( 405 | if objs != undefined do ( _cm.unselector objs ) 406 | unregisterRedrawViewsCallback GW_txt_callback 407 | ) 408 | ------------------------------------------------------------------------------------ objects selection 409 | on btn_sg pressed do 410 | ( 411 | if objs != undefined do ( _cm.unselector objs ) 412 | unregisterRedrawViewsCallback GW_txt_callback 413 | tempPoint = undefined 414 | btn_sg.caption = c_ss 415 | objs = _cm.getObjSelect() 416 | if objs != undefined do ( 417 | index = 1 418 | btn_sg.caption = c_ss + "("+(objs.count as String)+")" 419 | _cm.selector objs indx:index 420 | obj = objs[index] 421 | validate() 422 | tempPoint = (_cm.CalculateVolumeAndCenterOfMass obj)[2] 423 | tempText = (props.l as string)+"x"+(props.h as string)+"x"+(props.w as string) 424 | registerRedrawViewsCallback GW_txt_callback 425 | ) 426 | ) 427 | ------------------------------------------------------------------------------------ automatic selection 428 | on btn_a changed state do 429 | ( 430 | if state then ( 431 | registerRedrawViewsCallback GW_txt_callback 432 | startSelector &callbackItem CallBackSel 433 | ) else ( 434 | stopSelector &callbackItem 435 | unregisterRedrawViewsCallback GW_txt_callback 436 | ) 437 | ) 438 | ------------------------------------------------------------------------------------ 439 | on txt_m entered val do ( lst_m.items = append (lst_m.items) val ) 440 | on lst_m selected itm do (txt_m.text = lst_m.items[itm]) 441 | on txt_3 entered val do ( lst_t.items = append (lst_t.items) val ) 442 | on lst_t selected itm do (txt_3.text = lst_t.items[itm]) 443 | ------------------------------------------------------------------------------------ 444 | on drp_1 selected itm do 445 | ( 446 | case itm of ( 447 | 1:( 448 | props.orientation = "V" 449 | local t = copy props.H 450 | props.H = props.L 451 | props.L = t 452 | ) 453 | 2:( 454 | props.orientation = "H" 455 | local t = copy props.L 456 | props.L = props.H 457 | props.H = t 458 | ) 459 | ) 460 | loadToUI props 461 | ) 462 | ------------------------------------------------------------------------------------ 463 | on btn_n pressed do ( 464 | sel_shuffle &index (objs.count) _to:#up 465 | ) 466 | on btn_n rightclick do ( 467 | set_val_toObj obj objs _update_all:false 468 | sel_shuffle &index (objs.count) _to:#up 469 | ) 470 | -- update option 471 | on btn_p pressed do ( 472 | sel_shuffle &index (objs.count) _to:#down 473 | ) 474 | on btn_p rightclick do ( 475 | set_val_toObj obj objs _update_all:false 476 | sel_shuffle &index (objs.count) _to:#down 477 | ) 478 | ------------------------------------------------------------------------------------ establece valores 479 | on btn_1 pressed do ( 480 | set_val_toObj obj objs _update_all:false 481 | ) 482 | -- apply to all 483 | on btn_1 rightclick do ( 484 | set_val_toObj obj objs _update_all:true 485 | ) 486 | ------------------------------------------------------------------------------------ Save to file 487 | on btn_lst_s pressed do 488 | ( 489 | if objs != undefined then ( 490 | local the_caption = (if txt_c.text != "" then txt_c.text else unsupplied) 491 | local f = _cm.prop_str objs caption:the_caption titles:str_titles_2 vals:vals_to_file 492 | if f != "" do _cm.saveFile f ("cuts_"+(txt_c.text)+".csv") 493 | free f 494 | dispose 495 | ) 496 | ) 497 | on btn_lst_a pressed do 498 | ( 499 | local 500 | the_objs = objects, 501 | objs_count = the_objs.count, 502 | temp_nodelist = #() 503 | for i=1 to objs_count do ( 504 | local temp_node = the_objs[i] 505 | if isValidNode temp_node then ( 506 | if getUserProp temp_node "obj" != undefined then ( 507 | append temp_nodelist temp_node 508 | ) 509 | ) 510 | ) 511 | if temp_nodelist != #() then ( 512 | local the_caption = (if txt_c.text != "" then txt_c.text else unsupplied) 513 | local f = _cm.prop_str temp_nodelist caption:the_caption titles:str_titles_2 vals:vals_to_file 514 | if f != "" do _cm.saveFile f ("cuts_"+(txt_c.text)+".csv") 515 | free f 516 | dispose 517 | ) 518 | ) 519 | ------------------------------------------------------------------------------------ report 520 | on btn_p1 pressed do ( 521 | local p_area = spn_p4.value * (spn_p1.value * spn_p2.value ) 522 | local o_area = 0.0 523 | if objs != undefined then ( 524 | for i in objs do ( 525 | local coords = _cm.getDims i 526 | local a = coords[2] * coords[1] 527 | o_area += a 528 | ) 529 | ) else if obj != undefined then ( 530 | local coords = _cm.getDims obj 531 | o_area = coords[2] * coords[1] 532 | ) 533 | if o_area > 0.0 then ( 534 | local d = spn_p3.value / 100 535 | local c_sheet = (o_area / p_area) + (d * o_area) / p_area 536 | -- (o_area / p_area) + ( (o_area / p_area) * (spn_p3.value /100 )) 537 | local str = StringStream "" 538 | format "% %\% %:-------------------- % u." strf_p1 (spn_p3.value) strf_p2 c_sheet to:str 539 | messageBox str 540 | ) 541 | ) 542 | ------------------------------------------------------------------------------------ change units 543 | on btn_m1 pressed do 544 | ( 545 | local st = "" as stringStream 546 | format str_q1 (spn_f.value) to:st 547 | if (queryBox st) then ( 548 | _cm.changeUnits objs factor:spn_f.value 549 | ) 550 | ) 551 | on btn_m2 pressed do 552 | ( 553 | local st = "" as stringStream 554 | format str_q2 (spn_f.value) to:st 555 | if (queryBox st) then ( 556 | _cm.changeUnits objs factor:spn_f.value up:false 557 | ) 558 | ) 559 | ) 560 | m_props = newRolloutFloater r_title 280 950 561 | addRollout roll_props m_props border:true 562 | m_props.pos = [100,20] 563 | cui.RegisterDialogBar m_props style:#(#cui_dock_vert,#cui_floatable) parent:(Windows.GetMAXHWND()) minsize:[295,600] maxsize:[295,960] 564 | ) 565 | PanelCuts() 566 | ) -------------------------------------------------------------------------------- /src/Panel_cuts/src/usericons/panel_cuts_16a.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HAG87/maxscript-assorted/962c5c5a67dac1201e0878e7f536395d815cd817/src/Panel_cuts/src/usericons/panel_cuts_16a.bmp -------------------------------------------------------------------------------- /src/Panel_cuts/src/usericons/panel_cuts_16i.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HAG87/maxscript-assorted/962c5c5a67dac1201e0878e7f536395d815cd817/src/Panel_cuts/src/usericons/panel_cuts_16i.bmp -------------------------------------------------------------------------------- /src/Panel_cuts/src/usericons/panel_cuts_24a.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HAG87/maxscript-assorted/962c5c5a67dac1201e0878e7f536395d815cd817/src/Panel_cuts/src/usericons/panel_cuts_24a.bmp -------------------------------------------------------------------------------- /src/Panel_cuts/src/usericons/panel_cuts_24i.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HAG87/maxscript-assorted/962c5c5a67dac1201e0878e7f536395d815cd817/src/Panel_cuts/src/usericons/panel_cuts_24i.bmp -------------------------------------------------------------------------------- /src/Panel_cuts/src/usermacros/BUMP_pcuts.mcr: -------------------------------------------------------------------------------- 1 | macroScript BUMP_panelcuts 2 | category:"BUMP tools" 3 | ButtonText:"PQT" 4 | toolTip:"Tool for generating wood panel cuts reports." 5 | icon: #("panel_cuts",1) 6 | ( 7 | on execute do ( 8 | fileIN @"$UserScripts/BUMP_panelCuts.ms" 9 | ) 10 | ) -------------------------------------------------------------------------------- /src/Photographic_composition_guides/Icons/vcomp_24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HAG87/maxscript-assorted/962c5c5a67dac1201e0878e7f536395d815cd817/src/Photographic_composition_guides/Icons/vcomp_24.png -------------------------------------------------------------------------------- /src/Photographic_composition_guides/Icons/vcomp_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HAG87/maxscript-assorted/962c5c5a67dac1201e0878e7f536395d815cd817/src/Photographic_composition_guides/Icons/vcomp_32.png -------------------------------------------------------------------------------- /src/Photographic_composition_guides/Icons/vcomp_36.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HAG87/maxscript-assorted/962c5c5a67dac1201e0878e7f536395d815cd817/src/Photographic_composition_guides/Icons/vcomp_36.png -------------------------------------------------------------------------------- /src/Photographic_composition_guides/Icons/vcomp_48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HAG87/maxscript-assorted/962c5c5a67dac1201e0878e7f536395d815cd817/src/Photographic_composition_guides/Icons/vcomp_48.png -------------------------------------------------------------------------------- /src/Photographic_composition_guides/MacroScripts/BUMP_CompositionGuides.mcr: -------------------------------------------------------------------------------- 1 | /* 2 | VIEWPORT COMPOSITION GUIDES 3 | 2020 4 | 2022 - Added compatibility with Autodesk Exchange store 5 | */ 6 | macroscript DSTLBX_vpComp 7 | category: "BUMP tools" 8 | buttontext: "Photographic composition guides" 9 | tooltip: "Photographic Composition guides" 10 | ( 11 | -- this will contain an instance of the tool 12 | local vpCompositionGuides 13 | -- run each time the MacrosCript is executed... 14 | on execute do ( 15 | -- vpCompositionGuides = undefined 16 | -- safe load with support for Exchange store 17 | fn loadScriptFile = 18 | ( 19 | local ExchangeStorePath = "$publicExchangeStoreInstallPath/Photographic composition guides.bundle/Contents/scripts/vpCompositionGuides.mse" 20 | local LegacyPath = "$Scripts/vpCompositionGuides.mse" 21 | 22 | if doesFileExist ExchangeStorePath 23 | then (filein ExchangeStorePath)() 24 | else if doesFileExist LegacyPath 25 | then (filein LegacyPath)() 26 | else undefined 27 | ) 28 | 29 | if vpCompositionGuides == undefined then ( 30 | -- load the script file in to memory 31 | vpCompositionGuides = loadScriptFile() 32 | ) else ( 33 | -- open the tool UI 34 | vpCompositionGuides.showUI() 35 | ) 36 | ) 37 | -- check ui button state 38 | on isChecked do if (isProperty vpCompositionGuides #roll_compGuide) then vpCompositionGuides.roll_compGuide != undefined 39 | ) -------------------------------------------------------------------------------- /src/Photographic_composition_guides/MacroScripts/BUMP_CompositionGuides_DEBUG.mcr: -------------------------------------------------------------------------------- 1 | /* 2 | VIEWPORT COMPOSITION GUIDES 3 | 2020 4 | 2022 - Added compatibility with Autodesk Exchange store 5 | */ 6 | macroscript DSTLBX_vpComp 7 | category: "BUMP tools" 8 | buttontext: "Photographic composition guides" 9 | tooltip: "Photographic Composition guides" 10 | ( 11 | -- this will contain an instance of the tool 12 | local vpCompositionGuides 13 | -- run each time the MacrosCript is executed... 14 | on execute do ( 15 | -- vpCompositionGuides = undefined 16 | -- safe load with support for Exchange store 17 | fn loadScriptFile = 18 | ( 19 | -- DEBUG ONLY! 20 | local ExchangeStorePath = "$publicExchangeStoreInstallPath/Photographic composition guides.bundle/Contents/scripts/vpCompositionGuides.ms" 21 | local LegacyPath = "$Scripts/vpCompositionGuides.ms" 22 | 23 | -- local ExchangeStorePath = "$publicExchangeStoreInstallPath/Photographic composition guides.bundle/Contents/scripts/vpCompositionGuides.mse" 24 | -- local LegacyPath = "$Scripts/vpCompositionGuides.mse" 25 | 26 | if doesFileExist ExchangeStorePath 27 | then (filein ExchangeStorePath)() 28 | else if doesFileExist LegacyPath 29 | then (filein LegacyPath)() 30 | else undefined 31 | ) 32 | 33 | if vpCompositionGuides == undefined then ( 34 | -- load the script file in to memory 35 | vpCompositionGuides = loadScriptFile() 36 | ) else ( 37 | -- open the tool UI 38 | vpCompositionGuides.showUI() 39 | ) 40 | ) 41 | -- check ui button state 42 | on isChecked do if (isProperty vpCompositionGuides #roll_compGuide) then vpCompositionGuides.roll_compGuide != undefined 43 | ) -------------------------------------------------------------------------------- /src/Photographic_composition_guides/Scripts/vpCompositionGuides.mse: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HAG87/maxscript-assorted/962c5c5a67dac1201e0878e7f536395d815cd817/src/Photographic_composition_guides/Scripts/vpCompositionGuides.mse -------------------------------------------------------------------------------- /src/Random_detach/BUMP_Random_detach.mcr: -------------------------------------------------------------------------------- 1 | macroScript BUMP_RndDetach 2 | category:"BUMP tools" 3 | ButtonText:"Rnd Detach" 4 | toolTip:"Random Poly Element Delect & Detach" 5 | ( 6 | on execute do ( 7 | filein("$userScripts/BUMP_Random_detach.ms"); 8 | ) 9 | ) 10 | -------------------------------------------------------------------------------- /src/Random_detach/BUMP_Random_detach.ms: -------------------------------------------------------------------------------- 1 | /* 2 | ------------------------------------------------------------------------------------------------------------------------ 3 | RANDOM ELEMENTS SELECTOR 4 | ------------------------------------------------------------------------------------------------------------------------ 5 | Author: BUMP 2014 6 | Version: 1.4 7 | Date: 07-03-2014 8 | Tested on: 3D Max 2014 9 | */ 10 | ( 11 | struct Detach (_node,_poly,_selection,_faces) 12 | local _detach = Detach() 13 | local returnElems, flattenArr, EleRandomizer, EleDetacher, setSelection 14 | try(destroyDialog roll_rndElem; cui.UnRegisterDialogBar roll_rndElem)catch() 15 | global roll_rndElem, _dock 16 | rollout roll_rndElem "Random Elements Select/Detach" width:90 height:366 17 | ( 18 | button btn_c "CLOSE" width:90 height:20 pos:[0,0] align:#center 19 | GroupBox grp_1 "" width:90 height:5 pos:[0,20] align:#center 20 | label lbl_so "Select Objects" align:#center width:70 height:15 21 | fn pick_filter obj= (classOf obj==Editable_Poly) 22 | pickbutton pk_obj "Pick Poly" width:85 align:#center filter:pick_filter autoDisplay: true 23 | checkbutton chb_copy "Copy Src" width:85 align:#center highlightColor:(color 28 89 177) 24 | group "options" 25 | ( 26 | label lbl_s "Seed" align:#left 27 | spinner spn_Seed "" width:70 align:#center range:[0,1000,150] 28 | label lbl_p "Percent" align:#left 29 | spinner spn_Percent "" width:70 height:16 align:#center range:[0,100,50] 30 | label lbl_id "Mat ID's" align:#left 31 | spinner spn_ID "" width:70 height:16 align:#center range:[0,100,1] type:#integer 32 | ) 33 | button btn_Select "Select" width:85 height:40 align:#center 34 | button btn_Detach "Detach" width:85 height:25 align:#center offset:[0,5] 35 | button btn_DetachAll "Detach Unique" width:85 height:25 align:#center 36 | progressBar br_p value:0 color:(color 246 151 27) Width:90 height:6 pos:[0,360]align:#center 37 | local prev_pos=[10,10] 38 | local SDrag=false 39 | fn updateUI obj: =( 40 | roll_rndElem.lbl_so.caption= if obj!= unsupplied then "Selected" else "Select Object" 41 | for i=1 to roll_rndElem.controls.count do (if i>4 then roll_rndElem.controls[i].enabled=(if obj== unsupplied then false else true)) 42 | ) 43 | on roll_rndElem open do updateUI() 44 | on roll_rndElem lbuttondown p do (sDrag=true; prev_pos=p) 45 | on roll_rndElem mouseMove p do (print p; if sDrag==true then (try(SetDialogPos roll_rndElem (mouse.screenpos-prev_pos))catch())) 46 | on roll_rndElem lbuttonup p do sDrag=false 47 | on pk_obj picked obj do updateUI obj:obj 48 | on btn_c pressed do (if roll_rndElem.dialogBar==true then (cui.UnRegisterDialogBar roll_rndElem; destroyDialog roll_rndElem) else destroyDialog roll_rndElem) 49 | on btn_c rightclick do (popUpMenu _dock rollout:roll_rndElem) 50 | on btn_Select pressed do setSelection sel: roll_rndElem.pk_obj.object 51 | on btn_Detach pressed do (if _detach._node!=undefined then EleDetacher _detach._node _detach._poly _detach._selection _detach._faces roll_rndElem.spn_ID.value unit:false) 52 | on btn_DetachAll pressed do (if _detach._node!=undefined then EleDetacher _detach._node _detach._poly _detach._selection _detach._faces roll_rndElem.spn_ID.value unit:true) 53 | )--End Rollout 54 | rcmenu _dock 55 | ( 56 | menuitem rc_dl "Dock Left" 57 | menuitem rc_dr "Dock Right" 58 | separator b 59 | menuitem rc_ud "Undock" 60 | on rc_dl picked do( 61 | if roll_rndElem.dialogBar==true then( 62 | cui.DockDialogBar roll_rndElem #cui_dock_left 63 | )else( 64 | cui.RegisterDialogBar roll_rndElem style:#(#cui_dock_vert,#cui_floatable) 65 | cui.DockDialogBar roll_rndElem #cui_dock_left 66 | ) 67 | ) 68 | on rc_dr picked do( 69 | if roll_rndElem.dialogBar==true then( 70 | cui.DockDialogBar roll_rndElem #cui_dock_right 71 | )else( 72 | cui.RegisterDialogBar roll_rndElem style:#(#cui_dock_vert,#cui_floatable) 73 | cui.DockDialogBar roll_rndElem #cui_dock_right 74 | ) 75 | ) 76 | on rc_ud picked do(if roll_rndElem.dialogBar==true then cui.UnRegisterDialogBar roll_rndElem) 77 | )--End RC 78 | fn progress val: tot: =( 79 | if val!=unsupplied and tot!=unsupplied then roll_rndElem.br_p.value= ((val*100)/tot) else roll_rndElem.br_p.value=0 80 | ) 81 | fn flattenArr arr=( 82 | local tempArr=#() 83 | for i in arr do join tempArr i 84 | tempArr 85 | ) 86 | fn returnElems obj=( 87 | try( 88 | local num_faces=polyop.getNumFaces obj 89 | local elem_arr=#() 90 | local done=#() 91 | for f=1 to num_faces do( 92 | if (findItem done f)==0 then ( 93 | local faces= (polyop.getElementsUsingFace obj f) as BitArray 94 | append elem_arr faces 95 | join done faces 96 | progress val:f tot:num_faces 97 | ) 98 | ) 99 | progress() 100 | free done 101 | )catch(return undefined) 102 | elem_arr 103 | ) 104 | 105 | fn EleRandomizer obj eles delta: dSeed: sel:false =( 106 | if eles.count>1 then( 107 | if dSeed==unsupplied then (dSeed= eles.count) 108 | seed dSeed 109 | local rands=#() 110 | local umbral = if delta <1 or delta!=unsupplied then floor(eles.count*delta) else eles.count 111 | for r=1 to umbral do( 112 | local rnd=floor(random 1.0 eles.count) 113 | if (findItem rands eles[rnd])==0 then( 114 | append rands eles[rnd] 115 | progress val:r tot:umbral 116 | ) 117 | ) 118 | progress() 119 | )else rands=eles 120 | local flat=(flattenArr rands) 121 | _detach._faces=flat 122 | polyop.setFaceSelection obj #none 123 | polyop.setFaceSelection obj (flat as BitArray) 124 | if sel==true then ( 125 | max modify mode 126 | modPanel.setCurrentObject obj 127 | subobjectlevel = 4 128 | return rands 129 | )else return rands 130 | ) 131 | fn EleDetacher nod obj eles faces rID unit:true =( 132 | if eles.count==1 and not (queryBox "WARING! Only one element selected, do you want to continue?") then return undefined 133 | case unit of ( 134 | true:( 135 | undo on( 136 | for i=1 to eles.count do( 137 | polyop.setFaceMatID obj eles[i] (floor(random 1 rID)) 138 | polyop.detachFaces obj eles[i] name: (uniqueName "Elem_") delete:false asNode:true node:nod 139 | progress val:1 tot:eles.count 140 | ) 141 | polyop.deleteFaces obj faces 142 | progress() 143 | ) 144 | ) 145 | false:( 146 | undo on (polyop.detachFaces obj (faces as BitArray) name:(uniqueName "Elem_") asNode:true node:nod) 147 | ) 148 | ) 149 | ) 150 | fn setSelection sel: =( 151 | if classOf sel.baseobject==Editable_poly then( 152 | if roll_rndElem.chb_copy.checked==true then copy sel 153 | _detach._node= sel 154 | _detach._poly= _detach._node.baseobject 155 | _detach._selection= EleRandomizer _detach._poly (returnElems _detach._poly) delta:((roll_rndElem.spn_Percent.value/100)) dSeed: roll_rndElem.spn_Seed.value sel:true 156 | return true 157 | )else return false 158 | ) 159 | createdialog roll_rndElem pos:[100,200] style:#() 160 | )--END OF SCRIPT -------------------------------------------------------------------------------- /src/Random_detach/min/min_BUMP_Random_detach.ms: -------------------------------------------------------------------------------- 1 | (struct Detach(_node,_poly,_selection,_faces);local _detach=Detach();local returnElems,flattenArr,EleRandomizer,EleDetacher,setSelection;try(destroyDialog roll_rndElem;cui.UnRegisterDialogBar roll_rndElem)catch();global roll_rndElem,_dock;rollout roll_rndElem"Random Elements Select/Detach"width:90 height:366(button btn_c"CLOSE"width:90 height:20 pos:[0,0]align:#center;GroupBox grp_1""width:90 height:5 pos:[0,20]align:#center;label lbl_so"Select Objects"align:#center width:70 height:15;fn pick_filter obj=(classOf obj==Editable_Poly);pickbutton pk_obj"Pick Poly"width:85 align:#center filter:pick_filter autoDisplay:true;checkbutton chb_copy"Copy Src"width:85 align:#center highlightColor:(color 28 89 177);group"options"(label lbl_s"Seed"align:#left;spinner spn_Seed""width:70 align:#center range:[0,1000,150];label lbl_p"Percent"align:#left;spinner spn_Percent""width:70 height:16 align:#center range:[0,100,50];label lbl_id"Mat ID's"align:#left;spinner spn_ID""width:70 height:16 align:#center range:[0,100,1]type:#integer);button btn_Select"Select"width:85 height:40 align:#center;button btn_Detach"Detach"width:85 height:25 align:#center offset:[0,5];button btn_DetachAll"Detach Unique"width:85 height:25 align:#center;progressBar br_p value:0 color:(color 246 151 27)Width:90 height:6 pos:[0,360]align:#center;local prev_pos=[10,10];local SDrag=false;fn updateUI obj: =(roll_rndElem.lbl_so.caption=if obj!=unsupplied then"Selected"else"Select Object";for i=1 to roll_rndElem.controls.count do(if i>4 then roll_rndElem.controls[i].enabled=(if obj==unsupplied then false else true)));on roll_rndElem open do updateUI();on roll_rndElem lbuttondown p do(sDrag=true;prev_pos=p);on roll_rndElem mouseMove p do(print p;if sDrag==true then(try(SetDialogPos roll_rndElem(mouse.screenpos-prev_pos))catch()));on roll_rndElem lbuttonup p do sDrag=false;on pk_obj picked obj do updateUI obj:obj;on btn_c pressed do(if roll_rndElem.dialogBar==true then(cui.UnRegisterDialogBar roll_rndElem;destroyDialog roll_rndElem)else destroyDialog roll_rndElem);on btn_c rightclick do(popUpMenu _dock rollout:roll_rndElem);on btn_Select pressed do setSelection sel:roll_rndElem.pk_obj.object;on btn_Detach pressed do(if _detach._node!=undefined then EleDetacher _detach._node _detach._poly _detach._selection _detach._faces roll_rndElem.spn_ID.value unit:false);on btn_DetachAll pressed do(if _detach._node!=undefined then EleDetacher _detach._node _detach._poly _detach._selection _detach._faces roll_rndElem.spn_ID.value unit:true));rcmenu _dock(menuItem rc_dl"Dock Left";menuItem rc_dr"Dock Right";separator b;menuItem rc_ud"Undock";on rc_dl picked do(if roll_rndElem.dialogBar==true then(cui.DockDialogBar roll_rndElem#cui_dock_left)else(cui.RegisterDialogBar roll_rndElem style:#(#cui_dock_vert,#cui_floatable);cui.DockDialogBar roll_rndElem#cui_dock_left));on rc_dr picked do(if roll_rndElem.dialogBar==true then(cui.DockDialogBar roll_rndElem#cui_dock_right)else(cui.RegisterDialogBar roll_rndElem style:#(#cui_dock_vert,#cui_floatable);cui.DockDialogBar roll_rndElem#cui_dock_right));on rc_ud picked do(if roll_rndElem.dialogBar==true then cui.UnRegisterDialogBar roll_rndElem));fn progress val: tot: =(if val!=unsupplied and tot!=unsupplied then roll_rndElem.br_p.value=((val*100)/tot)else roll_rndElem.br_p.value=0);fn flattenArr arr=(local tempArr=#();for i in arr do join tempArr i;tempArr);fn returnElems obj=(try(local num_faces=polyop.getNumFaces obj;local elem_arr=#();local done=#();for f=1 to num_faces do(if(findItem done f)==0 then(local faces=(polyop.getElementsUsingFace obj f)as BitArray;append elem_arr faces;join done faces;progress val:f tot:num_faces));progress();free done)catch(return undefined);elem_arr);fn EleRandomizer obj eles delta: dSeed:sel:false=(if eles.count>1 then(if dSeed==unsupplied then(dSeed=eles.count);seed dSeed;local rands=#();local umbral=if delta<1 or delta!=unsupplied then floor(eles.count*delta)else eles.count;for r=1 to umbral do(local rnd=floor(random 1.0 eles.count);if(findItem rands eles[rnd])==0 then(append rands eles[rnd];progress val:r tot:umbral));progress())else rands=eles;local flat=(flattenArr rands);_detach._faces=flat;polyop.setFaceSelection obj#none;polyop.setFaceSelection obj(flat as BitArray);if sel==true then(max modify mode;modPanel.setCurrentObject obj;subobjectlevel=4;return rands)else return rands);fn EleDetacher nod obj eles faces rID unit:true=(if eles.count==1 and not(queryBox"WARING! Only one element selected, do you want to continue?")then return undefined;case unit of(true:(undo on(for i=1 to eles.count do(polyop.setFaceMatID obj eles[i](floor(random 1 rID));polyop.detachFaces obj eles[i]name:(uniqueName"Elem_")delete:false asNode:true node:nod;progress val:1 tot:eles.count);polyop.deleteFaces obj faces;progress()));false:(undo on(polyop.detachFaces obj(faces as BitArray)name:(uniqueName"Elem_")asNode:true node:nod))););fn setSelection sel: =(if classOf sel.baseobject==Editable_poly then(if roll_rndElem.chb_copy.checked==true then copy sel;_detach._node=sel;_detach._poly=_detach._node.baseobject;_detach._selection=EleRandomizer _detach._poly(returnElems _detach._poly)delta:((roll_rndElem.spn_Percent.value/100))dSeed:roll_rndElem.spn_Seed.value sel:true;return true)else return false);createdialog roll_rndElem pos:[100,200]style:#()) -------------------------------------------------------------------------------- /src/VrayMtlPopulate/BUMP_VrayMtlPopulate.mcr: -------------------------------------------------------------------------------- 1 | macroScript BUMP_VrayMts_gray 2 | category:"BUMP tools" 3 | ButtonText:"VrayMtl" 4 | toolTip:"Populate Medit Slots with Vray Materials" 5 | ( 6 | on execute do ( 7 | local setMat = fileIn @"$userScripts/BUMP_VrayMtlPopulate.ms" 8 | setMat.setSlots rndColor:false chk:(queryBox "Conserve scene materials slots?") 9 | ) 10 | ) 11 | macroScript BUMP_VrayMts_rnd 12 | category:"BUMP tools" 13 | ButtonText:"VrayMtl rnd" 14 | toolTip:"Populate Medit Slots with Vray Materials, apply random diffuse color" 15 | ( 16 | on execute do ( 17 | local setMat = fileIn @"$userScripts/BUMP_VrayMtlPopulate.ms" 18 | setMat.setSlots rndColor:true chk:(queryBox "Conserve scene materials slots?") 19 | ) 20 | ) 21 | -------------------------------------------------------------------------------- /src/VrayMtlPopulate/BUMP_VrayMtlPopulate.ms: -------------------------------------------------------------------------------- 1 | /* Vray Mat Populate v2.4 2 | AUTHOR: BUMP 3 | DATE: 17-09-2017 4 | TESTED ON: 3ds Max 2014+ 5 | ---------------------------------------------------------------------------------------------------------- 6 | This scipt replaces Medir Slots with (v-ray) materials. options: random color / gray color / retain existing materials 7 | ---------------------------------------------------------------------------------------------------------- 8 | */ 9 | ( 10 | struct matPop 11 | ( 12 | /* 13 | * rand: random color true|false 14 | * id Material editor slot [1-24] 15 | * prefix: name prefix 16 | * matClass: material type i.e: vraymtl, CoronaMtl, ... 17 | */ 18 | mapped fn assignMat id rand prefix:"VRayMtl_" matClass:vraymtl = 19 | ( 20 | if matClass != undefined then ( 21 | local mat = matClass () 22 | -- Name 23 | mat.name = prefix + (abs(random 1 100)) as String 24 | -- Test for unique name 25 | if not (okMtlForScene mat) then (mat.name += "_1") 26 | -- Random color 27 | if rand then ( 28 | local 29 | R = abs (random 1 254), 30 | G = abs (random 1 254), 31 | B = abs (random 1 254) 32 | mat.diffuse = color R G B 33 | ) 34 | -- assign to material slot 35 | setMeditMaterial id mat 36 | -- options 37 | showTextureMap mat true 38 | setMTLMEditFlags mat #{2..4} 39 | -- return 40 | ) 41 | true 42 | ), 43 | fn setSlots rndColor:false chk:true prefix:"VRayMtl_" matClass:vraymtl = 44 | ( 45 | local matIndx = #{1..24} as Array 46 | if chk then ( 47 | for i=1 to matIndx.count where ((findItem sceneMaterials meditMaterials[i]) == 0) do ( 48 | assignMat i rndColor prefix:prefix matClass:matClass 49 | ) 50 | ) else ( 51 | assignMat matIndx rndColor prefix:prefix matClass:matClass 52 | ) 53 | true 54 | ) 55 | ) 56 | _t = matPop() 57 | ) -------------------------------------------------------------------------------- /src/plugin/BUMP_resizer.ms: -------------------------------------------------------------------------------- 1 | plugin simpleMod resizer 2 | name:"Resize" 3 | classID:#(683325,456281) 4 | version:1.0 5 | ( 6 | fn getNode = (refs.dependentnodes this)[1] 7 | fn getLimits obj = 8 | ( 9 | local _min = getModContextBBoxMin obj this 10 | local _max = getModContextBBoxMax obj this 11 | _max - _min 12 | ) 13 | parameters main rollout:params 14 | ( 15 | x_amount type:#worldunits ui:SpinX default:100 16 | y_amount type:#worldunits ui:SpinY default:100 17 | z_amount type:#worldunits ui:SpinZ default:100 18 | 19 | proportion type:#point3 default:[1.0,1.0,1.0] 20 | 21 | newDims type:#point3 default:[100.0,100.0,100.0] 22 | 23 | isProportioned type:#boolean ui:Chk1 default:false 24 | 25 | lk_x type:#boolean ui:clk_x default:true 26 | lk_y type:#boolean ui:clk_y default:true 27 | lk_z type:#boolean ui:clk_z default:true 28 | 29 | on x_amount set val do (if not loading then newDims.x = val) 30 | on y_amount set val do (if not loading then newDims.y = val) 31 | on z_amount set val do (if not loading then newDims.z = val) 32 | ) 33 | /* 34 | on attachedToNode nd do ( 35 | if nd != undefined then ( 36 | proportion = getLimits nd 37 | newDims = proportion 38 | ) 39 | ) 40 | */ 41 | -- on clone nd do () 42 | rollout params "Resize Parameters" 43 | ( 44 | spinner SpinX "X : " type:#worldunits range:[-10000000.0,10000000.0,100.0] 45 | spinner SpinY "Y : " type:#worldunits range:[-10000000.0,10000000.0,100.0] 46 | spinner SpinZ "Z : " type:#worldunits range:[-10000000.0,10000000.0,100.0] 47 | Checkbox Chk1 "Keep proportions" 48 | 49 | group "Link proportions" 50 | ( 51 | Checkbox clk_x " X" align:#left across:3 52 | Checkbox clk_y " Y" align:#left 53 | Checkbox clk_z " Z" align:#left 54 | ) 55 | 56 | on SpinX changed val do ( 57 | if isProportioned then ( 58 | proportion = getLimits (getNode()) 59 | local delta = proportion.x / val 60 | if lk_y and lk_x then y_amount = proportion.y / delta 61 | if lk_z and lk_x then z_amount = proportion.z / delta 62 | ) 63 | ) 64 | 65 | on SpinY changed val do ( 66 | if isProportioned then ( 67 | proportion = getLimits (getNode()) 68 | local delta = proportion.y / val 69 | if lk_x and lk_y then x_amount = proportion.x / delta 70 | if lk_z and lk_y then z_amount = proportion.z / delta 71 | ) 72 | ) 73 | 74 | on SpinZ changed val do ( 75 | if isProportioned then ( 76 | proportion = getLimits (getNode()) 77 | local delta = proportion.z / val 78 | if lk_x and lk_z then x_amount = proportion.x / delta 79 | if lk_y and lk_z then y_amount = proportion.y / delta 80 | ) 81 | ) 82 | ) 83 | rollout help "About" rolledUp:true 84 | ( 85 | label lbl_1 "Node Resize modifier" 86 | hyperLink lnk_1 "Atelier Bump" color:(color 200 150 0) address:"https://atelierbump.com" align:#center 87 | ) 88 | on map i p do 89 | ( 90 | if extent.x != 0.0d0 then p.x = p.x / extent.x * newDims.x 91 | if extent.y != 0.0d0 then p.y = p.y / extent.y * newDims.y 92 | if extent.z != 0.0d0 then p.z = p.z / extent.z * newDims.z 93 | p 94 | ) 95 | ) --------------------------------------------------------------------------------