Server application for collaborative production of 3D assets and animations.
(define-module (vfx packages pixar)
  #:use-module (gnu packages)
  #:use-module (gnu packages cmake)
  #:use-module (gnu packages commencement)
  #:use-module (gnu packages pkg-config)
  #:use-module (gnu packages boost)
  #:use-module (gnu packages tbb)

  #:use-module (gnu packages python)
  #:use-module (gnu packages python-xyz)

  #:use-module (gnu packages xorg)
  #:use-module (gnu packages vulkan)
  #:use-module (gnu packages gl)
  #:use-module (gnu packages glib)
  #:use-module (gnu packages qt)
  #:use-module (gnu packages opencl)

  #:use-module (gnu packages image)
  #:use-module (gnu packages image-processing)
  #:use-module (gnu packages compression)
  #:use-module (gnu packages graphics)

  #:use-module (gnu packages documentation)
  #:use-module (gnu packages bash)

  #:use-module (vfx packages base)
  #:use-module (vfx packages opencl)
  #:use-module (vfx packages qt)
  #:use-module (vfx packages lucasfilm)

  #:use-module (guix)
  #:use-module (guix gexp)
  #:use-module (guix git-download)
  
  #:use-module (guix build-system gnu)
  #:use-module (guix build-system trivial)
  #:use-module (guix build-system cmake)
  #:use-module ((guix licenses) #:prefix licenses:))

(define-public opensubdiv-3.5
  (package
    (name "opensubdiv")
    (version "3.5.0")
    (source (origin
              (method git-fetch)
              (uri (git-reference
                    (url "https://github.com/PixarAnimationStudios/OpenSubdiv")
                    (commit (string-append "v"
					   (string-join (string-split version #\.)
                                                        "_")))))
              (file-name (git-file-name name version))
              (sha256
               (base32
                "05zmhm7izywkvpld1ridqx9pf7frxjg4hv2wqxa4zk1c20gzd055"))))
    (build-system cmake-build-system)
    (arguments `(
      ;; TODO: Fix OpenCL support for OpenSubdiv
      ;; #:configure-flags
      ;;   (list "-DCL_TARGET_OPENCL_VERSION=120"
      ;;         (string-append "-DOPENCL_INCLUDE_DIRS="
      ;;                        (assoc-ref %build-inputs "opencl-headers"))
      ;;         (string-append "-DOPENCL_LIBRARIES="
      ;;                        (search-input-file %build-inputs "lib/libOpenCL.so"))
      ;;         (string-append "-DCLEW_LOCATION="
      ;;                        (assoc-ref %build-inputs "clew")))
			       
       #:phases (modify-phases %standard-phases
                  (add-before 'check 'start-xorg-server
                    (lambda* (#:key inputs #:allow-other-keys)
		      ;; The test suite requires a running X server
                      (system "Xvfb :1 &")
                      (setenv "DISPLAY" ":1")
                      #t)))))
    (native-inputs
     (list xorg-server-for-tests
	   python
	   python-docutils	   
	   doxygen))
    (inputs
     (list tbb-2020
	   glfw
	   glew
	   ;;opencl-headers
	   ;;mesa-opencl
	   ;;mesa-opencl-icd
	   ;;clew
	   ptex
           zlib))
    (home-page "https://graphics.pixar.com/opensubdiv/")
    (synopsis "High performance subdivision surface evaluation")
    (description "OpenSubdiv is a set of libraries that implement high
performance subdivision surface (subdiv) evaluation on massively parallel CPU
and GPU architectures.")
    (license licenses:asl2.0)))

;; Python wrapped with jemalloc enabled
;; (needed by pxr.Usdviewq Python module)
(define python-for-usd
  (package
   (inherit python-3.9)
   (inputs (modify-inputs (package-inputs python-3.9)
			    (prepend jemalloc-5.3)))
   (arguments
     (substitute-keyword-arguments (package-arguments python-3.9)
       ((#:phases phases)
         `(modify-phases ,phases
	  (add-after 'install 'use-jemalloc
	    (lambda* (#:key inputs outputs #:allow-other-keys)
              (wrap-program (string-append (assoc-ref outputs "out")
			    "/bin/python3.9")
                `("LD_PRELOAD" =
                  (,(search-input-file
                    inputs "/lib/libjemalloc.so.2"))))))))))))

(define* (wrap-python3 python
                       #:optional
                       (name (string-append (package-name python) "-wrapper")))
  (package/inherit python
    (name name)
    (source #f)
    (build-system trivial-build-system)
    (outputs '("out"))
    (inputs `(("bash" ,bash)))
    (propagated-inputs `(("python" ,python)))
    (arguments
     `(#:modules ((guix build utils))
       #:builder
         (begin
           (use-modules (guix build utils))
           (let ((bin (string-append (assoc-ref %outputs "out") "/bin"))
                 (python (string-append (assoc-ref %build-inputs "python") "/bin/")))
                (mkdir-p bin)
                (for-each
                  (lambda (old new)
                    (symlink (string-append python old)
                             (string-append bin "/" new)))
                  `("python3" ,"pydoc3" ,"pip3")
                  `("python"  ,"pydoc"  ,"pip"))
                ;; python-config outputs search paths based upon its location,
                ;; use a bash wrapper to avoid changing its outputs.
                (let ((bash (string-append (assoc-ref %build-inputs "bash")
                                           "/bin/bash"))
                      (old  (string-append python "python3-config"))
                      (new  (string-append bin "/python-config")))
                  (with-output-to-file new
                    (lambda ()
                      (format #t "#!~a~%" bash)
                      (format #t "exec \"~a\" \"$@\"~%" old)
                      (chmod new #o755))))))))
    (synopsis "Wrapper for the Python 3 commands")
    (description
     "This package provides wrappers for the commands of Python@tie{}3.x such
that they can also be invoked under their usual names---e.g., @command{python}
instead of @command{python3} or @command{pip} instead of @command{pip3}.

To function properly, this package should not be installed together with the
@code{python} package: this package uses the @code{python} package as a
propagated input, so installing this package already makes both the versioned
and the unversioned commands available.")))

;; "python" link pointing to "python3" command
(define-public python-wrapper-for-usd (wrap-python3 python-for-usd))

(define-public usd
  (package
    (name "usd")
    (version "23.02")
    (source
     (origin
      (method url-fetch)
      (uri
       (string-append "https://github.com/PixarAnimationStudios/USD/"
                      "archive/refs/tags/v" version ".tar.gz"))
       (sha256
        (base32 "0pakwyf25kbf0934rm7i3jgmdwspr76hpf8ibg7682fv4bvzzvm8"))
       (patches
        (search-patches ;"vfx/patches/usd-fix-hgiinterop-vulkan.patch"
		        "vfx/patches/usd-use-normal-python.patch"))))
    (build-system cmake-build-system)
    (arguments
       `(#:tests? #f
         #:validate-runpath? #f
         #:configure-flags
         (list "-DPXR_BUILD_MONOLITHIC=ON"
               "-DTBB_USE_DEBUG_BUILD=OFF"
               "-DPXR_PREFER_SAFETY_OVER_SPEED=ON"
               "-DPXR_ENABLE_VULKAN_SUPPORT=OFF"

               (string-append "-DPXR_MALLOC_LIBRARY="
                             (search-input-file %build-inputs "lib/libjemalloc.so"))

               "-DPXR_BUILD_DOCUMENTATION=OFF"
               "-DPXR_BUILD_TESTS=OFF"
               "-DPXR_BUILD_EXAMPLES=OFF"
               "-DPXR_BUILD_TUTORIALS=OFF"
               "-DPXR_BUILD_USD_IMAGING=ON"
               "-DPXR_BUILD_USDVIEW=ON"

               "-DPXR_ENABLE_PYTHON_SUPPORT=ON"
               "-DPXR_USE_PYTHON_3=ON"
               "-DPXR_USE_DEBUG_PYTHON=OFF"

               "-DPXR_ENABLE_OPENVDB_SUPPORT=ON"
               "-DPXR_ENABLE_MATERIALX_SUPPORT=ON"
               "-DPXR_ENABLE_PTEX_SUPPORT=ON"

               "-DPXR_BUILD_OPENIMAGEIO_PLUGIN=ON"
               "-DPXR_BUILD_OPENCOLORIO_PLUGIN=ON"
               "-DPXR_BUILD_EMBREE_PLUGIN=ON"
               "-DPXR_BUILD_PRMAN_PLUGIN=OFF"
               "-DPXR_BUILD_ALEMBIC_PLUGIN=OFF"
               "-DPXR_BUILD_DRACO_PLUGIN=OFF"

               "-DCMAKE_EXPORT_NO_PACKAGE_REGISTRY=ON")

         #:phases
         (modify-phases %standard-phases
           ;; USD build system needs MaterialX and Vulkan explicit location
           (add-before 'configure 'set-env-vars
             (lambda _
                 (setenv "MaterialX_DIR" (assoc-ref %build-inputs "materialx"))
               ;; TODO: Fix vulkan support for USD
               ;;(setenv "VULKAN_SDK"    (assoc-ref %build-inputs "vulkan-headers"))
		 #t))
           (add-after 'install 'fix-installed-python-modules-path
		      (lambda* (#:key outputs #:allow-other-keys)
			       (let* ((now (string-append (assoc-ref outputs "out")
							  "/lib/python"))
				      (dir (string-append now
							  ,(version-major+minor
						            (package-version python-wrapper-for-usd))))
				      (fix (string-append dir
							  "/site-packages")))
				 (mkdir-p dir)
				 (rename-file now fix)))))))
    (native-inputs (list
      python-jinja2))

    (inputs (list
       jemalloc-5.3
       tbb-2020
       boost

       mesa
       ;;vulkan-headers
       ;;vulkan-loader
       ;;spirv-headers
       ;;spirv-cross
       ;;shaderc
       glu
       freeglut

       libx11
       libxi
       libxrender
       glib

       imath
       ilmbase
       openexr
       opencolorio-2.2
       openimageio-2.4
       opensubdiv-3.5
       openvdb-10.0
       materialx
       ptex
       embree

       openjpeg
       libjpeg-turbo
       libpng
       libtiff
       zlib))

    (propagated-inputs (list
       python-wrapper-for-usd
       python-pyside-6
       python-pyside-6-tools
       python-pyopengl))       

    (home-page "https://graphics.pixar.com/usd/")
    (synopsis "Pixar's Universal Scene Description libraries and tools")
    (description
     "USD is a high-performance extensible software platform
for collaboratively constructing animated 3D scenes,
designed to meet the needs of large-scale film and visual effects production.")
    (license licenses:asl2.0)))