Maps user-visible actions in 3ds Max to internal code paths. Source paths are relative to the repository root.
| User action | Class created | Descriptor / factory | Notes |
|---|---|---|---|
| Create X-Obj | MainObject |
MainObjDesc → new MainObject() |
Category X-Plane; internal name xObjectMain |
| Create X-Lod | LodObject |
LodObjDesc → new LodObject() |
Parent under an X-Obj for LOD near/far |
| Create X-Smoke | SmokeObject |
SmokeObjDesc → new SmokeObject() |
Writes deprecated smoke_white / smoke_black |
Sources: src/classes-desc/MainObjDesc.cpp, LodObjDesc.cpp, SmokeObjDesc.cpp; objects under src/objects/.
Typical hierarchy for export:
- Place one X-Obj as the export root.
- Optionally add X-Lod children with distance ranges.
- Parent geometry, lights, and animated nodes under the X-Obj (or under an X-Lod).
Without any X-Lod, export still creates one LOD group from the X-Obj’s children (Converterer::toXpln falls back when mLods is empty).
GUP startup creates the tool frame (ObjCommon::Start → ui::ToolFrame). Selection-driven dock UI lives in src/ui/MainDock.*.
| Rollup / panel (UI title) | Source | Applies to | Persists via |
|---|---|---|---|
| X Base attributes | src/ui/ObjAttr.cpp |
Selected mesh/object nodes | MdObjAttr / ObjAttrIO |
| X Manipulator | src/ui/ManipAttr.cpp + src/ui/manip/* |
Selected clickable geometry | MdManip / ManipIO |
| X Light attributes | src/ui/LightAttr.cpp + src/ui/light/* |
Lights (named / param / custom / spill) | MdLight / LightIO |
| Animation Translation | src/ui/anim/AnimTransView.cpp |
Nodes with translate anim | MdAnimTrans / AnimIO |
| Animation Rotate | src/ui/anim/AnimRotateRollup.cpp |
Nodes with rotate anim | MdAnimRot / AnimIO |
| Animation Visibility | src/ui/anim/AnimVisView.cpp |
Hide/show keyframes | MdAnimVis / AnimIO |
Defined in src/objects/main/MainObj.cpp / MainObjectParams.h:
| Rollup group | ParamBlock | Examples of exported OBJ concepts |
|---|---|---|
| Global shading | MainObjAttrParams / RollGlobShading |
TEXTURE, TEXTURE_LIT, TEXTURE_NORMAL, NORMAL_METALNESS, BLEND_GLASS, tint, specular, blend |
| Cockpit | RollGlobAttrCockpit |
GLOBAL_cockpit_lit, COCKPIT_REGION (×4) |
| Global attributes | RollGlobAttr |
GLOBAL_no_shadow, TILTED, SLOPE_LIMIT, slung_load_weight, layer groups, draped LOD |
| Export options | MainObjExpParams |
Toggles: meshes, lines, lights, animation, instancing, debug, optimisation, scale |
Wrappers: MainObjParamsWrapper (src/objects/main/MainObjParamsWrapper.*).
Examples present as dedicated panels (non-exhaustive of OBJ8; XP12 ATTR_manip_device is absent):
| UI module | Typical OBJ attribute |
|---|---|
ManipAttrCmd |
ATTR_manip_command |
ManipAttrCmdAxis |
ATTR_manip_command_axis |
ManipAttrCmdKnob |
ATTR_manip_command_knob |
ManipAttrCmdLr / ManipAttrCmdUd |
command switch L/R or U/D |
ManipAttrDragXy / DragAxis / DragAxisPix |
drag manipulators |
ManipAttrPush / Toggle / Radio / Delta / Wrap |
push/toggle/radio/delta/wrap |
ManipAttrNoop / Panel / AxisKnob / axis switches |
noop, panel, axis knob/switch |
ManipAttrWheel |
wheel embeddable ranges |
XplnObj also models newer VR manips (e.g. AttrManipDragRotate, AttrManipCmdKnob2) under third_party/XplnObj/include/xpln/obj/manipulators/; Max UI coverage may lag the library.
| Step | What happens | Source |
|---|---|---|
| 1 | Max invokes scene exporter | ObjExporter::DoExport — src/3dmax/ObjExporter.cpp |
| 2 | Export dialog opens | ui::DlgExport::show — src/ui/DlgExport.cpp |
| 3 | Scene scanned for X-Obj nodes | DlgExport::collectMainNodes / MainObjParamsWrapper::isMainObj |
| 4 | User selects which X-Obj roots to export | List control; setExportEnable on wrapper |
| 5 | Per selected root: Max → XplnObj | Converterer::toXpln — src/converters/Converterer.cpp |
| 6 | Hierarchy walk | processNode → ConverterMesh / ConverterLight / ConverterSmoke / ConverterLine / ConverterDummy, plus ConverterAttr, ConverterAnim |
| 7 | Write file | XplnObj export path (exportObj / export context via DlgExport) |
| 8 | Multi-root naming | If more than one selected root, derived paths use each node name + .obj (changeFileName) |
Export dialog options currently not supported (explicit warnings in DlgExport::startExport):
- Selected Only
- Suppress Prompts
Auto-export checkbox state is stored in GUP settings under group DlgExport.
Signature string stamped into the OBJ comes from generated src/Info.h (organization / project / version / compile date).
| Step | What happens | Source |
|---|---|---|
| 1 | Max invokes scene importer | ObjImporter::DoImport — src/3dmax/ObjImporter.cpp |
| 2 | Import dialog | ui::DlgImport — src/ui/DlgImport.cpp |
| 3 | File read into xobj::ObjMain |
XplnObj reader |
| 4 | XplnObj → Max | Converterer::toMax — src/converters/Converterer.cpp |
Converterer::toMax builds a main node and LOD children, then always returns false at the end of the function (after the LOD loop), even when hierarchy construction succeeded. DlgImport treats a false return as failure.
Additionally, processXObjects uses if / else if after a successful ConverterMesh::toMax, so light/smoke/dummy/line fallbacks are unreachable when a mesh conversion was attempted — logic defect relative to the intended chain.
Status: Import remains unfinished; do not rely on it for production. Export-first modernization deliberately defers import success.
Registered by CommonClassDesc (GUP_CLASS_ID, class name X-Common). Action table: ui::MainMenuActions (src/ui/main-menu/MainMenuActions.*).
| Menu action ID | Constant | Presenter wiring (MainMenuPresenter) |
|---|---|---|
| Documentation | MENU_ACTION_DOC |
MdLinks::openDocBinary |
| Update | MENU_ACTION_UPDATE |
Opens plugin download / binary page via MdLinks |
| Donate | MENU_ACTION_DONATE |
MdLinks::openDonate |
| About | MENU_ACTION_ABOUT |
ui::Factory::showAboutWindow |
| Settings | MENU_ACTION_SETTINGS |
ui::Factory::showSettingsWindow |
On ObjCommon::Start:
- Create main menu view + presenter
- Create
CloneNodeChunk, tool frame - Start
UpdateChecker::checkForUpdate - Timer polls
updateInfo()(5 s) and logs remote version - Register
NOTIFY_FILE_POST_OPENfor scene update paths
Export dialog also surfaces update availability after a run (DlgExport::printUpdateAvailability).
Converterer::toXpln outline:
ConverterMain::toXplnfills globalObjMainattributes from the X-Obj.- Collect X-Lod children; if none, use the main node as the sole LOD container.
- For each LOD: build
ObjLodGroup, apply scale/TM, recurse children. - Per node: optional
ConverterAnim::toXPLN, then mesh/light/smoke/line/dummy conversion andConverterAttr::toXpln.
Related converters:
| Converter | Path |
|---|---|
Converterer |
src/converters/Converterer.cpp |
ConverterMain |
src/converters/ConverterMain.cpp |
ConverterMesh |
src/converters/ConverterMesh.cpp |
ConverterLight |
src/converters/ConverterLight.cpp |
ConverterSmoke |
src/converters/ConverterSmoke.cpp |
ConverterAttr |
src/converters/ConverterATTR.cpp |
ConverterAnim |
src/converters/ConverterAnim.cpp |
ConverterUtils |
src/converters/ConverterUtils.cpp |
| User-visible action | Entry point | Downstream |
|---|---|---|
| Create X-Obj / X-Lod / X-Smoke | Create panel helpers | MainObject / LodObject / SmokeObject |
| Edit shading / cockpit / global ATTR on X-Obj | ParamBlock rollups on helper | MainObjParamsWrapper → export globals |
| Edit per-mesh ATTR / manip / light / anim | Dock rollups | src/models/* IO chunks on nodes |
| File → Export | ObjExporter → DlgExport |
Converterer::toXpln → XplnObj export |
| File → Import | ObjImporter → DlgImport |
Converterer::toMax (returns false) |
| Plugin menu | GUP ObjCommon + MainMenuActions |
Links, about, settings, update check |