# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=tcl:et:sw=4:ts=4:sts=4

PortSystem          1.0
PortGroup           github 1.0
PortGroup           cmake 1.1

name                nanogui
revision            1
categories          graphics
license             BSD
maintainers         @jasonliu-- openmaintainer

if {$subport eq "nanogui"} {

conflicts           nanogui-wjakob

github.setup        mitsuba-renderer nanogui 21e5cbc880b2e26b28b2a35085a9e6706da1e2a8
# Change github.tarball_from to 'releases' or 'archive' next update
github.tarball_from tarball
version             20200404-[string range ${github.version} 0 7]

checksums           rmd160  192baaa0a7f0ac862b2d09021daa98733e342932 \
                    sha256  f105aa23476f99c2db1b28bccf4751498584e366a30e5e5078d6963a8bab6c93 \
                    size    2911997

description         minimalistic C++/Python GUI library for OpenGL, \
                    GLES2/3, Metal, and WebAssembly/WebGL
long_description    NanoGUI is a minimalistic cross-platform widget \
                    library for OpenGL 3+, GLES 2/3, and Metal. It \
                    supports automatic layout generation, stateful C++ \
                    lambdas callbacks, a variety of useful widget \
                    types, and Retina-capable rendering on Apple \
                    devices. \
 \
                    (Note: This port is for the \"new\" NanoGUI, which \
                    still sees active development and improvement. \
                    This newer version of NanoGUI has been re-written \
                    for the Mitsuba renderer. If you still need to use \
                    the \"old\" NanoGUI, please take a look at the \
                    'nanogui-wjakob' port.)

compiler.cxx_standard 2017
configure.cxxflags-append -std=c++17

}

subport nanogui-wjakob {

conflicts           nanogui

github.setup        wjakob nanogui e9ec8a1a9861cf578d9c6e85a6420080aa715c03
# Change github.tarball_from to 'releases' or 'archive' next update
github.tarball_from tarball
version             20190922-[string range ${github.version} 0 7]

checksums           rmd160  ab08f55be3e6e78d353d05a4a9d7d6d4c5855c9f \
                    sha256  1d8201643ae809e0d861f5c33110f622902c0c50a700136ecfc49156c5ad2f23 \
                    size    2769126

description         minimalistic C++/Python GUI library for OpenGL 3+
long_description    NanoGUI is a minimalistic cross-platform widget \
                    library for OpenGL 3.x and higher. It supports \
                    automatic layout generation, stateful C++ lambdas \
                    callbacks, a variety of useful widget types, and \
                    Retina-capable rendering on Apple devices. \
 \
                    (Note: This port is for the \"old\" NanoGUI, which \
                    has been placed into maintenance-only mode by its \
                    author. However, most software projects that \
                    depend on NanoGUI as a library, are still using \
                    this version, instead of the newer version that \
                    has been re-written for the Mitsuba renderer. So \
                    even though this port is \"old\", it should not be \
                    considered to be deprecated or obselete.)

compiler.cxx_standard 2011
configure.cxxflags-append -std=c++11

}

# macOS 10.6 and earlier do not have OpenGL 3 (gl3.h)
if {${os.platform} eq "darwin" && ${os.major} <= 10} {
    known_fail      yes
    pre-fetch {
        ui_error "${subport} requires OpenGL 3 (available in Mac OS X 10.7 and later)."
        return -code error "incompatible Mac OS X version"
    }
}

depends_lib-append  port:glfw \
                    port:nanovg

if {$subport eq "nanogui-wjakob"} {
    depends_lib-append  path:share/pkgconfig/eigen3.pc:eigen3
}

post-patch {
    # By default, NanoGUI's code assumes that the source codes of its
    # dependencies have been copied into NanoGUI's source tree. The
    # following replacements allow NanoGUI to compile against MacPorts
    # packages.
    set regexes [list \
        "/NOT IS_DIRECTORY.*glfw/,/endif/s/^/#/g" \
        "s|\(NANOGUI_PYBIND11_DIR.*\)tools|\\1share/cmake/pybind11|" \
        "s|\(NANOGUI_EXTRA_DEFS -DNANOGUI_USE_METAL\)|\\1 -DTARGET_OS_OSX|" \
        "s|\".*CMAKE_CURRENT_SOURCE_DIR.*glfw/include|\"${prefix}/include/GLFW|" \
        "s|\".*CMAKE_CURRENT_SOURCE_DIR.*nanovg/src|\"${prefix}/include/nanovg|" \
        "s|ext/\(nanovg\)/\(src\)/\(.*\.c\)|${prefix}/\\2/\\1/\\3|g" \
        "s|ext/\(nanovg\)/src/\(.*\.h\)|${prefix}/include/\\1/\\2|g" \
        "s|ext/\(nanovg\)/\(src\)|${prefix}/include/\\1|g" \
        "s|ext/\(nanovg_metal\)/\(src\)/\(.*\.m\)|${prefix}/\\2/\\1/\\3|g" \
        "s|ext/\(nanovg_metal\)/src/\(.*\.h\)|${prefix}/include/\\1/\\2|g" \
        "s|ext/\(nanovg_metal\)/\(src\)|${prefix}/include/\\1|g" \
        "s|\(COPY resources.*DESTINATION \).*|\\1 share/nanogui/examples)|" \
    ]
    if {$subport eq "nanogui"} {
        lappend regexes \
            "s|\(example\[0-9\].*nanogui\)|\\1 \${NANOGUI_EXTRA_LIBS}|g"
    } elseif {$subport eq "nanogui-wjakob"} {
        lappend regexes \
            "/add_subdirectory/s/^/#/" \
            "s|\".*CMAKE_CURRENT_SOURCE_DIR.*tools|\"${prefix}/share/cmake/pybind11|" \
            "s|ext/glfw/include|${prefix}/include/GLFW|g"
    }
    foreach re $regexes {
        reinplace -q -E $re ${worksrcpath}/CMakeLists.txt
    }

    # Add MacPorts paths
    reinplace "/^if.*CMAKE_SYSTEM_NAME.*MATCHES.*BSD/i\\
if (APPLE)\\
\\  include_directories(${prefix}/include)\\
\\  link_directories(${prefix}/lib)\\
endif()\\
" \
        ${worksrcpath}/CMakeLists.txt

    # Make it so that CMake will be able to link to GL libraries,
    # even though we are running on "APPLE" and not "Linux".
    reinplace "/elseif.*CMAKE_SYSTEM MATCHES.*Linux.*OR CMAKE_SYSTEM_NAME.*BSD/a\\
endif()\\
if (APPLE)\\
" \
        ${worksrcpath}/CMakeLists.txt
    if {$subport eq "nanogui"} {
        reinplace "/NANOGUI_EXTRA_LIBS GL)/s/^/#/" \
            ${worksrcpath}/CMakeLists.txt
    }
    reinplace "/Xrandr Xinerama/s/^/#/" ${worksrcpath}/CMakeLists.txt
    reinplace -E "s|NOT \(CMAKE_SYSTEM_NAME MATCHES.*OpenBSD\)|\\1|" \
        ${worksrcpath}/CMakeLists.txt

    # Make it so that CMake can find MacPorts' glfw
    if {$subport eq "nanogui"} {
        reinplace "/include_directories.*glfw/a\\
else()\\
\\  include_directories(${prefix}/include/GLFW)\\
" \
            ${worksrcpath}/CMakeLists.txt
        reinplace "/TARGET_OBJECTS:glfw_objects/a\\
else()\\
\\  list(APPEND NANOGUI_EXTRA_LIBS glfw)\\
" \
            ${worksrcpath}/CMakeLists.txt
    } elseif {$subport eq "nanogui-wjakob"} {
        set glfw_replacements [list \
            "/set_target_properties.*glfw /s/^/#/g" \
            "/set_target_properties.*glfw_objects /s/^/#/g" \
            "/TARGET_OBJECTS:glfw_objects/d" \
        ]
        foreach re $glfw_replacements {
            reinplace -E $re ${worksrcpath}/CMakeLists.txt
        }

        reinplace "/iokit_library IOKit/a\\
\\  list(APPEND NANOGUI_EXTRA_LIBS glfw)\\
" \
            ${worksrcpath}/CMakeLists.txt
    }

    # For some reason, NanoGUI's source code compiles the examples,
    # but then never actually installs them anywhere and simply
    # leaves them in the build directory.
    reinplace "/COPY resources/a\\
\\  install(DIRECTORY src/ DESTINATION share/nanogui/examples\\
\\          FILES_MATCHING PATTERN \"example*\")\\
\\  install(TARGETS example1 example2 example3 example4 example_icons\\
\\          RUNTIME DESTINATION share/nanogui/examples)\\
" \
        ${worksrcpath}/CMakeLists.txt
    reinplace "s|file.COPY resources|install(DIRECTORY resources|" \
        ${worksrcpath}/CMakeLists.txt

    if {$subport eq "nanogui"} {
        # Fix typo in reference to GLES3 header file
        reinplace "s|GLES3/gl2ext|GLES3/gl3ext|" \
            ${worksrcpath}/include/nanogui/opengl.h

        if {${os.major} < 16} {
            # Reference:
            # https://github.com/catchorg/Catch2/issues/1218#issuecomment-372105189
            reinplace "s|std::uncaught_exceptions() > 0|std::uncaught_exception()|" \
                ${worksrcpath}/src/widget.cpp
        }
    } elseif {$subport eq "nanogui-wjakob"} {
        reinplace -E {s/(NVG_BUILD)/\1;NVG_STB_IMAGE_IMPLEMENTATION/} \
            ${worksrcpath}/CMakeLists.txt

        # Add missing file nanovg/stb_image.h
        reinplace "/Merge GLAD/i\\
\\  ${prefix}/include/nanovg/stb_image.h\\
" \
            ${worksrcpath}/CMakeLists.txt
    }
}

configure.args-append   -DNANOGUI_BUILD_PYTHON=OFF

if {$subport eq "nanogui"} {
    configure.args-append   -DNANOGUI_BUILD_GLFW=OFF
} elseif {$subport eq "nanogui-wjakob"} {
    configure.args-append   -DNANOGUI_EIGEN_INCLUDE_DIR=${prefix}/include/eigen3
}

# BEGIN variants that are only applicable to the "new" NanoGUI
if {$subport eq "nanogui"} {

variant opengl conflicts gles2 gles3 metal \
    description {Build NanoGUI using OpenGL backend} \
{
    configure.args-append   -DNANOGUI_BACKEND="OpenGL"
}

variant gles2 conflicts opengl gles3 metal \
    description {Build NanoGUI using GLES 2 backend} \
{
    depends_lib-append      lib:libGLESv2:mesa
    configure.args-append   -DNANOGUI_BACKEND="GLES 2"
}

variant gles3 conflicts opengl gles2 metal \
    description {Build NanoGUI using GLES 3 backend} \
{
    depends_lib-append      lib:libGLESv3:mesa
    configure.args-append   -DNANOGUI_BACKEND="GLES 3"
}

# NanoGUI's Metal-related code requires at least Metal 2, which is
# only available starting in macOS 10.13 High Sierra and above.
if {${os.major} >= 17} {
    variant metal conflicts opengl gles2 gles3 \
        description {Build NanoGUI using Metal backend} \
    {
        depends_lib-append      port:metalnanovg
        configure.args-append   -DNANOGUI_BACKEND="Metal"
        use_xcode               yes
    }

    default_variants +metal
} else {
    default_variants +opengl
}

}
# END variants that are only applicable to the "new" NanoGUI

### The following code was adapted from the portfiles
### of ports such as openvdb and openimageio

set pythons_suffixes    {34 35 36 37 38}

set pythons_ports       {}
foreach s ${pythons_suffixes} {
    lappend pythons_ports python${s}
}

foreach s ${pythons_suffixes} {
    set p python${s}
    set v [string index ${s} 0].[string index ${s} 1]
    set i [lsearch -exact ${pythons_ports} ${p}]
    set c [lreplace ${pythons_ports} ${i} ${i}]
    variant ${p} conflicts {*}${c} \
        description "Build the Python ${v} plugin" {}
    if {[variant_isset ${p}]} {
        # Note: We basically need to import the value of ${v}, otherwise
        # all foreach iterations will end up with the same value of
        # ${v}! This appears to be related to how Tcl does scoping.
        set selected_v          ${v}
        depends_lib-append      port:${p} \
                                port:pybind11

        configure.args-replace  -DNANOGUI_BUILD_PYTHON=OFF \
                                -DNANOGUI_BUILD_PYTHON=ON
        configure.args-append   -DNANOGUI_PYBIND11_DIR=${prefix}

        post-patch {
            reinplace "/find_package.PythonLibsNew/i\\
\\  set(PythonLibsNew_FIND_VERSION ${selected_v})\\
" \
                ${worksrcpath}/CMakeLists.txt
        }
    }
}
