From b3572d65ec8fdd888d49b09e061f4cf704222c3e Mon Sep 17 00:00:00 2001 From: Joseph Goldstone Date: Fri, 18 Jul 2014 11:10:28 -0700 Subject: [PATCH 01/12] Rework NukeCtl plugin for greater efficiency and stabler (albeit less powerful) UI. --- AUTHORS | 15 +- CHANGELOG | 3 + CMakeLists.txt | 5 +- Nuke_CTL/CMakeLists.txt | 54 ++ Nuke_CTL/NukeCtl.cpp | 230 +++++ Nuke_CTL/NukeCtlChanArgMap.cpp | 156 ++++ Nuke_CTL/NukeCtlChanArgMap.h | 108 +++ Nuke_CTL/NukeCtlTransform.cpp | 252 ++++++ Nuke_CTL/NukeCtlTransform.h | 141 +++ Nuke_CTL/NukeCtlUtils.cpp | 147 ++++ Nuke_CTL/NukeCtlUtils.h | 87 ++ README.md | 1 + .../NukeCtl/NukeCtl.xcodeproj/project.pbxproj | 802 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/NukeCtl.xccheckout | 41 + Xcode/NukeCtl/NukeCtl/Base.lproj/MainMenu.xib | 467 ++++++++++ .../AppIcon.appiconset/Contents.json | 58 ++ Xcode/NukeCtl/NukeCtl/NCAppDelegate.h | 15 + Xcode/NukeCtl/NukeCtl/NCAppDelegate.m | 18 + Xcode/NukeCtl/NukeCtl/NukeCtl-Info.plist | 34 + Xcode/NukeCtl/NukeCtl/NukeCtl-Prefix.pch | 9 + Xcode/NukeCtl/NukeCtl/en.lproj/Credits.rtf | 29 + .../NukeCtl/en.lproj/InfoPlist.strings | 2 + Xcode/NukeCtl/NukeCtl/main.m | 14 + .../NukeCtl/NukeCtlLib/NukeCtlLib-Prefix.pch | 8 + .../NukeCtlLib/NukeCtlLibProj.xcconfig | 4 + .../NukeCtlLib/NukeCtlLibTarget.xcconfig | 10 + .../NukeCtlTests/NukeCtlTests-Info.plist | 22 + Xcode/NukeCtl/NukeCtlTests/NukeCtlTests.mm | 674 +++++++++++++++ .../NukeCtlTests/en.lproj/InfoPlist.strings | 2 + Xcode/NukeCtl/NukeCtlTests/rrt.ctl | 70 ++ Xcode/NukeCtl/NukeCtlTests/utilities-aces.ctl | 637 ++++++++++++++ .../NukeCtl/NukeCtlTests/utilities-color.ctl | 282 ++++++ Xcode/NukeCtl/NukeCtlTests/utilities.ctl | 141 +++ cmake/modules/FindNuke.cmake | 76 ++ lib/dpx/dpx_raw.hh | 2 +- unittest/ctlrender/test.sh | 8 +- 37 files changed, 4625 insertions(+), 6 deletions(-) create mode 100644 Nuke_CTL/CMakeLists.txt create mode 100644 Nuke_CTL/NukeCtl.cpp create mode 100644 Nuke_CTL/NukeCtlChanArgMap.cpp create mode 100644 Nuke_CTL/NukeCtlChanArgMap.h create mode 100644 Nuke_CTL/NukeCtlTransform.cpp create mode 100644 Nuke_CTL/NukeCtlTransform.h create mode 100644 Nuke_CTL/NukeCtlUtils.cpp create mode 100644 Nuke_CTL/NukeCtlUtils.h create mode 100644 Xcode/NukeCtl/NukeCtl.xcodeproj/project.pbxproj create mode 100644 Xcode/NukeCtl/NukeCtl.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Xcode/NukeCtl/NukeCtl.xcodeproj/project.xcworkspace/xcshareddata/NukeCtl.xccheckout create mode 100644 Xcode/NukeCtl/NukeCtl/Base.lproj/MainMenu.xib create mode 100644 Xcode/NukeCtl/NukeCtl/Images.xcassets/AppIcon.appiconset/Contents.json create mode 100644 Xcode/NukeCtl/NukeCtl/NCAppDelegate.h create mode 100644 Xcode/NukeCtl/NukeCtl/NCAppDelegate.m create mode 100644 Xcode/NukeCtl/NukeCtl/NukeCtl-Info.plist create mode 100644 Xcode/NukeCtl/NukeCtl/NukeCtl-Prefix.pch create mode 100644 Xcode/NukeCtl/NukeCtl/en.lproj/Credits.rtf create mode 100644 Xcode/NukeCtl/NukeCtl/en.lproj/InfoPlist.strings create mode 100644 Xcode/NukeCtl/NukeCtl/main.m create mode 100644 Xcode/NukeCtl/NukeCtlLib/NukeCtlLib-Prefix.pch create mode 100644 Xcode/NukeCtl/NukeCtlLib/NukeCtlLibProj.xcconfig create mode 100644 Xcode/NukeCtl/NukeCtlLib/NukeCtlLibTarget.xcconfig create mode 100644 Xcode/NukeCtl/NukeCtlTests/NukeCtlTests-Info.plist create mode 100644 Xcode/NukeCtl/NukeCtlTests/NukeCtlTests.mm create mode 100644 Xcode/NukeCtl/NukeCtlTests/en.lproj/InfoPlist.strings create mode 100644 Xcode/NukeCtl/NukeCtlTests/rrt.ctl create mode 100644 Xcode/NukeCtl/NukeCtlTests/utilities-aces.ctl create mode 100644 Xcode/NukeCtl/NukeCtlTests/utilities-color.ctl create mode 100644 Xcode/NukeCtl/NukeCtlTests/utilities.ctl create mode 100644 cmake/modules/FindNuke.cmake diff --git a/AUTHORS b/AUTHORS index d127a635..09e69364 100644 --- a/AUTHORS +++ b/AUTHORS @@ -48,4 +48,17 @@ ctlrender ------------- Bill Elswick - \ No newline at end of file + +Nuke_CTL + + Developers: + ----------- + + Jonathan Grahamm + + Contributors: + ------------- + + Ken Boreham + + Joseph Goldstone diff --git a/CHANGELOG b/CHANGELOG index e94eafcc..6f49335a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,6 @@ +Version 1.5.3: + * added Nuke_CTL + Version 1.5: * added OpenEXR_CTL, ctlrender * changed build system to Cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 01f622c0..02d93c1c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,7 @@ project( CTL ) set( CTL_MAJOR_VERSION 1 ) set( CTL_MINOR_VERSION 5 ) -set( CTL_PATCH_VERSION 0 ) +set( CTL_PATCH_VERSION 3 ) set( CTL_VERSION ${CTL_MAJOR_VERSION}.${CTL_MINOR_VERSION}.${CTL_PATCH_VERSION} ) ## Make install directories overrideable @@ -44,6 +44,8 @@ endforeach() option(ENABLE_SHARED "Enable Shared Libraries" ON) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -v -stdlib=libstdc++") + if ( ENABLE_SHARED ) set( DO_SHARED SHARED ) else() @@ -63,6 +65,7 @@ add_subdirectory(doc) add_subdirectory(lib) add_subdirectory(ctlrender) add_subdirectory(OpenEXR_CTL) +add_subdirectory(Nuke_CTL) add_subdirectory(unittest EXCLUDE_FROM_ALL) # Add all targets to the build-tree export set diff --git a/Nuke_CTL/CMakeLists.txt b/Nuke_CTL/CMakeLists.txt new file mode 100644 index 00000000..8ae85c6f --- /dev/null +++ b/Nuke_CTL/CMakeLists.txt @@ -0,0 +1,54 @@ + +# NB: We use a fake component to indicate that we want to avoid +# the IlmBase / OpenEXR libraries in the Nuke folder itself +find_package(Nuke QUIET COMPONENTS AvoidNukeIlmBase) +if(NUKE_FOUND) + message( STATUS "NUKE API Version: ${NUKE_API_VERSION}" ) + set( DEFAULT_PLUGIN_DIR "" ) + if( "$ENV{NUKE_PATH}" STREQUAL "" ) + set( DEFAULT_PLUGIN_DIR $ENV{HOME}/.nuke ) + else() + set( DEFAULT_PLUGIN_DIR $ENV{NUKE_PATH} ) + endif() + + # The line below doesn't make sense for Nuke 8.0 or greater. The version-specific plugin dir is now + # /Library/Application Support/Nuke/8.0/plugins/ [for Mac OS X] + # /usr/local/Nuke/8.0/plugins/ [for linux] + # C:\Program Files\Common Files\Nuke\8.0\plugins or C:\Program Files (x86)\Common Files\Nuke\8.0\plugins [for Windows] + # set( DEFAULT_PLUGIN_DIR ${DEFAULT_PLUGIN_DIR}/plugins/${NUKE_API_VERSION} ) + + set( INSTALL_NUKE_PLUGIN_DIR ${DEFAULT_PLUGIN_DIR} CACHE PATH "Location to install Nuke plugins" ) + + if( NOT DEFINED INSTALL_NUKE_PLUGIN_DIR ) + message(WARNING " No install path defined for nuke plugins + please define NUKE_PATH or INSTALL_NUKE_PLUGIN_DIR + skipping Nuke_CTL") + return() + else() + message(STATUS "Nuke plugins will be installed in ${INSTALL_NUKE_PLUGIN_DIR}") + message("Don't forget to add this path to your init.py file") + endif() + + include_directories("${CMAKE_CURRENT_SOURCE_DIR}" + "${NUKE_INCLUDE_DIRS}" + "${PROJECT_SOURCE_DIR}/lib/IlmCtl" + "${PROJECT_SOURCE_DIR}/lib/IlmCtlMath" + "${PROJECT_SOURCE_DIR}/lib/IlmCtlSimd" + "${PROJECT_SOURCE_DIR}/lib/IlmImfCtl" ) + + add_library(NukeCtl SHARED + NukeCtl.cpp + NukeCtlUtils.cpp + NukeCtlChanArgMap.cpp + NukeCtlTransform.cpp + ) + + target_link_libraries( NukeCtl IlmCtl IlmCtlMath IlmCtlSimd IlmThread Half Iex ) + target_link_libraries( NukeCtl ${IlmBase_LIBRARIES} ${IlmBase_LDFLAGS_OTHER} ) + link_directories( ${NUKE_LIBRARY_DIR} ) + target_link_libraries( NukeCtl ${NUKE_LIBRARIES} ) + + install( TARGETS NukeCtl DESTINATION ${INSTALL_NUKE_PLUGIN_DIR} ) +else() + message( WARNING "NUKE not found, check NUKE_INSTALL_PATH setting or NDKDIR env. var, NukeCTL plugin disabled" ) +endif() diff --git a/Nuke_CTL/NukeCtl.cpp b/Nuke_CTL/NukeCtl.cpp new file mode 100644 index 00000000..7c5a31ca --- /dev/null +++ b/Nuke_CTL/NukeCtl.cpp @@ -0,0 +1,230 @@ +/////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2014 Academy of Motion Picture Arts and Sciences +// ("A.M.P.A.S."). Portions contributed by others as indicated. +// All rights reserved. +// +// A worldwide, royalty-free, non-exclusive right to copy, modify, create +// derivatives, and use, in source and binary forms, is hereby granted, +// subject to acceptance of this license. Performance of any of the +// aforementioned acts indicates acceptance to be bound by the following +// terms and conditions: +// +// * Copies of source code, in whole or in part, must retain the +// above copyright notice, this list of conditions and the +// Disclaimer of Warranty. +// +// * Use in binary form must retain the above copyright notice, +// this list of conditions and the Disclaimer of Warranty in the +// documentation and/or other materials provided with the distribution. +// +// * Nothing in this license shall be deemed to grant any rights to +// trademarks, copyrights, patents, trade secrets or any other +// intellectual property of A.M.P.A.S. or any contributors, except +// as expressly stated herein. +// +// * Neither the name "A.M.P.A.S." nor the name of any other +// contributors to this software may be used to endorse or promote +// products derivative of or based on this software without express +// prior written permission of A.M.P.A.S. or the contributors, as +// appropriate. +// +// This license shall be construed pursuant to the laws of the State of +// California, and any disputes related thereto shall be subject to the +// jurisdiction of the courts therein. +// +// Disclaimer of Warranty: THIS SOFTWARE IS PROVIDED BY A.M.P.A.S. AND +// CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, +// BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT ARE DISCLAIMED. IN NO +// EVENT SHALL A.M.P.A.S., OR ANY CONTRIBUTORS OR DISTRIBUTORS, BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, RESITUTIONARY, +// OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +// THE POSSIBILITY OF SUCH DAMAGE. +// +// WITHOUT LIMITING THE GENERALITY OF THE FOREGOING, THE ACADEMY +// SPECIFICALLY DISCLAIMS ANY REPRESENTATIONS OR WARRANTIES WHATSOEVER +// RELATED TO PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS IN THE ACADEMY +// COLOR ENCODING SYSTEM, OR APPLICATIONS THEREOF, HELD BY PARTIES OTHER +// THAN A.M.P.A.S., WHETHER DISCLOSED OR UNDISCLOSED. +/////////////////////////////////////////////////////////////////////////// + +const char* const HELP = +"

Applies Ctl transforms onto an image.

"; + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-register" +#endif + +#include "DDImage/PixelIop.h" +#include "DDImage/Row.h" +#include "DDImage/Knobs.h" +#include "DDImage/NukeWrapper.h" + +#include "NukeCtlUtils.h" +#include "NukeCtlTransform.h" + +#include "Iex.h" + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +using namespace DD::Image; +using namespace Iex; +using namespace std; +using namespace NukeCtl; + +static const char* const CLASS = "NukeCtl"; + +class NukeCtlIop : public PixelIop { + +private: + DD::Image::Knob* modulePathEnabledKnob; + DD::Image::Knob* modulePathKnob; + DD::Image::Knob* readKnob; + bool modulePathEnabled; + const char *modulePath; + const char *ctlPath; + NukeCtl::Transform* transform; + int reloadCount; +public: + + NukeCtlIop(Node* node) : PixelIop(node), + modulePathEnabled(false), modulePath(""), ctlPath(""), + transform(NULL), reloadCount(0) { + } + + static const Iop::Description d; + void in_channels(int input_number, ChannelSet& channels) const { + channels = Mask_RGBA; + } + + void append(Hash& h) { + h.append(__DATE__); + h.append(__TIME__); + } + + void pixel_engine(const Row &in, int y, int x, int r, ChannelMask, Row &); + void knobs(Knob_Callback); + void load_transform(const char* const modulePath, const char* const ctlPath); + int knob_changed(Knob*); + const char* Class() const { return CLASS; } + const char* node_help() const { return HELP; } + void _validate(bool); +}; + +void NukeCtlIop::_validate(bool for_real) { + set_out_channels(Mask_RGBA); + PixelIop::_validate(for_real); +} + +// Called on each scanline +void NukeCtlIop::pixel_engine(const Row& in, int y, int x, int r, ChannelMask channels, Row& out) { + if (transform != NULL) + { + try { + transform->execute(in, x, r, out); + } + catch (const BaseExc& e) { + error("Could not execute CTL argument transform: %s", e.what()); + } + catch (const exception& e) { + error("Could not execute CTL argument transform: %s", e.what()); + } + catch (...) // Something wicked this way comes + { + error("Could not execute CTL argument transform"); + } + } + else + { + out.copy(in, channels, x, r); + } +} + +void NukeCtlIop::load_transform(const char* const modulePath, const char* const ctlPath) +{ + try + { + if (transform != NULL) + { + delete transform; + transform = NULL; + } + transform = new NukeCtl::Transform(modulePath, ctlPath); + } + catch (const Iex::BaseExc& e) + { + error((string("Error instantiating CTL transform: ") + e.what()).c_str()); + } + catch (const exception& e) + { + error((string("Error instantiating CTL transform: ") + e.what()).c_str()); + } + catch (...) + { + error("Error instantiating CTL transform"); + } +} + +void NukeCtlIop::knobs(Knob_Callback f) { + Newline(f, "Module Path"); + modulePathEnabledKnob = Bool_knob(f, &modulePathEnabled, "enable_module_path", ""); + modulePathKnob = File_knob(f, &modulePath, "module_path", ""); + ClearFlags(f, Knob::STARTLINE); + readKnob = File_knob(f, &ctlPath, "ctl_path", "CTL file Path"); + SetFlags(f, Knob::EARLY_STORE); + if (f.makeKnobs() && transform == NULL && strlen(ctlPath) > 0) + { + load_transform(modulePath, ctlPath); + } + Script_knob(f, "knob reload_count [expr [value reload_count] + 1]", "reload"); + Int_knob(f, &reloadCount, "reload_count", INVISIBLE); + SetFlags(f, Knob::DO_NOT_WRITE); + Divider(f); +} + +// Knob state changed +int NukeCtlIop::knob_changed(Knob *k) { + + if (k == &Knob::showPanel) { + knob("module_path")->enable(modulePathEnabled); + return 1; + } + + // if the box is checked, enable or disable the set module knob + if (k->is("enable_module_path")) { + knob("module_path")->enable(modulePathEnabled); + return 1; + } + + // if the module path is changed, make sure it is valid + if (k->is("module_path")) { + if (strlen(ctlPath) > 0) + { + load_transform(modulePath, ctlPath); + } + return 1; + } + + if (k->is("ctl_path") || k->is("reload")) { + if (strlen(ctlPath) > 0) + { + load_transform(modulePath, ctlPath); + } + return 1; + } + return Iop::knob_changed(k); +} + +static Iop* build(Node* node) { + return (new NukeWrapper(new NukeCtlIop(node))); +} + +const Iop::Description NukeCtlIop::d(CLASS, "Color/NukeCtl", build); + diff --git a/Nuke_CTL/NukeCtlChanArgMap.cpp b/Nuke_CTL/NukeCtlChanArgMap.cpp new file mode 100644 index 00000000..fc478f5f --- /dev/null +++ b/Nuke_CTL/NukeCtlChanArgMap.cpp @@ -0,0 +1,156 @@ +/////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2014 Academy of Motion Picture Arts and Sciences +// ("A.M.P.A.S."). Portions contributed by others as indicated. +// All rights reserved. +// +// A worldwide, royalty-free, non-exclusive right to copy, modify, create +// derivatives, and use, in source and binary forms, is hereby granted, +// subject to acceptance of this license. Performance of any of the +// aforementioned acts indicates acceptance to be bound by the following +// terms and conditions: +// +// * Copies of source code, in whole or in part, must retain the +// above copyright notice, this list of conditions and the +// Disclaimer of Warranty. +// +// * Use in binary form must retain the above copyright notice, +// this list of conditions and the Disclaimer of Warranty in the +// documentation and/or other materials provided with the distribution. +// +// * Nothing in this license shall be deemed to grant any rights to +// trademarks, copyrights, patents, trade secrets or any other +// intellectual property of A.M.P.A.S. or any contributors, except +// as expressly stated herein. +// +// * Neither the name "A.M.P.A.S." nor the name of any other +// contributors to this software may be used to endorse or promote +// products derivative of or based on this software without express +// prior written permission of A.M.P.A.S. or the contributors, as +// appropriate. +// +// This license shall be construed pursuant to the laws of the State of +// California, and any disputes related thereto shall be subject to the +// jurisdiction of the courts therein. +// +// Disclaimer of Warranty: THIS SOFTWARE IS PROVIDED BY A.M.P.A.S. AND +// CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, +// BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT ARE DISCLAIMED. IN NO +// EVENT SHALL A.M.P.A.S., OR ANY CONTRIBUTORS OR DISTRIBUTORS, BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, RESITUTIONARY, +// OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +// THE POSSIBILITY OF SUCH DAMAGE. +// +// WITHOUT LIMITING THE GENERALITY OF THE FOREGOING, THE ACADEMY +// SPECIFICALLY DISCLAIMS ANY REPRESENTATIONS OR WARRANTIES WHATSOEVER +// RELATED TO PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS IN THE ACADEMY +// COLOR ENCODING SYSTEM, OR APPLICATIONS THEREOF, HELD BY PARTIES OTHER +// THAN A.M.P.A.S., WHETHER DISCLOSED OR UNDISCLOSED. +/////////////////////////////////////////////////////////////////////////// + + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-register" +#endif + +#include "NukeCtlChanArgMap.h" +#include "Iex.h" + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +using namespace Ctl; +using namespace DD::Image; +using namespace std; +using namespace Iex; + +namespace NukeCtl +{ + ChanArgMap::ChanArgMap(FunctionCallPtr fn) + { + argNameToChanName_["rIn"] = "r"; + argNameToChanName_["gIn"] = "g"; + argNameToChanName_["bIn"] = "b"; + argNameToChanName_["aIn"] = "a"; + argNameToChanName_["rOut"] = "r"; + argNameToChanName_["gOut"] = "g"; + argNameToChanName_["bOut"] = "b"; + argNameToChanName_["aOut"] = "a"; + chanToInArg_.clear(); + outArgToChan_.clear(); + for (size_t i = 0, n = fn->numInputArgs(); i < n; ++i) + { + FunctionArgPtr arg = fn->inputArg(i); + if (! arg) + { + THROW(LogicExc, "CTL function claims " << n << " arguments but cannot get info for arg " << i); + } + if (! arg->isVarying()) + { + THROW(LogicExc, "CTL function parameter " << arg->name() << " is not a varying parameter"); + } + map::const_iterator j = argNameToChanName_.find(arg->name()); + if (j == argNameToChanName_.end()) + { + THROW(LogicExc, "CTL function parameter " << arg->name() << " has no mapping to a Nuke channel"); + } + Channel c = findChannel(j->second.c_str()); + // TODO: Find out what findChannel returns if you ask for something it doesn't have, and throw an appropriate error. + chanToInArg_[c] = arg; + } + for (size_t i = 0, n = fn->numOutputArgs(); i < n; ++i) + { + FunctionArgPtr arg = fn->outputArg(i); + if (! arg) + { + THROW(LogicExc, "CTL function claims " << n << " output arguments but cannot get info for output arg " << i); + } + if (! arg->isVarying()) + { + THROW(LogicExc, "CTL function output argument " << arg->name() << " is not a varying parameter"); + } + map::const_iterator j = argNameToChanName_.find(arg->name()); + if (j == argNameToChanName_.end()) + { + THROW(LogicExc, "Could not find expected Nuke channel name for CTL " + "function output arg name '" << arg->name() << "'"); + } + outArgToChan_[arg] = findChannel(j->second.c_str()); + } + } + + void + ChanArgMap::copyInputRowToArgData(const DD::Image::Row &in, int x0, int x1) + { + for (map::const_iterator i = chanToInArg_.begin(); i != chanToInArg_.end(); ++i) + { + Channel channel = i->first; + FunctionArgPtr arg = i->second; + size_t src_stride = sizeof(float); + size_t dst_offset = 0; + size_t count = x1 - x0; + arg->set(in[channel] + x0, src_stride, dst_offset, count); + } + } + + void + ChanArgMap::copyArgDataToOutputRow(int x0, int x1, DD::Image::Row &out) + { + for (map::const_iterator i = outArgToChan_.begin(); i != outArgToChan_.end(); ++i) + { + FunctionArgPtr arg = i->first; + Channel channel = i->second; + size_t dst_stride = sizeof(float); + size_t src_offset = 0; + size_t count = x1 - x0; + arg->get(out.writable(channel) + x0, dst_stride, src_offset, count); + } + } + +} diff --git a/Nuke_CTL/NukeCtlChanArgMap.h b/Nuke_CTL/NukeCtlChanArgMap.h new file mode 100644 index 00000000..2e6f3cd6 --- /dev/null +++ b/Nuke_CTL/NukeCtlChanArgMap.h @@ -0,0 +1,108 @@ +/////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2014 Academy of Motion Picture Arts and Sciences +// ("A.M.P.A.S."). Portions contributed by others as indicated. +// All rights reserved. +// +// A worldwide, royalty-free, non-exclusive right to copy, modify, create +// derivatives, and use, in source and binary forms, is hereby granted, +// subject to acceptance of this license. Performance of any of the +// aforementioned acts indicates acceptance to be bound by the following +// terms and conditions: +// +// * Copies of source code, in whole or in part, must retain the +// above copyright notice, this list of conditions and the +// Disclaimer of Warranty. +// +// * Use in binary form must retain the above copyright notice, +// this list of conditions and the Disclaimer of Warranty in the +// documentation and/or other materials provided with the distribution. +// +// * Nothing in this license shall be deemed to grant any rights to +// trademarks, copyrights, patents, trade secrets or any other +// intellectual property of A.M.P.A.S. or any contributors, except +// as expressly stated herein. +// +// * Neither the name "A.M.P.A.S." nor the name of any other +// contributors to this software may be used to endorse or promote +// products derivative of or based on this software without express +// prior written permission of A.M.P.A.S. or the contributors, as +// appropriate. +// +// This license shall be construed pursuant to the laws of the State of +// California, and any disputes related thereto shall be subject to the +// jurisdiction of the courts therein. +// +// Disclaimer of Warranty: THIS SOFTWARE IS PROVIDED BY A.M.P.A.S. AND +// CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, +// BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT ARE DISCLAIMED. IN NO +// EVENT SHALL A.M.P.A.S., OR ANY CONTRIBUTORS OR DISTRIBUTORS, BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, RESITUTIONARY, +// OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +// THE POSSIBILITY OF SUCH DAMAGE. +// +// WITHOUT LIMITING THE GENERALITY OF THE FOREGOING, THE ACADEMY +// SPECIFICALLY DISCLAIMS ANY REPRESENTATIONS OR WARRANTIES WHATSOEVER +// RELATED TO PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS IN THE ACADEMY +// COLOR ENCODING SYSTEM, OR APPLICATIONS THEREOF, HELD BY PARTIES OTHER +// THAN A.M.P.A.S., WHETHER DISCLOSED OR UNDISCLOSED. +/////////////////////////////////////////////////////////////////////////// + +#ifndef __NukeCtl__NukeCtlChanArgMap__ +#define __NukeCtl__NukeCtlChanArgMap__ + +#include "DDImage/Channel.h" +#include "DDImage/Row.h" +#include "CtlFunctionCall.h" +#include "CtlRcPtr.h" +#include "CtlStdType.h" + +#include +#include + +namespace NukeCtl +{ + + class ChanArgMap + { + public: + ChanArgMap(Ctl::FunctionCallPtr fn); + + void + copyInputRowToArgData(const DD::Image::Row &in, int x0, int x1); + + void + copyArgDataToOutputRow(int x0, int x1, DD::Image::Row &out); + + private: + // Not implemented, and this guarantees the compiler will not improvise one for us. + ChanArgMap(const ChanArgMap &c); + + // Not implemented, and this guarantees the compiler will not improvise one for us. + ChanArgMap& + operator=(const ChanArgMap &rhs); + + std::map argNameToChanName_; + + typedef std::map ChannelToFunctionArgPtrMap; + + // Without this being specified as a third arg to std::map below, outArgToChan_ will never have more than one member. + struct FunctionArgPtrLess: + public std::binary_function { + bool operator() (const Ctl::FunctionArgPtr pa1, const Ctl::FunctionArgPtr pa2) const + { + return pa1->name() < pa2->name(); + } + }; + typedef std::map FunctionArgPtrToChannelMap; + + ChannelToFunctionArgPtrMap chanToInArg_; + FunctionArgPtrToChannelMap outArgToChan_; + }; +} + +#endif /* defined(__NukeCtl__NukeCtlChanArgMap__) */ diff --git a/Nuke_CTL/NukeCtlTransform.cpp b/Nuke_CTL/NukeCtlTransform.cpp new file mode 100644 index 00000000..ea156292 --- /dev/null +++ b/Nuke_CTL/NukeCtlTransform.cpp @@ -0,0 +1,252 @@ +/////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2014 Academy of Motion Picture Arts and Sciences +// ("A.M.P.A.S."). Portions contributed by others as indicated. +// All rights reserved. +// +// A worldwide, royalty-free, non-exclusive right to copy, modify, create +// derivatives, and use, in source and binary forms, is hereby granted, +// subject to acceptance of this license. Performance of any of the +// aforementioned acts indicates acceptance to be bound by the following +// terms and conditions: +// +// * Copies of source code, in whole or in part, must retain the +// above copyright notice, this list of conditions and the +// Disclaimer of Warranty. +// +// * Use in binary form must retain the above copyright notice, +// this list of conditions and the Disclaimer of Warranty in the +// documentation and/or other materials provided with the distribution. +// +// * Nothing in this license shall be deemed to grant any rights to +// trademarks, copyrights, patents, trade secrets or any other +// intellectual property of A.M.P.A.S. or any contributors, except +// as expressly stated herein. +// +// * Neither the name "A.M.P.A.S." nor the name of any other +// contributors to this software may be used to endorse or promote +// products derivative of or based on this software without express +// prior written permission of A.M.P.A.S. or the contributors, as +// appropriate. +// +// This license shall be construed pursuant to the laws of the State of +// California, and any disputes related thereto shall be subject to the +// jurisdiction of the courts therein. +// +// Disclaimer of Warranty: THIS SOFTWARE IS PROVIDED BY A.M.P.A.S. AND +// CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, +// BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT ARE DISCLAIMED. IN NO +// EVENT SHALL A.M.P.A.S., OR ANY CONTRIBUTORS OR DISTRIBUTORS, BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, RESITUTIONARY, +// OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +// THE POSSIBILITY OF SUCH DAMAGE. +// +// WITHOUT LIMITING THE GENERALITY OF THE FOREGOING, THE ACADEMY +// SPECIFICALLY DISCLAIMS ANY REPRESENTATIONS OR WARRANTIES WHATSOEVER +// RELATED TO PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS IN THE ACADEMY +// COLOR ENCODING SYSTEM, OR APPLICATIONS THEREOF, HELD BY PARTIES OTHER +// THAN A.M.P.A.S., WHETHER DISCLOSED OR UNDISCLOSED. +/////////////////////////////////////////////////////////////////////////// + + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-register" +#endif + +#include "NukeCtlChanArgMap.h" +#include "NukeCtlTransform.h" +#include "NukeCtlUtils.h" + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#include "Iex.h" + +#include + +using namespace DD::Image; +using namespace NukeCtl; +using namespace Iex; +using namespace Ctl; +using namespace std; + +namespace NukeCtl +{ + const vector + Transform::parseModulePath(const string &modulePath) + { + vector modulePathComponents; + try { + modulePathComponents = split(modulePath,':'); + } catch (const ArgExc &e) { + THROW(ArgExc, "Cannot parse module path '" << modulePath << "': " << e.what()); + } + return modulePathComponents; + } + + void + Transform::verifyModuleName(const string &moduleName) + { + // components of path need not exist, they just need to be syntactically legal. At least, that's as far as Ctl::Interpreter goes. + // path should be legal, as far as the interpreter allows; that means no /, :. ; or \ characters. + if (moduleName.find_first_of("/:;\\") != string::npos) + { + THROW(ArgExc, "Module path component `" << moduleName << "' contains invalid characters (one of /, :, ; or \\"); + } + } + + bool + Transform::matchesCTLCannotFindFunctionExceptionText(const exception& e, const string &functionName) + { + ostringstream s; + s << "Cannot find CTL function " << functionName << "."; + string pattern(s.str()); + return pattern == e.what(); + } + + bool + Transform::matchesCTLCannotFindModuleExceptionText(const exception& e) + { + string exceptionText(e.what()); + string::size_type i = exceptionText.find_first_of("Cannot find CTL module \""); + string::size_type j = exceptionText.find_last_of("\""); + return j != string::npos && i < j; + } + + const string + Transform::missingModuleFromException(const exception& e) + { + if (! matchesCTLCannotFindModuleExceptionText(e)) + { + THROW(LogicExc, "Attempt to extract missing module name from an exception not concerned with missing modules"); + } + string exceptionText(e.what()); + string::size_type i = exceptionText.find_first_not_of("Cannot find CTL module \""); + string::size_type j = exceptionText.find("\"."); + return exceptionText.substr(i, j-i); + } + + const string + Transform::topLevelFunctionNameInTransform() + { + FunctionCallPtr functionCall; + try { + functionCall = interpreter_->newFunctionCall("main"); + } + catch (const ArgExc &e) + { + // There is no CTL exception specific to this problem, so we use secret knowledge (i.e. we peek at the source) + // to see exactly what the CTL interpreter would do if the module cannot be found. And what it does is throw + // ArgExc with the what() string having the form "Cannot find CTL function ." + if (matchesCTLCannotFindFunctionExceptionText(e, "main")) + { + string moduleName(modulenameFromFilename(filenameFromPathname(transformPath_))); + try { + functionCall = interpreter_->newFunctionCall(moduleName); + return moduleName; + } catch (const exception &e) { + if (matchesCTLCannotFindFunctionExceptionText(e, moduleName)) + { + THROW(ArgExc, "CTL file at '" << transformPath_ << "' has neither a main function nor one named '" << moduleName << "'"); + } else if (matchesCTLCannotFindModuleExceptionText(e)) + { + string missingModule(missingModuleFromException(e)); + THROW(ArgExc, "Module '" << missingModule << "' not in the module path; referenced by " << moduleName << " function in CTL file '" << transformPath_ << "'"); + } + else + { + THROW(ArgExc, "Error searching for function 'main' and function '" << moduleName << "' in CTL file '" << transformPath_ << "': " << e.what()); + } + } + } + else if (matchesCTLCannotFindModuleExceptionText(e)) + { + string missingModule(missingModuleFromException(e)); + THROW(ArgExc, "Module '" << missingModule << "' not in the module path; referenced by main function in CTL file '" << transformPath_ << "'"); + } + else + { + THROW(ArgExc, "Error searching for function 'main' in CTL file '" << transformPath_ << "': " << e.what()); + } + } + return "main"; + } + + + Transform::Transform(const string &modulePath, + const string &transformPath) + : modulePathComponents_(parseModulePath(modulePath)), + interpreter_(RcPtr(new RcSimdInterpreter)), + transformPath_(transformPath) + { + // be diligent about not having bad parameters or state crash all of Nuke. + try { + interpreter_->setUserModulePath(modulePathComponents_, modulePathComponents_.size() > 0); + } + catch (const BaseExc& e) + { + THROW(ArgExc, "error setting CTL module path `" << modulePath << "': " << e.what()); + } + try { + interpreter_->loadFile(transformPath_); + try { + functionName_ = topLevelFunctionNameInTransform(); + } + catch (const BaseExc& e) + { + THROW(ArgExc, "error finding top-level function name in transform at path 1" << transformPath_ << "': " << e.what()); + } + } catch (const BaseExc& e) { + THROW(ArgExc, "error loading CTL transform from path `" << transformPath_ << "': " << e.what()); + } + } + + void + Transform::execute(const Row &in, int l, int r, Row &out) + { + // Although it doubtless looks tempting to create the function call and argument map + // just once, at transform ctor time, and avoid the expense on each call to this + // execute() function...you can't. As per page 17 of the CTL manual (24/07/2007 edition) + // function call objects are not thread-safe. Interpreters (or at least the reference + // SIMD interpreter) ARE thread-safe, so it's cool to stash an interpreter as CtlTransform + // member variable and share it...but stay away from FunctionCallPtr member variables in + // CtlTransform objects, and since they point into such objects, from ArgMap member + // variables as well. + + try { + FunctionCallPtr fn(interpreter_->newFunctionCall(functionName_)); + if (fn->returnValue()->type().cast().refcount() == 0) + { + THROW(ArgExc, "top-level function of CTL file at '" << transformPath_ + << "' returns other than void type"); + } + try { + ChanArgMap argMap(fn); + for (int x = l; x < r;) + { + int maxSamples = static_cast(interpreter_->maxSamples()); + int chunkSize = min(r - x, maxSamples); + argMap.copyInputRowToArgData(in, x, x + chunkSize); + fn->callFunction(chunkSize); + argMap.copyArgDataToOutputRow(x, x + chunkSize, out); + x += chunkSize; + } + } + catch (const BaseExc& e) + { + THROW(LogicExc, "could not construct argument map for CTL transform loaded from path `" << transformPath_ << ": " << e.what()); + } + } + catch (const BaseExc& e) + { + THROW(ArgExc, "error finding top-level function in CTL transform loaded from path `" << transformPath_ << ": " << e.what()); + } + } + +} diff --git a/Nuke_CTL/NukeCtlTransform.h b/Nuke_CTL/NukeCtlTransform.h new file mode 100644 index 00000000..511bc8e0 --- /dev/null +++ b/Nuke_CTL/NukeCtlTransform.h @@ -0,0 +1,141 @@ +/////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2014 Academy of Motion Picture Arts and Sciences +// ("A.M.P.A.S."). Portions contributed by others as indicated. +// All rights reserved. +// +// A worldwide, royalty-free, non-exclusive right to copy, modify, create +// derivatives, and use, in source and binary forms, is hereby granted, +// subject to acceptance of this license. Performance of any of the +// aforementioned acts indicates acceptance to be bound by the following +// terms and conditions: +// +// * Copies of source code, in whole or in part, must retain the +// above copyright notice, this list of conditions and the +// Disclaimer of Warranty. +// +// * Use in binary form must retain the above copyright notice, +// this list of conditions and the Disclaimer of Warranty in the +// documentation and/or other materials provided with the distribution. +// +// * Nothing in this license shall be deemed to grant any rights to +// trademarks, copyrights, patents, trade secrets or any other +// intellectual property of A.M.P.A.S. or any contributors, except +// as expressly stated herein. +// +// * Neither the name "A.M.P.A.S." nor the name of any other +// contributors to this software may be used to endorse or promote +// products derivative of or based on this software without express +// prior written permission of A.M.P.A.S. or the contributors, as +// appropriate. +// +// This license shall be construed pursuant to the laws of the State of +// California, and any disputes related thereto shall be subject to the +// jurisdiction of the courts therein. +// +// Disclaimer of Warranty: THIS SOFTWARE IS PROVIDED BY A.M.P.A.S. AND +// CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, +// BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT ARE DISCLAIMED. IN NO +// EVENT SHALL A.M.P.A.S., OR ANY CONTRIBUTORS OR DISTRIBUTORS, BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, RESITUTIONARY, +// OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +// THE POSSIBILITY OF SUCH DAMAGE. +// +// WITHOUT LIMITING THE GENERALITY OF THE FOREGOING, THE ACADEMY +// SPECIFICALLY DISCLAIMS ANY REPRESENTATIONS OR WARRANTIES WHATSOEVER +// RELATED TO PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS IN THE ACADEMY +// COLOR ENCODING SYSTEM, OR APPLICATIONS THEREOF, HELD BY PARTIES OTHER +// THAN A.M.P.A.S., WHETHER DISCLOSED OR UNDISCLOSED. +/////////////////////////////////////////////////////////////////////////// + + +#ifndef __IIF__NukeCtlTransform__ +#define __IIF__NukeCtlTransform__ + +#include "DDImage/Channel.h" +#include "DDImage/Row.h" + +#include +#include +#include + +#include +#include + +namespace NukeCtl +{ + class TransformFriend; + + class RcSimdInterpreter : public Ctl::SimdInterpreter, public Ctl::RcObject + { + }; + + typedef Ctl::RcPtr SimdInterpreterPtr; + + class Transform { + friend class TransformFriend; + public: + Transform(const std::string &modulePath, + const std::string &transformPath); + + void + execute(const DD::Image::Row &in, int l, int r, DD::Image::Row &out); + private: + static + const std::vector + parseModulePath(const std::string &modulePath); + + static + void + verifyModuleName(const std::string &moduleName); + + static + bool + matchesCTLCannotFindFunctionExceptionText(const std::exception& e, const std::string &functionName); + + static + bool + matchesCTLCannotFindModuleExceptionText(const std::exception& e); + + static + const std::string + missingModuleFromException(const std::exception& e); + + const std::string + topLevelFunctionNameInTransform(); + + void + loadArgMap(); + + std::vector modulePathComponents_; + + // Keeping this in the heap makes it possible to share it between the Transform + // and TransformFriend (which gets used in unit testing). + SimdInterpreterPtr interpreter_; + + // On the other hand, you do NOT want to try anything comparable for sharing + // functional calls with Ctl::FunctionCallPtr. That sort of thing will work in + // unit testing, which is single-threaded, but Nuke has multiple threads sharing + // from a single Nuke Op. + + // transformPath_ is not used at runtime but is handy for forensics + std::string transformPath_; + std::string functionName_; + + // Make this private, and don't implement them - that way we know that the compiler + // isn't doing anything odd. + Transform(const Transform &transform); + + // Make this private, and don't implement them - that way we know that the compiler + // isn't doing anything odd. + Transform& + operator=(const Transform &rhs); + + }; +} + +#endif /* defined(__IIF__NukeCtlTransform__) */ diff --git a/Nuke_CTL/NukeCtlUtils.cpp b/Nuke_CTL/NukeCtlUtils.cpp new file mode 100644 index 00000000..706b28d9 --- /dev/null +++ b/Nuke_CTL/NukeCtlUtils.cpp @@ -0,0 +1,147 @@ +/////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2014 Academy of Motion Picture Arts and Sciences +// ("A.M.P.A.S."). Portions contributed by others as indicated. +// All rights reserved. +// +// A worldwide, royalty-free, non-exclusive right to copy, modify, create +// derivatives, and use, in source and binary forms, is hereby granted, +// subject to acceptance of this license. Performance of any of the +// aforementioned acts indicates acceptance to be bound by the following +// terms and conditions: +// +// * Copies of source code, in whole or in part, must retain the +// above copyright notice, this list of conditions and the +// Disclaimer of Warranty. +// +// * Use in binary form must retain the above copyright notice, +// this list of conditions and the Disclaimer of Warranty in the +// documentation and/or other materials provided with the distribution. +// +// * Nothing in this license shall be deemed to grant any rights to +// trademarks, copyrights, patents, trade secrets or any other +// intellectual property of A.M.P.A.S. or any contributors, except +// as expressly stated herein. +// +// * Neither the name "A.M.P.A.S." nor the name of any other +// contributors to this software may be used to endorse or promote +// products derivative of or based on this software without express +// prior written permission of A.M.P.A.S. or the contributors, as +// appropriate. +// +// This license shall be construed pursuant to the laws of the State of +// California, and any disputes related thereto shall be subject to the +// jurisdiction of the courts therein. +// +// Disclaimer of Warranty: THIS SOFTWARE IS PROVIDED BY A.M.P.A.S. AND +// CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, +// BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT ARE DISCLAIMED. IN NO +// EVENT SHALL A.M.P.A.S., OR ANY CONTRIBUTORS OR DISTRIBUTORS, BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, RESITUTIONARY, +// OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +// THE POSSIBILITY OF SUCH DAMAGE. +// +// WITHOUT LIMITING THE GENERALITY OF THE FOREGOING, THE ACADEMY +// SPECIFICALLY DISCLAIMS ANY REPRESENTATIONS OR WARRANTIES WHATSOEVER +// RELATED TO PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS IN THE ACADEMY +// COLOR ENCODING SYSTEM, OR APPLICATIONS THEREOF, HELD BY PARTIES OTHER +// THAN A.M.P.A.S., WHETHER DISCLOSED OR UNDISCLOSED. +/////////////////////////////////////////////////////////////////////////// + +#include "NukeCtlUtils.h" + +#include +using namespace std; + +#include "Iex.h" +using namespace Iex; + +namespace NukeCtl { + + // These two are from http://stackoverflow.com/questions/236129/how-to-split-a-string-in-c + vector& + split(const string &s, char delim, vector &elems) + { + stringstream ss(s); + string item; + while (getline(ss, item, delim)) { + elems.push_back(item); + } + // special-case (not in the StackOverflow version) + // For some reason I can't find this C++11 predicate from + // if (all_of(elems.begin(), elems.end(), [](string s){ return s.size() == 0; })) + // Probably all for the best; I can't assume someone else compiling this would have C++11. + bool all_empty = true; + for (vector::const_iterator i = elems.begin(); i < elems.end(); ++i) + { + if (i->size() != 0) + { + all_empty = false; + break; + } + } + if (all_empty) + { + elems.clear(); + } + return elems; + } + + vector + split(const string &s, char delim) + { + vector elems; + split(s, delim, elems); + return elems; + } + + const string + trimLeft(const string &s, const string &debris) + { + // Beats me why passing an empty string as the first arg causes an exception, but the comparable trimRight case does not + return s.size() == 0 ? s : s.substr(s.find_first_not_of(debris), string::npos); + } + + const string + trimRight(const string &s, const string &debris) + { + return s.substr(0, s.find_last_not_of(debris) + 1); + } + + string + filenameFromPathname(const string &path) + { + string strippedPath(trimRight(trimLeft(path, "\t "), "\t ")); + // special-case the root + if (strippedPath == "/") + { + return strippedPath; + } + // directories are components too + strippedPath = trimRight(strippedPath, "/"); + vector pathComponents(split(path, '/')); + if (pathComponents.size() == 0) + { + THROW(ArgExc, "Expected at least one component of path '" << path << "', but saw none"); + } + return pathComponents[pathComponents.size() -1]; + } + + string + modulenameFromFilename(const string &filename) + { + // blank filename is an error + string strippedFilename(trimRight(trimLeft(filename, "\t "), "\t ")); + if (strippedFilename == "") + { + THROW(ArgExc, "Expected non-blank filename"); + } + vector filenameComponents(split(strippedFilename, '.')); + return filenameComponents[0]; + } + +} \ No newline at end of file diff --git a/Nuke_CTL/NukeCtlUtils.h b/Nuke_CTL/NukeCtlUtils.h new file mode 100644 index 00000000..f70ddcd2 --- /dev/null +++ b/Nuke_CTL/NukeCtlUtils.h @@ -0,0 +1,87 @@ +/////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2014 Academy of Motion Picture Arts and Sciences +// ("A.M.P.A.S."). Portions contributed by others as indicated. +// All rights reserved. +// +// A worldwide, royalty-free, non-exclusive right to copy, modify, create +// derivatives, and use, in source and binary forms, is hereby granted, +// subject to acceptance of this license. Performance of any of the +// aforementioned acts indicates acceptance to be bound by the following +// terms and conditions: +// +// * Copies of source code, in whole or in part, must retain the +// above copyright notice, this list of conditions and the +// Disclaimer of Warranty. +// +// * Use in binary form must retain the above copyright notice, +// this list of conditions and the Disclaimer of Warranty in the +// documentation and/or other materials provided with the distribution. +// +// * Nothing in this license shall be deemed to grant any rights to +// trademarks, copyrights, patents, trade secrets or any other +// intellectual property of A.M.P.A.S. or any contributors, except +// as expressly stated herein. +// +// * Neither the name "A.M.P.A.S." nor the name of any other +// contributors to this software may be used to endorse or promote +// products derivative of or based on this software without express +// prior written permission of A.M.P.A.S. or the contributors, as +// appropriate. +// +// This license shall be construed pursuant to the laws of the State of +// California, and any disputes related thereto shall be subject to the +// jurisdiction of the courts therein. +// +// Disclaimer of Warranty: THIS SOFTWARE IS PROVIDED BY A.M.P.A.S. AND +// CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, +// BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT ARE DISCLAIMED. IN NO +// EVENT SHALL A.M.P.A.S., OR ANY CONTRIBUTORS OR DISTRIBUTORS, BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, RESITUTIONARY, +// OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +// THE POSSIBILITY OF SUCH DAMAGE. +// +// WITHOUT LIMITING THE GENERALITY OF THE FOREGOING, THE ACADEMY +// SPECIFICALLY DISCLAIMS ANY REPRESENTATIONS OR WARRANTIES WHATSOEVER +// RELATED TO PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS IN THE ACADEMY +// COLOR ENCODING SYSTEM, OR APPLICATIONS THEREOF, HELD BY PARTIES OTHER +// THAN A.M.P.A.S., WHETHER DISCLOSED OR UNDISCLOSED. +/////////////////////////////////////////////////////////////////////////// + +#ifndef __IIF__NukeCtlUtils__ +#define __IIF__NukeCtlUtils__ + +#include +#include + +namespace NukeCtl { + + // These two are from http://stackoverflow.com/questions/236129/how-to-split-a-string-in-c + std::vector& + split(const std::string &s, + char delim, + std::vector &elems); + + std::vector + split(const std::string &s, char delim); + + const std::string + trimLeft(const std::string &s, const std::string &debris); + + const std::string + trimRight(const std::string &s, const std::string &debris); + + std::string + filenameFromPathname(const std::string &path); + + std::string + modulenameFromFilename(const std::string &filename); + +} + +#endif /* defined(__IIF__NukeCtlUtils__) */ + diff --git a/README.md b/README.md index 767141f7..e0c6f718 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,7 @@ The CTL source code contains the following: * `ctlrender/` - an application that allows for application of CTL transforms to an image using one or more CTL scripts, potentially converting the file format in the process. +* `Nuke_CTL/` - a Nuke plugin allowing the use of CTL transforms in a Nuke node. * `config/` - CMake configuration files * `unittest/` - unit test files diff --git a/Xcode/NukeCtl/NukeCtl.xcodeproj/project.pbxproj b/Xcode/NukeCtl/NukeCtl.xcodeproj/project.pbxproj new file mode 100644 index 00000000..36eafb04 --- /dev/null +++ b/Xcode/NukeCtl/NukeCtl.xcodeproj/project.pbxproj @@ -0,0 +1,802 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 590A90891947D54700F23DE4 /* NukeCtlUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 594B4E3A18134DF8003C263C /* NukeCtlUtils.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 594B4DEE18134B54003C263C /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 594B4DED18134B54003C263C /* Cocoa.framework */; }; + 594B4DF818134B54003C263C /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 594B4DF618134B54003C263C /* InfoPlist.strings */; }; + 594B4DFA18134B54003C263C /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 594B4DF918134B54003C263C /* main.m */; }; + 594B4DFE18134B54003C263C /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 594B4DFC18134B54003C263C /* Credits.rtf */; }; + 594B4E0118134B54003C263C /* NCAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 594B4E0018134B54003C263C /* NCAppDelegate.m */; }; + 594B4E0418134B54003C263C /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 594B4E0218134B54003C263C /* MainMenu.xib */; }; + 594B4E0618134B54003C263C /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 594B4E0518134B54003C263C /* Images.xcassets */; }; + 594B4E0D18134B54003C263C /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 594B4E0C18134B54003C263C /* XCTest.framework */; }; + 594B4E0E18134B54003C263C /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 594B4DED18134B54003C263C /* Cocoa.framework */; }; + 594B4E1618134B54003C263C /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 594B4E1418134B54003C263C /* InfoPlist.strings */; }; + 594B4E3318134D7A003C263C /* NukeCtlTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 594B4E3218134D7A003C263C /* NukeCtlTests.mm */; }; + 594B4E3F18134DF8003C263C /* NukeCtl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 594B4E3418134DF8003C263C /* NukeCtl.cpp */; }; + 594B4E4018134DF8003C263C /* NukeCtlChanArgMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 594B4E3518134DF8003C263C /* NukeCtlChanArgMap.cpp */; }; + 594B4E4218134DF8003C263C /* NukeCtlTransform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 594B4E3718134DF8003C263C /* NukeCtlTransform.cpp */; }; + 594B4E4418134DF8003C263C /* NukeCtlUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 594B4E3918134DF8003C263C /* NukeCtlUtils.cpp */; }; + 594B4E4E18134E6B003C263C /* libDDImage.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 594B4E4A18134E6B003C263C /* libDDImage.dylib */; }; + 594B4E4F18134E6B003C263C /* libGLEW.1.5.8.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 594B4E4B18134E6B003C263C /* libGLEW.1.5.8.dylib */; }; + 594B4E5118134E6B003C263C /* libtcmalloc_minimal.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 594B4E4D18134E6B003C263C /* libtcmalloc_minimal.dylib */; }; + 594B4E5718134F86003C263C /* libHalf.11.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 594B4E5218134F86003C263C /* libHalf.11.dylib */; }; + 594B4E6118134FF5003C263C /* libIlmCtlSimd.1.5.3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 594B4E5F18134FF5003C263C /* libIlmCtlSimd.1.5.3.dylib */; }; + 594B4E661813519E003C263C /* libIex-2_1.11.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 594B4E621813519E003C263C /* libIex-2_1.11.dylib */; }; + 594B4E671813519E003C263C /* libIexMath-2_1.11.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 594B4E631813519E003C263C /* libIexMath-2_1.11.dylib */; }; + 594B4E681813519E003C263C /* libIlmThread-2_1.11.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 594B4E641813519E003C263C /* libIlmThread-2_1.11.dylib */; }; + 594B4E691813519E003C263C /* libIlmCtl.1.5.3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 594B4E651813519E003C263C /* libIlmCtl.1.5.3.dylib */; }; + 594B4E6A181351EF003C263C /* libIex-2_1.11.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 594B4E621813519E003C263C /* libIex-2_1.11.dylib */; }; + 594B4E6B181351EF003C263C /* libIexMath-2_1.11.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 594B4E631813519E003C263C /* libIexMath-2_1.11.dylib */; }; + 594B4E6C181351EF003C263C /* libIlmThread-2_1.11.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 594B4E641813519E003C263C /* libIlmThread-2_1.11.dylib */; }; + 594B4E6D181351EF003C263C /* libIlmCtl.1.5.3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 594B4E651813519E003C263C /* libIlmCtl.1.5.3.dylib */; }; + 594B4E6F181351F0003C263C /* libIlmCtlSimd.1.5.3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 594B4E5F18134FF5003C263C /* libIlmCtlSimd.1.5.3.dylib */; }; + 594B4E71181351F0003C263C /* libHalf.11.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 594B4E5218134F86003C263C /* libHalf.11.dylib */; }; + 594B4E72181351F0003C263C /* libDDImage.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 594B4E4A18134E6B003C263C /* libDDImage.dylib */; }; + 594B4E74181351F0003C263C /* libGLEW.1.5.8.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 594B4E4B18134E6B003C263C /* libGLEW.1.5.8.dylib */; }; + 594B4E75181351F0003C263C /* libtcmalloc_minimal.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 594B4E4D18134E6B003C263C /* libtcmalloc_minimal.dylib */; }; + 594B4E7618135224003C263C /* NukeCtl.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 594B4E2518134BAF003C263C /* NukeCtl.dylib */; }; + 594E50D61852A4DA00FCE67C /* rrt.ctl in Resources */ = {isa = PBXBuildFile; fileRef = 594E50D51852A4DA00FCE67C /* rrt.ctl */; }; + 594E50DA1852A52E00FCE67C /* utilities-aces.ctl in Resources */ = {isa = PBXBuildFile; fileRef = 594E50D71852A52E00FCE67C /* utilities-aces.ctl */; }; + 594E50DB1852A52E00FCE67C /* utilities-color.ctl in Resources */ = {isa = PBXBuildFile; fileRef = 594E50D81852A52E00FCE67C /* utilities-color.ctl */; }; + 594E50DC1852A52E00FCE67C /* utilities.ctl in Resources */ = {isa = PBXBuildFile; fileRef = 594E50D91852A52E00FCE67C /* utilities.ctl */; }; + 594E50DE1852A59800FCE67C /* utilities-aces.ctl in CopyFiles */ = {isa = PBXBuildFile; fileRef = 594E50D71852A52E00FCE67C /* utilities-aces.ctl */; }; + 594E50DF1852A59800FCE67C /* utilities-color.ctl in CopyFiles */ = {isa = PBXBuildFile; fileRef = 594E50D81852A52E00FCE67C /* utilities-color.ctl */; }; + 594E50E01852A59800FCE67C /* utilities.ctl in CopyFiles */ = {isa = PBXBuildFile; fileRef = 594E50D91852A52E00FCE67C /* utilities.ctl */; }; + 594E50E11852A59800FCE67C /* rrt.ctl in CopyFiles */ = {isa = PBXBuildFile; fileRef = 594E50D51852A4DA00FCE67C /* rrt.ctl */; }; + 594E50E31852A98A00FCE67C /* NukeCtl.dylib in CopyFiles */ = {isa = PBXBuildFile; fileRef = 594B4E2518134BAF003C263C /* NukeCtl.dylib */; }; + 599F77FB185101C10051A510 /* NukeCtl.dylib in Resources */ = {isa = PBXBuildFile; fileRef = 594B4E2518134BAF003C263C /* NukeCtl.dylib */; }; + 599F77FD185101F00051A510 /* NukeCtl.dylib in CopyFiles */ = {isa = PBXBuildFile; fileRef = 594B4E2518134BAF003C263C /* NukeCtl.dylib */; }; + 599F77FE185102870051A510 /* NukeCtl.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 594B4E2518134BAF003C263C /* NukeCtl.dylib */; }; + 59BDB0821813556A00F32C47 /* libDDImage.dylib in CopyFiles */ = {isa = PBXBuildFile; fileRef = 594B4E4A18134E6B003C263C /* libDDImage.dylib */; }; + 59BDB0831813556D00F32C47 /* libGLEW.1.5.8.dylib in CopyFiles */ = {isa = PBXBuildFile; fileRef = 594B4E4B18134E6B003C263C /* libGLEW.1.5.8.dylib */; }; + 59BDB0851813557300F32C47 /* libtcmalloc_minimal.dylib in CopyFiles */ = {isa = PBXBuildFile; fileRef = 594B4E4D18134E6B003C263C /* libtcmalloc_minimal.dylib */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 590A908A1947DEF100F23DE4 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 594B4DE218134B54003C263C /* Project object */; + proxyType = 1; + remoteGlobalIDString = 594B4E2418134BAF003C263C; + remoteInfo = NukeCtlLib; + }; + 590A908C1947DF7700F23DE4 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 594B4DE218134B54003C263C /* Project object */; + proxyType = 1; + remoteGlobalIDString = 594B4E2418134BAF003C263C; + remoteInfo = NukeCtlLib; + }; + 594B4E0F18134B54003C263C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 594B4DE218134B54003C263C /* Project object */; + proxyType = 1; + remoteGlobalIDString = 594B4DE918134B54003C263C; + remoteInfo = NukeCtl; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 594E50DD1852A57D00FCE67C /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /tmp; + dstSubfolderSpec = 0; + files = ( + 594E50DE1852A59800FCE67C /* utilities-aces.ctl in CopyFiles */, + 594E50DF1852A59800FCE67C /* utilities-color.ctl in CopyFiles */, + 594E50E01852A59800FCE67C /* utilities.ctl in CopyFiles */, + 594E50E11852A59800FCE67C /* rrt.ctl in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 594E50E21852A97500FCE67C /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /Users/jgoldstone/.nuke; + dstSubfolderSpec = 0; + files = ( + 594E50E31852A98A00FCE67C /* NukeCtl.dylib in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 599F77FC185101DC0051A510 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /Users/jgoldstone/.nuke; + dstSubfolderSpec = 0; + files = ( + 599F77FD185101F00051A510 /* NukeCtl.dylib in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 59BDB0811813555F00F32C47 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 16; + files = ( + 59BDB0821813556A00F32C47 /* libDDImage.dylib in CopyFiles */, + 59BDB0831813556D00F32C47 /* libGLEW.1.5.8.dylib in CopyFiles */, + 59BDB0851813557300F32C47 /* libtcmalloc_minimal.dylib in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 594B4DEA18134B54003C263C /* NukeCtl.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = NukeCtl.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 594B4DED18134B54003C263C /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; + 594B4DF018134B54003C263C /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; + 594B4DF118134B54003C263C /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; + 594B4DF218134B54003C263C /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + 594B4DF518134B54003C263C /* NukeCtl-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "NukeCtl-Info.plist"; sourceTree = ""; }; + 594B4DF718134B54003C263C /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; + 594B4DF918134B54003C263C /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 594B4DFB18134B54003C263C /* NukeCtl-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NukeCtl-Prefix.pch"; sourceTree = ""; }; + 594B4DFD18134B54003C263C /* en */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = en; path = en.lproj/Credits.rtf; sourceTree = ""; }; + 594B4DFF18134B54003C263C /* NCAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NCAppDelegate.h; sourceTree = ""; }; + 594B4E0018134B54003C263C /* NCAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NCAppDelegate.m; sourceTree = ""; }; + 594B4E0318134B54003C263C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; + 594B4E0518134B54003C263C /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 594B4E0B18134B54003C263C /* NukeCtlTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NukeCtlTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 594B4E0C18134B54003C263C /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; + 594B4E1318134B54003C263C /* NukeCtlTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "NukeCtlTests-Info.plist"; sourceTree = ""; }; + 594B4E1518134B54003C263C /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; + 594B4E2518134BAF003C263C /* NukeCtl.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = NukeCtl.dylib; sourceTree = BUILT_PRODUCTS_DIR; }; + 594B4E2818134BAF003C263C /* NukeCtlLib-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NukeCtlLib-Prefix.pch"; sourceTree = ""; }; + 594B4E2918134BAF003C263C /* NukeCtlLibProj.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = NukeCtlLibProj.xcconfig; sourceTree = ""; }; + 594B4E2A18134BAF003C263C /* NukeCtlLibTarget.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = NukeCtlLibTarget.xcconfig; sourceTree = ""; }; + 594B4E3218134D7A003C263C /* NukeCtlTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = NukeCtlTests.mm; sourceTree = ""; }; + 594B4E3418134DF8003C263C /* NukeCtl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NukeCtl.cpp; path = ../../../Nuke_CTL/NukeCtl.cpp; sourceTree = ""; }; + 594B4E3518134DF8003C263C /* NukeCtlChanArgMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NukeCtlChanArgMap.cpp; path = ../../../Nuke_CTL/NukeCtlChanArgMap.cpp; sourceTree = ""; }; + 594B4E3618134DF8003C263C /* NukeCtlChanArgMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NukeCtlChanArgMap.h; path = ../../../Nuke_CTL/NukeCtlChanArgMap.h; sourceTree = ""; }; + 594B4E3718134DF8003C263C /* NukeCtlTransform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NukeCtlTransform.cpp; path = ../../../Nuke_CTL/NukeCtlTransform.cpp; sourceTree = ""; }; + 594B4E3818134DF8003C263C /* NukeCtlTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NukeCtlTransform.h; path = ../../../Nuke_CTL/NukeCtlTransform.h; sourceTree = ""; }; + 594B4E3918134DF8003C263C /* NukeCtlUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NukeCtlUtils.cpp; path = ../../../Nuke_CTL/NukeCtlUtils.cpp; sourceTree = ""; }; + 594B4E3A18134DF8003C263C /* NukeCtlUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NukeCtlUtils.h; path = ../../../Nuke_CTL/NukeCtlUtils.h; sourceTree = ""; }; + 594B4E4A18134E6B003C263C /* libDDImage.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libDDImage.dylib; path = ../../../../../../../Applications/Nuke8.0v5/Nuke8.0v5.app/Contents/MacOS/libDDImage.dylib; sourceTree = ""; }; + 594B4E4B18134E6B003C263C /* libGLEW.1.5.8.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libGLEW.1.5.8.dylib; path = ../../../../../../../Applications/Nuke8.0v5/Nuke8.0v5.app/Contents/MacOS/libGLEW.1.5.8.dylib; sourceTree = ""; }; + 594B4E4D18134E6B003C263C /* libtcmalloc_minimal.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libtcmalloc_minimal.dylib; path = ../../../../../../../Applications/Nuke8.0v5/Nuke8.0v5.app/Contents/MacOS/libtcmalloc_minimal.dylib; sourceTree = ""; }; + 594B4E5218134F86003C263C /* libHalf.11.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libHalf.11.dylib; path = ../../../../../../../usr/local/Cellar/ilmbase/2.1.0/lib/libHalf.11.dylib; sourceTree = ""; }; + 594B4E5F18134FF5003C263C /* libIlmCtlSimd.1.5.3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libIlmCtlSimd.1.5.3.dylib; path = ../../../../../../../usr/local/lib/libIlmCtlSimd.1.5.3.dylib; sourceTree = ""; }; + 594B4E621813519E003C263C /* libIex-2_1.11.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = "libIex-2_1.11.dylib"; path = "../../../../../../../usr/local/Cellar/ilmbase/2.1.0/lib/libIex-2_1.11.dylib"; sourceTree = ""; }; + 594B4E631813519E003C263C /* libIexMath-2_1.11.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = "libIexMath-2_1.11.dylib"; path = "../../../../../../../usr/local/Cellar/ilmbase/2.1.0/lib/libIexMath-2_1.11.dylib"; sourceTree = ""; }; + 594B4E641813519E003C263C /* libIlmThread-2_1.11.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = "libIlmThread-2_1.11.dylib"; path = "../../../../../../../usr/local/Cellar/ilmbase/2.1.0/lib/libIlmThread-2_1.11.dylib"; sourceTree = ""; }; + 594B4E651813519E003C263C /* libIlmCtl.1.5.3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libIlmCtl.1.5.3.dylib; path = ../../../../../../../usr/local/lib/libIlmCtl.1.5.3.dylib; sourceTree = ""; }; + 594E50D51852A4DA00FCE67C /* rrt.ctl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = rrt.ctl; sourceTree = ""; }; + 594E50D71852A52E00FCE67C /* utilities-aces.ctl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "utilities-aces.ctl"; sourceTree = ""; }; + 594E50D81852A52E00FCE67C /* utilities-color.ctl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "utilities-color.ctl"; sourceTree = ""; }; + 594E50D91852A52E00FCE67C /* utilities.ctl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = utilities.ctl; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 594B4DE718134B54003C263C /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 599F77FE185102870051A510 /* NukeCtl.dylib in Frameworks */, + 594B4DEE18134B54003C263C /* Cocoa.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 594B4E0818134B54003C263C /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 594B4E6D181351EF003C263C /* libIlmCtl.1.5.3.dylib in Frameworks */, + 594B4E0E18134B54003C263C /* Cocoa.framework in Frameworks */, + 594B4E6C181351EF003C263C /* libIlmThread-2_1.11.dylib in Frameworks */, + 594B4E74181351F0003C263C /* libGLEW.1.5.8.dylib in Frameworks */, + 594B4E6B181351EF003C263C /* libIexMath-2_1.11.dylib in Frameworks */, + 594B4E75181351F0003C263C /* libtcmalloc_minimal.dylib in Frameworks */, + 594B4E6F181351F0003C263C /* libIlmCtlSimd.1.5.3.dylib in Frameworks */, + 594B4E7618135224003C263C /* NukeCtl.dylib in Frameworks */, + 594B4E0D18134B54003C263C /* XCTest.framework in Frameworks */, + 594B4E71181351F0003C263C /* libHalf.11.dylib in Frameworks */, + 594B4E72181351F0003C263C /* libDDImage.dylib in Frameworks */, + 594B4E6A181351EF003C263C /* libIex-2_1.11.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 594B4E2218134BAF003C263C /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 594B4E681813519E003C263C /* libIlmThread-2_1.11.dylib in Frameworks */, + 594B4E4E18134E6B003C263C /* libDDImage.dylib in Frameworks */, + 594B4E4F18134E6B003C263C /* libGLEW.1.5.8.dylib in Frameworks */, + 594B4E671813519E003C263C /* libIexMath-2_1.11.dylib in Frameworks */, + 594B4E5718134F86003C263C /* libHalf.11.dylib in Frameworks */, + 594B4E691813519E003C263C /* libIlmCtl.1.5.3.dylib in Frameworks */, + 594B4E661813519E003C263C /* libIex-2_1.11.dylib in Frameworks */, + 594B4E6118134FF5003C263C /* libIlmCtlSimd.1.5.3.dylib in Frameworks */, + 594B4E5118134E6B003C263C /* libtcmalloc_minimal.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 594B4DE118134B54003C263C = { + isa = PBXGroup; + children = ( + 594B4DF318134B54003C263C /* NukeCtl */, + 594B4E1118134B54003C263C /* NukeCtlTests */, + 594B4E2618134BAF003C263C /* NukeCtlLib */, + 594B4DEC18134B54003C263C /* Frameworks */, + 594B4DEB18134B54003C263C /* Products */, + ); + sourceTree = ""; + }; + 594B4DEB18134B54003C263C /* Products */ = { + isa = PBXGroup; + children = ( + 594B4DEA18134B54003C263C /* NukeCtl.app */, + 594B4E0B18134B54003C263C /* NukeCtlTests.xctest */, + 594B4E2518134BAF003C263C /* NukeCtl.dylib */, + ); + name = Products; + sourceTree = ""; + }; + 594B4DEC18134B54003C263C /* Frameworks */ = { + isa = PBXGroup; + children = ( + 594B4E621813519E003C263C /* libIex-2_1.11.dylib */, + 594B4E631813519E003C263C /* libIexMath-2_1.11.dylib */, + 594B4E641813519E003C263C /* libIlmThread-2_1.11.dylib */, + 594B4E651813519E003C263C /* libIlmCtl.1.5.3.dylib */, + 594B4E5F18134FF5003C263C /* libIlmCtlSimd.1.5.3.dylib */, + 594B4E5218134F86003C263C /* libHalf.11.dylib */, + 594B4E4A18134E6B003C263C /* libDDImage.dylib */, + 594B4E4B18134E6B003C263C /* libGLEW.1.5.8.dylib */, + 594B4E4D18134E6B003C263C /* libtcmalloc_minimal.dylib */, + 594B4DED18134B54003C263C /* Cocoa.framework */, + 594B4E0C18134B54003C263C /* XCTest.framework */, + 594B4DEF18134B54003C263C /* Other Frameworks */, + ); + name = Frameworks; + sourceTree = ""; + }; + 594B4DEF18134B54003C263C /* Other Frameworks */ = { + isa = PBXGroup; + children = ( + 594B4DF018134B54003C263C /* AppKit.framework */, + 594B4DF118134B54003C263C /* CoreData.framework */, + 594B4DF218134B54003C263C /* Foundation.framework */, + ); + name = "Other Frameworks"; + sourceTree = ""; + }; + 594B4DF318134B54003C263C /* NukeCtl */ = { + isa = PBXGroup; + children = ( + 594B4DFF18134B54003C263C /* NCAppDelegate.h */, + 594B4E0018134B54003C263C /* NCAppDelegate.m */, + 594B4E0218134B54003C263C /* MainMenu.xib */, + 594B4E0518134B54003C263C /* Images.xcassets */, + 594B4DF418134B54003C263C /* Supporting Files */, + ); + path = NukeCtl; + sourceTree = ""; + }; + 594B4DF418134B54003C263C /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 594B4DF518134B54003C263C /* NukeCtl-Info.plist */, + 594B4DF618134B54003C263C /* InfoPlist.strings */, + 594B4DF918134B54003C263C /* main.m */, + 594B4DFB18134B54003C263C /* NukeCtl-Prefix.pch */, + 594B4DFC18134B54003C263C /* Credits.rtf */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 594B4E1118134B54003C263C /* NukeCtlTests */ = { + isa = PBXGroup; + children = ( + 594B4E3218134D7A003C263C /* NukeCtlTests.mm */, + 594B4E1218134B54003C263C /* Supporting Files */, + ); + path = NukeCtlTests; + sourceTree = ""; + }; + 594B4E1218134B54003C263C /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 594E50D71852A52E00FCE67C /* utilities-aces.ctl */, + 594E50D81852A52E00FCE67C /* utilities-color.ctl */, + 594E50D91852A52E00FCE67C /* utilities.ctl */, + 594E50D51852A4DA00FCE67C /* rrt.ctl */, + 594B4E1318134B54003C263C /* NukeCtlTests-Info.plist */, + 594B4E1418134B54003C263C /* InfoPlist.strings */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 594B4E2618134BAF003C263C /* NukeCtlLib */ = { + isa = PBXGroup; + children = ( + 594B4E3518134DF8003C263C /* NukeCtlChanArgMap.cpp */, + 594B4E3618134DF8003C263C /* NukeCtlChanArgMap.h */, + 594B4E3718134DF8003C263C /* NukeCtlTransform.cpp */, + 594B4E3818134DF8003C263C /* NukeCtlTransform.h */, + 594B4E3918134DF8003C263C /* NukeCtlUtils.cpp */, + 594B4E3A18134DF8003C263C /* NukeCtlUtils.h */, + 594B4E3418134DF8003C263C /* NukeCtl.cpp */, + 594B4E2918134BAF003C263C /* NukeCtlLibProj.xcconfig */, + 594B4E2A18134BAF003C263C /* NukeCtlLibTarget.xcconfig */, + 594B4E2718134BAF003C263C /* Supporting Files */, + ); + path = NukeCtlLib; + sourceTree = ""; + }; + 594B4E2718134BAF003C263C /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 594B4E2818134BAF003C263C /* NukeCtlLib-Prefix.pch */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 594B4E2318134BAF003C263C /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 590A90891947D54700F23DE4 /* NukeCtlUtils.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 594B4DE918134B54003C263C /* NukeCtl */ = { + isa = PBXNativeTarget; + buildConfigurationList = 594B4E1B18134B54003C263C /* Build configuration list for PBXNativeTarget "NukeCtl" */; + buildPhases = ( + 594B4DE618134B54003C263C /* Sources */, + 594B4DE718134B54003C263C /* Frameworks */, + 594B4DE818134B54003C263C /* Resources */, + 594E50E21852A97500FCE67C /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + 590A908B1947DEF100F23DE4 /* PBXTargetDependency */, + ); + name = NukeCtl; + productName = NukeCtl; + productReference = 594B4DEA18134B54003C263C /* NukeCtl.app */; + productType = "com.apple.product-type.application"; + }; + 594B4E0A18134B54003C263C /* NukeCtlTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 594B4E1E18134B54003C263C /* Build configuration list for PBXNativeTarget "NukeCtlTests" */; + buildPhases = ( + 594B4E0718134B54003C263C /* Sources */, + 594B4E0818134B54003C263C /* Frameworks */, + 594B4E0918134B54003C263C /* Resources */, + 59BDB0811813555F00F32C47 /* CopyFiles */, + 594E50DD1852A57D00FCE67C /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + 590A908D1947DF7700F23DE4 /* PBXTargetDependency */, + 594B4E1018134B54003C263C /* PBXTargetDependency */, + ); + name = NukeCtlTests; + productName = NukeCtlTests; + productReference = 594B4E0B18134B54003C263C /* NukeCtlTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 594B4E2418134BAF003C263C /* NukeCtlLib */ = { + isa = PBXNativeTarget; + buildConfigurationList = 594B4E2F18134BAF003C263C /* Build configuration list for PBXNativeTarget "NukeCtlLib" */; + buildPhases = ( + 594B4E2118134BAF003C263C /* Sources */, + 594B4E2218134BAF003C263C /* Frameworks */, + 594B4E2318134BAF003C263C /* Headers */, + 599F77FC185101DC0051A510 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = NukeCtlLib; + productName = NukeCtlLib; + productReference = 594B4E2518134BAF003C263C /* NukeCtl.dylib */; + productType = "com.apple.product-type.library.dynamic"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 594B4DE218134B54003C263C /* Project object */ = { + isa = PBXProject; + attributes = { + CLASSPREFIX = NC; + LastUpgradeCheck = 0500; + ORGANIZATIONNAME = "ARRI Inc."; + TargetAttributes = { + 594B4DE918134B54003C263C = { + DevelopmentTeam = N735C88KRN; + }; + 594B4E0A18134B54003C263C = { + TestTargetID = 594B4DE918134B54003C263C; + }; + }; + }; + buildConfigurationList = 594B4DE518134B54003C263C /* Build configuration list for PBXProject "NukeCtl" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 594B4DE118134B54003C263C; + productRefGroup = 594B4DEB18134B54003C263C /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 594B4DE918134B54003C263C /* NukeCtl */, + 594B4E0A18134B54003C263C /* NukeCtlTests */, + 594B4E2418134BAF003C263C /* NukeCtlLib */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 594B4DE818134B54003C263C /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 594B4DF818134B54003C263C /* InfoPlist.strings in Resources */, + 594B4E0618134B54003C263C /* Images.xcassets in Resources */, + 599F77FB185101C10051A510 /* NukeCtl.dylib in Resources */, + 594B4DFE18134B54003C263C /* Credits.rtf in Resources */, + 594B4E0418134B54003C263C /* MainMenu.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 594B4E0918134B54003C263C /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 594E50DB1852A52E00FCE67C /* utilities-color.ctl in Resources */, + 594E50D61852A4DA00FCE67C /* rrt.ctl in Resources */, + 594E50DC1852A52E00FCE67C /* utilities.ctl in Resources */, + 594B4E1618134B54003C263C /* InfoPlist.strings in Resources */, + 594E50DA1852A52E00FCE67C /* utilities-aces.ctl in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 594B4DE618134B54003C263C /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 594B4DFA18134B54003C263C /* main.m in Sources */, + 594B4E0118134B54003C263C /* NCAppDelegate.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 594B4E0718134B54003C263C /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 594B4E3318134D7A003C263C /* NukeCtlTests.mm in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 594B4E2118134BAF003C263C /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 594B4E4418134DF8003C263C /* NukeCtlUtils.cpp in Sources */, + 594B4E4018134DF8003C263C /* NukeCtlChanArgMap.cpp in Sources */, + 594B4E3F18134DF8003C263C /* NukeCtl.cpp in Sources */, + 594B4E4218134DF8003C263C /* NukeCtlTransform.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 590A908B1947DEF100F23DE4 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 594B4E2418134BAF003C263C /* NukeCtlLib */; + targetProxy = 590A908A1947DEF100F23DE4 /* PBXContainerItemProxy */; + }; + 590A908D1947DF7700F23DE4 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 594B4E2418134BAF003C263C /* NukeCtlLib */; + targetProxy = 590A908C1947DF7700F23DE4 /* PBXContainerItemProxy */; + }; + 594B4E1018134B54003C263C /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 594B4DE918134B54003C263C /* NukeCtl */; + targetProxy = 594B4E0F18134B54003C263C /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 594B4DF618134B54003C263C /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + 594B4DF718134B54003C263C /* en */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; + 594B4DFC18134B54003C263C /* Credits.rtf */ = { + isa = PBXVariantGroup; + children = ( + 594B4DFD18134B54003C263C /* en */, + ); + name = Credits.rtf; + sourceTree = ""; + }; + 594B4E0218134B54003C263C /* MainMenu.xib */ = { + isa = PBXVariantGroup; + children = ( + 594B4E0318134B54003C263C /* Base */, + ); + name = MainMenu.xib; + sourceTree = ""; + }; + 594B4E1418134B54003C263C /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + 594B4E1518134B54003C263C /* en */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 594B4E1918134B54003C263C /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; + CLANG_CXX_LIBRARY = "libstdc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, + /usr/local/foundry/include, + /usr/local/include/CTL, + /usr/local/include/OpenEXR, + ); + LIBRARY_SEARCH_PATHS = ( + /usr/local/foundry/lib, + /usr/local/lib, + ); + MACOSX_DEPLOYMENT_TARGET = ""; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + }; + name = Debug; + }; + 594B4E1A18134B54003C263C /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; + CLANG_CXX_LIBRARY = "libstdc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, + /usr/local/foundry/include, + /usr/local/include/CTL, + /usr/local/include/OpenEXR, + ); + LIBRARY_SEARCH_PATHS = ( + /usr/local/foundry/lib, + /usr/local/lib, + ); + MACOSX_DEPLOYMENT_TARGET = ""; + SDKROOT = macosx; + }; + name = Release; + }; + 594B4E1C18134B54003C263C /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "Mac Developer"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Mac Developer"; + COMBINE_HIDPI_IMAGES = YES; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "NukeCtl/NukeCtl-Prefix.pch"; + INFOPLIST_FILE = "NukeCtl/NukeCtl-Info.plist"; + LIBRARY_SEARCH_PATHS = "$(inherited)"; + MACOSX_DEPLOYMENT_TARGET = ""; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE = ""; + WRAPPER_EXTENSION = app; + }; + name = Debug; + }; + 594B4E1D18134B54003C263C /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "Mac Developer"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Mac Developer"; + COMBINE_HIDPI_IMAGES = YES; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "NukeCtl/NukeCtl-Prefix.pch"; + INFOPLIST_FILE = "NukeCtl/NukeCtl-Info.plist"; + LIBRARY_SEARCH_PATHS = "$(inherited)"; + MACOSX_DEPLOYMENT_TARGET = ""; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE = ""; + WRAPPER_EXTENSION = app; + }; + name = Release; + }; + 594B4E1F18134B54003C263C /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/NukeCtl.app/Contents/MacOS/NukeCtl"; + COMBINE_HIDPI_IMAGES = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(DEVELOPER_FRAMEWORKS_DIR)", + "$(inherited)", + ); + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "NukeCtl/NukeCtl-Prefix.pch"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = "NukeCtlTests/NukeCtlTests-Info.plist"; + LIBRARY_SEARCH_PATHS = "$(inherited)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_HOST = "$(BUNDLE_LOADER)"; + WRAPPER_EXTENSION = xctest; + }; + name = Debug; + }; + 594B4E2018134B54003C263C /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/NukeCtl.app/Contents/MacOS/NukeCtl"; + COMBINE_HIDPI_IMAGES = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(DEVELOPER_FRAMEWORKS_DIR)", + "$(inherited)", + ); + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "NukeCtl/NukeCtl-Prefix.pch"; + INFOPLIST_FILE = "NukeCtlTests/NukeCtlTests-Info.plist"; + LIBRARY_SEARCH_PATHS = "$(inherited)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_HOST = "$(BUNDLE_LOADER)"; + WRAPPER_EXTENSION = xctest; + }; + name = Release; + }; + 594B4E3018134BAF003C263C /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + LIBRARY_SEARCH_PATHS = "$(inherited)"; + PRODUCT_NAME = NukeCtl; + }; + name = Debug; + }; + 594B4E3118134BAF003C263C /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + LIBRARY_SEARCH_PATHS = "$(inherited)"; + PRODUCT_NAME = NukeCtl; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 594B4DE518134B54003C263C /* Build configuration list for PBXProject "NukeCtl" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 594B4E1918134B54003C263C /* Debug */, + 594B4E1A18134B54003C263C /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 594B4E1B18134B54003C263C /* Build configuration list for PBXNativeTarget "NukeCtl" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 594B4E1C18134B54003C263C /* Debug */, + 594B4E1D18134B54003C263C /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 594B4E1E18134B54003C263C /* Build configuration list for PBXNativeTarget "NukeCtlTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 594B4E1F18134B54003C263C /* Debug */, + 594B4E2018134B54003C263C /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 594B4E2F18134BAF003C263C /* Build configuration list for PBXNativeTarget "NukeCtlLib" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 594B4E3018134BAF003C263C /* Debug */, + 594B4E3118134BAF003C263C /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 594B4DE218134B54003C263C /* Project object */; +} diff --git a/Xcode/NukeCtl/NukeCtl.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Xcode/NukeCtl/NukeCtl.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..02f7fe60 --- /dev/null +++ b/Xcode/NukeCtl/NukeCtl.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Xcode/NukeCtl/NukeCtl.xcodeproj/project.xcworkspace/xcshareddata/NukeCtl.xccheckout b/Xcode/NukeCtl/NukeCtl.xcodeproj/project.xcworkspace/xcshareddata/NukeCtl.xccheckout new file mode 100644 index 00000000..b779b9c3 --- /dev/null +++ b/Xcode/NukeCtl/NukeCtl.xcodeproj/project.xcworkspace/xcshareddata/NukeCtl.xccheckout @@ -0,0 +1,41 @@ + + + + + IDESourceControlProjectFavoriteDictionaryKey + + IDESourceControlProjectIdentifier + D30E5D6A-2A05-4E42-82BF-66AD10BE245C + IDESourceControlProjectName + NukeCtl + IDESourceControlProjectOriginsDictionary + + 771C07CB-E0C1-47F3-A77C-1CA17592CEE8 + https://github.com/JGoldstone/CTL.git + + IDESourceControlProjectPath + Xcode/NukeCtl/NukeCtl.xcodeproj/project.xcworkspace + IDESourceControlProjectRelativeInstallPathDictionary + + 771C07CB-E0C1-47F3-A77C-1CA17592CEE8 + ../../../.. + + IDESourceControlProjectURL + https://github.com/JGoldstone/CTL.git + IDESourceControlProjectVersion + 110 + IDESourceControlProjectWCCIdentifier + 771C07CB-E0C1-47F3-A77C-1CA17592CEE8 + IDESourceControlProjectWCConfigurations + + + IDESourceControlRepositoryExtensionIdentifierKey + public.vcs.git + IDESourceControlWCCIdentifierKey + 771C07CB-E0C1-47F3-A77C-1CA17592CEE8 + IDESourceControlWCCName + CTL + + + + diff --git a/Xcode/NukeCtl/NukeCtl/Base.lproj/MainMenu.xib b/Xcode/NukeCtl/NukeCtl/Base.lproj/MainMenu.xib new file mode 100644 index 00000000..fa8114ad --- /dev/null +++ b/Xcode/NukeCtl/NukeCtl/Base.lproj/MainMenu.xib @@ -0,0 +1,467 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Default + + + + Left to Right + + + + Right to Left + + + + + + + + Default + + + + Left to Right + + + + Right to Left + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Xcode/NukeCtl/NukeCtl/Images.xcassets/AppIcon.appiconset/Contents.json b/Xcode/NukeCtl/NukeCtl/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..2db2b1c7 --- /dev/null +++ b/Xcode/NukeCtl/NukeCtl/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,58 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Xcode/NukeCtl/NukeCtl/NCAppDelegate.h b/Xcode/NukeCtl/NukeCtl/NCAppDelegate.h new file mode 100644 index 00000000..b59fb7a6 --- /dev/null +++ b/Xcode/NukeCtl/NukeCtl/NCAppDelegate.h @@ -0,0 +1,15 @@ +// +// NCAppDelegate.h +// NukeCtl +// +// Created by Joseph Goldstone on 10/19/13. +// Copyright (c) 2013 ARRI Inc. All rights reserved. +// + +#import + +@interface NCAppDelegate : NSObject + +@property (assign) IBOutlet NSWindow *window; + +@end diff --git a/Xcode/NukeCtl/NukeCtl/NCAppDelegate.m b/Xcode/NukeCtl/NukeCtl/NCAppDelegate.m new file mode 100644 index 00000000..ba8731dd --- /dev/null +++ b/Xcode/NukeCtl/NukeCtl/NCAppDelegate.m @@ -0,0 +1,18 @@ +// +// NCAppDelegate.m +// NukeCtl +// +// Created by Joseph Goldstone on 10/19/13. +// Copyright (c) 2013 ARRI Inc. All rights reserved. +// + +#import "NCAppDelegate.h" + +@implementation NCAppDelegate + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification +{ + // Insert code here to initialize your application +} + +@end diff --git a/Xcode/NukeCtl/NukeCtl/NukeCtl-Info.plist b/Xcode/NukeCtl/NukeCtl/NukeCtl-Info.plist new file mode 100644 index 00000000..f32e7879 --- /dev/null +++ b/Xcode/NukeCtl/NukeCtl/NukeCtl-Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + + CFBundleIdentifier + com.arri.${PRODUCT_NAME:rfc1034identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + ${MACOSX_DEPLOYMENT_TARGET} + NSHumanReadableCopyright + Copyright © 2013 ARRI Inc. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/Xcode/NukeCtl/NukeCtl/NukeCtl-Prefix.pch b/Xcode/NukeCtl/NukeCtl/NukeCtl-Prefix.pch new file mode 100644 index 00000000..4187f19f --- /dev/null +++ b/Xcode/NukeCtl/NukeCtl/NukeCtl-Prefix.pch @@ -0,0 +1,9 @@ +// +// Prefix header +// +// The contents of this file are implicitly included at the beginning of every source file. +// + +#ifdef __OBJC__ + #import +#endif diff --git a/Xcode/NukeCtl/NukeCtl/en.lproj/Credits.rtf b/Xcode/NukeCtl/NukeCtl/en.lproj/Credits.rtf new file mode 100644 index 00000000..46576ef2 --- /dev/null +++ b/Xcode/NukeCtl/NukeCtl/en.lproj/Credits.rtf @@ -0,0 +1,29 @@ +{\rtf0\ansi{\fonttbl\f0\fswiss Helvetica;} +{\colortbl;\red255\green255\blue255;} +\paperw9840\paperh8400 +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural + +\f0\b\fs24 \cf0 Engineering: +\b0 \ + Some people\ +\ + +\b Human Interface Design: +\b0 \ + Some other people\ +\ + +\b Testing: +\b0 \ + Hopefully not nobody\ +\ + +\b Documentation: +\b0 \ + Whoever\ +\ + +\b With special thanks to: +\b0 \ + Mom\ +} diff --git a/Xcode/NukeCtl/NukeCtl/en.lproj/InfoPlist.strings b/Xcode/NukeCtl/NukeCtl/en.lproj/InfoPlist.strings new file mode 100644 index 00000000..477b28ff --- /dev/null +++ b/Xcode/NukeCtl/NukeCtl/en.lproj/InfoPlist.strings @@ -0,0 +1,2 @@ +/* Localized versions of Info.plist keys */ + diff --git a/Xcode/NukeCtl/NukeCtl/main.m b/Xcode/NukeCtl/NukeCtl/main.m new file mode 100644 index 00000000..c54238ab --- /dev/null +++ b/Xcode/NukeCtl/NukeCtl/main.m @@ -0,0 +1,14 @@ +// +// main.m +// NukeCtl +// +// Created by Joseph Goldstone on 10/19/13. +// Copyright (c) 2013 ARRI Inc. All rights reserved. +// + +#import + +int main(int argc, const char * argv[]) +{ + return NSApplicationMain(argc, argv); +} diff --git a/Xcode/NukeCtl/NukeCtlLib/NukeCtlLib-Prefix.pch b/Xcode/NukeCtl/NukeCtlLib/NukeCtlLib-Prefix.pch new file mode 100644 index 00000000..b300bc29 --- /dev/null +++ b/Xcode/NukeCtl/NukeCtlLib/NukeCtlLib-Prefix.pch @@ -0,0 +1,8 @@ +// +// Prefix header +// +// The contents of this file are implicitly included at the beginning of every source file. +// + +#include + diff --git a/Xcode/NukeCtl/NukeCtlLib/NukeCtlLibProj.xcconfig b/Xcode/NukeCtl/NukeCtlLib/NukeCtlLibProj.xcconfig new file mode 100644 index 00000000..959fcc20 --- /dev/null +++ b/Xcode/NukeCtl/NukeCtlLib/NukeCtlLibProj.xcconfig @@ -0,0 +1,4 @@ +GCC_WARN_ABOUT_RETURN_TYPE = YES; +GCC_WARN_UNUSED_VARIABLE = YES; +GCC_INCREASE_PRECOMPILED_HEADER_SHARING = YES; +GCC_GENERATE_DEBUGGING_SYMBOLS = YES; diff --git a/Xcode/NukeCtl/NukeCtlLib/NukeCtlLibTarget.xcconfig b/Xcode/NukeCtl/NukeCtlLib/NukeCtlLibTarget.xcconfig new file mode 100644 index 00000000..93e974bd --- /dev/null +++ b/Xcode/NukeCtl/NukeCtlLib/NukeCtlLibTarget.xcconfig @@ -0,0 +1,10 @@ +PRODUCT_NAME = libNukeCtlLib; +MACH_O_TYPE = mh_dylib; +DYLIB_COMPATIBILITY_VERSION = 1; +DYLIB_CURRENT_VERSION = 1; +GCC_PRECOMPILE_PREFIX_HEADER = YES; +GCC_PREFIX_HEADER = NukeCtlLib/NukeCtlLib-Prefix.pch; +GCC_ENABLE_CPP_EXCEPTIONS = YES; +GCC_ENABLE_CPP_RTTI = YES; +GCC_SYMBOLS_PRIVATE_EXTERN = NO; + diff --git a/Xcode/NukeCtl/NukeCtlTests/NukeCtlTests-Info.plist b/Xcode/NukeCtl/NukeCtlTests/NukeCtlTests-Info.plist new file mode 100644 index 00000000..d7afb87d --- /dev/null +++ b/Xcode/NukeCtl/NukeCtlTests/NukeCtlTests-Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + com.arri.${PRODUCT_NAME:rfc1034identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/Xcode/NukeCtl/NukeCtlTests/NukeCtlTests.mm b/Xcode/NukeCtl/NukeCtlTests/NukeCtlTests.mm new file mode 100644 index 00000000..47d07438 --- /dev/null +++ b/Xcode/NukeCtl/NukeCtlTests/NukeCtlTests.mm @@ -0,0 +1,674 @@ +// +// NukeCtlTests.m +// NukeCtlTests +// +// Created by Joseph Goldstone on 10/14/13. +// Copyright (c) 2013 ARRI Inc. All rights reserved. +// + +#import + +#import "NukeCtlUtils.h" + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-register" +#endif + +#import "NukeCtlTransform.h" +// #import "NukeCtlChanArgMap.h" + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +using namespace NukeCtl; + +#include +#include +using namespace std; + +#include "Iex.h" +using namespace Iex; + +#include "ImathFun.h" +using namespace Imath; + +#include +#include +using namespace Ctl; + +#include "DDImage/Channel.h" +#include "DDImage/Row.h" +using namespace DD::Image; + +namespace NukeCtl +{ + class TransformFriend { + public: + + // Trampolines for static methods + static + const std::vector + parseModulePath(const std::string &mp) + { + return Transform::parseModulePath(mp); + } + + static + void + verifyModuleName(const string &n) + { + return Transform::verifyModuleName(n); + } + + TransformFriend(Transform& transform) + : transform_(transform) + { + } + + SimdInterpreterPtr + interpreter() + { + return transform_.interpreter_; + } + + FunctionCallPtr + topLevelFunctionInTransform() + { + string topLevelFunctionName(transform_.topLevelFunctionNameInTransform()); + return interpreter()->newFunctionCall(topLevelFunctionName); + } + + static + bool + matchesCTLCannotFindFunctionExceptionText(const exception&e , const string &functionName) + { + return Transform::matchesCTLCannotFindFunctionExceptionText(e, functionName); + } + + static + bool + matchesCTLCannotFindModuleExceptionText(const exception &e) + { + return Transform::matchesCTLCannotFindModuleExceptionText(e); + } + + static + string + missingModuleFromException(const exception &e) + { + return Transform::missingModuleFromException(e); + } + + private: + Transform& transform_; + }; +} + +@class NukeCtlTests; + +@interface NukeCtlTests : XCTestCase + +@end + + + +@implementation NukeCtlTests + +template +bool +equalLengthVectors(const vector &ref, const vector &test) +{ + return test.size() == ref.size(); +} + +template +bool +equalVectorContents(const vector &ref, const vector &test) +{ + if (! equalLengthVectors(test, ref)) + { + return false; + } + for (vector::const_iterator rIter = ref.begin(), tIter=test.begin(); rIter != ref.end(); ++rIter, ++tIter) + { + if (*tIter != *rIter) + { + return false; + } + } + return true; +} + +- (void)setUp +{ + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. +} + +- (void)tearDown +{ + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)testSplitNullString +{ + // Create it, but don't put any element in there. + vector expected; + XCTAssertEqual(split("", ':'), expected, @"splitting an empty string should return a vector with no elements"); +} + +- (void)testSplitBlankString +{ + vector expected; + expected.push_back(" "); + vector test(split(" ", ':')); + XCTAssert(equalVectorContents(expected, test), @"splitting a blank string should return a vector with one element, containing that blank string"); +} + +- (void)testSplitDelimOnlyString +{ + vector expected; + vector test(split(":", ':')); + XCTAssert(equalVectorContents(expected, test), @"splitting a string whose only element is the delimiter should return a vector with no elements"); +} + +- (void)testSplitDoubleDelimOnlyString +{ + vector expected; + vector test(split("::", ':')); + XCTAssert(equalVectorContents(expected, test), @"splitting a string whose only element is an adjacent pair of delimiters should return a vector with no elements"); +} + +- (void)testSplitSingleCharString +{ + vector expected; + expected.push_back("x"); + vector test(split("x", ':')); + XCTAssert(equalVectorContents(expected, test), @"splitting a single-character string should return a vector with a single element, containing that string"); +} + +- (void)testSplitTwoElementString +{ + // Create it, but don't put any element in there. + vector expected; + expected.push_back("x"); + expected.push_back("y"); + vector test(split("x:y", ':')); + XCTAssert(equalVectorContents(expected, test), @"splitting a two-element string should return a vector with two elements, in the same order as they occured in the string"); +} + +- (void)testSplitThreeElementString +{ + // Create it, but don't put any element in there. + vector expected; + expected.push_back("x"); + expected.push_back("y"); + expected.push_back("z"); + vector test(split("x:y:z", ':')); + XCTAssert(equalVectorContents(expected, test), @"splitting a three-element string should return a vector with three elements, in the same order as they occured in the string"); +} + +- (void)testTrimLeftEmptyStringEmptyDelim +{ + string expected; + string debris; + string test; + string result(trimLeft(test, debris)); + XCTAssert(result == expected, @"left trim of empty string with empty debris field should return empty string"); + +} + +- (void)testTrimLeftEmptyStringNonEmptyDelim +{ + string expected; + string debris(" "); + string test; + string result(trimLeft(test, debris)); + XCTAssert(result == expected, @"left trim of empty string with non-empty debris field should return empty string"); + +} + +- (void)testTrimLeftEmptyDebris +{ + string expected0(" blah blah blah"); + string expected1("blah blah blah"); + string debris; + string test0(expected0); + string result0(trimLeft(test0, debris)); + XCTAssert(result0 == expected0, @"left trim of string with leading debris but empty debris field should return string unmodified"); + string test1(expected1); + string result1(trimLeft(test1, debris)); + XCTAssert(result1 == expected1, @"left trim of string with no leading debris but empty debris field should return string unmodified"); +} + +- (void)testTrimLeft +{ + string expected("blah blah blah"); + string debris("\t "); + string test0(string(" ") + expected); + string test1(expected); + XCTAssert(trimLeft(test0, debris) == expected, @"left trim of string with leading debris and matching debris field should return trimmed string"); + XCTAssert(trimLeft(test1, debris) == expected, @"left trim of string with no leading debris and matching debris field should return trimmed string"); +} + +- (void)testTrimRightEmptyStringEmptyDelim +{ + string expected; + string debris; + string test; + string result(trimRight(test, debris)); + XCTAssert(result == expected, @"right trim of empty string with empty debris field should return empty string"); + +} + +- (void)testTrimRightEmptyStringNonEmptyDelim +{ + string expected; + string debris(" "); + string test; + string result(trimRight(test, debris)); + XCTAssert(result == expected, @"right trim of empty string with non-empty debris field should return empty string"); + +} + +- (void)testTrimRightEmptyDebris +{ + string expected0("blah blah blah "); + string expected1("blah blah blah"); + string debris; + string test0(expected0); + XCTAssert(trimRight(test0, debris) == expected0, @"right trim of string with trailing debris but empty debris field should return trimmed string"); + string test1(expected1); + XCTAssert(trimRight(test1, debris) == expected1, @"right trim of string with no leading debris but empty debris field should return trimmed string"); +} + +- (void)testTrimRight +{ + string expected("blah blah blah"); + string debris("\t "); + string test0(expected + string(" ")); + string test1(expected); + string result(trimRight(test0, debris)); + XCTAssert(result == expected, @"right trim of string with leading debris and matching debris field should return trimmed string"); + XCTAssert(trimRight(test1, debris) == expected, @"right trim of string with no leading debris and matching debris field should return trimmed string"); +} + +- (void)testFilenameFromEmptyPathname +{ + string test(""); + bool threw = false; + try { + filenameFromPathname(test); + } + catch(const ArgExc& e) + { + threw = true; + } + XCTAssert(threw, @"getting the filename name from an empty pathname should thrown ArgExc"); +} + +- (void)testFilenameFromRootPath +{ + string expected("/"); + string test("/"); + string result(filenameFromPathname(test)); + XCTAssert(result == expected, @"getting the filename of the root as a pathname is still the root"); +} + +- (void)testFilenameFromDirectoryPath +{ + string expected("foo"); + string test("/foo/"); + string result(filenameFromPathname(test)); + XCTAssert(result == expected, @"getting the filename of a directory as a pathname (i.e. with a trailing slash) is the last non-empty component of the pathname"); +} + +- (void)testFilenameFromNonDirectoryPath +{ + string expected("bar"); + string test("/foo/bar"); + string result(filenameFromPathname(test)); + XCTAssert(result == expected, @"getting the filename of a non-directory pathname (i.e. with no trailing slash) is the last component of the pathname"); +} + +- (void)testModuleNameFromEmptyFilename +{ + string test(""); + bool threw = false; + try { + modulenameFromFilename(test); + } + catch(const ArgExc& e) + { + threw = true; + } + XCTAssert(threw, @"getting the module name from an empty filename should thrown ArgExc"); +} + +- (void)testModuleNameFromMonadicFilename +{ + string expected("foo"); + string test("foo"); + string result(modulenameFromFilename(test)); + XCTAssert(result == expected, @"getting the module name from a monadic filename should return that filename"); +} + +- (void)testModuleNameFromDyadicFilename +{ + string expected("README"); + string test("README.txt"); + string result(modulenameFromFilename(test)); + XCTAssert(result == expected, @"getting the module name from a Dyadic filename should return the name component of that filename"); +} + +- (void)testModuleNameFromTriadicFilename +{ + string expected("foo"); + string test("foo.1.ari"); + string result(modulenameFromFilename(test)); + XCTAssert(result == expected, @"getting the module name from a triadic filename should return the name component of that filename"); +} + +- (void)testRowReadback +{ + // Imagine a line which is 30 pixels across, but where the first pixel is x=10 and the last is x=39 + int x = 10; + int r = 39; + Row srcRow(x, r); + Row::WritablePtr redBuf = srcRow.writable(Chan_Red); + Row::WritablePtr greenBuf = srcRow.writable(Chan_Green); + Row::WritablePtr blueBuf = srcRow.writable(Chan_Blue); + for (int i = x; i <= r; ++i) + { + float lf = lerpfactor(i + 0.0, x + 0.0, r + 0.0); + redBuf[i] = lf; + greenBuf[i] = 1 - lf; + blueBuf[i] = redBuf[i] * greenBuf[i]; + } + for (int i = x; i <= r; ++i) + { + float lf = lerpfactor(i + 0.0, x + 0.0, r + 0.0); + XCTAssertEqualWithAccuracy( redBuf[i], lf, 4 * numeric_limits::epsilon(), + @"red buffer contents should read back to match what was just written into them"); + XCTAssertEqualWithAccuracy(greenBuf[i], 1 - lf, 4 * numeric_limits::epsilon(), + @"red buffer contents should read back to match what was just written into them"); + XCTAssertEqualWithAccuracy( blueBuf[i], lf * (1 - lf), 4 * numeric_limits::epsilon(), + @"red buffer contents should read back to match what was just written into them"); + } +} + +#define BEGIN_WARINESS_OF_UNCAUGHT_EXCEPTIONS \ +try { + +#define END_WARINESS_OF_UNCAUGHT_EXCEPTIONS \ +} \ +catch (const std::exception& e) \ +{ \ +XCTFail(@"Failure due to uncaught std::exception subclass having been thrown"); \ +} \ +catch (...) \ +{ \ +XCTFail(@"Failure due to uncaught exception (and one not based on std::exception)"); \ +} + +- (void)writeGenericTransformWithName:(NSString *)name toPath:(NSString *)path +{ + ofstream s([path UTF8String]); + s << "void\n"; + s << [name UTF8String]; + s << "(input varying float rIn,\ninput varying float gIn,\ninput varying float bIn,\ninput varying float aIn,\noutput varying float rOut,\noutput varying float gOut,\noutput varying float bOut,\noutput varying float aOut)\n{\nrOut=rIn;\ngOut=gIn;\nbOut=bIn;\naOut=aIn;\n}\n" << endl; +} + +- (void)writeRGBASwappingTransformWithName:(NSString *)name toPath:(NSString *)path +{ + ofstream s([path UTF8String]); + s << "void\n"; + s << [name UTF8String]; + s << "(input varying float rIn,\ninput varying float gIn,\ninput varying float bIn,\ninput varying float aIn,\noutput varying float rOut,\noutput varying float gOut,\noutput varying float bOut,\noutput varying float aOut)\n{\nrOut=aIn;\ngOut=bIn;\nbOut=gIn;\naOut=rIn;\n}\n" << endl; +} + +- (void)testEmptyModulePath +{ + BEGIN_WARINESS_OF_UNCAUGHT_EXCEPTIONS + vector expected; + string test; + NSString* p = @"/tmp/genericMain.ctl"; + [self writeGenericTransformWithName:@"main" toPath:p]; + Transform transform("", [p UTF8String]); + TransformFriend amigo(transform); + XCTAssert(equalVectorContents(amigo.parseModulePath(test), expected), @"parsing an empty module path should return a vector with no elements"); + END_WARINESS_OF_UNCAUGHT_EXCEPTIONS +} + +- (void)testSingleElementModulePath +{ + BEGIN_WARINESS_OF_UNCAUGHT_EXCEPTIONS + const string test("/usr/local/ctl/aces-dev/utilities"); + vector expected(1, test); + NSString* p = @"/tmp/genericMain.ctl"; + [self writeGenericTransformWithName:@"main" toPath:p]; + Transform transform("", [p UTF8String]); + TransformFriend amigo(transform); + XCTAssert(equalVectorContents(amigo.parseModulePath(test), expected), @"parsing a module path with one element should return a vector with that element"); + END_WARINESS_OF_UNCAUGHT_EXCEPTIONS +} + +- (void)testVerificationOfModuleName +{ + BEGIN_WARINESS_OF_UNCAUGHT_EXCEPTIONS + string badChars("/:;\\"); + for (int i = 0; i < badChars.size(); ++i) + { + const string test(string("fo") + badChars[i] + "o"); + bool threw = false; + try { + NSString* p = @"/tmp/genericMain.ctl"; + [self writeGenericTransformWithName:@"main" toPath:p]; + Transform transform("", [p UTF8String]); + TransformFriend amigo(transform); + amigo.verifyModuleName(test); + } + catch(const ArgExc& e) + { + threw = true; + } + XCTAssert(threw, @"verifying a module name with bad characters embedded should thrown ArgExc"); + } + END_WARINESS_OF_UNCAUGHT_EXCEPTIONS +} + +- (void)testRecognizingCTLCannotFindFunctionExceptionText +{ + BEGIN_WARINESS_OF_UNCAUGHT_EXCEPTIONS + NSString* p = @"/tmp/genericFoo.ctl"; + [self writeGenericTransformWithName:@"genericFoo" toPath:p]; + SimdInterpreter interpreter; + interpreter.loadFile([p UTF8String]); + bool threwRecognizedError = false; + try { + FunctionCallPtr f = interpreter.newFunctionCall("main"); + } + catch(const ArgExc& e) + { + threwRecognizedError = TransformFriend::matchesCTLCannotFindFunctionExceptionText(e, "main"); + } + XCTAssert(threwRecognizedError, @"top-level function should not be found, neither as 'main' nor 'genericBaz'"); + + END_WARINESS_OF_UNCAUGHT_EXCEPTIONS +} + +- (void)testRecognizingCTLCannotFindModuleExceptionText +{ + BEGIN_WARINESS_OF_UNCAUGHT_EXCEPTIONS + bool threwRecognizedError = false; + try { + SimdInterpreter interpreter; + interpreter.loadModule("zzz"); + } + catch(const ArgExc& e) + { + threwRecognizedError = TransformFriend::matchesCTLCannotFindModuleExceptionText(e); + } + XCTAssert(threwRecognizedError, @"Failure to find CTL module should throw recognizable error"); + END_WARINESS_OF_UNCAUGHT_EXCEPTIONS +} + +- (void)testExtractingCTLCannotFindModuleExceptionText +{ + BEGIN_WARINESS_OF_UNCAUGHT_EXCEPTIONS + bool threwRecognizedError = false; + try { + SimdInterpreter interpreter; + interpreter.loadModule("zzz"); + } + catch(const ArgExc& e) + { + threwRecognizedError = TransformFriend::missingModuleFromException(e) == "zzz"; + } + XCTAssert(threwRecognizedError, @"Failure to find CTL module should throw error from which we can extract module name"); + END_WARINESS_OF_UNCAUGHT_EXCEPTIONS +} + +- (void)testFindingTopLevelMainFunctionInGenericCode +{ + BEGIN_WARINESS_OF_UNCAUGHT_EXCEPTIONS + NSString* p = @"/tmp/genericMain.ctl"; + [self writeGenericTransformWithName:@"main" toPath:p]; + Transform transform("", [p UTF8String]); + TransformFriend amigo(transform); + FunctionCallPtr f = amigo.topLevelFunctionInTransform(); + XCTAssert(f.refcount() != 0, @"top-level 'main' function should be visible"); + END_WARINESS_OF_UNCAUGHT_EXCEPTIONS +} + +- (void)testFindingTopLevelFooFunctionInGenericCode +{ + BEGIN_WARINESS_OF_UNCAUGHT_EXCEPTIONS + NSString* p = @"/tmp/genericFoo.ctl"; + [self writeGenericTransformWithName:@"genericFoo" toPath:p]; + try { + Transform transform("", [p UTF8String]); + TransformFriend amigo(transform); + FunctionCallPtr f = amigo.topLevelFunctionInTransform(); + } catch (const ArgExc &e) { + cout << "oops: " << e.what() << endl; + XCTFail("could not find genericFoo as top-level function"); + } + END_WARINESS_OF_UNCAUGHT_EXCEPTIONS +} + +- (void)testNotFindingTopLevelFunctionInGenericCode +{ + BEGIN_WARINESS_OF_UNCAUGHT_EXCEPTIONS + NSString* p = @"/tmp/genericBar.ctl"; + [self writeGenericTransformWithName:@"genericBaz" toPath:p]; + bool threw = false; + try { + Transform transform("", [p UTF8String]); + TransformFriend amigo(transform); + FunctionCallPtr f = amigo.topLevelFunctionInTransform(); + } + catch(const ArgExc& e) + { + threw = true; + } + XCTAssert(threw, @"top-level function should not be found, neither as 'main' nor 'genericBaz'"); + END_WARINESS_OF_UNCAUGHT_EXCEPTIONS +} + +- (void)testFindingRRTWhenModulePathSet +{ + BEGIN_WARINESS_OF_UNCAUGHT_EXCEPTIONS + NSString* p = @"/tmp/rrt.ctl"; + bool threw = false; + try { + Transform transform("/tmp", [p UTF8String]); + TransformFriend amigo(transform); + FunctionCallPtr f = amigo.topLevelFunctionInTransform(); + XCTAssert(f.refcount() != 0, @"top-level 'main' function should be visible"); + } + catch(const BaseExc& e) + { + threw = true; + } + END_WARINESS_OF_UNCAUGHT_EXCEPTIONS +} + +- (void)testFindingRRTWhenModulePathNotSet +{ + BEGIN_WARINESS_OF_UNCAUGHT_EXCEPTIONS + NSString* p = @"/tmp/rrt.ctl"; + ofstream s([p UTF8String]); + bool threw = false; + try { + Transform transform("/var/tmp", [p UTF8String]); + TransformFriend amigo(transform); + FunctionCallPtr f = amigo.topLevelFunctionInTransform(); + } + catch(const BaseExc& e) + { + threw = true; + } + XCTAssert(threw, @"RRT failing to find utilities modules should have been grounds for an exception, but none was thrown"); + END_WARINESS_OF_UNCAUGHT_EXCEPTIONS +} + +- (void)testTopLevelFunctionNotReturningVoidThrows +{ + BEGIN_WARINESS_OF_UNCAUGHT_EXCEPTIONS + NSString* p = @"/tmp/intMain.ctl"; + ofstream s([p UTF8String]); + s << "int main(input varying float rIn, input varying float gIn, input varying float bIn, input varying float aIn, output varying float rOut, output varying float gOut, output varying float bOut, output varying float aOut) {}" << endl; + bool threw = false; + try { + Transform transform("", [p UTF8String]); + TransformFriend amigo(transform); + FunctionCallPtr f = amigo.topLevelFunctionInTransform(); + } + catch(const BaseExc& e) + { + threw = true; + } + XCTAssert(threw, @"top-level function not returning void should have been grounds for an exception, but none was thrown"); + END_WARINESS_OF_UNCAUGHT_EXCEPTIONS +} + +// This is the short version. If this doesn't work, consider whether the long version works or not. +- (void)testNukeCTLArgAndResult +{ + BEGIN_WARINESS_OF_UNCAUGHT_EXCEPTIONS + NSString* p = @"/tmp/RGBASwap.ctl"; + [self writeRGBASwappingTransformWithName:@"main" toPath:p]; + try { + Transform transform("", [p UTF8String]); + int x = 10; + int r = 20; + Row in(x, r); + float red_test_value = 0.125; + float green_test_value = 0.250; + float blue_test_value = 2.0; + float alpha_test_value = 4.0; + in.writable(Chan_Red) [x] = red_test_value; + in.writable(Chan_Green)[x] = green_test_value; + in.writable(Chan_Blue) [x] = blue_test_value; + in.writable(Chan_Alpha)[x] = alpha_test_value; + Row out(x,r); + TransformFriend amigo(transform); + FunctionCallPtr functionCall = amigo.topLevelFunctionInTransform(); + transform.execute(in, x, r, out); + XCTAssertEqualWithAccuracy(out[Chan_Red][x], alpha_test_value, numeric_limits::epsilon() * 4, "Chan_red output value does not match Chan_alpha input"); + XCTAssertEqualWithAccuracy(out[Chan_Green][x], blue_test_value, numeric_limits::epsilon() * 4, "Chan_green output value does not match Chan_blue input"); + XCTAssertEqualWithAccuracy(out[Chan_Blue][x], green_test_value, numeric_limits::epsilon() * 4, "Chan_blue output value does not match Chan_green input"); + XCTAssertEqualWithAccuracy(out[Chan_Alpha][x], red_test_value, numeric_limits::epsilon() * 4, "Chan_alpha output value does not match Chan_red input"); + } catch (const ArgExc &e) { + cout << "oops: " << e.what() << endl; + XCTFail("could not load argument map, execute, or extract results of RGBA-swapping top-level function"); + } + END_WARINESS_OF_UNCAUGHT_EXCEPTIONS +} + + +@end diff --git a/Xcode/NukeCtl/NukeCtlTests/en.lproj/InfoPlist.strings b/Xcode/NukeCtl/NukeCtlTests/en.lproj/InfoPlist.strings new file mode 100644 index 00000000..477b28ff --- /dev/null +++ b/Xcode/NukeCtl/NukeCtlTests/en.lproj/InfoPlist.strings @@ -0,0 +1,2 @@ +/* Localized versions of Info.plist keys */ + diff --git a/Xcode/NukeCtl/NukeCtlTests/rrt.ctl b/Xcode/NukeCtl/NukeCtlTests/rrt.ctl new file mode 100644 index 00000000..13241f16 --- /dev/null +++ b/Xcode/NukeCtl/NukeCtlTests/rrt.ctl @@ -0,0 +1,70 @@ +// +// Reference Rendering Transform (RRT) +// v0.2.2 +// + +import "utilities"; +import "utilities-aces"; + +const Chromaticities RENDERING_PRI = +{ + {0.73470, 0.26530}, + {0.00000, 1.00000}, + {0.12676, 0.03521}, + {0.32168, 0.33767} +}; + +const float ACES_PRI_2_XYZ_MAT[4][4] = RGBtoXYZ(ACES_PRI,1.0); +const float XYZ_2_RENDERING_PRI_MAT[4][4] = XYZtoRGB(RENDERING_PRI,1.0); +const float ACES_PRI_2_RENDERING_PRI_MAT[4][4] = mult_f44_f44( ACES_PRI_2_XYZ_MAT, XYZ_2_RENDERING_PRI_MAT); + +// Chroma scaling parameters +const float center = 350.; // center hue (in degrees) +const float width = 140.; // full base width (in degrees) +const float percent = 0.83; // percent scale (0-1) + +// Reference Rendering Transform (RRT) +// Input is ACES RGB (linearly encoded) +// Output is OCES RGB (linearly encoded) +void main +( + input varying float rIn, + input varying float gIn, + input varying float bIn, + input varying float aIn, + output varying float rOut, + output varying float gOut, + output varying float bOut, + output varying float aOut +) +{ + // Put input variables into a 3-element array (ACES) + float aces[3] = {rIn, gIn, bIn}; + + // Adjust ACES values by scaling chroma in the red/magenta region + aces = scale_C_at_H( aces, center, width, percent); + + // Clamp negative ACES values + float acesClamp[3] = clamp_f3( aces, -0.05, HALF_POS_INF); + + // Convert from ACES RGB encoding to rendering primaries RGB encoding + float rgbPre[3] = mult_f3_f44( acesClamp, ACES_PRI_2_RENDERING_PRI_MAT); + + // Apply the RRT tone scale independently to RGB + float rgbPost[3]; + rgbPost[0] = rrt_tonescale_fwd( rgbPre[0]); + rgbPost[1] = rrt_tonescale_fwd( rgbPre[1]); + rgbPost[2] = rrt_tonescale_fwd( rgbPre[2]); + + // Restore the hue to the pre-tonescale hue + float rgbRestored[3] = restore_hue_dw3( rgbPre, rgbPost); + + // Convert from rendering primaries RGB encoding to OCES RGB encoding + float oces[3] = mult_f3_f44( rgbRestored, invert_f44(ACES_PRI_2_RENDERING_PRI_MAT)); + + // Assign OCES-RGB to output variables (OCES) + rOut = oces[0]; + gOut = oces[1]; + bOut = oces[2]; + aOut = aIn; +} \ No newline at end of file diff --git a/Xcode/NukeCtl/NukeCtlTests/utilities-aces.ctl b/Xcode/NukeCtl/NukeCtlTests/utilities-aces.ctl new file mode 100644 index 00000000..7dfb4302 --- /dev/null +++ b/Xcode/NukeCtl/NukeCtlTests/utilities-aces.ctl @@ -0,0 +1,637 @@ +// +// utilities-aces.ctl +// v0.2.2 +// +// Functions used by ACES system transforms that are unlikely to be reused in +// algorithms outside of ACES. +// + + + +import "utilities-color"; + + + +/* ----- Tone scale spline functions ----- */ + +// Textbook monomial to basis-function conversion matrix. +const float M[ 3][ 3] = { + { 0.5, -1.0, 0.5 }, + { -1.0, 1.0, 0.5 }, + { 0.5, 0.0, 0.0 } +}; + +const float ACESMAX = 65504.0; +const float ACESMID = 0.18; +const float ACESMIN = ACESMID * ACESMID / ACESMAX; +// This is the same as: pow10(log10(ACESMID) - (log10(ACESMAX)-log10(ACESMID))); +const float OCESMAX = 10000.0; +const float OCESMID = 5.0; +const float OCESMIN = 0.0001; + +const int RRT_KNOT_LEN = 21; +const float RRT_KNOT_START = log10(ACESMIN); +const float RRT_KNOT_END = log10(ACESMAX); +const float RRT_KNOT_SPAN = RRT_KNOT_END - RRT_KNOT_START; +const float RRT_KNOT_INC = RRT_KNOT_SPAN / (RRT_KNOT_LEN - 1.); + +// These are the coefficients used for WGR5. Before RCv0.2.1, the number of coefs +// may be reduced or the B-spline might be replaced with a function. +const float DEFAULT_RRT_COEFS[23] = { + -4.00000, + -4.00000, + -4.00000, + -3.95000, + -3.82000, + -3.55950, + -3.12710, + -2.52690, + -1.72810, + -0.76221, + 0.24019, + 1.15775, + 1.94320, + 2.61950, + 3.13250, + 3.49050, + 3.71550, + 3.85130, + 3.92710, + 3.96980, + 4.00000, + 4.00000, + 4.00000 +}; + +float rrt_tonescale_fwd + ( + varying float aces, // ACES value + varying float COEFS[23] = DEFAULT_RRT_COEFS // the control points + ) +{ + // Check for negatives or zero before taking the log. If negative or zero, + // set to ACESMIN. + float acesCheck = aces; + if (acesCheck <= ACESMIN) acesCheck = ACESMIN; + + float logAces = log10( acesCheck); + + float logOces; + + // For logOces values in the knot range, apply the B-spline shaper, b(x) + if (( logAces >= RRT_KNOT_START ) && ( logAces < RRT_KNOT_END)) + { + float knot_coord = (logAces - RRT_KNOT_START) / RRT_KNOT_SPAN * ( RRT_KNOT_LEN-1); + int j = knot_coord; + float t = knot_coord - j; + + // The following could be written as: + //float cf[ 3] = { COEFS[ j], COEFS[ j + 1], COEFS[ j + 2]}; + // but for now is expanded for compatibility with CTL < v1.5. + float cf[ 3]; + if ( j <= 0) { + cf[ 0] = COEFS[0]; cf[ 1] = COEFS[1]; cf[ 2] = COEFS[2]; + } else if ( j == 1) { + cf[ 0] = COEFS[1]; cf[ 1] = COEFS[2]; cf[ 2] = COEFS[3]; + } else if ( j == 2) { + cf[ 0] = COEFS[2]; cf[ 1] = COEFS[3]; cf[ 2] = COEFS[4]; + } else if ( j == 3) { + cf[ 0] = COEFS[3]; cf[ 1] = COEFS[4]; cf[ 2] = COEFS[5]; + } else if ( j == 4) { + cf[ 0] = COEFS[4]; cf[ 1] = COEFS[5]; cf[ 2] = COEFS[6]; + } else if ( j == 5) { + cf[ 0] = COEFS[5]; cf[ 1] = COEFS[6]; cf[ 2] = COEFS[7]; + } else if ( j == 6) { + cf[ 0] = COEFS[6]; cf[ 1] = COEFS[7]; cf[ 2] = COEFS[8]; + } else if ( j == 7) { + cf[ 0] = COEFS[7]; cf[ 1] = COEFS[8]; cf[ 2] = COEFS[9]; + } else if ( j == 8) { + cf[ 0] = COEFS[8]; cf[ 1] = COEFS[9]; cf[ 2] = COEFS[10]; + } else if ( j == 9) { + cf[ 0] = COEFS[9]; cf[ 1] = COEFS[10]; cf[ 2] = COEFS[11]; + } else if ( j == 10) { + cf[ 0] = COEFS[10]; cf[ 1] = COEFS[11]; cf[ 2] = COEFS[12]; + } else if ( j == 11) { + cf[ 0] = COEFS[11]; cf[ 1] = COEFS[12]; cf[ 2] = COEFS[13]; + } else if ( j == 12) { + cf[ 0] = COEFS[12]; cf[ 1] = COEFS[13]; cf[ 2] = COEFS[14]; + } else if ( j == 13) { + cf[ 0] = COEFS[13]; cf[ 1] = COEFS[14]; cf[ 2] = COEFS[15]; + } else if ( j == 14) { + cf[ 0] = COEFS[14]; cf[ 1] = COEFS[15]; cf[ 2] = COEFS[16]; + } else if ( j == 15) { + cf[ 0] = COEFS[15]; cf[ 1] = COEFS[16]; cf[ 2] = COEFS[17]; + } else if ( j == 16) { + cf[ 0] = COEFS[16]; cf[ 1] = COEFS[17]; cf[ 2] = COEFS[18]; + } else if ( j == 17) { + cf[ 0] = COEFS[17]; cf[ 1] = COEFS[18]; cf[ 2] = COEFS[19]; + } else if ( j == 18) { + cf[ 0] = COEFS[18]; cf[ 1] = COEFS[19]; cf[ 2] = COEFS[20]; + } else if ( j == 19) { + cf[ 0] = COEFS[19]; cf[ 1] = COEFS[20]; cf[ 2] = COEFS[21]; + } else { + cf[ 0] = COEFS[20]; cf[ 1] = COEFS[21]; cf[ 2] = COEFS[22]; + } + + float monomials[ 3] = { t * t, t, 1. }; + logOces = dot_f3_f3( monomials, mult_f3_f33( cf, M)); + } + else if ( logAces < RRT_KNOT_START) { + logOces = ( COEFS[0] + COEFS[1]) / 2.; + } + else if ( logAces >= RRT_KNOT_END) { + logOces = ( COEFS[RRT_KNOT_LEN-1] + COEFS[RRT_KNOT_LEN]) / 2.; + } + + return pow10(logOces); +} + + + +float rrt_tonescale_rev +( + varying float oces, // OCES value + varying float COEFS[23] = DEFAULT_RRT_COEFS // the control points +) +{ + // KNOT_Y is luminance of the spline at the knots. + float KNOT_Y[ RRT_KNOT_LEN]; + for (int i = 0; i < RRT_KNOT_LEN; i = i+1) { + KNOT_Y[ i] = ( COEFS[i] + COEFS[i+1]) / 2.; + }; + + float logOces = oces; + if (logOces <= OCESMIN) logOces = OCESMIN; + + logOces = log10( logOces ); + + float logAces; + if (logOces <= KNOT_Y[0]) { + logAces = RRT_KNOT_START; + } else if (logOces > KNOT_Y[RRT_KNOT_LEN-1]) { + logAces = RRT_KNOT_END; + } else { + // if (( logOces >= KNOT_Y[0] ) && ( logOces <= KNOT_Y[KNOT_LEN-1])) { + unsigned int j; + float cf[ 3]; + if ( logOces > KNOT_Y[ 0] && logOces <= KNOT_Y[ 1]) { + cf[ 0] = COEFS[0]; cf[ 1] = COEFS[1]; cf[ 2] = COEFS[2]; j = 0; + } else if ( logOces > KNOT_Y[ 1] && logOces <= KNOT_Y[ 2]) { + cf[ 0] = COEFS[1]; cf[ 1] = COEFS[2]; cf[ 2] = COEFS[3]; j = 1; + } else if ( logOces > KNOT_Y[ 2] && logOces <= KNOT_Y[ 3]) { + cf[ 0] = COEFS[2]; cf[ 1] = COEFS[3]; cf[ 2] = COEFS[4]; j = 2; + } else if ( logOces > KNOT_Y[ 3] && logOces <= KNOT_Y[ 4]) { + cf[ 0] = COEFS[3]; cf[ 1] = COEFS[4]; cf[ 2] = COEFS[5]; j = 3; + } else if ( logOces > KNOT_Y[ 4] && logOces <= KNOT_Y[ 5]) { + cf[ 0] = COEFS[4]; cf[ 1] = COEFS[5]; cf[ 2] = COEFS[6]; j = 4; + } else if ( logOces > KNOT_Y[ 5] && logOces <= KNOT_Y[ 6]) { + cf[ 0] = COEFS[5]; cf[ 1] = COEFS[6]; cf[ 2] = COEFS[7]; j = 5; + } else if ( logOces > KNOT_Y[ 6] && logOces <= KNOT_Y[ 7]) { + cf[ 0] = COEFS[6]; cf[ 1] = COEFS[7]; cf[ 2] = COEFS[8]; j = 6; + } else if ( logOces > KNOT_Y[ 7] && logOces <= KNOT_Y[ 8]) { + cf[ 0] = COEFS[7]; cf[ 1] = COEFS[8]; cf[ 2] = COEFS[9]; j = 7; + } else if ( logOces > KNOT_Y[ 8] && logOces <= KNOT_Y[ 9]) { + cf[ 0] = COEFS[8]; cf[ 1] = COEFS[9]; cf[ 2] = COEFS[10]; j = 8; + } else if ( logOces > KNOT_Y[ 9] && logOces <= KNOT_Y[10]) { + cf[ 0] = COEFS[9]; cf[ 1] = COEFS[10]; cf[ 2] = COEFS[11]; j = 9; + } else if ( logOces > KNOT_Y[10] && logOces <= KNOT_Y[11]) { + cf[ 0] = COEFS[10]; cf[ 1] = COEFS[11]; cf[ 2] = COEFS[12]; j = 10; + } else if ( logOces > KNOT_Y[11] && logOces <= KNOT_Y[12]) { + cf[ 0] = COEFS[11]; cf[ 1] = COEFS[12]; cf[ 2] = COEFS[13]; j = 11; + } else if ( logOces > KNOT_Y[12] && logOces <= KNOT_Y[13]) { + cf[ 0] = COEFS[12]; cf[ 1] = COEFS[13]; cf[ 2] = COEFS[14]; j = 12; + } else if ( logOces > KNOT_Y[13] && logOces <= KNOT_Y[14]) { + cf[ 0] = COEFS[13]; cf[ 1] = COEFS[14]; cf[ 2] = COEFS[15]; j = 13; + } else if ( logOces > KNOT_Y[14] && logOces <= KNOT_Y[15]) { + cf[ 0] = COEFS[14]; cf[ 1] = COEFS[15]; cf[ 2] = COEFS[16]; j = 14; + } else if ( logOces > KNOT_Y[15] && logOces <= KNOT_Y[16]) { + cf[ 0] = COEFS[15]; cf[ 1] = COEFS[16]; cf[ 2] = COEFS[17]; j = 15; + } else if ( logOces > KNOT_Y[16] && logOces <= KNOT_Y[17]) { + cf[ 0] = COEFS[16]; cf[ 1] = COEFS[17]; cf[ 2] = COEFS[18]; j = 16; + } else if ( logOces > KNOT_Y[17] && logOces <= KNOT_Y[18]) { + cf[ 0] = COEFS[17]; cf[ 1] = COEFS[18]; cf[ 2] = COEFS[19]; j = 17; + } else if ( logOces > KNOT_Y[18] && logOces <= KNOT_Y[19]) { + cf[ 0] = COEFS[18]; cf[ 1] = COEFS[19]; cf[ 2] = COEFS[20]; j = 18; + } else { + cf[ 0] = COEFS[19]; cf[ 1] = COEFS[20]; cf[ 2] = COEFS[21]; j = 19; + } + + const float tmp[ 3] = mult_f3_f33( cf, M); + + float a = tmp[ 0]; + float b = tmp[ 1]; + float c = tmp[ 2]; + c = c - logOces; + + const float d = sqrt( b * b - 4. * a * c); + + const float t = ( 2. * c) / ( -d - b); + + logAces = RRT_KNOT_START + ( t + j) * RRT_KNOT_INC; + } + + return pow10( logAces); +} + + + + +const float DEFAULT_YMIN_ABS = 5.0; +const float DEFAULT_YMAX_ABS = 48.0; +const float DEFAULT_ODT_HI_SLOPE = 0.04; +const float DEFAULT_ODT_COEFS[14] = { + 0.59886, + 0.80071, + 0.98498, + 1.14260, + 1.27700, + 1.38810, + 1.47380, + 1.53840, + 1.58360, + 1.61780, + 1.64350, + 1.66160, + 1.67765, + 1.68573 +}; + +const unsigned int ODT_KNOT_LEN = 13; +const float ODT_KNOT_START = log10( rrt_tonescale_fwd(0.18) ); +const float ODT_KNOT_END = log10( rrt_tonescale_fwd(0.18*pow(2.,6.5)) ); +const float ODT_KNOT_SPAN = ODT_KNOT_END - ODT_KNOT_START; +const float ODT_KNOT_INC = ODT_KNOT_SPAN / (ODT_KNOT_LEN - 1.); + +float odt_tonescale_fwd + ( // input is absolute luminance, output is absolute luminance + varying float oces, + varying float COEFS[14] = DEFAULT_ODT_COEFS, + varying float hi_slope = DEFAULT_ODT_HI_SLOPE, + varying float lumMin = DEFAULT_YMIN_ABS, + varying float lumMax = DEFAULT_YMAX_ABS + ) +{ + float ocesCheck = oces; + if (ocesCheck < OCESMIN) ocesCheck = OCESMIN; + // Just a safety check to make sure no negative OCES values somehow got by + + float logOces = log10( ocesCheck); + + float logy; + float y; + + // For logOces values in the knot range, apply the B-spline shaper, b(x) + if (( logOces > ODT_KNOT_START ) && ( logOces < ODT_KNOT_END)) { + + float knot_coord = (logOces - ODT_KNOT_START) / ODT_KNOT_SPAN * ( ODT_KNOT_LEN-1); + int j = knot_coord; + float t = knot_coord - j; + + // The following could be written as: + //float cf[ 3] = { COEFS[ j], COEFS[ j + 1], COEFS[ j + 2]}; + // but for now is expanded for compatibility with CTL < v1.5. + float cf[ 3]; + if ( j <= 0) { + cf[ 0] = COEFS[0]; cf[ 1] = COEFS[1]; cf[ 2] = COEFS[2]; + } else if ( j == 1) { + cf[ 0] = COEFS[1]; cf[ 1] = COEFS[2]; cf[ 2] = COEFS[3]; + } else if ( j == 2) { + cf[ 0] = COEFS[2]; cf[ 1] = COEFS[3]; cf[ 2] = COEFS[4]; + } else if ( j == 3) { + cf[ 0] = COEFS[3]; cf[ 1] = COEFS[4]; cf[ 2] = COEFS[5]; + } else if ( j == 4) { + cf[ 0] = COEFS[4]; cf[ 1] = COEFS[5]; cf[ 2] = COEFS[6]; + } else if ( j == 5) { + cf[ 0] = COEFS[5]; cf[ 1] = COEFS[6]; cf[ 2] = COEFS[7]; + } else if ( j == 6) { + cf[ 0] = COEFS[6]; cf[ 1] = COEFS[7]; cf[ 2] = COEFS[8]; + } else if ( j == 7) { + cf[ 0] = COEFS[7]; cf[ 1] = COEFS[8]; cf[ 2] = COEFS[9]; + } else if ( j == 8) { + cf[ 0] = COEFS[8]; cf[ 1] = COEFS[9]; cf[ 2] = COEFS[10]; + } else if ( j == 9) { + cf[ 0] = COEFS[9]; cf[ 1] = COEFS[10]; cf[ 2] = COEFS[11]; + } else if ( j == 10) { + cf[ 0] = COEFS[10]; cf[ 1] = COEFS[11]; cf[ 2] = COEFS[12]; + } else { + cf[ 0] = COEFS[11]; cf[ 1] = COEFS[12]; cf[ 2] = COEFS[13]; + } + + float monomials[ 3] = { t * t, t, 1. }; + logy = dot_f3_f3( monomials, mult_f3_f33( cf, M)); + } + + else if ( logOces <= ODT_KNOT_START) { + logy = logOces; + } + + else if ( logOces >= ODT_KNOT_END) { + logy = logOces * hi_slope + (log10(lumMax) - hi_slope * ODT_KNOT_END); + } + + return pow10(logy); +} + +float odt_tonescale_rev +( // input is absolute luminance, output is absolute luminance + varying float y, + varying float COEFS[14] = DEFAULT_ODT_COEFS, // values of the B-spline control points + varying float hi_slope = DEFAULT_ODT_HI_SLOPE, + varying float lumMin = DEFAULT_YMIN_ABS, + varying float lumMax = DEFAULT_YMAX_ABS +) +{ + // KNOT_Y is luminance of the spline at the knots. + float KNOT_Y[ ODT_KNOT_LEN]; + for (int i = 0; i < ODT_KNOT_LEN; i = i+1) { + KNOT_Y[ i] = ( COEFS[i] + COEFS[i+1]) / 2.; + }; + + float logy = log10( y); + + float logx; + if (logy <= KNOT_Y[0]) { + logx = logy; + } else if (logy >= KNOT_Y[ODT_KNOT_LEN-1]) { + logx = ODT_KNOT_END; + } else { + unsigned int j; + float cf[ 3]; + if ( logy > KNOT_Y[ 0] && logy <= KNOT_Y[ 1]) { + cf[ 0] = COEFS[0]; cf[ 1] = COEFS[1]; cf[ 2] = COEFS[2]; j = 0; + } else if ( logy > KNOT_Y[ 1] && logy <= KNOT_Y[ 2]) { + cf[ 0] = COEFS[1]; cf[ 1] = COEFS[2]; cf[ 2] = COEFS[3]; j = 1; + } else if ( logy > KNOT_Y[ 2] && logy <= KNOT_Y[ 3]) { + cf[ 0] = COEFS[2]; cf[ 1] = COEFS[3]; cf[ 2] = COEFS[4]; j = 2; + } else if ( logy > KNOT_Y[ 3] && logy <= KNOT_Y[ 4]) { + cf[ 0] = COEFS[3]; cf[ 1] = COEFS[4]; cf[ 2] = COEFS[5]; j = 3; + } else if ( logy > KNOT_Y[ 4] && logy <= KNOT_Y[ 5]) { + cf[ 0] = COEFS[4]; cf[ 1] = COEFS[5]; cf[ 2] = COEFS[6]; j = 4; + } else if ( logy > KNOT_Y[ 5] && logy <= KNOT_Y[ 6]) { + cf[ 0] = COEFS[5]; cf[ 1] = COEFS[6]; cf[ 2] = COEFS[7]; j = 5; + } else if ( logy > KNOT_Y[ 6] && logy <= KNOT_Y[ 7]) { + cf[ 0] = COEFS[6]; cf[ 1] = COEFS[7]; cf[ 2] = COEFS[8]; j = 6; + } else if ( logy > KNOT_Y[ 7] && logy <= KNOT_Y[ 8]) { + cf[ 0] = COEFS[7]; cf[ 1] = COEFS[8]; cf[ 2] = COEFS[9]; j = 7; + } else if ( logy > KNOT_Y[ 8] && logy <= KNOT_Y[ 9]) { + cf[ 0] = COEFS[8]; cf[ 1] = COEFS[9]; cf[ 2] = COEFS[10]; j = 8; + } else if ( logy > KNOT_Y[ 9] && logy <= KNOT_Y[10]) { + cf[ 0] = COEFS[9]; cf[ 1] = COEFS[10]; cf[ 2] = COEFS[11]; j = 9; + } else if ( logy > KNOT_Y[10] && logy <= KNOT_Y[11]) { + cf[ 0] = COEFS[10]; cf[ 1] = COEFS[11]; cf[ 2] = COEFS[12]; j = 10; + } else { + cf[ 0] = COEFS[11]; cf[ 1] = COEFS[12]; cf[ 2] = COEFS[13]; j = 11; + } + + const float tmp[ 3] = mult_f3_f33( cf, M); + + float a = tmp[ 0]; + float b = tmp[ 1]; + float c = tmp[ 2]; + c = c - logy; + + const float d = sqrt( b * b - 4. * a * c); + + const float t = ( 2. * c) / ( -d - b); + + logx = ODT_KNOT_START + ( t + j) * ODT_KNOT_INC; + } + + return pow10( logx); +} + + +float cubic_basis_shaper +( + varying float x, + varying float w // full base width of the shaper function (in degrees) +) +{ + float M[4][4] = { { -1./6, 3./6, -3./6, 1./6 }, + { 3./6, -6./6, 3./6, 0./6 }, + { -3./6, 0./6, 3./6, 0./6 }, + { 1./6, 4./6, 1./6, 0./6 } }; + + float knots[5] = { -w/2., + -w/4., + 0., + w/4., + w/2. }; + + float y; + if ((x > knots[0]) && (x < knots[4])) { + float knot_coord = (x - knots[0]) * 4./w; + int j = knot_coord; + float t = knot_coord - j; + + float monomials[4] = { t*t*t, t*t, t, 1. }; + + // (If/else structure required for compatibility with CTL < v1.5.) + if ( j == 3) { + y = monomials[0] * M[0][0] + monomials[1] * M[1][0] + + monomials[2] * M[2][0] + monomials[3] * M[3][0]; + } else if ( j == 2) { + y = monomials[0] * M[0][1] + monomials[1] * M[1][1] + + monomials[2] * M[2][1] + monomials[3] * M[3][1]; + } else if ( j == 1) { + y = monomials[0] * M[0][2] + monomials[1] * M[1][2] + + monomials[2] * M[2][2] + monomials[3] * M[3][2]; + } else if ( j == 0) { + y = monomials[0] * M[0][3] + monomials[1] * M[1][3] + + monomials[2] * M[2][3] + monomials[3] * M[3][3]; + } else + y = 0; + } + + return y * 3/2.; +} + + +float center_hue( float hue, float centerH) +{ + float hueCentered = hue - centerH; + if (hueCentered < -180.) hueCentered = hueCentered + 360.; + else if (hueCentered > 180.) hueCentered = hueCentered - 360.; + return hueCentered; +} + +float uncenter_hue( float hueCentered, float centerH) +{ + float hue = hueCentered + centerH; + if (hue < 0.) hue = hue + 360.; + else if (hue > 360.) hue = hue - 360.; + return hue; +} + +// Regions of hue and intensity are targeted using a cubic basis shaper +// function. The controls for the shape of this function are the center/peak +// (in degrees), and the full width (in degrees) at the base. Values in the +// center of the function get 1.0 of an adjustment while values at the tails +// of the function get 0.0 adjustment. +float[3] scale_C_at_H +( + float rgb[3], + float centerH, // center of targeted hue region (in degrees) + float widthH, // full width at base of targeted hue region (in degrees) + float percentC // percentage of scale: 1.0 is no adjustment (i.e. 100%) +) +{ + float ych[3] = rgb_2_ych( rgb); + + float centeredHue = center_hue( ych[2], centerH); + + float f_H = cubic_basis_shaper( centeredHue, widthH); + + float new_rgb[3]; + if (f_H > 0.0) { + // Scale chroma in red/magenta region + float new_ych[3] = ych; + new_ych[1] = ych[1] * (f_H * (percentC - 1.0) + 1.0); + new_rgb = ych_2_rgb( new_ych); + } else { + // If not in affected hue region, just return original values + // This helps to avoid precision errors that can occur in the RGB->YAB->RGB + // conversion + new_rgb = rgb; + } + + return new_rgb; +} + +float[3] scale_C_at_H_inv +( + float rgb[3], + float centerH, // center of targeted hue region (in degrees) + float widthH, // full width at base of targeted hue region (in degrees) + float percentC // percentage of scale: 1.0 is no adjustment (i.e. 100%) +) +{ + float ych[3] = rgb_2_ych( rgb); + + float centeredHue = center_hue( ych[2], centerH); + + float f_H = cubic_basis_shaper( centeredHue, widthH); + + float new_rgb[3]; + if (f_H > 0.0) { + // Scale chroma in red/magenta region + float new_ych[3] = ych; + new_ych[1] = ych[1] * 1.0/(f_H * (percentC - 1.0) + 1.0); + new_rgb = ych_2_rgb( new_ych); + } else { + // If not in affected hue region, just return original values + // This helps to avoid precision errors that can occur in the RGB->YAB->RGB + // conversion + new_rgb = rgb; + } + + return new_rgb; +} + +int[3] order3( float r, float g, float b) +{ + // Determine sort order, highest to lowest + if (r > g) { + if (g > b) { // r g b, hue [0,60] + int order[3] = {0, 1, 2}; + return order; + } else { + if (r > b) { // r b g, hue [300,360] + int order[3] = {0, 2, 1}; + return order; + } else { // b r g, hue [240,300] + int order[3] = {2, 0, 1}; + return order; + } + } + } + else { + if (r > b) { // g r b, hue [60,120] + int order[3] = {1, 0, 2}; + return order; + } else { + if (g > b) { // g b r, hue [120,180] + int order[3] = {1, 2, 0}; + return order; + } else { // b g r, hue [180,240] + int order[3] = {2, 1, 0}; + return order; + } + } + } +} + +// Modify the hue of post_tone to match pre_tone +float[3] restore_hue_dw3( float pre_tone[3], float post_tone[3]) +{ + int inds[3] = order3( pre_tone[0], pre_tone[1], pre_tone[2]); + + float orig_chroma = pre_tone[ inds[0]] - pre_tone[ inds[2]]; + + float hue_factor = ( pre_tone[ inds[1] ] - pre_tone[ inds[2] ]) / orig_chroma; + + if ( orig_chroma == 0.) hue_factor = 0.; + + float new_chroma = post_tone[ inds[0] ] - post_tone[ inds[2] ]; + + float out[3]; + out[ inds[ 0] ] = post_tone[ inds[0] ]; + out[ inds[ 1] ] = hue_factor * new_chroma + post_tone[ inds[2] ]; + out[ inds[ 2] ] = post_tone[ inds[2] ]; + + return out; +} + +// Functions to compress highlights to allow the simulated white point w/out clipping. +float roll_white_fwd( + float in, // color value to adjust (white scaled to around 1.0) + float new_wht, // white adjustment (e.g. 0.9 for 10% darkening) + float width // adjusted width (e.g. 0.25 for top quarter of the tone scale) + ) +{ + const float x0 = -1.0; + const float x1 = x0 + width; + const float y0 = -new_wht; + const float y1 = x1; + const float m1 = (x1 - x0); + const float a = y0 - y1 + m1; + const float b = 2 * ( y1 - y0) - m1; + const float c = y0; + const float t = (-in - x0) / (x1 - x0); + float out = 0.0; + if ( t < 0.0) + out = -(t * b + c); + else if ( t > 1.0) + out = in; + else + out = -(( t * a + b) * t + c); + return out; +} + +float roll_white_rev( + float in, // color value to adjust (white scaled to around 1.0) + float new_wht, // white adjustment (e.g. 0.9 for 10% darkening) + float width // adjusted width (e.g. 0.25 for top quarter of the tone scale) + ) +{ + const float x0 = -1.0; + const float x1 = x0 + width; + const float y0 = -new_wht; + const float y1 = x1; + const float m1 = (x1 - x0); + const float a = y0 - y1 + m1; + const float b = 2. * ( y1 - y0) - m1; + float c = y0; + float out = 0.0; + if ( -in < y0) + out = -x0; + else if ( -in > y1) + out = in; + else { + c = c + in; + const float discrim = sqrt( b * b - 4. * a * c); + const float t = ( 2. * c) / ( -discrim - b); + out = -(( t * ( x1 - x0)) + x0); + } + return out; +} diff --git a/Xcode/NukeCtl/NukeCtlTests/utilities-color.ctl b/Xcode/NukeCtl/NukeCtlTests/utilities-color.ctl new file mode 100644 index 00000000..7fdfb873 --- /dev/null +++ b/Xcode/NukeCtl/NukeCtlTests/utilities-color.ctl @@ -0,0 +1,282 @@ +// +// utilities-color.ctl +// v0.2.2 +// +// Color related constants and functions +// + +/* ---- Chromaticities of some common primary sets ---- */ + +const Chromaticities ACES_PRI = +{ + { 0.73470, 0.26530}, + { 0.00000, 1.00000}, + { 0.00010, -0.07700}, + { 0.32168, 0.33767} +}; + +const Chromaticities REC709_PRI = +{ + { 0.64000, 0.33000}, + { 0.30000, 0.60000}, + { 0.15000, 0.06000}, + { 0.31270, 0.32900} +}; + +const Chromaticities P3D60_PRI = +{ + { 0.68000, 0.32000}, + { 0.26500, 0.69000}, + { 0.15000, 0.06000}, + { 0.32168, 0.33767} +}; + +const Chromaticities P3DCI_PRI = +{ + { 0.68000, 0.32000}, + { 0.26500, 0.69000}, + { 0.15000, 0.06000}, + { 0.31400, 0.35100} +}; + +const Chromaticities ARRI_ALEXA_WG_PRI = +{ + {0.68400, 0.31300}, + {0.22100, 0.84800}, + {0.08610, -0.10200}, + {0.31270, 0.32900} +}; + +const Chromaticities REC2020_PRI = +{ + {0.70800, 0.29200}, + {0.17000, 0.79700}, + {0.13100, 0.04600}, + {0.31270, 0.32900} +}; + +const Chromaticities RIMMROMM_PRI = +{ + {0.7347, 0.2653}, + {0.1596, 0.8404}, + {0.0366, 0.0001}, + {0.3457, 0.3585} +}; + + + + +/* ---- Conversion Functions ---- */ +// Various transformations between color encodings and data representations +// + +// Transformations between CIE XYZ tristimulus values and CIE x,y +// chromaticity coordinates +float[3] XYZ_2_xyY( float XYZ[3]) +{ + float xyY[3]; + xyY[0] = XYZ[0] / (XYZ[0] + XYZ[1] + XYZ[2]); + xyY[1] = XYZ[1] / (XYZ[0] + XYZ[1] + XYZ[2]); + xyY[2] = XYZ[1]; + + return xyY; +} + +float[3] xyY_2_XYZ( input varying float xyY[3]) +{ + float XYZ[3]; + XYZ[0] = xyY[0] * xyY[2] / xyY[1]; + XYZ[1] = xyY[2]; + XYZ[2] = (1.0 - xyY[0] - xyY[1]) * xyY[2] / xyY[1]; + + return XYZ; +} + + +// Transformations between an RGB space, a "Yab" space, and a "YCH" space +const float sqrt3over4 = 0.433012701892219; // sqrt(3.)/4. +const float RGB_2_YAB_MAT[3][3] = { + {1./3., 1./2., 0.0}, + {1./3., -1./4., sqrt3over4}, + {1./3., -1./4., -sqrt3over4} +}; + +float[3] rgb_2_yab( float rgb[3]) +{ + float yab[3] = mult_f3_f33( rgb, RGB_2_YAB_MAT); + + return yab; +} + +float[3] yab_2_rgb( float yab[3]) +{ + float rgb[3] = mult_f3_f33( yab, invert_f33(RGB_2_YAB_MAT)); + + return rgb; +} + +float[3] yab_2_ych( float yab[3]) +{ + float ych[3] = yab; + + ych[1] = sqrt( pow( yab[1], 2.) + pow( yab[2], 2.) ); + + ych[2] = atan2( yab[2], yab[1] ) * (180.0 / M_PI); + if (ych[2] < 0.0) ych[2] = ych[2] + 360.; + + return ych; +} + +float[3] ych_2_yab( float ych[3] ) +{ + float yab[3]; + yab[0] = ych[0]; + + float h = ych[2] * (M_PI / 180.0); + yab[1] = ych[1]*cos(h); + yab[2] = ych[1]*sin(h); + + return yab; +} + +float[3] rgb_2_ych( float rgb[3]) +{ + return yab_2_ych( rgb_2_yab( rgb)); +} + +float[3] ych_2_rgb( float ych[3]) +{ + return yab_2_rgb( ych_2_yab( ych)); +} + + + + +/* ---- Chromatic Adaptation ---- */ + +const float CONE_RESP_MAT_BRADFORD[3][3] = { + {0.89510, -0.75020, 0.03890}, + {0.26640, 1.71350, -0.06850}, + {-0.16140, 0.03670, 1.02960} +}; + +const float CONE_RESP_MAT_CAT02[3][3] = { + {0.73280, -0.70360, 0.00300}, + {0.42960, 1.69750, 0.01360}, + {-0.16240, 0.00610, 0.98340} +}; + +float[3][3] calculate_cat_matrix + ( float src_xy[2], // Chromaticity of source white + float des_xy[2], // Chromaticity of destination white + float coneRespMat[3][3] = CONE_RESP_MAT_BRADFORD + ) +{ + // + // Calculates and returns a 3x3 Von Kries chromatic adaptation transform + // from src_xy to des_xy using the cone response primaries defined + // by coneRespMat. By default, coneRespMat is set to CONE_RESP_MAT_BRADFORD. + // The default coneRespMat can be overridden at runtime. + // + + const float src_xyY[3] = { src_xy[0], src_xy[1], 1. }; + const float des_xyY[3] = { des_xy[0], des_xy[1], 1. }; + + float src_XYZ[3] = xyY_2_XYZ( src_xyY ); + float des_XYZ[3] = xyY_2_XYZ( des_xyY ); + + float src_coneResp[3] = mult_f3_f33( src_XYZ, coneRespMat); + float des_coneResp[3] = mult_f3_f33( des_XYZ, coneRespMat); + + float vkMat[3][3] = { + { des_coneResp[0] / src_coneResp[0], 0.0, 0.0 }, + { 0.0, des_coneResp[1] / src_coneResp[1], 0.0 }, + { 0.0, 0.0, des_coneResp[2] / src_coneResp[2] } + }; + + float cat_matrix[3][3] = mult_f33_f33( coneRespMat, transpose_f33( mult_f33_f33( transpose_f33( invert_f33( coneRespMat ) ), vkMat ) ) ); + + return cat_matrix; +} + + + + + +float[3][3] calc_sat_adjust_matrix + ( input varying float sat, + input varying float rgb2Y[3] + ) +{ + // + // This function determines the terms for a 3x3 saturation matrix that is + // based on the luminance of the input. + // + float M[3][3]; + M[0][0] = (1.0 - sat) * rgb2Y[0] + sat; + M[1][0] = (1.0 - sat) * rgb2Y[0]; + M[2][0] = (1.0 - sat) * rgb2Y[0]; + + M[0][1] = (1.0 - sat) * rgb2Y[1]; + M[1][1] = (1.0 - sat) * rgb2Y[1] + sat; + M[2][1] = (1.0 - sat) * rgb2Y[1]; + + M[0][2] = (1.0 - sat) * rgb2Y[2]; + M[1][2] = (1.0 - sat) * rgb2Y[2]; + M[2][2] = (1.0 - sat) * rgb2Y[2] + sat; + + M = transpose_f33(M); + return M; +} + + + + + +/* ---- Signal encode/decode functions ---- */ + +float moncurve_f( float x, float gamma, float offs ) +{ + // Forward monitor curve + float y; + const float fs = (( gamma - 1.0) / offs) * pow( offs * gamma / ( ( gamma - 1.0) * ( 1.0 + offs)), gamma); + const float xb = offs / ( gamma - 1.0); + if ( x >= xb) + y = pow( ( x + offs) / ( 1.0 + offs), gamma); + else + y = x * fs; + return y; +} + +float moncurve_r( float y, float gamma, float offs ) +{ + // Reverse monitor curve + float x; + const float yb = pow( offs * gamma / ( ( gamma - 1.0) * ( 1.0 + offs)), gamma); + const float rs = pow( ( gamma - 1.0) / offs, gamma - 1.0) * pow( ( 1.0 + offs) / gamma, gamma); + if ( y >= yb) + x = ( 1.0 + offs) * pow( y, 1.0 / gamma) - offs; + else + x = y * rs; + return x; +} + +float bt1886_f( float V, float gamma, float Lw, float Lb) +{ + // The reference EOTF specified in Rec. ITU-R BT.1886 + // L = a(max[(V+b),0])^g + float a = pow( pow( Lw, 1./gamma) - pow( Lb, 1./gamma), gamma); + float b = pow( Lb, 1./gamma) / ( pow( Lw, 1./gamma) - pow( Lb, 1./gamma)); + float L = a * pow( max( V + b, 0.), gamma); + return L; +} + +float bt1886_r( float L, float gamma, float Lw, float Lb) +{ + // The reference EOTF specified in Rec. ITU-R BT.1886 + // L = a(max[(V+b),0])^g + float a = pow( pow( Lw, 1./gamma) - pow( Lb, 1./gamma), gamma); + float b = pow( Lb, 1./gamma) / ( pow( Lw, 1./gamma) - pow( Lb, 1./gamma)); + float V = pow( max( L / a, 0.), 1./gamma) - b; + return V; +} \ No newline at end of file diff --git a/Xcode/NukeCtl/NukeCtlTests/utilities.ctl b/Xcode/NukeCtl/NukeCtlTests/utilities.ctl new file mode 100644 index 00000000..67e763d3 --- /dev/null +++ b/Xcode/NukeCtl/NukeCtlTests/utilities.ctl @@ -0,0 +1,141 @@ +// +// utilities.ctl +// v0.2.2 +// +// Generic functions that may be useful for writing CTL programs +// + +float min( float a, float b) +{ + if (a < b) + return a; + else + return b; +} + +float max( float a, float b) +{ + if (a > b) + return a; + else + return b; +} + +float min_f3( float a[3]) +{ + return min( a[0], min( a[1], a[2])); +} + +float max_f3( float a[3]) +{ + return max( a[0], max( a[1], a[2])); +} + +float clip( float v) +{ + return min(v, 1.0); +} + +float[3] clip_f3( float in[3]) +{ + float out[3]; + out[0] = clip( in[0]); + out[1] = clip( in[1]); + out[2] = clip( in[2]); + + return out; +} + +float clamp( float in, float clampMin, float clampMax) +{ + // Note: Numeric constants can be used in place of a min or max value (i.e. + // use HALF_NEG_INF in place of clampMin or HALF_POS_INF in place of clampMax) + + return max( clampMin, min(in, clampMax)); +} + +float[3] clamp_f3( float in[3], float clampMin, float clampMax) +{ + // Note: Numeric constants can be used in place of a min or max value (i.e. + // use HALF_NEG_INF in place of clampMin or HALF_POS_INF in place of clampMax) + + float out[3]; + out[0] = clamp( in[0], clampMin, clampMax); + out[1] = clamp( in[1], clampMin, clampMax); + out[2] = clamp( in[2], clampMin, clampMax); + + return out; +} + +float[3] add_f_f3( float a, float b[3]) +{ + float out[3]; + out[0] = a + b[0]; + out[1] = a + b[1]; + out[2] = a + b[2]; + return out; +} + +float[3] pow_f3( float a[3], float b) +{ + float out[3]; + out[0] = pow(a[0], b); + out[1] = pow(a[1], b); + out[2] = pow(a[2], b); + return out; +} + +float[3] pow10_f3( float a[3]) +{ + float out[3]; + out[0] = pow10(a[0]); + out[1] = pow10(a[1]); + out[2] = pow10(a[2]); + return out; +} + +float[3] log10_f3( float a[3]) +{ + float out[3]; + out[0] = log10(a[0]); + out[1] = log10(a[1]); + out[2] = log10(a[2]); + return out; +} + +float round(float x) +{ + float x1; + + if (x < 0.0) + x1 = floor( x - 0.5); + else + x1 = floor( x + 0.5); + + return x1; +} + +float log2(float x) +{ + return log(x) / log(2.); +} + +void print_f3( float m[ 3]) +{ + print( m[ 0], ",\t", m[ 1], ",\t", m[ 2], "\n"); +} + +void print_f33( float m[ 3][ 3]) +{ + print( "{ {", m[ 0][ 0], ",\t", m[ 0][ 1], ",\t", m[ 0][ 2], "},\n"); + print( " {", m[ 1][ 0], ",\t", m[ 1][ 1], ",\t", m[ 1][ 2], "},\n"); + print( " {", m[ 2][ 0], ",\t", m[ 2][ 1], ",\t", m[ 2][ 2], "} };\n"); +} + +void print_f44( float m[ 4][ 4]) +{ + print( "{ { ", m[ 0][ 0], ",\t", m[ 0][ 1], ",\t", m[ 0][ 2], ",\t", m[ 0][ 3], "},\n"); + print( " { ", m[ 1][ 0], ",\t", m[ 1][ 1], ",\t", m[ 1][ 2], ",\t", m[ 1][ 3], "},\n"); + print( " { ", m[ 2][ 0], ",\t", m[ 2][ 1], ",\t", m[ 2][ 2], ",\t", m[ 2][ 3], "},\n"); + print( " { ", m[ 3][ 0], ",\t", m[ 3][ 1], ",\t", m[ 3][ 2], ",\t", m[ 3][ 3], "} };\n"); +} diff --git a/cmake/modules/FindNuke.cmake b/cmake/modules/FindNuke.cmake new file mode 100644 index 00000000..b0956869 --- /dev/null +++ b/cmake/modules/FindNuke.cmake @@ -0,0 +1,76 @@ +# +# A simple cmake find module for the Nuke NDK +# + +set( NUKE_INSTALL_PATH $ENV{NDKDIR} CACHE PATH "Path to folder where Nuke is installed" ) + +if(EXISTS ${NUKE_INSTALL_PATH}) + get_filename_component( NUKE_VERSION "${NUKE_INSTALL_PATH}" NAME ) + + set( NUKE_OSX_SUFFIX ${NUKE_VERSION}.app/Contents/MacOS ) + find_path( NUKE_INCLUDE_DIR + NAMES DDImage/Op.h + PATHS ${NUKE_INSTALL_PATH} + PATH_SUFFIXES include ${NUKE_OSX_SUFFIX}/include ) + + if(NUKE_INCLUDE_DIR AND EXISTS "${NUKE_INCLUDE_DIR}/DDImage/ddImageVersionNumbers.h") + file(STRINGS "${NUKE_INCLUDE_DIR}/DDImage/ddImageVersionNumbers.h" + nuke_version_str + REGEX "^#define[\t ]+kDDImageVersion[\t ]+\".*") + + string(REGEX REPLACE "^#define[\t ]+kDDImageVersion[\t ]+\"([^ \\n]*)\".*" + "\\1" NUKE_VERSION "${nuke_version_str}") + unset(nuke_version_str) + else() + string(REGEX REPLACE "^Nuke(.*)" + "\\1" NUKE_VERSION "${NUKE_VERSION}") + endif() + string(REGEX REPLACE "^(.*)v.*" + "\\1" NUKE_API_VERSION "${NUKE_VERSION}") + + find_library(NUKE_LIBRARY + NAMES DDImage + PATHS ${NUKE_INSTALL_PATH} + PATH_SUFFIXES ${NUKE_OSX_SUFFIX}) +else() + if(NOT Nuke_FIND_QUIETLY) + if("${NUKE_INSTALL_PATH}" STREQUAL "") + message( STATUS "NUKE_INSTALL_PATH has not been set for cmake, please set the NDKDIR environment variable and clear the cmake cache or use the CMake GUI to specify" ) + else() + message( STATUS "NUKE_INSTALL_PATH '${NUKE_INSTALL_PATH}' does not exist, please specify by setting the NDKDIR environment variable and clearing the cmake cache or use the CMake GUI to specify" ) + endif() + endif() +endif() + +# +# This is kind of a hack, but it allows us to pass in a flag whether +# we have to copy the DDImage library locally so we can avoid running +# afoul of the nuke Ilm libraries in case we are using a different +# version +# +if(Nuke_FIND_COMPONENTS) + foreach( component ${Nuke_FIND_COMPONENTS} ) + string( TOUPPER ${component} _COMPONENT ) + set(NUKE_${_COMPONENT} 1) + endforeach() +endif() + +if(NUKE_AVOIDNUKEILMBASE) + file(COPY ${NUKE_LIBRARY} DESTINATION ${CMAKE_BINARY_DIR}) + get_filename_component( libddimage "${NUKE_LIBRARY}" NAME ) + set(NUKE_LIBRARY ${CMAKE_BINARY_DIR}/${libddimage}) +endif() +set(NUKE_LIBRARIES ${NUKE_LIBRARY} ) +set(NUKE_INCLUDE_DIRS ${NUKE_INCLUDE_DIR} ) +get_filename_component(NUKE_LIBRARY_DIR "${NUKE_LIBRARY}" PATH) +set(NUKE_LIBRARY_DIRS ${NUKE_LIBRARY_DIR}) + +include(FindPackageHandleStandardArgs) +# handle the QUIETLY and REQUIRED arguments and set NUKE_FOUND to TRUE +# if all listed variables are TRUE +find_package_handle_standard_args(Nuke + REQUIRED_VARS NUKE_LIBRARY NUKE_INCLUDE_DIR + VERSION_VAR NUKE_VERSION + FAIL_MESSAGE "Unable to find NUKE NDK library" ) + +mark_as_advanced(NUKE_INCLUDE_DIR NUKE_LIBRARY) diff --git a/lib/dpx/dpx_raw.hh b/lib/dpx/dpx_raw.hh index b3e57b72..5c41bed8 100644 --- a/lib/dpx/dpx_raw.hh +++ b/lib/dpx/dpx_raw.hh @@ -53,7 +53,7 @@ /////////////////////////////////////////////////////////////////////////// #if !defined(CTL_DPX_RAW_INTERNAL_INCLUDE) -#define CRL_DPX_RAW_INTERNAL_INCLUDE +#define CTL_DPX_RAW_INTERNAL_INCLUDE namespace ctl { diff --git a/unittest/ctlrender/test.sh b/unittest/ctlrender/test.sh index b125b815..8faf5be4 100755 --- a/unittest/ctlrender/test.sh +++ b/unittest/ctlrender/test.sh @@ -3,15 +3,17 @@ CTLRENDER=$1 mkdir output +CTLRENDER=../../ctlrender/ctlrender + for J in tiff8 tiff16 tiff32 dpx8 dpx10 dpx12 dpx16; do for I in bars_cinepaint_10.dpx bars_nuke_10_be.dpx bars_nuke_10_le.dpx bars_nuke_12_be.dpx bars_nuke_12_le.dpx bars_nuke_16_be.dpx bars_nuke_16_le.dpx bars_nuke_8_be.dpx bars_nuke_8_le.dpx bars_photoshop_16_be_interleaved.tif bars_photoshop_16_be_planar.tif bars_photoshop_16_le_interleaved.tif bars_photoshop_16_le_planar.tif bars_photoshop_32_be_interleaved.tif bars_photoshop_32_be_planar.tif bars_photoshop_32_le_interleaved.tif bars_photoshop_32_le_planar.tif bars_photoshop_8_be_interleaved.tif bars_photoshop_8_be_planar.tif bars_photoshop_8_le_interleaved.tif bars_photoshop_8_le_planar.tif ; do name=`echo $I | sed -e 's/\..*//'` ext=`echo $J | sed -e 's/[0-9]//g'` echo ${I} '->' ${J} - $CTLRENDER -ctl unity.ctl -format ${J} -force ${I} output/${name}_${J}.${ext} + ${CTLRENDER} -ctl unity.ctl -format ${J} -force ${I} output/${name}_${J}.${ext} done echo ${J} unity test - $CTLRENDER -ctl unity.ctl -format ${J} -force bars_photoshop_32_be_planar.tif output/bars_tiff32_${J}.${ext} - $CTLRENDER -ctl unity.ctl -format tiff32 -force output/bars_tiff32_${J}.${ext} output/bars_tiff32_${J}_tiff32.tiff + ${CTLRENDER} -ctl unity.ctl -format ${J} -force bars_photoshop_32_be_planar.tif output/bars_tiff32_${J}.${ext} + ${CTLRENDER} -ctl unity.ctl -format tiff32 -force output/bars_tiff32_${J}.${ext} output/bars_tiff32_${J}_tiff32.tiff done From 2c9283cb2b2c576cbb388726dd84e1b0599267dc Mon Sep 17 00:00:00 2001 From: Joseph Goldstone Date: Fri, 18 Jul 2014 12:21:31 -0700 Subject: [PATCH 02/12] temporarily comment out ctlrender unit test so that 'brew install ctl --build-from-source --HEAD' works --- unittest/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unittest/CMakeLists.txt b/unittest/CMakeLists.txt index 553b5536..5eb24fb0 100644 --- a/unittest/CMakeLists.txt +++ b/unittest/CMakeLists.txt @@ -6,5 +6,5 @@ add_custom_target( check COMMAND ${CMAKE_CTEST_COMMAND} ) add_subdirectory( IlmCtl ) add_subdirectory( IlmCtlMath ) add_subdirectory( IlmImfCtl ) -add_subdirectory( ctlrender ) +# add_subdirectory( ctlrender ) From 46204297852b15f837eedce5d0b152886fec83c1 Mon Sep 17 00:00:00 2001 From: Joseph Goldstone Date: Mon, 21 Jul 2014 13:37:33 -0700 Subject: [PATCH 03/12] Incorporate changes from Jonathan Egstad fixing issue of CTL nodes being inactive when restored from saved script. --- Nuke_CTL/NukeCtl.cpp | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/Nuke_CTL/NukeCtl.cpp b/Nuke_CTL/NukeCtl.cpp index 7c5a31ca..594d4b00 100644 --- a/Nuke_CTL/NukeCtl.cpp +++ b/Nuke_CTL/NukeCtl.cpp @@ -109,6 +109,14 @@ class NukeCtlIop : public PixelIop { h.append(__TIME__); } + void expand_ctl_path(std::string& file) { + if (script_expand(knob("ctl_path")->get_text(&outputContext())) && script_result()) + file = script_result(); + else + file = ""; + script_unlock(); + } + void pixel_engine(const Row &in, int y, int x, int r, ChannelMask, Row &); void knobs(Knob_Callback); void load_transform(const char* const modulePath, const char* const ctlPath); @@ -179,10 +187,7 @@ void NukeCtlIop::knobs(Knob_Callback f) { ClearFlags(f, Knob::STARTLINE); readKnob = File_knob(f, &ctlPath, "ctl_path", "CTL file Path"); SetFlags(f, Knob::EARLY_STORE); - if (f.makeKnobs() && transform == NULL && strlen(ctlPath) > 0) - { - load_transform(modulePath, ctlPath); - } + SetFlags(f, Knob::KNOB_CHANGED_ALWAYS); Script_knob(f, "knob reload_count [expr [value reload_count] + 1]", "reload"); Int_knob(f, &reloadCount, "reload_count", INVISIBLE); SetFlags(f, Knob::DO_NOT_WRITE); @@ -205,19 +210,19 @@ int NukeCtlIop::knob_changed(Knob *k) { // if the module path is changed, make sure it is valid if (k->is("module_path")) { - if (strlen(ctlPath) > 0) - { - load_transform(modulePath, ctlPath); - } - return 1; + std::string file; + expand_ctl_path(file); + if (!file.empty()) + load_transform(modulePath, file.c_str()); + return 1; } if (k->is("ctl_path") || k->is("reload")) { - if (strlen(ctlPath) > 0) - { - load_transform(modulePath, ctlPath); - } - return 1; + std::string file; + expand_ctl_path(file); + if (!file.empty()) + load_transform(modulePath, file.c_str()); + return 1; } return Iop::knob_changed(k); } From ab1f007a6dd7140becc8fc8ed1b337a3f7180902 Mon Sep 17 00:00:00 2001 From: Joseph Goldstone Date: Mon, 21 Jul 2014 15:23:22 -0700 Subject: [PATCH 04/12] Remove leading "lib" on Nuke CTL plugin, since Nuke doesn't want such (and ignores any plugin that has it). --- Nuke_CTL/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Nuke_CTL/CMakeLists.txt b/Nuke_CTL/CMakeLists.txt index 8ae85c6f..7d9fe013 100644 --- a/Nuke_CTL/CMakeLists.txt +++ b/Nuke_CTL/CMakeLists.txt @@ -43,6 +43,8 @@ if(NUKE_FOUND) NukeCtlTransform.cpp ) + set_target_properties(NukeCtl PROPERTIES PREFIX "") + target_link_libraries( NukeCtl IlmCtl IlmCtlMath IlmCtlSimd IlmThread Half Iex ) target_link_libraries( NukeCtl ${IlmBase_LIBRARIES} ${IlmBase_LDFLAGS_OTHER} ) link_directories( ${NUKE_LIBRARY_DIR} ) From 86da3df95bb65ca634c957605655918bc988d912 Mon Sep 17 00:00:00 2001 From: Joseph Goldstone Date: Mon, 21 Jul 2014 15:50:11 -0700 Subject: [PATCH 05/12] Add back ctlrender unit tests, incorporating fixes suggested by Kimball Thurston 3rd. --- unittest/CMakeLists.txt | 2 +- unittest/ctlrender/CMakeLists.txt | 4 +++- unittest/ctlrender/test.sh | 3 +-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/unittest/CMakeLists.txt b/unittest/CMakeLists.txt index 5eb24fb0..553b5536 100644 --- a/unittest/CMakeLists.txt +++ b/unittest/CMakeLists.txt @@ -6,5 +6,5 @@ add_custom_target( check COMMAND ${CMAKE_CTEST_COMMAND} ) add_subdirectory( IlmCtl ) add_subdirectory( IlmCtlMath ) add_subdirectory( IlmImfCtl ) -# add_subdirectory( ctlrender ) +add_subdirectory( ctlrender ) diff --git a/unittest/ctlrender/CMakeLists.txt b/unittest/ctlrender/CMakeLists.txt index 5f02aad1..ea0f6d11 100644 --- a/unittest/ctlrender/CMakeLists.txt +++ b/unittest/ctlrender/CMakeLists.txt @@ -6,4 +6,6 @@ add_test( COMMAND ./test.sh $ ) -#add_dependencies(check ctlrender) +set_tests_properties(ctlrender PROPERTIES ENVIRONMENT "PATH=${CMAKE_BINARY_DIR}/ctlrender:$ENV{PATH}") + +add_dependencies(check ctlrender) diff --git a/unittest/ctlrender/test.sh b/unittest/ctlrender/test.sh index 8faf5be4..711dcfdf 100755 --- a/unittest/ctlrender/test.sh +++ b/unittest/ctlrender/test.sh @@ -1,9 +1,8 @@ #! /bin/bash -CTLRENDER=$1 mkdir output -CTLRENDER=../../ctlrender/ctlrender +CTLRENDER=ctlrender for J in tiff8 tiff16 tiff32 dpx8 dpx10 dpx12 dpx16; do for I in bars_cinepaint_10.dpx bars_nuke_10_be.dpx bars_nuke_10_le.dpx bars_nuke_12_be.dpx bars_nuke_12_le.dpx bars_nuke_16_be.dpx bars_nuke_16_le.dpx bars_nuke_8_be.dpx bars_nuke_8_le.dpx bars_photoshop_16_be_interleaved.tif bars_photoshop_16_be_planar.tif bars_photoshop_16_le_interleaved.tif bars_photoshop_16_le_planar.tif bars_photoshop_32_be_interleaved.tif bars_photoshop_32_be_planar.tif bars_photoshop_32_le_interleaved.tif bars_photoshop_32_le_planar.tif bars_photoshop_8_be_interleaved.tif bars_photoshop_8_be_planar.tif bars_photoshop_8_le_interleaved.tif bars_photoshop_8_le_planar.tif ; do From 50aed1b19f7ef09e7b515f84f93d55979f3bd8c2 Mon Sep 17 00:00:00 2001 From: Joseph Goldstone Date: Fri, 12 Dec 2014 13:56:47 -0800 Subject: [PATCH 06/12] Get CTL to compile when IlmBase and OpenEXR are not in the usual places; remove -pthread flag from IlmThread and OpenEXR compilation. --- cmake/modules/FindIlmBase.cmake | 2 +- cmake/modules/FindOpenEXR.cmake | 2 +- lib/IlmCtlSimd/CMakeLists.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cmake/modules/FindIlmBase.cmake b/cmake/modules/FindIlmBase.cmake index a51cdd8b..e960011d 100644 --- a/cmake/modules/FindIlmBase.cmake +++ b/cmake/modules/FindIlmBase.cmake @@ -28,9 +28,9 @@ if(PC_ILMBASE_FOUND) endif() else() if(UNIX) - set(IlmBase_CFLAGS "-pthread") if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") else() + set(IlmBase_CFLAGS "-pthread") set(OpenEXR_LDFLAGS "-pthread") endif() endif() diff --git a/cmake/modules/FindOpenEXR.cmake b/cmake/modules/FindOpenEXR.cmake index 40c1baa3..048bd7bc 100644 --- a/cmake/modules/FindOpenEXR.cmake +++ b/cmake/modules/FindOpenEXR.cmake @@ -28,9 +28,9 @@ if(PC_OPENEXR_FOUND) endif() else() if(UNIX) - set(OpenEXR_CFLAGS "-pthread") if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") else() + set(OpenEXR_CFLAGS "-pthread") set(OpenEXR_LDFLAGS "-pthread") endif() endif() diff --git a/lib/IlmCtlSimd/CMakeLists.txt b/lib/IlmCtlSimd/CMakeLists.txt index 2ba792a2..19a0fbed 100644 --- a/lib/IlmCtlSimd/CMakeLists.txt +++ b/lib/IlmCtlSimd/CMakeLists.txt @@ -1,7 +1,7 @@ include_directories( "${CMAKE_CURRENT_SOURCE_DIR}" "${PROJECT_SOURCE_DIR}/lib/IlmCtl" "${PROJECT_SOURCE_DIR}/lib/IlmCtlMath" ) add_executable( halfExpLogTable halfExpLogTable.cpp ) -target_link_libraries( halfExpLogTable Half ) +target_link_libraries( halfExpLogTable Half ${IlmBase_LDFLAGS_OTHER} ) add_custom_command( OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/halfExpLogTable.h" COMMAND halfExpLogTable "${CMAKE_CURRENT_BINARY_DIR}/halfExpLogTable.h" "${CMAKE_CURRENT_BINARY_DIR}/halfExpLog.h" From 7850ec168647f87efcf3616ee72b2d91d534dcdd Mon Sep 17 00:00:00 2001 From: Joseph Goldstone Date: Fri, 12 Dec 2014 15:45:36 -0800 Subject: [PATCH 07/12] Comment out ctlrender again; don't reinstate until we can search for it in CMAKE_INSTALL_PREFIX/lib as well as /usr/local/lib. --- unittest/CMakeLists.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/unittest/CMakeLists.txt b/unittest/CMakeLists.txt index 553b5536..6e1b7f40 100644 --- a/unittest/CMakeLists.txt +++ b/unittest/CMakeLists.txt @@ -6,5 +6,8 @@ add_custom_target( check COMMAND ${CMAKE_CTEST_COMMAND} ) add_subdirectory( IlmCtl ) add_subdirectory( IlmCtlMath ) add_subdirectory( IlmImfCtl ) -add_subdirectory( ctlrender ) +# This needs to be able to find aces_container.dylib, and the hints should include +# not just /usr/local/lib, but CMAKE_INSTALL_PREFIX/lib as well. But I don't want +# to take the time today to write FindAcesContainer. +# add_subdirectory( ctlrender ) From 093a935f9029f5161040e9313729ea0db15fcaa7 Mon Sep 17 00:00:00 2001 From: Joseph Goldstone Date: Fri, 12 Dec 2014 23:23:38 -0800 Subject: [PATCH 08/12] Use RPATH to set install names etc. --- CMakeLists.txt | 29 +++++++++--------- OpenEXR_CTL/exr_ctl_exr/CMakeLists.txt | 2 ++ OpenEXR_CTL/exrdpx/CMakeLists.txt | 2 +- .../NukeCtl/NukeCtl.xcodeproj/project.pbxproj | 30 +++++++++---------- .../xcshareddata/NukeCtl.xccheckout | 12 ++++---- ctlrender/CMakeLists.txt | 2 ++ 6 files changed, 41 insertions(+), 36 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 02d93c1c..628f5e0a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,20 +18,21 @@ else() endif() set(INSTALL_CMAKE_DIR ${DEF_INSTALL_CMAKE_DIR} CACHE PATH "Install directory for project CMake files" ) -# use, i.e. don't skip the full RPATH for the build tree -SET(CMAKE_SKIP_BUILD_RPATH FALSE) -# when building, don't use the install RPATH already -# (but later on when installing) -SET(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) -#SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") -# add the automatically determined parts of the RPATH -# which point to directories outside the build tree to the install RPATH -SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) -# the RPATH to be used when installing, but only if it's not a system directory -LIST(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${CMAKE_INSTALL_PREFIX}/lib" isSystemDir) -IF("${isSystemDir}" STREQUAL "-1") - SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") -ENDIF("${isSystemDir}" STREQUAL "-1") +# # use, i.e. don't skip the full RPATH for the build tree +# SET(CMAKE_SKIP_BUILD_RPATH FALSE) +# # when building, don't use the install RPATH already +# # (but later on when installing) +# SET(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) +# #SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") +# # add the automatically determined parts of the RPATH +# # which point to directories outside the build tree to the install RPATH +# SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) +# # the RPATH to be used when installing, but only if it's not a system directory +# LIST(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${CMAKE_INSTALL_PREFIX}/lib" isSystemDir) +# IF("${isSystemDir}" STREQUAL "-1") +# SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") +# ENDIF("${isSystemDir}" STREQUAL "-1") +set(CMAKE_MACOSX_RPATH 1) ## convert install paths to absolute diff --git a/OpenEXR_CTL/exr_ctl_exr/CMakeLists.txt b/OpenEXR_CTL/exr_ctl_exr/CMakeLists.txt index e396ec5a..0f44358f 100644 --- a/OpenEXR_CTL/exr_ctl_exr/CMakeLists.txt +++ b/OpenEXR_CTL/exr_ctl_exr/CMakeLists.txt @@ -23,3 +23,5 @@ target_link_libraries( exr_ctl_exr ${OpenEXR_LIBRARIES} ${OpenEXR_LDFLAGS_OTHER} install( TARGETS exr_ctl_exr DESTINATION ${INSTALL_BIN_DIR} ) install( FILES change_saturation.ctl DESTINATION ${INSTALL_LIB_DIR}/CTL ) + +set_target_properties(exr_ctl_exr PROPERTIES install_rpath "@loader_path/../lib") diff --git a/OpenEXR_CTL/exrdpx/CMakeLists.txt b/OpenEXR_CTL/exrdpx/CMakeLists.txt index 50bd116e..b3b4e008 100644 --- a/OpenEXR_CTL/exrdpx/CMakeLists.txt +++ b/OpenEXR_CTL/exrdpx/CMakeLists.txt @@ -24,4 +24,4 @@ install( TARGETS exrdpx DESTINATION ${INSTALL_BIN_DIR} ) install( FILES transform_DPX_EXR.ctl transform_EXR_DPX.ctl DESTINATION ${INSTALL_LIB_DIR}/CTL ) - +set_target_properties(exrdpx PROPERTIES install_rpath "@loader_path/../lib") diff --git a/Xcode/NukeCtl/NukeCtl.xcodeproj/project.pbxproj b/Xcode/NukeCtl/NukeCtl.xcodeproj/project.pbxproj index 36eafb04..f285032d 100644 --- a/Xcode/NukeCtl/NukeCtl.xcodeproj/project.pbxproj +++ b/Xcode/NukeCtl/NukeCtl.xcodeproj/project.pbxproj @@ -162,15 +162,15 @@ 594B4E3818134DF8003C263C /* NukeCtlTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NukeCtlTransform.h; path = ../../../Nuke_CTL/NukeCtlTransform.h; sourceTree = ""; }; 594B4E3918134DF8003C263C /* NukeCtlUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NukeCtlUtils.cpp; path = ../../../Nuke_CTL/NukeCtlUtils.cpp; sourceTree = ""; }; 594B4E3A18134DF8003C263C /* NukeCtlUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NukeCtlUtils.h; path = ../../../Nuke_CTL/NukeCtlUtils.h; sourceTree = ""; }; - 594B4E4A18134E6B003C263C /* libDDImage.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libDDImage.dylib; path = ../../../../../../../Applications/Nuke8.0v5/Nuke8.0v5.app/Contents/MacOS/libDDImage.dylib; sourceTree = ""; }; - 594B4E4B18134E6B003C263C /* libGLEW.1.5.8.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libGLEW.1.5.8.dylib; path = ../../../../../../../Applications/Nuke8.0v5/Nuke8.0v5.app/Contents/MacOS/libGLEW.1.5.8.dylib; sourceTree = ""; }; - 594B4E4D18134E6B003C263C /* libtcmalloc_minimal.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libtcmalloc_minimal.dylib; path = ../../../../../../../Applications/Nuke8.0v5/Nuke8.0v5.app/Contents/MacOS/libtcmalloc_minimal.dylib; sourceTree = ""; }; - 594B4E5218134F86003C263C /* libHalf.11.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libHalf.11.dylib; path = ../../../../../../../usr/local/Cellar/ilmbase/2.1.0/lib/libHalf.11.dylib; sourceTree = ""; }; - 594B4E5F18134FF5003C263C /* libIlmCtlSimd.1.5.3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libIlmCtlSimd.1.5.3.dylib; path = ../../../../../../../usr/local/lib/libIlmCtlSimd.1.5.3.dylib; sourceTree = ""; }; - 594B4E621813519E003C263C /* libIex-2_1.11.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = "libIex-2_1.11.dylib"; path = "../../../../../../../usr/local/Cellar/ilmbase/2.1.0/lib/libIex-2_1.11.dylib"; sourceTree = ""; }; - 594B4E631813519E003C263C /* libIexMath-2_1.11.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = "libIexMath-2_1.11.dylib"; path = "../../../../../../../usr/local/Cellar/ilmbase/2.1.0/lib/libIexMath-2_1.11.dylib"; sourceTree = ""; }; - 594B4E641813519E003C263C /* libIlmThread-2_1.11.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = "libIlmThread-2_1.11.dylib"; path = "../../../../../../../usr/local/Cellar/ilmbase/2.1.0/lib/libIlmThread-2_1.11.dylib"; sourceTree = ""; }; - 594B4E651813519E003C263C /* libIlmCtl.1.5.3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libIlmCtl.1.5.3.dylib; path = ../../../../../../../usr/local/lib/libIlmCtl.1.5.3.dylib; sourceTree = ""; }; + 594B4E4A18134E6B003C263C /* libDDImage.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libDDImage.dylib; path = ../../../../../../../Applications/Nuke9.0v2/Nuke9.0v2.app/Contents/MacOS/libDDImage.dylib; sourceTree = ""; }; + 594B4E4B18134E6B003C263C /* libGLEW.1.5.8.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libGLEW.1.5.8.dylib; path = ../../../../../../../Applications/Nuke9.0v2/Nuke9.0v2.app/Contents/MacOS/libGLEW.1.5.8.dylib; sourceTree = ""; }; + 594B4E4D18134E6B003C263C /* libtcmalloc_minimal.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libtcmalloc_minimal.dylib; path = ../../../../../../../Applications/Nuke9.0v2/Nuke9.0v2.app/Contents/MacOS/libtcmalloc_minimal.dylib; sourceTree = ""; }; + 594B4E5218134F86003C263C /* libHalf.11.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libHalf.11.dylib; path = "../../../../../../../usr/local/nuke-compatible/lib/libHalf.11.dylib"; sourceTree = ""; }; + 594B4E5F18134FF5003C263C /* libIlmCtlSimd.1.5.3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libIlmCtlSimd.1.5.3.dylib; path = "../../../../../../../usr/local/nuke-compatible/lib/libIlmCtlSimd.1.5.3.dylib"; sourceTree = ""; }; + 594B4E621813519E003C263C /* libIex-2_1.11.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = "libIex-2_1.11.dylib"; path = "../../../../../../../usr/local/nuke-compatible/lib/libIex-2_1.11.dylib"; sourceTree = ""; }; + 594B4E631813519E003C263C /* libIexMath-2_1.11.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = "libIexMath-2_1.11.dylib"; path = "../../../../../../../usr/local/nuke-compatible/lib/libIexMath-2_1.11.dylib"; sourceTree = ""; }; + 594B4E641813519E003C263C /* libIlmThread-2_1.11.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = "libIlmThread-2_1.11.dylib"; path = "../../../../../../../usr/local/nuke-compatible/lib/libIlmThread-2_1.11.dylib"; sourceTree = ""; }; + 594B4E651813519E003C263C /* libIlmCtl.1.5.3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libIlmCtl.1.5.3.dylib; path = "../../../../../../../usr/local/nuke-compatible/lib/libIlmCtl.1.5.3.dylib"; sourceTree = ""; }; 594E50D51852A4DA00FCE67C /* rrt.ctl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = rrt.ctl; sourceTree = ""; }; 594E50D71852A52E00FCE67C /* utilities-aces.ctl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "utilities-aces.ctl"; sourceTree = ""; }; 594E50D81852A52E00FCE67C /* utilities-color.ctl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "utilities-color.ctl"; sourceTree = ""; }; @@ -604,12 +604,12 @@ "$(inherited)", /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, /usr/local/foundry/include, - /usr/local/include/CTL, - /usr/local/include/OpenEXR, + "/usr/local/nuke-compatible/include/CTL", + "/usr/local/nuke-compatible/include/OpenEXR", ); LIBRARY_SEARCH_PATHS = ( /usr/local/foundry/lib, - /usr/local/lib, + "/usr/local/nuke-compatible/lib", ); MACOSX_DEPLOYMENT_TARGET = ""; ONLY_ACTIVE_ARCH = YES; @@ -647,12 +647,12 @@ "$(inherited)", /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, /usr/local/foundry/include, - /usr/local/include/CTL, - /usr/local/include/OpenEXR, + "/usr/local/nuke-compatible/include/CTL", + "/usr/local/nuke-compatible/include/OpenEXR", ); LIBRARY_SEARCH_PATHS = ( /usr/local/foundry/lib, - /usr/local/lib, + "/usr/local/nuke-compatible/lib", ); MACOSX_DEPLOYMENT_TARGET = ""; SDKROOT = macosx; diff --git a/Xcode/NukeCtl/NukeCtl.xcodeproj/project.xcworkspace/xcshareddata/NukeCtl.xccheckout b/Xcode/NukeCtl/NukeCtl.xcodeproj/project.xcworkspace/xcshareddata/NukeCtl.xccheckout index b779b9c3..c376cccc 100644 --- a/Xcode/NukeCtl/NukeCtl.xcodeproj/project.xcworkspace/xcshareddata/NukeCtl.xccheckout +++ b/Xcode/NukeCtl/NukeCtl.xcodeproj/project.xcworkspace/xcshareddata/NukeCtl.xccheckout @@ -10,29 +10,29 @@ NukeCtl IDESourceControlProjectOriginsDictionary - 771C07CB-E0C1-47F3-A77C-1CA17592CEE8 + 678EA61BA214C8F83B78544D3E1FC9207E799CEE https://github.com/JGoldstone/CTL.git IDESourceControlProjectPath - Xcode/NukeCtl/NukeCtl.xcodeproj/project.xcworkspace + Xcode/NukeCtl/NukeCtl.xcodeproj IDESourceControlProjectRelativeInstallPathDictionary - 771C07CB-E0C1-47F3-A77C-1CA17592CEE8 + 678EA61BA214C8F83B78544D3E1FC9207E799CEE ../../../.. IDESourceControlProjectURL https://github.com/JGoldstone/CTL.git IDESourceControlProjectVersion - 110 + 111 IDESourceControlProjectWCCIdentifier - 771C07CB-E0C1-47F3-A77C-1CA17592CEE8 + 678EA61BA214C8F83B78544D3E1FC9207E799CEE IDESourceControlProjectWCConfigurations IDESourceControlRepositoryExtensionIdentifierKey public.vcs.git IDESourceControlWCCIdentifierKey - 771C07CB-E0C1-47F3-A77C-1CA17592CEE8 + 678EA61BA214C8F83B78544D3E1FC9207E799CEE IDESourceControlWCCName CTL diff --git a/ctlrender/CMakeLists.txt b/ctlrender/CMakeLists.txt index 9fced147..650aba1c 100644 --- a/ctlrender/CMakeLists.txt +++ b/ctlrender/CMakeLists.txt @@ -47,3 +47,5 @@ target_link_libraries( ctlrender ${AcesContainer_LDFLAGS_OTHER} ) endif() install( TARGETS ctlrender DESTINATION bin ) + +set_target_properties(ctlrender PROPERTIES install_rpath "@loader_path/../lib") From 48cb2effe964f0bf07870c24b5f4f2b19e4562f7 Mon Sep 17 00:00:00 2001 From: Joseph Goldstone Date: Fri, 12 Dec 2014 23:36:22 -0800 Subject: [PATCH 09/12] Properly capitalize INSTALL_RPATH when used in setting up executable properties. --- OpenEXR_CTL/exr_ctl_exr/CMakeLists.txt | 2 +- OpenEXR_CTL/exrdpx/CMakeLists.txt | 2 +- ctlrender/CMakeLists.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/OpenEXR_CTL/exr_ctl_exr/CMakeLists.txt b/OpenEXR_CTL/exr_ctl_exr/CMakeLists.txt index 0f44358f..ec6c6a31 100644 --- a/OpenEXR_CTL/exr_ctl_exr/CMakeLists.txt +++ b/OpenEXR_CTL/exr_ctl_exr/CMakeLists.txt @@ -24,4 +24,4 @@ install( TARGETS exr_ctl_exr DESTINATION ${INSTALL_BIN_DIR} ) install( FILES change_saturation.ctl DESTINATION ${INSTALL_LIB_DIR}/CTL ) -set_target_properties(exr_ctl_exr PROPERTIES install_rpath "@loader_path/../lib") +set_target_properties(exr_ctl_exr PROPERTIES INSTALL_RPATH "@loader_path/../lib") diff --git a/OpenEXR_CTL/exrdpx/CMakeLists.txt b/OpenEXR_CTL/exrdpx/CMakeLists.txt index b3b4e008..0c0c980b 100644 --- a/OpenEXR_CTL/exrdpx/CMakeLists.txt +++ b/OpenEXR_CTL/exrdpx/CMakeLists.txt @@ -24,4 +24,4 @@ install( TARGETS exrdpx DESTINATION ${INSTALL_BIN_DIR} ) install( FILES transform_DPX_EXR.ctl transform_EXR_DPX.ctl DESTINATION ${INSTALL_LIB_DIR}/CTL ) -set_target_properties(exrdpx PROPERTIES install_rpath "@loader_path/../lib") +set_target_properties(exrdpx PROPERTIES INSTALL_RPATH "@loader_path/../lib") diff --git a/ctlrender/CMakeLists.txt b/ctlrender/CMakeLists.txt index 650aba1c..932c6e4c 100644 --- a/ctlrender/CMakeLists.txt +++ b/ctlrender/CMakeLists.txt @@ -48,4 +48,4 @@ endif() install( TARGETS ctlrender DESTINATION bin ) -set_target_properties(ctlrender PROPERTIES install_rpath "@loader_path/../lib") +set_target_properties(ctlrender PROPERTIES INSTALL_RPATH "@loader_path/../lib") From 3421d80f9dc71add0c6e2a0fbe3aa150f2397ac2 Mon Sep 17 00:00:00 2001 From: Joseph Goldstone Date: Sat, 13 Dec 2014 09:29:41 -0800 Subject: [PATCH 10/12] Make RPATH use consistent with OpenEXR. --- CMakeLists.txt | 35 ++++++++++--------- Nuke_CTL/CMakeLists.txt | 1 + OpenEXR_CTL/exr_ctl_exr/CMakeLists.txt | 4 ++- OpenEXR_CTL/exrdpx/CMakeLists.txt | 4 ++- .../NukeCtl/NukeCtl.xcodeproj/project.pbxproj | 2 ++ ctlrender/CMakeLists.txt | 4 ++- 6 files changed, 31 insertions(+), 19 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 628f5e0a..d8268e26 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,22 +18,25 @@ else() endif() set(INSTALL_CMAKE_DIR ${DEF_INSTALL_CMAKE_DIR} CACHE PATH "Install directory for project CMake files" ) -# # use, i.e. don't skip the full RPATH for the build tree -# SET(CMAKE_SKIP_BUILD_RPATH FALSE) -# # when building, don't use the install RPATH already -# # (but later on when installing) -# SET(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) -# #SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") -# # add the automatically determined parts of the RPATH -# # which point to directories outside the build tree to the install RPATH -# SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) -# # the RPATH to be used when installing, but only if it's not a system directory -# LIST(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${CMAKE_INSTALL_PREFIX}/lib" isSystemDir) -# IF("${isSystemDir}" STREQUAL "-1") -# SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") -# ENDIF("${isSystemDir}" STREQUAL "-1") -set(CMAKE_MACOSX_RPATH 1) - +IF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + SET(CMAKE_MACOSX_RPATH 1) + SET(BUILD_WITH_INSTALL_RPATH 1) +ELSE() + # use, i.e. don't skip the full RPATH for the build tree + SET(CMAKE_SKIP_BUILD_RPATH FALSE) + # when building, don't use the install RPATH already + # (but later on when installing) + SET(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) + #SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") + # add the automatically determined parts of the RPATH + # which point to directories outside the build tree to the install RPATH + SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) + # the RPATH to be used when installing, but only if it's not a system directory + LIST(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${CMAKE_INSTALL_PREFIX}/lib" isSystemDir) + IF("${isSystemDir}" STREQUAL "-1") + SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") + ENDIF("${isSystemDir}" STREQUAL "-1") +ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") ## convert install paths to absolute foreach( p LIB BIN INCLUDE CMAKE DOC) diff --git a/Nuke_CTL/CMakeLists.txt b/Nuke_CTL/CMakeLists.txt index 7d9fe013..d72a6603 100644 --- a/Nuke_CTL/CMakeLists.txt +++ b/Nuke_CTL/CMakeLists.txt @@ -44,6 +44,7 @@ if(NUKE_FOUND) ) set_target_properties(NukeCtl PROPERTIES PREFIX "") + set_target_properties(NukeCtl PROPERTIES INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") target_link_libraries( NukeCtl IlmCtl IlmCtlMath IlmCtlSimd IlmThread Half Iex ) target_link_libraries( NukeCtl ${IlmBase_LIBRARIES} ${IlmBase_LDFLAGS_OTHER} ) diff --git a/OpenEXR_CTL/exr_ctl_exr/CMakeLists.txt b/OpenEXR_CTL/exr_ctl_exr/CMakeLists.txt index ec6c6a31..50dc51ce 100644 --- a/OpenEXR_CTL/exr_ctl_exr/CMakeLists.txt +++ b/OpenEXR_CTL/exr_ctl_exr/CMakeLists.txt @@ -24,4 +24,6 @@ install( TARGETS exr_ctl_exr DESTINATION ${INSTALL_BIN_DIR} ) install( FILES change_saturation.ctl DESTINATION ${INSTALL_LIB_DIR}/CTL ) -set_target_properties(exr_ctl_exr PROPERTIES INSTALL_RPATH "@loader_path/../lib") +IF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + set_target_properties(exr_ctl_exr PROPERTIES INSTALL_RPATH "@loader_path/../lib") +ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") diff --git a/OpenEXR_CTL/exrdpx/CMakeLists.txt b/OpenEXR_CTL/exrdpx/CMakeLists.txt index 0c0c980b..1329dfeb 100644 --- a/OpenEXR_CTL/exrdpx/CMakeLists.txt +++ b/OpenEXR_CTL/exrdpx/CMakeLists.txt @@ -24,4 +24,6 @@ install( TARGETS exrdpx DESTINATION ${INSTALL_BIN_DIR} ) install( FILES transform_DPX_EXR.ctl transform_EXR_DPX.ctl DESTINATION ${INSTALL_LIB_DIR}/CTL ) -set_target_properties(exrdpx PROPERTIES INSTALL_RPATH "@loader_path/../lib") +IF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + set_target_properties(exrdpx PROPERTIES INSTALL_RPATH "@loader_path/../lib") +ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") diff --git a/Xcode/NukeCtl/NukeCtl.xcodeproj/project.pbxproj b/Xcode/NukeCtl/NukeCtl.xcodeproj/project.pbxproj index f285032d..93212cd9 100644 --- a/Xcode/NukeCtl/NukeCtl.xcodeproj/project.pbxproj +++ b/Xcode/NukeCtl/NukeCtl.xcodeproj/project.pbxproj @@ -744,6 +744,7 @@ "DEBUG=1", "$(inherited)", ); + LD_RUNPATH_SEARCH_PATHS = "/usr/local/nuke-compatible/lib /usr/local/lib"; LIBRARY_SEARCH_PATHS = "$(inherited)"; PRODUCT_NAME = NukeCtl; }; @@ -752,6 +753,7 @@ 594B4E3118134BAF003C263C /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + LD_RUNPATH_SEARCH_PATHS = "/usr/local/nuke-compatible/lib /usr/local/lib"; LIBRARY_SEARCH_PATHS = "$(inherited)"; PRODUCT_NAME = NukeCtl; }; diff --git a/ctlrender/CMakeLists.txt b/ctlrender/CMakeLists.txt index 932c6e4c..63606cc0 100644 --- a/ctlrender/CMakeLists.txt +++ b/ctlrender/CMakeLists.txt @@ -48,4 +48,6 @@ endif() install( TARGETS ctlrender DESTINATION bin ) -set_target_properties(ctlrender PROPERTIES INSTALL_RPATH "@loader_path/../lib") +IF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + set_target_properties(ctlrender PROPERTIES INSTALL_RPATH "@loader_path/../lib") +ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") From 0828070bbfb4210e6471e2d5866d52283254e01a Mon Sep 17 00:00:00 2001 From: Joseph Goldstone Date: Sun, 14 Dec 2014 08:00:05 -0800 Subject: [PATCH 11/12] Remove hard-coded addition of -stdlib=libstdc++ from CMakeLists.txt. --- CMakeLists.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d8268e26..f6a0d9ab 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -48,8 +48,6 @@ endforeach() option(ENABLE_SHARED "Enable Shared Libraries" ON) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -v -stdlib=libstdc++") - if ( ENABLE_SHARED ) set( DO_SHARED SHARED ) else() From 8d6941366190e536032f4fac726f18d7786ae91f Mon Sep 17 00:00:00 2001 From: Joseph Goldstone Date: Sat, 3 Jan 2015 13:28:55 -0800 Subject: [PATCH 12/12] Manually set INSTALL_RPATH property in each target's CMakeLists.txt file. --- CMakeLists.txt | 6 ++++-- ctlrender/CMakeLists.txt | 4 ++-- lib/IlmCtl/CMakeLists.txt | 4 ++++ lib/IlmCtlMath/CMakeLists.txt | 4 ++++ lib/IlmCtlSimd/CMakeLists.txt | 4 ++++ lib/IlmImfCtl/CMakeLists.txt | 4 ++++ 6 files changed, 22 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f6a0d9ab..74ed6d27 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,8 +19,10 @@ endif() set(INSTALL_CMAKE_DIR ${DEF_INSTALL_CMAKE_DIR} CACHE PATH "Install directory for project CMake files" ) IF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - SET(CMAKE_MACOSX_RPATH 1) - SET(BUILD_WITH_INSTALL_RPATH 1) + SET(CMAKE_MACOSX_RPATH TRUE) + # Don't set this at build time; set it at install time with each target's INSTALL_RPATH property + # (again, only on Darwin) + SET(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) ELSE() # use, i.e. don't skip the full RPATH for the build tree SET(CMAKE_SKIP_BUILD_RPATH FALSE) diff --git a/ctlrender/CMakeLists.txt b/ctlrender/CMakeLists.txt index 63606cc0..706e420b 100644 --- a/ctlrender/CMakeLists.txt +++ b/ctlrender/CMakeLists.txt @@ -46,8 +46,8 @@ target_link_libraries( ctlrender ${AcesContainer_LIBRARIES} ) target_link_libraries( ctlrender ${AcesContainer_LDFLAGS_OTHER} ) endif() -install( TARGETS ctlrender DESTINATION bin ) - IF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set_target_properties(ctlrender PROPERTIES INSTALL_RPATH "@loader_path/../lib") ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + +install( TARGETS ctlrender DESTINATION bin ) diff --git a/lib/IlmCtl/CMakeLists.txt b/lib/IlmCtl/CMakeLists.txt index 3672a431..237522e7 100644 --- a/lib/IlmCtl/CMakeLists.txt +++ b/lib/IlmCtl/CMakeLists.txt @@ -29,6 +29,10 @@ set_target_properties( IlmCtl PROPERTIES SOVERSION ${CTL_VERSION} ) +IF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + set_target_properties(IlmCtl PROPERTIES INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") +ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + install( FILES CtlAddr.h CtlAlign.h diff --git a/lib/IlmCtlMath/CMakeLists.txt b/lib/IlmCtlMath/CMakeLists.txt index 96738cf8..d01583ae 100644 --- a/lib/IlmCtlMath/CMakeLists.txt +++ b/lib/IlmCtlMath/CMakeLists.txt @@ -13,6 +13,10 @@ set_target_properties( IlmCtlMath PROPERTIES SOVERSION ${CTL_VERSION} ) +IF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + set_target_properties(IlmCtlMath PROPERTIES INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") +ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + install( FILES CtlColorSpace.h CtlLookupTable.h diff --git a/lib/IlmCtlSimd/CMakeLists.txt b/lib/IlmCtlSimd/CMakeLists.txt index 19a0fbed..d261d7a2 100644 --- a/lib/IlmCtlSimd/CMakeLists.txt +++ b/lib/IlmCtlSimd/CMakeLists.txt @@ -40,6 +40,10 @@ set_target_properties( IlmCtlSimd PROPERTIES SOVERSION ${CTL_VERSION} ) +IF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + set_target_properties(IlmCtlSimd PROPERTIES INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") +ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + install( FILES CtlSimdInterpreter.h DESTINATION include/CTL ) install( TARGETS IlmCtlSimd DESTINATION lib ) diff --git a/lib/IlmImfCtl/CMakeLists.txt b/lib/IlmImfCtl/CMakeLists.txt index 47563df4..2ca7391e 100644 --- a/lib/IlmImfCtl/CMakeLists.txt +++ b/lib/IlmImfCtl/CMakeLists.txt @@ -11,6 +11,10 @@ target_link_libraries( IlmImfCtl IlmCtl IlmImf Iex IlmThread Half ) install( FILES ImfCtlApplyTransforms.h DESTINATION include/OpenEXR ) +IF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + set_target_properties(IlmImfCtl PROPERTIES INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") +ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + export( TARGETS IlmImfCtl IlmCtl FILE "${PROJECT_BINARY_DIR}/CTLLibraryDepends.cmake" ) install( TARGETS IlmImfCtl DESTINATION lib )