This document outlines coding guidelines for contributions to the 3dsmax-usd project.
Many of the C++ coding guidelines below are validated and enforced through the use of clang-format
which is provided by the LLVM project. Since the adjustments made by clang-format
can vary from version to version, we standardize this project on a single clang-format
version to ensure consistent results for all contributions made to 3dsmax-usd.
Version | Source Code | Release | |
---|---|---|---|
clang-format /LLVM |
10.0.0 | llvmorg-10.0.0 Tag | LLVM 10.0.0 |
Every file should start with the Apache 2.0 licensing statement:
// Licensed under the Apache License, Version 2.0 (the “License”);
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an “AS IS” BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
- Every file should contain at least one Copyright line at the top, which can be to Autodesk or the individual/company that contributed the code.
- Multiple copyright lines are allowed, and if a significant new contribution is made to an existing file then an individual or company can append a new line to the copyright section.
- The year the original contribution is made should be included but there is no requirement to update this every year.
- There is no requirement that an Autodesk copyright line should be in all files. If an individual or company contributes new files they do not have to add both their name and Autodesk's name.
- If existing code is being refactored or moved within the repo then the original copyright lines should be maintained. You should only append a new copyright line if significant new changes are added. For example, if some utility code is being moved from a plugin into a common area, and the work involved is only minor name changes or include path updates, then the original copyright should be maintained. In this case, there is no requirement to add a new copyright for the person that handled the refactoring.
The project makes use of #pragma once
to avoid files being #include’d
multiple times (which can cause duplication of definitions & compilation errors). While it is a non-standard and non-portable extension, it is widely supported. It is also a choice aligned with the 3ds Max SDK. The platform and compiler used (Windows/VS) fully support the preprocessor option.
Naming (file, type, variable, constant, function, namespace, macro, template parameters, schema names)
General Naming Rules MaxUsd strives to use “camel case” naming. That is, each word is capitalized, except possibly the first word:
- UpperCamelCase
- lowerCamelCase
While underscores in names (_) (e.g., as separator) are not strictly forbidden, they are strongly discouraged. Optimize for readability by selecting names that are clear to others (e.g., people on different teams.) Use names that describe the purpose or intent of the object. Do not worry about saving horizontal space. It is more important to make your code easily understandable by others. Minimize the use of abbreviations that would likely be unknown to someone outside your project (especially acronyms and initialisms).
File Names Filenames should be UpperCamelCase and should not include underscores (_) or dashes (-). C++ files should end in .cpp and header files should end in .h. In general, make your filenames as specific as possible. For example:
StageData.cpp
StageData.h
Type Names All type names (i.e., classes, structs, type aliases, enums, and type template parameters) should use UpperCamelCase, with no underscores. For example:
class MaxUsdStageData;
class ImportData;
enum Roles;
Variable Names Class/Struct Data Members Constant Names All variables, data member and constant names, including function parameters and data members should use lowerCamelCase, with no underscores. For example:
const INode* parentNode;
const MSTR& rayDirection
bool* drawRenderPurpose;
Function/Method Names All functions should be UpperCamelCase. This avoids inconsistencies with the 3ds Max SDK. For example:
MSTR Name() const override;
void RegisterExitCallback();
Namespace Names Namespace names should be UpperCamelCase. Top-level namespace names are based on the project name.
namespace MaxUsd {}
Enumerator Names Enumerators (for both scoped and unscoped enums) should be UpperCamelCase.
The enumeration name, StringPolicy
is a type and therefore mixed case.
enum class StringPolicy
{
StringOptional,
StringMustHaveValue
};
Macro Names In general, macros should be avoided (see Modern C++ ). However, if they are absolutely needed, macros should be all capitals, with words separated by underscores.
#define ROUND(x) …
#define PI_ROUNDED 3.0
- Doxygen will be used to generate documentation from MaxUsd C++ sources.
- Doxygen tags must be used to document classes, function parameters, function return values, and thrown exceptions.
- The MaxUsd project does require the use of any Doxygen formatting style ( Doxygen built-in formatting )
- Comments for users of classes and functions must be written in headers files. Comments in definition files are meant for contributors and maintainers.
- Required: to use fully qualified namespace names. Global scope using directives are not allowed. Inline code can use using directives in implementations, within a scope, when there is no other choice (e.g. when using macros, which are not namespaced).
// In aFile.h
inline PXR_NS::UsdPrim prim() const
{
PXR_NAMESPACE_USING_DIRECTIVE
TF_VERIFY(item != nullptr);
return item->prim();
}
- Recommended: to use fully qualified namespace names, unless clarity or readability is degraded by use of explicit namespaces, in which case a using directive is acceptable.
- Recommended: to use the existing namespace style, and not make gratuitous changes. If the file is using explicit namespaces, new code should follow this style, unless the changes are so significant that clarity or readability is degraded. If the file has one or more using directives, new code should follow this style.
For source files (.cpp) with an associated header file (.h) that resides in the same directory, it should be #include
'd with double quotes and no path. This formatting should be followed regardless of with whether the associated header is public or private. For example:
// In foobar.cpp
#include "foobar.h"
All included public header files from outside and inside the project should be #include
’d using angle brackets. For example:
#include <pxr/base/tf/stringUtils.h>
#include <MaxUsd/MeshConversion/MeshConverter.h>
Private project’s header files should be #include
'd using double quotes, and a relative path. Private headers may live in the same directory or sub-directories, but they should never be included using "." or ".." as part of a relative path. For example:
#include "privateUtils.h"
#include "pvt/helperFunctions.h"
Headers should be included in the following order, with each section separated by a blank line and files sorted alphabetically:
- Related header
- All private headers
- All public headers from this repository (3dsmax-usd)
- UsdUfe library headers
- Pixar + USD headers
- Autodesk + 3ds Max headers
- Other libraries' headers
- C++ standard library headers
- C system headers
- Conditional includes
#include "MaxSceneBuilder.h"
#include "private/util.h"
#include <MaxUsd/Translators/PrimReaderRegistry.h>
#include <MaxUsd/Translators/TranslatorXformable.h>
#include <usdUfe/ufe/UsdSceneItem.h>
#include <pxr/base/tf/pyPolymorphic.h>
#include <GetCOREInterface.h>
#include <maxscript/maxscript.h>
#include <string>
#ifdef IS_MAX2023_OR_GREATER
#include <Graphics/UpdateDisplayContext.h>
#include <Graphics/InstanceDisplayGeometry.h>
#endif
3ds Max
- A series of
IS_MAX20XX_OR_GREATER
defines are available (seeMaxUsd/Utilities/MaxSupportUtils.h
) MAX_RELEASE
is the consistent macro to test 3ds Max version (seemaxsdk/include/plugapi.h
from the 3ds Max SDK)
UFE
- Each version of Ufe contains a features available define (in ufe.h) such as
UFE_V4_FEATURES_AVAILABLE
that can be used for conditional compilation on code depending on Ufe Version.
USD
PXR_VERSION
is the macro to test USD version (PXR_MAJOR_VERSION
* 10000 +PXR_MINOR_VERSION
* 100 +PXR_PATCH_VERSION
)
Respect the minimum supported version for 3ds Max and USD stated in build.md .
Recent extensions to the C++ standard introduce many features previously only found in boost. To avoid introducing additional dependencies, developers should strive to use functionality in the C++ std over boost. If you encounter usage of boost in the code, consider converting this to the equivalent std mechanism. Our library currently has the following boost dependencies:
boost::python
Our goal is to develop 3dsmax-usd following modern C++ practices. We’ll follow the C++ Core Guidelines and pay attention to:
using
(vstypedef
) keywordvirtual
,override
andfinal
keyworddefault
anddelete
keywordsauto
keyword- initialization -
{}
nullptr
keyword- …
Developers are encouraged to use TF library diagnostic facilities in 3ds Max USD. Please follow below guideline for picking the correct facility: https://graphics.pixar.com/usd/docs/api/page_tf__diagnostic.html
In MaxUsd, DiagnosticDelegate
converts TF diagnostics into native 3ds Max infos, warnings, and errors. The environment flag MAXUSD_SHOW_FULL_DIAGNOSTICS
, controls the granularity of TF error/warning/status messages being displayed in 3ds Max:
e.g
[2024-05-23 12:06:53.623] [USDImport] [warning] Unexpected input type or mapped value - normal3f:(0, 0, 1):normal
vs
[2024-05-23 12:06:53.623] [USDImport] [warning] Unexpected input type or mapped value - normal3f:(0, 0, 1):normal -- Warning in usd_material_reader.output_max_material at line 463 of d:\usd-component-2024/contents/scripts//materials\usd_material_reader.py
We are adopting the PEP-8 style for Python Code with the following modification:
- Mixed-case for variable and function names are allowed
Pylint is recommended for automation.