Advertisement
Guest User

script_manager_environment.py

a guest
Mar 22nd, 2020
339
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.36 KB | None | 0 0
  1. """A command line wrapper for Cinema 4D Script Manager Python scripts.
  2.  
  3. The wrapper makes scripts that have been written for the Cinema4D script manager, i.e. rely on the presence of predefined attributes like ``doc`` or ``op``, executeable in a ``c4dpy`` environment. The wrapper takes a script path and a Cinema 4D document path as its CL arguments, then executes the script on the document and finally saves the modified document.
  4.  
  5. The argument syntax of the script is:
  6.    
  7.    ``[-h] [-out OUT] -in IN -script SCRIPT``
  8.  
  9. Where ``SCRIPT`` is the path to the script to run and ``IN`` is the document to run the script on and ``OUT`` is an optional output path. If ``OUT`` is not present, the modified document will be written to ``IN``.
  10.  
  11. The wrapper will set the active document of the running ``c4dpy`` instance to an instance of the document specified by ``IN`` and also reveal the following objects in the dictionary of the executing module:
  12.    
  13.    doc (``c4d.documents.BaseDocument``): The document specified by ``IN``.
  14.    op (``c4d.BaseObject`` or ``None``): The active object in the document.
  15.    tp (``c4d.modules.thinkingparticles.TP_MasterSystem``): The particle master system of the document.
  16.  
  17. The script does accept both absolute and relative paths for its path inputs. For an overview of the command line arguments of the script, run the script with the ``-h`` flag.
  18. """
  19.  
  20. import argparse
  21. import c4d
  22. import os
  23. import runpy
  24.  
  25.  
  26. def get_paths():
  27.     """Parses the command line arguments of the script and ensures that the file paths do resolve and converts them to absolute paths.
  28.  
  29.    Returns:
  30.        ``tuple[str, str, str]``: The absolute script path, document path and the document output path.
  31.  
  32.    Prints:
  33.        IOError: If the argument values for the ``script`` or ``in`` path is not an existing file path.
  34.    """
  35.     parser = argparse.ArgumentParser(
  36.         description=("Wraps a Python script that has been written for the "
  37.                      "Cinema 4D main app, so that it can be executed on a "
  38.                      "document from the c4dpy command line."))
  39.     arguments = {
  40.         "-script":
  41.             {
  42.                 "help": "The path to the python script to execute.",
  43.                 "required": True,
  44.                 "type": str
  45.             },
  46.         "-in":
  47.             {
  48.                 "help": "The path to the document to execute the script on.",
  49.                 "required": True,
  50.                 "type": str
  51.             },
  52.         "-out":
  53.             {
  54.                 "default": None,
  55.                 "help": ("An optional path to write the state of the "
  56.                          "document to, after the scripted has been executed "
  57.                          ". If not provided, the '-in' path will be used "
  58.                          "instead."),
  59.                 "required": False,
  60.                 "type": str
  61.             },
  62.     }
  63.     for name, kwargs in arguments.items():
  64.         parser.add_argument(name, **kwargs)
  65.     paths = parser.parse_args().__dict__
  66.  
  67.     # Validate the paths
  68.     for name, path in paths.items():
  69.         path = os.path.abspath(path) if path is not None else None
  70.         paths[name] = path
  71.  
  72.         if name not in ("script", "in"):
  73.             continue
  74.         elif not os.path.exists(path) or not os.path.isfile(path):
  75.             msg = "IOError: Non-existing or non-file path received: {}"
  76.             print msg.format(path)
  77.             return None
  78.  
  79.     if paths["out"] is None:
  80.         paths["out"] = paths["in"]
  81.  
  82.     return paths["script"], paths["in"], paths["out"],
  83.  
  84.  
  85. def run_script(script_path, in_path, out_path):
  86.     """Runs a Python script on a Cinema document and saves the modified document.
  87.  
  88.    Args:
  89.        script_path (``str``): The absolute file path of the script.
  90.        in_path (``str``): The absolute file path of the input document.
  91.        out_path (``str``): The absolute file path of the output document.
  92.  
  93.    Prints:
  94.        IOError: When Cinema cannot load the file at ``in_path``.
  95.    """
  96.     # Load the document and build the globals.
  97.     doc = c4d.documents.LoadDocument(
  98.         name=in_path,
  99.         loadflags=c4d.SCENEFILTER_OBJECTS | c4d.SCENEFILTER_MATERIALS,
  100.         thread=None)
  101.     if doc is None:
  102.         msg = "IOError: Could not load Cinema 4D document at: {}."
  103.         print msg.format(in_path)
  104.         return
  105.  
  106.     c4d.documents.SetActiveDocument(doc)
  107.     op = doc.GetActiveObject()
  108.     tp = doc.GetParticleSystem()
  109.     # Execute the script
  110.     data = runpy.run_path(
  111.         script_path,
  112.         init_globals={"doc": doc, "op": op, "tp": tp},
  113.         run_name="__main__")
  114.  
  115.     # Save the modified state.
  116.     result = c4d.documents.SaveDocument(doc=doc,
  117.                                         name=out_path,
  118.                                         saveflags=c4d.SAVEDOCUMENTFLAGS_NONE,
  119.                                         format=c4d.FORMAT_C4DEXPORT)
  120.     if not result:
  121.         msg = "IOError: Could not write to file path: {}."
  122.         print msg.format(file_path)
  123.         return
  124.  
  125.     msg = "Executed '{}' on '{}' and saved the result to '{}'."
  126.     print msg.format(os.path.split(script_path)[1],
  127.                      os.path.split(in_path)[1],
  128.                      out_path)
  129.  
  130.  
  131. def main():
  132.     """Entry point.
  133.    """
  134.     paths = get_paths()
  135.     if paths:
  136.         run_script(*paths)
  137.  
  138.  
  139. if __name__ == "__main__":
  140.     main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement