mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-25 13:24:54 +01:00
Merge branch 'develop' of github.com:pypeclub/OpenPype into feature/OP-3446_tray-publish-batch-mov
This commit is contained in:
commit
c384c8b8ba
53 changed files with 1588 additions and 479 deletions
7
.gitmodules
vendored
Normal file
7
.gitmodules
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
[submodule "vendor/powershell/BurntToast"]
|
||||
path = vendor/powershell/BurntToast
|
||||
url = https://github.com/Windos/BurntToast.git
|
||||
|
||||
[submodule "vendor/powershell/PSWriteColor"]
|
||||
path = vendor/powershell/PSWriteColor
|
||||
url = https://github.com/EvotecIT/PSWriteColor.git
|
||||
37
CHANGELOG.md
37
CHANGELOG.md
|
|
@ -1,8 +1,8 @@
|
|||
# Changelog
|
||||
|
||||
## [3.12.1-nightly.4](https://github.com/pypeclub/OpenPype/tree/HEAD)
|
||||
## [3.12.1](https://github.com/pypeclub/OpenPype/tree/3.12.1) (2022-07-13)
|
||||
|
||||
[Full Changelog](https://github.com/pypeclub/OpenPype/compare/3.12.0...HEAD)
|
||||
[Full Changelog](https://github.com/pypeclub/OpenPype/compare/3.12.0...3.12.1)
|
||||
|
||||
### 📖 Documentation
|
||||
|
||||
|
|
@ -14,6 +14,9 @@
|
|||
|
||||
**🚀 Enhancements**
|
||||
|
||||
- TrayPublisher: Added more options for grouping of instances [\#3494](https://github.com/pypeclub/OpenPype/pull/3494)
|
||||
- NewPublisher: Align creator attributes from top to bottom [\#3487](https://github.com/pypeclub/OpenPype/pull/3487)
|
||||
- NewPublisher: Added ability to use label of instance [\#3484](https://github.com/pypeclub/OpenPype/pull/3484)
|
||||
- General: Creator Plugins have access to project [\#3476](https://github.com/pypeclub/OpenPype/pull/3476)
|
||||
- General: Better arguments order in creator init [\#3475](https://github.com/pypeclub/OpenPype/pull/3475)
|
||||
- Ftrack: Trigger custom ftrack events on project creation and preparation [\#3465](https://github.com/pypeclub/OpenPype/pull/3465)
|
||||
|
|
@ -21,10 +24,15 @@
|
|||
- Blender: Bugfix - Set fps properly on open [\#3426](https://github.com/pypeclub/OpenPype/pull/3426)
|
||||
- Hiero: Add custom scripts menu [\#3425](https://github.com/pypeclub/OpenPype/pull/3425)
|
||||
- Blender: pre pyside install for all platforms [\#3400](https://github.com/pypeclub/OpenPype/pull/3400)
|
||||
- Maya: Ability to set resolution for playblasts from asset, and override through review instance. [\#3360](https://github.com/pypeclub/OpenPype/pull/3360)
|
||||
- Maya: Add additional playblast options to review Extractor. [\#3384](https://github.com/pypeclub/OpenPype/pull/3384)
|
||||
|
||||
**🐛 Bug fixes**
|
||||
|
||||
- TrayPublisher: Keep use instance label in list view [\#3493](https://github.com/pypeclub/OpenPype/pull/3493)
|
||||
- General: Extract review use first frame of input sequence [\#3491](https://github.com/pypeclub/OpenPype/pull/3491)
|
||||
- General: Fix Plist loading for application launch [\#3485](https://github.com/pypeclub/OpenPype/pull/3485)
|
||||
- Nuke: Workfile tools open on start [\#3479](https://github.com/pypeclub/OpenPype/pull/3479)
|
||||
- New Publisher: Disabled context change allows creation [\#3478](https://github.com/pypeclub/OpenPype/pull/3478)
|
||||
- General: thumbnail extractor fix [\#3474](https://github.com/pypeclub/OpenPype/pull/3474)
|
||||
- Kitsu: bugfix with sync-service ans publish plugins [\#3473](https://github.com/pypeclub/OpenPype/pull/3473)
|
||||
- Flame: solved problem with multi-selected loading [\#3470](https://github.com/pypeclub/OpenPype/pull/3470)
|
||||
|
|
@ -38,6 +46,7 @@
|
|||
- Nuke: Slate frame is integrated [\#3427](https://github.com/pypeclub/OpenPype/pull/3427)
|
||||
- Maya: Camera extra data - additional fix for \#3304 [\#3386](https://github.com/pypeclub/OpenPype/pull/3386)
|
||||
- Maya: Handle excluding `model` family from frame range validator. [\#3370](https://github.com/pypeclub/OpenPype/pull/3370)
|
||||
- Harmony: audio validator has wrong logic [\#3364](https://github.com/pypeclub/OpenPype/pull/3364)
|
||||
|
||||
**🔀 Refactored code**
|
||||
|
||||
|
|
@ -46,7 +55,9 @@
|
|||
- General: Use query functions in global plugins [\#3459](https://github.com/pypeclub/OpenPype/pull/3459)
|
||||
- Clockify: Use query functions in clockify actions [\#3458](https://github.com/pypeclub/OpenPype/pull/3458)
|
||||
- General: Use query functions in rest api calls [\#3457](https://github.com/pypeclub/OpenPype/pull/3457)
|
||||
- General: Use query functions in openpype lib functions [\#3454](https://github.com/pypeclub/OpenPype/pull/3454)
|
||||
- General: Use query functions in load utils [\#3446](https://github.com/pypeclub/OpenPype/pull/3446)
|
||||
- General: Move publish plugin and publish render abstractions [\#3442](https://github.com/pypeclub/OpenPype/pull/3442)
|
||||
- General: Use Anatomy after move to pipeline [\#3436](https://github.com/pypeclub/OpenPype/pull/3436)
|
||||
- General: Anatomy moved to pipeline [\#3435](https://github.com/pypeclub/OpenPype/pull/3435)
|
||||
- Fusion: Use client query functions [\#3380](https://github.com/pypeclub/OpenPype/pull/3380)
|
||||
|
|
@ -66,8 +77,6 @@
|
|||
- Webserver: Added CORS middleware [\#3422](https://github.com/pypeclub/OpenPype/pull/3422)
|
||||
- Attribute Defs UI: Files widget show what is allowed to drop in [\#3411](https://github.com/pypeclub/OpenPype/pull/3411)
|
||||
- General: Add ability to change user value for templates [\#3366](https://github.com/pypeclub/OpenPype/pull/3366)
|
||||
- Hosts: More options for in-host callbacks [\#3357](https://github.com/pypeclub/OpenPype/pull/3357)
|
||||
- Multiverse: expose some settings to GUI [\#3350](https://github.com/pypeclub/OpenPype/pull/3350)
|
||||
|
||||
**🐛 Bug fixes**
|
||||
|
||||
|
|
@ -82,7 +91,6 @@
|
|||
- Maya: vray device aspect ratio fix [\#3381](https://github.com/pypeclub/OpenPype/pull/3381)
|
||||
- Flame: bunch of publishing issues [\#3377](https://github.com/pypeclub/OpenPype/pull/3377)
|
||||
- Harmony: added unc path to zifile command in Harmony [\#3372](https://github.com/pypeclub/OpenPype/pull/3372)
|
||||
- Standalone: settings improvements [\#3355](https://github.com/pypeclub/OpenPype/pull/3355)
|
||||
|
||||
**🔀 Refactored code**
|
||||
|
||||
|
|
@ -107,37 +115,20 @@
|
|||
|
||||
[Full Changelog](https://github.com/pypeclub/OpenPype/compare/CI/3.11.1-nightly.1...3.11.1)
|
||||
|
||||
**🆕 New features**
|
||||
|
||||
- Flame: custom export temp folder [\#3346](https://github.com/pypeclub/OpenPype/pull/3346)
|
||||
- Nuke: removing third-party plugins [\#3344](https://github.com/pypeclub/OpenPype/pull/3344)
|
||||
|
||||
**🚀 Enhancements**
|
||||
|
||||
- Pyblish Pype: Hiding/Close issues [\#3367](https://github.com/pypeclub/OpenPype/pull/3367)
|
||||
- Ftrack: Removed requirement of pypeclub role from default settings [\#3354](https://github.com/pypeclub/OpenPype/pull/3354)
|
||||
- Kitsu: Prevent crash on missing frames information [\#3352](https://github.com/pypeclub/OpenPype/pull/3352)
|
||||
|
||||
**🐛 Bug fixes**
|
||||
|
||||
- Nuke: bake streams with slate on farm [\#3368](https://github.com/pypeclub/OpenPype/pull/3368)
|
||||
- Harmony: audio validator has wrong logic [\#3364](https://github.com/pypeclub/OpenPype/pull/3364)
|
||||
- Nuke: Fix missing variable in extract thumbnail [\#3363](https://github.com/pypeclub/OpenPype/pull/3363)
|
||||
- Nuke: Fix precollect writes [\#3361](https://github.com/pypeclub/OpenPype/pull/3361)
|
||||
- AE- fix validate\_scene\_settings and renderLocal [\#3358](https://github.com/pypeclub/OpenPype/pull/3358)
|
||||
- deadline: fixing misidentification of revieables [\#3356](https://github.com/pypeclub/OpenPype/pull/3356)
|
||||
- General: Create only one thumbnail per instance [\#3351](https://github.com/pypeclub/OpenPype/pull/3351)
|
||||
- nuke: adding extract thumbnail settings 3.10 [\#3347](https://github.com/pypeclub/OpenPype/pull/3347)
|
||||
- General: Fix last version function [\#3345](https://github.com/pypeclub/OpenPype/pull/3345)
|
||||
|
||||
## [3.11.0](https://github.com/pypeclub/OpenPype/tree/3.11.0) (2022-06-17)
|
||||
|
||||
[Full Changelog](https://github.com/pypeclub/OpenPype/compare/CI/3.11.0-nightly.4...3.11.0)
|
||||
|
||||
**🐛 Bug fixes**
|
||||
|
||||
- General: Handle empty source key on instance [\#3342](https://github.com/pypeclub/OpenPype/pull/3342)
|
||||
|
||||
## [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)
|
||||
|
|
|
|||
|
|
@ -2522,12 +2522,30 @@ def load_capture_preset(data=None):
|
|||
temp_options2['multiSampleEnable'] = False
|
||||
temp_options2['multiSampleCount'] = preset[id][key]
|
||||
|
||||
if key == 'renderDepthOfField':
|
||||
temp_options2['renderDepthOfField'] = preset[id][key]
|
||||
|
||||
if key == 'ssaoEnable':
|
||||
if preset[id][key] is True:
|
||||
temp_options2['ssaoEnable'] = True
|
||||
else:
|
||||
temp_options2['ssaoEnable'] = False
|
||||
|
||||
if key == 'ssaoSamples':
|
||||
temp_options2['ssaoSamples'] = preset[id][key]
|
||||
|
||||
if key == 'ssaoAmount':
|
||||
temp_options2['ssaoAmount'] = preset[id][key]
|
||||
|
||||
if key == 'ssaoRadius':
|
||||
temp_options2['ssaoRadius'] = preset[id][key]
|
||||
|
||||
if key == 'hwFogDensity':
|
||||
temp_options2['hwFogDensity'] = preset[id][key]
|
||||
|
||||
if key == 'ssaoFilterRadius':
|
||||
temp_options2['ssaoFilterRadius'] = preset[id][key]
|
||||
|
||||
if key == 'alphaCut':
|
||||
temp_options2['transparencyAlgorithm'] = 5
|
||||
temp_options2['transparencyQuality'] = 1
|
||||
|
|
@ -2535,6 +2553,48 @@ def load_capture_preset(data=None):
|
|||
if key == 'headsUpDisplay':
|
||||
temp_options['headsUpDisplay'] = True
|
||||
|
||||
if key == 'fogging':
|
||||
temp_options['fogging'] = preset[id][key] or False
|
||||
|
||||
if key == 'hwFogStart':
|
||||
temp_options2['hwFogStart'] = preset[id][key]
|
||||
|
||||
if key == 'hwFogEnd':
|
||||
temp_options2['hwFogEnd'] = preset[id][key]
|
||||
|
||||
if key == 'hwFogAlpha':
|
||||
temp_options2['hwFogAlpha'] = preset[id][key]
|
||||
|
||||
if key == 'hwFogFalloff':
|
||||
temp_options2['hwFogFalloff'] = int(preset[id][key])
|
||||
|
||||
if key == 'hwFogColorR':
|
||||
temp_options2['hwFogColorR'] = preset[id][key]
|
||||
|
||||
if key == 'hwFogColorG':
|
||||
temp_options2['hwFogColorG'] = preset[id][key]
|
||||
|
||||
if key == 'hwFogColorB':
|
||||
temp_options2['hwFogColorB'] = preset[id][key]
|
||||
|
||||
if key == 'motionBlurEnable':
|
||||
if preset[id][key] is True:
|
||||
temp_options2['motionBlurEnable'] = True
|
||||
else:
|
||||
temp_options2['motionBlurEnable'] = False
|
||||
|
||||
if key == 'motionBlurSampleCount':
|
||||
temp_options2['motionBlurSampleCount'] = preset[id][key]
|
||||
|
||||
if key == 'motionBlurShutterOpenFraction':
|
||||
temp_options2['motionBlurShutterOpenFraction'] = preset[id][key]
|
||||
|
||||
if key == 'lineAAEnable':
|
||||
if preset[id][key] is True:
|
||||
temp_options2['lineAAEnable'] = True
|
||||
else:
|
||||
temp_options2['lineAAEnable'] = False
|
||||
|
||||
else:
|
||||
temp_options[str(key)] = preset[id][key]
|
||||
|
||||
|
|
@ -2544,7 +2604,24 @@ def load_capture_preset(data=None):
|
|||
'gpuCacheDisplayFilter',
|
||||
'multiSample',
|
||||
'ssaoEnable',
|
||||
'textureMaxResolution'
|
||||
'ssaoSamples',
|
||||
'ssaoAmount',
|
||||
'ssaoFilterRadius',
|
||||
'ssaoRadius',
|
||||
'hwFogStart',
|
||||
'hwFogEnd',
|
||||
'hwFogAlpha',
|
||||
'hwFogFalloff',
|
||||
'hwFogColorR',
|
||||
'hwFogColorG',
|
||||
'hwFogColorB',
|
||||
'hwFogDensity',
|
||||
'textureMaxResolution',
|
||||
'motionBlurEnable',
|
||||
'motionBlurSampleCount',
|
||||
'motionBlurShutterOpenFraction',
|
||||
'lineAAEnable',
|
||||
'renderDepthOfField'
|
||||
]:
|
||||
temp_options.pop(key, None)
|
||||
|
||||
|
|
|
|||
|
|
@ -54,20 +54,28 @@ class LoadClip(plugin.NukeLoader):
|
|||
script_start = int(nuke.root()["first_frame"].value())
|
||||
|
||||
# option gui
|
||||
defaults = {
|
||||
"start_at_workfile": True
|
||||
options_defaults = {
|
||||
"start_at_workfile": True,
|
||||
"add_retime": True
|
||||
}
|
||||
|
||||
options = [
|
||||
qargparse.Boolean(
|
||||
"start_at_workfile",
|
||||
help="Load at workfile start frame",
|
||||
default=True
|
||||
)
|
||||
]
|
||||
|
||||
node_name_template = "{class_name}_{ext}"
|
||||
|
||||
@classmethod
|
||||
def get_options(cls, *args):
|
||||
return [
|
||||
qargparse.Boolean(
|
||||
"start_at_workfile",
|
||||
help="Load at workfile start frame",
|
||||
default=cls.options_defaults["start_at_workfile"]
|
||||
),
|
||||
qargparse.Boolean(
|
||||
"add_retime",
|
||||
help="Load with retime",
|
||||
default=cls.options_defaults["add_retime"]
|
||||
)
|
||||
]
|
||||
|
||||
@classmethod
|
||||
def get_representations(cls):
|
||||
return (
|
||||
|
|
@ -86,7 +94,10 @@ class LoadClip(plugin.NukeLoader):
|
|||
file = self.fname.replace("\\", "/")
|
||||
|
||||
start_at_workfile = options.get(
|
||||
"start_at_workfile", self.defaults["start_at_workfile"])
|
||||
"start_at_workfile", self.options_defaults["start_at_workfile"])
|
||||
|
||||
add_retime = options.get(
|
||||
"add_retime", self.options_defaults["add_retime"])
|
||||
|
||||
version = context['version']
|
||||
version_data = version.get("data", {})
|
||||
|
|
@ -151,7 +162,7 @@ class LoadClip(plugin.NukeLoader):
|
|||
data_imprint = {}
|
||||
for k in add_keys:
|
||||
if k == 'version':
|
||||
data_imprint.update({k: context["version"]['name']})
|
||||
data_imprint[k] = context["version"]['name']
|
||||
elif k == 'colorspace':
|
||||
colorspace = repre["data"].get(k)
|
||||
colorspace = colorspace or version_data.get(k)
|
||||
|
|
@ -159,10 +170,13 @@ class LoadClip(plugin.NukeLoader):
|
|||
if used_colorspace:
|
||||
data_imprint["used_colorspace"] = used_colorspace
|
||||
else:
|
||||
data_imprint.update(
|
||||
{k: context["version"]['data'].get(k, str(None))})
|
||||
data_imprint[k] = context["version"]['data'].get(
|
||||
k, str(None))
|
||||
|
||||
data_imprint.update({"objectName": read_name})
|
||||
data_imprint["objectName"] = read_name
|
||||
|
||||
if add_retime and version_data.get("retime", None):
|
||||
data_imprint["addRetime"] = True
|
||||
|
||||
read_node["tile_color"].setValue(int("0x4ecd25ff", 16))
|
||||
|
||||
|
|
@ -174,7 +188,7 @@ class LoadClip(plugin.NukeLoader):
|
|||
loader=self.__class__.__name__,
|
||||
data=data_imprint)
|
||||
|
||||
if version_data.get("retime", None):
|
||||
if add_retime and version_data.get("retime", None):
|
||||
self._make_retimes(read_node, version_data)
|
||||
|
||||
self.set_as_member(read_node)
|
||||
|
|
@ -198,7 +212,12 @@ class LoadClip(plugin.NukeLoader):
|
|||
read_node = nuke.toNode(container['objectName'])
|
||||
file = get_representation_path(representation).replace("\\", "/")
|
||||
|
||||
start_at_workfile = bool("start at" in read_node['frame_mode'].value())
|
||||
start_at_workfile = "start at" in read_node['frame_mode'].value()
|
||||
|
||||
add_retime = [
|
||||
key for key in read_node.knobs().keys()
|
||||
if "addRetime" in key
|
||||
]
|
||||
|
||||
project_name = legacy_io.active_project()
|
||||
version_doc = get_version_by_id(project_name, representation["parent"])
|
||||
|
|
@ -286,7 +305,7 @@ class LoadClip(plugin.NukeLoader):
|
|||
"updated to version: {}".format(version_doc.get("name"))
|
||||
)
|
||||
|
||||
if version_data.get("retime", None):
|
||||
if add_retime and version_data.get("retime", None):
|
||||
self._make_retimes(read_node, version_data)
|
||||
else:
|
||||
self.clear_members(read_node)
|
||||
|
|
|
|||
|
|
@ -1,20 +1,8 @@
|
|||
from .pipeline import (
|
||||
install,
|
||||
ls,
|
||||
|
||||
set_project_name,
|
||||
get_context_title,
|
||||
get_context_data,
|
||||
update_context_data,
|
||||
TrayPublisherHost,
|
||||
)
|
||||
|
||||
|
||||
__all__ = (
|
||||
"install",
|
||||
"ls",
|
||||
|
||||
"set_project_name",
|
||||
"get_context_title",
|
||||
"get_context_data",
|
||||
"update_context_data",
|
||||
"TrayPublisherHost",
|
||||
)
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ from openpype.pipeline import (
|
|||
register_creator_plugin_path,
|
||||
legacy_io,
|
||||
)
|
||||
from openpype.host import HostBase, INewPublisher
|
||||
|
||||
|
||||
ROOT_DIR = os.path.dirname(os.path.dirname(
|
||||
os.path.abspath(__file__)
|
||||
|
|
@ -17,6 +19,35 @@ PUBLISH_PATH = os.path.join(ROOT_DIR, "plugins", "publish")
|
|||
CREATE_PATH = os.path.join(ROOT_DIR, "plugins", "create")
|
||||
|
||||
|
||||
class TrayPublisherHost(HostBase, INewPublisher):
|
||||
name = "traypublisher"
|
||||
|
||||
def install(self):
|
||||
os.environ["AVALON_APP"] = self.name
|
||||
legacy_io.Session["AVALON_APP"] = self.name
|
||||
|
||||
pyblish.api.register_host("traypublisher")
|
||||
pyblish.api.register_plugin_path(PUBLISH_PATH)
|
||||
register_creator_plugin_path(CREATE_PATH)
|
||||
|
||||
def get_context_title(self):
|
||||
return HostContext.get_project_name()
|
||||
|
||||
def get_context_data(self):
|
||||
return HostContext.get_context_data()
|
||||
|
||||
def update_context_data(self, data, changes):
|
||||
HostContext.save_context_data(data, changes)
|
||||
|
||||
def set_project_name(self, project_name):
|
||||
# TODO Deregister project specific plugins and register new project
|
||||
# plugins
|
||||
os.environ["AVALON_PROJECT"] = project_name
|
||||
legacy_io.Session["AVALON_PROJECT"] = project_name
|
||||
legacy_io.install()
|
||||
HostContext.set_project_name(project_name)
|
||||
|
||||
|
||||
class HostContext:
|
||||
_context_json_path = None
|
||||
|
||||
|
|
@ -150,32 +181,3 @@ def get_context_data():
|
|||
|
||||
def update_context_data(data, changes):
|
||||
HostContext.save_context_data(data)
|
||||
|
||||
|
||||
def get_context_title():
|
||||
return HostContext.get_project_name()
|
||||
|
||||
|
||||
def ls():
|
||||
"""Probably will never return loaded containers."""
|
||||
return []
|
||||
|
||||
|
||||
def install():
|
||||
"""This is called before a project is known.
|
||||
|
||||
Project is defined with 'set_project_name'.
|
||||
"""
|
||||
os.environ["AVALON_APP"] = "traypublisher"
|
||||
|
||||
pyblish.api.register_host("traypublisher")
|
||||
pyblish.api.register_plugin_path(PUBLISH_PATH)
|
||||
register_creator_plugin_path(CREATE_PATH)
|
||||
|
||||
|
||||
def set_project_name(project_name):
|
||||
# TODO Deregister project specific plugins and register new project plugins
|
||||
os.environ["AVALON_PROJECT"] = project_name
|
||||
legacy_io.Session["AVALON_PROJECT"] = project_name
|
||||
legacy_io.install()
|
||||
HostContext.set_project_name(project_name)
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
from openpype.lib.attribute_definitions import FileDef
|
||||
from openpype.pipeline import (
|
||||
Creator,
|
||||
CreatedInstance
|
||||
)
|
||||
from openpype.lib import FileDef
|
||||
|
||||
from .pipeline import (
|
||||
list_instances,
|
||||
|
|
@ -12,6 +12,29 @@ from .pipeline import (
|
|||
)
|
||||
|
||||
|
||||
IMAGE_EXTENSIONS = [
|
||||
".ani", ".anim", ".apng", ".art", ".bmp", ".bpg", ".bsave", ".cal",
|
||||
".cin", ".cpc", ".cpt", ".dds", ".dpx", ".ecw", ".exr", ".fits",
|
||||
".flic", ".flif", ".fpx", ".gif", ".hdri", ".hevc", ".icer",
|
||||
".icns", ".ico", ".cur", ".ics", ".ilbm", ".jbig", ".jbig2",
|
||||
".jng", ".jpeg", ".jpeg-ls", ".jpeg", ".2000", ".jpg", ".xr",
|
||||
".jpeg", ".xt", ".jpeg-hdr", ".kra", ".mng", ".miff", ".nrrd",
|
||||
".ora", ".pam", ".pbm", ".pgm", ".ppm", ".pnm", ".pcx", ".pgf",
|
||||
".pictor", ".png", ".psb", ".psp", ".qtvr", ".ras",
|
||||
".rgbe", ".logluv", ".tiff", ".sgi", ".tga", ".tiff", ".tiff/ep",
|
||||
".tiff/it", ".ufo", ".ufp", ".wbmp", ".webp", ".xbm", ".xcf",
|
||||
".xpm", ".xwd"
|
||||
]
|
||||
VIDEO_EXTENSIONS = [
|
||||
".3g2", ".3gp", ".amv", ".asf", ".avi", ".drc", ".f4a", ".f4b",
|
||||
".f4p", ".f4v", ".flv", ".gif", ".gifv", ".m2v", ".m4p", ".m4v",
|
||||
".mkv", ".mng", ".mov", ".mp2", ".mp4", ".mpe", ".mpeg", ".mpg",
|
||||
".mpv", ".mxf", ".nsv", ".ogg", ".ogv", ".qt", ".rm", ".rmvb",
|
||||
".roq", ".svi", ".vob", ".webm", ".wmv", ".yuv"
|
||||
]
|
||||
REVIEW_EXTENSIONS = IMAGE_EXTENSIONS + VIDEO_EXTENSIONS
|
||||
|
||||
|
||||
class TrayPublishCreator(Creator):
|
||||
create_allow_context_change = True
|
||||
host_name = "traypublisher"
|
||||
|
|
@ -37,6 +60,21 @@ class TrayPublishCreator(Creator):
|
|||
# Use same attributes as for instance attrobites
|
||||
return self.get_instance_attr_defs()
|
||||
|
||||
def _store_new_instance(self, new_instance):
|
||||
"""Tray publisher specific method to store instance.
|
||||
|
||||
Instance is stored into "workfile" of traypublisher and also add it
|
||||
to CreateContext.
|
||||
|
||||
Args:
|
||||
new_instance (CreatedInstance): Instance that should be stored.
|
||||
"""
|
||||
|
||||
# Host implementation of storing metadata about instance
|
||||
HostContext.add_instance(new_instance.data_to_store())
|
||||
# Add instance to current context
|
||||
self._add_instance_to_context(new_instance)
|
||||
|
||||
|
||||
class SettingsCreator(TrayPublishCreator):
|
||||
create_allow_context_change = True
|
||||
|
|
@ -58,19 +96,27 @@ class SettingsCreator(TrayPublishCreator):
|
|||
data["settings_creator"] = True
|
||||
# Create new instance
|
||||
new_instance = CreatedInstance(self.family, subset_name, data, self)
|
||||
# Host implementation of storing metadata about instance
|
||||
HostContext.add_instance(new_instance.data_to_store())
|
||||
# Add instance to current context
|
||||
self._add_instance_to_context(new_instance)
|
||||
|
||||
self._store_new_instance(new_instance)
|
||||
|
||||
def get_instance_attr_defs(self):
|
||||
return [
|
||||
FileDef(
|
||||
"filepath",
|
||||
"representation_files",
|
||||
folders=False,
|
||||
extensions=self.extensions,
|
||||
allow_sequences=self.allow_sequences,
|
||||
label="Filepath",
|
||||
single_item=not self.allow_multiple_items,
|
||||
label="Representations",
|
||||
),
|
||||
FileDef(
|
||||
"reviewable",
|
||||
folders=False,
|
||||
extensions=REVIEW_EXTENSIONS,
|
||||
allow_sequences=True,
|
||||
single_item=True,
|
||||
label="Reviewable representations",
|
||||
extensions_label="Single reviewable item"
|
||||
)
|
||||
]
|
||||
|
||||
|
|
@ -92,6 +138,7 @@ class SettingsCreator(TrayPublishCreator):
|
|||
"detailed_description": item_data["detailed_description"],
|
||||
"extensions": item_data["extensions"],
|
||||
"allow_sequences": item_data["allow_sequences"],
|
||||
"allow_multiple_items": item_data["allow_multiple_items"],
|
||||
"default_variants": item_data["default_variants"]
|
||||
}
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,31 +0,0 @@
|
|||
import pyblish.api
|
||||
from openpype.lib import BoolDef
|
||||
from openpype.pipeline import OpenPypePyblishPluginMixin
|
||||
|
||||
|
||||
class CollectReviewFamily(
|
||||
pyblish.api.InstancePlugin, OpenPypePyblishPluginMixin
|
||||
):
|
||||
"""Add review family."""
|
||||
|
||||
label = "Collect Review Family"
|
||||
order = pyblish.api.CollectorOrder - 0.49
|
||||
|
||||
hosts = ["traypublisher"]
|
||||
families = [
|
||||
"image",
|
||||
"render",
|
||||
"plate",
|
||||
"review"
|
||||
]
|
||||
|
||||
def process(self, instance):
|
||||
values = self.get_attr_values_from_data(instance.data)
|
||||
if values.get("add_review_family"):
|
||||
instance.data["families"].append("review")
|
||||
|
||||
@classmethod
|
||||
def get_attribute_defs(cls):
|
||||
return [
|
||||
BoolDef("add_review_family", label="Review", default=True)
|
||||
]
|
||||
|
|
@ -1,9 +1,31 @@
|
|||
import os
|
||||
import tempfile
|
||||
|
||||
import clique
|
||||
import pyblish.api
|
||||
|
||||
|
||||
class CollectSettingsSimpleInstances(pyblish.api.InstancePlugin):
|
||||
"""Collect data for instances created by settings creators."""
|
||||
"""Collect data for instances created by settings creators.
|
||||
|
||||
Plugin create representations for simple instances based
|
||||
on 'representation_files' attribute stored on instance data.
|
||||
|
||||
There is also possibility to have reviewable representation which can be
|
||||
stored under 'reviewable' attribute stored on instance data. If there was
|
||||
already created representation with the same files as 'revieable' containes
|
||||
|
||||
Representations can be marked for review and in that case is also added
|
||||
'review' family to instance families. For review can be marked only one
|
||||
representation so **first** representation that has extension available
|
||||
in '_review_extensions' is used for review.
|
||||
|
||||
For instance 'source' is used path from last representation created
|
||||
from 'representation_files'.
|
||||
|
||||
Set staging directory on instance. That is probably never used because
|
||||
each created representation has it's own staging dir.
|
||||
"""
|
||||
|
||||
label = "Collect Settings Simple Instances"
|
||||
order = pyblish.api.CollectorOrder - 0.49
|
||||
|
|
@ -14,37 +36,193 @@ class CollectSettingsSimpleInstances(pyblish.api.InstancePlugin):
|
|||
if not instance.data.get("settings_creator"):
|
||||
return
|
||||
|
||||
if "families" not in instance.data:
|
||||
instance.data["families"] = []
|
||||
instance_label = instance.data["name"]
|
||||
# Create instance's staging dir in temp
|
||||
tmp_folder = tempfile.mkdtemp(prefix="traypublisher_")
|
||||
instance.data["stagingDir"] = tmp_folder
|
||||
instance.context.data["cleanupFullPaths"].append(tmp_folder)
|
||||
|
||||
if "representations" not in instance.data:
|
||||
instance.data["representations"] = []
|
||||
repres = instance.data["representations"]
|
||||
self.log.debug((
|
||||
"Created temp staging directory for instance {}. {}"
|
||||
).format(instance_label, tmp_folder))
|
||||
|
||||
# Store filepaths for validation of their existence
|
||||
source_filepaths = []
|
||||
# Make sure there are no representations with same name
|
||||
repre_names_counter = {}
|
||||
# Store created names for logging
|
||||
repre_names = []
|
||||
# Store set of filepaths per each representation
|
||||
representation_files_mapping = []
|
||||
source = self._create_main_representations(
|
||||
instance,
|
||||
source_filepaths,
|
||||
repre_names_counter,
|
||||
repre_names,
|
||||
representation_files_mapping
|
||||
)
|
||||
|
||||
self._create_review_representation(
|
||||
instance,
|
||||
source_filepaths,
|
||||
repre_names_counter,
|
||||
repre_names,
|
||||
representation_files_mapping
|
||||
)
|
||||
|
||||
instance.data["source"] = source
|
||||
instance.data["sourceFilepaths"] = list(set(source_filepaths))
|
||||
|
||||
self.log.debug(
|
||||
(
|
||||
"Created Simple Settings instance \"{}\""
|
||||
" with {} representations: {}"
|
||||
).format(
|
||||
instance_label,
|
||||
len(instance.data["representations"]),
|
||||
", ".join(repre_names)
|
||||
)
|
||||
)
|
||||
|
||||
def _create_main_representations(
|
||||
self,
|
||||
instance,
|
||||
source_filepaths,
|
||||
repre_names_counter,
|
||||
repre_names,
|
||||
representation_files_mapping
|
||||
):
|
||||
creator_attributes = instance.data["creator_attributes"]
|
||||
filepath_items = creator_attributes["representation_files"]
|
||||
if not isinstance(filepath_items, list):
|
||||
filepath_items = [filepath_items]
|
||||
|
||||
source = None
|
||||
for filepath_item in filepath_items:
|
||||
# Skip if filepath item does not have filenames
|
||||
if not filepath_item["filenames"]:
|
||||
continue
|
||||
|
||||
filepaths = {
|
||||
os.path.join(filepath_item["directory"], filename)
|
||||
for filename in filepath_item["filenames"]
|
||||
}
|
||||
source_filepaths.extend(filepaths)
|
||||
|
||||
source = self._calculate_source(filepaths)
|
||||
representation = self._create_representation_data(
|
||||
filepath_item, repre_names_counter, repre_names
|
||||
)
|
||||
instance.data["representations"].append(representation)
|
||||
representation_files_mapping.append(
|
||||
(filepaths, representation, source)
|
||||
)
|
||||
return source
|
||||
|
||||
def _create_review_representation(
|
||||
self,
|
||||
instance,
|
||||
source_filepaths,
|
||||
repre_names_counter,
|
||||
repre_names,
|
||||
representation_files_mapping
|
||||
):
|
||||
# Skip review representation creation if there are no representations
|
||||
# created for "main" part
|
||||
# - review representation must not be created in that case so
|
||||
# validation can care about it
|
||||
if not representation_files_mapping:
|
||||
self.log.warning((
|
||||
"There are missing source representations."
|
||||
" Creation of review representation was skipped."
|
||||
))
|
||||
return
|
||||
|
||||
creator_attributes = instance.data["creator_attributes"]
|
||||
filepath_item = creator_attributes["filepath"]
|
||||
self.log.info(filepath_item)
|
||||
filepaths = [
|
||||
os.path.join(filepath_item["directory"], filename)
|
||||
for filename in filepath_item["filenames"]
|
||||
]
|
||||
review_file_item = creator_attributes["reviewable"]
|
||||
filenames = review_file_item.get("filenames")
|
||||
if not filenames:
|
||||
self.log.debug((
|
||||
"Filepath for review is not defined."
|
||||
" Skipping review representation creation."
|
||||
))
|
||||
return
|
||||
|
||||
instance.data["sourceFilepaths"] = filepaths
|
||||
instance.data["stagingDir"] = filepath_item["directory"]
|
||||
filepaths = {
|
||||
os.path.join(review_file_item["directory"], filename)
|
||||
for filename in filenames
|
||||
}
|
||||
source_filepaths.extend(filepaths)
|
||||
# First try to find out representation with same filepaths
|
||||
# so it's not needed to create new representation just for review
|
||||
review_representation = None
|
||||
# Review path (only for logging)
|
||||
review_path = None
|
||||
for item in representation_files_mapping:
|
||||
_filepaths, representation, repre_path = item
|
||||
if _filepaths == filepaths:
|
||||
review_representation = representation
|
||||
review_path = repre_path
|
||||
break
|
||||
|
||||
if review_representation is None:
|
||||
self.log.debug("Creating new review representation")
|
||||
review_path = self._calculate_source(filepaths)
|
||||
review_representation = self._create_representation_data(
|
||||
review_file_item, repre_names_counter, repre_names
|
||||
)
|
||||
instance.data["representations"].append(review_representation)
|
||||
|
||||
if "review" not in instance.data["families"]:
|
||||
instance.data["families"].append("review")
|
||||
|
||||
review_representation["tags"].append("review")
|
||||
self.log.debug("Representation {} was marked for review. {}".format(
|
||||
review_representation["name"], review_path
|
||||
))
|
||||
|
||||
def _create_representation_data(
|
||||
self, filepath_item, repre_names_counter, repre_names
|
||||
):
|
||||
"""Create new representation data based on file item.
|
||||
|
||||
Args:
|
||||
filepath_item (Dict[str, Any]): Item with information about
|
||||
representation paths.
|
||||
repre_names_counter (Dict[str, int]): Store count of representation
|
||||
names.
|
||||
repre_names (List[str]): All used representation names. For
|
||||
logging purposes.
|
||||
|
||||
Returns:
|
||||
Dict: Prepared base representation data.
|
||||
"""
|
||||
|
||||
filenames = filepath_item["filenames"]
|
||||
_, ext = os.path.splitext(filenames[0])
|
||||
ext = ext[1:]
|
||||
if len(filenames) == 1:
|
||||
filenames = filenames[0]
|
||||
|
||||
repres.append({
|
||||
"ext": ext,
|
||||
"name": ext,
|
||||
repre_name = repre_ext = ext[1:]
|
||||
if repre_name not in repre_names_counter:
|
||||
repre_names_counter[repre_name] = 2
|
||||
else:
|
||||
counter = repre_names_counter[repre_name]
|
||||
repre_names_counter[repre_name] += 1
|
||||
repre_name = "{}_{}".format(repre_name, counter)
|
||||
repre_names.append(repre_name)
|
||||
return {
|
||||
"ext": repre_ext,
|
||||
"name": repre_name,
|
||||
"stagingDir": filepath_item["directory"],
|
||||
"files": filenames
|
||||
})
|
||||
"files": filenames,
|
||||
"tags": []
|
||||
}
|
||||
|
||||
self.log.debug("Created Simple Settings instance {}".format(
|
||||
instance.data
|
||||
))
|
||||
def _calculate_source(self, filepaths):
|
||||
cols, rems = clique.assemble(filepaths)
|
||||
if cols:
|
||||
source = cols[0].format("{head}{padding}{tail}")
|
||||
elif rems:
|
||||
source = rems[0]
|
||||
return source
|
||||
|
|
|
|||
|
|
@ -3,8 +3,17 @@ import pyblish.api
|
|||
from openpype.pipeline import PublishValidationError
|
||||
|
||||
|
||||
class ValidateWorkfilePath(pyblish.api.InstancePlugin):
|
||||
"""Validate existence of workfile instance existence."""
|
||||
class ValidateFilePath(pyblish.api.InstancePlugin):
|
||||
"""Validate existence of source filepaths on instance.
|
||||
|
||||
Plugins looks into key 'sourceFilepaths' and validate if paths there
|
||||
actually exist on disk.
|
||||
|
||||
Also validate if the key is filled but is empty. In that case also
|
||||
crashes so do not fill the key if unfilled value should not cause error.
|
||||
|
||||
This is primarily created for Simple Creator instances.
|
||||
"""
|
||||
|
||||
label = "Validate Workfile"
|
||||
order = pyblish.api.ValidatorOrder - 0.49
|
||||
|
|
@ -14,12 +23,28 @@ class ValidateWorkfilePath(pyblish.api.InstancePlugin):
|
|||
def process(self, instance):
|
||||
if "sourceFilepaths" not in instance.data:
|
||||
self.log.info((
|
||||
"Can't validate source filepaths existence."
|
||||
"Skipped validation of source filepaths existence."
|
||||
" Instance does not have collected 'sourceFilepaths'"
|
||||
))
|
||||
return
|
||||
|
||||
filepaths = instance.data.get("sourceFilepaths")
|
||||
family = instance.data["family"]
|
||||
label = instance.data["name"]
|
||||
filepaths = instance.data["sourceFilepaths"]
|
||||
if not filepaths:
|
||||
raise PublishValidationError(
|
||||
(
|
||||
"Source filepaths of '{}' instance \"{}\" are not filled"
|
||||
).format(family, label),
|
||||
"File not filled",
|
||||
(
|
||||
"## Files were not filled"
|
||||
"\nThis mean that you didn't enter any files into required"
|
||||
" file input."
|
||||
"\n- Please refresh publishing and check instance"
|
||||
" <b>{}</b>"
|
||||
).format(label)
|
||||
)
|
||||
|
||||
not_found_files = [
|
||||
filepath
|
||||
|
|
@ -34,11 +59,7 @@ class ValidateWorkfilePath(pyblish.api.InstancePlugin):
|
|||
raise PublishValidationError(
|
||||
(
|
||||
"Filepath of '{}' instance \"{}\" does not exist:\n{}"
|
||||
).format(
|
||||
instance.data["family"],
|
||||
instance.data["name"],
|
||||
joined_paths
|
||||
),
|
||||
).format(family, label, joined_paths),
|
||||
"File not found",
|
||||
(
|
||||
"## Files were not found\nFiles\n{}"
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ class AbstractAttrDefMeta(ABCMeta):
|
|||
|
||||
Each object of `AbtractAttrDef` mus have defined 'key' attribute.
|
||||
"""
|
||||
|
||||
def __call__(self, *args, **kwargs):
|
||||
obj = super(AbstractAttrDefMeta, self).__call__(*args, **kwargs)
|
||||
init_class = getattr(obj, "__init__class__", None)
|
||||
|
|
@ -45,6 +46,7 @@ class AbtractAttrDef:
|
|||
is_label_horizontal(bool): UI specific argument. Specify if label is
|
||||
next to value input or ahead.
|
||||
"""
|
||||
|
||||
is_value_def = True
|
||||
|
||||
def __init__(
|
||||
|
|
@ -77,6 +79,7 @@ class AbtractAttrDef:
|
|||
Convert passed value to a valid type. Use default if value can't be
|
||||
converted.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
|
|
@ -113,6 +116,7 @@ class UnknownDef(AbtractAttrDef):
|
|||
This attribute can be used to keep existing data unchanged but does not
|
||||
have known definition of type.
|
||||
"""
|
||||
|
||||
def __init__(self, key, default=None, **kwargs):
|
||||
kwargs["default"] = default
|
||||
super(UnknownDef, self).__init__(key, **kwargs)
|
||||
|
|
@ -204,6 +208,7 @@ class TextDef(AbtractAttrDef):
|
|||
placeholder(str): UI placeholder for attribute.
|
||||
default(str, None): Default value. Empty string used when not defined.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self, key, multiline=None, regex=None, placeholder=None, default=None,
|
||||
**kwargs
|
||||
|
|
@ -531,14 +536,15 @@ class FileDef(AbtractAttrDef):
|
|||
Args:
|
||||
single_item(bool): Allow only single path item.
|
||||
folders(bool): Allow folder paths.
|
||||
extensions(list<str>): Allow files with extensions. Empty list will
|
||||
extensions(List[str]): Allow files with extensions. Empty list will
|
||||
allow all extensions and None will disable files completely.
|
||||
default(str, list<str>): Defautl value.
|
||||
extensions_label(str): Custom label shown instead of extensions in UI.
|
||||
default(str, List[str]): Default value.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self, key, single_item=True, folders=None, extensions=None,
|
||||
allow_sequences=True, default=None, **kwargs
|
||||
allow_sequences=True, extensions_label=None, default=None, **kwargs
|
||||
):
|
||||
if folders is None and extensions is None:
|
||||
folders = True
|
||||
|
|
@ -578,6 +584,7 @@ class FileDef(AbtractAttrDef):
|
|||
self.folders = folders
|
||||
self.extensions = set(extensions)
|
||||
self.allow_sequences = allow_sequences
|
||||
self.extensions_label = extensions_label
|
||||
super(FileDef, self).__init__(key, default=default, **kwargs)
|
||||
|
||||
def __eq__(self, other):
|
||||
|
|
|
|||
|
|
@ -11,6 +11,10 @@ except Exception:
|
|||
from openpype.lib.python_2_comp import WeakMethod
|
||||
|
||||
|
||||
class MissingEventSystem(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class EventCallback(object):
|
||||
"""Callback registered to a topic.
|
||||
|
||||
|
|
@ -176,16 +180,20 @@ class Event(object):
|
|||
topic (str): Identifier of event.
|
||||
data (Any): Data specific for event. Dictionary is recommended.
|
||||
source (str): Identifier of source.
|
||||
event_system (EventSystem): Event system in which can be event
|
||||
triggered.
|
||||
"""
|
||||
|
||||
_data = {}
|
||||
|
||||
def __init__(self, topic, data=None, source=None):
|
||||
def __init__(self, topic, data=None, source=None, event_system=None):
|
||||
self._id = str(uuid4())
|
||||
self._topic = topic
|
||||
if data is None:
|
||||
data = {}
|
||||
self._data = data
|
||||
self._source = source
|
||||
self._event_system = event_system
|
||||
|
||||
def __getitem__(self, key):
|
||||
return self._data[key]
|
||||
|
|
@ -211,28 +219,118 @@ class Event(object):
|
|||
|
||||
def emit(self):
|
||||
"""Emit event and trigger callbacks."""
|
||||
StoredCallbacks.emit_event(self)
|
||||
if self._event_system is None:
|
||||
raise MissingEventSystem(
|
||||
"Can't emit event {}. Does not have set event system.".format(
|
||||
str(repr(self))
|
||||
)
|
||||
)
|
||||
self._event_system.emit_event(self)
|
||||
|
||||
|
||||
class StoredCallbacks:
|
||||
_registered_callbacks = []
|
||||
class EventSystem(object):
|
||||
"""Encapsulate event handling into an object.
|
||||
|
||||
System wraps registered callbacks and triggered events into single object
|
||||
so it is possible to create mutltiple independent systems that have their
|
||||
topics and callbacks.
|
||||
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self._registered_callbacks = []
|
||||
|
||||
def add_callback(self, topic, callback):
|
||||
"""Register callback in event system.
|
||||
|
||||
Args:
|
||||
topic (str): Topic for EventCallback.
|
||||
callback (Callable): Function or method that will be called
|
||||
when topic is triggered.
|
||||
|
||||
Returns:
|
||||
EventCallback: Created callback object which can be used to
|
||||
stop listening.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def add_callback(cls, topic, callback):
|
||||
callback = EventCallback(topic, callback)
|
||||
cls._registered_callbacks.append(callback)
|
||||
self._registered_callbacks.append(callback)
|
||||
return callback
|
||||
|
||||
@classmethod
|
||||
def emit_event(cls, event):
|
||||
def create_event(self, topic, data, source):
|
||||
"""Create new event which is bound to event system.
|
||||
|
||||
Args:
|
||||
topic (str): Event topic.
|
||||
data (dict): Data related to event.
|
||||
source (str): Source of event.
|
||||
|
||||
Returns:
|
||||
Event: Object of event.
|
||||
"""
|
||||
|
||||
return Event(topic, data, source, self)
|
||||
|
||||
def emit(self, topic, data, source):
|
||||
"""Create event based on passed data and emit it.
|
||||
|
||||
This is easiest way how to trigger event in an event system.
|
||||
|
||||
Args:
|
||||
topic (str): Event topic.
|
||||
data (dict): Data related to event.
|
||||
source (str): Source of event.
|
||||
|
||||
Returns:
|
||||
Event: Created and emitted event.
|
||||
"""
|
||||
|
||||
event = self.create_event(topic, data, source)
|
||||
event.emit()
|
||||
return event
|
||||
|
||||
def emit_event(self, event):
|
||||
"""Emit event object.
|
||||
|
||||
Args:
|
||||
event (Event): Prepared event with topic and data.
|
||||
"""
|
||||
|
||||
invalid_callbacks = []
|
||||
for callback in cls._registered_callbacks:
|
||||
for callback in self._registered_callbacks:
|
||||
callback.process_event(event)
|
||||
if not callback.is_ref_valid:
|
||||
invalid_callbacks.append(callback)
|
||||
|
||||
for callback in invalid_callbacks:
|
||||
cls._registered_callbacks.remove(callback)
|
||||
self._registered_callbacks.remove(callback)
|
||||
|
||||
|
||||
class GlobalEventSystem:
|
||||
"""Event system living in global scope of process.
|
||||
|
||||
This is primarily used in host implementation to trigger events
|
||||
related to DCC changes or changes of context in the host implementation.
|
||||
"""
|
||||
|
||||
_global_event_system = None
|
||||
|
||||
@classmethod
|
||||
def get_global_event_system(cls):
|
||||
if cls._global_event_system is None:
|
||||
cls._global_event_system = EventSystem()
|
||||
return cls._global_event_system
|
||||
|
||||
@classmethod
|
||||
def add_callback(cls, topic, callback):
|
||||
event_system = cls.get_global_event_system()
|
||||
return event_system.add_callback(topic, callback)
|
||||
|
||||
@classmethod
|
||||
def emit(cls, topic, data, source):
|
||||
event_system = cls.get_global_event_system()
|
||||
return event_system.emit(topic, data, source)
|
||||
|
||||
|
||||
def register_event_callback(topic, callback):
|
||||
|
|
@ -249,7 +347,8 @@ def register_event_callback(topic, callback):
|
|||
enable/disable listening to a topic or remove the callback from
|
||||
the topic completely.
|
||||
"""
|
||||
return StoredCallbacks.add_callback(topic, callback)
|
||||
|
||||
return GlobalEventSystem.add_callback(topic, callback)
|
||||
|
||||
|
||||
def emit_event(topic, data=None, source=None):
|
||||
|
|
@ -263,6 +362,5 @@ def emit_event(topic, data=None, source=None):
|
|||
Returns:
|
||||
Event: Object of event that was emitted.
|
||||
"""
|
||||
event = Event(topic, data, source)
|
||||
event.emit()
|
||||
return event
|
||||
|
||||
return GlobalEventSystem.emit(topic, data, source)
|
||||
|
|
|
|||
|
|
@ -84,6 +84,11 @@ class CreateProjectFolders(BaseAction):
|
|||
create_project_folders(basic_paths, project_name)
|
||||
self.create_ftrack_entities(basic_paths, project_entity)
|
||||
|
||||
self.trigger_event(
|
||||
"openpype.project.structure.created",
|
||||
{"project_name": project_name}
|
||||
)
|
||||
|
||||
except Exception as exc:
|
||||
self.log.warning("Creating of structure crashed.", exc_info=True)
|
||||
session.rollback()
|
||||
|
|
|
|||
|
|
@ -116,6 +116,7 @@ class IntegrateFtrackNote(pyblish.api.InstancePlugin):
|
|||
"app_name": app_name,
|
||||
"app_label": app_label,
|
||||
"published_paths": "<br/>".join(sorted(published_paths)),
|
||||
"source": instance.data.get("source", '')
|
||||
}
|
||||
comment = template.format(**format_data)
|
||||
if not comment:
|
||||
|
|
|
|||
|
|
@ -2,13 +2,13 @@ import os
|
|||
import platform
|
||||
|
||||
|
||||
from openpype.client import get_asset_by_name
|
||||
from openpype.modules import OpenPypeModule
|
||||
from openpype_interfaces import (
|
||||
ITrayService,
|
||||
ILaunchHookPaths
|
||||
)
|
||||
from openpype.lib.events import register_event_callback
|
||||
from openpype.pipeline import AvalonMongoDB
|
||||
|
||||
from .exceptions import InvalidContextError
|
||||
|
||||
|
|
@ -197,22 +197,13 @@ class TimersManager(OpenPypeModule, ITrayService, ILaunchHookPaths):
|
|||
" Project: \"{}\" Asset: \"{}\" Task: \"{}\""
|
||||
).format(str(project_name), str(asset_name), str(task_name)))
|
||||
|
||||
dbconn = AvalonMongoDB()
|
||||
dbconn.install()
|
||||
dbconn.Session["AVALON_PROJECT"] = project_name
|
||||
|
||||
asset_doc = dbconn.find_one(
|
||||
{
|
||||
"type": "asset",
|
||||
"name": asset_name
|
||||
},
|
||||
{
|
||||
"data.tasks": True,
|
||||
"data.parents": True
|
||||
}
|
||||
asset_doc = get_asset_by_name(
|
||||
project_name,
|
||||
asset_name,
|
||||
fields=["_id", "name", "data.tasks", "data.parents"]
|
||||
)
|
||||
|
||||
if not asset_doc:
|
||||
dbconn.uninstall()
|
||||
raise InvalidContextError((
|
||||
"Asset \"{}\" not found in project \"{}\""
|
||||
).format(asset_name, project_name))
|
||||
|
|
@ -220,7 +211,6 @@ class TimersManager(OpenPypeModule, ITrayService, ILaunchHookPaths):
|
|||
asset_data = asset_doc.get("data") or {}
|
||||
asset_tasks = asset_data.get("tasks") or {}
|
||||
if task_name not in asset_tasks:
|
||||
dbconn.uninstall()
|
||||
raise InvalidContextError((
|
||||
"Task \"{}\" not found on asset \"{}\" in project \"{}\""
|
||||
).format(task_name, asset_name, project_name))
|
||||
|
|
@ -238,9 +228,10 @@ class TimersManager(OpenPypeModule, ITrayService, ILaunchHookPaths):
|
|||
hierarchy_items = asset_data.get("parents") or []
|
||||
hierarchy_items.append(asset_name)
|
||||
|
||||
dbconn.uninstall()
|
||||
return {
|
||||
"project_name": project_name,
|
||||
"asset_id": str(asset_doc["_id"]),
|
||||
"asset_name": asset_doc["name"],
|
||||
"task_name": task_name,
|
||||
"task_type": task_type,
|
||||
"hierarchy": hierarchy_items
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ UpdateData = collections.namedtuple("UpdateData", ["instance", "changes"])
|
|||
|
||||
class ImmutableKeyError(TypeError):
|
||||
"""Accessed key is immutable so does not allow changes or removements."""
|
||||
|
||||
def __init__(self, key, msg=None):
|
||||
self.immutable_key = key
|
||||
if not msg:
|
||||
|
|
@ -40,6 +41,7 @@ class ImmutableKeyError(TypeError):
|
|||
|
||||
class HostMissRequiredMethod(Exception):
|
||||
"""Host does not have implemented required functions for creation."""
|
||||
|
||||
def __init__(self, host, missing_methods):
|
||||
self.missing_methods = missing_methods
|
||||
self.host = host
|
||||
|
|
@ -66,6 +68,7 @@ class InstanceMember:
|
|||
TODO:
|
||||
Implement and use!
|
||||
"""
|
||||
|
||||
def __init__(self, instance, name):
|
||||
self.instance = instance
|
||||
|
||||
|
|
@ -94,6 +97,7 @@ class AttributeValues:
|
|||
values(dict): Values after possible conversion.
|
||||
origin_data(dict): Values loaded from host before conversion.
|
||||
"""
|
||||
|
||||
def __init__(self, attr_defs, values, origin_data=None):
|
||||
from openpype.lib.attribute_definitions import UnknownDef
|
||||
|
||||
|
|
@ -174,6 +178,10 @@ class AttributeValues:
|
|||
output = {}
|
||||
for key in self._data:
|
||||
output[key] = self[key]
|
||||
|
||||
for key, attr_def in self._attr_defs_by_key.items():
|
||||
if key not in output:
|
||||
output[key] = attr_def.default
|
||||
return output
|
||||
|
||||
@staticmethod
|
||||
|
|
@ -196,6 +204,7 @@ class CreatorAttributeValues(AttributeValues):
|
|||
Args:
|
||||
instance (CreatedInstance): Instance for which are values hold.
|
||||
"""
|
||||
|
||||
def __init__(self, instance, *args, **kwargs):
|
||||
self.instance = instance
|
||||
super(CreatorAttributeValues, self).__init__(*args, **kwargs)
|
||||
|
|
@ -211,6 +220,7 @@ class PublishAttributeValues(AttributeValues):
|
|||
publish_attributes(PublishAttributes): Wrapper for multiple publish
|
||||
attributes is used as parent object.
|
||||
"""
|
||||
|
||||
def __init__(self, publish_attributes, *args, **kwargs):
|
||||
self.publish_attributes = publish_attributes
|
||||
super(PublishAttributeValues, self).__init__(*args, **kwargs)
|
||||
|
|
@ -232,6 +242,7 @@ class PublishAttributes:
|
|||
attr_plugins(list): List of publish plugins that may have defined
|
||||
attribute definitions.
|
||||
"""
|
||||
|
||||
def __init__(self, parent, origin_data, attr_plugins=None):
|
||||
self.parent = parent
|
||||
self._origin_data = copy.deepcopy(origin_data)
|
||||
|
|
@ -270,6 +281,7 @@ class PublishAttributes:
|
|||
key(str): Plugin name.
|
||||
default: Default value if plugin was not found.
|
||||
"""
|
||||
|
||||
if key not in self._data:
|
||||
return default
|
||||
|
||||
|
|
@ -287,11 +299,13 @@ class PublishAttributes:
|
|||
|
||||
def plugin_names_order(self):
|
||||
"""Plugin names order by their 'order' attribute."""
|
||||
|
||||
for name in self._plugin_names_order:
|
||||
yield name
|
||||
|
||||
def data_to_store(self):
|
||||
"""Convert attribute values to "data to store"."""
|
||||
|
||||
output = {}
|
||||
for key, attr_value in self._data.items():
|
||||
output[key] = attr_value.data_to_store()
|
||||
|
|
@ -299,6 +313,7 @@ class PublishAttributes:
|
|||
|
||||
def changes(self):
|
||||
"""Return changes per each key."""
|
||||
|
||||
changes = {}
|
||||
for key, attr_val in self._data.items():
|
||||
attr_changes = attr_val.changes()
|
||||
|
|
@ -314,6 +329,7 @@ class PublishAttributes:
|
|||
|
||||
def set_publish_plugins(self, attr_plugins):
|
||||
"""Set publish plugins attribute definitions."""
|
||||
|
||||
self._plugin_names_order = []
|
||||
self._missing_plugins = []
|
||||
self.attr_plugins = attr_plugins or []
|
||||
|
|
@ -365,6 +381,7 @@ class CreatedInstance:
|
|||
`openpype.pipeline.registered_host`.
|
||||
new(bool): Is instance new.
|
||||
"""
|
||||
|
||||
# Keys that can't be changed or removed from data after loading using
|
||||
# creator.
|
||||
# - 'creator_attributes' and 'publish_attributes' can change values of
|
||||
|
|
@ -566,6 +583,7 @@ class CreatedInstance:
|
|||
@property
|
||||
def id(self):
|
||||
"""Instance identifier."""
|
||||
|
||||
return self._data["instance_id"]
|
||||
|
||||
@property
|
||||
|
|
@ -574,10 +592,12 @@ class CreatedInstance:
|
|||
|
||||
Access to data is needed to modify values.
|
||||
"""
|
||||
|
||||
return self
|
||||
|
||||
def changes(self):
|
||||
"""Calculate and return changes."""
|
||||
|
||||
changes = {}
|
||||
new_keys = set()
|
||||
for key, new_value in self._data.items():
|
||||
|
|
@ -716,6 +736,7 @@ class CreateContext:
|
|||
self.manual_creators = {}
|
||||
|
||||
self.publish_discover_result = None
|
||||
self.publish_plugins_mismatch_targets = []
|
||||
self.publish_plugins = []
|
||||
self.plugins_with_defs = []
|
||||
self._attr_plugins_by_family = {}
|
||||
|
|
@ -838,6 +859,7 @@ class CreateContext:
|
|||
discover_result = DiscoverResult()
|
||||
plugins_with_defs = []
|
||||
plugins_by_targets = []
|
||||
plugins_mismatch_targets = []
|
||||
if discover_publish_plugins:
|
||||
discover_result = publish_plugins_discover()
|
||||
publish_plugins = discover_result.plugins
|
||||
|
|
@ -847,11 +869,19 @@ class CreateContext:
|
|||
plugins_by_targets = pyblish.logic.plugins_by_targets(
|
||||
publish_plugins, list(targets)
|
||||
)
|
||||
|
||||
# Collect plugins that can have attribute definitions
|
||||
for plugin in publish_plugins:
|
||||
if OpenPypePyblishPluginMixin in inspect.getmro(plugin):
|
||||
plugins_with_defs.append(plugin)
|
||||
|
||||
plugins_mismatch_targets = [
|
||||
plugin
|
||||
for plugin in publish_plugins
|
||||
if plugin not in plugins_by_targets
|
||||
]
|
||||
|
||||
self.publish_plugins_mismatch_targets = plugins_mismatch_targets
|
||||
self.publish_discover_result = discover_result
|
||||
self.publish_plugins = plugins_by_targets
|
||||
self.plugins_with_defs = plugins_with_defs
|
||||
|
|
|
|||
|
|
@ -102,6 +102,10 @@ class BaseCreator:
|
|||
|
||||
return self.create_context.project_name
|
||||
|
||||
@property
|
||||
def host(self):
|
||||
return self.create_context.host
|
||||
|
||||
def get_group_label(self):
|
||||
"""Group label under which are instances grouped in UI.
|
||||
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ class CollectAnatomyInstanceData(pyblish.api.ContextPlugin):
|
|||
|
||||
project_name = legacy_io.active_project()
|
||||
self.fill_missing_asset_docs(context, project_name)
|
||||
self.fill_instance_data_from_asset(context)
|
||||
self.fill_latest_versions(context, project_name)
|
||||
self.fill_anatomy_data(context)
|
||||
|
||||
|
|
@ -115,6 +116,23 @@ class CollectAnatomyInstanceData(pyblish.api.ContextPlugin):
|
|||
"Not found asset documents with names \"{}\"."
|
||||
).format(joined_asset_names))
|
||||
|
||||
def fill_instance_data_from_asset(self, context):
|
||||
for instance in context:
|
||||
asset_doc = instance.data.get("assetEntity")
|
||||
if not asset_doc:
|
||||
continue
|
||||
|
||||
asset_data = asset_doc["data"]
|
||||
for key in (
|
||||
"fps",
|
||||
"frameStart",
|
||||
"frameEnd",
|
||||
"handleStart",
|
||||
"handleEnd",
|
||||
):
|
||||
if key not in instance.data and key in asset_data:
|
||||
instance.data[key] = asset_data[key]
|
||||
|
||||
def fill_latest_versions(self, context, project_name):
|
||||
"""Try to find latest version for each instance's subset.
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ class CollectCleanupKeys(pyblish.api.ContextPlugin):
|
|||
"""Prepare keys for 'ExplicitCleanUp' plugin."""
|
||||
|
||||
label = "Collect Cleanup Keys"
|
||||
order = pyblish.api.CollectorOrder
|
||||
order = pyblish.api.CollectorOrder - 0.5
|
||||
|
||||
def process(self, context):
|
||||
context.data["cleanupFullPaths"] = []
|
||||
|
|
|
|||
|
|
@ -47,12 +47,11 @@ class CollectFromCreateContext(pyblish.api.ContextPlugin):
|
|||
"label": subset,
|
||||
"name": subset,
|
||||
"family": in_data["family"],
|
||||
"families": instance_families
|
||||
"families": instance_families,
|
||||
"representations": []
|
||||
})
|
||||
for key, value in in_data.items():
|
||||
if key not in instance.data:
|
||||
instance.data[key] = value
|
||||
self.log.info("collected instance: {}".format(instance.data))
|
||||
self.log.info("parsing data: {}".format(in_data))
|
||||
|
||||
instance.data["representations"] = list()
|
||||
|
|
|
|||
|
|
@ -497,11 +497,29 @@
|
|||
"override_viewport_options": true,
|
||||
"displayLights": "default",
|
||||
"textureMaxResolution": 1024,
|
||||
"multiSample": 4,
|
||||
"renderDepthOfField": true,
|
||||
"shadows": true,
|
||||
"textures": true,
|
||||
"twoSidedLighting": true,
|
||||
"ssaoEnable": true,
|
||||
"lineAAEnable": true,
|
||||
"multiSample": 8,
|
||||
"ssaoEnable": false,
|
||||
"ssaoAmount": 1,
|
||||
"ssaoRadius": 16,
|
||||
"ssaoFilterRadius": 16,
|
||||
"ssaoSamples": 16,
|
||||
"fogging": false,
|
||||
"hwFogFalloff": "0",
|
||||
"hwFogDensity": 0.0,
|
||||
"hwFogStart": 0,
|
||||
"hwFogEnd": 100,
|
||||
"hwFogAlpha": 0,
|
||||
"hwFogColorR": 1.0,
|
||||
"hwFogColorG": 1.0,
|
||||
"hwFogColorB": 1.0,
|
||||
"motionBlurEnable": false,
|
||||
"motionBlurSampleCount": 8,
|
||||
"motionBlurShutterOpenFraction": 0.2,
|
||||
"cameras": false,
|
||||
"clipGhosts": false,
|
||||
"controlVertices": false,
|
||||
|
|
|
|||
|
|
@ -287,7 +287,11 @@
|
|||
"LoadClip": {
|
||||
"enabled": true,
|
||||
"_representations": [],
|
||||
"node_name_template": "{class_name}_{ext}"
|
||||
"node_name_template": "{class_name}_{ext}",
|
||||
"options_defaults": {
|
||||
"start_at_workfile": true,
|
||||
"add_retime": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"workfile_builder": {
|
||||
|
|
|
|||
|
|
@ -8,9 +8,10 @@
|
|||
"default_variants": [
|
||||
"Main"
|
||||
],
|
||||
"description": "Publish workfile backup",
|
||||
"detailed_description": "",
|
||||
"allow_sequences": true,
|
||||
"description": "Backup of a working scene",
|
||||
"detailed_description": "Workfiles are full scenes from any application that are directly edited by artists. They represent a state of work on a task at a given point and are usually not directly referenced into other scenes.",
|
||||
"allow_sequences": false,
|
||||
"allow_multiple_items": false,
|
||||
"extensions": [
|
||||
".ma",
|
||||
".mb",
|
||||
|
|
@ -30,6 +31,209 @@
|
|||
".psb",
|
||||
".aep"
|
||||
]
|
||||
},
|
||||
{
|
||||
"family": "model",
|
||||
"identifier": "",
|
||||
"label": "Model",
|
||||
"icon": "fa.cubes",
|
||||
"default_variants": [
|
||||
"Main",
|
||||
"Proxy",
|
||||
"Sculpt"
|
||||
],
|
||||
"description": "Clean models",
|
||||
"detailed_description": "Models should only contain geometry data, without any extras like cameras, locators or bones.\n\nKeep in mind that models published from tray publisher are not validated for correctness. ",
|
||||
"allow_sequences": false,
|
||||
"allow_multiple_items": true,
|
||||
"extensions": [
|
||||
".ma",
|
||||
".mb",
|
||||
".obj",
|
||||
".abc",
|
||||
".fbx",
|
||||
".bgeo",
|
||||
".bgeogz",
|
||||
".bgeosc",
|
||||
".usd",
|
||||
".blend"
|
||||
]
|
||||
},
|
||||
{
|
||||
"family": "pointcache",
|
||||
"identifier": "",
|
||||
"label": "Pointcache",
|
||||
"icon": "fa.gears",
|
||||
"default_variants": [
|
||||
"Main"
|
||||
],
|
||||
"description": "Geometry Caches",
|
||||
"detailed_description": "Alembic or bgeo cache of animated data",
|
||||
"allow_sequences": true,
|
||||
"allow_multiple_items": true,
|
||||
"extensions": [
|
||||
".abc",
|
||||
".bgeo",
|
||||
".bgeogz",
|
||||
".bgeosc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"family": "plate",
|
||||
"identifier": "",
|
||||
"label": "Plate",
|
||||
"icon": "mdi.camera-image",
|
||||
"default_variants": [
|
||||
"Main",
|
||||
"BG",
|
||||
"Animatic",
|
||||
"Reference",
|
||||
"Offline"
|
||||
],
|
||||
"description": "Footage Plates",
|
||||
"detailed_description": "Any type of image seqeuence coming from outside of the studio. Usually camera footage, but could also be animatics used for reference.",
|
||||
"allow_sequences": true,
|
||||
"allow_multiple_items": true,
|
||||
"extensions": [
|
||||
".exr",
|
||||
".png",
|
||||
".dpx",
|
||||
".jpg",
|
||||
".tiff",
|
||||
".tif",
|
||||
".mov",
|
||||
".mp4",
|
||||
".avi"
|
||||
]
|
||||
},
|
||||
{
|
||||
"family": "render",
|
||||
"identifier": "",
|
||||
"label": "Render",
|
||||
"icon": "mdi.folder-multiple-image",
|
||||
"default_variants": [],
|
||||
"description": "Rendered images or video",
|
||||
"detailed_description": "Sequence or single file renders",
|
||||
"allow_sequences": true,
|
||||
"allow_multiple_items": true,
|
||||
"extensions": [
|
||||
".exr",
|
||||
".png",
|
||||
".dpx",
|
||||
".jpg",
|
||||
".jpeg",
|
||||
".tiff",
|
||||
".tif",
|
||||
".mov",
|
||||
".mp4",
|
||||
".avi"
|
||||
]
|
||||
},
|
||||
{
|
||||
"family": "camera",
|
||||
"identifier": "",
|
||||
"label": "Camera",
|
||||
"icon": "fa.video-camera",
|
||||
"default_variants": [],
|
||||
"description": "3d Camera",
|
||||
"detailed_description": "Ideally this should be only camera itself with baked animation, however, it can technically also include helper geometry.",
|
||||
"allow_sequences": false,
|
||||
"allow_multiple_items": true,
|
||||
"extensions": [
|
||||
".abc",
|
||||
".ma",
|
||||
".hip",
|
||||
".blend",
|
||||
".fbx",
|
||||
".usd"
|
||||
]
|
||||
},
|
||||
{
|
||||
"family": "image",
|
||||
"identifier": "",
|
||||
"label": "Image",
|
||||
"icon": "fa.image",
|
||||
"default_variants": [
|
||||
"Reference",
|
||||
"Texture",
|
||||
"Concept",
|
||||
"Background"
|
||||
],
|
||||
"description": "Single image",
|
||||
"detailed_description": "Any image data can be published as image family. References, textures, concept art, matte paints. This is a fallback 2d family for everything that doesn't fit more specific family.",
|
||||
"allow_sequences": false,
|
||||
"allow_multiple_items": true,
|
||||
"extensions": [
|
||||
".exr",
|
||||
".jpg",
|
||||
".jpeg",
|
||||
".dpx",
|
||||
".bmp",
|
||||
".tif",
|
||||
".tiff",
|
||||
".png",
|
||||
".psb",
|
||||
".psd"
|
||||
]
|
||||
},
|
||||
{
|
||||
"family": "vdb",
|
||||
"identifier": "",
|
||||
"label": "VDB Volumes",
|
||||
"icon": "fa.cloud",
|
||||
"default_variants": [],
|
||||
"description": "Sparse volumetric data",
|
||||
"detailed_description": "Hierarchical data structure for the efficient storage and manipulation of sparse volumetric data discretized on three-dimensional grids",
|
||||
"allow_sequences": true,
|
||||
"allow_multiple_items": true,
|
||||
"extensions": [
|
||||
".vdb"
|
||||
]
|
||||
},
|
||||
{
|
||||
"family": "matchmove",
|
||||
"identifier": "",
|
||||
"label": "Matchmove",
|
||||
"icon": "fa.empire",
|
||||
"default_variants": [
|
||||
"Camera",
|
||||
"Object",
|
||||
"Mocap"
|
||||
],
|
||||
"description": "Matchmoving script",
|
||||
"detailed_description": "Script exported from matchmoving application to be later processed into a tracked camera with additional data",
|
||||
"allow_sequences": false,
|
||||
"allow_multiple_items": true,
|
||||
"extensions": []
|
||||
},
|
||||
{
|
||||
"family": "rig",
|
||||
"identifier": "",
|
||||
"label": "Rig",
|
||||
"icon": "fa.wheelchair",
|
||||
"default_variants": [],
|
||||
"description": "CG rig file",
|
||||
"detailed_description": "CG rigged character or prop. Rig should be clean of any extra data and directly loadable into it's respective application\t",
|
||||
"allow_sequences": false,
|
||||
"allow_multiple_items": false,
|
||||
"extensions": [
|
||||
".ma",
|
||||
".blend",
|
||||
".hip",
|
||||
".hda"
|
||||
]
|
||||
},
|
||||
{
|
||||
"family": "simpleUnrealTexture",
|
||||
"identifier": "",
|
||||
"label": "Simple UE texture",
|
||||
"icon": "fa.image",
|
||||
"default_variants": [],
|
||||
"description": "Simple Unreal Engine texture",
|
||||
"detailed_description": "Texture files with Unreal Engine naming conventions",
|
||||
"allow_sequences": false,
|
||||
"allow_multiple_items": true,
|
||||
"extensions": []
|
||||
}
|
||||
],
|
||||
"BatchMovCreator": {
|
||||
|
|
|
|||
|
|
@ -822,7 +822,7 @@
|
|||
},
|
||||
{
|
||||
"type": "label",
|
||||
"label": "Template may contain formatting keys <b>intent</b>, <b>comment</b>, <b>host_name</b>, <b>app_name</b>, <b>app_label</b> and <b>published_paths</b>."
|
||||
"label": "Template may contain formatting keys <b>intent</b>, <b>comment</b>, <b>host_name</b>, <b>app_name</b>, <b>app_label</b>, <b>published_paths</b> and <b>source</b>."
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
|
|
|
|||
|
|
@ -67,6 +67,11 @@
|
|||
"label": "Allow sequences",
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"key": "allow_multiple_items",
|
||||
"label": "Allow multiple items",
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"type": "list",
|
||||
"key": "extensions",
|
||||
|
|
|
|||
|
|
@ -202,12 +202,15 @@
|
|||
"decimal": 0
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"key": "multiSample",
|
||||
"label": "Anti Aliasing Samples",
|
||||
"decimal": 0,
|
||||
"minimum": 0,
|
||||
"maximum": 32
|
||||
"type": "splitter"
|
||||
},
|
||||
{
|
||||
"type":"boolean",
|
||||
"key": "renderDepthOfField",
|
||||
"label": "Depth of Field"
|
||||
},
|
||||
{
|
||||
"type": "splitter"
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
|
|
@ -224,11 +227,145 @@
|
|||
"key": "twoSidedLighting",
|
||||
"label": "Two Sided Lighting"
|
||||
},
|
||||
{
|
||||
"type": "splitter"
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "lineAAEnable",
|
||||
"label": "Enable Anti-Aliasing"
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"key": "multiSample",
|
||||
"label": "Anti Aliasing Samples",
|
||||
"decimal": 0,
|
||||
"minimum": 0,
|
||||
"maximum": 32
|
||||
},
|
||||
{
|
||||
"type": "splitter"
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "ssaoEnable",
|
||||
"label": "Screen Space Ambient Occlusion"
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"key": "ssaoAmount",
|
||||
"label": "SSAO Amount"
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"key": "ssaoRadius",
|
||||
"label": "SSAO Radius"
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"key": "ssaoFilterRadius",
|
||||
"label": "SSAO Filter Radius",
|
||||
"decimal": 0,
|
||||
"minimum": 1,
|
||||
"maximum": 32
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"key": "ssaoSamples",
|
||||
"label": "SSAO Samples",
|
||||
"decimal": 0,
|
||||
"minimum": 8,
|
||||
"maximum": 32
|
||||
},
|
||||
{
|
||||
"type": "splitter"
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "fogging",
|
||||
"label": "Enable Hardware Fog"
|
||||
},
|
||||
{
|
||||
"type": "enum",
|
||||
"key": "hwFogFalloff",
|
||||
"label": "Hardware Falloff",
|
||||
"enum_items": [
|
||||
{ "0": "Linear"},
|
||||
{ "1": "Exponential"},
|
||||
{ "2": "Exponential Squared"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"key": "hwFogDensity",
|
||||
"label": "Fog Density",
|
||||
"decimal": 2,
|
||||
"minimum": 0,
|
||||
"maximum": 1
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"key": "hwFogStart",
|
||||
"label": "Fog Start"
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"key": "hwFogEnd",
|
||||
"label": "Fog End"
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"key": "hwFogAlpha",
|
||||
"label": "Fog Alpha"
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"key": "hwFogColorR",
|
||||
"label": "Fog Color R",
|
||||
"decimal": 2,
|
||||
"minimum": 0,
|
||||
"maximum": 1
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"key": "hwFogColorG",
|
||||
"label": "Fog Color G",
|
||||
"decimal": 2,
|
||||
"minimum": 0,
|
||||
"maximum": 1
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"key": "hwFogColorB",
|
||||
"label": "Fog Color B",
|
||||
"decimal": 2,
|
||||
"minimum": 0,
|
||||
"maximum": 1
|
||||
},
|
||||
{
|
||||
"type": "splitter"
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "motionBlurEnable",
|
||||
"label": "Enable Motion Blur"
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"key": "motionBlurSampleCount",
|
||||
"label": "Motion Blur Sample Count",
|
||||
"decimal": 0,
|
||||
"minimum": 8,
|
||||
"maximum": 32
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"key": "motionBlurShutterOpenFraction",
|
||||
"label": "Shutter Open Fraction",
|
||||
"decimal": 3,
|
||||
"minimum": 0.01,
|
||||
"maximum": 32
|
||||
},
|
||||
{
|
||||
"type": "splitter"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -11,10 +11,52 @@
|
|||
{
|
||||
"key": "LoadImage",
|
||||
"label": "Image Loader"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "dict",
|
||||
"collapsible": true,
|
||||
"key": "LoadClip",
|
||||
"label": "Clip Loader",
|
||||
"checkbox_key": "enabled",
|
||||
"children": [
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "enabled",
|
||||
"label": "Enabled"
|
||||
},
|
||||
{
|
||||
"key": "LoadClip",
|
||||
"label": "Clip Loader"
|
||||
"type": "list",
|
||||
"key": "_representations",
|
||||
"label": "Representations",
|
||||
"object_type": "text"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"key": "node_name_template",
|
||||
"label": "Node name template"
|
||||
},
|
||||
{
|
||||
"type": "splitter"
|
||||
},
|
||||
{
|
||||
"type": "dict",
|
||||
"collapsible": false,
|
||||
"key": "options_defaults",
|
||||
"label": "Loader option defaults",
|
||||
"children": [
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "start_at_workfile",
|
||||
"label": "Start at worfile beggining"
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "add_retime",
|
||||
"label": "Add retime"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -154,15 +154,20 @@ class PublishReport:
|
|||
self._all_instances_by_id = {}
|
||||
self._current_context = None
|
||||
|
||||
def reset(self, context, publish_discover_result=None):
|
||||
def reset(self, context, create_context):
|
||||
"""Reset report and clear all data."""
|
||||
self._publish_discover_result = publish_discover_result
|
||||
|
||||
self._publish_discover_result = create_context.publish_discover_result
|
||||
self._plugin_data = []
|
||||
self._plugin_data_with_plugin = []
|
||||
self._current_plugin_data = {}
|
||||
self._all_instances_by_id = {}
|
||||
self._current_context = context
|
||||
|
||||
for plugin in create_context.publish_plugins_mismatch_targets:
|
||||
plugin_data = self._add_plugin_data_item(plugin)
|
||||
plugin_data["skipped"] = True
|
||||
|
||||
def add_plugin_iter(self, plugin, context):
|
||||
"""Add report about single iteration of plugin."""
|
||||
for instance in context:
|
||||
|
|
@ -205,6 +210,7 @@ class PublishReport:
|
|||
"name": plugin.__name__,
|
||||
"label": label,
|
||||
"order": plugin.order,
|
||||
"targets": list(plugin.targets),
|
||||
"instances_data": [],
|
||||
"actions_data": [],
|
||||
"skipped": False,
|
||||
|
|
@ -569,6 +575,8 @@ class PublisherController:
|
|||
# Stop publishing
|
||||
self.stop_publish()
|
||||
|
||||
self.save_changes()
|
||||
|
||||
# Reset avalon context
|
||||
self.create_context.reset_avalon_context()
|
||||
|
||||
|
|
@ -777,10 +785,7 @@ class PublisherController:
|
|||
# - pop the key after first collector using it would be safest option?
|
||||
self._publish_context.data["create_context"] = self.create_context
|
||||
|
||||
self._publish_report.reset(
|
||||
self._publish_context,
|
||||
self.create_context.publish_discover_result
|
||||
)
|
||||
self._publish_report.reset(self._publish_context, self.create_context)
|
||||
self._publish_validation_errors = []
|
||||
self._publish_current_plugin_validation_errors = None
|
||||
self._publish_error = None
|
||||
|
|
|
|||
|
|
@ -83,10 +83,8 @@ class PublishReport:
|
|||
|
||||
logs = []
|
||||
plugins_items_by_id = {}
|
||||
plugins_id_order = []
|
||||
for plugin_data in data["plugins_data"]:
|
||||
item = PluginItem(plugin_data)
|
||||
plugins_id_order.append(item.id)
|
||||
plugins_items_by_id[item.id] = item
|
||||
for instance_data_item in plugin_data["instances_data"]:
|
||||
instance_id = instance_data_item["id"]
|
||||
|
|
@ -95,6 +93,14 @@ class PublishReport:
|
|||
copy.deepcopy(log_item_data), item.id, instance_id
|
||||
)
|
||||
logs.append(log_item)
|
||||
sorted_plugins = sorted(
|
||||
plugins_items_by_id.values(),
|
||||
key=lambda item: item.order
|
||||
)
|
||||
plugins_id_order = [
|
||||
plugin_item.id
|
||||
for plugin_item in sorted_plugins
|
||||
]
|
||||
|
||||
logs_by_instance_id = collections.defaultdict(list)
|
||||
for log_item in logs:
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
from math import ceil
|
||||
from Qt import QtWidgets, QtCore, QtGui
|
||||
|
||||
from openpype.widgets.nice_checkbox import NiceCheckbox
|
||||
|
|
@ -137,13 +138,75 @@ class PluginLoadReportWidget(QtWidgets.QWidget):
|
|||
self._model.set_report(report)
|
||||
|
||||
|
||||
class ZoomPlainText(QtWidgets.QPlainTextEdit):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(ZoomPlainText, self).__init__(*args, **kwargs)
|
||||
|
||||
anim_timer = QtCore.QTimer()
|
||||
anim_timer.setInterval(20)
|
||||
|
||||
anim_timer.timeout.connect(self._scaling_callback)
|
||||
|
||||
self._anim_timer = anim_timer
|
||||
self._zoom_enabled = False
|
||||
self._scheduled_scalings = 0
|
||||
self._point_size = None
|
||||
|
||||
def wheelEvent(self, event):
|
||||
if not self._zoom_enabled:
|
||||
super(ZoomPlainText, self).wheelEvent(event)
|
||||
return
|
||||
|
||||
degrees = float(event.delta()) / 8
|
||||
steps = int(ceil(degrees / 5))
|
||||
self._scheduled_scalings += steps
|
||||
if (self._scheduled_scalings * steps < 0):
|
||||
self._scheduled_scalings = steps
|
||||
|
||||
self._anim_timer.start()
|
||||
|
||||
def _scaling_callback(self):
|
||||
if self._scheduled_scalings == 0:
|
||||
self._anim_timer.stop()
|
||||
return
|
||||
|
||||
factor = 1.0 + (self._scheduled_scalings / 300)
|
||||
font = self.font()
|
||||
if self._point_size is None:
|
||||
self._point_size = font.pointSizeF()
|
||||
|
||||
self._point_size *= factor
|
||||
if self._point_size < 1:
|
||||
self._point_size = 1.0
|
||||
|
||||
font.setPointSizeF(self._point_size)
|
||||
# Using 'self.setFont(font)' would not be propagated when stylesheets
|
||||
# are applied on this widget
|
||||
self.setStyleSheet("font-size: {}pt".format(font.pointSize()))
|
||||
|
||||
if self._scheduled_scalings > 0:
|
||||
self._scheduled_scalings -= 1
|
||||
else:
|
||||
self._scheduled_scalings += 1
|
||||
|
||||
def keyPressEvent(self, event):
|
||||
if event.key() == QtCore.Qt.Key_Control:
|
||||
self._zoom_enabled = True
|
||||
super(ZoomPlainText, self).keyPressEvent(event)
|
||||
|
||||
def keyReleaseEvent(self, event):
|
||||
if event.key() == QtCore.Qt.Key_Control:
|
||||
self._zoom_enabled = False
|
||||
super(ZoomPlainText, self).keyReleaseEvent(event)
|
||||
|
||||
|
||||
class DetailsWidget(QtWidgets.QWidget):
|
||||
def __init__(self, parent):
|
||||
super(DetailsWidget, self).__init__(parent)
|
||||
|
||||
output_widget = QtWidgets.QPlainTextEdit(self)
|
||||
output_widget.setTextInteractionFlags(QtCore.Qt.TextBrowserInteraction)
|
||||
output_widget = ZoomPlainText(self)
|
||||
output_widget.setObjectName("PublishLogConsole")
|
||||
output_widget.setTextInteractionFlags(QtCore.Qt.TextBrowserInteraction)
|
||||
|
||||
layout = QtWidgets.QVBoxLayout(self)
|
||||
layout.setContentsMargins(0, 0, 0, 0)
|
||||
|
|
|
|||
|
|
@ -854,6 +854,9 @@ class ProjectWidget(SettingsCategoryWidget):
|
|||
project_list_widget.version_change_requested.connect(
|
||||
self._on_source_version_change
|
||||
)
|
||||
project_list_widget.extract_to_file_requested.connect(
|
||||
self._on_extract_to_file
|
||||
)
|
||||
|
||||
self.project_list_widget = project_list_widget
|
||||
|
||||
|
|
|
|||
|
|
@ -1008,6 +1008,7 @@ class ProjectSortFilterProxy(QtCore.QSortFilterProxyModel):
|
|||
class ProjectListWidget(QtWidgets.QWidget):
|
||||
project_changed = QtCore.Signal()
|
||||
version_change_requested = QtCore.Signal(str)
|
||||
extract_to_file_requested = QtCore.Signal()
|
||||
|
||||
def __init__(self, parent, only_active=False):
|
||||
self._parent = parent
|
||||
|
|
@ -1099,7 +1100,12 @@ class ProjectListWidget(QtWidgets.QWidget):
|
|||
self.version_change_requested
|
||||
)
|
||||
submenu.addAction(action)
|
||||
|
||||
extract_action = QtWidgets.QAction("Extract to file", menu)
|
||||
extract_action.triggered.connect(self.extract_to_file_requested)
|
||||
|
||||
menu.addMenu(submenu)
|
||||
menu.addAction(extract_action)
|
||||
menu.exec_(QtGui.QCursor.pos())
|
||||
|
||||
def on_item_clicked(self, new_index):
|
||||
|
|
|
|||
|
|
@ -12,9 +12,7 @@ from openpype.pipeline import (
|
|||
install_host,
|
||||
AvalonMongoDB,
|
||||
)
|
||||
from openpype.hosts.traypublisher import (
|
||||
api as traypublisher
|
||||
)
|
||||
from openpype.hosts.traypublisher.api import TrayPublisherHost
|
||||
from openpype.tools.publisher import PublisherWindow
|
||||
from openpype.tools.utils.constants import PROJECT_NAME_ROLE
|
||||
from openpype.tools.utils.models import (
|
||||
|
|
@ -111,9 +109,13 @@ class StandaloneOverlayWidget(QtWidgets.QFrame):
|
|||
if project_name:
|
||||
self._set_project(project_name)
|
||||
|
||||
@property
|
||||
def host(self):
|
||||
return self._publisher_window.controller.host
|
||||
|
||||
def _set_project(self, project_name):
|
||||
self._project_name = project_name
|
||||
traypublisher.set_project_name(project_name)
|
||||
self.host.set_project_name(project_name)
|
||||
self.setVisible(False)
|
||||
self.project_selected.emit(project_name)
|
||||
|
||||
|
|
@ -190,7 +192,8 @@ class TrayPublishWindow(PublisherWindow):
|
|||
|
||||
|
||||
def main():
|
||||
install_host(traypublisher)
|
||||
host = TrayPublisherHost()
|
||||
install_host(host)
|
||||
app = QtWidgets.QApplication([])
|
||||
window = TrayPublishWindow()
|
||||
window.show()
|
||||
|
|
|
|||
3
openpype/vendor/python/common/capture.py
vendored
3
openpype/vendor/python/common/capture.py
vendored
|
|
@ -380,7 +380,8 @@ Viewport2Options = {
|
|||
"transparencyAlgorithm": 1,
|
||||
"transparencyQuality": 0.33,
|
||||
"useMaximumHardwareLights": True,
|
||||
"vertexAnimationCache": 0
|
||||
"vertexAnimationCache": 0,
|
||||
"renderDepthOfField": 0
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""Package declaring Pype version."""
|
||||
__version__ = "3.12.1-nightly.4"
|
||||
__version__ = "3.12.1"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import os
|
||||
import collections
|
||||
import uuid
|
||||
import json
|
||||
|
||||
from Qt import QtWidgets, QtCore, QtGui
|
||||
|
||||
|
|
@ -26,6 +27,27 @@ IS_SEQUENCE_ROLE = QtCore.Qt.UserRole + 7
|
|||
EXT_ROLE = QtCore.Qt.UserRole + 8
|
||||
|
||||
|
||||
def convert_bytes_to_json(bytes_value):
|
||||
if isinstance(bytes_value, QtCore.QByteArray):
|
||||
# Raw data are already QByteArray and we don't have to load them
|
||||
encoded_data = bytes_value
|
||||
else:
|
||||
encoded_data = QtCore.QByteArray.fromRawData(bytes_value)
|
||||
stream = QtCore.QDataStream(encoded_data, QtCore.QIODevice.ReadOnly)
|
||||
text = stream.readQString()
|
||||
try:
|
||||
return json.loads(text)
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
|
||||
def convert_data_to_bytes(data):
|
||||
bytes_value = QtCore.QByteArray()
|
||||
stream = QtCore.QDataStream(bytes_value, QtCore.QIODevice.WriteOnly)
|
||||
stream.writeQString(json.dumps(data))
|
||||
return bytes_value
|
||||
|
||||
|
||||
class SupportLabel(QtWidgets.QLabel):
|
||||
pass
|
||||
|
||||
|
|
@ -33,7 +55,7 @@ class SupportLabel(QtWidgets.QLabel):
|
|||
class DropEmpty(QtWidgets.QWidget):
|
||||
_empty_extensions = "Any file"
|
||||
|
||||
def __init__(self, single_item, allow_sequences, parent):
|
||||
def __init__(self, single_item, allow_sequences, extensions_label, parent):
|
||||
super(DropEmpty, self).__init__(parent)
|
||||
|
||||
drop_label_widget = QtWidgets.QLabel("Drag & Drop files here", self)
|
||||
|
|
@ -61,7 +83,19 @@ class DropEmpty(QtWidgets.QWidget):
|
|||
widget.setAlignment(QtCore.Qt.AlignCenter)
|
||||
widget.setAttribute(QtCore.Qt.WA_TranslucentBackground)
|
||||
|
||||
update_size_timer = QtCore.QTimer()
|
||||
update_size_timer.setInterval(10)
|
||||
update_size_timer.setSingleShot(True)
|
||||
|
||||
update_size_timer.timeout.connect(self._on_update_size_timer)
|
||||
|
||||
self._update_size_timer = update_size_timer
|
||||
|
||||
if extensions_label and not extensions_label.startswith(" "):
|
||||
extensions_label = " " + extensions_label
|
||||
|
||||
self._single_item = single_item
|
||||
self._extensions_label = extensions_label
|
||||
self._allow_sequences = allow_sequences
|
||||
self._allowed_extensions = set()
|
||||
self._allow_folders = None
|
||||
|
|
@ -114,22 +148,51 @@ class DropEmpty(QtWidgets.QWidget):
|
|||
items_label = "Single "
|
||||
|
||||
if len(allowed_items) == 1:
|
||||
allowed_items_label = allowed_items[0]
|
||||
extensions_label = allowed_items[0]
|
||||
elif len(allowed_items) == 2:
|
||||
allowed_items_label = " or ".join(allowed_items)
|
||||
extensions_label = " or ".join(allowed_items)
|
||||
else:
|
||||
last_item = allowed_items.pop(-1)
|
||||
new_last_item = " or ".join(last_item, allowed_items.pop(-1))
|
||||
allowed_items.append(new_last_item)
|
||||
allowed_items_label = ", ".join(allowed_items)
|
||||
extensions_label = ", ".join(allowed_items)
|
||||
|
||||
allowed_items_label = extensions_label
|
||||
|
||||
items_label += allowed_items_label
|
||||
label_tooltip = None
|
||||
if self._allowed_extensions:
|
||||
items_label += " of\n{}".format(
|
||||
", ".join(sorted(self._allowed_extensions))
|
||||
)
|
||||
|
||||
if self._extensions_label:
|
||||
label_tooltip = items_label
|
||||
items_label = self._extensions_label
|
||||
|
||||
if self._items_label_widget.text() == items_label:
|
||||
return
|
||||
|
||||
self._items_label_widget.setToolTip(label_tooltip)
|
||||
self._items_label_widget.setText(items_label)
|
||||
self._update_size_timer.start()
|
||||
|
||||
def resizeEvent(self, event):
|
||||
super(DropEmpty, self).resizeEvent(event)
|
||||
self._update_size_timer.start()
|
||||
|
||||
def _on_update_size_timer(self):
|
||||
"""Recalculate height of label with extensions.
|
||||
|
||||
Dynamic QLabel with word wrap does not handle properly it's sizeHint
|
||||
calculations on show. This way it is recalculated. It is good practice
|
||||
to trigger this method with small offset using '_update_size_timer'.
|
||||
"""
|
||||
|
||||
width = self._items_label_widget.width()
|
||||
height = self._items_label_widget.heightForWidth(width)
|
||||
self._items_label_widget.setMinimumHeight(height)
|
||||
self._items_label_widget.updateGeometry()
|
||||
|
||||
def paintEvent(self, event):
|
||||
super(DropEmpty, self).paintEvent(event)
|
||||
|
|
@ -162,6 +225,7 @@ class FilesModel(QtGui.QStandardItemModel):
|
|||
def __init__(self, single_item, allow_sequences):
|
||||
super(FilesModel, self).__init__()
|
||||
|
||||
self._id = str(uuid.uuid4())
|
||||
self._single_item = single_item
|
||||
self._multivalue = False
|
||||
self._allow_sequences = allow_sequences
|
||||
|
|
@ -171,6 +235,10 @@ class FilesModel(QtGui.QStandardItemModel):
|
|||
self._filenames_by_dirpath = collections.defaultdict(set)
|
||||
self._items_by_dirpath = collections.defaultdict(list)
|
||||
|
||||
@property
|
||||
def id(self):
|
||||
return self._id
|
||||
|
||||
def set_multivalue(self, multivalue):
|
||||
"""Disable filtering."""
|
||||
|
||||
|
|
@ -245,6 +313,66 @@ class FilesModel(QtGui.QStandardItemModel):
|
|||
|
||||
return item_id, item
|
||||
|
||||
def mimeData(self, indexes):
|
||||
item_ids = [
|
||||
index.data(ITEM_ID_ROLE)
|
||||
for index in indexes
|
||||
]
|
||||
|
||||
item_ids_data = convert_data_to_bytes(item_ids)
|
||||
mime_data = super(FilesModel, self).mimeData(indexes)
|
||||
mime_data.setData("files_widget/internal_move", item_ids_data)
|
||||
|
||||
file_items = []
|
||||
for item_id in item_ids:
|
||||
file_item = self.get_file_item_by_id(item_id)
|
||||
if file_item:
|
||||
file_items.append(file_item.to_dict())
|
||||
|
||||
full_item_data = convert_data_to_bytes({
|
||||
"items": file_items,
|
||||
"id": self._id
|
||||
})
|
||||
mime_data.setData("files_widget/full_data", full_item_data)
|
||||
return mime_data
|
||||
|
||||
def dropMimeData(self, mime_data, action, row, col, index):
|
||||
item_ids = convert_bytes_to_json(
|
||||
mime_data.data("files_widget/internal_move")
|
||||
)
|
||||
if item_ids is None:
|
||||
return False
|
||||
|
||||
# Find matching item after which will be items moved
|
||||
# - store item before moved items are removed
|
||||
root = self.invisibleRootItem()
|
||||
if row >= 0:
|
||||
src_item = self.item(row)
|
||||
else:
|
||||
src_item_id = index.data(ITEM_ID_ROLE)
|
||||
src_item = self._items_by_id.get(src_item_id)
|
||||
|
||||
# Take out items that should be moved
|
||||
items = []
|
||||
for item_id in item_ids:
|
||||
item = self._items_by_id.get(item_id)
|
||||
if item:
|
||||
self.takeRow(item.row())
|
||||
items.append(item)
|
||||
|
||||
# Skip if there are not items that can be moved
|
||||
if not items:
|
||||
return False
|
||||
|
||||
# Calculate row where items should be inserted
|
||||
if src_item:
|
||||
src_row = src_item.row()
|
||||
else:
|
||||
src_row = root.rowCount()
|
||||
|
||||
root.insertRow(src_row, items)
|
||||
return True
|
||||
|
||||
|
||||
class FilesProxyModel(QtCore.QSortFilterProxyModel):
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
|
@ -428,6 +556,9 @@ class FilesView(QtWidgets.QListView):
|
|||
QtWidgets.QAbstractItemView.ExtendedSelection
|
||||
)
|
||||
self.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
|
||||
self.setAcceptDrops(True)
|
||||
self.setDragEnabled(True)
|
||||
self.setDragDropMode(self.InternalMove)
|
||||
|
||||
remove_btn = InViewButton(self)
|
||||
pix_enabled = paint_image_with_color(
|
||||
|
|
@ -529,11 +660,13 @@ class FilesView(QtWidgets.QListView):
|
|||
class FilesWidget(QtWidgets.QFrame):
|
||||
value_changed = QtCore.Signal()
|
||||
|
||||
def __init__(self, single_item, allow_sequences, parent):
|
||||
def __init__(self, single_item, allow_sequences, extensions_label, parent):
|
||||
super(FilesWidget, self).__init__(parent)
|
||||
self.setAcceptDrops(True)
|
||||
|
||||
empty_widget = DropEmpty(single_item, allow_sequences, self)
|
||||
empty_widget = DropEmpty(
|
||||
single_item, allow_sequences, extensions_label, self
|
||||
)
|
||||
|
||||
files_model = FilesModel(single_item, allow_sequences)
|
||||
files_proxy_model = FilesProxyModel()
|
||||
|
|
@ -553,6 +686,7 @@ class FilesWidget(QtWidgets.QFrame):
|
|||
files_view.context_menu_requested.connect(
|
||||
self._on_context_menu_requested
|
||||
)
|
||||
|
||||
self._in_set_value = False
|
||||
self._single_item = single_item
|
||||
self._multivalue = False
|
||||
|
|
@ -637,8 +771,6 @@ class FilesWidget(QtWidgets.QFrame):
|
|||
)
|
||||
self._widgets_by_id[item_id] = widget
|
||||
|
||||
self._files_proxy_model.sort(0)
|
||||
|
||||
if not self._in_set_value:
|
||||
self.value_changed.emit()
|
||||
|
||||
|
|
@ -743,12 +875,22 @@ class FilesWidget(QtWidgets.QFrame):
|
|||
event.setDropAction(QtCore.Qt.CopyAction)
|
||||
event.accept()
|
||||
|
||||
full_data_value = mime_data.data("files_widget/full_data")
|
||||
if self._handle_full_data_drag(full_data_value):
|
||||
event.setDropAction(QtCore.Qt.CopyAction)
|
||||
event.accept()
|
||||
|
||||
def dragLeaveEvent(self, event):
|
||||
event.accept()
|
||||
|
||||
def dropEvent(self, event):
|
||||
if self._multivalue:
|
||||
return
|
||||
|
||||
mime_data = event.mimeData()
|
||||
if not self._multivalue and mime_data.hasUrls():
|
||||
if mime_data.hasUrls():
|
||||
event.accept()
|
||||
# event.setDropAction(QtCore.Qt.CopyAction)
|
||||
filepaths = []
|
||||
for url in mime_data.urls():
|
||||
filepath = url.toLocalFile()
|
||||
|
|
@ -759,7 +901,58 @@ class FilesWidget(QtWidgets.QFrame):
|
|||
filepaths = self._files_proxy_model.filter_valid_files(filepaths)
|
||||
if filepaths:
|
||||
self._add_filepaths(filepaths)
|
||||
event.accept()
|
||||
|
||||
if self._handle_full_data_drop(
|
||||
mime_data.data("files_widget/full_data")
|
||||
):
|
||||
event.setDropAction(QtCore.Qt.CopyAction)
|
||||
event.accept()
|
||||
|
||||
super(FilesWidget, self).dropEvent(event)
|
||||
|
||||
def _handle_full_data_drag(self, value):
|
||||
if value is None:
|
||||
return False
|
||||
|
||||
full_data = convert_bytes_to_json(value)
|
||||
if full_data is None:
|
||||
return False
|
||||
|
||||
if full_data["id"] == self._files_model.id:
|
||||
return False
|
||||
return True
|
||||
|
||||
def _handle_full_data_drop(self, value):
|
||||
if value is None:
|
||||
return False
|
||||
|
||||
full_data = convert_bytes_to_json(value)
|
||||
if full_data is None:
|
||||
return False
|
||||
|
||||
if full_data["id"] == self._files_model.id:
|
||||
return False
|
||||
|
||||
for item in full_data["items"]:
|
||||
filepaths = [
|
||||
os.path.join(item["directory"], filename)
|
||||
for filename in item["filenames"]
|
||||
]
|
||||
filepaths = self._files_proxy_model.filter_valid_files(filepaths)
|
||||
if filepaths:
|
||||
self._add_filepaths(filepaths)
|
||||
|
||||
if self._copy_modifiers_enabled():
|
||||
return False
|
||||
return True
|
||||
|
||||
def _copy_modifiers_enabled(self):
|
||||
if (
|
||||
QtWidgets.QApplication.keyboardModifiers()
|
||||
& QtCore.Qt.ControlModifier
|
||||
):
|
||||
return True
|
||||
return False
|
||||
|
||||
def _add_filepaths(self, filepaths):
|
||||
self._files_model.add_filepaths(filepaths)
|
||||
|
|
|
|||
|
|
@ -443,7 +443,10 @@ class UnknownAttrWidget(_BaseAttrDefWidget):
|
|||
class FileAttrWidget(_BaseAttrDefWidget):
|
||||
def _ui_init(self):
|
||||
input_widget = FilesWidget(
|
||||
self.attr_def.single_item, self.attr_def.allow_sequences, self
|
||||
self.attr_def.single_item,
|
||||
self.attr_def.allow_sequences,
|
||||
self.attr_def.extensions_label,
|
||||
self
|
||||
)
|
||||
|
||||
if self.attr_def.tooltip:
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
[tool.poetry]
|
||||
name = "OpenPype"
|
||||
version = "3.12.1-nightly.4" # OpenPype
|
||||
version = "3.12.1" # OpenPype
|
||||
description = "Open VFX and Animation pipeline with support."
|
||||
authors = ["OpenPype Team <info@openpype.io>"]
|
||||
license = "MIT License"
|
||||
|
|
|
|||
|
|
@ -28,6 +28,13 @@ if($arguments -eq "--no-submodule-update") {
|
|||
$disable_submodule_update=$true
|
||||
}
|
||||
|
||||
$current_dir = Get-Location
|
||||
$script_dir = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent
|
||||
$openpype_root = (Get-Item $script_dir).parent.FullName
|
||||
|
||||
# Install PSWriteColor to support colorized output to terminal
|
||||
$env:PSModulePath = $env:PSModulePath + ";$($openpype_root)\vendor\powershell"
|
||||
|
||||
function Start-Progress {
|
||||
param([ScriptBlock]$code)
|
||||
$scroll = "/-\|/-\|"
|
||||
|
|
@ -72,14 +79,18 @@ function Exit-WithCode($exitcode) {
|
|||
|
||||
function Show-PSWarning() {
|
||||
if ($PSVersionTable.PSVersion.Major -lt 7) {
|
||||
Write-Host "!!! " -NoNewline -ForegroundColor Red
|
||||
Write-Host "You are using old version of PowerShell. $($PSVersionTable.PSVersion.Major).$($PSVersionTable.PSVersion.Minor)"
|
||||
Write-Host "Please update to at least 7.0 - " -NoNewline -ForegroundColor Gray
|
||||
Write-Host "https://github.com/PowerShell/PowerShell/releases" -ForegroundColor White
|
||||
Write-Color -Text "!!! ", "You are using old version of PowerShell - ", "$($PSVersionTable.PSVersion.Major).$($PSVersionTable.PSVersion.Minor)" -Color Red, Yellow, White
|
||||
Write-Color -Text " Please update to at least 7.0 - ", "https://github.com/PowerShell/PowerShell/releases" -Color Yellow, White
|
||||
Exit-WithCode 1
|
||||
}
|
||||
}
|
||||
|
||||
function Install-Poetry() {
|
||||
Write-Color -Text ">>> ", "Installing Poetry ... " -Color Green, Gray
|
||||
$env:POETRY_HOME="$openpype_root\.poetry"
|
||||
(Invoke-WebRequest -Uri https://raw.githubusercontent.com/python-poetry/poetry/master/install-poetry.py -UseBasicParsing).Content | python -
|
||||
}
|
||||
|
||||
$art = @"
|
||||
|
||||
. . .. . ..
|
||||
|
|
@ -103,10 +114,6 @@ Write-Host $art -ForegroundColor DarkGreen
|
|||
# Enable if PS 7.x is needed.
|
||||
# Show-PSWarning
|
||||
|
||||
$current_dir = Get-Location
|
||||
$script_dir = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent
|
||||
$openpype_root = (Get-Item $script_dir).parent.FullName
|
||||
|
||||
$env:_INSIDE_OPENPYPE_TOOL = "1"
|
||||
|
||||
if (-not (Test-Path 'env:POETRY_HOME')) {
|
||||
|
|
@ -119,8 +126,7 @@ $version_file = Get-Content -Path "$($openpype_root)\openpype\version.py"
|
|||
$result = [regex]::Matches($version_file, '__version__ = "(?<version>\d+\.\d+.\d+.*)"')
|
||||
$openpype_version = $result[0].Groups['version'].Value
|
||||
if (-not $openpype_version) {
|
||||
Write-Host "!!! " -ForegroundColor yellow -NoNewline
|
||||
Write-Host "Cannot determine OpenPype version."
|
||||
Write-Color -Text "!!! ", "Cannot determine OpenPype version." -Color Yellow, Gray
|
||||
Exit-WithCode 1
|
||||
}
|
||||
|
||||
|
|
@ -129,75 +135,60 @@ if (-not (Test-Path -PathType Container -Path "$($openpype_root)\build")) {
|
|||
New-Item -ItemType Directory -Force -Path "$($openpype_root)\build"
|
||||
}
|
||||
|
||||
Write-Host "--- " -NoNewline -ForegroundColor yellow
|
||||
Write-Host "Cleaning build directory ..."
|
||||
Write-Color -Text "--- ", "Cleaning build directory ..." -Color Yellow, Gray
|
||||
try {
|
||||
Remove-Item -Recurse -Force "$($openpype_root)\build\*"
|
||||
}
|
||||
catch {
|
||||
Write-Host "!!! " -NoNewline -ForegroundColor Red
|
||||
Write-Host "Cannot clean build directory, possibly because process is using it."
|
||||
Write-Host $_.Exception.Message
|
||||
Write-Color -Text "!!! ", "Cannot clean build directory, possibly because process is using it." -Color Red, Gray
|
||||
Write-Color -Text $_.Exception.Message -Color Red
|
||||
Exit-WithCode 1
|
||||
}
|
||||
if (-not $disable_submodule_update) {
|
||||
Write-Host ">>> " -NoNewLine -ForegroundColor green
|
||||
Write-Host "Making sure submodules are up-to-date ..."
|
||||
git submodule update --init --recursive
|
||||
Write-Color -Text ">>> ", "Making sure submodules are up-to-date ..." -Color Green, Gray
|
||||
& git submodule update --init --recursive
|
||||
} else {
|
||||
Write-Host "*** " -NoNewLine -ForegroundColor yellow
|
||||
Write-Host "Not updating submodules ..."
|
||||
Write-Color -Text "*** ", "Not updating submodules ..." -Color Green, Gray
|
||||
}
|
||||
|
||||
Write-Host ">>> " -NoNewline -ForegroundColor green
|
||||
Write-Host "OpenPype [ " -NoNewline -ForegroundColor white
|
||||
Write-host $openpype_version -NoNewline -ForegroundColor green
|
||||
Write-Host " ]" -ForegroundColor white
|
||||
Write-Color -Text ">>> ", "OpenPype [ ", $openpype_version, " ]" -Color Green, White, Cyan, White
|
||||
|
||||
Write-Host ">>> " -NoNewline -ForegroundColor Green
|
||||
Write-Host "Reading Poetry ... " -NoNewline
|
||||
Write-Color -Text ">>> ", "Reading Poetry ... " -Color Green, Gray -NoNewline
|
||||
if (-not (Test-Path -PathType Container -Path "$($env:POETRY_HOME)\bin")) {
|
||||
Write-Host "NOT FOUND" -ForegroundColor Yellow
|
||||
Write-Host "*** " -NoNewline -ForegroundColor Yellow
|
||||
Write-Host "We need to install Poetry create virtual env first ..."
|
||||
Write-Color -Text "NOT FOUND" -Color Yellow
|
||||
Write-Color -Text "*** ", "We need to install Poetry create virtual env first ..." -Color Yellow, Gray
|
||||
& "$openpype_root\tools\create_env.ps1"
|
||||
} else {
|
||||
Write-Host "OK" -ForegroundColor Green
|
||||
Write-Color -Text "OK" -Color Green
|
||||
}
|
||||
|
||||
Write-Host ">>> " -NoNewline -ForegroundColor green
|
||||
Write-Host "Cleaning cache files ... " -NoNewline
|
||||
Write-Color -Text ">>> ", "Cleaning cache files ... " -Color Green, Gray -NoNewline
|
||||
Get-ChildItem $openpype_root -Filter "*.pyc" -Force -Recurse | Where-Object { $_.FullName -inotmatch 'build' } | Remove-Item -Force
|
||||
Get-ChildItem $openpype_root -Filter "*.pyo" -Force -Recurse | Where-Object { $_.FullName -inotmatch 'build' } | Remove-Item -Force
|
||||
Get-ChildItem $openpype_root -Filter "__pycache__" -Force -Recurse | Where-Object { $_.FullName -inotmatch 'build' } | Remove-Item -Force -Recurse
|
||||
Write-Host "OK" -ForegroundColor green
|
||||
Write-Color -Text "OK" -Color green
|
||||
|
||||
Write-Host ">>> " -NoNewline -ForegroundColor green
|
||||
Write-Host "Building OpenPype ..."
|
||||
Write-Color -Text ">>> ", "Building OpenPype ..." -Color Green, White
|
||||
$startTime = [int][double]::Parse((Get-Date -UFormat %s))
|
||||
|
||||
$out = & "$($env:POETRY_HOME)\bin\poetry" run python setup.py build 2>&1
|
||||
Set-Content -Path "$($openpype_root)\build\build.log" -Value $out
|
||||
if ($LASTEXITCODE -ne 0)
|
||||
{
|
||||
Write-Host "------------------------------------------" -ForegroundColor Red
|
||||
Write-Color -Text "------------------------------------------" -Color Red
|
||||
Get-Content "$($openpype_root)\build\build.log"
|
||||
Write-Host "------------------------------------------" -ForegroundColor Red
|
||||
Write-Host "!!! " -NoNewLine -ForegroundColor Red
|
||||
Write-Host "Build failed. Check the log: " -NoNewline
|
||||
Write-Host ".\build\build.log" -ForegroundColor Yellow
|
||||
Write-Color -Text "------------------------------------------" -Color Yellow
|
||||
Write-Color -Text "!!! ", "Build failed. Check the log: ", ".\build\build.log" -Color Red, Yellow, White
|
||||
Exit-WithCode $LASTEXITCODE
|
||||
}
|
||||
|
||||
Set-Content -Path "$($openpype_root)\build\build.log" -Value $out
|
||||
& "$($env:POETRY_HOME)\bin\poetry" run python "$($openpype_root)\tools\build_dependencies.py"
|
||||
|
||||
Write-Host ">>> " -NoNewline -ForegroundColor green
|
||||
Write-Host "restoring current directory"
|
||||
Write-Color -Text ">>> ", "Restoring current directory" -Color Green, Gray
|
||||
Set-Location -Path $current_dir
|
||||
|
||||
$endTime = [int][double]::Parse((Get-Date -UFormat %s))
|
||||
Write-Host "*** " -NoNewline -ForegroundColor Cyan
|
||||
Write-Host "All done in $($endTime - $startTime) secs. You will find OpenPype and build log in " -NoNewLine
|
||||
Write-Host "'.\build'" -NoNewline -ForegroundColor Green
|
||||
Write-Host " directory."
|
||||
New-BurntToastNotification -AppLogo "$openpype_root/openpype/resources/icons/openpype_icon.png" -Text "OpenPype build complete!", "All done in $($endTime - $startTime) secs. You will find OpenPype and build log in build directory."
|
||||
|
||||
Write-Color -Text "*** ", "All done in ", $($endTime - $startTime), " secs. You will find OpenPype and build log in ", "'.\build'", " directory." -Color Green, Gray, White, Gray, White, Gray
|
||||
|
|
|
|||
|
|
@ -11,6 +11,12 @@
|
|||
PS> .\build_win_installer.ps1
|
||||
|
||||
#>
|
||||
$current_dir = Get-Location
|
||||
$script_dir = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent
|
||||
$openpype_root = (Get-Item $script_dir).parent.FullName
|
||||
|
||||
# Install PSWriteColor to support colorized output to terminal
|
||||
$env:PSModulePath = $env:PSModulePath + ";$($openpype_root)\vendor\powershell"
|
||||
|
||||
function Start-Progress {
|
||||
param([ScriptBlock]$code)
|
||||
|
|
@ -44,7 +50,6 @@ function Start-Progress {
|
|||
#>
|
||||
}
|
||||
|
||||
|
||||
function Exit-WithCode($exitcode) {
|
||||
# Only exit this host process if it's a child of another PowerShell parent process...
|
||||
$parentPID = (Get-CimInstance -ClassName Win32_Process -Filter "ProcessId=$PID" | Select-Object -Property ParentProcessId).ParentProcessId
|
||||
|
|
@ -56,10 +61,8 @@ function Exit-WithCode($exitcode) {
|
|||
|
||||
function Show-PSWarning() {
|
||||
if ($PSVersionTable.PSVersion.Major -lt 7) {
|
||||
Write-Host "!!! " -NoNewline -ForegroundColor Red
|
||||
Write-Host "You are using old version of PowerShell. $($PSVersionTable.PSVersion.Major).$($PSVersionTable.PSVersion.Minor)"
|
||||
Write-Host "Please update to at least 7.0 - " -NoNewline -ForegroundColor Gray
|
||||
Write-Host "https://github.com/PowerShell/PowerShell/releases" -ForegroundColor White
|
||||
Write-Color -Text "!!! ", "You are using old version of PowerShell - ", "$($PSVersionTable.PSVersion.Major).$($PSVersionTable.PSVersion.Minor)" -Color Red, Yellow, White
|
||||
Write-Color -Text " Please update to at least 7.0 - ", "https://github.com/PowerShell/PowerShell/releases" -Color Yellow, White
|
||||
Exit-WithCode 1
|
||||
}
|
||||
}
|
||||
|
|
@ -87,9 +90,6 @@ Write-Host $art -ForegroundColor DarkGreen
|
|||
# Enable if PS 7.x is needed.
|
||||
# Show-PSWarning
|
||||
|
||||
$current_dir = Get-Location
|
||||
$script_dir = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent
|
||||
$openpype_root = (Get-Item $script_dir).parent.FullName
|
||||
|
||||
Set-Location -Path $openpype_root
|
||||
|
||||
|
|
@ -97,16 +97,15 @@ $version_file = Get-Content -Path "$($openpype_root)\openpype\version.py"
|
|||
$result = [regex]::Matches($version_file, '__version__ = "(?<version>\d+\.\d+.\d+.*)"')
|
||||
$openpype_version = $result[0].Groups['version'].Value
|
||||
if (-not $openpype_version) {
|
||||
Write-Host "!!! " -ForegroundColor yellow -NoNewline
|
||||
Write-Host "Cannot determine OpenPype version."
|
||||
Write-Color -Text "!!! ", "Cannot determine OpenPype version." -Color Yellow, Gray
|
||||
Exit-WithCode 1
|
||||
}
|
||||
|
||||
$env:BUILD_VERSION = $openpype_version
|
||||
|
||||
iscc
|
||||
|
||||
Write-Host ">>> " -NoNewline -ForegroundColor green
|
||||
Write-Host "Detecting host Python ... " -NoNewline
|
||||
Write-Color ">>> ", "Detecting host Python ... " -Color Green, White -NoNewline
|
||||
$python = "python"
|
||||
if (Get-Command "pyenv" -ErrorAction SilentlyContinue) {
|
||||
$pyenv_python = & pyenv which python
|
||||
|
|
@ -115,7 +114,7 @@ if (Get-Command "pyenv" -ErrorAction SilentlyContinue) {
|
|||
}
|
||||
}
|
||||
if (-not (Get-Command $python -ErrorAction SilentlyContinue)) {
|
||||
Write-Host "!!! Python not detected" -ForegroundColor red
|
||||
Write-Color "!!! ", "Python not detected" -Color Red, Yellow
|
||||
Set-Location -Path $current_dir
|
||||
Exit-WithCode 1
|
||||
}
|
||||
|
|
@ -128,7 +127,7 @@ $p = & $python -c $version_command
|
|||
$env:PYTHON_VERSION = $p
|
||||
$m = $p -match '(\d+)\.(\d+)'
|
||||
if(-not $m) {
|
||||
Write-Host "!!! Cannot determine version" -ForegroundColor red
|
||||
Write-Color "!!! ", "Cannot determine version" -Color Red, Yellow
|
||||
Set-Location -Path $current_dir
|
||||
Exit-WithCode 1
|
||||
}
|
||||
|
|
@ -145,8 +144,7 @@ if (($matches[1] -lt 3) -or ($matches[2] -lt 7)) {
|
|||
Write-Host "OK [ $p ]" -ForegroundColor green
|
||||
}
|
||||
|
||||
Write-Host ">>> " -NoNewline -ForegroundColor green
|
||||
Write-Host "Creating OpenPype installer ... " -ForegroundColor white
|
||||
Write-Color -Text ">>> ", "Creating OpenPype installer ... " -Color Green, White
|
||||
|
||||
$build_dir_command = @"
|
||||
import sys
|
||||
|
|
@ -155,24 +153,25 @@ print('exe.{}-{}'.format(get_platform(), sys.version[0:3]))
|
|||
"@
|
||||
|
||||
$build_dir = & $python -c $build_dir_command
|
||||
Write-Host "Build directory ... ${build_dir}" -ForegroundColor white
|
||||
Write-Color -Text "--- ", "Build directory ", "${build_dir}" -Color Green, Gray, White
|
||||
$env:BUILD_DIR = $build_dir
|
||||
|
||||
if (Get-Command iscc -errorAction SilentlyContinue -ErrorVariable ProcessError)
|
||||
{
|
||||
iscc "$openpype_root\inno_setup.iss"
|
||||
}else {
|
||||
Write-Host "!!! Cannot find Inno Setup command" -ForegroundColor red
|
||||
Write-Host "!!! You can download it at https://jrsoftware.org/" -ForegroundColor red
|
||||
if (-not (Get-Command iscc -errorAction SilentlyContinue -ErrorVariable ProcessError)) {
|
||||
Write-Color -Text "!!! ", "Cannot find Inno Setup command" -Color Red, Yellow
|
||||
Write-Color "!!! You can download it at https://jrsoftware.org/" -ForegroundColor red
|
||||
Exit-WithCode 1
|
||||
}
|
||||
|
||||
& iscc "$openpype_root\inno_setup.iss"
|
||||
|
||||
Write-Host ">>> " -NoNewline -ForegroundColor green
|
||||
Write-Host "restoring current directory"
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Color -Text "!!! ", "Creating installer failed." -Color Red, Yellow
|
||||
Exit-WithCode 1
|
||||
}
|
||||
|
||||
Write-Color -Text ">>> ", "Restoring current directory" -Color Green, Gray
|
||||
Set-Location -Path $current_dir
|
||||
|
||||
Write-Host "*** " -NoNewline -ForegroundColor Cyan
|
||||
Write-Host "All done. You will find OpenPype installer in " -NoNewLine
|
||||
Write-Host "'.\build'" -NoNewline -ForegroundColor Green
|
||||
Write-Host " directory."
|
||||
New-BurntToastNotification -AppLogo "$openpype_root/openpype/resources/icons/openpype_icon.png" -Text "OpenPype build complete!", "All done. You will find You will find OpenPype installer in '.\build' directory."
|
||||
|
||||
Write-Color -Text "*** ", "All done. You will find OpenPype installer in ", "'.\build'", " directory." -Color Green, Gray, White, Gray
|
||||
|
|
|
|||
|
|
@ -24,6 +24,15 @@ if($arguments -eq "--verbose") {
|
|||
$poetry_verbosity="-vvv"
|
||||
}
|
||||
|
||||
$current_dir = Get-Location
|
||||
$script_dir = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent
|
||||
$openpype_root = (Get-Item $script_dir).parent.FullName
|
||||
|
||||
& git submodule update --init --recursive
|
||||
# Install PSWriteColor to support colorized output to terminal
|
||||
$env:PSModulePath = $env:PSModulePath + ";$($openpype_root)\vendor\powershell"
|
||||
|
||||
|
||||
function Exit-WithCode($exitcode) {
|
||||
# Only exit this host process if it's a child of another PowerShell parent process...
|
||||
$parentPID = (Get-CimInstance -ClassName Win32_Process -Filter "ProcessId=$PID" | Select-Object -Property ParentProcessId).ParentProcessId
|
||||
|
|
@ -36,30 +45,26 @@ function Exit-WithCode($exitcode) {
|
|||
|
||||
function Show-PSWarning() {
|
||||
if ($PSVersionTable.PSVersion.Major -lt 7) {
|
||||
Write-Host "!!! " -NoNewline -ForegroundColor Red
|
||||
Write-Host "You are using old version of PowerShell. $($PSVersionTable.PSVersion.Major).$($PSVersionTable.PSVersion.Minor)"
|
||||
Write-Host "Please update to at least 7.0 - " -NoNewline -ForegroundColor Gray
|
||||
Write-Host "https://github.com/PowerShell/PowerShell/releases" -ForegroundColor White
|
||||
Write-Color -Text "!!! ", "You are using old version of PowerShell - ", "$($PSVersionTable.PSVersion.Major).$($PSVersionTable.PSVersion.Minor)" -Color Red, Yellow, White
|
||||
Write-Color -Text " Please update to at least 7.0 - ", "https://github.com/PowerShell/PowerShell/releases" -Color Yellow, White
|
||||
Exit-WithCode 1
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function Install-Poetry() {
|
||||
Write-Host ">>> " -NoNewline -ForegroundColor Green
|
||||
Write-Host "Installing Poetry ... "
|
||||
Write-Color -Text ">>> ", "Installing Poetry ... " -Color Green, Gray
|
||||
$python = "python"
|
||||
if (Get-Command "pyenv" -ErrorAction SilentlyContinue) {
|
||||
if (-not (Test-Path -PathType Leaf -Path "$($openpype_root)\.python-version")) {
|
||||
$result = & pyenv global
|
||||
if ($result -eq "no global version configured") {
|
||||
Write-Host "!!! " -NoNewline -ForegroundColor Red
|
||||
Write-Host "Using pyenv but having no local or global version of Python set."
|
||||
Write-Color -Text "!!! ", "Using pyenv but having no local or global version of Python set." -Color Red, Yellow
|
||||
Exit-WithCode 1
|
||||
}
|
||||
}
|
||||
$python = & pyenv which python
|
||||
|
||||
|
||||
}
|
||||
|
||||
$env:POETRY_HOME="$openpype_root\.poetry"
|
||||
|
|
@ -68,8 +73,7 @@ function Install-Poetry() {
|
|||
|
||||
|
||||
function Test-Python() {
|
||||
Write-Host ">>> " -NoNewline -ForegroundColor green
|
||||
Write-Host "Detecting host Python ... " -NoNewline
|
||||
Write-Color -Text ">>> ", "Detecting host Python ... " -Color Green, Gray -NoNewline
|
||||
$python = "python"
|
||||
if (Get-Command "pyenv" -ErrorAction SilentlyContinue) {
|
||||
$pyenv_python = & pyenv which python
|
||||
|
|
@ -97,22 +101,17 @@ print('{0}.{1}'.format(sys.version_info[0], sys.version_info[1]))
|
|||
}
|
||||
# We are supporting python 3.7 only
|
||||
if (($matches[1] -lt 3) -or ($matches[2] -lt 7)) {
|
||||
Write-Host "FAILED Version [ $p ] is old and unsupported" -ForegroundColor red
|
||||
Write-Color -Text "FAILED ", "Version ", "[", $p ,"]", "is old and unsupported" -Color Red, Yellow, Cyan, White, Cyan, Yellow
|
||||
Set-Location -Path $current_dir
|
||||
Exit-WithCode 1
|
||||
} elseif (($matches[1] -eq 3) -and ($matches[2] -gt 7)) {
|
||||
Write-Host "WARNING Version [ $p ] is unsupported, use at your own risk." -ForegroundColor yellow
|
||||
Write-Host "*** " -NoNewline -ForegroundColor yellow
|
||||
Write-Host "OpenPype supports only Python 3.7" -ForegroundColor white
|
||||
Write-Color -Text "WARNING Version ", "[", $p, "]", " is unsupported, use at your own risk." -Color Yellow, Cyan, White, Cyan, Yellow
|
||||
Write-Color -Text "*** ", "OpenPype supports only Python 3.7" -Color Yellow, White
|
||||
} else {
|
||||
Write-Host "OK [ $p ]" -ForegroundColor green
|
||||
Write-Color "OK ", "[", $p, "]" -Color Green, Cyan, White, Cyan
|
||||
}
|
||||
}
|
||||
|
||||
$current_dir = Get-Location
|
||||
$script_dir = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent
|
||||
$openpype_root = (Get-Item $script_dir).parent.FullName
|
||||
|
||||
if (-not (Test-Path 'env:POETRY_HOME')) {
|
||||
$env:POETRY_HOME = "$openpype_root\.poetry"
|
||||
}
|
||||
|
|
@ -150,41 +149,38 @@ $version_file = Get-Content -Path "$($openpype_root)\openpype\version.py"
|
|||
$result = [regex]::Matches($version_file, '__version__ = "(?<version>\d+\.\d+.\d+.*)"')
|
||||
$openpype_version = $result[0].Groups['version'].Value
|
||||
if (-not $openpype_version) {
|
||||
Write-Host "!!! " -ForegroundColor yellow -NoNewline
|
||||
Write-Host "Cannot determine OpenPype version."
|
||||
Write-Color -Text "!!! ", "Cannot determine OpenPype version." -Color Red, Yellow
|
||||
Set-Location -Path $current_dir
|
||||
Exit-WithCode 1
|
||||
}
|
||||
Write-Host ">>> " -NoNewline -ForegroundColor Green
|
||||
Write-Host "Found OpenPype version " -NoNewline
|
||||
Write-Host "[ $($openpype_version) ]" -ForegroundColor Green
|
||||
Write-Color -Text ">>> ", "Found OpenPype version ", "[ ", $($openpype_version), " ]" -Color Green, Gray, Cyan, White, Cyan
|
||||
|
||||
Test-Python
|
||||
|
||||
Write-Host ">>> " -NoNewline -ForegroundColor Green
|
||||
Write-Host "Reading Poetry ... " -NoNewline
|
||||
Write-Color -Text ">>> ", "Reading Poetry ... " -Color Green, Gray -NoNewline
|
||||
if (-not (Test-Path -PathType Container -Path "$($env:POETRY_HOME)\bin")) {
|
||||
Write-Host "NOT FOUND" -ForegroundColor Yellow
|
||||
Write-Color -Text "NOT FOUND" -Color Yellow
|
||||
Install-Poetry
|
||||
Write-Host "INSTALLED" -ForegroundColor Cyan
|
||||
Write-Color -Text "INSTALLED" -Color Cyan
|
||||
} else {
|
||||
Write-Host "OK" -ForegroundColor Green
|
||||
Write-Color -Text "OK" -Color Green
|
||||
}
|
||||
|
||||
if (-not (Test-Path -PathType Leaf -Path "$($openpype_root)\poetry.lock")) {
|
||||
Write-Host ">>> " -NoNewline -ForegroundColor green
|
||||
Write-Host "Installing virtual environment and creating lock."
|
||||
Write-Color -Text ">>> ", "Installing virtual environment and creating lock." -Color Green, Gray
|
||||
} else {
|
||||
Write-Host ">>> " -NoNewline -ForegroundColor green
|
||||
Write-Host "Installing virtual environment from lock."
|
||||
Write-Color -Text ">>> ", "Installing virtual environment from lock." -Color Green, Gray
|
||||
}
|
||||
$startTime = [int][double]::Parse((Get-Date -UFormat %s))
|
||||
& "$env:POETRY_HOME\bin\poetry" install --no-root $poetry_verbosity --ansi
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Host "!!! " -ForegroundColor yellow -NoNewline
|
||||
Write-Host "Poetry command failed."
|
||||
Write-Color -Text "!!! ", "Poetry command failed." -Color Red, Yellow
|
||||
Set-Location -Path $current_dir
|
||||
Exit-WithCode 1
|
||||
}
|
||||
$endTime = [int][double]::Parse((Get-Date -UFormat %s))
|
||||
Set-Location -Path $current_dir
|
||||
Write-Host ">>> " -NoNewline -ForegroundColor green
|
||||
Write-Host "Virtual environment created."
|
||||
|
||||
New-BurntToastNotification -AppLogo "$openpype_root/openpype/resources/icons/openpype_icon.png" -Text "OpenPype", "Virtual environment created.", "All done in $($endTime - $startTime) secs."
|
||||
|
||||
Write-Color -Text ">>> ", "Virtual environment created." -Color Green, White
|
||||
|
|
|
|||
|
|
@ -19,6 +19,13 @@ PS> .\create_zip.ps1 --path C:\OpenPype
|
|||
|
||||
#>
|
||||
|
||||
$current_dir = Get-Location
|
||||
$script_dir = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent
|
||||
$openpype_root = (Get-Item $script_dir).parent.FullName
|
||||
|
||||
# Install PSWriteColor to support colorized output to terminal
|
||||
$env:PSModulePath = $env:PSModulePath + ";$($openpype_root)\vendor\powershell"
|
||||
|
||||
function Exit-WithCode($exitcode) {
|
||||
# Only exit this host process if it's a child of another PowerShell parent process...
|
||||
$parentPID = (Get-CimInstance -ClassName Win32_Process -Filter "ProcessId=$PID" | Select-Object -Property ParentProcessId).ParentProcessId
|
||||
|
|
@ -31,18 +38,12 @@ function Exit-WithCode($exitcode) {
|
|||
|
||||
function Show-PSWarning() {
|
||||
if ($PSVersionTable.PSVersion.Major -lt 7) {
|
||||
Write-Host "!!! " -NoNewline -ForegroundColor Red
|
||||
Write-Host "You are using old version of PowerShell. $($PSVersionTable.PSVersion.Major).$($PSVersionTable.PSVersion.Minor)"
|
||||
Write-Host "Please update to at least 7.0 - " -NoNewline -ForegroundColor Gray
|
||||
Write-Host "https://github.com/PowerShell/PowerShell/releases" -ForegroundColor White
|
||||
Write-Color -Text "!!! ", "You are using old version of PowerShell - ", "$($PSVersionTable.PSVersion.Major).$($PSVersionTable.PSVersion.Minor)" -Color Red, Yellow, White
|
||||
Write-Color -Text " Please update to at least 7.0 - ", "https://github.com/PowerShell/PowerShell/releases" -Color Yellow, White
|
||||
Exit-WithCode 1
|
||||
}
|
||||
}
|
||||
|
||||
$current_dir = Get-Location
|
||||
$script_dir = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent
|
||||
$openpype_root = (Get-Item $script_dir).parent.FullName
|
||||
|
||||
$env:_INSIDE_OPENPYPE_TOOL = "1"
|
||||
|
||||
if (-not (Test-Path 'env:POETRY_HOME')) {
|
||||
|
|
@ -78,31 +79,25 @@ $version_file = Get-Content -Path "$($openpype_root)\openpype\version.py"
|
|||
$result = [regex]::Matches($version_file, '__version__ = "(?<version>\d+\.\d+.\d+.*)"')
|
||||
$openpype_version = $result[0].Groups['version'].Value
|
||||
if (-not $openpype_version) {
|
||||
Write-Host "!!! " -ForegroundColor yellow -NoNewline
|
||||
Write-Host "Cannot determine OpenPype version."
|
||||
Write-Color -Text "!!! ", "Cannot determine OpenPype version." -Color Yellow, Gray
|
||||
Exit-WithCode 1
|
||||
}
|
||||
|
||||
Write-Host ">>> " -NoNewline -ForegroundColor Green
|
||||
Write-Host "Reading Poetry ... " -NoNewline
|
||||
Write-Color -Text ">>> ", "Reading Poetry ... " -Color Green, Gray -NoNewline
|
||||
if (-not (Test-Path -PathType Container -Path "$($env:POETRY_HOME)\bin")) {
|
||||
Write-Host "NOT FOUND" -ForegroundColor Yellow
|
||||
Write-Host "*** " -NoNewline -ForegroundColor Yellow
|
||||
Write-Host "We need to install Poetry create virtual env first ..."
|
||||
Write-Color -Text "NOT FOUND" -Color Yellow
|
||||
Write-Color -Text "*** ", "We need to install Poetry create virtual env first ..." -Color Yellow, Gray
|
||||
& "$openpype_root\tools\create_env.ps1"
|
||||
} else {
|
||||
Write-Host "OK" -ForegroundColor Green
|
||||
Write-Color -Text "OK" -Color Green
|
||||
}
|
||||
|
||||
Write-Host ">>> " -NoNewline -ForegroundColor green
|
||||
Write-Host "Cleaning cache files ... " -NoNewline
|
||||
Write-Color -Text ">>> ", "Cleaning cache files ... " -Color Green, Gray -NoNewline
|
||||
Get-ChildItem $openpype_root -Filter "__pycache__" -Force -Recurse| Where-Object {( $_.FullName -inotmatch '\\build\\' ) -and ( $_.FullName -inotmatch '\\.venv' )} | Remove-Item -Force -Recurse
|
||||
Get-ChildItem $openpype_root -Filter "*.pyc" -Force -Recurse | Where-Object {( $_.FullName -inotmatch '\\build\\' ) -and ( $_.FullName -inotmatch '\\.venv' )} | Remove-Item -Force
|
||||
Get-ChildItem $openpype_root -Filter "*.pyo" -Force -Recurse | Where-Object {( $_.FullName -inotmatch '\\build\\' ) -and ( $_.FullName -inotmatch '\\.venv' )} | Remove-Item -Force
|
||||
Write-Host "OK" -ForegroundColor green
|
||||
|
||||
Write-Host ">>> " -NoNewline -ForegroundColor green
|
||||
Write-Host "Generating zip from current sources ..."
|
||||
Write-Color -Text ">>> ", "Generating zip from current sources ..." -Color Green, Gray
|
||||
$env:PYTHONPATH="$($openpype_root);$($env:PYTHONPATH)"
|
||||
$env:OPENPYPE_ROOT="$($openpype_root)"
|
||||
& "$($env:POETRY_HOME)\bin\poetry" run python "$($openpype_root)\tools\create_zip.py" $ARGS
|
||||
|
|
|
|||
|
|
@ -15,6 +15,9 @@ $current_dir = Get-Location
|
|||
$script_dir = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent
|
||||
$openpype_root = (Get-Item $script_dir).parent.FullName
|
||||
|
||||
# Install PSWriteColor to support colorized output to terminal
|
||||
$env:PSModulePath = $env:PSModulePath + ";$($openpype_root)\vendor\powershell"
|
||||
|
||||
$env:_INSIDE_OPENPYPE_TOOL = "1"
|
||||
|
||||
if (-not (Test-Path 'env:POETRY_HOME')) {
|
||||
|
|
@ -23,16 +26,16 @@ if (-not (Test-Path 'env:POETRY_HOME')) {
|
|||
|
||||
Set-Location -Path $openpype_root
|
||||
|
||||
Write-Host ">>> " -NoNewline -ForegroundColor Green
|
||||
Write-Host "Reading Poetry ... " -NoNewline
|
||||
Write-Color -Text ">>> ", "Reading Poetry ... " -Color Green, Gray -NoNewline
|
||||
if (-not (Test-Path -PathType Container -Path "$($env:POETRY_HOME)\bin")) {
|
||||
Write-Host "NOT FOUND" -ForegroundColor Yellow
|
||||
Write-Host "*** " -NoNewline -ForegroundColor Yellow
|
||||
Write-Host "We need to install Poetry create virtual env first ..."
|
||||
Write-Color -Text "NOT FOUND" -Color Yellow
|
||||
Write-Color -Text "*** ", "We need to install Poetry create virtual env first ..." -Color Yellow, Gray
|
||||
& "$openpype_root\tools\create_env.ps1"
|
||||
} else {
|
||||
Write-Host "OK" -ForegroundColor Green
|
||||
Write-Color -Text "OK" -Color Green
|
||||
}
|
||||
|
||||
$startTime = [int][double]::Parse((Get-Date -UFormat %s))
|
||||
& "$($env:POETRY_HOME)\bin\poetry" run python "$($openpype_root)\tools\fetch_thirdparty_libs.py"
|
||||
$endTime = [int][double]::Parse((Get-Date -UFormat %s))
|
||||
Set-Location -Path $current_dir
|
||||
New-BurntToastNotification -AppLogo "$openpype_root/openpype/resources/icons/openpype_icon.png" -Text "OpenPype", "Dependencies downloaded", "All done in $($endTime - $startTime) secs."
|
||||
|
|
|
|||
|
|
@ -44,27 +44,30 @@ $art = @"
|
|||
|
||||
"@
|
||||
|
||||
$current_dir = Get-Location
|
||||
$script_dir = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent
|
||||
$openpype_root = (Get-Item $script_dir).parent.FullName
|
||||
|
||||
# Install PSWriteColor to support colorized output to terminal
|
||||
$env:PSModulePath = $env:PSModulePath + ";$($openpype_root)\vendor\powershell"
|
||||
|
||||
Write-Host $art -ForegroundColor DarkGreen
|
||||
|
||||
Write-Host ">>> " -NoNewline -ForegroundColor Green
|
||||
Write-Host "Reading Poetry ... " -NoNewline
|
||||
Write-Color -Text ">>> ", "Reading Poetry ... " -Color Green, Gray -NoNewline
|
||||
if (-not (Test-Path -PathType Container -Path "$($env:POETRY_HOME)\bin")) {
|
||||
Write-Host "NOT FOUND" -ForegroundColor Yellow
|
||||
Write-Host "*** " -NoNewline -ForegroundColor Yellow
|
||||
Write-Host "We need to install Poetry create virtual env first ..."
|
||||
& "$openpype_root\tools\create_env.ps1"
|
||||
Write-Color -Text "NOT FOUND" -Color Yellow
|
||||
Install-Poetry
|
||||
Write-Color -Text "INSTALLED" -Color Cyan
|
||||
} else {
|
||||
Write-Host "OK" -ForegroundColor Green
|
||||
Write-Color -Text "OK" -Color Green
|
||||
}
|
||||
|
||||
Write-Host "This will not overwrite existing source rst files, only scan and add new."
|
||||
Write-Color -Text "... ", "This will not overwrite existing source rst files, only scan and add new." -Color Yellow, Gray
|
||||
Set-Location -Path $openpype_root
|
||||
Write-Host ">>> " -NoNewline -ForegroundColor green
|
||||
Write-Host "Running apidoc ..."
|
||||
Write-Color -Text ">>> ", "Running apidoc ..." -Color Green, Gray
|
||||
& "$env:POETRY_HOME\bin\poetry" run sphinx-apidoc -M -e -d 10 --ext-intersphinx --ext-todo --ext-coverage --ext-viewcode -o "$($openpype_root)\docs\source" igniter
|
||||
& "$env:POETRY_HOME\bin\poetry" run sphinx-apidoc.exe -M -e -d 10 --ext-intersphinx --ext-todo --ext-coverage --ext-viewcode -o "$($openpype_root)\docs\source" openpype vendor, openpype\vendor
|
||||
|
||||
Write-Host ">>> " -NoNewline -ForegroundColor green
|
||||
Write-Host "Building html ..."
|
||||
Write-Color -Text ">>> ", "Building html ..." -Color Green, Gray
|
||||
& "$env:POETRY_HOME\bin\poetry" run python "$($openpype_root)\setup.py" build_sphinx
|
||||
Set-Location -Path $current_dir
|
||||
|
|
|
|||
|
|
@ -11,6 +11,13 @@ PS> .\run_mongo.ps1
|
|||
|
||||
#>
|
||||
|
||||
$current_dir = Get-Location
|
||||
$script_dir = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent
|
||||
$openpype_root = (Get-Item $script_dir).parent.FullName
|
||||
|
||||
# Install PSWriteColor to support colorized output to terminal
|
||||
$env:PSModulePath = $env:PSModulePath + ";$($openpype_root)\vendor\powershell"
|
||||
|
||||
$art = @"
|
||||
|
||||
. . .. . ..
|
||||
|
|
@ -43,8 +50,7 @@ function Exit-WithCode($exitcode) {
|
|||
|
||||
function Find-Mongo ($preferred_version) {
|
||||
$defaultPath = "C:\Program Files\MongoDB\Server"
|
||||
Write-Host ">>> " -NoNewLine -ForegroundColor Green
|
||||
Write-Host "Detecting MongoDB ... " -NoNewline
|
||||
Write-Color -Text ">>> ", "Detecting MongoDB ... " -Color Geen, Gray -NoNewline
|
||||
if (-not (Get-Command "mongod" -ErrorAction SilentlyContinue)) {
|
||||
if(Test-Path "$($defaultPath)\*\bin\mongod.exe" -PathType Leaf) {
|
||||
# we have mongo server installed on standard Windows location
|
||||
|
|
@ -52,17 +58,14 @@ function Find-Mongo ($preferred_version) {
|
|||
# $preferred_version.
|
||||
$mongoVersions = Get-ChildItem -Directory 'C:\Program Files\MongoDB\Server' | Sort-Object -Property {$_.Name -as [int]}
|
||||
if(Test-Path "$($mongoVersions[-1])\bin\mongod.exe" -PathType Leaf) {
|
||||
Write-Host "OK" -ForegroundColor Green
|
||||
Write-Color -Text "OK" -Color Green
|
||||
$use_version = $mongoVersions[-1]
|
||||
foreach ($v in $mongoVersions) {
|
||||
Write-Host " - found [ " -NoNewline
|
||||
Write-Host $v -NoNewLine -ForegroundColor Cyan
|
||||
Write-Host " ]" -NoNewLine
|
||||
|
||||
Write-Color -Text " - found [ ", $v, " ]" - Color Cyan, White, Cyan -NoNewLine
|
||||
$version = Split-Path $v -Leaf
|
||||
|
||||
if ($preferred_version -eq $version) {
|
||||
Write-Host " *" -ForegroundColor Green
|
||||
Write-Color -Text " *" -Color Green
|
||||
$use_version = $v
|
||||
} else {
|
||||
Write-Host ""
|
||||
|
|
@ -71,27 +74,20 @@ function Find-Mongo ($preferred_version) {
|
|||
|
||||
$env:PATH = "$($env:PATH);$($use_version)\bin\"
|
||||
|
||||
Write-Host " - auto-added from [ " -NoNewline
|
||||
Write-Host "$($use_version)\bin\mongod.exe" -NoNewLine -ForegroundColor Cyan
|
||||
Write-Host " ]"
|
||||
Write-Color -Text " - auto-added from [ ", "$($use_version)\bin\mongod.exe", " ]" -Color Cyan, White, Cyan
|
||||
return "$($use_version)\bin\mongod.exe"
|
||||
} else {
|
||||
Write-Host "FAILED " -NoNewLine -ForegroundColor Red
|
||||
Write-Host "MongoDB not detected" -ForegroundColor Yellow
|
||||
Write-Host "Tried to find it on standard location " -NoNewline -ForegroundColor Gray
|
||||
Write-Host " [ " -NoNewline -ForegroundColor Cyan
|
||||
Write-Host "$($mongoVersions[-1])\bin\mongod.exe" -NoNewline -ForegroundColor White
|
||||
Write-Host " ] " -NoNewLine -ForegroundColor Cyan
|
||||
Write-Host "but failed." -ForegroundColor Gray
|
||||
Write-Color -Text "FAILED " -Color Red -NoNewLine
|
||||
Write-Color -Text "MongoDB not detected" -Color Yellow
|
||||
Write-Color -Text "Tried to find it on standard location ", "[ ", "$($mongoVersions[-1])\bin\mongod.exe", " ]", " but failed." -Color Gray, Cyan, White, Cyan, Gray -NoNewline
|
||||
Exit-WithCode 1
|
||||
}
|
||||
} else {
|
||||
Write-Host "FAILED " -NoNewLine -ForegroundColor Red
|
||||
Write-Host "MongoDB not detected in PATH" -ForegroundColor Yellow
|
||||
Write-Color -Text "FAILED ", "MongoDB not detected in PATH" -Color Red, Yellow
|
||||
Exit-WithCode 1
|
||||
}
|
||||
} else {
|
||||
Write-Host "OK" -ForegroundColor Green
|
||||
Write-Color -Text "OK" -Color Green
|
||||
return Get-Command "mongod" -ErrorAction SilentlyContinue
|
||||
}
|
||||
<#
|
||||
|
|
@ -104,9 +100,6 @@ function Find-Mongo ($preferred_version) {
|
|||
#>
|
||||
}
|
||||
|
||||
$script_dir = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent
|
||||
$openpype_root = (Get-Item $script_dir).parent.FullName
|
||||
|
||||
# mongodb port
|
||||
$port = 2707
|
||||
|
||||
|
|
@ -116,15 +109,7 @@ $dbpath = (Get-Item $openpype_root).parent.FullName + "\mongo_db_data"
|
|||
$preferred_version = "5.0"
|
||||
|
||||
$mongoPath = Find-Mongo $preferred_version
|
||||
Write-Host ">>> " -NoNewLine -ForegroundColor Green
|
||||
Write-Host "Using DB path: " -NoNewLine
|
||||
Write-Host " [ " -NoNewline -ForegroundColor Cyan
|
||||
Write-Host "$($dbpath)" -NoNewline -ForegroundColor White
|
||||
Write-Host " ] "-ForegroundColor Cyan
|
||||
Write-Host ">>> " -NoNewLine -ForegroundColor Green
|
||||
Write-Host "Port: " -NoNewLine
|
||||
Write-Host " [ " -NoNewline -ForegroundColor Cyan
|
||||
Write-Host "$($port)" -NoNewline -ForegroundColor White
|
||||
Write-Host " ] " -ForegroundColor Cyan
|
||||
Start-Process -FilePath $mongopath "--dbpath $($dbpath) --port $($port)" -PassThru | Out-Null
|
||||
Write-Color -Text ">>> ", "Using DB path: ", "[ ", "$($dbpath)", " ]" -Color Green, Gray, Cyan, White, Cyan
|
||||
Write-Color -Text ">>> ", "Port: ", "[ ", "$($port)", " ]", -Color Green, Gray, Cyan, White, Cyan
|
||||
|
||||
Start-Process -FilePath $mongopath "--dbpath $($dbpath) --port $($port)" -PassThru | Out-Null
|
||||
|
|
|
|||
|
|
@ -35,6 +35,9 @@ $current_dir = Get-Location
|
|||
$script_dir = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent
|
||||
$openpype_root = (Get-Item $script_dir).parent.FullName
|
||||
|
||||
# Install PSWriteColor to support colorized output to terminal
|
||||
$env:PSModulePath = $env:PSModulePath + ";$($openpype_root)\vendor\powershell"
|
||||
|
||||
$env:_INSIDE_OPENPYPE_TOOL = "1"
|
||||
|
||||
# make sure Poetry is in PATH
|
||||
|
|
@ -45,15 +48,13 @@ $env:PATH = "$($env:PATH);$($env:POETRY_HOME)\bin"
|
|||
|
||||
Set-Location -Path $openpype_root
|
||||
|
||||
Write-Host ">>> " -NoNewline -ForegroundColor Green
|
||||
Write-Host "Reading Poetry ... " -NoNewline
|
||||
Write-Color -Text ">>> ", "Reading Poetry ... " -Color Green, Gray -NoNewline
|
||||
if (-not (Test-Path -PathType Container -Path "$($env:POETRY_HOME)\bin")) {
|
||||
Write-Host "NOT FOUND" -ForegroundColor Yellow
|
||||
Write-Host "*** " -NoNewline -ForegroundColor Yellow
|
||||
Write-Host "We need to install Poetry create virtual env first ..."
|
||||
& "$openpype_root\tools\create_env.ps1"
|
||||
Write-Color -Text "NOT FOUND" -Color Yellow
|
||||
Install-Poetry
|
||||
Write-Color -Text "INSTALLED" -Color Cyan
|
||||
} else {
|
||||
Write-Host "OK" -ForegroundColor Green
|
||||
Write-Color -Text "OK" -Color Green
|
||||
}
|
||||
|
||||
& "$env:POETRY_HOME\bin\poetry" run python "$($openpype_root)\start.py" projectmanager
|
||||
|
|
|
|||
|
|
@ -15,6 +15,9 @@ $current_dir = Get-Location
|
|||
$script_dir = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent
|
||||
$openpype_root = (Get-Item $script_dir).parent.FullName
|
||||
|
||||
# Install PSWriteColor to support colorized output to terminal
|
||||
$env:PSModulePath = $env:PSModulePath + ";$($openpype_root)\vendor\powershell"
|
||||
|
||||
$env:_INSIDE_OPENPYPE_TOOL = "1"
|
||||
|
||||
# make sure Poetry is in PATH
|
||||
|
|
@ -25,15 +28,13 @@ $env:PATH = "$($env:PATH);$($env:POETRY_HOME)\bin"
|
|||
|
||||
Set-Location -Path $openpype_root
|
||||
|
||||
Write-Host ">>> " -NoNewline -ForegroundColor Green
|
||||
Write-Host "Reading Poetry ... " -NoNewline
|
||||
Write-Color -Text ">>> ", "Reading Poetry ... " -Color Green, Gray -NoNewline
|
||||
if (-not (Test-Path -PathType Container -Path "$($env:POETRY_HOME)\bin")) {
|
||||
Write-Host "NOT FOUND" -ForegroundColor Yellow
|
||||
Write-Host "*** " -NoNewline -ForegroundColor Yellow
|
||||
Write-Host "We need to install Poetry create virtual env first ..."
|
||||
& "$openpype_root\tools\create_env.ps1"
|
||||
Write-Color -Text "NOT FOUND" -Color Yellow
|
||||
Install-Poetry
|
||||
Write-Color -Text "INSTALLED" -Color Cyan
|
||||
} else {
|
||||
Write-Host "OK" -ForegroundColor Green
|
||||
Write-Color -Text "OK" -Color Green
|
||||
}
|
||||
|
||||
& "$env:POETRY_HOME\bin\poetry" run python "$($openpype_root)\start.py" settings --dev
|
||||
|
|
|
|||
|
|
@ -11,6 +11,13 @@ PS> .\run_test.ps1
|
|||
|
||||
#>
|
||||
|
||||
$current_dir = Get-Location
|
||||
$script_dir = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent
|
||||
$openpype_root = (Get-Item $script_dir).parent.FullName
|
||||
|
||||
# Install PSWriteColor to support colorized output to terminal
|
||||
$env:PSModulePath = $env:PSModulePath + ";$($openpype_root)\vendor\powershell"
|
||||
|
||||
function Exit-WithCode($exitcode) {
|
||||
# Only exit this host process if it's a child of another PowerShell parent process...
|
||||
$parentPID = (Get-CimInstance -ClassName Win32_Process -Filter "ProcessId=$PID" | Select-Object -Property ParentProcessId).ParentProcessId
|
||||
|
|
@ -22,10 +29,8 @@ function Exit-WithCode($exitcode) {
|
|||
|
||||
function Show-PSWarning() {
|
||||
if ($PSVersionTable.PSVersion.Major -lt 7) {
|
||||
Write-Host "!!! " -NoNewline -ForegroundColor Red
|
||||
Write-Host "You are using old version of PowerShell. $($PSVersionTable.PSVersion.Major).$($PSVersionTable.PSVersion.Minor)"
|
||||
Write-Host "Please update to at least 7.0 - " -NoNewline -ForegroundColor Gray
|
||||
Write-Host "https://github.com/PowerShell/PowerShell/releases" -ForegroundColor White
|
||||
Write-Color -Text "!!! ", "You are using old version of PowerShell - ", "$($PSVersionTable.PSVersion.Major).$($PSVersionTable.PSVersion.Minor)" -Color Red, Yellow, White
|
||||
Write-Color -Text " Please update to at least 7.0 - ", "https://github.com/PowerShell/PowerShell/releases" -Color Yellow, White
|
||||
Exit-WithCode 1
|
||||
}
|
||||
}
|
||||
|
|
@ -53,10 +58,6 @@ Write-Host $art -ForegroundColor DarkGreen
|
|||
# Enable if PS 7.x is needed.
|
||||
# Show-PSWarning
|
||||
|
||||
$current_dir = Get-Location
|
||||
$script_dir = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent
|
||||
$openpype_root = (Get-Item $script_dir).parent.FullName
|
||||
|
||||
$env:_INSIDE_OPENPYPE_TOOL = "1"
|
||||
|
||||
if (-not (Test-Path 'env:POETRY_HOME')) {
|
||||
|
|
@ -69,46 +70,32 @@ $version_file = Get-Content -Path "$($openpype_root)\openpype\version.py"
|
|||
$result = [regex]::Matches($version_file, '__version__ = "(?<version>\d+\.\d+.\d+.*)"')
|
||||
$openpype_version = $result[0].Groups['version'].Value
|
||||
if (-not $openpype_version) {
|
||||
Write-Host "!!! " -ForegroundColor yellow -NoNewline
|
||||
Write-Host "Cannot determine OpenPype version."
|
||||
Write-Color -Text "!!! ", "Cannot determine OpenPype version." -Color Yellow, Gray
|
||||
Exit-WithCode 1
|
||||
}
|
||||
|
||||
Write-Host ">>> " -NoNewline -ForegroundColor green
|
||||
Write-Host "OpenPype [ " -NoNewline -ForegroundColor white
|
||||
Write-host $openpype_version -NoNewline -ForegroundColor green
|
||||
Write-Host " ] ..." -ForegroundColor white
|
||||
Write-Color -Text ">>> ", "OpenPype [ ", $openpype_version, " ]" -Color Green, White, Cyan, White
|
||||
|
||||
Write-Host ">>> " -NoNewline -ForegroundColor Green
|
||||
Write-Host "Reading Poetry ... " -NoNewline
|
||||
Write-Color -Text ">>> ", "Reading Poetry ... " -Color Green, Gray -NoNewline
|
||||
if (-not (Test-Path -PathType Container -Path "$($env:POETRY_HOME)\bin")) {
|
||||
Write-Host "NOT FOUND" -ForegroundColor Yellow
|
||||
Write-Host "*** " -NoNewline -ForegroundColor Yellow
|
||||
Write-Host "We need to install Poetry create virtual env first ..."
|
||||
Write-Color -Text "NOT FOUND" -Color Yellow
|
||||
Write-Color -Text "*** ", "We need to install Poetry create virtual env first ..." -Color Yellow, Gray
|
||||
& "$openpype_root\tools\create_env.ps1"
|
||||
} else {
|
||||
Write-Host "OK" -ForegroundColor Green
|
||||
Write-Color -Text "OK" -Color Green
|
||||
}
|
||||
|
||||
Write-Host ">>> " -NoNewline -ForegroundColor green
|
||||
Write-Host "Cleaning cache files ... " -NoNewline
|
||||
Write-Color -Text ">>> ", "Cleaning cache files ... " -Color Green, Gray -NoNewline
|
||||
Get-ChildItem $openpype_root -Filter "*.pyc" -Force -Recurse | Where-Object { $_.FullName -inotmatch 'build' } | Remove-Item -Force
|
||||
Get-ChildItem $openpype_root -Filter "*.pyo" -Force -Recurse | Where-Object { $_.FullName -inotmatch 'build' } | Remove-Item -Force
|
||||
Get-ChildItem $openpype_root -Filter "__pycache__" -Force -Recurse | Where-Object { $_.FullName -inotmatch 'build' } | Remove-Item -Force -Recurse
|
||||
Write-Host "OK" -ForegroundColor green
|
||||
Write-Color -Text "OK" -Color green
|
||||
|
||||
Write-Host ">>> " -NoNewline -ForegroundColor green
|
||||
Write-Host "Testing OpenPype ..."
|
||||
Write-Color -Text ">>> ", "Testing OpenPype ..." -Color Green, White
|
||||
$original_pythonpath = $env:PYTHONPATH
|
||||
$env:PYTHONPATH="$($openpype_root);$($env:PYTHONPATH)"
|
||||
& "$env:POETRY_HOME\bin\poetry" run pytest -x --capture=sys --print -W ignore::DeprecationWarning "$($openpype_root)/tests"
|
||||
$env:PYTHONPATH = $original_pythonpath
|
||||
|
||||
Write-Host ">>> " -NoNewline -ForegroundColor green
|
||||
Write-Host "restoring current directory"
|
||||
Write-Color -Text ">>> ", "Restoring current directory" -Color Green, Gray
|
||||
Set-Location -Path $current_dir
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,9 @@ $current_dir = Get-Location
|
|||
$script_dir = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent
|
||||
$openpype_root = (Get-Item $script_dir).parent.FullName
|
||||
|
||||
# Install PSWriteColor to support colorized output to terminal
|
||||
$env:PSModulePath = $env:PSModulePath + ";$($openpype_root)\vendor\powershell"
|
||||
|
||||
$env:_INSIDE_OPENPYPE_TOOL = "1"
|
||||
|
||||
# make sure Poetry is in PATH
|
||||
|
|
@ -24,15 +27,13 @@ $env:PATH = "$($env:PATH);$($env:POETRY_HOME)\bin"
|
|||
|
||||
Set-Location -Path $openpype_root
|
||||
|
||||
Write-Host ">>> " -NoNewline -ForegroundColor Green
|
||||
Write-Host "Reading Poetry ... " -NoNewline
|
||||
Write-Color -Text ">>> ", "Reading Poetry ... " -Color Green, Gray -NoNewline
|
||||
if (-not (Test-Path -PathType Container -Path "$($env:POETRY_HOME)\bin")) {
|
||||
Write-Host "NOT FOUND" -ForegroundColor Yellow
|
||||
Write-Host "*** " -NoNewline -ForegroundColor Yellow
|
||||
Write-Host "We need to install Poetry create virtual env first ..."
|
||||
Write-Color -Text "NOT FOUND" -Color Yellow
|
||||
Write-Color -Text "*** ", "We need to install Poetry create virtual env first ..." -Color Yellow, Gray
|
||||
& "$openpype_root\tools\create_env.ps1"
|
||||
} else {
|
||||
Write-Host "OK" -ForegroundColor Green
|
||||
Write-Color -Text "OK" -Color Green
|
||||
}
|
||||
|
||||
& "$($env:POETRY_HOME)\bin\poetry" run python "$($openpype_root)\start.py" tray --debug
|
||||
|
|
|
|||
1
vendor/powershell/BurntToast
vendored
Submodule
1
vendor/powershell/BurntToast
vendored
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit ae0acdd870a2fd8d9f0d147de22dc36d6c5e399e
|
||||
1
vendor/powershell/PSWriteColor
vendored
Submodule
1
vendor/powershell/PSWriteColor
vendored
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 12eda384ebd7a7954e15855e312215c009c97114
|
||||
Loading…
Add table
Add a link
Reference in a new issue