diff --git a/CMakeLists.txt b/CMakeLists.txt index 75e9b5b..ab06b1b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,14 +33,21 @@ ## ##-***************************************************************************** -CMAKE_MINIMUM_REQUIRED( VERSION 2.8 ) +CMAKE_MINIMUM_REQUIRED( VERSION 3.13 ) +project(AlembicDocs) SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/cmake) if (NOT DOXYGEN_EXECUTABLE) find_package( Doxygen REQUIRED ) endif() -find_package( PythonInterp REQUIRED ) +find_package( Python REQUIRED COMPONENTS Interpreter ) + +# Allow uppercase `ALEMBIC_ROOT` to be passed without warnings. +# cmake 3.27+ +if(POLICY CMP0144) + cmake_policy(SET CMP0144 NEW) +endif() find_package( Alembic REQUIRED ) CONFIGURE_FILE ( diff --git a/README.md b/README.md index 5871782..d3d8e8a 100644 --- a/README.md +++ b/README.md @@ -4,10 +4,11 @@ The documentation [website](http://docs.alembic.io) for Requires -------- -:: - - sphinx 1.4 (pip install sphinx) - - breathe 4.1.0 (pip install breathe) +- `doxygen` available from PATH +- `alembic` and `imath` installed as Python modules +- [`alembic`](https://github.com/alembic/alembic/) installed and available from PATH +- Python dependencies - can be installed with `pip install -r requirements.txt` Building -------- diff --git a/cmake/FindAlembic.cmake b/cmake/FindAlembic.cmake index 6aa6d12..ac2607b 100644 --- a/cmake/FindAlembic.cmake +++ b/cmake/FindAlembic.cmake @@ -32,6 +32,16 @@ ## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ## ##-***************************************************************************** +# +# +# Module resulting variables: +# - `Alembic_FOUND` - `TRUE` if Alembic was found +# - `ALEMBIC_INCLUDE_PATH` - include directory path +# - `ALEMBIC_LIB` - path to library +# +# Other variables: +# - `ALEMBIC_ROOT` - installation root folder. Can be provided to hint search paths. +# Also can be provided as an environment variable. IF (NOT ALEMBIC_ROOT AND NOT $ENV{ALEMBIC_ROOT} STREQUAL "") SET(ALEMBIC_ROOT $ENV{ALEMBIC_ROOT}) @@ -105,20 +115,22 @@ FIND_LIBRARY(ALEMBIC_LIB Alembic DOC "The Alembic library" ) -SET( ALEMBIC_FOUND TRUE ) - -IF (${ALEMBIC_INCLUDE_PATH} STREQUAL "ALEMBIC_INCLUDE_PATH-NOTFOUND") - MESSAGE( STATUS "Alembic include path not found" ) - SET(ALEMBIC_FOUND FALSE) -ELSE() +IF(ALEMBIC_INCLUDE_PATH) GET_FILENAME_COMPONENT(ALEMBIC_INCLUDE_PATH ${ALEMBIC_INCLUDE_PATH} DIRECTORY) - MESSAGE(STATUS "ALEMBIC_INCLUDE_PATH ${ALEMBIC_INCLUDE_PATH}") + MESSAGE(STATUS "Alembic include path is found at '${ALEMBIC_INCLUDE_PATH}'") +ELSE() + MESSAGE(STATUS "Alembic include path not found" ) ENDIF() -IF (${ALEMBIC_LIB} STREQUAL "ALEMBIC_LIB-NOTFOUND") - MESSAGE( STATUS "Alembic library not found" ) - SET( ALEMBIC_FOUND FALSE ) - SET( ALEMBIC_LIB NOTFOUND ) +IF(ALEMBIC_LIB) + MESSAGE(STATUS "Alembic library is found at '${ALEMBIC_LIB}'") ELSE() - MESSAGE(STATUS "ALEMBIC_LIB ${ALEMBIC_LIB}") + MESSAGE(STATUS "Alembic library not found" ) ENDIF() + +include(FindPackageHandleStandardArgs) + +find_package_handle_standard_args( + Alembic + REQUIRED_VARS ALEMBIC_INCLUDE_PATH ALEMBIC_LIB +) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..992b598 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +sphinx +breathe +sphinx_rtd_theme diff --git a/sphinx/conf.py.in b/sphinx/conf.py.in index 3a33e54..8cfd8da 100644 --- a/sphinx/conf.py.in +++ b/sphinx/conf.py.in @@ -24,15 +24,22 @@ import alembic # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.todo', - 'sphinx.ext.coverage', 'sphinx.ext.pngmath', 'sphinx.ext.ifconfig', + 'sphinx.ext.coverage', 'sphinx.ext.imgmath', 'sphinx.ext.ifconfig', 'sphinx.ext.viewcode', 'sphinx.ext.autosummary', 'breathe'] def get_header_files(path): h_files = [] + assert os.path.exists(path), path for (path, dirs, files) in os.walk(path): h_files.extend([f for f in files if f.endswith(".h")]) return h_files +breathe_doxygen_config_options = { + # Expand export macro to nothing for doxygen to succeed. + "MACRO_EXPANSION": "YES", + "PREDEFINED": "ALEMBIC_EXPORT=", +} + breathe_projects_source = { "Abc": ("@ALEMBIC_INCLUDE_PATH@/Abc", get_header_files("@ALEMBIC_INCLUDE_PATH@/Abc")), @@ -65,8 +72,8 @@ source_suffix = '.rst' master_doc = 'index' # General information about the project. -project = u'Alembic' -copyright = u'2012-2016, Sony Pictures Imageworks Inc. and Industrial Light & Magic, a division of Lucasfilm Entertainment Company Ltd.' +project = 'Alembic' +copyright = '2012-2016, Sony Pictures Imageworks Inc. and Industrial Light & Magic, a division of Lucasfilm Entertainment Company Ltd.' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -120,10 +127,9 @@ pygments_style = 'sphinx' try: import sphinx_rtd_theme html_theme = "sphinx_rtd_theme" - html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] except ImportError as err: - print "Error importing theme, use `easy_install sphinx_rtd_theme`" + print("Error importing theme, use `pip install sphinx_rtd_theme`") sys.exit(1) # The name for this set of Sphinx documents. If None, it defaults to @@ -145,7 +151,7 @@ html_logo = "alembic.png" # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] +html_static_path = [] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. @@ -203,8 +209,8 @@ htmlhelp_basename = 'AlembicDoc' # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ - ('index', 'Alembic.tex', u'Alembic Documentation', - u'Lucasfilm LTD.', 'manual'), + ('index', 'Alembic.tex', 'Alembic Documentation', + 'Lucasfilm LTD.', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of @@ -236,18 +242,18 @@ latex_documents = [ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ - ('index', 'alembic', u'Alembic Documentation', - [u'Lucasfilm LTD.'], 1) + ('index', 'alembic', 'Alembic Documentation', + ['Lucasfilm LTD.'], 1) ] # -- Options for Epub output --------------------------------------------------- # Bibliographic Dublin Core info. -epub_title = u'Alembic' -epub_author = u'Lucasfilm LTD.' -epub_publisher = u'Lucasfilm LTD.' -epub_copyright = u'2012-2016, Lucasfilm LTD.' +epub_title = 'Alembic' +epub_author = 'Lucasfilm LTD.' +epub_publisher = 'Lucasfilm LTD.' +epub_copyright = '2012-2016, Lucasfilm LTD.' # The language of the text. It defaults to the language option # or en if the language is not set. @@ -280,5 +286,5 @@ epub_copyright = u'2012-2016, Lucasfilm LTD.' # Allow duplicate toc entries. #epub_tocdup = True -rst_epilog = ".. |version| replace: %s" % version +rst_epilog = '.. |version| replace:: %s' % version diff --git a/sphinx/index.rst b/sphinx/index.rst index dd3e160..7b5274b 100644 --- a/sphinx/index.rst +++ b/sphinx/index.rst @@ -16,6 +16,12 @@ that result from an arbitrarily complex animation and simulation process, but wi attempt to store a representation of the network of computations (rigs, basically) which were required to produce the final, animated vertex positions and animated transforms. +.. toctree:: + :maxdepth: 2 + :hidden: + + python/examples + reference/index Get Alembic ----------- diff --git a/sphinx/python/abcm.rst b/sphinx/python/abcm.rst index acfeed9..e2d54d8 100644 --- a/sphinx/python/abcm.rst +++ b/sphinx/python/abcm.rst @@ -14,7 +14,7 @@ include a document of conventions for interchange via a reserved "abc" target va shader type: a string representing a shader classification by name and agreed-upon convention. Examples include "surface," "displacement" and "light." This could also -express things like "coshader_taco" in which the value text following the "coshader_" +express things like "coshader_taco" in which the value text following the "coshader\_" prefix is used as a coshader instance name. shader name: a string identifying a shader object within a specified target and shader diff --git a/sphinx/python/examples.rst b/sphinx/python/examples.rst index b44eafe..5a7ca0f 100644 --- a/sphinx/python/examples.rst +++ b/sphinx/python/examples.rst @@ -79,6 +79,7 @@ Our sample output Archive will contain a single animated Transform with a single as its child. Because we're creating an :py:class:`.OArchive`, this will create (or clobber) the archive file with this filename: :: + >>> from alembic.Abc import OArchive >>> oarch = OArchive('polyMesh1.abc') @@ -103,6 +104,7 @@ An :py:class:`.OPolyMesh` is-an OObject that has-an :py:class:`.OPolyMeshSchema`. An OPolyMeshSchema is-an :py:class:`.OCompoundProperty`. In this case, we're parenting the PolyMesh under the Archive's top node and naming it "meshy". :: + >>> from alembic.AbcGeom import OPolyMesh >>> meshObj = OPolyMesh(oarch.getTop(), "meshy") >>> mesh = meshyObj.getSchema() @@ -174,16 +176,19 @@ The typed GeomParams have an inner Sample class that is used for setting and get according to the type of data they will contain, for example the :py:class:`.OV2fGeomParamSample` is used to store V2f data, such as UVs. Continuing our example: :: + >>> from alembic.AbcGeom import OPolyMeshSchemaSample >>> uvsamp = OV2fGeomParamSample(uvs, kFacevaryingScope) Normals have their own type. :: + >>> from alembic.AbcGeom import ON3fGeomParamSample >>> nsamp = ON3fGeomParamSample(normals, kFacevaryingScope) Create a :py:class:`.OPolyMeshSchemaSample` Sample. We're creating the Sample inline here, but we could create a static sample and leave it around, only modifying the parts that have changed. The first sample should contain at least all of the required data for a PolyMesh. :: + >>> from alembic.AbcGeom import OPolyMeshSchemaSample >>> mesh_samp = OPolyMeshSchemaSample(verts, indices, counts, uvsamp, nsamp) Make up some bounding box data and set it on the sample. :: @@ -237,8 +242,9 @@ Reading an Archive Read an Alembic archive, also referred to as an :py:class:`.IArchive`. :: + >>> from alembic.Abc import IArchive >>> iarch = IArchive('polyMesh1.abc') - >>> print "Reading", iarch.getName() + >>> print("Reading", iarch.getName()) Reading polyMesh1.abc @@ -263,6 +269,7 @@ called *ABC*. So, in our example: :: All scene data is parented under this top node. :: + >>> from alembic.AbcGeom import IPolyMesh >>> meshObj = IPolyMesh(top, "meshy") >>> mesh = meshObj.getSchema() >>> N = mesh.getNormalsParam() @@ -273,6 +280,7 @@ All scene data is parented under this top node. :: If you don't know the object type of the input data, you can check the Object MetaData and match it to a specific type. :: + >>> from alembic.AbcGeom import IPolyMesh, IPolyMeshSchema >>> obj = top.children[0] >>> if IPolyMeshSchema.matches(obj): >>> ... meshObj = IPolyMesh(obj, KWrapExisting) @@ -335,11 +343,14 @@ adapted from the previous example and we're only bothering to match against the :: + from alembic.Abc import IArchive + from alembic.AbcGeom import IPolyMesh, ISubD + def visitObject(obj, name): md = obj.getMetaData() if IPolyMesh.matches(md) or ISubD.matches(md): if obj.getName() == name: - print "Found it!", obj.getFullName() + print("Found it!", obj.getFullName()) return for childObject in obj.children: visitObject(childObject, name) @@ -357,6 +368,10 @@ name, we're going to call a new function, :py:func:`getBounds()`. :: + import imath + from alembic.Abc import IArchive + from alembic.AbcGeom import IPolyMesh, ISubD, IXform + gBounds = imath.Box3d() gBounds.makeEmpty() kWrapExisting = alembic.Abc.WrapExistingFlag.kWrapExisting @@ -408,6 +423,15 @@ workflows. Here we need an :py:class:`.OCompoundProperty` to use as the parent o :: + from alembic.Abc import OArchive + from alembic.AbcGeom import ( + OPolyMesh, + OPolyMeshSchemaSample, + ODoubleProperty, + OP3fGeomParamSample, + OInt32GeomParamSample + ) + archive = OArchive("crazyPolyMesh1.abc") meshObj = OPolyMesh(archive.getTop(), "crazy") diff --git a/sphinx/reference/abcm.rst b/sphinx/reference/abcm.rst index 7ef85ab..f56de79 100644 --- a/sphinx/reference/abcm.rst +++ b/sphinx/reference/abcm.rst @@ -14,7 +14,7 @@ include a document of conventions for interchange via a reserved "abc" target va shader type: a string representing a shader classification by name and agreed-upon convention. Examples include "surface," "displacement" and "light." This could also -express things like "coshader_taco" in which the value text following the "coshader_" +express things like "coshader_taco" in which the value text following the "coshader\_" prefix is used as a coshader instance name. shader name: a string identifying a shader object within a specified target and shader