1#------------------------------------------------------------------------------- 2# Post processing (color management) related Mari scripts 3# coding: utf-8 4# Copyright (c) 2011 The Foundry Visionmongers Ltd. All Rights Reserved. 5#------------------------------------------------------------------------------- 6 7import mari, time, PythonQt, os, math 8QtGui = PythonQt.QtGui 9QtCore = PythonQt.QtCore 10ocio = mari.utils.ocio 11 12############################################################################################## 13 14GAIN_GROUP_MAX_WIDTH = 312 15FSTOP_MAX_WIDTH = 50 16EXPOSURE_MAX_WIDTH = 102 17GAIN_MAX_WIDTH = 80 18GAMMA_MAX_WIDTH = 200 19TOOLBAR_SPACING = 3 20 21toolbar = None 22 23class OcioToolBar(): 24 25 #----------------------------------------------------------------------------------------- 26 27 def __init__(self): 28 # Default all members... 29 self._config_file_list = mari.FileList(ocio.config_file_list_default) 30 self._config = ocio.config_default 31 self._lut_file_list = mari.FileList(ocio.lut_file_list_default) 32 self._lut_extrapolate = ocio.lut_extrapolate_default 33 self._color_space = ocio.color_space_default 34 self._display = ocio.display_default 35 self._view = ocio.view_default 36 self._swizzle = ocio.swizzle_default 37 self._gain = ocio.gain_default 38 self._gamma = ocio.gamma_default 39 40 self._lut_filter = None 41 self._lut_filter_cache_id = None 42 self._lut_texture_cache_id = None 43 self._lut_sampler_name = None 44 45 self._display_filter = None 46 self._display_filter_cache_id = None 47 self._display_texture_cache_id = None 48 self._display_sampler_name = None 49 50 self._lut_extrapolate_widget = None 51 self._color_space_widget = None 52 self._display_widget = None 53 self._view_widget = None 54 self._swizzle_widget = None 55 self._fstop_widget = None 56 self._fstop_decrement_widget = None 57 self._fstop_increment_widget = None 58 self._gain_widget = None 59 self._exposure_widget = None 60 self._gain_reset_widget = None 61 self._gamma_widget = None 62 self._gamma_reset_widget = None 63 64 self._buildWidgets() 65 self._toggle_color_management_action.setEnabled(False) 66 self._enableWidgets(False) 67 68 # Enable/disable color management. 69 mari.gl_render.setPostProcessingEnabled(self.isColorManagementEnabled()) 70 71 # *** IMPORTANT *** The post filter collection used to be called 'OpenColorIO' but was renamed to hide the fact 72 # we use OpenColorIO from our users. So as a temporary workaround we need to check for the old filter collection 73 # on startup and remove it if found. 74 delete_filter_collection = mari.gl_render.findPostFilterCollection('OpenColorIO') 75 if delete_filter_collection is not None: 76 mari.gl_render.deletePostFilterCollection(delete_filter_collection) 77 78 # Create the OCIO post filter collection if not present. 79 self._filter_collection = mari.gl_render.findPostFilterCollection('Color Space') 80 if self._filter_collection is None: 81 self._filter_collection = mari.gl_render.createPostFilterCollection('Color Space') 82 else: 83 self._filter_collection.clear() 84 self._filter_collection.setReadOnly(True) 85 86 self._lut_filter = self._filter_collection.createGLSL('LUT Transform') 87 if not self._lut_file_list.isEmpty() and not self._rebuildLUTFilter(self._lut_file_list.at(0)): 88 self._lut_file_list.clear() 89 90 self._display_filter = self._filter_collection.createGLSL('Display Transform') 91 self._rebuildDisplayFilter() 92 93 self._buildMetadata() 94 95 # Set the color management filter stack as the current. 96 mari.gl_render.setPostFilterCollection(self._filter_collection) 97 98 # Attach ourselves to the applications toolbar created signal so we can rebuild the toolbar when it's been 99 # destoyed. 100 mari.utils.connect(mari.app.toolBarsCreated, self._toolBarsCreated) 101 102 # Attach ourselves to the appropriate GL signals so we can enable and disable widgets. 103 mari.utils.connect(mari.gl_render.postProcessingEnabled, self._postProcessingEnabled) 104 mari.utils.connect(mari.gl_render.setCurrentPostFilterCollection, self._setCurrentPostFilterCollection) 105 106 # Attach ourselves to the appropriate project signals so we can load and save settings. 107 mari.utils.connect(mari.projects.openedProject, self._openedProject) 108 mari.utils.connect(mari.projects.aboutToSaveProject, self._aboutToSaveProject) 109 mari.utils.connect(mari.projects.projectClosed, self._closedProject) 110 111 # Update the UI to match the current project, if we have one. 112 current_project = mari.projects.current() 113 if current_project is not None: 114 self._openedProject(current_project) 115 116 #----------------------------------------------------------------------------------------- 117 118 def isColorManagementEnabled(self): 119 return self._toggle_color_management_action.isChecked() 120 121 #----------------------------------------------------------------------------------------- 122 123 def setLUTPath(self, value, update_metadata = True, force_shader_build = False): 124 if (self._lut_file_list.isEmpty() and value != '') or \ 125 (not self._lut_file_list.isEmpty() and value == '') or \ 126 (not self._lut_file_list.isEmpty() and value != self._lut_file_list.at(0)) \ 127 : 128 if self._rebuildLUTFilter(value, force_shader_build): 129 self._lut_file_list.clear() 130 if value != '': 131 self._lut_file_list.append(value) 132 self._lut_file_list.setPickedFile(value) 133 134 self._clear_lut_action.setEnabled(True) 135 self._lut_extrapolate_widget.setEnabled(True) 136 self._lut_filter.setEnabled(True) 137 else: 138 self._clear_lut_action.setEnabled(False) 139 self._lut_extrapolate_widget.setEnabled(False) 140 self._lut_filter.setEnabled(False) 141 142 if update_metadata: 143 mari.utils.disconnect(self._lut_filter.metadataValueChanged, lutMetadataValueChanged) 144 self._lut_filter.setMetadata('File', self._lut_file_list) 145 mari.utils.connect(self._lut_filter.metadataValueChanged, lutMetadataValueChanged) 146 147 else: 148 # If this was a request via the metadata system we will need to put the value back to what it was 149 # before. 150 if not update_metadata: 151 mari.utils.disconnect(self._lut_filter.metadataValueChanged, lutMetadataValueChanged) 152 self._lut_filter.setMetadata('File', self._lut_file_list) 153 mari.utils.connect(self._lut_filter.metadataValueChanged, lutMetadataValueChanged) 154 155 return False 156 157 return True 158 159 #----------------------------------------------------------------------------------------- 160 161 def resetLUT(self): 162 if ocio.lut_file_list_default.isEmpty() or not self.setLUTPath(ocio.lut_file_list_default.at(0)): 163 self.setLUTPath('') 164 165 #----------------------------------------------------------------------------------------- 166 167 def selectLUT(self): 168 lut_path = mari.utils.misc.getOpenFileName(None, 169 'Select LUT File', 170 '' if self._lut_file_list.isEmpty() else self._lut_file_list.at(0), 171 ocio.lutFileFilter(), 172 None, 173 0) 174 if os.path.isfile(lut_path): 175 self.setLUTPath(lut_path) 176 177 #----------------------------------------------------------------------------------------- 178 179 def setExtrapolateEnabled(self, value, update_widget = True, update_metadata = True): 180 if value != self._lut_extrapolate: 181 self._lut_extrapolate = value 182 183 if update_widget: 184 block = self._lut_extrapolate_widget.blockSignals(True) 185 self._lut_extrapolate_widget.setChecked(self._lut_extrapolate) 186 self._lut_extrapolate_widget.blockSignals(block) 187 188 if update_metadata: 189 mari.utils.disconnect(self._lut_filter.metadataValueChanged, lutMetadataValueChanged) 190 self._lut_filter.setMetadata('Extrapolate', self._lut_extrapolate) 191 mari.utils.connect(self._lut_filter.metadataValueChanged, lutMetadataValueChanged) 192 193 if not self._rebuildLUTFilter(lut_path = '' if self._lut_file_list.isEmpty() else self._lut_file_list.at(0), 194 force_shader_build = True): 195 self.resetLUT() 196 197 ocio.printMessage(ocio.MessageType.DEBUG, 'Changed extrapolate to \'%s\'' % self._lut_extrapolate) 198 199 #----------------------------------------------------------------------------------------- 200 201 def setConfigPath(self, value, update_metadata = True): 202 if self._config_file_list.isEmpty() or value != self._config_file_list.at(0): 203 config = ocio.loadConfig(value, True) 204 if config is not None: 205 self._config_file_list.clear() 206 self._config_file_list.append(value) 207 self._config_file_list.setPickedFile(value) 208 209 self._config = config 210 211 self._updateDisplayWidgets() 212 self._updateDisplayMetadata() 213 214 self._rebuildDisplayFilter() 215 216 ocio.printMessage(ocio.MessageType.DEBUG, 'Changed config to \'%s\'' % self._config_file_list.at(0)) 217 218 else: 219 # If this was a request via the metadata system we will need to put the value back to what it was 220 # before. 221 if not update_metadata: 222 mari.utils.disconnect(self._display_filter.metadataValueChanged, displayMetadataValueChanged) 223 self._display_filter.setMetadata('ConfigPath', self._config_file_list) 224 mari.utils.connect(self._display_filter.metadataValueChanged, displayMetadataValueChanged) 225 226 return False 227 228 return True 229 230 #----------------------------------------------------------------------------------------- 231 232 def selectConfig(self): 233 config_path = mari.utils.misc.getOpenFileName(None, 234 'Select Configuration File', 235 '' if self._config_file_list.isEmpty() else self._config_file_list.at(0), 236 ocio.configFileFilter(), 237 None, 238 0) 239 if os.path.isfile(config_path): 240 self.setConfigPath(config_path) 241 242 #----------------------------------------------------------------------------------------- 243 244 def setColorSpace(self, value, update_widget = True, update_metadata = True): 245 if value != self._color_space: 246 self._color_space = value 247 248 if update_widget: 249 block = self._color_space_widget.blockSignals(True) 250 index = self._color_space_widget.findText(self._color_space) 251 self._color_space_widget.setCurrentIndex(index) 252 self._color_space_widget.blockSignals(block) 253 254 if update_metadata: 255 mari.utils.disconnect(self._display_filter.metadataValueChanged, displayMetadataValueChanged) 256 self._display_filter.setMetadata('InputColorSpace', self._color_space) 257 mari.utils.connect(self._display_filter.metadataValueChanged, displayMetadataValueChanged) 258 259 self._rebuildDisplayFilter() 260 261 ocio.printMessage(ocio.MessageType.DEBUG, 'Changed input color space to \'%s\'' % self._color_space) 262 263 #----------------------------------------------------------------------------------------- 264 265 def setDisplay(self, value, update_widget = True, update_metadata = True): 266 if value != self._display: 267 self._display = value 268 269 if update_widget: 270 block = self._display_widget.blockSignals(True) 271 index = self._display_widget.findText(self._display) 272 self._display_widget.setCurrentIndex(index) 273 self._display_widget.blockSignals(block) 274 275 if update_metadata: 276 mari.utils.disconnect(self._display_filter.metadataValueChanged, displayMetadataValueChanged) 277 self._display_filter.setMetadata('Display', self._display) 278 mari.utils.connect(self._display_filter.metadataValueChanged, displayMetadataValueChanged) 279 280 self.setView(self._config.getDefaultView(self._display), update_widget, update_metadata) 281 282 self._rebuildDisplayFilter() 283 284 ocio.printMessage(ocio.MessageType.DEBUG, 'Changed display to \'%s\'' % self._display) 285 286 #----------------------------------------------------------------------------------------- 287 288 def setView(self, value, update_widget = True, update_metadata = True): 289 if value != self._view: 290 self._view = value 291 292 if update_widget: 293 block = self._view_widget.blockSignals(True) 294 index = self._view_widget.findText(self._view) 295 self._view_widget.setCurrentIndex(index) 296 self._view_widget.blockSignals(block) 297 298 if update_metadata: 299 mari.utils.disconnect(self._display_filter.metadataValueChanged, displayMetadataValueChanged) 300 self._display_filter.setMetadata('View', self._view) 301 mari.utils.connect(self._display_filter.metadataValueChanged, displayMetadataValueChanged) 302 303 self._rebuildDisplayFilter() 304 305 ocio.printMessage(ocio.MessageType.DEBUG, 'Changed view to \'%s\'' % self._view) 306 307 #----------------------------------------------------------------------------------------- 308 309 def setSwizzle(self, value, update_widget = True, update_metadata = True): 310 if value != self._swizzle: 311 self._swizzle = value 312 313 if update_widget: 314 block = self._swizzle_widget.blockSignals(True) 315 index = self._swizzle_widget.findText(self._swizzle) 316 self._swizzle_widget.setCurrentIndex(index) 317 self._swizzle_widget.blockSignals(block) 318 319 if update_metadata: 320 mari.utils.disconnect(self._display_filter.metadataValueChanged, displayMetadataValueChanged) 321 self._display_filter.setMetadata('Swizzle', self._swizzle) 322 mari.utils.connect(self._display_filter.metadataValueChanged, displayMetadataValueChanged) 323 324 self._rebuildDisplayFilter() 325 326 ocio.printMessage(ocio.MessageType.DEBUG, 'Changed swizzle to \'%s\'' % self._swizzle) 327 328 #----------------------------------------------------------------------------------------- 329 330 def setGain(self, value, update_widget = True, update_metadata = True): 331 if value != self._gain: 332 self._gain = value 333 334 if update_widget: 335 self._updateGainWidgets() 336 337 if update_metadata: 338 mari.utils.disconnect(self._display_filter.metadataValueChanged, displayMetadataValueChanged) 339 self._display_filter.setMetadata('Gain', self._gain) 340 mari.utils.connect(self._display_filter.metadataValueChanged, displayMetadataValueChanged) 341 342 self._rebuildDisplayFilter() 343 344 ocio.printMessage(ocio.MessageType.DEBUG, 'Changed gain to \'%s\'' % self._gain) 345 346 #----------------------------------------------------------------------------------------- 347 348 def setGamma(self, value, update_widget = True, update_metadata = True): 349 if value != self._gamma: 350 self._gamma = value 351 352 if update_widget: 353 block = self._gamma_widget.blockSignals(True) 354 self._gamma_widget.setValue(self._gamma) 355 self._gamma_widget.blockSignals(block) 356 357 if update_metadata: 358 mari.utils.disconnect(self._display_filter.metadataValueChanged, displayMetadataValueChanged) 359 self._display_filter.setMetadata('Gamma', self._gamma) 360 mari.utils.connect(self._display_filter.metadataValueChanged, displayMetadataValueChanged) 361 362 self._rebuildDisplayFilter() 363 364 ocio.printMessage(ocio.MessageType.DEBUG, 'Changed gamma to \'%s\'' % self._gamma) 365 366 #----------------------------------------------------------------------------------------- 367 368 def updateLUTSize(self): 369 ocio.printMessage(ocio.MessageType.DEBUG, 'Updating LUT size...') 370 371 # Rebuild the LUT filter. 372 if self._lut_sampler_name is not None: 373 self._lut_filter.deleteTexture(self._lut_sampler_name) 374 self._lut_sampler_name = None 375 376 self._lut_filter_cache_id = None 377 self._lut_texture_cache_id = None 378 379 if not self._rebuildLUTFilter(lut_path = '' if self._lut_file_list.isEmpty() else self._lut_file_list.at(0), 380 force_shader_build = True): 381 self.resetLUT() 382 383 # Rebuild the display filter. 384 if self._display_sampler_name is not None: 385 self._display_filter.deleteTexture(self._display_sampler_name) 386 self._display_sampler_name = None 387 388 self._display_filter_cache_id = None 389 self._display_texture_cache_id = None 390 391 self._rebuildDisplayFilter() 392 393 #----------------------------------------------------------------------------------------- 394 395 def updateFStopCenter(self): 396 ocio.printMessage(ocio.MessageType.DEBUG, 'Updating f-stop center...') 397 398 fstop = ocio.convertGainToFStop(self._gain) 399 self._updateFStopWidgetText(fstop) 400 401 #----------------------------------------------------------------------------------------- 402 # Widgets: 403 #----------------------------------------------------------------------------------------- 404 405 def _buildWidgets(self): 406 action_list = list() 407 408 self._toggle_color_management_action = self._addAction( 409 '/Mari/OpenColorIO/&Toggle Color Management', 410 'mari.system._ocio_toolbar.toolbar._toggleColorManagement()', 411 'ColorManager.png', 412 'Toggle on/off color management', 413 'Toggle color management') 414 self._toggle_color_management_action.setCheckable(True) 415 self._toggle_color_management_action.setChecked(ocio.enabled_default) 416 action_list.append('/Mari/OpenColorIO/&Toggle Color Management') 417 418 self._select_config_action = self._addAction( 419 '/Mari/OpenColorIO/&Select Config', 420 'mari.system._ocio_toolbar.toolbar.selectConfig()', 421 'LoadColorConfig.png', 422 'Select color space configuration file', 423 'Select config') 424 action_list.append('/Mari/OpenColorIO/&Select Config') 425 426 self._select_lut_action = self._addAction( 427 '/Mari/OpenColorIO/&Select LUT', 428 'mari.system._ocio_toolbar.toolbar.selectLUT()', 429 'LoadLookupTable.png', 430 'Select LUT file', 431 'Select LUT') 432 action_list.append('/Mari/OpenColorIO/&Select LUT') 433 434 self._clear_lut_action = self._addAction( 435 '/Mari/OpenColorIO/&Clear LUT', 436 'mari.system._ocio_toolbar.toolbar._clearLUT()', 437 'ClearLookupTable.png', 438 'Clear current LUT', 439 'Clear LUT') 440 action_list.append('/Mari/OpenColorIO/&Clear LUT') 441 442 mari.app.deleteToolBar('Color Space') 443 self._toolbar = mari.app.createToolBar('Color Space', True) 444 self._toolbar.addActionList(action_list, False) 445 self._toolbar.setLockedSlot(True) 446 self._toolbar.setSpacing(TOOLBAR_SPACING) 447 448 self._toolbar.insertSeparator('/Mari/OpenColorIO/&Select LUT') 449 450 # Extrapolate: 451 self._toolbar.addWidget(QtGui.QLabel('Extrapolate')) 452 self._lut_extrapolate_widget = QtGui.QCheckBox() 453 self._lut_extrapolate_widget.setToolTip('Extrapolate if outside LUT range'); 454 self._lut_extrapolate_widget.setChecked(self._lut_extrapolate) 455 self._lut_extrapolate_widget.connect( 456 QtCore.SIGNAL('toggled(bool)'), 457 lambda value: self.setExtrapolateEnabled(value = value, update_widget = False, update_metadata = True)) 458 self._toolbar.addWidget(self._lut_extrapolate_widget) 459 460 self._toolbar.addSeparator() 461 462 color_spaces = [color_space.getName() for color_space in self._config.getColorSpaces()] 463 464 # Color-Space: 465 self._color_space_widget = self._addComboBox( 466 'Input Color Space', 467 color_spaces, 468 self._color_space, 469 ocio.color_space_default, 470 lambda value: self.setColorSpace(value = value, update_widget = False, update_metadata = True)) 471 self._color_space = self._color_space_widget.currentText 472 473 # Display: 474 self._display_widget = self._addComboBox( 475 'Display Device', 476 self._config.getDisplays(), 477 self._display, 478 ocio.display_default, 479 lambda value: self.setDisplay(value = value, update_widget = False, update_metadata = True)) 480 self._display = self._display_widget.currentText 481 482 # View: 483 self._view_widget = self._addComboBox( 484 'View Transform', 485 self._config.getViews(self._display), 486 self._view, 487 ocio.view_default, 488 lambda value: self.setView(value = value, update_widget = False, update_metadata = True)) 489 self._view = self._view_widget.currentText 490 491 # Swizzle: 492 self._swizzle_widget = self._addComboBox( 493 'Component', 494 ocio.SWIZZLE_TYPES, 495 self._swizzle, 496 ocio.swizzle_default, 497 lambda value: self.setSwizzle(value = value, update_widget = False, update_metadata = True)) 498 self._swizzle = self._swizzle_widget.currentText 499 500 # Gain Group: 501 group_widget, layout = self._addWidgetGroup() 502 group_widget.setMaximumWidth(GAIN_GROUP_MAX_WIDTH) 503 504 layout.addWidget(QtGui.QLabel('Gain')) 505 506 # F-Stop: 507 subgroup_widget = QtGui.QWidget() 508 layout.addWidget(subgroup_widget) 509 510 sublayout = QtGui.QHBoxLayout() 511 sublayout.setSpacing(0) 512 sublayout.setMargin(0) 513 subgroup_widget.setLayout(sublayout) 514 515 exposure = ocio.convertGainToExposure(self._gain) 516 fstop = ocio.convertExposureToFStop(exposure) 517 scale = (exposure - ocio.EXPOSURE_MIN) / ocio.EXPOSURE_DELTA 518 widget_max = int(math.ceil(ocio.EXPOSURE_DELTA / ocio.FSTOP_STEP_SIZE)) 519 widget_value = scale * widget_max 520 self._fstop_widget = mari.LineEdit() 521 self._fstop_widget.setRange(widget_max) 522 self._fstop_widget.setMaximumWidth(FSTOP_MAX_WIDTH) 523 self._fstop_widget.setReadOnly(True) 524 self._updateFStopWidgetText(fstop) 525 self._fstop_widget.setValue(widget_value) 526 mari.utils.connect(self._fstop_widget.movedMouse, self._fstopMovedMouse) 527 self._fstop_widget.addToLayout(sublayout) 528 529 self._fstop_decrement_widget = self._addSmallButtom( 530 sublayout, 531 '-', 532 'Decrease gain 1/2 stop', 533 lambda: self.setGain(ocio.convertExposureToGain(ocio.convertGainToExposure(self._gain) - 0.5))) 534 self._fstop_increment_widget = self._addSmallButtom( 535 sublayout, 536 '+', 537 'Increase gain 1/2 stop', 538 lambda: self.setGain(ocio.convertExposureToGain(ocio.convertGainToExposure(self._gain) + 0.5))) 539 540 ocio.registerLUTSizeChanged(self.updateLUTSize) 541 ocio.registerFStopCenterChanged(self.updateFStopCenter) 542 543 # Gain: 544 subgroup_widget = QtGui.QWidget() 545 layout.addWidget(subgroup_widget) 546 547 sublayout = QtGui.QHBoxLayout() 548 sublayout.setSpacing(3) 549 sublayout.setMargin(0) 550 subgroup_widget.setLayout(sublayout) 551 552 widget_max = int(math.ceil(ocio.EXPOSURE_DELTA / ocio.EXPOSURE_STEP_SIZE)) 553 widget_value = scale * widget_max 554 self._gain_widget = mari.LineEdit() 555 self._gain_widget.setRange(widget_max) 556 self._gain_widget.addFloatValidator(ocio.GAIN_MIN, ocio.GAIN_MAX, ocio.GAIN_PRECISION) 557 self._gain_widget.setMaximumWidth(GAIN_MAX_WIDTH) 558 self._updateGainWidgetText() 559 self._gain_widget.setValue(widget_value) 560 mari.utils.connect( 561 self._gain_widget.lostFocus, 562 lambda: self.setGain(max(min(float(self._gain_widget.text()), ocio.GAIN_MAX), ocio.GAIN_MIN))) 563 mari.utils.connect(self._gain_widget.movedMouse, self._gainMovedMouse) 564 self._gain_widget.addToLayout(sublayout) 565 566 # Exposure: 567 self._exposure_widget = QtGui.QSlider() 568 self._exposure_widget.orientation = 1 569 self._exposure_widget.setMaximum(widget_max) 570 self._exposure_widget.setValue(widget_value) 571 self._exposure_widget.setMinimumWidth(EXPOSURE_MAX_WIDTH) 572 self._exposure_widget.setMaximumWidth(EXPOSURE_MAX_WIDTH) 573 mari.utils.connect(self._exposure_widget.valueChanged, self._exposureChanged) 574 sublayout.addWidget(self._exposure_widget) 575 576 self._gain_reset_widget = self._addSmallButtom( 577 layout, 578 'R', 579 'Reset gain to default', 580 lambda: self.setGain(value = ocio.GAIN_RESET, update_widget = True, update_metadata = True)) 581 582 # Gamma: 583 group_widget, layout = self._addWidgetGroup() 584 group_widget.setMaximumWidth(GAMMA_MAX_WIDTH) 585 586 layout.addWidget(QtGui.QLabel('Gamma')) 587 588 self._gamma_widget = mari.FloatSlider() 589 self._gamma_widget.setRange(ocio.GAMMA_MIN, ocio.GAMMA_MAX) 590 self._gamma_widget.setStepSize(ocio.GAMMA_STEP_SIZE) 591 self._gamma_widget.setPrecision(ocio.GAMMA_PRECISION) 592 self._gamma_widget.setValue(self._gamma) 593 mari.utils.connect( 594 self._gamma_widget.valueChanged, 595 lambda value: self.setGamma(value = value, update_widget = False, update_metadata = True)) 596 self._gamma_widget.addToLayout(layout) 597 598 self._gamma_reset_widget = self._addSmallButtom( 599 layout, 600 'R', 601 'Reset gamma to default', 602 lambda: self.setGamma(value = ocio.GAMMA_RESET, update_widget = True, update_metadata = True)) 603 604 #----------------------------------------------------------------------------------------- 605 606 def _updateDisplayWidgets(self): 607 color_spaces = [color_space.getName() for color_space in self._config.getColorSpaces()] 608 609 self._updateComboBox(self._color_space_widget, color_spaces, self._color_space, ocio.color_space_default) 610 self._color_space = self._color_space_widget.currentText 611 612 self._updateComboBox(self._display_widget, self._config.getDisplays(), self._display, ocio.display_default) 613 self._display = self._display_widget.currentText 614 615 self._updateComboBox(self._view_widget, self._config.getViews(self._display), self._view, ocio.view_default) 616 self._view = self._view_widget.currentText 617 618 self._updateComboBox(self._swizzle_widget, ocio.SWIZZLE_TYPES, self._swizzle, ocio.swizzle_default) 619 self._swizzle = self._swizzle_widget.currentText 620 621 self._updateGainWidgets() 622 623 self._gamma_widget.setValue(self._gamma) 624 625 #----------------------------------------------------------------------------------------- 626 627 def _enableWidgets(self, enable): 628 self._select_config_action.setEnabled(enable) 629 self._select_lut_action.setEnabled(enable) 630 lut_enable = enable and not self._lut_file_list.isEmpty() 631 self._clear_lut_action.setEnabled(lut_enable) 632 self._lut_extrapolate_widget.setEnabled(lut_enable) 633 634 self._color_space_widget.setEnabled(enable) 635 self._display_widget.setEnabled(enable) 636 self._view_widget.setEnabled(enable) 637 self._swizzle_widget.setEnabled(enable) 638 639 self._fstop_widget.setEnabled(enable) 640 self._fstop_decrement_widget.setEnabled(enable) 641 self._fstop_increment_widget.setEnabled(enable) 642 self._gain_widget.setEnabled(enable) 643 self._exposure_widget.setEnabled(enable) 644 self._gain_reset_widget.setEnabled(enable) 645 646 self._gamma_widget.setEnabled(enable) 647 self._gamma_reset_widget.setEnabled(enable) 648 649 #----------------------------------------------------------------------------------------- 650 651 def _addAction(self, identifier, command, icon_filename, tip, whats_this): 652 action = mari.actions.find(identifier) 653 if action is None: 654 action = mari.actions.create(identifier, command) 655 656 icon_path = mari.resources.path(mari.resources.ICONS) + '/' + icon_filename 657 action.setIconPath(icon_path) 658 659 action.setStatusTip(tip) 660 action.setToolTip(tip) 661 action.setWhatsThis(whats_this) 662 663 return action 664 665 #----------------------------------------------------------------------------------------- 666 667 def _addWidgetGroup(self): 668 group_widget = QtGui.QWidget() 669 self._toolbar.addWidget(group_widget) 670 671 layout = QtGui.QHBoxLayout() 672 layout.setSpacing(1) 673 layout.setMargin(1) 674 group_widget.setLayout(layout) 675 676 return (group_widget, layout) 677 678 #----------------------------------------------------------------------------------------- 679 680 def _addComboBox(self, label, items, value, default, value_changed, *args): 681 group_widget, layout = self._addWidgetGroup() 682 683 layout.addWidget(QtGui.QLabel(label)) 684 685 widget = QtGui.QComboBox() 686 self._updateComboBox(widget, items, value, default) 687 widget.connect(QtCore.SIGNAL('currentIndexChanged(const QString &)'), value_changed) 688 layout.addWidget(widget) 689 690 return widget 691 692 #----------------------------------------------------------------------------------------- 693 694 def _updateComboBox(self, widget, items, value, default): 695 block = widget.blockSignals(True) 696 697 widget.clear() 698 for item in items: 699 widget.addItem(item) 700 701 if items.count(value) != 0: 702 widget.setCurrentIndex(items.index(value)) 703 elif items.count(default) != 0: 704 widget.setCurrentIndex(items.index(default)) 705 706 widget.blockSignals(block) 707 708 #----------------------------------------------------------------------------------------- 709 710 def _addSmallButtom(self, layout, label, tool_tip, value_changed, *args): 711 widget = QtGui.QPushButton(label); 712 widget.setToolTip(tool_tip); 713 widget.setFixedHeight(16); 714 widget.setFixedWidth(16); 715 widget.connect(QtCore.SIGNAL('released()'), value_changed) 716 layout.addWidget(widget); 717 718 return widget 719 720 #----------------------------------------------------------------------------------------- 721 722 def _convertFStopWidgetValueToGain(self, value): 723 widget_max = int(math.ceil(ocio.EXPOSURE_DELTA / ocio.FSTOP_STEP_SIZE)) 724 scale = float(value) / float(widget_max) 725 exposure = ocio.EXPOSURE_MIN + scale * ocio.EXPOSURE_DELTA 726 return ocio.convertExposureToGain(exposure) 727 728 #----------------------------------------------------------------------------------------- 729 730 def _convertExposureWidgetValueToGain(self, value): 731 widget_max = int(math.ceil(ocio.EXPOSURE_DELTA / ocio.EXPOSURE_STEP_SIZE)) 732 scale = float(value) / float(widget_max) 733 exposure = ocio.EXPOSURE_MIN + scale * ocio.EXPOSURE_DELTA 734 return ocio.convertExposureToGain(exposure) 735 736 #----------------------------------------------------------------------------------------- 737 738 def _updateFStopWidgetText(self, fstop): 739 block = self._fstop_widget.blockSignals(True) 740 if fstop < 10.0: 741 # Floor the value to one decimal place and only display the decimal point if necessary 742 text = '%f' % fstop 743 index = text.index('.') 744 if text[index + 1] == '0': 745 text = text[:index] 746 else: 747 text = text[:index + 2] 748 self._fstop_widget.setText('f/%s' % text) 749 else: 750 self._fstop_widget.setText('f/%d' % int(fstop)) 751 self._fstop_widget.blockSignals(block) 752 753 #----------------------------------------------------------------------------------------- 754 755 def _updateGainWidgetText(self): 756 block = self._gain_widget.blockSignals(True) 757 self._gain_widget.setText(('%.' + ('%d' % ocio.GAIN_PRECISION) + 'f') % self._gain) 758 self._gain_widget.home(False) 759 self._gain_widget.blockSignals(block) 760 761 #----------------------------------------------------------------------------------------- 762 763 def _updateGainWidgets(self): 764 exposure = ocio.convertGainToExposure(self._gain) 765 fstop = ocio.convertExposureToFStop(exposure) 766 self._updateFStopWidgetText(fstop) 767 768 scale = (exposure - ocio.EXPOSURE_MIN) / ocio.EXPOSURE_DELTA 769 widget_max = int(math.ceil(ocio.EXPOSURE_DELTA / ocio.FSTOP_STEP_SIZE)) 770 widget_value = int(round(scale * float(widget_max))) 771 block = self._fstop_widget.blockSignals(True) 772 self._fstop_widget.setValue(widget_value) 773 self._fstop_widget.blockSignals(block) 774 775 self._updateGainWidgetText() 776 777 widget_max = int(math.ceil(ocio.EXPOSURE_DELTA / ocio.EXPOSURE_STEP_SIZE)) 778 widget_value = int(round(scale * float(widget_max))) 779 block = self._gain_widget.blockSignals(True) 780 self._gain_widget.setValue(widget_value) 781 self._gain_widget.blockSignals(block) 782 block = self._exposure_widget.blockSignals(True) 783 self._exposure_widget.setValue(widget_value) 784 self._exposure_widget.blockSignals(block) 785 786 #----------------------------------------------------------------------------------------- 787 788 def _toggleColorManagement(self): 789 enabled = self.isColorManagementEnabled() 790 mari.gl_render.setPostProcessingEnabled(enabled) 791 self._enableWidgets(enabled) 792 ocio.printMessage(ocio.MessageType.DEBUG, 'Toggled color management to \'%s\'' % ('on' if enabled else 'off')) 793 794 #----------------------------------------------------------------------------------------- 795 796 def _clearLUT(self): 797 self.setLUTPath('') 798 ocio.printMessage(ocio.MessageType.DEBUG, 'Cleared lut') 799 800 #----------------------------------------------------------------------------------------- 801 802 def _fstopMovedMouse(self, value): 803 self.setGain(self._convertFStopWidgetValueToGain(float(value)), False) 804 805 exposure = ocio.convertGainToExposure(self._gain) 806 fstop = ocio.convertExposureToFStop(exposure) 807 self._updateFStopWidgetText(fstop) 808 809 self._updateGainWidgetText() 810 811 widget_max = int(math.ceil(ocio.EXPOSURE_DELTA / ocio.EXPOSURE_STEP_SIZE)) 812 scale = (exposure - ocio.EXPOSURE_MIN) / ocio.EXPOSURE_DELTA 813 value = int(round(scale * float(widget_max))) 814 self._gain_widget.setValue(value) 815 816 value = max(min(value, widget_max), 0) 817 self._exposure_widget.setValue(value) 818 819 #----------------------------------------------------------------------------------------- 820 821 def _gainMovedMouse(self, value): 822 self.setGain(self._convertExposureWidgetValueToGain(float(value)), False) 823 824 self._updateGainWidgetText() 825 826 widget_max = int(math.ceil(ocio.EXPOSURE_DELTA / ocio.EXPOSURE_STEP_SIZE)) 827 value = max(min(value, widget_max), 0) 828 self._exposure_widget.setValue(value) 829 830 exposure = ocio.convertGainToExposure(self._gain) 831 fstop = ocio.convertExposureToFStop(exposure) 832 self._updateFStopWidgetText(fstop) 833 834 scale = (exposure - ocio.EXPOSURE_MIN) / ocio.EXPOSURE_DELTA 835 widget_max = int(math.ceil(ocio.EXPOSURE_DELTA / ocio.FSTOP_STEP_SIZE)) 836 value = int(round(scale * float(widget_max))) 837 self._fstop_widget.setValue(value) 838 839 #----------------------------------------------------------------------------------------- 840 841 def _exposureChanged(self, value): 842 self.setGain(value = self._convertExposureWidgetValueToGain(float(value)), 843 update_widget = False, 844 update_metadata = True) 845 846 self._updateGainWidgetText() 847 848 self._gain_widget.setValue(value) 849 850 exposure = ocio.convertGainToExposure(self._gain) 851 fstop = ocio.convertExposureToFStop(exposure) 852 self._updateFStopWidgetText(fstop) 853 854 scale = (exposure - ocio.EXPOSURE_MIN) / ocio.EXPOSURE_DELTA 855 widget_max = int(math.ceil(ocio.EXPOSURE_DELTA / ocio.FSTOP_STEP_SIZE)) 856 value = int(round(scale * float(widget_max))) 857 self._fstop_widget.setValue(value) 858 859 #----------------------------------------------------------------------------------------- 860 # Metadata: 861 #----------------------------------------------------------------------------------------- 862 863 def _buildMetadata(self): 864 # LUT: 865 # --- 866 mari.utils.connect(self._lut_filter.metadataValueChanged, lutMetadataValueChanged) 867 self._updateLUTMetadata() 868 869 flags = self._lut_filter.METADATA_VISIBLE | self._lut_filter.METADATA_EDITABLE 870 self._lut_filter.setMetadataFlags('File', flags) 871 872 self._lut_filter.setMetadataFlags('Extrapolate', flags) 873 874 # Display: 875 # ------- 876 mari.utils.connect(self._display_filter.metadataValueChanged, displayMetadataValueChanged) 877 self._updateDisplayMetadata() 878 879 self._display_filter.setMetadataDisplayName('ConfigPath', 'Configuration File') 880 flags = self._display_filter.METADATA_VISIBLE | self._display_filter.METADATA_EDITABLE 881 self._display_filter.setMetadataFlags('ConfigPath', flags) 882 883 self._display_filter.setMetadataDisplayName('InputColorSpace', 'Input Color Space') 884 self._display_filter.setMetadataFlags('InputColorSpace', flags) 885 886 self._display_filter.setMetadataDisplayName('Display', 'Display Device') 887 self._display_filter.setMetadataFlags('Display', flags) 888 889 self._display_filter.setMetadataDisplayName('View', 'View Transform') 890 self._display_filter.setMetadataFlags('View', flags) 891 892 self._display_filter.setMetadataDisplayName('Swizzle', 'Component') 893 self._display_filter.setMetadataFlags('Swizzle', flags) 894 895 self._display_filter.setMetadataDefault('Gain', ocio.GAIN_RESET) 896 self._display_filter.setMetadataRange('Gain', ocio.GAIN_MIN, ocio.GAIN_MAX) 897 self._display_filter.setMetadataStep('Gain', ocio.GAIN_STEP_SIZE) 898 self._display_filter.setMetadataFlags('Gain', flags) 899 900 self._display_filter.setMetadataDefault('Gamma', ocio.GAMMA_RESET) 901 self._display_filter.setMetadataRange('Gamma', ocio.GAMMA_MIN, ocio.GAMMA_MAX) 902 self._display_filter.setMetadataStep('Gamma', ocio.GAMMA_STEP_SIZE) 903 self._display_filter.setMetadataFlags('Gamma', flags) 904 905 #----------------------------------------------------------------------------------------- 906 907 def _updateLUTMetadata(self): 908 mari.utils.disconnect(self._lut_filter.metadataValueChanged, lutMetadataValueChanged) 909 910 self._lut_filter.setMetadata('File', self._lut_file_list) 911 912 self._lut_filter.setMetadata('Extrapolate', self._lut_extrapolate) 913 914 mari.utils.connect(self._lut_filter.metadataValueChanged, lutMetadataValueChanged) 915 916 #----------------------------------------------------------------------------------------- 917 918 def _updateDisplayMetadata(self): 919 mari.utils.disconnect(self._display_filter.metadataValueChanged, displayMetadataValueChanged) 920 921 self._display_filter.setMetadata('ConfigPath', self._config_file_list) 922 923 color_spaces = [color_space.getName() for color_space in self._config.getColorSpaces()] 924 925 self._display_filter.setMetadata('InputColorSpace', self._color_space) 926 self._display_filter.setMetadataItemList('InputColorSpace', color_spaces) 927 928 self._display_filter.setMetadata('Display', self._display) 929 self._display_filter.setMetadataItemList('Display', self._config.getDisplays()) 930 931 self._display_filter.setMetadata('View', self._view) 932 self._display_filter.setMetadataItemList('View', self._config.getViews(self._display)) 933 934 self._display_filter.setMetadata('Swizzle', self._swizzle) 935 self._display_filter.setMetadataItemList('Swizzle', ocio.SWIZZLE_TYPES) 936 937 self._display_filter.setMetadata('Gain', self._gain) 938 939 self._display_filter.setMetadata('Gamma', self._gain) 940 941 mari.utils.connect(self._display_filter.metadataValueChanged, displayMetadataValueChanged) 942 943 944 #----------------------------------------------------------------------------------------- 945 # External Connections: 946 #----------------------------------------------------------------------------------------- 947 948 def _openedProject(self, project): 949 ocio.printMessage(ocio.MessageType.DEBUG, 'Loading settings for project \'%s\'' % project.name()) 950 951 # Load the settings stored as metadata on the project... 952 953 # General: 954 # ------- 955 956 self._toggle_color_management_action.setEnabled(True) 957 self._toggle_color_management_action.setChecked(project.metadata('ColorEnabled') if project.hasMetadata('ColorEnabled') else ocio.enabled_default) 958 959 # Enable/disable color management (MUST be done after modifications to 'self._toggle_color_management_action'. 960 mari.gl_render.setPostProcessingEnabled(self.isColorManagementEnabled()) 961 962 filter_collection = None 963 if project.hasMetadata('ColorProfile'): 964 # *** IMPORTANT *** The post filter collection used to be called 'OpenColorIO' but was renamed to hide the 965 # fact we use OpenColorIO from our users. So as a temporary workaround we need to check for the old filter 966 # collection correct for it. 967 name = project.metadata('ColorProfile') 968 if name == 'OpenColorIO': 969 name = 'Color Space' 970 filter_collection = mari.gl_render.findPostFilterCollection(name) 971 972 # Default the color management filter stack if the working one doesn't exist. 973 if filter_collection is None: 974 filter_collection = mari.gl_render.findPostFilterCollection(ocio.profile_default) 975 976 mari.gl_render.setPostFilterCollection(filter_collection) 977 978 # LUT: 979 # --- 980 981 lut_extrapolate = project.metadata('OcioLutExtrapolate') if project.hasMetadata('OcioLutExtrapolate') else ocio.lut_extrapolate_default 982 force_shader_build = lut_extrapolate != self._lut_extrapolate 983 self._lut_extrapolate = lut_extrapolate 984 self._lut_extrapolate_widget.setChecked(self._lut_extrapolate) 985 986 if project.hasMetadata('OcioLutPath'): 987 lut_path = ocio.buildLoadPath(project.metadata('OcioLutPath')) 988 if not self.setLUTPath(value = lut_path, update_metadata = True, force_shader_build = force_shader_build): 989 self.resetLUT() 990 else: 991 self.resetLUT() 992 993 # Display: 994 # ------- 995 996 self._color_space = project.metadata( 'OcioColorSpace') if project.hasMetadata('OcioColorSpace') else ocio.color_space_default 997 self._display = project.metadata( 'OcioDisplay') if project.hasMetadata( 'OcioDisplay') else ocio.display_default 998 self._view = project.metadata( 'OcioView') if project.hasMetadata( 'OcioView') else ocio.view_default 999 self._swizzle = project.metadata( 'OcioSwizzle') if project.hasMetadata( 'OcioSwizzle') else ocio.swizzle_default 1000 self._gain = max(min(project.metadata('OcioGain'), 1001 ocio.GAIN_MAX), 1002 ocio.GAIN_MIN) if project.hasMetadata( 'OcioGain') else ocio.gain_default 1003 self._gamma = project.metadata( 'OcioGamma') if project.hasMetadata( 'OcioGamma') else ocio.gamma_default 1004 1005 # Attempt to load a configuration file... 1006 self._config_file_list.clear() 1007 self._config = None 1008 1009 # 1. Environment variable. 1010 config_path = os.getenv('OCIO') 1011 if config_path is not None: 1012 self.setConfigPath(config_path) 1013 1014 # 2. Project setting. 1015 if self._config is None and project.hasMetadata('OcioConfigPath'): 1016 self.setConfigPath(ocio.buildLoadPath(project.metadata('OcioConfigPath'))) 1017 1018 # 3. Use the default if nothing was found. 1019 if self._config is None: 1020 self._config_file_list = mari.FileList(ocio.config_file_list_default) 1021 self._config = ocio.config_default 1022 1023 self._updateDisplayWidgets() 1024 self._rebuildDisplayFilter() 1025 1026 self._enableWidgets(filter_collection.name() == 'Color Space' and self._toggle_color_management_action.isChecked()) 1027 self._updateLUTMetadata() 1028 self._updateDisplayMetadata() 1029 1030 self._printLog() 1031 1032 #----------------------------------------------------------------------------------------- 1033 1034 def _aboutToSaveProject(self, project): 1035 ocio.printMessage(ocio.MessageType.DEBUG, 'Saving settings for project \'%s\'' % project.name()) 1036 1037 # Store the settings as metadata on the project. 1038 project.setMetadata( 'ColorEnabled', self.isColorManagementEnabled()) 1039 filter_collection = mari.gl_render.currentPostFilterCollection() 1040 if filter_collection is not None: 1041 project.setMetadata( 'ColorProfile', filter_collection.name()) 1042 project.setMetadata('OcioLutExtrapolate', self._lut_extrapolate) 1043 project.setMetadata( 'OcioLutPath', '' if self._lut_file_list.isEmpty() else ocio.buildSavePath(self._lut_file_list.at(0))) 1044 if os.getenv('OCIO') is None: 1045 project.setMetadata('OcioConfigPath', '' if self._config_file_list.isEmpty() else ocio.buildSavePath(self._config_file_list.at(0))) 1046 project.setMetadata( 'OcioColorSpace', self._color_space) 1047 project.setMetadata( 'OcioDisplay', self._display) 1048 project.setMetadata( 'OcioView', self._view) 1049 project.setMetadata( 'OcioSwizzle', self._swizzle) 1050 project.setMetadata( 'OcioGain', self._gain) 1051 project.setMetadata( 'OcioGamma', self._gamma) 1052 1053 #----------------------------------------------------------------------------------------- 1054 1055 def _closedProject(self): 1056 self._toggle_color_management_action.setEnabled(False) 1057 self._enableWidgets(False) 1058 1059 #----------------------------------------------------------------------------------------- 1060 1061 def _toolBarsCreated(self): 1062 # Things like deleting Mari's configuration file and reseting the layout to the default will destroy the toolbar 1063 # so we need to detect if this is the case and rebuild it! 1064 toolbar = mari.app.findToolBar('Color Space') 1065 if toolbar is None: 1066 ocio.printMessage(ocio.MessageType.DEBUG, 'Rebuilding missing toolbar...') 1067 self._buildWidgets() 1068 1069 #----------------------------------------------------------------------------------------- 1070 1071 def _postProcessingEnabled(self, enabled): 1072 self._toggle_color_management_action.setChecked(enabled) 1073 1074 # Only enable or disable UI if we have a current project. 1075 current_project = mari.projects.current() 1076 if current_project is not None: 1077 self._enableWidgets(enabled) 1078 1079 #----------------------------------------------------------------------------------------- 1080 1081 def _setCurrentPostFilterCollection(self): 1082 # Only enable or disable UI if we have a current project. 1083 current_project = mari.projects.current() 1084 if current_project is not None: 1085 filter_collection = mari.gl_render.currentPostFilterCollection() 1086 if filter_collection is None or filter_collection.name() != 'Color Space': 1087 ocio.printMessage(ocio.MessageType.DEBUG, 'Disabling OpenColorIO') 1088 self._enableWidgets(False) 1089 else: 1090 ocio.printMessage(ocio.MessageType.DEBUG, 'Enabling OpenColorIO') 1091 self._enableWidgets(True) 1092 1093 #----------------------------------------------------------------------------------------- 1094 # Filter: 1095 #----------------------------------------------------------------------------------------- 1096 1097 def _rebuildLUTFilter(self, lut_path, force_shader_build = False): 1098 if lut_path == '': 1099 self._lut_filter.setDefinitionsSnippet('') 1100 self._lut_filter.setBodySnippet('') 1101 1102 if self._lut_sampler_name is not None: 1103 self._lut_filter.deleteTexture(self._lut_sampler_name) 1104 self._lut_sampler_name = None 1105 1106 self._lut_filter_cache_id = None 1107 self._lut_texture_cache_id = None 1108 1109 else: 1110 # There is a chance this is a bad file so we need to guard against it. 1111 try: 1112 self._lut_filter_cache_id, self._lut_texture_cache_id, self._lut_sampler_name = ocio.buildLUTFilter( 1113 self._config, 1114 lut_path, 1115 self._lut_filter, 1116 self._lut_filter_cache_id, 1117 self._lut_texture_cache_id, 1118 self._lut_extrapolate, 1119 force_shader_build) 1120 1121 except Exception, e: 1122 message = 'Failed to load LUT file \'%s\' due to \'%s\'' % (lut_path, e) 1123 ocio.printMessage(ocio.MessageType.ERROR, '%s' % message) 1124 if not mari.app.inTerminalMode(): 1125 mari.utils.misc.message(message, 'Color Space', 1024, 2) 1126 1127 return False 1128 1129 ocio.printMessage(ocio.MessageType.DEBUG, 'Changed LUT to \'%s\'' % lut_path) 1130 1131 return True 1132 1133 #----------------------------------------------------------------------------------------- 1134 1135 def _rebuildDisplayFilter(self): 1136 display_transform = ocio.PyOpenColorIO.DisplayTransform() 1137 display_transform.setInputColorSpaceName(self._color_space) 1138 1139 if hasattr(display_transform, 'setDisplay'): 1140 # OCIO 1.0+ 1141 display_transform.setDisplay(self._display) 1142 display_transform.setView(self._view) 1143 else: 1144 # OCIO 0.8.X 1145 display_color_space = self._config.getDisplayColorSpaceName(self._display, self._view) 1146 display_transform.setDisplayColorSpaceName(display_color_space) 1147 1148 # Add the channel sizzle. 1149 luma_coefs = self._config.getDefaultLumaCoefs() 1150 mtx, offset = ocio.PyOpenColorIO.MatrixTransform.View(ocio.SWIZZLE_VALUES[self._swizzle], luma_coefs) 1151 1152 transform = ocio.PyOpenColorIO.MatrixTransform() 1153 transform.setValue(mtx, offset) 1154 display_transform.setChannelView(transform) 1155 1156 # Add the linear gain. 1157 transform = ocio.PyOpenColorIO.CDLTransform() 1158 transform.setSlope((self._gain, self._gain, self._gain)) 1159 display_transform.setLinearCC(transform) 1160 1161 # Add the post-display CC. 1162 transform = ocio.PyOpenColorIO.ExponentTransform() 1163 transform.setValue([1.0 / max(1e-6, v) for v in (self._gamma, self._gamma, self._gamma, self._gamma)]) 1164 display_transform.setDisplayCC(transform) 1165 1166 processor = self._config.getProcessor(display_transform) 1167 1168 self._display_filter_cache_id, self._display_texture_cache_id, self._display_sampler_name = ocio.buildProcessorFilter( 1169 processor, 1170 self._display_filter, 1171 self._display_filter_cache_id, 1172 self._display_texture_cache_id) 1173 1174 current_canvas = mari.canvases.current() 1175 if current_canvas is not None: 1176 current_canvas.repaint() 1177 1178 #----------------------------------------------------------------------------------------- 1179 # Debugging: 1180 #----------------------------------------------------------------------------------------- 1181 1182 def _printLog(self): 1183 ocio.printMessage( ocio.MessageType.INFO, '==============================================================') 1184 ocio.printMessage( ocio.MessageType.INFO, 'Configuration:') 1185 ocio.printMessage( ocio.MessageType.INFO, '==============================================================') 1186 ocio.printMessage( ocio.MessageType.INFO, ' Enabled: %s; Default: %s' % (mari.gl_render.isPostProcessingEnabled(), 1187 ocio.enabled_default)) 1188 filter_collection = mari.gl_render.currentPostFilterCollection() 1189 if filter_collection is not None: 1190 ocio.printMessage(ocio.MessageType.INFO, ' Profile: %s; Default: %s' % (filter_collection.name(), 1191 ocio.profile_default)) 1192 else: 1193 ocio.printMessage(ocio.MessageType.INFO, ' Profile: None; Default: %s' % (ocio.profile_default)) 1194 ocio.printMessage( ocio.MessageType.INFO, ' LUT Path: %s; Default: %s' % ('' if self._lut_file_list.isEmpty() else self._lut_file_list.at(0), 1195 '' if ocio.lut_file_list_default.isEmpty() else ocio.lut_file_list_default.at(0))) 1196 ocio.printMessage( ocio.MessageType.INFO, ' Extrapolate: %s; Default: %s' % (self._lut_extrapolate, 1197 ocio.lut_extrapolate_default)) 1198 ocio.printMessage( ocio.MessageType.INFO, ' Config Path: %s; Default: %s' % ('' if self._config_file_list.isEmpty() else self._config_file_list.at(0), 1199 '' if ocio.config_file_list_default.isEmpty() else ocio.config_file_list_default.at(0))) 1200 ocio.printMessage( ocio.MessageType.INFO, ' Color Space: %s; Default: %s' % (self._color_space, 1201 ocio.color_space_default)) 1202 ocio.printMessage( ocio.MessageType.INFO, ' Display: %s; Default: %s' % (self._display, 1203 ocio.display_default)) 1204 ocio.printMessage( ocio.MessageType.INFO, ' View: %s; Default: %s' % (self._view, 1205 ocio.view_default)) 1206 ocio.printMessage( ocio.MessageType.INFO, ' Swizzle: %s; Default: %s' % (self._swizzle, 1207 ocio.swizzle_default)) 1208 ocio.printMessage( ocio.MessageType.INFO, ' F-Stop: %f; Default: %f; Center: %f' % (ocio.convertGainToFStop(self._gain), 1209 ocio.convertGainToFStop(ocio.gain_default), 1210 ocio.fstop_center)) 1211 ocio.printMessage( ocio.MessageType.INFO, ' Gain: %f; Default: %f' % (self._gain, 1212 ocio.gain_default)) 1213 ocio.printMessage( ocio.MessageType.INFO, ' Gamma: %f; Default: %f' % (self._gamma, 1214 ocio.gamma_default)) 1215 ocio.printMessage( ocio.MessageType.INFO, '==============================================================') 1216 1217############################################################################################## 1218# The following functions CAN'T be part of the toolbar class as a potential bug in PythonQt 1219# causes the disconnect function to fail 1220 1221def lutMetadataValueChanged(name, value): 1222 global toolbar 1223 1224 ocio.printMessage(ocio.MessageType.DEBUG, 'LUT metadata \'%s\' changed to \'%s\'' % (name, value)) 1225 1226 if name == 'File': 1227 toolbar.setLUTPath(value = '' if value.isEmpty() else value.at(0), 1228 update_metadata = False, 1229 force_shader_build = False) 1230 1231 elif name == 'Extrapolate': 1232 toolbar.setExtrapolateEnabled(value = value, update_widget = True, update_metadata = False) 1233 1234#----------------------------------------------------------------------------------------- 1235 1236def displayMetadataValueChanged(name, value): 1237 global toolbar 1238 1239 ocio.printMessage(ocio.MessageType.DEBUG, 'Display metadata \'%s\' changed to \'%s\'' % (name, value)) 1240 1241 if name == 'ConfigPath': 1242 toolbar.setConfigPath(value = '' if value.isEmpty() else value.at(0), update_metadata = False) 1243 1244 elif name == 'InputColorSpace': 1245 toolbar.setColorSpace(value = value, update_widget = True, update_metadata = False) 1246 1247 elif name == 'Display': 1248 toolbar.setDisplay(value = value, update_widget = True, update_metadata = False) 1249 1250 elif name == 'View': 1251 toolbar.setView(value = value, update_widget = True, update_metadata = False) 1252 1253 elif name == 'Swizzle': 1254 toolbar.setSwizzle(value = value, update_widget = True, update_metadata = False) 1255 1256 elif name == 'Gain': 1257 toolbar.setGain(value = value, update_widget = True, update_metadata = False) 1258 1259 elif name == 'Gamma': 1260 toolbar.setGamma(value = value, update_widget = True, update_metadata = False) 1261 1262############################################################################################## 1263 1264if mari.app.isRunning(): 1265 if not hasattr(mari.gl_render, 'createPostFilterCollection'): 1266 ocio.printMessage(ocio.MessageType.ERROR, 'This version of Mari does not support the mari.gl_render.createPostFilterCollection API') 1267 1268 else: 1269 if ocio.config_default is not None: 1270 toolbar = OcioToolBar() 1271 1272 else: 1273 # Destroy the OCIO post filter collection if present to prevent the user trying to use it. 1274 filter_collection = mari.gl_render.findPostFilterCollection('Color Space') 1275 if filter_collection is not None: 1276 mari.gl_render.deletePostFilterCollection(filter_collection) 1277 1278 # Destroy the toolbar to prevent the user trying to use it. 1279 mari.app.deleteToolBar('Color Space') 1280