[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6EE84BTYV2M62ZDY34EYKY6":3,"skill-same:01M6EE84BTYV2M62ZDY34EYKY6":47},{"skillNo":4,"name":5,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":17,"publishedAt":20,"linkOnly":21,"markdownContent":22,"markdownBody":22,"frontMatter":23,"refName":24,"commitSha":25,"skillDirectory":26,"forksCount":27,"repositoryHtmlUrl":28,"repositoryHomepageUrl":29,"ownerHtmlUrl":30,"ownerBlogUrl":6,"ownerDescription":31,"updatedAt":32,"install":33,"resources":46},"01M6EE84BTYV2M62ZDY34EYKY6","3dsmax-scripting",null,"ComeOnOliver\u002Fskillshub","ComeOnOliver","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F43215937?v=4","01M6E5JNFECJAAVFE0W7SMWWD2","Haoran Shu","01M6E5JNNDQS7AJZDYFQ8TPZCK",67,"MIT","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002FTerminalSkills\u002Fskills\u002F3dsmax-scripting\u002FSKILL.md",[],[18,19],"scripting","3dsmax scripting","2026-11-10 10:12:30",false,"# 3ds Max Scripting\n\nAutomate 3ds Max workflows with MAXScript (native) and Python (3ds Max 2022+).\n\n## MAXScript Basics\n\nMAXScript is 3ds Max's built-in scripting language. Run scripts from the MAXScript Listener (F11), Script Editor, or command line.\n\n### Objects and Scene\n\n```maxscript\n-- Create objects\nlocal b = Box width:100 height:50 length:100 pos:[0, 0, 0] name:\"MyBox\"\nlocal s = Sphere radius:25 pos:[200, 0, 25] segments:32\nlocal p = Plane width:500 length:500 pos:[0, 0, 0]\n\n-- Access objects\nlocal obj = $MyBox              -- By name ($ selector)\nlocal obj = getNodeByName \"MyBox\"  -- By name (function)\nlocal all = objects              -- All scene objects\nlocal sel = selection            -- Current selection\n\n-- Transform\nobj.pos = [100, 200, 0]         -- Position\nobj.rotation = eulerAngles 0 0 45  -- Rotation (degrees)\nobj.scale = [2, 2, 2]           -- Scale\n\n-- Properties\nobj.wirecolor = color 255 0 0   -- Wireframe color\nobj.renderable = true\nobj.isHidden = false\n\n-- Iterate all objects\nfor obj in objects do (\n    if classOf obj == Box then (\n        format \"Box: % at %\\n\" obj.name obj.pos\n    )\n)\n```\n\n### Materials\n\n```maxscript\n-- Standard material\nlocal mat = StandardMaterial()\nmat.name = \"Red Glossy\"\nmat.diffuseColor = color 200 30 30\nmat.specularLevel = 80\nmat.glossiness = 60\n\n-- V-Ray material (requires V-Ray installed)\nlocal vmat = VRayMtl()\nvmat.name = \"Wood Floor\"\nvmat.diffuse = color 180 140 100\nvmat.reflection = color 30 30 30         -- Subtle reflection\nvmat.reflectionGlossiness = 0.85          -- Slightly rough\nvmat.texmap_diffuse = BitmapTexture filename:\"D:\u002Ftextures\u002Fwood_diffuse.jpg\"\nvmat.texmap_bump = BitmapTexture filename:\"D:\u002Ftextures\u002Fwood_normal.jpg\"\nvmat.texmap_bump_multiplier = 1.5         -- Bump strength\n\n-- Apply material to object\n$MyBox.material = vmat\n\n-- Multi-sub material (different material per face ID)\nlocal multi = MultiSubMaterial numsubs:3\nmulti[1] = VRayMtl name:\"Wall Paint\" diffuse:(color 240 238 232)\nmulti[2] = VRayMtl name:\"Wood Trim\" diffuse:(color 160 120 80)\nmulti[3] = VRayMtl name:\"Glass\" diffuse:(color 200 220 230) refraction:(color 250 250 250)\n```\n\n### Cameras\n\n```maxscript\n-- V-Ray Physical Camera (archviz standard)\nfn createArchvizCamera name pos target fov:65.0 = (\n    local cam = VRayPhysicalCamera()\n    cam.name = name\n    cam.pos = pos\n    cam.targeted = true\n    cam.target.pos = target\n\n    -- Lens\n    cam.specify_fov = true\n    cam.fov = fov\n\n    -- Exposure\n    cam.ISO = 400\n    cam.shutter_speed = 60.0\n    cam.f_number = 2.8\n\n    -- Auto white balance\n    cam.white_balance_preset = 1  -- Daylight\n\n    -- Vertical correction (crucial for archviz — keeps verticals straight)\n    cam.auto_vertical_tilt_correction = 1.0\n\n    cam\n)\n\ncreateArchvizCamera \"LivingRoom\" [5, -3, 1.5] [-2, 5, 1.2] fov:75\n```\n\n### Lights\n\n```maxscript\n-- V-Ray Sun + Sky (exterior lighting)\nlocal sun = VRaySun pos:[100, -50, 80]\nsun.intensity_multiplier = 1.0\nsun.size_multiplier = 3.0          -- Soft shadows\nsun.turbidity = 3.0                -- Atmosphere haze\n\n-- V-Ray Rectangle Light (interior fill)\nlocal rect = VRayLight()\nrect.type = 1                       -- Plane light\nrect.pos = [0, 0, 2.8]             -- Ceiling height\nrect.multiplier = 15.0\nrect.color = color 255 244 229      -- Warm white (3000K)\nrect.width = 60\nrect.height = 60\nrect.invisible = true               -- Don't render the light shape\n\n-- V-Ray IES Light (architectural fixtures)\nlocal ies = VRayIES()\nies.pos = [1.5, 3.0, 2.7]\nies.ies_file = \"D:\u002Fies\u002Fdownlight.ies\"\nies.multiplier = 800.0              -- Lumens\nies.color_mode = 1                  -- Temperature\nies.color_temperature = 3000        -- Warm\n```\n\n### File I\u002FO\n\n```maxscript\n-- Read JSON config (3ds Max 2022+)\nfn readJSON path = (\n    local f = openFile path mode:\"r\"\n    local str = \"\"\n    while not eof f do str += readLine f + \"\\n\"\n    close f\n    -- Use .NET JSON parser\n    local jObj = (dotNetClass \"Newtonsoft.Json.Linq.JObject\").Parse str\n    jObj\n)\n\n-- Write log file\nfn writeLog path msg = (\n    local f = openFile path mode:\"a\"\n    if f == undefined then f = createFile path\n    format \"% | %\\n\" localTime msg to:f\n    close f\n)\n\n-- Import\u002Fexport\nimportFile \"D:\u002Fmodels\u002Ffurniture.fbx\" #noPrompt\nexportFile \"D:\u002Fexport\u002Fscene.fbx\" #noPrompt selectedOnly:true\n```\n\n## Python in 3ds Max\n\n3ds Max 2022+ includes Python 3 with `pymxs` module for accessing MAXScript objects:\n\n```python\n\"\"\"scene_audit.py — Audit scene for common archviz issues.\"\"\"\nimport pymxs\nfrom pymxs import runtime as rt\n\ndef audit_scene():\n    \"\"\"Check scene for common issues: missing textures, high-poly objects, etc.\"\"\"\n    issues = []\n\n    for obj in rt.objects:\n        # Check for high-poly objects (>500K faces in archviz is suspicious)\n        if rt.classOf(obj) in [rt.Editable_Poly, rt.Editable_Mesh]:\n            face_count = rt.getNumFaces(obj)\n            if face_count > 500000:\n                issues.append(f\"High poly: {obj.name} ({face_count:,} faces)\")\n\n        # Check for missing materials\n        if obj.material is None and obj.renderable:\n            issues.append(f\"No material: {obj.name}\")\n\n    # Check for missing texture files\n    for mat in rt.sceneMaterials:\n        check_material_textures(mat, issues)\n\n    return issues\n\ndef check_material_textures(mat, issues):\n    \"\"\"Recursively check material tree for missing texture files.\"\"\"\n    if hasattr(mat, 'texmap_diffuse') and mat.texmap_diffuse:\n        tex = mat.texmap_diffuse\n        if hasattr(tex, 'filename') and tex.filename:\n            import os\n            if not os.path.exists(tex.filename):\n                issues.append(f\"Missing texture: {tex.filename} (in {mat.name})\")\n```\n\n## Batch Operations\n\n### Command Line Rendering\n\n```bash\n# Render a scene from command line (no GUI)\n\"C:\\Program Files\\Autodesk\\3ds Max 2025\\3dsmax.exe\" ^\n  -silent -mxs \"loadMaxFile \\\"D:\u002Fscene.max\\\"; render()\" ^\n  -o \"D:\u002Foutput\u002Frender.exr\" -w 4000 -h 2250\n\n# Run a MAXScript file\n3dsmax.exe -silent -mxs \"fileIn \\\"D:\u002Fscripts\u002Fbatch_render.ms\\\"\"\n\n# Run with specific camera\n3dsmax.exe -silent -mxs \"loadMaxFile \\\"D:\u002Fscene.max\\\"; viewport.setCamera (getNodeByName \\\"Camera01\\\"); render()\"\n```\n\n### Batch Process Multiple Files\n\n```maxscript\n-- batch_process.ms — Process all .max files in a directory\n\nfn processAllScenes folderPath = (\n    local files = getFiles (folderPath + \"\u002F*.max\")\n    local results = #()\n\n    for f in files do (\n        format \"Processing: %\\n\" f\n        loadMaxFile f quiet:true\n\n        -- Do something with each scene\n        local objCount = objects.count\n        local camCount = (for c in cameras where classOf c != Targetobject collect c).count\n\n        append results #(getFilenameFile f, objCount, camCount)\n\n        resetMaxFile #noPrompt\n    )\n\n    results\n)\n```\n\n## Scene Management\n\n```maxscript\n-- Layer management\nfn organizeByType = (\n    local layerMgr = LayerManager\n\n    -- Create layers\n    local furnitureLayer = layerMgr.newLayerFromName \"Furniture\"\n    local architectureLayer = layerMgr.newLayerFromName \"Architecture\"\n    local lightsLayer = layerMgr.newLayerFromName \"Lights\"\n\n    for obj in objects do (\n        case (superClassOf obj) of (\n            Light: lightsLayer.addNode obj\n            default: (\n                if matchPattern obj.name pattern:\"*chair*\" or\n                   matchPattern obj.name pattern:\"*table*\" or\n                   matchPattern obj.name pattern:\"*sofa*\" then\n                    furnitureLayer.addNode obj\n                else\n                    architectureLayer.addNode obj\n            )\n        )\n    )\n)\n\n-- Selection sets\nselectionSets[\"Interior Cameras\"] = for c in cameras where\n    matchPattern c.name pattern:\"int_*\" collect c\n\n-- Named selection sets for render elements\nfn selectByMaterialName matName = (\n    select (for obj in objects where obj.material != undefined and\n            obj.material.name == matName collect obj)\n)\n```\n\n## Guidelines\n\n- **Always `#noPrompt` for batch operations** — without it, file dialogs block script execution\n- **Use `undo on` blocks** for destructive operations — wrap scene changes so they can be undone\n- **`gc()` (garbage collect) in loops** — MAXScript leaks memory in long-running scripts. Call `gc light:true` periodically.\n- **Test in Listener first** — debug scripts interactively before running them in batch mode\n- **V-Ray objects require V-Ray loaded** — check `renderers.current` before creating V-Ray-specific objects\n- **File paths use forward slashes or escaped backslashes** — `\"D:\u002Fpath\"` or `\"D:\\\\path\"`, never raw `\"D:\\path\"`\n- **Python `pymxs` is slower than MAXScript** — use Python for file I\u002FO and logic, MAXScript for scene manipulation\n- **Save before batch operations** — `saveMaxFile (maxFilePath + maxFileName)` as a safety net\n",{},"main","def8531e65114c0fca8fb8551c1871ee0eed705c","skills\u002FTerminalSkills\u002Fskills\u002F3dsmax-scripting",24,"https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub","https:\u002F\u002Fskillshub.wtf","https:\u002F\u002Fgithub.com\u002FComeOnOliver","AI & Blockchain Engineer\r\n","2026-06-24 22:07:19",{"source":7,"skillName":5,"commands":34,"prompt":44,"zipAvailable":45},[35,38,41],{"tool":36,"command":37},"npx","npx skills add ComeOnOliver\u002Fskillshub --skill 3dsmax-scripting",{"tool":39,"command":40},"bunx","bunx skills add ComeOnOliver\u002Fskillshub --skill 3dsmax-scripting",{"tool":42,"command":43},"pnpm","pnpm dlx skills add ComeOnOliver\u002Fskillshub --skill 3dsmax-scripting","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002FTerminalSkills\u002Fskills\u002F3dsmax-scripting\u002FSKILL.md",true,[],[48,62,72,81,87,94],{"skillNo":49,"name":50,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":51,"categories":52,"keywords":58,"publishedAt":20},"01M6FKJN13GMG4KY57J3QD8GY5","model-hierarchy-skill","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzscole\u002Fmodel-hierarchy-skill\u002Fmodel-hierarchy-skill\u002FSKILL.md",[53],{"categoryNo":54,"categoryName":55,"taxonomyType":56,"taxonomyTypeDesc":57},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[59,60,61],"model","model hierarchy","model hierarchy skill",{"skillNo":63,"name":64,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":65,"categories":66,"keywords":68,"publishedAt":20},"01M6FKJJJ6GCAMR4PPPRD12M5X","zoom-mcp","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-mcp\u002FSKILL.md",[67],{"categoryNo":54,"categoryName":55,"taxonomyType":56,"taxonomyTypeDesc":57},[69,70,71],"MCP","zoom","zoom mcp",{"skillNo":73,"name":74,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":75,"categories":76,"keywords":77,"publishedAt":20},"01M6FKJE3KYT3KPEZMEEHYKA6K","zoom-apps-sdk","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-apps-sdk\u002FSKILL.md",[],[78,79,80,70],"sdk","zoom apps sdk","apps",{"skillNo":82,"name":83,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":84,"categories":85,"keywords":86,"publishedAt":20},"01M6FKJ9EDH9Q5VWDF8HAJRSP0","windows","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwindows\u002FSKILL.md",[],[83],{"skillNo":88,"name":89,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":90,"categories":91,"keywords":93,"publishedAt":20},"01M6FKJ666BEEFC3AE9GJ72Q93","whiteboard","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwhiteboard\u002FSKILL.md",[92],{"categoryNo":54,"categoryName":55,"taxonomyType":56,"taxonomyTypeDesc":57},[89],{"skillNo":95,"name":96,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":97,"categories":98,"keywords":99,"publishedAt":20},"01M6FKJ21WFCDGTJQ2Q91T9DVW","websockets","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwebsockets\u002FSKILL.md",[],[96]]