Skip to content

Commit

Permalink
Merge pull request #87 from masqu3rad3/TIK-114-Gaffer-Integration
Browse files Browse the repository at this point in the history
Tik 114 gaffer integration
  • Loading branch information
masqu3rad3 authored Apr 6, 2024
2 parents 60aef43 + d59502a commit f9afcc8
Show file tree
Hide file tree
Showing 23 changed files with 393 additions and 17 deletions.
3 changes: 3 additions & 0 deletions package/tik_manager4_innosetup.iss
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ Name: "Nuke"; Description: "Nuke"; Flags: checkedonce
Name: "Photoshop"; Description: "Photoshop"; Flags: checkedonce
Name: "Katana"; Description: "Katana"; Flags: checkedonce
Name: "Mari"; Description: "Mari"; Flags: checkedonce
Name: "Gaffer"; Description: "Gaffer"; Flags: checkedonce

[Code]
type
Expand Down Expand Up @@ -93,6 +94,8 @@ begin
strFlag := strFlag + ' ' + 'Katana';
if WizardIsTaskSelected('Mari') then
strFlag := strFlag + ' ' + 'Mari';
if WizardIsTaskSelected('Gaffer') then
strFlag := strFlag + ' ' + 'Gaffer';
result := strFlag;
end;
Expand Down
2 changes: 2 additions & 0 deletions tik_manager4/dcc/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
from tik_manager4.dcc.max.main import Dcc
elif NAME == "blender":
from tik_manager4.dcc.blender.main import Dcc
elif NAME == "gaffer":
from tik_manager4.dcc.gaffer.main import Dcc
elif NAME == "houdini":
from tik_manager4.dcc.houdini.main import Dcc
elif NAME == "katana":
Expand Down
56 changes: 53 additions & 3 deletions tik_manager4/dcc/dcc_install.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ def __init__(self, argv):
"Photoshop": self.photoshop_setup,
"Katana": self.katana_setup,
"Mari": self.mari_setup,
"Gaffer": self.gaffer_setup,
}

def install_all(self):
Expand All @@ -69,6 +70,7 @@ def install_all(self):
self.photoshop_setup(prompt=False)
self.katana_setup(prompt=False)
self.mari_setup(prompt=False)
self.gaffer_setup(prompt=False)
ret = input("Setup Completed. Press Enter to Exit...")
assert isinstance(ret, str)
sys.exit()
Expand Down Expand Up @@ -516,7 +518,6 @@ def mari_setup(self, prompt=True):
_r = input("Press Enter to continue...")
assert isinstance(_r, str)


def photoshop_setup(self, prompt=True):
"""Install the Photoshop plugin."""
print_msg("Starting Photoshop Setup...")
Expand Down Expand Up @@ -604,6 +605,57 @@ def photoshop_setup(self, prompt=True):
ret = input("Press Enter to continue...")
assert isinstance(ret, str)

def gaffer_setup(self, prompt=True):
"""Install Gaffer integration."""
print_msg("Starting Gaffer Setup...")

# find the gaffer installation folder.
places_to_look = ["C:/Program Files", "C:/Program Files (x86)", "C:/opt", "C:/software"]

gaffer_versions = []
for place in places_to_look:
# it the place doesn't exist, skip it
if not Path(place).exists():
continue
# look for folders that starts with "gaffer" and append them to the list
for x in Path(place).iterdir():
# print("path", x)
if x.is_dir() and x.name.startswith("gaffer"):
print("gaffer", x)
gaffer_versions.append(x)
# gaffer_versions.extend([x for x in Path(place).iterdir() if x.is_dir() and x.name.startswith("gaffer")])

# for each gaffer version check for the startup/gui folders. If they don't exist, skip the version
for version in list(gaffer_versions):
gui_folder = version / "startup" / "gui"
if not gui_folder.exists():
gaffer_versions.remove(version)
if not gaffer_versions:
print_msg("No Gaffer version can be found.")
print_msg(f"Make sure Gaffer is installed in one of the following folder and try again. {places_to_look}"
"Alternatively you can try manual install. "
"Check the documentation for more information.")
if prompt:
ret = input("Press Enter to continue...")
assert isinstance(ret, str)
return
source_init_file = self.tik_dcc_folder / "gaffer" / "setup" / "tik_4_init.py"

for version in gaffer_versions:
print_msg(f"Setting up {version.name}...")
gui_folder = version / "startup" / "gui"
init_file = gui_folder / "tik_4_init.py"
shutil.copy(source_init_file, init_file)
injector = Injector(init_file)
injector.match_mode = "contains"
injector.replace_single_line(f"tik_path = '{self.tik_root.parent.as_posix()}'",
line="tik_path = ")

print_msg("Gaffer setup completed.")
if prompt:
_r = input("Press Enter to continue...")
assert isinstance(_r, str)

def __set_csx_key(self, val):
"""Convenience function to set the csx key."""
try:
Expand Down Expand Up @@ -888,8 +940,6 @@ def replace_single_line(self, new_content, line, suppress_warnings=False):
self._dump_content(injected_content)
return True



def read(self):
"""Reads the file."""
if not self.file_path.is_file():
Expand Down
Empty file.
22 changes: 22 additions & 0 deletions tik_manager4/dcc/gaffer/extract/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import os
import glob
import importlib
import inspect
from tik_manager4.dcc.extract_core import ExtractCore

classes = {}
modules = glob.glob(os.path.join(os.path.dirname(__file__), "*.py"))

exceptions = ["__init__.py"]

for mod in modules:
file_name = os.path.basename(mod)
if file_name not in exceptions and not file_name.startswith("_"):
module_name = file_name[:-3]
module_path = os.path.join(os.path.dirname(__file__), module_name)
module = importlib.import_module(f"{__name__}.{module_name}")

for name, obj in inspect.getmembers(module):
if inspect.isclass(obj) and issubclass(obj, ExtractCore) and obj != ExtractCore:
classes[obj.name] = obj

24 changes: 24 additions & 0 deletions tik_manager4/dcc/gaffer/extract/source.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
"""Extract Gaffer Scene."""

from tik_manager4.dcc.gaffer import gaffer_menu

from tik_manager4.dcc.extract_core import ExtractCore

class Source(ExtractCore):
"""Extract Gaffer scene."""

nice_name = "Source Scene"
color = (255, 255, 255)

def __init__(self):
super(Source, self).__init__()
self.gaffer = gaffer_menu.GafferMenu()
self.extension = ".gfr"

def _extract_default(self):
"""Extract method for any non-specified category"""
_file_path = self.resolve_output()
_original_path = self.gaffer.script["fileName"].getValue()
self.gaffer.script["fileName"].setValue(_file_path)
self.gaffer.script.save()
self.gaffer.script["fileName"].setValue(_original_path)
30 changes: 30 additions & 0 deletions tik_manager4/dcc/gaffer/gaffer_menu.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
"""Class for holding Gaffer menu."""

import Gaffer
import GafferUI

class GafferMenu:
"""Class for holding Gaffer menu."""
menu = None

@classmethod
def set_menu(cls, menu):
"""Set the menu."""
cls.menu = menu

@property
def script_window(self):
"""Get the script window."""
return self.menu.ancestor(GafferUI.ScriptWindow)

@property
def script(self):
"""Return the script."""
script_window = self.menu.ancestor(GafferUI.ScriptWindow)
return script_window.scriptNode()

@property
def application(self):
"""Return the application."""
return self.script.ancestor(Gaffer.ApplicationRoot)

21 changes: 21 additions & 0 deletions tik_manager4/dcc/gaffer/ingest/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import os
import glob
import importlib
import inspect
from tik_manager4.dcc.ingest_core import IngestCore

classes = {}
modules = glob.glob(os.path.join(os.path.dirname(__file__), "*.py"))

exceptions = ["__init__.py"]

for mod in modules:
file_name = os.path.basename(mod)
if file_name not in exceptions and not file_name.startswith("_"):
module_name = file_name[:-3]
module_path = os.path.join(os.path.dirname(__file__), module_name)
module = importlib.import_module(f"{__name__}.{module_name}")

for name, obj in inspect.getmembers(module):
if inspect.isclass(obj) and issubclass(obj, IngestCore) and obj != IngestCore:
classes[obj.name] = obj
25 changes: 25 additions & 0 deletions tik_manager4/dcc/gaffer/ingest/reader.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
"""Element reader for Gaffer ingest module"""

from pathlib import Path

import GafferScene

from tik_manager4.dcc.gaffer import gaffer_menu

from tik_manager4.dcc.ingest_core import IngestCore

class Reader(IngestCore):
"""Ingest elements."""

nice_name = "Reader"
valid_extensions = [".abc", ".lscc", ".scc", ".usd", ".usda", ".usdc", ".usdz", ".vdb"]
referencable = False

def __init__(self):
super(Reader, self).__init__()
self.gaffer = gaffer_menu.GafferMenu()
def _bring_in_default(self):
"""Import various file types."""
reader_node = GafferScene.SceneReader()
self.gaffer.script.addChild(reader_node)
reader_node["fileName"].setValue(Path(self.ingest_path).as_posix())
21 changes: 21 additions & 0 deletions tik_manager4/dcc/gaffer/ingest/source.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
"""Ingest source scenne."""

from tik_manager4.dcc.gaffer import gaffer_menu

from tik_manager4.dcc.ingest_core import IngestCore

class Source(IngestCore):
"""Ingest Source Gaffer Scene."""

nice_name = "Ingest Source Scene"
valid_extensions = [".gfr"]
referencable = False

def __init__(self):
super(Source, self).__init__()
self.gaffer = gaffer_menu.GafferMenu()

def _bring_in_default(self):
"""Import the Gaffer scene."""
self.gaffer.script.importFile(self.ingest_path)

115 changes: 115 additions & 0 deletions tik_manager4/dcc/gaffer/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
"""Main module for Gaffer integration."""

import logging

import Gaffer
import GafferUI

from tik_manager4.dcc.gaffer import gaffer_menu

from tik_manager4.dcc.main_core import MainCore
from tik_manager4.dcc.gaffer import validate
from tik_manager4.dcc.gaffer import extract
from tik_manager4.dcc.gaffer import ingest

LOG = logging.getLogger(__name__)

class Dcc(MainCore):
"""Gaffer DCC class."""

name = "Gaffer"
formats = [".gfr"] # File formats supported by the DCC
preview_enabled = False # Whether or not to enable the preview in the UI
validations = validate.classes
extracts = extract.classes
ingests = ingest.classes

# Override the applicable methods from the MainCore class

def __init__(self):
"""Initialize the Gaffer DCC."""
super(Dcc, self).__init__()
self.gaffer = gaffer_menu.GafferMenu()

def get_main_window(self):
"""Get the main window of the DCC."""
return self.gaffer.script_window._qtWidget()

def save_scene(self):
"""Save the current scene."""
self.gaffer.script.save()

def save_as(self, file_path):
"""Save the current scene as the given file path."""
self.gaffer.script["fileName"].setValue(file_path)
self.gaffer.script.save()

if self.gaffer.application:
GafferUI.FileMenu.addRecentFile(self.gaffer.application, file_path)

return file_path

def save_prompt(self):
"""Pop up the save prompt."""
GafferUI.FileMenu.save(self.gaffer.menu)
return True # this is important or else will be an indefinite loop

def open(self, file_path, force=True, **_extra_arguments):
"""Open the given file path
Args:
file_path: (String) File path to open
force: (Bool) if true any unsaved changes on current scene will be lost
**_extra_arguments: Compatibility arguments for other DCCs
Returns: None
"""
self.gaffer.script["fileName"].setValue(file_path)
self.gaffer.script.load()

def is_modified(self):
"""Check if the current scene is modified."""
return self.gaffer.script["unsavedChanges"].getValue()

def get_scene_file(self):
"""Get the current scene file path."""
_filename = self.gaffer.script["fileName"].getValue()
return _filename


def get_ranges(self):
"""Get the viewport ranges."""
playback_range = GafferUI.Playback.acquire( self.gaffer.script.context() ).getFrameRange()
r_ast = self.gaffer.script["frameRange"]["start"].getValue()
r_min = playback_range[0]
r_max = playback_range[1]
r_aet = self.gaffer.script["frameRange"]["end"].getValue()
return [r_ast, r_min, r_max, r_aet]

def get_current_frame(self):
"""Get the current frame."""
return self.gaffer.script["frame"].getValue()

def set_ranges(self, range_list):
"""Set the viewport ranges."""
self.gaffer.script["frameRange"]["start"].setValue(range_list[0])
GafferUI.Playback.acquire(self.gaffer.script.context()).setFrameRange(range_list[1], range_list[2])
self.gaffer.script["frameRange"]["end"].setValue(range_list[3])

def generate_thumbnail(self, file_path, width, height):
"""Generate a thumbnail for the current scene."""
GafferUI.WidgetAlgo.grab(self.gaffer.script_window, file_path)
# TODO: figure out a way to resize/crop the image to the width and height
return file_path

def get_scene_fps(self):
"""Get the FPS of the scene."""
return self.gaffer.script["framesPerSecond"].getValue()

def set_scene_fps(self, fps_value):
"""Set the FPS of the scene."""
self.gaffer.script["framesPerSecond"].setValue(fps_value)

@staticmethod
def get_dcc_version():
"""Get the version of the DCC."""
return Gaffer.About.versionString()
Empty file.
Loading

0 comments on commit f9afcc8

Please sign in to comment.