Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Max: Create/Set Project Folder when starting Max or task changed #2

Merged
merged 12 commits into from
Jul 18, 2024
26 changes: 26 additions & 0 deletions client/ayon_max/api/pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import json

from ayon_core.host import HostBase, IWorkfileHost, ILoadHost, IPublishHost

from ayon_core.lib import register_event_callback
import pyblish.api
from ayon_core.pipeline import (
register_creator_plugin_path,
Expand Down Expand Up @@ -48,8 +50,11 @@ def install(self):
register_creator_plugin_path(CREATE_PATH)

# self._register_callbacks()
_set_project()

self.menu = AYONMenu()

register_event_callback("workfile.open.before", on_before_open)
self._has_been_setup = True

rt.callbacks.addScript(rt.Name('systemPostNew'), on_new)
Expand Down Expand Up @@ -205,6 +210,27 @@ def containerise(name: str, nodes: list, context,
return container


def _set_project():
workdir = os.getenv("AYON_WORKDIR")

os.makedirs(workdir, exist_ok=True)
mxp_filepath = os.path.join(workdir, "workspace.mxp")
if os.path.exists(mxp_filepath):
rt.pathConfig.load(mxp_filepath)
directory_count = rt.pathConfig.getProjectSubDirectoryCount()
for count in range(directory_count):
proj_dir = rt.pathConfig.getProjectSubDirectory(count)
os.makedirs(proj_dir, exist_ok=True)
rt.pathConfig.doProjectSetupStepsUsingDirectory(workdir)
rt.pathConfig.setCurrentProjectFolder(workdir)


def on_before_open():
"""Check and set up project before opening workfile
"""
_set_project()


def load_custom_attribute_data():
"""Re-loading the AYON custom parameter built by the creator

Expand Down
32 changes: 32 additions & 0 deletions client/ayon_max/hooks/pre_copy_mxp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
from ayon_applications import PreLaunchHook, LaunchTypes
from ayon_max.mxp import create_workspace_mxp
from ayon_core.settings import get_project_settings


class PreCopyMxp(PreLaunchHook):
"""Copy workspace.mxp to workdir.

Hook `GlobalHostDataHook` must be executed before this hook.
"""
app_groups = {"3dsmax", "adsk_3dsmax"}
launch_types = {LaunchTypes.local}

def execute(self):
project_entity = self.data["project_entity"]
project_settings = get_project_settings(project_entity.get("name"))
if not project_settings:
return
mxp_workspace = project_settings["max"].get("mxp_workspace")
# Ensure the hook would not cause possible error
# when using the old addon.
if mxp_workspace is None:
self.log.warning("No mxp workspace setting found in the "
"latest Max Addon.")
return

workdir = self.launch_context.env.get("AYON_WORKDIR")
if not workdir:
self.log.warning("BUG: Workdir is not filled.")
return

create_workspace_mxp(workdir, mxp_workspace=mxp_workspace)
48 changes: 48 additions & 0 deletions client/ayon_max/mxp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import os
from ayon_core.lib import Logger


def create_workspace_mxp(workdir, mxp_workspace=None):
dst_filepath = os.path.join(workdir, "workspace.mxp")
if os.path.exists(dst_filepath):
return

log = Logger.get_logger("create_workspace_mxp")
os.makedirs(workdir, exist_ok=True)
max_script = default_mxp_template()
if mxp_workspace.get("enabled_project_creation"):
max_script = mxp_workspace.get("mxp_workspace_script")
# Skip if mxp script in settings is empty
if not max_script:
log.debug("File 'workspace.mxp' not created. Settings value is empty.")
return

with open(dst_filepath, "w") as mxp_file:
mxp_file.write(max_script)

return dst_filepath


def default_mxp_template():
"""Return text script for the path configuration if
users do not enable project creation in AYON project
setting
"""
mxp_template = "\n".join((
'[Directories]',
'Animations= ./',
'Archives=./',
'AutoBackup=./',
'BitmapProxies=./',
'Fluid Simulations=./',
'Images=./',
'MaxStart=./',
'Previews=./',
'RenderAssets=./',
'RenderOutput= ./renders/3dsmax',
'Scenes=./',
'Sounds=./',
'[XReferenceDirs]',
'Dir1=./'
))
return mxp_template
36 changes: 36 additions & 0 deletions server/settings/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,14 @@ def unit_scale_enum():
]


class MxpWorkspaceSettings(BaseSettingsModel):
enabled_project_creation: bool = SettingsField(
False, title="Enable Project Creation")
mxp_workspace_script: str = SettingsField(
title="Max mxp Workspace", widget="textarea"
)


class UnitScaleSettings(BaseSettingsModel):
enabled: bool = SettingsField(True, title="Enabled")
scene_unit_scale: str = SettingsField(
Expand All @@ -46,6 +54,10 @@ class MaxSettings(BaseSettingsModel):
default_factory=UnitScaleSettings,
title="Set Unit Scale"
)
mxp_workspace: MxpWorkspaceSettings = SettingsField(
default_factory=MxpWorkspaceSettings,
title="Max Workspace"
)
imageio: ImageIOSettings = SettingsField(
default_factory=ImageIOSettings,
title="Color Management (ImageIO)"
Expand All @@ -67,11 +79,35 @@ class MaxSettings(BaseSettingsModel):
title="Publish Plugins")


DEFAULT_MXP_WORKSPACE_SETTINGS = "\n".join((
'[Directories]',
'Animations= ./sceneassets/animations',
'Archives=./archives',
'AutoBackup=./autoback',
'BitmapProxies=./proxies',
'Fluid Simulations=./SimCache',
'Images=./sceneassets/images',
'MaxStart=./',
'Previews=./previews',
'RenderAssets=./sceneassets/renderassets',
'RenderOutput= ./renders/3dsmax',
'Scenes=./',
'Sounds=./sceneassets/sounds',
'[XReferenceDirs]',
'Dir1=./',
'',
))


DEFAULT_VALUES = {
"unit_scale_settings": {
"enabled": True,
"scene_unit_scale": "Centimeters"
},
"mxp_workspace": {
"enabled_project_creation": False,
"mxp_workspace_script": DEFAULT_MXP_WORKSPACE_SETTINGS
},
"RenderSettings": DEFAULT_RENDER_SETTINGS,
"CreateReview": DEFAULT_CREATE_REVIEW_SETTINGS,
"PointCloud": {
Expand Down