diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1d7798cb48..d0d25908cd 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,23 +1,39 @@
# Changelog
-## [3.11.0-nightly.1](https://github.com/pypeclub/OpenPype/tree/HEAD)
+## [3.11.0-nightly.2](https://github.com/pypeclub/OpenPype/tree/HEAD)
[Full Changelog](https://github.com/pypeclub/OpenPype/compare/3.10.0...HEAD)
### 📖 Documentation
+- Documentation: Add app key to template documentation [\#3299](https://github.com/pypeclub/OpenPype/pull/3299)
- doc: adding royal render and multiverse to the web site [\#3285](https://github.com/pypeclub/OpenPype/pull/3285)
**🚀 Enhancements**
+- updated poetry installation source [\#3316](https://github.com/pypeclub/OpenPype/pull/3316)
+- TVPaint: Extractor use mark in/out range to render [\#3309](https://github.com/pypeclub/OpenPype/pull/3309)
+- Ftrack: Delivery action can work on ReviewSessions [\#3307](https://github.com/pypeclub/OpenPype/pull/3307)
+- Maya: Look assigner UI improvements [\#3298](https://github.com/pypeclub/OpenPype/pull/3298)
+- Ftrack: Action to transfer values of hierarchical attributes [\#3284](https://github.com/pypeclub/OpenPype/pull/3284)
+- Maya: better handling of legacy review subsets names [\#3269](https://github.com/pypeclub/OpenPype/pull/3269)
- General: Updated windows oiio tool [\#3268](https://github.com/pypeclub/OpenPype/pull/3268)
- Unreal: add support for skeletalMesh and staticMesh to loaders [\#3267](https://github.com/pypeclub/OpenPype/pull/3267)
- Maya: reference loaders could store placeholder in referenced url [\#3264](https://github.com/pypeclub/OpenPype/pull/3264)
- TVPaint: Init file for TVPaint worker also handle guideline images [\#3250](https://github.com/pypeclub/OpenPype/pull/3250)
- Nuke: Change default icon path in settings [\#3247](https://github.com/pypeclub/OpenPype/pull/3247)
+- Maya: publishing of animation and pointcache on a farm [\#3225](https://github.com/pypeclub/OpenPype/pull/3225)
+- Maya: Look assigner UI improvements [\#3208](https://github.com/pypeclub/OpenPype/pull/3208)
+- Nuke: add pointcache and animation to loader [\#3186](https://github.com/pypeclub/OpenPype/pull/3186)
**🐛 Bug fixes**
+- Houdini: Fix Houdini VDB manage update wrong file attribute name [\#3322](https://github.com/pypeclub/OpenPype/pull/3322)
+- General: Vendorized modules for Python 2 and update poetry lock [\#3305](https://github.com/pypeclub/OpenPype/pull/3305)
+- Fix - added local targets to install host [\#3303](https://github.com/pypeclub/OpenPype/pull/3303)
+- Settings: Add missing default settings for nuke gizmo [\#3301](https://github.com/pypeclub/OpenPype/pull/3301)
+- Maya: Fix swaped width and height in reviews [\#3300](https://github.com/pypeclub/OpenPype/pull/3300)
+- Maya: point cache publish handles Maya instances [\#3297](https://github.com/pypeclub/OpenPype/pull/3297)
- Global: extract review slate issues [\#3286](https://github.com/pypeclub/OpenPype/pull/3286)
- Webpublisher: return only active projects in ProjectsEndpoint [\#3281](https://github.com/pypeclub/OpenPype/pull/3281)
- Hiero: add support for task tags 3.10.x [\#3279](https://github.com/pypeclub/OpenPype/pull/3279)
@@ -30,24 +46,15 @@
- Unreal: Fixed Render creation in UE5 [\#3239](https://github.com/pypeclub/OpenPype/pull/3239)
- Unreal: Fixed Camera loading in UE5 [\#3238](https://github.com/pypeclub/OpenPype/pull/3238)
- Flame: debugging [\#3224](https://github.com/pypeclub/OpenPype/pull/3224)
-- add silent audio to slate [\#3162](https://github.com/pypeclub/OpenPype/pull/3162)
**Merged pull requests:**
-- Maya: better handling of legacy review subsets names [\#3269](https://github.com/pypeclub/OpenPype/pull/3269)
-- Deadline: publishing of animation and pointcache on a farm [\#3225](https://github.com/pypeclub/OpenPype/pull/3225)
-- Nuke: add pointcache and animation to loader [\#3186](https://github.com/pypeclub/OpenPype/pull/3186)
-- Add a gizmo menu to nuke [\#3172](https://github.com/pypeclub/OpenPype/pull/3172)
+- Maya: add pointcache family to gpu cache loader [\#3318](https://github.com/pypeclub/OpenPype/pull/3318)
## [3.10.0](https://github.com/pypeclub/OpenPype/tree/3.10.0) (2022-05-26)
[Full Changelog](https://github.com/pypeclub/OpenPype/compare/CI/3.10.0-nightly.6...3.10.0)
-**🆕 New features**
-
-- General: OpenPype modules publish plugins are registered in host [\#3180](https://github.com/pypeclub/OpenPype/pull/3180)
-- General: Creator plugins from addons can be registered [\#3179](https://github.com/pypeclub/OpenPype/pull/3179)
-
**🚀 Enhancements**
- Maya: FBX camera export [\#3253](https://github.com/pypeclub/OpenPype/pull/3253)
@@ -55,10 +62,6 @@
- Project Manager: Allow to paste Tasks into multiple assets at the same time [\#3226](https://github.com/pypeclub/OpenPype/pull/3226)
- Project manager: Sped up project load [\#3216](https://github.com/pypeclub/OpenPype/pull/3216)
- Loader UI: Speed issues of loader with sync server [\#3199](https://github.com/pypeclub/OpenPype/pull/3199)
-- Looks: add basic support for Renderman [\#3190](https://github.com/pypeclub/OpenPype/pull/3190)
-- Maya: added clean\_import option to Import loader [\#3181](https://github.com/pypeclub/OpenPype/pull/3181)
-- Add the scripts menu definition to nuke [\#3168](https://github.com/pypeclub/OpenPype/pull/3168)
-- Maya: add maya 2023 to default applications [\#3167](https://github.com/pypeclub/OpenPype/pull/3167)
**🐛 Bug fixes**
@@ -76,12 +79,6 @@
- Photoshop: skip collector when automatic testing [\#3202](https://github.com/pypeclub/OpenPype/pull/3202)
- Nuke: render/workfile version sync doesn't work on farm [\#3185](https://github.com/pypeclub/OpenPype/pull/3185)
- Ftrack: Review image only if there are no mp4 reviews [\#3183](https://github.com/pypeclub/OpenPype/pull/3183)
-- Ftrack: Locations deepcopy issue [\#3177](https://github.com/pypeclub/OpenPype/pull/3177)
-- General: Avoid creating multiple thumbnails [\#3176](https://github.com/pypeclub/OpenPype/pull/3176)
-- General/Hiero: better clip duration calculation [\#3169](https://github.com/pypeclub/OpenPype/pull/3169)
-- General: Oiio conversion for ffmpeg checks for invalid characters [\#3166](https://github.com/pypeclub/OpenPype/pull/3166)
-- Fix for attaching render to subset [\#3164](https://github.com/pypeclub/OpenPype/pull/3164)
-- Harmony: fixed missing task name in render instance [\#3163](https://github.com/pypeclub/OpenPype/pull/3163)
**🔀 Refactored code**
@@ -92,7 +89,6 @@
- Harmony: message length in 21.1 [\#3257](https://github.com/pypeclub/OpenPype/pull/3257)
- Harmony: 21.1 fix [\#3249](https://github.com/pypeclub/OpenPype/pull/3249)
- Maya: added jpg to filter for Image Plane Loader [\#3223](https://github.com/pypeclub/OpenPype/pull/3223)
-- Webpublisher: replace space by underscore in subset names [\#3160](https://github.com/pypeclub/OpenPype/pull/3160)
## [3.9.8](https://github.com/pypeclub/OpenPype/tree/3.9.8) (2022-05-19)
@@ -103,15 +99,13 @@
- nuke: generate publishing nodes inside render group node [\#3206](https://github.com/pypeclub/OpenPype/pull/3206)
- Loader UI: Speed issues of loader with sync server [\#3200](https://github.com/pypeclub/OpenPype/pull/3200)
- Backport of fix for attaching renders to subsets [\#3195](https://github.com/pypeclub/OpenPype/pull/3195)
+- Looks: add basic support for Renderman [\#3190](https://github.com/pypeclub/OpenPype/pull/3190)
**🐛 Bug fixes**
- Standalone Publisher: Always create new representation for thumbnail [\#3204](https://github.com/pypeclub/OpenPype/pull/3204)
- Nuke: render/workfile version sync doesn't work on farm [\#3184](https://github.com/pypeclub/OpenPype/pull/3184)
- Ftrack: Review image only if there are no mp4 reviews [\#3182](https://github.com/pypeclub/OpenPype/pull/3182)
-- Ftrack: Locations deepcopy issue [\#3175](https://github.com/pypeclub/OpenPype/pull/3175)
-- General: Avoid creating multiple thumbnails [\#3174](https://github.com/pypeclub/OpenPype/pull/3174)
-- General: TemplateResult can be copied [\#3170](https://github.com/pypeclub/OpenPype/pull/3170)
**Merged pull requests:**
diff --git a/openpype/hosts/hiero/api/otio/hiero_export.py b/openpype/hosts/hiero/api/otio/hiero_export.py
index 1e4088d9c0..81cb43fa12 100644
--- a/openpype/hosts/hiero/api/otio/hiero_export.py
+++ b/openpype/hosts/hiero/api/otio/hiero_export.py
@@ -132,7 +132,7 @@ def create_time_effects(otio_clip, track_item):
otio_effect = otio.schema.TimeEffect()
otio_effect.name = name
otio_effect.effect_name = effect_name
- otio_effect.metadata = metadata
+ otio_effect.metadata.update(metadata)
# add otio effect to clip effects
otio_clip.effects.append(otio_effect)
diff --git a/openpype/hosts/maya/plugins/load/load_gpucache.py b/openpype/hosts/maya/plugins/load/load_gpucache.py
index 6d5e945508..179819f904 100644
--- a/openpype/hosts/maya/plugins/load/load_gpucache.py
+++ b/openpype/hosts/maya/plugins/load/load_gpucache.py
@@ -10,7 +10,7 @@ from openpype.api import get_project_settings
class GpuCacheLoader(load.LoaderPlugin):
"""Load Alembic as gpuCache"""
- families = ["model"]
+ families = ["model", "animation", "pointcache"]
representations = ["abc"]
label = "Import Gpu Cache"
diff --git a/openpype/hosts/maya/plugins/publish/collect_instances.py b/openpype/hosts/maya/plugins/publish/collect_instances.py
index 1d59a68bf6..433fa9886d 100644
--- a/openpype/hosts/maya/plugins/publish/collect_instances.py
+++ b/openpype/hosts/maya/plugins/publish/collect_instances.py
@@ -1,9 +1,49 @@
from maya import cmds
+import maya.api.OpenMaya as om
import pyblish.api
import json
+def get_all_children(nodes):
+ """Return all children of `nodes` including each instanced child.
+ Using maya.cmds.listRelatives(allDescendents=True) includes only the first
+ instance. As such, this function acts as an optimal replacement with a
+ focus on a fast query.
+
+ """
+
+ sel = om.MSelectionList()
+ traversed = set()
+ iterator = om.MItDag(om.MItDag.kDepthFirst)
+ for node in nodes:
+
+ if node in traversed:
+ # Ignore if already processed as a child
+ # before
+ continue
+
+ sel.clear()
+ sel.add(node)
+ dag = sel.getDagPath(0)
+
+ iterator.reset(dag)
+ next(iterator) # ignore self
+ while not iterator.isDone():
+
+ path = iterator.fullPathName()
+
+ if path in traversed:
+ iterator.prune()
+ next(iterator)
+ continue
+
+ traversed.add(path)
+ next(iterator)
+
+ return list(traversed)
+
+
class CollectInstances(pyblish.api.ContextPlugin):
"""Gather instances by objectSet and pre-defined attribute
@@ -86,12 +126,8 @@ class CollectInstances(pyblish.api.ContextPlugin):
# Collect members
members = cmds.ls(members, long=True) or []
- # `maya.cmds.listRelatives(noIntermediate=True)` only works when
- # `shapes=True` argument is passed, since we also want to include
- # transforms we filter afterwards.
- children = cmds.listRelatives(members,
- allDescendents=True,
- fullPath=True) or []
+ dag_members = cmds.ls(members, type="dagNode", long=True)
+ children = get_all_children(dag_members)
children = cmds.ls(children, noIntermediate=True, long=True)
parents = []
diff --git a/openpype/modules/ftrack/event_handlers_server/action_create_review_session.py b/openpype/modules/ftrack/event_handlers_server/action_create_review_session.py
new file mode 100644
index 0000000000..8a8e86e7b9
--- /dev/null
+++ b/openpype/modules/ftrack/event_handlers_server/action_create_review_session.py
@@ -0,0 +1,288 @@
+import threading
+import datetime
+import copy
+import collections
+
+import ftrack_api
+
+from openpype.lib import get_datetime_data
+from openpype.api import get_project_settings
+from openpype_modules.ftrack.lib import ServerAction
+
+
+class CreateDailyReviewSessionServerAction(ServerAction):
+ """Create daily review session object per project.
+
+ Action creates review sessions based on settings. Settings define if is
+ action enabled and what is a template for review session name. Logic works
+ in a way that if review session with the name already exists then skip
+ process. If review session for current day does not exist but yesterdays
+ review exists and is empty then yesterdays is renamed otherwise creates
+ new review session.
+
+ Also contains cycle creation of dailies which is triggered each morning.
+ This option must be enabled in project settings. Cycle creation is also
+ checked on registration of action.
+ """
+
+ identifier = "create.daily.review.session"
+ #: Action label.
+ label = "OpenPype Admin"
+ variant = "- Create Daily Review Session (Server)"
+ #: Action description.
+ description = "Manually create daily review session"
+ role_list = {"Pypeclub", "Administrator", "Project Manager"}
+
+ settings_key = "create_daily_review_session"
+ default_template = "{yy}{mm}{dd}"
+
+ def __init__(self, *args, **kwargs):
+ super(CreateDailyReviewSessionServerAction, self).__init__(
+ *args, **kwargs
+ )
+
+ self._cycle_timer = None
+ self._last_cyle_time = None
+ self._day_delta = datetime.timedelta(days=1)
+
+ def discover(self, session, entities, event):
+ """Show action only on AssetVersions."""
+
+ valid_selection = False
+ for ent in event["data"]["selection"]:
+ # Ignore entities that are not tasks or projects
+ if ent["entityType"].lower() in (
+ "show", "task", "reviewsession", "assetversion"
+ ):
+ valid_selection = True
+ break
+
+ if not valid_selection:
+ return False
+ return self.valid_roles(session, entities, event)
+
+ def launch(self, session, entities, event):
+ project_entity = self.get_project_from_entity(entities[0], session)
+ project_name = project_entity["full_name"]
+ project_settings = self.get_project_settings_from_event(
+ event, project_name
+ )
+ action_settings = self._extract_action_settings(project_settings)
+ project_name_by_id = {
+ project_entity["id"]: project_name
+ }
+ settings_by_project_id = {
+ project_entity["id"]: action_settings
+ }
+ self._process_review_session(
+ session, settings_by_project_id, project_name_by_id
+ )
+ return True
+
+ def register(self, *args, **kwargs):
+ """Override register to be able trigger """
+ # Register server action as would be normally
+ super(CreateDailyReviewSessionServerAction, self).register(
+ *args, **kwargs
+ )
+
+ # Create threading timer which will trigger creation of report
+ # at the 00:00:01 of next day
+ # - callback will trigger another timer which will have 1 day offset
+ now = datetime.datetime.now()
+ # Create object of today morning
+ today_morning = datetime.datetime(
+ now.year, now.month, now.day, 0, 0, 1
+ )
+ # Add a day delta (to calculate next day date)
+ next_day_morning = today_morning + self._day_delta
+ # Calculate first delta in seconds for first threading timer
+ first_delta = (next_day_morning - now).total_seconds()
+ # Store cycle time which will be used to create next timer
+ self._last_cyle_time = next_day_morning
+ # Create timer thread
+ self._cycle_timer = threading.Timer(first_delta, self._timer_callback)
+ self._cycle_timer.start()
+
+ self._check_review_session()
+
+ def _timer_callback(self):
+ if (
+ self._cycle_timer is not None
+ and self._last_cyle_time is not None
+ ):
+ now = datetime.datetime.now()
+ while self._last_cyle_time < now:
+ self._last_cyle_time = self._last_cyle_time + self._day_delta
+
+ delay = (self._last_cyle_time - now).total_seconds()
+
+ self._cycle_timer = threading.Timer(delay, self._timer_callback)
+ self._cycle_timer.start()
+ self._check_review_session()
+
+ def _check_review_session(self):
+ session = ftrack_api.Session(
+ server_url=self.session.server_url,
+ api_key=self.session.api_key,
+ api_user=self.session.api_user,
+ auto_connect_event_hub=False
+ )
+ project_entities = session.query(
+ "select id, full_name from Project"
+ ).all()
+ project_names_by_id = {
+ project_entity["id"]: project_entity["full_name"]
+ for project_entity in project_entities
+ }
+
+ action_settings_by_project_id = self._get_action_settings(
+ project_names_by_id
+ )
+ enabled_action_settings_by_project_id = {}
+ for item in action_settings_by_project_id.items():
+ project_id, action_settings = item
+ if action_settings.get("cycle_enabled"):
+ enabled_action_settings_by_project_id[project_id] = (
+ action_settings
+ )
+
+ if not enabled_action_settings_by_project_id:
+ self.log.info((
+ "There are no projects that have enabled"
+ " cycle review sesison creation"
+ ))
+
+ else:
+ self._process_review_session(
+ session,
+ enabled_action_settings_by_project_id,
+ project_names_by_id
+ )
+
+ session.close()
+
+ def _process_review_session(
+ self, session, settings_by_project_id, project_names_by_id
+ ):
+ review_sessions = session.query((
+ "select id, name, project_id"
+ " from ReviewSession where project_id in ({})"
+ ).format(self.join_query_keys(settings_by_project_id))).all()
+
+ review_sessions_by_project_id = collections.defaultdict(list)
+ for review_session in review_sessions:
+ project_id = review_session["project_id"]
+ review_sessions_by_project_id[project_id].append(review_session)
+
+ # Prepare fill data for today's review sesison and yesterdays
+ now = datetime.datetime.now()
+ today_obj = datetime.datetime(
+ now.year, now.month, now.day, 0, 0, 0
+ )
+ yesterday_obj = today_obj - self._day_delta
+
+ today_fill_data = get_datetime_data(today_obj)
+ yesterday_fill_data = get_datetime_data(yesterday_obj)
+
+ # Loop through projects and try to create daily reviews
+ for project_id, action_settings in settings_by_project_id.items():
+ review_session_template = (
+ action_settings["review_session_template"]
+ ).strip() or self.default_template
+
+ today_project_fill_data = copy.deepcopy(today_fill_data)
+ yesterday_project_fill_data = copy.deepcopy(yesterday_fill_data)
+ project_name = project_names_by_id[project_id]
+ today_project_fill_data["project_name"] = project_name
+ yesterday_project_fill_data["project_name"] = project_name
+
+ today_session_name = self._fill_review_template(
+ review_session_template, today_project_fill_data
+ )
+ yesterday_session_name = self._fill_review_template(
+ review_session_template, yesterday_project_fill_data
+ )
+ # Skip if today's session name could not be filled
+ if not today_session_name:
+ continue
+
+ # Find matchin review session
+ project_review_sessions = review_sessions_by_project_id[project_id]
+ todays_session = None
+ yesterdays_session = None
+ for review_session in project_review_sessions:
+ session_name = review_session["name"]
+ if session_name == today_session_name:
+ todays_session = review_session
+ break
+ elif session_name == yesterday_session_name:
+ yesterdays_session = review_session
+
+ # Skip if today's session already exist
+ if todays_session is not None:
+ self.log.debug((
+ "Todays ReviewSession \"{}\""
+ " in project \"{}\" already exists"
+ ).format(today_session_name, project_name))
+ continue
+
+ # Check if there is yesterday's session and is empty
+ # - in that case just rename it
+ if (
+ yesterdays_session is not None
+ and len(yesterdays_session["review_session_objects"]) == 0
+ ):
+ self.log.debug((
+ "Renaming yesterdays empty review session \"{}\" to \"{}\""
+ " in project \"{}\""
+ ).format(
+ yesterday_session_name, today_session_name, project_name
+ ))
+ yesterdays_session["name"] = today_session_name
+ session.commit()
+ continue
+
+ # Create new review session with new name
+ self.log.debug((
+ "Creating new review session \"{}\" in project \"{}\""
+ ).format(today_session_name, project_name))
+ session.create("ReviewSession", {
+ "project_id": project_id,
+ "name": today_session_name
+ })
+ session.commit()
+
+ def _get_action_settings(self, project_names_by_id):
+ settings_by_project_id = {}
+ for project_id, project_name in project_names_by_id.items():
+ project_settings = get_project_settings(project_name)
+ action_settings = self._extract_action_settings(project_settings)
+ settings_by_project_id[project_id] = action_settings
+ return settings_by_project_id
+
+ def _extract_action_settings(self, project_settings):
+ return (
+ project_settings
+ .get("ftrack", {})
+ .get(self.settings_frack_subkey, {})
+ .get(self.settings_key)
+ ) or {}
+
+ def _fill_review_template(self, template, data):
+ output = None
+ try:
+ output = template.format(**data)
+ except Exception:
+ self.log.warning(
+ (
+ "Failed to fill review session template {} with data {}"
+ ).format(template, data),
+ exc_info=True
+ )
+ return output
+
+
+def register(session):
+ '''Register plugin. Called when used as an plugin.'''
+ CreateDailyReviewSessionServerAction(session).register()
diff --git a/openpype/settings/defaults/project_settings/ftrack.json b/openpype/settings/defaults/project_settings/ftrack.json
index 9d59deea3d..831c34835e 100644
--- a/openpype/settings/defaults/project_settings/ftrack.json
+++ b/openpype/settings/defaults/project_settings/ftrack.json
@@ -116,6 +116,15 @@
"Administrator",
"Project manager"
]
+ },
+ "create_daily_review_session": {
+ "enabled": true,
+ "role_list": [
+ "Administrator",
+ "Project Manager"
+ ],
+ "cycle_enabled": false,
+ "review_session_template": "{yy}{mm}{dd}"
}
},
"user_handlers": {
diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_ftrack.json b/openpype/settings/entities/schemas/projects_schema/schema_project_ftrack.json
index 16cab49d5d..f8f9d5093d 100644
--- a/openpype/settings/entities/schemas/projects_schema/schema_project_ftrack.json
+++ b/openpype/settings/entities/schemas/projects_schema/schema_project_ftrack.json
@@ -388,6 +388,44 @@
"object_type": "text"
}
]
+ },
+ {
+ "key": "create_daily_review_session",
+ "label": "Create daily review session",
+ "type": "dict",
+ "is_group": true,
+ "checkbox_key": "enabled",
+ "children": [
+ {
+ "type": "boolean",
+ "key": "enabled"
+ },
+ {
+ "type": "list",
+ "key": "role_list",
+ "label": "Roles",
+ "object_type": "text",
+ "use_label_wrap": true
+ },
+ {
+ "type": "boolean",
+ "key": "cycle_enabled",
+ "label": "Create daily review session"
+ },
+ {
+ "type": "separator"
+ },
+ {
+ "type": "text",
+ "key": "review_session_template",
+ "label": "ReviewSession template",
+ "placeholder": "Default: {yy}{mm}{dd}"
+ },
+ {
+ "type": "label",
+ "label": "Possible formatting keys in template:
- \"project_name\" - <Name of project>
- \"d\" - <Day of month number> in shortest possible way.
- \"dd\" - <Day of month number> with 2 digits.
- \"ddd\" - <Week day name> shortened week day. e.g.: `Mon`, ...
- \"dddd\" - <Week day name> full name of week day. e.g.: `Monday`, ...
- \"m\" - <Month number> in shortest possible way. e.g.: `1` if January
- \"mm\" - <Month number> with 2 digits.
- \"mmm\" - <Month name> shortened month name. e.g.: `Jan`, ...
- \"mmmm\" -<Month name> full month name. e.g.: `January`, ...
- \"yy\" - <Year number> shortened year. e.g.: `19`, `20`, ...
- \"yyyy\" - <Year number> full year. e.g.: `2019`, `2020`, ..."
+ }
+ ]
}
]
},
diff --git a/openpype/tools/project_manager/project_manager/delegates.py b/openpype/tools/project_manager/project_manager/delegates.py
index 31487ff132..b066bbb159 100644
--- a/openpype/tools/project_manager/project_manager/delegates.py
+++ b/openpype/tools/project_manager/project_manager/delegates.py
@@ -205,3 +205,9 @@ class ToolsDelegate(QtWidgets.QStyledItemDelegate):
def setModelData(self, editor, model, index):
model.setData(index, editor.value(), QtCore.Qt.EditRole)
+
+ def displayText(self, value, locale):
+ if value:
+ return ", ".join(value)
+ else:
+ return
diff --git a/openpype/tools/project_manager/project_manager/view.py b/openpype/tools/project_manager/project_manager/view.py
index 4b5bc36aeb..a16def276d 100644
--- a/openpype/tools/project_manager/project_manager/view.py
+++ b/openpype/tools/project_manager/project_manager/view.py
@@ -381,7 +381,7 @@ class HierarchyView(QtWidgets.QTreeView):
self._source_model.delete_indexes(indexes)
def _on_ctrl_shift_enter_pressed(self):
- self._add_task_and_edit()
+ self.add_task_and_edit()
def add_asset(self, parent_index=None):
if parent_index is None:
@@ -423,9 +423,9 @@ class HierarchyView(QtWidgets.QTreeView):
self.edit(new_index)
def _add_task_action(self):
- self._add_task_and_edit()
+ self.add_task_and_edit()
- def _add_task_and_edit(self):
+ def add_task_and_edit(self):
new_index = self.add_task()
if new_index is None:
return
diff --git a/openpype/tools/project_manager/project_manager/window.py b/openpype/tools/project_manager/project_manager/window.py
index 6a2bc29fd1..c6ae0ff352 100644
--- a/openpype/tools/project_manager/project_manager/window.py
+++ b/openpype/tools/project_manager/project_manager/window.py
@@ -245,7 +245,7 @@ class ProjectManagerWindow(QtWidgets.QWidget):
self.hierarchy_view.add_asset()
def _on_add_task(self):
- self.hierarchy_view.add_task()
+ self.hierarchy_view.add_task_and_edit()
def _on_create_folders(self):
project_name = self._current_project()
diff --git a/openpype/version.py b/openpype/version.py
index 4c78a6e0a1..4b0a688cbf 100644
--- a/openpype/version.py
+++ b/openpype/version.py
@@ -1,3 +1,3 @@
# -*- coding: utf-8 -*-
"""Package declaring Pype version."""
-__version__ = "3.11.0-nightly.1"
+__version__ = "3.11.0-nightly.2"
diff --git a/pyproject.toml b/pyproject.toml
index 63bd08d644..4289c74ebe 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[tool.poetry]
name = "OpenPype"
-version = "3.11.0-nightly.1" # OpenPype
+version = "3.11.0-nightly.2" # OpenPype
description = "Open VFX and Animation pipeline with support."
authors = ["OpenPype Team "]
license = "MIT License"