diff --git a/igniter/bootstrap_repos.py b/igniter/bootstrap_repos.py
index b44689ba89..7c4f8b4b69 100644
--- a/igniter/bootstrap_repos.py
+++ b/igniter/bootstrap_repos.py
@@ -203,6 +203,12 @@ class OpenPypeVersion(semver.VersionInfo):
openpype_version.staging = True
return openpype_version
+ def __hash__(self):
+ if self.path:
+ return hash(self.path)
+ else:
+ return hash(str(self))
+
class BootstrapRepos:
"""Class for bootstrapping local OpenPype installation.
@@ -650,6 +656,9 @@ class BootstrapRepos:
v for v in openpype_versions if v.path.suffix != ".zip"
]
+ # remove duplicates
+ openpype_versions = list(set(openpype_versions))
+
return openpype_versions
def process_entered_location(self, location: str) -> Union[Path, None]:
diff --git a/openpype/cli.py b/openpype/cli.py
index 71f689f159..835ca9209c 100644
--- a/openpype/cli.py
+++ b/openpype/cli.py
@@ -60,13 +60,6 @@ def tray(debug=False):
help="Ftrack api user")
@click.option("--ftrack-api-key", envvar="FTRACK_API_KEY",
help="Ftrack api key")
-@click.option("--ftrack-events-path",
- envvar="FTRACK_EVENTS_PATH",
- help=("path to ftrack event handlers"))
-@click.option("--no-stored-credentials", is_flag=True,
- help="don't use stored credentials")
-@click.option("--store-credentials", is_flag=True,
- help="store provided credentials")
@click.option("--legacy", is_flag=True,
help="run event server without mongo storing")
@click.option("--clockify-api-key", envvar="CLOCKIFY_API_KEY",
@@ -77,9 +70,6 @@ def eventserver(debug,
ftrack_url,
ftrack_user,
ftrack_api_key,
- ftrack_events_path,
- no_stored_credentials,
- store_credentials,
legacy,
clockify_api_key,
clockify_workspace):
@@ -87,10 +77,6 @@ def eventserver(debug,
This should be ideally used by system service (such us systemd or upstart
on linux and window service).
-
- You have to set either proper environment variables to provide URL and
- credentials or use option to specify them. If you use --store_credentials
- provided credentials will be stored for later use.
"""
if debug:
os.environ['OPENPYPE_DEBUG'] = "3"
@@ -99,9 +85,6 @@ def eventserver(debug,
ftrack_url,
ftrack_user,
ftrack_api_key,
- ftrack_events_path,
- no_stored_credentials,
- store_credentials,
legacy,
clockify_api_key,
clockify_workspace
diff --git a/openpype/hooks/pre_add_last_workfile_arg.py b/openpype/hooks/pre_add_last_workfile_arg.py
index 377026da4a..5ca2a42510 100644
--- a/openpype/hooks/pre_add_last_workfile_arg.py
+++ b/openpype/hooks/pre_add_last_workfile_arg.py
@@ -8,8 +8,19 @@ class AddLastWorkfileToLaunchArgs(PreLaunchHook):
This is not possible to do for all applications the same way.
"""
- order = 0
- app_groups = ["maya", "nuke", "nukex", "hiero", "nukestudio"]
+ # Execute after workfile template copy
+ order = 10
+ app_groups = [
+ "maya",
+ "nuke",
+ "nukex",
+ "hiero",
+ "nukestudio",
+ "blender",
+ "photoshop",
+ "tvpaint",
+ "afftereffects"
+ ]
def execute(self):
if not self.data.get("start_last_workfile"):
diff --git a/openpype/hooks/pre_copy_template_workfile.py b/openpype/hooks/pre_copy_template_workfile.py
new file mode 100644
index 0000000000..29a522f933
--- /dev/null
+++ b/openpype/hooks/pre_copy_template_workfile.py
@@ -0,0 +1,127 @@
+import os
+import shutil
+from openpype.lib import (
+ PreLaunchHook,
+ get_custom_workfile_template_by_context,
+ get_custom_workfile_template_by_string_context
+)
+from openpype.settings import get_project_settings
+
+
+class CopyTemplateWorkfile(PreLaunchHook):
+ """Copy workfile template.
+
+ This is not possible to do for all applications the same way.
+
+ Prelaunch hook works only if last workfile leads to not existing file.
+ - That is possible only if it's first version.
+ """
+
+ # Before `AddLastWorkfileToLaunchArgs`
+ order = 0
+ app_groups = ["blender", "photoshop", "tvpaint", "afftereffects"]
+
+ def execute(self):
+ """Check if can copy template for context and do it if possible.
+
+ First check if host for current project should create first workfile.
+ Second check is if template is reachable and can be copied.
+
+ Args:
+ last_workfile(str): Path where template will be copied.
+
+ Returns:
+ None: This is a void method.
+ """
+
+ last_workfile = self.data.get("last_workfile_path")
+ if not last_workfile:
+ self.log.warning((
+ "Last workfile was not collected."
+ " Can't add it to launch arguments or determine if should"
+ " copy template."
+ ))
+ return
+
+ if os.path.exists(last_workfile):
+ self.log.debug("Last workfile exits. Skipping {} process.".format(
+ self.__class__.__name__
+ ))
+ return
+
+ self.log.info("Last workfile does not exits.")
+
+ project_name = self.data["project_name"]
+ asset_name = self.data["asset_name"]
+ task_name = self.data["task_name"]
+
+ project_settings = get_project_settings(project_name)
+ host_settings = project_settings[self.application.host_name]
+
+ workfile_builder_settings = host_settings.get("workfile_builder")
+ if not workfile_builder_settings:
+ # TODO remove warning when deprecated
+ self.log.warning((
+ "Seems like old version of settings is used."
+ " Can't access custom templates in host \"{}\"."
+ ).format(self.application.full_label))
+ return
+
+ if not workfile_builder_settings["create_first_version"]:
+ self.log.info((
+ "Project \"{}\" has turned off to create first workfile for"
+ " application \"{}\""
+ ).format(project_name, self.application.full_label))
+ return
+
+ # Backwards compatibility
+ template_profiles = workfile_builder_settings.get("custom_templates")
+ if not template_profiles:
+ self.log.info(
+ "Custom templates are not filled. Skipping template copy."
+ )
+ return
+
+ project_doc = self.data.get("project_doc")
+ asset_doc = self.data.get("asset_doc")
+ anatomy = self.data.get("anatomy")
+ if project_doc and asset_doc:
+ self.log.debug("Started filtering of custom template paths.")
+ template_path = get_custom_workfile_template_by_context(
+ template_profiles, project_doc, asset_doc, task_name, anatomy
+ )
+
+ else:
+ self.log.warning((
+ "Global data collection probably did not execute."
+ " Using backup solution."
+ ))
+ dbcon = self.data.get("dbcon")
+ template_path = get_custom_workfile_template_by_string_context(
+ template_profiles, project_name, asset_name, task_name,
+ dbcon, anatomy
+ )
+
+ if not template_path:
+ self.log.info(
+ "Registered custom templates didn't match current context."
+ )
+ return
+
+ if not os.path.exists(template_path):
+ self.log.warning(
+ "Couldn't find workfile template file \"{}\"".format(
+ template_path
+ )
+ )
+ return
+
+ self.log.info(
+ f"Creating workfile from template: \"{template_path}\""
+ )
+
+ # Copy template workfile to new destinantion
+ shutil.copy2(
+ os.path.normpath(template_path),
+ os.path.normpath(last_workfile)
+ )
diff --git a/openpype/hooks/pre_mac_launch.py b/openpype/hooks/pre_mac_launch.py
new file mode 100644
index 0000000000..3f07ae07db
--- /dev/null
+++ b/openpype/hooks/pre_mac_launch.py
@@ -0,0 +1,34 @@
+import os
+from openpype.lib import PreLaunchHook
+
+
+class LaunchWithTerminal(PreLaunchHook):
+ """Mac specific pre arguments for application.
+
+ Mac applications should be launched using "open" argument which is internal
+ callbacks to open executable. We also add argument "-a" to tell it's
+ application open. This is used only for executables ending with ".app". It
+ is expected that these executables lead to app packages.
+ """
+ order = 1000
+
+ platforms = ["darwin"]
+
+ def execute(self):
+ executable = str(self.launch_context.executable)
+ # Skip executables not ending with ".app" or that are not folder
+ if not executable.endswith(".app") or not os.path.isdir(executable):
+ return
+
+ # Check if first argument match executable path
+ # - Few applications are not executed directly but through OpenPype
+ # process (Photoshop, AfterEffects, Harmony, ...). These should not
+ # use `open`.
+ if self.launch_context.launch_args[0] != executable:
+ return
+
+ # Tell `open` to pass arguments if there are any
+ if len(self.launch_context.launch_args) > 1:
+ self.launch_context.launch_args.insert(1, "--args")
+ # Prepend open arguments
+ self.launch_context.launch_args.insert(0, ["open", "-a"])
diff --git a/openpype/hooks/pre_non_python_host_launch.py b/openpype/hooks/pre_non_python_host_launch.py
index c16a72c5e5..393a878f76 100644
--- a/openpype/hooks/pre_non_python_host_launch.py
+++ b/openpype/hooks/pre_non_python_host_launch.py
@@ -1,4 +1,5 @@
import os
+import subprocess
from openpype.lib import (
PreLaunchHook,
@@ -17,6 +18,8 @@ class NonPythonHostHook(PreLaunchHook):
"""
app_groups = ["harmony", "photoshop", "aftereffects"]
+ order = 20
+
def execute(self):
# Pop executable
executable_path = self.launch_context.launch_args.pop(0)
@@ -45,3 +48,6 @@ class NonPythonHostHook(PreLaunchHook):
if remainders:
self.launch_context.launch_args.extend(remainders)
+
+ self.launch_context.kwargs["stdout"] = subprocess.DEVNULL
+ self.launch_context.kwargs["stderr"] = subprocess.STDOUT
diff --git a/openpype/hooks/pre_with_windows_shell.py b/openpype/hooks/pre_with_windows_shell.py
index 0c10583b99..441ab1a675 100644
--- a/openpype/hooks/pre_with_windows_shell.py
+++ b/openpype/hooks/pre_with_windows_shell.py
@@ -11,12 +11,14 @@ class LaunchWithWindowsShell(PreLaunchHook):
instead.
"""
- # Should be as last hook becuase must change launch arguments to string
+ # Should be as last hook because must change launch arguments to string
order = 1000
app_groups = ["nuke", "nukex", "hiero", "nukestudio"]
platforms = ["windows"]
def execute(self):
+ launch_args = self.launch_context.clear_launch_args(
+ self.launch_context.launch_args)
new_args = [
# Get comspec which is cmd.exe in most cases.
os.environ.get("COMSPEC", "cmd.exe"),
@@ -24,7 +26,7 @@ class LaunchWithWindowsShell(PreLaunchHook):
"/c",
# Convert arguments to command line arguments (as string)
"\"{}\"".format(
- subprocess.list2cmdline(self.launch_context.launch_args)
+ subprocess.list2cmdline(launch_args)
)
]
# Convert list to string
diff --git a/openpype/hosts/blender/plugins/create/create_setdress.py b/openpype/hosts/blender/plugins/create/create_setdress.py
deleted file mode 100644
index 97c737c235..0000000000
--- a/openpype/hosts/blender/plugins/create/create_setdress.py
+++ /dev/null
@@ -1,25 +0,0 @@
-import bpy
-
-from avalon import api, blender
-import openpype.hosts.blender.api.plugin
-
-
-class CreateSetDress(openpype.hosts.blender.api.plugin.Creator):
- """A grouped package of loaded content"""
-
- name = "setdressMain"
- label = "Set Dress"
- family = "setdress"
- icon = "cubes"
- defaults = ["Main", "Anim"]
-
- def process(self):
- asset = self.data["asset"]
- subset = self.data["subset"]
- name = openpype.hosts.blender.api.plugin.asset_name(asset, subset)
- collection = bpy.data.collections.new(name=name)
- bpy.context.scene.collection.children.link(collection)
- self.data['task'] = api.Session.get('AVALON_TASK')
- blender.lib.imprint(collection, self.data)
-
- return collection
diff --git a/openpype/hosts/blender/plugins/load/load_layout.py b/openpype/hosts/blender/plugins/load/load_layout.py
index 87ef9670a6..2092be9139 100644
--- a/openpype/hosts/blender/plugins/load/load_layout.py
+++ b/openpype/hosts/blender/plugins/load/load_layout.py
@@ -25,9 +25,6 @@ class BlendLayoutLoader(plugin.AssetLoader):
icon = "code-fork"
color = "orange"
- animation_creator_name = "CreateAnimation"
- setdress_creator_name = "CreateSetDress"
-
def _remove(self, objects, obj_container):
for obj in list(objects):
if obj.type == 'ARMATURE':
@@ -293,7 +290,6 @@ class UnrealLayoutLoader(plugin.AssetLoader):
color = "orange"
animation_creator_name = "CreateAnimation"
- setdress_creator_name = "CreateSetDress"
def _remove_objects(self, objects):
for obj in list(objects):
@@ -383,7 +379,7 @@ class UnrealLayoutLoader(plugin.AssetLoader):
def _process(
self, libpath, layout_container, container_name, representation,
- actions, parent
+ actions, parent_collection
):
with open(libpath, "r") as fp:
data = json.load(fp)
@@ -392,6 +388,11 @@ class UnrealLayoutLoader(plugin.AssetLoader):
layout_collection = bpy.data.collections.new(container_name)
scene.collection.children.link(layout_collection)
+ parent = parent_collection
+
+ if parent is None:
+ parent = scene.collection
+
all_loaders = api.discover(api.Loader)
avalon_container = bpy.data.collections.get(
@@ -516,23 +517,9 @@ class UnrealLayoutLoader(plugin.AssetLoader):
container_metadata["libpath"] = libpath
container_metadata["lib_container"] = lib_container
- # Create a setdress subset to contain all the animation for all
- # the rigs in the layout
- creator_plugin = get_creator_by_name(self.setdress_creator_name)
- if not creator_plugin:
- raise ValueError("Creator plugin \"{}\" was not found.".format(
- self.setdress_creator_name
- ))
- parent = api.create(
- creator_plugin,
- name="animation",
- asset=api.Session["AVALON_ASSET"],
- options={"useSelection": True},
- data={"dependencies": str(context["representation"]["_id"])})
-
layout_collection = self._process(
libpath, layout_container, container_name,
- str(context["representation"]["_id"]), None, parent)
+ str(context["representation"]["_id"]), None, None)
container_metadata["obj_container"] = layout_collection
diff --git a/openpype/hosts/blender/plugins/load/load_look.py b/openpype/hosts/blender/plugins/load/load_look.py
new file mode 100644
index 0000000000..279af2b626
--- /dev/null
+++ b/openpype/hosts/blender/plugins/load/load_look.py
@@ -0,0 +1,218 @@
+"""Load a model asset in Blender."""
+
+from pathlib import Path
+from pprint import pformat
+from typing import Dict, List, Optional
+
+import os
+import json
+import bpy
+
+from avalon import api, blender
+import openpype.hosts.blender.api.plugin as plugin
+
+
+class BlendLookLoader(plugin.AssetLoader):
+ """Load models from a .blend file.
+
+ Because they come from a .blend file we can simply link the collection that
+ contains the model. There is no further need to 'containerise' it.
+ """
+
+ families = ["look"]
+ representations = ["json"]
+
+ label = "Load Look"
+ icon = "code-fork"
+ color = "orange"
+
+ def get_all_children(self, obj):
+ children = list(obj.children)
+
+ for child in children:
+ children.extend(child.children)
+
+ return children
+
+ def _process(self, libpath, container_name, objects):
+ with open(libpath, "r") as fp:
+ data = json.load(fp)
+
+ path = os.path.dirname(libpath)
+ materials_path = f"{path}/resources"
+
+ materials = []
+
+ for entry in data:
+ file = entry.get('fbx_filename')
+ if file is None:
+ continue
+
+ bpy.ops.import_scene.fbx(filepath=f"{materials_path}/{file}")
+
+ mesh = [o for o in bpy.context.scene.objects if o.select_get()][0]
+ material = mesh.data.materials[0]
+ material.name = f"{material.name}:{container_name}"
+
+ texture_file = entry.get('tga_filename')
+ if texture_file:
+ node_tree = material.node_tree
+ pbsdf = node_tree.nodes['Principled BSDF']
+ base_color = pbsdf.inputs[0]
+ tex_node = base_color.links[0].from_node
+ tex_node.image.filepath = f"{materials_path}/{texture_file}"
+
+ materials.append(material)
+
+ for obj in objects:
+ for child in self.get_all_children(obj):
+ mesh_name = child.name.split(':')[0]
+ if mesh_name == material.name.split(':')[0]:
+ child.data.materials.clear()
+ child.data.materials.append(material)
+ break
+
+ bpy.data.objects.remove(mesh)
+
+ return materials, objects
+
+ def process_asset(
+ self, context: dict, name: str, namespace: Optional[str] = None,
+ options: Optional[Dict] = None
+ ) -> Optional[List]:
+ """
+ Arguments:
+ name: Use pre-defined name
+ namespace: Use pre-defined namespace
+ context: Full parenthood of representation to load
+ options: Additional settings dictionary
+ """
+
+ libpath = self.fname
+ asset = context["asset"]["name"]
+ subset = context["subset"]["name"]
+
+ lib_container = plugin.asset_name(
+ asset, subset
+ )
+ unique_number = plugin.get_unique_number(
+ asset, subset
+ )
+ namespace = namespace or f"{asset}_{unique_number}"
+ container_name = plugin.asset_name(
+ asset, subset, unique_number
+ )
+
+ container = bpy.data.collections.new(lib_container)
+ container.name = container_name
+ blender.pipeline.containerise_existing(
+ container,
+ name,
+ namespace,
+ context,
+ self.__class__.__name__,
+ )
+
+ metadata = container.get(blender.pipeline.AVALON_PROPERTY)
+
+ metadata["libpath"] = libpath
+ metadata["lib_container"] = lib_container
+
+ selected = [o for o in bpy.context.scene.objects if o.select_get()]
+
+ materials, objects = self._process(libpath, container_name, selected)
+
+ # Save the list of imported materials in the metadata container
+ metadata["objects"] = objects
+ metadata["materials"] = materials
+
+ metadata["parent"] = str(context["representation"]["parent"])
+ metadata["family"] = context["representation"]["context"]["family"]
+
+ nodes = list(container.objects)
+ nodes.append(container)
+ self[:] = nodes
+ return nodes
+
+ def update(self, container: Dict, representation: Dict):
+ collection = bpy.data.collections.get(container["objectName"])
+ libpath = Path(api.get_representation_path(representation))
+ extension = libpath.suffix.lower()
+
+ self.log.info(
+ "Container: %s\nRepresentation: %s",
+ pformat(container, indent=2),
+ pformat(representation, indent=2),
+ )
+
+ assert collection, (
+ f"The asset is not loaded: {container['objectName']}"
+ )
+ assert not (collection.children), (
+ "Nested collections are not supported."
+ )
+ assert libpath, (
+ "No existing library file found for {container['objectName']}"
+ )
+ assert libpath.is_file(), (
+ f"The file doesn't exist: {libpath}"
+ )
+ assert extension in plugin.VALID_EXTENSIONS, (
+ f"Unsupported file: {libpath}"
+ )
+
+ collection_metadata = collection.get(blender.pipeline.AVALON_PROPERTY)
+ collection_libpath = collection_metadata["libpath"]
+
+ normalized_collection_libpath = (
+ str(Path(bpy.path.abspath(collection_libpath)).resolve())
+ )
+ normalized_libpath = (
+ str(Path(bpy.path.abspath(str(libpath))).resolve())
+ )
+ self.log.debug(
+ "normalized_collection_libpath:\n %s\nnormalized_libpath:\n %s",
+ normalized_collection_libpath,
+ normalized_libpath,
+ )
+ if normalized_collection_libpath == normalized_libpath:
+ self.log.info("Library already loaded, not updating...")
+ return
+
+ for obj in collection_metadata['objects']:
+ for child in self.get_all_children(obj):
+ child.data.materials.clear()
+
+ for material in collection_metadata['materials']:
+ bpy.data.materials.remove(material)
+
+ namespace = collection_metadata['namespace']
+ name = collection_metadata['name']
+
+ container_name = f"{namespace}_{name}"
+
+ materials, objects = self._process(
+ libpath, container_name, collection_metadata['objects'])
+
+ collection_metadata["objects"] = objects
+ collection_metadata["materials"] = materials
+ collection_metadata["libpath"] = str(libpath)
+ collection_metadata["representation"] = str(representation["_id"])
+
+ def remove(self, container: Dict) -> bool:
+ collection = bpy.data.collections.get(container["objectName"])
+ if not collection:
+ return False
+
+ collection_metadata = collection.get(blender.pipeline.AVALON_PROPERTY)
+
+ for obj in collection_metadata['objects']:
+ for child in self.get_all_children(obj):
+ child.data.materials.clear()
+
+ for material in collection_metadata['materials']:
+ bpy.data.materials.remove(material)
+
+ bpy.data.collections.remove(collection)
+
+ return True
diff --git a/openpype/hosts/blender/plugins/load/load_rig.py b/openpype/hosts/blender/plugins/load/load_rig.py
index 9035458c12..b6be8f4cf6 100644
--- a/openpype/hosts/blender/plugins/load/load_rig.py
+++ b/openpype/hosts/blender/plugins/load/load_rig.py
@@ -107,6 +107,9 @@ class BlendRigLoader(plugin.AssetLoader):
if action is not None:
local_obj.animation_data.action = action
+ elif local_obj.animation_data.action is not None:
+ plugin.prepare_data(
+ local_obj.animation_data.action, collection_name)
# Set link the drivers to the local object
if local_obj.data.animation_data:
diff --git a/openpype/hosts/blender/plugins/publish/extract_animation_collection.py b/openpype/hosts/blender/plugins/publish/extract_animation_collection.py
deleted file mode 100644
index 19dc59c5cd..0000000000
--- a/openpype/hosts/blender/plugins/publish/extract_animation_collection.py
+++ /dev/null
@@ -1,61 +0,0 @@
-import os
-import json
-
-import openpype.api
-import pyblish.api
-
-import bpy
-
-
-class ExtractSetDress(openpype.api.Extractor):
- """Extract setdress."""
-
- label = "Extract SetDress"
- hosts = ["blender"]
- families = ["setdress"]
- optional = True
- order = pyblish.api.ExtractorOrder + 0.1
-
- def process(self, instance):
- stagingdir = self.staging_dir(instance)
-
- json_data = []
-
- for i in instance.context:
- collection = i.data.get("name")
- container = None
- for obj in bpy.data.collections[collection].objects:
- if obj.type == "ARMATURE":
- container_name = obj.get("avalon").get("container_name")
- container = bpy.data.collections[container_name]
- if container:
- json_dict = {
- "subset": i.data.get("subset"),
- "container": container.name,
- }
- json_dict["instance_name"] = container.get("avalon").get(
- "instance_name"
- )
- json_data.append(json_dict)
-
- if "representations" not in instance.data:
- instance.data["representations"] = []
-
- json_filename = f"{instance.name}.json"
- json_path = os.path.join(stagingdir, json_filename)
-
- with open(json_path, "w+") as file:
- json.dump(json_data, fp=file, indent=2)
-
- json_representation = {
- "name": "json",
- "ext": "json",
- "files": json_filename,
- "stagingDir": stagingdir,
- }
- instance.data["representations"].append(json_representation)
-
- self.log.info(
- "Extracted instance '{}' to: {}".format(instance.name,
- json_representation)
- )
diff --git a/openpype/hosts/blender/plugins/publish/extract_fbx.py b/openpype/hosts/blender/plugins/publish/extract_fbx.py
index dc74348949..05149eacc1 100644
--- a/openpype/hosts/blender/plugins/publish/extract_fbx.py
+++ b/openpype/hosts/blender/plugins/publish/extract_fbx.py
@@ -54,6 +54,14 @@ class ExtractFBX(openpype.api.Extractor):
# We set the scale of the scene for the export
scene.unit_settings.scale_length = 0.01
+ new_materials = []
+
+ for obj in collections[0].all_objects:
+ if obj.type == 'MESH':
+ mat = bpy.data.materials.new(obj.name)
+ obj.data.materials.append(mat)
+ new_materials.append(mat)
+
# We export the fbx
bpy.ops.export_scene.fbx(
filepath=filepath,
@@ -66,6 +74,13 @@ class ExtractFBX(openpype.api.Extractor):
scene.unit_settings.scale_length = old_scale
+ for mat in new_materials:
+ bpy.data.materials.remove(mat)
+
+ for obj in collections[0].all_objects:
+ if obj.type == 'MESH':
+ obj.data.materials.pop()
+
if "representations" not in instance.data:
instance.data["representations"] = []
diff --git a/openpype/hosts/blender/plugins/publish/extract_fbx_animation.py b/openpype/hosts/blender/plugins/publish/extract_fbx_animation.py
index 1036800705..8312114c7b 100644
--- a/openpype/hosts/blender/plugins/publish/extract_fbx_animation.py
+++ b/openpype/hosts/blender/plugins/publish/extract_fbx_animation.py
@@ -1,4 +1,5 @@
import os
+import json
import openpype.api
@@ -121,6 +122,25 @@ class ExtractAnimationFBX(openpype.api.Extractor):
pair[1].user_clear()
bpy.data.actions.remove(pair[1])
+ json_filename = f"{instance.name}.json"
+ json_path = os.path.join(stagingdir, json_filename)
+
+ json_dict = {}
+
+ collection = instance.data.get("name")
+ container = None
+ for obj in bpy.data.collections[collection].objects:
+ if obj.type == "ARMATURE":
+ container_name = obj.get("avalon").get("container_name")
+ container = bpy.data.collections[container_name]
+ if container:
+ json_dict = {
+ "instance_name": container.get("avalon").get("instance_name")
+ }
+
+ with open(json_path, "w+") as file:
+ json.dump(json_dict, fp=file, indent=2)
+
if "representations" not in instance.data:
instance.data["representations"] = []
@@ -130,7 +150,15 @@ class ExtractAnimationFBX(openpype.api.Extractor):
'files': fbx_filename,
"stagingDir": stagingdir,
}
+ json_representation = {
+ 'name': 'json',
+ 'ext': 'json',
+ 'files': json_filename,
+ "stagingDir": stagingdir,
+ }
instance.data["representations"].append(fbx_representation)
+ instance.data["representations"].append(json_representation)
+
self.log.info("Extracted instance '{}' to: {}".format(
instance.name, fbx_representation))
diff --git a/openpype/hosts/hiero/api/lib.py b/openpype/hosts/hiero/api/lib.py
index a9982d96c4..d8a235be77 100644
--- a/openpype/hosts/hiero/api/lib.py
+++ b/openpype/hosts/hiero/api/lib.py
@@ -214,7 +214,9 @@ def get_track_items(
# add all if no track_type is defined
return_list.append(track_item)
- return return_list
+ # return output list but make sure all items are TrackItems
+ return [_i for _i in return_list
+ if type(_i) == hiero.core.TrackItem]
def get_track_item_pype_tag(track_item):
diff --git a/openpype/hosts/hiero/plugins/publish_old_workflow/extract_clip_effects.py b/openpype/hosts/hiero/plugins/publish/extract_clip_effects.py
similarity index 92%
rename from openpype/hosts/hiero/plugins/publish_old_workflow/extract_clip_effects.py
rename to openpype/hosts/hiero/plugins/publish/extract_clip_effects.py
index d2ac7f4786..5b0aa270a7 100644
--- a/openpype/hosts/hiero/plugins/publish_old_workflow/extract_clip_effects.py
+++ b/openpype/hosts/hiero/plugins/publish/extract_clip_effects.py
@@ -52,10 +52,11 @@ class ExtractClipEffects(openpype.api.Extractor):
instance.data["representations"] = list()
transfer_data = [
- "handleStart", "handleEnd", "sourceIn", "sourceOut",
- "frameStart", "frameEnd", "sourceInH", "sourceOutH",
- "clipIn", "clipOut", "clipInH", "clipOutH", "asset", "track",
- "version"
+ "handleStart", "handleEnd",
+ "sourceStart", "sourceStartH", "sourceEnd", "sourceEndH",
+ "frameStart", "frameEnd",
+ "clipIn", "clipOut", "clipInH", "clipOutH",
+ "asset", "version"
]
# pass data to version
diff --git a/openpype/hosts/hiero/plugins/publish_old_workflow/precollect_clip_effects.py b/openpype/hosts/hiero/plugins/publish/precollect_clip_effects.py
similarity index 93%
rename from openpype/hosts/hiero/plugins/publish_old_workflow/precollect_clip_effects.py
rename to openpype/hosts/hiero/plugins/publish/precollect_clip_effects.py
index f9bde24255..5a9f89651c 100644
--- a/openpype/hosts/hiero/plugins/publish_old_workflow/precollect_clip_effects.py
+++ b/openpype/hosts/hiero/plugins/publish/precollect_clip_effects.py
@@ -5,7 +5,7 @@ import pyblish.api
class PreCollectClipEffects(pyblish.api.InstancePlugin):
"""Collect soft effects instances."""
- order = pyblish.api.CollectorOrder - 0.508
+ order = pyblish.api.CollectorOrder - 0.579
label = "Pre-collect Clip Effects Instances"
families = ["clip"]
@@ -24,7 +24,8 @@ class PreCollectClipEffects(pyblish.api.InstancePlugin):
self.clip_in_h = self.clip_in - self.handle_start
self.clip_out_h = self.clip_out + self.handle_end
- track = instance.data["trackItem"]
+ track_item = instance.data["item"]
+ track = track_item.parent()
track_index = track.trackIndex()
tracks_effect_items = instance.context.data.get("tracksEffectItems")
clip_effect_items = instance.data.get("clipEffectItems")
@@ -112,7 +113,12 @@ class PreCollectClipEffects(pyblish.api.InstancePlugin):
node = sitem.node()
node_serialized = self.node_serialisation(node)
node_name = sitem.name()
- node_class = re.sub(r"\d+", "", node_name)
+
+ if "_" in node_name:
+ node_class = re.sub(r"(?:_)[_0-9]+", "", node_name) # more numbers
+ else:
+ node_class = re.sub(r"\d+", "", node_name) # one number
+
# collect timelineIn/Out
effect_t_in = int(sitem.timelineIn())
effect_t_out = int(sitem.timelineOut())
@@ -121,6 +127,7 @@ class PreCollectClipEffects(pyblish.api.InstancePlugin):
return
self.log.debug("node_name: `{}`".format(node_name))
+ self.log.debug("node_class: `{}`".format(node_class))
return {node_name: {
"class": node_class,
diff --git a/openpype/hosts/hiero/plugins/publish/precollect_instances.py b/openpype/hosts/hiero/plugins/publish/precollect_instances.py
index 8cccdec99a..f7449561ef 100644
--- a/openpype/hosts/hiero/plugins/publish/precollect_instances.py
+++ b/openpype/hosts/hiero/plugins/publish/precollect_instances.py
@@ -2,6 +2,9 @@ import pyblish
import openpype
from openpype.hosts.hiero import api as phiero
from openpype.hosts.hiero.otio import hiero_export
+import hiero
+
+from compiler.ast import flatten
# # developer reload modules
from pprint import pformat
@@ -14,18 +17,40 @@ class PrecollectInstances(pyblish.api.ContextPlugin):
label = "Precollect Instances"
hosts = ["hiero"]
+ audio_track_items = []
+
def process(self, context):
- otio_timeline = context.data["otioTimeline"]
+ self.otio_timeline = context.data["otioTimeline"]
+
selected_timeline_items = phiero.get_track_items(
- selected=True, check_enabled=True, check_tagged=True)
+ selected=True, check_tagged=True, check_enabled=True)
+
+ # only return enabled track items
+ if not selected_timeline_items:
+ selected_timeline_items = phiero.get_track_items(
+ check_enabled=True, check_tagged=True)
+
self.log.info(
"Processing enabled track items: {}".format(
selected_timeline_items))
+ # add all tracks subtreck effect items to context
+ all_tracks = hiero.ui.activeSequence().videoTracks()
+ tracks_effect_items = self.collect_sub_track_items(all_tracks)
+ context.data["tracksEffectItems"] = tracks_effect_items
+
+ # process all sellected timeline track items
for track_item in selected_timeline_items:
data = {}
clip_name = track_item.name()
+ source_clip = track_item.source()
+
+ # get clips subtracks and anotations
+ annotations = self.clip_annotations(source_clip)
+ subtracks = self.clip_subtrack(track_item)
+ self.log.debug("Annotations: {}".format(annotations))
+ self.log.debug(">> Subtracks: {}".format(subtracks))
# get openpype tag data
tag_data = phiero.get_track_item_pype_data(track_item)
@@ -76,12 +101,15 @@ class PrecollectInstances(pyblish.api.ContextPlugin):
"item": track_item,
"families": families,
"publish": tag_data["publish"],
- "fps": context.data["fps"]
+ "fps": context.data["fps"],
+
+ # clip's effect
+ "clipEffectItems": subtracks,
+ "clipAnnotations": annotations
})
# otio clip data
- otio_data = self.get_otio_clip_instance_data(
- otio_timeline, track_item) or {}
+ otio_data = self.get_otio_clip_instance_data(track_item) or {}
self.log.debug("__ otio_data: {}".format(pformat(otio_data)))
data.update(otio_data)
self.log.debug("__ data: {}".format(pformat(data)))
@@ -185,6 +213,10 @@ class PrecollectInstances(pyblish.api.ContextPlugin):
item = data.get("item")
clip_name = item.name()
+ # test if any audio clips
+ if not self.test_any_audio(item):
+ return
+
asset = data["asset"]
subset = "audioMain"
@@ -215,7 +247,28 @@ class PrecollectInstances(pyblish.api.ContextPlugin):
self.log.debug(
"_ instance.data: {}".format(pformat(instance.data)))
- def get_otio_clip_instance_data(self, otio_timeline, track_item):
+ def test_any_audio(self, track_item):
+ # collect all audio tracks to class variable
+ if not self.audio_track_items:
+ for otio_clip in self.otio_timeline.each_clip():
+ if otio_clip.parent().kind != "Audio":
+ continue
+ self.audio_track_items.append(otio_clip)
+
+ # get track item timeline range
+ timeline_range = self.create_otio_time_range_from_timeline_item_data(
+ track_item)
+
+ # loop trough audio track items and search for overlaping clip
+ for otio_audio in self.audio_track_items:
+ parent_range = otio_audio.range_in_parent()
+
+ # if any overaling clip found then return True
+ if openpype.lib.is_overlapping_otio_ranges(
+ parent_range, timeline_range, strict=False):
+ return True
+
+ def get_otio_clip_instance_data(self, track_item):
"""
Return otio objects for timeline, track and clip
@@ -231,7 +284,7 @@ class PrecollectInstances(pyblish.api.ContextPlugin):
ti_track_name = track_item.parent().name()
timeline_range = self.create_otio_time_range_from_timeline_item_data(
track_item)
- for otio_clip in otio_timeline.each_clip():
+ for otio_clip in self.otio_timeline.each_clip():
track_name = otio_clip.parent().name
parent_range = otio_clip.range_in_parent()
if ti_track_name not in track_name:
@@ -258,3 +311,76 @@ class PrecollectInstances(pyblish.api.ContextPlugin):
return hiero_export.create_otio_time_range(
frame_start, frame_duration, fps)
+
+ @staticmethod
+ def collect_sub_track_items(tracks):
+ """
+ Returns dictionary with track index as key and list of subtracks
+ """
+ # collect all subtrack items
+ sub_track_items = {}
+ for track in tracks:
+ items = track.items()
+
+ # skip if no clips on track > need track with effect only
+ if items:
+ continue
+
+ # skip all disabled tracks
+ if not track.isEnabled():
+ continue
+
+ track_index = track.trackIndex()
+ _sub_track_items = flatten(track.subTrackItems())
+
+ # continue only if any subtrack items are collected
+ if len(_sub_track_items) < 1:
+ continue
+
+ enabled_sti = []
+ # loop all found subtrack items and check if they are enabled
+ for _sti in _sub_track_items:
+ # checking if not enabled
+ if not _sti.isEnabled():
+ continue
+ if isinstance(_sti, hiero.core.Annotation):
+ continue
+ # collect the subtrack item
+ enabled_sti.append(_sti)
+
+ # continue only if any subtrack items are collected
+ if len(enabled_sti) < 1:
+ continue
+
+ # add collection of subtrackitems to dict
+ sub_track_items[track_index] = enabled_sti
+
+ return sub_track_items
+
+ @staticmethod
+ def clip_annotations(clip):
+ """
+ Returns list of Clip's hiero.core.Annotation
+ """
+ annotations = []
+ subTrackItems = flatten(clip.subTrackItems())
+ annotations += [item for item in subTrackItems if isinstance(
+ item, hiero.core.Annotation)]
+ return annotations
+
+ @staticmethod
+ def clip_subtrack(clip):
+ """
+ Returns list of Clip's hiero.core.SubTrackItem
+ """
+ subtracks = []
+ subTrackItems = flatten(clip.parent().subTrackItems())
+ for item in subTrackItems:
+ # avoid all anotation
+ if isinstance(item, hiero.core.Annotation):
+ continue
+ # # avoid all not anaibled
+ if not item.isEnabled():
+ continue
+ subtracks.append(item)
+ return subtracks
diff --git a/openpype/hosts/hiero/plugins/publish/precollect_workfile.py b/openpype/hosts/hiero/plugins/publish/precollect_workfile.py
index bc4ef7e150..530a433423 100644
--- a/openpype/hosts/hiero/plugins/publish/precollect_workfile.py
+++ b/openpype/hosts/hiero/plugins/publish/precollect_workfile.py
@@ -75,10 +75,26 @@ class PrecollectWorkfile(pyblish.api.ContextPlugin):
"activeProject": project,
"otioTimeline": otio_timeline,
"currentFile": curent_file,
- "fps": fps,
+ "colorspace": self.get_colorspace(project),
+ "fps": fps
}
context.data.update(context_data)
self.log.info("Creating instance: {}".format(instance))
self.log.debug("__ instance.data: {}".format(pformat(instance.data)))
self.log.debug("__ context_data: {}".format(pformat(context_data)))
+
+ def get_colorspace(self, project):
+ # get workfile's colorspace properties
+ return {
+ "useOCIOEnvironmentOverride": project.useOCIOEnvironmentOverride(),
+ "lutSetting16Bit": project.lutSetting16Bit(),
+ "lutSetting8Bit": project.lutSetting8Bit(),
+ "lutSettingFloat": project.lutSettingFloat(),
+ "lutSettingLog": project.lutSettingLog(),
+ "lutSettingViewer": project.lutSettingViewer(),
+ "lutSettingWorkingSpace": project.lutSettingWorkingSpace(),
+ "lutUseOCIOForExport": project.lutUseOCIOForExport(),
+ "ocioConfigName": project.ocioConfigName(),
+ "ocioConfigPath": project.ocioConfigPath()
+ }
diff --git a/openpype/hosts/maya/api/lib.py b/openpype/hosts/maya/api/lib.py
index 909993a173..b87e106865 100644
--- a/openpype/hosts/maya/api/lib.py
+++ b/openpype/hosts/maya/api/lib.py
@@ -2124,7 +2124,7 @@ def bake_to_world_space(nodes,
return world_space_nodes
-def load_capture_preset(path=None, data=None):
+def load_capture_preset(data=None):
import capture
preset = data
@@ -2139,11 +2139,7 @@ def load_capture_preset(path=None, data=None):
# GENERIC
id = 'Generic'
for key in preset[id]:
- if key.startswith('isolate'):
- pass
- # options['isolate'] = preset[id][key]
- else:
- options[str(key)] = preset[id][key]
+ options[str(key)] = preset[id][key]
# RESOLUTION
id = 'Resolution'
@@ -2156,6 +2152,10 @@ def load_capture_preset(path=None, data=None):
for key in preset['Display Options']:
if key.startswith('background'):
disp_options[key] = preset['Display Options'][key]
+ disp_options[key][0] = (float(disp_options[key][0])/255)
+ disp_options[key][1] = (float(disp_options[key][1])/255)
+ disp_options[key][2] = (float(disp_options[key][2])/255)
+ disp_options[key].pop()
else:
disp_options['displayGradient'] = True
@@ -2220,16 +2220,6 @@ def load_capture_preset(path=None, data=None):
# use active sound track
scene = capture.parse_active_scene()
options['sound'] = scene['sound']
- cam_options = dict()
- cam_options['overscan'] = 1.0
- cam_options['displayFieldChart'] = False
- cam_options['displayFilmGate'] = False
- cam_options['displayFilmOrigin'] = False
- cam_options['displayFilmPivot'] = False
- cam_options['displayGateMask'] = False
- cam_options['displayResolution'] = False
- cam_options['displaySafeAction'] = False
- cam_options['displaySafeTitle'] = False
# options['display_options'] = temp_options
diff --git a/openpype/hosts/maya/plugins/load/load_ass.py b/openpype/hosts/maya/plugins/load/load_ass.py
index b4bbd93f99..b7d44dd431 100644
--- a/openpype/hosts/maya/plugins/load/load_ass.py
+++ b/openpype/hosts/maya/plugins/load/load_ass.py
@@ -81,7 +81,10 @@ class AssProxyLoader(openpype.hosts.maya.api.plugin.ReferenceLoader):
if c is not None:
cmds.setAttr(groupName + ".useOutlinerColor", 1)
cmds.setAttr(groupName + ".outlinerColor",
- c[0], c[1], c[2])
+ (float(c[0])/255),
+ (float(c[1])/255),
+ (float(c[2])/255)
+ )
self[:] = nodes
diff --git a/openpype/hosts/maya/plugins/load/load_gpucache.py b/openpype/hosts/maya/plugins/load/load_gpucache.py
index 5b1b29e184..d0a83b8177 100644
--- a/openpype/hosts/maya/plugins/load/load_gpucache.py
+++ b/openpype/hosts/maya/plugins/load/load_gpucache.py
@@ -38,7 +38,10 @@ class GpuCacheLoader(api.Loader):
if c is not None:
cmds.setAttr(root + ".useOutlinerColor", 1)
cmds.setAttr(root + ".outlinerColor",
- c[0], c[1], c[2])
+ (float(c[0])/255),
+ (float(c[1])/255),
+ (float(c[2])/255)
+ )
# Create transform with shape
transform_name = label + "_GPU"
diff --git a/openpype/hosts/maya/plugins/load/load_reference.py b/openpype/hosts/maya/plugins/load/load_reference.py
index 37a2b145d4..96269f2771 100644
--- a/openpype/hosts/maya/plugins/load/load_reference.py
+++ b/openpype/hosts/maya/plugins/load/load_reference.py
@@ -85,7 +85,11 @@ class ReferenceLoader(openpype.hosts.maya.api.plugin.ReferenceLoader):
c = colors.get(family)
if c is not None:
groupNode.useOutlinerColor.set(1)
- groupNode.outlinerColor.set(c[0], c[1], c[2])
+ groupNode.outlinerColor.set(
+ (float(c[0])/255),
+ (float(c[1])/255),
+ (float(c[2])/255)
+ )
self[:] = newNodes
diff --git a/openpype/hosts/maya/plugins/load/load_vdb_to_redshift.py b/openpype/hosts/maya/plugins/load/load_vdb_to_redshift.py
index b705b55f4d..f5662ba462 100644
--- a/openpype/hosts/maya/plugins/load/load_vdb_to_redshift.py
+++ b/openpype/hosts/maya/plugins/load/load_vdb_to_redshift.py
@@ -62,7 +62,10 @@ class LoadVDBtoRedShift(api.Loader):
if c is not None:
cmds.setAttr(root + ".useOutlinerColor", 1)
cmds.setAttr(root + ".outlinerColor",
- c[0], c[1], c[2])
+ (float(c[0])/255),
+ (float(c[1])/255),
+ (float(c[2])/255)
+ )
# Create VR
volume_node = cmds.createNode("RedshiftVolumeShape",
diff --git a/openpype/hosts/maya/plugins/load/load_vdb_to_vray.py b/openpype/hosts/maya/plugins/load/load_vdb_to_vray.py
index 82ccdb481b..80b453bd13 100644
--- a/openpype/hosts/maya/plugins/load/load_vdb_to_vray.py
+++ b/openpype/hosts/maya/plugins/load/load_vdb_to_vray.py
@@ -55,7 +55,10 @@ class LoadVDBtoVRay(api.Loader):
if c is not None:
cmds.setAttr(root + ".useOutlinerColor", 1)
cmds.setAttr(root + ".outlinerColor",
- c[0], c[1], c[2])
+ (float(c[0])/255),
+ (float(c[1])/255),
+ (float(c[2])/255)
+ )
# Create VR
grid_node = cmds.createNode("VRayVolumeGrid",
diff --git a/openpype/hosts/maya/plugins/load/load_vrayproxy.py b/openpype/hosts/maya/plugins/load/load_vrayproxy.py
index d5d4a941e3..e70f40bf5a 100644
--- a/openpype/hosts/maya/plugins/load/load_vrayproxy.py
+++ b/openpype/hosts/maya/plugins/load/load_vrayproxy.py
@@ -74,7 +74,10 @@ class VRayProxyLoader(api.Loader):
if c is not None:
cmds.setAttr("{0}.useOutlinerColor".format(group_node), 1)
cmds.setAttr("{0}.outlinerColor".format(group_node),
- c[0], c[1], c[2])
+ (float(c[0])/255),
+ (float(c[1])/255),
+ (float(c[2])/255)
+ )
return containerise(
name=name,
diff --git a/openpype/hosts/maya/plugins/load/load_vrayscene.py b/openpype/hosts/maya/plugins/load/load_vrayscene.py
index b0f0c2a54b..465dab2a76 100644
--- a/openpype/hosts/maya/plugins/load/load_vrayscene.py
+++ b/openpype/hosts/maya/plugins/load/load_vrayscene.py
@@ -53,7 +53,10 @@ class VRaySceneLoader(api.Loader):
if c is not None:
cmds.setAttr("{0}.useOutlinerColor".format(group_node), 1)
cmds.setAttr("{0}.outlinerColor".format(group_node),
- c[0], c[1], c[2])
+ (float(c[0])/255),
+ (float(c[1])/255),
+ (float(c[2])/255)
+ )
return containerise(
name=name,
diff --git a/openpype/hosts/maya/plugins/load/load_yeti_cache.py b/openpype/hosts/maya/plugins/load/load_yeti_cache.py
index 43c8aa16a0..de0ea6823c 100644
--- a/openpype/hosts/maya/plugins/load/load_yeti_cache.py
+++ b/openpype/hosts/maya/plugins/load/load_yeti_cache.py
@@ -66,7 +66,10 @@ class YetiCacheLoader(api.Loader):
if c is not None:
cmds.setAttr(group_name + ".useOutlinerColor", 1)
cmds.setAttr(group_name + ".outlinerColor",
- c[0], c[1], c[2])
+ (float(c[0])/255),
+ (float(c[1])/255),
+ (float(c[2])/255)
+ )
nodes.append(group_node)
diff --git a/openpype/hosts/maya/plugins/load/load_yeti_rig.py b/openpype/hosts/maya/plugins/load/load_yeti_rig.py
index a329be4cf5..3f67f98f51 100644
--- a/openpype/hosts/maya/plugins/load/load_yeti_rig.py
+++ b/openpype/hosts/maya/plugins/load/load_yeti_rig.py
@@ -84,7 +84,10 @@ class YetiRigLoader(openpype.hosts.maya.api.plugin.ReferenceLoader):
if c is not None:
cmds.setAttr(groupName + ".useOutlinerColor", 1)
cmds.setAttr(groupName + ".outlinerColor",
- c[0], c[1], c[2])
+ (float(c[0])/255),
+ (float(c[1])/255),
+ (float(c[2])/255)
+ )
self[:] = nodes
return nodes
diff --git a/openpype/hosts/maya/plugins/publish/extract_playblast.py b/openpype/hosts/maya/plugins/publish/extract_playblast.py
index 0dc91d67a9..fa1ce7f9a9 100644
--- a/openpype/hosts/maya/plugins/publish/extract_playblast.py
+++ b/openpype/hosts/maya/plugins/publish/extract_playblast.py
@@ -49,9 +49,6 @@ class ExtractPlayblast(openpype.api.Extractor):
preset['camera'] = camera
- preset['format'] = "image"
- preset['quality'] = 95
- preset['compression'] = "png"
preset['start_frame'] = start
preset['end_frame'] = end
camera_option = preset.get("camera_option", {})
@@ -75,7 +72,7 @@ class ExtractPlayblast(openpype.api.Extractor):
# Isolate view is requested by having objects in the set besides a
# camera.
- if instance.data.get("isolate"):
+ if preset.pop("isolate_view", False) or instance.data.get("isolate"):
preset["isolate"] = instance.data["setMembers"]
# Show/Hide image planes on request.
@@ -93,9 +90,6 @@ class ExtractPlayblast(openpype.api.Extractor):
# playblast and viewer
preset['viewer'] = False
- # Remove panel key since it's internal value to capture_gui
- preset.pop("panel", None)
-
self.log.info('using viewport preset: {}'.format(preset))
path = capture.capture(**preset)
diff --git a/openpype/hosts/maya/plugins/publish/extract_thumbnail.py b/openpype/hosts/maya/plugins/publish/extract_thumbnail.py
index 016efa6499..5a91888781 100644
--- a/openpype/hosts/maya/plugins/publish/extract_thumbnail.py
+++ b/openpype/hosts/maya/plugins/publish/extract_thumbnail.py
@@ -12,10 +12,10 @@ import pymel.core as pm
class ExtractThumbnail(openpype.api.Extractor):
- """Extract a Camera as Alembic.
+ """Extract viewport thumbnail.
- The cameras gets baked to world space by default. Only when the instance's
- `bakeToWorldSpace` is set to False it will include its full hierarchy.
+ Takes review camera and creates a thumbnail based on viewport
+ capture.
"""
@@ -35,17 +35,14 @@ class ExtractThumbnail(openpype.api.Extractor):
try:
preset = lib.load_capture_preset(data=capture_preset)
- except:
+ except KeyError as ke:
+ self.log.error('Error loading capture presets: {}'.format(str(ke)))
preset = {}
- self.log.info('using viewport preset: {}'.format(capture_preset))
+ self.log.info('Using viewport preset: {}'.format(preset))
# preset["off_screen"] = False
preset['camera'] = camera
- preset['format'] = "image"
- # preset['compression'] = "qt"
- preset['quality'] = 50
- preset['compression'] = "jpg"
preset['start_frame'] = instance.data["frameStart"]
preset['end_frame'] = instance.data["frameStart"]
preset['camera_options'] = {
@@ -78,7 +75,7 @@ class ExtractThumbnail(openpype.api.Extractor):
# Isolate view is requested by having objects in the set besides a
# camera.
- if instance.data.get("isolate"):
+ if preset.pop("isolate_view", False) or instance.data.get("isolate"):
preset["isolate"] = instance.data["setMembers"]
with maintained_time():
@@ -89,9 +86,6 @@ class ExtractThumbnail(openpype.api.Extractor):
# playblast and viewer
preset['viewer'] = False
- # Remove panel key since it's internal value to capture_gui
- preset.pop("panel", None)
-
path = capture.capture(**preset)
playblast = self._fix_playblast_output_path(path)
diff --git a/openpype/hosts/maya/plugins/publish/validate_rendersettings.py b/openpype/hosts/maya/plugins/publish/validate_rendersettings.py
index 9aeaad7ff1..8d2c7d8f63 100644
--- a/openpype/hosts/maya/plugins/publish/validate_rendersettings.py
+++ b/openpype/hosts/maya/plugins/publish/validate_rendersettings.py
@@ -243,7 +243,10 @@ class ValidateRenderSettings(pyblish.api.InstancePlugin):
"Cannot get value of {}.{}".format(
node, attribute_name))
else:
- if value != render_value:
+ # compare values as strings to get around various
+ # datatypes possible in Settings and Render
+ # Settings
+ if str(value) != str(render_value):
invalid = True
cls.log.error(
("Invalid value {} set on {}.{}. "
diff --git a/openpype/hosts/nuke/api/__init__.py b/openpype/hosts/nuke/api/__init__.py
index bd7a95f916..e6dab5cfc9 100644
--- a/openpype/hosts/nuke/api/__init__.py
+++ b/openpype/hosts/nuke/api/__init__.py
@@ -80,7 +80,7 @@ def install():
# Set context settings.
nuke.addOnCreate(workfile_settings.set_context_settings, nodeClass="Root")
nuke.addOnCreate(workfile_settings.set_favorites, nodeClass="Root")
- nuke.addOnCreate(lib.open_last_workfile, nodeClass="Root")
+ nuke.addOnCreate(lib.process_workfile_builder, nodeClass="Root")
nuke.addOnCreate(lib.launch_workfiles_app, nodeClass="Root")
menu.install()
diff --git a/openpype/hosts/nuke/api/lib.py b/openpype/hosts/nuke/api/lib.py
index e6dde813a7..3c41574dbf 100644
--- a/openpype/hosts/nuke/api/lib.py
+++ b/openpype/hosts/nuke/api/lib.py
@@ -16,6 +16,7 @@ from avalon.nuke import (
from openpype.api import (
Logger,
Anatomy,
+ BuildWorkfile,
get_version_from_path,
get_anatomy_settings,
get_hierarchy,
@@ -1059,7 +1060,7 @@ class WorkfileSettings(object):
# replace reset resolution from avalon core to pype's
self.reset_frame_range_handles()
# add colorspace menu item
- # self.set_colorspace()
+ self.set_colorspace()
def set_favorites(self):
work_dir = os.getenv("AVALON_WORKDIR")
@@ -1641,23 +1642,69 @@ def launch_workfiles_app():
workfiles.show(os.environ["AVALON_WORKDIR"])
-def open_last_workfile():
- # get state from settings
- open_last_version = get_current_project_settings()["nuke"].get(
- "general", {}).get("create_initial_workfile")
+def process_workfile_builder():
+ from openpype.lib import (
+ env_value_to_bool,
+ get_custom_workfile_template
+ )
+
+ # get state from settings
+ workfile_builder = get_current_project_settings()["nuke"].get(
+ "workfile_builder", {})
+
+ # get all imortant settings
+ openlv_on = env_value_to_bool(
+ env_key="AVALON_OPEN_LAST_WORKFILE",
+ default=None)
+
+ # get settings
+ createfv_on = workfile_builder.get("create_first_version") or None
+ custom_templates = workfile_builder.get("custom_templates") or None
+ builder_on = workfile_builder.get("builder_on_start") or None
- log.info("Opening last workfile...")
last_workfile_path = os.environ.get("AVALON_LAST_WORKFILE")
- if not os.path.exists(last_workfile_path):
- # return if none is defined
- if not open_last_version:
- return
+ # generate first version in file not existing and feature is enabled
+ if createfv_on and not os.path.exists(last_workfile_path):
+ # get custom template path if any
+ custom_template_path = get_custom_workfile_template(
+ custom_templates
+ )
+ # if custom template is defined
+ if custom_template_path:
+ log.info("Adding nodes from `{}`...".format(
+ custom_template_path
+ ))
+ try:
+ # import nodes into current script
+ nuke.nodePaste(custom_template_path)
+ except RuntimeError:
+ raise RuntimeError((
+ "Template defined for project: {} is not working. "
+ "Talk to your manager for an advise").format(
+ custom_template_path))
+
+ # if builder at start is defined
+ if builder_on:
+ log.info("Building nodes from presets...")
+ # build nodes by defined presets
+ BuildWorkfile().process()
+
+ log.info("Saving script as version `{}`...".format(
+ last_workfile_path
+ ))
+ # safe file as version
save_file(last_workfile_path)
- else:
- # to avoid looping of the callback, remove it!
- nuke.removeOnCreate(open_last_workfile, nodeClass="Root")
+ return
- # open workfile
- open_file(last_workfile_path)
+ # skip opening of last version if it is not enabled
+ if not openlv_on or not os.path.exists(last_workfile_path):
+ return
+
+ # to avoid looping of the callback, remove it!
+ nuke.removeOnCreate(process_workfile_builder, nodeClass="Root")
+
+ log.info("Opening last workfile...")
+ # open workfile
+ open_file(last_workfile_path)
diff --git a/openpype/hosts/nuke/plugins/load/load_luts.py b/openpype/hosts/nuke/plugins/load/load_effects.py
similarity index 94%
rename from openpype/hosts/nuke/plugins/load/load_luts.py
rename to openpype/hosts/nuke/plugins/load/load_effects.py
index 85ec3e2060..6306767f37 100644
--- a/openpype/hosts/nuke/plugins/load/load_luts.py
+++ b/openpype/hosts/nuke/plugins/load/load_effects.py
@@ -4,18 +4,19 @@ import json
from collections import OrderedDict
-class LoadLuts(api.Loader):
+class LoadEffects(api.Loader):
"""Loading colorspace soft effect exported from nukestudio"""
- representations = ["lutJson"]
- families = ["lut"]
+ representations = ["effectJson"]
+ families = ["effect"]
- label = "Load Luts - nodes"
+ label = "Load Effects - nodes"
order = 0
icon = "cc"
color = style.colors.light
ignore_attr = ["useLifetime"]
+
def load(self, context, name, namespace, data):
"""
Loading function to get the soft effects to particular read node
@@ -66,15 +67,15 @@ class LoadLuts(api.Loader):
for key, value in json.load(f).iteritems()}
# get correct order of nodes by positions on track and subtrack
- nodes_order = self.reorder_nodes(json_f["effects"])
+ nodes_order = self.reorder_nodes(json_f)
# adding nodes to node graph
# just in case we are in group lets jump out of it
nuke.endGroup()
- GN = nuke.createNode("Group")
-
- GN["name"].setValue(object_name)
+ GN = nuke.createNode(
+ "Group",
+ "name {}_1".format(object_name))
# adding content to the group node
with GN:
@@ -186,7 +187,7 @@ class LoadLuts(api.Loader):
for key, value in json.load(f).iteritems()}
# get correct order of nodes by positions on track and subtrack
- nodes_order = self.reorder_nodes(json_f["effects"])
+ nodes_order = self.reorder_nodes(json_f)
# adding nodes to node graph
# just in case we are in group lets jump out of it
@@ -266,7 +267,11 @@ class LoadLuts(api.Loader):
None: if nothing found
"""
search_name = "{0}_{1}".format(asset, subset)
- node = [n for n in nuke.allNodes() if search_name in n["name"].value()]
+
+ node = [
+ n for n in nuke.allNodes(filter="Read")
+ if search_name in n["file"].value()
+ ]
if len(node) > 0:
rn = node[0]
else:
@@ -286,8 +291,10 @@ class LoadLuts(api.Loader):
def reorder_nodes(self, data):
new_order = OrderedDict()
- trackNums = [v["trackIndex"] for k, v in data.items()]
- subTrackNums = [v["subTrackIndex"] for k, v in data.items()]
+ trackNums = [v["trackIndex"] for k, v in data.items()
+ if isinstance(v, dict)]
+ subTrackNums = [v["subTrackIndex"] for k, v in data.items()
+ if isinstance(v, dict)]
for trackIndex in range(
min(trackNums), max(trackNums) + 1):
@@ -300,6 +307,7 @@ class LoadLuts(api.Loader):
def get_item(self, data, trackIndex, subTrackIndex):
return {key: val for key, val in data.items()
+ if isinstance(val, dict)
if subTrackIndex == val["subTrackIndex"]
if trackIndex == val["trackIndex"]}
diff --git a/openpype/hosts/nuke/plugins/load/load_luts_ip.py b/openpype/hosts/nuke/plugins/load/load_effects_ip.py
similarity index 95%
rename from openpype/hosts/nuke/plugins/load/load_luts_ip.py
rename to openpype/hosts/nuke/plugins/load/load_effects_ip.py
index a0af29c7f4..6c71f2ae16 100644
--- a/openpype/hosts/nuke/plugins/load/load_luts_ip.py
+++ b/openpype/hosts/nuke/plugins/load/load_effects_ip.py
@@ -5,13 +5,13 @@ from collections import OrderedDict
from openpype.hosts.nuke.api import lib
-class LoadLutsInputProcess(api.Loader):
+class LoadEffectsInputProcess(api.Loader):
"""Loading colorspace soft effect exported from nukestudio"""
- representations = ["lutJson"]
- families = ["lut"]
+ representations = ["effectJson"]
+ families = ["effect"]
- label = "Load Luts - Input Process"
+ label = "Load Effects - Input Process"
order = 0
icon = "eye"
color = style.colors.alert
@@ -67,15 +67,15 @@ class LoadLutsInputProcess(api.Loader):
for key, value in json.load(f).iteritems()}
# get correct order of nodes by positions on track and subtrack
- nodes_order = self.reorder_nodes(json_f["effects"])
+ nodes_order = self.reorder_nodes(json_f)
# adding nodes to node graph
# just in case we are in group lets jump out of it
nuke.endGroup()
- GN = nuke.createNode("Group")
-
- GN["name"].setValue(object_name)
+ GN = nuke.createNode(
+ "Group",
+ "name {}_1".format(object_name))
# adding content to the group node
with GN:
@@ -190,7 +190,7 @@ class LoadLutsInputProcess(api.Loader):
for key, value in json.load(f).iteritems()}
# get correct order of nodes by positions on track and subtrack
- nodes_order = self.reorder_nodes(json_f["effects"])
+ nodes_order = self.reorder_nodes(json_f)
# adding nodes to node graph
# just in case we are in group lets jump out of it
@@ -304,8 +304,10 @@ class LoadLutsInputProcess(api.Loader):
def reorder_nodes(self, data):
new_order = OrderedDict()
- trackNums = [v["trackIndex"] for k, v in data.items()]
- subTrackNums = [v["subTrackIndex"] for k, v in data.items()]
+ trackNums = [v["trackIndex"] for k, v in data.items()
+ if isinstance(v, dict)]
+ subTrackNums = [v["subTrackIndex"] for k, v in data.items()
+ if isinstance(v, dict)]
for trackIndex in range(
min(trackNums), max(trackNums) + 1):
@@ -318,6 +320,7 @@ class LoadLutsInputProcess(api.Loader):
def get_item(self, data, trackIndex, subTrackIndex):
return {key: val for key, val in data.items()
+ if isinstance(val, dict)
if subTrackIndex == val["subTrackIndex"]
if trackIndex == val["trackIndex"]}
diff --git a/openpype/hosts/nuke/startup/menu.py b/openpype/hosts/nuke/startup/menu.py
index 9eb656afa9..c452acb709 100644
--- a/openpype/hosts/nuke/startup/menu.py
+++ b/openpype/hosts/nuke/startup/menu.py
@@ -1,6 +1,7 @@
from openpype.hosts.nuke.api.lib import (
on_script_load,
- check_inventory_versions
+ check_inventory_versions,
+ WorkfileSettings
)
import nuke
@@ -9,8 +10,14 @@ from openpype.api import Logger
log = Logger().get_logger(__name__)
-nuke.addOnScriptSave(on_script_load)
+# fix ffmpeg settings on script
+nuke.addOnScriptLoad(on_script_load)
+
+# set checker for last versions on loaded containers
nuke.addOnScriptLoad(check_inventory_versions)
nuke.addOnScriptSave(check_inventory_versions)
+# # set apply all workfile settings on script load and save
+nuke.addOnScriptLoad(WorkfileSettings().set_context_settings)
+
log.info('Automatic syncing of write file knob to script version')
diff --git a/openpype/hosts/tvpaint/api/__init__.py b/openpype/hosts/tvpaint/api/__init__.py
index bd9ef51a76..57a03d38b7 100644
--- a/openpype/hosts/tvpaint/api/__init__.py
+++ b/openpype/hosts/tvpaint/api/__init__.py
@@ -19,6 +19,10 @@ CREATE_PATH = os.path.join(PLUGINS_DIR, "create")
def on_instance_toggle(instance, old_value, new_value):
+ # Review may not have real instance in wokrfile metadata
+ if not instance.data.get("uuid"):
+ return
+
instance_id = instance.data["uuid"]
found_idx = None
current_instances = pipeline.list_instances()
diff --git a/openpype/hosts/tvpaint/hooks/pre_launch_args.py b/openpype/hosts/tvpaint/hooks/pre_launch_args.py
index 04cca5d789..b0b13529ca 100644
--- a/openpype/hosts/tvpaint/hooks/pre_launch_args.py
+++ b/openpype/hosts/tvpaint/hooks/pre_launch_args.py
@@ -34,20 +34,6 @@ class TvpaintPrelaunchHook(PreLaunchHook):
"run", self.launch_script_path(), executable_path
)
- # Add workfile to launch arguments
- workfile_path = self.workfile_path()
- if workfile_path:
- new_launch_args.append(workfile_path)
-
- # How to create new command line
- # if platform.system().lower() == "windows":
- # new_launch_args = [
- # "cmd.exe",
- # "/c",
- # "Call cmd.exe /k",
- # *new_launch_args
- # ]
-
# Append as whole list as these areguments should not be separated
self.launch_context.launch_args.append(new_launch_args)
@@ -64,38 +50,4 @@ class TvpaintPrelaunchHook(PreLaunchHook):
"tvpaint",
"launch_script.py"
)
- return script_path
-
- def workfile_path(self):
- workfile_path = self.data["last_workfile_path"]
-
- # copy workfile from template if doesnt exist any on path
- if not os.path.exists(workfile_path):
- # TODO add ability to set different template workfile path via
- # settings
- pype_dir = os.path.dirname(os.path.abspath(tvpaint.__file__))
- template_path = os.path.join(
- pype_dir, "resources", "template.tvpp"
- )
-
- if not os.path.exists(template_path):
- self.log.warning(
- "Couldn't find workfile template file in {}".format(
- template_path
- )
- )
- return
-
- self.log.info(
- f"Creating workfile from template: \"{template_path}\""
- )
-
- # Copy template workfile to new destinantion
- shutil.copy2(
- os.path.normpath(template_path),
- os.path.normpath(workfile_path)
- )
-
- self.log.info(f"Workfile to open: \"{workfile_path}\"")
-
- return workfile_path
+ return script_path
\ No newline at end of file
diff --git a/openpype/hosts/tvpaint/plugins/create/create_review.py b/openpype/hosts/tvpaint/plugins/create/create_review.py
deleted file mode 100644
index 88b039c8e4..0000000000
--- a/openpype/hosts/tvpaint/plugins/create/create_review.py
+++ /dev/null
@@ -1,19 +0,0 @@
-from avalon.tvpaint import pipeline
-from openpype.hosts.tvpaint.api import plugin
-
-
-class CreateReview(plugin.Creator):
- """Review for global review of all layers."""
- name = "review"
- label = "Review"
- family = "review"
- icon = "cube"
- defaults = ["Main"]
-
- def process(self):
- instances = pipeline.list_instances()
- for instance in instances:
- if instance["family"] == self.family:
- self.log.info("Review family is already Created.")
- return
- super(CreateReview, self).process()
diff --git a/openpype/hosts/tvpaint/plugins/publish/collect_instances.py b/openpype/hosts/tvpaint/plugins/publish/collect_instances.py
index 27bd8e9ede..9b11f9fe80 100644
--- a/openpype/hosts/tvpaint/plugins/publish/collect_instances.py
+++ b/openpype/hosts/tvpaint/plugins/publish/collect_instances.py
@@ -1,3 +1,4 @@
+import os
import json
import copy
import pyblish.api
@@ -17,6 +18,20 @@ class CollectInstances(pyblish.api.ContextPlugin):
json.dumps(workfile_instances, indent=4)
))
+ # Backwards compatibility for workfiles that already have review
+ # instance in metadata.
+ review_instance_exist = False
+ for instance_data in workfile_instances:
+ if instance_data["family"] == "review":
+ review_instance_exist = True
+ break
+
+ # Fake review instance if review was not found in metadata families
+ if not review_instance_exist:
+ workfile_instances.append(
+ self._create_review_instance_data(context)
+ )
+
for instance_data in workfile_instances:
instance_data["fps"] = context.data["sceneFps"]
@@ -90,6 +105,16 @@ class CollectInstances(pyblish.api.ContextPlugin):
instance, json.dumps(instance.data, indent=4)
))
+ def _create_review_instance_data(self, context):
+ """Fake review instance data."""
+
+ return {
+ "family": "review",
+ "asset": context.data["asset"],
+ # Dummy subset name
+ "subset": "reviewMain"
+ }
+
def create_render_layer_instance(self, context, instance_data):
name = instance_data["name"]
# Change label
diff --git a/openpype/hosts/tvpaint/plugins/publish/collect_workfile.py b/openpype/hosts/tvpaint/plugins/publish/collect_workfile.py
new file mode 100644
index 0000000000..b059be90bf
--- /dev/null
+++ b/openpype/hosts/tvpaint/plugins/publish/collect_workfile.py
@@ -0,0 +1,43 @@
+import os
+import json
+import pyblish.api
+from avalon import io
+
+
+class CollectWorkfile(pyblish.api.ContextPlugin):
+ label = "Collect Workfile"
+ order = pyblish.api.CollectorOrder - 1
+ hosts = ["tvpaint"]
+
+ def process(self, context):
+ current_file = context.data["currentFile"]
+
+ self.log.info(
+ "Workfile path used for workfile family: {}".format(current_file)
+ )
+
+ dirpath, filename = os.path.split(current_file)
+ basename, ext = os.path.splitext(filename)
+ instance = context.create_instance(name=basename)
+
+ task_name = io.Session["AVALON_TASK"]
+ subset_name = "workfile" + task_name.capitalize()
+
+ # Create Workfile instance
+ instance.data.update({
+ "subset": subset_name,
+ "asset": context.data["asset"],
+ "label": subset_name,
+ "publish": True,
+ "family": "workfile",
+ "families": ["workfile"],
+ "representations": [{
+ "name": ext.lstrip("."),
+ "ext": ext.lstrip("."),
+ "files": filename,
+ "stagingDir": dirpath
+ }]
+ })
+ self.log.info("Collected workfile instance: {}".format(
+ json.dumps(instance.data, indent=4)
+ ))
diff --git a/openpype/hosts/tvpaint/plugins/publish/validate_workfile_metadata.py b/openpype/hosts/tvpaint/plugins/publish/validate_workfile_metadata.py
new file mode 100644
index 0000000000..757da3294a
--- /dev/null
+++ b/openpype/hosts/tvpaint/plugins/publish/validate_workfile_metadata.py
@@ -0,0 +1,49 @@
+import pyblish.api
+from avalon.tvpaint import save_file
+
+
+class ValidateWorkfileMetadataRepair(pyblish.api.Action):
+ """Store current context into workfile metadata."""
+
+ label = "Use current context"
+ icon = "wrench"
+ on = "failed"
+
+ def process(self, context, _plugin):
+ """Save current workfile which should trigger storing of metadata."""
+ current_file = context.data["currentFile"]
+ # Save file should trigger
+ save_file(current_file)
+
+
+class ValidateWorkfileMetadata(pyblish.api.ContextPlugin):
+ """Validate if wokrfile contain required metadata for publising."""
+
+ label = "Validate Workfile Metadata"
+ order = pyblish.api.ValidatorOrder
+
+ families = ["workfile"]
+
+ actions = [ValidateWorkfileMetadataRepair]
+
+ required_keys = {"project", "asset", "task"}
+
+ def process(self, context):
+ workfile_context = context.data["workfile_context"]
+ if not workfile_context:
+ raise AssertionError(
+ "Current workfile is missing whole metadata about context."
+ )
+
+ missing_keys = []
+ for key in self.required_keys:
+ value = workfile_context.get(key)
+ if not value:
+ missing_keys.append(key)
+
+ if missing_keys:
+ raise AssertionError(
+ "Current workfile is missing metadata about {}.".format(
+ ", ".join(missing_keys)
+ )
+ )
diff --git a/openpype/hosts/unreal/plugins/create/create_look.py b/openpype/hosts/unreal/plugins/create/create_look.py
new file mode 100644
index 0000000000..7d3913b883
--- /dev/null
+++ b/openpype/hosts/unreal/plugins/create/create_look.py
@@ -0,0 +1,66 @@
+import unreal
+from openpype.hosts.unreal.api.plugin import Creator
+from avalon.unreal import pipeline
+
+
+class CreateLook(Creator):
+ """Shader connections defining shape look"""
+
+ name = "unrealLook"
+ label = "Unreal - Look"
+ family = "look"
+ icon = "paint-brush"
+
+ root = "/Game/Avalon/Assets"
+ suffix = "_INS"
+
+ def __init__(self, *args, **kwargs):
+ super(CreateLook, self).__init__(*args, **kwargs)
+
+ def process(self):
+ name = self.data["subset"]
+
+ selection = []
+ if (self.options or {}).get("useSelection"):
+ sel_objects = unreal.EditorUtilityLibrary.get_selected_assets()
+ selection = [a.get_path_name() for a in sel_objects]
+
+ # Create the folder
+ path = f"{self.root}/{self.data['asset']}"
+ new_name = pipeline.create_folder(path, name)
+ full_path = f"{path}/{new_name}"
+
+ # Create a new cube static mesh
+ ar = unreal.AssetRegistryHelpers.get_asset_registry()
+ cube = ar.get_asset_by_object_path("/Engine/BasicShapes/Cube.Cube")
+
+ # Create the avalon publish instance object
+ container_name = f"{name}{self.suffix}"
+ pipeline.create_publish_instance(
+ instance=container_name, path=full_path)
+
+ # Get the mesh of the selected object
+ original_mesh = ar.get_asset_by_object_path(selection[0]).get_asset()
+ materials = original_mesh.get_editor_property('materials')
+
+ self.data["members"] = []
+
+ # Add the materials to the cube
+ for material in materials:
+ name = material.get_editor_property('material_slot_name')
+ object_path = f"{full_path}/{name}.{name}"
+ object = unreal.EditorAssetLibrary.duplicate_loaded_asset(
+ cube.get_asset(), object_path
+ )
+
+ # Remove the default material of the cube object
+ object.get_editor_property('static_materials').pop()
+
+ object.add_material(
+ material.get_editor_property('material_interface'))
+
+ self.data["members"].append(object_path)
+
+ unreal.EditorAssetLibrary.save_asset(object_path)
+
+ pipeline.imprint(f"{full_path}/{container_name}", self.data)
diff --git a/openpype/hosts/unreal/plugins/load/load_animation.py b/openpype/hosts/unreal/plugins/load/load_animation.py
index 18910983ea..481285d603 100644
--- a/openpype/hosts/unreal/plugins/load/load_animation.py
+++ b/openpype/hosts/unreal/plugins/load/load_animation.py
@@ -1,4 +1,5 @@
import os
+import json
from avalon import api, pipeline
from avalon.unreal import lib
@@ -61,10 +62,16 @@ class AnimationFBXLoader(api.Loader):
task = unreal.AssetImportTask()
task.options = unreal.FbxImportUI()
- # If there are no options, the process cannot be automated
- if options:
+ libpath = self.fname.replace("fbx", "json")
+
+ with open(libpath, "r") as fp:
+ data = json.load(fp)
+
+ instance_name = data.get("instance_name")
+
+ if instance_name:
automated = True
- actor_name = 'PersistentLevel.' + options.get('instance_name')
+ actor_name = 'PersistentLevel.' + instance_name
actor = unreal.EditorLevelLibrary.get_actor_reference(actor_name)
skeleton = actor.skeletal_mesh_component.skeletal_mesh.skeleton
task.options.set_editor_property('skeleton', skeleton)
@@ -81,16 +88,31 @@ class AnimationFBXLoader(api.Loader):
# set import options here
task.options.set_editor_property(
- 'automated_import_should_detect_type', True)
+ 'automated_import_should_detect_type', False)
task.options.set_editor_property(
- 'original_import_type', unreal.FBXImportType.FBXIT_ANIMATION)
+ 'original_import_type', unreal.FBXImportType.FBXIT_SKELETAL_MESH)
+ task.options.set_editor_property(
+ 'mesh_type_to_import', unreal.FBXImportType.FBXIT_ANIMATION)
task.options.set_editor_property('import_mesh', False)
task.options.set_editor_property('import_animations', True)
+ task.options.set_editor_property('override_full_name', True)
- task.options.skeletal_mesh_import_data.set_editor_property(
- 'import_content_type',
- unreal.FBXImportContentType.FBXICT_SKINNING_WEIGHTS
+ task.options.anim_sequence_import_data.set_editor_property(
+ 'animation_length',
+ unreal.FBXAnimationLengthImportType.FBXALIT_EXPORTED_TIME
)
+ task.options.anim_sequence_import_data.set_editor_property(
+ 'import_meshes_in_bone_hierarchy', False)
+ task.options.anim_sequence_import_data.set_editor_property(
+ 'use_default_sample_rate', True)
+ task.options.anim_sequence_import_data.set_editor_property(
+ 'import_custom_attribute', True)
+ task.options.anim_sequence_import_data.set_editor_property(
+ 'import_bone_tracks', True)
+ task.options.anim_sequence_import_data.set_editor_property(
+ 'remove_redundant_keys', True)
+ task.options.anim_sequence_import_data.set_editor_property(
+ 'convert_scene', True)
unreal.AssetToolsHelpers.get_asset_tools().import_asset_tasks([task])
diff --git a/openpype/hosts/unreal/plugins/load/load_setdress.py b/openpype/hosts/unreal/plugins/load/load_setdress.py
deleted file mode 100644
index da302deb1c..0000000000
--- a/openpype/hosts/unreal/plugins/load/load_setdress.py
+++ /dev/null
@@ -1,127 +0,0 @@
-import json
-
-from avalon import api
-import unreal
-
-
-class AnimationCollectionLoader(api.Loader):
- """Load Unreal SkeletalMesh from FBX"""
-
- families = ["setdress"]
- representations = ["json"]
-
- label = "Load Animation Collection"
- icon = "cube"
- color = "orange"
-
- def load(self, context, name, namespace, options):
- from avalon import api, pipeline
- from avalon.unreal import lib
- from avalon.unreal import pipeline as unreal_pipeline
- import unreal
-
- # Create directory for asset and avalon container
- root = "/Game/Avalon/Assets"
- asset = context.get('asset').get('name')
- suffix = "_CON"
-
- tools = unreal.AssetToolsHelpers().get_asset_tools()
- asset_dir, container_name = tools.create_unique_asset_name(
- "{}/{}".format(root, asset), suffix="")
-
- container_name += suffix
-
- unreal.EditorAssetLibrary.make_directory(asset_dir)
-
- libpath = self.fname
-
- with open(libpath, "r") as fp:
- data = json.load(fp)
-
- all_loaders = api.discover(api.Loader)
-
- for element in data:
- reference = element.get('_id')
-
- loaders = api.loaders_from_representation(all_loaders, reference)
- loader = None
- for l in loaders:
- if l.__name__ == "AnimationFBXLoader":
- loader = l
- break
-
- if not loader:
- continue
-
- instance_name = element.get('instance_name')
-
- api.load(
- loader,
- reference,
- namespace=instance_name,
- options=element
- )
-
- # Create Asset Container
- lib.create_avalon_container(
- container=container_name, path=asset_dir)
-
- data = {
- "schema": "openpype:container-2.0",
- "id": pipeline.AVALON_CONTAINER_ID,
- "asset": asset,
- "namespace": asset_dir,
- "container_name": container_name,
- "loader": str(self.__class__.__name__),
- "representation": context["representation"]["_id"],
- "parent": context["representation"]["parent"],
- "family": context["representation"]["context"]["family"]
- }
- unreal_pipeline.imprint(
- "{}/{}".format(asset_dir, container_name), data)
-
- asset_content = unreal.EditorAssetLibrary.list_assets(
- asset_dir, recursive=True, include_folder=True
- )
-
- return asset_content
-
- def update(self, container, representation):
- from avalon import api, io
- from avalon.unreal import pipeline
-
- source_path = api.get_representation_path(representation)
-
- with open(source_path, "r") as fp:
- data = json.load(fp)
-
- animation_containers = [
- i for i in pipeline.ls() if
- i.get('asset') == container.get('asset') and
- i.get('family') == 'animation']
-
- for element in data:
- new_version = io.find_one({"_id": io.ObjectId(element.get('_id'))})
- new_version_number = new_version.get('context').get('version')
- anim_container = None
- for i in animation_containers:
- if i.get('container_name') == (element.get('subset') + "_CON"):
- anim_container = i
- break
- if not anim_container:
- continue
-
- api.update(anim_container, new_version_number)
-
- container_path = "{}/{}".format(container["namespace"],
- container["objectName"])
- # update metadata
- pipeline.imprint(
- container_path,
- {
- "representation": str(representation["_id"]),
- "parent": str(representation["parent"])
- })
-
- def remove(self, container):
- unreal.EditorAssetLibrary.delete_directory(container["namespace"])
diff --git a/openpype/hosts/unreal/plugins/publish/extract_look.py b/openpype/hosts/unreal/plugins/publish/extract_look.py
new file mode 100644
index 0000000000..0f1539a7d5
--- /dev/null
+++ b/openpype/hosts/unreal/plugins/publish/extract_look.py
@@ -0,0 +1,120 @@
+import json
+import os
+
+import unreal
+from unreal import MaterialEditingLibrary as mat_lib
+
+import openpype.api
+
+
+class ExtractLook(openpype.api.Extractor):
+ """Extract look."""
+
+ label = "Extract Look"
+ hosts = ["unreal"]
+ families = ["look"]
+ optional = True
+
+ def process(self, instance):
+ # Define extract output file path
+ stagingdir = self.staging_dir(instance)
+ resources_dir = instance.data["resourcesDir"]
+
+ ar = unreal.AssetRegistryHelpers.get_asset_registry()
+
+ transfers = []
+
+ json_data = []
+
+ for member in instance:
+ asset = ar.get_asset_by_object_path(member)
+ object = asset.get_asset()
+
+ name = asset.get_editor_property('asset_name')
+
+ json_element = {'material': str(name)}
+
+ material_obj = object.get_editor_property('static_materials')[0]
+ material = material_obj.material_interface
+
+ base_color = mat_lib.get_material_property_input_node(
+ material, unreal.MaterialProperty.MP_BASE_COLOR)
+
+ base_color_name = base_color.get_editor_property('parameter_name')
+
+ texture = mat_lib.get_material_default_texture_parameter_value(
+ material, base_color_name)
+
+ if texture:
+ # Export Texture
+ tga_filename = f"{instance.name}_{name}_texture.tga"
+
+ tga_exporter = unreal.TextureExporterTGA()
+
+ tga_export_task = unreal.AssetExportTask()
+
+ tga_export_task.set_editor_property('exporter', tga_exporter)
+ tga_export_task.set_editor_property('automated', True)
+ tga_export_task.set_editor_property('object', texture)
+ tga_export_task.set_editor_property(
+ 'filename', f"{stagingdir}/{tga_filename}")
+ tga_export_task.set_editor_property('prompt', False)
+ tga_export_task.set_editor_property('selected', False)
+
+ unreal.Exporter.run_asset_export_task(tga_export_task)
+
+ json_element['tga_filename'] = tga_filename
+
+ transfers.append((
+ f"{stagingdir}/{tga_filename}",
+ f"{resources_dir}/{tga_filename}"))
+
+ fbx_filename = f"{instance.name}_{name}.fbx"
+
+ fbx_exporter = unreal.StaticMeshExporterFBX()
+ fbx_exporter.set_editor_property('text', False)
+
+ options = unreal.FbxExportOption()
+ options.set_editor_property('ascii', False)
+ options.set_editor_property('collision', False)
+
+ task = unreal.AssetExportTask()
+ task.set_editor_property('exporter', fbx_exporter)
+ task.set_editor_property('options', options)
+ task.set_editor_property('automated', True)
+ task.set_editor_property('object', object)
+ task.set_editor_property(
+ 'filename', f"{stagingdir}/{fbx_filename}")
+ task.set_editor_property('prompt', False)
+ task.set_editor_property('selected', False)
+
+ unreal.Exporter.run_asset_export_task(task)
+
+ json_element['fbx_filename'] = fbx_filename
+
+ transfers.append((
+ f"{stagingdir}/{fbx_filename}",
+ f"{resources_dir}/{fbx_filename}"))
+
+ json_data.append(json_element)
+
+ json_filename = f"{instance.name}.json"
+ json_path = os.path.join(stagingdir, json_filename)
+
+ with open(json_path, "w+") as file:
+ json.dump(json_data, fp=file, indent=2)
+
+ if "transfers" not in instance.data:
+ instance.data["transfers"] = []
+ if "representations" not in instance.data:
+ instance.data["representations"] = []
+
+ json_representation = {
+ 'name': 'json',
+ 'ext': 'json',
+ 'files': json_filename,
+ "stagingDir": stagingdir,
+ }
+
+ instance.data["representations"].append(json_representation)
+ instance.data["transfers"].extend(transfers)
diff --git a/openpype/lib/__init__.py b/openpype/lib/__init__.py
index c97545fdf4..02ae9635c1 100644
--- a/openpype/lib/__init__.py
+++ b/openpype/lib/__init__.py
@@ -81,7 +81,13 @@ from .avalon_context import (
get_creator_by_name,
- change_timer_to_current_context
+ get_custom_workfile_template,
+
+ change_timer_to_current_context,
+
+ get_custom_workfile_template_by_context,
+ get_custom_workfile_template_by_string_context,
+ get_custom_workfile_template
)
from .local_settings import (
@@ -192,6 +198,10 @@ __all__ = [
"change_timer_to_current_context",
+ "get_custom_workfile_template_by_context",
+ "get_custom_workfile_template_by_string_context",
+ "get_custom_workfile_template",
+
"IniSettingRegistry",
"JSONSettingRegistry",
"OpenPypeSecureRegistry",
diff --git a/openpype/lib/applications.py b/openpype/lib/applications.py
index a44c43102f..d82b7cd847 100644
--- a/openpype/lib/applications.py
+++ b/openpype/lib/applications.py
@@ -440,7 +440,20 @@ class EnvironmentTool:
class ApplicationExecutable:
+ """Representation of executable loaded from settings."""
+
def __init__(self, executable):
+ # On MacOS check if exists path to executable when ends with `.app`
+ # - it is common that path will lead to "/Applications/Blender" but
+ # real path is "/Applications/Blender.app"
+ if (
+ platform.system().lower() == "darwin"
+ and not os.path.exists(executable)
+ ):
+ _executable = executable + ".app"
+ if os.path.exists(_executable):
+ executable = _executable
+
self.executable_path = executable
def __str__(self):
@@ -1177,17 +1190,23 @@ def prepare_context_environments(data):
try:
workdir = get_workdir_with_workdir_data(workdir_data, anatomy)
- if not os.path.exists(workdir):
- log.debug(
- "Creating workdir folder: \"{}\"".format(workdir)
- )
- os.makedirs(workdir)
except Exception as exc:
raise ApplicationLaunchFailed(
"Error in anatomy.format: {}".format(str(exc))
)
+ if not os.path.exists(workdir):
+ log.debug(
+ "Creating workdir folder: \"{}\"".format(workdir)
+ )
+ try:
+ os.makedirs(workdir)
+ except Exception as exc:
+ raise ApplicationLaunchFailed(
+ "Couldn't create workdir because: {}".format(str(exc))
+ )
+
context_env = {
"AVALON_PROJECT": project_doc["name"],
"AVALON_ASSET": asset_doc["name"],
diff --git a/openpype/lib/avalon_context.py b/openpype/lib/avalon_context.py
index 2a7c58c4ee..c4217cc6d5 100644
--- a/openpype/lib/avalon_context.py
+++ b/openpype/lib/avalon_context.py
@@ -3,6 +3,7 @@ import os
import json
import re
import copy
+import platform
import logging
import collections
import functools
@@ -755,18 +756,22 @@ class BuildWorkfile:
"""
host_name = avalon.api.registered_host().__name__.rsplit(".", 1)[-1]
presets = get_project_settings(avalon.io.Session["AVALON_PROJECT"])
+
# Get presets for host
- build_presets = (
- presets.get(host_name, {})
- .get("workfile_build")
- .get("profiles")
- )
- if not build_presets:
+ wb_settings = presets.get(host_name, {}).get("workfile_builder")
+
+ if not wb_settings:
+ # backward compatibility
+ wb_settings = presets.get(host_name, {}).get("workfile_build")
+
+ builder_presets = wb_settings.get("profiles")
+
+ if not builder_presets:
return
task_name_low = task_name.lower()
per_task_preset = None
- for preset in build_presets:
+ for preset in builder_presets:
preset_tasks = preset.get("tasks") or []
preset_tasks_low = [task.lower() for task in preset_tasks]
if task_name_low in preset_tasks_low:
@@ -1266,3 +1271,201 @@ def change_timer_to_current_context():
}
requests.post(rest_api_url, json=data)
+
+
+def _get_task_context_data_for_anatomy(
+ project_doc, asset_doc, task_name, anatomy=None
+):
+ """Prepare Task context for anatomy data.
+
+ WARNING: this data structure is currently used only in workfile templates.
+ Key "task" is currently in rest of pipeline used as string with task
+ name.
+
+ Args:
+ project_doc (dict): Project document with available "name" and
+ "data.code" keys.
+ asset_doc (dict): Asset document from MongoDB.
+ task_name (str): Name of context task.
+ anatomy (Anatomy): Optionally Anatomy for passed project name can be
+ passed as Anatomy creation may be slow.
+
+ Returns:
+ dict: With Anatomy context data.
+ """
+
+ if anatomy is None:
+ anatomy = Anatomy(project_doc["name"])
+
+ asset_name = asset_doc["name"]
+ project_task_types = anatomy["tasks"]
+
+ # get relevant task type from asset doc
+ assert task_name in asset_doc["data"]["tasks"], (
+ "Task name \"{}\" not found on asset \"{}\"".format(
+ task_name, asset_name
+ )
+ )
+
+ task_type = asset_doc["data"]["tasks"][task_name].get("type")
+
+ assert task_type, (
+ "Task name \"{}\" on asset \"{}\" does not have specified task type."
+ ).format(asset_name, task_name)
+
+ # get short name for task type defined in default anatomy settings
+ project_task_type_data = project_task_types.get(task_type)
+ assert project_task_type_data, (
+ "Something went wrong. Default anatomy tasks are not holding"
+ "requested task type: `{}`".format(task_type)
+ )
+
+ return {
+ "project": {
+ "name": project_doc["name"],
+ "code": project_doc["data"].get("code")
+ },
+ "asset": asset_name,
+ "task": {
+ "name": task_name,
+ "type": task_type,
+ "short_name": project_task_type_data["short_name"]
+ }
+ }
+
+
+def get_custom_workfile_template_by_context(
+ template_profiles, project_doc, asset_doc, task_name, anatomy=None
+):
+ """Filter and fill workfile template profiles by passed context.
+
+ It is expected that passed argument are already queried documents of
+ project and asset as parents of processing task name.
+
+ Existence of formatted path is not validated.
+
+ Args:
+ template_profiles(list): Template profiles from settings.
+ project_doc(dict): Project document from MongoDB.
+ asset_doc(dict): Asset document from MongoDB.
+ task_name(str): Name of task for which templates are filtered.
+ anatomy(Anatomy): Optionally passed anatomy object for passed project
+ name.
+
+ Returns:
+ str: Path to template or None if none of profiles match current
+ context. (Existence of formatted path is not validated.)
+ """
+
+ from openpype.lib import filter_profiles
+
+ if anatomy is None:
+ anatomy = Anatomy(project_doc["name"])
+
+ # get project, asset, task anatomy context data
+ anatomy_context_data = _get_task_context_data_for_anatomy(
+ project_doc, asset_doc, task_name, anatomy
+ )
+ # add root dict
+ anatomy_context_data["root"] = anatomy.roots
+
+ # get task type for the task in context
+ current_task_type = anatomy_context_data["task"]["type"]
+
+ # get path from matching profile
+ matching_item = filter_profiles(
+ template_profiles,
+ {"task_type": current_task_type}
+ )
+ # when path is available try to format it in case
+ # there are some anatomy template strings
+ if matching_item:
+ template = matching_item["path"][platform.system().lower()]
+ return template.format(**anatomy_context_data)
+
+ return None
+
+
+def get_custom_workfile_template_by_string_context(
+ template_profiles, project_name, asset_name, task_name,
+ dbcon=None, anatomy=None
+):
+ """Filter and fill workfile template profiles by passed context.
+
+ Passed context are string representations of project, asset and task.
+ Function will query documents of project and asset to be able use
+ `get_custom_workfile_template_by_context` for rest of logic.
+
+ Args:
+ template_profiles(list): Loaded workfile template profiles.
+ project_name(str): Project name.
+ asset_name(str): Asset name.
+ task_name(str): Task name.
+ dbcon(AvalonMongoDB): Optional avalon implementation of mongo
+ connection with context Session.
+ anatomy(Anatomy): Optionally prepared anatomy object for passed
+ project.
+
+ Returns:
+ str: Path to template or None if none of profiles match current
+ context. (Existence of formatted path is not validated.)
+ """
+
+ if dbcon is None:
+ from avalon.api import AvalonMongoDB
+
+ dbcon = AvalonMongoDB()
+
+ dbcon.install()
+
+ if dbcon.Session["AVALON_PROJECT"] != project_name:
+ dbcon.Session["AVALON_PROJECT"] = project_name
+
+ project_doc = dbcon.find_one(
+ {"type": "project"},
+ # All we need is "name" and "data.code" keys
+ {
+ "name": 1,
+ "data.code": 1
+ }
+ )
+ asset_doc = dbcon.find_one(
+ {
+ "type": "asset",
+ "name": asset_name
+ },
+ # All we need is "name" and "data.tasks" keys
+ {
+ "name": 1,
+ "data.tasks": 1
+ }
+ )
+
+ return get_custom_workfile_template_by_context(
+ template_profiles, project_doc, asset_doc, task_name, anatomy
+ )
+
+
+def get_custom_workfile_template(template_profiles):
+ """Filter and fill workfile template profiles by current context.
+
+ Current context is defined by `avalon.api.Session`. That's why this
+ function should be used only inside host where context is set and stable.
+
+ Args:
+ template_profiles(list): Template profiles from settings.
+
+ Returns:
+ str: Path to template or None if none of profiles match current
+ context. (Existence of formatted path is not validated.)
+ """
+ # Use `avalon.io` as Mongo connection
+ from avalon import io
+
+ return get_custom_workfile_template_by_string_context(
+ template_profiles,
+ io.Session["AVALON_PROJECT"],
+ io.Session["AVALON_ASSET"],
+ io.Session["AVALON_TASK"],
+ io
+ )
diff --git a/openpype/lib/delivery.py b/openpype/lib/delivery.py
new file mode 100644
index 0000000000..943cd9fcaf
--- /dev/null
+++ b/openpype/lib/delivery.py
@@ -0,0 +1,306 @@
+"""Functions useful for delivery action or loader"""
+import os
+import shutil
+import clique
+import collections
+
+def collect_frames(files):
+ """
+ Returns dict of source path and its frame, if from sequence
+
+ Uses clique as most precise solution
+
+ Args:
+ files(list): list of source paths
+ Returns:
+ (dict): {'/asset/subset_v001.0001.png': '0001', ....}
+ """
+ collections, remainder = clique.assemble(files)
+
+ sources_and_frames = {}
+ if collections:
+ for collection in collections:
+ src_head = collection.head
+ src_tail = collection.tail
+
+ for index in collection.indexes:
+ src_frame = collection.format("{padding}") % index
+ src_file_name = "{}{}{}".format(src_head, src_frame,
+ src_tail)
+ sources_and_frames[src_file_name] = src_frame
+ else:
+ sources_and_frames[remainder.pop()] = None
+
+ return sources_and_frames
+
+
+def sizeof_fmt(num, suffix='B'):
+ """Returns formatted string with size in appropriate unit"""
+ for unit in ['', 'Ki', 'Mi', 'Gi', 'Ti', 'Pi', 'Ei', 'Zi']:
+ if abs(num) < 1024.0:
+ return "%3.1f%s%s" % (num, unit, suffix)
+ num /= 1024.0
+ return "%.1f%s%s" % (num, 'Yi', suffix)
+
+
+def path_from_representation(representation, anatomy):
+ from avalon import pipeline # safer importing
+
+ try:
+ template = representation["data"]["template"]
+
+ except KeyError:
+ return None
+
+ try:
+ context = representation["context"]
+ context["root"] = anatomy.roots
+ path = pipeline.format_template_with_optional_keys(
+ context, template
+ )
+
+ except KeyError:
+ # Template references unavailable data
+ return None
+
+ return os.path.normpath(path)
+
+
+def copy_file(src_path, dst_path):
+ """Hardlink file if possible(to save space), copy if not"""
+ from avalon.vendor import filelink # safer importing
+
+ if os.path.exists(dst_path):
+ return
+ try:
+ filelink.create(
+ src_path,
+ dst_path,
+ filelink.HARDLINK
+ )
+ except OSError:
+ shutil.copyfile(src_path, dst_path)
+
+
+def get_format_dict(anatomy, location_path):
+ """Returns replaced root values from user provider value.
+
+ Args:
+ anatomy (Anatomy)
+ location_path (str): user provided value
+ Returns:
+ (dict): prepared for formatting of a template
+ """
+ format_dict = {}
+ if location_path:
+ location_path = location_path.replace("\\", "/")
+ root_names = anatomy.root_names_from_templates(
+ anatomy.templates["delivery"]
+ )
+ if root_names is None:
+ format_dict["root"] = location_path
+ else:
+ format_dict["root"] = {}
+ for name in root_names:
+ format_dict["root"][name] = location_path
+ return format_dict
+
+
+def check_destination_path(repre_id,
+ anatomy, anatomy_data,
+ datetime_data, template_name):
+ """ Try to create destination path based on 'template_name'.
+
+ In the case that path cannot be filled, template contains unmatched
+ keys, provide error message to filter out repre later.
+
+ Args:
+ anatomy (Anatomy)
+ anatomy_data (dict): context to fill anatomy
+ datetime_data (dict): values with actual date
+ template_name (str): to pick correct delivery template
+ Returns:
+ (collections.defauldict): {"TYPE_OF_ERROR":"ERROR_DETAIL"}
+ """
+ anatomy_data.update(datetime_data)
+ anatomy_filled = anatomy.format_all(anatomy_data)
+ dest_path = anatomy_filled["delivery"][template_name]
+ report_items = collections.defaultdict(list)
+
+ if not dest_path.solved:
+ msg = (
+ "Missing keys in Representation's context"
+ " for anatomy template \"{}\"."
+ ).format(template_name)
+
+ sub_msg = (
+ "Representation: {}
"
+ ).format(repre_id)
+
+ if dest_path.missing_keys:
+ keys = ", ".join(dest_path.missing_keys)
+ sub_msg += (
+ "- Missing keys: \"{}\"
"
+ ).format(keys)
+
+ if dest_path.invalid_types:
+ items = []
+ for key, value in dest_path.invalid_types.items():
+ items.append("\"{}\" {}".format(key, str(value)))
+
+ keys = ", ".join(items)
+ sub_msg += (
+ "- Invalid value DataType: \"{}\"
"
+ ).format(keys)
+
+ report_items[msg].append(sub_msg)
+
+ return report_items
+
+
+def process_single_file(
+ src_path, repre, anatomy, template_name, anatomy_data, format_dict,
+ report_items, log
+):
+ """Copy single file to calculated path based on template
+
+ Args:
+ src_path(str): path of source representation file
+ _repre (dict): full repre, used only in process_sequence, here only
+ as to share same signature
+ anatomy (Anatomy)
+ template_name (string): user selected delivery template name
+ anatomy_data (dict): data from repre to fill anatomy with
+ format_dict (dict): root dictionary with names and values
+ report_items (collections.defaultdict): to return error messages
+ log (Logger): for log printing
+ Returns:
+ (collections.defaultdict , int)
+ """
+ if not os.path.exists(src_path):
+ msg = "{} doesn't exist for {}".format(src_path,
+ repre["_id"])
+ report_items["Source file was not found"].append(msg)
+ return report_items, 0
+
+ anatomy_filled = anatomy.format(anatomy_data)
+ if format_dict:
+ template_result = anatomy_filled["delivery"][template_name]
+ delivery_path = template_result.rootless.format(**format_dict)
+ else:
+ delivery_path = anatomy_filled["delivery"][template_name]
+
+ # context.representation could be .psd
+ delivery_path = delivery_path.replace("..", ".")
+
+ delivery_folder = os.path.dirname(delivery_path)
+ if not os.path.exists(delivery_folder):
+ os.makedirs(delivery_folder)
+
+ log.debug("Copying single: {} -> {}".format(src_path, delivery_path))
+ copy_file(src_path, delivery_path)
+
+ return report_items, 1
+
+
+def process_sequence(
+ src_path, repre, anatomy, template_name, anatomy_data, format_dict,
+ report_items, log
+):
+ """ For Pype2(mainly - works in 3 too) where representation might not
+ contain files.
+
+ Uses listing physical files (not 'files' on repre as a)might not be
+ present, b)might not be reliable for representation and copying them.
+
+ TODO Should be refactored when files are sufficient to drive all
+ representations.
+
+ Args:
+ src_path(str): path of source representation file
+ repre (dict): full representation
+ anatomy (Anatomy)
+ template_name (string): user selected delivery template name
+ anatomy_data (dict): data from repre to fill anatomy with
+ format_dict (dict): root dictionary with names and values
+ report_items (collections.defaultdict): to return error messages
+ log (Logger): for log printing
+ Returns:
+ (collections.defaultdict , int)
+ """
+ if not os.path.exists(src_path):
+ msg = "{} doesn't exist for {}".format(src_path,
+ repre["_id"])
+ report_items["Source file was not found"].append(msg)
+ return report_items, 0
+
+ dir_path, file_name = os.path.split(str(src_path))
+
+ context = repre["context"]
+ ext = context.get("ext", context.get("representation"))
+
+ if not ext:
+ msg = "Source extension not found, cannot find collection"
+ report_items[msg].append(src_path)
+ log.warning("{} <{}>".format(msg, context))
+ return report_items, 0
+
+ ext = "." + ext
+ # context.representation could be .psd
+ ext = ext.replace("..", ".")
+
+ src_collections, remainder = clique.assemble(os.listdir(dir_path))
+ src_collection = None
+ for col in src_collections:
+ if col.tail != ext:
+ continue
+
+ src_collection = col
+ break
+
+ if src_collection is None:
+ msg = "Source collection of files was not found"
+ report_items[msg].append(src_path)
+ log.warning("{} <{}>".format(msg, src_path))
+ return report_items, 0
+
+ frame_indicator = "@####@"
+
+ anatomy_data["frame"] = frame_indicator
+ anatomy_filled = anatomy.format(anatomy_data)
+
+ if format_dict:
+ template_result = anatomy_filled["delivery"][template_name]
+ delivery_path = template_result.rootless.format(**format_dict)
+ else:
+ delivery_path = anatomy_filled["delivery"][template_name]
+
+ delivery_folder = os.path.dirname(delivery_path)
+ dst_head, dst_tail = delivery_path.split(frame_indicator)
+ dst_padding = src_collection.padding
+ dst_collection = clique.Collection(
+ head=dst_head,
+ tail=dst_tail,
+ padding=dst_padding
+ )
+
+ if not os.path.exists(delivery_folder):
+ os.makedirs(delivery_folder)
+
+ src_head = src_collection.head
+ src_tail = src_collection.tail
+ uploaded = 0
+ for index in src_collection.indexes:
+ src_padding = src_collection.format("{padding}") % index
+ src_file_name = "{}{}{}".format(src_head, src_padding, src_tail)
+ src = os.path.normpath(
+ os.path.join(dir_path, src_file_name)
+ )
+
+ dst_padding = dst_collection.format("{padding}") % index
+ dst = "{}{}{}".format(dst_head, dst_padding, dst_tail)
+ log.debug("Copying single: {} -> {}".format(src, dst))
+ copy_file(src, dst)
+ uploaded += 1
+
+ return report_items, uploaded
diff --git a/openpype/modules/base.py b/openpype/modules/base.py
index b8d76aa028..441a9731b7 100644
--- a/openpype/modules/base.py
+++ b/openpype/modules/base.py
@@ -139,6 +139,25 @@ class ITrayModule:
"""
pass
+ def execute_in_main_thread(self, callback):
+ """ Pushes callback to the queue or process 'callback' on a main thread
+
+ Some callbacks need to be processed on main thread (menu actions
+ must be added on main thread or they won't get triggered etc.)
+ """
+ # called without initialized tray, still main thread needed
+ if not self.tray_initialized:
+ try:
+ callback = self._main_thread_callbacks.popleft()
+ callback()
+ except:
+ self.log.warning(
+ "Failed to execute {} in main thread".format(callback),
+ exc_info=True)
+
+ return
+ self.manager.tray_manager.execute_in_main_thread(callback)
+
def show_tray_message(self, title, message, icon=None, msecs=None):
"""Show tray message.
@@ -680,6 +699,10 @@ class TrayModulesManager(ModulesManager):
output.append(module)
return output
+ def restart_tray(self):
+ if self.tray_manager:
+ self.tray_manager.restart()
+
def tray_init(self):
report = {}
time_start = time.time()
diff --git a/openpype/modules/deadline/plugins/publish/submit_publish_job.py b/openpype/modules/deadline/plugins/publish/submit_publish_job.py
index a485f432e2..99c5f6536c 100644
--- a/openpype/modules/deadline/plugins/publish/submit_publish_job.py
+++ b/openpype/modules/deadline/plugins/publish/submit_publish_job.py
@@ -105,7 +105,7 @@ class ProcessSubmittedJobOnFarm(pyblish.api.InstancePlugin):
families = ["render.farm", "prerender.farm",
"renderlayer", "imagesequence", "vrayscene"]
- aov_filter = {"maya": [r".+(?:\.|_)([Bb]eauty)(?:\.|_).*"],
+ aov_filter = {"maya": [r".*(?:\.|_)?([Bb]eauty)(?:\.|_)?.*"],
"aftereffects": [r".*"], # for everything from AE
"harmony": [r".*"], # for everything from AE
"celaction": [r".*"]}
diff --git a/openpype/modules/ftrack/event_handlers_server/event_sync_to_avalon.py b/openpype/modules/ftrack/event_handlers_server/event_sync_to_avalon.py
index 410e51e2a4..e60045bd50 100644
--- a/openpype/modules/ftrack/event_handlers_server/event_sync_to_avalon.py
+++ b/openpype/modules/ftrack/event_handlers_server/event_sync_to_avalon.py
@@ -1101,9 +1101,6 @@ class SyncToAvalonEvent(BaseEvent):
# Parents, Hierarchy
ent_path_items = [ent["name"] for ent in ftrack_ent["link"]]
parents = ent_path_items[1:len(ent_path_items)-1:]
- hierarchy = ""
- if len(parents) > 0:
- hierarchy = os.path.sep.join(parents)
# TODO logging
self.log.debug(
@@ -1132,7 +1129,6 @@ class SyncToAvalonEvent(BaseEvent):
"ftrackId": ftrack_ent["id"],
"entityType": ftrack_ent.entity_type,
"parents": parents,
- "hierarchy": hierarchy,
"tasks": {},
"visualParent": vis_par
}
@@ -1975,14 +1971,9 @@ class SyncToAvalonEvent(BaseEvent):
if cur_par == parents:
continue
- hierarchy = ""
- if len(parents) > 0:
- hierarchy = os.path.sep.join(parents)
-
if "data" not in self.updates[mongo_id]:
self.updates[mongo_id]["data"] = {}
self.updates[mongo_id]["data"]["parents"] = parents
- self.updates[mongo_id]["data"]["hierarchy"] = hierarchy
# Skip custom attributes if didn't change
if not hier_cust_attrs_ids:
diff --git a/openpype/modules/ftrack/event_handlers_user/action_delete_asset.py b/openpype/modules/ftrack/event_handlers_user/action_delete_asset.py
index ff39db4383..c20491349f 100644
--- a/openpype/modules/ftrack/event_handlers_user/action_delete_asset.py
+++ b/openpype/modules/ftrack/event_handlers_user/action_delete_asset.py
@@ -11,23 +11,28 @@ from avalon.api import AvalonMongoDB
class DeleteAssetSubset(BaseAction):
'''Edit meta data action.'''
- #: Action identifier.
+ # Action identifier.
identifier = "delete.asset.subset"
- #: Action label.
+ # Action label.
label = "Delete Asset/Subsets"
- #: Action description.
+ # Action description.
description = "Removes from Avalon with all childs and asset from Ftrack"
icon = statics_icon("ftrack", "action_icons", "DeleteAsset.svg")
settings_key = "delete_asset_subset"
- #: Db connection
- dbcon = AvalonMongoDB()
+ # Db connection
+ dbcon = None
splitter = {"type": "label", "value": "---"}
action_data_by_id = {}
asset_prefix = "asset:"
subset_prefix = "subset:"
+ def __init__(self, *args, **kwargs):
+ self.dbcon = AvalonMongoDB()
+
+ super(DeleteAssetSubset, self).__init__(*args, **kwargs)
+
def discover(self, session, entities, event):
""" Validation """
task_ids = []
@@ -446,7 +451,14 @@ class DeleteAssetSubset(BaseAction):
if len(assets_to_delete) > 0:
map_av_ftrack_id = spec_data["without_ftrack_id"]
# Prepare data when deleting whole avalon asset
- avalon_assets = self.dbcon.find({"type": "asset"})
+ avalon_assets = self.dbcon.find(
+ {"type": "asset"},
+ {
+ "_id": 1,
+ "data.visualParent": 1,
+ "data.ftrackId": 1
+ }
+ )
avalon_assets_by_parent = collections.defaultdict(list)
for asset in avalon_assets:
asset_id = asset["_id"]
@@ -537,11 +549,13 @@ class DeleteAssetSubset(BaseAction):
ftrack_proc_txt, ", ".join(ftrack_ids_to_delete)
))
- ftrack_ents_to_delete = (
+ entities_by_link_len = (
self._filter_entities_to_delete(ftrack_ids_to_delete, session)
)
- for entity in ftrack_ents_to_delete:
- session.delete(entity)
+ for link_len in sorted(entities_by_link_len.keys(), reverse=True):
+ for entity in entities_by_link_len[link_len]:
+ session.delete(entity)
+
try:
session.commit()
except Exception:
@@ -600,29 +614,11 @@ class DeleteAssetSubset(BaseAction):
joined_ids_to_delete
)
).all()
- filtered = to_delete_entities[:]
- while True:
- changed = False
- _filtered = filtered[:]
- for entity in filtered:
- entity_id = entity["id"]
+ entities_by_link_len = collections.defaultdict(list)
+ for entity in to_delete_entities:
+ entities_by_link_len[len(entity["link"])].append(entity)
- for _entity in tuple(_filtered):
- if entity_id == _entity["id"]:
- continue
-
- for _link in _entity["link"]:
- if entity_id == _link["id"] and _entity in _filtered:
- _filtered.remove(_entity)
- changed = True
- break
-
- filtered = _filtered
-
- if not changed:
- break
-
- return filtered
+ return entities_by_link_len
def report_handle(self, report_messages, project_name, event):
if not report_messages:
diff --git a/openpype/modules/ftrack/event_handlers_user/action_delivery.py b/openpype/modules/ftrack/event_handlers_user/action_delivery.py
index 88fdbe3669..2e7599647a 100644
--- a/openpype/modules/ftrack/event_handlers_user/action_delivery.py
+++ b/openpype/modules/ftrack/event_handlers_user/action_delivery.py
@@ -1,18 +1,20 @@
import os
import copy
import json
-import shutil
import collections
-import clique
from bson.objectid import ObjectId
-from avalon import pipeline
-from avalon.vendor import filelink
-
from openpype.api import Anatomy, config
from openpype.modules.ftrack.lib import BaseAction, statics_icon
from openpype.modules.ftrack.lib.avalon_sync import CUST_ATTR_ID_KEY
+from openpype.lib.delivery import (
+ path_from_representation,
+ get_format_dict,
+ check_destination_path,
+ process_single_file,
+ process_sequence
+)
from avalon.api import AvalonMongoDB
@@ -72,7 +74,7 @@ class Delivery(BaseAction):
"value": project_name
})
- # Prpeare anatomy data
+ # Prepare anatomy data
anatomy = Anatomy(project_name)
new_anatomies = []
first = None
@@ -366,12 +368,18 @@ class Delivery(BaseAction):
def launch(self, session, entities, event):
if "values" not in event["data"]:
- return
+ return {
+ "success": True,
+ "message": "Nothing to do"
+ }
values = event["data"]["values"]
skipped = values.pop("__skipped__")
if skipped:
- return None
+ return {
+ "success": False,
+ "message": "Action skipped"
+ }
user_id = event["source"]["user"]["id"]
user_entity = session.query(
@@ -389,27 +397,45 @@ class Delivery(BaseAction):
try:
self.db_con.install()
- self.real_launch(session, entities, event)
- job["status"] = "done"
+ report = self.real_launch(session, entities, event)
- except Exception:
+ except Exception as exc:
+ report = {
+ "success": False,
+ "title": "Delivery failed",
+ "items": [{
+ "type": "label",
+ "value": (
+ "Error during delivery action process:
{}"
+ "
Check logs for more information."
+ ).format(str(exc))
+ }]
+ }
self.log.warning(
"Failed during processing delivery action.",
exc_info=True
)
finally:
- if job["status"] != "done":
+ if report["success"]:
+ job["status"] = "done"
+ else:
job["status"] = "failed"
session.commit()
self.db_con.uninstall()
- if job["status"] == "failed":
+ if not report["success"]:
+ self.show_interface(
+ items=report["items"],
+ title=report["title"],
+ event=event
+ )
return {
"success": False,
- "message": "Delivery failed. Check logs for more information."
+ "message": "Errors during delivery process. See report."
}
- return True
+
+ return report
def real_launch(self, session, entities, event):
self.log.info("Delivery action just started.")
@@ -429,7 +455,7 @@ class Delivery(BaseAction):
if not repre_names:
return {
"success": True,
- "message": "Not selected components to deliver."
+ "message": "No selected components to deliver."
}
location_path = location_path.strip()
@@ -450,18 +476,7 @@ class Delivery(BaseAction):
anatomy = Anatomy(project_name)
- format_dict = {}
- if location_path:
- location_path = location_path.replace("\\", "/")
- root_names = anatomy.root_names_from_templates(
- anatomy.templates["delivery"]
- )
- if root_names is None:
- format_dict["root"] = location_path
- else:
- format_dict["root"] = {}
- for name in root_names:
- format_dict["root"][name] = location_path
+ format_dict = get_format_dict(anatomy, location_path)
datetime_data = config.get_datetime_data()
for repre in repres_to_deliver:
@@ -471,41 +486,15 @@ class Delivery(BaseAction):
debug_msg += " with published path {}.".format(source_path)
self.log.debug(debug_msg)
- # Get destination repre path
anatomy_data = copy.deepcopy(repre["context"])
- anatomy_data.update(datetime_data)
- anatomy_filled = anatomy.format_all(anatomy_data)
- test_path = anatomy_filled["delivery"][anatomy_name]
+ repre_report_items = check_destination_path(repre["_id"],
+ anatomy,
+ anatomy_data,
+ datetime_data,
+ anatomy_name)
- if not test_path.solved:
- msg = (
- "Missing keys in Representation's context"
- " for anatomy template \"{}\"."
- ).format(anatomy_name)
-
- if test_path.missing_keys:
- keys = ", ".join(test_path.missing_keys)
- sub_msg = (
- "Representation: {}
- Missing keys: \"{}\"
"
- ).format(str(repre["_id"]), keys)
-
- if test_path.invalid_types:
- items = []
- for key, value in test_path.invalid_types.items():
- items.append("\"{}\" {}".format(key, str(value)))
-
- keys = ", ".join(items)
- sub_msg = (
- "Representation: {}
"
- "- Invalid value DataType: \"{}\"
"
- ).format(str(repre["_id"]), keys)
-
- report_items[msg].append(sub_msg)
- self.log.warning(
- "{} Representation: \"{}\" Filled: <{}>".format(
- msg, str(repre["_id"]), str(test_path)
- )
- )
+ if repre_report_items:
+ report_items.update(repre_report_items)
continue
# Get source repre path
@@ -514,153 +503,30 @@ class Delivery(BaseAction):
if frame:
repre["context"]["frame"] = len(str(frame)) * "#"
- repre_path = self.path_from_represenation(repre, anatomy)
+ repre_path = path_from_representation(repre, anatomy)
# TODO add backup solution where root of path from component
- # is repalced with root
+ # is replaced with root
args = (
repre_path,
+ repre,
anatomy,
anatomy_name,
anatomy_data,
format_dict,
- report_items
+ report_items,
+ self.log
)
if not frame:
- self.process_single_file(*args)
+ process_single_file(*args)
else:
- self.process_sequence(*args)
+ process_sequence(*args)
return self.report(report_items)
- def process_single_file(
- self, repre_path, anatomy, anatomy_name, anatomy_data, format_dict,
- report_items
- ):
- anatomy_filled = anatomy.format(anatomy_data)
- if format_dict:
- template_result = anatomy_filled["delivery"][anatomy_name]
- delivery_path = template_result.rootless.format(**format_dict)
- else:
- delivery_path = anatomy_filled["delivery"][anatomy_name]
-
- delivery_folder = os.path.dirname(delivery_path)
- if not os.path.exists(delivery_folder):
- os.makedirs(delivery_folder)
-
- self.copy_file(repre_path, delivery_path)
-
- def process_sequence(
- self, repre_path, anatomy, anatomy_name, anatomy_data, format_dict,
- report_items
- ):
- dir_path, file_name = os.path.split(str(repre_path))
-
- base_name, ext = os.path.splitext(file_name)
- file_name_items = None
- if "#" in base_name:
- file_name_items = [part for part in base_name.split("#") if part]
-
- elif "%" in base_name:
- file_name_items = base_name.split("%")
-
- if not file_name_items:
- msg = "Source file was not found"
- report_items[msg].append(repre_path)
- self.log.warning("{} <{}>".format(msg, repre_path))
- return
-
- src_collections, remainder = clique.assemble(os.listdir(dir_path))
- src_collection = None
- for col in src_collections:
- if col.tail != ext:
- continue
-
- # skip if collection don't have same basename
- if not col.head.startswith(file_name_items[0]):
- continue
-
- src_collection = col
- break
-
- if src_collection is None:
- # TODO log error!
- msg = "Source collection of files was not found"
- report_items[msg].append(repre_path)
- self.log.warning("{} <{}>".format(msg, repre_path))
- return
-
- frame_indicator = "@####@"
-
- anatomy_data["frame"] = frame_indicator
- anatomy_filled = anatomy.format(anatomy_data)
-
- if format_dict:
- template_result = anatomy_filled["delivery"][anatomy_name]
- delivery_path = template_result.rootless.format(**format_dict)
- else:
- delivery_path = anatomy_filled["delivery"][anatomy_name]
-
- delivery_folder = os.path.dirname(delivery_path)
- dst_head, dst_tail = delivery_path.split(frame_indicator)
- dst_padding = src_collection.padding
- dst_collection = clique.Collection(
- head=dst_head,
- tail=dst_tail,
- padding=dst_padding
- )
-
- if not os.path.exists(delivery_folder):
- os.makedirs(delivery_folder)
-
- src_head = src_collection.head
- src_tail = src_collection.tail
- for index in src_collection.indexes:
- src_padding = src_collection.format("{padding}") % index
- src_file_name = "{}{}{}".format(src_head, src_padding, src_tail)
- src = os.path.normpath(
- os.path.join(dir_path, src_file_name)
- )
-
- dst_padding = dst_collection.format("{padding}") % index
- dst = "{}{}{}".format(dst_head, dst_padding, dst_tail)
-
- self.copy_file(src, dst)
-
- def path_from_represenation(self, representation, anatomy):
- try:
- template = representation["data"]["template"]
-
- except KeyError:
- return None
-
- try:
- context = representation["context"]
- context["root"] = anatomy.roots
- path = pipeline.format_template_with_optional_keys(
- context, template
- )
-
- except KeyError:
- # Template references unavailable data
- return None
-
- return os.path.normpath(path)
-
- def copy_file(self, src_path, dst_path):
- if os.path.exists(dst_path):
- return
- try:
- filelink.create(
- src_path,
- dst_path,
- filelink.HARDLINK
- )
- except OSError:
- shutil.copyfile(src_path, dst_path)
-
def report(self, report_items):
+ """Returns dict with final status of delivery (succes, fail etc.)."""
items = []
- title = "Delivery report"
+
for msg, _items in report_items.items():
if not _items:
continue
@@ -691,9 +557,8 @@ class Delivery(BaseAction):
return {
"items": items,
- "title": title,
- "success": False,
- "message": "Delivery Finished"
+ "title": "Delivery report",
+ "success": False
}
diff --git a/openpype/modules/ftrack/ftrack_server/event_server_cli.py b/openpype/modules/ftrack/ftrack_server/event_server_cli.py
index b5cc1bef3e..8bba22b475 100644
--- a/openpype/modules/ftrack/ftrack_server/event_server_cli.py
+++ b/openpype/modules/ftrack/ftrack_server/event_server_cli.py
@@ -422,17 +422,18 @@ def run_event_server(
ftrack_url,
ftrack_user,
ftrack_api_key,
- ftrack_events_path,
- no_stored_credentials,
- store_credentials,
legacy,
clockify_api_key,
clockify_workspace
):
- if not no_stored_credentials:
+ if not ftrack_user or not ftrack_api_key:
+ print((
+ "Ftrack user/api key were not passed."
+ " Trying to use credentials from user keyring."
+ ))
cred = credentials.get_credentials(ftrack_url)
- username = cred.get('username')
- api_key = cred.get('api_key')
+ ftrack_user = cred.get("username")
+ ftrack_api_key = cred.get("api_key")
if clockify_workspace and clockify_api_key:
os.environ["CLOCKIFY_WORKSPACE"] = clockify_workspace
@@ -445,209 +446,16 @@ def run_event_server(
return 1
# Validate entered credentials
- if not validate_credentials(ftrack_url, username, api_key):
+ if not validate_credentials(ftrack_url, ftrack_user, ftrack_api_key):
print('Exiting! < Please enter valid credentials >')
return 1
- if store_credentials:
- credentials.save_credentials(username, api_key, ftrack_url)
-
# Set Ftrack environments
os.environ["FTRACK_SERVER"] = ftrack_url
- os.environ["FTRACK_API_USER"] = username
- os.environ["FTRACK_API_KEY"] = api_key
- # TODO This won't work probably
- if ftrack_events_path:
- if isinstance(ftrack_events_path, (list, tuple)):
- ftrack_events_path = os.pathsep.join(ftrack_events_path)
- os.environ["FTRACK_EVENTS_PATH"] = ftrack_events_path
+ os.environ["FTRACK_API_USER"] = ftrack_user
+ os.environ["FTRACK_API_KEY"] = ftrack_api_key
if legacy:
return legacy_server(ftrack_url)
return main_loop(ftrack_url)
-
-
-def main(argv):
- '''
- There are 4 values neccessary for event server:
- 1.) Ftrack url - "studio.ftrackapp.com"
- 2.) Username - "my.username"
- 3.) API key - "apikey-long11223344-6665588-5565"
- 4.) Path/s to events - "X:/path/to/folder/with/events"
-
- All these values can be entered with arguments or environment variables.
- - arguments:
- "-ftrackurl {url}"
- "-ftrackuser {username}"
- "-ftrackapikey {api key}"
- "-ftrackeventpaths {path to events}"
- - environment variables:
- FTRACK_SERVER
- FTRACK_API_USER
- FTRACK_API_KEY
- FTRACK_EVENTS_PATH
-
- Credentials (Username & API key):
- - Credentials can be stored for auto load on next start
- - To *Store/Update* these values add argument "-storecred"
- - They will be stored to appsdir file when login is successful
- - To *Update/Override* values with enviromnet variables is also needed to:
- - *don't enter argument for that value*
- - add argument "-noloadcred" (currently stored credentials won't be loaded)
-
- Order of getting values:
- 1.) Arguments are always used when entered.
- - entered values through args have most priority! (in each case)
- 2.) Credentials are tried to load from appsdir file.
- - skipped when credentials were entered through args or credentials
- are not stored yet
- - can be skipped with "-noloadcred" argument
- 3.) Environment variables are last source of values.
- - will try to get not yet set values from environments
-
- Best practice:
- - set environment variables FTRACK_SERVER & FTRACK_EVENTS_PATH
- - launch event_server_cli with args:
- ~/event_server_cli.py -ftrackuser "{username}" -ftrackapikey "{API key}" -storecred
- - next time launch event_server_cli.py only with set environment variables
- FTRACK_SERVER & FTRACK_EVENTS_PATH
- '''
- parser = argparse.ArgumentParser(description='Ftrack event server')
- parser.add_argument(
- "-ftrackurl", type=str, metavar='FTRACKURL',
- help=(
- "URL to ftrack server where events should handle"
- " (default from environment: $FTRACK_SERVER)"
- )
- )
- parser.add_argument(
- "-ftrackuser", type=str,
- help=(
- "Username should be the username of the user in ftrack"
- " to record operations against."
- " (default from environment: $FTRACK_API_USER)"
- )
- )
- parser.add_argument(
- "-ftrackapikey", type=str,
- help=(
- "Should be the API key to use for authentication"
- " (default from environment: $FTRACK_API_KEY)"
- )
- )
- parser.add_argument(
- "-ftrackeventpaths", nargs='+',
- help=(
- "List of paths where events are stored."
- " (default from environment: $FTRACK_EVENTS_PATH)"
- )
- )
- parser.add_argument(
- '-storecred',
- help=(
- "Entered credentials will be also stored"
- " to apps dir for future usage"
- ),
- action="store_true"
- )
- parser.add_argument(
- '-noloadcred',
- help="Load creadentials from apps dir",
- action="store_true"
- )
- parser.add_argument(
- '-legacy',
- help="Load creadentials from apps dir",
- action="store_true"
- )
- parser.add_argument(
- "-clockifyapikey", type=str,
- help=(
- "Enter API key for Clockify actions."
- " (default from environment: $CLOCKIFY_API_KEY)"
- )
- )
- parser.add_argument(
- "-clockifyworkspace", type=str,
- help=(
- "Enter workspace for Clockify."
- " (default from module presets or "
- "environment: $CLOCKIFY_WORKSPACE)"
- )
- )
- ftrack_url = os.environ.get("FTRACK_SERVER")
- username = os.environ.get("FTRACK_API_USER")
- api_key = os.environ.get("FTRACK_API_KEY")
-
- kwargs, args = parser.parse_known_args(argv)
-
- if kwargs.ftrackurl:
- ftrack_url = kwargs.ftrackurl
-
- # Load Ftrack url from settings if not set
- if not ftrack_url:
- ftrack_url = get_ftrack_url_from_settings()
-
- event_paths = None
- if kwargs.ftrackeventpaths:
- event_paths = kwargs.ftrackeventpaths
-
- if not kwargs.noloadcred:
- cred = credentials.get_credentials(ftrack_url)
- username = cred.get('username')
- api_key = cred.get('api_key')
-
- if kwargs.ftrackuser:
- username = kwargs.ftrackuser
-
- if kwargs.ftrackapikey:
- api_key = kwargs.ftrackapikey
-
- if kwargs.clockifyworkspace:
- os.environ["CLOCKIFY_WORKSPACE"] = kwargs.clockifyworkspace
-
- if kwargs.clockifyapikey:
- os.environ["CLOCKIFY_API_KEY"] = kwargs.clockifyapikey
-
- legacy = kwargs.legacy
-
- # Check url regex and accessibility
- ftrack_url = check_ftrack_url(ftrack_url)
- if not ftrack_url:
- print('Exiting! < Please enter Ftrack server url >')
- return 1
-
- # Validate entered credentials
- if not validate_credentials(ftrack_url, username, api_key):
- print('Exiting! < Please enter valid credentials >')
- return 1
-
- if kwargs.storecred:
- credentials.save_credentials(username, api_key, ftrack_url)
-
- # Set Ftrack environments
- os.environ["FTRACK_SERVER"] = ftrack_url
- os.environ["FTRACK_API_USER"] = username
- os.environ["FTRACK_API_KEY"] = api_key
- if event_paths:
- if isinstance(event_paths, (list, tuple)):
- event_paths = os.pathsep.join(event_paths)
- os.environ["FTRACK_EVENTS_PATH"] = event_paths
-
- if legacy:
- return legacy_server(ftrack_url)
-
- return main_loop(ftrack_url)
-
-
-if __name__ == "__main__":
- # Register interupt signal
- def signal_handler(sig, frame):
- print("You pressed Ctrl+C. Process ended.")
- sys.exit(0)
-
- signal.signal(signal.SIGINT, signal_handler)
- signal.signal(signal.SIGTERM, signal_handler)
-
- sys.exit(main(sys.argv))
diff --git a/openpype/modules/ftrack/lib/avalon_sync.py b/openpype/modules/ftrack/lib/avalon_sync.py
index a3b926464e..5d1da005dc 100644
--- a/openpype/modules/ftrack/lib/avalon_sync.py
+++ b/openpype/modules/ftrack/lib/avalon_sync.py
@@ -1237,12 +1237,8 @@ class SyncEntitiesFactory:
ent_path_items = [ent["name"] for ent in entity["link"]]
parents = ent_path_items[1:len(ent_path_items) - 1:]
- hierarchy = ""
- if len(parents) > 0:
- hierarchy = os.path.sep.join(parents)
data["parents"] = parents
- data["hierarchy"] = hierarchy
data["tasks"] = self.entities_dict[id].pop("tasks", {})
self.entities_dict[id]["final_entity"]["data"] = data
self.entities_dict[id]["final_entity"]["type"] = "asset"
@@ -2169,8 +2165,6 @@ class SyncEntitiesFactory:
hierarchy = "/".join(parents)
self.entities_dict[ftrack_id][
"final_entity"]["data"]["parents"] = parents
- self.entities_dict[ftrack_id][
- "final_entity"]["data"]["hierarchy"] = hierarchy
_parents.append(self.entities_dict[ftrack_id]["name"])
for child_id in self.entities_dict[ftrack_id]["children"]:
@@ -2181,7 +2175,6 @@ class SyncEntitiesFactory:
if "data" not in self.updates[mongo_id]:
self.updates[mongo_id]["data"] = {}
self.updates[mongo_id]["data"]["parents"] = parents
- self.updates[mongo_id]["data"]["hierarchy"] = hierarchy
def prepare_project_changes(self):
ftrack_ent_dict = self.entities_dict[self.ft_project_id]
diff --git a/openpype/modules/ftrack/tray/login_tools.py b/openpype/modules/ftrack/tray/login_tools.py
index c6cf5b5f7b..95a072c352 100644
--- a/openpype/modules/ftrack/tray/login_tools.py
+++ b/openpype/modules/ftrack/tray/login_tools.py
@@ -16,6 +16,18 @@ class LoginServerHandler(BaseHTTPRequestHandler):
self.login_callback = login_callback
BaseHTTPRequestHandler.__init__(self, *args, **kw)
+ def log_message(self, format_str, *args):
+ """Override method of BaseHTTPRequestHandler.
+
+ Goal is to use `print` instead of `sys.stderr.write`
+ """
+ # Change
+ print("%s - - [%s] %s\n" % (
+ self.client_address[0],
+ self.log_date_time_string(),
+ format_str % args
+ ))
+
def do_GET(self):
'''Override to handle requests ourselves.'''
parsed_path = parse.urlparse(self.path)
diff --git a/openpype/modules/settings_action.py b/openpype/modules/settings_action.py
index 5651868f68..f5bcb5342d 100644
--- a/openpype/modules/settings_action.py
+++ b/openpype/modules/settings_action.py
@@ -67,6 +67,10 @@ class SettingsAction(PypeModule, ITrayAction):
return
from openpype.tools.settings import MainWidget
self.settings_window = MainWidget(self.user_role)
+ self.settings_window.trigger_restart.connect(self._on_trigger_restart)
+
+ def _on_trigger_restart(self):
+ self.manager.restart_tray()
def show_settings_window(self):
"""Show settings tool window.
diff --git a/openpype/modules/standalonepublish_action.py b/openpype/modules/standalonepublish_action.py
index 87f7446341..78d87cb6c7 100644
--- a/openpype/modules/standalonepublish_action.py
+++ b/openpype/modules/standalonepublish_action.py
@@ -1,5 +1,5 @@
import os
-import sys
+import platform
import subprocess
from openpype.lib import get_pype_execute_args
from . import PypeModule, ITrayAction
@@ -35,4 +35,14 @@ class StandAlonePublishAction(PypeModule, ITrayAction):
def run_standalone_publisher(self):
args = get_pype_execute_args("standalonepublisher")
- subprocess.Popen(args, creationflags=subprocess.DETACHED_PROCESS)
+ kwargs = {}
+ if platform.system().lower() == "darwin":
+ new_args = ["open", "-a", args.pop(0), "--args"]
+ new_args.extend(args)
+ args = new_args
+
+ detached_process = getattr(subprocess, "DETACHED_PROCESS", None)
+ if detached_process is not None:
+ kwargs["creationflags"] = detached_process
+
+ subprocess.Popen(args, **kwargs)
diff --git a/openpype/modules/webserver/host_console_listener.py b/openpype/modules/webserver/host_console_listener.py
new file mode 100644
index 0000000000..9dd7dcc9b6
--- /dev/null
+++ b/openpype/modules/webserver/host_console_listener.py
@@ -0,0 +1,151 @@
+import aiohttp
+from aiohttp import web
+import json
+import logging
+from concurrent.futures import CancelledError
+from Qt import QtWidgets
+
+from openpype.modules import ITrayService
+from openpype.tools.tray_app.app import ConsoleDialog
+
+log = logging.getLogger(__name__)
+
+
+class IconType:
+ IDLE = "idle"
+ RUNNING = "running"
+ FAILED = "failed"
+
+
+class MsgAction:
+ CONNECTING = "connecting"
+ INITIALIZED = "initialized"
+ ADD = "add"
+ CLOSE = "close"
+
+
+class HostListener:
+ def __init__(self, webserver, module):
+ self._window_per_id = {}
+ self.module = module
+ self.webserver = webserver
+ self._window_per_id = {} # dialogs per host name
+ self._action_per_id = {} # QAction per host name
+
+ webserver.add_route('*', "/ws/host_listener", self.websocket_handler)
+
+ def _host_is_connecting(self, host_name, label):
+ """ Initialize dialog, adds to submenu. """
+ services_submenu = self.module._services_submenu
+ action = QtWidgets.QAction(label, services_submenu)
+ action.triggered.connect(lambda: self.show_widget(host_name))
+
+ services_submenu.addAction(action)
+ self._action_per_id[host_name] = action
+ self._set_host_icon(host_name, IconType.IDLE)
+ widget = ConsoleDialog("")
+ self._window_per_id[host_name] = widget
+
+ def _set_host_icon(self, host_name, icon_type):
+ """Assigns icon to action for 'host_name' with 'icon_type'.
+
+ Action must exist in self._action_per_id
+
+ Args:
+ host_name (str)
+ icon_type (IconType)
+ """
+ action = self._action_per_id.get(host_name)
+ if not action:
+ raise ValueError("Unknown host {}".format(host_name))
+
+ icon = None
+ if icon_type == IconType.IDLE:
+ icon = ITrayService.get_icon_idle()
+ elif icon_type == IconType.RUNNING:
+ icon = ITrayService.get_icon_running()
+ elif icon_type == IconType.FAILED:
+ icon = ITrayService.get_icon_failed()
+ else:
+ log.info("Unknown icon type {} for {}".format(icon_type,
+ host_name))
+ action.setIcon(icon)
+
+ def show_widget(self, host_name):
+ """Shows prepared widget for 'host_name'.
+
+ Dialog get initialized when 'host_name' is connecting.
+ """
+ self.module.execute_in_main_thread(
+ lambda: self._show_widget(host_name))
+
+ def _show_widget(self, host_name):
+ widget = self._window_per_id[host_name]
+ widget.show()
+ widget.raise_()
+ widget.activateWindow()
+
+ async def websocket_handler(self, request):
+ ws = web.WebSocketResponse()
+ await ws.prepare(request)
+
+ widget = None
+ try:
+ async for msg in ws:
+ if msg.type == aiohttp.WSMsgType.TEXT:
+ host_name, action, text = self._parse_message(msg)
+
+ if action == MsgAction.CONNECTING:
+ self._action_per_id[host_name] = None
+ # must be sent to main thread, or action wont trigger
+ self.module.execute_in_main_thread(
+ lambda: self._host_is_connecting(host_name, text))
+ elif action == MsgAction.CLOSE:
+ # clean close
+ self._close(host_name)
+ await ws.close()
+ elif action == MsgAction.INITIALIZED:
+ self.module.execute_in_main_thread(
+ # must be queued as _host_is_connecting might not
+ # be triggered/finished yet
+ lambda: self._set_host_icon(host_name,
+ IconType.RUNNING))
+ elif action == MsgAction.ADD:
+ self.module.execute_in_main_thread(
+ lambda: self._add_text(host_name, text))
+ elif msg.type == aiohttp.WSMsgType.ERROR:
+ print('ws connection closed with exception %s' %
+ ws.exception())
+ host_name, _, _ = self._parse_message(msg)
+ self._set_host_icon(host_name, IconType.FAILED)
+ except CancelledError: # recoverable
+ pass
+ except Exception as exc:
+ log.warning("Exception during communication", exc_info=True)
+ if widget:
+ error_msg = str(exc)
+ widget.append_text(error_msg)
+
+ return ws
+
+ def _add_text(self, host_name, text):
+ widget = self._window_per_id[host_name]
+ widget.append_text(text)
+
+ def _close(self, host_name):
+ """ Clean close - remove from menu, delete widget."""
+ services_submenu = self.module._services_submenu
+ action = self._action_per_id.pop(host_name)
+ services_submenu.removeAction(action)
+ widget = self._window_per_id.pop(host_name)
+ if widget.isVisible():
+ widget.hide()
+ widget.deleteLater()
+
+ def _parse_message(self, msg):
+ data = json.loads(msg.data)
+ action = data.get("action")
+ host_name = data["host"]
+ value = data.get("text")
+
+ return host_name, action, value
diff --git a/openpype/modules/webserver/webserver_module.py b/openpype/modules/webserver/webserver_module.py
index 59a0a08427..2d88aff40d 100644
--- a/openpype/modules/webserver/webserver_module.py
+++ b/openpype/modules/webserver/webserver_module.py
@@ -7,6 +7,8 @@ import six
from openpype import resources
from .. import PypeModule, ITrayService
+from openpype.modules.webserver.host_console_listener import HostListener
+
@six.add_metaclass(ABCMeta)
class IWebServerRoutes:
@@ -23,6 +25,7 @@ class WebServerModule(PypeModule, ITrayService):
def initialize(self, _module_settings):
self.enabled = True
self.server_manager = None
+ self._host_listener = None
self.port = self.find_free_port()
@@ -37,6 +40,7 @@ class WebServerModule(PypeModule, ITrayService):
def tray_init(self):
self.create_server_manager()
self._add_resources_statics()
+ self._add_listeners()
def tray_start(self):
self.start_server()
@@ -54,6 +58,9 @@ class WebServerModule(PypeModule, ITrayService):
webserver_url, static_prefix
)
+ def _add_listeners(self):
+ self._host_listener = HostListener(self.server_manager, self)
+
def start_server(self):
if self.server_manager:
self.server_manager.start_server()
diff --git a/openpype/plugins/load/delivery.py b/openpype/plugins/load/delivery.py
new file mode 100644
index 0000000000..3753f1bfc9
--- /dev/null
+++ b/openpype/plugins/load/delivery.py
@@ -0,0 +1,318 @@
+from collections import defaultdict
+import copy
+
+from Qt import QtWidgets, QtCore, QtGui
+
+from avalon import api, style
+from avalon.api import AvalonMongoDB
+
+from openpype.api import Anatomy, config
+from openpype import resources
+
+from openpype.lib.delivery import (
+ sizeof_fmt,
+ path_from_representation,
+ get_format_dict,
+ check_destination_path,
+ process_single_file,
+ process_sequence,
+ collect_frames
+)
+
+
+class Delivery(api.SubsetLoader):
+ """Export selected versions to folder structure from Template"""
+
+ is_multiple_contexts_compatible = True
+ sequence_splitter = "__sequence_splitter__"
+
+ representations = ["*"]
+ families = ["*"]
+ tool_names = ["library_loader"]
+
+ label = "Deliver Versions"
+ order = 35
+ icon = "upload"
+ color = "#d8d8d8"
+
+ def message(self, text):
+ msgBox = QtWidgets.QMessageBox()
+ msgBox.setText(text)
+ msgBox.setStyleSheet(style.load_stylesheet())
+ msgBox.setWindowFlags(
+ msgBox.windowFlags() | QtCore.Qt.FramelessWindowHint
+ )
+ msgBox.exec_()
+
+ def load(self, contexts, name=None, namespace=None, options=None):
+ try:
+ dialog = DeliveryOptionsDialog(contexts, self.log)
+ dialog.exec_()
+ except Exception:
+ self.log.error("Failed to deliver versions.", exc_info=True)
+
+
+class DeliveryOptionsDialog(QtWidgets.QDialog):
+ """Dialog to select template where to deliver selected representations."""
+
+ def __init__(self, contexts, log=None, parent=None):
+ super(DeliveryOptionsDialog, self).__init__(parent=parent)
+
+ project = contexts[0]["project"]["name"]
+ self.anatomy = Anatomy(project)
+ self._representations = None
+ self.log = log
+ self.currently_uploaded = 0
+
+ self.dbcon = AvalonMongoDB()
+ self.dbcon.Session["AVALON_PROJECT"] = project
+ self.dbcon.install()
+
+ self._set_representations(contexts)
+
+ self.setWindowTitle("OpenPype - Deliver versions")
+ icon = QtGui.QIcon(resources.pype_icon_filepath())
+ self.setWindowIcon(icon)
+
+ self.setWindowFlags(
+ QtCore.Qt.WindowCloseButtonHint |
+ QtCore.Qt.WindowMinimizeButtonHint
+ )
+ self.setStyleSheet(style.load_stylesheet())
+
+ dropdown = QtWidgets.QComboBox()
+ self.templates = self._get_templates(self.anatomy)
+ for name, _ in self.templates.items():
+ dropdown.addItem(name)
+
+ template_label = QtWidgets.QLabel()
+ template_label.setCursor(QtGui.QCursor(QtCore.Qt.IBeamCursor))
+ template_label.setTextInteractionFlags(QtCore.Qt.TextSelectableByMouse)
+
+ root_line_edit = QtWidgets.QLineEdit()
+
+ repre_checkboxes_layout = QtWidgets.QFormLayout()
+ repre_checkboxes_layout.setContentsMargins(10, 5, 5, 10)
+
+ self._representation_checkboxes = {}
+ for repre in self._get_representation_names():
+ checkbox = QtWidgets.QCheckBox()
+ checkbox.setChecked(False)
+ self._representation_checkboxes[repre] = checkbox
+
+ checkbox.stateChanged.connect(self._update_selected_label)
+ repre_checkboxes_layout.addRow(repre, checkbox)
+
+ selected_label = QtWidgets.QLabel()
+
+ input_widget = QtWidgets.QWidget(self)
+ input_layout = QtWidgets.QFormLayout(input_widget)
+ input_layout.setContentsMargins(10, 15, 5, 5)
+
+ input_layout.addRow("Selected representations", selected_label)
+ input_layout.addRow("Delivery template", dropdown)
+ input_layout.addRow("Template value", template_label)
+ input_layout.addRow("Root", root_line_edit)
+ input_layout.addRow("Representations", repre_checkboxes_layout)
+
+ btn_delivery = QtWidgets.QPushButton("Deliver")
+ btn_delivery.setEnabled(bool(dropdown.currentText()))
+
+ progress_bar = QtWidgets.QProgressBar(self)
+ progress_bar.setMinimum = 0
+ progress_bar.setMaximum = 100
+ progress_bar.setVisible(False)
+
+ text_area = QtWidgets.QTextEdit()
+ text_area.setReadOnly(True)
+ text_area.setVisible(False)
+ text_area.setMinimumHeight(100)
+
+ layout = QtWidgets.QVBoxLayout(self)
+
+ layout.addWidget(input_widget)
+ layout.addStretch(1)
+ layout.addWidget(btn_delivery)
+ layout.addWidget(progress_bar)
+ layout.addWidget(text_area)
+
+ self.selected_label = selected_label
+ self.template_label = template_label
+ self.dropdown = dropdown
+ self.root_line_edit = root_line_edit
+ self.progress_bar = progress_bar
+ self.text_area = text_area
+ self.btn_delivery = btn_delivery
+
+ self.files_selected, self.size_selected = \
+ self._get_counts(self._get_selected_repres())
+
+ self._update_selected_label()
+ self._update_template_value()
+
+ btn_delivery.clicked.connect(self.deliver)
+ dropdown.currentIndexChanged.connect(self._update_template_value)
+
+ def deliver(self):
+ """Main method to loop through all selected representations"""
+ self.progress_bar.setVisible(True)
+ self.btn_delivery.setEnabled(False)
+ QtWidgets.QApplication.processEvents()
+
+ report_items = defaultdict(list)
+
+ selected_repres = self._get_selected_repres()
+
+ datetime_data = config.get_datetime_data()
+ template_name = self.dropdown.currentText()
+ format_dict = get_format_dict(self.anatomy, self.root_line_edit.text())
+ for repre in self._representations:
+ if repre["name"] not in selected_repres:
+ continue
+
+ repre_path = path_from_representation(repre, self.anatomy)
+
+ anatomy_data = copy.deepcopy(repre["context"])
+ new_report_items = check_destination_path(str(repre["_id"]),
+ self.anatomy,
+ anatomy_data,
+ datetime_data,
+ template_name)
+
+ report_items.update(new_report_items)
+ if new_report_items:
+ continue
+
+ args = [
+ repre_path,
+ repre,
+ self.anatomy,
+ template_name,
+ anatomy_data,
+ format_dict,
+ report_items,
+ self.log
+ ]
+
+ if repre.get("files"):
+ src_paths = []
+ for repre_file in repre["files"]:
+ src_path = self.anatomy.fill_root(repre_file["path"])
+ src_paths.append(src_path)
+ sources_and_frames = collect_frames(src_paths)
+
+ for src_path, frame in sources_and_frames.items():
+ args[0] = src_path
+ if frame:
+ anatomy_data["frame"] = frame
+ new_report_items, uploaded = process_single_file(*args)
+ report_items.update(new_report_items)
+ self._update_progress(uploaded)
+ else: # fallback for Pype2 and representations without files
+ frame = repre['context'].get('frame')
+ if frame:
+ repre["context"]["frame"] = len(str(frame)) * "#"
+
+ if not frame:
+ new_report_items, uploaded = process_single_file(*args)
+ else:
+ new_report_items, uploaded = process_sequence(*args)
+ report_items.update(new_report_items)
+ self._update_progress(uploaded)
+
+ self.text_area.setText(self._format_report(report_items))
+ self.text_area.setVisible(True)
+
+ def _get_representation_names(self):
+ """Get set of representation names for checkbox filtering."""
+ return set([repre["name"] for repre in self._representations])
+
+ def _get_templates(self, anatomy):
+ """Adds list of delivery templates from Anatomy to dropdown."""
+ templates = {}
+ for template_name, value in anatomy.templates["delivery"].items():
+ if not isinstance(value, str) or not value.startswith('{root'):
+ continue
+
+ templates[template_name] = value
+
+ return templates
+
+ def _set_representations(self, contexts):
+ version_ids = [context["version"]["_id"] for context in contexts]
+
+ repres = list(self.dbcon.find({
+ "type": "representation",
+ "parent": {"$in": version_ids}
+ }))
+
+ self._representations = repres
+
+ def _get_counts(self, selected_repres=None):
+ """Returns tuple of number of selected files and their size."""
+ files_selected = 0
+ size_selected = 0
+ for repre in self._representations:
+ if repre["name"] in selected_repres:
+ files = repre.get("files", [])
+ if not files: # for repre without files, cannot divide by 0
+ files_selected += 1
+ size_selected += 0
+ else:
+ for repre_file in files:
+ files_selected += 1
+ size_selected += repre_file["size"]
+
+ return files_selected, size_selected
+
+ def _prepare_label(self):
+ """Provides text with no of selected files and their size."""
+ label = "{} files, size {}".format(self.files_selected,
+ sizeof_fmt(self.size_selected))
+ return label
+
+ def _get_selected_repres(self):
+ """Returns list of representation names filtered from checkboxes."""
+ selected_repres = []
+ for repre_name, chckbox in self._representation_checkboxes.items():
+ if chckbox.isChecked():
+ selected_repres.append(repre_name)
+
+ return selected_repres
+
+ def _update_selected_label(self):
+ """Updates label with list of number of selected files."""
+ selected_repres = self._get_selected_repres()
+ self.files_selected, self.size_selected = \
+ self._get_counts(selected_repres)
+ self.selected_label.setText(self._prepare_label())
+
+ def _update_template_value(self, _index=None):
+ """Sets template value to label after selection in dropdown."""
+ name = self.dropdown.currentText()
+ template_value = self.templates.get(name)
+ if template_value:
+ self.btn_delivery.setEnabled(True)
+ self.template_label.setText(template_value)
+
+ def _update_progress(self, uploaded):
+ """Update progress bar after each repre copied."""
+ self.currently_uploaded += uploaded
+
+ ratio = self.currently_uploaded / self.files_selected
+ self.progress_bar.setValue(ratio * self.progress_bar.maximum())
+
+ def _format_report(self, report_items):
+ """Format final result and error details as html."""
+ msg = "Delivery finished"
+ if not report_items:
+ msg += " successfully"
+ else:
+ msg += " with errors"
+ txt = "
{}
".format(msg)
+ for header, data in report_items.items():
+ txt += "{}
".format(header)
+ for item in data:
+ txt += "{}
".format(item)
+
+ return txt
diff --git a/openpype/plugins/publish/collect_resources_path.py b/openpype/plugins/publish/collect_resources_path.py
index 04a33cd5be..98b59332da 100644
--- a/openpype/plugins/publish/collect_resources_path.py
+++ b/openpype/plugins/publish/collect_resources_path.py
@@ -39,7 +39,6 @@ class CollectResourcesPath(pyblish.api.InstancePlugin):
"rig",
"plate",
"look",
- "lut",
"yetiRig",
"yeticache",
"nukenodes",
@@ -52,7 +51,8 @@ class CollectResourcesPath(pyblish.api.InstancePlugin):
"fbx",
"textures",
"action",
- "background"
+ "background",
+ "effect"
]
def process(self, instance):
diff --git a/openpype/plugins/publish/extract_burnin.py b/openpype/plugins/publish/extract_burnin.py
index 76f6ffc608..ef52d51325 100644
--- a/openpype/plugins/publish/extract_burnin.py
+++ b/openpype/plugins/publish/extract_burnin.py
@@ -44,6 +44,7 @@ class ExtractBurnin(openpype.api.Extractor):
"harmony",
"fusion",
"aftereffects",
+ "tvpaint"
# "resolve"
]
optional = True
diff --git a/openpype/plugins/publish/extract_otio_audio_tracks.py b/openpype/plugins/publish/extract_otio_audio_tracks.py
index 43e40097f7..2dc822fb0e 100644
--- a/openpype/plugins/publish/extract_otio_audio_tracks.py
+++ b/openpype/plugins/publish/extract_otio_audio_tracks.py
@@ -40,12 +40,15 @@ class ExtractOtioAudioTracks(pyblish.api.ContextPlugin):
# get sequence
otio_timeline = context.data["otioTimeline"]
- # temp file
- audio_temp_fpath = self.create_temp_file("audio")
-
# get all audio inputs from otio timeline
audio_inputs = self.get_audio_track_items(otio_timeline)
+ if not audio_inputs:
+ return
+
+ # temp file
+ audio_temp_fpath = self.create_temp_file("audio")
+
# create empty audio with longest duration
empty = self.create_empty(audio_inputs)
@@ -53,14 +56,14 @@ class ExtractOtioAudioTracks(pyblish.api.ContextPlugin):
audio_inputs.insert(0, empty)
# create cmd
- cmd = self.ffmpeg_path + " "
+ cmd = '"{}"'.format(self.ffmpeg_path) + " "
cmd += self.create_cmd(audio_inputs)
- cmd += audio_temp_fpath
+ cmd += "\"{}\"".format(audio_temp_fpath)
# run subprocess
self.log.debug("Executing: {}".format(cmd))
openpype.api.run_subprocess(
- cmd, shell=True, logger=self.log
+ cmd, logger=self.log
)
# remove empty
@@ -97,17 +100,17 @@ class ExtractOtioAudioTracks(pyblish.api.ContextPlugin):
audio_fpath = self.create_temp_file(name)
cmd = " ".join([
- self.ffmpeg_path,
+ '"{}"'.format(self.ffmpeg_path),
"-ss {}".format(start_sec),
"-t {}".format(duration_sec),
- "-i {}".format(audio_file),
+ "-i \"{}\"".format(audio_file),
audio_fpath
])
# run subprocess
self.log.debug("Executing: {}".format(cmd))
openpype.api.run_subprocess(
- cmd, shell=True, logger=self.log
+ cmd, logger=self.log
)
else:
audio_fpath = recycling_file.pop()
@@ -218,11 +221,11 @@ class ExtractOtioAudioTracks(pyblish.api.ContextPlugin):
# create empty cmd
cmd = " ".join([
- self.ffmpeg_path,
+ '"{}"'.format(self.ffmpeg_path),
"-f lavfi",
"-i anullsrc=channel_layout=stereo:sample_rate=48000",
"-t {}".format(max_duration_sec),
- empty_fpath
+ "\"{}\"".format(empty_fpath)
])
# generate empty with ffmpeg
@@ -230,7 +233,7 @@ class ExtractOtioAudioTracks(pyblish.api.ContextPlugin):
self.log.debug("Executing: {}".format(cmd))
openpype.api.run_subprocess(
- cmd, shell=True, logger=self.log
+ cmd, logger=self.log
)
# return dict with output
diff --git a/openpype/plugins/publish/extract_otio_review.py b/openpype/plugins/publish/extract_otio_review.py
index 07fe6f2731..2f46bcb375 100644
--- a/openpype/plugins/publish/extract_otio_review.py
+++ b/openpype/plugins/publish/extract_otio_review.py
@@ -209,7 +209,7 @@ class ExtractOTIOReview(openpype.api.Extractor):
"frameStart": start,
"frameEnd": end,
"stagingDir": self.staging_dir,
- "tags": ["review", "ftrackreview", "delete"]
+ "tags": ["review", "delete"]
}
collection = clique.Collection(
@@ -313,7 +313,7 @@ class ExtractOTIOReview(openpype.api.Extractor):
out_frame_start += end_offset
# start command list
- command = [ffmpeg_path]
+ command = ['"{}"'.format(ffmpeg_path)]
if sequence:
input_dir, collection = sequence
@@ -326,7 +326,7 @@ class ExtractOTIOReview(openpype.api.Extractor):
# form command for rendering gap files
command.extend([
"-start_number {}".format(in_frame_start),
- "-i {}".format(input_path)
+ "-i \"{}\"".format(input_path)
])
elif video:
@@ -341,7 +341,7 @@ class ExtractOTIOReview(openpype.api.Extractor):
command.extend([
"-ss {}".format(sec_start),
"-t {}".format(sec_duration),
- "-i {}".format(video_path)
+ "-i \"{}\"".format(video_path)
])
elif gap:
@@ -360,11 +360,13 @@ class ExtractOTIOReview(openpype.api.Extractor):
# add output attributes
command.extend([
"-start_number {}".format(out_frame_start),
- output_path
+ "\"{}\"".format(output_path)
])
# execute
self.log.debug("Executing: {}".format(" ".join(command)))
- output = openpype.api.run_subprocess(" ".join(command), shell=True)
+ output = openpype.api.run_subprocess(
+ " ".join(command), logger=self.log
+ )
self.log.debug("Output: {}".format(output))
def _generate_used_frames(self, duration, end_offset=None):
diff --git a/openpype/plugins/publish/extract_review.py b/openpype/plugins/publish/extract_review.py
index 048d16fabb..769a0d3919 100644
--- a/openpype/plugins/publish/extract_review.py
+++ b/openpype/plugins/publish/extract_review.py
@@ -3,6 +3,9 @@ import re
import copy
import json
+from abc import ABCMeta, abstractmethod
+import six
+
import clique
import pyblish.api
@@ -48,6 +51,8 @@ class ExtractReview(pyblish.api.InstancePlugin):
video_exts = ["mov", "mp4"]
supported_exts = image_exts + video_exts
+ alpha_exts = ["exr", "png", "dpx"]
+
# FFmpeg tools paths
ffmpeg_path = get_ffmpeg_tool_path("ffmpeg")
@@ -296,6 +301,13 @@ class ExtractReview(pyblish.api.InstancePlugin):
):
with_audio = False
+ input_is_sequence = self.input_is_sequence(repre)
+ input_allow_bg = False
+ if input_is_sequence and repre["files"]:
+ ext = os.path.splitext(repre["files"][0])[1].replace(".", "")
+ if ext in self.alpha_exts:
+ input_allow_bg = True
+
return {
"fps": float(instance.data["fps"]),
"frame_start": frame_start,
@@ -310,7 +322,8 @@ class ExtractReview(pyblish.api.InstancePlugin):
"resolution_width": instance.data.get("resolutionWidth"),
"resolution_height": instance.data.get("resolutionHeight"),
"origin_repre": repre,
- "input_is_sequence": self.input_is_sequence(repre),
+ "input_is_sequence": input_is_sequence,
+ "input_allow_bg": input_allow_bg,
"with_audio": with_audio,
"without_handles": without_handles,
"handles_are_set": handles_are_set
@@ -470,6 +483,39 @@ class ExtractReview(pyblish.api.InstancePlugin):
lut_filters = self.lut_filters(new_repre, instance, ffmpeg_input_args)
ffmpeg_video_filters.extend(lut_filters)
+ bg_alpha = 0
+ bg_color = output_def.get("bg_color")
+ if bg_color:
+ bg_red, bg_green, bg_blue, bg_alpha = bg_color
+
+ if bg_alpha > 0:
+ if not temp_data["input_allow_bg"]:
+ self.log.info((
+ "Output definition has defined BG color input was"
+ " resolved as does not support adding BG."
+ ))
+ else:
+ bg_color_hex = "#{0:0>2X}{1:0>2X}{2:0>2X}".format(
+ bg_red, bg_green, bg_blue
+ )
+ bg_color_alpha = float(bg_alpha) / 255
+ bg_color_str = "{}@{}".format(bg_color_hex, bg_color_alpha)
+
+ self.log.info("Applying BG color {}".format(bg_color_str))
+ color_args = [
+ "split=2[bg][fg]",
+ "[bg]drawbox=c={}:replace=1:t=fill[bg]".format(
+ bg_color_str
+ ),
+ "[bg][fg]overlay=format=auto"
+ ]
+ # Prepend bg color change before all video filters
+ # NOTE at the time of creation it is required as video filters
+ # from settings may affect color of BG
+ # e.g. `eq` can remove alpha from input
+ for arg in reversed(color_args):
+ ffmpeg_video_filters.insert(0, arg)
+
# Add argument to override output file
ffmpeg_output_args.append("-y")
@@ -547,10 +593,12 @@ class ExtractReview(pyblish.api.InstancePlugin):
all_args.append("\"{}\"".format(self.ffmpeg_path))
all_args.extend(input_args)
if video_filters:
- all_args.append("-filter:v {}".format(",".join(video_filters)))
+ all_args.append("-filter:v")
+ all_args.append("\"{}\"".format(",".join(video_filters)))
if audio_filters:
- all_args.append("-filter:a {}".format(",".join(audio_filters)))
+ all_args.append("-filter:a")
+ all_args.append("\"{}\"".format(",".join(audio_filters)))
all_args.extend(output_args)
@@ -828,12 +876,6 @@ class ExtractReview(pyblish.api.InstancePlugin):
"""
filters = []
- letter_box_def = output_def["letter_box"]
- letter_box_enabled = letter_box_def["enabled"]
-
- # Get instance data
- pixel_aspect = temp_data["pixel_aspect"]
-
# NOTE Skipped using instance's resolution
full_input_path_single_file = temp_data["full_input_path_single_file"]
input_data = ffprobe_streams(
@@ -842,6 +884,33 @@ class ExtractReview(pyblish.api.InstancePlugin):
input_width = int(input_data["width"])
input_height = int(input_data["height"])
+ # NOTE Setting only one of `width` or `heigth` is not allowed
+ # - settings value can't have None but has value of 0
+ output_width = output_def.get("width") or None
+ output_height = output_def.get("height") or None
+
+ # Convert overscan value video filters
+ overscan_crop = output_def.get("overscan_crop")
+ overscan = OverscanCrop(input_width, input_height, overscan_crop)
+ overscan_crop_filters = overscan.video_filters()
+ # Add overscan filters to filters if are any and modify input
+ # resolution by it's values
+ if overscan_crop_filters:
+ filters.extend(overscan_crop_filters)
+ input_width = overscan.width()
+ input_height = overscan.height()
+ # Use output resolution as inputs after cropping to skip usage of
+ # instance data resolution
+ if output_width is None or output_height is None:
+ output_width = input_width
+ output_height = input_height
+
+ letter_box_def = output_def["letter_box"]
+ letter_box_enabled = letter_box_def["enabled"]
+
+ # Get instance data
+ pixel_aspect = temp_data["pixel_aspect"]
+
# Make sure input width and height is not an odd number
input_width_is_odd = bool(input_width % 2 != 0)
input_height_is_odd = bool(input_height % 2 != 0)
@@ -866,10 +935,6 @@ class ExtractReview(pyblish.api.InstancePlugin):
self.log.debug("input_width: `{}`".format(input_width))
self.log.debug("input_height: `{}`".format(input_height))
- # NOTE Setting only one of `width` or `heigth` is not allowed
- # - settings value can't have None but has value of 0
- output_width = output_def.get("width") or None
- output_height = output_def.get("height") or None
# Use instance resolution if output definition has not set it.
if output_width is None or output_height is None:
output_width = temp_data["resolution_width"]
@@ -1393,3 +1458,291 @@ class ExtractReview(pyblish.api.InstancePlugin):
vf_back = "-vf " + ",".join(vf_fixed)
return vf_back
+
+
+@six.add_metaclass(ABCMeta)
+class _OverscanValue:
+ def __repr__(self):
+ return "<{}> {}".format(self.__class__.__name__, str(self))
+
+ @abstractmethod
+ def copy(self):
+ """Create a copy of object."""
+ pass
+
+ @abstractmethod
+ def size_for(self, value):
+ """Calculate new value for passed value."""
+ pass
+
+
+class PixValueExplicit(_OverscanValue):
+ def __init__(self, value):
+ self._value = int(value)
+
+ def __str__(self):
+ return "{}px".format(self._value)
+
+ def copy(self):
+ return PixValueExplicit(self._value)
+
+ def size_for(self, value):
+ if self._value == 0:
+ return value
+ return self._value
+
+
+class PercentValueExplicit(_OverscanValue):
+ def __init__(self, value):
+ self._value = float(value)
+
+ def __str__(self):
+ return "{}%".format(abs(self._value))
+
+ def copy(self):
+ return PercentValueExplicit(self._value)
+
+ def size_for(self, value):
+ if self._value == 0:
+ return value
+ return int((value / 100) * self._value)
+
+
+class PixValueRelative(_OverscanValue):
+ def __init__(self, value):
+ self._value = int(value)
+
+ def __str__(self):
+ sign = "-" if self._value < 0 else "+"
+ return "{}{}px".format(sign, abs(self._value))
+
+ def copy(self):
+ return PixValueRelative(self._value)
+
+ def size_for(self, value):
+ return value + self._value
+
+
+class PercentValueRelative(_OverscanValue):
+ def __init__(self, value):
+ self._value = float(value)
+
+ def __str__(self):
+ return "{}%".format(self._value)
+
+ def copy(self):
+ return PercentValueRelative(self._value)
+
+ def size_for(self, value):
+ if self._value == 0:
+ return value
+
+ offset = int((value / 100) * self._value)
+
+ return value + offset
+
+
+class PercentValueRelativeSource(_OverscanValue):
+ def __init__(self, value, source_sign):
+ self._value = float(value)
+ if source_sign not in ("-", "+"):
+ raise ValueError(
+ "Invalid sign value \"{}\" expected \"-\" or \"+\"".format(
+ source_sign
+ )
+ )
+ self._source_sign = source_sign
+
+ def __str__(self):
+ return "{}%{}".format(self._value, self._source_sign)
+
+ def copy(self):
+ return PercentValueRelativeSource(self._value, self._source_sign)
+
+ def size_for(self, value):
+ if self._value == 0:
+ return value
+ return int((value * 100) / (100 - self._value))
+
+
+class OverscanCrop:
+ """Helper class to read overscan string and calculate output resolution.
+
+ It is possible to enter single value for both width and heigh or two values
+ for width and height. Overscan string may have a few variants. Each variant
+ define output size for input size.
+
+ ### Example
+ For input size: 2200px
+
+ | String | Output | Description |
+ |----------|--------|-------------------------------------------------|
+ | "" | 2200px | Empty string does nothing. |
+ | "10%" | 220px | Explicit percent size. |
+ | "-10%" | 1980px | Relative percent size (decrease). |
+ | "+10%" | 2420px | Relative percent size (increase). |
+ | "-10%+" | 2000px | Relative percent size to output size. |
+ | "300px" | 300px | Explicit output size cropped or expanded. |
+ | "-300px" | 1900px | Relative pixel size (decrease). |
+ | "+300px" | 2500px | Relative pixel size (increase). |
+ | "300" | 300px | Value without "%" and "px" is used as has "px". |
+
+ Value without sign (+/-) in is always explicit and value with sign is
+ relative. Output size for "200px" and "+200px" are not the same.
+ Values "0", "0px" or "0%" are ignored.
+
+ All values that cause output resolution smaller than 1 pixel are invalid.
+
+ Value "-10%+" is a special case which says that input's resolution is
+ bigger by 10% than expected output.
+
+ It is possible to combine these variants to define different output for
+ width and height.
+
+ Resolution: 2000px 1000px
+
+ | String | Output |
+ |---------------|---------------|
+ | "100px 120px" | 2100px 1120px |
+ | "-10% -200px" | 1800px 800px |
+ """
+
+ item_regex = re.compile(r"([\+\-])?([0-9]+)(.+)?")
+ relative_source_regex = re.compile(r"%([\+\-])")
+
+ def __init__(self, input_width, input_height, string_value):
+ # Make sure that is not None
+ string_value = string_value or ""
+
+ self.input_width = input_width
+ self.input_height = input_height
+
+ width, height = self._convert_string_to_values(string_value)
+ self._width_value = width
+ self._height_value = height
+
+ self._string_value = string_value
+
+ def __str__(self):
+ return "{}".format(self._string_value)
+
+ def __repr__(self):
+ return "<{}>".format(self.__class__.__name__)
+
+ def width(self):
+ """Calculated width."""
+ return self._width_value.size_for(self.input_width)
+
+ def height(self):
+ """Calculated height."""
+ return self._height_value.size_for(self.input_height)
+
+ def video_filters(self):
+ """FFmpeg video filters to achieve expected result.
+
+ Filter may be empty, use "crop" filter, "pad" filter or combination of
+ "crop" and "pad".
+
+ Returns:
+ list: FFmpeg video filters.
+ """
+ # crop=width:height:x:y - explicit start x, y position
+ # crop=width:height - x, y are related to center by width/height
+ # pad=width:heigth:x:y - explicit start x, y position
+ # pad=width:heigth - x, y are set to 0 by default
+
+ width = self.width()
+ height = self.height()
+
+ output = []
+ if self.input_width == width and self.input_height == height:
+ return output
+
+ # Make sure resolution has odd numbers
+ if width % 2 == 1:
+ width -= 1
+
+ if height % 2 == 1:
+ height -= 1
+
+ if width <= self.input_width and height <= self.input_height:
+ output.append("crop={}:{}".format(width, height))
+
+ elif width >= self.input_width and height >= self.input_height:
+ output.append(
+ "pad={}:{}:(iw-ow)/2:(ih-oh)/2".format(width, height)
+ )
+
+ elif width > self.input_width and height < self.input_height:
+ output.append("crop=iw:{}".format(height))
+ output.append("pad={}:ih:(iw-ow)/2:(ih-oh)/2".format(width))
+
+ elif width < self.input_width and height > self.input_height:
+ output.append("crop={}:ih".format(width))
+ output.append("pad=iw:{}:(iw-ow)/2:(ih-oh)/2".format(height))
+
+ return output
+
+ def _convert_string_to_values(self, orig_string_value):
+ string_value = orig_string_value.strip().lower()
+ if not string_value:
+ return [PixValueRelative(0), PixValueRelative(0)]
+
+ # Replace "px" (and spaces before) with single space
+ string_value = re.sub(r"([ ]+)?px", " ", string_value)
+ string_value = re.sub(r"([ ]+)%", "%", string_value)
+ # Make sure +/- sign at the beggining of string is next to number
+ string_value = re.sub(r"^([\+\-])[ ]+", "\g<1>", string_value)
+ # Make sure +/- sign in the middle has zero spaces before number under
+ # which belongs
+ string_value = re.sub(
+ r"[ ]([\+\-])[ ]+([0-9])",
+ r" \g<1>\g<2>",
+ string_value
+ )
+ string_parts = [
+ part
+ for part in string_value.split(" ")
+ if part
+ ]
+
+ error_msg = "Invalid string for rescaling \"{}\"".format(
+ orig_string_value
+ )
+ if 1 > len(string_parts) > 2:
+ raise ValueError(error_msg)
+
+ output = []
+ for item in string_parts:
+ groups = self.item_regex.findall(item)
+ if not groups:
+ raise ValueError(error_msg)
+
+ relative_sign, value, ending = groups[0]
+ if not relative_sign:
+ if not ending:
+ output.append(PixValueExplicit(value))
+ else:
+ output.append(PercentValueExplicit(value))
+ else:
+ source_sign_group = self.relative_source_regex.findall(ending)
+ if not ending:
+ output.append(PixValueRelative(int(relative_sign + value)))
+
+ elif source_sign_group:
+ source_sign = source_sign_group[0]
+ output.append(PercentValueRelativeSource(
+ float(relative_sign + value), source_sign
+ ))
+ else:
+ output.append(
+ PercentValueRelative(float(relative_sign + value))
+ )
+
+ if len(output) == 1:
+ width = output.pop(0)
+ height = width.copy()
+ else:
+ width, height = output
+
+ return width, height
diff --git a/openpype/plugins/publish/integrate_new.py b/openpype/plugins/publish/integrate_new.py
index 9769f0d165..3a926789fb 100644
--- a/openpype/plugins/publish/integrate_new.py
+++ b/openpype/plugins/publish/integrate_new.py
@@ -78,7 +78,6 @@ class IntegrateAssetNew(pyblish.api.InstancePlugin):
"rig",
"plate",
"look",
- "lut",
"audio",
"yetiRig",
"yeticache",
@@ -97,7 +96,8 @@ class IntegrateAssetNew(pyblish.api.InstancePlugin):
"editorial",
"background",
"camerarig",
- "redshiftproxy"
+ "redshiftproxy",
+ "effect"
]
exclude_families = ["clip"]
db_representation_context_keys = [
diff --git a/openpype/scripts/non_python_host_launch.py b/openpype/scripts/non_python_host_launch.py
index 506105d2ce..32c4b23f4f 100644
--- a/openpype/scripts/non_python_host_launch.py
+++ b/openpype/scripts/non_python_host_launch.py
@@ -81,11 +81,11 @@ def main(argv):
host_name = os.environ["AVALON_APP"].lower()
if host_name == "photoshop":
- from avalon.photoshop.lib import launch
+ from avalon.photoshop.lib import main
elif host_name == "aftereffects":
- from avalon.aftereffects.lib import launch
+ from avalon.aftereffects.lib import main
elif host_name == "harmony":
- from avalon.harmony.lib import launch
+ from avalon.harmony.lib import main
else:
title = "Unknown host name"
message = (
@@ -97,7 +97,7 @@ def main(argv):
if launch_args:
# Launch host implementation
- launch(*launch_args)
+ main(*launch_args)
else:
# Show message box
on_invalid_args(after_script_idx is None)
diff --git a/openpype/settings/defaults/project_settings/aftereffects.json b/openpype/settings/defaults/project_settings/aftereffects.json
index f54dbb9612..698b3b35a9 100644
--- a/openpype/settings/defaults/project_settings/aftereffects.json
+++ b/openpype/settings/defaults/project_settings/aftereffects.json
@@ -4,8 +4,12 @@
"enabled": true,
"optional": true,
"active": true,
- "skip_resolution_check": [".*"],
- "skip_timelines_check": [".*"]
+ "skip_resolution_check": [
+ ".*"
+ ],
+ "skip_timelines_check": [
+ ".*"
+ ]
},
"AfterEffectsSubmitDeadline": {
"use_published": true,
@@ -14,5 +18,9 @@
"secondary_pool": "",
"chunk_size": 1000000
}
+ },
+ "workfile_builder": {
+ "create_first_version": false,
+ "custom_templates": []
}
}
\ No newline at end of file
diff --git a/openpype/settings/defaults/project_settings/blender.json b/openpype/settings/defaults/project_settings/blender.json
new file mode 100644
index 0000000000..a7262dcb5d
--- /dev/null
+++ b/openpype/settings/defaults/project_settings/blender.json
@@ -0,0 +1,6 @@
+{
+ "workfile_builder": {
+ "create_first_version": false,
+ "custom_templates": []
+ }
+}
\ No newline at end of file
diff --git a/openpype/settings/defaults/project_settings/global.json b/openpype/settings/defaults/project_settings/global.json
index 1f54bed03c..5f779fccfa 100644
--- a/openpype/settings/defaults/project_settings/global.json
+++ b/openpype/settings/defaults/project_settings/global.json
@@ -37,11 +37,11 @@
"ftrackreview"
],
"ffmpeg_args": {
- "video_filters": [
- "eq=gamma=2.2"
- ],
+ "video_filters": [],
"audio_filters": [],
- "input": [],
+ "input": [
+ "-apply_trc gamma22"
+ ],
"output": [
"-pix_fmt yuv420p",
"-crf 18",
@@ -55,8 +55,15 @@
"ftrack"
]
},
+ "overscan_crop": "",
"width": 0,
"height": 0,
+ "bg_color": [
+ 0,
+ 0,
+ 0,
+ 0
+ ],
"letter_box": {
"enabled": false,
"ratio": 0.0,
@@ -266,8 +273,7 @@
"active_site": "studio",
"remote_site": "studio"
},
- "sites": {
- }
+ "sites": {}
},
"project_plugins": {
"windows": [],
diff --git a/openpype/settings/defaults/project_settings/maya.json b/openpype/settings/defaults/project_settings/maya.json
index 779b8bb3f3..ba685ae502 100644
--- a/openpype/settings/defaults/project_settings/maya.json
+++ b/openpype/settings/defaults/project_settings/maya.json
@@ -293,19 +293,22 @@
},
"Display Options": {
"background": [
- 0.7,
- 0.7,
- 0.7
+ 125,
+ 125,
+ 125,
+ 255
],
"backgroundBottom": [
- 0.7,
- 0.7,
- 0.7
+ 125,
+ 125,
+ 125,
+ 255
],
"backgroundTop": [
- 0.7,
- 0.7,
- 0.7
+ 125,
+ 125,
+ 125,
+ 255
],
"override_display": true
},
@@ -393,74 +396,88 @@
"load": {
"colors": {
"model": [
- 0.821,
- 0.518,
- 0.117
+ 209,
+ 132,
+ 30,
+ 255
],
"rig": [
- 0.144,
- 0.443,
- 0.463
+ 59,
+ 226,
+ 235,
+ 255
],
"pointcache": [
- 0.368,
- 0.821,
- 0.117
+ 94,
+ 209,
+ 30,
+ 255
],
"animation": [
- 0.368,
- 0.821,
- 0.117
+ 94,
+ 209,
+ 30,
+ 255
],
"ass": [
- 1.0,
- 0.332,
- 0.312
+ 249,
+ 135,
+ 53,
+ 255
],
"camera": [
- 0.447,
- 0.312,
- 1.0
+ 136,
+ 114,
+ 244,
+ 255
],
"fbx": [
- 1.0,
- 0.931,
- 0.312
+ 215,
+ 166,
+ 255,
+ 255
],
"mayaAscii": [
- 0.312,
- 1.0,
- 0.747
+ 67,
+ 174,
+ 255,
+ 255
],
"setdress": [
- 0.312,
- 1.0,
- 0.747
+ 255,
+ 250,
+ 90,
+ 255
],
"layout": [
- 0.312,
- 1.0,
- 0.747
+ 255,
+ 250,
+ 90,
+ 255
],
"vdbcache": [
- 0.312,
- 1.0,
- 0.428
+ 249,
+ 54,
+ 0,
+ 255
],
"vrayproxy": [
- 0.258,
- 0.95,
- 0.541
+ 255,
+ 150,
+ 12,
+ 255
],
"yeticache": [
- 0.2,
- 0.8,
- 0.3
+ 99,
+ 206,
+ 220,
+ 255
],
"yetiRig": [
- 0.0,
- 0.8,
- 0.5
+ 0,
+ 205,
+ 125,
+ 255
]
}
},
diff --git a/openpype/settings/defaults/project_settings/nuke.json b/openpype/settings/defaults/project_settings/nuke.json
index bb5232cea7..13e1924b36 100644
--- a/openpype/settings/defaults/project_settings/nuke.json
+++ b/openpype/settings/defaults/project_settings/nuke.json
@@ -6,9 +6,7 @@
"load": "ctrl+alt+l",
"manage": "ctrl+alt+m",
"build_workfile": "ctrl+alt+b"
- },
- "open_workfile_at_start": false,
- "create_initial_workfile": true
+ }
},
"create": {
"CreateWriteRender": {
@@ -147,12 +145,13 @@
"node_name_template": "{class_name}_{ext}"
}
},
- "workfile_build": {
+ "workfile_builder": {
+ "create_first_version": false,
+ "custom_templates": [],
+ "builder_on_start": false,
"profiles": [
{
- "tasks": [
- "compositing"
- ],
+ "tasks": [],
"current_context": [
{
"subset_name_filters": [],
@@ -162,10 +161,12 @@
],
"repre_names": [
"exr",
- "dpx"
+ "dpx",
+ "mov"
],
"loaders": [
- "LoadSequence"
+ "LoadSequence",
+ "LoadMov"
]
}
],
diff --git a/openpype/settings/defaults/project_settings/photoshop.json b/openpype/settings/defaults/project_settings/photoshop.json
index 0db6e8248d..b306a757a6 100644
--- a/openpype/settings/defaults/project_settings/photoshop.json
+++ b/openpype/settings/defaults/project_settings/photoshop.json
@@ -13,5 +13,9 @@
"jpg"
]
}
+ },
+ "workfile_builder": {
+ "create_first_version": false,
+ "custom_templates": []
}
}
\ No newline at end of file
diff --git a/openpype/settings/defaults/project_settings/tvpaint.json b/openpype/settings/defaults/project_settings/tvpaint.json
index 9d5b922b8e..b4f3b315ec 100644
--- a/openpype/settings/defaults/project_settings/tvpaint.json
+++ b/openpype/settings/defaults/project_settings/tvpaint.json
@@ -32,5 +32,9 @@
}
}
},
+ "workfile_builder": {
+ "create_first_version": false,
+ "custom_templates": []
+ },
"filters": {}
}
\ No newline at end of file
diff --git a/openpype/settings/entities/__init__.py b/openpype/settings/entities/__init__.py
index 33881a6097..f64ca1e98d 100644
--- a/openpype/settings/entities/__init__.py
+++ b/openpype/settings/entities/__init__.py
@@ -103,6 +103,7 @@ from .enum_entity import (
EnumEntity,
AppsEnumEntity,
ToolsEnumEntity,
+ TaskTypeEnumEntity,
ProvidersEnum
)
@@ -154,6 +155,7 @@ __all__ = (
"EnumEntity",
"AppsEnumEntity",
"ToolsEnumEntity",
+ "TaskTypeEnumEntity",
"ProvidersEnum",
"ListEntity",
diff --git a/openpype/settings/entities/base_entity.py b/openpype/settings/entities/base_entity.py
index 90efb73fbc..c6bff1ff47 100644
--- a/openpype/settings/entities/base_entity.py
+++ b/openpype/settings/entities/base_entity.py
@@ -111,6 +111,8 @@ class BaseItemEntity(BaseEntity):
self.file_item = None
# Reference to `RootEntity`
self.root_item = None
+ # Change of value requires restart of OpenPype
+ self._require_restart_on_change = False
# Entity is in hierarchy of dynamically created entity
self.is_in_dynamic_item = False
@@ -171,6 +173,14 @@ class BaseItemEntity(BaseEntity):
roles = [roles]
self.roles = roles
+ @property
+ def require_restart_on_change(self):
+ return self._require_restart_on_change
+
+ @property
+ def require_restart(self):
+ return False
+
@property
def has_studio_override(self):
"""Says if entity or it's children has studio overrides."""
@@ -261,6 +271,14 @@ class BaseItemEntity(BaseEntity):
self, "Dynamic entity has set `is_group` to true."
)
+ if (
+ self.require_restart_on_change
+ and (self.is_dynamic_item or self.is_in_dynamic_item)
+ ):
+ raise EntitySchemaError(
+ self, "Dynamic entity can't require restart."
+ )
+
@abstractmethod
def set_override_state(self, state):
"""Set override state and trigger it on children.
@@ -788,6 +806,15 @@ class ItemEntity(BaseItemEntity):
# Root item reference
self.root_item = self.parent.root_item
+ # Item require restart on value change
+ require_restart_on_change = self.schema_data.get("require_restart")
+ if (
+ require_restart_on_change is None
+ and not (self.is_dynamic_item or self.is_in_dynamic_item)
+ ):
+ require_restart_on_change = self.parent.require_restart_on_change
+ self._require_restart_on_change = require_restart_on_change
+
# File item reference
if self.parent.is_file:
self.file_item = self.parent
diff --git a/openpype/settings/entities/dict_mutable_keys_entity.py b/openpype/settings/entities/dict_mutable_keys_entity.py
index 907bf98784..4b221720c3 100644
--- a/openpype/settings/entities/dict_mutable_keys_entity.py
+++ b/openpype/settings/entities/dict_mutable_keys_entity.py
@@ -439,10 +439,10 @@ class DictMutableKeysEntity(EndpointEntity):
new_initial_value = []
for key, value in _settings_value:
if key in initial_value:
- new_initial_value.append(key, initial_value.pop(key))
+ new_initial_value.append([key, initial_value.pop(key)])
for key, value in initial_value.items():
- new_initial_value.append(key, value)
+ new_initial_value.append([key, value])
initial_value = new_initial_value
else:
initial_value = _settings_value
diff --git a/openpype/settings/entities/enum_entity.py b/openpype/settings/entities/enum_entity.py
index c6021b68de..5df365508c 100644
--- a/openpype/settings/entities/enum_entity.py
+++ b/openpype/settings/entities/enum_entity.py
@@ -219,6 +219,41 @@ class ToolsEnumEntity(BaseEnumEntity):
self._current_value = new_value
+class TaskTypeEnumEntity(BaseEnumEntity):
+ schema_types = ["task-types-enum"]
+
+ def _item_initalization(self):
+ self.multiselection = True
+ self.value_on_not_set = []
+ self.enum_items = []
+ self.valid_keys = set()
+ self.valid_value_types = (list, )
+ self.placeholder = None
+
+ def _get_enum_values(self):
+ anatomy_entity = self.get_entity_from_path(
+ "project_settings/project_anatomy"
+ )
+
+ valid_keys = set()
+ enum_items = []
+ for task_type in anatomy_entity["tasks"].keys():
+ enum_items.append({task_type: task_type})
+ valid_keys.add(task_type)
+
+ return enum_items, valid_keys
+
+ def set_override_state(self, *args, **kwargs):
+ super(TaskTypeEnumEntity, self).set_override_state(*args, **kwargs)
+
+ self.enum_items, self.valid_keys = self._get_enum_values()
+ new_value = []
+ for key in self._current_value:
+ if key in self.valid_keys:
+ new_value.append(key)
+ self._current_value = new_value
+
+
class ProvidersEnum(BaseEnumEntity):
schema_types = ["providers-enum"]
diff --git a/openpype/settings/entities/input_entities.py b/openpype/settings/entities/input_entities.py
index 409e6a66b4..295333eb60 100644
--- a/openpype/settings/entities/input_entities.py
+++ b/openpype/settings/entities/input_entities.py
@@ -68,8 +68,18 @@ class EndpointEntity(ItemEntity):
def on_change(self):
for callback in self.on_change_callbacks:
callback()
+
+ if self.require_restart_on_change:
+ if self.require_restart:
+ self.root_item.add_item_require_restart(self)
+ else:
+ self.root_item.remove_item_require_restart(self)
self.parent.on_child_change(self)
+ @property
+ def require_restart(self):
+ return self.has_unsaved_changes
+
def update_default_value(self, value):
value = self._check_update_value(value, "default")
self._default_value = value
@@ -115,6 +125,10 @@ class InputEntity(EndpointEntity):
"""Entity's value without metadata."""
return self._current_value
+ @property
+ def require_restart(self):
+ return self._value_is_modified
+
def _settings_value(self):
return copy.deepcopy(self.value)
diff --git a/openpype/settings/entities/lib.py b/openpype/settings/entities/lib.py
index ed3d7aed84..05f4ea64f8 100644
--- a/openpype/settings/entities/lib.py
+++ b/openpype/settings/entities/lib.py
@@ -17,26 +17,60 @@ WRAPPER_TYPES = ["form", "collapsible-wrap"]
NOT_SET = type("NOT_SET", (), {"__bool__": lambda obj: False})()
OVERRIDE_VERSION = 1
+DEFAULT_VALUES_KEY = "__default_values__"
+TEMPLATE_METADATA_KEYS = (
+ DEFAULT_VALUES_KEY,
+)
+
template_key_pattern = re.compile(r"(\{.*?[^{0]*\})")
+def _pop_metadata_item(template):
+ found_idx = None
+ for idx, item in enumerate(template):
+ if not isinstance(item, dict):
+ continue
+
+ for key in TEMPLATE_METADATA_KEYS:
+ if key in item:
+ found_idx = idx
+ break
+
+ if found_idx is not None:
+ break
+
+ metadata_item = {}
+ if found_idx is not None:
+ metadata_item = template.pop(found_idx)
+ return metadata_item
+
+
def _fill_schema_template_data(
- template, template_data, required_keys=None, missing_keys=None
+ template, template_data, skip_paths, required_keys=None, missing_keys=None
):
first = False
if required_keys is None:
first = True
+
+ if "skip_paths" in template_data:
+ skip_paths = template_data["skip_paths"]
+ if not isinstance(skip_paths, list):
+ skip_paths = [skip_paths]
+
+ # Cleanup skip paths (skip empty values)
+ skip_paths = [path for path in skip_paths if path]
+
required_keys = set()
missing_keys = set()
- _template = []
- default_values = {}
- for item in template:
- if isinstance(item, dict) and "__default_values__" in item:
- default_values = item["__default_values__"]
- else:
- _template.append(item)
- template = _template
+ # Copy template data as content may change
+ template = copy.deepcopy(template)
+
+ # Get metadata item from template
+ metadata_item = _pop_metadata_item(template)
+
+ # Check for default values for template data
+ default_values = metadata_item.get(DEFAULT_VALUES_KEY) or {}
for key, value in default_values.items():
if key not in template_data:
@@ -46,21 +80,55 @@ def _fill_schema_template_data(
output = template
elif isinstance(template, list):
+ # Store paths by first part if path
+ # - None value says that whole key should be skipped
+ skip_paths_by_first_key = {}
+ for path in skip_paths:
+ parts = path.split("/")
+ key = parts.pop(0)
+ if key not in skip_paths_by_first_key:
+ skip_paths_by_first_key[key] = []
+
+ value = "/".join(parts)
+ skip_paths_by_first_key[key].append(value or None)
+
output = []
for item in template:
- output.append(_fill_schema_template_data(
- item, template_data, required_keys, missing_keys
- ))
+ # Get skip paths for children item
+ _skip_paths = []
+ if not isinstance(item, dict):
+ pass
+
+ elif item.get("type") in WRAPPER_TYPES:
+ _skip_paths = copy.deepcopy(skip_paths)
+
+ elif skip_paths_by_first_key:
+ # Check if this item should be skipped
+ key = item.get("key")
+ if key and key in skip_paths_by_first_key:
+ _skip_paths = skip_paths_by_first_key[key]
+ # Skip whole item if None is in skip paths value
+ if None in _skip_paths:
+ continue
+
+ output_item = _fill_schema_template_data(
+ item, template_data, _skip_paths, required_keys, missing_keys
+ )
+ if output_item:
+ output.append(output_item)
elif isinstance(template, dict):
output = {}
for key, value in template.items():
output[key] = _fill_schema_template_data(
- value, template_data, required_keys, missing_keys
+ value, template_data, skip_paths, required_keys, missing_keys
)
+ if output.get("type") in WRAPPER_TYPES and not output.get("children"):
+ return {}
elif isinstance(template, STRING_TYPE):
# TODO find much better way how to handle filling template data
+ template = template.replace("{{", "__dbcb__").replace("}}", "__decb__")
for replacement_string in template_key_pattern.findall(template):
key = str(replacement_string[1:-1])
required_keys.add(key)
@@ -76,7 +144,8 @@ def _fill_schema_template_data(
else:
# Only replace the key in string
template = template.replace(replacement_string, value)
- output = template
+
+ output = template.replace("__dbcb__", "{").replace("__decb__", "}")
else:
output = template
@@ -105,11 +174,15 @@ def _fill_schema_template(child_data, schema_collection, schema_templates):
if isinstance(template_data, dict):
template_data = [template_data]
+ skip_paths = child_data.get("skip_paths") or []
+ if isinstance(skip_paths, STRING_TYPE):
+ skip_paths = [skip_paths]
+
output = []
for single_template_data in template_data:
try:
filled_child = _fill_schema_template_data(
- template, single_template_data
+ template, single_template_data, skip_paths
)
except SchemaTemplateMissingKeys as exc:
@@ -166,7 +239,7 @@ def _fill_inner_schemas(schema_data, schema_collection, schema_templates):
schema_templates
)
- elif child_type == "schema_template":
+ elif child_type in ("template", "schema_template"):
for filled_child in _fill_schema_template(
child, schema_collection, schema_templates
):
diff --git a/openpype/settings/entities/root_entities.py b/openpype/settings/entities/root_entities.py
index b89473d9fb..401d3980c9 100644
--- a/openpype/settings/entities/root_entities.py
+++ b/openpype/settings/entities/root_entities.py
@@ -55,6 +55,8 @@ class RootEntity(BaseItemEntity):
def __init__(self, schema_data, reset):
super(RootEntity, self).__init__(schema_data)
+ self._require_restart_callbacks = []
+ self._item_ids_require_restart = set()
self._item_initalization()
if reset:
self.reset()
@@ -64,6 +66,31 @@ class RootEntity(BaseItemEntity):
"""Current OverrideState."""
return self._override_state
+ @property
+ def require_restart(self):
+ return bool(self._item_ids_require_restart)
+
+ def add_require_restart_change_callback(self, callback):
+ self._require_restart_callbacks.append(callback)
+
+ def _on_require_restart_change(self):
+ for callback in self._require_restart_callbacks:
+ callback()
+
+ def add_item_require_restart(self, item):
+ was_empty = len(self._item_ids_require_restart) == 0
+ self._item_ids_require_restart.add(item.id)
+ if was_empty:
+ self._on_require_restart_change()
+
+ def remove_item_require_restart(self, item):
+ if item.id not in self._item_ids_require_restart:
+ return
+
+ self._item_ids_require_restart.remove(item.id)
+ if not self._item_ids_require_restart:
+ self._on_require_restart_change()
+
@abstractmethod
def reset(self):
"""Reset values and entities to initial state.
diff --git a/openpype/settings/entities/schemas/projects_schema/schema_main.json b/openpype/settings/entities/schemas/projects_schema/schema_main.json
index e77f13d351..64c5a7f366 100644
--- a/openpype/settings/entities/schemas/projects_schema/schema_main.json
+++ b/openpype/settings/entities/schemas/projects_schema/schema_main.json
@@ -78,6 +78,10 @@
"type": "schema",
"name": "schema_project_hiero"
},
+ {
+ "type": "schema",
+ "name": "schema_project_blender"
+ },
{
"type": "schema",
"name": "schema_project_aftereffects"
diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_aftereffects.json b/openpype/settings/entities/schemas/projects_schema/schema_project_aftereffects.json
index 63bf9274a3..8024de6d45 100644
--- a/openpype/settings/entities/schemas/projects_schema/schema_project_aftereffects.json
+++ b/openpype/settings/entities/schemas/projects_schema/schema_project_aftereffects.json
@@ -85,6 +85,14 @@
]
}
]
+ },
+ {
+ "type": "schema_template",
+ "name": "template_workfile_options",
+ "skip_paths": [
+ "workfile_builder/builder_on_start",
+ "workfile_builder/profiles"
+ ]
}
]
}
diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_blender.json b/openpype/settings/entities/schemas/projects_schema/schema_project_blender.json
new file mode 100644
index 0000000000..af09329a03
--- /dev/null
+++ b/openpype/settings/entities/schemas/projects_schema/schema_project_blender.json
@@ -0,0 +1,17 @@
+{
+ "type": "dict",
+ "collapsible": true,
+ "key": "blender",
+ "label": "Blender",
+ "is_file": true,
+ "children": [
+ {
+ "type": "schema_template",
+ "name": "template_workfile_options",
+ "skip_paths": [
+ "workfile_builder/builder_on_start",
+ "workfile_builder/profiles"
+ ]
+ }
+ ]
+}
diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_nuke.json b/openpype/settings/entities/schemas/projects_schema/schema_project_nuke.json
index 5022b75719..f709e84651 100644
--- a/openpype/settings/entities/schemas/projects_schema/schema_project_nuke.json
+++ b/openpype/settings/entities/schemas/projects_schema/schema_project_nuke.json
@@ -43,16 +43,6 @@
"label": "Build Workfile"
}
]
- },
- {
- "type": "boolean",
- "key": "open_workfile_at_start",
- "label": "Open Workfile window at start of a Nuke session"
- },
- {
- "type": "boolean",
- "key": "create_initial_workfile",
- "label": "Create initial workfile version if none available"
}
]
},
@@ -103,8 +93,8 @@
"template_data": []
},
{
- "type": "schema",
- "name": "schema_workfile_build"
+ "type": "schema_template",
+ "name": "template_workfile_options"
},
{
"type": "schema",
diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_photoshop.json b/openpype/settings/entities/schemas/projects_schema/schema_project_photoshop.json
index 3a20b4e79c..4eb6c26dbb 100644
--- a/openpype/settings/entities/schemas/projects_schema/schema_project_photoshop.json
+++ b/openpype/settings/entities/schemas/projects_schema/schema_project_photoshop.json
@@ -52,6 +52,14 @@
]
}
]
+ },
+ {
+ "type": "schema_template",
+ "name": "template_workfile_options",
+ "skip_paths": [
+ "workfile_builder/builder_on_start",
+ "workfile_builder/profiles"
+ ]
}
]
}
diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_tvpaint.json b/openpype/settings/entities/schemas/projects_schema/schema_project_tvpaint.json
index 00080f8247..6f90bb4263 100644
--- a/openpype/settings/entities/schemas/projects_schema/schema_project_tvpaint.json
+++ b/openpype/settings/entities/schemas/projects_schema/schema_project_tvpaint.json
@@ -112,6 +112,14 @@
}
]
},
+ {
+ "type": "schema_template",
+ "name": "template_workfile_options",
+ "skip_paths": [
+ "workfile_builder/builder_on_start",
+ "workfile_builder/profiles"
+ ]
+ },
{
"type": "schema",
"name": "schema_publish_gui_filter"
diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_global_publish.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_global_publish.json
index 426da4b71e..0c89575d74 100644
--- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_global_publish.json
+++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_global_publish.json
@@ -173,6 +173,15 @@
{
"type": "separator"
},
+ {
+ "type": "label",
+ "label": "Crop input overscan. See the documentation for more information."
+ },
+ {
+ "type": "text",
+ "key": "overscan_crop",
+ "label": "Overscan crop"
+ },
{
"type": "label",
"label": "Width and Height must be both set to higher value than 0 else source resolution is used."
@@ -193,6 +202,15 @@
"minimum": 0,
"maximum": 100000
},
+ {
+ "type": "label",
+ "label": "Background color is used only when input have transparency and Alpha is higher than 0."
+ },
+ {
+ "type": "color",
+ "label": "Background color",
+ "key": "bg_color"
+ },
{
"key": "letter_box",
"label": "Letter box",
@@ -280,24 +298,14 @@
"minimum": 0
},
{
- "type": "schema_template",
- "name": "template_rgba_color",
- "template_data": [
- {
- "label": "Font Color",
- "name": "font_color"
- }
- ]
+ "type": "color",
+ "key": "font_color",
+ "label": "Font Color"
},
{
- "type": "schema_template",
- "name": "template_rgba_color",
- "template_data": [
- {
- "label": "Background Color",
- "name": "bg_color"
- }
- ]
+ "type": "color",
+ "key": "bg_color",
+ "label": "Background Color"
},
{
"type": "number",
diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_capture.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_capture.json
new file mode 100644
index 0000000000..d6b81c8687
--- /dev/null
+++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_capture.json
@@ -0,0 +1,471 @@
+{
+ "type": "dict",
+ "collapsible": true,
+ "key": "ExtractPlayblast",
+ "label": "Extract Playblast settings",
+ "children": [
+ {
+ "type": "dict",
+ "key": "capture_preset",
+ "children": [
+ {
+ "type": "dict",
+ "key": "Codec",
+ "children": [
+ {
+ "type": "label",
+ "label": "Codec"
+ },
+ {
+ "type": "text",
+ "key": "compression",
+ "label": "Compression type"
+ },
+ {
+ "type": "text",
+ "key": "format",
+ "label": "Data format"
+ },
+ {
+ "type": "number",
+ "key": "quality",
+ "label": "Quality",
+ "decimal": 0,
+ "minimum": 0,
+ "maximum": 100
+ },
+
+ {
+ "type": "splitter"
+ }
+ ]
+ },
+ {
+ "type": "dict",
+ "key": "Display Options",
+ "children": [
+ {
+ "type": "label",
+ "label": "Display Options"
+ },
+
+ {
+ "type": "color",
+ "key": "background",
+ "label": "Background Color: "
+ },
+ {
+ "type": "color",
+ "key": "backgroundBottom",
+ "label": "Background Bottom: "
+ },
+ {
+ "type": "color",
+ "key": "backgroundTop",
+ "label": "Background Top: "
+ },
+ {
+ "type": "boolean",
+ "key": "override_display",
+ "label": "Override display options"
+ }
+ ]
+ },
+ {
+ "type": "splitter"
+ },
+ {
+ "type": "dict",
+ "key": "Generic",
+ "children": [
+ {
+ "type": "label",
+ "label": "Generic"
+ },
+ {
+ "type": "boolean",
+ "key": "isolate_view",
+ "label": " Isolate view"
+ },
+ {
+ "type": "boolean",
+ "key": "off_screen",
+ "label": " Off Screen"
+ }
+ ]
+ },
+
+ {
+ "type": "dict",
+ "key": "PanZoom",
+ "children": [
+ {
+ "type": "boolean",
+ "key": "pan_zoom",
+ "label": " Pan Zoom"
+ }
+ ]
+ },
+ {
+ "type": "splitter"
+ },
+ {
+ "type": "dict",
+ "key": "Renderer",
+ "children": [
+ {
+ "type": "label",
+ "label": "Renderer"
+ },
+ {
+ "type": "enum",
+ "key": "rendererName",
+ "label": "Renderer name",
+ "enum_items": [
+ { "vp2Renderer": "Viewport 2.0" }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "dict",
+ "key": "Resolution",
+ "children": [
+ {
+ "type": "splitter"
+ },
+ {
+ "type": "label",
+ "label": "Resolution"
+ },
+ {
+ "type": "number",
+ "key": "width",
+ "label": " Width",
+ "decimal": 0,
+ "minimum": 0,
+ "maximum": 99999
+ },
+ {
+ "type": "number",
+ "key": "height",
+ "label": "Height",
+ "decimal": 0,
+ "minimum": 0,
+ "maximum": 99999
+ },
+ {
+ "type": "number",
+ "key": "percent",
+ "label": "percent",
+ "decimal": 1,
+ "minimum": 0,
+ "maximum": 200
+ },
+ {
+ "type": "text",
+ "key": "mode",
+ "label": "Mode"
+ }
+ ]
+ },
+ {
+ "type": "splitter"
+ },
+ {
+ "type": "dict",
+ "collapsible": true,
+ "key": "Viewport Options",
+ "label": "Viewport Options",
+ "children": [
+ {
+ "type": "boolean",
+ "key": "override_viewport_options",
+ "label": "override_viewport_options"
+ },
+ {
+ "type": "enum",
+ "key": "displayLights",
+ "label": "Display Lights",
+ "enum_items": [
+ { "default": "Default Lighting"},
+ { "all": "All Lights"},
+ { "selected": "Selected Lights"},
+ { "flat": "Flat Lighting"},
+ { "nolights": "No Lights"}
+ ]
+ },
+ {
+ "type": "number",
+ "key": "textureMaxResolution",
+ "label": "Texture Clamp Resolution",
+ "decimal": 0
+ },
+ {
+ "type": "number",
+ "key": "multiSample",
+ "label": "Anti Aliasing Samples",
+ "decimal": 0,
+ "minimum": 0,
+ "maximum": 32
+ },
+ {
+ "type": "boolean",
+ "key": "shadows",
+ "label": "Display Shadows"
+ },
+ {
+ "type": "boolean",
+ "key": "textures",
+ "label": "Display Textures"
+ },
+ {
+ "type": "boolean",
+ "key": "twoSidedLighting",
+ "label": "Two Sided Lighting"
+ },
+ {
+ "type": "boolean",
+ "key": "ssaoEnable",
+ "label": "Screen Space Ambient Occlusion"
+ },
+ {
+ "type": "splitter"
+ },
+ {
+ "type": "boolean",
+ "key": "cameras",
+ "label": "cameras"
+ },
+ {
+ "type": "boolean",
+ "key": "clipGhosts",
+ "label": "clipGhosts"
+ },
+ {
+ "type": "boolean",
+ "key": "controlVertices",
+ "label": "controlVertices"
+ },
+ {
+ "type": "boolean",
+ "key": "deformers",
+ "label": "deformers"
+ },
+ {
+ "type": "boolean",
+ "key": "dimensions",
+ "label": "dimensions"
+ },
+ {
+ "type": "boolean",
+ "key": "dynamicConstraints",
+ "label": "dynamicConstraints"
+ },
+ {
+ "type": "boolean",
+ "key": "dynamics",
+ "label": "dynamics"
+ },
+ {
+ "type": "boolean",
+ "key": "fluids",
+ "label": "fluids"
+ },
+ {
+ "type": "boolean",
+ "key": "follicles",
+ "label": "follicles"
+ },
+ {
+ "type": "boolean",
+ "key": "gpuCacheDisplayFilter",
+ "label": "gpuCacheDisplayFilter"
+ },
+ {
+ "type": "boolean",
+ "key": "greasePencils",
+ "label": "greasePencils"
+ },
+ {
+ "type": "boolean",
+ "key": "grid",
+ "label": "grid"
+ },
+ {
+ "type": "boolean",
+ "key": "hairSystems",
+ "label": "hairSystems"
+ },
+ {
+ "type": "boolean",
+ "key": "handles",
+ "label": "handles"
+ },
+ {
+ "type": "boolean",
+ "key": "hud",
+ "label": "hud"
+ },
+ {
+ "type": "boolean",
+ "key": "hulls",
+ "label": "hulls"
+ },
+ {
+ "type": "boolean",
+ "key": "ikHandles",
+ "label": "ikHandles"
+ },
+ {
+ "type": "boolean",
+ "key": "imagePlane",
+ "label": "imagePlane"
+ },
+ {
+ "type": "boolean",
+ "key": "joints",
+ "label": "joints"
+ },
+ {
+ "type": "boolean",
+ "key": "lights",
+ "label": "lights"
+ },
+ {
+ "type": "boolean",
+ "key": "locators",
+ "label": "locators"
+ },
+ {
+ "type": "boolean",
+ "key": "manipulators",
+ "label": "manipulators"
+ },
+ {
+ "type": "boolean",
+ "key": "motionTrails",
+ "label": "motionTrails"
+ },
+ {
+ "type": "boolean",
+ "key": "nCloths",
+ "label": "nCloths"
+ },
+ {
+ "type": "boolean",
+ "key": "nParticles",
+ "label": "nParticles"
+ },
+ {
+ "type": "boolean",
+ "key": "nRigids",
+ "label": "nRigids"
+ },
+ {
+ "type": "boolean",
+ "key": "nurbsCurves",
+ "label": "nurbsCurves"
+ },
+ {
+ "type": "boolean",
+ "key": "nurbsSurfaces",
+ "label": "nurbsSurfaces"
+ },
+ {
+ "type": "boolean",
+ "key": "particleInstancers",
+ "label": "particleInstancers"
+ },
+ {
+ "type": "boolean",
+ "key": "pivots",
+ "label": "pivots"
+ },
+ {
+ "type": "boolean",
+ "key": "planes",
+ "label": "planes"
+ },
+ {
+ "type": "boolean",
+ "key": "pluginShapes",
+ "label": "pluginShapes"
+ },
+ {
+ "type": "boolean",
+ "key": "polymeshes",
+ "label": "polymeshes"
+ },
+ {
+ "type": "boolean",
+ "key": "strokes",
+ "label": "strokes"
+ },
+ {
+ "type": "boolean",
+ "key": "subdivSurfaces",
+ "label": "subdivSurfaces"
+ }
+ ]
+ },
+ {
+ "type": "dict",
+ "collapsible": true,
+ "key": "Camera Options",
+ "label": "Camera Options",
+ "children": [
+ {
+ "type": "boolean",
+ "key": "displayGateMask",
+ "label": "displayGateMask"
+ },
+ {
+ "type": "boolean",
+ "key": "displayResolution",
+ "label": "displayResolution"
+ },
+ {
+ "type": "boolean",
+ "key": "displayFilmGate",
+ "label": "displayFilmGate"
+ },
+ {
+ "type": "boolean",
+ "key": "displayFieldChart",
+ "label": "displayFieldChart"
+ },
+ {
+ "type": "boolean",
+ "key": "displaySafeAction",
+ "label": "displaySafeAction"
+ },
+ {
+ "type": "boolean",
+ "key": "displaySafeTitle",
+ "label": "displaySafeTitle"
+ },
+ {
+ "type": "boolean",
+ "key": "displayFilmPivot",
+ "label": "displayFilmPivot"
+ },
+ {
+ "type": "boolean",
+ "key": "displayFilmOrigin",
+ "label": "displayFilmOrigin"
+ },
+ {
+ "type": "number",
+ "key": "overscan",
+ "label": "overscan",
+ "decimal": 1,
+ "minimum": 0,
+ "maximum": 10
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_load.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_load.json
index dd9d0508b4..0b09d08700 100644
--- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_load.json
+++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_load.json
@@ -11,144 +11,74 @@
"label": "Loaded Subsets Outliner Colors",
"children": [
{
- "type": "schema_template",
- "name": "template_color",
- "template_data": [
- {
- "label": "Model",
- "name": "model"
- }
- ]
+ "type": "color",
+ "label": "Model:",
+ "key": "model"
},
{
- "type": "schema_template",
- "name": "template_color",
- "template_data": [
- {
- "label": "Rig",
- "name": "rig"
- }
- ]
+ "type": "color",
+ "label": "Rig:",
+ "key": "rig"
},
{
- "type": "schema_template",
- "name": "template_color",
- "template_data": [
- {
- "label": "Pointcache",
- "name": "pointcache"
- }
- ]
+ "type": "color",
+ "label": "Pointcache:",
+ "key": "pointcache"
},
{
- "type": "schema_template",
- "name": "template_color",
- "template_data": [
- {
- "label": "Animation",
- "name": "animation"
- }
- ]
+ "type": "color",
+ "label": "Animation:",
+ "key": "animation"
},
{
- "type": "schema_template",
- "name": "template_color",
- "template_data": [
- {
- "label": "Arnold Standin",
- "name": "ass"
- }
- ]
+ "type": "color",
+ "label": "Arnold Standin:",
+ "key": "ass"
},
{
- "type": "schema_template",
- "name": "template_color",
- "template_data": [
- {
- "label": "Camera",
- "name": "camera"
- }
- ]
+ "type": "color",
+ "label": "Camera:",
+ "key": "camera"
},
{
- "type": "schema_template",
- "name": "template_color",
- "template_data": [
- {
- "label": "FBX",
- "name": "fbx"
- }
- ]
+ "type": "color",
+ "label": "FBX:",
+ "key": "fbx"
},
{
- "type": "schema_template",
- "name": "template_color",
- "template_data": [
- {
- "label": "Maya Scene",
- "name": "mayaAscii"
- }
- ]
+ "type": "color",
+ "label": "Maya Scene:",
+ "key": "mayaAscii"
},
{
- "type": "schema_template",
- "name": "template_color",
- "template_data": [
- {
- "label": "Set Dress",
- "name": "setdress"
- }
- ]
+ "type": "color",
+ "label": "Set Dress:",
+ "key": "setdress"
},
{
- "type": "schema_template",
- "name": "template_color",
- "template_data": [
- {
- "label": "Layout",
- "name": "layout"
- }
- ]
+ "type": "color",
+ "label": "Layout:",
+ "key": "layout"
},
{
- "type": "schema_template",
- "name": "template_color",
- "template_data": [
- {
- "label": "VDB Cache",
- "name": "vdbcache"
- }
- ]
+ "type": "color",
+ "label": "VDB Cache:",
+ "key": "vdbcache"
},
{
- "type": "schema_template",
- "name": "template_color",
- "template_data": [
- {
- "label": "Vray Proxy",
- "name": "vrayproxy"
- }
- ]
+ "type": "color",
+ "label": "Vray Proxy:",
+ "key": "vrayproxy"
},
{
- "type": "schema_template",
- "name": "template_color",
- "template_data": [
- {
- "label": "Yeti Cache",
- "name": "yeticache"
- }
- ]
+ "type": "color",
+ "label": "Yeti Cache:",
+ "key": "yeticache"
},
{
- "type": "schema_template",
- "name": "template_color",
- "template_data": [
- {
- "label": "Yeti Rig",
- "name": "yetiRig"
- }
- ]
+ "type": "color",
+ "label": "Yeti Rig:",
+ "key": "yetiRig"
}
]
}
diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json
index 4cabf5bb74..0abcdd2965 100644
--- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json
+++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json
@@ -297,8 +297,8 @@
"label": "Extractors"
},
{
- "type": "schema_template",
- "name": "template_maya_capture"
+ "type": "schema",
+ "name": "schema_maya_capture"
},
{
"type": "dict",
diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_workfile_build.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_workfile_build.json
index 0cb36c2f92..078bb81bba 100644
--- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_workfile_build.json
+++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_workfile_build.json
@@ -94,4 +94,4 @@
}
}
]
-}
+}
\ No newline at end of file
diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/template_color.json b/openpype/settings/entities/schemas/projects_schema/schemas/template_color.json
index 04ce055525..af8fd9dae4 100644
--- a/openpype/settings/entities/schemas/projects_schema/schemas/template_color.json
+++ b/openpype/settings/entities/schemas/projects_schema/schemas/template_color.json
@@ -2,7 +2,7 @@
{
"type": "list-strict",
"key": "{name}",
- "label": "{label}:",
+ "label": "{label}",
"object_types": [
{
"label": "Red",
diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/template_maya_capture.json b/openpype/settings/entities/schemas/projects_schema/schemas/template_maya_capture.json
deleted file mode 100644
index e4e0b034dd..0000000000
--- a/openpype/settings/entities/schemas/projects_schema/schemas/template_maya_capture.json
+++ /dev/null
@@ -1,541 +0,0 @@
-[
- {
- "type": "dict",
- "collapsible": true,
- "key": "ExtractPlayblast",
- "label": "Extract Playblast settings",
- "children": [
- {
- "type": "dict",
- "key": "capture_preset",
- "children": [
- {
- "type": "dict",
- "key": "Codec",
- "children": [
- {
- "type": "label",
- "label": "Codec"
- },
- {
- "type": "text",
- "key": "compression",
- "label": "Compression type"
- },
- {
- "type": "text",
- "key": "format",
- "label": "Data format"
- },
- {
- "type": "number",
- "key": "quality",
- "label": "Quality",
- "decimal": 0,
- "minimum": 0,
- "maximum": 100
- },
-
- {
- "type": "splitter"
- }
- ]
- },
- {
- "type": "dict",
- "key": "Display Options",
- "children": [
- {
- "type": "label",
- "label": "Display Options"
- },
- {
- "type": "list-strict",
- "key": "background",
- "label": "Background Color: ",
- "object_types": [
- {
- "label": "Red",
- "type": "number",
- "minimum": 0,
- "maximum": 1,
- "decimal": 3
- },
- {
- "label": "Green",
- "type": "number",
- "minimum": 0,
- "maximum": 1,
- "decimal": 3
- },
- {
- "label": "Blue",
- "type": "number",
- "minimum": 0,
- "maximum": 1,
- "decimal": 3
- }
- ]
- },
- {
- "type": "list-strict",
- "key": "backgroundBottom",
- "label": "Background Bottom: ",
- "object_types": [
- {
- "label": "Red",
- "type": "number",
- "minimum": 0,
- "maximum": 1,
- "decimal": 3
- },
- {
- "label": "Green",
- "type": "number",
- "minimum": 0,
- "maximum": 1,
- "decimal": 3
- },
- {
- "label": "Blue",
- "type": "number",
- "minimum": 0,
- "maximum": 1,
- "decimal": 3
- }
- ]
- },
- {
- "type": "list-strict",
- "key": "backgroundTop",
- "label": "Background Top: ",
- "object_types": [
- {
- "label": "Red",
- "type": "number",
- "minimum": 0,
- "maximum": 1,
- "decimal": 3
- },
- {
- "label": "Green",
- "type": "number",
- "minimum": 0,
- "maximum": 1,
- "decimal": 3
- },
- {
- "label": "Blue",
- "type": "number",
- "minimum": 0,
- "maximum": 1,
- "decimal": 3
- }
- ]
- },
- {
- "type": "boolean",
- "key": "override_display",
- "label": "Override display options"
- }
- ]
- },
- {
- "type": "splitter"
- },
- {
- "type": "dict",
- "key": "Generic",
- "children": [
- {
- "type": "label",
- "label": "Generic"
- },
- {
- "type": "boolean",
- "key": "isolate_view",
- "label": " Isolate view"
- },
- {
- "type": "boolean",
- "key": "off_screen",
- "label": " Off Screen"
- }
- ]
- },
-
- {
- "type": "dict",
- "key": "PanZoom",
- "children": [
- {
- "type": "boolean",
- "key": "pan_zoom",
- "label": " Pan Zoom"
- }
- ]
- },
- {
- "type": "splitter"
- },
- {
- "type": "dict",
- "key": "Renderer",
- "children": [
- {
- "type": "label",
- "label": "Renderer"
- },
- {
- "type": "enum",
- "key": "rendererName",
- "label": "Renderer name",
- "enum_items": [
- { "vp2Renderer": "Viewport 2.0" }
- ]
- }
- ]
- },
- {
- "type": "dict",
- "key": "Resolution",
- "children": [
- {
- "type": "splitter"
- },
- {
- "type": "label",
- "label": "Resolution"
- },
- {
- "type": "number",
- "key": "width",
- "label": " Width",
- "decimal": 0,
- "minimum": 0,
- "maximum": 99999
- },
- {
- "type": "number",
- "key": "height",
- "label": "Height",
- "decimal": 0,
- "minimum": 0,
- "maximum": 99999
- },
- {
- "type": "number",
- "key": "percent",
- "label": "percent",
- "decimal": 1,
- "minimum": 0,
- "maximum": 200
- },
- {
- "type": "text",
- "key": "mode",
- "label": "Mode"
- }
- ]
- },
- {
- "type": "splitter"
- },
- {
- "type": "dict",
- "collapsible": true,
- "key": "Viewport Options",
- "label": "Viewport Options",
- "children": [
- {
- "type": "boolean",
- "key": "override_viewport_options",
- "label": "override_viewport_options"
- },
- {
- "type": "enum",
- "key": "displayLights",
- "label": "Display Lights",
- "enum_items": [
- { "default": "Default Lighting"},
- { "all": "All Lights"},
- { "selected": "Selected Lights"},
- { "flat": "Flat Lighting"},
- { "nolights": "No Lights"}
- ]
- },
- {
- "type": "number",
- "key": "textureMaxResolution",
- "label": "Texture Clamp Resolution",
- "decimal": 0
- },
- {
- "type": "number",
- "key": "multiSample",
- "label": "Anti Aliasing Samples",
- "decimal": 0,
- "minimum": 0,
- "maximum": 32
- },
- {
- "type": "boolean",
- "key": "shadows",
- "label": "Display Shadows"
- },
- {
- "type": "boolean",
- "key": "textures",
- "label": "Display Textures"
- },
- {
- "type": "boolean",
- "key": "twoSidedLighting",
- "label": "Two Sided Lighting"
- },
- {
- "type": "boolean",
- "key": "ssaoEnable",
- "label": "Screen Space Ambient Occlusion"
- },
- {
- "type": "splitter"
- },
- {
- "type": "boolean",
- "key": "cameras",
- "label": "cameras"
- },
- {
- "type": "boolean",
- "key": "clipGhosts",
- "label": "clipGhosts"
- },
- {
- "type": "boolean",
- "key": "controlVertices",
- "label": "controlVertices"
- },
- {
- "type": "boolean",
- "key": "deformers",
- "label": "deformers"
- },
- {
- "type": "boolean",
- "key": "dimensions",
- "label": "dimensions"
- },
- {
- "type": "boolean",
- "key": "dynamicConstraints",
- "label": "dynamicConstraints"
- },
- {
- "type": "boolean",
- "key": "dynamics",
- "label": "dynamics"
- },
- {
- "type": "boolean",
- "key": "fluids",
- "label": "fluids"
- },
- {
- "type": "boolean",
- "key": "follicles",
- "label": "follicles"
- },
- {
- "type": "boolean",
- "key": "gpuCacheDisplayFilter",
- "label": "gpuCacheDisplayFilter"
- },
- {
- "type": "boolean",
- "key": "greasePencils",
- "label": "greasePencils"
- },
- {
- "type": "boolean",
- "key": "grid",
- "label": "grid"
- },
- {
- "type": "boolean",
- "key": "hairSystems",
- "label": "hairSystems"
- },
- {
- "type": "boolean",
- "key": "handles",
- "label": "handles"
- },
- {
- "type": "boolean",
- "key": "hud",
- "label": "hud"
- },
- {
- "type": "boolean",
- "key": "hulls",
- "label": "hulls"
- },
- {
- "type": "boolean",
- "key": "ikHandles",
- "label": "ikHandles"
- },
- {
- "type": "boolean",
- "key": "imagePlane",
- "label": "imagePlane"
- },
- {
- "type": "boolean",
- "key": "joints",
- "label": "joints"
- },
- {
- "type": "boolean",
- "key": "lights",
- "label": "lights"
- },
- {
- "type": "boolean",
- "key": "locators",
- "label": "locators"
- },
- {
- "type": "boolean",
- "key": "manipulators",
- "label": "manipulators"
- },
- {
- "type": "boolean",
- "key": "motionTrails",
- "label": "motionTrails"
- },
- {
- "type": "boolean",
- "key": "nCloths",
- "label": "nCloths"
- },
- {
- "type": "boolean",
- "key": "nParticles",
- "label": "nParticles"
- },
- {
- "type": "boolean",
- "key": "nRigids",
- "label": "nRigids"
- },
- {
- "type": "boolean",
- "key": "nurbsCurves",
- "label": "nurbsCurves"
- },
- {
- "type": "boolean",
- "key": "nurbsSurfaces",
- "label": "nurbsSurfaces"
- },
- {
- "type": "boolean",
- "key": "particleInstancers",
- "label": "particleInstancers"
- },
- {
- "type": "boolean",
- "key": "pivots",
- "label": "pivots"
- },
- {
- "type": "boolean",
- "key": "planes",
- "label": "planes"
- },
- {
- "type": "boolean",
- "key": "pluginShapes",
- "label": "pluginShapes"
- },
- {
- "type": "boolean",
- "key": "polymeshes",
- "label": "polymeshes"
- },
- {
- "type": "boolean",
- "key": "strokes",
- "label": "strokes"
- },
- {
- "type": "boolean",
- "key": "subdivSurfaces",
- "label": "subdivSurfaces"
- }
- ]
- },
- {
- "type": "dict",
- "collapsible": true,
- "key": "Camera Options",
- "label": "Camera Options",
- "children": [
- {
- "type": "boolean",
- "key": "displayGateMask",
- "label": "displayGateMask"
- },
- {
- "type": "boolean",
- "key": "displayResolution",
- "label": "displayResolution"
- },
- {
- "type": "boolean",
- "key": "displayFilmGate",
- "label": "displayFilmGate"
- },
- {
- "type": "boolean",
- "key": "displayFieldChart",
- "label": "displayFieldChart"
- },
- {
- "type": "boolean",
- "key": "displaySafeAction",
- "label": "displaySafeAction"
- },
- {
- "type": "boolean",
- "key": "displaySafeTitle",
- "label": "displaySafeTitle"
- },
- {
- "type": "boolean",
- "key": "displayFilmPivot",
- "label": "displayFilmPivot"
- },
- {
- "type": "boolean",
- "key": "displayFilmOrigin",
- "label": "displayFilmOrigin"
- },
- {
- "type": "number",
- "key": "overscan",
- "label": "overscan",
- "decimal": 1,
- "minimum": 0,
- "maximum": 10
- }
- ]
- }
- ]
- }
- ]
- }
-]
diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/template_rgba_color.json b/openpype/settings/entities/schemas/projects_schema/schemas/template_rgba_color.json
deleted file mode 100644
index ffe530175a..0000000000
--- a/openpype/settings/entities/schemas/projects_schema/schemas/template_rgba_color.json
+++ /dev/null
@@ -1,33 +0,0 @@
-[
- {
- "type": "list-strict",
- "key": "{name}",
- "label": "{label}",
- "object_types": [
- {
- "label": "R",
- "type": "number",
- "minimum": 0,
- "maximum": 255
- },
- {
- "label": "G",
- "type": "number",
- "minimum": 0,
- "maximum": 255
- },
- {
- "label": "B",
- "type": "number",
- "minimum": 0,
- "maximum": 255
- },
- {
- "label": "A",
- "type": "number",
- "minimum": 0,
- "maximum": 255
- }
- ]
- }
-]
diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/template_workfile_builder_simple.json b/openpype/settings/entities/schemas/projects_schema/schemas/template_workfile_builder_simple.json
new file mode 100644
index 0000000000..49cf9ca94a
--- /dev/null
+++ b/openpype/settings/entities/schemas/projects_schema/schemas/template_workfile_builder_simple.json
@@ -0,0 +1,23 @@
+[
+ {
+ "type": "dict",
+ "collapsible": true,
+ "key": "workfile_builder",
+ "label": "Workfile Builder",
+ "children": [
+ {
+ "type": "boolean",
+ "key": "create_first_version",
+ "label": "Create first workfile",
+ "default": false
+ },
+ {
+ "type": "path",
+ "key": "template_path",
+ "label": "First workfile template",
+ "multiplatform": true,
+ "multipath": false
+ }
+ ]
+ }
+]
diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/template_workfile_options.json b/openpype/settings/entities/schemas/projects_schema/schemas/template_workfile_options.json
new file mode 100644
index 0000000000..815df85879
--- /dev/null
+++ b/openpype/settings/entities/schemas/projects_schema/schemas/template_workfile_options.json
@@ -0,0 +1,145 @@
+[{
+ "type": "dict",
+ "collapsible": true,
+ "key": "workfile_builder",
+ "label": "Workfile Builder",
+ "children": [
+ {
+ "type": "boolean",
+ "key": "create_first_version",
+ "label": "Create first workfile",
+ "default": false
+ },
+ {
+ "type": "list",
+ "key": "custom_templates",
+ "label": "Custom templates",
+ "is_group": true,
+ "use_label_wrap": true,
+ "object_type": {
+ "type": "dict",
+ "children": [
+ {
+ "type": "task-types-enum",
+ "key": "task_types",
+ "label": "Task types"
+ },
+ {
+ "type": "splitter"
+ },
+ {
+ "type": "label",
+ "label": "Absolute path to workfile template or OpenPype Anatomy text is accepted."
+ },
+ {
+ "type": "path",
+ "key": "path",
+ "label": "Path",
+ "multiplatform": true,
+ "multipath": false
+ }
+ ]
+ }
+ },
+ {
+ "type": "boolean",
+ "key": "builder_on_start",
+ "label": "Run Builder Profiles on first launch",
+ "default": false
+ },
+ {
+ "type": "list",
+ "key": "profiles",
+ "label": "Profiles",
+ "use_label_wrap": true,
+ "object_type": {
+ "type": "dict",
+ "children": [
+ {
+ "key": "tasks",
+ "label": "Tasks",
+ "type": "list",
+ "object_type": "text"
+ },
+ {
+ "type": "splitter"
+ },
+ {
+ "key": "current_context",
+ "label": "Current Context",
+ "type": "list",
+ "highlight_content": true,
+ "object_type": {
+ "type": "dict",
+ "children": [
+ {
+ "key": "subset_name_filters",
+ "label": "Subset name Filters",
+ "type": "list",
+ "object_type": "text"
+ },
+ {
+ "key": "families",
+ "label": "Families",
+ "type": "list",
+ "object_type": "text"
+ },
+ {
+ "key": "repre_names",
+ "label": "Repre Names",
+ "type": "list",
+ "object_type": "text"
+ },
+ {
+ "key": "loaders",
+ "label": "Loaders",
+ "type": "list",
+ "object_type": "text"
+ }
+ ]
+ }
+ },
+ {
+ "type": "separator"
+ },
+ {
+ "key": "linked_assets",
+ "label": "Linked Assets/Shots",
+ "type": "list",
+ "highlight_content": true,
+ "object_type": {
+ "type": "dict",
+ "children": [
+ {
+ "key": "subset_name_filters",
+ "label": "Subset name Filters",
+ "type": "list",
+ "object_type": "text"
+ },
+ {
+ "key": "families",
+ "label": "Families",
+ "type": "list",
+ "object_type": "text"
+ },
+ {
+ "key": "repre_names",
+ "label": "Repre Names",
+ "type": "list",
+ "object_type": "text"
+ },
+ {
+ "key": "loaders",
+ "label": "Loaders",
+ "type": "list",
+ "object_type": "text"
+ }
+ ]
+ }
+ }
+ ]
+ }
+ }
+ ]
+}
+]
diff --git a/openpype/settings/entities/schemas/system_schema/module_settings/schema_ftrack.json b/openpype/settings/entities/schemas/system_schema/module_settings/schema_ftrack.json
index 50ec330a11..5f659522c3 100644
--- a/openpype/settings/entities/schemas/system_schema/module_settings/schema_ftrack.json
+++ b/openpype/settings/entities/schemas/system_schema/module_settings/schema_ftrack.json
@@ -3,6 +3,7 @@
"key": "ftrack",
"label": "Ftrack",
"collapsible": true,
+ "require_restart": true,
"checkbox_key": "enabled",
"children": [
{
diff --git a/openpype/settings/entities/schemas/system_schema/schema_general.json b/openpype/settings/entities/schemas/system_schema/schema_general.json
index 568ccad5b9..fe5a8d8203 100644
--- a/openpype/settings/entities/schemas/system_schema/schema_general.json
+++ b/openpype/settings/entities/schemas/system_schema/schema_general.json
@@ -34,7 +34,8 @@
"key": "environment",
"label": "Environment",
"type": "raw-json",
- "env_group_key": "global"
+ "env_group_key": "global",
+ "require_restart": true
},
{
"type": "splitter"
@@ -44,7 +45,8 @@
"key": "openpype_path",
"label": "Versions Repository",
"multiplatform": true,
- "multipath": true
+ "multipath": true,
+ "require_restart": true
}
]
}
diff --git a/openpype/settings/entities/schemas/system_schema/schema_modules.json b/openpype/settings/entities/schemas/system_schema/schema_modules.json
index b643293c87..16251b5f27 100644
--- a/openpype/settings/entities/schemas/system_schema/schema_modules.json
+++ b/openpype/settings/entities/schemas/system_schema/schema_modules.json
@@ -10,6 +10,7 @@
"key": "avalon",
"label": "Avalon",
"collapsible": true,
+ "require_restart": true,
"children": [
{
"type": "number",
@@ -35,6 +36,7 @@
"key": "timers_manager",
"label": "Timers Manager",
"collapsible": true,
+ "require_restart": true,
"checkbox_key": "enabled",
"children": [
{
@@ -66,6 +68,7 @@
"key": "clockify",
"label": "Clockify",
"collapsible": true,
+ "require_restart": true,
"checkbox_key": "enabled",
"children": [
{
@@ -84,6 +87,7 @@
"key": "sync_server",
"label": "Site Sync",
"collapsible": true,
+ "require_restart": true,
"checkbox_key": "enabled",
"children": [
{
@@ -114,6 +118,7 @@
"type": "dict",
"key": "deadline",
"label": "Deadline",
+ "require_restart": true,
"collapsible": true,
"checkbox_key": "enabled",
"children": [
@@ -133,6 +138,7 @@
"type": "dict",
"key": "muster",
"label": "Muster",
+ "require_restart": true,
"collapsible": true,
"checkbox_key": "enabled",
"children": [
diff --git a/openpype/style/__init__.py b/openpype/style/__init__.py
new file mode 100644
index 0000000000..89a210bee9
--- /dev/null
+++ b/openpype/style/__init__.py
@@ -0,0 +1,93 @@
+import os
+import json
+import collections
+from openpype import resources
+
+
+_STYLESHEET_CACHE = None
+_FONT_IDS = None
+
+current_dir = os.path.dirname(os.path.abspath(__file__))
+
+
+def _load_stylesheet():
+ from . import qrc_resources
+
+ qrc_resources.qInitResources()
+
+ style_path = os.path.join(current_dir, "style.css")
+ with open(style_path, "r") as style_file:
+ stylesheet = style_file.read()
+
+ data_path = os.path.join(current_dir, "data.json")
+ with open(data_path, "r") as data_stream:
+ data = json.load(data_stream)
+
+ data_deque = collections.deque()
+ for item in data.items():
+ data_deque.append(item)
+
+ fill_data = {}
+ while data_deque:
+ key, value = data_deque.popleft()
+ if isinstance(value, dict):
+ for sub_key, sub_value in value.items():
+ new_key = "{}:{}".format(key, sub_key)
+ data_deque.append((new_key, sub_value))
+ continue
+ fill_data[key] = value
+
+ for key, value in fill_data.items():
+ replacement_key = "{" + key + "}"
+ stylesheet = stylesheet.replace(replacement_key, value)
+ return stylesheet
+
+
+def _load_font():
+ from Qt import QtGui
+
+ global _FONT_IDS
+
+ # Check if font ids are still loaded
+ if _FONT_IDS is not None:
+ for font_id in tuple(_FONT_IDS):
+ font_families = QtGui.QFontDatabase.applicationFontFamilies(
+ font_id
+ )
+ # Reset font if font id is not available
+ if not font_families:
+ _FONT_IDS = None
+ break
+
+ if _FONT_IDS is None:
+ _FONT_IDS = []
+ fonts_dirpath = os.path.join(current_dir, "fonts")
+ font_dirs = []
+ font_dirs.append(os.path.join(fonts_dirpath, "Montserrat"))
+ font_dirs.append(os.path.join(fonts_dirpath, "Spartan"))
+
+ loaded_fonts = []
+ for font_dir in font_dirs:
+ for filename in os.listdir(font_dir):
+ if os.path.splitext(filename)[1] not in [".ttf"]:
+ continue
+ full_path = os.path.join(font_dir, filename)
+ font_id = QtGui.QFontDatabase.addApplicationFont(full_path)
+ _FONT_IDS.append(font_id)
+ font_families = QtGui.QFontDatabase.applicationFontFamilies(
+ font_id
+ )
+ loaded_fonts.extend(font_families)
+ print("Registered font families: {}".format(", ".join(loaded_fonts)))
+
+
+def load_stylesheet():
+ global _STYLESHEET_CACHE
+ if _STYLESHEET_CACHE is None:
+ _STYLESHEET_CACHE = _load_stylesheet()
+ _load_font()
+ return _STYLESHEET_CACHE
+
+
+def app_icon_path():
+ return resources.pype_icon_filepath()
diff --git a/openpype/style/data.json b/openpype/style/data.json
new file mode 100644
index 0000000000..a58829d946
--- /dev/null
+++ b/openpype/style/data.json
@@ -0,0 +1,52 @@
+{
+ "palette": {
+ "grey-base": "#2C313A",
+ "grey-light": "#373D48",
+ "grey-lighter": "#434a56",
+ "grey-lightest": "#4E5565",
+ "grey-input": "#353A45",
+ "grey-dark": "#21252B",
+
+ "text-darker": "#99A3B2",
+ "text-base": "#D3D8DE",
+ "text-lighter": "#F0F2F5",
+
+ "blue-base": "hsl(200, 60%, 60%)",
+ "blue-light": "hsl(200, 80%, 80%)",
+
+ "green-base": "hsl(155, 55%, 55%)",
+ "green-light": "hsl(155, 80%, 80%)"
+ },
+ "color": {
+
+ "font": "#D3D8DE",
+ "font-hover": "#F0F2F5",
+ "font-disabled": "#99A3B2",
+ "font-view-selection": "#ffffff",
+ "font-view-hover": "#F0F2F5",
+
+ "bg": "#2C313A",
+ "bg-inputs": "#21252B",
+ "bg-buttons": "#434a56",
+ "bg-button-hover": "hsla(220, 14%, 70%, .3)",
+ "bg-inputs-disabled": "#2C313A",
+ "bg-buttons-disabled": "#434a56",
+
+ "bg-menu-separator": "rgba(75, 83, 98, 127)",
+
+ "bg-scroll-handle": "#4B5362",
+
+ "bg-view": "#21252B",
+ "bg-view-header": "#373D48",
+ "bg-view-hover": "hsla(220, 14%, 70%, .3)",
+ "bg-view-alternate": "rgb(36, 42, 50)",
+ "bg-view-disabled": "#434a56",
+ "bg-view-alternate-disabled": "#2C313A",
+ "bg-view-selection": "hsla(200, 60%, 60%, .4)",
+ "bg-view-selection-hover": "hsla(200, 60%, 60%, .8)",
+
+ "border": "#373D48",
+ "border-hover": "hsla(220, 14%, 70%, .3)",
+ "border-focus": "hsl(200, 60%, 60%)"
+ }
+}
diff --git a/openpype/style/fonts/Montserrat/Montserrat-Black.ttf b/openpype/style/fonts/Montserrat/Montserrat-Black.ttf
new file mode 100644
index 0000000000..437b1157cb
Binary files /dev/null and b/openpype/style/fonts/Montserrat/Montserrat-Black.ttf differ
diff --git a/openpype/style/fonts/Montserrat/Montserrat-BlackItalic.ttf b/openpype/style/fonts/Montserrat/Montserrat-BlackItalic.ttf
new file mode 100644
index 0000000000..52348354c2
Binary files /dev/null and b/openpype/style/fonts/Montserrat/Montserrat-BlackItalic.ttf differ
diff --git a/openpype/style/fonts/Montserrat/Montserrat-Bold.ttf b/openpype/style/fonts/Montserrat/Montserrat-Bold.ttf
new file mode 100644
index 0000000000..221819bca0
Binary files /dev/null and b/openpype/style/fonts/Montserrat/Montserrat-Bold.ttf differ
diff --git a/openpype/style/fonts/Montserrat/Montserrat-BoldItalic.ttf b/openpype/style/fonts/Montserrat/Montserrat-BoldItalic.ttf
new file mode 100644
index 0000000000..9ae2bd240f
Binary files /dev/null and b/openpype/style/fonts/Montserrat/Montserrat-BoldItalic.ttf differ
diff --git a/openpype/style/fonts/Montserrat/Montserrat-ExtraBold.ttf b/openpype/style/fonts/Montserrat/Montserrat-ExtraBold.ttf
new file mode 100644
index 0000000000..80ea8061b0
Binary files /dev/null and b/openpype/style/fonts/Montserrat/Montserrat-ExtraBold.ttf differ
diff --git a/openpype/style/fonts/Montserrat/Montserrat-ExtraBoldItalic.ttf b/openpype/style/fonts/Montserrat/Montserrat-ExtraBoldItalic.ttf
new file mode 100644
index 0000000000..6c961e1cc9
Binary files /dev/null and b/openpype/style/fonts/Montserrat/Montserrat-ExtraBoldItalic.ttf differ
diff --git a/openpype/style/fonts/Montserrat/Montserrat-ExtraLight.ttf b/openpype/style/fonts/Montserrat/Montserrat-ExtraLight.ttf
new file mode 100644
index 0000000000..ca0bbb6569
Binary files /dev/null and b/openpype/style/fonts/Montserrat/Montserrat-ExtraLight.ttf differ
diff --git a/openpype/style/fonts/Montserrat/Montserrat-ExtraLightItalic.ttf b/openpype/style/fonts/Montserrat/Montserrat-ExtraLightItalic.ttf
new file mode 100644
index 0000000000..f3c1559ec7
Binary files /dev/null and b/openpype/style/fonts/Montserrat/Montserrat-ExtraLightItalic.ttf differ
diff --git a/openpype/style/fonts/Montserrat/Montserrat-Italic.ttf b/openpype/style/fonts/Montserrat/Montserrat-Italic.ttf
new file mode 100644
index 0000000000..eb4232a0c2
Binary files /dev/null and b/openpype/style/fonts/Montserrat/Montserrat-Italic.ttf differ
diff --git a/openpype/style/fonts/Montserrat/Montserrat-Light.ttf b/openpype/style/fonts/Montserrat/Montserrat-Light.ttf
new file mode 100644
index 0000000000..990857de8e
Binary files /dev/null and b/openpype/style/fonts/Montserrat/Montserrat-Light.ttf differ
diff --git a/openpype/style/fonts/Montserrat/Montserrat-LightItalic.ttf b/openpype/style/fonts/Montserrat/Montserrat-LightItalic.ttf
new file mode 100644
index 0000000000..209604046b
Binary files /dev/null and b/openpype/style/fonts/Montserrat/Montserrat-LightItalic.ttf differ
diff --git a/openpype/style/fonts/Montserrat/Montserrat-Medium.ttf b/openpype/style/fonts/Montserrat/Montserrat-Medium.ttf
new file mode 100644
index 0000000000..6e079f6984
Binary files /dev/null and b/openpype/style/fonts/Montserrat/Montserrat-Medium.ttf differ
diff --git a/openpype/style/fonts/Montserrat/Montserrat-MediumItalic.ttf b/openpype/style/fonts/Montserrat/Montserrat-MediumItalic.ttf
new file mode 100644
index 0000000000..0dc3ac9c29
Binary files /dev/null and b/openpype/style/fonts/Montserrat/Montserrat-MediumItalic.ttf differ
diff --git a/openpype/style/fonts/Montserrat/Montserrat-Regular.ttf b/openpype/style/fonts/Montserrat/Montserrat-Regular.ttf
new file mode 100644
index 0000000000..8d443d5d56
Binary files /dev/null and b/openpype/style/fonts/Montserrat/Montserrat-Regular.ttf differ
diff --git a/openpype/style/fonts/Montserrat/Montserrat-SemiBold.ttf b/openpype/style/fonts/Montserrat/Montserrat-SemiBold.ttf
new file mode 100644
index 0000000000..f8a43f2b20
Binary files /dev/null and b/openpype/style/fonts/Montserrat/Montserrat-SemiBold.ttf differ
diff --git a/openpype/style/fonts/Montserrat/Montserrat-SemiBoldItalic.ttf b/openpype/style/fonts/Montserrat/Montserrat-SemiBoldItalic.ttf
new file mode 100644
index 0000000000..336c56ec0c
Binary files /dev/null and b/openpype/style/fonts/Montserrat/Montserrat-SemiBoldItalic.ttf differ
diff --git a/openpype/style/fonts/Montserrat/Montserrat-Thin.ttf b/openpype/style/fonts/Montserrat/Montserrat-Thin.ttf
new file mode 100644
index 0000000000..b9858757eb
Binary files /dev/null and b/openpype/style/fonts/Montserrat/Montserrat-Thin.ttf differ
diff --git a/openpype/style/fonts/Montserrat/Montserrat-ThinItalic.ttf b/openpype/style/fonts/Montserrat/Montserrat-ThinItalic.ttf
new file mode 100644
index 0000000000..e488998ec7
Binary files /dev/null and b/openpype/style/fonts/Montserrat/Montserrat-ThinItalic.ttf differ
diff --git a/openpype/style/fonts/Montserrat/OFL.txt b/openpype/style/fonts/Montserrat/OFL.txt
new file mode 100644
index 0000000000..f435ed8b5e
--- /dev/null
+++ b/openpype/style/fonts/Montserrat/OFL.txt
@@ -0,0 +1,93 @@
+Copyright 2011 The Montserrat Project Authors (https://github.com/JulietaUla/Montserrat)
+
+This Font Software is licensed under the SIL Open Font License, Version 1.1.
+This license is copied below, and is also available with a FAQ at:
+http://scripts.sil.org/OFL
+
+
+-----------------------------------------------------------
+SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
+-----------------------------------------------------------
+
+PREAMBLE
+The goals of the Open Font License (OFL) are to stimulate worldwide
+development of collaborative font projects, to support the font creation
+efforts of academic and linguistic communities, and to provide a free and
+open framework in which fonts may be shared and improved in partnership
+with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and
+redistributed freely as long as they are not sold by themselves. The
+fonts, including any derivative works, can be bundled, embedded,
+redistributed and/or sold with any software provided that any reserved
+names are not used by derivative works. The fonts and derivatives,
+however, cannot be released under any other type of license. The
+requirement for fonts to remain under this license does not apply
+to any document created using the fonts or their derivatives.
+
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright
+Holder(s) under this license and clearly marked as such. This may
+include source files, build scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the
+copyright statement(s).
+
+"Original Version" refers to the collection of Font Software components as
+distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to, deleting,
+or substituting -- in part or in whole -- any of the components of the
+Original Version, by changing formats or by porting the Font Software to a
+new environment.
+
+"Author" refers to any designer, engineer, programmer, technical
+writer or other person who contributed to the Font Software.
+
+PERMISSION & CONDITIONS
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Font Software, to use, study, copy, merge, embed, modify,
+redistribute, and sell modified and unmodified copies of the Font
+Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components,
+in Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled,
+redistributed and/or sold with any software, provided that each copy
+contains the above copyright notice and this license. These can be
+included either as stand-alone text files, human-readable headers or
+in the appropriate machine-readable metadata fields within text or
+binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font
+Name(s) unless explicit written permission is granted by the corresponding
+Copyright Holder. This restriction only applies to the primary font name as
+presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
+Software shall not be used to promote, endorse or advertise any
+Modified Version, except to acknowledge the contribution(s) of the
+Copyright Holder(s) and the Author(s) or with their explicit written
+permission.
+
+5) The Font Software, modified or unmodified, in part or in whole,
+must be distributed entirely under this license, and must not be
+distributed under any other license. The requirement for fonts to
+remain under this license does not apply to any document created
+using the Font Software.
+
+TERMINATION
+This license becomes null and void if any of the above conditions are
+not met.
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+OTHER DEALINGS IN THE FONT SOFTWARE.
diff --git a/openpype/style/fonts/Spartan/OFL.txt b/openpype/style/fonts/Spartan/OFL.txt
new file mode 100644
index 0000000000..808b610ffd
--- /dev/null
+++ b/openpype/style/fonts/Spartan/OFL.txt
@@ -0,0 +1,93 @@
+Copyright 2020 The Spartan Project Authors (https://github.com/bghryct/Spartan-MB)
+
+This Font Software is licensed under the SIL Open Font License, Version 1.1.
+This license is copied below, and is also available with a FAQ at:
+http://scripts.sil.org/OFL
+
+
+-----------------------------------------------------------
+SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
+-----------------------------------------------------------
+
+PREAMBLE
+The goals of the Open Font License (OFL) are to stimulate worldwide
+development of collaborative font projects, to support the font creation
+efforts of academic and linguistic communities, and to provide a free and
+open framework in which fonts may be shared and improved in partnership
+with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and
+redistributed freely as long as they are not sold by themselves. The
+fonts, including any derivative works, can be bundled, embedded,
+redistributed and/or sold with any software provided that any reserved
+names are not used by derivative works. The fonts and derivatives,
+however, cannot be released under any other type of license. The
+requirement for fonts to remain under this license does not apply
+to any document created using the fonts or their derivatives.
+
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright
+Holder(s) under this license and clearly marked as such. This may
+include source files, build scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the
+copyright statement(s).
+
+"Original Version" refers to the collection of Font Software components as
+distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to, deleting,
+or substituting -- in part or in whole -- any of the components of the
+Original Version, by changing formats or by porting the Font Software to a
+new environment.
+
+"Author" refers to any designer, engineer, programmer, technical
+writer or other person who contributed to the Font Software.
+
+PERMISSION & CONDITIONS
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Font Software, to use, study, copy, merge, embed, modify,
+redistribute, and sell modified and unmodified copies of the Font
+Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components,
+in Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled,
+redistributed and/or sold with any software, provided that each copy
+contains the above copyright notice and this license. These can be
+included either as stand-alone text files, human-readable headers or
+in the appropriate machine-readable metadata fields within text or
+binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font
+Name(s) unless explicit written permission is granted by the corresponding
+Copyright Holder. This restriction only applies to the primary font name as
+presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
+Software shall not be used to promote, endorse or advertise any
+Modified Version, except to acknowledge the contribution(s) of the
+Copyright Holder(s) and the Author(s) or with their explicit written
+permission.
+
+5) The Font Software, modified or unmodified, in part or in whole,
+must be distributed entirely under this license, and must not be
+distributed under any other license. The requirement for fonts to
+remain under this license does not apply to any document created
+using the Font Software.
+
+TERMINATION
+This license becomes null and void if any of the above conditions are
+not met.
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+OTHER DEALINGS IN THE FONT SOFTWARE.
diff --git a/openpype/style/fonts/Spartan/README.txt b/openpype/style/fonts/Spartan/README.txt
new file mode 100644
index 0000000000..9db64aff0b
--- /dev/null
+++ b/openpype/style/fonts/Spartan/README.txt
@@ -0,0 +1,71 @@
+Spartan Variable Font
+=====================
+
+This download contains Spartan as both a variable font and static fonts.
+
+Spartan is a variable font with this axis:
+ wght
+
+This means all the styles are contained in a single file:
+ Spartan-VariableFont_wght.ttf
+
+If your app fully supports variable fonts, you can now pick intermediate styles
+that aren’t available as static fonts. Not all apps support variable fonts, and
+in those cases you can use the static font files for Spartan:
+ static/Spartan-Thin.ttf
+ static/Spartan-ExtraLight.ttf
+ static/Spartan-Light.ttf
+ static/Spartan-Regular.ttf
+ static/Spartan-Medium.ttf
+ static/Spartan-SemiBold.ttf
+ static/Spartan-Bold.ttf
+ static/Spartan-ExtraBold.ttf
+ static/Spartan-Black.ttf
+
+Get started
+-----------
+
+1. Install the font files you want to use
+
+2. Use your app's font picker to view the font family and all the
+available styles
+
+Learn more about variable fonts
+-------------------------------
+
+ https://developers.google.com/web/fundamentals/design-and-ux/typography/variable-fonts
+ https://variablefonts.typenetwork.com
+ https://medium.com/variable-fonts
+
+In desktop apps
+
+ https://theblog.adobe.com/can-variable-fonts-illustrator-cc
+ https://helpx.adobe.com/nz/photoshop/using/fonts.html#variable_fonts
+
+Online
+
+ https://developers.google.com/fonts/docs/getting_started
+ https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Fonts/Variable_Fonts_Guide
+ https://developer.microsoft.com/en-us/microsoft-edge/testdrive/demos/variable-fonts
+
+Installing fonts
+
+ MacOS: https://support.apple.com/en-us/HT201749
+ Linux: https://www.google.com/search?q=how+to+install+a+font+on+gnu%2Blinux
+ Windows: https://support.microsoft.com/en-us/help/314960/how-to-install-or-remove-a-font-in-windows
+
+Android Apps
+
+ https://developers.google.com/fonts/docs/android
+ https://developer.android.com/guide/topics/ui/look-and-feel/downloadable-fonts
+
+License
+-------
+Please read the full license text (OFL.txt) to understand the permissions,
+restrictions and requirements for usage, redistribution, and modification.
+
+You can use them freely in your products & projects - print or digital,
+commercial or otherwise. However, you can't sell the fonts on their own.
+
+This isn't legal advice, please consider consulting a lawyer and see the full
+license for all details.
diff --git a/openpype/style/fonts/Spartan/Spartan-Black.ttf b/openpype/style/fonts/Spartan/Spartan-Black.ttf
new file mode 100644
index 0000000000..5d3147011e
Binary files /dev/null and b/openpype/style/fonts/Spartan/Spartan-Black.ttf differ
diff --git a/openpype/style/fonts/Spartan/Spartan-Bold.ttf b/openpype/style/fonts/Spartan/Spartan-Bold.ttf
new file mode 100644
index 0000000000..5fe4b702b2
Binary files /dev/null and b/openpype/style/fonts/Spartan/Spartan-Bold.ttf differ
diff --git a/openpype/style/fonts/Spartan/Spartan-ExtraBold.ttf b/openpype/style/fonts/Spartan/Spartan-ExtraBold.ttf
new file mode 100644
index 0000000000..1030b6dec0
Binary files /dev/null and b/openpype/style/fonts/Spartan/Spartan-ExtraBold.ttf differ
diff --git a/openpype/style/fonts/Spartan/Spartan-ExtraLight.ttf b/openpype/style/fonts/Spartan/Spartan-ExtraLight.ttf
new file mode 100644
index 0000000000..aced3a9e94
Binary files /dev/null and b/openpype/style/fonts/Spartan/Spartan-ExtraLight.ttf differ
diff --git a/openpype/style/fonts/Spartan/Spartan-Light.ttf b/openpype/style/fonts/Spartan/Spartan-Light.ttf
new file mode 100644
index 0000000000..3bb6efa40e
Binary files /dev/null and b/openpype/style/fonts/Spartan/Spartan-Light.ttf differ
diff --git a/openpype/style/fonts/Spartan/Spartan-Medium.ttf b/openpype/style/fonts/Spartan/Spartan-Medium.ttf
new file mode 100644
index 0000000000..94b22ecc08
Binary files /dev/null and b/openpype/style/fonts/Spartan/Spartan-Medium.ttf differ
diff --git a/openpype/style/fonts/Spartan/Spartan-Regular.ttf b/openpype/style/fonts/Spartan/Spartan-Regular.ttf
new file mode 100644
index 0000000000..7560322e3f
Binary files /dev/null and b/openpype/style/fonts/Spartan/Spartan-Regular.ttf differ
diff --git a/openpype/style/fonts/Spartan/Spartan-SemiBold.ttf b/openpype/style/fonts/Spartan/Spartan-SemiBold.ttf
new file mode 100644
index 0000000000..7a5f74adb3
Binary files /dev/null and b/openpype/style/fonts/Spartan/Spartan-SemiBold.ttf differ
diff --git a/openpype/style/fonts/Spartan/Spartan-Thin.ttf b/openpype/style/fonts/Spartan/Spartan-Thin.ttf
new file mode 100644
index 0000000000..4caa0b2be9
Binary files /dev/null and b/openpype/style/fonts/Spartan/Spartan-Thin.ttf differ
diff --git a/openpype/style/fonts/Spartan/Spartan-VariableFont_wght.ttf b/openpype/style/fonts/Spartan/Spartan-VariableFont_wght.ttf
new file mode 100644
index 0000000000..b2dd7c3076
Binary files /dev/null and b/openpype/style/fonts/Spartan/Spartan-VariableFont_wght.ttf differ
diff --git a/openpype/style/images/branch_closed.png b/openpype/style/images/branch_closed.png
new file mode 100644
index 0000000000..135cd0b29d
Binary files /dev/null and b/openpype/style/images/branch_closed.png differ
diff --git a/openpype/style/images/branch_closed_on.png b/openpype/style/images/branch_closed_on.png
new file mode 100644
index 0000000000..0ba35bd4ea
Binary files /dev/null and b/openpype/style/images/branch_closed_on.png differ
diff --git a/openpype/style/images/branch_open.png b/openpype/style/images/branch_open.png
new file mode 100644
index 0000000000..1a83955306
Binary files /dev/null and b/openpype/style/images/branch_open.png differ
diff --git a/openpype/style/images/branch_open_on.png b/openpype/style/images/branch_open_on.png
new file mode 100644
index 0000000000..c09f5fd95d
Binary files /dev/null and b/openpype/style/images/branch_open_on.png differ
diff --git a/openpype/tools/project_manager/project_manager/style/images/combobox_arrow.png b/openpype/style/images/combobox_arrow.png
similarity index 100%
rename from openpype/tools/project_manager/project_manager/style/images/combobox_arrow.png
rename to openpype/style/images/combobox_arrow.png
diff --git a/openpype/tools/project_manager/project_manager/style/images/combobox_arrow_disabled.png b/openpype/style/images/combobox_arrow_disabled.png
similarity index 100%
rename from openpype/tools/project_manager/project_manager/style/images/combobox_arrow_disabled.png
rename to openpype/style/images/combobox_arrow_disabled.png
diff --git a/openpype/style/images/combobox_arrow_on.png b/openpype/style/images/combobox_arrow_on.png
new file mode 100644
index 0000000000..5805d9842b
Binary files /dev/null and b/openpype/style/images/combobox_arrow_on.png differ
diff --git a/openpype/style/images/down_arrow.png b/openpype/style/images/down_arrow.png
new file mode 100644
index 0000000000..e271f7f90b
Binary files /dev/null and b/openpype/style/images/down_arrow.png differ
diff --git a/openpype/style/images/down_arrow_disabled.png b/openpype/style/images/down_arrow_disabled.png
new file mode 100644
index 0000000000..5805d9842b
Binary files /dev/null and b/openpype/style/images/down_arrow_disabled.png differ
diff --git a/openpype/style/images/down_arrow_on.png b/openpype/style/images/down_arrow_on.png
new file mode 100644
index 0000000000..e271f7f90b
Binary files /dev/null and b/openpype/style/images/down_arrow_on.png differ
diff --git a/openpype/style/images/left_arrow.png b/openpype/style/images/left_arrow.png
new file mode 100644
index 0000000000..f808d2d720
Binary files /dev/null and b/openpype/style/images/left_arrow.png differ
diff --git a/openpype/style/images/left_arrow_disabled.png b/openpype/style/images/left_arrow_disabled.png
new file mode 100644
index 0000000000..f5b9af8a34
Binary files /dev/null and b/openpype/style/images/left_arrow_disabled.png differ
diff --git a/openpype/style/images/left_arrow_on.png b/openpype/style/images/left_arrow_on.png
new file mode 100644
index 0000000000..f808d2d720
Binary files /dev/null and b/openpype/style/images/left_arrow_on.png differ
diff --git a/openpype/style/images/right_arrow.png b/openpype/style/images/right_arrow.png
new file mode 100644
index 0000000000..9b0a4e6a7a
Binary files /dev/null and b/openpype/style/images/right_arrow.png differ
diff --git a/openpype/style/images/right_arrow_disabled.png b/openpype/style/images/right_arrow_disabled.png
new file mode 100644
index 0000000000..5c0bee402f
Binary files /dev/null and b/openpype/style/images/right_arrow_disabled.png differ
diff --git a/openpype/style/images/right_arrow_on.png b/openpype/style/images/right_arrow_on.png
new file mode 100644
index 0000000000..9b0a4e6a7a
Binary files /dev/null and b/openpype/style/images/right_arrow_on.png differ
diff --git a/openpype/style/images/up_arrow.png b/openpype/style/images/up_arrow.png
new file mode 100644
index 0000000000..abcc724521
Binary files /dev/null and b/openpype/style/images/up_arrow.png differ
diff --git a/openpype/style/images/up_arrow_disabled.png b/openpype/style/images/up_arrow_disabled.png
new file mode 100644
index 0000000000..b9c8e3b535
Binary files /dev/null and b/openpype/style/images/up_arrow_disabled.png differ
diff --git a/openpype/style/images/up_arrow_on.png b/openpype/style/images/up_arrow_on.png
new file mode 100644
index 0000000000..abcc724521
Binary files /dev/null and b/openpype/style/images/up_arrow_on.png differ
diff --git a/openpype/style/pyqt5_resources.py b/openpype/style/pyqt5_resources.py
new file mode 100644
index 0000000000..3dc21be12a
--- /dev/null
+++ b/openpype/style/pyqt5_resources.py
@@ -0,0 +1,880 @@
+# -*- coding: utf-8 -*-
+
+# Resource object code
+#
+# Created by: The Resource Compiler for PyQt5 (Qt v5.15.2)
+#
+# WARNING! All changes made in this file will be lost!
+
+from PyQt5 import QtCore
+
+
+qt_resource_data = b"\
+\x00\x00\x00\xa0\
+\x89\
+\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
+\x00\x00\x06\x00\x00\x00\x09\x08\x04\x00\x00\x00\xbb\x93\x95\x16\
+\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
+\x02\x62\x4b\x47\x44\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09\x70\
+\x48\x59\x73\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
+\x00\x00\x00\x07\x74\x49\x4d\x45\x07\xdc\x08\x17\x14\x1c\x1f\x24\
+\xc6\x09\x17\x00\x00\x00\x24\x49\x44\x41\x54\x08\xd7\x63\x60\x40\
+\x05\xff\xcf\xc3\x58\x4c\xc8\x5c\x26\x64\x59\x26\x64\xc5\x70\x0e\
+\xa3\x21\x9c\xc3\x68\x88\x61\x1a\x0a\x00\x00\x6d\x84\x09\x75\x37\
+\x9e\xd9\x23\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
+\x00\x00\x07\x30\
+\x89\
+\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
+\x00\x00\x0a\x00\x00\x00\x07\x08\x06\x00\x00\x00\x31\xac\xdc\x63\
+\x00\x00\x04\xb0\x69\x54\x58\x74\x58\x4d\x4c\x3a\x63\x6f\x6d\x2e\
+\x61\x64\x6f\x62\x65\x2e\x78\x6d\x70\x00\x00\x00\x00\x00\x3c\x3f\
+\x78\x70\x61\x63\x6b\x65\x74\x20\x62\x65\x67\x69\x6e\x3d\x22\xef\
+\xbb\xbf\x22\x20\x69\x64\x3d\x22\x57\x35\x4d\x30\x4d\x70\x43\x65\
+\x68\x69\x48\x7a\x72\x65\x53\x7a\x4e\x54\x63\x7a\x6b\x63\x39\x64\
+\x22\x3f\x3e\x0a\x3c\x78\x3a\x78\x6d\x70\x6d\x65\x74\x61\x20\x78\
+\x6d\x6c\x6e\x73\x3a\x78\x3d\x22\x61\x64\x6f\x62\x65\x3a\x6e\x73\
+\x3a\x6d\x65\x74\x61\x2f\x22\x20\x78\x3a\x78\x6d\x70\x74\x6b\x3d\
+\x22\x58\x4d\x50\x20\x43\x6f\x72\x65\x20\x35\x2e\x35\x2e\x30\x22\
+\x3e\x0a\x20\x3c\x72\x64\x66\x3a\x52\x44\x46\x20\x78\x6d\x6c\x6e\
+\x73\x3a\x72\x64\x66\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\x39\x2f\x30\x32\
+\x2f\x32\x32\x2d\x72\x64\x66\x2d\x73\x79\x6e\x74\x61\x78\x2d\x6e\
+\x73\x23\x22\x3e\x0a\x20\x20\x3c\x72\x64\x66\x3a\x44\x65\x73\x63\
+\x72\x69\x70\x74\x69\x6f\x6e\x20\x72\x64\x66\x3a\x61\x62\x6f\x75\
+\x74\x3d\x22\x22\x0a\x20\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x65\
+\x78\x69\x66\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x6e\x73\x2e\x61\
+\x64\x6f\x62\x65\x2e\x63\x6f\x6d\x2f\x65\x78\x69\x66\x2f\x31\x2e\
+\x30\x2f\x22\x0a\x20\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x74\x69\
+\x66\x66\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x6e\x73\x2e\x61\x64\
+\x6f\x62\x65\x2e\x63\x6f\x6d\x2f\x74\x69\x66\x66\x2f\x31\x2e\x30\
+\x2f\x22\x0a\x20\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x70\x68\x6f\
+\x74\x6f\x73\x68\x6f\x70\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x6e\
+\x73\x2e\x61\x64\x6f\x62\x65\x2e\x63\x6f\x6d\x2f\x70\x68\x6f\x74\
+\x6f\x73\x68\x6f\x70\x2f\x31\x2e\x30\x2f\x22\x0a\x20\x20\x20\x20\
+\x78\x6d\x6c\x6e\x73\x3a\x78\x6d\x70\x3d\x22\x68\x74\x74\x70\x3a\
+\x2f\x2f\x6e\x73\x2e\x61\x64\x6f\x62\x65\x2e\x63\x6f\x6d\x2f\x78\
+\x61\x70\x2f\x31\x2e\x30\x2f\x22\x0a\x20\x20\x20\x20\x78\x6d\x6c\
+\x6e\x73\x3a\x78\x6d\x70\x4d\x4d\x3d\x22\x68\x74\x74\x70\x3a\x2f\
+\x2f\x6e\x73\x2e\x61\x64\x6f\x62\x65\x2e\x63\x6f\x6d\x2f\x78\x61\
+\x70\x2f\x31\x2e\x30\x2f\x6d\x6d\x2f\x22\x0a\x20\x20\x20\x20\x78\
+\x6d\x6c\x6e\x73\x3a\x73\x74\x45\x76\x74\x3d\x22\x68\x74\x74\x70\
+\x3a\x2f\x2f\x6e\x73\x2e\x61\x64\x6f\x62\x65\x2e\x63\x6f\x6d\x2f\
+\x78\x61\x70\x2f\x31\x2e\x30\x2f\x73\x54\x79\x70\x65\x2f\x52\x65\
+\x73\x6f\x75\x72\x63\x65\x45\x76\x65\x6e\x74\x23\x22\x0a\x20\x20\
+\x20\x65\x78\x69\x66\x3a\x50\x69\x78\x65\x6c\x58\x44\x69\x6d\x65\
+\x6e\x73\x69\x6f\x6e\x3d\x22\x31\x30\x22\x0a\x20\x20\x20\x65\x78\
+\x69\x66\x3a\x50\x69\x78\x65\x6c\x59\x44\x69\x6d\x65\x6e\x73\x69\
+\x6f\x6e\x3d\x22\x37\x22\x0a\x20\x20\x20\x65\x78\x69\x66\x3a\x43\
+\x6f\x6c\x6f\x72\x53\x70\x61\x63\x65\x3d\x22\x31\x22\x0a\x20\x20\
+\x20\x74\x69\x66\x66\x3a\x49\x6d\x61\x67\x65\x57\x69\x64\x74\x68\
+\x3d\x22\x31\x30\x22\x0a\x20\x20\x20\x74\x69\x66\x66\x3a\x49\x6d\
+\x61\x67\x65\x4c\x65\x6e\x67\x74\x68\x3d\x22\x37\x22\x0a\x20\x20\
+\x20\x74\x69\x66\x66\x3a\x52\x65\x73\x6f\x6c\x75\x74\x69\x6f\x6e\
+\x55\x6e\x69\x74\x3d\x22\x32\x22\x0a\x20\x20\x20\x74\x69\x66\x66\
+\x3a\x58\x52\x65\x73\x6f\x6c\x75\x74\x69\x6f\x6e\x3d\x22\x37\x32\
+\x2e\x30\x22\x0a\x20\x20\x20\x74\x69\x66\x66\x3a\x59\x52\x65\x73\
+\x6f\x6c\x75\x74\x69\x6f\x6e\x3d\x22\x37\x32\x2e\x30\x22\x0a\x20\
+\x20\x20\x70\x68\x6f\x74\x6f\x73\x68\x6f\x70\x3a\x43\x6f\x6c\x6f\
+\x72\x4d\x6f\x64\x65\x3d\x22\x33\x22\x0a\x20\x20\x20\x70\x68\x6f\
+\x74\x6f\x73\x68\x6f\x70\x3a\x49\x43\x43\x50\x72\x6f\x66\x69\x6c\
+\x65\x3d\x22\x73\x52\x47\x42\x20\x49\x45\x43\x36\x31\x39\x36\x36\
+\x2d\x32\x2e\x31\x22\x0a\x20\x20\x20\x78\x6d\x70\x3a\x4d\x6f\x64\
+\x69\x66\x79\x44\x61\x74\x65\x3d\x22\x32\x30\x32\x31\x2d\x30\x35\
+\x2d\x33\x31\x54\x31\x32\x3a\x33\x33\x3a\x31\x34\x2b\x30\x32\x3a\
+\x30\x30\x22\x0a\x20\x20\x20\x78\x6d\x70\x3a\x4d\x65\x74\x61\x64\
+\x61\x74\x61\x44\x61\x74\x65\x3d\x22\x32\x30\x32\x31\x2d\x30\x35\
+\x2d\x33\x31\x54\x31\x32\x3a\x33\x33\x3a\x31\x34\x2b\x30\x32\x3a\
+\x30\x30\x22\x3e\x0a\x20\x20\x20\x3c\x78\x6d\x70\x4d\x4d\x3a\x48\
+\x69\x73\x74\x6f\x72\x79\x3e\x0a\x20\x20\x20\x20\x3c\x72\x64\x66\
+\x3a\x53\x65\x71\x3e\x0a\x20\x20\x20\x20\x20\x3c\x72\x64\x66\x3a\
+\x6c\x69\x0a\x20\x20\x20\x20\x20\x20\x73\x74\x45\x76\x74\x3a\x61\
+\x63\x74\x69\x6f\x6e\x3d\x22\x70\x72\x6f\x64\x75\x63\x65\x64\x22\
+\x0a\x20\x20\x20\x20\x20\x20\x73\x74\x45\x76\x74\x3a\x73\x6f\x66\
+\x74\x77\x61\x72\x65\x41\x67\x65\x6e\x74\x3d\x22\x41\x66\x66\x69\
+\x6e\x69\x74\x79\x20\x44\x65\x73\x69\x67\x6e\x65\x72\x20\x31\x2e\
+\x39\x2e\x32\x22\x0a\x20\x20\x20\x20\x20\x20\x73\x74\x45\x76\x74\
+\x3a\x77\x68\x65\x6e\x3d\x22\x32\x30\x32\x31\x2d\x30\x35\x2d\x33\
+\x31\x54\x31\x32\x3a\x33\x33\x3a\x31\x34\x2b\x30\x32\x3a\x30\x30\
+\x22\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x2f\x72\x64\x66\x3a\x53\x65\
+\x71\x3e\x0a\x20\x20\x20\x3c\x2f\x78\x6d\x70\x4d\x4d\x3a\x48\x69\
+\x73\x74\x6f\x72\x79\x3e\x0a\x20\x20\x3c\x2f\x72\x64\x66\x3a\x44\
+\x65\x73\x63\x72\x69\x70\x74\x69\x6f\x6e\x3e\x0a\x20\x3c\x2f\x72\
+\x64\x66\x3a\x52\x44\x46\x3e\x0a\x3c\x2f\x78\x3a\x78\x6d\x70\x6d\
+\x65\x74\x61\x3e\x0a\x3c\x3f\x78\x70\x61\x63\x6b\x65\x74\x20\x65\
+\x6e\x64\x3d\x22\x72\x22\x3f\x3e\x48\x8b\x5b\x5e\x00\x00\x01\x83\
+\x69\x43\x43\x50\x73\x52\x47\x42\x20\x49\x45\x43\x36\x31\x39\x36\
+\x36\x2d\x32\x2e\x31\x00\x00\x28\x91\x75\x91\xcf\x2b\x44\x51\x14\
+\xc7\x3f\x66\x68\xfc\x18\x8d\x62\x61\x31\x65\x12\x16\x42\x83\x12\
+\x1b\x8b\x99\x18\x0a\x8b\x99\x51\x7e\x6d\x66\x9e\x79\x33\x6a\xde\
+\x78\xbd\x37\xd2\x64\xab\x6c\xa7\x28\xb1\xf1\x6b\xc1\x5f\xc0\x56\
+\x59\x2b\x45\xa4\x64\xa7\xac\x89\x0d\x7a\xce\x9b\x51\x23\x99\x73\
+\x3b\xf7\x7c\xee\xf7\xde\x73\xba\xf7\x5c\x70\x44\xd3\x8a\x66\x56\
+\xfa\x41\xcb\x64\x8d\x70\x28\xe0\x9b\x99\x9d\xf3\xb9\x9e\xa8\xa2\
+\x85\x1a\x3a\xf1\xc6\x14\x53\x9f\x8c\x8c\x46\x29\x6b\xef\xb7\x54\
+\xd8\xf1\xba\xdb\xae\x55\xfe\xdc\xbf\x56\xb7\x98\x30\x15\xa8\xa8\
+\x16\x1e\x56\x74\x23\x2b\x3c\x26\x3c\xb1\x9a\xd5\x6d\xde\x12\x6e\
+\x52\x52\xb1\x45\xe1\x13\xe1\x2e\x43\x2e\x28\x7c\x63\xeb\xf1\x22\
+\x3f\xdb\x9c\x2c\xf2\xa7\xcd\x46\x34\x1c\x04\x47\x83\xb0\x2f\xf9\
+\x8b\xe3\xbf\x58\x49\x19\x9a\xb0\xbc\x9c\x36\x2d\xbd\xa2\xfc\xdc\
+\xc7\x7e\x89\x3b\x91\x99\x8e\x48\x6c\x15\xf7\x62\x12\x26\x44\x00\
+\x1f\xe3\x8c\x10\x64\x80\x5e\x86\x64\x1e\xa0\x9b\x3e\x7a\x64\x45\
+\x99\x7c\x7f\x21\x7f\x8a\x65\xc9\x55\x64\xd6\xc9\x61\xb0\x44\x92\
+\x14\x59\xba\x44\x5d\x91\xea\x09\x89\xaa\xe8\x09\x19\x69\x72\x76\
+\xff\xff\xf6\xd5\x54\xfb\xfb\x8a\xd5\xdd\x01\xa8\x7a\xb4\xac\xd7\
+\x76\x70\x6d\xc2\x57\xde\xb2\x3e\x0e\x2c\xeb\xeb\x10\x9c\x0f\x70\
+\x9e\x29\xe5\x2f\xef\xc3\xe0\x9b\xe8\xf9\x92\xd6\xb6\x07\x9e\x75\
+\x38\xbd\x28\x69\xf1\x6d\x38\xdb\x80\xe6\x7b\x3d\x66\xc4\x0a\x92\
+\x53\xdc\xa1\xaa\xf0\x72\x0c\xf5\xb3\xd0\x78\x05\xb5\xf3\xc5\x9e\
+\xfd\xec\x73\x74\x07\xd1\x35\xf9\xaa\x4b\xd8\xd9\x85\x0e\x39\xef\
+\x59\xf8\x06\x8e\xfd\x67\xf8\xfd\x8a\x18\x97\x00\x00\x00\x09\x70\
+\x48\x59\x73\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
+\x00\x00\x00\x97\x49\x44\x41\x54\x18\x95\x6d\xcf\xb1\x6a\x02\x41\
+\x14\x85\xe1\x6f\xb7\xb6\xd0\x27\x48\x3d\x56\x69\x03\xb1\xb4\x48\
+\x3b\x6c\xa5\xf1\x39\xf6\x59\x02\x56\x42\xba\x61\x0a\x0b\x3b\x1b\
+\x1b\x6b\x41\x18\x02\x29\x6d\xe3\xbe\x82\xcd\x06\x16\xd9\xdb\xdd\
+\x9f\xff\x5c\xee\xa9\x62\x2a\x13\x4c\x73\x13\x6e\x46\x26\xa6\xf2\
+\x82\xae\x46\x8b\xdf\x98\xca\xfb\x88\xb4\xc0\x0f\xda\x1a\x5b\x74\
+\xd8\xc7\x54\xc2\x40\x9a\x63\x8f\x3f\x7c\x55\x3d\x7c\xc5\x09\x77\
+\xbc\xa1\xc2\x19\x33\x2c\x72\x13\x2e\xd5\xe0\xc2\x12\x07\x5c\x51\
+\x23\xe0\x23\x37\xe1\xa8\x4f\x0e\x7f\xda\x60\xd7\xaf\x9f\xb9\x09\
+\xdf\x63\x05\xff\xe5\x75\x4c\x65\xf5\xcc\x1f\x0d\x33\x2c\x83\xb6\
+\x06\x44\x83\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
+\x00\x00\x00\xa5\
+\x89\
+\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
+\x00\x00\x09\x00\x00\x00\x06\x08\x04\x00\x00\x00\xbb\xce\x7c\x4e\
+\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
+\x02\x62\x4b\x47\x44\x00\x9c\x53\x34\xfc\x5d\x00\x00\x00\x09\x70\
+\x48\x59\x73\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
+\x00\x00\x00\x07\x74\x49\x4d\x45\x07\xdc\x08\x17\x0b\x02\x04\x6d\
+\x98\x1b\x69\x00\x00\x00\x29\x49\x44\x41\x54\x08\xd7\x63\x60\xc0\
+\x00\x8c\x0c\x0c\xff\xcf\xa3\x08\x18\x32\x32\x30\x20\x0b\x32\x1a\
+\x32\x30\x30\x42\x98\x10\x41\x46\x43\x14\x13\x50\xb5\xa3\x01\x00\
+\xd6\x10\x07\xd2\x2f\x48\xdf\x4a\x00\x00\x00\x00\x49\x45\x4e\x44\
+\xae\x42\x60\x82\
+\x00\x00\x00\xa0\
+\x89\
+\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
+\x00\x00\x06\x00\x00\x00\x09\x08\x04\x00\x00\x00\xbb\x93\x95\x16\
+\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
+\x02\x62\x4b\x47\x44\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09\x70\
+\x48\x59\x73\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
+\x00\x00\x00\x07\x74\x49\x4d\x45\x07\xdc\x08\x17\x14\x1f\x0d\xfc\
+\x52\x2b\x9c\x00\x00\x00\x24\x49\x44\x41\x54\x08\xd7\x63\x60\x40\
+\x05\x73\x3e\xc0\x58\x4c\xc8\x5c\x26\x64\x59\x26\x64\xc5\x70\x4e\
+\x8a\x00\x9c\x93\x22\x80\x61\x1a\x0a\x00\x00\x29\x95\x08\xaf\x88\
+\xac\xba\x34\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
+\x00\x00\x07\xad\
+\x89\
+\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
+\x00\x00\x07\x00\x00\x00\x0a\x08\x06\x00\x00\x00\x78\xcc\x44\x0d\
+\x00\x00\x05\x52\x69\x54\x58\x74\x58\x4d\x4c\x3a\x63\x6f\x6d\x2e\
+\x61\x64\x6f\x62\x65\x2e\x78\x6d\x70\x00\x00\x00\x00\x00\x3c\x3f\
+\x78\x70\x61\x63\x6b\x65\x74\x20\x62\x65\x67\x69\x6e\x3d\x22\xef\
+\xbb\xbf\x22\x20\x69\x64\x3d\x22\x57\x35\x4d\x30\x4d\x70\x43\x65\
+\x68\x69\x48\x7a\x72\x65\x53\x7a\x4e\x54\x63\x7a\x6b\x63\x39\x64\
+\x22\x3f\x3e\x0a\x3c\x78\x3a\x78\x6d\x70\x6d\x65\x74\x61\x20\x78\
+\x6d\x6c\x6e\x73\x3a\x78\x3d\x22\x61\x64\x6f\x62\x65\x3a\x6e\x73\
+\x3a\x6d\x65\x74\x61\x2f\x22\x20\x78\x3a\x78\x6d\x70\x74\x6b\x3d\
+\x22\x58\x4d\x50\x20\x43\x6f\x72\x65\x20\x35\x2e\x35\x2e\x30\x22\
+\x3e\x0a\x20\x3c\x72\x64\x66\x3a\x52\x44\x46\x20\x78\x6d\x6c\x6e\
+\x73\x3a\x72\x64\x66\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\x39\x2f\x30\x32\
+\x2f\x32\x32\x2d\x72\x64\x66\x2d\x73\x79\x6e\x74\x61\x78\x2d\x6e\
+\x73\x23\x22\x3e\x0a\x20\x20\x3c\x72\x64\x66\x3a\x44\x65\x73\x63\
+\x72\x69\x70\x74\x69\x6f\x6e\x20\x72\x64\x66\x3a\x61\x62\x6f\x75\
+\x74\x3d\x22\x22\x0a\x20\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x64\
+\x63\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x70\x75\x72\x6c\x2e\x6f\
+\x72\x67\x2f\x64\x63\x2f\x65\x6c\x65\x6d\x65\x6e\x74\x73\x2f\x31\
+\x2e\x31\x2f\x22\x0a\x20\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x65\
+\x78\x69\x66\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x6e\x73\x2e\x61\
+\x64\x6f\x62\x65\x2e\x63\x6f\x6d\x2f\x65\x78\x69\x66\x2f\x31\x2e\
+\x30\x2f\x22\x0a\x20\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x74\x69\
+\x66\x66\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x6e\x73\x2e\x61\x64\
+\x6f\x62\x65\x2e\x63\x6f\x6d\x2f\x74\x69\x66\x66\x2f\x31\x2e\x30\
+\x2f\x22\x0a\x20\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x70\x68\x6f\
+\x74\x6f\x73\x68\x6f\x70\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x6e\
+\x73\x2e\x61\x64\x6f\x62\x65\x2e\x63\x6f\x6d\x2f\x70\x68\x6f\x74\
+\x6f\x73\x68\x6f\x70\x2f\x31\x2e\x30\x2f\x22\x0a\x20\x20\x20\x20\
+\x78\x6d\x6c\x6e\x73\x3a\x78\x6d\x70\x3d\x22\x68\x74\x74\x70\x3a\
+\x2f\x2f\x6e\x73\x2e\x61\x64\x6f\x62\x65\x2e\x63\x6f\x6d\x2f\x78\
+\x61\x70\x2f\x31\x2e\x30\x2f\x22\x0a\x20\x20\x20\x20\x78\x6d\x6c\
+\x6e\x73\x3a\x78\x6d\x70\x4d\x4d\x3d\x22\x68\x74\x74\x70\x3a\x2f\
+\x2f\x6e\x73\x2e\x61\x64\x6f\x62\x65\x2e\x63\x6f\x6d\x2f\x78\x61\
+\x70\x2f\x31\x2e\x30\x2f\x6d\x6d\x2f\x22\x0a\x20\x20\x20\x20\x78\
+\x6d\x6c\x6e\x73\x3a\x73\x74\x45\x76\x74\x3d\x22\x68\x74\x74\x70\
+\x3a\x2f\x2f\x6e\x73\x2e\x61\x64\x6f\x62\x65\x2e\x63\x6f\x6d\x2f\
+\x78\x61\x70\x2f\x31\x2e\x30\x2f\x73\x54\x79\x70\x65\x2f\x52\x65\
+\x73\x6f\x75\x72\x63\x65\x45\x76\x65\x6e\x74\x23\x22\x0a\x20\x20\
+\x20\x65\x78\x69\x66\x3a\x50\x69\x78\x65\x6c\x58\x44\x69\x6d\x65\
+\x6e\x73\x69\x6f\x6e\x3d\x22\x37\x22\x0a\x20\x20\x20\x65\x78\x69\
+\x66\x3a\x50\x69\x78\x65\x6c\x59\x44\x69\x6d\x65\x6e\x73\x69\x6f\
+\x6e\x3d\x22\x31\x30\x22\x0a\x20\x20\x20\x65\x78\x69\x66\x3a\x43\
+\x6f\x6c\x6f\x72\x53\x70\x61\x63\x65\x3d\x22\x31\x22\x0a\x20\x20\
+\x20\x74\x69\x66\x66\x3a\x49\x6d\x61\x67\x65\x57\x69\x64\x74\x68\
+\x3d\x22\x37\x22\x0a\x20\x20\x20\x74\x69\x66\x66\x3a\x49\x6d\x61\
+\x67\x65\x4c\x65\x6e\x67\x74\x68\x3d\x22\x31\x30\x22\x0a\x20\x20\
+\x20\x74\x69\x66\x66\x3a\x52\x65\x73\x6f\x6c\x75\x74\x69\x6f\x6e\
+\x55\x6e\x69\x74\x3d\x22\x32\x22\x0a\x20\x20\x20\x74\x69\x66\x66\
+\x3a\x58\x52\x65\x73\x6f\x6c\x75\x74\x69\x6f\x6e\x3d\x22\x37\x32\
+\x2e\x30\x22\x0a\x20\x20\x20\x74\x69\x66\x66\x3a\x59\x52\x65\x73\
+\x6f\x6c\x75\x74\x69\x6f\x6e\x3d\x22\x37\x32\x2e\x30\x22\x0a\x20\
+\x20\x20\x70\x68\x6f\x74\x6f\x73\x68\x6f\x70\x3a\x43\x6f\x6c\x6f\
+\x72\x4d\x6f\x64\x65\x3d\x22\x33\x22\x0a\x20\x20\x20\x70\x68\x6f\
+\x74\x6f\x73\x68\x6f\x70\x3a\x49\x43\x43\x50\x72\x6f\x66\x69\x6c\
+\x65\x3d\x22\x73\x52\x47\x42\x20\x49\x45\x43\x36\x31\x39\x36\x36\
+\x2d\x32\x2e\x31\x22\x0a\x20\x20\x20\x78\x6d\x70\x3a\x4d\x6f\x64\
+\x69\x66\x79\x44\x61\x74\x65\x3d\x22\x32\x30\x32\x31\x2d\x30\x35\
+\x2d\x33\x31\x54\x31\x32\x3a\x34\x33\x3a\x33\x35\x2b\x30\x32\x3a\
+\x30\x30\x22\x0a\x20\x20\x20\x78\x6d\x70\x3a\x4d\x65\x74\x61\x64\
+\x61\x74\x61\x44\x61\x74\x65\x3d\x22\x32\x30\x32\x31\x2d\x30\x35\
+\x2d\x33\x31\x54\x31\x32\x3a\x34\x33\x3a\x33\x35\x2b\x30\x32\x3a\
+\x30\x30\x22\x3e\x0a\x20\x20\x20\x3c\x64\x63\x3a\x74\x69\x74\x6c\
+\x65\x3e\x0a\x20\x20\x20\x20\x3c\x72\x64\x66\x3a\x41\x6c\x74\x3e\
+\x0a\x20\x20\x20\x20\x20\x3c\x72\x64\x66\x3a\x6c\x69\x20\x78\x6d\
+\x6c\x3a\x6c\x61\x6e\x67\x3d\x22\x78\x2d\x64\x65\x66\x61\x75\x6c\
+\x74\x22\x3e\x62\x72\x61\x6e\x63\x68\x5f\x63\x6c\x6f\x73\x65\x3c\
+\x2f\x72\x64\x66\x3a\x6c\x69\x3e\x0a\x20\x20\x20\x20\x3c\x2f\x72\
+\x64\x66\x3a\x41\x6c\x74\x3e\x0a\x20\x20\x20\x3c\x2f\x64\x63\x3a\
+\x74\x69\x74\x6c\x65\x3e\x0a\x20\x20\x20\x3c\x78\x6d\x70\x4d\x4d\
+\x3a\x48\x69\x73\x74\x6f\x72\x79\x3e\x0a\x20\x20\x20\x20\x3c\x72\
+\x64\x66\x3a\x53\x65\x71\x3e\x0a\x20\x20\x20\x20\x20\x3c\x72\x64\
+\x66\x3a\x6c\x69\x0a\x20\x20\x20\x20\x20\x20\x73\x74\x45\x76\x74\
+\x3a\x61\x63\x74\x69\x6f\x6e\x3d\x22\x70\x72\x6f\x64\x75\x63\x65\
+\x64\x22\x0a\x20\x20\x20\x20\x20\x20\x73\x74\x45\x76\x74\x3a\x73\
+\x6f\x66\x74\x77\x61\x72\x65\x41\x67\x65\x6e\x74\x3d\x22\x41\x66\
+\x66\x69\x6e\x69\x74\x79\x20\x44\x65\x73\x69\x67\x6e\x65\x72\x20\
+\x31\x2e\x39\x2e\x32\x22\x0a\x20\x20\x20\x20\x20\x20\x73\x74\x45\
+\x76\x74\x3a\x77\x68\x65\x6e\x3d\x22\x32\x30\x32\x31\x2d\x30\x35\
+\x2d\x33\x31\x54\x31\x32\x3a\x34\x33\x3a\x33\x35\x2b\x30\x32\x3a\
+\x30\x30\x22\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x2f\x72\x64\x66\x3a\
+\x53\x65\x71\x3e\x0a\x20\x20\x20\x3c\x2f\x78\x6d\x70\x4d\x4d\x3a\
+\x48\x69\x73\x74\x6f\x72\x79\x3e\x0a\x20\x20\x3c\x2f\x72\x64\x66\
+\x3a\x44\x65\x73\x63\x72\x69\x70\x74\x69\x6f\x6e\x3e\x0a\x20\x3c\
+\x2f\x72\x64\x66\x3a\x52\x44\x46\x3e\x0a\x3c\x2f\x78\x3a\x78\x6d\
+\x70\x6d\x65\x74\x61\x3e\x0a\x3c\x3f\x78\x70\x61\x63\x6b\x65\x74\
+\x20\x65\x6e\x64\x3d\x22\x72\x22\x3f\x3e\x24\xe1\x35\x97\x00\x00\
+\x01\x83\x69\x43\x43\x50\x73\x52\x47\x42\x20\x49\x45\x43\x36\x31\
+\x39\x36\x36\x2d\x32\x2e\x31\x00\x00\x28\x91\x75\x91\xcf\x2b\x44\
+\x51\x14\xc7\x3f\x66\x68\xfc\x18\x8d\x62\x61\x31\x65\x12\x16\x42\
+\x83\x12\x1b\x8b\x99\x18\x0a\x8b\x99\x51\x7e\x6d\x66\x9e\x79\x33\
+\x6a\xde\x78\xbd\x37\xd2\x64\xab\x6c\xa7\x28\xb1\xf1\x6b\xc1\x5f\
+\xc0\x56\x59\x2b\x45\xa4\x64\xa7\xac\x89\x0d\x7a\xce\x9b\x51\x23\
+\x99\x73\x3b\xf7\x7c\xee\xf7\xde\x73\xba\xf7\x5c\x70\x44\xd3\x8a\
+\x66\x56\xfa\x41\xcb\x64\x8d\x70\x28\xe0\x9b\x99\x9d\xf3\xb9\x9e\
+\xa8\xa2\x85\x1a\x3a\xf1\xc6\x14\x53\x9f\x8c\x8c\x46\x29\x6b\xef\
+\xb7\x54\xd8\xf1\xba\xdb\xae\x55\xfe\xdc\xbf\x56\xb7\x98\x30\x15\
+\xa8\xa8\x16\x1e\x56\x74\x23\x2b\x3c\x26\x3c\xb1\x9a\xd5\x6d\xde\
+\x12\x6e\x52\x52\xb1\x45\xe1\x13\xe1\x2e\x43\x2e\x28\x7c\x63\xeb\
+\xf1\x22\x3f\xdb\x9c\x2c\xf2\xa7\xcd\x46\x34\x1c\x04\x47\x83\xb0\
+\x2f\xf9\x8b\xe3\xbf\x58\x49\x19\x9a\xb0\xbc\x9c\x36\x2d\xbd\xa2\
+\xfc\xdc\xc7\x7e\x89\x3b\x91\x99\x8e\x48\x6c\x15\xf7\x62\x12\x26\
+\x44\x00\x1f\xe3\x8c\x10\x64\x80\x5e\x86\x64\x1e\xa0\x9b\x3e\x7a\
+\x64\x45\x99\x7c\x7f\x21\x7f\x8a\x65\xc9\x55\x64\xd6\xc9\x61\xb0\
+\x44\x92\x14\x59\xba\x44\x5d\x91\xea\x09\x89\xaa\xe8\x09\x19\x69\
+\x72\x76\xff\xff\xf6\xd5\x54\xfb\xfb\x8a\xd5\xdd\x01\xa8\x7a\xb4\
+\xac\xd7\x76\x70\x6d\xc2\x57\xde\xb2\x3e\x0e\x2c\xeb\xeb\x10\x9c\
+\x0f\x70\x9e\x29\xe5\x2f\xef\xc3\xe0\x9b\xe8\xf9\x92\xd6\xb6\x07\
+\x9e\x75\x38\xbd\x28\x69\xf1\x6d\x38\xdb\x80\xe6\x7b\x3d\x66\xc4\
+\x0a\x92\x53\xdc\xa1\xaa\xf0\x72\x0c\xf5\xb3\xd0\x78\x05\xb5\xf3\
+\xc5\x9e\xfd\xec\x73\x74\x07\xd1\x35\xf9\xaa\x4b\xd8\xd9\x85\x0e\
+\x39\xef\x59\xf8\x06\x8e\xfd\x67\xf8\xfd\x8a\x18\x97\x00\x00\x00\
+\x09\x70\x48\x59\x73\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\
+\x9c\x18\x00\x00\x00\x72\x49\x44\x41\x54\x18\x95\x6d\xcf\x31\x0a\
+\xc2\x50\x14\x44\xd1\xe8\x02\xb4\x57\x08\xd6\x49\x61\x99\x4a\x43\
+\x74\x15\x82\xab\x49\x36\x28\xee\x40\x04\xdb\xa8\x95\x58\x78\x2c\
+\xf2\x09\xe1\xf3\x07\xa6\x9a\xfb\xe0\xbe\x0c\x1b\xb4\x58\x64\x71\
+\x70\x30\xe4\x82\x55\x0a\x38\xe3\x8b\x1b\x8a\x14\x70\xc4\x1b\x3d\
+\x76\x29\x60\x8b\x07\x3e\xa8\xe6\xd1\xfe\x0b\x9d\x85\x8e\x57\x0d\
+\x5e\x78\xa2\x9e\x0e\xa7\x20\x74\x47\x39\x1d\xf6\xe1\x95\x2b\xd6\
+\xb1\x44\x8e\x0e\xcb\x58\xf0\x0f\x52\x8a\x79\x18\xdc\xe2\x02\x70\
+\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
+\x00\x00\x00\xa0\
+\x89\
+\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
+\x00\x00\x06\x00\x00\x00\x09\x08\x04\x00\x00\x00\xbb\x93\x95\x16\
+\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
+\x02\x62\x4b\x47\x44\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09\x70\
+\x48\x59\x73\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
+\x00\x00\x00\x07\x74\x49\x4d\x45\x07\xdc\x08\x17\x14\x1c\x1f\x24\
+\xc6\x09\x17\x00\x00\x00\x24\x49\x44\x41\x54\x08\xd7\x63\x60\x40\
+\x05\xff\xcf\xc3\x58\x4c\xc8\x5c\x26\x64\x59\x26\x64\xc5\x70\x0e\
+\xa3\x21\x9c\xc3\x68\x88\x61\x1a\x0a\x00\x00\x6d\x84\x09\x75\x37\
+\x9e\xd9\x23\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
+\x00\x00\x00\x9f\
+\x89\
+\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
+\x00\x00\x09\x00\x00\x00\x06\x08\x04\x00\x00\x00\xbb\xce\x7c\x4e\
+\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
+\x02\x62\x4b\x47\x44\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09\x70\
+\x48\x59\x73\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
+\x00\x00\x00\x07\x74\x49\x4d\x45\x07\xdc\x08\x17\x08\x14\x1f\xf9\
+\x23\xd9\x0b\x00\x00\x00\x23\x49\x44\x41\x54\x08\xd7\x63\x60\xc0\
+\x0d\xe6\x7c\x80\xb1\x18\x91\x05\x52\x04\xe0\x42\x08\x15\x29\x02\
+\x0c\x0c\x8c\xc8\x02\x08\x95\x68\x00\x00\xac\xac\x07\x90\x4e\x65\
+\x34\xac\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
+\x00\x00\x00\x9e\
+\x89\
+\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
+\x00\x00\x09\x00\x00\x00\x06\x08\x04\x00\x00\x00\xbb\xce\x7c\x4e\
+\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
+\x02\x62\x4b\x47\x44\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09\x70\
+\x48\x59\x73\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
+\x00\x00\x00\x07\x74\x49\x4d\x45\x07\xdc\x08\x17\x08\x15\x0f\xfd\
+\x8f\xf8\x2e\x00\x00\x00\x22\x49\x44\x41\x54\x08\xd7\x63\x60\xc0\
+\x0d\xfe\x9f\x87\xb1\x18\x91\x05\x18\x0d\xe1\x42\x48\x2a\x0c\x19\
+\x18\x18\x91\x05\x10\x2a\xd1\x00\x00\xca\xb5\x07\xd2\x76\xbb\xb2\
+\xc5\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
+\x00\x00\x00\xa5\
+\x89\
+\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
+\x00\x00\x09\x00\x00\x00\x06\x08\x04\x00\x00\x00\xbb\xce\x7c\x4e\
+\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
+\x02\x62\x4b\x47\x44\x00\x9c\x53\x34\xfc\x5d\x00\x00\x00\x09\x70\
+\x48\x59\x73\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
+\x00\x00\x00\x07\x74\x49\x4d\x45\x07\xdc\x08\x17\x0b\x02\x04\x6d\
+\x98\x1b\x69\x00\x00\x00\x29\x49\x44\x41\x54\x08\xd7\x63\x60\xc0\
+\x00\x8c\x0c\x0c\xff\xcf\xa3\x08\x18\x32\x32\x30\x20\x0b\x32\x1a\
+\x32\x30\x30\x42\x98\x10\x41\x46\x43\x14\x13\x50\xb5\xa3\x01\x00\
+\xd6\x10\x07\xd2\x2f\x48\xdf\x4a\x00\x00\x00\x00\x49\x45\x4e\x44\
+\xae\x42\x60\x82\
+\x00\x00\x00\xa6\
+\x89\
+\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
+\x00\x00\x09\x00\x00\x00\x06\x08\x04\x00\x00\x00\xbb\xce\x7c\x4e\
+\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
+\x02\x62\x4b\x47\x44\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09\x70\
+\x48\x59\x73\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
+\x00\x00\x00\x07\x74\x49\x4d\x45\x07\xdc\x08\x17\x08\x15\x3b\xdc\
+\x3b\x0c\x9b\x00\x00\x00\x2a\x49\x44\x41\x54\x08\xd7\x63\x60\xc0\
+\x00\x8c\x0c\x0c\x73\x3e\x20\x0b\xa4\x08\x30\x32\x30\x20\x0b\xa6\
+\x08\x30\x30\x30\x42\x98\x10\xc1\x14\x01\x14\x13\x50\xb5\xa3\x01\
+\x00\xc6\xb9\x07\x90\x5d\x66\x1f\x83\x00\x00\x00\x00\x49\x45\x4e\
+\x44\xae\x42\x60\x82\
+\x00\x00\x07\xdd\
+\x89\
+\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
+\x00\x00\x07\x00\x00\x00\x0a\x08\x06\x00\x00\x00\x78\xcc\x44\x0d\
+\x00\x00\x05\x52\x69\x54\x58\x74\x58\x4d\x4c\x3a\x63\x6f\x6d\x2e\
+\x61\x64\x6f\x62\x65\x2e\x78\x6d\x70\x00\x00\x00\x00\x00\x3c\x3f\
+\x78\x70\x61\x63\x6b\x65\x74\x20\x62\x65\x67\x69\x6e\x3d\x22\xef\
+\xbb\xbf\x22\x20\x69\x64\x3d\x22\x57\x35\x4d\x30\x4d\x70\x43\x65\
+\x68\x69\x48\x7a\x72\x65\x53\x7a\x4e\x54\x63\x7a\x6b\x63\x39\x64\
+\x22\x3f\x3e\x0a\x3c\x78\x3a\x78\x6d\x70\x6d\x65\x74\x61\x20\x78\
+\x6d\x6c\x6e\x73\x3a\x78\x3d\x22\x61\x64\x6f\x62\x65\x3a\x6e\x73\
+\x3a\x6d\x65\x74\x61\x2f\x22\x20\x78\x3a\x78\x6d\x70\x74\x6b\x3d\
+\x22\x58\x4d\x50\x20\x43\x6f\x72\x65\x20\x35\x2e\x35\x2e\x30\x22\
+\x3e\x0a\x20\x3c\x72\x64\x66\x3a\x52\x44\x46\x20\x78\x6d\x6c\x6e\
+\x73\x3a\x72\x64\x66\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\x39\x2f\x30\x32\
+\x2f\x32\x32\x2d\x72\x64\x66\x2d\x73\x79\x6e\x74\x61\x78\x2d\x6e\
+\x73\x23\x22\x3e\x0a\x20\x20\x3c\x72\x64\x66\x3a\x44\x65\x73\x63\
+\x72\x69\x70\x74\x69\x6f\x6e\x20\x72\x64\x66\x3a\x61\x62\x6f\x75\
+\x74\x3d\x22\x22\x0a\x20\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x64\
+\x63\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x70\x75\x72\x6c\x2e\x6f\
+\x72\x67\x2f\x64\x63\x2f\x65\x6c\x65\x6d\x65\x6e\x74\x73\x2f\x31\
+\x2e\x31\x2f\x22\x0a\x20\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x65\
+\x78\x69\x66\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x6e\x73\x2e\x61\
+\x64\x6f\x62\x65\x2e\x63\x6f\x6d\x2f\x65\x78\x69\x66\x2f\x31\x2e\
+\x30\x2f\x22\x0a\x20\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x74\x69\
+\x66\x66\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x6e\x73\x2e\x61\x64\
+\x6f\x62\x65\x2e\x63\x6f\x6d\x2f\x74\x69\x66\x66\x2f\x31\x2e\x30\
+\x2f\x22\x0a\x20\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x70\x68\x6f\
+\x74\x6f\x73\x68\x6f\x70\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x6e\
+\x73\x2e\x61\x64\x6f\x62\x65\x2e\x63\x6f\x6d\x2f\x70\x68\x6f\x74\
+\x6f\x73\x68\x6f\x70\x2f\x31\x2e\x30\x2f\x22\x0a\x20\x20\x20\x20\
+\x78\x6d\x6c\x6e\x73\x3a\x78\x6d\x70\x3d\x22\x68\x74\x74\x70\x3a\
+\x2f\x2f\x6e\x73\x2e\x61\x64\x6f\x62\x65\x2e\x63\x6f\x6d\x2f\x78\
+\x61\x70\x2f\x31\x2e\x30\x2f\x22\x0a\x20\x20\x20\x20\x78\x6d\x6c\
+\x6e\x73\x3a\x78\x6d\x70\x4d\x4d\x3d\x22\x68\x74\x74\x70\x3a\x2f\
+\x2f\x6e\x73\x2e\x61\x64\x6f\x62\x65\x2e\x63\x6f\x6d\x2f\x78\x61\
+\x70\x2f\x31\x2e\x30\x2f\x6d\x6d\x2f\x22\x0a\x20\x20\x20\x20\x78\
+\x6d\x6c\x6e\x73\x3a\x73\x74\x45\x76\x74\x3d\x22\x68\x74\x74\x70\
+\x3a\x2f\x2f\x6e\x73\x2e\x61\x64\x6f\x62\x65\x2e\x63\x6f\x6d\x2f\
+\x78\x61\x70\x2f\x31\x2e\x30\x2f\x73\x54\x79\x70\x65\x2f\x52\x65\
+\x73\x6f\x75\x72\x63\x65\x45\x76\x65\x6e\x74\x23\x22\x0a\x20\x20\
+\x20\x65\x78\x69\x66\x3a\x50\x69\x78\x65\x6c\x58\x44\x69\x6d\x65\
+\x6e\x73\x69\x6f\x6e\x3d\x22\x37\x22\x0a\x20\x20\x20\x65\x78\x69\
+\x66\x3a\x50\x69\x78\x65\x6c\x59\x44\x69\x6d\x65\x6e\x73\x69\x6f\
+\x6e\x3d\x22\x31\x30\x22\x0a\x20\x20\x20\x65\x78\x69\x66\x3a\x43\
+\x6f\x6c\x6f\x72\x53\x70\x61\x63\x65\x3d\x22\x31\x22\x0a\x20\x20\
+\x20\x74\x69\x66\x66\x3a\x49\x6d\x61\x67\x65\x57\x69\x64\x74\x68\
+\x3d\x22\x37\x22\x0a\x20\x20\x20\x74\x69\x66\x66\x3a\x49\x6d\x61\
+\x67\x65\x4c\x65\x6e\x67\x74\x68\x3d\x22\x31\x30\x22\x0a\x20\x20\
+\x20\x74\x69\x66\x66\x3a\x52\x65\x73\x6f\x6c\x75\x74\x69\x6f\x6e\
+\x55\x6e\x69\x74\x3d\x22\x32\x22\x0a\x20\x20\x20\x74\x69\x66\x66\
+\x3a\x58\x52\x65\x73\x6f\x6c\x75\x74\x69\x6f\x6e\x3d\x22\x37\x32\
+\x2e\x30\x22\x0a\x20\x20\x20\x74\x69\x66\x66\x3a\x59\x52\x65\x73\
+\x6f\x6c\x75\x74\x69\x6f\x6e\x3d\x22\x37\x32\x2e\x30\x22\x0a\x20\
+\x20\x20\x70\x68\x6f\x74\x6f\x73\x68\x6f\x70\x3a\x43\x6f\x6c\x6f\
+\x72\x4d\x6f\x64\x65\x3d\x22\x33\x22\x0a\x20\x20\x20\x70\x68\x6f\
+\x74\x6f\x73\x68\x6f\x70\x3a\x49\x43\x43\x50\x72\x6f\x66\x69\x6c\
+\x65\x3d\x22\x73\x52\x47\x42\x20\x49\x45\x43\x36\x31\x39\x36\x36\
+\x2d\x32\x2e\x31\x22\x0a\x20\x20\x20\x78\x6d\x70\x3a\x4d\x6f\x64\
+\x69\x66\x79\x44\x61\x74\x65\x3d\x22\x32\x30\x32\x31\x2d\x30\x35\
+\x2d\x33\x31\x54\x31\x32\x3a\x34\x33\x3a\x30\x39\x2b\x30\x32\x3a\
+\x30\x30\x22\x0a\x20\x20\x20\x78\x6d\x70\x3a\x4d\x65\x74\x61\x64\
+\x61\x74\x61\x44\x61\x74\x65\x3d\x22\x32\x30\x32\x31\x2d\x30\x35\
+\x2d\x33\x31\x54\x31\x32\x3a\x34\x33\x3a\x30\x39\x2b\x30\x32\x3a\
+\x30\x30\x22\x3e\x0a\x20\x20\x20\x3c\x64\x63\x3a\x74\x69\x74\x6c\
+\x65\x3e\x0a\x20\x20\x20\x20\x3c\x72\x64\x66\x3a\x41\x6c\x74\x3e\
+\x0a\x20\x20\x20\x20\x20\x3c\x72\x64\x66\x3a\x6c\x69\x20\x78\x6d\
+\x6c\x3a\x6c\x61\x6e\x67\x3d\x22\x78\x2d\x64\x65\x66\x61\x75\x6c\
+\x74\x22\x3e\x62\x72\x61\x6e\x63\x68\x5f\x63\x6c\x6f\x73\x65\x3c\
+\x2f\x72\x64\x66\x3a\x6c\x69\x3e\x0a\x20\x20\x20\x20\x3c\x2f\x72\
+\x64\x66\x3a\x41\x6c\x74\x3e\x0a\x20\x20\x20\x3c\x2f\x64\x63\x3a\
+\x74\x69\x74\x6c\x65\x3e\x0a\x20\x20\x20\x3c\x78\x6d\x70\x4d\x4d\
+\x3a\x48\x69\x73\x74\x6f\x72\x79\x3e\x0a\x20\x20\x20\x20\x3c\x72\
+\x64\x66\x3a\x53\x65\x71\x3e\x0a\x20\x20\x20\x20\x20\x3c\x72\x64\
+\x66\x3a\x6c\x69\x0a\x20\x20\x20\x20\x20\x20\x73\x74\x45\x76\x74\
+\x3a\x61\x63\x74\x69\x6f\x6e\x3d\x22\x70\x72\x6f\x64\x75\x63\x65\
+\x64\x22\x0a\x20\x20\x20\x20\x20\x20\x73\x74\x45\x76\x74\x3a\x73\
+\x6f\x66\x74\x77\x61\x72\x65\x41\x67\x65\x6e\x74\x3d\x22\x41\x66\
+\x66\x69\x6e\x69\x74\x79\x20\x44\x65\x73\x69\x67\x6e\x65\x72\x20\
+\x31\x2e\x39\x2e\x32\x22\x0a\x20\x20\x20\x20\x20\x20\x73\x74\x45\
+\x76\x74\x3a\x77\x68\x65\x6e\x3d\x22\x32\x30\x32\x31\x2d\x30\x35\
+\x2d\x33\x31\x54\x31\x32\x3a\x34\x33\x3a\x30\x39\x2b\x30\x32\x3a\
+\x30\x30\x22\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x2f\x72\x64\x66\x3a\
+\x53\x65\x71\x3e\x0a\x20\x20\x20\x3c\x2f\x78\x6d\x70\x4d\x4d\x3a\
+\x48\x69\x73\x74\x6f\x72\x79\x3e\x0a\x20\x20\x3c\x2f\x72\x64\x66\
+\x3a\x44\x65\x73\x63\x72\x69\x70\x74\x69\x6f\x6e\x3e\x0a\x20\x3c\
+\x2f\x72\x64\x66\x3a\x52\x44\x46\x3e\x0a\x3c\x2f\x78\x3a\x78\x6d\
+\x70\x6d\x65\x74\x61\x3e\x0a\x3c\x3f\x78\x70\x61\x63\x6b\x65\x74\
+\x20\x65\x6e\x64\x3d\x22\x72\x22\x3f\x3e\x58\xad\xf2\x80\x00\x00\
+\x01\x83\x69\x43\x43\x50\x73\x52\x47\x42\x20\x49\x45\x43\x36\x31\
+\x39\x36\x36\x2d\x32\x2e\x31\x00\x00\x28\x91\x75\x91\xcf\x2b\x44\
+\x51\x14\xc7\x3f\x66\x68\xfc\x18\x8d\x62\x61\x31\x65\x12\x16\x42\
+\x83\x12\x1b\x8b\x99\x18\x0a\x8b\x99\x51\x7e\x6d\x66\x9e\x79\x33\
+\x6a\xde\x78\xbd\x37\xd2\x64\xab\x6c\xa7\x28\xb1\xf1\x6b\xc1\x5f\
+\xc0\x56\x59\x2b\x45\xa4\x64\xa7\xac\x89\x0d\x7a\xce\x9b\x51\x23\
+\x99\x73\x3b\xf7\x7c\xee\xf7\xde\x73\xba\xf7\x5c\x70\x44\xd3\x8a\
+\x66\x56\xfa\x41\xcb\x64\x8d\x70\x28\xe0\x9b\x99\x9d\xf3\xb9\x9e\
+\xa8\xa2\x85\x1a\x3a\xf1\xc6\x14\x53\x9f\x8c\x8c\x46\x29\x6b\xef\
+\xb7\x54\xd8\xf1\xba\xdb\xae\x55\xfe\xdc\xbf\x56\xb7\x98\x30\x15\
+\xa8\xa8\x16\x1e\x56\x74\x23\x2b\x3c\x26\x3c\xb1\x9a\xd5\x6d\xde\
+\x12\x6e\x52\x52\xb1\x45\xe1\x13\xe1\x2e\x43\x2e\x28\x7c\x63\xeb\
+\xf1\x22\x3f\xdb\x9c\x2c\xf2\xa7\xcd\x46\x34\x1c\x04\x47\x83\xb0\
+\x2f\xf9\x8b\xe3\xbf\x58\x49\x19\x9a\xb0\xbc\x9c\x36\x2d\xbd\xa2\
+\xfc\xdc\xc7\x7e\x89\x3b\x91\x99\x8e\x48\x6c\x15\xf7\x62\x12\x26\
+\x44\x00\x1f\xe3\x8c\x10\x64\x80\x5e\x86\x64\x1e\xa0\x9b\x3e\x7a\
+\x64\x45\x99\x7c\x7f\x21\x7f\x8a\x65\xc9\x55\x64\xd6\xc9\x61\xb0\
+\x44\x92\x14\x59\xba\x44\x5d\x91\xea\x09\x89\xaa\xe8\x09\x19\x69\
+\x72\x76\xff\xff\xf6\xd5\x54\xfb\xfb\x8a\xd5\xdd\x01\xa8\x7a\xb4\
+\xac\xd7\x76\x70\x6d\xc2\x57\xde\xb2\x3e\x0e\x2c\xeb\xeb\x10\x9c\
+\x0f\x70\x9e\x29\xe5\x2f\xef\xc3\xe0\x9b\xe8\xf9\x92\xd6\xb6\x07\
+\x9e\x75\x38\xbd\x28\x69\xf1\x6d\x38\xdb\x80\xe6\x7b\x3d\x66\xc4\
+\x0a\x92\x53\xdc\xa1\xaa\xf0\x72\x0c\xf5\xb3\xd0\x78\x05\xb5\xf3\
+\xc5\x9e\xfd\xec\x73\x74\x07\xd1\x35\xf9\xaa\x4b\xd8\xd9\x85\x0e\
+\x39\xef\x59\xf8\x06\x8e\xfd\x67\xf8\xfd\x8a\x18\x97\x00\x00\x00\
+\x09\x70\x48\x59\x73\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\
+\x9c\x18\x00\x00\x00\xa2\x49\x44\x41\x54\x18\x95\x55\xcf\xb1\x4a\
+\xc3\x31\x00\xc4\xe1\x2f\xff\xb9\x93\xa3\x93\xb8\xa5\x8b\x0f\x20\
+\x55\x44\x10\x5c\x3a\x84\x2c\x1d\x5c\x7c\x0f\xb7\x8e\x3e\x4a\x88\
+\xa3\xb8\x08\x6d\x05\xbb\x77\xc8\xea\xe2\x0b\x74\x6f\xe9\xd2\x42\
+\x7a\x70\x70\xf0\xe3\x0e\x2e\xa4\xd2\xae\xf0\x8a\xf7\x9a\xe3\x56\
+\xa7\x01\xd7\x78\xc3\x32\x95\x76\x79\x06\x6b\x8e\xdf\x78\xc1\x18\
+\xbf\xa9\xb4\xf1\x09\x86\x53\x48\xa5\x3d\xe2\x03\x3b\x4c\x6b\x8e\
+\xab\xd0\xcf\xa4\xd2\x6e\xf0\x89\x0b\xdc\x0f\xce\xb5\x3f\x3a\x20\
+\x0c\x5d\xeb\x01\x3f\x18\xe1\xa9\xe6\xb8\x1e\x8e\x60\x86\x2f\x6c\
+\x71\x5b\x73\x5c\x40\x48\xa5\xdd\x61\x81\x0d\x9e\x6b\x8e\xff\xfd\
+\xcf\x3f\xcc\x31\xe9\x01\x1c\x00\x73\x52\x2d\x71\xe4\x4a\x1b\x69\
+\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
+\x00\x00\x00\xa6\
+\x89\
+\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
+\x00\x00\x09\x00\x00\x00\x06\x08\x04\x00\x00\x00\xbb\xce\x7c\x4e\
+\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
+\x02\x62\x4b\x47\x44\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09\x70\
+\x48\x59\x73\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
+\x00\x00\x00\x07\x74\x49\x4d\x45\x07\xdc\x08\x17\x08\x15\x3b\xdc\
+\x3b\x0c\x9b\x00\x00\x00\x2a\x49\x44\x41\x54\x08\xd7\x63\x60\xc0\
+\x00\x8c\x0c\x0c\x73\x3e\x20\x0b\xa4\x08\x30\x32\x30\x20\x0b\xa6\
+\x08\x30\x30\x30\x42\x98\x10\xc1\x14\x01\x14\x13\x50\xb5\xa3\x01\
+\x00\xc6\xb9\x07\x90\x5d\x66\x1f\x83\x00\x00\x00\x00\x49\x45\x4e\
+\x44\xae\x42\x60\x82\
+\x00\x00\x00\xa5\
+\x89\
+\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
+\x00\x00\x09\x00\x00\x00\x06\x08\x04\x00\x00\x00\xbb\xce\x7c\x4e\
+\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
+\x02\x62\x4b\x47\x44\x00\x9c\x53\x34\xfc\x5d\x00\x00\x00\x09\x70\
+\x48\x59\x73\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
+\x00\x00\x00\x07\x74\x49\x4d\x45\x07\xdc\x08\x17\x0b\x02\x04\x6d\
+\x98\x1b\x69\x00\x00\x00\x29\x49\x44\x41\x54\x08\xd7\x63\x60\xc0\
+\x00\x8c\x0c\x0c\xff\xcf\xa3\x08\x18\x32\x32\x30\x20\x0b\x32\x1a\
+\x32\x30\x30\x42\x98\x10\x41\x46\x43\x14\x13\x50\xb5\xa3\x01\x00\
+\xd6\x10\x07\xd2\x2f\x48\xdf\x4a\x00\x00\x00\x00\x49\x45\x4e\x44\
+\xae\x42\x60\x82\
+\x00\x00\x00\xa6\
+\x89\
+\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
+\x00\x00\x06\x00\x00\x00\x09\x08\x04\x00\x00\x00\xbb\x93\x95\x16\
+\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
+\x02\x62\x4b\x47\x44\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09\x70\
+\x48\x59\x73\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
+\x00\x00\x00\x07\x74\x49\x4d\x45\x07\xdc\x08\x17\x14\x1f\x20\xb9\
+\x8d\x77\xe9\x00\x00\x00\x2a\x49\x44\x41\x54\x08\xd7\x63\x60\xc0\
+\x06\xe6\x7c\x60\x60\x60\x42\x30\xa1\x1c\x08\x93\x81\x81\x09\xc1\
+\x64\x60\x60\x62\x60\x48\x11\x40\xe2\x20\x73\x19\x90\x8d\x40\x02\
+\x00\x23\xed\x08\xaf\x64\x9f\x0f\x15\x00\x00\x00\x00\x49\x45\x4e\
+\x44\xae\x42\x60\x82\
+\x00\x00\x00\x9e\
+\x89\
+\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
+\x00\x00\x09\x00\x00\x00\x06\x08\x04\x00\x00\x00\xbb\xce\x7c\x4e\
+\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
+\x02\x62\x4b\x47\x44\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09\x70\
+\x48\x59\x73\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
+\x00\x00\x00\x07\x74\x49\x4d\x45\x07\xdc\x08\x17\x08\x15\x0f\xfd\
+\x8f\xf8\x2e\x00\x00\x00\x22\x49\x44\x41\x54\x08\xd7\x63\x60\xc0\
+\x0d\xfe\x9f\x87\xb1\x18\x91\x05\x18\x0d\xe1\x42\x48\x2a\x0c\x19\
+\x18\x18\x91\x05\x10\x2a\xd1\x00\x00\xca\xb5\x07\xd2\x76\xbb\xb2\
+\xc5\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
+\x00\x00\x00\xa6\
+\x89\
+\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
+\x00\x00\x09\x00\x00\x00\x06\x08\x04\x00\x00\x00\xbb\xce\x7c\x4e\
+\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
+\x02\x62\x4b\x47\x44\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09\x70\
+\x48\x59\x73\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
+\x00\x00\x00\x07\x74\x49\x4d\x45\x07\xdc\x08\x17\x08\x15\x3b\xdc\
+\x3b\x0c\x9b\x00\x00\x00\x2a\x49\x44\x41\x54\x08\xd7\x63\x60\xc0\
+\x00\x8c\x0c\x0c\x73\x3e\x20\x0b\xa4\x08\x30\x32\x30\x20\x0b\xa6\
+\x08\x30\x30\x30\x42\x98\x10\xc1\x14\x01\x14\x13\x50\xb5\xa3\x01\
+\x00\xc6\xb9\x07\x90\x5d\x66\x1f\x83\x00\x00\x00\x00\x49\x45\x4e\
+\x44\xae\x42\x60\x82\
+\x00\x00\x00\xa6\
+\x89\
+\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
+\x00\x00\x06\x00\x00\x00\x09\x08\x04\x00\x00\x00\xbb\x93\x95\x16\
+\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
+\x02\x62\x4b\x47\x44\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09\x70\
+\x48\x59\x73\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
+\x00\x00\x00\x07\x74\x49\x4d\x45\x07\xdc\x08\x17\x14\x1d\x00\xb0\
+\xd5\x35\xa3\x00\x00\x00\x2a\x49\x44\x41\x54\x08\xd7\x63\x60\xc0\
+\x06\xfe\x9f\x67\x60\x60\x42\x30\xa1\x1c\x08\x93\x81\x81\x09\xc1\
+\x64\x60\x60\x62\x60\x60\x34\x44\xe2\x20\x73\x19\x90\x8d\x40\x02\
+\x00\x64\x40\x09\x75\x86\xb3\xad\x9c\x00\x00\x00\x00\x49\x45\x4e\
+\x44\xae\x42\x60\x82\
+\x00\x00\x00\xa6\
+\x89\
+\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
+\x00\x00\x06\x00\x00\x00\x09\x08\x04\x00\x00\x00\xbb\x93\x95\x16\
+\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
+\x02\x62\x4b\x47\x44\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09\x70\
+\x48\x59\x73\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
+\x00\x00\x00\x07\x74\x49\x4d\x45\x07\xdc\x08\x17\x14\x1d\x00\xb0\
+\xd5\x35\xa3\x00\x00\x00\x2a\x49\x44\x41\x54\x08\xd7\x63\x60\xc0\
+\x06\xfe\x9f\x67\x60\x60\x42\x30\xa1\x1c\x08\x93\x81\x81\x09\xc1\
+\x64\x60\x60\x62\x60\x60\x34\x44\xe2\x20\x73\x19\x90\x8d\x40\x02\
+\x00\x64\x40\x09\x75\x86\xb3\xad\x9c\x00\x00\x00\x00\x49\x45\x4e\
+\x44\xae\x42\x60\x82\
+\x00\x00\x07\x06\
+\x89\
+\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
+\x00\x00\x0a\x00\x00\x00\x07\x08\x06\x00\x00\x00\x31\xac\xdc\x63\
+\x00\x00\x04\xb0\x69\x54\x58\x74\x58\x4d\x4c\x3a\x63\x6f\x6d\x2e\
+\x61\x64\x6f\x62\x65\x2e\x78\x6d\x70\x00\x00\x00\x00\x00\x3c\x3f\
+\x78\x70\x61\x63\x6b\x65\x74\x20\x62\x65\x67\x69\x6e\x3d\x22\xef\
+\xbb\xbf\x22\x20\x69\x64\x3d\x22\x57\x35\x4d\x30\x4d\x70\x43\x65\
+\x68\x69\x48\x7a\x72\x65\x53\x7a\x4e\x54\x63\x7a\x6b\x63\x39\x64\
+\x22\x3f\x3e\x0a\x3c\x78\x3a\x78\x6d\x70\x6d\x65\x74\x61\x20\x78\
+\x6d\x6c\x6e\x73\x3a\x78\x3d\x22\x61\x64\x6f\x62\x65\x3a\x6e\x73\
+\x3a\x6d\x65\x74\x61\x2f\x22\x20\x78\x3a\x78\x6d\x70\x74\x6b\x3d\
+\x22\x58\x4d\x50\x20\x43\x6f\x72\x65\x20\x35\x2e\x35\x2e\x30\x22\
+\x3e\x0a\x20\x3c\x72\x64\x66\x3a\x52\x44\x46\x20\x78\x6d\x6c\x6e\
+\x73\x3a\x72\x64\x66\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\x39\x2f\x30\x32\
+\x2f\x32\x32\x2d\x72\x64\x66\x2d\x73\x79\x6e\x74\x61\x78\x2d\x6e\
+\x73\x23\x22\x3e\x0a\x20\x20\x3c\x72\x64\x66\x3a\x44\x65\x73\x63\
+\x72\x69\x70\x74\x69\x6f\x6e\x20\x72\x64\x66\x3a\x61\x62\x6f\x75\
+\x74\x3d\x22\x22\x0a\x20\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x65\
+\x78\x69\x66\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x6e\x73\x2e\x61\
+\x64\x6f\x62\x65\x2e\x63\x6f\x6d\x2f\x65\x78\x69\x66\x2f\x31\x2e\
+\x30\x2f\x22\x0a\x20\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x74\x69\
+\x66\x66\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x6e\x73\x2e\x61\x64\
+\x6f\x62\x65\x2e\x63\x6f\x6d\x2f\x74\x69\x66\x66\x2f\x31\x2e\x30\
+\x2f\x22\x0a\x20\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x70\x68\x6f\
+\x74\x6f\x73\x68\x6f\x70\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x6e\
+\x73\x2e\x61\x64\x6f\x62\x65\x2e\x63\x6f\x6d\x2f\x70\x68\x6f\x74\
+\x6f\x73\x68\x6f\x70\x2f\x31\x2e\x30\x2f\x22\x0a\x20\x20\x20\x20\
+\x78\x6d\x6c\x6e\x73\x3a\x78\x6d\x70\x3d\x22\x68\x74\x74\x70\x3a\
+\x2f\x2f\x6e\x73\x2e\x61\x64\x6f\x62\x65\x2e\x63\x6f\x6d\x2f\x78\
+\x61\x70\x2f\x31\x2e\x30\x2f\x22\x0a\x20\x20\x20\x20\x78\x6d\x6c\
+\x6e\x73\x3a\x78\x6d\x70\x4d\x4d\x3d\x22\x68\x74\x74\x70\x3a\x2f\
+\x2f\x6e\x73\x2e\x61\x64\x6f\x62\x65\x2e\x63\x6f\x6d\x2f\x78\x61\
+\x70\x2f\x31\x2e\x30\x2f\x6d\x6d\x2f\x22\x0a\x20\x20\x20\x20\x78\
+\x6d\x6c\x6e\x73\x3a\x73\x74\x45\x76\x74\x3d\x22\x68\x74\x74\x70\
+\x3a\x2f\x2f\x6e\x73\x2e\x61\x64\x6f\x62\x65\x2e\x63\x6f\x6d\x2f\
+\x78\x61\x70\x2f\x31\x2e\x30\x2f\x73\x54\x79\x70\x65\x2f\x52\x65\
+\x73\x6f\x75\x72\x63\x65\x45\x76\x65\x6e\x74\x23\x22\x0a\x20\x20\
+\x20\x65\x78\x69\x66\x3a\x50\x69\x78\x65\x6c\x58\x44\x69\x6d\x65\
+\x6e\x73\x69\x6f\x6e\x3d\x22\x31\x30\x22\x0a\x20\x20\x20\x65\x78\
+\x69\x66\x3a\x50\x69\x78\x65\x6c\x59\x44\x69\x6d\x65\x6e\x73\x69\
+\x6f\x6e\x3d\x22\x37\x22\x0a\x20\x20\x20\x65\x78\x69\x66\x3a\x43\
+\x6f\x6c\x6f\x72\x53\x70\x61\x63\x65\x3d\x22\x31\x22\x0a\x20\x20\
+\x20\x74\x69\x66\x66\x3a\x49\x6d\x61\x67\x65\x57\x69\x64\x74\x68\
+\x3d\x22\x31\x30\x22\x0a\x20\x20\x20\x74\x69\x66\x66\x3a\x49\x6d\
+\x61\x67\x65\x4c\x65\x6e\x67\x74\x68\x3d\x22\x37\x22\x0a\x20\x20\
+\x20\x74\x69\x66\x66\x3a\x52\x65\x73\x6f\x6c\x75\x74\x69\x6f\x6e\
+\x55\x6e\x69\x74\x3d\x22\x32\x22\x0a\x20\x20\x20\x74\x69\x66\x66\
+\x3a\x58\x52\x65\x73\x6f\x6c\x75\x74\x69\x6f\x6e\x3d\x22\x37\x32\
+\x2e\x30\x22\x0a\x20\x20\x20\x74\x69\x66\x66\x3a\x59\x52\x65\x73\
+\x6f\x6c\x75\x74\x69\x6f\x6e\x3d\x22\x37\x32\x2e\x30\x22\x0a\x20\
+\x20\x20\x70\x68\x6f\x74\x6f\x73\x68\x6f\x70\x3a\x43\x6f\x6c\x6f\
+\x72\x4d\x6f\x64\x65\x3d\x22\x33\x22\x0a\x20\x20\x20\x70\x68\x6f\
+\x74\x6f\x73\x68\x6f\x70\x3a\x49\x43\x43\x50\x72\x6f\x66\x69\x6c\
+\x65\x3d\x22\x73\x52\x47\x42\x20\x49\x45\x43\x36\x31\x39\x36\x36\
+\x2d\x32\x2e\x31\x22\x0a\x20\x20\x20\x78\x6d\x70\x3a\x4d\x6f\x64\
+\x69\x66\x79\x44\x61\x74\x65\x3d\x22\x32\x30\x32\x31\x2d\x30\x35\
+\x2d\x33\x31\x54\x31\x32\x3a\x33\x30\x3a\x31\x31\x2b\x30\x32\x3a\
+\x30\x30\x22\x0a\x20\x20\x20\x78\x6d\x70\x3a\x4d\x65\x74\x61\x64\
+\x61\x74\x61\x44\x61\x74\x65\x3d\x22\x32\x30\x32\x31\x2d\x30\x35\
+\x2d\x33\x31\x54\x31\x32\x3a\x33\x30\x3a\x31\x31\x2b\x30\x32\x3a\
+\x30\x30\x22\x3e\x0a\x20\x20\x20\x3c\x78\x6d\x70\x4d\x4d\x3a\x48\
+\x69\x73\x74\x6f\x72\x79\x3e\x0a\x20\x20\x20\x20\x3c\x72\x64\x66\
+\x3a\x53\x65\x71\x3e\x0a\x20\x20\x20\x20\x20\x3c\x72\x64\x66\x3a\
+\x6c\x69\x0a\x20\x20\x20\x20\x20\x20\x73\x74\x45\x76\x74\x3a\x61\
+\x63\x74\x69\x6f\x6e\x3d\x22\x70\x72\x6f\x64\x75\x63\x65\x64\x22\
+\x0a\x20\x20\x20\x20\x20\x20\x73\x74\x45\x76\x74\x3a\x73\x6f\x66\
+\x74\x77\x61\x72\x65\x41\x67\x65\x6e\x74\x3d\x22\x41\x66\x66\x69\
+\x6e\x69\x74\x79\x20\x44\x65\x73\x69\x67\x6e\x65\x72\x20\x31\x2e\
+\x39\x2e\x32\x22\x0a\x20\x20\x20\x20\x20\x20\x73\x74\x45\x76\x74\
+\x3a\x77\x68\x65\x6e\x3d\x22\x32\x30\x32\x31\x2d\x30\x35\x2d\x33\
+\x31\x54\x31\x32\x3a\x33\x30\x3a\x31\x31\x2b\x30\x32\x3a\x30\x30\
+\x22\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x2f\x72\x64\x66\x3a\x53\x65\
+\x71\x3e\x0a\x20\x20\x20\x3c\x2f\x78\x6d\x70\x4d\x4d\x3a\x48\x69\
+\x73\x74\x6f\x72\x79\x3e\x0a\x20\x20\x3c\x2f\x72\x64\x66\x3a\x44\
+\x65\x73\x63\x72\x69\x70\x74\x69\x6f\x6e\x3e\x0a\x20\x3c\x2f\x72\
+\x64\x66\x3a\x52\x44\x46\x3e\x0a\x3c\x2f\x78\x3a\x78\x6d\x70\x6d\
+\x65\x74\x61\x3e\x0a\x3c\x3f\x78\x70\x61\x63\x6b\x65\x74\x20\x65\
+\x6e\x64\x3d\x22\x72\x22\x3f\x3e\x85\x9d\x9f\x08\x00\x00\x01\x83\
+\x69\x43\x43\x50\x73\x52\x47\x42\x20\x49\x45\x43\x36\x31\x39\x36\
+\x36\x2d\x32\x2e\x31\x00\x00\x28\x91\x75\x91\xcf\x2b\x44\x51\x14\
+\xc7\x3f\x66\x68\xfc\x18\x8d\x62\x61\x31\x65\x12\x16\x42\x83\x12\
+\x1b\x8b\x99\x18\x0a\x8b\x99\x51\x7e\x6d\x66\x9e\x79\x33\x6a\xde\
+\x78\xbd\x37\xd2\x64\xab\x6c\xa7\x28\xb1\xf1\x6b\xc1\x5f\xc0\x56\
+\x59\x2b\x45\xa4\x64\xa7\xac\x89\x0d\x7a\xce\x9b\x51\x23\x99\x73\
+\x3b\xf7\x7c\xee\xf7\xde\x73\xba\xf7\x5c\x70\x44\xd3\x8a\x66\x56\
+\xfa\x41\xcb\x64\x8d\x70\x28\xe0\x9b\x99\x9d\xf3\xb9\x9e\xa8\xa2\
+\x85\x1a\x3a\xf1\xc6\x14\x53\x9f\x8c\x8c\x46\x29\x6b\xef\xb7\x54\
+\xd8\xf1\xba\xdb\xae\x55\xfe\xdc\xbf\x56\xb7\x98\x30\x15\xa8\xa8\
+\x16\x1e\x56\x74\x23\x2b\x3c\x26\x3c\xb1\x9a\xd5\x6d\xde\x12\x6e\
+\x52\x52\xb1\x45\xe1\x13\xe1\x2e\x43\x2e\x28\x7c\x63\xeb\xf1\x22\
+\x3f\xdb\x9c\x2c\xf2\xa7\xcd\x46\x34\x1c\x04\x47\x83\xb0\x2f\xf9\
+\x8b\xe3\xbf\x58\x49\x19\x9a\xb0\xbc\x9c\x36\x2d\xbd\xa2\xfc\xdc\
+\xc7\x7e\x89\x3b\x91\x99\x8e\x48\x6c\x15\xf7\x62\x12\x26\x44\x00\
+\x1f\xe3\x8c\x10\x64\x80\x5e\x86\x64\x1e\xa0\x9b\x3e\x7a\x64\x45\
+\x99\x7c\x7f\x21\x7f\x8a\x65\xc9\x55\x64\xd6\xc9\x61\xb0\x44\x92\
+\x14\x59\xba\x44\x5d\x91\xea\x09\x89\xaa\xe8\x09\x19\x69\x72\x76\
+\xff\xff\xf6\xd5\x54\xfb\xfb\x8a\xd5\xdd\x01\xa8\x7a\xb4\xac\xd7\
+\x76\x70\x6d\xc2\x57\xde\xb2\x3e\x0e\x2c\xeb\xeb\x10\x9c\x0f\x70\
+\x9e\x29\xe5\x2f\xef\xc3\xe0\x9b\xe8\xf9\x92\xd6\xb6\x07\x9e\x75\
+\x38\xbd\x28\x69\xf1\x6d\x38\xdb\x80\xe6\x7b\x3d\x66\xc4\x0a\x92\
+\x53\xdc\xa1\xaa\xf0\x72\x0c\xf5\xb3\xd0\x78\x05\xb5\xf3\xc5\x9e\
+\xfd\xec\x73\x74\x07\xd1\x35\xf9\xaa\x4b\xd8\xd9\x85\x0e\x39\xef\
+\x59\xf8\x06\x8e\xfd\x67\xf8\xfd\x8a\x18\x97\x00\x00\x00\x09\x70\
+\x48\x59\x73\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
+\x00\x00\x00\x6d\x49\x44\x41\x54\x18\x95\x75\xcf\xc1\x09\xc2\x50\
+\x10\x84\xe1\xd7\x85\x07\x9b\xd0\x43\x40\xd2\x82\x78\x14\x7b\x30\
+\x57\x21\x8d\x84\x60\x3f\x62\x4b\x7a\x48\xcc\x97\x83\xfb\x30\x04\
+\xdf\x9c\x86\x7f\x67\x99\xdd\x84\x0d\xaa\x54\x10\x6a\x6c\x13\x1e\
+\xbe\xba\xfe\x09\x35\x31\x7b\xe6\x8d\x0f\x26\x1c\x17\xa1\x53\xb0\
+\x11\x87\x0c\x2f\x01\x07\xec\xb0\x0f\x3f\xe1\xbc\xae\x69\xa3\xe6\
+\x85\x77\xf8\x5b\xe9\xf0\xbb\x9f\xfa\xd2\x83\x39\xdc\xa3\x5b\xf3\
+\x19\x2e\xa8\x89\xb5\x30\xf7\x43\xa0\x00\x00\x00\x00\x49\x45\x4e\
+\x44\xae\x42\x60\x82\
+"
+
+qt_resource_name = b"\
+\x00\x08\
+\x06\xc5\x8e\xa5\
+\x00\x6f\
+\x00\x70\x00\x65\x00\x6e\x00\x70\x00\x79\x00\x70\x00\x65\
+\x00\x06\
+\x07\x03\x7d\xc3\
+\x00\x69\
+\x00\x6d\x00\x61\x00\x67\x00\x65\x00\x73\
+\x00\x0f\
+\x02\x9f\x05\x87\
+\x00\x72\
+\x00\x69\x00\x67\x00\x68\x00\x74\x00\x5f\x00\x61\x00\x72\x00\x72\x00\x6f\x00\x77\x00\x2e\x00\x70\x00\x6e\x00\x67\
+\x00\x12\
+\x05\x8f\x9d\x07\
+\x00\x62\
+\x00\x72\x00\x61\x00\x6e\x00\x63\x00\x68\x00\x5f\x00\x6f\x00\x70\x00\x65\x00\x6e\x00\x5f\x00\x6f\x00\x6e\x00\x2e\x00\x70\x00\x6e\
+\x00\x67\
+\x00\x1b\
+\x03\x5a\x32\x27\
+\x00\x63\
+\x00\x6f\x00\x6d\x00\x62\x00\x6f\x00\x62\x00\x6f\x00\x78\x00\x5f\x00\x61\x00\x72\x00\x72\x00\x6f\x00\x77\x00\x5f\x00\x64\x00\x69\
+\x00\x73\x00\x61\x00\x62\x00\x6c\x00\x65\x00\x64\x00\x2e\x00\x70\x00\x6e\x00\x67\
+\x00\x18\
+\x03\x8e\xde\x67\
+\x00\x72\
+\x00\x69\x00\x67\x00\x68\x00\x74\x00\x5f\x00\x61\x00\x72\x00\x72\x00\x6f\x00\x77\x00\x5f\x00\x64\x00\x69\x00\x73\x00\x61\x00\x62\
+\x00\x6c\x00\x65\x00\x64\x00\x2e\x00\x70\x00\x6e\x00\x67\
+\x00\x11\
+\x0b\xda\x30\xa7\
+\x00\x62\
+\x00\x72\x00\x61\x00\x6e\x00\x63\x00\x68\x00\x5f\x00\x63\x00\x6c\x00\x6f\x00\x73\x00\x65\x00\x64\x00\x2e\x00\x70\x00\x6e\x00\x67\
+\
+\x00\x12\
+\x03\x8d\x04\x47\
+\x00\x72\
+\x00\x69\x00\x67\x00\x68\x00\x74\x00\x5f\x00\x61\x00\x72\x00\x72\x00\x6f\x00\x77\x00\x5f\x00\x6f\x00\x6e\x00\x2e\x00\x70\x00\x6e\
+\x00\x67\
+\x00\x15\
+\x0f\xf3\xc0\x07\
+\x00\x75\
+\x00\x70\x00\x5f\x00\x61\x00\x72\x00\x72\x00\x6f\x00\x77\x00\x5f\x00\x64\x00\x69\x00\x73\x00\x61\x00\x62\x00\x6c\x00\x65\x00\x64\
+\x00\x2e\x00\x70\x00\x6e\x00\x67\
+\x00\x0f\
+\x01\x73\x8b\x07\
+\x00\x75\
+\x00\x70\x00\x5f\x00\x61\x00\x72\x00\x72\x00\x6f\x00\x77\x00\x5f\x00\x6f\x00\x6e\x00\x2e\x00\x70\x00\x6e\x00\x67\
+\x00\x0e\
+\x04\xa2\xfc\xa7\
+\x00\x64\
+\x00\x6f\x00\x77\x00\x6e\x00\x5f\x00\x61\x00\x72\x00\x72\x00\x6f\x00\x77\x00\x2e\x00\x70\x00\x6e\x00\x67\
+\x00\x12\
+\x01\x2e\x03\x27\
+\x00\x63\
+\x00\x6f\x00\x6d\x00\x62\x00\x6f\x00\x62\x00\x6f\x00\x78\x00\x5f\x00\x61\x00\x72\x00\x72\x00\x6f\x00\x77\x00\x2e\x00\x70\x00\x6e\
+\x00\x67\
+\x00\x14\
+\x04\x5e\x2d\xa7\
+\x00\x62\
+\x00\x72\x00\x61\x00\x6e\x00\x63\x00\x68\x00\x5f\x00\x63\x00\x6c\x00\x6f\x00\x73\x00\x65\x00\x64\x00\x5f\x00\x6f\x00\x6e\x00\x2e\
+\x00\x70\x00\x6e\x00\x67\
+\x00\x17\
+\x0c\xab\x51\x07\
+\x00\x64\
+\x00\x6f\x00\x77\x00\x6e\x00\x5f\x00\x61\x00\x72\x00\x72\x00\x6f\x00\x77\x00\x5f\x00\x64\x00\x69\x00\x73\x00\x61\x00\x62\x00\x6c\
+\x00\x65\x00\x64\x00\x2e\x00\x70\x00\x6e\x00\x67\
+\x00\x11\
+\x01\x1f\xc3\x87\
+\x00\x64\
+\x00\x6f\x00\x77\x00\x6e\x00\x5f\x00\x61\x00\x72\x00\x72\x00\x6f\x00\x77\x00\x5f\x00\x6f\x00\x6e\x00\x2e\x00\x70\x00\x6e\x00\x67\
+\
+\x00\x17\
+\x0c\x65\xce\x07\
+\x00\x6c\
+\x00\x65\x00\x66\x00\x74\x00\x5f\x00\x61\x00\x72\x00\x72\x00\x6f\x00\x77\x00\x5f\x00\x64\x00\x69\x00\x73\x00\x61\x00\x62\x00\x6c\
+\x00\x65\x00\x64\x00\x2e\x00\x70\x00\x6e\x00\x67\
+\x00\x0c\
+\x06\xe6\xe6\x67\
+\x00\x75\
+\x00\x70\x00\x5f\x00\x61\x00\x72\x00\x72\x00\x6f\x00\x77\x00\x2e\x00\x70\x00\x6e\x00\x67\
+\x00\x15\
+\x03\x27\x72\x67\
+\x00\x63\
+\x00\x6f\x00\x6d\x00\x62\x00\x6f\x00\x62\x00\x6f\x00\x78\x00\x5f\x00\x61\x00\x72\x00\x72\x00\x6f\x00\x77\x00\x5f\x00\x6f\x00\x6e\
+\x00\x2e\x00\x70\x00\x6e\x00\x67\
+\x00\x11\
+\x00\xb8\x8c\x07\
+\x00\x6c\
+\x00\x65\x00\x66\x00\x74\x00\x5f\x00\x61\x00\x72\x00\x72\x00\x6f\x00\x77\x00\x5f\x00\x6f\x00\x6e\x00\x2e\x00\x70\x00\x6e\x00\x67\
+\
+\x00\x0e\
+\x0e\xde\xfa\xc7\
+\x00\x6c\
+\x00\x65\x00\x66\x00\x74\x00\x5f\x00\x61\x00\x72\x00\x72\x00\x6f\x00\x77\x00\x2e\x00\x70\x00\x6e\x00\x67\
+\x00\x0f\
+\x06\x53\x25\xa7\
+\x00\x62\
+\x00\x72\x00\x61\x00\x6e\x00\x63\x00\x68\x00\x5f\x00\x6f\x00\x70\x00\x65\x00\x6e\x00\x2e\x00\x70\x00\x6e\x00\x67\
+"
+
+qt_resource_struct_v1 = b"\
+\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
+\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\
+\x00\x00\x00\x16\x00\x02\x00\x00\x00\x13\x00\x00\x00\x03\
+\x00\x00\x02\xe6\x00\x00\x00\x00\x00\x01\x00\x00\x1f\x3c\
+\x00\x00\x02\x3c\x00\x00\x00\x00\x00\x01\x00\x00\x1c\x9d\
+\x00\x00\x01\xb0\x00\x00\x00\x00\x00\x01\x00\x00\x13\x68\
+\x00\x00\x01\x6a\x00\x00\x00\x00\x00\x01\x00\x00\x12\x1d\
+\x00\x00\x00\x28\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
+\x00\x00\x02\xb6\x00\x00\x00\x00\x00\x01\x00\x00\x1e\x92\
+\x00\x00\x00\x76\x00\x00\x00\x00\x00\x01\x00\x00\x07\xd8\
+\x00\x00\x01\x10\x00\x00\x00\x00\x00\x01\x00\x00\x10\xd6\
+\x00\x00\x00\xb2\x00\x00\x00\x00\x00\x01\x00\x00\x08\x81\
+\x00\x00\x01\xda\x00\x00\x00\x00\x00\x01\x00\x00\x14\x12\
+\x00\x00\x01\x8e\x00\x00\x00\x00\x00\x01\x00\x00\x12\xbf\
+\x00\x00\x00\x4c\x00\x00\x00\x00\x00\x01\x00\x00\x00\xa4\
+\x00\x00\x03\x30\x00\x00\x00\x00\x00\x01\x00\x00\x20\x90\
+\x00\x00\x02\x98\x00\x00\x00\x00\x00\x01\x00\x00\x1d\xf0\
+\x00\x00\x00\xe8\x00\x00\x00\x00\x00\x01\x00\x00\x09\x25\
+\x00\x00\x02\x64\x00\x00\x00\x00\x00\x01\x00\x00\x1d\x46\
+\x00\x00\x02\x08\x00\x00\x00\x00\x00\x01\x00\x00\x1b\xf3\
+\x00\x00\x03\x0e\x00\x00\x00\x00\x00\x01\x00\x00\x1f\xe6\
+\x00\x00\x01\x3a\x00\x00\x00\x00\x00\x01\x00\x00\x11\x7a\
+"
+
+qt_resource_struct_v2 = b"\
+\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
+\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\
+\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x00\x16\x00\x02\x00\x00\x00\x13\x00\x00\x00\x03\
+\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x02\xe6\x00\x00\x00\x00\x00\x01\x00\x00\x1f\x3c\
+\x00\x00\x01\x76\x41\x9d\xa2\x35\
+\x00\x00\x02\x3c\x00\x00\x00\x00\x00\x01\x00\x00\x1c\x9d\
+\x00\x00\x01\x76\x41\x9d\xa2\x35\
+\x00\x00\x01\xb0\x00\x00\x00\x00\x00\x01\x00\x00\x13\x68\
+\x00\x00\x01\x79\xb4\x72\xcc\x9c\
+\x00\x00\x01\x6a\x00\x00\x00\x00\x00\x01\x00\x00\x12\x1d\
+\x00\x00\x01\x76\x41\x9d\xa2\x39\
+\x00\x00\x00\x28\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
+\x00\x00\x01\x76\x41\x9d\xa2\x37\
+\x00\x00\x02\xb6\x00\x00\x00\x00\x00\x01\x00\x00\x1e\x92\
+\x00\x00\x01\x79\xb4\x72\xcc\x9c\
+\x00\x00\x00\x76\x00\x00\x00\x00\x00\x01\x00\x00\x07\xd8\
+\x00\x00\x01\x79\xb4\x72\xcc\x9c\
+\x00\x00\x01\x10\x00\x00\x00\x00\x00\x01\x00\x00\x10\xd6\
+\x00\x00\x01\x76\x41\x9d\xa2\x37\
+\x00\x00\x00\xb2\x00\x00\x00\x00\x00\x01\x00\x00\x08\x81\
+\x00\x00\x01\x76\x41\x9d\xa2\x37\
+\x00\x00\x01\xda\x00\x00\x00\x00\x00\x01\x00\x00\x14\x12\
+\x00\x00\x01\x79\xc2\x05\x2b\x60\
+\x00\x00\x01\x8e\x00\x00\x00\x00\x00\x01\x00\x00\x12\xbf\
+\x00\x00\x01\x76\x41\x9d\xa2\x35\
+\x00\x00\x00\x4c\x00\x00\x00\x00\x00\x01\x00\x00\x00\xa4\
+\x00\x00\x01\x79\xc1\xfc\x16\x91\
+\x00\x00\x03\x30\x00\x00\x00\x00\x00\x01\x00\x00\x20\x90\
+\x00\x00\x01\x79\xc1\xf9\x4b\x78\
+\x00\x00\x02\x98\x00\x00\x00\x00\x00\x01\x00\x00\x1d\xf0\
+\x00\x00\x01\x76\x41\x9d\xa2\x39\
+\x00\x00\x00\xe8\x00\x00\x00\x00\x00\x01\x00\x00\x09\x25\
+\x00\x00\x01\x79\xc2\x05\x91\x2a\
+\x00\x00\x02\x64\x00\x00\x00\x00\x00\x01\x00\x00\x1d\x46\
+\x00\x00\x01\x76\x41\x9d\xa2\x35\
+\x00\x00\x02\x08\x00\x00\x00\x00\x00\x01\x00\x00\x1b\xf3\
+\x00\x00\x01\x76\x41\x9d\xa2\x35\
+\x00\x00\x03\x0e\x00\x00\x00\x00\x00\x01\x00\x00\x1f\xe6\
+\x00\x00\x01\x76\x41\x9d\xa2\x35\
+\x00\x00\x01\x3a\x00\x00\x00\x00\x00\x01\x00\x00\x11\x7a\
+\x00\x00\x01\x76\x41\x9d\xa2\x39\
+"
+
+
+qt_version = [int(v) for v in QtCore.qVersion().split('.')]
+if qt_version < [5, 8, 0]:
+ rcc_version = 1
+ qt_resource_struct = qt_resource_struct_v1
+else:
+ rcc_version = 2
+ qt_resource_struct = qt_resource_struct_v2
+
+
+def qInitResources():
+ QtCore.qRegisterResourceData(
+ rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data
+ )
+
+
+def qCleanupResources():
+ QtCore.qUnregisterResourceData(
+ rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data
+ )
diff --git a/openpype/style/pyside2_resources.py b/openpype/style/pyside2_resources.py
new file mode 100644
index 0000000000..ee68a74b8e
--- /dev/null
+++ b/openpype/style/pyside2_resources.py
@@ -0,0 +1,843 @@
+# Resource object code (Python 3)
+# Created by: object code
+# Created by: The Resource Compiler for Qt version 5.15.2
+# WARNING! All changes made in this file will be lost!
+
+from PySide2 import QtCore
+
+
+qt_resource_data = b"\
+\x00\x00\x00\x9f\
+\x89\
+PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
+\x00\x00\x09\x00\x00\x00\x06\x08\x04\x00\x00\x00\xbb\xce|N\
+\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\
+\x02bKGD\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09p\
+HYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
+\x00\x00\x00\x07tIME\x07\xdc\x08\x17\x08\x14\x1f\xf9\
+#\xd9\x0b\x00\x00\x00#IDAT\x08\xd7c`\xc0\
+\x0d\xe6|\x80\xb1\x18\x91\x05R\x04\xe0B\x08\x15)\x02\
+\x0c\x0c\x8c\xc8\x02\x08\x95h\x00\x00\xac\xac\x07\x90Ne\
+4\xac\x00\x00\x00\x00IEND\xaeB`\x82\
+\x00\x00\x00\xa6\
+\x89\
+PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
+\x00\x00\x09\x00\x00\x00\x06\x08\x04\x00\x00\x00\xbb\xce|N\
+\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\
+\x02bKGD\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09p\
+HYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
+\x00\x00\x00\x07tIME\x07\xdc\x08\x17\x08\x15;\xdc\
+;\x0c\x9b\x00\x00\x00*IDAT\x08\xd7c`\xc0\
+\x00\x8c\x0c\x0cs> \x0b\xa4\x08020 \x0b\xa6\
+\x08000B\x98\x10\xc1\x14\x01\x14\x13P\xb5\xa3\x01\
+\x00\xc6\xb9\x07\x90]f\x1f\x83\x00\x00\x00\x00IEN\
+D\xaeB`\x82\
+\x00\x00\x00\xa5\
+\x89\
+PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
+\x00\x00\x09\x00\x00\x00\x06\x08\x04\x00\x00\x00\xbb\xce|N\
+\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\
+\x02bKGD\x00\x9cS4\xfc]\x00\x00\x00\x09p\
+HYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
+\x00\x00\x00\x07tIME\x07\xdc\x08\x17\x0b\x02\x04m\
+\x98\x1bi\x00\x00\x00)IDAT\x08\xd7c`\xc0\
+\x00\x8c\x0c\x0c\xff\xcf\xa3\x08\x18220 \x0b2\x1a\
+200B\x98\x10AFC\x14\x13P\xb5\xa3\x01\x00\
+\xd6\x10\x07\xd2/H\xdfJ\x00\x00\x00\x00IEND\
+\xaeB`\x82\
+\x00\x00\x00\xa5\
+\x89\
+PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
+\x00\x00\x09\x00\x00\x00\x06\x08\x04\x00\x00\x00\xbb\xce|N\
+\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\
+\x02bKGD\x00\x9cS4\xfc]\x00\x00\x00\x09p\
+HYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
+\x00\x00\x00\x07tIME\x07\xdc\x08\x17\x0b\x02\x04m\
+\x98\x1bi\x00\x00\x00)IDAT\x08\xd7c`\xc0\
+\x00\x8c\x0c\x0c\xff\xcf\xa3\x08\x18220 \x0b2\x1a\
+200B\x98\x10AFC\x14\x13P\xb5\xa3\x01\x00\
+\xd6\x10\x07\xd2/H\xdfJ\x00\x00\x00\x00IEND\
+\xaeB`\x82\
+\x00\x00\x00\xa0\
+\x89\
+PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
+\x00\x00\x06\x00\x00\x00\x09\x08\x04\x00\x00\x00\xbb\x93\x95\x16\
+\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\
+\x02bKGD\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09p\
+HYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
+\x00\x00\x00\x07tIME\x07\xdc\x08\x17\x14\x1f\x0d\xfc\
+R+\x9c\x00\x00\x00$IDAT\x08\xd7c`@\
+\x05s>\xc0XL\xc8\x5c&dY&d\xc5pN\
+\x8a\x00\x9c\x93\x22\x80a\x1a\x0a\x00\x00)\x95\x08\xaf\x88\
+\xac\xba4\x00\x00\x00\x00IEND\xaeB`\x82\
+\x00\x00\x00\xa6\
+\x89\
+PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
+\x00\x00\x06\x00\x00\x00\x09\x08\x04\x00\x00\x00\xbb\x93\x95\x16\
+\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\
+\x02bKGD\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09p\
+HYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
+\x00\x00\x00\x07tIME\x07\xdc\x08\x17\x14\x1d\x00\xb0\
+\xd55\xa3\x00\x00\x00*IDAT\x08\xd7c`\xc0\
+\x06\xfe\x9fg``B0\xa1\x1c\x08\x93\x81\x81\x09\xc1\
+d``b``4D\xe2 s\x19\x90\x8d@\x02\
+\x00d@\x09u\x86\xb3\xad\x9c\x00\x00\x00\x00IEN\
+D\xaeB`\x82\
+\x00\x00\x00\x9e\
+\x89\
+PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
+\x00\x00\x09\x00\x00\x00\x06\x08\x04\x00\x00\x00\xbb\xce|N\
+\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\
+\x02bKGD\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09p\
+HYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
+\x00\x00\x00\x07tIME\x07\xdc\x08\x17\x08\x15\x0f\xfd\
+\x8f\xf8.\x00\x00\x00\x22IDAT\x08\xd7c`\xc0\
+\x0d\xfe\x9f\x87\xb1\x18\x91\x05\x18\x0d\xe1BH*\x0c\x19\
+\x18\x18\x91\x05\x10*\xd1\x00\x00\xca\xb5\x07\xd2v\xbb\xb2\
+\xc5\x00\x00\x00\x00IEND\xaeB`\x82\
+\x00\x00\x00\x9e\
+\x89\
+PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
+\x00\x00\x09\x00\x00\x00\x06\x08\x04\x00\x00\x00\xbb\xce|N\
+\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\
+\x02bKGD\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09p\
+HYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
+\x00\x00\x00\x07tIME\x07\xdc\x08\x17\x08\x15\x0f\xfd\
+\x8f\xf8.\x00\x00\x00\x22IDAT\x08\xd7c`\xc0\
+\x0d\xfe\x9f\x87\xb1\x18\x91\x05\x18\x0d\xe1BH*\x0c\x19\
+\x18\x18\x91\x05\x10*\xd1\x00\x00\xca\xb5\x07\xd2v\xbb\xb2\
+\xc5\x00\x00\x00\x00IEND\xaeB`\x82\
+\x00\x00\x07\x06\
+\x89\
+PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
+\x00\x00\x0a\x00\x00\x00\x07\x08\x06\x00\x00\x001\xac\xdcc\
+\x00\x00\x04\xb0iTXtXML:com.\
+adobe.xmp\x00\x00\x00\x00\x00\
+xpacket begin=\x22\xef\
+\xbb\xbf\x22 id=\x22W5M0MpCe\
+hiHzreSzNTczkc9d\
+\x22?>\x0a\x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a\x0a\x85\x9d\x9f\x08\x00\x00\x01\x83\
+iCCPsRGB IEC6196\
+6-2.1\x00\x00(\x91u\x91\xcf+DQ\x14\
+\xc7?fh\xfc\x18\x8dba1e\x12\x16B\x83\x12\
+\x1b\x8b\x99\x18\x0a\x8b\x99Q~mf\x9ey3j\xde\
+x\xbd7\xd2d\xabl\xa7(\xb1\xf1k\xc1_\xc0V\
+Y+E\xa4d\xa7\xac\x89\x0dz\xce\x9bQ#\x99s\
+;\xf7|\xee\xf7\xdes\xba\xf7\x5cpD\xd3\x8afV\
+\xfaA\xcbd\x8dp(\xe0\x9b\x99\x9d\xf3\xb9\x9e\xa8\xa2\
+\x85\x1a:\xf1\xc6\x14S\x9f\x8c\x8cF)k\xef\xb7T\
+\xd8\xf1\xba\xdb\xaeU\xfe\xdc\xbfV\xb7\x980\x15\xa8\xa8\
+\x16\x1eVt#+<&<\xb1\x9a\xd5m\xde\x12n\
+RR\xb1E\xe1\x13\xe1.C.(|c\xeb\xf1\x22\
+?\xdb\x9c,\xf2\xa7\xcdF4\x1c\x04G\x83\xb0/\xf9\
+\x8b\xe3\xbfXI\x19\x9a\xb0\xbc\x9c6-\xbd\xa2\xfc\xdc\
+\xc7~\x89;\x91\x99\x8eHl\x15\xf7b\x12&D\x00\
+\x1f\xe3\x8c\x10d\x80^\x86d\x1e\xa0\x9b>zdE\
+\x99|\x7f!\x7f\x8ae\xc9Ud\xd6\xc9a\xb0D\x92\
+\x14Y\xbaD]\x91\xea\x09\x89\xaa\xe8\x09\x19irv\
+\xff\xff\xf6\xd5T\xfb\xfb\x8a\xd5\xdd\x01\xa8z\xb4\xac\xd7\
+vpm\xc2W\xde\xb2>\x0e,\xeb\xeb\x10\x9c\x0fp\
+\x9e)\xe5/\xef\xc3\xe0\x9b\xe8\xf9\x92\xd6\xb6\x07\x9eu\
+8\xbd(i\xf1m8\xdb\x80\xe6{=f\xc4\x0a\x92\
+S\xdc\xa1\xaa\xf0r\x0c\xf5\xb3\xd0x\x05\xb5\xf3\xc5\x9e\
+\xfd\xecst\x07\xd15\xf9\xaaK\xd8\xd9\x85\x0e9\xef\
+Y\xf8\x06\x8e\xfdg\xf8\xfd\x8a\x18\x97\x00\x00\x00\x09p\
+HYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
+\x00\x00\x00mIDAT\x18\x95u\xcf\xc1\x09\xc2P\
+\x10\x84\xe1\xd7\x85\x07\x9b\xd0C@\xd2\x82x\x14{0\
+W!\x8d\x84`?bKzH\xcc\x97\x83\xfb0\x04\
+\xdf\x9c\x86\x7fg\x99\xdd\x84\x0d\xaaT\x10jl\x13\x1e\
+\xbe\xba\xfe\x0951{\xe6\x8d\x0f&\x1c\x17\xa1S\xb0\
+\x11\x87\x0c/\x01\x07\xec\xb0\x0f?\xe1\xbc\xaei\xa3\xe6\
+\x85w\xf8[\xe9\xf0\xbb\x9f\xfa\xd2\x839\xdc\xa3[\xf3\
+\x19.\xa8\x89\xb50\xf7C\xa0\x00\x00\x00\x00IEN\
+D\xaeB`\x82\
+\x00\x00\x00\xa6\
+\x89\
+PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
+\x00\x00\x06\x00\x00\x00\x09\x08\x04\x00\x00\x00\xbb\x93\x95\x16\
+\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\
+\x02bKGD\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09p\
+HYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
+\x00\x00\x00\x07tIME\x07\xdc\x08\x17\x14\x1f \xb9\
+\x8dw\xe9\x00\x00\x00*IDAT\x08\xd7c`\xc0\
+\x06\xe6|```B0\xa1\x1c\x08\x93\x81\x81\x09\xc1\
+d``b`H\x11@\xe2 s\x19\x90\x8d@\x02\
+\x00#\xed\x08\xafd\x9f\x0f\x15\x00\x00\x00\x00IEN\
+D\xaeB`\x82\
+\x00\x00\x07\xdd\
+\x89\
+PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
+\x00\x00\x07\x00\x00\x00\x0a\x08\x06\x00\x00\x00x\xccD\x0d\
+\x00\x00\x05RiTXtXML:com.\
+adobe.xmp\x00\x00\x00\x00\x00\
+xpacket begin=\x22\xef\
+\xbb\xbf\x22 id=\x22W5M0MpCe\
+hiHzreSzNTczkc9d\
+\x22?>\x0a\x0a \x0a \x0a \x0a \
+\x0a branch_close<\
+/rdf:li>\x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a <\
+/rdf:RDF>\x0a\x0aX\xad\xf2\x80\x00\x00\
+\x01\x83iCCPsRGB IEC61\
+966-2.1\x00\x00(\x91u\x91\xcf+D\
+Q\x14\xc7?fh\xfc\x18\x8dba1e\x12\x16B\
+\x83\x12\x1b\x8b\x99\x18\x0a\x8b\x99Q~mf\x9ey3\
+j\xdex\xbd7\xd2d\xabl\xa7(\xb1\xf1k\xc1_\
+\xc0VY+E\xa4d\xa7\xac\x89\x0dz\xce\x9bQ#\
+\x99s;\xf7|\xee\xf7\xdes\xba\xf7\x5cpD\xd3\x8a\
+fV\xfaA\xcbd\x8dp(\xe0\x9b\x99\x9d\xf3\xb9\x9e\
+\xa8\xa2\x85\x1a:\xf1\xc6\x14S\x9f\x8c\x8cF)k\xef\
+\xb7T\xd8\xf1\xba\xdb\xaeU\xfe\xdc\xbfV\xb7\x980\x15\
+\xa8\xa8\x16\x1eVt#+<&<\xb1\x9a\xd5m\xde\
+\x12nRR\xb1E\xe1\x13\xe1.C.(|c\xeb\
+\xf1\x22?\xdb\x9c,\xf2\xa7\xcdF4\x1c\x04G\x83\xb0\
+/\xf9\x8b\xe3\xbfXI\x19\x9a\xb0\xbc\x9c6-\xbd\xa2\
+\xfc\xdc\xc7~\x89;\x91\x99\x8eHl\x15\xf7b\x12&\
+D\x00\x1f\xe3\x8c\x10d\x80^\x86d\x1e\xa0\x9b>z\
+dE\x99|\x7f!\x7f\x8ae\xc9Ud\xd6\xc9a\xb0\
+D\x92\x14Y\xbaD]\x91\xea\x09\x89\xaa\xe8\x09\x19i\
+rv\xff\xff\xf6\xd5T\xfb\xfb\x8a\xd5\xdd\x01\xa8z\xb4\
+\xac\xd7vpm\xc2W\xde\xb2>\x0e,\xeb\xeb\x10\x9c\
+\x0fp\x9e)\xe5/\xef\xc3\xe0\x9b\xe8\xf9\x92\xd6\xb6\x07\
+\x9eu8\xbd(i\xf1m8\xdb\x80\xe6{=f\xc4\
+\x0a\x92S\xdc\xa1\xaa\xf0r\x0c\xf5\xb3\xd0x\x05\xb5\xf3\
+\xc5\x9e\xfd\xecst\x07\xd15\xf9\xaaK\xd8\xd9\x85\x0e\
+9\xefY\xf8\x06\x8e\xfdg\xf8\xfd\x8a\x18\x97\x00\x00\x00\
+\x09pHYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\
+\x9c\x18\x00\x00\x00\xa2IDAT\x18\x95U\xcf\xb1J\
+\xc31\x00\xc4\xe1/\xff\xb9\x93\xa3\x93\xb8\xa5\x8b\x0f \
+UD\x10\x5c:\x84,\x1d\x5c|\x0f\xb7\x8e>J\x88\
+\xa3\xb8\x08m\x05\xbbw\xc8\xea\xe2\x0bto\xe9\xd2B\
+zpp\xf0\xe3\x0e.\xa4\xd2\xae\xf0\x8a\xf7\x9a\xe3V\
+\xa7\x01\xd7x\xc32\x95vy\x06k\x8e\xdfx\xc1\x18\
+\xbf\xa9\xb4\xf1\x09\x86SH\xa5=\xe2\x03;Lk\x8e\
+\xab\xd0\xcf\xa4\xd2n\xf0\x89\x0b\xdc\x0f\xce\xb5?: \
+\x0c]\xeb\x01?\x18\xe1\xa9\xe6\xb8\x1e\x8e`\x86/l\
+q[s\x5c@H\xa5\xdda\x81\x0d\x9ek\x8e\xff\xfd\
+\xcf?\xcc1\xe9\x01\x1c\x00sR-q\xe4J\x1bi\
+\x00\x00\x00\x00IEND\xaeB`\x82\
+\x00\x00\x07\xad\
+\x89\
+PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
+\x00\x00\x07\x00\x00\x00\x0a\x08\x06\x00\x00\x00x\xccD\x0d\
+\x00\x00\x05RiTXtXML:com.\
+adobe.xmp\x00\x00\x00\x00\x00\
+xpacket begin=\x22\xef\
+\xbb\xbf\x22 id=\x22W5M0MpCe\
+hiHzreSzNTczkc9d\
+\x22?>\x0a\x0a \x0a \x0a \x0a \
+\x0a branch_close<\
+/rdf:li>\x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a <\
+/rdf:RDF>\x0a\x0a$\xe15\x97\x00\x00\
+\x01\x83iCCPsRGB IEC61\
+966-2.1\x00\x00(\x91u\x91\xcf+D\
+Q\x14\xc7?fh\xfc\x18\x8dba1e\x12\x16B\
+\x83\x12\x1b\x8b\x99\x18\x0a\x8b\x99Q~mf\x9ey3\
+j\xdex\xbd7\xd2d\xabl\xa7(\xb1\xf1k\xc1_\
+\xc0VY+E\xa4d\xa7\xac\x89\x0dz\xce\x9bQ#\
+\x99s;\xf7|\xee\xf7\xdes\xba\xf7\x5cpD\xd3\x8a\
+fV\xfaA\xcbd\x8dp(\xe0\x9b\x99\x9d\xf3\xb9\x9e\
+\xa8\xa2\x85\x1a:\xf1\xc6\x14S\x9f\x8c\x8cF)k\xef\
+\xb7T\xd8\xf1\xba\xdb\xaeU\xfe\xdc\xbfV\xb7\x980\x15\
+\xa8\xa8\x16\x1eVt#+<&<\xb1\x9a\xd5m\xde\
+\x12nRR\xb1E\xe1\x13\xe1.C.(|c\xeb\
+\xf1\x22?\xdb\x9c,\xf2\xa7\xcdF4\x1c\x04G\x83\xb0\
+/\xf9\x8b\xe3\xbfXI\x19\x9a\xb0\xbc\x9c6-\xbd\xa2\
+\xfc\xdc\xc7~\x89;\x91\x99\x8eHl\x15\xf7b\x12&\
+D\x00\x1f\xe3\x8c\x10d\x80^\x86d\x1e\xa0\x9b>z\
+dE\x99|\x7f!\x7f\x8ae\xc9Ud\xd6\xc9a\xb0\
+D\x92\x14Y\xbaD]\x91\xea\x09\x89\xaa\xe8\x09\x19i\
+rv\xff\xff\xf6\xd5T\xfb\xfb\x8a\xd5\xdd\x01\xa8z\xb4\
+\xac\xd7vpm\xc2W\xde\xb2>\x0e,\xeb\xeb\x10\x9c\
+\x0fp\x9e)\xe5/\xef\xc3\xe0\x9b\xe8\xf9\x92\xd6\xb6\x07\
+\x9eu8\xbd(i\xf1m8\xdb\x80\xe6{=f\xc4\
+\x0a\x92S\xdc\xa1\xaa\xf0r\x0c\xf5\xb3\xd0x\x05\xb5\xf3\
+\xc5\x9e\xfd\xecst\x07\xd15\xf9\xaaK\xd8\xd9\x85\x0e\
+9\xefY\xf8\x06\x8e\xfdg\xf8\xfd\x8a\x18\x97\x00\x00\x00\
+\x09pHYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\
+\x9c\x18\x00\x00\x00rIDAT\x18\x95m\xcf1\x0a\
+\xc2P\x14D\xd1\xe8\x02\xb4W\x08\xd6Ia\x99JC\
+t\x15\x82\xabI6(\xee@\x04\xdb\xa8\x95Xx,\
+\xf2\x09\xe1\xf3\x07\xa6\x9a\xfb\xe0\xbe\x0c\x1b\xb4Xdq\
+p0\xe4\x82U\x0a8\xe3\x8b\x1b\x8a\x14p\xc4\x1b=\
+v)`\x8b\x07>\xa8\xe6\xd1\xfe\x0b\x9d\x85\x8eW\x0d\
+^x\xa2\x9e\x0e\xa7 tG9\x1d\xf6\xe1\x95+\xd6\
+\xb1D\x8e\x0e\xcbX\xf0\x0fR\x8ay\x18\xdc\xe2\x02p\
+\x00\x00\x00\x00IEND\xaeB`\x82\
+\x00\x00\x00\xa6\
+\x89\
+PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
+\x00\x00\x06\x00\x00\x00\x09\x08\x04\x00\x00\x00\xbb\x93\x95\x16\
+\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\
+\x02bKGD\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09p\
+HYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
+\x00\x00\x00\x07tIME\x07\xdc\x08\x17\x14\x1d\x00\xb0\
+\xd55\xa3\x00\x00\x00*IDAT\x08\xd7c`\xc0\
+\x06\xfe\x9fg``B0\xa1\x1c\x08\x93\x81\x81\x09\xc1\
+d``b``4D\xe2 s\x19\x90\x8d@\x02\
+\x00d@\x09u\x86\xb3\xad\x9c\x00\x00\x00\x00IEN\
+D\xaeB`\x82\
+\x00\x00\x00\xa5\
+\x89\
+PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
+\x00\x00\x09\x00\x00\x00\x06\x08\x04\x00\x00\x00\xbb\xce|N\
+\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\
+\x02bKGD\x00\x9cS4\xfc]\x00\x00\x00\x09p\
+HYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
+\x00\x00\x00\x07tIME\x07\xdc\x08\x17\x0b\x02\x04m\
+\x98\x1bi\x00\x00\x00)IDAT\x08\xd7c`\xc0\
+\x00\x8c\x0c\x0c\xff\xcf\xa3\x08\x18220 \x0b2\x1a\
+200B\x98\x10AFC\x14\x13P\xb5\xa3\x01\x00\
+\xd6\x10\x07\xd2/H\xdfJ\x00\x00\x00\x00IEND\
+\xaeB`\x82\
+\x00\x00\x00\xa0\
+\x89\
+PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
+\x00\x00\x06\x00\x00\x00\x09\x08\x04\x00\x00\x00\xbb\x93\x95\x16\
+\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\
+\x02bKGD\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09p\
+HYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
+\x00\x00\x00\x07tIME\x07\xdc\x08\x17\x14\x1c\x1f$\
+\xc6\x09\x17\x00\x00\x00$IDAT\x08\xd7c`@\
+\x05\xff\xcf\xc3XL\xc8\x5c&dY&d\xc5p\x0e\
+\xa3!\x9c\xc3h\x88a\x1a\x0a\x00\x00m\x84\x09u7\
+\x9e\xd9#\x00\x00\x00\x00IEND\xaeB`\x82\
+\x00\x00\x070\
+\x89\
+PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
+\x00\x00\x0a\x00\x00\x00\x07\x08\x06\x00\x00\x001\xac\xdcc\
+\x00\x00\x04\xb0iTXtXML:com.\
+adobe.xmp\x00\x00\x00\x00\x00\
+xpacket begin=\x22\xef\
+\xbb\xbf\x22 id=\x22W5M0MpCe\
+hiHzreSzNTczkc9d\
+\x22?>\x0a\x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a\x0aH\x8b[^\x00\x00\x01\x83\
+iCCPsRGB IEC6196\
+6-2.1\x00\x00(\x91u\x91\xcf+DQ\x14\
+\xc7?fh\xfc\x18\x8dba1e\x12\x16B\x83\x12\
+\x1b\x8b\x99\x18\x0a\x8b\x99Q~mf\x9ey3j\xde\
+x\xbd7\xd2d\xabl\xa7(\xb1\xf1k\xc1_\xc0V\
+Y+E\xa4d\xa7\xac\x89\x0dz\xce\x9bQ#\x99s\
+;\xf7|\xee\xf7\xdes\xba\xf7\x5cpD\xd3\x8afV\
+\xfaA\xcbd\x8dp(\xe0\x9b\x99\x9d\xf3\xb9\x9e\xa8\xa2\
+\x85\x1a:\xf1\xc6\x14S\x9f\x8c\x8cF)k\xef\xb7T\
+\xd8\xf1\xba\xdb\xaeU\xfe\xdc\xbfV\xb7\x980\x15\xa8\xa8\
+\x16\x1eVt#+<&<\xb1\x9a\xd5m\xde\x12n\
+RR\xb1E\xe1\x13\xe1.C.(|c\xeb\xf1\x22\
+?\xdb\x9c,\xf2\xa7\xcdF4\x1c\x04G\x83\xb0/\xf9\
+\x8b\xe3\xbfXI\x19\x9a\xb0\xbc\x9c6-\xbd\xa2\xfc\xdc\
+\xc7~\x89;\x91\x99\x8eHl\x15\xf7b\x12&D\x00\
+\x1f\xe3\x8c\x10d\x80^\x86d\x1e\xa0\x9b>zdE\
+\x99|\x7f!\x7f\x8ae\xc9Ud\xd6\xc9a\xb0D\x92\
+\x14Y\xbaD]\x91\xea\x09\x89\xaa\xe8\x09\x19irv\
+\xff\xff\xf6\xd5T\xfb\xfb\x8a\xd5\xdd\x01\xa8z\xb4\xac\xd7\
+vpm\xc2W\xde\xb2>\x0e,\xeb\xeb\x10\x9c\x0fp\
+\x9e)\xe5/\xef\xc3\xe0\x9b\xe8\xf9\x92\xd6\xb6\x07\x9eu\
+8\xbd(i\xf1m8\xdb\x80\xe6{=f\xc4\x0a\x92\
+S\xdc\xa1\xaa\xf0r\x0c\xf5\xb3\xd0x\x05\xb5\xf3\xc5\x9e\
+\xfd\xecst\x07\xd15\xf9\xaaK\xd8\xd9\x85\x0e9\xef\
+Y\xf8\x06\x8e\xfdg\xf8\xfd\x8a\x18\x97\x00\x00\x00\x09p\
+HYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
+\x00\x00\x00\x97IDAT\x18\x95m\xcf\xb1j\x02A\
+\x14\x85\xe1o\xb7\xb6\xd0'H=Vi\x03\xb1\xb4H\
+;l\xa5\xf19\xf6Y\x02VB\xbaa\x0a\x0b;\x1b\
+\x1bkA\x18\x02)m\xe3\xbe\x82\xcd\x06\x16\xd9\xdb\xdd\
+\x9f\xff\x5c\xee\xa9b*\x13Ls\x13nF&\xa6\xf2\
+\x82\xaeF\x8b\xdf\x98\xca\xfb\x88\xb4\xc0\x0f\xda\x1a[t\
+\xd8\xc7T\xc2@\x9ac\x8f?|U=|\xc5\x09w\
+\xbc\xa1\xc2\x193,r\x13.\xd5\xe0\xc2\x12\x07\x5cQ\
+#\xe0#7\xe1\xa8O\x0e\x7f\xda`\xd7\xaf\x9f\xb9\x09\
+\xdfc\x05\xff\xe5uLe\xf5\xcc\x1f\x0d3,\x83\xb6\
+\x06D\x83\x00\x00\x00\x00IEND\xaeB`\x82\
+\x00\x00\x00\xa6\
+\x89\
+PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
+\x00\x00\x09\x00\x00\x00\x06\x08\x04\x00\x00\x00\xbb\xce|N\
+\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\
+\x02bKGD\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09p\
+HYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
+\x00\x00\x00\x07tIME\x07\xdc\x08\x17\x08\x15;\xdc\
+;\x0c\x9b\x00\x00\x00*IDAT\x08\xd7c`\xc0\
+\x00\x8c\x0c\x0cs> \x0b\xa4\x08020 \x0b\xa6\
+\x08000B\x98\x10\xc1\x14\x01\x14\x13P\xb5\xa3\x01\
+\x00\xc6\xb9\x07\x90]f\x1f\x83\x00\x00\x00\x00IEN\
+D\xaeB`\x82\
+\x00\x00\x00\xa0\
+\x89\
+PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
+\x00\x00\x06\x00\x00\x00\x09\x08\x04\x00\x00\x00\xbb\x93\x95\x16\
+\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\
+\x02bKGD\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09p\
+HYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
+\x00\x00\x00\x07tIME\x07\xdc\x08\x17\x14\x1c\x1f$\
+\xc6\x09\x17\x00\x00\x00$IDAT\x08\xd7c`@\
+\x05\xff\xcf\xc3XL\xc8\x5c&dY&d\xc5p\x0e\
+\xa3!\x9c\xc3h\x88a\x1a\x0a\x00\x00m\x84\x09u7\
+\x9e\xd9#\x00\x00\x00\x00IEND\xaeB`\x82\
+\x00\x00\x00\xa6\
+\x89\
+PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
+\x00\x00\x09\x00\x00\x00\x06\x08\x04\x00\x00\x00\xbb\xce|N\
+\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\
+\x02bKGD\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09p\
+HYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
+\x00\x00\x00\x07tIME\x07\xdc\x08\x17\x08\x15;\xdc\
+;\x0c\x9b\x00\x00\x00*IDAT\x08\xd7c`\xc0\
+\x00\x8c\x0c\x0cs> \x0b\xa4\x08020 \x0b\xa6\
+\x08000B\x98\x10\xc1\x14\x01\x14\x13P\xb5\xa3\x01\
+\x00\xc6\xb9\x07\x90]f\x1f\x83\x00\x00\x00\x00IEN\
+D\xaeB`\x82\
+"
+
+qt_resource_name = b"\
+\x00\x08\
+\x06\xc5\x8e\xa5\
+\x00o\
+\x00p\x00e\x00n\x00p\x00y\x00p\x00e\
+\x00\x06\
+\x07\x03}\xc3\
+\x00i\
+\x00m\x00a\x00g\x00e\x00s\
+\x00\x15\
+\x0f\xf3\xc0\x07\
+\x00u\
+\x00p\x00_\x00a\x00r\x00r\x00o\x00w\x00_\x00d\x00i\x00s\x00a\x00b\x00l\x00e\x00d\
+\x00.\x00p\x00n\x00g\
+\x00\x12\
+\x01.\x03'\
+\x00c\
+\x00o\x00m\x00b\x00o\x00b\x00o\x00x\x00_\x00a\x00r\x00r\x00o\x00w\x00.\x00p\x00n\
+\x00g\
+\x00\x0e\
+\x04\xa2\xfc\xa7\
+\x00d\
+\x00o\x00w\x00n\x00_\x00a\x00r\x00r\x00o\x00w\x00.\x00p\x00n\x00g\
+\x00\x1b\
+\x03Z2'\
+\x00c\
+\x00o\x00m\x00b\x00o\x00b\x00o\x00x\x00_\x00a\x00r\x00r\x00o\x00w\x00_\x00d\x00i\
+\x00s\x00a\x00b\x00l\x00e\x00d\x00.\x00p\x00n\x00g\
+\x00\x18\
+\x03\x8e\xdeg\
+\x00r\
+\x00i\x00g\x00h\x00t\x00_\x00a\x00r\x00r\x00o\x00w\x00_\x00d\x00i\x00s\x00a\x00b\
+\x00l\x00e\x00d\x00.\x00p\x00n\x00g\
+\x00\x11\
+\x00\xb8\x8c\x07\
+\x00l\
+\x00e\x00f\x00t\x00_\x00a\x00r\x00r\x00o\x00w\x00_\x00o\x00n\x00.\x00p\x00n\x00g\
+\
+\x00\x0f\
+\x01s\x8b\x07\
+\x00u\
+\x00p\x00_\x00a\x00r\x00r\x00o\x00w\x00_\x00o\x00n\x00.\x00p\x00n\x00g\
+\x00\x0c\
+\x06\xe6\xe6g\
+\x00u\
+\x00p\x00_\x00a\x00r\x00r\x00o\x00w\x00.\x00p\x00n\x00g\
+\x00\x0f\
+\x06S%\xa7\
+\x00b\
+\x00r\x00a\x00n\x00c\x00h\x00_\x00o\x00p\x00e\x00n\x00.\x00p\x00n\x00g\
+\x00\x17\
+\x0ce\xce\x07\
+\x00l\
+\x00e\x00f\x00t\x00_\x00a\x00r\x00r\x00o\x00w\x00_\x00d\x00i\x00s\x00a\x00b\x00l\
+\x00e\x00d\x00.\x00p\x00n\x00g\
+\x00\x14\
+\x04^-\xa7\
+\x00b\
+\x00r\x00a\x00n\x00c\x00h\x00_\x00c\x00l\x00o\x00s\x00e\x00d\x00_\x00o\x00n\x00.\
+\x00p\x00n\x00g\
+\x00\x11\
+\x0b\xda0\xa7\
+\x00b\
+\x00r\x00a\x00n\x00c\x00h\x00_\x00c\x00l\x00o\x00s\x00e\x00d\x00.\x00p\x00n\x00g\
+\
+\x00\x0e\
+\x0e\xde\xfa\xc7\
+\x00l\
+\x00e\x00f\x00t\x00_\x00a\x00r\x00r\x00o\x00w\x00.\x00p\x00n\x00g\
+\x00\x11\
+\x01\x1f\xc3\x87\
+\x00d\
+\x00o\x00w\x00n\x00_\x00a\x00r\x00r\x00o\x00w\x00_\x00o\x00n\x00.\x00p\x00n\x00g\
+\
+\x00\x0f\
+\x02\x9f\x05\x87\
+\x00r\
+\x00i\x00g\x00h\x00t\x00_\x00a\x00r\x00r\x00o\x00w\x00.\x00p\x00n\x00g\
+\x00\x12\
+\x05\x8f\x9d\x07\
+\x00b\
+\x00r\x00a\x00n\x00c\x00h\x00_\x00o\x00p\x00e\x00n\x00_\x00o\x00n\x00.\x00p\x00n\
+\x00g\
+\x00\x17\
+\x0c\xabQ\x07\
+\x00d\
+\x00o\x00w\x00n\x00_\x00a\x00r\x00r\x00o\x00w\x00_\x00d\x00i\x00s\x00a\x00b\x00l\
+\x00e\x00d\x00.\x00p\x00n\x00g\
+\x00\x12\
+\x03\x8d\x04G\
+\x00r\
+\x00i\x00g\x00h\x00t\x00_\x00a\x00r\x00r\x00o\x00w\x00_\x00o\x00n\x00.\x00p\x00n\
+\x00g\
+\x00\x15\
+\x03'rg\
+\x00c\
+\x00o\x00m\x00b\x00o\x00b\x00o\x00x\x00_\x00a\x00r\x00r\x00o\x00w\x00_\x00o\x00n\
+\x00.\x00p\x00n\x00g\
+"
+
+qt_resource_struct = b"\
+\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
+\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\
+\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x00\x16\x00\x02\x00\x00\x00\x13\x00\x00\x00\x03\
+\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x01\x16\x00\x00\x00\x00\x00\x01\x00\x00\x03C\
+\x00\x00\x01vA\x9d\xa25\
+\x00\x00\x02P\x00\x00\x00\x00\x00\x01\x00\x00\x1d!\
+\x00\x00\x01vA\x9d\xa25\
+\x00\x00\x00X\x00\x00\x00\x00\x00\x01\x00\x00\x00\xa3\
+\x00\x00\x01y\xb4r\xcc\x9c\
+\x00\x00\x01>\x00\x00\x00\x00\x00\x01\x00\x00\x03\xed\
+\x00\x00\x01vA\x9d\xa29\
+\x00\x00\x02x\x00\x00\x00\x00\x00\x01\x00\x00\x1d\xca\
+\x00\x00\x01vA\x9d\xa27\
+\x00\x00\x03$\x00\x00\x00\x00\x00\x01\x00\x00&\xf0\
+\x00\x00\x01y\xb4r\xcc\x9c\
+\x00\x00\x00\xa4\x00\x00\x00\x00\x00\x01\x00\x00\x01\xf6\
+\x00\x00\x01y\xb4r\xcc\x9c\
+\x00\x00\x02\xfa\x00\x00\x00\x00\x00\x01\x00\x00&L\
+\x00\x00\x01vA\x9d\xa27\
+\x00\x00\x00\xe0\x00\x00\x00\x00\x00\x01\x00\x00\x02\x9f\
+\x00\x00\x01vA\x9d\xa27\
+\x00\x00\x01\xd8\x00\x00\x00\x00\x00\x01\x00\x00\x0c\xe5\
+\x00\x00\x01y\xc2\x05+`\
+\x00\x00\x00\x82\x00\x00\x00\x00\x00\x01\x00\x00\x01M\
+\x00\x00\x01vA\x9d\xa25\
+\x00\x00\x02\x9c\x00\x00\x00\x00\x00\x01\x00\x00\x1en\
+\x00\x00\x01y\xc1\xfc\x16\x91\
+\x00\x00\x01\x80\x00\x00\x00\x00\x00\x01\x00\x00\x051\
+\x00\x00\x01y\xc1\xf9Kx\
+\x00\x00\x01b\x00\x00\x00\x00\x00\x01\x00\x00\x04\x8f\
+\x00\x00\x01vA\x9d\xa29\
+\x00\x00\x02\x06\x00\x00\x00\x00\x00\x01\x00\x00\x14\xc6\
+\x00\x00\x01y\xc2\x05\x91*\
+\x00\x00\x01\xa4\x00\x00\x00\x00\x00\x01\x00\x00\x0c;\
+\x00\x00\x01vA\x9d\xa25\
+\x00\x00\x02\xc6\x00\x00\x00\x00\x00\x01\x00\x00%\xa2\
+\x00\x00\x01vA\x9d\xa25\
+\x00\x00\x02.\x00\x00\x00\x00\x00\x01\x00\x00\x1cw\
+\x00\x00\x01vA\x9d\xa25\
+\x00\x00\x00(\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
+\x00\x00\x01vA\x9d\xa29\
+"
+
+
+def qInitResources():
+ QtCore.qRegisterResourceData(
+ 0x03, qt_resource_struct, qt_resource_name, qt_resource_data
+ )
+
+
+def qCleanupResources():
+ QtCore.qUnregisterResourceData(
+ 0x03, qt_resource_struct, qt_resource_name, qt_resource_data
+ )
diff --git a/openpype/tools/project_manager/project_manager/style/qrc_resources.py b/openpype/style/qrc_resources.py
similarity index 100%
rename from openpype/tools/project_manager/project_manager/style/qrc_resources.py
rename to openpype/style/qrc_resources.py
diff --git a/openpype/style/resources.qrc b/openpype/style/resources.qrc
new file mode 100644
index 0000000000..a583d9458e
--- /dev/null
+++ b/openpype/style/resources.qrc
@@ -0,0 +1,23 @@
+
+
+ images/combobox_arrow.png
+ images/combobox_arrow_disabled.png
+ images/branch_closed.png
+ images/branch_closed_on.png
+ images/branch_open.png
+ images/branch_open_on.png
+ images/combobox_arrow_on.png
+ images/down_arrow.png
+ images/down_arrow_disabled.png
+ images/down_arrow_on.png
+ images/left_arrow.png
+ images/left_arrow_disabled.png
+ images/left_arrow_on.png
+ images/right_arrow.png
+ images/right_arrow_disabled.png
+ images/right_arrow_on.png
+ images/up_arrow.png
+ images/up_arrow_disabled.png
+ images/up_arrow_on.png
+
+
diff --git a/openpype/style/style.css b/openpype/style/style.css
new file mode 100644
index 0000000000..78052a9fdd
--- /dev/null
+++ b/openpype/style/style.css
@@ -0,0 +1,534 @@
+/*
+Enabled vs Disabled logic in most of stylesheets
+
+- global font color
+ Enabled - should be same globalle except placeholders
+ Disabled - font color is greyed out
+
+- global active/hover
+ Enabled - color motive of borders and bg color
+ - combobox, slider, views, buttons, checkbox, radiobox, inputs
+
+- QLineEdit, QTextEdit, QPlainTextEdit, QAbstractSpinBox
+ Enabled - bg has lighter or darked color
+ Disabled - bg has same color as background
+
+- QComboBox, QPushButton, QToolButton
+ Enabled - slightly lighter color
+ Disabled - even lighter color
+*/
+
+* {
+ font-size: 9pt;
+ font-family: "Spartan";
+ font-weight: 450;
+}
+
+QWidget {
+ color: {color:font};
+ background: {color:bg};
+ border-radius: 0px;
+}
+
+QWidget:disabled {
+ color: {color:font-disabled};
+}
+
+/* Inputs */
+QAbstractSpinBox, QLineEdit, QPlainTextEdit, QTextEdit {
+ border: 1px solid {color:border};
+ border-radius: 0.3em;
+ background: {color:bg-inputs};
+ padding: 0.1em;
+}
+
+QAbstractSpinBox:disabled, QLineEdit:disabled, QPlainTextEdit:disabled, QTextEdit:disabled {
+ background: {color:bg-inputs-disabled};
+}
+QAbstractSpinBox:hover, QLineEdit:hover, QPlainTextEdit:hover, QTextEdit:hover{
+ border-color: {color:border-hover};
+}
+QAbstractSpinBox:focus, QLineEdit:focus, QPlainTextEdit:focus, QTextEdit:focus{
+ border-color: {color:border-focus};
+}
+
+/* Buttons */
+QPushButton {
+ text-align:center center;
+ border: 0px solid {color:border};
+ border-radius: 0.2em;
+ padding: 3px 5px 3px 5px;
+ background: {color:bg-buttons};
+}
+
+QPushButton:hover {
+ background: {color:bg-button-hover};
+ border-color: {color:border-hover};
+ color: {color:font-hover};
+}
+QPushButton:pressed {
+ border-color: {color:border-focus};
+}
+QPushButton:disabled {
+ background: {color:bg-buttons-disabled};
+}
+
+QToolButton {
+ border: none;
+ background: transparent;
+ border-radius: 0.2em;
+ padding: 2px;
+}
+
+QToolButton:hover {
+ background: #333840;
+ border-color: {color:border-hover};
+}
+
+QToolButton:disabled {
+ background: {color:bg-buttons-disabled};
+}
+
+/* QMenu */
+QMenu {
+ border: 1px solid #555555;
+ background: {color:bg-inputs};
+}
+
+QMenu::icon {
+ padding-left: 7px;
+}
+
+QMenu::item {
+ padding: 6px 25px 6px 10px;
+}
+
+QMenu::item:selected {
+ background: {color:bg-view-hover};
+}
+
+QMenu::item:selected:hover {
+ background: {color:bg-view-hover};
+}
+
+QMenu::right-arrow {
+ min-width: 10px;
+}
+QMenu::separator {
+ background: {color:bg-menu-separator};
+ height: 2px;
+ margin-right: 5px;
+}
+
+/* Combobox */
+QComboBox {
+ border: 1px solid {color:border};
+ border-radius: 3px;
+ padding: 1px 3px 1px 3px;
+ background: {color:bg-inputs};
+}
+QComboBox:hover {
+ border-color: {color:border-hover};
+}
+QComboBox:disabled {
+ background: {color:bg-inputs-disabled};
+}
+
+/* QComboBox must have explicitly set Styled delegate! */
+QComboBox QAbstractItemView {
+ border: 1px solid {color:border};
+ background: {color:bg-inputs};
+ outline: none;
+}
+
+QComboBox QAbstractItemView::item:selected {
+ background: {color:bg-view-hover};
+ color: {color:font};
+ padding-left: 0px;
+}
+
+QComboBox QAbstractItemView::item:selected:hover {
+ background: {color:bg-view-hover};
+}
+
+QComboBox::drop-down {
+ subcontrol-origin: padding;
+ subcontrol-position: center right;
+ width: 15px;
+ border-style: none;
+ border-left-style: solid;
+ border-left-color: {color:border};
+ border-left-width: 1px;
+}
+QComboBox::down-arrow, QComboBox::down-arrow:on, QComboBox::down-arrow:hover, QComboBox::down-arrow:focus
+{
+ image: url(:/openpype/images/combobox_arrow.png);
+}
+
+/* SLider */
+QSlider::groove {
+ border: 1px solid #464b54;
+ border-radius: 0.3em;
+ background: {color:bg-inputs};
+}
+QSlider::groove:horizontal {
+ height: 8px;
+}
+
+QSlider::groove:vertical {
+ width: 8px;
+}
+
+QSlider::groove:hover {
+ border-color: {color:border-hover};
+}
+QSlider::groove:disabled {
+ background: {color:bg-inputs-disabled};
+}
+QSlider::groove:focus {
+ border-color: {color:border-focus};
+}
+QSlider::handle {
+ background: qlineargradient(
+ x1: 0, y1: 0.5,
+ x2: 1, y2: 0.5,
+ stop: 0 {palette:blue-base},
+ stop: 1 {palette:green-base}
+ );
+ border: 1px solid #5c5c5c;
+ width: 10px;
+ height: 10px;
+
+ border-radius: 5px;
+}
+QSlider::handle:horizontal {
+ margin: -2px 0;
+}
+QSlider::handle:vertical {
+ margin: 0 -2px;
+}
+
+QSlider::handle:disabled {
+ background: qlineargradient(
+ x1:0, y1:0,
+ x2:1, y2:1,
+ stop:0 {color:bg-buttons},
+ stop:1 {color:bg-buttons-disabled}
+ );
+}
+
+/* Tab widget*/
+QTabWidget::pane {
+ border-top-style: none;
+}
+
+/* move to the right to not mess with borders of widget underneath */
+QTabWidget::tab-bar {
+ left: 2px;
+}
+
+QTabBar::tab {
+ border-top-left-radius: 4px;
+ border-top-right-radius: 4px;
+ padding: 5px;
+
+}
+
+QTabBar::tab:selected {
+ background: {color:grey-lighter};
+ /* background: qradialgradient(
+ cx:0.5, cy:0.5, radius: 2,
+ fx:0.5, fy:1,
+ stop:0.3 {color:bg}, stop:1 white
+ ) */
+ /* background: qlineargradient(
+ x1: 0, y1: 0, x2: 0, y2: 1,
+ stop: 0 {color:bg-inputs}, stop: 1.0 {color:bg}
+ ); */
+}
+
+QTabBar::tab:!selected {
+ /* Make it smaller*/
+ margin-top: 3px;
+ background: {color:grey-light};
+}
+
+QTabBar::tab:!selected:hover {
+ background: {color:grey-lighter};
+}
+
+QTabBar::tab:first:selected {
+ margin-left: 0;
+}
+
+QTabBar::tab:last:selected {
+ margin-right: 0;
+}
+
+QTabBar::tab:only-one {
+ margin: 0;
+}
+
+QHeaderView {
+ border: none;
+ border-radius: 2px;
+ margin: 0px;
+ padding: 0px;
+}
+
+QHeaderView::section {
+ background: {color:bg-view-header};
+ padding: 4px;
+ border-right: 1px solid {color:bg-view};
+ border-radius: 0px;
+ text-align: center;
+ color: {color:font};
+ font-weight: bold;
+}
+QHeaderView::section:first {
+ border-left: none;
+}
+QHeaderView::section:last {
+ border-right: none;
+}
+/* Views QListView QTreeView QTableView */
+QAbstractItemView {
+ border: 0px solid {color:border};
+ border-radius: 0.2em;
+ background: {color:bg-view};
+ alternate-background-color: {color:bg-view-alternate};
+}
+
+QAbstractItemView:disabled{
+ background: {color:bg-view-disabled};
+ alternate-background-color: {color:bg-view-alternate-disabled};
+}
+
+QAbstractItemView::item:hover {
+ /* color: {color:bg-view-hover}; */
+ background: {color:bg-view-hover};
+}
+
+QAbstractItemView::item:selected {
+ background: {color:bg-view-selection};
+ color: {color:font-view-selection};
+}
+
+QAbstractItemView::item:selected:active {
+ color: {color:font-view-selection};
+}
+
+/* Same as selected but give ability to easy change it */
+QAbstractItemView::item:selected:!active {
+ background: {color:bg-view-selection};
+ color: {color:font-view-selection};
+}
+
+QAbstractItemView::item:selected:hover {
+ background: {color:bg-view-selection-hover};
+}
+
+QAbstractItemView::branch:open:has-children:!has-siblings,
+QAbstractItemView::branch:open:has-children:has-siblings {
+ border-image: none;
+ image: url(:/openpype/images/branch_open.png);
+ background: {color:bg-view};
+}
+QAbstractItemView::branch:open:has-children:!has-siblings:hover,
+QAbstractItemView::branch:open:has-children:has-siblings:hover {
+ border-image: none;
+ image: url(:/openpype/images//branch_open_on.png);
+ /* background: {color:bg-view-hover}; */
+}
+
+QAbstractItemView::branch:has-children:!has-siblings:closed,
+QAbstractItemView::branch:closed:has-children:has-siblings {
+ border-image: none;
+ image: url(:/openpype/images//branch_closed.png);
+ background: {color:bg-view};
+}
+QAbstractItemView::branch:has-children:!has-siblings:closed:hover,
+QAbstractItemView::branch:closed:has-children:has-siblings:hover {
+ border-image: none;
+ image: url(:/openpype/images//branch_closed_on.png);
+ /* background: {color:bg-view-hover}; */
+}
+
+/* Progress bar */
+QProgressBar {
+ border: 1px solid {color:border};
+ font-weight: bold;
+ text-align: center;
+}
+
+QProgressBar:horizontal {
+ height: 20px;
+}
+QProgressBar:vertical {
+ width: 20px;
+}
+
+QProgressBar::chunk {
+ background: qlineargradient(
+ x1: 0, y1: 0.5,
+ x2: 1, y2: 0.5,
+ stop: 0 {palette:blue-base},
+ stop: 1 {palette:green-base}
+ );
+}
+
+/* Scroll bars */
+QScrollBar {
+ background: {color:bg-inputs};
+ border-radius: 4px;
+ border: 1px transparent {color:bg-inputs};
+}
+
+QScrollBar:horizontal {
+ height: 15px;
+ margin: 3px 3px 3px 6px;
+}
+
+QScrollBar:vertical {
+ width: 15px;
+ margin: 6px 3px 3px 3px;
+}
+
+QScrollBar::handle {
+ background: {color:bg-scroll-handle};
+ border-radius: 4px;
+}
+
+QScrollBar::handle:horizontal {
+ min-width: 5px;
+}
+
+QScrollBar::handle:vertical {
+ min-height: 5px;
+}
+
+QScrollBar::add-line:horizontal {
+ margin: 0px 3px 0px 3px;
+ width: 0px;
+ height: 0px;
+ subcontrol-position: right;
+ subcontrol-origin: margin;
+}
+
+QScrollBar::sub-line:horizontal {
+ margin: 0px 3px 0px 3px;
+ height: 0px;
+ width: 0px;
+ subcontrol-position: left;
+ subcontrol-origin: margin;
+}
+
+QScrollBar::add-line:horizontal:hover,QScrollBar::add-line:horizontal:on {
+ height: 0px;
+ width: 0px;
+ subcontrol-position: right;
+ subcontrol-origin: margin;
+}
+
+QScrollBar::sub-line:horizontal:hover, QScrollBar::sub-line:horizontal:on {
+ height: 0px;
+ width: 0px;
+ subcontrol-position: left;
+ subcontrol-origin: margin;
+}
+
+QScrollBar::up-arrow:horizontal, QScrollBar::down-arrow:horizontal {
+ background: none;
+}
+
+QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal {
+ background: none;
+}
+
+QScrollBar::sub-line:vertical {
+ margin: 3px 0px 3px 0px;
+ height: 0px;
+ width: 0px;
+ subcontrol-position: top;
+ subcontrol-origin: margin;
+}
+
+QScrollBar::add-line:vertical {
+ margin: 3px 0px 3px 0px;
+ height: 0px;
+ width: 0px;
+ subcontrol-position: bottom;
+ subcontrol-origin: margin;
+}
+
+QScrollBar::sub-line:vertical:hover,QScrollBar::sub-line:vertical:on {
+ subcontrol-position: top;
+ subcontrol-origin: margin;
+}
+
+
+QScrollBar::add-line:vertical:hover, QScrollBar::add-line:vertical:on {
+ subcontrol-position: bottom;
+ subcontrol-origin: margin;
+}
+
+QScrollBar::up-arrow:vertical, QScrollBar::down-arrow:vertical {
+ background: none;
+}
+
+
+QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical {
+ background: none;
+}
+
+#IconBtn {}
+
+/* Project Manager stylesheets */
+#HierarchyView::item {
+ padding-top: 3px;
+ padding-bottom: 3px;
+ padding-right: 3px;
+}
+
+#TypeEditor, #ToolEditor, #NameEditor, #NumberEditor {
+ background: transparent;
+ border-radius: 0.3em;
+}
+
+#TypeEditor:focus, #ToolEditor:focus, #NameEditor:focus, #NumberEditor:focus {
+ background: {color:bg-inputs};
+}
+
+#CompleterView {
+ border: 1px solid {color:border};
+ background: {color:bg-inputs};
+ outline: none;
+}
+
+#CompleterView::item {
+ padding: 2px 4px 2px 4px;
+ border-left: 3px solid {color:bg-view};
+}
+
+#CompleterView::item:hover {
+ border-left-color: {palette:blue-base};
+ background: {color:bg-view-selection};
+ color: {color:font};
+}
+
+/* Launcher specific stylesheets */
+#IconView[mode="icon"] {
+ font-size: 8pt;
+ border: 0px;
+ padding: 0px;
+ margin: 0px;
+}
+
+#IconView[mode="icon"]::item {
+ margin-top: 6px;
+ border: 0px;
+}
+
+#IconView[mode="icon"]::icon {
+ top: 3px;
+}
diff --git a/openpype/tools/project_manager/project_manager/style/__init__.py b/openpype/tools/project_manager/project_manager/style.py
similarity index 70%
rename from openpype/tools/project_manager/project_manager/style/__init__.py
rename to openpype/tools/project_manager/project_manager/style.py
index b686967ddd..17e269c1f6 100644
--- a/openpype/tools/project_manager/project_manager/style/__init__.py
+++ b/openpype/tools/project_manager/project_manager/style.py
@@ -1,11 +1,9 @@
-import os
-from openpype import resources
from avalon.vendor import qtawesome
class ResourceCache:
colors = {
- "standard": "#333333",
+ "standard": "#bfccd6",
"new": "#2d9a4c",
"warning": "#c83232"
}
@@ -68,31 +66,3 @@ class ResourceCache:
@classmethod
def get_color(cls, color_name):
return cls.colors[color_name]
-
- @classmethod
- def style_fill_data(cls):
- output = {}
- for color_name, color_value in cls.colors.items():
- key = "color:{}".format(color_name)
- output[key] = color_value
- return output
-
-
-def load_stylesheet():
- from . import qrc_resources
-
- qrc_resources.qInitResources()
-
- current_dir = os.path.dirname(os.path.abspath(__file__))
- style_path = os.path.join(current_dir, "style.css")
- with open(style_path, "r") as style_file:
- stylesheet = style_file.read()
-
- for key, value in ResourceCache.style_fill_data().items():
- replacement_key = "{" + key + "}"
- stylesheet = stylesheet.replace(replacement_key, value)
- return stylesheet
-
-
-def app_icon_path():
- return resources.pype_icon_filepath()
diff --git a/openpype/tools/project_manager/project_manager/style/pyqt5_resources.py b/openpype/tools/project_manager/project_manager/style/pyqt5_resources.py
deleted file mode 100644
index 836934019d..0000000000
--- a/openpype/tools/project_manager/project_manager/style/pyqt5_resources.py
+++ /dev/null
@@ -1,105 +0,0 @@
-# -*- coding: utf-8 -*-
-
-# Resource object code
-#
-# Created by: The Resource Compiler for PyQt5 (Qt v5.15.2)
-#
-# WARNING! All changes made in this file will be lost!
-
-from PyQt5 import QtCore
-
-
-qt_resource_data = b"\
-\x00\x00\x00\xa5\
-\x89\
-\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
-\x00\x00\x09\x00\x00\x00\x06\x08\x04\x00\x00\x00\xbb\xce\x7c\x4e\
-\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
-\x02\x62\x4b\x47\x44\x00\x9c\x53\x34\xfc\x5d\x00\x00\x00\x09\x70\
-\x48\x59\x73\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
-\x00\x00\x00\x07\x74\x49\x4d\x45\x07\xdc\x08\x17\x0b\x02\x04\x6d\
-\x98\x1b\x69\x00\x00\x00\x29\x49\x44\x41\x54\x08\xd7\x63\x60\xc0\
-\x00\x8c\x0c\x0c\xff\xcf\xa3\x08\x18\x32\x32\x30\x20\x0b\x32\x1a\
-\x32\x30\x30\x42\x98\x10\x41\x46\x43\x14\x13\x50\xb5\xa3\x01\x00\
-\xd6\x10\x07\xd2\x2f\x48\xdf\x4a\x00\x00\x00\x00\x49\x45\x4e\x44\
-\xae\x42\x60\x82\
-\x00\x00\x00\xa6\
-\x89\
-\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
-\x00\x00\x09\x00\x00\x00\x06\x08\x04\x00\x00\x00\xbb\xce\x7c\x4e\
-\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
-\x02\x62\x4b\x47\x44\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09\x70\
-\x48\x59\x73\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
-\x00\x00\x00\x07\x74\x49\x4d\x45\x07\xdc\x08\x17\x08\x15\x3b\xdc\
-\x3b\x0c\x9b\x00\x00\x00\x2a\x49\x44\x41\x54\x08\xd7\x63\x60\xc0\
-\x00\x8c\x0c\x0c\x73\x3e\x20\x0b\xa4\x08\x30\x32\x30\x20\x0b\xa6\
-\x08\x30\x30\x30\x42\x98\x10\xc1\x14\x01\x14\x13\x50\xb5\xa3\x01\
-\x00\xc6\xb9\x07\x90\x5d\x66\x1f\x83\x00\x00\x00\x00\x49\x45\x4e\
-\x44\xae\x42\x60\x82\
-"
-
-
-qt_resource_name = b"\
-\x00\x08\
-\x06\xc5\x8e\xa5\
-\x00\x6f\
-\x00\x70\x00\x65\x00\x6e\x00\x70\x00\x79\x00\x70\x00\x65\
-\x00\x06\
-\x07\x03\x7d\xc3\
-\x00\x69\
-\x00\x6d\x00\x61\x00\x67\x00\x65\x00\x73\
-\x00\x12\
-\x01\x2e\x03\x27\
-\x00\x63\
-\x00\x6f\x00\x6d\x00\x62\x00\x6f\x00\x62\x00\x6f\x00\x78\x00\x5f\x00\x61\x00\x72\x00\x72\x00\x6f\x00\x77\x00\x2e\x00\x70\x00\x6e\
-\x00\x67\
-\x00\x1b\
-\x03\x5a\x32\x27\
-\x00\x63\
-\x00\x6f\x00\x6d\x00\x62\x00\x6f\x00\x62\x00\x6f\x00\x78\x00\x5f\x00\x61\x00\x72\x00\x72\x00\x6f\x00\x77\x00\x5f\x00\x64\x00\x69\
-\x00\x73\x00\x61\x00\x62\x00\x6c\x00\x65\x00\x64\x00\x2e\x00\x70\x00\x6e\x00\x67\
-"
-
-
-qt_resource_struct_v1 = b"\
-\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
-\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\
-\x00\x00\x00\x16\x00\x02\x00\x00\x00\x02\x00\x00\x00\x03\
-\x00\x00\x00\x28\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
-\x00\x00\x00\x52\x00\x00\x00\x00\x00\x01\x00\x00\x00\xa9\
-"
-
-
-qt_resource_struct_v2 = b"\
-\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
-\x00\x00\x00\x00\x00\x00\x00\x00\
-\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\
-\x00\x00\x00\x00\x00\x00\x00\x00\
-\x00\x00\x00\x16\x00\x02\x00\x00\x00\x02\x00\x00\x00\x03\
-\x00\x00\x00\x00\x00\x00\x00\x00\
-\x00\x00\x00\x28\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
-\x00\x00\x01\x76\x41\x9d\xa2\x35\
-\x00\x00\x00\x52\x00\x00\x00\x00\x00\x01\x00\x00\x00\xa9\
-\x00\x00\x01\x76\x41\x9d\xa2\x35\
-"
-
-
-qt_version = [int(v) for v in QtCore.qVersion().split('.')]
-if qt_version < [5, 8, 0]:
- rcc_version = 1
- qt_resource_struct = qt_resource_struct_v1
-else:
- rcc_version = 2
- qt_resource_struct = qt_resource_struct_v2
-
-
-def qInitResources():
- QtCore.qRegisterResourceData(
- rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data
- )
-
-
-def qCleanupResources():
- QtCore.qUnregisterResourceData(
- rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data
- )
diff --git a/openpype/tools/project_manager/project_manager/style/pyside2_resources.py b/openpype/tools/project_manager/project_manager/style/pyside2_resources.py
deleted file mode 100644
index b73d5e334a..0000000000
--- a/openpype/tools/project_manager/project_manager/style/pyside2_resources.py
+++ /dev/null
@@ -1,84 +0,0 @@
-# Resource object code (Python 3)
-# Created by: object code
-# Created by: The Resource Compiler for Qt version 5.15.2
-# WARNING! All changes made in this file will be lost!
-
-from PySide2 import QtCore
-
-
-qt_resource_data = b"\
-\x00\x00\x00\xa5\
-\x89\
-PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
-\x00\x00\x09\x00\x00\x00\x06\x08\x04\x00\x00\x00\xbb\xce|N\
-\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\
-\x02bKGD\x00\x9cS4\xfc]\x00\x00\x00\x09p\
-HYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
-\x00\x00\x00\x07tIME\x07\xdc\x08\x17\x0b\x02\x04m\
-\x98\x1bi\x00\x00\x00)IDAT\x08\xd7c`\xc0\
-\x00\x8c\x0c\x0c\xff\xcf\xa3\x08\x18220 \x0b2\x1a\
-200B\x98\x10AFC\x14\x13P\xb5\xa3\x01\x00\
-\xd6\x10\x07\xd2/H\xdfJ\x00\x00\x00\x00IEND\
-\xaeB`\x82\
-\x00\x00\x00\xa6\
-\x89\
-PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
-\x00\x00\x09\x00\x00\x00\x06\x08\x04\x00\x00\x00\xbb\xce|N\
-\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\
-\x02bKGD\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09p\
-HYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
-\x00\x00\x00\x07tIME\x07\xdc\x08\x17\x08\x15;\xdc\
-;\x0c\x9b\x00\x00\x00*IDAT\x08\xd7c`\xc0\
-\x00\x8c\x0c\x0cs> \x0b\xa4\x08020 \x0b\xa6\
-\x08000B\x98\x10\xc1\x14\x01\x14\x13P\xb5\xa3\x01\
-\x00\xc6\xb9\x07\x90]f\x1f\x83\x00\x00\x00\x00IEN\
-D\xaeB`\x82\
-"
-
-
-qt_resource_name = b"\
-\x00\x08\
-\x06\xc5\x8e\xa5\
-\x00o\
-\x00p\x00e\x00n\x00p\x00y\x00p\x00e\
-\x00\x06\
-\x07\x03}\xc3\
-\x00i\
-\x00m\x00a\x00g\x00e\x00s\
-\x00\x12\
-\x01.\x03'\
-\x00c\
-\x00o\x00m\x00b\x00o\x00b\x00o\x00x\x00_\x00a\x00r\x00r\x00o\x00w\x00.\x00p\x00n\
-\x00g\
-\x00\x1b\
-\x03Z2'\
-\x00c\
-\x00o\x00m\x00b\x00o\x00b\x00o\x00x\x00_\x00a\x00r\x00r\x00o\x00w\x00_\x00d\x00i\
-\x00s\x00a\x00b\x00l\x00e\x00d\x00.\x00p\x00n\x00g\
-"
-
-
-qt_resource_struct = b"\
-\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
-\x00\x00\x00\x00\x00\x00\x00\x00\
-\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\
-\x00\x00\x00\x00\x00\x00\x00\x00\
-\x00\x00\x00\x16\x00\x02\x00\x00\x00\x02\x00\x00\x00\x03\
-\x00\x00\x00\x00\x00\x00\x00\x00\
-\x00\x00\x00(\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
-\x00\x00\x01vA\x9d\xa25\
-\x00\x00\x00R\x00\x00\x00\x00\x00\x01\x00\x00\x00\xa9\
-\x00\x00\x01vA\x9d\xa25\
-"
-
-
-def qInitResources():
- QtCore.qRegisterResourceData(
- 0x03, qt_resource_struct, qt_resource_name, qt_resource_data
- )
-
-
-def qCleanupResources():
- QtCore.qUnregisterResourceData(
- 0x03, qt_resource_struct, qt_resource_name, qt_resource_data
- )
diff --git a/openpype/tools/project_manager/project_manager/style/resources.qrc b/openpype/tools/project_manager/project_manager/style/resources.qrc
deleted file mode 100644
index 9281c69479..0000000000
--- a/openpype/tools/project_manager/project_manager/style/resources.qrc
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
- images/combobox_arrow.png
- images/combobox_arrow_disabled.png
-
-
diff --git a/openpype/tools/project_manager/project_manager/style/style.css b/openpype/tools/project_manager/project_manager/style/style.css
deleted file mode 100644
index 31196b7cc6..0000000000
--- a/openpype/tools/project_manager/project_manager/style/style.css
+++ /dev/null
@@ -1,21 +0,0 @@
-QTreeView::item {
- padding-top: 3px;
- padding-bottom: 3px;
- padding-right: 3px;
-}
-
-
-QTreeView::item:selected, QTreeView::item:selected:!active {
- background: rgba(0, 122, 204, 127);
- color: black;
-}
-
-#RefreshBtn {
- padding: 2px;
-}
-
-#TypeEditor, #ToolEditor, #NameEditor, #NumberEditor {
- background: transparent;
- border: 1px solid #005c99;
- border-radius: 0.3em;
-}
diff --git a/openpype/tools/project_manager/project_manager/view.py b/openpype/tools/project_manager/project_manager/view.py
index 70af11e68d..4d75af3405 100644
--- a/openpype/tools/project_manager/project_manager/view.py
+++ b/openpype/tools/project_manager/project_manager/view.py
@@ -124,6 +124,9 @@ class HierarchyView(QtWidgets.QTreeView):
def __init__(self, dbcon, source_model, parent):
super(HierarchyView, self).__init__(parent)
+
+ self.setObjectName("HierarchyView")
+
# Direct access to model
self._source_model = source_model
self._editors_mapping = {}
@@ -409,6 +412,9 @@ class HierarchyView(QtWidgets.QTreeView):
return self._source_model.add_new_task(parent_index)
+ def _add_asset_action(self):
+ self._add_asset_and_edit()
+
def _add_asset_and_edit(self, parent_index=None):
new_index = self.add_asset(parent_index)
if new_index is None:
@@ -423,6 +429,9 @@ class HierarchyView(QtWidgets.QTreeView):
# Start editing
self.edit(new_index)
+ def _add_task_action(self):
+ self._add_task_and_edit()
+
def _add_task_and_edit(self):
new_index = self.add_task()
if new_index is None:
@@ -574,14 +583,14 @@ class HierarchyView(QtWidgets.QTreeView):
if item_type in ("asset", "project"):
add_asset_action = QtWidgets.QAction("Add Asset", context_menu)
add_asset_action.triggered.connect(
- self._add_asset_and_edit
+ self._add_asset_action
)
actions.append(add_asset_action)
if item_type in ("asset", "task"):
add_task_action = QtWidgets.QAction("Add Task", context_menu)
add_task_action.triggered.connect(
- self._add_task_and_edit
+ self._add_task_action
)
actions.append(add_task_action)
diff --git a/openpype/tools/project_manager/project_manager/widgets.py b/openpype/tools/project_manager/project_manager/widgets.py
index 9c57febcf6..8c2f693f11 100644
--- a/openpype/tools/project_manager/project_manager/widgets.py
+++ b/openpype/tools/project_manager/project_manager/widgets.py
@@ -9,6 +9,7 @@ from openpype.lib import (
PROJECT_NAME_ALLOWED_SYMBOLS,
PROJECT_NAME_REGEX
)
+from openpype.style import load_stylesheet
from avalon.api import AvalonMongoDB
from Qt import QtWidgets, QtCore
@@ -44,6 +45,8 @@ class FilterComboBox(QtWidgets.QComboBox):
self.setFocusPolicy(QtCore.Qt.StrongFocus)
self.setEditable(True)
+ combobox_delegate = QtWidgets.QStyledItemDelegate(self)
+ self.setItemDelegate(combobox_delegate)
filter_proxy_model = QtCore.QSortFilterProxyModel(self)
filter_proxy_model.setFilterCaseSensitivity(QtCore.Qt.CaseInsensitive)
@@ -55,6 +58,12 @@ class FilterComboBox(QtWidgets.QComboBox):
)
self.setCompleter(completer)
+ completer_view = completer.popup()
+ completer_view.setObjectName("CompleterView")
+ delegate = QtWidgets.QStyledItemDelegate(completer_view)
+ completer_view.setItemDelegate(delegate)
+ completer_view.setStyleSheet(load_stylesheet())
+
self.lineEdit().textEdited.connect(
filter_proxy_model.setFilterFixedString
)
diff --git a/openpype/tools/project_manager/project_manager/window.py b/openpype/tools/project_manager/project_manager/window.py
index a800214517..83184f9981 100644
--- a/openpype/tools/project_manager/project_manager/window.py
+++ b/openpype/tools/project_manager/project_manager/window.py
@@ -9,7 +9,8 @@ from . import (
CreateProjectDialog
)
-from .style import load_stylesheet, ResourceCache
+from openpype.style import load_stylesheet
+from .style import ResourceCache
from openpype import resources
from avalon.api import AvalonMongoDB
@@ -34,11 +35,13 @@ class ProjectManagerWindow(QtWidgets.QWidget):
project_combobox = QtWidgets.QComboBox(project_widget)
project_combobox.setModel(project_model)
project_combobox.setRootModelIndex(QtCore.QModelIndex())
+ style_delegate = QtWidgets.QStyledItemDelegate()
+ project_combobox.setItemDelegate(style_delegate)
refresh_projects_btn = QtWidgets.QPushButton(project_widget)
refresh_projects_btn.setIcon(ResourceCache.get_icon("refresh"))
refresh_projects_btn.setToolTip("Refresh projects")
- refresh_projects_btn.setObjectName("RefreshBtn")
+ refresh_projects_btn.setObjectName("IconBtn")
create_project_btn = QtWidgets.QPushButton(
"Create project...", project_widget
@@ -65,6 +68,8 @@ class ProjectManagerWindow(QtWidgets.QWidget):
"Task",
helper_btns_widget
)
+ add_asset_btn.setObjectName("IconBtn")
+ add_task_btn.setObjectName("IconBtn")
helper_btns_layout = QtWidgets.QHBoxLayout(helper_btns_widget)
helper_btns_layout.setContentsMargins(0, 0, 0, 0)
@@ -113,14 +118,20 @@ class ProjectManagerWindow(QtWidgets.QWidget):
add_asset_btn.clicked.connect(self._on_add_asset)
add_task_btn.clicked.connect(self._on_add_task)
- self.project_model = project_model
- self.project_combobox = project_combobox
+ self._project_model = project_model
self.hierarchy_view = hierarchy_view
self.hierarchy_model = hierarchy_model
self.message_label = message_label
+ self._refresh_projects_btn = refresh_projects_btn
+ self._project_combobox = project_combobox
+ self._create_project_btn = create_project_btn
+
+ self._add_asset_btn = add_asset_btn
+ self._add_task_btn = add_task_btn
+
self.resize(1200, 600)
self.setStyleSheet(load_stylesheet())
@@ -129,25 +140,33 @@ class ProjectManagerWindow(QtWidgets.QWidget):
def _set_project(self, project_name=None):
self.hierarchy_view.set_project(project_name)
+ def showEvent(self, event):
+ super(ProjectManagerWindow, self).showEvent(event)
+ font_size = self._refresh_projects_btn.fontMetrics().height()
+ icon_size = QtCore.QSize(font_size, font_size)
+ self._refresh_projects_btn.setIconSize(icon_size)
+ self._add_asset_btn.setIconSize(icon_size)
+ self._add_task_btn.setIconSize(icon_size)
+
def refresh_projects(self, project_name=None):
if project_name is None:
- if self.project_combobox.count() > 0:
- project_name = self.project_combobox.currentText()
+ if self._project_combobox.count() > 0:
+ project_name = self._project_combobox.currentText()
- self.project_model.refresh()
+ self._project_model.refresh()
- if self.project_combobox.count() == 0:
+ if self._project_combobox.count() == 0:
return self._set_project()
if project_name:
- row = self.project_combobox.findText(project_name)
+ row = self._project_combobox.findText(project_name)
if row >= 0:
- self.project_combobox.setCurrentIndex(row)
+ self._project_combobox.setCurrentIndex(row)
- self._set_project(self.project_combobox.currentText())
+ self._set_project(self._project_combobox.currentText())
def _on_project_change(self):
- self._set_project(self.project_combobox.currentText())
+ self._set_project(self._project_combobox.currentText())
def _on_project_refresh(self):
self.refresh_projects()
diff --git a/openpype/tools/settings/settings/categories.py b/openpype/tools/settings/settings/categories.py
index 01d4babd0f..b072a7f337 100644
--- a/openpype/tools/settings/settings/categories.py
+++ b/openpype/tools/settings/settings/categories.py
@@ -73,6 +73,7 @@ class IgnoreInputChangesObj:
class SettingsCategoryWidget(QtWidgets.QWidget):
state_changed = QtCore.Signal()
saved = QtCore.Signal(QtWidgets.QWidget)
+ restart_required_trigger = QtCore.Signal()
def __init__(self, user_role, parent=None):
super(SettingsCategoryWidget, self).__init__(parent)
@@ -185,9 +186,10 @@ class SettingsCategoryWidget(QtWidgets.QWidget):
if self.user_role == "developer":
self._add_developer_ui(footer_layout)
- save_btn = QtWidgets.QPushButton("Save")
- spacer_widget = QtWidgets.QWidget()
- footer_layout.addWidget(spacer_widget, 1)
+ save_btn = QtWidgets.QPushButton("Save", footer_widget)
+ require_restart_label = QtWidgets.QLabel(footer_widget)
+ require_restart_label.setAlignment(QtCore.Qt.AlignCenter)
+ footer_layout.addWidget(require_restart_label, 1)
footer_layout.addWidget(save_btn, 0)
configurations_layout = QtWidgets.QVBoxLayout(configurations_widget)
@@ -205,6 +207,7 @@ class SettingsCategoryWidget(QtWidgets.QWidget):
save_btn.clicked.connect(self._save)
self.save_btn = save_btn
+ self.require_restart_label = require_restart_label
self.scroll_widget = scroll_widget
self.content_layout = content_layout
self.content_widget = content_widget
@@ -323,6 +326,15 @@ class SettingsCategoryWidget(QtWidgets.QWidget):
def _on_reset_start(self):
return
+ def _on_require_restart_change(self):
+ value = ""
+ if self.entity.require_restart:
+ value = (
+ "Your changes require restart of"
+ " all running OpenPype processes to take affect."
+ )
+ self.require_restart_label.setText(value)
+
def reset(self):
self.set_state(CategoryState.Working)
@@ -339,6 +351,9 @@ class SettingsCategoryWidget(QtWidgets.QWidget):
dialog = None
try:
self._create_root_entity()
+ self.entity.add_require_restart_change_callback(
+ self._on_require_restart_change
+ )
self.add_children_gui()
@@ -433,6 +448,15 @@ class SettingsCategoryWidget(QtWidgets.QWidget):
return
def _save(self):
+ # Don't trigger restart if defaults are modified
+ if (
+ self.modify_defaults_checkbox
+ and self.modify_defaults_checkbox.isChecked()
+ ):
+ require_restart = False
+ else:
+ require_restart = self.entity.require_restart
+
self.set_state(CategoryState.Working)
if self.items_are_valid():
@@ -442,6 +466,10 @@ class SettingsCategoryWidget(QtWidgets.QWidget):
self.saved.emit(self)
+ if require_restart:
+ self.restart_required_trigger.emit()
+ self.require_restart_label.setText("")
+
def _on_refresh(self):
self.reset()
diff --git a/openpype/tools/settings/settings/item_widgets.py b/openpype/tools/settings/settings/item_widgets.py
index 11ccb60ae4..b23372e9ac 100644
--- a/openpype/tools/settings/settings/item_widgets.py
+++ b/openpype/tools/settings/settings/item_widgets.py
@@ -508,6 +508,8 @@ class PathWidget(BaseWidget):
self.content_layout = QtWidgets.QGridLayout(self)
self.content_layout.setContentsMargins(0, 0, 0, 0)
self.content_layout.setSpacing(5)
+ # Add stretch to second column
+ self.content_layout.setColumnStretch(1, 1)
self.body_widget = None
self.setAttribute(QtCore.Qt.WA_TranslucentBackground)
diff --git a/openpype/tools/settings/settings/widgets.py b/openpype/tools/settings/settings/widgets.py
index 249b4e305d..b20ce5ed66 100644
--- a/openpype/tools/settings/settings/widgets.py
+++ b/openpype/tools/settings/settings/widgets.py
@@ -275,8 +275,6 @@ class UnsavedChangesDialog(QtWidgets.QDialog):
layout.addWidget(message_label)
layout.addWidget(btns_widget)
- self.state = None
-
def on_cancel_pressed(self):
self.done(0)
@@ -287,6 +285,48 @@ class UnsavedChangesDialog(QtWidgets.QDialog):
self.done(2)
+class RestartDialog(QtWidgets.QDialog):
+ message = (
+ "Your changes require restart of process to take effect."
+ " Do you want to restart now?"
+ )
+
+ def __init__(self, parent=None):
+ super(RestartDialog, self).__init__(parent)
+ message_label = QtWidgets.QLabel(self.message)
+
+ btns_widget = QtWidgets.QWidget(self)
+ btns_layout = QtWidgets.QHBoxLayout(btns_widget)
+
+ btn_restart = QtWidgets.QPushButton("Restart")
+ btn_restart.clicked.connect(self.on_restart_pressed)
+ btn_cancel = QtWidgets.QPushButton("Cancel")
+ btn_cancel.clicked.connect(self.on_cancel_pressed)
+
+ btns_layout.addStretch(1)
+ btns_layout.addWidget(btn_restart)
+ btns_layout.addWidget(btn_cancel)
+
+ layout = QtWidgets.QVBoxLayout(self)
+ layout.addWidget(message_label)
+ layout.addWidget(btns_widget)
+
+ self.btn_cancel = btn_cancel
+ self.btn_restart = btn_restart
+
+ def showEvent(self, event):
+ super(RestartDialog, self).showEvent(event)
+ btns_width = max(self.btn_cancel.width(), self.btn_restart.width())
+ self.btn_cancel.setFixedWidth(btns_width)
+ self.btn_restart.setFixedWidth(btns_width)
+
+ def on_cancel_pressed(self):
+ self.done(0)
+
+ def on_restart_pressed(self):
+ self.done(1)
+
+
class SpacerWidget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(SpacerWidget, self).__init__(parent)
diff --git a/openpype/tools/settings/settings/window.py b/openpype/tools/settings/settings/window.py
index 9b368588c3..7a6536fd78 100644
--- a/openpype/tools/settings/settings/window.py
+++ b/openpype/tools/settings/settings/window.py
@@ -4,7 +4,7 @@ from .categories import (
SystemWidget,
ProjectWidget
)
-from .widgets import ShadowWidget
+from .widgets import ShadowWidget, RestartDialog
from . import style
from openpype.tools.settings import (
@@ -14,6 +14,8 @@ from openpype.tools.settings import (
class MainWidget(QtWidgets.QWidget):
+ trigger_restart = QtCore.Signal()
+
widget_width = 1000
widget_height = 600
@@ -60,6 +62,9 @@ class MainWidget(QtWidgets.QWidget):
for tab_widget in tab_widgets:
tab_widget.saved.connect(self._on_tab_save)
tab_widget.state_changed.connect(self._on_state_change)
+ tab_widget.restart_required_trigger.connect(
+ self._on_restart_required
+ )
self.tab_widgets = tab_widgets
@@ -132,3 +137,15 @@ class MainWidget(QtWidgets.QWidget):
for tab_widget in self.tab_widgets:
tab_widget.reset()
+
+ def _on_restart_required(self):
+ # Don't show dialog if there are not registered slots for
+ # `trigger_restart` signal.
+ # - For example when settings are runnin as standalone tool
+ if self.receivers(self.trigger_restart) < 1:
+ return
+
+ dialog = RestartDialog(self)
+ result = dialog.exec_()
+ if result == 1:
+ self.trigger_restart.emit()
diff --git a/openpype/tools/tray/pype_tray.py b/openpype/tools/tray/pype_tray.py
index 534c99bd90..d9806a96fd 100644
--- a/openpype/tools/tray/pype_tray.py
+++ b/openpype/tools/tray/pype_tray.py
@@ -1,10 +1,14 @@
+import collections
import os
import sys
+import atexit
+import subprocess
import platform
from avalon import style
from Qt import QtCore, QtGui, QtWidgets
from openpype.api import Logger, resources
+from openpype.lib import get_pype_execute_args
from openpype.modules import TrayModulesManager, ITrayService
from openpype.settings.lib import get_system_settings
import openpype.version
@@ -20,7 +24,6 @@ class TrayManager:
def __init__(self, tray_widget, main_window):
self.tray_widget = tray_widget
self.main_window = main_window
-
self.pype_info_widget = None
self.log = Logger.get_logger(self.__class__.__name__)
@@ -31,6 +34,28 @@ class TrayManager:
self.errors = []
+ self.main_thread_timer = None
+ self._main_thread_callbacks = collections.deque()
+ self._execution_in_progress = None
+
+ def execute_in_main_thread(self, callback):
+ self._main_thread_callbacks.append(callback)
+
+ def _main_thread_execution(self):
+ if self._execution_in_progress:
+ return
+ self._execution_in_progress = True
+ while self._main_thread_callbacks:
+ try:
+ callback = self._main_thread_callbacks.popleft()
+ callback()
+ except:
+ self.log.warning(
+ "Failed to execute {} in main thread".format(callback),
+ exc_info=True)
+
+ self._execution_in_progress = False
+
def initialize_modules(self):
"""Add modules to tray."""
@@ -56,6 +81,14 @@ class TrayManager:
# Print time report
self.modules_manager.print_report()
+ # create timer loop to check callback functions
+ main_thread_timer = QtCore.QTimer()
+ main_thread_timer.setInterval(300)
+ main_thread_timer.timeout.connect(self._main_thread_execution)
+ main_thread_timer.start()
+
+ self.main_thread_timer = main_thread_timer
+
def show_tray_message(self, title, message, icon=None, msecs=None):
"""Show tray message.
@@ -92,6 +125,34 @@ class TrayManager:
self.tray_widget.menu.addAction(version_action)
self.tray_widget.menu.addSeparator()
+ def restart(self):
+ """Restart Tray tool.
+
+ First creates new process with same argument and close current tray.
+ """
+ args = get_pype_execute_args()
+ # Create a copy of sys.argv
+ additional_args = list(sys.argv)
+ # Check last argument from `get_pype_execute_args`
+ # - when running from code it is the same as first from sys.argv
+ if args[-1] == additional_args[0]:
+ additional_args.pop(0)
+ args.extend(additional_args)
+
+ kwargs = {}
+ if platform.system().lower() == "windows":
+ flags = (
+ subprocess.CREATE_NEW_PROCESS_GROUP
+ | subprocess.DETACHED_PROCESS
+ )
+ kwargs["creationflags"] = flags
+
+ subprocess.Popen(args, **kwargs)
+ self.exit()
+
+ def exit(self):
+ self.tray_widget.exit()
+
def on_exit(self):
self.modules_manager.on_exit()
@@ -116,6 +177,8 @@ class SystemTrayIcon(QtWidgets.QSystemTrayIcon):
super(SystemTrayIcon, self).__init__(icon, parent)
+ self._exited = False
+
# Store parent - QtWidgets.QMainWindow()
self.parent = parent
@@ -134,6 +197,8 @@ class SystemTrayIcon(QtWidgets.QSystemTrayIcon):
# Add menu to Context of SystemTrayIcon
self.setContextMenu(self.menu)
+ atexit.register(self.exit)
+
def on_systray_activated(self, reason):
# show contextMenu if left click
if reason == QtWidgets.QSystemTrayIcon.Trigger:
@@ -145,6 +210,10 @@ class SystemTrayIcon(QtWidgets.QSystemTrayIcon):
- Icon won't stay in tray after exit.
"""
+ if self._exited:
+ return
+ self._exited = True
+
self.hide()
self.tray_man.on_exit()
QtCore.QCoreApplication.exit()
diff --git a/openpype/vendor/python/common/capture_gui/vendor/__init__.py b/openpype/tools/tray_app/__init__.py
similarity index 100%
rename from openpype/vendor/python/common/capture_gui/vendor/__init__.py
rename to openpype/tools/tray_app/__init__.py
diff --git a/openpype/tools/tray_app/app.py b/openpype/tools/tray_app/app.py
new file mode 100644
index 0000000000..339e6343f8
--- /dev/null
+++ b/openpype/tools/tray_app/app.py
@@ -0,0 +1,331 @@
+import os
+import sys
+import re
+import collections
+import queue
+import websocket
+import json
+import itertools
+from datetime import datetime
+
+from avalon import style
+from openpype.modules.webserver import host_console_listener
+
+from Qt import QtWidgets, QtCore
+
+
+class ConsoleTrayApp:
+ """
+ Application showing console in Services tray for non python hosts
+ instead of cmd window.
+ """
+ callback_queue = None
+ process = None
+ webserver_client = None
+
+ MAX_LINES = 10000
+
+ sdict = {
+ r">>> ":
+ ' >>> ',
+ r"!!!(?!\sCRI|\sERR)":
+ ' !!! ',
+ r"\-\-\- ":
+ ' --- ',
+ r"\*\*\*(?!\sWRN)":
+ ' *** ',
+ r"\*\*\* WRN":
+ ' *** WRN',
+ r" \- ":
+ ' - ',
+ r"\[ ":
+ '[',
+ r"\]":
+ ']',
+ r"{":
+ '{',
+ r"}":
+ r"}",
+ r"\(":
+ '(',
+ r"\)":
+ r")",
+ r"^\.\.\. ":
+ ' ... ',
+ r"!!! ERR: ":
+ ' !!! ERR: ',
+ r"!!! CRI: ":
+ ' !!! CRI: ',
+ r"(?i)failed":
+ ' FAILED ',
+ r"(?i)error":
+ ' ERROR '
+ }
+
+ def __init__(self, host, launch_method, subprocess_args, is_host_connected,
+ parent=None):
+ self.host = host
+
+ self.initialized = False
+ self.websocket_server = None
+ self.initializing = False
+ self.tray = False
+ self.launch_method = launch_method
+ self.subprocess_args = subprocess_args
+ self.is_host_connected = is_host_connected
+ self.tray_reconnect = True
+
+ self.original_stdout_write = None
+ self.original_stderr_write = None
+ self.new_text = collections.deque()
+
+ timer = QtCore.QTimer()
+ timer.timeout.connect(self.on_timer)
+ timer.setInterval(200)
+ timer.start()
+
+ self.timer = timer
+
+ self.catch_std_outputs()
+ date_str = datetime.now().strftime("%d%m%Y%H%M%S")
+ self.host_id = "{}_{}".format(self.host, date_str)
+
+ def _connect(self):
+ """ Connect to Tray webserver to pass console output. """
+ ws = websocket.WebSocket()
+ webserver_url = os.environ.get("OPENPYPE_WEBSERVER_URL")
+
+ if not webserver_url:
+ print("Unknown webserver url, cannot connect to pass log")
+ self.tray_reconnect = False
+ return
+
+ webserver_url = webserver_url.replace("http", "ws")
+ ws.connect("{}/ws/host_listener".format(webserver_url))
+ ConsoleTrayApp.webserver_client = ws
+
+ payload = {
+ "host": self.host_id,
+ "action": host_console_listener.MsgAction.CONNECTING,
+ "text": "Integration with {}".format(str.capitalize(self.host))
+ }
+ self.tray_reconnect = False
+ self._send(payload)
+
+ def _connected(self):
+ """ Send to Tray console that host is ready - icon change. """
+ print("Host {} connected".format(self.host))
+ if not ConsoleTrayApp.webserver_client:
+ return
+
+ payload = {
+ "host": self.host_id,
+ "action": host_console_listener.MsgAction.INITIALIZED,
+ "text": "Integration with {}".format(str.capitalize(self.host))
+ }
+ self.tray_reconnect = False
+ self._send(payload)
+
+ def _close(self):
+ """ Send to Tray that host is closing - remove from Services. """
+ print("Host {} closing".format(self.host))
+ if not ConsoleTrayApp.webserver_client:
+ return
+
+ payload = {
+ "host": self.host_id,
+ "action": host_console_listener.MsgAction.CLOSE,
+ "text": "Integration with {}".format(str.capitalize(self.host))
+ }
+
+ self._send(payload)
+ self.tray_reconnect = False
+ ConsoleTrayApp.webserver_client.close()
+
+ def _send_text(self, new_text):
+ """ Send console content. """
+ if not ConsoleTrayApp.webserver_client:
+ return
+
+ if isinstance(new_text, str):
+ new_text = collections.deque(new_text.split("\n"))
+
+ payload = {
+ "host": self.host_id,
+ "action": host_console_listener.MsgAction.ADD,
+ "text": "\n".join(new_text)
+ }
+
+ self._send(payload)
+
+ def _send(self, payload):
+ """ Worker method to send to existing websocket connection. """
+ if not ConsoleTrayApp.webserver_client:
+ return
+
+ try:
+ ConsoleTrayApp.webserver_client.send(json.dumps(payload))
+ except ConnectionResetError: # Tray closed
+ ConsoleTrayApp.webserver_client = None
+ self.tray_reconnect = True
+
+ def on_timer(self):
+ """Called periodically to initialize and run function on main thread"""
+ if self.tray_reconnect:
+ self._connect() # reconnect
+
+ if ConsoleTrayApp.webserver_client and self.new_text:
+ self._send_text(self.new_text)
+ self.new_text = collections.deque()
+
+ if self.new_text: # no webserver_client, text keeps stashing
+ start = max(len(self.new_text) - self.MAX_LINES, 0)
+ self.new_text = itertools.islice(self.new_text,
+ start, self.MAX_LINES)
+
+ if not self.initialized:
+ if self.initializing:
+ host_connected = self.is_host_connected()
+ if host_connected is None: # keep trying
+ return
+ elif not host_connected:
+ text = "{} process is not alive. Exiting".format(self.host)
+ print(text)
+ self._send_text([text])
+ ConsoleTrayApp.websocket_server.stop()
+ sys.exit(1)
+ elif host_connected:
+ self.initialized = True
+ self.initializing = False
+ self._connected()
+
+ return
+
+ ConsoleTrayApp.callback_queue = queue.Queue()
+ self.initializing = True
+
+ self.launch_method(*self.subprocess_args)
+ elif ConsoleTrayApp.process.poll() is not None:
+ self.exit()
+ elif ConsoleTrayApp.callback_queue:
+ try:
+ callback = ConsoleTrayApp.callback_queue.get(block=False)
+ callback()
+ except queue.Empty:
+ pass
+
+ @classmethod
+ def execute_in_main_thread(cls, func_to_call_from_main_thread):
+ """Put function to the queue to be picked by 'on_timer'"""
+ if not cls.callback_queue:
+ cls.callback_queue = queue.Queue()
+ cls.callback_queue.put(func_to_call_from_main_thread)
+
+ @classmethod
+ def restart_server(cls):
+ if ConsoleTrayApp.websocket_server:
+ ConsoleTrayApp.websocket_server.stop_server(restart=True)
+
+ # obsolete
+ def exit(self):
+ """ Exit whole application. """
+ self._close()
+ if ConsoleTrayApp.websocket_server:
+ ConsoleTrayApp.websocket_server.stop()
+ ConsoleTrayApp.process.kill()
+ ConsoleTrayApp.process.wait()
+ if self.timer:
+ self.timer.stop()
+ QtCore.QCoreApplication.exit()
+
+ def catch_std_outputs(self):
+ """Redirects standard out and error to own functions"""
+ if not sys.stdout:
+ self.dialog.append_text("Cannot read from stdout!")
+ else:
+ self.original_stdout_write = sys.stdout.write
+ sys.stdout.write = self.my_stdout_write
+
+ if not sys.stderr:
+ self.dialog.append_text("Cannot read from stderr!")
+ else:
+ self.original_stderr_write = sys.stderr.write
+ sys.stderr.write = self.my_stderr_write
+
+ def my_stdout_write(self, text):
+ """Appends outputted text to queue, keep writing to original stdout"""
+ if self.original_stdout_write is not None:
+ self.original_stdout_write(text)
+ self.new_text.append(text)
+
+ def my_stderr_write(self, text):
+ """Appends outputted text to queue, keep writing to original stderr"""
+ if self.original_stderr_write is not None:
+ self.original_stderr_write(text)
+ self.new_text.append(text)
+
+ @staticmethod
+ def _multiple_replace(text, adict):
+ """Replace multiple tokens defined in dict.
+
+ Find and replace all occurances of strings defined in dict is
+ supplied string.
+
+ Args:
+ text (str): string to be searched
+ adict (dict): dictionary with `{'search': 'replace'}`
+
+ Returns:
+ str: string with replaced tokens
+
+ """
+ for r, v in adict.items():
+ text = re.sub(r, v, text)
+
+ return text
+
+ @staticmethod
+ def color(message):
+ """ Color message with html tags. """
+ message = ConsoleTrayApp._multiple_replace(message,
+ ConsoleTrayApp.sdict)
+
+ return message
+
+
+class ConsoleDialog(QtWidgets.QDialog):
+ """Qt dialog to show stdout instead of unwieldy cmd window"""
+ WIDTH = 720
+ HEIGHT = 450
+ MAX_LINES = 10000
+
+ def __init__(self, text, parent=None):
+ super(ConsoleDialog, self).__init__(parent)
+ layout = QtWidgets.QHBoxLayout(parent)
+
+ plain_text = QtWidgets.QPlainTextEdit(self)
+ plain_text.setReadOnly(True)
+ plain_text.resize(self.WIDTH, self.HEIGHT)
+ plain_text.maximumBlockCount = self.MAX_LINES
+
+ while text:
+ plain_text.appendPlainText(text.popleft().strip())
+
+ layout.addWidget(plain_text)
+
+ self.setWindowTitle("Console output")
+
+ self.plain_text = plain_text
+
+ self.setStyleSheet(style.load_stylesheet())
+
+ self.resize(self.WIDTH, self.HEIGHT)
+
+ def append_text(self, new_text):
+ if isinstance(new_text, str):
+ new_text = collections.deque(new_text.split("\n"))
+ while new_text:
+ text = new_text.popleft()
+ if text:
+ self.plain_text.appendHtml(
+ ConsoleTrayApp.color(text))
diff --git a/openpype/vendor/python/common/capture_gui/__init__.py b/openpype/vendor/python/common/capture_gui/__init__.py
deleted file mode 100644
index 6c6a813636..0000000000
--- a/openpype/vendor/python/common/capture_gui/__init__.py
+++ /dev/null
@@ -1,29 +0,0 @@
-from .vendor.Qt import QtWidgets
-from . import app
-from . import lib
-
-
-def main(show=True):
- """Convenience method to run the Application inside Maya.
-
- Args:
- show (bool): Whether to directly show the instantiated application.
- Defaults to True. Set this to False if you want to manage the
- application (like callbacks) prior to showing the interface.
-
- Returns:
- capture_gui.app.App: The pyblish gui application instance.
-
- """
- # get main maya window to parent widget to
- parent = lib.get_maya_main_window()
- instance = parent.findChild(QtWidgets.QWidget, app.App.object_name)
- if instance:
- instance.close()
-
- # launch app
- window = app.App(title="Capture GUI", parent=parent)
- if show:
- window.show()
-
- return window
diff --git a/openpype/vendor/python/common/capture_gui/accordion.py b/openpype/vendor/python/common/capture_gui/accordion.py
deleted file mode 100644
index f721837c57..0000000000
--- a/openpype/vendor/python/common/capture_gui/accordion.py
+++ /dev/null
@@ -1,624 +0,0 @@
-from .vendor.Qt import QtCore, QtWidgets, QtGui
-
-
-class AccordionItem(QtWidgets.QGroupBox):
- trigger = QtCore.Signal(bool)
-
- def __init__(self, accordion, title, widget):
- QtWidgets.QGroupBox.__init__(self, parent=accordion)
-
- # create the layout
- layout = QtWidgets.QVBoxLayout()
- layout.setContentsMargins(6, 12, 6, 6)
- layout.setSpacing(0)
- layout.addWidget(widget)
-
- self._accordianWidget = accordion
- self._rolloutStyle = 2
- self._dragDropMode = 0
-
- self.setAcceptDrops(True)
- self.setLayout(layout)
- self.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
- self.customContextMenuRequested.connect(self.showMenu)
-
- # create custom properties
- self._widget = widget
- self._collapsed = False
- self._collapsible = True
- self._clicked = False
- self._customData = {}
-
- # set common properties
- self.setTitle(title)
-
- def accordionWidget(self):
- """
- \remarks grabs the parent item for the accordian widget
- \return
- """
- return self._accordianWidget
-
- def customData(self, key, default=None):
- """
- \remarks return a custom pointer to information stored with this item
- \param key
- \param default default value to return if the key was not found
- \return data
- """
- return self._customData.get(str(key), default)
-
- def dragEnterEvent(self, event):
- if not self._dragDropMode:
- return
-
- source = event.source()
- if source != self and source.parent() == self.parent() and isinstance(
- source, AccordionItem):
- event.acceptProposedAction()
-
- def dragDropRect(self):
- return QtCore.QRect(25, 7, 10, 6)
-
- def dragDropMode(self):
- return self._dragDropMode
-
- def dragMoveEvent(self, event):
- if not self._dragDropMode:
- return
-
- source = event.source()
- if source != self and source.parent() == self.parent() and isinstance(
- source, AccordionItem):
- event.acceptProposedAction()
-
- def dropEvent(self, event):
- widget = event.source()
- layout = self.parent().layout()
- layout.insertWidget(layout.indexOf(self), widget)
- self._accordianWidget.emitItemsReordered()
-
- def expandCollapseRect(self):
- return QtCore.QRect(0, 0, self.width(), 20)
-
- def enterEvent(self, event):
- self.accordionWidget().leaveEvent(event)
- event.accept()
-
- def leaveEvent(self, event):
- self.accordionWidget().enterEvent(event)
- event.accept()
-
- def mouseReleaseEvent(self, event):
- if self._clicked and self.expandCollapseRect().contains(event.pos()):
- self.toggleCollapsed()
- event.accept()
- else:
- event.ignore()
-
- self._clicked = False
-
- def mouseMoveEvent(self, event):
- event.ignore()
-
- def mousePressEvent(self, event):
- # handle an internal move
-
- # start a drag event
- if event.button() == QtCore.Qt.LeftButton and self.dragDropRect().contains(
- event.pos()):
- # create the pixmap
- pixmap = QtGui.QPixmap.grabWidget(self, self.rect())
-
- # create the mimedata
- mimeData = QtCore.QMimeData()
- mimeData.setText('ItemTitle::%s' % (self.title()))
-
- # create the drag
- drag = QtGui.QDrag(self)
- drag.setMimeData(mimeData)
- drag.setPixmap(pixmap)
- drag.setHotSpot(event.pos())
-
- if not drag.exec_():
- self._accordianWidget.emitItemDragFailed(self)
-
- event.accept()
-
- # determine if the expand/collapse should occur
- elif event.button() == QtCore.Qt.LeftButton and self.expandCollapseRect().contains(
- event.pos()):
- self._clicked = True
- event.accept()
-
- else:
- event.ignore()
-
- def isCollapsed(self):
- return self._collapsed
-
- def isCollapsible(self):
- return self._collapsible
-
- def __drawTriangle(self, painter, x, y):
-
- brush = QtGui.QBrush(QtGui.QColor(255, 255, 255, 160),
- QtCore.Qt.SolidPattern)
- if not self.isCollapsed():
- tl, tr, tp = QtCore.QPoint(x + 9, y + 8), QtCore.QPoint(x + 19,
- y + 8), QtCore.QPoint(
- x + 14, y + 13.0)
- points = [tl, tr, tp]
- triangle = QtGui.QPolygon(points)
- else:
- tl, tr, tp = QtCore.QPoint(x + 11, y + 6), QtCore.QPoint(x + 16,
- y + 11), QtCore.QPoint(
- x + 11, y + 16.0)
- points = [tl, tr, tp]
- triangle = QtGui.QPolygon(points)
-
- currentBrush = painter.brush()
- painter.setBrush(brush)
- painter.drawPolygon(triangle)
- painter.setBrush(currentBrush)
-
- def paintEvent(self, event):
- painter = QtGui.QPainter()
- painter.begin(self)
- painter.setRenderHint(painter.Antialiasing)
- font = painter.font()
- font.setBold(True)
- painter.setFont(font)
-
- x = self.rect().x()
- y = self.rect().y()
- w = self.rect().width() - 1
- h = self.rect().height() - 1
- r = 8
-
- # draw a rounded style
- if self._rolloutStyle == 2:
- # draw the text
- painter.drawText(x + 33, y + 3, w, 16,
- QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop,
- self.title())
-
- # draw the triangle
- self.__drawTriangle(painter, x, y)
-
- # draw the borders
- pen = QtGui.QPen(self.palette().color(QtGui.QPalette.Light))
- pen.setWidthF(0.6)
- painter.setPen(pen)
-
- painter.drawRoundedRect(x + 1, y + 1, w - 1, h - 1, r, r)
-
- pen.setColor(self.palette().color(QtGui.QPalette.Shadow))
- painter.setPen(pen)
-
- painter.drawRoundedRect(x, y, w - 1, h - 1, r, r)
-
- # draw a square style
- if self._rolloutStyle == 3:
- # draw the text
- painter.drawText(x + 33, y + 3, w, 16,
- QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop,
- self.title())
-
- self.__drawTriangle(painter, x, y)
-
- # draw the borders
- pen = QtGui.QPen(self.palette().color(QtGui.QPalette.Light))
- pen.setWidthF(0.6)
- painter.setPen(pen)
-
- painter.drawRect(x + 1, y + 1, w - 1, h - 1)
-
- pen.setColor(self.palette().color(QtGui.QPalette.Shadow))
- painter.setPen(pen)
-
- painter.drawRect(x, y, w - 1, h - 1)
-
- # draw a Maya style
- if self._rolloutStyle == 4:
- # draw the text
- painter.drawText(x + 33, y + 3, w, 16,
- QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop,
- self.title())
-
- painter.setRenderHint(QtGui.QPainter.Antialiasing, False)
-
- self.__drawTriangle(painter, x, y)
-
- # draw the borders - top
- headerHeight = 20
-
- headerRect = QtCore.QRect(x + 1, y + 1, w - 1, headerHeight)
- headerRectShadow = QtCore.QRect(x - 1, y - 1, w + 1,
- headerHeight + 2)
-
- # Highlight
- pen = QtGui.QPen(self.palette().color(QtGui.QPalette.Light))
- pen.setWidthF(0.4)
- painter.setPen(pen)
-
- painter.drawRect(headerRect)
- painter.fillRect(headerRect, QtGui.QColor(255, 255, 255, 18))
-
- # Shadow
- pen.setColor(self.palette().color(QtGui.QPalette.Dark))
- painter.setPen(pen)
- painter.drawRect(headerRectShadow)
-
- if not self.isCollapsed():
- # draw the lover border
- pen = QtGui.QPen(self.palette().color(QtGui.QPalette.Dark))
- pen.setWidthF(0.8)
- painter.setPen(pen)
-
- offSet = headerHeight + 3
- bodyRect = QtCore.QRect(x, y + offSet, w, h - offSet)
- bodyRectShadow = QtCore.QRect(x + 1, y + offSet, w + 1,
- h - offSet + 1)
- painter.drawRect(bodyRect)
-
- pen.setColor(self.palette().color(QtGui.QPalette.Light))
- pen.setWidthF(0.4)
- painter.setPen(pen)
-
- painter.drawRect(bodyRectShadow)
-
- # draw a boxed style
- elif self._rolloutStyle == 1:
- if self.isCollapsed():
- arect = QtCore.QRect(x + 1, y + 9, w - 1, 4)
- brect = QtCore.QRect(x, y + 8, w - 1, 4)
- text = '+'
- else:
- arect = QtCore.QRect(x + 1, y + 9, w - 1, h - 9)
- brect = QtCore.QRect(x, y + 8, w - 1, h - 9)
- text = '-'
-
- # draw the borders
- pen = QtGui.QPen(self.palette().color(QtGui.QPalette.Light))
- pen.setWidthF(0.6)
- painter.setPen(pen)
-
- painter.drawRect(arect)
-
- pen.setColor(self.palette().color(QtGui.QPalette.Shadow))
- painter.setPen(pen)
-
- painter.drawRect(brect)
-
- painter.setRenderHint(painter.Antialiasing, False)
- painter.setBrush(
- self.palette().color(QtGui.QPalette.Window).darker(120))
- painter.drawRect(x + 10, y + 1, w - 20, 16)
- painter.drawText(x + 16, y + 1,
- w - 32, 16,
- QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter,
- text)
- painter.drawText(x + 10, y + 1,
- w - 20, 16,
- QtCore.Qt.AlignCenter,
- self.title())
-
- if self.dragDropMode():
- rect = self.dragDropRect()
-
- # draw the lines
- l = rect.left()
- r = rect.right()
- cy = rect.center().y()
-
- for y in (cy - 3, cy, cy + 3):
- painter.drawLine(l, y, r, y)
-
- painter.end()
-
- def setCollapsed(self, state=True):
- if self.isCollapsible():
- accord = self.accordionWidget()
- accord.setUpdatesEnabled(False)
-
- self._collapsed = state
-
- if state:
- self.setMinimumHeight(22)
- self.setMaximumHeight(22)
- self.widget().setVisible(False)
- else:
- self.setMinimumHeight(0)
- self.setMaximumHeight(1000000)
- self.widget().setVisible(True)
-
- self._accordianWidget.emitItemCollapsed(self)
- accord.setUpdatesEnabled(True)
-
- def setCollapsible(self, state=True):
- self._collapsible = state
-
- def setCustomData(self, key, value):
- """
- \remarks set a custom pointer to information stored on this item
- \param key
- \param value
- """
- self._customData[str(key)] = value
-
- def setDragDropMode(self, mode):
- self._dragDropMode = mode
-
- def setRolloutStyle(self, style):
- self._rolloutStyle = style
-
- def showMenu(self):
- if QtCore.QRect(0, 0, self.width(), 20).contains(
- self.mapFromGlobal(QtGui.QCursor.pos())):
- self._accordianWidget.emitItemMenuRequested(self)
-
- def rolloutStyle(self):
- return self._rolloutStyle
-
- def toggleCollapsed(self):
- # enable signaling here
- collapse_state = not self.isCollapsed()
- self.setCollapsed(collapse_state)
- return collapse_state
-
- def widget(self):
- return self._widget
-
-
-class AccordionWidget(QtWidgets.QScrollArea):
- """Accordion style widget.
-
- A collapsible accordion widget like Maya's attribute editor.
-
- This is a modified version bsed on Blur's Accordion Widget to
- include a Maya style.
-
- """
- itemCollapsed = QtCore.Signal(AccordionItem)
- itemMenuRequested = QtCore.Signal(AccordionItem)
- itemDragFailed = QtCore.Signal(AccordionItem)
- itemsReordered = QtCore.Signal()
-
- Boxed = 1
- Rounded = 2
- Square = 3
- Maya = 4
-
- NoDragDrop = 0
- InternalMove = 1
-
- def __init__(self, parent):
-
- QtWidgets.QScrollArea.__init__(self, parent)
-
- self.setFrameShape(QtWidgets.QScrollArea.NoFrame)
- self.setAutoFillBackground(False)
- self.setWidgetResizable(True)
- self.setMouseTracking(True)
- self.verticalScrollBar().setMaximumWidth(10)
-
- widget = QtWidgets.QWidget(self)
-
- # define custom properties
- self._rolloutStyle = AccordionWidget.Rounded
- self._dragDropMode = AccordionWidget.NoDragDrop
- self._scrolling = False
- self._scrollInitY = 0
- self._scrollInitVal = 0
- self._itemClass = AccordionItem
-
- layout = QtWidgets.QVBoxLayout()
- layout.setContentsMargins(2, 2, 2, 6)
- layout.setSpacing(2)
- layout.addStretch(1)
-
- widget.setLayout(layout)
-
- self.setWidget(widget)
-
- def setSpacing(self, spaceInt):
- self.widget().layout().setSpacing(spaceInt)
-
- def addItem(self, title, widget, collapsed=False):
- self.setUpdatesEnabled(False)
- item = self._itemClass(self, title, widget)
- item.setRolloutStyle(self.rolloutStyle())
- item.setDragDropMode(self.dragDropMode())
- layout = self.widget().layout()
- layout.insertWidget(layout.count() - 1, item)
- layout.setStretchFactor(item, 0)
-
- if collapsed:
- item.setCollapsed(collapsed)
-
- self.setUpdatesEnabled(True)
-
- return item
-
- def clear(self):
- self.setUpdatesEnabled(False)
- layout = self.widget().layout()
- while layout.count() > 1:
- item = layout.itemAt(0)
-
- # remove the item from the layout
- w = item.widget()
- layout.removeItem(item)
-
- # close the widget and delete it
- w.close()
- w.deleteLater()
-
- self.setUpdatesEnabled(True)
-
- def eventFilter(self, object, event):
- if event.type() == QtCore.QEvent.MouseButtonPress:
- self.mousePressEvent(event)
- return True
-
- elif event.type() == QtCore.QEvent.MouseMove:
- self.mouseMoveEvent(event)
- return True
-
- elif event.type() == QtCore.QEvent.MouseButtonRelease:
- self.mouseReleaseEvent(event)
- return True
-
- return False
-
- def canScroll(self):
- return self.verticalScrollBar().maximum() > 0
-
- def count(self):
- return self.widget().layout().count() - 1
-
- def dragDropMode(self):
- return self._dragDropMode
-
- def indexOf(self, widget):
- """
- \remarks Searches for widget(not including child layouts).
- Returns the index of widget, or -1 if widget is not found
- \return
- """
- layout = self.widget().layout()
- for index in range(layout.count()):
- if layout.itemAt(index).widget().widget() == widget:
- return index
- return -1
-
- def isBoxedMode(self):
- return self._rolloutStyle == AccordionWidget.Maya
-
- def itemClass(self):
- return self._itemClass
-
- def itemAt(self, index):
- layout = self.widget().layout()
- if 0 <= index and index < layout.count() - 1:
- return layout.itemAt(index).widget()
- return None
-
- def emitItemCollapsed(self, item):
- if not self.signalsBlocked():
- self.itemCollapsed.emit(item)
-
- def emitItemDragFailed(self, item):
- if not self.signalsBlocked():
- self.itemDragFailed.emit(item)
-
- def emitItemMenuRequested(self, item):
- if not self.signalsBlocked():
- self.itemMenuRequested.emit(item)
-
- def emitItemsReordered(self):
- if not self.signalsBlocked():
- self.itemsReordered.emit()
-
- def enterEvent(self, event):
- if self.canScroll():
- QtWidgets.QApplication.setOverrideCursor(QtCore.Qt.OpenHandCursor)
-
- def leaveEvent(self, event):
- if self.canScroll():
- QtWidgets.QApplication.restoreOverrideCursor()
-
- def mouseMoveEvent(self, event):
- if self._scrolling:
- sbar = self.verticalScrollBar()
- smax = sbar.maximum()
-
- # calculate the distance moved for the moust point
- dy = event.globalY() - self._scrollInitY
-
- # calculate the percentage that is of the scroll bar
- dval = smax * (dy / float(sbar.height()))
-
- # calculate the new value
- sbar.setValue(self._scrollInitVal - dval)
-
- event.accept()
-
- def mousePressEvent(self, event):
- # handle a scroll event
- if event.button() == QtCore.Qt.LeftButton and self.canScroll():
- self._scrolling = True
- self._scrollInitY = event.globalY()
- self._scrollInitVal = self.verticalScrollBar().value()
-
- QtWidgets.QApplication.setOverrideCursor(
- QtCore.Qt.ClosedHandCursor)
-
- event.accept()
-
- def mouseReleaseEvent(self, event):
- if self._scrolling:
- QtWidgets.QApplication.restoreOverrideCursor()
-
- self._scrolling = False
- self._scrollInitY = 0
- self._scrollInitVal = 0
- event.accept()
-
- def moveItemDown(self, index):
- layout = self.widget().layout()
- if (layout.count() - 1) > (index + 1):
- widget = layout.takeAt(index).widget()
- layout.insertWidget(index + 1, widget)
-
- def moveItemUp(self, index):
- if index > 0:
- layout = self.widget().layout()
- widget = layout.takeAt(index).widget()
- layout.insertWidget(index - 1, widget)
-
- def setBoxedMode(self, state):
- if state:
- self._rolloutStyle = AccordionWidget.Boxed
- else:
- self._rolloutStyle = AccordionWidget.Rounded
-
- def setDragDropMode(self, dragDropMode):
- self._dragDropMode = dragDropMode
-
- for item in self.findChildren(AccordionItem):
- item.setDragDropMode(self._dragDropMode)
-
- def setItemClass(self, itemClass):
- self._itemClass = itemClass
-
- def setRolloutStyle(self, rolloutStyle):
- self._rolloutStyle = rolloutStyle
-
- for item in self.findChildren(AccordionItem):
- item.setRolloutStyle(self._rolloutStyle)
-
- def rolloutStyle(self):
- return self._rolloutStyle
-
- def takeAt(self, index):
- self.setUpdatesEnabled(False)
- layout = self.widget().layout()
- widget = None
- if 0 <= index and index < layout.count() - 1:
- item = layout.itemAt(index)
- widget = item.widget()
-
- layout.removeItem(item)
- widget.close()
- self.setUpdatesEnabled(True)
- return widget
-
- def widgetAt(self, index):
- item = self.itemAt(index)
- if item:
- return item.widget()
- return None
-
- pyBoxedMode = QtCore.Property('bool', isBoxedMode, setBoxedMode)
diff --git a/openpype/vendor/python/common/capture_gui/app.py b/openpype/vendor/python/common/capture_gui/app.py
deleted file mode 100644
index 1860b084ba..0000000000
--- a/openpype/vendor/python/common/capture_gui/app.py
+++ /dev/null
@@ -1,711 +0,0 @@
-import json
-import logging
-import os
-import tempfile
-
-import capture
-import maya.cmds as cmds
-
-from .vendor.Qt import QtCore, QtWidgets, QtGui
-from . import lib
-from . import plugin
-from . import presets
-from . import version
-from . import tokens
-from .accordion import AccordionWidget
-
-log = logging.getLogger("Capture Gui")
-
-
-class ClickLabel(QtWidgets.QLabel):
- """A QLabel that emits a clicked signal when clicked upon."""
- clicked = QtCore.Signal()
-
- def mouseReleaseEvent(self, event):
- self.clicked.emit()
- return super(ClickLabel, self).mouseReleaseEvent(event)
-
-
-class PreviewWidget(QtWidgets.QWidget):
- """The playblast image preview widget.
-
- Upon refresh it will retrieve the options through the function set as
- `options_getter` and make a call to `capture.capture()` for a single
- frame (playblasted) snapshot. The result is displayed as image.
- """
-
- preview_width = 320
- preview_height = 180
-
- def __init__(self, options_getter, validator, parent=None):
- QtWidgets.QWidget.__init__(self, parent=parent)
-
- # Add attributes
- self.options_getter = options_getter
- self.validator = validator
- self.preview = ClickLabel()
- self.preview.setFixedWidth(self.preview_width)
- self.preview.setFixedHeight(self.preview_height)
-
- tip = "Click to force a refresh"
- self.preview.setToolTip(tip)
- self.preview.setStatusTip(tip)
-
- # region Build
- self.layout = QtWidgets.QVBoxLayout()
- self.layout.setAlignment(QtCore.Qt.AlignHCenter)
- self.layout.setContentsMargins(0, 0, 0, 0)
-
- self.setLayout(self.layout)
- self.layout.addWidget(self.preview)
- # endregion Build
-
- # Connect widgets to functions
- self.preview.clicked.connect(self.refresh)
-
- def refresh(self):
- """Refresh the playblast preview"""
-
- frame = cmds.currentTime(query=True)
-
- # When playblasting outside of an undo queue it seems that undoing
- # actually triggers a reset to frame 0. As such we sneak in the current
- # time into the undo queue to enforce correct undoing.
- cmds.currentTime(frame, update=True)
-
- # check if plugin outputs are correct
- valid = self.validator()
- if not valid:
- return
-
- with lib.no_undo():
- options = self.options_getter()
- tempdir = tempfile.mkdtemp()
-
- # override settings that are constants for the preview
- options = options.copy()
- options['filename'] = None
- options['complete_filename'] = os.path.join(tempdir, "temp.jpg")
- options['width'] = self.preview_width
- options['height'] = self.preview_height
- options['viewer'] = False
- options['frame'] = frame
- options['off_screen'] = True
- options['format'] = "image"
- options['compression'] = "jpg"
- options['sound'] = None
-
- fname = capture.capture(**options)
- if not fname:
- log.warning("Preview failed")
- return
-
- image = QtGui.QPixmap(fname)
- self.preview.setPixmap(image)
- os.remove(fname)
-
- def showEvent(self, event):
- """Initialize when shown"""
- self.refresh()
- event.accept()
-
-
-class PresetWidget(QtWidgets.QWidget):
- """Preset Widget
-
- Allows the user to set preferences and create presets to load before
- capturing.
-
- """
-
- preset_loaded = QtCore.Signal(dict)
- config_opened = QtCore.Signal()
-
- id = "Presets"
- label = "Presets"
-
- def __init__(self, inputs_getter, parent=None):
- QtWidgets.QWidget.__init__(self, parent=parent)
-
- self.inputs_getter = inputs_getter
-
- layout = QtWidgets.QHBoxLayout(self)
- layout.setAlignment(QtCore.Qt.AlignCenter)
- layout.setContentsMargins(0, 0, 0, 0)
-
- presets = QtWidgets.QComboBox()
- presets.setFixedWidth(220)
- presets.addItem("*")
-
- # Icons
- icon_path = os.path.join(os.path.dirname(__file__), "resources")
- save_icon = os.path.join(icon_path, "save.png")
- load_icon = os.path.join(icon_path, "import.png")
- config_icon = os.path.join(icon_path, "config.png")
-
- # Create buttons
- save = QtWidgets.QPushButton()
- save.setIcon(QtGui.QIcon(save_icon))
- save.setFixedWidth(30)
- save.setToolTip("Save Preset")
- save.setStatusTip("Save Preset")
-
- load = QtWidgets.QPushButton()
- load.setIcon(QtGui.QIcon(load_icon))
- load.setFixedWidth(30)
- load.setToolTip("Load Preset")
- load.setStatusTip("Load Preset")
-
- config = QtWidgets.QPushButton()
- config.setIcon(QtGui.QIcon(config_icon))
- config.setFixedWidth(30)
- config.setToolTip("Preset configuration")
- config.setStatusTip("Preset configuration")
-
- layout.addWidget(presets)
- layout.addWidget(save)
- layout.addWidget(load)
- layout.addWidget(config)
-
- # Make available for all methods
- self.presets = presets
- self.config = config
- self.load = load
- self.save = save
-
- # Signals
- self.save.clicked.connect(self.on_save_preset)
- self.load.clicked.connect(self.import_preset)
- self.config.clicked.connect(self.config_opened)
- self.presets.currentIndexChanged.connect(self.load_active_preset)
-
- self._process_presets()
-
- def _process_presets(self):
- """Adds all preset files from preset paths to the Preset widget.
-
- Returns:
- None
-
- """
- for presetfile in presets.discover():
- self.add_preset(presetfile)
-
- def import_preset(self):
- """Load preset files to override output values"""
-
- path = self._default_browse_path()
- filters = "Text file (*.json)"
- dialog = QtWidgets.QFileDialog
- filename, _ = dialog.getOpenFileName(self, "Open preference file",
- path, filters)
- if not filename:
- return
-
- # create new entry in combobox
- self.add_preset(filename)
-
- # read file
- return self.load_active_preset()
-
- def load_active_preset(self):
- """Load the active preset.
-
- Returns:
- dict: The preset inputs.
-
- """
- current_index = self.presets.currentIndex()
- filename = self.presets.itemData(current_index)
- if not filename:
- return {}
-
- preset = lib.load_json(filename)
-
- # Emit preset load signal
- log.debug("Emitting preset_loaded: {0}".format(filename))
- self.preset_loaded.emit(preset)
-
- # Ensure we preserve the index after loading the changes
- # for all the plugin widgets
- self.presets.blockSignals(True)
- self.presets.setCurrentIndex(current_index)
- self.presets.blockSignals(False)
-
- return preset
-
- def add_preset(self, filename):
- """Add the filename to the preset list.
-
- This also sets the index to the filename.
-
- Returns:
- None
-
- """
-
- filename = os.path.normpath(filename)
- if not os.path.exists(filename):
- log.warning("Preset file does not exist: {0}".format(filename))
- return
-
- label = os.path.splitext(os.path.basename(filename))[0]
- item_count = self.presets.count()
-
- paths = [self.presets.itemData(i) for i in range(item_count)]
- if filename in paths:
- log.info("Preset is already in the "
- "presets list: {0}".format(filename))
- item_index = paths.index(filename)
- else:
- self.presets.addItem(label, userData=filename)
- item_index = item_count
-
- self.presets.blockSignals(True)
- self.presets.setCurrentIndex(item_index)
- self.presets.blockSignals(False)
-
- return item_index
-
- def _default_browse_path(self):
- """Return the current browse path for save/load preset.
-
- If a preset is currently loaded it will use that specific path
- otherwise it will go to the last registered preset path.
-
- Returns:
- str: Path to use as default browse location.
-
- """
-
- current_index = self.presets.currentIndex()
- path = self.presets.itemData(current_index)
-
- if not path:
- # Fallback to last registered preset path
- paths = presets.preset_paths()
- if paths:
- path = paths[-1]
-
- return path
-
- def save_preset(self, inputs):
- """Save inputs to a file"""
-
- path = self._default_browse_path()
- filters = "Text file (*.json)"
- filename, _ = QtWidgets.QFileDialog.getSaveFileName(self,
- "Save preferences",
- path,
- filters)
- if not filename:
- return
-
- with open(filename, "w") as f:
- json.dump(inputs, f, sort_keys=True,
- indent=4, separators=(',', ': '))
-
- self.add_preset(filename)
-
- return filename
-
- def get_presets(self):
- """Return all currently listed presets"""
- configurations = [self.presets.itemText(i) for
- i in range(self.presets.count())]
-
- return configurations
-
- def on_save_preset(self):
- """Save the inputs of all the plugins in a preset."""
-
- inputs = self.inputs_getter(as_preset=True)
- self.save_preset(inputs)
-
- def apply_inputs(self, settings):
-
- path = settings.get("selected", None)
- index = self.presets.findData(path)
- if index == -1:
- # If the last loaded preset still exists but wasn't on the
- # "discovered preset paths" then add it.
- if os.path.exists(path):
- log.info("Adding previously selected preset explicitly: %s",
- path)
- self.add_preset(path)
- return
- else:
- log.warning("Previously selected preset is not available: %s",
- path)
- index = 0
-
- self.presets.setCurrentIndex(index)
-
- def get_inputs(self, as_preset=False):
-
- if as_preset:
- # Don't save the current preset into the preset because
- # that would just be recursive and make no sense
- return {}
- else:
- current_index = self.presets.currentIndex()
- selected = self.presets.itemData(current_index)
- return {"selected": selected}
-
-
-class App(QtWidgets.QWidget):
- """The main application in which the widgets are placed"""
-
- # Signals
- options_changed = QtCore.Signal(dict)
- playblast_start = QtCore.Signal(dict)
- playblast_finished = QtCore.Signal(dict)
- viewer_start = QtCore.Signal(dict)
-
- # Attributes
- object_name = "CaptureGUI"
- application_sections = ["config", "app"]
-
- def __init__(self, title, parent=None):
- QtWidgets.QWidget.__init__(self, parent=parent)
-
- # Settings
- # Remove pointer for memory when closed
- self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
- self.settingfile = self._ensure_config_exist()
- self.plugins = {"app": list(),
- "config": list()}
-
- self._config_dialog = None
- self._build_configuration_dialog()
-
- # region Set Attributes
- title_version = "{} v{}".format(title, version.version)
- self.setObjectName(self.object_name)
- self.setWindowTitle(title_version)
- self.setMinimumWidth(380)
-
- # Set dialog window flags so the widget can be correctly parented
- # to Maya main window
- self.setWindowFlags(self.windowFlags() | QtCore.Qt.Dialog)
- self.setProperty("saveWindowPref", True)
- # endregion Set Attributes
-
- self.layout = QtWidgets.QVBoxLayout()
- self.layout.setContentsMargins(0, 0, 0, 0)
- self.setLayout(self.layout)
-
- # Add accordion widget (Maya attribute editor style)
- self.widgetlibrary = AccordionWidget(self)
- self.widgetlibrary.setRolloutStyle(AccordionWidget.Maya)
-
- # Add separate widgets
- self.widgetlibrary.addItem("Preview",
- PreviewWidget(self.get_outputs,
- self.validate,
- parent=self),
- collapsed=True)
-
- self.presetwidget = PresetWidget(inputs_getter=self.get_inputs,
- parent=self)
- self.widgetlibrary.addItem("Presets", self.presetwidget)
-
- # add plug-in widgets
- for widget in plugin.discover():
- self.add_plugin(widget)
-
- self.layout.addWidget(self.widgetlibrary)
-
- # add standard buttons
- self.apply_button = QtWidgets.QPushButton("Capture")
- self.layout.addWidget(self.apply_button)
-
- # default actions
- self.apply_button.clicked.connect(self.apply)
-
- # signals and slots
- self.presetwidget.config_opened.connect(self.show_config)
- self.presetwidget.preset_loaded.connect(self.apply_inputs)
-
- self.apply_inputs(self._read_widget_configuration())
-
- def apply(self):
- """Run capture action with current settings"""
-
- valid = self.validate()
- if not valid:
- return
-
- options = self.get_outputs()
- filename = options.get("filename", None)
-
- self.playblast_start.emit(options)
-
- # The filename can be `None` when the
- # playblast will *not* be saved.
- if filename is not None:
- # Format the tokens in the filename
- filename = tokens.format_tokens(filename, options)
-
- # expand environment variables
- filename = os.path.expandvars(filename)
-
- # Make relative paths absolute to the "images" file rule by default
- if not os.path.isabs(filename):
- root = lib.get_project_rule("images")
- filename = os.path.join(root, filename)
-
- # normalize (to remove double slashes and alike)
- filename = os.path.normpath(filename)
-
- options["filename"] = filename
-
- # Perform capture and store returned filename with extension
- options["filename"] = lib.capture_scene(options)
-
- self.playblast_finished.emit(options)
- filename = options["filename"] # get filename after callbacks
-
- # Show viewer
- viewer = options.get("viewer", False)
- if viewer:
- if filename and os.path.exists(filename):
- self.viewer_start.emit(options)
- lib.open_file(filename)
- else:
- raise RuntimeError("Can't open playblast because file "
- "doesn't exist: {0}".format(filename))
-
- return filename
-
- def apply_inputs(self, inputs):
- """Apply all the settings of the widgets.
-
- Arguments:
- inputs (dict): input values per plug-in widget
-
- Returns:
- None
-
- """
- if not inputs:
- return
-
- widgets = self._get_plugin_widgets()
- widgets.append(self.presetwidget)
- for widget in widgets:
- widget_inputs = inputs.get(widget.id, None)
- if not widget_inputs:
- continue
- widget.apply_inputs(widget_inputs)
-
- def show_config(self):
- """Show the advanced configuration"""
- # calculate center of main widget
- geometry = self.geometry()
- self._config_dialog.move(QtCore.QPoint(geometry.x()+30,
- geometry.y()))
- self._config_dialog.show()
-
- def add_plugin(self, plugin):
- """Add an options widget plug-in to the UI"""
-
- if plugin.section not in self.application_sections:
- log.warning("{}'s section is invalid: "
- "{}".format(plugin.label, plugin.section))
- return
-
- widget = plugin(parent=self)
- widget.initialize()
- widget.options_changed.connect(self.on_widget_settings_changed)
- self.playblast_finished.connect(widget.on_playblast_finished)
-
- # Add to plug-ins in its section
- self.plugins[widget.section].append(widget)
-
- # Implement additional settings depending on section
- if widget.section == "app":
- if not widget.hidden:
- item = self.widgetlibrary.addItem(widget.label, widget)
- # connect label change behaviour
- widget.label_changed.connect(item.setTitle)
-
- # Add the plugin in a QGroupBox to the configuration dialog
- if widget.section == "config":
- layout = self._config_dialog.layout()
- # create group box
- group_widget = QtWidgets.QGroupBox(widget.label)
- group_layout = QtWidgets.QVBoxLayout(group_widget)
- group_layout.addWidget(widget)
-
- layout.addWidget(group_widget)
-
- def validate(self):
- """Validate whether the outputs of the widgets are good.
-
- Returns:
- bool: Whether it's valid to capture the current settings.
-
- """
-
- errors = list()
- for widget in self._get_plugin_widgets():
- widget_errors = widget.validate()
- if widget_errors:
- errors.extend(widget_errors)
-
- if errors:
- message_title = "%s Validation Error(s)" % len(errors)
- message = "\n".join(errors)
- QtWidgets.QMessageBox.critical(self,
- message_title,
- message,
- QtWidgets.QMessageBox.Ok)
- return False
-
- return True
-
- def get_outputs(self):
- """Return settings for a capture as currently set in the Application.
-
- Returns:
- dict: Current output settings
-
- """
-
- # Get settings from widgets
- outputs = dict()
- for widget in self._get_plugin_widgets():
- widget_outputs = widget.get_outputs()
- if not widget_outputs:
- continue
-
- for key, value in widget_outputs.items():
-
- # We merge dictionaries by updating them so we have
- # the "mixed" values of both settings
- if isinstance(value, dict) and key in outputs:
- outputs[key].update(value)
- else:
- outputs[key] = value
-
- return outputs
-
- def get_inputs(self, as_preset=False):
- """Return the inputs per plug-in widgets by `plugin.id`.
-
- Returns:
- dict: The inputs per widget
-
- """
-
- inputs = dict()
- # Here we collect all the widgets from which we want to store the
- # current inputs. This will be restored in the next session
- # The preset widget is added to make sure the user starts with the
- # previously selected preset configuration
- config_widgets = self._get_plugin_widgets()
- config_widgets.append(self.presetwidget)
- for widget in config_widgets:
- widget_inputs = widget.get_inputs(as_preset=as_preset)
- if not isinstance(widget_inputs, dict):
- log.debug("Widget inputs are not a dictionary "
- "'{}': {}".format(widget.id, widget_inputs))
- return
-
- if not widget_inputs:
- continue
-
- inputs[widget.id] = widget_inputs
-
- return inputs
-
- def on_widget_settings_changed(self):
- """Set current preset to '*' on settings change"""
-
- self.options_changed.emit(self.get_outputs)
- self.presetwidget.presets.setCurrentIndex(0)
-
- def _build_configuration_dialog(self):
- """Build a configuration to store configuration widgets in"""
-
- dialog = QtWidgets.QDialog(self)
- dialog.setWindowTitle("Capture - Preset Configuration")
- QtWidgets.QVBoxLayout(dialog)
-
- self._config_dialog = dialog
-
- def _ensure_config_exist(self):
- """Create the configuration file if it does not exist yet.
-
- Returns:
- unicode: filepath of the configuration file
-
- """
-
- userdir = os.path.expanduser("~")
- capturegui_dir = os.path.join(userdir, "CaptureGUI")
- capturegui_inputs = os.path.join(capturegui_dir, "capturegui.json")
- if not os.path.exists(capturegui_dir):
- os.makedirs(capturegui_dir)
-
- if not os.path.isfile(capturegui_inputs):
- config = open(capturegui_inputs, "w")
- config.close()
-
- return capturegui_inputs
-
- def _store_widget_configuration(self):
- """Store all used widget settings in the local json file"""
-
- inputs = self.get_inputs(as_preset=False)
- path = self.settingfile
-
- with open(path, "w") as f:
- log.debug("Writing JSON file: {0}".format(path))
- json.dump(inputs, f, sort_keys=True,
- indent=4, separators=(',', ': '))
-
- def _read_widget_configuration(self):
- """Read the stored widget inputs"""
-
- inputs = {}
- path = self.settingfile
-
- if not os.path.isfile(path) or os.stat(path).st_size == 0:
- return inputs
-
- with open(path, "r") as f:
- log.debug("Reading JSON file: {0}".format(path))
- try:
- inputs = json.load(f)
- except ValueError as error:
- log.error(str(error))
-
- return inputs
-
- def _get_plugin_widgets(self):
- """List all plug-in widgets.
-
- Returns:
- list: The plug-in widgets in *all* sections
-
- """
-
- widgets = list()
- for section in self.plugins.values():
- widgets.extend(section)
-
- return widgets
-
- # override close event to ensure the input are stored
-
- def closeEvent(self, event):
- """Store current configuration upon closing the application."""
-
- self._store_widget_configuration()
- for section_widgets in self.plugins.values():
- for widget in section_widgets:
- widget.uninitialize()
-
- event.accept()
diff --git a/openpype/vendor/python/common/capture_gui/colorpicker.py b/openpype/vendor/python/common/capture_gui/colorpicker.py
deleted file mode 100644
index aa00a7386d..0000000000
--- a/openpype/vendor/python/common/capture_gui/colorpicker.py
+++ /dev/null
@@ -1,55 +0,0 @@
-from capture_gui.vendor.Qt import QtCore, QtWidgets, QtGui
-
-
-class ColorPicker(QtWidgets.QPushButton):
- """Custom color pick button to store and retrieve color values"""
-
- valueChanged = QtCore.Signal()
-
- def __init__(self):
- QtWidgets.QPushButton.__init__(self)
-
- self.clicked.connect(self.show_color_dialog)
- self._color = None
-
- self.color = [1, 1, 1]
-
- # region properties
- @property
- def color(self):
- return self._color
-
- @color.setter
- def color(self, values):
- """Set the color value and update the stylesheet
-
- Arguments:
- values (list): the color values; red, green, blue
-
- Returns:
- None
-
- """
- self._color = values
- self.valueChanged.emit()
-
- values = [int(x*255) for x in values]
- self.setStyleSheet("background: rgb({},{},{})".format(*values))
-
- # endregion properties
-
- def show_color_dialog(self):
- """Display a color picker to change color.
-
- When a color has been chosen this updates the color of the button
- and its current value
-
- :return: the red, green and blue values
- :rtype: list
- """
- current = QtGui.QColor()
- current.setRgbF(*self._color)
- colors = QtWidgets.QColorDialog.getColor(current)
- if not colors:
- return
- self.color = [colors.redF(), colors.greenF(), colors.blueF()]
diff --git a/openpype/vendor/python/common/capture_gui/lib.py b/openpype/vendor/python/common/capture_gui/lib.py
deleted file mode 100644
index 823ca8f7c8..0000000000
--- a/openpype/vendor/python/common/capture_gui/lib.py
+++ /dev/null
@@ -1,396 +0,0 @@
-# TODO: fetch Maya main window without shiboken that also doesn't crash
-
-import sys
-import logging
-import json
-import os
-import glob
-import subprocess
-import contextlib
-from collections import OrderedDict
-
-import datetime
-import maya.cmds as cmds
-import maya.mel as mel
-import maya.OpenMayaUI as omui
-import capture
-
-from .vendor.Qt import QtWidgets
-try:
- # PySide1
- import shiboken
-except ImportError:
- # PySide2
- import shiboken2 as shiboken
-
-log = logging.getLogger(__name__)
-
-# region Object types
-OBJECT_TYPES = OrderedDict()
-OBJECT_TYPES['NURBS Curves'] = 'nurbsCurves'
-OBJECT_TYPES['NURBS Surfaces'] = 'nurbsSurfaces'
-OBJECT_TYPES['NURBS CVs'] = 'controlVertices'
-OBJECT_TYPES['NURBS Hulls'] = 'hulls'
-OBJECT_TYPES['Polygons'] = 'polymeshes'
-OBJECT_TYPES['Subdiv Surfaces'] = 'subdivSurfaces'
-OBJECT_TYPES['Planes'] = 'planes'
-OBJECT_TYPES['Lights'] = 'lights'
-OBJECT_TYPES['Cameras'] = 'cameras'
-OBJECT_TYPES['Image Planes'] = 'imagePlane'
-OBJECT_TYPES['Joints'] = 'joints'
-OBJECT_TYPES['IK Handles'] = 'ikHandles'
-OBJECT_TYPES['Deformers'] = 'deformers'
-OBJECT_TYPES['Dynamics'] = 'dynamics'
-OBJECT_TYPES['Particle Instancers'] = 'particleInstancers'
-OBJECT_TYPES['Fluids'] = 'fluids'
-OBJECT_TYPES['Hair Systems'] = 'hairSystems'
-OBJECT_TYPES['Follicles'] = 'follicles'
-OBJECT_TYPES['nCloths'] = 'nCloths'
-OBJECT_TYPES['nParticles'] = 'nParticles'
-OBJECT_TYPES['nRigids'] = 'nRigids'
-OBJECT_TYPES['Dynamic Constraints'] = 'dynamicConstraints'
-OBJECT_TYPES['Locators'] = 'locators'
-OBJECT_TYPES['Dimensions'] = 'dimensions'
-OBJECT_TYPES['Pivots'] = 'pivots'
-OBJECT_TYPES['Handles'] = 'handles'
-OBJECT_TYPES['Textures Placements'] = 'textures'
-OBJECT_TYPES['Strokes'] = 'strokes'
-OBJECT_TYPES['Motion Trails'] = 'motionTrails'
-OBJECT_TYPES['Plugin Shapes'] = 'pluginShapes'
-OBJECT_TYPES['Clip Ghosts'] = 'clipGhosts'
-OBJECT_TYPES['Grease Pencil'] = 'greasePencils'
-OBJECT_TYPES['Manipulators'] = 'manipulators'
-OBJECT_TYPES['Grid'] = 'grid'
-OBJECT_TYPES['HUD'] = 'hud'
-# endregion Object types
-
-
-def get_show_object_types():
-
- results = OrderedDict()
-
- # Add the plug-in shapes
- plugin_shapes = get_plugin_shapes()
- results.update(plugin_shapes)
-
- # We add default shapes last so plug-in shapes could
- # never potentially overwrite any built-ins.
- results.update(OBJECT_TYPES)
-
- return results
-
-
-def get_current_scenename():
- path = cmds.file(query=True, sceneName=True)
- if path:
- return os.path.splitext(os.path.basename(path))[0]
- return None
-
-
-def get_current_camera():
- """Returns the currently active camera.
-
- Searched in the order of:
- 1. Active Panel
- 2. Selected Camera Shape
- 3. Selected Camera Transform
-
- Returns:
- str: name of active camera transform
-
- """
-
- # Get camera from active modelPanel (if any)
- panel = cmds.getPanel(withFocus=True)
- if cmds.getPanel(typeOf=panel) == "modelPanel":
- cam = cmds.modelEditor(panel, query=True, camera=True)
- # In some cases above returns the shape, but most often it returns the
- # transform. Still we need to make sure we return the transform.
- if cam:
- if cmds.nodeType(cam) == "transform":
- return cam
- # camera shape is a shape type
- elif cmds.objectType(cam, isAType="shape"):
- parent = cmds.listRelatives(cam, parent=True, fullPath=True)
- if parent:
- return parent[0]
-
- # Check if a camShape is selected (if so use that)
- cam_shapes = cmds.ls(selection=True, type="camera")
- if cam_shapes:
- return cmds.listRelatives(cam_shapes,
- parent=True,
- fullPath=True)[0]
-
- # Check if a transform of a camShape is selected
- # (return cam transform if any)
- transforms = cmds.ls(selection=True, type="transform")
- if transforms:
- cam_shapes = cmds.listRelatives(transforms, shapes=True, type="camera")
- if cam_shapes:
- return cmds.listRelatives(cam_shapes,
- parent=True,
- fullPath=True)[0]
-
-
-def get_active_editor():
- """Return the active editor panel to playblast with"""
- # fixes `cmds.playblast` undo bug
- cmds.currentTime(cmds.currentTime(query=True))
- panel = cmds.playblast(activeEditor=True)
- return panel.split("|")[-1]
-
-
-def get_current_frame():
- return cmds.currentTime(query=True)
-
-
-def get_time_slider_range(highlighted=True,
- withinHighlighted=True,
- highlightedOnly=False):
- """Return the time range from Maya's time slider.
-
- Arguments:
- highlighted (bool): When True if will return a selected frame range
- (if there's any selection of more than one frame!) otherwise it
- will return min and max playback time.
- withinHighlighted (bool): By default Maya returns the highlighted range
- end as a plus one value. When this is True this will be fixed by
- removing one from the last number.
-
- Returns:
- list: List of two floats of start and end frame numbers.
-
- """
- if highlighted is True:
- gPlaybackSlider = mel.eval("global string $gPlayBackSlider; "
- "$gPlayBackSlider = $gPlayBackSlider;")
- if cmds.timeControl(gPlaybackSlider, query=True, rangeVisible=True):
- highlightedRange = cmds.timeControl(gPlaybackSlider,
- query=True,
- rangeArray=True)
- if withinHighlighted:
- highlightedRange[-1] -= 1
- return highlightedRange
- if not highlightedOnly:
- return [cmds.playbackOptions(query=True, minTime=True),
- cmds.playbackOptions(query=True, maxTime=True)]
-
-
-def get_current_renderlayer():
- return cmds.editRenderLayerGlobals(query=True, currentRenderLayer=True)
-
-
-def get_plugin_shapes():
- """Get all currently available plugin shapes
-
- Returns:
- dict: plugin shapes by their menu label and script name
-
- """
- filters = cmds.pluginDisplayFilter(query=True, listFilters=True)
- labels = [cmds.pluginDisplayFilter(f, query=True, label=True) for f in
- filters]
- return OrderedDict(zip(labels, filters))
-
-
-def open_file(filepath):
- """Open file using OS default settings"""
- if sys.platform.startswith('darwin'):
- subprocess.call(('open', filepath))
- elif os.name == 'nt':
- os.startfile(filepath)
- elif os.name == 'posix':
- subprocess.call(('xdg-open', filepath))
- else:
- raise NotImplementedError("OS not supported: {0}".format(os.name))
-
-
-def load_json(filepath):
- """open and read json, return read values"""
- with open(filepath, "r") as f:
- return json.load(f)
-
-
-def _fix_playblast_output_path(filepath):
- """Workaround a bug in maya.cmds.playblast to return correct filepath.
-
- When the `viewer` argument is set to False and maya.cmds.playblast does not
- automatically open the playblasted file the returned filepath does not have
- the file's extension added correctly.
-
- To workaround this we just glob.glob() for any file extensions and assume
- the latest modified file is the correct file and return it.
-
- """
- # Catch cancelled playblast
- if filepath is None:
- log.warning("Playblast did not result in output path. "
- "Playblast is probably interrupted.")
- return
-
- # Fix: playblast not returning correct filename (with extension)
- # Lets assume the most recently modified file is the correct one.
- if not os.path.exists(filepath):
- directory = os.path.dirname(filepath)
- filename = os.path.basename(filepath)
- # check if the filepath is has frame based filename
- # example : capture.####.png
- parts = filename.split(".")
- if len(parts) == 3:
- query = os.path.join(directory, "{}.*.{}".format(parts[0],
- parts[-1]))
- files = glob.glob(query)
- else:
- files = glob.glob("{}.*".format(filepath))
-
- if not files:
- raise RuntimeError("Couldn't find playblast from: "
- "{0}".format(filepath))
- filepath = max(files, key=os.path.getmtime)
-
- return filepath
-
-
-def capture_scene(options):
- """Capture using scene settings.
-
- Uses the view settings from "panel".
-
- This ensures playblast is done as quicktime H.264 100% quality.
- It forces showOrnaments to be off and does not render off screen.
-
- Arguments:
- options (dict): a collection of output options
-
- Returns:
- str: Full path to playblast file.
-
- """
-
- filename = options.get("filename", "%TEMP%")
- log.info("Capturing to: {0}".format(filename))
-
- options = options.copy()
-
- # Force viewer to False in call to capture because we have our own
- # viewer opening call to allow a signal to trigger between playblast
- # and viewer
- options['viewer'] = False
-
- # Remove panel key since it's internal value to capture_gui
- options.pop("panel", None)
-
- path = capture.capture(**options)
- path = _fix_playblast_output_path(path)
-
- return path
-
-
-def browse(path=None):
- """Open a pop-up browser for the user"""
-
- # Acquire path from user input if none defined
- if path is None:
-
- scene_path = cmds.file(query=True, sceneName=True)
-
- # use scene file name as default name
- default_filename = os.path.splitext(os.path.basename(scene_path))[0]
- if not default_filename:
- # Scene wasn't saved yet so found no valid name for playblast.
- default_filename = "playblast"
-
- # Default to images rule
- default_root = os.path.normpath(get_project_rule("images"))
- default_path = os.path.join(default_root, default_filename)
- path = cmds.fileDialog2(fileMode=0,
- dialogStyle=2,
- startingDirectory=default_path)
-
- if not path:
- return
-
- if isinstance(path, (tuple, list)):
- path = path[0]
-
- if path.endswith(".*"):
- path = path[:-2]
-
- # Bug-Fix/Workaround:
- # Fix for playblasts that result in nesting of the
- # extension (eg. '.mov.mov.mov') which happens if the format
- # is defined in the filename used for saving.
- extension = os.path.splitext(path)[-1]
- if extension:
- path = path[:-len(extension)]
-
- return path
-
-
-def default_output():
- """Return filename based on current scene name.
-
- Returns:
- str: A relative filename
-
- """
-
- scene = get_current_scenename() or "playblast"
-
- # get current datetime
- timestamp = datetime.datetime.today()
- str_timestamp = timestamp.strftime("%Y-%m-%d_%H-%M-%S")
- filename = "{}_{}".format(scene, str_timestamp)
-
- return filename
-
-
-def get_project_rule(rule):
- """Get the full path of the rule of the project"""
-
- workspace = cmds.workspace(query=True, rootDirectory=True)
- folder = cmds.workspace(fileRuleEntry=rule)
- if not folder:
- log.warning("File Rule Entry '{}' has no value, please check if the "
- "rule name is typed correctly".format(rule))
-
- return os.path.join(workspace, folder)
-
-
-def list_formats():
- # Workaround for Maya playblast bug where undo would
- # move the currentTime to frame one.
- cmds.currentTime(cmds.currentTime(query=True))
- return cmds.playblast(query=True, format=True)
-
-
-def list_compressions(format='avi'):
- # Workaround for Maya playblast bug where undo would
- # move the currentTime to frame one.
- cmds.currentTime(cmds.currentTime(query=True))
-
- cmd = 'playblast -format "{0}" -query -compression'.format(format)
- return mel.eval(cmd)
-
-
-@contextlib.contextmanager
-def no_undo():
- """Disable undo during the context"""
- try:
- cmds.undoInfo(stateWithoutFlush=False)
- yield
- finally:
- cmds.undoInfo(stateWithoutFlush=True)
-
-
-def get_maya_main_window():
- """Get the main Maya window as a QtGui.QMainWindow instance
-
- Returns:
- QtGui.QMainWindow: instance of the top level Maya windows
-
- """
- ptr = omui.MQtUtil.mainWindow()
- if ptr is not None:
- return shiboken.wrapInstance(long(ptr), QtWidgets.QWidget)
diff --git a/openpype/vendor/python/common/capture_gui/plugin.py b/openpype/vendor/python/common/capture_gui/plugin.py
deleted file mode 100644
index 7d087936d7..0000000000
--- a/openpype/vendor/python/common/capture_gui/plugin.py
+++ /dev/null
@@ -1,401 +0,0 @@
-"""Plug-in system
-
-Works similar to how OSs look for executables; i.e. a number of
-absolute paths are searched for a given match. The predicate for
-executables is whether or not an extension matches a number of
-options, such as ".exe" or ".bat".
-
-In this system, the predicate is whether or not a fname ends with ".py"
-
-"""
-
-# Standard library
-import os
-import sys
-import types
-import logging
-import inspect
-
-from .vendor.Qt import QtCore, QtWidgets
-
-log = logging.getLogger(__name__)
-
-_registered_paths = list()
-_registered_plugins = dict()
-
-
-class classproperty(object):
- def __init__(self, getter):
- self.getter = getter
-
- def __get__(self, instance, owner):
- return self.getter(owner)
-
-
-class Plugin(QtWidgets.QWidget):
- """Base class for Option plug-in Widgets.
-
- This is a regular Qt widget that can be added to the capture interface
- as an additional component, like a plugin.
-
- The plug-ins are sorted in the interface by their `order` attribute and
- will be displayed in the main interface when `section` is set to "app"
- and displayed in the additional settings pop-up when set to "config".
-
- When `hidden` is set to True the widget will not be shown in the interface.
- This could be useful as a plug-in that supplies solely default values to
- the capture GUI command.
-
- """
-
- label = ""
- section = "app" # "config" or "app"
- hidden = False
- options_changed = QtCore.Signal()
- label_changed = QtCore.Signal(str)
- order = 0
- highlight = "border: 1px solid red;"
- validate_state = True
-
- def on_playblast_finished(self, options):
- pass
-
- def validate(self):
- """
- Ensure outputs of the widget are possible, when errors are raised it
- will return a message with what has caused the error
- :return:
- """
- errors = []
- return errors
-
- def get_outputs(self):
- """Return the options as set in this plug-in widget.
-
- This is used to identify the settings to be used for the playblast.
- As such the values should be returned in a way that a call to
- `capture.capture()` would understand as arguments.
-
- Args:
- panel (str): The active modelPanel of the user. This is passed so
- values could potentially be parsed from the active panel
-
- Returns:
- dict: The options for this plug-in. (formatted `capture` style)
-
- """
- return dict()
-
- def get_inputs(self, as_preset):
- """Return widget's child settings.
-
- This should provide a dictionary of input settings of the plug-in
- that results in a dictionary that can be supplied to `apply_input()`
- This is used to save the settings of the preset to a widget.
-
- :param as_preset:
- :param as_presets: Toggle to mute certain input values of the widget
- :type as_presets: bool
-
- Returns:
- dict: The currently set inputs of this widget.
-
- """
- return dict()
-
- def apply_inputs(self, settings):
- """Apply a dictionary of settings to the widget.
-
- This should update the widget's inputs to the settings provided in
- the dictionary. This is used to apply settings from a preset.
-
- Returns:
- None
-
- """
- pass
-
- def initialize(self):
- """
- This method is used to register any callbacks
- :return:
- """
- pass
-
- def uninitialize(self):
- """
- Unregister any callback created when deleting the widget
-
- A general explation:
-
- The deletion method is an attribute that lives inside the object to be
- deleted, and that is the problem:
- Destruction seems not to care about the order of destruction,
- and the __dict__ that also holds the onDestroy bound method
- gets destructed before it is called.
-
- Another solution is to use a weakref
-
- :return: None
- """
- pass
-
- def __str__(self):
- return self.label or type(self).__name__
-
- def __repr__(self):
- return u"%s.%s(%r)" % (__name__, type(self).__name__, self.__str__())
-
- id = classproperty(lambda cls: cls.__name__)
-
-
-def register_plugin_path(path):
- """Plug-ins are looked up at run-time from directories registered here
-
- To register a new directory, run this command along with the absolute
- path to where you"re plug-ins are located.
-
- Example:
- >>> import os
- >>> my_plugins = "/server/plugins"
- >>> register_plugin_path(my_plugins)
- '/server/plugins'
-
- Returns:
- Actual path added, including any post-processing
-
- """
-
- if path in _registered_paths:
- return log.warning("Path already registered: {0}".format(path))
-
- _registered_paths.append(path)
-
- return path
-
-
-def deregister_plugin_path(path):
- """Remove a _registered_paths path
-
- Raises:
- KeyError if `path` isn't registered
-
- """
-
- _registered_paths.remove(path)
-
-
-def deregister_all_plugin_paths():
- """Mainly used in tests"""
- _registered_paths[:] = []
-
-
-def registered_plugin_paths():
- """Return paths added via registration
-
- ..note:: This returns a copy of the registered paths
- and can therefore not be modified directly.
-
- """
-
- return list(_registered_paths)
-
-
-def registered_plugins():
- """Return plug-ins added via :func:`register_plugin`
-
- .. note:: This returns a copy of the registered plug-ins
- and can therefore not be modified directly
-
- """
-
- return _registered_plugins.values()
-
-
-def register_plugin(plugin):
- """Register a new plug-in
-
- Arguments:
- plugin (Plugin): Plug-in to register
-
- Raises:
- TypeError if `plugin` is not callable
-
- """
-
- if not hasattr(plugin, "__call__"):
- raise TypeError("Plug-in must be callable "
- "returning an instance of a class")
-
- if not plugin_is_valid(plugin):
- raise TypeError("Plug-in invalid: %s", plugin)
-
- _registered_plugins[plugin.__name__] = plugin
-
-
-def plugin_paths():
- """Collect paths from all sources.
-
- This function looks at the three potential sources of paths
- and returns a list with all of them together.
-
- The sources are:
-
- - Registered paths using :func:`register_plugin_path`
-
- Returns:
- list of paths in which plugins may be locat
-
- """
-
- paths = list()
-
- for path in registered_plugin_paths():
- if path in paths:
- continue
- paths.append(path)
-
- return paths
-
-
-def discover(paths=None):
- """Find and return available plug-ins
-
- This function looks for files within paths registered via
- :func:`register_plugin_path`.
-
- Arguments:
- paths (list, optional): Paths to discover plug-ins from.
- If no paths are provided, all paths are searched.
-
- """
-
- plugins = dict()
-
- # Include plug-ins from registered paths
- for path in paths or plugin_paths():
- path = os.path.normpath(path)
-
- if not os.path.isdir(path):
- continue
-
- for fname in os.listdir(path):
- if fname.startswith("_"):
- continue
-
- abspath = os.path.join(path, fname)
-
- if not os.path.isfile(abspath):
- continue
-
- mod_name, mod_ext = os.path.splitext(fname)
-
- if not mod_ext == ".py":
- continue
-
- module = types.ModuleType(mod_name)
- module.__file__ = abspath
-
- try:
- execfile(abspath, module.__dict__)
-
- # Store reference to original module, to avoid
- # garbage collection from collecting it's global
- # imports, such as `import os`.
- sys.modules[mod_name] = module
-
- except Exception as err:
- log.debug("Skipped: \"%s\" (%s)", mod_name, err)
- continue
-
- for plugin in plugins_from_module(module):
- if plugin.id in plugins:
- log.debug("Duplicate plug-in found: %s", plugin)
- continue
-
- plugins[plugin.id] = plugin
-
- # Include plug-ins from registration.
- # Directly registered plug-ins take precedence.
- for name, plugin in _registered_plugins.items():
- if name in plugins:
- log.debug("Duplicate plug-in found: %s", plugin)
- continue
- plugins[name] = plugin
-
- plugins = list(plugins.values())
- sort(plugins) # In-place
-
- return plugins
-
-
-def plugins_from_module(module):
- """Return plug-ins from module
-
- Arguments:
- module (types.ModuleType): Imported module from which to
- parse valid plug-ins.
-
- Returns:
- List of plug-ins, or empty list if none is found.
-
- """
-
- plugins = list()
-
- for name in dir(module):
- if name.startswith("_"):
- continue
-
- # It could be anything at this point
- obj = getattr(module, name)
-
- if not inspect.isclass(obj):
- continue
-
- if not issubclass(obj, Plugin):
- continue
-
- if not plugin_is_valid(obj):
- log.debug("Plug-in invalid: %s", obj)
- continue
-
- plugins.append(obj)
-
- return plugins
-
-
-def plugin_is_valid(plugin):
- """Determine whether or not plug-in `plugin` is valid
-
- Arguments:
- plugin (Plugin): Plug-in to assess
-
- """
-
- if not plugin:
- return False
-
- return True
-
-
-def sort(plugins):
- """Sort `plugins` in-place
-
- Their order is determined by their `order` attribute.
-
- Arguments:
- plugins (list): Plug-ins to sort
-
- """
-
- if not isinstance(plugins, list):
- raise TypeError("plugins must be of type list")
-
- plugins.sort(key=lambda p: p.order)
- return plugins
-
-
-# Register default paths
-default_plugins_path = os.path.join(os.path.dirname(__file__), "plugins")
-register_plugin_path(default_plugins_path)
diff --git a/openpype/vendor/python/common/capture_gui/plugins/cameraplugin.py b/openpype/vendor/python/common/capture_gui/plugins/cameraplugin.py
deleted file mode 100644
index 1902330622..0000000000
--- a/openpype/vendor/python/common/capture_gui/plugins/cameraplugin.py
+++ /dev/null
@@ -1,141 +0,0 @@
-import maya.cmds as cmds
-from capture_gui.vendor.Qt import QtCore, QtWidgets
-
-import capture_gui.lib as lib
-import capture_gui.plugin
-
-
-class CameraPlugin(capture_gui.plugin.Plugin):
- """Camera widget.
-
- Allows to select a camera.
-
- """
- id = "Camera"
- section = "app"
- order = 10
-
- def __init__(self, parent=None):
- super(CameraPlugin, self).__init__(parent=parent)
-
- self._layout = QtWidgets.QHBoxLayout()
- self._layout.setContentsMargins(5, 0, 5, 0)
- self.setLayout(self._layout)
-
- self.cameras = QtWidgets.QComboBox()
- self.cameras.setMinimumWidth(200)
-
- self.get_active = QtWidgets.QPushButton("Get active")
- self.get_active.setToolTip("Set camera from currently active view")
- self.refresh = QtWidgets.QPushButton("Refresh")
- self.refresh.setToolTip("Refresh the list of cameras")
-
- self._layout.addWidget(self.cameras)
- self._layout.addWidget(self.get_active)
- self._layout.addWidget(self.refresh)
-
- # Signals
- self.connections()
-
- # Force update of the label
- self.set_active_cam()
- self.on_update_label()
-
- def connections(self):
- self.get_active.clicked.connect(self.set_active_cam)
- self.refresh.clicked.connect(self.on_refresh)
-
- self.cameras.currentIndexChanged.connect(self.on_update_label)
- self.cameras.currentIndexChanged.connect(self.validate)
-
- def set_active_cam(self):
- cam = lib.get_current_camera()
- self.on_refresh(camera=cam)
-
- def select_camera(self, cam):
- if cam:
- # Ensure long name
- cameras = cmds.ls(cam, long=True)
- if not cameras:
- return
- cam = cameras[0]
-
- # Find the index in the list
- for i in range(self.cameras.count()):
- value = str(self.cameras.itemText(i))
- if value == cam:
- self.cameras.setCurrentIndex(i)
- return
-
- def validate(self):
-
- errors = []
- camera = self.cameras.currentText()
- if not cmds.objExists(camera):
- errors.append("{} : Selected camera '{}' "
- "does not exist!".format(self.id, camera))
- self.cameras.setStyleSheet(self.highlight)
- else:
- self.cameras.setStyleSheet("")
-
- return errors
-
- def get_outputs(self):
- """Return currently selected camera from combobox."""
-
- idx = self.cameras.currentIndex()
- camera = str(self.cameras.itemText(idx)) if idx != -1 else None
-
- return {"camera": camera}
-
- def on_refresh(self, camera=None):
- """Refresh the camera list with all current cameras in scene.
-
- A currentIndexChanged signal is only emitted for the cameras combobox
- when the camera is different at the end of the refresh.
-
- Args:
- camera (str): When name of camera is passed it will try to select
- the camera with this name after the refresh.
-
- Returns:
- None
-
- """
-
- cam = self.get_outputs()['camera']
-
- # Get original selection
- if camera is None:
- index = self.cameras.currentIndex()
- if index != -1:
- camera = self.cameras.currentText()
-
- self.cameras.blockSignals(True)
-
- # Update the list with available cameras
- self.cameras.clear()
-
- cam_shapes = cmds.ls(type="camera")
- cam_transforms = cmds.listRelatives(cam_shapes,
- parent=True,
- fullPath=True)
- self.cameras.addItems(cam_transforms)
-
- # If original selection, try to reselect
- self.select_camera(camera)
-
- self.cameras.blockSignals(False)
-
- # If camera changed emit signal
- if cam != self.get_outputs()['camera']:
- idx = self.cameras.currentIndex()
- self.cameras.currentIndexChanged.emit(idx)
-
- def on_update_label(self):
-
- cam = self.cameras.currentText()
- cam = cam.rsplit("|", 1)[-1] # ensure short name
- self.label = "Camera ({0})".format(cam)
-
- self.label_changed.emit(self.label)
diff --git a/openpype/vendor/python/common/capture_gui/plugins/codecplugin.py b/openpype/vendor/python/common/capture_gui/plugins/codecplugin.py
deleted file mode 100644
index 694194aafe..0000000000
--- a/openpype/vendor/python/common/capture_gui/plugins/codecplugin.py
+++ /dev/null
@@ -1,95 +0,0 @@
-from capture_gui.vendor.Qt import QtCore, QtWidgets
-
-import capture_gui.lib as lib
-import capture_gui.plugin
-
-
-class CodecPlugin(capture_gui.plugin.Plugin):
- """Codec widget.
-
- Allows to set format, compression and quality.
-
- """
- id = "Codec"
- label = "Codec"
- section = "config"
- order = 50
-
- def __init__(self, parent=None):
- super(CodecPlugin, self).__init__(parent=parent)
-
- self._layout = QtWidgets.QHBoxLayout()
- self._layout.setContentsMargins(0, 0, 0, 0)
- self.setLayout(self._layout)
-
- self.format = QtWidgets.QComboBox()
- self.compression = QtWidgets.QComboBox()
- self.quality = QtWidgets.QSpinBox()
- self.quality.setMinimum(0)
- self.quality.setMaximum(100)
- self.quality.setValue(100)
- self.quality.setToolTip("Compression quality percentage")
-
- self._layout.addWidget(self.format)
- self._layout.addWidget(self.compression)
- self._layout.addWidget(self.quality)
-
- self.format.currentIndexChanged.connect(self.on_format_changed)
-
- self.refresh()
-
- # Default to format 'qt'
- index = self.format.findText("qt")
- if index != -1:
- self.format.setCurrentIndex(index)
-
- # Default to compression 'H.264'
- index = self.compression.findText("H.264")
- if index != -1:
- self.compression.setCurrentIndex(index)
-
- self.connections()
-
- def connections(self):
- self.compression.currentIndexChanged.connect(self.options_changed)
- self.format.currentIndexChanged.connect(self.options_changed)
- self.quality.valueChanged.connect(self.options_changed)
-
- def refresh(self):
- formats = sorted(lib.list_formats())
- self.format.clear()
- self.format.addItems(formats)
-
- def on_format_changed(self):
- """Refresh the available compressions."""
-
- format = self.format.currentText()
- compressions = lib.list_compressions(format)
- self.compression.clear()
- self.compression.addItems(compressions)
-
- def get_outputs(self):
- """Get the plugin outputs that matches `capture.capture` arguments
-
- Returns:
- dict: Plugin outputs
-
- """
-
- return {"format": self.format.currentText(),
- "compression": self.compression.currentText(),
- "quality": self.quality.value()}
-
- def get_inputs(self, as_preset):
- # a bit redundant but it will work when iterating over widgets
- # so we don't have to write an exception
- return self.get_outputs()
-
- def apply_inputs(self, settings):
- codec_format = settings.get("format", 0)
- compr = settings.get("compression", 4)
- quality = settings.get("quality", 100)
-
- self.format.setCurrentIndex(self.format.findText(codec_format))
- self.compression.setCurrentIndex(self.compression.findText(compr))
- self.quality.setValue(int(quality))
diff --git a/openpype/vendor/python/common/capture_gui/plugins/defaultoptionsplugin.py b/openpype/vendor/python/common/capture_gui/plugins/defaultoptionsplugin.py
deleted file mode 100644
index f56897e562..0000000000
--- a/openpype/vendor/python/common/capture_gui/plugins/defaultoptionsplugin.py
+++ /dev/null
@@ -1,47 +0,0 @@
-import capture
-import capture_gui.plugin
-
-
-class DefaultOptionsPlugin(capture_gui.plugin.Plugin):
- """Invisible Plugin that supplies some default values to the gui.
-
- This enures:
- - no HUD is present in playblasts
- - no overscan (`overscan` set to 1.0)
- - no title safe, action safe, gate mask, etc.
- - active sound is included in video playblasts
-
- """
- order = -1
- hidden = True
-
- def get_outputs(self):
- """Get the plugin outputs that matches `capture.capture` arguments
-
- Returns:
- dict: Plugin outputs
-
- """
-
- outputs = dict()
-
- # use active sound track
- scene = capture.parse_active_scene()
- outputs['sound'] = scene['sound']
-
- # override default settings
- outputs['show_ornaments'] = True # never show HUD or overlays
-
- # override camera options
- outputs['camera_options'] = dict()
- outputs['camera_options']['overscan'] = 1.0
- outputs['camera_options']['displayFieldChart'] = False
- outputs['camera_options']['displayFilmGate'] = False
- outputs['camera_options']['displayFilmOrigin'] = False
- outputs['camera_options']['displayFilmPivot'] = False
- outputs['camera_options']['displayGateMask'] = False
- outputs['camera_options']['displayResolution'] = False
- outputs['camera_options']['displaySafeAction'] = False
- outputs['camera_options']['displaySafeTitle'] = False
-
- return outputs
diff --git a/openpype/vendor/python/common/capture_gui/plugins/displayplugin.py b/openpype/vendor/python/common/capture_gui/plugins/displayplugin.py
deleted file mode 100644
index 3dffb98654..0000000000
--- a/openpype/vendor/python/common/capture_gui/plugins/displayplugin.py
+++ /dev/null
@@ -1,179 +0,0 @@
-import maya.cmds as cmds
-
-from capture_gui.vendor.Qt import QtCore, QtWidgets
-import capture_gui.plugin
-import capture_gui.colorpicker as colorpicker
-
-
-# region GLOBALS
-
-BACKGROUND_DEFAULT = [0.6309999823570251,
- 0.6309999823570251,
- 0.6309999823570251]
-
-TOP_DEFAULT = [0.5350000262260437,
- 0.6169999837875366,
- 0.7020000219345093]
-
-BOTTOM_DEFAULT = [0.052000001072883606,
- 0.052000001072883606,
- 0.052000001072883606]
-
-COLORS = {"background": BACKGROUND_DEFAULT,
- "backgroundTop": TOP_DEFAULT,
- "backgroundBottom": BOTTOM_DEFAULT}
-
-LABELS = {"background": "Background",
- "backgroundTop": "Top",
- "backgroundBottom": "Bottom"}
-# endregion GLOBALS
-
-
-class DisplayPlugin(capture_gui.plugin.Plugin):
- """Plugin to apply viewport visibilities and settings"""
-
- id = "Display Options"
- label = "Display Options"
- section = "config"
- order = 70
-
- def __init__(self, parent=None):
- super(DisplayPlugin, self).__init__(parent=parent)
-
- self._colors = dict()
-
- self._layout = QtWidgets.QVBoxLayout()
- self._layout.setContentsMargins(0, 0, 0, 0)
- self.setLayout(self._layout)
-
- self.override = QtWidgets.QCheckBox("Override Display Options")
-
- self.display_type = QtWidgets.QComboBox()
- self.display_type.addItems(["Solid", "Gradient"])
-
- # create color columns
- self._color_layout = QtWidgets.QHBoxLayout()
- for label, default in COLORS.items():
- self.add_color_picker(self._color_layout, label, default)
-
- # populate layout
- self._layout.addWidget(self.override)
- self._layout.addWidget(self.display_type)
- self._layout.addLayout(self._color_layout)
-
- # ensure widgets are in the correct enable state
- self.on_toggle_override()
-
- self.connections()
-
- def connections(self):
- self.override.toggled.connect(self.on_toggle_override)
- self.override.toggled.connect(self.options_changed)
- self.display_type.currentIndexChanged.connect(self.options_changed)
-
- def add_color_picker(self, layout, label, default):
- """Create a column with a label and a button to select a color
-
- Arguments:
- layout (QtWidgets.QLayout): Layout to add color picker to
- label (str): system name for the color type, e.g. : backgroundTop
- default (list): The default color values to start with
-
- Returns:
- colorpicker.ColorPicker: a color picker instance
-
- """
-
- column = QtWidgets.QVBoxLayout()
- label_widget = QtWidgets.QLabel(LABELS[label])
-
- color_picker = colorpicker.ColorPicker()
- color_picker.color = default
-
- column.addWidget(label_widget)
- column.addWidget(color_picker)
-
- column.setAlignment(label_widget, QtCore.Qt.AlignCenter)
-
- layout.addLayout(column)
-
- # connect signal
- color_picker.valueChanged.connect(self.options_changed)
-
- # store widget
- self._colors[label] = color_picker
-
- return color_picker
-
- def on_toggle_override(self):
- """Callback when override is toggled.
-
- Enable or disable the color pickers and background type widgets bases
- on the current state of the override checkbox
-
- Returns:
- None
-
- """
- state = self.override.isChecked()
- self.display_type.setEnabled(state)
- for widget in self._colors.values():
- widget.setEnabled(state)
-
- def display_gradient(self):
- """Return whether the background should be displayed as gradient.
-
- When True the colors will use the top and bottom color to define the
- gradient otherwise the background color will be used as solid color.
-
- Returns:
- bool: Whether background is gradient
-
- """
- return self.display_type.currentText() == "Gradient"
-
- def apply_inputs(self, settings):
- """Apply the saved inputs from the inputs configuration
-
- Arguments:
- settings (dict): The input settings to apply.
-
- """
-
- for label, widget in self._colors.items():
- default = COLORS.get(label, [0, 0, 0]) # fallback default to black
- value = settings.get(label, default)
- widget.color = value
-
- override = settings.get("override_display", False)
- self.override.setChecked(override)
-
- def get_inputs(self, as_preset):
- inputs = {"override_display": self.override.isChecked()}
- for label, widget in self._colors.items():
- inputs[label] = widget.color
-
- return inputs
-
- def get_outputs(self):
- """Get the plugin outputs that matches `capture.capture` arguments
-
- Returns:
- dict: Plugin outputs
-
- """
-
- outputs = {}
- if self.override.isChecked():
- outputs["displayGradient"] = self.display_gradient()
- for label, widget in self._colors.items():
- outputs[label] = widget.color
- else:
- # Parse active color settings
- outputs["displayGradient"] = cmds.displayPref(query=True,
- displayGradient=True)
- for key in COLORS.keys():
- color = cmds.displayRGBColor(key, query=True)
- outputs[key] = color
-
- return {"display_options": outputs}
diff --git a/openpype/vendor/python/common/capture_gui/plugins/genericplugin.py b/openpype/vendor/python/common/capture_gui/plugins/genericplugin.py
deleted file mode 100644
index a43d43f3cc..0000000000
--- a/openpype/vendor/python/common/capture_gui/plugins/genericplugin.py
+++ /dev/null
@@ -1,95 +0,0 @@
-import maya.cmds as mc
-from capture_gui.vendor.Qt import QtCore, QtWidgets
-
-import capture_gui.plugin
-import capture_gui.lib
-
-
-class GenericPlugin(capture_gui.plugin.Plugin):
- """Widget for generic options"""
- id = "Generic"
- label = "Generic"
- section = "config"
- order = 100
-
- def __init__(self, parent=None):
- super(GenericPlugin, self).__init__(parent=parent)
-
- layout = QtWidgets.QVBoxLayout(self)
- layout.setContentsMargins(0, 0, 0, 0)
- self.setLayout(layout)
-
- isolate_view = QtWidgets.QCheckBox(
- "Use isolate view from active panel")
- off_screen = QtWidgets.QCheckBox("Render offscreen")
-
- layout.addWidget(isolate_view)
- layout.addWidget(off_screen)
-
- isolate_view.stateChanged.connect(self.options_changed)
- off_screen.stateChanged.connect(self.options_changed)
-
- self.widgets = {
- "off_screen": off_screen,
- "isolate_view": isolate_view
- }
-
- self.apply_inputs(self.get_defaults())
-
- def get_defaults(self):
- return {
- "off_screen": True,
- "isolate_view": False
- }
-
- def get_inputs(self, as_preset):
- """Return the widget options
-
- Returns:
- dict: The input settings of the widgets.
-
- """
-
- inputs = dict()
- for key, widget in self.widgets.items():
- state = widget.isChecked()
- inputs[key] = state
-
- return inputs
-
- def apply_inputs(self, inputs):
- """Apply the saved inputs from the inputs configuration
-
- Arguments:
- inputs (dict): The input settings to apply.
-
- """
-
- for key, widget in self.widgets.items():
- state = inputs.get(key, None)
- if state is not None:
- widget.setChecked(state)
-
- return inputs
-
- def get_outputs(self):
- """Returns all the options from the widget
-
- Returns: dictionary with the settings
-
- """
-
- inputs = self.get_inputs(as_preset=False)
- outputs = dict()
- outputs['off_screen'] = inputs['off_screen']
-
- import capture_gui.lib
-
- # Get isolate view members of the active panel
- if inputs['isolate_view']:
- panel = capture_gui.lib.get_active_editor()
- filter_set = mc.modelEditor(panel, query=True, viewObjects=True)
- isolate = mc.sets(filter_set, query=True) if filter_set else None
- outputs['isolate'] = isolate
-
- return outputs
diff --git a/openpype/vendor/python/common/capture_gui/plugins/ioplugin.py b/openpype/vendor/python/common/capture_gui/plugins/ioplugin.py
deleted file mode 100644
index defdc190df..0000000000
--- a/openpype/vendor/python/common/capture_gui/plugins/ioplugin.py
+++ /dev/null
@@ -1,254 +0,0 @@
-import os
-import logging
-from functools import partial
-
-from capture_gui.vendor.Qt import QtCore, QtWidgets
-from capture_gui import plugin, lib
-from capture_gui import tokens
-
-log = logging.getLogger("IO")
-
-
-class IoAction(QtWidgets.QAction):
-
- def __init__(self, parent, filepath):
- super(IoAction, self).__init__(parent)
-
- action_label = os.path.basename(filepath)
-
- self.setText(action_label)
- self.setData(filepath)
-
- # check if file exists and disable when false
- self.setEnabled(os.path.isfile(filepath))
-
- # get icon from file
- info = QtCore.QFileInfo(filepath)
- icon_provider = QtWidgets.QFileIconProvider()
- self.setIcon(icon_provider.icon(info))
-
- self.triggered.connect(self.open_object_data)
-
- def open_object_data(self):
- lib.open_file(self.data())
-
-
-class IoPlugin(plugin.Plugin):
- """Codec widget.
-
- Allows to set format, compression and quality.
-
- """
- id = "IO"
- label = "Save"
- section = "app"
- order = 40
- max_recent_playblasts = 5
-
- def __init__(self, parent=None):
- super(IoPlugin, self).__init__(parent=parent)
-
- self.recent_playblasts = list()
-
- self._layout = QtWidgets.QVBoxLayout()
- self._layout.setContentsMargins(0, 0, 0, 0)
- self.setLayout(self._layout)
-
- # region Checkboxes
- self.save_file = QtWidgets.QCheckBox(text="Save")
- self.open_viewer = QtWidgets.QCheckBox(text="View when finished")
- self.raw_frame_numbers = QtWidgets.QCheckBox(text="Raw frame numbers")
-
- checkbox_hlayout = QtWidgets.QHBoxLayout()
- checkbox_hlayout.setContentsMargins(5, 0, 5, 0)
- checkbox_hlayout.addWidget(self.save_file)
- checkbox_hlayout.addWidget(self.open_viewer)
- checkbox_hlayout.addWidget(self.raw_frame_numbers)
- checkbox_hlayout.addStretch(True)
- # endregion Checkboxes
-
- # region Path
- self.path_widget = QtWidgets.QWidget()
-
- self.browse = QtWidgets.QPushButton("Browse")
- self.file_path = QtWidgets.QLineEdit()
- self.file_path.setPlaceholderText("(not set; using scene name)")
- tip = "Right click in the text field to insert tokens"
- self.file_path.setToolTip(tip)
- self.file_path.setStatusTip(tip)
- self.file_path.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
- self.file_path.customContextMenuRequested.connect(self.show_token_menu)
-
- path_hlayout = QtWidgets.QHBoxLayout()
- path_hlayout.setContentsMargins(0, 0, 0, 0)
- path_label = QtWidgets.QLabel("Path:")
- path_label.setFixedWidth(30)
-
- path_hlayout.addWidget(path_label)
- path_hlayout.addWidget(self.file_path)
- path_hlayout.addWidget(self.browse)
- self.path_widget.setLayout(path_hlayout)
- # endregion Path
-
- # region Recent Playblast
- self.play_recent = QtWidgets.QPushButton("Play recent playblast")
- self.recent_menu = QtWidgets.QMenu()
- self.play_recent.setMenu(self.recent_menu)
- # endregion Recent Playblast
-
- self._layout.addLayout(checkbox_hlayout)
- self._layout.addWidget(self.path_widget)
- self._layout.addWidget(self.play_recent)
-
- # Signals / connections
- self.browse.clicked.connect(self.show_browse_dialog)
- self.file_path.textChanged.connect(self.options_changed)
- self.save_file.stateChanged.connect(self.options_changed)
- self.raw_frame_numbers.stateChanged.connect(self.options_changed)
- self.save_file.stateChanged.connect(self.on_save_changed)
-
- # Ensure state is up-to-date with current settings
- self.on_save_changed()
-
- def on_save_changed(self):
- """Update the visibility of the path field"""
-
- state = self.save_file.isChecked()
- if state:
- self.path_widget.show()
- else:
- self.path_widget.hide()
-
- def show_browse_dialog(self):
- """Set the filepath using a browser dialog.
-
- :return: None
- """
-
- path = lib.browse()
- if not path:
- return
-
- # Maya's browser return Linux based file paths to ensure Windows is
- # supported we use normpath
- path = os.path.normpath(path)
-
- self.file_path.setText(path)
-
- def add_playblast(self, item):
- """
- Add an item to the previous playblast menu
-
- :param item: full path to a playblast file
- :type item: str
-
- :return: None
- """
-
- # If item already in the recent playblasts remove it so we are
- # sure to add it as the new first most-recent
- try:
- self.recent_playblasts.remove(item)
- except ValueError:
- pass
-
- # Add as first in the recent playblasts
- self.recent_playblasts.insert(0, item)
-
- # Ensure the playblast list is never longer than maximum amount
- # by removing the older entries that are at the end of the list
- if len(self.recent_playblasts) > self.max_recent_playblasts:
- del self.recent_playblasts[self.max_recent_playblasts:]
-
- # Rebuild the actions menu
- self.recent_menu.clear()
- for playblast in self.recent_playblasts:
- action = IoAction(parent=self, filepath=playblast)
- self.recent_menu.addAction(action)
-
- def on_playblast_finished(self, options):
- """Take action after the play blast is done"""
- playblast_file = options['filename']
- if not playblast_file:
- return
- self.add_playblast(playblast_file)
-
- def get_outputs(self):
- """Get the plugin outputs that matches `capture.capture` arguments
-
- Returns:
- dict: Plugin outputs
-
- """
-
- output = {"filename": None,
- "raw_frame_numbers": self.raw_frame_numbers.isChecked(),
- "viewer": self.open_viewer.isChecked()}
-
- save = self.save_file.isChecked()
- if not save:
- return output
-
- # get path, if nothing is set fall back to default
- # project/images/playblast
- path = self.file_path.text()
- if not path:
- path = lib.default_output()
-
- output["filename"] = path
-
- return output
-
- def get_inputs(self, as_preset):
- inputs = {"name": self.file_path.text(),
- "save_file": self.save_file.isChecked(),
- "open_finished": self.open_viewer.isChecked(),
- "recent_playblasts": self.recent_playblasts,
- "raw_frame_numbers": self.raw_frame_numbers.isChecked()}
-
- if as_preset:
- inputs["recent_playblasts"] = []
-
- return inputs
-
- def apply_inputs(self, settings):
-
- directory = settings.get("name", None)
- save_file = settings.get("save_file", True)
- open_finished = settings.get("open_finished", True)
- raw_frame_numbers = settings.get("raw_frame_numbers", False)
- previous_playblasts = settings.get("recent_playblasts", [])
-
- self.save_file.setChecked(save_file)
- self.open_viewer.setChecked(open_finished)
- self.raw_frame_numbers.setChecked(raw_frame_numbers)
-
- for playblast in reversed(previous_playblasts):
- self.add_playblast(playblast)
-
- self.file_path.setText(directory)
-
- def token_menu(self):
- """
- Build the token menu based on the registered tokens
-
- :returns: Menu
- :rtype: QtWidgets.QMenu
- """
- menu = QtWidgets.QMenu(self)
- registered_tokens = tokens.list_tokens()
-
- for token, value in registered_tokens.items():
- label = "{} \t{}".format(token, value['label'])
- action = QtWidgets.QAction(label, menu)
- fn = partial(self.file_path.insert, token)
- action.triggered.connect(fn)
- menu.addAction(action)
-
- return menu
-
- def show_token_menu(self, pos):
- """Show custom manu on position of widget"""
- menu = self.token_menu()
- globalpos = QtCore.QPoint(self.file_path.mapToGlobal(pos))
- menu.exec_(globalpos)
diff --git a/openpype/vendor/python/common/capture_gui/plugins/panzoomplugin.py b/openpype/vendor/python/common/capture_gui/plugins/panzoomplugin.py
deleted file mode 100644
index 5bf818ff2d..0000000000
--- a/openpype/vendor/python/common/capture_gui/plugins/panzoomplugin.py
+++ /dev/null
@@ -1,48 +0,0 @@
-from capture_gui.vendor.Qt import QtCore, QtWidgets
-import capture_gui.plugin
-
-
-class PanZoomPlugin(capture_gui.plugin.Plugin):
- """Pan/Zoom widget.
-
- Allows to toggle whether you want to playblast with the camera's pan/zoom
- state or disable it during the playblast. When "Use pan/zoom from camera"
- is *not* checked it will force disable pan/zoom.
-
- """
- id = "PanZoom"
- label = "Pan/Zoom"
- section = "config"
- order = 110
-
- def __init__(self, parent=None):
- super(PanZoomPlugin, self).__init__(parent=parent)
-
- self._layout = QtWidgets.QHBoxLayout()
- self._layout.setContentsMargins(5, 0, 5, 0)
- self.setLayout(self._layout)
-
- self.pan_zoom = QtWidgets.QCheckBox("Use pan/zoom from camera")
- self.pan_zoom.setChecked(True)
-
- self._layout.addWidget(self.pan_zoom)
-
- self.pan_zoom.stateChanged.connect(self.options_changed)
-
- def get_outputs(self):
-
- if not self.pan_zoom.isChecked():
- return {"camera_options": {
- "panZoomEnabled": 1,
- "horizontalPan": 0.0,
- "verticalPan": 0.0,
- "zoom": 1.0}
- }
- else:
- return {}
-
- def apply_inputs(self, settings):
- self.pan_zoom.setChecked(settings.get("pan_zoom", True))
-
- def get_inputs(self, as_preset):
- return {"pan_zoom": self.pan_zoom.isChecked()}
diff --git a/openpype/vendor/python/common/capture_gui/plugins/rendererplugin.py b/openpype/vendor/python/common/capture_gui/plugins/rendererplugin.py
deleted file mode 100644
index 17932d69d9..0000000000
--- a/openpype/vendor/python/common/capture_gui/plugins/rendererplugin.py
+++ /dev/null
@@ -1,104 +0,0 @@
-import maya.cmds as cmds
-
-from capture_gui.vendor.Qt import QtCore, QtWidgets
-import capture_gui.lib as lib
-import capture_gui.plugin
-
-
-class RendererPlugin(capture_gui.plugin.Plugin):
- """Renderer plugin to control the used playblast renderer for viewport"""
-
- id = "Renderer"
- label = "Renderer"
- section = "config"
- order = 60
-
- def __init__(self, parent=None):
- super(RendererPlugin, self).__init__(parent=parent)
-
- layout = QtWidgets.QVBoxLayout(self)
- layout.setContentsMargins(0, 0, 0, 0)
- self.setLayout(layout)
-
- # Get active renderers for viewport
- self._renderers = self.get_renderers()
-
- # Create list of renderers
- self.renderers = QtWidgets.QComboBox()
- self.renderers.addItems(self._renderers.keys())
-
- layout.addWidget(self.renderers)
-
- self.apply_inputs(self.get_defaults())
-
- # Signals
- self.renderers.currentIndexChanged.connect(self.options_changed)
-
- def get_current_renderer(self):
- """Get current renderer by internal name (non-UI)
-
- Returns:
- str: Name of renderer.
-
- """
- renderer_ui = self.renderers.currentText()
- renderer = self._renderers.get(renderer_ui, None)
- if renderer is None:
- raise RuntimeError("No valid renderer: {0}".format(renderer_ui))
-
- return renderer
-
- def get_renderers(self):
- """Collect all available renderers for playblast"""
- active_editor = lib.get_active_editor()
- renderers_ui = cmds.modelEditor(active_editor,
- query=True,
- rendererListUI=True)
- renderers_id = cmds.modelEditor(active_editor,
- query=True,
- rendererList=True)
-
- renderers = dict(zip(renderers_ui, renderers_id))
- renderers.pop("Stub Renderer")
-
- return renderers
-
- def get_defaults(self):
- return {"rendererName": "vp2Renderer"}
-
- def get_inputs(self, as_preset):
- return {"rendererName": self.get_current_renderer()}
-
- def get_outputs(self):
- """Get the plugin outputs that matches `capture.capture` arguments
-
- Returns:
- dict: Plugin outputs
-
- """
- return {
- "viewport_options": {
- "rendererName": self.get_current_renderer()
- }
- }
-
- def apply_inputs(self, inputs):
- """Apply previous settings or settings from a preset
-
- Args:
- inputs (dict): Plugin input settings
-
- Returns:
- None
-
- """
-
- reverse_lookup = {value: key for key, value in self._renderers.items()}
- renderer = inputs.get("rendererName", "vp2Renderer")
- renderer_ui = reverse_lookup.get(renderer)
-
- if renderer_ui:
- index = self.renderers.findText(renderer_ui)
- self.renderers.setCurrentIndex(index)
- else:
- self.renderers.setCurrentIndex(1)
diff --git a/openpype/vendor/python/common/capture_gui/plugins/resolutionplugin.py b/openpype/vendor/python/common/capture_gui/plugins/resolutionplugin.py
deleted file mode 100644
index 193a95b8ba..0000000000
--- a/openpype/vendor/python/common/capture_gui/plugins/resolutionplugin.py
+++ /dev/null
@@ -1,199 +0,0 @@
-import math
-from functools import partial
-
-import maya.cmds as cmds
-from capture_gui.vendor.Qt import QtCore, QtWidgets
-
-import capture_gui.lib as lib
-import capture_gui.plugin
-
-
-class ResolutionPlugin(capture_gui.plugin.Plugin):
- """Resolution widget.
-
- Allows to set scale based on set of options.
-
- """
- id = "Resolution"
- section = "app"
- order = 20
-
- resolution_changed = QtCore.Signal()
-
- ScaleWindow = "From Window"
- ScaleRenderSettings = "From Render Settings"
- ScaleCustom = "Custom"
-
- def __init__(self, parent=None):
- super(ResolutionPlugin, self).__init__(parent=parent)
-
- self._layout = QtWidgets.QVBoxLayout()
- self._layout.setContentsMargins(0, 0, 0, 0)
- self.setLayout(self._layout)
-
- # Scale
- self.mode = QtWidgets.QComboBox()
- self.mode.addItems([self.ScaleWindow,
- self.ScaleRenderSettings,
- self.ScaleCustom])
- self.mode.setCurrentIndex(1) # Default: From render settings
-
- # Custom width/height
- self.resolution = QtWidgets.QWidget()
- self.resolution.setContentsMargins(0, 0, 0, 0)
- resolution_layout = QtWidgets.QHBoxLayout()
- resolution_layout.setContentsMargins(0, 0, 0, 0)
- resolution_layout.setSpacing(6)
-
- self.resolution.setLayout(resolution_layout)
- width_label = QtWidgets.QLabel("Width")
- width_label.setFixedWidth(40)
- self.width = QtWidgets.QSpinBox()
- self.width.setMinimum(0)
- self.width.setMaximum(99999)
- self.width.setValue(1920)
- heigth_label = QtWidgets.QLabel("Height")
- heigth_label.setFixedWidth(40)
- self.height = QtWidgets.QSpinBox()
- self.height.setMinimum(0)
- self.height.setMaximum(99999)
- self.height.setValue(1080)
-
- resolution_layout.addWidget(width_label)
- resolution_layout.addWidget(self.width)
- resolution_layout.addWidget(heigth_label)
- resolution_layout.addWidget(self.height)
-
- self.scale_result = QtWidgets.QLineEdit()
- self.scale_result.setReadOnly(True)
-
- # Percentage
- self.percent_label = QtWidgets.QLabel("Scale")
- self.percent = QtWidgets.QDoubleSpinBox()
- self.percent.setMinimum(0.01)
- self.percent.setValue(1.0) # default value
- self.percent.setSingleStep(0.05)
-
- self.percent_presets = QtWidgets.QHBoxLayout()
- self.percent_presets.setSpacing(4)
- for value in [0.25, 0.5, 0.75, 1.0, 2.0]:
- btn = QtWidgets.QPushButton(str(value))
- self.percent_presets.addWidget(btn)
- btn.setFixedWidth(35)
- btn.clicked.connect(partial(self.percent.setValue, value))
-
- self.percent_layout = QtWidgets.QHBoxLayout()
- self.percent_layout.addWidget(self.percent_label)
- self.percent_layout.addWidget(self.percent)
- self.percent_layout.addLayout(self.percent_presets)
-
- # Resulting scale display
- self._layout.addWidget(self.mode)
- self._layout.addWidget(self.resolution)
- self._layout.addLayout(self.percent_layout)
- self._layout.addWidget(self.scale_result)
-
- # refresh states
- self.on_mode_changed()
- self.on_resolution_changed()
-
- # connect signals
- self.mode.currentIndexChanged.connect(self.on_mode_changed)
- self.mode.currentIndexChanged.connect(self.on_resolution_changed)
- self.percent.valueChanged.connect(self.on_resolution_changed)
- self.width.valueChanged.connect(self.on_resolution_changed)
- self.height.valueChanged.connect(self.on_resolution_changed)
-
- # Connect options changed
- self.mode.currentIndexChanged.connect(self.options_changed)
- self.percent.valueChanged.connect(self.options_changed)
- self.width.valueChanged.connect(self.options_changed)
- self.height.valueChanged.connect(self.options_changed)
-
- def on_mode_changed(self):
- """Update the width/height enabled state when mode changes"""
-
- if self.mode.currentText() != self.ScaleCustom:
- self.width.setEnabled(False)
- self.height.setEnabled(False)
- self.resolution.hide()
- else:
- self.width.setEnabled(True)
- self.height.setEnabled(True)
- self.resolution.show()
-
- def _get_output_resolution(self):
-
- options = self.get_outputs()
- return int(options["width"]), int(options["height"])
-
- def on_resolution_changed(self):
- """Update the resulting resolution label"""
-
- width, height = self._get_output_resolution()
- label = "Result: {0}x{1}".format(width, height)
-
- self.scale_result.setText(label)
-
- # Update label
- self.label = "Resolution ({0}x{1})".format(width, height)
- self.label_changed.emit(self.label)
-
- def get_outputs(self):
- """Return width x height defined by the combination of settings
-
- Returns:
- dict: width and height key values
-
- """
- mode = self.mode.currentText()
- panel = lib.get_active_editor()
-
- if mode == self.ScaleCustom:
- width = self.width.value()
- height = self.height.value()
-
- elif mode == self.ScaleRenderSettings:
- # width height from render resolution
- width = cmds.getAttr("defaultResolution.width")
- height = cmds.getAttr("defaultResolution.height")
-
- elif mode == self.ScaleWindow:
- # width height from active view panel size
- if not panel:
- # No panel would be passed when updating in the UI as such
- # the resulting resolution can't be previewed. But this should
- # never happen when starting the capture.
- width = 0
- height = 0
- else:
- width = cmds.control(panel, query=True, width=True)
- height = cmds.control(panel, query=True, height=True)
- else:
- raise NotImplementedError("Unsupported scale mode: "
- "{0}".format(mode))
-
- scale = [width, height]
- percentage = self.percent.value()
- scale = [math.floor(x * percentage) for x in scale]
-
- return {"width": scale[0], "height": scale[1]}
-
- def get_inputs(self, as_preset):
- return {"mode": self.mode.currentText(),
- "width": self.width.value(),
- "height": self.height.value(),
- "percent": self.percent.value()}
-
- def apply_inputs(self, settings):
- # get value else fall back to default values
- mode = settings.get("mode", self.ScaleRenderSettings)
- width = int(settings.get("width", 1920))
- height = int(settings.get("height", 1080))
- percent = float(settings.get("percent", 1.0))
-
- # set values
- self.mode.setCurrentIndex(self.mode.findText(mode))
- self.width.setValue(width)
- self.height.setValue(height)
- self.percent.setValue(percent)
diff --git a/openpype/vendor/python/common/capture_gui/plugins/timeplugin.py b/openpype/vendor/python/common/capture_gui/plugins/timeplugin.py
deleted file mode 100644
index b4901f9cb4..0000000000
--- a/openpype/vendor/python/common/capture_gui/plugins/timeplugin.py
+++ /dev/null
@@ -1,292 +0,0 @@
-import sys
-import logging
-import re
-
-import maya.OpenMaya as om
-from capture_gui.vendor.Qt import QtCore, QtWidgets
-
-import capture_gui.lib
-import capture_gui.plugin
-
-log = logging.getLogger("Time Range")
-
-
-def parse_frames(string):
- """Parse the resulting frames list from a frame list string.
-
- Examples
- >>> parse_frames("0-3;30")
- [0, 1, 2, 3, 30]
- >>> parse_frames("0,2,4,-10")
- [0, 2, 4, -10]
- >>> parse_frames("-10--5,-2")
- [-10, -9, -8, -7, -6, -5, -2]
-
- Args:
- string (str): The string to parse for frames.
-
- Returns:
- list: A list of frames
-
- """
-
- result = list()
- if not string.strip():
- raise ValueError("Can't parse an empty frame string.")
-
- if not re.match("^[-0-9,; ]*$", string):
- raise ValueError("Invalid symbols in frame string: {}".format(string))
-
- for raw in re.split(";|,", string):
-
- # Skip empty elements
- value = raw.strip().replace(" ", "")
- if not value:
- continue
-
- # Check for sequences (1-20) including negatives (-10--8)
- sequence = re.search("(-?[0-9]+)-(-?[0-9]+)", value)
-
- # Sequence
- if sequence:
- start, end = sequence.groups()
- frames = range(int(start), int(end) + 1)
- result.extend(frames)
-
- # Single frame
- else:
- try:
- frame = int(value)
- except ValueError:
- raise ValueError("Invalid frame description: "
- "'{0}'".format(value))
-
- result.append(frame)
-
- if not result:
- # This happens when only spaces are entered with a separator like `,` or `;`
- raise ValueError("Unable to parse any frames from string: {}".format(string))
-
- return result
-
-
-class TimePlugin(capture_gui.plugin.Plugin):
- """Widget for time based options"""
-
- id = "Time Range"
- section = "app"
- order = 30
-
- RangeTimeSlider = "Time Slider"
- RangeStartEnd = "Start/End"
- CurrentFrame = "Current Frame"
- CustomFrames = "Custom Frames"
-
- def __init__(self, parent=None):
- super(TimePlugin, self).__init__(parent=parent)
-
- self._event_callbacks = list()
-
- self._layout = QtWidgets.QHBoxLayout()
- self._layout.setContentsMargins(5, 0, 5, 0)
- self.setLayout(self._layout)
-
- self.mode = QtWidgets.QComboBox()
- self.mode.addItems([self.RangeTimeSlider,
- self.RangeStartEnd,
- self.CurrentFrame,
- self.CustomFrames])
-
- frame_input_height = 20
- self.start = QtWidgets.QSpinBox()
- self.start.setRange(-sys.maxint, sys.maxint)
- self.start.setFixedHeight(frame_input_height)
- self.end = QtWidgets.QSpinBox()
- self.end.setRange(-sys.maxint, sys.maxint)
- self.end.setFixedHeight(frame_input_height)
-
- # unique frames field
- self.custom_frames = QtWidgets.QLineEdit()
- self.custom_frames.setFixedHeight(frame_input_height)
- self.custom_frames.setPlaceholderText("Example: 1-20,25;50;75,100-150")
- self.custom_frames.setVisible(False)
-
- self._layout.addWidget(self.mode)
- self._layout.addWidget(self.start)
- self._layout.addWidget(self.end)
- self._layout.addWidget(self.custom_frames)
-
- # Connect callbacks to ensure start is never higher then end
- # and the end is never lower than start
- self.end.valueChanged.connect(self._ensure_start)
- self.start.valueChanged.connect(self._ensure_end)
-
- self.on_mode_changed() # force enabled state refresh
-
- self.mode.currentIndexChanged.connect(self.on_mode_changed)
- self.start.valueChanged.connect(self.on_mode_changed)
- self.end.valueChanged.connect(self.on_mode_changed)
- self.custom_frames.textChanged.connect(self.on_mode_changed)
-
- def _ensure_start(self, value):
- self.start.setValue(min(self.start.value(), value))
-
- def _ensure_end(self, value):
- self.end.setValue(max(self.end.value(), value))
-
- def on_mode_changed(self, emit=True):
- """Update the GUI when the user updated the time range or settings.
-
- Arguments:
- emit (bool): Whether to emit the options changed signal
-
- Returns:
- None
-
- """
-
- mode = self.mode.currentText()
- if mode == self.RangeTimeSlider:
- start, end = capture_gui.lib.get_time_slider_range()
- self.start.setEnabled(False)
- self.end.setEnabled(False)
- self.start.setVisible(True)
- self.end.setVisible(True)
- self.custom_frames.setVisible(False)
- mode_values = int(start), int(end)
- elif mode == self.RangeStartEnd:
- self.start.setEnabled(True)
- self.end.setEnabled(True)
- self.start.setVisible(True)
- self.end.setVisible(True)
- self.custom_frames.setVisible(False)
- mode_values = self.start.value(), self.end.value()
- elif mode == self.CustomFrames:
- self.start.setVisible(False)
- self.end.setVisible(False)
- self.custom_frames.setVisible(True)
- mode_values = "({})".format(self.custom_frames.text())
-
- # ensure validation state for custom frames
- self.validate()
-
- else:
- self.start.setEnabled(False)
- self.end.setEnabled(False)
- self.start.setVisible(True)
- self.end.setVisible(True)
- self.custom_frames.setVisible(False)
- currentframe = int(capture_gui.lib.get_current_frame())
- mode_values = "({})".format(currentframe)
-
- # Update label
- self.label = "Time Range {}".format(mode_values)
- self.label_changed.emit(self.label)
-
- if emit:
- self.options_changed.emit()
-
- def validate(self):
- errors = []
-
- if self.mode.currentText() == self.CustomFrames:
-
- # Reset
- self.custom_frames.setStyleSheet("")
-
- try:
- parse_frames(self.custom_frames.text())
- except ValueError as exc:
- errors.append("{} : Invalid frame description: "
- "{}".format(self.id, exc))
- self.custom_frames.setStyleSheet(self.highlight)
-
- return errors
-
- def get_outputs(self, panel=""):
- """Get the plugin outputs that matches `capture.capture` arguments
-
- Returns:
- dict: Plugin outputs
-
- """
-
- mode = self.mode.currentText()
- frames = None
-
- if mode == self.RangeTimeSlider:
- start, end = capture_gui.lib.get_time_slider_range()
-
- elif mode == self.RangeStartEnd:
- start = self.start.value()
- end = self.end.value()
-
- elif mode == self.CurrentFrame:
- frame = capture_gui.lib.get_current_frame()
- start = frame
- end = frame
-
- elif mode == self.CustomFrames:
- frames = parse_frames(self.custom_frames.text())
- start = None
- end = None
- else:
- raise NotImplementedError("Unsupported time range mode: "
- "{0}".format(mode))
-
- return {"start_frame": start,
- "end_frame": end,
- "frame": frames}
-
- def get_inputs(self, as_preset):
- return {"time": self.mode.currentText(),
- "start_frame": self.start.value(),
- "end_frame": self.end.value(),
- "frame": self.custom_frames.text()}
-
- def apply_inputs(self, settings):
- # get values
- mode = self.mode.findText(settings.get("time", self.RangeTimeSlider))
- startframe = settings.get("start_frame", 1)
- endframe = settings.get("end_frame", 120)
- custom_frames = settings.get("frame", None)
-
- # set values
- self.mode.setCurrentIndex(mode)
- self.start.setValue(int(startframe))
- self.end.setValue(int(endframe))
- if custom_frames is not None:
- self.custom_frames.setText(custom_frames)
-
- def initialize(self):
- self._register_callbacks()
-
- def uninitialize(self):
- self._remove_callbacks()
-
- def _register_callbacks(self):
- """Register maya time and playback range change callbacks.
-
- Register callbacks to ensure Capture GUI reacts to changes in
- the Maya GUI in regards to time slider and current frame
-
- """
-
- callback = lambda x: self.on_mode_changed(emit=False)
-
- # this avoid overriding the ids on re-run
- currentframe = om.MEventMessage.addEventCallback("timeChanged",
- callback)
- timerange = om.MEventMessage.addEventCallback("playbackRangeChanged",
- callback)
-
- self._event_callbacks.append(currentframe)
- self._event_callbacks.append(timerange)
-
- def _remove_callbacks(self):
- """Remove callbacks when closing widget"""
- for callback in self._event_callbacks:
- try:
- om.MEventMessage.removeCallback(callback)
- except RuntimeError, error:
- log.error("Encounter error : {}".format(error))
diff --git a/openpype/vendor/python/common/capture_gui/plugins/viewportplugin.py b/openpype/vendor/python/common/capture_gui/plugins/viewportplugin.py
deleted file mode 100644
index 96f311fdcf..0000000000
--- a/openpype/vendor/python/common/capture_gui/plugins/viewportplugin.py
+++ /dev/null
@@ -1,292 +0,0 @@
-from capture_gui.vendor.Qt import QtCore, QtWidgets
-import capture_gui.plugin
-import capture_gui.lib as lib
-import capture
-
-
-class ViewportPlugin(capture_gui.plugin.Plugin):
- """Plugin to apply viewport visibilities and settings"""
-
- id = "Viewport Options"
- label = "Viewport Options"
- section = "config"
- order = 70
-
- def __init__(self, parent=None):
- super(ViewportPlugin, self).__init__(parent=parent)
-
- # set inherited attributes
- self.setObjectName(self.label)
-
- # custom atttributes
- self.show_type_actions = list()
-
- # get information
- self.show_types = lib.get_show_object_types()
-
- # set main layout for widget
- self._layout = QtWidgets.QVBoxLayout()
- self._layout.setContentsMargins(0, 0, 0, 0)
- self.setLayout(self._layout)
-
- # build
- # region Menus
- menus_vlayout = QtWidgets.QHBoxLayout()
-
- # Display Lights
- self.display_light_menu = self._build_light_menu()
- self.display_light_menu.setFixedHeight(20)
-
- # Show
- self.show_types_button = QtWidgets.QPushButton("Show")
- self.show_types_button.setFixedHeight(20)
- self.show_types_menu = self._build_show_menu()
- self.show_types_button.setMenu(self.show_types_menu)
-
- # fill layout
- menus_vlayout.addWidget(self.display_light_menu)
- menus_vlayout.addWidget(self.show_types_button)
-
- # endregion Menus
-
- # region Checkboxes
- checkbox_layout = QtWidgets.QGridLayout()
- self.high_quality = QtWidgets.QCheckBox()
- self.high_quality.setText("Force Viewport 2.0 + AA")
- self.override_viewport = QtWidgets.QCheckBox("Override viewport "
- "settings")
- self.override_viewport.setChecked(True)
-
- # two sided lighting
- self.two_sided_ligthing = QtWidgets.QCheckBox("Two Sided Ligthing")
- self.two_sided_ligthing.setChecked(False)
-
- # show
- self.shadows = QtWidgets.QCheckBox("Shadows")
- self.shadows.setChecked(False)
-
- checkbox_layout.addWidget(self.override_viewport, 0, 0)
- checkbox_layout.addWidget(self.high_quality, 0, 1)
- checkbox_layout.addWidget(self.two_sided_ligthing, 1, 0)
- checkbox_layout.addWidget(self.shadows, 1, 1)
- # endregion Checkboxes
-
- self._layout.addLayout(checkbox_layout)
- self._layout.addLayout(menus_vlayout)
-
- self.connections()
-
- def connections(self):
-
- self.high_quality.stateChanged.connect(self.options_changed)
- self.override_viewport.stateChanged.connect(self.options_changed)
- self.override_viewport.stateChanged.connect(self.on_toggle_override)
-
- self.two_sided_ligthing.stateChanged.connect(self.options_changed)
- self.shadows.stateChanged.connect(self.options_changed)
-
- self.display_light_menu.currentIndexChanged.connect(
- self.options_changed
- )
-
- def _build_show_menu(self):
- """Build the menu to select which object types are shown in the output.
-
- Returns:
- QtGui.QMenu: The visibilities "show" menu.
-
- """
-
- menu = QtWidgets.QMenu(self)
- menu.setObjectName("ShowShapesMenu")
- menu.setWindowTitle("Show")
- menu.setFixedWidth(180)
- menu.setTearOffEnabled(True)
-
- # Show all check
- toggle_all = QtWidgets.QAction(menu, text="All")
- toggle_none = QtWidgets.QAction(menu, text="None")
- menu.addAction(toggle_all)
- menu.addAction(toggle_none)
- menu.addSeparator()
-
- # add plugin shapes if any
- for shape in self.show_types:
- action = QtWidgets.QAction(menu, text=shape)
- action.setCheckable(True)
- # emit signal when the state is changed of the checkbox
- action.toggled.connect(self.options_changed)
- menu.addAction(action)
- self.show_type_actions.append(action)
-
- # connect signals
- toggle_all.triggered.connect(self.toggle_all_visbile)
- toggle_none.triggered.connect(self.toggle_all_hide)
-
- return menu
-
- def _build_light_menu(self):
- """Build lighting menu.
-
- Create the menu items for the different types of lighting for
- in the viewport
-
- Returns:
- None
-
- """
-
- menu = QtWidgets.QComboBox(self)
-
- # names cane be found in
- display_lights = (("Use Default Lighting", "default"),
- ("Use All Lights", "all"),
- ("Use Selected Lights", "active"),
- ("Use Flat Lighting", "flat"),
- ("Use No Lights", "none"))
-
- for label, name in display_lights:
- menu.addItem(label, userData=name)
-
- return menu
-
- def on_toggle_override(self):
- """Enable or disable show menu when override is checked"""
- state = self.override_viewport.isChecked()
- self.show_types_button.setEnabled(state)
- self.high_quality.setEnabled(state)
- self.display_light_menu.setEnabled(state)
- self.shadows.setEnabled(state)
- self.two_sided_ligthing.setEnabled(state)
-
- def toggle_all_visbile(self):
- """Set all object types off or on depending on the state"""
- for action in self.show_type_actions:
- action.setChecked(True)
-
- def toggle_all_hide(self):
- """Set all object types off or on depending on the state"""
- for action in self.show_type_actions:
- action.setChecked(False)
-
- def get_show_inputs(self):
- """Return checked state of show menu items
-
- Returns:
- dict: The checked show states in the widget.
-
- """
-
- show_inputs = {}
- # get all checked objects
- for action in self.show_type_actions:
- label = action.text()
- name = self.show_types.get(label, None)
- if name is None:
- continue
- show_inputs[name] = action.isChecked()
-
- return show_inputs
-
- def get_displaylights(self):
- """Get and parse the currently selected displayLights options.
-
- Returns:
- dict: The display light options
-
- """
- indx = self.display_light_menu.currentIndex()
- return {"displayLights": self.display_light_menu.itemData(indx),
- "shadows": self.shadows.isChecked(),
- "twoSidedLighting": self.two_sided_ligthing.isChecked()}
-
- def get_inputs(self, as_preset):
- """Return the widget options
-
- Returns:
- dict: The input settings of the widgets.
-
- """
- inputs = {"high_quality": self.high_quality.isChecked(),
- "override_viewport_options": self.override_viewport.isChecked(),
- "displayLights": self.display_light_menu.currentIndex(),
- "shadows": self.shadows.isChecked(),
- "twoSidedLighting": self.two_sided_ligthing.isChecked()}
-
- inputs.update(self.get_show_inputs())
-
- return inputs
-
- def apply_inputs(self, inputs):
- """Apply the saved inputs from the inputs configuration
-
- Arguments:
- settings (dict): The input settings to apply.
-
- """
-
- # get input values directly from input given
- override_viewport = inputs.get("override_viewport_options", True)
- high_quality = inputs.get("high_quality", True)
- displaylight = inputs.get("displayLights", 0) # default lighting
- two_sided_ligthing = inputs.get("twoSidedLighting", False)
- shadows = inputs.get("shadows", False)
-
- self.high_quality.setChecked(high_quality)
- self.override_viewport.setChecked(override_viewport)
- self.show_types_button.setEnabled(override_viewport)
-
- # display light menu
- self.display_light_menu.setCurrentIndex(displaylight)
- self.shadows.setChecked(shadows)
- self.two_sided_ligthing.setChecked(two_sided_ligthing)
-
- for action in self.show_type_actions:
- system_name = self.show_types[action.text()]
- state = inputs.get(system_name, True)
- action.setChecked(state)
-
- def get_outputs(self):
- """Get the plugin outputs that matches `capture.capture` arguments
-
- Returns:
- dict: Plugin outputs
-
- """
- outputs = dict()
-
- high_quality = self.high_quality.isChecked()
- override_viewport_options = self.override_viewport.isChecked()
-
- if override_viewport_options:
- outputs['viewport2_options'] = dict()
- outputs['viewport_options'] = dict()
-
- if high_quality:
- # force viewport 2.0 and AA
- outputs['viewport_options']['rendererName'] = 'vp2Renderer'
- outputs['viewport2_options']['multiSampleEnable'] = True
- outputs['viewport2_options']['multiSampleCount'] = 8
-
- show_per_type = self.get_show_inputs()
- display_lights = self.get_displaylights()
- outputs['viewport_options'].update(show_per_type)
- outputs['viewport_options'].update(display_lights)
- else:
- # TODO: When this fails we should give the user a warning
- # Use settings from the active viewport
- outputs = capture.parse_active_view()
-
- # Remove the display options and camera attributes
- outputs.pop("display_options", None)
- outputs.pop("camera", None)
-
- # Remove the current renderer because there's already
- # renderer plug-in handling that
- outputs["viewport_options"].pop("rendererName", None)
-
- # Remove all camera options except depth of field
- dof = outputs["camera_options"]["depthOfField"]
- outputs["camera_options"] = {"depthOfField": dof}
-
- return outputs
diff --git a/openpype/vendor/python/common/capture_gui/presets.py b/openpype/vendor/python/common/capture_gui/presets.py
deleted file mode 100644
index 634e8264ec..0000000000
--- a/openpype/vendor/python/common/capture_gui/presets.py
+++ /dev/null
@@ -1,105 +0,0 @@
-import glob
-import os
-import logging
-
-_registered_paths = []
-log = logging.getLogger("Presets")
-
-
-def discover(paths=None):
- """Get the full list of files found in the registered folders
-
- Args:
- paths (list, Optional): directories which host preset files or None.
- When None (default) it will list from the registered preset paths.
-
- Returns:
- list: valid .json preset file paths.
-
- """
-
- presets = []
- for path in paths or preset_paths():
- path = os.path.normpath(path)
- if not os.path.isdir(path):
- continue
-
- # check for json files
- glob_query = os.path.abspath(os.path.join(path, "*.json"))
- filenames = glob.glob(glob_query)
- for filename in filenames:
- # skip private files
- if filename.startswith("_"):
- continue
-
- # check for file size
- if not check_file_size(filename):
- log.warning("Filesize is smaller than 1 byte for file '%s'",
- filename)
- continue
-
- if filename not in presets:
- presets.append(filename)
-
- return presets
-
-
-def check_file_size(filepath):
- """Check if filesize of the given file is bigger than 1.0 byte
-
- Args:
- filepath (str): full filepath of the file to check
-
- Returns:
- bool: Whether bigger than 1 byte.
-
- """
-
- file_stats = os.stat(filepath)
- if file_stats.st_size < 1:
- return False
- return True
-
-
-def preset_paths():
- """Return existing registered preset paths
-
- Returns:
- list: List of full paths.
-
- """
-
- paths = list()
- for path in _registered_paths:
- # filter duplicates
- if path in paths:
- continue
-
- if not os.path.exists(path):
- continue
-
- paths.append(path)
-
- return paths
-
-
-def register_preset_path(path):
- """Add filepath to registered presets
-
- :param path: the directory of the preset file(s)
- :type path: str
-
- :return:
- """
- if path in _registered_paths:
- return log.warning("Path already registered: %s", path)
-
- _registered_paths.append(path)
-
- return path
-
-
-# Register default user folder
-user_folder = os.path.expanduser("~")
-capture_gui_presets = os.path.join(user_folder, "CaptureGUI", "presets")
-register_preset_path(capture_gui_presets)
diff --git a/openpype/vendor/python/common/capture_gui/resources/config.png b/openpype/vendor/python/common/capture_gui/resources/config.png
deleted file mode 100644
index 634a1da65a..0000000000
Binary files a/openpype/vendor/python/common/capture_gui/resources/config.png and /dev/null differ
diff --git a/openpype/vendor/python/common/capture_gui/resources/import.png b/openpype/vendor/python/common/capture_gui/resources/import.png
deleted file mode 100644
index 785747191a..0000000000
Binary files a/openpype/vendor/python/common/capture_gui/resources/import.png and /dev/null differ
diff --git a/openpype/vendor/python/common/capture_gui/resources/reset.png b/openpype/vendor/python/common/capture_gui/resources/reset.png
deleted file mode 100644
index 629822cd44..0000000000
Binary files a/openpype/vendor/python/common/capture_gui/resources/reset.png and /dev/null differ
diff --git a/openpype/vendor/python/common/capture_gui/resources/save.png b/openpype/vendor/python/common/capture_gui/resources/save.png
deleted file mode 100644
index 817af19e9f..0000000000
Binary files a/openpype/vendor/python/common/capture_gui/resources/save.png and /dev/null differ
diff --git a/openpype/vendor/python/common/capture_gui/tokens.py b/openpype/vendor/python/common/capture_gui/tokens.py
deleted file mode 100644
index d34167b53d..0000000000
--- a/openpype/vendor/python/common/capture_gui/tokens.py
+++ /dev/null
@@ -1,68 +0,0 @@
-"""Token system
-
-The capture gui application will format tokens in the filename.
-The tokens can be registered using `register_token`
-
-"""
-from . import lib
-
-_registered_tokens = dict()
-
-
-def format_tokens(string, options):
- """Replace the tokens with the correlated strings
-
- Arguments:
- string (str): filename of the playblast with tokens.
- options (dict): The parsed capture options.
-
- Returns:
- str: The formatted filename with all tokens resolved
-
- """
-
- if not string:
- return string
-
- for token, value in _registered_tokens.items():
- if token in string:
- func = value['func']
- string = string.replace(token, func(options))
-
- return string
-
-
-def register_token(token, func, label=""):
- assert token.startswith("<") and token.endswith(">")
- assert callable(func)
- _registered_tokens[token] = {"func": func, "label": label}
-
-
-def list_tokens():
- return _registered_tokens.copy()
-
-
-# register default tokens
-# scene based tokens
-def _camera_token(options):
- """Return short name of camera from capture options"""
- camera = options['camera']
- camera = camera.rsplit("|", 1)[-1] # use short name
- camera = camera.replace(":", "_") # namespace `:` to `_`
- return camera
-
-
-register_token("", _camera_token,
- label="Insert camera name")
-register_token("", lambda options: lib.get_current_scenename() or "playblast",
- label="Insert current scene name")
-register_token("", lambda options: lib.get_current_renderlayer(),
- label="Insert active render layer name")
-
-# project based tokens
-register_token("",
- lambda options: lib.get_project_rule("images"),
- label="Insert image directory of set project")
-register_token("",
- lambda options: lib.get_project_rule("movie"),
- label="Insert movies directory of set project")
diff --git a/openpype/vendor/python/common/capture_gui/vendor/Qt.py b/openpype/vendor/python/common/capture_gui/vendor/Qt.py
deleted file mode 100644
index 3a97da872d..0000000000
--- a/openpype/vendor/python/common/capture_gui/vendor/Qt.py
+++ /dev/null
@@ -1,1030 +0,0 @@
-"""The MIT License (MIT)
-
-Copyright (c) 2016-2017 Marcus Ottosson
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
-Documentation
-
- Map all bindings to PySide2
-
- Project goals:
- Qt.py was born in the film and visual effects industry to address
- the growing need for the development of software capable of running
- with more than one flavour of the Qt bindings for Python - PySide,
- PySide2, PyQt4 and PyQt5.
-
- 1. Build for one, run with all
- 2. Explicit is better than implicit
- 3. Support co-existence
-
- Default resolution order:
- - PySide2
- - PyQt5
- - PySide
- - PyQt4
-
- Usage:
- >> import sys
- >> from Qt import QtWidgets
- >> app = QtWidgets.QApplication(sys.argv)
- >> button = QtWidgets.QPushButton("Hello World")
- >> button.show()
- >> app.exec_()
-
- All members of PySide2 are mapped from other bindings, should they exist.
- If no equivalent member exist, it is excluded from Qt.py and inaccessible.
- The idea is to highlight members that exist across all supported binding,
- and guarantee that code that runs on one binding runs on all others.
-
- For more details, visit https://github.com/mottosso/Qt.py
-
-"""
-
-import os
-import sys
-import types
-import shutil
-import importlib
-
-__version__ = "1.0.0.b3"
-
-# Enable support for `from Qt import *`
-__all__ = []
-
-# Flags from environment variables
-QT_VERBOSE = bool(os.getenv("QT_VERBOSE"))
-QT_PREFERRED_BINDING = os.getenv("QT_PREFERRED_BINDING", "")
-QT_SIP_API_HINT = os.getenv("QT_SIP_API_HINT")
-
-# Reference to Qt.py
-Qt = sys.modules[__name__]
-Qt.QtCompat = types.ModuleType("QtCompat")
-
-"""Common members of all bindings
-
-This is where each member of Qt.py is explicitly defined.
-It is based on a "lowest commond denominator" of all bindings;
-including members found in each of the 4 bindings.
-
-Find or add excluded members in build_membership.py
-
-"""
-
-_common_members = {
- "QtGui": [
- "QAbstractTextDocumentLayout",
- "QActionEvent",
- "QBitmap",
- "QBrush",
- "QClipboard",
- "QCloseEvent",
- "QColor",
- "QConicalGradient",
- "QContextMenuEvent",
- "QCursor",
- "QDoubleValidator",
- "QDrag",
- "QDragEnterEvent",
- "QDragLeaveEvent",
- "QDragMoveEvent",
- "QDropEvent",
- "QFileOpenEvent",
- "QFocusEvent",
- "QFont",
- "QFontDatabase",
- "QFontInfo",
- "QFontMetrics",
- "QFontMetricsF",
- "QGradient",
- "QHelpEvent",
- "QHideEvent",
- "QHoverEvent",
- "QIcon",
- "QIconDragEvent",
- "QIconEngine",
- "QImage",
- "QImageIOHandler",
- "QImageReader",
- "QImageWriter",
- "QInputEvent",
- "QInputMethodEvent",
- "QIntValidator",
- "QKeyEvent",
- "QKeySequence",
- "QLinearGradient",
- "QMatrix2x2",
- "QMatrix2x3",
- "QMatrix2x4",
- "QMatrix3x2",
- "QMatrix3x3",
- "QMatrix3x4",
- "QMatrix4x2",
- "QMatrix4x3",
- "QMatrix4x4",
- "QMouseEvent",
- "QMoveEvent",
- "QMovie",
- "QPaintDevice",
- "QPaintEngine",
- "QPaintEngineState",
- "QPaintEvent",
- "QPainter",
- "QPainterPath",
- "QPainterPathStroker",
- "QPalette",
- "QPen",
- "QPicture",
- "QPictureIO",
- "QPixmap",
- "QPixmapCache",
- "QPolygon",
- "QPolygonF",
- "QQuaternion",
- "QRadialGradient",
- "QRegExpValidator",
- "QRegion",
- "QResizeEvent",
- "QSessionManager",
- "QShortcutEvent",
- "QShowEvent",
- "QStandardItem",
- "QStandardItemModel",
- "QStatusTipEvent",
- "QSyntaxHighlighter",
- "QTabletEvent",
- "QTextBlock",
- "QTextBlockFormat",
- "QTextBlockGroup",
- "QTextBlockUserData",
- "QTextCharFormat",
- "QTextCursor",
- "QTextDocument",
- "QTextDocumentFragment",
- "QTextFormat",
- "QTextFragment",
- "QTextFrame",
- "QTextFrameFormat",
- "QTextImageFormat",
- "QTextInlineObject",
- "QTextItem",
- "QTextLayout",
- "QTextLength",
- "QTextLine",
- "QTextList",
- "QTextListFormat",
- "QTextObject",
- "QTextObjectInterface",
- "QTextOption",
- "QTextTable",
- "QTextTableCell",
- "QTextTableCellFormat",
- "QTextTableFormat",
- "QTransform",
- "QValidator",
- "QVector2D",
- "QVector3D",
- "QVector4D",
- "QWhatsThisClickedEvent",
- "QWheelEvent",
- "QWindowStateChangeEvent",
- "qAlpha",
- "qBlue",
- "qGray",
- "qGreen",
- "qIsGray",
- "qRed",
- "qRgb",
- "qRgb",
- ],
- "QtWidgets": [
- "QAbstractButton",
- "QAbstractGraphicsShapeItem",
- "QAbstractItemDelegate",
- "QAbstractItemView",
- "QAbstractScrollArea",
- "QAbstractSlider",
- "QAbstractSpinBox",
- "QAction",
- "QActionGroup",
- "QApplication",
- "QBoxLayout",
- "QButtonGroup",
- "QCalendarWidget",
- "QCheckBox",
- "QColorDialog",
- "QColumnView",
- "QComboBox",
- "QCommandLinkButton",
- "QCommonStyle",
- "QCompleter",
- "QDataWidgetMapper",
- "QDateEdit",
- "QDateTimeEdit",
- "QDesktopWidget",
- "QDial",
- "QDialog",
- "QDialogButtonBox",
- "QDirModel",
- "QDockWidget",
- "QDoubleSpinBox",
- "QErrorMessage",
- "QFileDialog",
- "QFileIconProvider",
- "QFileSystemModel",
- "QFocusFrame",
- "QFontComboBox",
- "QFontDialog",
- "QFormLayout",
- "QFrame",
- "QGesture",
- "QGestureEvent",
- "QGestureRecognizer",
- "QGraphicsAnchor",
- "QGraphicsAnchorLayout",
- "QGraphicsBlurEffect",
- "QGraphicsColorizeEffect",
- "QGraphicsDropShadowEffect",
- "QGraphicsEffect",
- "QGraphicsEllipseItem",
- "QGraphicsGridLayout",
- "QGraphicsItem",
- "QGraphicsItemGroup",
- "QGraphicsLayout",
- "QGraphicsLayoutItem",
- "QGraphicsLineItem",
- "QGraphicsLinearLayout",
- "QGraphicsObject",
- "QGraphicsOpacityEffect",
- "QGraphicsPathItem",
- "QGraphicsPixmapItem",
- "QGraphicsPolygonItem",
- "QGraphicsProxyWidget",
- "QGraphicsRectItem",
- "QGraphicsRotation",
- "QGraphicsScale",
- "QGraphicsScene",
- "QGraphicsSceneContextMenuEvent",
- "QGraphicsSceneDragDropEvent",
- "QGraphicsSceneEvent",
- "QGraphicsSceneHelpEvent",
- "QGraphicsSceneHoverEvent",
- "QGraphicsSceneMouseEvent",
- "QGraphicsSceneMoveEvent",
- "QGraphicsSceneResizeEvent",
- "QGraphicsSceneWheelEvent",
- "QGraphicsSimpleTextItem",
- "QGraphicsTextItem",
- "QGraphicsTransform",
- "QGraphicsView",
- "QGraphicsWidget",
- "QGridLayout",
- "QGroupBox",
- "QHBoxLayout",
- "QHeaderView",
- "QInputDialog",
- "QItemDelegate",
- "QItemEditorCreatorBase",
- "QItemEditorFactory",
- "QKeyEventTransition",
- "QLCDNumber",
- "QLabel",
- "QLayout",
- "QLayoutItem",
- "QLineEdit",
- "QListView",
- "QListWidget",
- "QListWidgetItem",
- "QMainWindow",
- "QMdiArea",
- "QMdiSubWindow",
- "QMenu",
- "QMenuBar",
- "QMessageBox",
- "QMouseEventTransition",
- "QPanGesture",
- "QPinchGesture",
- "QPlainTextDocumentLayout",
- "QPlainTextEdit",
- "QProgressBar",
- "QProgressDialog",
- "QPushButton",
- "QRadioButton",
- "QRubberBand",
- "QScrollArea",
- "QScrollBar",
- "QShortcut",
- "QSizeGrip",
- "QSizePolicy",
- "QSlider",
- "QSpacerItem",
- "QSpinBox",
- "QSplashScreen",
- "QSplitter",
- "QSplitterHandle",
- "QStackedLayout",
- "QStackedWidget",
- "QStatusBar",
- "QStyle",
- "QStyleFactory",
- "QStyleHintReturn",
- "QStyleHintReturnMask",
- "QStyleHintReturnVariant",
- "QStyleOption",
- "QStyleOptionButton",
- "QStyleOptionComboBox",
- "QStyleOptionComplex",
- "QStyleOptionDockWidget",
- "QStyleOptionFocusRect",
- "QStyleOptionFrame",
- "QStyleOptionGraphicsItem",
- "QStyleOptionGroupBox",
- "QStyleOptionHeader",
- "QStyleOptionMenuItem",
- "QStyleOptionProgressBar",
- "QStyleOptionRubberBand",
- "QStyleOptionSizeGrip",
- "QStyleOptionSlider",
- "QStyleOptionSpinBox",
- "QStyleOptionTab",
- "QStyleOptionTabBarBase",
- "QStyleOptionTabWidgetFrame",
- "QStyleOptionTitleBar",
- "QStyleOptionToolBar",
- "QStyleOptionToolBox",
- "QStyleOptionToolButton",
- "QStyleOptionViewItem",
- "QStylePainter",
- "QStyledItemDelegate",
- "QSwipeGesture",
- "QSystemTrayIcon",
- "QTabBar",
- "QTabWidget",
- "QTableView",
- "QTableWidget",
- "QTableWidgetItem",
- "QTableWidgetSelectionRange",
- "QTapAndHoldGesture",
- "QTapGesture",
- "QTextBrowser",
- "QTextEdit",
- "QTimeEdit",
- "QToolBar",
- "QToolBox",
- "QToolButton",
- "QToolTip",
- "QTreeView",
- "QTreeWidget",
- "QTreeWidgetItem",
- "QTreeWidgetItemIterator",
- "QUndoCommand",
- "QUndoGroup",
- "QUndoStack",
- "QUndoView",
- "QVBoxLayout",
- "QWhatsThis",
- "QWidget",
- "QWidgetAction",
- "QWidgetItem",
- "QWizard",
- "QWizardPage",
- ],
- "QtCore": [
- "QAbstractAnimation",
- "QAbstractEventDispatcher",
- "QAbstractItemModel",
- "QAbstractListModel",
- "QAbstractState",
- "QAbstractTableModel",
- "QAbstractTransition",
- "QAnimationGroup",
- "QBasicTimer",
- "QBitArray",
- "QBuffer",
- "QByteArray",
- "QByteArrayMatcher",
- "QChildEvent",
- "QCoreApplication",
- "QCryptographicHash",
- "QDataStream",
- "QDate",
- "QDateTime",
- "QDir",
- "QDirIterator",
- "QDynamicPropertyChangeEvent",
- "QEasingCurve",
- "QElapsedTimer",
- "QEvent",
- "QEventLoop",
- "QEventTransition",
- "QFile",
- "QFileInfo",
- "QFileSystemWatcher",
- "QFinalState",
- "QGenericArgument",
- "QGenericReturnArgument",
- "QHistoryState",
- "QIODevice",
- "QLibraryInfo",
- "QLine",
- "QLineF",
- "QLocale",
- "QMargins",
- "QMetaClassInfo",
- "QMetaEnum",
- "QMetaMethod",
- "QMetaObject",
- "QMetaProperty",
- "QMimeData",
- "QModelIndex",
- "QMutex",
- "QMutexLocker",
- "QObject",
- "QParallelAnimationGroup",
- "QPauseAnimation",
- "QPersistentModelIndex",
- "QPluginLoader",
- "QPoint",
- "QPointF",
- "QProcess",
- "QProcessEnvironment",
- "QPropertyAnimation",
- "QReadLocker",
- "QReadWriteLock",
- "QRect",
- "QRectF",
- "QRegExp",
- "QResource",
- "QRunnable",
- "QSemaphore",
- "QSequentialAnimationGroup",
- "QSettings",
- "QSignalMapper",
- "QSignalTransition",
- "QSize",
- "QSizeF",
- "QSocketNotifier",
- "QState",
- "QStateMachine",
- "QSysInfo",
- "QSystemSemaphore",
- "QTemporaryFile",
- "QTextBoundaryFinder",
- "QTextCodec",
- "QTextDecoder",
- "QTextEncoder",
- "QTextStream",
- "QTextStreamManipulator",
- "QThread",
- "QThreadPool",
- "QTime",
- "QTimeLine",
- "QTimer",
- "QTimerEvent",
- "QTranslator",
- "QUrl",
- "QVariantAnimation",
- "QWaitCondition",
- "QWriteLocker",
- "QXmlStreamAttribute",
- "QXmlStreamAttributes",
- "QXmlStreamEntityDeclaration",
- "QXmlStreamEntityResolver",
- "QXmlStreamNamespaceDeclaration",
- "QXmlStreamNotationDeclaration",
- "QXmlStreamReader",
- "QXmlStreamWriter",
- "Qt",
- "QtCriticalMsg",
- "QtDebugMsg",
- "QtFatalMsg",
- "QtMsgType",
- "QtSystemMsg",
- "QtWarningMsg",
- "qAbs",
- "qAddPostRoutine",
- "qChecksum",
- "qCritical",
- "qDebug",
- "qFatal",
- "qFuzzyCompare",
- "qIsFinite",
- "qIsInf",
- "qIsNaN",
- "qIsNull",
- "qRegisterResourceData",
- "qUnregisterResourceData",
- "qVersion",
- "qWarning",
- "qrand",
- "qsrand",
- ],
- "QtXml": [
- "QDomAttr",
- "QDomCDATASection",
- "QDomCharacterData",
- "QDomComment",
- "QDomDocument",
- "QDomDocumentFragment",
- "QDomDocumentType",
- "QDomElement",
- "QDomEntity",
- "QDomEntityReference",
- "QDomImplementation",
- "QDomNamedNodeMap",
- "QDomNode",
- "QDomNodeList",
- "QDomNotation",
- "QDomProcessingInstruction",
- "QDomText",
- "QXmlAttributes",
- "QXmlContentHandler",
- "QXmlDTDHandler",
- "QXmlDeclHandler",
- "QXmlDefaultHandler",
- "QXmlEntityResolver",
- "QXmlErrorHandler",
- "QXmlInputSource",
- "QXmlLexicalHandler",
- "QXmlLocator",
- "QXmlNamespaceSupport",
- "QXmlParseException",
- "QXmlReader",
- "QXmlSimpleReader"
- ],
- "QtHelp": [
- "QHelpContentItem",
- "QHelpContentModel",
- "QHelpContentWidget",
- "QHelpEngine",
- "QHelpEngineCore",
- "QHelpIndexModel",
- "QHelpIndexWidget",
- "QHelpSearchEngine",
- "QHelpSearchQuery",
- "QHelpSearchQueryWidget",
- "QHelpSearchResultWidget"
- ],
- "QtNetwork": [
- "QAbstractNetworkCache",
- "QAbstractSocket",
- "QAuthenticator",
- "QHostAddress",
- "QHostInfo",
- "QLocalServer",
- "QLocalSocket",
- "QNetworkAccessManager",
- "QNetworkAddressEntry",
- "QNetworkCacheMetaData",
- "QNetworkConfiguration",
- "QNetworkConfigurationManager",
- "QNetworkCookie",
- "QNetworkCookieJar",
- "QNetworkDiskCache",
- "QNetworkInterface",
- "QNetworkProxy",
- "QNetworkProxyFactory",
- "QNetworkProxyQuery",
- "QNetworkReply",
- "QNetworkRequest",
- "QNetworkSession",
- "QSsl",
- "QTcpServer",
- "QTcpSocket",
- "QUdpSocket"
- ],
- "QtOpenGL": [
- "QGL",
- "QGLContext",
- "QGLFormat",
- "QGLWidget"
- ]
-}
-
-
-def _new_module(name):
- return types.ModuleType(__name__ + "." + name)
-
-
-def _setup(module, extras):
- """Install common submodules"""
-
- Qt.__binding__ = module.__name__
-
- for name in list(_common_members) + extras:
- try:
- # print("Trying %s" % name)
- submodule = importlib.import_module(
- module.__name__ + "." + name)
- except ImportError:
- # print("Failed %s" % name)
- continue
-
- setattr(Qt, "_" + name, submodule)
-
- if name not in extras:
- # Store reference to original binding,
- # but don't store speciality modules
- # such as uic or QtUiTools
- setattr(Qt, name, _new_module(name))
-
-
-def _pyside2():
- """Initialise PySide2
-
- These functions serve to test the existence of a binding
- along with set it up in such a way that it aligns with
- the final step; adding members from the original binding
- to Qt.py
-
- """
-
- import PySide2 as module
- _setup(module, ["QtUiTools"])
-
- Qt.__binding_version__ = module.__version__
-
- if hasattr(Qt, "_QtUiTools"):
- Qt.QtCompat.loadUi = lambda fname: \
- Qt._QtUiTools.QUiLoader().load(fname)
-
- if hasattr(Qt, "_QtGui") and hasattr(Qt, "_QtCore"):
- Qt.QtCore.QStringListModel = Qt._QtGui.QStringListModel
-
- if hasattr(Qt, "_QtWidgets"):
- Qt.QtCompat.setSectionResizeMode = \
- Qt._QtWidgets.QHeaderView.setSectionResizeMode
-
- if hasattr(Qt, "_QtCore"):
- Qt.__qt_version__ = Qt._QtCore.qVersion()
- Qt.QtCompat.translate = Qt._QtCore.QCoreApplication.translate
-
- Qt.QtCore.Property = Qt._QtCore.Property
- Qt.QtCore.Signal = Qt._QtCore.Signal
- Qt.QtCore.Slot = Qt._QtCore.Slot
-
- Qt.QtCore.QAbstractProxyModel = Qt._QtCore.QAbstractProxyModel
- Qt.QtCore.QSortFilterProxyModel = Qt._QtCore.QSortFilterProxyModel
- Qt.QtCore.QItemSelection = Qt._QtCore.QItemSelection
- Qt.QtCore.QItemSelectionRange = Qt._QtCore.QItemSelectionRange
- Qt.QtCore.QItemSelectionModel = Qt._QtCore.QItemSelectionModel
-
-
-def _pyside():
- """Initialise PySide"""
-
- import PySide as module
- _setup(module, ["QtUiTools"])
-
- Qt.__binding_version__ = module.__version__
-
- if hasattr(Qt, "_QtUiTools"):
- Qt.QtCompat.loadUi = lambda fname: \
- Qt._QtUiTools.QUiLoader().load(fname)
-
- if hasattr(Qt, "_QtGui"):
- setattr(Qt, "QtWidgets", _new_module("QtWidgets"))
- setattr(Qt, "_QtWidgets", Qt._QtGui)
-
- Qt.QtCompat.setSectionResizeMode = Qt._QtGui.QHeaderView.setResizeMode
-
- if hasattr(Qt, "_QtCore"):
- Qt.QtCore.QAbstractProxyModel = Qt._QtGui.QAbstractProxyModel
- Qt.QtCore.QSortFilterProxyModel = Qt._QtGui.QSortFilterProxyModel
- Qt.QtCore.QStringListModel = Qt._QtGui.QStringListModel
- Qt.QtCore.QItemSelection = Qt._QtGui.QItemSelection
- Qt.QtCore.QItemSelectionRange = Qt._QtGui.QItemSelectionRange
- Qt.QtCore.QItemSelectionModel = Qt._QtGui.QItemSelectionModel
-
- if hasattr(Qt, "_QtCore"):
- Qt.__qt_version__ = Qt._QtCore.qVersion()
-
- Qt.QtCore.Property = Qt._QtCore.Property
- Qt.QtCore.Signal = Qt._QtCore.Signal
- Qt.QtCore.Slot = Qt._QtCore.Slot
-
- QCoreApplication = Qt._QtCore.QCoreApplication
- Qt.QtCompat.translate = (
- lambda context, sourceText, disambiguation, n:
- QCoreApplication.translate(
- context,
- sourceText,
- disambiguation,
- QCoreApplication.CodecForTr,
- n
- )
- )
-
-
-def _pyqt5():
- """Initialise PyQt5"""
-
- import PyQt5 as module
- _setup(module, ["uic"])
-
- if hasattr(Qt, "_uic"):
- Qt.QtCompat.loadUi = lambda fname: Qt._uic.loadUi(fname)
-
- if hasattr(Qt, "_QtWidgets"):
- Qt.QtCompat.setSectionResizeMode = \
- Qt._QtWidgets.QHeaderView.setSectionResizeMode
-
- if hasattr(Qt, "_QtCore"):
- Qt.QtCompat.translate = Qt._QtCore.QCoreApplication.translate
-
- Qt.QtCore.Property = Qt._QtCore.pyqtProperty
- Qt.QtCore.Signal = Qt._QtCore.pyqtSignal
- Qt.QtCore.Slot = Qt._QtCore.pyqtSlot
-
- Qt.QtCore.QAbstractProxyModel = Qt._QtCore.QAbstractProxyModel
- Qt.QtCore.QSortFilterProxyModel = Qt._QtCore.QSortFilterProxyModel
- Qt.QtCore.QStringListModel = Qt._QtCore.QStringListModel
- Qt.QtCore.QItemSelection = Qt._QtCore.QItemSelection
- Qt.QtCore.QItemSelectionModel = Qt._QtCore.QItemSelectionModel
- Qt.QtCore.QItemSelectionRange = Qt._QtCore.QItemSelectionRange
-
- Qt.__qt_version__ = Qt._QtCore.QT_VERSION_STR
- Qt.__binding_version__ = Qt._QtCore.PYQT_VERSION_STR
-
-
-def _pyqt4():
- """Initialise PyQt4"""
-
- import sip
-
- # Validation of envivornment variable. Prevents an error if
- # the variable is invalid since it's just a hint.
- try:
- hint = int(QT_SIP_API_HINT)
- except TypeError:
- hint = None # Variable was None, i.e. not set.
- except ValueError:
- raise ImportError("QT_SIP_API_HINT=%s must be a 1 or 2")
-
- for api in ("QString",
- "QVariant",
- "QDate",
- "QDateTime",
- "QTextStream",
- "QTime",
- "QUrl"):
- try:
- sip.setapi(api, hint or 2)
- except AttributeError:
- raise ImportError("PyQt4 < 4.6 isn't supported by Qt.py")
- except ValueError:
- actual = sip.getapi(api)
- if not hint:
- raise ImportError("API version already set to %d" % actual)
- else:
- # Having provided a hint indicates a soft constraint, one
- # that doesn't throw an exception.
- sys.stderr.write(
- "Warning: API '%s' has already been set to %d.\n"
- % (api, actual)
- )
-
- import PyQt4 as module
- _setup(module, ["uic"])
-
- if hasattr(Qt, "_uic"):
- Qt.QtCompat.loadUi = lambda fname: Qt._uic.loadUi(fname)
-
- if hasattr(Qt, "_QtGui"):
- setattr(Qt, "QtWidgets", _new_module("QtWidgets"))
- setattr(Qt, "_QtWidgets", Qt._QtGui)
-
- Qt.QtCompat.setSectionResizeMode = \
- Qt._QtGui.QHeaderView.setResizeMode
-
- if hasattr(Qt, "_QtCore"):
- Qt.QtCore.QAbstractProxyModel = Qt._QtGui.QAbstractProxyModel
- Qt.QtCore.QSortFilterProxyModel = Qt._QtGui.QSortFilterProxyModel
- Qt.QtCore.QItemSelection = Qt._QtGui.QItemSelection
- Qt.QtCore.QStringListModel = Qt._QtGui.QStringListModel
- Qt.QtCore.QItemSelectionModel = Qt._QtGui.QItemSelectionModel
- Qt.QtCore.QItemSelectionRange = Qt._QtGui.QItemSelectionRange
-
- if hasattr(Qt, "_QtCore"):
- Qt.__qt_version__ = Qt._QtCore.QT_VERSION_STR
- Qt.__binding_version__ = Qt._QtCore.PYQT_VERSION_STR
-
- Qt.QtCore.Property = Qt._QtCore.pyqtProperty
- Qt.QtCore.Signal = Qt._QtCore.pyqtSignal
- Qt.QtCore.Slot = Qt._QtCore.pyqtSlot
-
- QCoreApplication = Qt._QtCore.QCoreApplication
- Qt.QtCompat.translate = (
- lambda context, sourceText, disambiguation, n:
- QCoreApplication.translate(
- context,
- sourceText,
- disambiguation,
- QCoreApplication.CodecForTr,
- n)
- )
-
-
-def _none():
- """Internal option (used in installer)"""
-
- Mock = type("Mock", (), {"__getattr__": lambda Qt, attr: None})
-
- Qt.__binding__ = "None"
- Qt.__qt_version__ = "0.0.0"
- Qt.__binding_version__ = "0.0.0"
- Qt.QtCompat.loadUi = lambda fname: None
- Qt.QtCompat.setSectionResizeMode = lambda *args, **kwargs: None
-
- for submodule in _common_members.keys():
- setattr(Qt, submodule, Mock())
- setattr(Qt, "_" + submodule, Mock())
-
-
-def _log(text):
- if QT_VERBOSE:
- sys.stdout.write(text + "\n")
-
-
-def _convert(lines):
- """Convert compiled .ui file from PySide2 to Qt.py
-
- Arguments:
- lines (list): Each line of of .ui file
-
- Usage:
- >> with open("myui.py") as f:
- .. lines = _convert(f.readlines())
-
- """
-
- def parse(line):
- line = line.replace("from PySide2 import", "from Qt import")
- line = line.replace("QtWidgets.QApplication.translate",
- "Qt.QtCompat.translate")
- return line
-
- parsed = list()
- for line in lines:
- line = parse(line)
- parsed.append(line)
-
- return parsed
-
-
-def _cli(args):
- """Qt.py command-line interface"""
- import argparse
-
- parser = argparse.ArgumentParser()
- parser.add_argument("--convert",
- help="Path to compiled Python module, e.g. my_ui.py")
- parser.add_argument("--compile",
- help="Accept raw .ui file and compile with native "
- "PySide2 compiler.")
- parser.add_argument("--stdout",
- help="Write to stdout instead of file",
- action="store_true")
- parser.add_argument("--stdin",
- help="Read from stdin instead of file",
- action="store_true")
-
- args = parser.parse_args(args)
-
- if args.stdout:
- raise NotImplementedError("--stdout")
-
- if args.stdin:
- raise NotImplementedError("--stdin")
-
- if args.compile:
- raise NotImplementedError("--compile")
-
- if args.convert:
- sys.stdout.write("#\n"
- "# WARNING: --convert is an ALPHA feature.\n#\n"
- "# See https://github.com/mottosso/Qt.py/pull/132\n"
- "# for details.\n"
- "#\n")
-
- #
- # ------> Read
- #
- with open(args.convert) as f:
- lines = _convert(f.readlines())
-
- backup = "%s_backup%s" % os.path.splitext(args.convert)
- sys.stdout.write("Creating \"%s\"..\n" % backup)
- shutil.copy(args.convert, backup)
-
- #
- # <------ Write
- #
- with open(args.convert, "w") as f:
- f.write("".join(lines))
-
- sys.stdout.write("Successfully converted \"%s\"\n" % args.convert)
-
-
-def _install():
- # Default order (customise order and content via QT_PREFERRED_BINDING)
- default_order = ("PySide2", "PyQt5", "PySide", "PyQt4")
- preferred_order = list(
- b for b in QT_PREFERRED_BINDING.split(os.pathsep) if b
- )
-
- order = preferred_order or default_order
-
- available = {
- "PySide2": _pyside2,
- "PyQt5": _pyqt5,
- "PySide": _pyside,
- "PyQt4": _pyqt4,
- "None": _none
- }
-
- _log("Order: '%s'" % "', '".join(order))
-
- found_binding = False
- for name in order:
- _log("Trying %s" % name)
-
- try:
- available[name]()
- found_binding = True
- break
-
- except ImportError as e:
- _log("ImportError: %s" % e)
-
- except KeyError:
- _log("ImportError: Preferred binding '%s' not found." % name)
-
- if not found_binding:
- # If not binding were found, throw this error
- raise ImportError("No Qt binding were found.")
-
- # Install individual members
- for name, members in _common_members.items():
- try:
- their_submodule = getattr(Qt, "_%s" % name)
- except AttributeError:
- continue
-
- our_submodule = getattr(Qt, name)
-
- # Enable import *
- __all__.append(name)
-
- # Enable direct import of submodule,
- # e.g. import Qt.QtCore
- sys.modules[__name__ + "." + name] = our_submodule
-
- for member in members:
- # Accept that a submodule may miss certain members.
- try:
- their_member = getattr(their_submodule, member)
- except AttributeError:
- _log("'%s.%s' was missing." % (name, member))
- continue
-
- setattr(our_submodule, member, their_member)
-
- # Backwards compatibility
- Qt.QtCompat.load_ui = Qt.QtCompat.loadUi
-
-
-_install()
-
-
-"""Augment QtCompat
-
-QtCompat contains wrappers and added functionality
-to the original bindings, such as the CLI interface
-and otherwise incompatible members between bindings,
-such as `QHeaderView.setSectionResizeMode`.
-
-"""
-
-Qt.QtCompat._cli = _cli
-Qt.QtCompat._convert = _convert
-
-# Enable command-line interface
-if __name__ == "__main__":
- _cli(sys.argv[1:])
diff --git a/openpype/vendor/python/common/capture_gui/version.py b/openpype/vendor/python/common/capture_gui/version.py
deleted file mode 100644
index badefb1659..0000000000
--- a/openpype/vendor/python/common/capture_gui/version.py
+++ /dev/null
@@ -1,9 +0,0 @@
-VERSION_MAJOR = 1
-VERSION_MINOR = 5
-VERSION_PATCH = 0
-
-
-version = '{}.{}.{}'.format(VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH)
-__version__ = version
-
-__all__ = ['version', 'version_info', '__version__']
diff --git a/openpype/version.py b/openpype/version.py
index a88ae329d0..202cb9348e 100644
--- a/openpype/version.py
+++ b/openpype/version.py
@@ -1,3 +1,3 @@
# -*- coding: utf-8 -*-
"""Package declaring Pype version."""
-__version__ = "3.0.0-rc.5"
+__version__ = "3.0.0-rc.6"
diff --git a/pyproject.toml b/pyproject.toml
index f7eeafd04f..7ba869e50e 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[tool.poetry]
name = "OpenPype"
-version = "3.0.0-rc.5"
+version = "3.0.0-rc.6"
description = "Open VFX and Animation pipeline with support."
authors = ["OpenPype Team "]
license = "MIT License"
diff --git a/repos/avalon-core b/repos/avalon-core
index cfd4191e36..07756c7368 160000
--- a/repos/avalon-core
+++ b/repos/avalon-core
@@ -1 +1 @@
-Subproject commit cfd4191e364b47de7364096f45d9d9d9a901692a
+Subproject commit 07756c7368e4447d28f27dc88b6a46c95692e035
diff --git a/start.py b/start.py
index 660d0c9006..8e7c195e95 100644
--- a/start.py
+++ b/start.py
@@ -6,10 +6,11 @@ Bootstrapping process of OpenPype is as follows:
`OPENPYPE_PATH` is checked for existence - either one from environment or
from user settings. Precedence takes the one set by environment.
-On this path we try to find OpenPype in directories version string in their names.
-For example: `openpype-v3.0.1-foo` is valid name, or even `foo_3.0.2` - as long
-as version can be determined from its name _AND_ file `openpype/openpype/version.py`
-can be found inside, it is considered OpenPype installation.
+On this path we try to find OpenPype in directories version string in their
+names. For example: `openpype-v3.0.1-foo` is valid name, or
+even `foo_3.0.2` - as long as version can be determined from its name
+_AND_ file `openpype/openpype/version.py` can be found inside, it is
+considered OpenPype installation.
If no OpenPype repositories are found in `OPENPYPE_PATH` (user data dir)
then **Igniter** (OpenPype setup tool) will launch its GUI.
@@ -20,19 +21,19 @@ appdata dir in user home and extract it there. Version will be determined by
version specified in OpenPype module.
If OpenPype repository directories are found in default install location
-(user data dir) or in `OPENPYPE_PATH`, it will get list of those dirs there and
-use latest one or the one specified with optional `--use-version` command
-line argument. If the one specified doesn't exist then latest available
-version will be used. All repositories in that dir will be added
+(user data dir) or in `OPENPYPE_PATH`, it will get list of those dirs
+there and use latest one or the one specified with optional `--use-version`
+command line argument. If the one specified doesn't exist then latest
+available version will be used. All repositories in that dir will be added
to `sys.path` and `PYTHONPATH`.
-If OpenPype is live (not frozen) then current version of OpenPype module will be
-used. All directories under `repos` will be added to `sys.path` and
+If OpenPype is live (not frozen) then current version of OpenPype module
+will be used. All directories under `repos` will be added to `sys.path` and
`PYTHONPATH`.
-OpenPype depends on connection to `MongoDB`_. You can specify MongoDB connection
-string via `OPENPYPE_MONGO` set in environment or it can be set in user
-settings or via **Igniter** GUI.
+OpenPype depends on connection to `MongoDB`_. You can specify MongoDB
+connection string via `OPENPYPE_MONGO` set in environment or it can be set
+in user settings or via **Igniter** GUI.
So, bootstrapping OpenPype looks like this::
@@ -99,7 +100,6 @@ import traceback
import subprocess
import site
from pathlib import Path
-import platform
# OPENPYPE_ROOT is variable pointing to build (or code) directory
@@ -112,17 +112,6 @@ if not getattr(sys, 'frozen', False):
else:
OPENPYPE_ROOT = os.path.dirname(sys.executable)
- # FIX #1469: Certificates from certifi are not available in some
- # macos builds, so connection to ftrack/mongo will fail with
- # unable to verify certificate issuer error. This will add certifi
- # certificates so ssl can see them.
- # WARNING: this can break stuff if custom certificates are used. In that
- # case they need to be merged to certificate bundle and SSL_CERT_FILE
- # should point to them.
- if not os.getenv("SSL_CERT_FILE") and platform.system().lower() == "darwin": # noqa: E501
- ssl_cert_file = Path(OPENPYPE_ROOT) / "dependencies" / "certifi" / "cacert.pem" # noqa: E501
- os.environ["SSL_CERT_FILE"] = ssl_cert_file.as_posix()
-
# add dependencies folder to sys.pat for frozen code
frozen_libs = os.path.normpath(
os.path.join(OPENPYPE_ROOT, "dependencies")
@@ -135,6 +124,44 @@ else:
paths.append(frozen_libs)
os.environ["PYTHONPATH"] = os.pathsep.join(paths)
+
+import blessed # noqa: E402
+import certifi # noqa: E402
+
+
+if sys.__stdout__:
+ term = blessed.Terminal()
+
+ def _print(message: str):
+ if message.startswith("!!! "):
+ print("{}{}".format(term.orangered2("!!! "), message[4:]))
+ if message.startswith(">>> "):
+ print("{}{}".format(term.aquamarine3(">>> "), message[4:]))
+ if message.startswith("--- "):
+ print("{}{}".format(term.darkolivegreen3("--- "), message[4:]))
+ if message.startswith(" "):
+ print("{}{}".format(term.darkseagreen3(" "), message[4:]))
+ if message.startswith("*** "):
+ print("{}{}".format(term.gold("*** "), message[4:]))
+ if message.startswith(" - "):
+ print("{}{}".format(term.wheat(" - "), message[4:]))
+ if message.startswith(" . "):
+ print("{}{}".format(term.tan(" . "), message[4:]))
+else:
+ def _print(message: str):
+ print(message)
+
+
+# if SSL_CERT_FILE is not set prior to OpenPype launch, we set it to point
+# to certifi bundle to make sure we have reasonably new CA certificates.
+if os.getenv("SSL_CERT_FILE") and \
+ os.getenv("SSL_CERT_FILE") != certifi.where():
+ _print("--- your system is set to use custom CA certificate bundle.")
+else:
+ ssl_cert_file = certifi.where()
+ os.environ["SSL_CERT_FILE"] = ssl_cert_file
+
+
import igniter # noqa: E402
from igniter import BootstrapRepos # noqa: E402
from igniter.tools import (
@@ -197,7 +224,7 @@ def run(arguments: list, env: dict = None) -> int:
p = subprocess.Popen(interpreter, env=env)
p.wait()
- print(f">>> done [{p.returncode}]")
+ _print(f">>> done [{p.returncode}]")
return p.returncode
@@ -278,11 +305,12 @@ def _process_arguments() -> tuple:
use_staging = False
for arg in sys.argv:
if arg == "--use-version":
- print("!!! Please use option --use-version like:")
- print(" --use-version=3.0.0")
+ _print("!!! Please use option --use-version like:")
+ _print(" --use-version=3.0.0")
sys.exit(1)
- m = re.search(r"--use-version=(?P\d+\.\d+\.\d*.+?)", arg)
+ m = re.search(
+ r"--use-version=(?P\d+\.\d+\.\d+(?:\S*)?)", arg)
if m and m.group('version'):
use_version = m.group('version')
sys.argv.remove(arg)
@@ -336,12 +364,12 @@ def _determine_mongodb() -> str:
if openpype_mongo:
result, msg = validate_mongo_connection(openpype_mongo)
if not result:
- print(msg)
+ _print(msg)
openpype_mongo = None
if not openpype_mongo:
- print("*** No DB connection string specified.")
- print("--- launching setup UI ...")
+ _print("*** No DB connection string specified.")
+ _print("--- launching setup UI ...")
result = igniter.open_dialog()
if result == 0:
@@ -366,7 +394,7 @@ def _initialize_environment(openpype_version: OpenPypeVersion) -> None:
version_path.as_posix()
)
# inject version to Python environment (sys.path, ...)
- print(">>> Injecting OpenPype version to running environment ...")
+ _print(">>> Injecting OpenPype version to running environment ...")
bootstrap.add_paths_from_directory(version_path)
# Additional sys paths related to OPENPYPE_REPOS_ROOT directory
@@ -414,6 +442,7 @@ def _find_frozen_openpype(use_version: str = None,
(if requested).
"""
+ version_path = None
openpype_version = None
openpype_versions = bootstrap.find_openpype(include_zips=True,
staging=use_staging)
@@ -433,9 +462,8 @@ def _find_frozen_openpype(use_version: str = None,
if local_version == openpype_versions[-1]:
os.environ["OPENPYPE_TRYOUT"] = "1"
openpype_versions = []
-
else:
- print("!!! Warning: cannot determine current running version.")
+ _print("!!! Warning: cannot determine current running version.")
if not os.getenv("OPENPYPE_TRYOUT"):
try:
@@ -443,8 +471,8 @@ def _find_frozen_openpype(use_version: str = None,
openpype_version = openpype_versions[-1]
except IndexError:
# no OpenPype version found, run Igniter and ask for them.
- print('*** No OpenPype versions found.')
- print("--- launching setup UI ...")
+ _print('*** No OpenPype versions found.')
+ _print("--- launching setup UI ...")
import igniter
return_code = igniter.open_dialog()
if return_code == 2:
@@ -452,25 +480,25 @@ def _find_frozen_openpype(use_version: str = None,
if return_code == 3:
# run OpenPype after installation
- print('>>> Finding OpenPype again ...')
+ _print('>>> Finding OpenPype again ...')
openpype_versions = bootstrap.find_openpype(
staging=use_staging)
try:
openpype_version = openpype_versions[-1]
except IndexError:
- print(("!!! Something is wrong and we didn't "
+ _print(("!!! Something is wrong and we didn't "
"found it again."))
sys.exit(1)
elif return_code != 2:
- print(f" . finished ({return_code})")
+ _print(f" . finished ({return_code})")
sys.exit(return_code)
if not openpype_versions:
# no openpype versions found anyway, lets use then the one
# shipped with frozen OpenPype
if not os.getenv("OPENPYPE_TRYOUT"):
- print("*** Still no luck finding OpenPype.")
- print(("*** We'll try to use the one coming "
+ _print("*** Still no luck finding OpenPype.")
+ _print(("*** We'll try to use the one coming "
"with OpenPype installation."))
version_path = _bootstrap_from_code(use_version)
openpype_version = OpenPypeVersion(
@@ -480,17 +508,25 @@ def _find_frozen_openpype(use_version: str = None,
return version_path
# get path of version specified in `--use-version`
- version_path = BootstrapRepos.get_version_path_from_list(
- use_version, openpype_versions)
+ local_version = bootstrap.get_version(OPENPYPE_ROOT)
+ if use_version and use_version != local_version:
+ # force the one user has selected
+ openpype_version = None
+ openpype_versions = bootstrap.find_openpype(include_zips=True,
+ staging=use_staging)
+ v: OpenPypeVersion
+ found = [v for v in openpype_versions if str(v) == use_version]
+ if found:
+ openpype_version = sorted(found)[-1]
+ if not openpype_version:
+ _print(f"!!! requested version {use_version} was not found.")
+ if openpype_versions:
+ _print(" - found: ")
+ for v in sorted(openpype_versions):
+ _print(f" - {v}: {v.path}")
- if not version_path:
- if use_version is not None and openpype_version:
- print(("!!! Specified version was not found, using "
- "latest available"))
- # specified version was not found so use latest detected.
- version_path = openpype_version.path
- print(f">>> Using version [ {openpype_version} ]")
- print(f" From {version_path}")
+ _print(f" - local version {local_version}")
+ sys.exit(1)
# test if latest detected is installed (in user data dir)
is_inside = False
@@ -508,11 +544,11 @@ def _find_frozen_openpype(use_version: str = None,
openpype_version, force=True)
if openpype_version.path.is_file():
- print(">>> Extracting zip file ...")
+ _print(">>> Extracting zip file ...")
try:
version_path = bootstrap.extract_openpype(openpype_version)
except OSError as e:
- print("!!! failed: {}".format(str(e)))
+ _print("!!! failed: {}".format(str(e)))
sys.exit(1)
else:
# cleanup zip after extraction
@@ -521,7 +557,7 @@ def _find_frozen_openpype(use_version: str = None,
openpype_version.path = version_path
_initialize_environment(openpype_version)
- return version_path
+ return openpype_version.path
def _bootstrap_from_code(use_version):
@@ -536,36 +572,53 @@ def _bootstrap_from_code(use_version):
"""
# run through repos and add them to `sys.path` and `PYTHONPATH`
# set root
+ _openpype_root = OPENPYPE_ROOT
if getattr(sys, 'frozen', False):
- local_version = bootstrap.get_version(Path(OPENPYPE_ROOT))
- print(f" - running version: {local_version}")
+ local_version = bootstrap.get_version(Path(_openpype_root))
+ _print(f" - running version: {local_version}")
assert local_version
else:
# get current version of OpenPype
local_version = bootstrap.get_local_live_version()
- os.environ["OPENPYPE_VERSION"] = local_version
if use_version and use_version != local_version:
+ version_to_use = None
openpype_versions = bootstrap.find_openpype(include_zips=True)
- version_path = BootstrapRepos.get_version_path_from_list(
- use_version, openpype_versions)
- if version_path:
- # use specified
- bootstrap.add_paths_from_directory(version_path)
- os.environ["OPENPYPE_VERSION"] = use_version
- else:
- version_path = OPENPYPE_ROOT
+ v: OpenPypeVersion
+ found = [v for v in openpype_versions if str(v) == use_version]
+ if found:
+ version_to_use = sorted(found)[-1]
- repos = os.listdir(os.path.join(OPENPYPE_ROOT, "repos"))
- repos = [os.path.join(OPENPYPE_ROOT, "repos", repo) for repo in repos]
+ if version_to_use:
+ # use specified
+ if version_to_use.path.is_file():
+ version_to_use.path = bootstrap.extract_openpype(
+ version_to_use)
+ bootstrap.add_paths_from_directory(version_to_use.path)
+ os.environ["OPENPYPE_VERSION"] = use_version
+ version_path = version_to_use.path
+ os.environ["OPENPYPE_REPOS_ROOT"] = (version_path / "openpype").as_posix() # noqa: E501
+ _openpype_root = version_to_use.path.as_posix()
+ else:
+ _print(f"!!! requested version {use_version} was not found.")
+ if openpype_versions:
+ _print(" - found: ")
+ for v in sorted(openpype_versions):
+ _print(f" - {v}: {v.path}")
+
+ _print(f" - local version {local_version}")
+ sys.exit(1)
+ else:
+ os.environ["OPENPYPE_VERSION"] = local_version
+ version_path = Path(_openpype_root)
+ os.environ["OPENPYPE_REPOS_ROOT"] = _openpype_root
+
+ repos = os.listdir(os.path.join(_openpype_root, "repos"))
+ repos = [os.path.join(_openpype_root, "repos", repo) for repo in repos]
# add self to python paths
- repos.insert(0, OPENPYPE_ROOT)
+ repos.insert(0, _openpype_root)
for repo in repos:
sys.path.insert(0, repo)
-
- # Set OPENPYPE_REPOS_ROOT to code root
- os.environ["OPENPYPE_REPOS_ROOT"] = OPENPYPE_ROOT
-
# add venv 'site-packages' to PYTHONPATH
python_path = os.getenv("PYTHONPATH", "")
split_paths = python_path.split(os.pathsep)
@@ -580,11 +633,11 @@ def _bootstrap_from_code(use_version):
# point to same hierarchy from code and from frozen OpenPype
additional_paths = [
# add OpenPype tools
- os.path.join(OPENPYPE_ROOT, "openpype", "tools"),
+ os.path.join(_openpype_root, "openpype", "tools"),
# add common OpenPype vendor
# (common for multiple Python interpreter versions)
os.path.join(
- OPENPYPE_ROOT,
+ _openpype_root,
"openpype",
"vendor",
"python",
@@ -597,7 +650,7 @@ def _bootstrap_from_code(use_version):
os.environ["PYTHONPATH"] = os.pathsep.join(split_paths)
- return Path(version_path)
+ return version_path
def boot():
@@ -624,6 +677,10 @@ def boot():
use_version, use_staging = _process_arguments()
+ if os.getenv("OPENPYPE_VERSION"):
+ use_staging = "staging" in os.getenv("OPENPYPE_VERSION")
+ use_version = os.getenv("OPENPYPE_VERSION")
+
# ------------------------------------------------------------------------
# Determine mongodb connection
# ------------------------------------------------------------------------
@@ -632,7 +689,7 @@ def boot():
openpype_mongo = _determine_mongodb()
except RuntimeError as e:
# without mongodb url we are done for.
- print(f"!!! {e}")
+ _print(f"!!! {e}")
sys.exit(1)
os.environ["OPENPYPE_MONGO"] = openpype_mongo
@@ -642,7 +699,7 @@ def boot():
# find its versions there and bootstrap them.
openpype_path = get_openpype_path_from_db(openpype_mongo)
if not openpype_path:
- print("*** Cannot get OpenPype path from database.")
+ _print("*** Cannot get OpenPype path from database.")
if not os.getenv("OPENPYPE_PATH") and openpype_path:
os.environ["OPENPYPE_PATH"] = openpype_path
@@ -658,7 +715,7 @@ def boot():
version_path = _find_frozen_openpype(use_version, use_staging)
except RuntimeError as e:
# no version to run
- print(f"!!! {e}")
+ _print(f"!!! {e}")
sys.exit(1)
else:
version_path = _bootstrap_from_code(use_version)
@@ -683,13 +740,13 @@ def boot():
except KeyError:
pass
- print(">>> loading environments ...")
+ _print(">>> loading environments ...")
# Avalon environments must be set before avalon module is imported
- print(" - for Avalon ...")
+ _print(" - for Avalon ...")
set_avalon_environments()
- print(" - global OpenPype ...")
+ _print(" - global OpenPype ...")
set_openpype_global_environments()
- print(" - for modules ...")
+ _print(" - for modules ...")
set_modules_environments()
from openpype import cli
@@ -719,7 +776,7 @@ def boot():
cli.main(obj={}, prog_name="openpype")
except Exception: # noqa
exc_info = sys.exc_info()
- print("!!! OpenPype crashed:")
+ _print("!!! OpenPype crashed:")
traceback.print_exception(*exc_info)
sys.exit(1)
diff --git a/tools/build.ps1 b/tools/build.ps1
index d9fef0f471..c8c2f392ad 100644
--- a/tools/build.ps1
+++ b/tools/build.ps1
@@ -175,9 +175,9 @@ if (-not (Test-Path -PathType Container -Path "$openpype_root\.poetry\bin")) {
Write-Host ">>> " -NoNewline -ForegroundColor green
Write-Host "Cleaning cache files ... " -NoNewline
-Get-ChildItem $openpype_root -Filter "*.pyc" -Force -Recurse | Remove-Item -Force
-Get-ChildItem $openpype_root -Filter "*.pyo" -Force -Recurse | Remove-Item -Force
-Get-ChildItem $openpype_root -Filter "__pycache__" -Force -Recurse | Remove-Item -Force -Recurse
+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-Host ">>> " -NoNewline -ForegroundColor green
diff --git a/tools/build.sh b/tools/build.sh
index ccd97ea4c1..aa8f0121ea 100755
--- a/tools/build.sh
+++ b/tools/build.sh
@@ -122,7 +122,8 @@ clean_pyc () {
local path
path=$openpype_root
echo -e "${BIGreen}>>>${RST} Cleaning pyc at [ ${BIWhite}$path${RST} ] ... \c"
- find "$path" -regex '^.*\(__pycache__\|\.py[co]\)$' -delete
+ find "$path" -path ./build -prune -o -regex '^.*\(__pycache__\|\.py[co]\)$' -delete
+
echo -e "${BIGreen}DONE${RST}"
}
diff --git a/tools/create_env.ps1 b/tools/create_env.ps1
index 7ada92c1e8..94a91ce48f 100644
--- a/tools/create_env.ps1
+++ b/tools/create_env.ps1
@@ -76,16 +76,20 @@ print('{0}.{1}'.format(sys.version_info[0], sys.version_info[1]))
Set-Location -Path $current_dir
Exit-WithCode 1
}
- # We are supporting python 3.6 and up
- if(($matches[1] -lt 3) -or ($matches[2] -lt 7)) {
+ # 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
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
+ } else {
+ Write-Host "OK [ $p ]" -ForegroundColor green
}
- Write-Host "OK [ $p ]" -ForegroundColor green
}
-
$current_dir = Get-Location
$script_dir = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent
$openpype_root = (Get-Item $script_dir).parent.FullName
diff --git a/tools/create_env.sh b/tools/create_env.sh
index d6a6828718..226a26e199 100755
--- a/tools/create_env.sh
+++ b/tools/create_env.sh
@@ -126,7 +126,7 @@ clean_pyc () {
local path
path=$openpype_root
echo -e "${BIGreen}>>>${RST} Cleaning pyc at [ ${BIWhite}$path${RST} ] ... \c"
- find "$path" -regex '^.*\(__pycache__\|\.py[co]\)$' -delete
+ find "$path" -path ./build -prune -o -regex '^.*\(__pycache__\|\.py[co]\)$' -delete
echo -e "${BIGreen}DONE${RST}"
}
diff --git a/tools/create_zip.ps1 b/tools/create_zip.ps1
index a34af89159..1a7520eb11 100644
--- a/tools/create_zip.ps1
+++ b/tools/create_zip.ps1
@@ -98,9 +98,9 @@ if (-not (Test-Path -PathType Container -Path "$openpype_root\.poetry\bin")) {
Write-Host ">>> " -NoNewline -ForegroundColor green
Write-Host "Cleaning cache files ... " -NoNewline
-Get-ChildItem $openpype_root -Filter "*.pyc" -Force -Recurse | Remove-Item -Force
-Get-ChildItem $openpype_root -Filter "*.pyo" -Force -Recurse | Remove-Item -Force
-Get-ChildItem $openpype_root -Filter "__pycache__" -Force -Recurse | Remove-Item -Force -Recurse
+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-Host ">>> " -NoNewline -ForegroundColor green
diff --git a/tools/create_zip.sh b/tools/create_zip.sh
index adaf9431a7..ec0276b040 100755
--- a/tools/create_zip.sh
+++ b/tools/create_zip.sh
@@ -89,23 +89,6 @@ detect_python () {
fi
}
-##############################################################################
-# Clean pyc files in specified directory
-# Globals:
-# None
-# Arguments:
-# Optional path to clean
-# Returns:
-# None
-###############################################################################
-clean_pyc () {
- local path
- path=$openpype_root
- echo -e "${BIGreen}>>>${RST} Cleaning pyc at [ ${BIWhite}$path${RST} ] ... \c"
- find "$path" -regex '^.*\(__pycache__\|\.py[co]\)$' -delete
- echo -e "${BIGreen}DONE${RST}"
-}
-
##############################################################################
# Return absolute path
# Globals:
diff --git a/tools/run_project_manager.ps1 b/tools/run_project_manager.ps1
index 67c2d2eb5e..9886a80316 100644
--- a/tools/run_project_manager.ps1
+++ b/tools/run_project_manager.ps1
@@ -10,9 +10,51 @@
PS> .\run_project_manager.ps1
#>
+
+$art = @"
+
+ . . .. . ..
+ _oOOP3OPP3Op_. .
+ .PPpo~. .. ~2p. .. .... . .
+ .Ppo . .pPO3Op.. . O:. . . .
+ .3Pp . oP3'. 'P33. . 4 .. . . . .. . . .
+ .~OP 3PO. .Op3 : . .. _____ _____ _____
+ .P3O . oP3oP3O3P' . . . . / /./ /./ /
+ O3:. O3p~ . .:. . ./____/./____/ /____/
+ 'P . 3p3. oP3~. ..P:. . . .. . . .. . . .
+ . ': . Po' .Opo'. .3O. . o[ by Pype Club ]]]==- - - . .
+ . '_ .. . . _OP3.. . .https://openpype.io.. .
+ ~P3.OPPPO3OP~ . .. .
+ . ' '. . .. . . . .. .
+
+"@
+
+Write-Host $art -ForegroundColor DarkGreen
+
$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"
+
+# make sure Poetry is in PATH
+if (-not (Test-Path 'env:POETRY_HOME')) {
+ $env:POETRY_HOME = "$openpype_root\.poetry"
+}
+$env:PATH = "$($env:PATH);$($env:POETRY_HOME)\bin"
+
Set-Location -Path $openpype_root
+
+Write-Host ">>> " -NoNewline -ForegroundColor Green
+Write-Host "Reading Poetry ... " -NoNewline
+if (-not (Test-Path -PathType Container -Path "$openpype_root\.poetry\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"
+} else {
+ Write-Host "OK" -ForegroundColor Green
+}
+
& poetry run python "$($openpype_root)\start.py" projectmanager
Set-Location -Path $current_dir
diff --git a/tools/run_projectmanager.sh b/tools/run_projectmanager.sh
new file mode 100755
index 0000000000..312f321d67
--- /dev/null
+++ b/tools/run_projectmanager.sh
@@ -0,0 +1,103 @@
+#!/usr/bin/env bash
+
+# Run OpenPype Settings GUI
+
+
+art () {
+ cat <<-EOF
+
+ . . .. . ..
+ _oOOP3OPP3Op_. .
+ .PPpo~· ·· ~2p. ·· ···· · ·
+ ·Ppo · .pPO3Op.· · O:· · · ·
+ .3Pp · oP3'· 'P33· · 4 ·· · · · ·· · · ·
+ ·~OP 3PO· .Op3 : · ·· _____ _____ _____
+ ·P3O · oP3oP3O3P' · · · · / /·/ /·/ /
+ O3:· O3p~ · ·:· · ·/____/·/____/ /____/
+ 'P · 3p3· oP3~· ·.P:· · · ·· · · ·· · · ·
+ · ': · Po' ·Opo'· .3O· . o[ by Pype Club ]]]==- - - · ·
+ · '_ .. · . _OP3·· · ·https://openpype.io·· ·
+ ~P3·OPPPO3OP~ · ·· ·
+ · ' '· · ·· · · · ·· ·
+
+EOF
+}
+
+# Colors for terminal
+
+RST='\033[0m' # Text Reset
+
+# Regular Colors
+Black='\033[0;30m' # Black
+Red='\033[0;31m' # Red
+Green='\033[0;32m' # Green
+Yellow='\033[0;33m' # Yellow
+Blue='\033[0;34m' # Blue
+Purple='\033[0;35m' # Purple
+Cyan='\033[0;36m' # Cyan
+White='\033[0;37m' # White
+
+# Bold
+BBlack='\033[1;30m' # Black
+BRed='\033[1;31m' # Red
+BGreen='\033[1;32m' # Green
+BYellow='\033[1;33m' # Yellow
+BBlue='\033[1;34m' # Blue
+BPurple='\033[1;35m' # Purple
+BCyan='\033[1;36m' # Cyan
+BWhite='\033[1;37m' # White
+
+# Bold High Intensity
+BIBlack='\033[1;90m' # Black
+BIRed='\033[1;91m' # Red
+BIGreen='\033[1;92m' # Green
+BIYellow='\033[1;93m' # Yellow
+BIBlue='\033[1;94m' # Blue
+BIPurple='\033[1;95m' # Purple
+BICyan='\033[1;96m' # Cyan
+BIWhite='\033[1;97m' # White
+
+
+##############################################################################
+# Return absolute path
+# Globals:
+# None
+# Arguments:
+# Path to resolve
+# Returns:
+# None
+###############################################################################
+realpath () {
+ echo $(cd $(dirname "$1"); pwd)/$(basename "$1")
+}
+
+# Main
+main () {
+
+ # Directories
+ openpype_root=$(realpath $(dirname $(dirname "${BASH_SOURCE[0]}")))
+
+ _inside_openpype_tool="1"
+
+ # make sure Poetry is in PATH
+ if [[ -z $POETRY_HOME ]]; then
+ export POETRY_HOME="$openpype_root/.poetry"
+ fi
+ export PATH="$POETRY_HOME/bin:$PATH"
+
+ pushd "$openpype_root" > /dev/null || return > /dev/null
+
+ echo -e "${BIGreen}>>>${RST} Reading Poetry ... \c"
+ if [ -f "$POETRY_HOME/bin/poetry" ]; then
+ echo -e "${BIGreen}OK${RST}"
+ else
+ echo -e "${BIYellow}NOT FOUND${RST}"
+ echo -e "${BIYellow}***${RST} We need to install Poetry and virtual env ..."
+ . "$openpype_root/tools/create_env.sh" || { echo -e "${BIRed}!!!${RST} Poetry installation failed"; return; }
+ fi
+
+ echo -e "${BIGreen}>>>${RST} Generating zip from current sources ..."
+ poetry run python "$openpype_root/start.py" projectmanager
+}
+
+main
diff --git a/tools/run_tests.ps1 b/tools/run_tests.ps1
index 30e1f29e59..a6882e2a09 100644
--- a/tools/run_tests.ps1
+++ b/tools/run_tests.ps1
@@ -94,8 +94,8 @@ if (-not (Test-Path -PathType Container -Path "$openpype_root\.poetry\bin")) {
Write-Host ">>> " -NoNewline -ForegroundColor green
Write-Host "Cleaning cache files ... " -NoNewline
-Get-ChildItem $openpype_root -Filter "*.pyc" -Force -Recurse | Remove-Item -Force
-Get-ChildItem $openpype_root -Filter "__pycache__" -Force -Recurse | Remove-Item -Force -Recurse
+Get-ChildItem $openpype_root -Filter "*.pyc" -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-Host ">>> " -NoNewline -ForegroundColor green
diff --git a/tools/run_tests.sh b/tools/run_tests.sh
index 3620ebc0e5..90977edc83 100755
--- a/tools/run_tests.sh
+++ b/tools/run_tests.sh
@@ -70,7 +70,7 @@ clean_pyc () {
local path
path=$openpype_root
echo -e "${BIGreen}>>>${RST} Cleaning pyc at [ ${BIWhite}$path${RST} ] ... \c"
- find "$path" -regex '^.*\(__pycache__\|\.py[co]\)$' -delete
+ find "$path" -path ./build -prune -o -regex '^.*\(__pycache__\|\.py[co]\)$' -delete
echo -e "${BIGreen}DONE${RST}"
}
diff --git a/website/docs/admin_distribute.md b/website/docs/admin_distribute.md
index b0ab71e2f3..b574a21cb2 100644
--- a/website/docs/admin_distribute.md
+++ b/website/docs/admin_distribute.md
@@ -41,10 +41,26 @@ version to run for the artist, until a higher version is detected in the update
#### Manual Updates
If for some reason you don't want to use the automatic updates, you can distribute your
-zips manually. Your artist will then have to unpack them to the correct place on their disk.
+zips manually. Your artist will then have to put them to the correct place on their disk.
+Zips will be automatically unzipped there.
The default locations are:
-- Windows: `C:\Users\%USERNAME%\AppData\Local\pypeclub\openpype`
-- Linux: ` `
-- Mac: ` `
+- Windows: `%LOCALAPPDATA%\pypeclub\openpype`
+- Linux: `~/.local/share/pypeclub/openpype`
+- Mac: `~/Library/Application Support/pypeclub/openpype`
+
+
+### Staging vs. Production
+You can have version of OpenPype with experimental features you want to try somewhere but you
+don't want to disrupt your production. You can tag version as **staging** simply by appending `+staging`
+to its name.
+
+So if you have OpenPype version like `OpenPype-v3.0.0.zip` just name it `OpenPype-v3.0.0+staging.zip`.
+When both these versions are present, production one will always take precedence over staging.
+
+You can run OpenPype with `--use-staging` argument to add use staging versions.
+
+:::note
+Running staging version is identified by orange **P** icon in system tray.
+:::
\ No newline at end of file
diff --git a/website/docs/admin_openpype_commands.md b/website/docs/admin_openpype_commands.md
index 6e187c3c8a..324e0e8481 100644
--- a/website/docs/admin_openpype_commands.md
+++ b/website/docs/admin_openpype_commands.md
@@ -4,137 +4,154 @@ title: OpenPype Commands Reference
sidebar_label: OpenPype Commands
---
+:::info
+You can substitute `openpype_console` with `poetry run python start.py` if you want to run it
+directly from sources.
+:::
-## `tray`
+:::note
+Running OpenPype without any commands will default to `tray`.
+:::
-To launch Tray:
-```sh
-pype tray
+## Common arguments
+`--use-version` to specify explicit version to use:
+```shell
+openpype_console --use-version=3.0.0-foo+bar
```
-### `--debug`
+`--use-staging` - to use staging versions of OpenPype.
+
+For more information [see here](admin_use#run-openpype).
+
+## Commands
+
+| Command | Description | Arguments |
+| --- | --- |: --- :|
+| tray | Launch OpenPype Tray. | [📑](#tray-arguments)
+| eventserver | This should be ideally used by system service (such as systemd or upstart on linux and window service). | [📑](#eventserver-arguments) |
+| launch | Launch application in Pype environment. | [📑](#launch-arguments) |
+| publish | Pype takes JSON from provided path and use it to publish data in it. | [📑](#publish-arguments) |
+| extractenvironments | Extract environment variables for entered context to a json file. | [📑](#extractenvironments-arguments) |
+| run | Execute given python script within OpenPype environment. | [📑](#run-arguments) |
+| projectmanager | Launch Project Manager UI | [📑](#projectmanager-arguments) |
+| settings | Open Settings UI | [📑](#settings-arguments) |
+| standalonepublisher | Open Standalone Publisher UI | [📑](#standalonepublisher-arguments) |
+
+---
+### `tray` arguments {#tray-arguments}
+| Argument | Description |
+| --- | --- |
+| `--debug` | print verbose information useful for debugging (works with `openpype_console`) |
To launch Tray with debugging information:
-```sh
-pype tray --debug
+```shell
+openpype_console tray --debug
```
+---
+### `launch` arguments {#eventserver-arguments}
+You have to set either proper environment variables to provide URL and credentials or use
+option to specify them. If you use `--store_credentials` provided credentials will be stored for later use.
---------------------
-
-
-## `eventserver`
-
-This command launches ftrack event server.
-
-This should be ideally used by system service (such us systemd or upstart
-on linux and window service).
-
-You have to set either proper environment variables to provide URL and
-credentials or use option to specify them. If you use `--store_credentials`
-provided credentials will be stored for later use.
+| Argument | Description |
+| --- | --- |
+| `--debug` | print debug info |
+| `--ftrack-url` | URL to ftrack server (can be set with `FTRACK_SERVER`) |
+| `--ftrack-user` |user name to log in to ftrack (can be set with `FTRACK_API_USER`) |
+| `--ftrack-api-key` | ftrack api key (can be set with `FTRACK_API_KEY`) |
+| `--ftrack-events-path` | path to event server plugins (can be set with `FTRACK_EVENTS_PATH`) |
+| `--no-stored-credentials` | will use credential specified with options above |
+| `--store-credentials` | will store credentials to file for later use |
+| `--legacy` | run event server without mongo storing |
+| `--clockify-api-key` | Clockify API key (can be set with `CLOCKIFY_API_KEY`) |
+| `--clockify-workspace` | Clockify workspace (can be set with `CLOCKIFY_WORKSPACE`) |
To run ftrack event server:
-```sh
-pype eventserver --ftrack-url= --ftrack-user= --ftrack-api-key= --ftrack-events-path= --no-stored-credentials --store-credentials
+```shell
+openpype_console eventserver --ftrack-url= --ftrack-user= --ftrack-api-key= --ftrack-events-path= --no-stored-credentials --store-credentials
```
+---
+### `launch` arguments {#launch-arguments}
-### `--debug`
-- print debug info
-
-### `--ftrack-url`
-- URL to ftrack server
-
-### `--ftrack-user`
-- user name to log in to ftrack
-
-### `--ftrack-api-key`
-- ftrack api key
-
-### `--ftrack-events-path`
-- path to event server plugins
-
-### `--no-stored-credentials`
-- will use credential specified with options above
-
-### `--store-credentials`
-- will store credentials to file for later use
-
---------------------
-
-## `launch`
-
-Launch application in Pype environment.
-
-### `--app`
-
-Application name - this should be the same as it's [defining toml](admin_hosts#launchers) file (without .toml)
-
-### `--project`
-Project name
-
-### `--asset`
-Asset name
-
-### `--task`
-Task name
-
-### `--tools`
-*Optional: Additional tools environment files to add*
-
-### `--user`
-*Optional: User on behalf to run*
-
-### `--ftrack-server` / `-fs`
-*Optional: Ftrack server URL*
-
-### `--ftrack-user` / `-fu`
-*Optional: Ftrack user*
-
-### `--ftrack-key` / `-fk`
-*Optional: Ftrack API key*
+| Argument | Description |
+| --- | --- |
+| `--app` | Application name - this should be the key for application from Settings. |
+| `--project` | Project name (default taken from `AVALON_PROJECT` if set) |
+| `--asset` | Asset name (default taken from `AVALON_ASSET` if set) |
+| `--task` | Task name (default taken from `AVALON_TASK` is set) |
+| `--tools` | *Optional: Additional tools to add* |
+| `--user` | *Optional: User on behalf to run* |
+| `--ftrack-server` / `-fs` | *Optional: Ftrack server URL* |
+| `--ftrack-user` / `-fu` | *Optional: Ftrack user* |
+| `--ftrack-key` / `-fk` | *Optional: Ftrack API key* |
For example to run Python interactive console in Pype context:
-```sh
+```shell
pype launch --app python --project my_project --asset my_asset --task my_task
```
---------------------
+---
+### `publish` arguments {#publish-arguments}
+| Argument | Description |
+| --- | --- |
+| `--debug` | print more verbose infomation |
-## `publish`
-
-Pype takes JSON from provided path and use it to publish data in it.
-```sh
+```shell
pype publish
```
-### `--debug`
-- print more verbose infomation
-
---------------------
-
-## `extractenvironments`
-
-Extract environment variables for entered context to a json file.
+---
+### `extractenvironments` arguments {#extractenvironments-arguments}
Entered output filepath will be created if does not exists.
-
All context options must be passed otherwise only openpype's global environments will be extracted.
+Context options are `project`, `asset`, `task`, `app`
-Context options are "project", "asset", "task", "app"
+| Argument | Description |
+| --- | --- |
+| `output_json_path` | Absolute path to the exported json file |
+| `--project` | Project name |
+| `--asset` | Asset name |
+| `--task` | Task name |
+| `--app` | Application name |
-### `output_json_path`
-- Absolute path to the exported json file
+```shell
+openpype_console /home/openpype/env.json --project Foo --asset Bar --task modeling --app maya-2019
+```
-### `--project`
-- Project name
+---
+### `run` arguments {#run-arguments}
-### `--asset`
-- Asset name
+| Argument | Description |
+| `--script` | run specified python script |
-### `--task`
-- Task name
+Note that additional arguments are passed to the script.
-### `--app`
-- Application name
\ No newline at end of file
+```shell
+openpype_console run --script /foo/bar/baz.py arg1 arg2
+```
+
+---
+### `projectmanager` arguments {#projectmanager-arguments}
+`projectmanager` has no command-line arguments.
+```shell
+openpype_console projectmanager
+```
+
+---
+### `settings` arguments {#settings-arguments}
+
+| Argument | Description |
+| `-d` / `--dev` | Run settings in developer mode. |
+
+```shell
+openpypeconsole settings
+```
+
+---
+### `standalonepublisher` arguments {#standalonepublisher-arguments}
+`standalonepublisher` has no command-line arguments.
+```shell
+openpype_console standalonepublisher
+```
\ No newline at end of file
diff --git a/website/docs/admin_use.md b/website/docs/admin_use.md
index 376e9397a1..4a2b56e6f4 100644
--- a/website/docs/admin_use.md
+++ b/website/docs/admin_use.md
@@ -32,6 +32,60 @@ Once artist enters the Mongo URL address, OpenPype will remember the connection
next launch, so it is a one time process.From that moment OpenPype will do it's best to
always keep up to date with the latest studio updates.
-If the launch was successfull, the artist should see a green OpenPype logo in their
+If the launch was successful, the artist should see a green OpenPype logo in their
tray menu. Keep in mind that on Windows this icon might be hidden by default, in which case,
-the artist can simply drag the icon down to the tray.
\ No newline at end of file
+the artist can simply drag the icon down to the tray.
+
+You can use following command line arguments:
+
+`--use-version` - to specify version you want to run explicitly, like:
+```shell
+openpype_console --use-version=3.0.1
+```
+
+`--use-staging` - to specify you prefer staging version. In that case it will be used
+(if found) instead of production one.
+
+### Details
+When you run OpenPype from executable, few check are made:
+
+#### Check for mongoDB database connection
+MongoDB connection string is in format:
+```shell
+mongodb[+srv]://[username:password@]host1[:port1][,...hostN[:portN]][/[defaultauthdb][?options]
+```
+More on that in [MongoDB documentation](https://docs.mongodb.com/manual/reference/connection-string/).
+
+Example connection strings are `mongodb://local-unprotected-server:2707` or
+`mongodb+srv://user:superpassword:some.mongodb-hosted-on.net:27072`.
+
+When you start OpenPype first time, Igniter UI will show up and ask you for this string. It will then
+save it in secure way to your systems keyring - on Windows it is **Credential Manager**, on MacOS it will use its
+**Keychain**, on Linux it can be **GNOME Keyring** or other software, depending on your distribution.
+
+This can be also set beforehand with environment variable `OPENPYPE_MONGO`. If set it takes precedence
+over the one set in keyring.
+
+#### Check for OpenPype version path
+When connection to MongoDB is made, OpenPype will get various settings from there - one among them is
+directory location where OpenPype versions are stored. If this directory exists OpenPype tries to
+find the latest version there and if succeed it will copy it to user system and use it.
+
+This path can be set is OpenPype settings, but also with environment variable `OPENPYPE_PATH` or with
+`openPypePath` in json file located application directory depending on your system.
+
+- Windows: `%LOCALAPPDATA%\pypeclub\openpype`
+- Linux: `~/.local/share/pypeclub/openpype`
+- Mac: `~/Library/Application Support/pypeclub/openpype`
+
+### Runtime provided environment variables
+OpenPype is providing following environment variables for its subprocesses that can be used
+in various places, like scripting, etc.
+
+- `OPENPYPE_ROOT` - this will point to currently running code.
+- `OPENPYPE_VERSION` - string of current version - like `3.0.0-foo+bar`
+- `OPENPYPE_REPOS_ROOT` - this is path where all components can be find (like Avalon Core and OpenPype)
+- `OPENPYPE_DATABASE_NAME` - database name in MongoDB used by OpenPype
+- `OPENPYPE_EXECUTABLE` - path to executable used to run OpenPype - when run from sources it will point
+to **python** stored in virtual environment. If run from frozen code, it will point to either `openpype_gui` or
+ `openpype_console`.
diff --git a/website/docs/artist_hosts_maya.md b/website/docs/artist_hosts_maya.md
index fc94f20f02..6fbd59ae1e 100644
--- a/website/docs/artist_hosts_maya.md
+++ b/website/docs/artist_hosts_maya.md
@@ -531,7 +531,10 @@ OpenPype supports creating review video for almost any type of data you want to
What we call review video is actually _playblast_ or _capture_ (depending on terminology
you are familiar with) made from pre-defined camera in scene. This is very useful
in cases where you want to add turntable preview of your model for example. But it can
-be used to generate preview for animation, simulations, and so on.
+be used to generate preview for animation, simulations, and so on. You can either
+publish review as separate subset version, or you can attach generated video to subset you
+are publishing - for example attach video of turntable rotation to published model as in
+following example.
### Setting scene for review extraction
@@ -570,10 +573,14 @@ on this set to control review video generation:
* `Step` - number of steps
* `Fps` - framerate
+Next step is to move your model set to review set so it will be connected to each other.
+
This is my scene:

+You see that `modelMain` in under `reviewMain` with `reviewCamera`.
+
_* note that I had to fix UVs and normals on Stanford dragon model as it wouldn't pass
model validators_
@@ -588,6 +595,8 @@ version. All parts of this process - like what burnins, what type of video file,
settings for Maya playblast - can be customized by your TDs. For more information
about customizing review process refer to [admin section](admin_presets_plugins).
+If you don't move `modelMain` into `reviewMain`, review will be generated but it will
+be published as separate entity.
## Working with Yeti in OpenPype
diff --git a/website/docs/artist_tools.md b/website/docs/artist_tools.md
index 5bc3f4c1fd..f099b48a9a 100644
--- a/website/docs/artist_tools.md
+++ b/website/docs/artist_tools.md
@@ -177,6 +177,22 @@ Library loader is extended [loader](#loader) which allows to load published subs
+### Delivery Action ###
+
+Library Loader contains functionality to export any selected asset, subsets and their version to configurable folder.
+Delivery follows structure based on defined template, this template must be configured first by Admin in the Settings.
+
+
+
+* Usage
+- Select all required subsets for export (you can change theirs versions by double clicking on 'Version' value)
+- Right click and select **Deliver Versions** from context menu
+- Select predefined Delivery template (must be configured by Admin system or project wide)
+- Fill value for root folder (folder will be created if it doesn't exist)
+- Filter out type of representation you are not interested in
+- Push **Deliver** button
+- Dialog must be kept open until export is finished
+- In a case of problems with any of the representation, that one will be skipped, description of error will be provided in the dialog
* * *
## Publisher
diff --git a/website/docs/assets/maya-model_review_setup.jpg b/website/docs/assets/maya-model_review_setup.jpg
index 6c43807596..16576894b1 100644
Binary files a/website/docs/assets/maya-model_review_setup.jpg and b/website/docs/assets/maya-model_review_setup.jpg differ
diff --git a/website/docs/assets/tools/tools_delivery_loader.png b/website/docs/assets/tools/tools_delivery_loader.png
new file mode 100644
index 0000000000..511cd24fbb
Binary files /dev/null and b/website/docs/assets/tools/tools_delivery_loader.png differ
diff --git a/website/docs/dev_build.md b/website/docs/dev_build.md
index 14efeaa850..2c4bd1e9af 100644
--- a/website/docs/dev_build.md
+++ b/website/docs/dev_build.md
@@ -7,14 +7,31 @@ sidebar_label: Build
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
+## Introduction
To build Pype you currently need (on all platforms):
- **[Python 3.7](https://www.python.org/downloads/)** as we are following [vfx platform](https://vfxplatform.com).
- **[git](https://git-scm.com/downloads)**
-We use [CX_Freeze](https://cx-freeze.readthedocs.io/en/latest) to freeze the code and all dependencies.
+We use [CX_Freeze](https://cx-freeze.readthedocs.io/en/latest) to freeze the code and all dependencies and
+[Poetry](https://python-poetry.org/) for virtual environment management.
+This is outline of build steps. Most of them are done automatically via scripts:
+- Virtual environment is created using **Poetry** in `.venv`
+- Necessary third-party tools (like [ffmpeg](https://www.ffmpeg.org/), [OpenImageIO](https://github.com/OpenImageIO/oiio)
+ and [usd libraries](https://developer.nvidia.com/usd)) are downloaded to `./vendor/bin`
+- OpenPype code is frozen with **cx_freeze** to `./build`
+- Modules are moved from `lib` to `dependencies` to solve some Python 2 / Python 3 clashes
+- On Mac application bundle and dmg image will be created from built code.
+- On Windows, you can create executable installer with `./tools/build_win_installer.ps1`
+
+### Clone OpenPype repository:
+```powershell
+git clone --recurse-submodules https://github.com/pypeclub/OpenPype.git
+```
+
+## Platform specific steps
+### Windows
More tools might be needed for installing some dependencies (for example for **OpenTimelineIO**) - mostly
development tools like [CMake](https://cmake.org/) and [Visual Studio](https://visualstudio.microsoft.com/cs/downloads/)
-### Clone repository:
-```sh
-git clone --recurse-submodules git@github.com:pypeclub/pype.git
-```
-
-### Run from source
+#### Run from source
For development purposes it is possible to run OpenPype directly from the source. We provide a simple launcher script for this.
To start OpenPype from source you need to
-1) Run `.\tools\create_env.ps1` to create virtual environment in `.\venv`
-2) Run `.\tools\run_tray.ps1` if you have all required dependencies on your machine you should be greeted with OpenPype igniter window and once you give it your Mongo URL, with OpenPype icon in the system tray.
+1. Run `.\tools\create_env.ps1` to create virtual environment in `.venv`
+2. Run `.\tools\fetch_thirdparty_libs.ps1` to get **ffmpeg**, **oiio** and other tools needed.
+3. Run `.\tools\run_tray.ps1` if you have all required dependencies on your machine you should be greeted with OpenPype igniter window and once you give it your Mongo URL, with OpenPype icon in the system tray.
+
+Step 1 and 2 needs to be run only once (or when something was changed).
+
+#### To build OpenPype:
+1. Run `.\tools\create_env.ps1` to create virtual environment in `.venv`
+2. Run `.\tools\fetch_thirdparty_libs.ps1` to get **ffmpeg**, **oiio** and other tools needed.
+3. `.\tools\build.ps1` to build OpenPype to `.\build`
-### To build OpenPype:
-
-1) Run `.\tools\create_env.ps1` to create virtual environment in `.\venv`
-2) Run `.\tools\build.ps1` to build pype executables in `.\build\`
-
-To create distributable OpenPype versions, run `./tools/create_zip.ps1` - that will
+To create distributable OpenPype versions, run `.\tools\create_zip.ps1` - that will
create zip file with name `pype-vx.x.x.zip` parsed from current pype repository and
-copy it to user data dir. You can specify `--path /path/to/zip` to force it into a different
+copy it to user data dir. You can specify `--path \path\to\zip` to force it into a different
location. This can be used to prepare new version releases for artists in the studio environment
without the need to re-build the whole package
@@ -61,27 +77,33 @@ without the need to re-build the whole package
+### Linux
+
#### Docker
You can use Docker to build OpenPype. Just run:
-```sh
-sudo ./tools/docker_build.sh
+```shell
+$ sudo ./tools/docker_build.sh
```
and you should have built OpenPype in `build` directory. It is using **Centos 7**
as a base image.
You can pull the image:
-```sh
+```shell
# replace 3.0.0 tag with version you want
-docker pull pypeclub/openpype:3.0.0
+$ docker pull pypeclub/openpype:3.0.0
```
See https://hub.docker.com/r/pypeclub/openpype/tag for more.
+Beware that as Python is built against some libraries version in Centos 7 base image,
+those might not be available in linux version you are using. We try to handle those we
+found (libffi, libcrypto/ssl, etc.) but there might be more.
+
#### Manual build
-To build OpenPype on Linux you wil need:
+
+To build OpenPype on Linux you will need:
- **[curl](https://curl.se)** on systems that doesn't have one preinstalled.
-- Python header files installed (**python3-dev** on Ubuntu for example).
- **bzip2**, **readline**, **sqlite3** and other libraries.
Because some Linux distros come with newer Python version pre-installed, you might
@@ -90,117 +112,283 @@ Your best bet is probably using [pyenv](https://github.com/pyenv/pyenv).
You can use your package manager to install **git** and other packages to your build
environment.
-Use curl for pyenv installation
+#### Common steps for all Distros
+
+Use pyenv to prepare Python version for Pype build
+
+```shell
+$ curl https://pyenv.run | bash
+
+# you can add those to ~/.bashrc
+$ export PATH="$HOME/.pyenv/bin:$PATH"
+$ eval "$(pyenv init -)"
+$ eval "$(pyenv virtualenv-init -)"
+
+# reload shell
+$ exec $SHELL
+
+# install Python 3.7.10
+# python will be downloaded and build so please make sure
+# you have all necessary requirements installed (see bellow).
+$ pyenv install -v 3.7.10
+
+# change path to pype 3
+$ cd /path/to/pype-3
+
+# set local python version
+$ pyenv local 3.7.9
+```
:::note Install build requirements for **Ubuntu**
-```sh
+```shell
sudo apt-get update; sudo apt-get install --no-install-recommends make build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev git
```
In case you run in error about `xcb` when running Pype,
you'll need also additional libraries for Qt5:
-```sh
+```shell
sudo apt install qt5-default
```
:::
-:::note Install build requirements for **Centos**
+:::note Install build requirements for **Centos 7**
-```sh
-yum install gcc zlib-devel bzip2 bzip2-devel readline-devel sqlite sqlite-devel openssl-devel tk-devel libffi-devel git
+```shell
+$ sudo yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
+$ sudo yum install centos-release-scl
+$ sudo yum install bash which git devtoolset-7-gcc* \
+ make cmake curl wget gcc zlib-devel bzip2 \
+ bzip2-devel readline-devel sqlite sqlite-devel \
+ openssl-devel tk-devel libffi-devel qt5-qtbase-devel \
+ patchelf
```
-
-In case you run in error about `xcb` when running Pype,
-you'll need also additional libraries for Qt5:
-
-```sh
-sudo yum install qt5-qtbase-devel
-```
-
:::
-For more information about setting your build environmet please refer to [pyenv suggested build environment](https://github.com/pyenv/pyenv/wiki#suggested-build-environment)
+:::note Install build requirements for other distros
-#### Common steps for all Distros
+Build process usually needs some reasonably recent versions of libraries and tools. You
+can follow what's needed for Ubuntu and change it for your package manager. Centos 7 steps
+have additional magic to overcame very old versions.
+:::
-Use pyenv to prepare Python version for Pype build
+For more information about setting your build environment please refer to [pyenv suggested build environment](https://github.com/pyenv/pyenv/wiki#suggested-build-environment).
-```sh
-curl https://pyenv.run | bash
-
-# you can add those to ~/.bashrc
-export PATH="$HOME/.pyenv/bin:$PATH"
-eval "$(pyenv init -)"
-eval "$(pyenv virtualenv-init -)"
-
-# reload shell
-exec $SHELL
-
-# install Python 3.7.9
-pyenv install -v 3.7.9
-
-# change path to pype 3
-cd /path/to/pype-3
-
-# set local python version
-pyenv local 3.7.9
-
-```
#### To build Pype:
-
-1. Run `.\tools\create_env.sh` to create virtual environment in `.\venv`
-2. Run `.\tools\build.sh` to build pype executables in `.\build\`
+1. Run `./tools/create_env.sh` to create virtual environment in `./venv`
+2. Run `./tools/fetch_thirdparty_libs.sh` to get **ffmpeg**, **oiio** and other tools needed.
+3. Run `./tools/build.sh` to build pype executables in `.\build\`
+### MacOS
To build pype on MacOS you wil need:
-- **[Homebrew](https://brew.sh)**, Easy way of installing everything necessary is to use.
+- **[Homebrew](https://brew.sh)** - easy way of installing everything necessary.
- **[CMake](https://cmake.org/)** to build some external OpenPype dependencies.
- **XCode Command Line Tools** (or some other build system)
+- **[create-dmg](https://formulae.brew.sh/formula/create-dmg)** to create dmg image from application
+bundle.
1) Install **Homebrew**:
-```sh
-/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
+```shell
+$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
```
2) Install **cmake**:
-```sh
-brew install cmake
+```shell
+$ brew install cmake
```
3) Install [pyenv](https://github.com/pyenv/pyenv):
-```sh
-brew install pyenv
-echo 'eval "$(pypenv init -)"' >> ~/.zshrc
-pyenv init
-exec "$SHELL"
-PATH=$(pyenv root)/shims:$PATH
+```shell
+$ brew install pyenv
+$ echo 'eval "$(pypenv init -)"' >> ~/.zshrc
+$ pyenv init
+$ exec "$SHELL"
+$ PATH=$(pyenv root)/shims:$PATH
```
4) Pull in required Python version 3.7.x
-```sh
+```shell
# install Python build dependences
-brew install openssl readline sqlite3 xz zlib
+$ brew install openssl readline sqlite3 xz zlib
# replace with up-to-date 3.7.x version
-pyenv install 3.7.9
+$ pyenv install 3.7.9
```
5) Set local Python version
-```sh
+```shell
# switch to Pype source directory
-pyenv local 3.7.9
+$ pyenv local 3.7.9
+```
+
+6) Install `create-dmg`
+```shell
+$ brew install create-dmg
```
#### To build Pype:
-1. Run `.\tools\create_env.sh` to create virtual environment in `.\venv`
-2. Run `.\tools\build.sh` to build Pype executables in `.\build\`
+1. Run `./tools/create_env.sh` to create virtual environment in `./venv`.
+2. Run `./tools/fetch_thirdparty_libs.sh` to get **ffmpeg**, **oiio** and other tools needed.
+3. Run `./tools/build.sh` to build OpenPype Application bundle in `./build/`.
+
+## Adding dependencies
+### Python modules
+If you are extending OpenPype and you need some new modules not included, you can add them
+to `pyproject.toml` to `[tool.poetry.dependencies]` section.
+
+```toml title="/pyproject.toml"
+[tool.poetry.dependencies]
+python = "3.7.*"
+aiohttp = "^3.7"
+aiohttp_json_rpc = "*" # TVPaint server
+acre = { git = "https://github.com/pypeclub/acre.git" }
+opentimelineio = { version = "0.14.0.dev1", source = "openpype" }
+#...
+```
+It is useful to add comment to it so others can see why this was added and where it is used.
+As you can see you can add git repositories or custom wheels (those must be
+added to `[[tool.poetry.source]]` section).
+
+To add something only for specific platform, you can use markers like:
+```toml title="Install pywin32 only on Windows"
+pywin32 = { version = "300", markers = "sys_platform == 'win32'" }
+```
+
+For more information see [Poetry documentation](https://python-poetry.org/docs/dependency-specification/).
+
+### Binary dependencies
+To add some binary tool or something that doesn't fit standard Python distribution methods, you
+can use [fetch_thirdparty_libs](#fetch_thirdparty_libs) script. It will take things defined in
+`pyproject.toml` under `[openpype]` section like this:
+
+```toml title="/pyproject.toml"
+[openpype]
+
+[openpype.thirdparty.ffmpeg.windows]
+url = "https://distribute.openpype.io/thirdparty/ffmpeg-4.4-windows.zip"
+hash = "dd51ba29d64ee238e7c4c3c7301b19754c3f0ee2e2a729c20a0e2789e72db925"
+# ...
+```
+This defines FFMpeg for Windows. It will be downloaded from specified url, its checksum will
+be validated (it's sha256) and it will be extracted to `/vendor/bin/ffmpeg/windows` (partly taken
+from its section name).
+
+## Script tools
+(replace extension with the one for your system - `ps1` for windows, `sh` for linux/macos)
+
+### build
+This will build OpenPype to `build` directory. If virtual environment is not created yet, it will
+install [Poetry](https://python-poetry.org/) and using it download and install necessary
+packages needed for build. It is recommended that you run [fetch_thirdparty_libs](#fetch_thirdparty_libs)
+to download FFMpeg, OpenImageIO and others that are needed by OpenPype and are copied during the build.
+
+#### Arguments
+`--no-submodule-update` - to disable updating submodules. This allows to make custom-builds for testing
+feature changes in submodules.
+
+### build_win_installer
+This will take already existing build in `build` directory and create executable installer using
+[Inno Setup](https://jrsoftware.org/isinfo.php) and definitions in `./inno_setup.iss`. You need OpenPype
+build using [build script](#build), Inno Setup installed and in PATH before running this script.
+
+:::note
+Windows only
+:::
+
+### create_env
+Script to create virtual environment for build and running OpenPype from sources. It is using
+[Poetry](https://python-poetry.org/). All dependencies are defined in `pyproject.toml`, resolved by
+Poetry into `poetry.lock` file and then installed. Running this script without Poetry will download
+it, install it to `.poetry` and then install virtual environment from `poetry.lock` file. If you want
+to update packages version, just run `poetry update` or delete lock file.
+
+#### Arguments
+`--verbose` - to increase verbosity of Poetry. This can be useful for debugging package conflicts.
+
+### create_zip
+Script to create packaged OpenPype version from current sources. This will strip developer stuff and
+package it into zip that can be used for [auto-updates for studio wide distributions](admin_distribute#automatic-updates), etc.
+Same as:
+```shell
+poetry run python ./tools/create_zip.py
+```
+
+### docker_build.sh
+Script to build OpenPype on [Docker](https://www.docker.com/) enabled systems - usually Linux and Windows
+with [Docker Desktop](https://docs.docker.com/docker-for-windows/install/)
+and [Windows Subsystem for Linux](https://docs.microsoft.com/en-us/windows/wsl/about) (WSL) installed.
+
+It must be run with administrative privileges - `sudo ./docker_build.sh`.
+
+It will use **Centos 7** base image to build OpenPype. You'll see your build in `./build` folder.
+
+### fetch_thirdparty_libs
+This script will download necessary tools for OpenPype defined in `pyproject.toml` like FFMpeg,
+OpenImageIO and USD libraries and put them to `./vendor/bin`. Those are then included in build.
+Running it will overwrite everything on their respective paths.
+Same as:
+```shell
+poetry run python ./tools/fetch_thirdparty_libs.py
+```
+
+### make_docs
+Script will run [sphinx](https://www.sphinx-doc.org/) to build api documentation in html. You
+should see it then under `./docs/build/html`.
+
+### run_documentation
+This will start up [Docusaurus](https://docusaurus.io/) to display OpenPype user documentation.
+Useful for offline browsing or editing documentation itself. You will need [Node.js](https://nodejs.org/)
+and [Yarn](https://yarnpkg.com/) to run this script. After executing it, you'll see new
+browser window with current OpenPype documentation.
+Same as:
+```shell
+cd ./website
+yarn start
+```
+
+### run_mongo
+Helper script to run local mongoDB server for development and testing. You will need
+[mongoDB server](https://www.mongodb.com/try/download/community) installed in standard location
+or in PATH (standard location works only on Windows). It will start by default on port `2707` and
+it will put its db files to `../mongo_db_data` relative to OpenPype sources.
+
+### run_project_manager
+Helper script to start OpenPype Project Manager tool.
+Same as:
+```shell
+poetry run python start.py projectmanager
+```
+
+### run_settings
+Helper script to open OpenPype Settings UI.
+Same as:
+```shell
+poetry run python start.py settings --dev
+```
+
+### run_tests
+Runs OpenPype test suite.
+
+### run_tray
+Helper script to run OpenPype Tray.
+Same as:
+```shell
+poetry run python start.py tray
+```
+
+### update_submodules
+Helper script to update OpenPype git submodules.
+Same as:
+```shell
+git submodule update --recursive --remote
+```
diff --git a/website/docs/project_settings/assets/global_extract_review_letter_box.png b/website/docs/project_settings/assets/global_extract_review_letter_box.png
index 7cd9ecbdd6..45c1942f24 100644
Binary files a/website/docs/project_settings/assets/global_extract_review_letter_box.png and b/website/docs/project_settings/assets/global_extract_review_letter_box.png differ
diff --git a/website/docs/project_settings/assets/global_extract_review_letter_box_settings.png b/website/docs/project_settings/assets/global_extract_review_letter_box_settings.png
index 9ad9c05f43..80e00702e6 100644
Binary files a/website/docs/project_settings/assets/global_extract_review_letter_box_settings.png and b/website/docs/project_settings/assets/global_extract_review_letter_box_settings.png differ
diff --git a/website/docs/project_settings/assets/global_extract_review_output_defs.png b/website/docs/project_settings/assets/global_extract_review_output_defs.png
index 0dc8329324..ce3c00ca40 100644
Binary files a/website/docs/project_settings/assets/global_extract_review_output_defs.png and b/website/docs/project_settings/assets/global_extract_review_output_defs.png differ
diff --git a/website/docs/project_settings/assets/global_tools_workfile_open_last_version.png b/website/docs/project_settings/assets/global_tools_workfile_open_last_version.png
new file mode 100644
index 0000000000..dfcac072c5
Binary files /dev/null and b/website/docs/project_settings/assets/global_tools_workfile_open_last_version.png differ
diff --git a/website/docs/project_settings/assets/nuke_workfile_builder_create_first_workfile.png b/website/docs/project_settings/assets/nuke_workfile_builder_create_first_workfile.png
new file mode 100644
index 0000000000..f138709a7f
Binary files /dev/null and b/website/docs/project_settings/assets/nuke_workfile_builder_create_first_workfile.png differ
diff --git a/website/docs/project_settings/assets/nuke_workfile_builder_location.png b/website/docs/project_settings/assets/nuke_workfile_builder_location.png
new file mode 100644
index 0000000000..916b79755d
Binary files /dev/null and b/website/docs/project_settings/assets/nuke_workfile_builder_location.png differ
diff --git a/website/docs/project_settings/assets/nuke_workfile_builder_profiles.png b/website/docs/project_settings/assets/nuke_workfile_builder_profiles.png
new file mode 100644
index 0000000000..e4105767ef
Binary files /dev/null and b/website/docs/project_settings/assets/nuke_workfile_builder_profiles.png differ
diff --git a/website/docs/project_settings/assets/nuke_workfile_builder_template_anatomy.png b/website/docs/project_settings/assets/nuke_workfile_builder_template_anatomy.png
new file mode 100644
index 0000000000..195e884bfb
Binary files /dev/null and b/website/docs/project_settings/assets/nuke_workfile_builder_template_anatomy.png differ
diff --git a/website/docs/project_settings/assets/nuke_workfile_builder_template_task_type.png b/website/docs/project_settings/assets/nuke_workfile_builder_template_task_type.png
new file mode 100644
index 0000000000..4c84f37c0e
Binary files /dev/null and b/website/docs/project_settings/assets/nuke_workfile_builder_template_task_type.png differ
diff --git a/website/docs/project_settings/settings_project_global.md b/website/docs/project_settings/settings_project_global.md
index 4fee57d575..5d23dd75e6 100644
--- a/website/docs/project_settings/settings_project_global.md
+++ b/website/docs/project_settings/settings_project_global.md
@@ -17,10 +17,10 @@ Projects always use default project values unless they have [project override](.
Many of the settings are using a concept of **Profile filters**
-You can define multiple profiles to choose from for different contexts. Each filter is evaluated and a
-profile with filters matching the current context the most, is used.
+You can define multiple profiles to choose from for different contexts. Each filter is evaluated and a
+profile with filters matching the current context the most, is used.
-You can define profile without any filters and use it as **default**.
+You can define profile without any filters and use it as **default**.
Only **one or none** profile will be returned per context.
@@ -69,6 +69,49 @@ Profile may generate multiple outputs from a single input. Each output must defi
- it is possible to rescale output to specified resolution and keep aspect ratio.
- If value is set to 0, source resolution will be used.
+- **`Overscan crop`**
+ - Crop input resolution before rescaling.
+
+ - Value is text may have a few variants. Each variant define output size for input size.
+
+ - All values that cause output resolution smaller than 1 pixel are invalid.
+
+ - Value without sign (+/-) in is always explicit and value with sign is
+ relative. Output size for values "200px" and "+200px" are not the same "+200px" will add 200 pixels to source and "200px" will keep only 200px from source. Value of "0", "0px" or "0%" are automatically converted to "+0px" as 0px is invalid ouput.
+
+ - Cropped value is related to center. It is better to avoid odd numbers if
+ possible.
+
+ **Example outputs for input size: 2200px**
+
+ | String | Output | Description |
+ |---|---|---|
+ | ` ` | 2200px | Empty string keep resolution unchanged. |
+ | `50%` | 1100px | Crop 25% of input width on left and right side. |
+ | `300px` | 300px | Keep 300px in center of input and crop rest on left adn right. |
+ | `300` | 300px | Values without units are used as pixels (`px`). |
+ | `+0px` | 2200px | Keep resolution unchanged. |
+ | `0px` | 2200px | Same as `+0px`. |
+ | `+300px` | 2500px | Add black pillars of 150px width on left and right side. |
+ | `-300px` | 1900px | Crop 150px on left and right side |
+ | `+10%` | 2420px | Add black pillars of 5% size of input on left and right side. |
+ | `-10%` | 1980px | Crop 5% of input size by on left and right side. |
+ | `-10%+` | 2000px | Input width is 110% of output width. |
+
+ **Value "-10%+" is a special case which says that input's resolution is
+ bigger by 10% than expected output.**
+
+ - It is possible to enter single value for both width and height or
+ combination of two variants for width and height separated with space.
+
+ **Example for resolution: 2000px 1000px**
+
+ | String | Output |
+ |---------------|---------------|
+ | "100px 120px" | 2100px 1120px |
+ | "-10% -200px" | 1800px 800px |
+ | "-10% -0px" | 1800px 1000px |
+
- **`Letter Box`**
- **Enabled** - Enable letter boxes
- **Ratio** - Ratio of letter boxes
@@ -86,7 +129,7 @@ Profile may generate multiple outputs from a single input. Each output must defi
Saves information for all published subsets into DB, published assets are available for other hosts, tools and tasks after.
#### Template name profiles
-Allows to select [anatomy template](admin_settings_project_anatomy.md#templates) based on context of subset being published.
+Allows to select [anatomy template](admin_settings_project_anatomy.md#templates) based on context of subset being published.
For example for `render` profile you might want to publish and store assets in different location (based on anatomy setting) then for `publish` profile.
[Profile filtering](#profile-filters) is used to select between appropriate template for each context of published subsets.
@@ -96,7 +139,7 @@ Applicable context filters:
- **`tasks`** - Current task. `["modeling", "animation"]`

-
+
(This image shows use case where `render` anatomy template is used for subsets of families ['review, 'render', 'prerender'], `publish` template is chosen for all other.)
#### Subset grouping profiles
@@ -111,5 +154,16 @@ Applicable context filters:
- **`tasks`** - Current task. `["modeling", "animation"]`

-
-(This image shows use case where only assets published from 'photoshop', for all families for all tasks should be marked as grouped with a capitalized name of Task where they are published from.)
\ No newline at end of file
+
+(This image shows use case where only assets published from 'photoshop', for all families for all tasks should be marked as grouped with a capitalized name of Task where they are published from.)
+
+## Tools
+Settings for OpenPype tools.
+
+## Workfiles
+All settings related to Workfile tool.
+
+### Open last workfile at launch
+This feature allows you to define a rule for each task/host or toggle the feature globally to all tasks as they are visible in the picture.
+
+
\ No newline at end of file
diff --git a/website/docs/project_settings/settings_project_nuke.md b/website/docs/project_settings/settings_project_nuke.md
new file mode 100644
index 0000000000..561311317f
--- /dev/null
+++ b/website/docs/project_settings/settings_project_nuke.md
@@ -0,0 +1,63 @@
+---
+id: settings_project_nuke
+title: Project Nuke Setting
+sidebar_label: Nuke
+---
+
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+Project settings can have project specific values. Each new project is using studio values defined in **default** project but these values can be modified or overriden per project.
+
+:::warning Default studio values
+Projects always use default project values unless they have [project override](../admin_settings#project-overrides) (orage colour). Any changes in default project may affect all existing projects.
+:::
+
+## Workfile Builder
+
+All Workfile Builder related settings can be found here. This is a list of available features:
+- Create first workfile
+- Custom Template path (task type filtered)
+- Run Builder profiles at first run
+- Define Builder Profiles With Filters
+
+
+
+:::important Auto Load Last Version
+In case you want to set the auto load of the latest available version of workfiles, you can do it from [here](settings_project_global#open-last-workfile-at-launch).
+:::
+
+### Create first workfile
+
+By switchintg this feature on, OpenPype will generate initial workfile version. Following attributes are possible to configure:
+
+
+
+#### Custom templates
+Custom templates are added into nuke's node graph as nodes. List of task types can be defined for templates filtering.
+
+- Task types are sourced from project related Anatomy/Task Types
+
+
+
+ - multi platform path can be used in a variety of ways. Along the absolut path to a template file also an python formating could be used. At the moment these keys are supported (image example bellow):
+ - `root[key]`: definitions from anatomy roots
+ - `project[name, code]`: project in context
+ - `asset`: name of asset/shot in context
+ - `task[type, name, short_name]`: as they are defined on asset/shot and in **Anatomy/Task Type** on project context
+
+
+
+#### Run Builder profiles on first launch
+Enabling this feature will look into available Builder's Prorfiles (look bellow for more informations about this feature) and load available versions into node graph.
+
+### Profiles (Builder)
+Builder profiles are set of rules allowing artist Load any available versions for the context of the asset, which it is run from. Preset is having following attributes:
+
+- **Filter**: Each profile could be defined with task filter. In case no filter is defined, a profile will be working for all.
+
+- **Context section**: filtres for subset name (regex accepted), families, representation names and available Loader plugin.
+
+- **Linked Assets/Shots**: filters for asset builds to be added
+
+
diff --git a/website/package.json b/website/package.json
index 7bd8b4e77b..604eb69591 100644
--- a/website/package.json
+++ b/website/package.json
@@ -1,5 +1,6 @@
{
"name": "pype-documentation",
+ "license": "MIT",
"scripts": {
"examples": "docusaurus-examples",
"start": "docusaurus start",
@@ -13,8 +14,8 @@
"docusaurus": "docusaurus"
},
"dependencies": {
- "@docusaurus/core": "2.0.0-alpha.72",
- "@docusaurus/preset-classic": "2.0.0-alpha.72",
+ "@docusaurus/core": "2.0.0-beta.0",
+ "@docusaurus/preset-classic": "2.0.0-beta.0",
"classnames": "^2.2.6",
"clsx": "^1.1.1",
"react": "^16.10.2",
diff --git a/website/sidebars.js b/website/sidebars.js
index 7a5379c36b..0b831bccb3 100644
--- a/website/sidebars.js
+++ b/website/sidebars.js
@@ -64,7 +64,8 @@ module.exports = {
type: "category",
label: "Project Settings",
items: [
- "project_settings/settings_project_global"
+ "project_settings/settings_project_global",
+ "project_settings/settings_project_nuke"
],
},
],
diff --git a/website/src/pages/index.js b/website/src/pages/index.js
index 81b8d77bd3..8eb6e84c24 100644
--- a/website/src/pages/index.js
+++ b/website/src/pages/index.js
@@ -50,7 +50,7 @@ const collab = [
infoLink: 'http://kredenc.studio'
}, {
title: 'Colorbleed',
- image: '/img/colorbleed_logo.png',
+ image: '/img/colorbleed_logo_black.png',
infoLink: 'http://colorbleed.nl'
}, {
title: 'Bumpybox',
@@ -67,7 +67,7 @@ const collab = [
}
];
-const clients = [
+const studios = [
{
title: 'Imagine Studio',
image: '/img/imagine_logo.png',
@@ -82,11 +82,11 @@ const clients = [
infoLink: 'https://www.3de.com.pl/'
}, {
title: 'Incognito',
- image: '/img/client_incognito.png',
+ image: '/img/incognito.png',
infoLink: 'https://incognito.studio/'
}, {
title: 'Fourth Wall Animation',
- image: '/img/client_fourthwall_logo.png',
+ image: '/img/fourthwall_logo.png',
infoLink: 'https://fourthwallanimation.com/'
}, {
title: 'The Scope Studio',
@@ -99,22 +99,27 @@ const clients = [
}, {
title: 'Filmmore',
image: '/img/filmmore_logotype_bw.png',
- infoLink: 'https://filmmore.nl/'
+ infoLink: 'https://filmmore.eu/'
},
{
title: 'Yowza Animation',
- image: '/img/client_yowza_logo.png',
+ image: '/img/yowza_logo.png',
infoLink: 'https://yowzaanimation.com/'
},
{
title: "Red Knuckles",
- image: "/img/redknuckles_logotype.png",
+ image: "/img/redknuckles_logo.png",
infoLink: "https://www.redknuckles.co.uk/",
},
{
title: "Orca Studios",
image: "/img/orcastudios_logo.png",
infoLink: "https://orcastudios.es/",
+ },
+ {
+ title: "Bad Clay",
+ image: "/img/badClay_logo.png",
+ infoLink: "https://www.bad-clay.com/",
}
];
@@ -343,7 +348,7 @@ function Home() {
- DaVinci Resolve (Alpha)
+ DaVinci Resolve (Beta)
@@ -387,12 +392,12 @@ function Home() {
)}
- {clients && clients.length && (
+ {studios && studios.length && (
Studios using openPYPE
- {clients.map((props, idx) => (
+ {studios.map((props, idx) => (
))}
diff --git a/website/static/img/3bohemians-logo.png b/website/static/img/3bohemians-logo.png
deleted file mode 100644
index 8910e7a4e3..0000000000
Binary files a/website/static/img/3bohemians-logo.png and /dev/null differ
diff --git a/website/static/img/3bohemians-logo.svg b/website/static/img/3bohemians-logo.svg
deleted file mode 100644
index e15a2668e7..0000000000
--- a/website/static/img/3bohemians-logo.svg
+++ /dev/null
@@ -1,37 +0,0 @@
-
-
-
diff --git a/website/static/img/BionautAnimation.png b/website/static/img/BionautAnimation.png
deleted file mode 100644
index 1200444d9e..0000000000
Binary files a/website/static/img/BionautAnimation.png and /dev/null differ
diff --git a/website/static/img/badClay_logo.png b/website/static/img/badClay_logo.png
new file mode 100644
index 0000000000..d3385a6e33
Binary files /dev/null and b/website/static/img/badClay_logo.png differ
diff --git a/website/static/img/bionaut_logo.png b/website/static/img/bionaut_logo.png
deleted file mode 100644
index 1603a10468..0000000000
Binary files a/website/static/img/bionaut_logo.png and /dev/null differ
diff --git a/website/static/img/bumpybox.png b/website/static/img/bumpybox.png
deleted file mode 100644
index e07c605a59..0000000000
Binary files a/website/static/img/bumpybox.png and /dev/null differ
diff --git a/website/static/img/client_krutart_logo.png b/website/static/img/client_krutart_logo.png
deleted file mode 100644
index 77b0b580d5..0000000000
Binary files a/website/static/img/client_krutart_logo.png and /dev/null differ
diff --git a/website/static/img/colorbleed_logo.png b/website/static/img/colorbleed_logo.png
deleted file mode 100644
index bab83b7e8f..0000000000
Binary files a/website/static/img/colorbleed_logo.png and /dev/null differ
diff --git a/website/static/img/cubicmotion.png b/website/static/img/cubicmotion.png
deleted file mode 100644
index 0c496867ac..0000000000
Binary files a/website/static/img/cubicmotion.png and /dev/null differ
diff --git a/website/static/img/filmmore.png b/website/static/img/filmmore.png
deleted file mode 100644
index 4d05c6782b..0000000000
Binary files a/website/static/img/filmmore.png and /dev/null differ
diff --git a/website/static/img/client_fourthwall_logo.png b/website/static/img/fourthwall_logo.png
similarity index 100%
rename from website/static/img/client_fourthwall_logo.png
rename to website/static/img/fourthwall_logo.png
diff --git a/website/static/img/client_incognito.png b/website/static/img/incognito.png
similarity index 100%
rename from website/static/img/client_incognito.png
rename to website/static/img/incognito.png
diff --git a/website/static/img/redknuckles_logo.png b/website/static/img/redknuckles_logo.png
new file mode 100644
index 0000000000..9f852128f5
Binary files /dev/null and b/website/static/img/redknuckles_logo.png differ
diff --git a/website/static/img/redknuckles_logotype.png b/website/static/img/redknuckles_logotype.png
deleted file mode 100644
index 13c49c8504..0000000000
Binary files a/website/static/img/redknuckles_logotype.png and /dev/null differ
diff --git a/website/static/img/client_yowza_logo.png b/website/static/img/yowza_logo.png
similarity index 100%
rename from website/static/img/client_yowza_logo.png
rename to website/static/img/yowza_logo.png
diff --git a/website/yarn.lock b/website/yarn.lock
index d29fe48fce..e23e29c0e5 100644
--- a/website/yarn.lock
+++ b/website/yarn.lock
@@ -472,7 +472,7 @@
"@babel/helper-plugin-utils" "^7.13.0"
"@babel/plugin-syntax-logical-assignment-operators" "^7.10.4"
-"@babel/plugin-proposal-nullish-coalescing-operator@^7.12.13", "@babel/plugin-proposal-nullish-coalescing-operator@^7.13.8":
+"@babel/plugin-proposal-nullish-coalescing-operator@^7.13.8":
version "7.13.8"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.13.8.tgz#3730a31dafd3c10d8ccd10648ed80a2ac5472ef3"
integrity sha512-iePlDPBn//UhxExyS9KyeYU7RM9WScAG+D3Hhno0PLJebAEpDZMocbDe64eqynhNAnwz/vZoL/q/QB2T1OH39A==
@@ -516,7 +516,7 @@
"@babel/helper-plugin-utils" "^7.13.0"
"@babel/plugin-syntax-optional-catch-binding" "^7.8.3"
-"@babel/plugin-proposal-optional-chaining@^7.12.16", "@babel/plugin-proposal-optional-chaining@^7.13.12":
+"@babel/plugin-proposal-optional-chaining@^7.13.12":
version "7.13.12"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.13.12.tgz#ba9feb601d422e0adea6760c2bd6bbb7bfec4866"
integrity sha512-fcEdKOkIB7Tf4IxrgEVeFC4zeJSTr78no9wTdBuZZbqF64kzllU0ybo2zrzm7gUQfxGhBgq4E39oRs8Zx/RMYQ==
@@ -1109,18 +1109,6 @@
lodash "^4.17.19"
to-fast-properties "^2.0.0"
-"@choojs/findup@^0.2.1":
- version "0.2.1"
- resolved "https://registry.yarnpkg.com/@choojs/findup/-/findup-0.2.1.tgz#ac13c59ae7be6e1da64de0779a0a7f03d75615a3"
- integrity sha512-YstAqNb0MCN8PjdLCDfRsBcGVRN41f3vgLvaI0IrIcBp4AqILRSS0DeWNGkicC+f/zRIPJLc+9RURVSepwvfBw==
- dependencies:
- commander "^2.15.1"
-
-"@csstools/convert-colors@^1.4.0":
- version "1.4.0"
- resolved "https://registry.yarnpkg.com/@csstools/convert-colors/-/convert-colors-1.4.0.tgz#ad495dc41b12e75d588c6db8b9834f08fa131eb7"
- integrity sha512-5a6wqoJV/xEdbRNKVo6I4hO3VjyDq//8q2f9I6PBAvMesJHFauXDorcNCsr9RzvsZnaWi5NYCcfyqP1QeFHFbw==
-
"@docsearch/css@3.0.0-alpha.34":
version "3.0.0-alpha.34"
resolved "https://registry.yarnpkg.com/@docsearch/css/-/css-3.0.0-alpha.34.tgz#5d5c39955956e237884a9997eb29e28c8adc99fa"
@@ -1136,15 +1124,13 @@
"@docsearch/css" "3.0.0-alpha.34"
algoliasearch "^4.0.0"
-"@docusaurus/core@2.0.0-alpha.72":
- version "2.0.0-alpha.72"
- resolved "https://registry.yarnpkg.com/@docusaurus/core/-/core-2.0.0-alpha.72.tgz#f1acff2d84b3cbca9c35906186c49ba16d019ce3"
- integrity sha512-PV0rlvVRvVEdqs1I4PktwZBJkhFg4O4bVeqseaTYuA1u/poQSiiZ+rhrZRJ+/OcTHZ8VlYZw7tCHaRH4RLbP2g==
+"@docusaurus/core@2.0.0-beta.0":
+ version "2.0.0-beta.0"
+ resolved "https://registry.yarnpkg.com/@docusaurus/core/-/core-2.0.0-beta.0.tgz#05506ee02e7d40e9f4c8d7b4f918d26d3b191159"
+ integrity sha512-xWwpuEwFRKJmZvNGOpr/dyRDnx/psckLPsozQTg2hu3u81Wqu9gigWgYK/C2fPlEjxMcVw0/2WH+zwpbyWmF2Q==
dependencies:
"@babel/core" "^7.12.16"
"@babel/generator" "^7.12.15"
- "@babel/plugin-proposal-nullish-coalescing-operator" "^7.12.13"
- "@babel/plugin-proposal-optional-chaining" "^7.12.16"
"@babel/plugin-syntax-dynamic-import" "^7.8.3"
"@babel/plugin-transform-runtime" "^7.12.15"
"@babel/preset-env" "^7.12.16"
@@ -1153,25 +1139,26 @@
"@babel/runtime" "^7.12.5"
"@babel/runtime-corejs3" "^7.12.13"
"@babel/traverse" "^7.12.13"
- "@docusaurus/cssnano-preset" "2.0.0-alpha.72"
+ "@docusaurus/cssnano-preset" "2.0.0-beta.0"
"@docusaurus/react-loadable" "5.5.0"
- "@docusaurus/types" "2.0.0-alpha.72"
- "@docusaurus/utils" "2.0.0-alpha.72"
- "@docusaurus/utils-validation" "2.0.0-alpha.72"
+ "@docusaurus/types" "2.0.0-beta.0"
+ "@docusaurus/utils" "2.0.0-beta.0"
+ "@docusaurus/utils-validation" "2.0.0-beta.0"
"@endiliey/static-site-generator-webpack-plugin" "^4.0.0"
"@svgr/webpack" "^5.5.0"
autoprefixer "^10.2.5"
babel-loader "^8.2.2"
babel-plugin-dynamic-import-node "2.3.0"
boxen "^5.0.0"
- cache-loader "^4.1.0"
chalk "^4.1.0"
chokidar "^3.5.1"
clean-css "^5.1.1"
commander "^5.1.0"
- copy-webpack-plugin "^6.4.1"
+ copy-webpack-plugin "^8.1.0"
core-js "^3.9.1"
css-loader "^5.1.1"
+ css-minimizer-webpack-plugin "^2.0.0"
+ cssnano "^5.0.1"
del "^6.0.0"
detect-port "^1.3.0"
eta "^1.12.1"
@@ -1182,62 +1169,61 @@
globby "^11.0.2"
html-minifier-terser "^5.1.1"
html-tags "^3.1.0"
- html-webpack-plugin "^4.5.0"
+ html-webpack-plugin "^5.2.0"
import-fresh "^3.3.0"
is-root "^2.1.0"
- joi "^17.4.0"
leven "^3.1.0"
lodash "^4.17.20"
- mini-css-extract-plugin "^0.8.0"
+ mini-css-extract-plugin "^1.4.0"
module-alias "^2.2.2"
nprogress "^0.2.0"
- null-loader "^4.0.0"
- optimize-css-assets-webpack-plugin "^5.0.4"
- pnp-webpack-plugin "^1.6.4"
- postcss "^8.2.7"
- postcss-loader "^4.1.0"
- postcss-preset-env "^6.7.0"
+ postcss "^8.2.10"
+ postcss-loader "^5.2.0"
prompts "^2.4.0"
react-dev-utils "^11.0.1"
+ react-error-overlay "^6.0.9"
react-helmet "^6.1.0"
react-loadable "^5.5.0"
- react-loadable-ssr-addon "^0.3.0"
+ react-loadable-ssr-addon-v5-slorber "^1.0.1"
react-router "^5.2.0"
react-router-config "^5.1.1"
react-router-dom "^5.2.0"
resolve-pathname "^3.0.0"
+ rtl-detect "^1.0.2"
semver "^7.3.4"
serve-handler "^6.1.3"
shelljs "^0.8.4"
std-env "^2.2.1"
- terser-webpack-plugin "^4.1.0"
+ strip-ansi "^6.0.0"
+ terser-webpack-plugin "^5.1.1"
+ tslib "^2.1.0"
update-notifier "^5.1.0"
url-loader "^4.1.1"
wait-on "^5.2.1"
- webpack "^4.44.1"
+ webpack "^5.28.0"
webpack-bundle-analyzer "^4.4.0"
webpack-dev-server "^3.11.2"
- webpack-merge "^4.2.2"
+ webpack-merge "^5.7.3"
webpackbar "^5.0.0-3"
-"@docusaurus/cssnano-preset@2.0.0-alpha.72":
- version "2.0.0-alpha.72"
- resolved "https://registry.yarnpkg.com/@docusaurus/cssnano-preset/-/cssnano-preset-2.0.0-alpha.72.tgz#03433315207b5f43f5ba280a75b8c00f2e02b461"
- integrity sha512-7W/dlemTaipVd/zrd9Fjq/xp6IX/qn2z/GDaPbJ2SPklHbts5nWuRAt++wkG8Ue+Qxc9Q5uOBjW0ihVb4478+A==
+"@docusaurus/cssnano-preset@2.0.0-beta.0":
+ version "2.0.0-beta.0"
+ resolved "https://registry.yarnpkg.com/@docusaurus/cssnano-preset/-/cssnano-preset-2.0.0-beta.0.tgz#a79223479666059565d60a505bed2bbcac770384"
+ integrity sha512-gqQHeQCDHZDd5NaiKZwDiyg75sBCqDyAsvmFukkDAty8xE7u9IhzbOQKvCAtwseuvzu2BNN41gnJ8bz7vZzQiw==
dependencies:
- cssnano-preset-advanced "^4.0.7"
- postcss "^7.0.2"
- postcss-sort-media-queries "^1.7.26"
+ cssnano-preset-advanced "^5.0.0"
+ postcss "^8.2.10"
+ postcss-sort-media-queries "^3.8.9"
-"@docusaurus/mdx-loader@2.0.0-alpha.72":
- version "2.0.0-alpha.72"
- resolved "https://registry.yarnpkg.com/@docusaurus/mdx-loader/-/mdx-loader-2.0.0-alpha.72.tgz#03369c9fc156318a4696ece15b65b78f8ba727d0"
- integrity sha512-tG8EZc3w4xt7IKJIniPFChfVY1/adpn6w6vsXVxE96Y/1PmqKjIp6mtVKdzTShaf6MCnKrAOtEUSQR0eCRHOjQ==
+"@docusaurus/mdx-loader@2.0.0-beta.0":
+ version "2.0.0-beta.0"
+ resolved "https://registry.yarnpkg.com/@docusaurus/mdx-loader/-/mdx-loader-2.0.0-beta.0.tgz#7a58933994b2face62e34698db2f9c88c53c6d61"
+ integrity sha512-oQLS2ZeUnqw79CV37glglZpaYgFfA5Az5lT83m5tJfMUZjoK4ehG1XWBeUzWy8QQNI452yAID8jz8jihEQeCcw==
dependencies:
"@babel/parser" "^7.12.16"
"@babel/traverse" "^7.12.13"
- "@docusaurus/core" "2.0.0-alpha.72"
- "@docusaurus/utils" "2.0.0-alpha.72"
+ "@docusaurus/core" "2.0.0-beta.0"
+ "@docusaurus/utils" "2.0.0-beta.0"
"@mdx-js/mdx" "^1.6.21"
"@mdx-js/react" "^1.6.21"
escape-html "^1.0.3"
@@ -1245,128 +1231,130 @@
fs-extra "^9.1.0"
github-slugger "^1.3.0"
gray-matter "^4.0.2"
- loader-utils "^2.0.0"
mdast-util-to-string "^2.0.0"
remark-emoji "^2.1.0"
stringify-object "^3.3.0"
unist-util-visit "^2.0.2"
url-loader "^4.1.1"
- webpack "^4.44.1"
+ webpack "^5.28.0"
-"@docusaurus/plugin-content-blog@2.0.0-alpha.72":
- version "2.0.0-alpha.72"
- resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-blog/-/plugin-content-blog-2.0.0-alpha.72.tgz#478fe3c1011b8cfdb3ba7d782f8e192206954aee"
- integrity sha512-q1noOyULAQ5CkSNciUZDf1v0ly234jX3Ts6ckAy/XK5B3F340Ou8UuEFNbVap2fkRC1hOXe7RnEmFwW1PxmqmA==
+"@docusaurus/plugin-content-blog@2.0.0-beta.0":
+ version "2.0.0-beta.0"
+ resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-blog/-/plugin-content-blog-2.0.0-beta.0.tgz#ea7d3679ab252e8f0e58aaf80f1fc6001c72c755"
+ integrity sha512-lz63i5k/23RJ3Rk/2fIsYAoD8Wua3b5b0AbH2JoOhQu1iAIQiV8m91Z3XALBSzA3nBtAOIweNI7yzWL+JFSTvw==
dependencies:
- "@docusaurus/core" "2.0.0-alpha.72"
- "@docusaurus/mdx-loader" "2.0.0-alpha.72"
- "@docusaurus/types" "2.0.0-alpha.72"
- "@docusaurus/utils" "2.0.0-alpha.72"
- "@docusaurus/utils-validation" "2.0.0-alpha.72"
+ "@docusaurus/core" "2.0.0-beta.0"
+ "@docusaurus/mdx-loader" "2.0.0-beta.0"
+ "@docusaurus/types" "2.0.0-beta.0"
+ "@docusaurus/utils" "2.0.0-beta.0"
+ "@docusaurus/utils-validation" "2.0.0-beta.0"
chalk "^4.1.0"
feed "^4.2.2"
fs-extra "^9.1.0"
globby "^11.0.2"
- joi "^17.4.0"
- loader-utils "^1.2.3"
+ loader-utils "^2.0.0"
lodash "^4.17.20"
reading-time "^1.3.0"
remark-admonitions "^1.2.1"
- webpack "^4.44.1"
+ tslib "^2.1.0"
+ webpack "^5.28.0"
-"@docusaurus/plugin-content-docs@2.0.0-alpha.72":
- version "2.0.0-alpha.72"
- resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-docs/-/plugin-content-docs-2.0.0-alpha.72.tgz#65255a0fa4fabbc5f3469b04c07f263ec93c67ac"
- integrity sha512-EpMt0z/Z7SsOuQFIZlo31XsndxJ0blp7n0bVNcIlcFiNHYoBVVPbYb4VKP2W+1Sfw5K1XouUxoXRM30FyDrjhw==
+"@docusaurus/plugin-content-docs@2.0.0-beta.0":
+ version "2.0.0-beta.0"
+ resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-docs/-/plugin-content-docs-2.0.0-beta.0.tgz#a5a1e0e95e499eefee53e4f61aeb99ac4a669648"
+ integrity sha512-WdDQUh2rRCbfJswVc0vY9EaAspxgziqpVEZja8+BmQR/TZh7HuLplT6GJbiFbE4RvwM3+PwG/jHMPglYDK60kw==
dependencies:
- "@docusaurus/core" "2.0.0-alpha.72"
- "@docusaurus/mdx-loader" "2.0.0-alpha.72"
- "@docusaurus/types" "2.0.0-alpha.72"
- "@docusaurus/utils" "2.0.0-alpha.72"
- "@docusaurus/utils-validation" "2.0.0-alpha.72"
+ "@docusaurus/core" "2.0.0-beta.0"
+ "@docusaurus/mdx-loader" "2.0.0-beta.0"
+ "@docusaurus/types" "2.0.0-beta.0"
+ "@docusaurus/utils" "2.0.0-beta.0"
+ "@docusaurus/utils-validation" "2.0.0-beta.0"
chalk "^4.1.0"
+ combine-promises "^1.1.0"
execa "^5.0.0"
fs-extra "^9.1.0"
globby "^11.0.2"
import-fresh "^3.2.2"
- joi "^17.4.0"
+ js-yaml "^4.0.0"
loader-utils "^1.2.3"
lodash "^4.17.20"
remark-admonitions "^1.2.1"
shelljs "^0.8.4"
+ tslib "^2.1.0"
utility-types "^3.10.0"
- webpack "^4.44.1"
+ webpack "^5.28.0"
-"@docusaurus/plugin-content-pages@2.0.0-alpha.72":
- version "2.0.0-alpha.72"
- resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-pages/-/plugin-content-pages-2.0.0-alpha.72.tgz#5b1ddf48f5270b8295f9b20d18f76cd230147c2b"
- integrity sha512-ETBx+3+U+1sj0C/E8C3huQj5lGcSlmj0ZHBrBb3qP3zHS8+gWHAyUiXst3bvFs5mJX7JHkxfaHZc2hLxXLpaJg==
+"@docusaurus/plugin-content-pages@2.0.0-beta.0":
+ version "2.0.0-beta.0"
+ resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-pages/-/plugin-content-pages-2.0.0-beta.0.tgz#1cab3ebe0a08be74576f10c95675291bf84f848e"
+ integrity sha512-mk5LVVSvn+HJPKBaAs/Pceq/hTGxF2LVBvJEquuQz0NMAW3QdBWaYRRpOrL9CO8v+ygn5RuLslXsyZBsDNuhww==
dependencies:
- "@docusaurus/core" "2.0.0-alpha.72"
- "@docusaurus/mdx-loader" "2.0.0-alpha.72"
- "@docusaurus/types" "2.0.0-alpha.72"
- "@docusaurus/utils" "2.0.0-alpha.72"
- "@docusaurus/utils-validation" "2.0.0-alpha.72"
+ "@docusaurus/core" "2.0.0-beta.0"
+ "@docusaurus/mdx-loader" "2.0.0-beta.0"
+ "@docusaurus/types" "2.0.0-beta.0"
+ "@docusaurus/utils" "2.0.0-beta.0"
+ "@docusaurus/utils-validation" "2.0.0-beta.0"
globby "^11.0.2"
- joi "^17.4.0"
- loader-utils "^1.2.3"
lodash "^4.17.20"
minimatch "^3.0.4"
remark-admonitions "^1.2.1"
slash "^3.0.0"
- webpack "^4.44.1"
+ tslib "^2.1.0"
+ webpack "^5.28.0"
-"@docusaurus/plugin-debug@2.0.0-alpha.72":
- version "2.0.0-alpha.72"
- resolved "https://registry.yarnpkg.com/@docusaurus/plugin-debug/-/plugin-debug-2.0.0-alpha.72.tgz#79f31decce97094117924875dfe267ae7572f48c"
- integrity sha512-j2xR7i0Hw8v4SBtNvf8H5zoeKFZHScLdfJ93aUHe4ERf3AfACZuG8/tjnsarrfQK59HjbwWqbRC1mUgc2nFfwA==
+"@docusaurus/plugin-debug@2.0.0-beta.0":
+ version "2.0.0-beta.0"
+ resolved "https://registry.yarnpkg.com/@docusaurus/plugin-debug/-/plugin-debug-2.0.0-beta.0.tgz#bee672b8858d88bdb229d4301785ff4692ebd17f"
+ integrity sha512-m75sZdF8Yccxfih3qfdQg9DucMTrYBnmeTA8GNmdVaK701Ip8t50d1pDJchtu0FSEh6vzVB9C6D2YD5YgVFp8A==
dependencies:
- "@docusaurus/core" "2.0.0-alpha.72"
- "@docusaurus/types" "2.0.0-alpha.72"
- "@docusaurus/utils" "2.0.0-alpha.72"
+ "@docusaurus/core" "2.0.0-beta.0"
+ "@docusaurus/types" "2.0.0-beta.0"
+ "@docusaurus/utils" "2.0.0-beta.0"
react-json-view "^1.21.1"
+ tslib "^2.1.0"
-"@docusaurus/plugin-google-analytics@2.0.0-alpha.72":
- version "2.0.0-alpha.72"
- resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-2.0.0-alpha.72.tgz#57b66682e6aad5cd5a70c9bf9ab8ef7177832aae"
- integrity sha512-A73FA1hRHxbCZ7WVUthrEty5jRAdWlWAg9pijwSFFg5YG2kb0thNqGqMU/P5dqcV/ytE4907WvXMpKYmLtFVOg==
+"@docusaurus/plugin-google-analytics@2.0.0-beta.0":
+ version "2.0.0-beta.0"
+ resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-2.0.0-beta.0.tgz#ee287fb991202d8e9b792129dcc5542ef3ccd6c9"
+ integrity sha512-7lHrg1L+adc8VbiaLexa15i4fdq4MRPUTLMxRPAWz+QskhisW89Ryi2/gDmfMNqLblX84Qg2RASa+2gqO4wepw==
dependencies:
- "@docusaurus/core" "2.0.0-alpha.72"
+ "@docusaurus/core" "2.0.0-beta.0"
-"@docusaurus/plugin-google-gtag@2.0.0-alpha.72":
- version "2.0.0-alpha.72"
- resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-2.0.0-alpha.72.tgz#c7cbc4daa1be148b607ac3d1df3d396eede344f6"
- integrity sha512-161+C6XZAziT/MRF9HZFCzg0ybzzkW/NHIuIKPmiQjeBB+DXYopvEmldKcPlZbs8YCSD9nMxkTx39pr1AWjffw==
+"@docusaurus/plugin-google-gtag@2.0.0-beta.0":
+ version "2.0.0-beta.0"
+ resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-2.0.0-beta.0.tgz#4836770130cf54ff2cd83affbff9644ee7293e9e"
+ integrity sha512-V7zaYbhAMv0jexm5H/5sAnoM1GHibcn9QQk5UWC++x1kE0KRuLDZHV+9OyvW5wr0wWFajod/b88SpUpSMF5u+g==
dependencies:
- "@docusaurus/core" "2.0.0-alpha.72"
+ "@docusaurus/core" "2.0.0-beta.0"
-"@docusaurus/plugin-sitemap@2.0.0-alpha.72":
- version "2.0.0-alpha.72"
- resolved "https://registry.yarnpkg.com/@docusaurus/plugin-sitemap/-/plugin-sitemap-2.0.0-alpha.72.tgz#6ad55c894c19315c91847d17f0c9dcfb145132f8"
- integrity sha512-ZaMeJFDdey+PDMxg7qI2u9Wm7ylZb30FBR14wPSH5da+yMnNtl8wAlWEW8RkEgKYo04mE7DMvdEZ1YdsPF7cQg==
+"@docusaurus/plugin-sitemap@2.0.0-beta.0":
+ version "2.0.0-beta.0"
+ resolved "https://registry.yarnpkg.com/@docusaurus/plugin-sitemap/-/plugin-sitemap-2.0.0-beta.0.tgz#985d4cc3af86499f616ced024ba1fab8329e601d"
+ integrity sha512-dvmk8Sr+6pBkiKDb7Rjdp0GeFDWPUlayoJWK3fN3g0Fno6uxFfYhNZyXJ+ObyCA7HoW5rzeBMiO+uAja19JXTg==
dependencies:
- "@docusaurus/core" "2.0.0-alpha.72"
- "@docusaurus/types" "2.0.0-alpha.72"
- "@docusaurus/utils" "2.0.0-alpha.72"
+ "@docusaurus/core" "2.0.0-beta.0"
+ "@docusaurus/types" "2.0.0-beta.0"
+ "@docusaurus/utils" "2.0.0-beta.0"
+ "@docusaurus/utils-validation" "2.0.0-beta.0"
fs-extra "^9.1.0"
- joi "^17.4.0"
sitemap "^6.3.6"
+ tslib "^2.1.0"
-"@docusaurus/preset-classic@2.0.0-alpha.72":
- version "2.0.0-alpha.72"
- resolved "https://registry.yarnpkg.com/@docusaurus/preset-classic/-/preset-classic-2.0.0-alpha.72.tgz#8f20437207d53718387676cddccdb8d6f2eaf055"
- integrity sha512-Z5XKcgyrZWyUvqQZ7cAJ+E3rHkXZPRo8/23vOV5f/5sM7HeW871e+FU37RXIEFu8E8fhpCgQQ6FPEVMyiVS7Uw==
+"@docusaurus/preset-classic@2.0.0-beta.0":
+ version "2.0.0-beta.0"
+ resolved "https://registry.yarnpkg.com/@docusaurus/preset-classic/-/preset-classic-2.0.0-beta.0.tgz#79eb4366e6b5eb7061370019127e40172432d770"
+ integrity sha512-cFpR0UaAeUt5qVx1bpidhlar6tiRNITIQlxP4bOVsjbxVTZhZ/cNuIz7C+2zFPCuKIflGXdTIQOrucPmd7z51Q==
dependencies:
- "@docusaurus/core" "2.0.0-alpha.72"
- "@docusaurus/plugin-content-blog" "2.0.0-alpha.72"
- "@docusaurus/plugin-content-docs" "2.0.0-alpha.72"
- "@docusaurus/plugin-content-pages" "2.0.0-alpha.72"
- "@docusaurus/plugin-debug" "2.0.0-alpha.72"
- "@docusaurus/plugin-google-analytics" "2.0.0-alpha.72"
- "@docusaurus/plugin-google-gtag" "2.0.0-alpha.72"
- "@docusaurus/plugin-sitemap" "2.0.0-alpha.72"
- "@docusaurus/theme-classic" "2.0.0-alpha.72"
- "@docusaurus/theme-search-algolia" "2.0.0-alpha.72"
+ "@docusaurus/core" "2.0.0-beta.0"
+ "@docusaurus/plugin-content-blog" "2.0.0-beta.0"
+ "@docusaurus/plugin-content-docs" "2.0.0-beta.0"
+ "@docusaurus/plugin-content-pages" "2.0.0-beta.0"
+ "@docusaurus/plugin-debug" "2.0.0-beta.0"
+ "@docusaurus/plugin-google-analytics" "2.0.0-beta.0"
+ "@docusaurus/plugin-google-gtag" "2.0.0-beta.0"
+ "@docusaurus/plugin-sitemap" "2.0.0-beta.0"
+ "@docusaurus/theme-classic" "2.0.0-beta.0"
+ "@docusaurus/theme-search-algolia" "2.0.0-beta.0"
"@docusaurus/react-loadable@5.5.0":
version "5.5.0"
@@ -1375,92 +1363,91 @@
dependencies:
prop-types "^15.6.2"
-"@docusaurus/theme-classic@2.0.0-alpha.72":
- version "2.0.0-alpha.72"
- resolved "https://registry.yarnpkg.com/@docusaurus/theme-classic/-/theme-classic-2.0.0-alpha.72.tgz#355ed24e4252ad6e24b774496e4a52598013116a"
- integrity sha512-X5kDmMG6xCw+PpkOysnulcq9OuSsljR7Z/JiAkOeAFfd6LNeMk983q+Eu72xWxpmhmBBBkE56rhdxuBXKQJCsw==
+"@docusaurus/theme-classic@2.0.0-beta.0":
+ version "2.0.0-beta.0"
+ resolved "https://registry.yarnpkg.com/@docusaurus/theme-classic/-/theme-classic-2.0.0-beta.0.tgz#0ad74264dc592590bd7d8a6f6327cb83bbabc665"
+ integrity sha512-cBNtwAyg3be7Gk41FazMtgyibAcfuYaGHhGHIDRsXfc/qp3RhbiGiei7tyh200QT0NgKZxiVQy/r4d0mtjC++Q==
dependencies:
- "@docusaurus/core" "2.0.0-alpha.72"
- "@docusaurus/plugin-content-blog" "2.0.0-alpha.72"
- "@docusaurus/plugin-content-docs" "2.0.0-alpha.72"
- "@docusaurus/plugin-content-pages" "2.0.0-alpha.72"
- "@docusaurus/theme-common" "2.0.0-alpha.72"
- "@docusaurus/types" "2.0.0-alpha.72"
- "@docusaurus/utils" "2.0.0-alpha.72"
- "@docusaurus/utils-validation" "2.0.0-alpha.72"
+ "@docusaurus/core" "2.0.0-beta.0"
+ "@docusaurus/plugin-content-blog" "2.0.0-beta.0"
+ "@docusaurus/plugin-content-docs" "2.0.0-beta.0"
+ "@docusaurus/plugin-content-pages" "2.0.0-beta.0"
+ "@docusaurus/theme-common" "2.0.0-beta.0"
+ "@docusaurus/types" "2.0.0-beta.0"
+ "@docusaurus/utils" "2.0.0-beta.0"
+ "@docusaurus/utils-validation" "2.0.0-beta.0"
"@mdx-js/mdx" "^1.6.21"
"@mdx-js/react" "^1.6.21"
- "@types/react-toggle" "^4.0.2"
chalk "^4.1.0"
clsx "^1.1.1"
copy-text-to-clipboard "^3.0.0"
fs-extra "^9.1.0"
globby "^11.0.2"
- infima "0.2.0-alpha.21"
- joi "^17.4.0"
+ infima "0.2.0-alpha.23"
lodash "^4.17.20"
parse-numeric-range "^1.2.0"
- postcss "^7.0.2"
+ postcss "^8.2.10"
prism-react-renderer "^1.1.1"
prismjs "^1.23.0"
prop-types "^15.7.2"
react-router-dom "^5.2.0"
- react-toggle "^4.1.2"
- rtlcss "^2.6.2"
+ rtlcss "^3.1.2"
-"@docusaurus/theme-common@2.0.0-alpha.72":
- version "2.0.0-alpha.72"
- resolved "https://registry.yarnpkg.com/@docusaurus/theme-common/-/theme-common-2.0.0-alpha.72.tgz#509426c81986676038e8300d457d1dc1bdda6c65"
- integrity sha512-4NI3VCIBVJvOUk1YhBs2V4QwH1CR65sQQt2MFhHbeAmkKh1V0dYDFF8bVxrTSl7NhTICVk2Azn+tItRNkAXbdg==
+"@docusaurus/theme-common@2.0.0-beta.0":
+ version "2.0.0-beta.0"
+ resolved "https://registry.yarnpkg.com/@docusaurus/theme-common/-/theme-common-2.0.0-beta.0.tgz#3674ef6482cc39efa034fd8d8b1c831588896329"
+ integrity sha512-2rcVmQpvbdAgnzTWuM7Bfpu+2TQm928bhlvxn226jQy7IYz8ySRlIode63HhCtpx03hpdMCkrK6HxhfEcvHjQg==
dependencies:
- "@docusaurus/core" "2.0.0-alpha.72"
- "@docusaurus/plugin-content-blog" "2.0.0-alpha.72"
- "@docusaurus/plugin-content-docs" "2.0.0-alpha.72"
- "@docusaurus/plugin-content-pages" "2.0.0-alpha.72"
- "@docusaurus/types" "2.0.0-alpha.72"
+ "@docusaurus/core" "2.0.0-beta.0"
+ "@docusaurus/plugin-content-blog" "2.0.0-beta.0"
+ "@docusaurus/plugin-content-docs" "2.0.0-beta.0"
+ "@docusaurus/plugin-content-pages" "2.0.0-beta.0"
+ "@docusaurus/types" "2.0.0-beta.0"
+ tslib "^2.1.0"
-"@docusaurus/theme-search-algolia@2.0.0-alpha.72":
- version "2.0.0-alpha.72"
- resolved "https://registry.yarnpkg.com/@docusaurus/theme-search-algolia/-/theme-search-algolia-2.0.0-alpha.72.tgz#3b9e074f6dd38b4fe0b51ac42eec64a4735b37ec"
- integrity sha512-K+7WvYx0vkclaCN6nvcX4rFD/M+0b0YpjAbg+aFLzeAo77vIJESgByOc6RuK3XNALX4H2U8k7j0+wWIPsJtM1Q==
+"@docusaurus/theme-search-algolia@2.0.0-beta.0":
+ version "2.0.0-beta.0"
+ resolved "https://registry.yarnpkg.com/@docusaurus/theme-search-algolia/-/theme-search-algolia-2.0.0-beta.0.tgz#bfdee3981d8da72377b9045459950686d28a01fd"
+ integrity sha512-/GhgAm4yuwqTXWTsWnqpFYxpjTv+t45Wk8q/LmTVINa+A7b6jkMkch2lygagIt69/ufDm2Uw6eYhgrmF4DJqfQ==
dependencies:
"@docsearch/react" "^3.0.0-alpha.33"
- "@docusaurus/core" "2.0.0-alpha.72"
- "@docusaurus/theme-common" "2.0.0-alpha.72"
- "@docusaurus/utils" "2.0.0-alpha.72"
+ "@docusaurus/core" "2.0.0-beta.0"
+ "@docusaurus/theme-common" "2.0.0-beta.0"
+ "@docusaurus/utils" "2.0.0-beta.0"
+ "@docusaurus/utils-validation" "2.0.0-beta.0"
algoliasearch "^4.8.4"
algoliasearch-helper "^3.3.4"
clsx "^1.1.1"
eta "^1.12.1"
- joi "^17.4.0"
lodash "^4.17.20"
-"@docusaurus/types@2.0.0-alpha.72":
- version "2.0.0-alpha.72"
- resolved "https://registry.yarnpkg.com/@docusaurus/types/-/types-2.0.0-alpha.72.tgz#5805b0536d584b67b914b937b0f08b17a47b8c18"
- integrity sha512-/AfFD2Kdfm2rvG5j1v0w0L5gVuTPIE2vGOgLZh6EGzJT/Xx6CDdso9aAbhHiGfQkQS3bu1BPpLWqKlX9Ovi/aw==
+"@docusaurus/types@2.0.0-beta.0":
+ version "2.0.0-beta.0"
+ resolved "https://registry.yarnpkg.com/@docusaurus/types/-/types-2.0.0-beta.0.tgz#f473f417bdf690cfd52611ddf6d89ff939d1f2a4"
+ integrity sha512-z9PI+GbtYwqTXnkX4/a/A6psDX2p8N2uWlN2f4ifrm8WY4WhR9yiTOh0uo0pIqqaUQQvkEq3o5hOXuXLECEs+w==
dependencies:
- "@types/webpack" "^4.41.0"
commander "^5.1.0"
joi "^17.4.0"
querystring "0.2.0"
- webpack-merge "^4.2.2"
+ webpack "^5.28.0"
+ webpack-merge "^5.7.3"
-"@docusaurus/utils-validation@2.0.0-alpha.72":
- version "2.0.0-alpha.72"
- resolved "https://registry.yarnpkg.com/@docusaurus/utils-validation/-/utils-validation-2.0.0-alpha.72.tgz#38f2fa7907a57e3c5a1427b6ba0a514df1ea1d48"
- integrity sha512-qhpyCVCCCTy0ui62GxXz6vLazcRCGal/jBGcgnxSgQ4AyXrU2NpPQH2hunOLknL6D3BivTb+w+IAFHE9JAMX0Q==
+"@docusaurus/utils-validation@2.0.0-beta.0":
+ version "2.0.0-beta.0"
+ resolved "https://registry.yarnpkg.com/@docusaurus/utils-validation/-/utils-validation-2.0.0-beta.0.tgz#3e6491c269a397fed29717a1cb69109df9483461"
+ integrity sha512-ELl/FVJ6xBz35TisZ1NmJhjbiVXDeU++K531PEFPCPmwnQPh7S6hZXdPnR71/Kc3BmuN9X2ZkwGOqNKVfys2Bg==
dependencies:
- "@docusaurus/utils" "2.0.0-alpha.72"
+ "@docusaurus/utils" "2.0.0-beta.0"
chalk "^4.1.0"
joi "^17.4.0"
+ tslib "^2.1.0"
-"@docusaurus/utils@2.0.0-alpha.72":
- version "2.0.0-alpha.72"
- resolved "https://registry.yarnpkg.com/@docusaurus/utils/-/utils-2.0.0-alpha.72.tgz#04469cd9fee615d76b74b01680368af41129e916"
- integrity sha512-seWNBdX9LI1jREiogh0azXZaf2HStzb3MECsjAVrtEikQFbfG7K7S27C9WXDlUeQw6LVL/q0JEjHFOJD+cTSLA==
+"@docusaurus/utils@2.0.0-beta.0":
+ version "2.0.0-beta.0"
+ resolved "https://registry.yarnpkg.com/@docusaurus/utils/-/utils-2.0.0-beta.0.tgz#6f2690fd6fcd942f0d690db1dffb96742762deb3"
+ integrity sha512-bvrT1EQu0maavr0Hb/lke9jmpzgVL/9tn5VQtbyahf472eJFY0bQDExllDrHK+l784SUvucqX0iaQeg0q6ySUw==
dependencies:
- "@docusaurus/types" "2.0.0-alpha.72"
+ "@docusaurus/types" "2.0.0-beta.0"
"@types/github-slugger" "^1.3.0"
chalk "^4.1.0"
escape-string-regexp "^4.0.0"
@@ -1468,6 +1455,7 @@
gray-matter "^4.0.2"
lodash "^4.17.20"
resolve-pathname "^3.0.0"
+ tslib "^2.1.0"
"@endiliey/static-site-generator-webpack-plugin@^4.0.0":
version "4.0.0"
@@ -1548,14 +1536,6 @@
"@nodelib/fs.scandir" "2.1.4"
fastq "^1.6.0"
-"@npmcli/move-file@^1.0.1":
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/@npmcli/move-file/-/move-file-1.1.2.tgz#1a82c3e372f7cae9253eb66d72543d6b8685c674"
- integrity sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==
- dependencies:
- mkdirp "^1.0.4"
- rimraf "^3.0.2"
-
"@polka/url@^1.0.0-next.9":
version "1.0.0-next.11"
resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.11.tgz#aeb16f50649a91af79dbe36574b66d0f9e4d9f71"
@@ -1693,10 +1673,31 @@
dependencies:
defer-to-connect "^1.0.1"
-"@types/anymatch@*":
- version "1.3.1"
- resolved "https://registry.yarnpkg.com/@types/anymatch/-/anymatch-1.3.1.tgz#336badc1beecb9dacc38bea2cf32adf627a8421a"
- integrity sha512-/+CRPXpBDpo2RK9C68N3b2cOvO0Cf5B9aPijHsoDQTHivnGSObdOF2BRQOYjojWTDy6nQvMjmqRXIxH55VjxxA==
+"@trysound/sax@0.1.1":
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/@trysound/sax/-/sax-0.1.1.tgz#3348564048e7a2d7398c935d466c0414ebb6a669"
+ integrity sha512-Z6DoceYb/1xSg5+e+ZlPZ9v0N16ZvZ+wYMraFue4HYrE4ttONKtsvruIRf6t9TBR0YvSOfi1hUU0fJfBLCDYow==
+
+"@types/eslint-scope@^3.7.0":
+ version "3.7.0"
+ resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.0.tgz#4792816e31119ebd506902a482caec4951fabd86"
+ integrity sha512-O/ql2+rrCUe2W2rs7wMR+GqPRcgB6UiqN5RhrR5xruFlY7l9YLMn0ZkDzjoHLeiFkR8MCQZVudUuuvQ2BLC9Qw==
+ dependencies:
+ "@types/eslint" "*"
+ "@types/estree" "*"
+
+"@types/eslint@*":
+ version "7.2.10"
+ resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-7.2.10.tgz#4b7a9368d46c0f8cd5408c23288a59aa2394d917"
+ integrity sha512-kUEPnMKrqbtpCq/KTaGFFKAcz6Ethm2EjCoKIDaCmfRBWLbFuTcOJfTlorwbnboXBzahqWLgUp1BQeKHiJzPUQ==
+ dependencies:
+ "@types/estree" "*"
+ "@types/json-schema" "*"
+
+"@types/estree@*", "@types/estree@^0.0.47":
+ version "0.0.47"
+ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.47.tgz#d7a51db20f0650efec24cd04994f523d93172ed4"
+ integrity sha512-c5ciR06jK8u9BstrmJyO97m+klJrrhCf9u3rLu3DEAJBirxRqSCvDQoYKmxuYwQI5SZChAWu+tq9oVlGRuzPAg==
"@types/github-slugger@^1.3.0":
version "1.3.0"
@@ -1723,7 +1724,7 @@
resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz#3c9ee980f1a10d6021ae6632ca3e79ca2ec4fb50"
integrity sha512-giAlZwstKbmvMk1OO7WXSj4OZ0keXAcl2TQq4LWHiiPH2ByaH7WeUzng+Qej8UPxxv+8lRTuouo0iaNDBuzIBA==
-"@types/json-schema@^7.0.5", "@types/json-schema@^7.0.6":
+"@types/json-schema@*", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.6":
version "7.0.7"
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.7.tgz#98a993516c859eb0d5c4c8f098317a9ea68db9ad"
integrity sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA==
@@ -1755,32 +1756,11 @@
resolved "https://registry.yarnpkg.com/@types/parse5/-/parse5-5.0.3.tgz#e7b5aebbac150f8b5fdd4a46e7f0bd8e65e19109"
integrity sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw==
-"@types/prop-types@*":
- version "15.7.3"
- resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7"
- integrity sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==
-
"@types/q@^1.5.1":
version "1.5.4"
resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.4.tgz#15925414e0ad2cd765bfef58842f7e26a7accb24"
integrity sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug==
-"@types/react-toggle@^4.0.2":
- version "4.0.2"
- resolved "https://registry.yarnpkg.com/@types/react-toggle/-/react-toggle-4.0.2.tgz#46ffa5af1a55de5f25d0aa78ef0b557b5c8bf276"
- integrity sha512-sHqfoKFnL0YU2+OC4meNEC8Ptx9FE8/+nFeFvNcdBa6ANA8KpAzj3R9JN8GtrvlLgjKDoYgI7iILgXYcTPo2IA==
- dependencies:
- "@types/react" "*"
-
-"@types/react@*":
- version "17.0.3"
- resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.3.tgz#ba6e215368501ac3826951eef2904574c262cc79"
- integrity sha512-wYOUxIgs2HZZ0ACNiIayItyluADNbONl7kt8lkLjVK8IitMH5QMyAh75Fwhmo37r1m7L2JaFj03sIfxBVDvRAg==
- dependencies:
- "@types/prop-types" "*"
- "@types/scheduler" "*"
- csstype "^3.0.2"
-
"@types/sax@^1.2.1":
version "1.2.1"
resolved "https://registry.yarnpkg.com/@types/sax/-/sax-1.2.1.tgz#e0248be936ece791a82db1a57f3fb5f7c87e8172"
@@ -1788,197 +1768,130 @@
dependencies:
"@types/node" "*"
-"@types/scheduler@*":
- version "0.16.1"
- resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.1.tgz#18845205e86ff0038517aab7a18a62a6b9f71275"
- integrity sha512-EaCxbanVeyxDRTQBkdLb3Bvl/HK7PBK6UJjsSixB0iHKoWxE5uu2Q/DgtpOhPIojN0Zl1whvOd7PoHs2P0s5eA==
-
-"@types/source-list-map@*":
- version "0.1.2"
- resolved "https://registry.yarnpkg.com/@types/source-list-map/-/source-list-map-0.1.2.tgz#0078836063ffaf17412349bba364087e0ac02ec9"
- integrity sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==
-
-"@types/tapable@*", "@types/tapable@^1.0.5":
- version "1.0.6"
- resolved "https://registry.yarnpkg.com/@types/tapable/-/tapable-1.0.6.tgz#a9ca4b70a18b270ccb2bc0aaafefd1d486b7ea74"
- integrity sha512-W+bw9ds02rAQaMvaLYxAbJ6cvguW/iJXNT6lTssS1ps6QdrMKttqEAMEG/b5CR8TZl3/L7/lH0ZV5nNR1LXikA==
-
-"@types/uglify-js@*":
- version "3.13.0"
- resolved "https://registry.yarnpkg.com/@types/uglify-js/-/uglify-js-3.13.0.tgz#1cad8df1fb0b143c5aba08de5712ea9d1ff71124"
- integrity sha512-EGkrJD5Uy+Pg0NUR8uA4bJ5WMfljyad0G+784vLCNUkD+QwOJXUbBYExXfVGf7YtyzdQp3L/XMYcliB987kL5Q==
- dependencies:
- source-map "^0.6.1"
-
"@types/unist@*", "@types/unist@^2.0.0", "@types/unist@^2.0.2", "@types/unist@^2.0.3":
version "2.0.3"
resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.3.tgz#9c088679876f374eb5983f150d4787aa6fb32d7e"
integrity sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ==
-"@types/webpack-sources@*":
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/@types/webpack-sources/-/webpack-sources-2.1.0.tgz#8882b0bd62d1e0ce62f183d0d01b72e6e82e8c10"
- integrity sha512-LXn/oYIpBeucgP1EIJbKQ2/4ZmpvRl+dlrFdX7+94SKRUV3Evy3FsfMZY318vGhkWUS5MPhtOM3w1/hCOAOXcg==
+"@webassemblyjs/ast@1.11.0":
+ version "1.11.0"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.0.tgz#a5aa679efdc9e51707a4207139da57920555961f"
+ integrity sha512-kX2W49LWsbthrmIRMbQZuQDhGtjyqXfEmmHyEi4XWnSZtPmxY0+3anPIzsnRb45VH/J55zlOfWvZuY47aJZTJg==
dependencies:
- "@types/node" "*"
- "@types/source-list-map" "*"
- source-map "^0.7.3"
+ "@webassemblyjs/helper-numbers" "1.11.0"
+ "@webassemblyjs/helper-wasm-bytecode" "1.11.0"
-"@types/webpack@^4.41.0", "@types/webpack@^4.41.8":
- version "4.41.26"
- resolved "https://registry.yarnpkg.com/@types/webpack/-/webpack-4.41.26.tgz#27a30d7d531e16489f9c7607c747be6bc1a459ef"
- integrity sha512-7ZyTfxjCRwexh+EJFwRUM+CDB2XvgHl4vfuqf1ZKrgGvcS5BrNvPQqJh3tsZ0P6h6Aa1qClVHaJZszLPzpqHeA==
+"@webassemblyjs/floating-point-hex-parser@1.11.0":
+ version "1.11.0"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.0.tgz#34d62052f453cd43101d72eab4966a022587947c"
+ integrity sha512-Q/aVYs/VnPDVYvsCBL/gSgwmfjeCb4LW8+TMrO3cSzJImgv8lxxEPM2JA5jMrivE7LSz3V+PFqtMbls3m1exDA==
+
+"@webassemblyjs/helper-api-error@1.11.0":
+ version "1.11.0"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.0.tgz#aaea8fb3b923f4aaa9b512ff541b013ffb68d2d4"
+ integrity sha512-baT/va95eXiXb2QflSx95QGT5ClzWpGaa8L7JnJbgzoYeaA27FCvuBXU758l+KXWRndEmUXjP0Q5fibhavIn8w==
+
+"@webassemblyjs/helper-buffer@1.11.0":
+ version "1.11.0"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.0.tgz#d026c25d175e388a7dbda9694e91e743cbe9b642"
+ integrity sha512-u9HPBEl4DS+vA8qLQdEQ6N/eJQ7gT7aNvMIo8AAWvAl/xMrcOSiI2M0MAnMCy3jIFke7bEee/JwdX1nUpCtdyA==
+
+"@webassemblyjs/helper-numbers@1.11.0":
+ version "1.11.0"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.0.tgz#7ab04172d54e312cc6ea4286d7d9fa27c88cd4f9"
+ integrity sha512-DhRQKelIj01s5IgdsOJMKLppI+4zpmcMQ3XboFPLwCpSNH6Hqo1ritgHgD0nqHeSYqofA6aBN/NmXuGjM1jEfQ==
dependencies:
- "@types/anymatch" "*"
- "@types/node" "*"
- "@types/tapable" "*"
- "@types/uglify-js" "*"
- "@types/webpack-sources" "*"
- source-map "^0.6.0"
+ "@webassemblyjs/floating-point-hex-parser" "1.11.0"
+ "@webassemblyjs/helper-api-error" "1.11.0"
+ "@xtuc/long" "4.2.2"
-"@webassemblyjs/ast@1.9.0":
- version "1.9.0"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.9.0.tgz#bd850604b4042459a5a41cd7d338cbed695ed964"
- integrity sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==
+"@webassemblyjs/helper-wasm-bytecode@1.11.0":
+ version "1.11.0"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.0.tgz#85fdcda4129902fe86f81abf7e7236953ec5a4e1"
+ integrity sha512-MbmhvxXExm542tWREgSFnOVo07fDpsBJg3sIl6fSp9xuu75eGz5lz31q7wTLffwL3Za7XNRCMZy210+tnsUSEA==
+
+"@webassemblyjs/helper-wasm-section@1.11.0":
+ version "1.11.0"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.0.tgz#9ce2cc89300262509c801b4af113d1ca25c1a75b"
+ integrity sha512-3Eb88hcbfY/FCukrg6i3EH8H2UsD7x8Vy47iVJrP967A9JGqgBVL9aH71SETPx1JrGsOUVLo0c7vMCN22ytJew==
dependencies:
- "@webassemblyjs/helper-module-context" "1.9.0"
- "@webassemblyjs/helper-wasm-bytecode" "1.9.0"
- "@webassemblyjs/wast-parser" "1.9.0"
+ "@webassemblyjs/ast" "1.11.0"
+ "@webassemblyjs/helper-buffer" "1.11.0"
+ "@webassemblyjs/helper-wasm-bytecode" "1.11.0"
+ "@webassemblyjs/wasm-gen" "1.11.0"
-"@webassemblyjs/floating-point-hex-parser@1.9.0":
- version "1.9.0"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz#3c3d3b271bddfc84deb00f71344438311d52ffb4"
- integrity sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA==
-
-"@webassemblyjs/helper-api-error@1.9.0":
- version "1.9.0"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz#203f676e333b96c9da2eeab3ccef33c45928b6a2"
- integrity sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==
-
-"@webassemblyjs/helper-buffer@1.9.0":
- version "1.9.0"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz#a1442d269c5feb23fcbc9ef759dac3547f29de00"
- integrity sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==
-
-"@webassemblyjs/helper-code-frame@1.9.0":
- version "1.9.0"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz#647f8892cd2043a82ac0c8c5e75c36f1d9159f27"
- integrity sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA==
- dependencies:
- "@webassemblyjs/wast-printer" "1.9.0"
-
-"@webassemblyjs/helper-fsm@1.9.0":
- version "1.9.0"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz#c05256b71244214671f4b08ec108ad63b70eddb8"
- integrity sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw==
-
-"@webassemblyjs/helper-module-context@1.9.0":
- version "1.9.0"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz#25d8884b76839871a08a6c6f806c3979ef712f07"
- integrity sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g==
- dependencies:
- "@webassemblyjs/ast" "1.9.0"
-
-"@webassemblyjs/helper-wasm-bytecode@1.9.0":
- version "1.9.0"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz#4fed8beac9b8c14f8c58b70d124d549dd1fe5790"
- integrity sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==
-
-"@webassemblyjs/helper-wasm-section@1.9.0":
- version "1.9.0"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz#5a4138d5a6292ba18b04c5ae49717e4167965346"
- integrity sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==
- dependencies:
- "@webassemblyjs/ast" "1.9.0"
- "@webassemblyjs/helper-buffer" "1.9.0"
- "@webassemblyjs/helper-wasm-bytecode" "1.9.0"
- "@webassemblyjs/wasm-gen" "1.9.0"
-
-"@webassemblyjs/ieee754@1.9.0":
- version "1.9.0"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz#15c7a0fbaae83fb26143bbacf6d6df1702ad39e4"
- integrity sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==
+"@webassemblyjs/ieee754@1.11.0":
+ version "1.11.0"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.0.tgz#46975d583f9828f5d094ac210e219441c4e6f5cf"
+ integrity sha512-KXzOqpcYQwAfeQ6WbF6HXo+0udBNmw0iXDmEK5sFlmQdmND+tr773Ti8/5T/M6Tl/413ArSJErATd8In3B+WBA==
dependencies:
"@xtuc/ieee754" "^1.2.0"
-"@webassemblyjs/leb128@1.9.0":
- version "1.9.0"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.9.0.tgz#f19ca0b76a6dc55623a09cffa769e838fa1e1c95"
- integrity sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==
+"@webassemblyjs/leb128@1.11.0":
+ version "1.11.0"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.0.tgz#f7353de1df38aa201cba9fb88b43f41f75ff403b"
+ integrity sha512-aqbsHa1mSQAbeeNcl38un6qVY++hh8OpCOzxhixSYgbRfNWcxJNJQwe2rezK9XEcssJbbWIkblaJRwGMS9zp+g==
dependencies:
"@xtuc/long" "4.2.2"
-"@webassemblyjs/utf8@1.9.0":
- version "1.9.0"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.9.0.tgz#04d33b636f78e6a6813227e82402f7637b6229ab"
- integrity sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==
+"@webassemblyjs/utf8@1.11.0":
+ version "1.11.0"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.0.tgz#86e48f959cf49e0e5091f069a709b862f5a2cadf"
+ integrity sha512-A/lclGxH6SpSLSyFowMzO/+aDEPU4hvEiooCMXQPcQFPPJaYcPQNKGOCLUySJsYJ4trbpr+Fs08n4jelkVTGVw==
-"@webassemblyjs/wasm-edit@1.9.0":
- version "1.9.0"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz#3fe6d79d3f0f922183aa86002c42dd256cfee9cf"
- integrity sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==
+"@webassemblyjs/wasm-edit@1.11.0":
+ version "1.11.0"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.0.tgz#ee4a5c9f677046a210542ae63897094c2027cb78"
+ integrity sha512-JHQ0damXy0G6J9ucyKVXO2j08JVJ2ntkdJlq1UTiUrIgfGMmA7Ik5VdC/L8hBK46kVJgujkBIoMtT8yVr+yVOQ==
dependencies:
- "@webassemblyjs/ast" "1.9.0"
- "@webassemblyjs/helper-buffer" "1.9.0"
- "@webassemblyjs/helper-wasm-bytecode" "1.9.0"
- "@webassemblyjs/helper-wasm-section" "1.9.0"
- "@webassemblyjs/wasm-gen" "1.9.0"
- "@webassemblyjs/wasm-opt" "1.9.0"
- "@webassemblyjs/wasm-parser" "1.9.0"
- "@webassemblyjs/wast-printer" "1.9.0"
+ "@webassemblyjs/ast" "1.11.0"
+ "@webassemblyjs/helper-buffer" "1.11.0"
+ "@webassemblyjs/helper-wasm-bytecode" "1.11.0"
+ "@webassemblyjs/helper-wasm-section" "1.11.0"
+ "@webassemblyjs/wasm-gen" "1.11.0"
+ "@webassemblyjs/wasm-opt" "1.11.0"
+ "@webassemblyjs/wasm-parser" "1.11.0"
+ "@webassemblyjs/wast-printer" "1.11.0"
-"@webassemblyjs/wasm-gen@1.9.0":
- version "1.9.0"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz#50bc70ec68ded8e2763b01a1418bf43491a7a49c"
- integrity sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==
+"@webassemblyjs/wasm-gen@1.11.0":
+ version "1.11.0"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.0.tgz#3cdb35e70082d42a35166988dda64f24ceb97abe"
+ integrity sha512-BEUv1aj0WptCZ9kIS30th5ILASUnAPEvE3tVMTrItnZRT9tXCLW2LEXT8ezLw59rqPP9klh9LPmpU+WmRQmCPQ==
dependencies:
- "@webassemblyjs/ast" "1.9.0"
- "@webassemblyjs/helper-wasm-bytecode" "1.9.0"
- "@webassemblyjs/ieee754" "1.9.0"
- "@webassemblyjs/leb128" "1.9.0"
- "@webassemblyjs/utf8" "1.9.0"
+ "@webassemblyjs/ast" "1.11.0"
+ "@webassemblyjs/helper-wasm-bytecode" "1.11.0"
+ "@webassemblyjs/ieee754" "1.11.0"
+ "@webassemblyjs/leb128" "1.11.0"
+ "@webassemblyjs/utf8" "1.11.0"
-"@webassemblyjs/wasm-opt@1.9.0":
- version "1.9.0"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz#2211181e5b31326443cc8112eb9f0b9028721a61"
- integrity sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==
+"@webassemblyjs/wasm-opt@1.11.0":
+ version "1.11.0"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.0.tgz#1638ae188137f4bb031f568a413cd24d32f92978"
+ integrity sha512-tHUSP5F4ywyh3hZ0+fDQuWxKx3mJiPeFufg+9gwTpYp324mPCQgnuVKwzLTZVqj0duRDovnPaZqDwoyhIO8kYg==
dependencies:
- "@webassemblyjs/ast" "1.9.0"
- "@webassemblyjs/helper-buffer" "1.9.0"
- "@webassemblyjs/wasm-gen" "1.9.0"
- "@webassemblyjs/wasm-parser" "1.9.0"
+ "@webassemblyjs/ast" "1.11.0"
+ "@webassemblyjs/helper-buffer" "1.11.0"
+ "@webassemblyjs/wasm-gen" "1.11.0"
+ "@webassemblyjs/wasm-parser" "1.11.0"
-"@webassemblyjs/wasm-parser@1.9.0":
- version "1.9.0"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz#9d48e44826df4a6598294aa6c87469d642fff65e"
- integrity sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==
+"@webassemblyjs/wasm-parser@1.11.0":
+ version "1.11.0"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.0.tgz#3e680b8830d5b13d1ec86cc42f38f3d4a7700754"
+ integrity sha512-6L285Sgu9gphrcpDXINvm0M9BskznnzJTE7gYkjDbxET28shDqp27wpruyx3C2S/dvEwiigBwLA1cz7lNUi0kw==
dependencies:
- "@webassemblyjs/ast" "1.9.0"
- "@webassemblyjs/helper-api-error" "1.9.0"
- "@webassemblyjs/helper-wasm-bytecode" "1.9.0"
- "@webassemblyjs/ieee754" "1.9.0"
- "@webassemblyjs/leb128" "1.9.0"
- "@webassemblyjs/utf8" "1.9.0"
+ "@webassemblyjs/ast" "1.11.0"
+ "@webassemblyjs/helper-api-error" "1.11.0"
+ "@webassemblyjs/helper-wasm-bytecode" "1.11.0"
+ "@webassemblyjs/ieee754" "1.11.0"
+ "@webassemblyjs/leb128" "1.11.0"
+ "@webassemblyjs/utf8" "1.11.0"
-"@webassemblyjs/wast-parser@1.9.0":
- version "1.9.0"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz#3031115d79ac5bd261556cecc3fa90a3ef451914"
- integrity sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw==
+"@webassemblyjs/wast-printer@1.11.0":
+ version "1.11.0"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.0.tgz#680d1f6a5365d6d401974a8e949e05474e1fab7e"
+ integrity sha512-Fg5OX46pRdTgB7rKIUojkh9vXaVN6sGYCnEiJN1GYkb0RPwShZXp6KTDqmoMdQPKhcroOXh3fEzmkWmCYaKYhQ==
dependencies:
- "@webassemblyjs/ast" "1.9.0"
- "@webassemblyjs/floating-point-hex-parser" "1.9.0"
- "@webassemblyjs/helper-api-error" "1.9.0"
- "@webassemblyjs/helper-code-frame" "1.9.0"
- "@webassemblyjs/helper-fsm" "1.9.0"
- "@xtuc/long" "4.2.2"
-
-"@webassemblyjs/wast-printer@1.9.0":
- version "1.9.0"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz#4935d54c85fef637b00ce9f52377451d00d47899"
- integrity sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==
- dependencies:
- "@webassemblyjs/ast" "1.9.0"
- "@webassemblyjs/wast-parser" "1.9.0"
+ "@webassemblyjs/ast" "1.11.0"
"@xtuc/long" "4.2.2"
"@xtuc/ieee754@^1.2.0":
@@ -2004,16 +1917,16 @@ acorn-walk@^8.0.0:
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.0.2.tgz#d4632bfc63fd93d0f15fd05ea0e984ffd3f5a8c3"
integrity sha512-+bpA9MJsHdZ4bgfDcpk0ozQyhhVct7rzOmO0s1IIr0AGGgKBljss8n2zp11rRP2wid5VGeh04CgeKzgat5/25A==
-acorn@^6.4.1:
- version "6.4.2"
- resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6"
- integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==
-
acorn@^8.0.4:
version "8.1.0"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.1.0.tgz#52311fd7037ae119cbb134309e901aa46295b3fe"
integrity sha512-LWCF/Wn0nfHOmJ9rzQApGnxnvgfROzGilS8936rqN/lfcYkY9MYZzdMqN+2NJ4SlTc+m5HiSa+kNfDtI64dwUA==
+acorn@^8.2.1:
+ version "8.2.4"
+ resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.2.4.tgz#caba24b08185c3b56e3168e97d15ed17f4d31fd0"
+ integrity sha512-Ibt84YwBDDA890eDiDCEqcbwvHlBvzzDkU2cGBBDDI1QWT12jTiXIOn2CIw5KK4i6N5Z2HUxwYjzriDyqaqqZg==
+
address@1.1.2, address@^1.0.1:
version "1.1.2"
resolved "https://registry.yarnpkg.com/address/-/address-1.1.2.tgz#bf1116c9c758c51b7a933d296b72c221ed9428b6"
@@ -2032,12 +1945,12 @@ ajv-errors@^1.0.0:
resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.1.tgz#f35986aceb91afadec4102fbd85014950cefa64d"
integrity sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==
-ajv-keywords@^3.1.0, ajv-keywords@^3.4.1, ajv-keywords@^3.5.2:
+ajv-keywords@^3.1.0, ajv-keywords@^3.5.2:
version "3.5.2"
resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d"
integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==
-ajv@^6.1.0, ajv@^6.10.2, ajv@^6.12.4, ajv@^6.12.5:
+ajv@^6.1.0, ajv@^6.12.4, ajv@^6.12.5:
version "6.12.6"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
@@ -2074,7 +1987,7 @@ algoliasearch@^4.0.0, algoliasearch@^4.8.4:
"@algolia/requester-node-http" "4.8.6"
"@algolia/transporter" "4.8.6"
-alphanum-sort@^1.0.0:
+alphanum-sort@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3"
integrity sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=
@@ -2148,11 +2061,6 @@ anymatch@~3.1.1:
normalize-path "^3.0.0"
picomatch "^2.0.4"
-aproba@^1.1.1:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a"
- integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==
-
arg@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.0.tgz#a20e2bb5710e82950a516b3f933fee5ed478be90"
@@ -2165,6 +2073,11 @@ argparse@^1.0.7:
dependencies:
sprintf-js "~1.0.2"
+argparse@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
+ integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==
+
arr-diff@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520"
@@ -2217,24 +2130,6 @@ asap@~2.0.3:
resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46"
integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=
-asn1.js@^5.2.0:
- version "5.4.1"
- resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07"
- integrity sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==
- dependencies:
- bn.js "^4.0.0"
- inherits "^2.0.1"
- minimalistic-assert "^1.0.0"
- safer-buffer "^2.1.0"
-
-assert@^1.1.1:
- version "1.5.0"
- resolved "https://registry.yarnpkg.com/assert/-/assert-1.5.0.tgz#55c109aaf6e0aefdb3dc4b71240c70bf574b18eb"
- integrity sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==
- dependencies:
- object-assign "^4.1.1"
- util "0.10.3"
-
assign-symbols@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367"
@@ -2267,7 +2162,7 @@ atob@^2.1.2:
resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==
-autoprefixer@^10.2.5:
+autoprefixer@^10.0.2, autoprefixer@^10.2.5:
version "10.2.5"
resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.2.5.tgz#096a0337dbc96c0873526d7fef5de4428d05382d"
integrity sha512-7H4AJZXvSsn62SqZyJCP+1AWwOuoYpUfK6ot9vm0e87XD6mT8lDywc9D9OTJPMULyGcvmIxzTAMeG2Cc+YX+fA==
@@ -2279,19 +2174,6 @@ autoprefixer@^10.2.5:
normalize-range "^0.1.2"
postcss-value-parser "^4.1.0"
-autoprefixer@^9.4.7, autoprefixer@^9.6.1:
- version "9.8.6"
- resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.8.6.tgz#3b73594ca1bf9266320c5acf1588d74dea74210f"
- integrity sha512-XrvP4VVHdRBCdX1S3WXVD8+RyG9qeb1D5Sn1DeLiG2xfSpzellk5k54xbUERJ3M5DggQxes39UGOTP8CFrEGbg==
- dependencies:
- browserslist "^4.12.0"
- caniuse-lite "^1.0.30001109"
- colorette "^1.2.1"
- normalize-range "^0.1.2"
- num2fraction "^1.2.2"
- postcss "^7.0.32"
- postcss-value-parser "^4.1.0"
-
axios@^0.21.1:
version "0.21.1"
resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.1.tgz#22563481962f4d6bde9a76d516ef0e5d3c09b2b8"
@@ -2377,11 +2259,6 @@ base16@^1.0.0:
resolved "https://registry.yarnpkg.com/base16/-/base16-1.0.0.tgz#e297f60d7ec1014a7a971a39ebc8a98c0b681e70"
integrity sha1-4pf2DX7BAUp6lxo568ipjAtoHnA=
-base64-js@^1.0.2:
- version "1.5.1"
- resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
- integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
-
base@^0.11.1:
version "0.11.2"
resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f"
@@ -2422,21 +2299,11 @@ bindings@^1.5.0:
dependencies:
file-uri-to-path "1.0.0"
-bluebird@^3.5.5, bluebird@^3.7.1:
+bluebird@^3.7.1:
version "3.7.2"
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f"
integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==
-bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.9:
- version "4.12.0"
- resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88"
- integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==
-
-bn.js@^5.0.0, bn.js@^5.1.1:
- version "5.2.0"
- resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.0.tgz#358860674396c6997771a9d051fcc1b57d4ae002"
- integrity sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==
-
body-parser@1.19.0:
version "1.19.0"
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a"
@@ -2515,72 +2382,6 @@ braces@^3.0.1, braces@~3.0.2:
dependencies:
fill-range "^7.0.1"
-brorand@^1.0.1, brorand@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f"
- integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=
-
-browserify-aes@^1.0.0, browserify-aes@^1.0.4:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48"
- integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==
- dependencies:
- buffer-xor "^1.0.3"
- cipher-base "^1.0.0"
- create-hash "^1.1.0"
- evp_bytestokey "^1.0.3"
- inherits "^2.0.1"
- safe-buffer "^5.0.1"
-
-browserify-cipher@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0"
- integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==
- dependencies:
- browserify-aes "^1.0.4"
- browserify-des "^1.0.0"
- evp_bytestokey "^1.0.0"
-
-browserify-des@^1.0.0:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c"
- integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==
- dependencies:
- cipher-base "^1.0.1"
- des.js "^1.0.0"
- inherits "^2.0.1"
- safe-buffer "^5.1.2"
-
-browserify-rsa@^4.0.0, browserify-rsa@^4.0.1:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.1.0.tgz#b2fd06b5b75ae297f7ce2dc651f918f5be158c8d"
- integrity sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==
- dependencies:
- bn.js "^5.0.0"
- randombytes "^2.0.1"
-
-browserify-sign@^4.0.0:
- version "4.2.1"
- resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.1.tgz#eaf4add46dd54be3bb3b36c0cf15abbeba7956c3"
- integrity sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==
- dependencies:
- bn.js "^5.1.1"
- browserify-rsa "^4.0.1"
- create-hash "^1.2.0"
- create-hmac "^1.1.7"
- elliptic "^6.5.3"
- inherits "^2.0.4"
- parse-asn1 "^5.1.5"
- readable-stream "^3.6.0"
- safe-buffer "^5.2.0"
-
-browserify-zlib@^0.2.0:
- version "0.2.0"
- resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f"
- integrity sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==
- dependencies:
- pako "~1.0.5"
-
browserslist@4.14.2:
version "4.14.2"
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.14.2.tgz#1b3cec458a1ba87588cc5e9be62f19b6d48813ce"
@@ -2591,7 +2392,7 @@ browserslist@4.14.2:
escalade "^3.0.2"
node-releases "^1.1.61"
-browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.14.5, browserslist@^4.16.3, browserslist@^4.6.4:
+browserslist@^4.0.0, browserslist@^4.14.5, browserslist@^4.16.3:
version "4.16.3"
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.16.3.tgz#340aa46940d7db878748567c5dea24a48ddf3717"
integrity sha512-vIyhWmIkULaq04Gt93txdh+j02yX/JzlyhLYbV3YQCn/zvES3JnY7TifHHvvr1w5hTDluNKMkV05cs4vy8Q7sw==
@@ -2602,6 +2403,17 @@ browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.14.5, browserslist@^4
escalade "^3.1.1"
node-releases "^1.1.70"
+browserslist@^4.16.0:
+ version "4.16.6"
+ resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.16.6.tgz#d7901277a5a88e554ed305b183ec9b0c08f66fa2"
+ integrity sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ==
+ dependencies:
+ caniuse-lite "^1.0.30001219"
+ colorette "^1.2.2"
+ electron-to-chromium "^1.3.723"
+ escalade "^3.1.1"
+ node-releases "^1.1.71"
+
buffer-from@^1.0.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
@@ -2612,30 +2424,6 @@ buffer-indexof@^1.0.0:
resolved "https://registry.yarnpkg.com/buffer-indexof/-/buffer-indexof-1.1.1.tgz#52fabcc6a606d1a00302802648ef68f639da268c"
integrity sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==
-buffer-json@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/buffer-json/-/buffer-json-2.0.0.tgz#f73e13b1e42f196fe2fd67d001c7d7107edd7c23"
- integrity sha512-+jjPFVqyfF1esi9fvfUs3NqM0pH1ziZ36VP4hmA/y/Ssfo/5w5xHKfTw9BwQjoJ1w/oVtpLomqwUHKdefGyuHw==
-
-buffer-xor@^1.0.3:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9"
- integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=
-
-buffer@^4.3.0:
- version "4.9.2"
- resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.2.tgz#230ead344002988644841ab0244af8c44bbe3ef8"
- integrity sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==
- dependencies:
- base64-js "^1.0.2"
- ieee754 "^1.1.4"
- isarray "^1.0.0"
-
-builtin-status-codes@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8"
- integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=
-
bytes@3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048"
@@ -2646,50 +2434,6 @@ bytes@3.1.0:
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6"
integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==
-cacache@^12.0.2:
- version "12.0.4"
- resolved "https://registry.yarnpkg.com/cacache/-/cacache-12.0.4.tgz#668bcbd105aeb5f1d92fe25570ec9525c8faa40c"
- integrity sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==
- dependencies:
- bluebird "^3.5.5"
- chownr "^1.1.1"
- figgy-pudding "^3.5.1"
- glob "^7.1.4"
- graceful-fs "^4.1.15"
- infer-owner "^1.0.3"
- lru-cache "^5.1.1"
- mississippi "^3.0.0"
- mkdirp "^0.5.1"
- move-concurrently "^1.0.1"
- promise-inflight "^1.0.1"
- rimraf "^2.6.3"
- ssri "^6.0.1"
- unique-filename "^1.1.1"
- y18n "^4.0.0"
-
-cacache@^15.0.5:
- version "15.0.6"
- resolved "https://registry.yarnpkg.com/cacache/-/cacache-15.0.6.tgz#65a8c580fda15b59150fb76bf3f3a8e45d583099"
- integrity sha512-g1WYDMct/jzW+JdWEyjaX2zoBkZ6ZT9VpOyp2I/VMtDsNLffNat3kqPFfi1eDRSK9/SuKGyORDHcQMcPF8sQ/w==
- dependencies:
- "@npmcli/move-file" "^1.0.1"
- chownr "^2.0.0"
- fs-minipass "^2.0.0"
- glob "^7.1.4"
- infer-owner "^1.0.4"
- lru-cache "^6.0.0"
- minipass "^3.1.1"
- minipass-collect "^1.0.2"
- minipass-flush "^1.0.5"
- minipass-pipeline "^1.2.2"
- mkdirp "^1.0.3"
- p-map "^4.0.0"
- promise-inflight "^1.0.1"
- rimraf "^3.0.2"
- ssri "^8.0.1"
- tar "^6.0.2"
- unique-filename "^1.1.1"
-
cache-base@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2"
@@ -2705,18 +2449,6 @@ cache-base@^1.0.1:
union-value "^1.0.0"
unset-value "^1.0.0"
-cache-loader@^4.1.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/cache-loader/-/cache-loader-4.1.0.tgz#9948cae353aec0a1fcb1eafda2300816ec85387e"
- integrity sha512-ftOayxve0PwKzBF/GLsZNC9fJBXl8lkZE3TOsjkboHfVHVkL39iUEs1FO07A33mizmci5Dudt38UZrrYXDtbhw==
- dependencies:
- buffer-json "^2.0.0"
- find-cache-dir "^3.0.0"
- loader-utils "^1.2.3"
- mkdirp "^0.5.1"
- neo-async "^2.6.1"
- schema-utils "^2.0.0"
-
cacheable-request@^6.0.0:
version "6.1.0"
resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912"
@@ -2738,25 +2470,6 @@ call-bind@^1.0.0, call-bind@^1.0.2:
function-bind "^1.1.1"
get-intrinsic "^1.0.2"
-caller-callsite@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134"
- integrity sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=
- dependencies:
- callsites "^2.0.0"
-
-caller-path@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4"
- integrity sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=
- dependencies:
- caller-callsite "^2.0.0"
-
-callsites@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50"
- integrity sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=
-
callsites@^3.0.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
@@ -2795,17 +2508,22 @@ caniuse-api@^3.0.0:
lodash.memoize "^4.1.2"
lodash.uniq "^4.5.0"
-caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001125, caniuse-lite@^1.0.30001181, caniuse-lite@^1.0.30001196:
+caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001125, caniuse-lite@^1.0.30001181, caniuse-lite@^1.0.30001196:
version "1.0.30001204"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001204.tgz#256c85709a348ec4d175e847a3b515c66e79f2aa"
integrity sha512-JUdjWpcxfJ9IPamy2f5JaRDCaqJOxDzOSKtbdx4rH9VivMd1vIzoPumsJa9LoMIi4Fx2BV2KZOxWhNkBjaYivQ==
+caniuse-lite@^1.0.30001219:
+ version "1.0.30001228"
+ resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001228.tgz#bfdc5942cd3326fa51ee0b42fbef4da9d492a7fa"
+ integrity sha512-QQmLOGJ3DEgokHbMSA8cj2a+geXqmnpyOFT0lhQV6P3/YOJvGDEwoedcwxEQ30gJIwIIunHIicunJ2rzK5gB2A==
+
ccount@^1.0.0, ccount@^1.0.3:
version "1.1.0"
resolved "https://registry.yarnpkg.com/ccount/-/ccount-1.1.0.tgz#246687debb6014735131be8abab2d93898f8d043"
integrity sha512-vlNK021QdI7PNeiUh/lKkC/mNHHfV0m/Ad5JoI0TYtlBnJAslM/JIkm/tGC88bkLIwO6OQ5uV6ztS6kVAtCDlg==
-chalk@2.4.2, chalk@^2.0.0, chalk@^2.4.1, chalk@^2.4.2:
+chalk@2.4.2, chalk@^2.0.0, chalk@^2.4.1:
version "2.4.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
@@ -2878,7 +2596,7 @@ chokidar@^2.1.8:
optionalDependencies:
fsevents "^1.2.7"
-chokidar@^3.4.1, chokidar@^3.5.1:
+chokidar@^3.5.1:
version "3.5.1"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.1.tgz#ee9ce7bbebd2b79f49f304799d5468e31e14e68a"
integrity sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==
@@ -2893,16 +2611,6 @@ chokidar@^3.4.1, chokidar@^3.5.1:
optionalDependencies:
fsevents "~2.3.1"
-chownr@^1.1.1:
- version "1.1.4"
- resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b"
- integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==
-
-chownr@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece"
- integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==
-
chrome-trace-event@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz#234090ee97c7d4ad1a2c4beae27505deffc608a4"
@@ -2920,14 +2628,6 @@ ci-info@^3.0.0:
resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.1.1.tgz#9a32fcefdf7bcdb6f0a7e1c0f8098ec57897b80a"
integrity sha512-kdRWLBIJwdsYJWYJFtAFFYxybguqeF91qpZaggjG5Nf8QKdizFG2hjqvaTXbxFIcYbSaD74KpAXv6BSm17DHEQ==
-cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de"
- integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==
- dependencies:
- inherits "^2.0.1"
- safe-buffer "^5.0.1"
-
class-utils@^0.3.5:
version "0.3.6"
resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463"
@@ -2938,7 +2638,7 @@ class-utils@^0.3.5:
isobject "^3.0.0"
static-extend "^0.1.1"
-classnames@^2.2.5, classnames@^2.2.6:
+classnames@^2.2.6:
version "2.2.6"
resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce"
integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==
@@ -2985,6 +2685,15 @@ cliui@^5.0.0:
strip-ansi "^5.2.0"
wrap-ansi "^5.1.0"
+clone-deep@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387"
+ integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==
+ dependencies:
+ is-plain-object "^2.0.4"
+ kind-of "^6.0.2"
+ shallow-clone "^3.0.0"
+
clone-response@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b"
@@ -3051,7 +2760,7 @@ color-string@^1.5.4:
color-name "^1.0.0"
simple-swizzle "^0.2.2"
-color@^3.0.0:
+color@^3.1.1:
version "3.1.3"
resolved "https://registry.yarnpkg.com/color/-/color-3.1.3.tgz#ca67fb4e7b97d611dcde39eceed422067d91596e"
integrity sha512-xgXAcTHa2HeFCGLE9Xs/R82hujGtu9Jd9x4NW3T34+OMs7VoPsjwzRczKHvTAHeJwWFwX5j15+MgAppE8ztObQ==
@@ -3064,12 +2773,17 @@ colorette@^1.2.1, colorette@^1.2.2:
resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.2.tgz#cbcc79d5e99caea2dbf10eb3a26fd8b3e6acfa94"
integrity sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==
+combine-promises@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/combine-promises/-/combine-promises-1.1.0.tgz#72db90743c0ca7aab7d0d8d2052fd7b0f674de71"
+ integrity sha512-ZI9jvcLDxqwaXEixOhArm3r7ReIivsXkpbyEWyeOhzz1QS0iSgBPnWvEqvIQtYyamGCYA88gFhmUrs9hrrQ0pg==
+
comma-separated-tokens@^1.0.0:
version "1.0.8"
resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz#632b80b6117867a158f1080ad498b2fbe7e3f5ea"
integrity sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==
-commander@^2.15.1, commander@^2.20.0:
+commander@^2.20.0:
version "2.20.3"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
@@ -3089,6 +2803,11 @@ commander@^6.2.0:
resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c"
integrity sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==
+commander@^7.1.0:
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7"
+ integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==
+
commondir@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
@@ -3124,16 +2843,6 @@ concat-map@0.0.1:
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
-concat-stream@^1.5.0:
- version "1.6.2"
- resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34"
- integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==
- dependencies:
- buffer-from "^1.0.0"
- inherits "^2.0.3"
- readable-stream "^2.2.2"
- typedarray "^0.0.6"
-
configstore@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/configstore/-/configstore-5.0.1.tgz#d365021b5df4b98cdd187d6a3b0e3f6a7cc5ed96"
@@ -3156,16 +2865,6 @@ consola@^2.15.0:
resolved "https://registry.yarnpkg.com/consola/-/consola-2.15.3.tgz#2e11f98d6a4be71ff72e0bdf07bd23e12cb61550"
integrity sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==
-console-browserify@^1.1.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336"
- integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==
-
-constants-browserify@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75"
- integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=
-
content-disposition@0.5.2:
version "0.5.2"
resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4"
@@ -3200,18 +2899,6 @@ cookie@0.4.0:
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba"
integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==
-copy-concurrently@^1.0.0:
- version "1.0.5"
- resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0"
- integrity sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==
- dependencies:
- aproba "^1.1.1"
- fs-write-stream-atomic "^1.0.8"
- iferr "^0.1.5"
- mkdirp "^0.5.1"
- rimraf "^2.5.4"
- run-queue "^1.0.0"
-
copy-descriptor@^0.1.0:
version "0.1.1"
resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d"
@@ -3222,22 +2909,18 @@ copy-text-to-clipboard@^3.0.0:
resolved "https://registry.yarnpkg.com/copy-text-to-clipboard/-/copy-text-to-clipboard-3.0.1.tgz#8cbf8f90e0a47f12e4a24743736265d157bce69c"
integrity sha512-rvVsHrpFcL4F2P8ihsoLdFHmd404+CMg71S756oRSeQgqk51U3kicGdnvfkrxva0xXH92SjGS62B0XIJsbh+9Q==
-copy-webpack-plugin@^6.4.1:
- version "6.4.1"
- resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-6.4.1.tgz#138cd9b436dbca0a6d071720d5414848992ec47e"
- integrity sha512-MXyPCjdPVx5iiWyl40Va3JGh27bKzOTNY3NjUTrosD2q7dR/cLD0013uqJ3BpFbUjyONINjb6qI7nDIJujrMbA==
+copy-webpack-plugin@^8.1.0:
+ version "8.1.1"
+ resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-8.1.1.tgz#3f697e162764925c2f0d235f380676125508fd26"
+ integrity sha512-rYM2uzRxrLRpcyPqGceRBDpxxUV8vcDqIKxAUKfcnFpcrPxT5+XvhTxv7XLjo5AvEJFPdAE3zCogG2JVahqgSQ==
dependencies:
- cacache "^15.0.5"
- fast-glob "^3.2.4"
- find-cache-dir "^3.3.1"
+ fast-glob "^3.2.5"
glob-parent "^5.1.1"
- globby "^11.0.1"
- loader-utils "^2.0.0"
+ globby "^11.0.3"
normalize-path "^3.0.0"
- p-limit "^3.0.2"
+ p-limit "^3.1.0"
schema-utils "^3.0.0"
serialize-javascript "^5.0.1"
- webpack-sources "^1.4.3"
core-js-compat@^3.8.1, core-js-compat@^3.9.0:
version "3.9.1"
@@ -3262,16 +2945,6 @@ core-util-is@~1.0.0:
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
-cosmiconfig@^5.0.0:
- version "5.2.1"
- resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a"
- integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==
- dependencies:
- import-fresh "^2.0.0"
- is-directory "^0.3.1"
- js-yaml "^3.13.1"
- parse-json "^4.0.0"
-
cosmiconfig@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.0.0.tgz#ef9b44d773959cae63ddecd122de23853b60f8d3"
@@ -3283,37 +2956,6 @@ cosmiconfig@^7.0.0:
path-type "^4.0.0"
yaml "^1.10.0"
-create-ecdh@^4.0.0:
- version "4.0.4"
- resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e"
- integrity sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==
- dependencies:
- bn.js "^4.1.0"
- elliptic "^6.5.3"
-
-create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196"
- integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==
- dependencies:
- cipher-base "^1.0.1"
- inherits "^2.0.1"
- md5.js "^1.3.4"
- ripemd160 "^2.0.1"
- sha.js "^2.4.0"
-
-create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7:
- version "1.1.7"
- resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff"
- integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==
- dependencies:
- cipher-base "^1.0.3"
- create-hash "^1.1.0"
- inherits "^2.0.1"
- ripemd160 "^2.0.0"
- safe-buffer "^5.0.1"
- sha.js "^2.4.8"
-
cross-fetch@^3.0.4:
version "3.1.2"
resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.2.tgz#ee0c2f18844c4fde36150c2a4ddc068d20c1bc41"
@@ -3341,55 +2983,27 @@ cross-spawn@^6.0.0:
shebang-command "^1.2.0"
which "^1.2.9"
-crypto-browserify@^3.11.0:
- version "3.12.0"
- resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec"
- integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==
- dependencies:
- browserify-cipher "^1.0.0"
- browserify-sign "^4.0.0"
- create-ecdh "^4.0.0"
- create-hash "^1.1.0"
- create-hmac "^1.1.0"
- diffie-hellman "^5.0.0"
- inherits "^2.0.1"
- pbkdf2 "^3.0.3"
- public-encrypt "^4.0.0"
- randombytes "^2.0.0"
- randomfill "^1.0.3"
-
crypto-random-string@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5"
integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==
-css-blank-pseudo@^0.1.4:
- version "0.1.4"
- resolved "https://registry.yarnpkg.com/css-blank-pseudo/-/css-blank-pseudo-0.1.4.tgz#dfdefd3254bf8a82027993674ccf35483bfcb3c5"
- integrity sha512-LHz35Hr83dnFeipc7oqFDmsjHdljj3TQtxGGiNWSOsTLIAubSm4TEz8qCaKFpk7idaQ1GfWscF4E6mgpBysA1w==
- dependencies:
- postcss "^7.0.5"
-
-css-color-names@0.0.4, css-color-names@^0.0.4:
+css-color-names@^0.0.4:
version "0.0.4"
resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0"
integrity sha1-gIrcLnnPhHOAabZGyyDsJ762KeA=
-css-declaration-sorter@^4.0.1:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-4.0.1.tgz#c198940f63a76d7e36c1e71018b001721054cb22"
- integrity sha512-BcxQSKTSEEQUftYpBVnsH4SF05NTuBokb19/sBt6asXGKZ/6VP7PLG1CBCkFDYOnhXhPh0jMhO6xZ71oYHXHBA==
- dependencies:
- postcss "^7.0.1"
- timsort "^0.3.0"
+css-color-names@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-1.0.1.tgz#6ff7ee81a823ad46e020fa2fd6ab40a887e2ba67"
+ integrity sha512-/loXYOch1qU1biStIFsHH8SxTmOseh1IJqFvy8IujXOm1h+QjUdDhkzOrR5HG8K8mlxREj0yfi8ewCHx0eMxzA==
-css-has-pseudo@^0.10.0:
- version "0.10.0"
- resolved "https://registry.yarnpkg.com/css-has-pseudo/-/css-has-pseudo-0.10.0.tgz#3c642ab34ca242c59c41a125df9105841f6966ee"
- integrity sha512-Z8hnfsZu4o/kt+AuFzeGpLVhFOGO9mluyHBaA2bA8aCGTwah5sT3WV/fTHH8UNZUytOIImuGPrl/prlb4oX4qQ==
+css-declaration-sorter@6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-6.0.0.tgz#eb21f75860078627e9e3cc6f5535ccfcea445817"
+ integrity sha512-S0TE4E0ha5+tBHdLWPc5n+S8E4dFBS5xScPvgHkLNZwWvX4ISoFGhGeerLC9uS1cKA/sC+K2wHq6qEbcagT/fg==
dependencies:
- postcss "^7.0.6"
- postcss-selector-parser "^5.0.0-rc.4"
+ timsort "^0.3.0"
css-loader@^5.1.1:
version "5.1.4"
@@ -3409,12 +3023,18 @@ css-loader@^5.1.1:
schema-utils "^3.0.0"
semver "^7.3.4"
-css-prefers-color-scheme@^3.1.1:
- version "3.1.1"
- resolved "https://registry.yarnpkg.com/css-prefers-color-scheme/-/css-prefers-color-scheme-3.1.1.tgz#6f830a2714199d4f0d0d0bb8a27916ed65cff1f4"
- integrity sha512-MTu6+tMs9S3EUqzmqLXEcgNRbNkkD/TGFvowpeoWJn5Vfq7FMgsmRQs9X5NXAURiOBmOxm/lLjsDNXDE6k9bhg==
+css-minimizer-webpack-plugin@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-2.0.0.tgz#3c42f6624ed4cf4780dd963e23ee649e5a25c1a8"
+ integrity sha512-cG/uc94727tx5pBNtb1Sd7gvUPzwmcQi1lkpfqTpdkuNq75hJCw7bIVsCNijLm4dhDcr1atvuysl2rZqOG8Txw==
dependencies:
- postcss "^7.0.5"
+ cssnano "^5.0.0"
+ jest-worker "^26.3.0"
+ p-limit "^3.0.2"
+ postcss "^8.2.9"
+ schema-utils "^3.0.0"
+ serialize-javascript "^5.0.1"
+ source-map "^0.6.1"
css-select-base-adapter@^0.1.1:
version "0.1.1"
@@ -3431,6 +3051,17 @@ css-select@^2.0.0, css-select@^2.0.2:
domutils "^1.7.0"
nth-check "^1.0.2"
+css-select@^3.1.2:
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/css-select/-/css-select-3.1.2.tgz#d52cbdc6fee379fba97fb0d3925abbd18af2d9d8"
+ integrity sha512-qmss1EihSuBNWNNhHjxzxSfJoFBM/lERB/Q4EnsJQQC62R2evJDW481091oAdOr9uh46/0n4nrg0It5cAnj1RA==
+ dependencies:
+ boolbase "^1.0.0"
+ css-what "^4.0.0"
+ domhandler "^4.0.0"
+ domutils "^2.4.3"
+ nth-check "^2.0.0"
+
css-select@~1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.2.0.tgz#2b3a110539c5355f1cd8d314623e870b121ec858"
@@ -3467,118 +3098,84 @@ css-what@^3.2.1:
resolved "https://registry.yarnpkg.com/css-what/-/css-what-3.4.2.tgz#ea7026fcb01777edbde52124e21f327e7ae950e4"
integrity sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ==
-cssdb@^4.4.0:
- version "4.4.0"
- resolved "https://registry.yarnpkg.com/cssdb/-/cssdb-4.4.0.tgz#3bf2f2a68c10f5c6a08abd92378331ee803cddb0"
- integrity sha512-LsTAR1JPEM9TpGhl/0p3nQecC2LJ0kD8X5YARu1hk/9I1gril5vDtMZyNxcEpxxDj34YNck/ucjuoUd66K03oQ==
-
-cssesc@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-2.0.0.tgz#3b13bd1bb1cb36e1bcb5a4dcd27f54c5dcb35703"
- integrity sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==
+css-what@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/css-what/-/css-what-4.0.0.tgz#35e73761cab2eeb3d3661126b23d7aa0e8432233"
+ integrity sha512-teijzG7kwYfNVsUh2H/YN62xW3KK9YhXEgSlbxMlcyjPNvdKJqFx5lrwlJgoFP1ZHlB89iGDlo/JyshKeRhv5A==
cssesc@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee"
integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==
-cssnano-preset-advanced@^4.0.7:
- version "4.0.7"
- resolved "https://registry.yarnpkg.com/cssnano-preset-advanced/-/cssnano-preset-advanced-4.0.7.tgz#d981527b77712e2f3f3f09c73313e9b71b278b88"
- integrity sha512-j1O5/DQnaAqEyFFQfC+Z/vRlLXL3LxJHN+lvsfYqr7KgPH74t69+Rsy2yXkovWNaJjZYBpdz2Fj8ab2nH7pZXw==
+cssnano-preset-advanced@^5.0.0:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/cssnano-preset-advanced/-/cssnano-preset-advanced-5.0.1.tgz#b551bb9ad3abf7a9a79f0cace3bf50264018df64"
+ integrity sha512-g+LB6GcihLXcBEdDh+mzk1qX9jgtBkVpzAg1OlgrH6C+qKIQYRHwAPyaoXy95Ci83sYYXlwJ0OrqLYTIUEBLZQ==
dependencies:
- autoprefixer "^9.4.7"
- cssnano-preset-default "^4.0.7"
- postcss-discard-unused "^4.0.1"
- postcss-merge-idents "^4.0.1"
- postcss-reduce-idents "^4.0.2"
- postcss-zindex "^4.0.1"
+ autoprefixer "^10.0.2"
+ cssnano-preset-default "^5.0.1"
+ postcss-discard-unused "^5.0.0"
+ postcss-merge-idents "^5.0.0"
+ postcss-reduce-idents "^5.0.0"
+ postcss-zindex "^5.0.0"
-cssnano-preset-default@^4.0.7:
- version "4.0.7"
- resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-4.0.7.tgz#51ec662ccfca0f88b396dcd9679cdb931be17f76"
- integrity sha512-x0YHHx2h6p0fCl1zY9L9roD7rnlltugGu7zXSKQx6k2rYw0Hi3IqxcoAGF7u9Q5w1nt7vK0ulxV8Lo+EvllGsA==
+cssnano-preset-default@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-5.0.1.tgz#76adc00f7aae36ae80552b8356e21bec4b233ca2"
+ integrity sha512-cfmfThYODGqhpQKDq9H0MTAqkMvZ3dGbOUTBKw0xWZiIycMqHid22LsJXJl4r1qX4qzDeKxcSyQ/Xb5Mu3Z//Q==
dependencies:
- css-declaration-sorter "^4.0.1"
- cssnano-util-raw-cache "^4.0.1"
- postcss "^7.0.0"
- postcss-calc "^7.0.1"
- postcss-colormin "^4.0.3"
- postcss-convert-values "^4.0.1"
- postcss-discard-comments "^4.0.2"
- postcss-discard-duplicates "^4.0.2"
- postcss-discard-empty "^4.0.1"
- postcss-discard-overridden "^4.0.1"
- postcss-merge-longhand "^4.0.11"
- postcss-merge-rules "^4.0.3"
- postcss-minify-font-values "^4.0.2"
- postcss-minify-gradients "^4.0.2"
- postcss-minify-params "^4.0.2"
- postcss-minify-selectors "^4.0.2"
- postcss-normalize-charset "^4.0.1"
- postcss-normalize-display-values "^4.0.2"
- postcss-normalize-positions "^4.0.2"
- postcss-normalize-repeat-style "^4.0.2"
- postcss-normalize-string "^4.0.2"
- postcss-normalize-timing-functions "^4.0.2"
- postcss-normalize-unicode "^4.0.1"
- postcss-normalize-url "^4.0.1"
- postcss-normalize-whitespace "^4.0.2"
- postcss-ordered-values "^4.1.2"
- postcss-reduce-initial "^4.0.3"
- postcss-reduce-transforms "^4.0.2"
- postcss-svgo "^4.0.2"
- postcss-unique-selectors "^4.0.1"
+ css-declaration-sorter "6.0.0"
+ cssnano-utils "^2.0.0"
+ postcss-calc "^8.0.0"
+ postcss-colormin "^5.0.0"
+ postcss-convert-values "^5.0.0"
+ postcss-discard-comments "^5.0.0"
+ postcss-discard-duplicates "^5.0.0"
+ postcss-discard-empty "^5.0.0"
+ postcss-discard-overridden "^5.0.0"
+ postcss-merge-longhand "^5.0.1"
+ postcss-merge-rules "^5.0.0"
+ postcss-minify-font-values "^5.0.0"
+ postcss-minify-gradients "^5.0.0"
+ postcss-minify-params "^5.0.0"
+ postcss-minify-selectors "^5.0.0"
+ postcss-normalize-charset "^5.0.0"
+ postcss-normalize-display-values "^5.0.0"
+ postcss-normalize-positions "^5.0.0"
+ postcss-normalize-repeat-style "^5.0.0"
+ postcss-normalize-string "^5.0.0"
+ postcss-normalize-timing-functions "^5.0.0"
+ postcss-normalize-unicode "^5.0.0"
+ postcss-normalize-url "^5.0.0"
+ postcss-normalize-whitespace "^5.0.0"
+ postcss-ordered-values "^5.0.0"
+ postcss-reduce-initial "^5.0.0"
+ postcss-reduce-transforms "^5.0.0"
+ postcss-svgo "^5.0.0"
+ postcss-unique-selectors "^5.0.0"
-cssnano-util-get-arguments@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/cssnano-util-get-arguments/-/cssnano-util-get-arguments-4.0.0.tgz#ed3a08299f21d75741b20f3b81f194ed49cc150f"
- integrity sha1-7ToIKZ8h11dBsg87gfGU7UnMFQ8=
+cssnano-utils@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/cssnano-utils/-/cssnano-utils-2.0.0.tgz#b04baaa312aa3dd5a854b7f61d76b9d94be07f74"
+ integrity sha512-xvxmTszdrvSyTACdPe8VU5J6p4sm3egpgw54dILvNqt5eBUv6TFjACLhSxtRuEsxYrgy8uDy269YjScO5aKbGA==
-cssnano-util-get-match@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/cssnano-util-get-match/-/cssnano-util-get-match-4.0.0.tgz#c0e4ca07f5386bb17ec5e52250b4f5961365156d"
- integrity sha1-wOTKB/U4a7F+xeUiULT1lhNlFW0=
-
-cssnano-util-raw-cache@^4.0.1:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/cssnano-util-raw-cache/-/cssnano-util-raw-cache-4.0.1.tgz#b26d5fd5f72a11dfe7a7846fb4c67260f96bf282"
- integrity sha512-qLuYtWK2b2Dy55I8ZX3ky1Z16WYsx544Q0UWViebptpwn/xDBmog2TLg4f+DBMg1rJ6JDWtn96WHbOKDWt1WQA==
+cssnano@^5.0.0, cssnano@^5.0.1:
+ version "5.0.2"
+ resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-5.0.2.tgz#3f6de4fd5ecb7b5fb636c1a606de5f38cd241493"
+ integrity sha512-8JK3EnPsjQsULme9/e5M2hF564f/480hwsdcHvQ7ZtAIMfQ1O3SCfs+b8Mjf5KJxhYApyRshR2QSovEJi2K72Q==
dependencies:
- postcss "^7.0.0"
+ cosmiconfig "^7.0.0"
+ cssnano-preset-default "^5.0.1"
+ is-resolvable "^1.1.0"
-cssnano-util-same-parent@^4.0.0:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/cssnano-util-same-parent/-/cssnano-util-same-parent-4.0.1.tgz#574082fb2859d2db433855835d9a8456ea18bbf3"
- integrity sha512-WcKx5OY+KoSIAxBW6UBBRay1U6vkYheCdjyVNDm85zt5K9mHoGOfsOsqIszfAqrQQFIIKgjh2+FDgIj/zsl21Q==
-
-cssnano@^4.1.10:
- version "4.1.10"
- resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-4.1.10.tgz#0ac41f0b13d13d465487e111b778d42da631b8b2"
- integrity sha512-5wny+F6H4/8RgNlaqab4ktc3e0/blKutmq8yNlBFXA//nSFFAqAngjNVRzUvCgYROULmZZUoosL/KSoZo5aUaQ==
- dependencies:
- cosmiconfig "^5.0.0"
- cssnano-preset-default "^4.0.7"
- is-resolvable "^1.0.0"
- postcss "^7.0.0"
-
-csso@^4.0.2:
+csso@^4.0.2, csso@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/csso/-/csso-4.2.0.tgz#ea3a561346e8dc9f546d6febedd50187cf389529"
integrity sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==
dependencies:
css-tree "^1.1.2"
-csstype@^3.0.2:
- version "3.0.7"
- resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.7.tgz#2a5fb75e1015e84dd15692f71e89a1450290950b"
- integrity sha512-KxnUB0ZMlnUWCsx2Z8MUsr6qV6ja1w9ArPErJaJaF8a5SOWoHLIszeCTKGRGRgtLgYrs1E8CHkNSP1VZTTPc9g==
-
-cyclist@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9"
- integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=
-
debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0:
version "2.6.9"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
@@ -3657,7 +3254,7 @@ defer-to-connect@^1.0.1:
resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591"
integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==
-define-properties@^1.1.2, define-properties@^1.1.3:
+define-properties@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1"
integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==
@@ -3723,14 +3320,6 @@ depd@~1.1.2:
resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=
-des.js@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843"
- integrity sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==
- dependencies:
- inherits "^2.0.1"
- minimalistic-assert "^1.0.0"
-
destroy@~1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
@@ -3764,15 +3353,6 @@ detect-port@^1.3.0:
address "^1.0.1"
debug "^2.6.0"
-diffie-hellman@^5.0.0:
- version "5.0.3"
- resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875"
- integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==
- dependencies:
- bn.js "^4.1.0"
- miller-rabin "^4.0.0"
- randombytes "^2.0.0"
-
dir-glob@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f"
@@ -3786,9 +3366,9 @@ dns-equal@^1.0.0:
integrity sha1-s55/HabrCnW6nBcySzR1PEfgZU0=
dns-packet@^1.3.1:
- version "1.3.1"
- resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-1.3.1.tgz#12aa426981075be500b910eedcd0b47dd7deda5a"
- integrity sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg==
+ version "1.3.4"
+ resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-1.3.4.tgz#e3455065824a2507ba886c55a89963bb107dec6f"
+ integrity sha512-BQ6F4vycLXBvdrJZ6S3gZewt6rcrks9KBgM9vrhW+knGRqc8uEdT7fuCwloc7nny5xNoMJ17HGH0R/6fpo8ECA==
dependencies:
ip "^1.1.0"
safe-buffer "^5.0.1"
@@ -3815,6 +3395,15 @@ dom-serializer@0:
domelementtype "^2.0.1"
entities "^2.0.0"
+dom-serializer@^1.0.1:
+ version "1.3.2"
+ resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.3.2.tgz#6206437d32ceefaec7161803230c7a20bc1b4d91"
+ integrity sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==
+ dependencies:
+ domelementtype "^2.0.1"
+ domhandler "^4.2.0"
+ entities "^2.0.0"
+
dom-serializer@~0.1.0:
version "0.1.1"
resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.1.tgz#1ec4059e284babed36eec2941d4a970a189ce7c0"
@@ -3823,11 +3412,6 @@ dom-serializer@~0.1.0:
domelementtype "^1.3.0"
entities "^1.1.1"
-domain-browser@^1.1.1:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda"
- integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==
-
domelementtype@1, domelementtype@^1.3.0, domelementtype@^1.3.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f"
@@ -3838,6 +3422,11 @@ domelementtype@^2.0.1:
resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.1.0.tgz#a851c080a6d1c3d94344aed151d99f669edf585e"
integrity sha512-LsTgx/L5VpD+Q8lmsXSHW2WpA+eBlZ9HPf3erD1IoPF00/3JKHZ3BknUVA2QGDNu69ZNmyFmCWBSO45XjYKC5w==
+domelementtype@^2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.2.0.tgz#9a0b6c2782ed6a1c7323d42267183df9bd8b1d57"
+ integrity sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==
+
domhandler@^2.3.0:
version "2.4.2"
resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803"
@@ -3845,6 +3434,13 @@ domhandler@^2.3.0:
dependencies:
domelementtype "1"
+domhandler@^4.0.0, domhandler@^4.2.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.2.0.tgz#f9768a5f034be60a89a27c2e4d0f74eba0d8b059"
+ integrity sha512-zk7sgt970kzPks2Bf+dwT/PLzghLnsivb9CcxkvR8Mzr66Olr0Ofd8neSbglHJHaHa2MadfoSdNlKYAaafmWfA==
+ dependencies:
+ domelementtype "^2.2.0"
+
domutils@1.5.1:
version "1.5.1"
resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf"
@@ -3861,6 +3457,15 @@ domutils@^1.5.1, domutils@^1.7.0:
dom-serializer "0"
domelementtype "1"
+domutils@^2.4.3:
+ version "2.6.0"
+ resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.6.0.tgz#2e15c04185d43fb16ae7057cb76433c6edb938b7"
+ integrity sha512-y0BezHuy4MDYxh6OvolXYsH+1EMGmFbwv5FKW7ovwMG6zTPWqNPq3WF9ayZssFq+UlKdffGLbOEaghNdaOm1WA==
+ dependencies:
+ dom-serializer "^1.0.1"
+ domelementtype "^2.2.0"
+ domhandler "^4.2.0"
+
dot-case@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.4.tgz#9b2b670d00a431667a8a75ba29cd1b98809ce751"
@@ -3886,16 +3491,6 @@ duplexer@^0.1.1, duplexer@^0.1.2:
resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6"
integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==
-duplexify@^3.4.2, duplexify@^3.6.0:
- version "3.7.1"
- resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309"
- integrity sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==
- dependencies:
- end-of-stream "^1.0.0"
- inherits "^2.0.1"
- readable-stream "^2.0.0"
- stream-shift "^1.0.0"
-
ee-first@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
@@ -3906,18 +3501,10 @@ electron-to-chromium@^1.3.564, electron-to-chromium@^1.3.649:
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.698.tgz#5de813960f23581a268718a0058683dffa15d221"
integrity sha512-VEXDzYblnlT+g8Q3gedwzgKOso1evkeJzV8lih7lV8mL8eAnGVnKyC3KsFT6S+R5PQO4ffdr1PI16/ElibY/kQ==
-elliptic@^6.5.3:
- version "6.5.4"
- resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb"
- integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==
- dependencies:
- bn.js "^4.11.9"
- brorand "^1.1.0"
- hash.js "^1.0.0"
- hmac-drbg "^1.0.1"
- inherits "^2.0.4"
- minimalistic-assert "^1.0.1"
- minimalistic-crypto-utils "^1.0.1"
+electron-to-chromium@^1.3.723:
+ version "1.3.732"
+ resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.732.tgz#2a07a8d61f74f2084b6f6bf2a908605a7a0b2d8d"
+ integrity sha512-qKD5Pbq+QMk4nea4lMuncUMhpEiQwaJyCW7MrvissnRcBDENhVfDmAqQYRQ3X525oTzhar9Zh1cK0L2d1UKYcw==
"emoji-regex@>=6.0.0 <=6.1.1":
version "6.1.1"
@@ -3949,21 +3536,20 @@ encodeurl@~1.0.2:
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=
-end-of-stream@^1.0.0, end-of-stream@^1.1.0:
+end-of-stream@^1.1.0:
version "1.4.4"
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==
dependencies:
once "^1.4.0"
-enhanced-resolve@^4.5.0:
- version "4.5.0"
- resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz#2f3cfd84dbe3b487f18f2db2ef1e064a571ca5ec"
- integrity sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==
+enhanced-resolve@^5.8.0:
+ version "5.8.2"
+ resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.8.2.tgz#15ddc779345cbb73e97c611cd00c01c1e7bf4d8b"
+ integrity sha512-F27oB3WuHDzvR2DOGNTaYy0D5o0cnrv8TeI482VM4kYgQd/FT9lUQwuNsJ0oOHtBUq7eiW5ytqzp7nBFknL+GA==
dependencies:
- graceful-fs "^4.1.2"
- memory-fs "^0.5.0"
- tapable "^1.0.0"
+ graceful-fs "^4.2.4"
+ tapable "^2.2.0"
entities@^1.1.1, entities@~1.1.1:
version "1.1.2"
@@ -3975,7 +3561,7 @@ entities@^2.0.0:
resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55"
integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==
-errno@^0.1.3, errno@~0.1.7:
+errno@^0.1.3:
version "0.1.8"
resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.8.tgz#8bb3e9c7d463be4976ff888f76b4809ebc2e811f"
integrity sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==
@@ -4011,6 +3597,11 @@ es-abstract@^1.17.2, es-abstract@^1.18.0-next.2:
string.prototype.trimstart "^1.0.4"
unbox-primitive "^1.0.0"
+es-module-lexer@^0.4.0:
+ version "0.4.1"
+ resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.4.1.tgz#dda8c6a14d8f340a24e34331e0fab0cb50438e0e"
+ integrity sha512-ooYciCUtfw6/d2w56UVeqHPcoCFAiJdz5XOkYpv/Txl1HMUozpXjz/2RIQgqwKdXNDPSF1W7mJCFse3G+HDyAA==
+
es-to-primitive@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a"
@@ -4050,12 +3641,12 @@ escape-string-regexp@^4.0.0:
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34"
integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
-eslint-scope@^4.0.3:
- version "4.0.3"
- resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848"
- integrity sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==
+eslint-scope@^5.1.1:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c"
+ integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==
dependencies:
- esrecurse "^4.1.0"
+ esrecurse "^4.3.0"
estraverse "^4.1.1"
esprima@^4.0.0:
@@ -4063,7 +3654,7 @@ esprima@^4.0.0:
resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==
-esrecurse@^4.1.0:
+esrecurse@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921"
integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==
@@ -4112,7 +3703,7 @@ events@^1.1.1:
resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924"
integrity sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=
-events@^3.0.0:
+events@^3.2.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400"
integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==
@@ -4124,14 +3715,6 @@ eventsource@^1.0.7:
dependencies:
original "^1.0.0"
-evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02"
- integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==
- dependencies:
- md5.js "^1.3.4"
- safe-buffer "^5.1.1"
-
execa@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8"
@@ -4248,7 +3831,7 @@ fast-deep-equal@^3.1.1:
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
-fast-glob@^3.1.1, fast-glob@^3.2.4:
+fast-glob@^3.1.1, fast-glob@^3.2.5:
version "3.2.5"
resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.5.tgz#7939af2a656de79a4f1901903ee8adcaa7cb9661"
integrity sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==
@@ -4318,11 +3901,6 @@ feed@^4.2.2:
dependencies:
xml-js "^1.6.11"
-figgy-pudding@^3.5.1:
- version "3.5.2"
- resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.2.tgz#b4eee8148abb01dcf1d1ac34367d59e12fa61d6e"
- integrity sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==
-
figures@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af"
@@ -4378,16 +3956,7 @@ finalhandler@~1.1.2:
statuses "~1.5.0"
unpipe "~1.0.0"
-find-cache-dir@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7"
- integrity sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==
- dependencies:
- commondir "^1.0.1"
- make-dir "^2.0.0"
- pkg-dir "^3.0.0"
-
-find-cache-dir@^3.0.0, find-cache-dir@^3.3.1:
+find-cache-dir@^3.3.1:
version "3.3.1"
resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.1.tgz#89b33fad4a4670daa94f855f7fbe31d6d84fe880"
integrity sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==
@@ -4411,18 +3980,13 @@ find-up@^3.0.0:
dependencies:
locate-path "^3.0.0"
-flatten@^1.0.2:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.3.tgz#c1283ac9f27b368abc1e36d1ff7b04501a30356b"
- integrity sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg==
-
-flush-write-stream@^1.0.0:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.1.1.tgz#8dd7d873a1babc207d94ead0c2e0e44276ebf2e8"
- integrity sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==
+find-up@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc"
+ integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==
dependencies:
- inherits "^2.0.3"
- readable-stream "^2.3.6"
+ locate-path "^6.0.0"
+ path-exists "^4.0.0"
flux@^4.0.1:
version "4.0.1"
@@ -4477,14 +4041,6 @@ fresh@0.5.2:
resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=
-from2@^2.1.0:
- version "2.3.0"
- resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af"
- integrity sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=
- dependencies:
- inherits "^2.0.1"
- readable-stream "^2.0.0"
-
fs-extra@^9.1.0:
version "9.1.0"
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d"
@@ -4495,23 +4051,6 @@ fs-extra@^9.1.0:
jsonfile "^6.0.1"
universalify "^2.0.0"
-fs-minipass@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb"
- integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==
- dependencies:
- minipass "^3.0.0"
-
-fs-write-stream-atomic@^1.0.8:
- version "1.0.10"
- resolved "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9"
- integrity sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=
- dependencies:
- graceful-fs "^4.1.2"
- iferr "^0.1.5"
- imurmurhash "^0.1.4"
- readable-stream "1 || 2"
-
fs.realpath@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
@@ -4605,7 +4144,12 @@ glob-parent@^5.1.0, glob-parent@^5.1.1, glob-parent@~5.1.0:
dependencies:
is-glob "^4.0.1"
-glob@^7.0.0, glob@^7.0.3, glob@^7.1.3, glob@^7.1.4:
+glob-to-regexp@^0.4.1:
+ version "0.4.1"
+ resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e"
+ integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==
+
+glob@^7.0.0, glob@^7.0.3, glob@^7.1.3:
version "7.1.6"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6"
integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==
@@ -4657,7 +4201,7 @@ globby@11.0.1:
merge2 "^1.3.0"
slash "^3.0.0"
-globby@^11.0.1, globby@^11.0.2:
+globby@^11.0.1, globby@^11.0.2, globby@^11.0.3:
version "11.0.3"
resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.3.tgz#9b1f0cb523e171dd1ad8c7b2a9fb4b644b9593cb"
integrity sha512-ffdmosjA807y7+lA1NM0jELARVmYul/715xiILEjo3hBLPTcirgQNnXECn5g3mtR8TOLCVbkfua1Hpen25/Xcg==
@@ -4704,7 +4248,7 @@ got@^9.6.0:
to-readable-stream "^1.0.0"
url-parse-lax "^3.0.0"
-graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4:
+graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4:
version "4.2.6"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.6.tgz#ff040b2b0853b23c3d31027523706f1885d76bee"
integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==
@@ -4795,30 +4339,13 @@ has-yarn@^2.1.0:
resolved "https://registry.yarnpkg.com/has-yarn/-/has-yarn-2.1.0.tgz#137e11354a7b5bf11aa5cb649cf0c6f3ff2b2e77"
integrity sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==
-has@^1.0.0, has@^1.0.3:
+has@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
dependencies:
function-bind "^1.1.1"
-hash-base@^3.0.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33"
- integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==
- dependencies:
- inherits "^2.0.4"
- readable-stream "^3.6.0"
- safe-buffer "^5.2.0"
-
-hash.js@^1.0.0, hash.js@^1.0.3:
- version "1.1.7"
- resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42"
- integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==
- dependencies:
- inherits "^2.0.3"
- minimalistic-assert "^1.0.1"
-
hast-to-hyperscript@^9.0.0:
version "9.0.1"
resolved "https://registry.yarnpkg.com/hast-to-hyperscript/-/hast-to-hyperscript-9.0.1.tgz#9b67fd188e4c81e8ad66f803855334173920218d"
@@ -4930,15 +4457,6 @@ history@^4.9.0:
tiny-warning "^1.0.0"
value-equal "^1.0.1"
-hmac-drbg@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1"
- integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=
- dependencies:
- hash.js "^1.0.3"
- minimalistic-assert "^1.0.0"
- minimalistic-crypto-utils "^1.0.1"
-
hoist-non-react-statics@^3.1.0:
version "3.3.2"
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
@@ -4966,11 +4484,6 @@ hsla-regex@^1.0.0:
resolved "https://registry.yarnpkg.com/hsla-regex/-/hsla-regex-1.0.0.tgz#c1ce7a3168c8c6614033a4b5f7877f3b225f9c38"
integrity sha1-wc56MWjIxmFAM6S194d/OyJfnDg=
-html-comment-regex@^1.1.0:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/html-comment-regex/-/html-comment-regex-1.1.2.tgz#97d4688aeb5c81886a364faa0cad1dda14d433a7"
- integrity sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ==
-
html-entities@^1.3.1:
version "1.4.0"
resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.4.0.tgz#cfbd1b01d2afaf9adca1b10ae7dffab98c71d2dc"
@@ -4999,20 +4512,16 @@ html-void-elements@^1.0.0:
resolved "https://registry.yarnpkg.com/html-void-elements/-/html-void-elements-1.0.5.tgz#ce9159494e86d95e45795b166c2021c2cfca4483"
integrity sha512-uE/TxKuyNIcx44cIWnjr/rfIATDH7ZaOMmstu0CwhFG1Dunhlp4OC6/NMbhiwoq5BpW0ubi303qnEk/PZj614w==
-html-webpack-plugin@^4.5.0:
- version "4.5.2"
- resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-4.5.2.tgz#76fc83fa1a0f12dd5f7da0404a54e2699666bc12"
- integrity sha512-q5oYdzjKUIPQVjOosjgvCHQOv9Ett9CYYHlgvJeXG0qQvdSojnBq4vAdQBwn1+yGveAwHCoe/rMR86ozX3+c2A==
+html-webpack-plugin@^5.2.0:
+ version "5.3.1"
+ resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-5.3.1.tgz#8797327548e3de438e3494e0c6d06f181a7f20d1"
+ integrity sha512-rZsVvPXUYFyME0cuGkyOHfx9hmkFa4pWfxY/mdY38PsBEaVNsRoA+Id+8z6DBDgyv3zaw6XQszdF8HLwfQvcdQ==
dependencies:
"@types/html-minifier-terser" "^5.0.0"
- "@types/tapable" "^1.0.5"
- "@types/webpack" "^4.41.8"
html-minifier-terser "^5.0.1"
- loader-utils "^1.2.3"
lodash "^4.17.20"
pretty-error "^2.1.1"
- tapable "^1.1.3"
- util.promisify "1.0.0"
+ tapable "^2.0.0"
htmlparser2@^3.10.1, htmlparser2@^3.9.1:
version "3.10.1"
@@ -5092,11 +4601,6 @@ http-proxy@^1.17.0:
follow-redirects "^1.0.0"
requires-port "^1.0.0"
-https-browserify@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73"
- integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=
-
human-signals@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0"
@@ -5114,16 +4618,6 @@ icss-utils@^5.0.0, icss-utils@^5.1.0:
resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae"
integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==
-ieee754@^1.1.4:
- version "1.2.1"
- resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
- integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
-
-iferr@^0.1.5:
- version "0.1.5"
- resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501"
- integrity sha1-xg7taebY/bazEEofy8ocGS3FtQE=
-
ignore@^5.1.4:
version "5.1.8"
resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57"
@@ -5134,14 +4628,6 @@ immer@8.0.1:
resolved "https://registry.yarnpkg.com/immer/-/immer-8.0.1.tgz#9c73db683e2b3975c424fb0572af5889877ae656"
integrity sha512-aqXhGP7//Gui2+UrEtvxZxSquQVXTpZ7KDxfCcKAF3Vysvw0CViVaW9RZ1j1xlIYqaaaipBoqdqeibkc18PNvA==
-import-fresh@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546"
- integrity sha1-2BNVwVYS04bGH53dOSLUMEgipUY=
- dependencies:
- caller-path "^2.0.0"
- resolve-from "^3.0.0"
-
import-fresh@^3.2.1, import-fresh@^3.2.2, import-fresh@^3.3.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b"
@@ -5178,15 +4664,10 @@ indexes-of@^1.0.1:
resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607"
integrity sha1-8w9xbI4r00bHtn0985FVZqfAVgc=
-infer-owner@^1.0.3, infer-owner@^1.0.4:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467"
- integrity sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==
-
-infima@0.2.0-alpha.21:
- version "0.2.0-alpha.21"
- resolved "https://registry.yarnpkg.com/infima/-/infima-0.2.0-alpha.21.tgz#53cc49dbcaf5a8d165cbe4acf214eee02bca6154"
- integrity sha512-32uq+rWIrLNZx0jzNrwJWE8Go9NvpP0JTRKMXJ8aYlWZ0vm9OCgAEcVquwFBSW6ZP7R2rjBUjPy/nJ3PK7MhUA==
+infima@0.2.0-alpha.23:
+ version "0.2.0-alpha.23"
+ resolved "https://registry.yarnpkg.com/infima/-/infima-0.2.0-alpha.23.tgz#2c17b473784ae8244fd985f126f9c27a49b24523"
+ integrity sha512-V0RTjB1otjpH3E2asbydx3gz7ovdSJsuV7r9JTdBggqRilnelTJUcXxLawBQQKsjQi5qPcRTjxnlaV8xyyKhhw==
inflight@^1.0.4:
version "1.0.6"
@@ -5196,16 +4677,11 @@ inflight@^1.0.4:
once "^1.3.0"
wrappy "1"
-inherits@2, inherits@2.0.4, inherits@^2.0.0, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3:
+inherits@2, inherits@2.0.4, inherits@^2.0.0, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3:
version "2.0.4"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
-inherits@2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1"
- integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=
-
inherits@2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
@@ -5254,11 +4730,6 @@ ipaddr.js@1.9.1, ipaddr.js@^1.9.0:
resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3"
integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==
-is-absolute-url@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-2.1.0.tgz#50530dfb84fcc9aa7dbe7852e83a37b93b9f2aa6"
- integrity sha1-UFMN+4T8yap9vnhS6Do3uTufKqY=
-
is-absolute-url@^3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-3.0.3.tgz#96c6a22b6a23929b11ea0afb1836c36ad4a5d698"
@@ -5356,7 +4827,7 @@ is-ci@^2.0.0:
dependencies:
ci-info "^2.0.0"
-is-color-stop@^1.0.0:
+is-color-stop@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-color-stop/-/is-color-stop-1.1.0.tgz#cfff471aee4dd5c9e158598fbe12967b5cdad345"
integrity sha1-z/9HGu5N1cnhWFmPvhKWe1za00U=
@@ -5417,11 +4888,6 @@ is-descriptor@^1.0.0, is-descriptor@^1.0.2:
is-data-descriptor "^1.0.0"
kind-of "^6.0.2"
-is-directory@^0.3.1:
- version "0.3.1"
- resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1"
- integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=
-
is-docker@^2.0.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.1.1.tgz#4125a88e44e450d384e09047ede71adc2d144156"
@@ -5542,11 +5008,6 @@ is-path-inside@^3.0.2:
resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283"
integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==
-is-plain-obj@^1.0.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e"
- integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4=
-
is-plain-obj@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287"
@@ -5572,7 +5033,7 @@ is-regexp@^1.0.0:
resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069"
integrity sha1-/S2INUXEa6xaYz57mgnof6LLUGk=
-is-resolvable@^1.0.0:
+is-resolvable@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88"
integrity sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==
@@ -5597,13 +5058,6 @@ is-string@^1.0.5:
resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.5.tgz#40493ed198ef3ff477b8c7f92f644ec82a5cd3a6"
integrity sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==
-is-svg@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/is-svg/-/is-svg-3.0.0.tgz#9321dbd29c212e5ca99c4fa9794c714bcafa2f75"
- integrity sha512-gi4iHK53LR2ujhLVVj+37Ykh9GLqYHX6JOVXbLAucaG/Cqw9xwdFOjDM2qeifLs1sF1npXXFvDu0r5HNgCMrzQ==
- dependencies:
- html-comment-regex "^1.1.0"
-
is-symbol@^1.0.2, is-symbol@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.3.tgz#38e1014b9e6329be0de9d24a414fd7441ec61937"
@@ -5653,7 +5107,7 @@ isarray@0.0.1:
resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf"
integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=
-isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0:
+isarray@1.0.0, isarray@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
@@ -5675,7 +5129,7 @@ isobject@^3.0.0, isobject@^3.0.1:
resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df"
integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8=
-jest-worker@^26.5.0:
+jest-worker@^26.3.0, jest-worker@^26.6.2:
version "26.6.2"
resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.6.2.tgz#7f72cbc4d643c365e27b9fd775f9d0eaa9c7a8ed"
integrity sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==
@@ -5708,6 +5162,13 @@ js-yaml@^3.11.0, js-yaml@^3.13.1:
argparse "^1.0.7"
esprima "^4.0.0"
+js-yaml@^4.0.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602"
+ integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==
+ dependencies:
+ argparse "^2.0.1"
+
jsesc@^2.5.1:
version "2.5.2"
resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4"
@@ -5723,7 +5184,7 @@ json-buffer@3.0.0:
resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898"
integrity sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=
-json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2:
+json-parse-better-errors@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9"
integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==
@@ -5812,14 +5273,6 @@ klona@^2.0.4:
resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.4.tgz#7bb1e3affb0cb8624547ef7e8f6708ea2e39dfc0"
integrity sha512-ZRbnvdg/NxqzC7L9Uyqzf4psi1OM4Cuc+sJAkQPjO6XkQIJTNbfK2Rsmbw8fx1p2mkZdp2FZYo2+LwXYY/uwIA==
-last-call-webpack-plugin@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/last-call-webpack-plugin/-/last-call-webpack-plugin-3.0.0.tgz#9742df0e10e3cf46e5c0381c2de90d3a7a2d7555"
- integrity sha512-7KI2l2GIZa9p2spzPIVZBYyNKkN+e/SQPpnjlTiPhdbDW3F86tdKKELxKpzJ5sgU19wQWsACULZmpTPYHeWO5w==
- dependencies:
- lodash "^4.17.5"
- webpack-sources "^1.1.0"
-
latest-version@^5.1.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-5.1.0.tgz#119dfe908fe38d15dfa43ecd13fa12ec8832face"
@@ -5837,10 +5290,10 @@ lines-and-columns@^1.1.6:
resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00"
integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=
-loader-runner@^2.4.0:
- version "2.4.0"
- resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357"
- integrity sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==
+loader-runner@^4.2.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.2.0.tgz#d7022380d66d14c5fb1d496b89864ebcfd478384"
+ integrity sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==
loader-utils@2.0.0, loader-utils@^2.0.0:
version "2.0.0"
@@ -5851,7 +5304,7 @@ loader-utils@2.0.0, loader-utils@^2.0.0:
emojis-list "^3.0.0"
json5 "^2.1.2"
-loader-utils@^1.1.0, loader-utils@^1.2.3, loader-utils@^1.4.0:
+loader-utils@^1.2.3, loader-utils@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613"
integrity sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==
@@ -5875,10 +5328,12 @@ locate-path@^5.0.0:
dependencies:
p-locate "^4.1.0"
-lodash._reinterpolate@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d"
- integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=
+locate-path@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286"
+ integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==
+ dependencies:
+ p-locate "^5.0.0"
lodash.assignin@^4.0.9:
version "4.2.0"
@@ -5960,21 +5415,6 @@ lodash.some@^4.4.0:
resolved "https://registry.yarnpkg.com/lodash.some/-/lodash.some-4.6.0.tgz#1bb9f314ef6b8baded13b549169b2a945eb68e4d"
integrity sha1-G7nzFO9ri63tE7VJFpsqlF62jk0=
-lodash.template@^4.5.0:
- version "4.5.0"
- resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.5.0.tgz#f976195cf3f347d0d5f52483569fe8031ccce8ab"
- integrity sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==
- dependencies:
- lodash._reinterpolate "^3.0.0"
- lodash.templatesettings "^4.0.0"
-
-lodash.templatesettings@^4.0.0:
- version "4.2.0"
- resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz#e481310f049d3cf6d47e912ad09313b154f0fb33"
- integrity sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==
- dependencies:
- lodash._reinterpolate "^3.0.0"
-
lodash.toarray@^4.4.0:
version "4.4.0"
resolved "https://registry.yarnpkg.com/lodash.toarray/-/lodash.toarray-4.4.0.tgz#24c4bfcd6b2fba38bfd0594db1179d8e9b656561"
@@ -5985,7 +5425,7 @@ lodash.uniq@4.5.0, lodash.uniq@^4.5.0:
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=
-lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.5:
+lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
@@ -6019,13 +5459,6 @@ lowercase-keys@^2.0.0:
resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479"
integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==
-lru-cache@^5.1.1:
- version "5.1.1"
- resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920"
- integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==
- dependencies:
- yallist "^3.0.2"
-
lru-cache@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
@@ -6033,14 +5466,6 @@ lru-cache@^6.0.0:
dependencies:
yallist "^4.0.0"
-make-dir@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5"
- integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==
- dependencies:
- pify "^4.0.1"
- semver "^5.6.0"
-
make-dir@^3.0.0, make-dir@^3.0.2, make-dir@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f"
@@ -6065,15 +5490,6 @@ markdown-escapes@^1.0.0:
resolved "https://registry.yarnpkg.com/markdown-escapes/-/markdown-escapes-1.0.4.tgz#c95415ef451499d7602b91095f3c8e8975f78535"
integrity sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg==
-md5.js@^1.3.4:
- version "1.3.5"
- resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f"
- integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==
- dependencies:
- hash-base "^3.0.0"
- inherits "^2.0.1"
- safe-buffer "^5.1.2"
-
mdast-squeeze-paragraphs@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/mdast-squeeze-paragraphs/-/mdast-squeeze-paragraphs-4.0.0.tgz#7c4c114679c3bee27ef10b58e2e015be79f1ef97"
@@ -6135,14 +5551,6 @@ memory-fs@^0.4.1:
errno "^0.1.3"
readable-stream "^2.0.1"
-memory-fs@^0.5.0:
- version "0.5.0"
- resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.5.0.tgz#324c01288b88652966d161db77838720845a8e3c"
- integrity sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==
- dependencies:
- errno "^0.1.3"
- readable-stream "^2.0.1"
-
merge-descriptors@1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
@@ -6195,14 +5603,6 @@ micromatch@^4.0.2:
braces "^3.0.1"
picomatch "^2.0.5"
-miller-rabin@^4.0.0:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d"
- integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==
- dependencies:
- bn.js "^4.0.0"
- brorand "^1.0.1"
-
mime-db@1.46.0, "mime-db@>= 1.43.0 < 2":
version "1.46.0"
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.46.0.tgz#6267748a7f799594de3cbc8cde91def349661cee"
@@ -6255,26 +5655,20 @@ mini-create-react-context@^0.4.0:
"@babel/runtime" "^7.12.1"
tiny-warning "^1.0.3"
-mini-css-extract-plugin@^0.8.0:
- version "0.8.2"
- resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-0.8.2.tgz#a875e169beb27c88af77dd962771c9eedc3da161"
- integrity sha512-a3Y4of27Wz+mqK3qrcd3VhYz6cU0iW5x3Sgvqzbj+XmlrSizmvu8QQMl5oMYJjgHOC4iyt+w7l4umP+dQeW3bw==
+mini-css-extract-plugin@^1.4.0:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-1.6.0.tgz#b4db2525af2624899ed64a23b0016e0036411893"
+ integrity sha512-nPFKI7NSy6uONUo9yn2hIfb9vyYvkFu95qki0e21DQ9uaqNKDP15DGpK0KnV6wDroWxPHtExrdEwx/yDQ8nVRw==
dependencies:
- loader-utils "^1.1.0"
- normalize-url "1.9.1"
- schema-utils "^1.0.0"
+ loader-utils "^2.0.0"
+ schema-utils "^3.0.0"
webpack-sources "^1.1.0"
-minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1:
+minimalistic-assert@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7"
integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==
-minimalistic-crypto-utils@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a"
- integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=
-
minimatch@3.0.4, minimatch@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
@@ -6287,58 +5681,6 @@ minimist@^1.2.0, minimist@^1.2.5:
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
-minipass-collect@^1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/minipass-collect/-/minipass-collect-1.0.2.tgz#22b813bf745dc6edba2576b940022ad6edc8c617"
- integrity sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==
- dependencies:
- minipass "^3.0.0"
-
-minipass-flush@^1.0.5:
- version "1.0.5"
- resolved "https://registry.yarnpkg.com/minipass-flush/-/minipass-flush-1.0.5.tgz#82e7135d7e89a50ffe64610a787953c4c4cbb373"
- integrity sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==
- dependencies:
- minipass "^3.0.0"
-
-minipass-pipeline@^1.2.2:
- version "1.2.4"
- resolved "https://registry.yarnpkg.com/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz#68472f79711c084657c067c5c6ad93cddea8214c"
- integrity sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==
- dependencies:
- minipass "^3.0.0"
-
-minipass@^3.0.0, minipass@^3.1.1:
- version "3.1.3"
- resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.3.tgz#7d42ff1f39635482e15f9cdb53184deebd5815fd"
- integrity sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==
- dependencies:
- yallist "^4.0.0"
-
-minizlib@^2.1.1:
- version "2.1.2"
- resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931"
- integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==
- dependencies:
- minipass "^3.0.0"
- yallist "^4.0.0"
-
-mississippi@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022"
- integrity sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==
- dependencies:
- concat-stream "^1.5.0"
- duplexify "^3.4.2"
- end-of-stream "^1.1.0"
- flush-write-stream "^1.0.0"
- from2 "^2.1.0"
- parallel-transform "^1.1.0"
- pump "^3.0.0"
- pumpify "^1.3.3"
- stream-each "^1.1.0"
- through2 "^2.0.0"
-
mixin-deep@^1.2.0:
version "1.3.2"
resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566"
@@ -6347,14 +5689,14 @@ mixin-deep@^1.2.0:
for-in "^1.0.2"
is-extendable "^1.0.1"
-mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@^0.5.5, mkdirp@~0.5.1:
+mkdirp@^0.5.1, mkdirp@^0.5.5, mkdirp@~0.5.1:
version "0.5.5"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def"
integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==
dependencies:
minimist "^1.2.5"
-mkdirp@^1.0.3, mkdirp@^1.0.4:
+mkdirp@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
@@ -6364,18 +5706,6 @@ module-alias@^2.2.2:
resolved "https://registry.yarnpkg.com/module-alias/-/module-alias-2.2.2.tgz#151cdcecc24e25739ff0aa6e51e1c5716974c0e0"
integrity sha512-A/78XjoX2EmNvppVWEhM2oGk3x4lLxnkEA4jTbaK97QKSDjkIoOsKQlfylt/d3kKKi596Qy3NP5XrXJ6fZIC9Q==
-move-concurrently@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92"
- integrity sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=
- dependencies:
- aproba "^1.1.1"
- copy-concurrently "^1.0.0"
- fs-write-stream-atomic "^1.0.8"
- mkdirp "^0.5.1"
- rimraf "^2.5.4"
- run-queue "^1.0.3"
-
ms@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
@@ -6414,10 +5744,10 @@ nan@^2.12.1:
resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19"
integrity sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==
-nanoid@^3.1.20:
- version "3.1.22"
- resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.22.tgz#b35f8fb7d151990a8aebd5aa5015c03cf726f844"
- integrity sha512-/2ZUaJX2ANuLtTvqTlgqBQNJoQO398KyJgZloL0PZkC0dpysjncRUPsFe3DUPzz/y3h+u7C46np8RMuvF3jsSQ==
+nanoid@^3.1.23:
+ version "3.1.23"
+ resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.23.tgz#f744086ce7c2bc47ee0a8472574d5c78e4183a81"
+ integrity sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw==
nanomatch@^1.2.9:
version "1.2.13"
@@ -6441,7 +5771,7 @@ negotiator@0.6.2:
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb"
integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==
-neo-async@^2.5.0, neo-async@^2.6.1:
+neo-async@^2.6.2:
version "2.6.2"
resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f"
integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==
@@ -6476,40 +5806,16 @@ node-forge@^0.10.0:
resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.10.0.tgz#32dea2afb3e9926f02ee5ce8794902691a676bf3"
integrity sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==
-node-libs-browser@^2.2.1:
- version "2.2.1"
- resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425"
- integrity sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==
- dependencies:
- assert "^1.1.1"
- browserify-zlib "^0.2.0"
- buffer "^4.3.0"
- console-browserify "^1.1.0"
- constants-browserify "^1.0.0"
- crypto-browserify "^3.11.0"
- domain-browser "^1.1.1"
- events "^3.0.0"
- https-browserify "^1.0.0"
- os-browserify "^0.3.0"
- path-browserify "0.0.1"
- process "^0.11.10"
- punycode "^1.2.4"
- querystring-es3 "^0.2.0"
- readable-stream "^2.3.3"
- stream-browserify "^2.0.1"
- stream-http "^2.7.2"
- string_decoder "^1.0.0"
- timers-browserify "^2.0.4"
- tty-browserify "0.0.0"
- url "^0.11.0"
- util "^0.11.0"
- vm-browserify "^1.0.1"
-
node-releases@^1.1.61, node-releases@^1.1.70:
version "1.1.71"
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.71.tgz#cb1334b179896b1c89ecfdd4b725fb7bbdfc7dbb"
integrity sha512-zR6HoT6LrLCRBwukmrVbHv0EpEQjksO6GmFcZQQuCAy139BEsoVKPYnf3jongYW83fAa1torLGYwxxky/p28sg==
+node-releases@^1.1.71:
+ version "1.1.72"
+ resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.72.tgz#14802ab6b1039a79a0c7d662b610a5bbd76eacbe"
+ integrity sha512-LLUo+PpH3dU6XizX3iVoubUNheF/owjXCZZ5yACDxNnPtgFuludV1ZL3ayK1kVep42Rmm0+R9/Y60NQbZ2bifw==
+
normalize-path@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9"
@@ -6527,22 +5833,7 @@ normalize-range@^0.1.2:
resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942"
integrity sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=
-normalize-url@1.9.1:
- version "1.9.1"
- resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-1.9.1.tgz#2cc0d66b31ea23036458436e3620d85954c66c3c"
- integrity sha1-LMDWazHqIwNkWENuNiDYWVTGbDw=
- dependencies:
- object-assign "^4.0.1"
- prepend-http "^1.0.0"
- query-string "^4.1.0"
- sort-keys "^1.0.0"
-
-normalize-url@^3.0.0:
- version "3.3.0"
- resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559"
- integrity sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==
-
-normalize-url@^4.1.0:
+normalize-url@^4.1.0, normalize-url@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.0.tgz#453354087e6ca96957bd8f5baf753f5982142129"
integrity sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==
@@ -6573,18 +5864,12 @@ nth-check@^1.0.2, nth-check@~1.0.1:
dependencies:
boolbase "~1.0.0"
-null-loader@^4.0.0:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/null-loader/-/null-loader-4.0.1.tgz#8e63bd3a2dd3c64236a4679428632edd0a6dbc6a"
- integrity sha512-pxqVbi4U6N26lq+LmgIbB5XATP0VdZKOG25DhHi8btMmJJefGArFyDg1yc4U3hWCJbMqSrw0qyrz1UQX+qYXqg==
+nth-check@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.0.0.tgz#1bb4f6dac70072fc313e8c9cd1417b5074c0a125"
+ integrity sha512-i4sc/Kj8htBrAiH1viZ0TgU8Y5XqCaV/FziYK6TBczxmeKm3AEFWqqF3195yKudrarqy7Zu80Ra5dobFjn9X/Q==
dependencies:
- loader-utils "^2.0.0"
- schema-utils "^3.0.0"
-
-num2fraction@^1.2.2:
- version "1.2.2"
- resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede"
- integrity sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=
+ boolbase "^1.0.0"
object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1:
version "4.1.1"
@@ -6635,7 +5920,7 @@ object.assign@^4.1.0, object.assign@^4.1.2:
has-symbols "^1.0.1"
object-keys "^1.1.1"
-object.getownpropertydescriptors@^2.0.3, object.getownpropertydescriptors@^2.1.0:
+object.getownpropertydescriptors@^2.1.0:
version "2.1.2"
resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.2.tgz#1bd63aeacf0d5d2d2f31b5e393b03a7c601a23f7"
integrity sha512-WtxeKSzfBjlzL+F9b7M7hewDzMwy+C8NRssHd1YrNlzHzIDrXcXiNOMrezdAEM4UXixgV+vvnyBeN7Rygl2ttQ==
@@ -6712,14 +5997,6 @@ opn@^5.5.0:
dependencies:
is-wsl "^1.1.0"
-optimize-css-assets-webpack-plugin@^5.0.4:
- version "5.0.4"
- resolved "https://registry.yarnpkg.com/optimize-css-assets-webpack-plugin/-/optimize-css-assets-webpack-plugin-5.0.4.tgz#85883c6528aaa02e30bbad9908c92926bb52dc90"
- integrity sha512-wqd6FdI2a5/FdoiCNNkEvLeA//lHHfG24Ln2Xm2qqdIk4aOlsR18jwpyOihqQ8849W3qu2DX8fOYxpvTMj+93A==
- dependencies:
- cssnano "^4.1.10"
- last-call-webpack-plugin "^3.0.0"
-
original@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/original/-/original-1.0.2.tgz#e442a61cffe1c5fd20a65f3261c26663b303f25f"
@@ -6727,11 +6004,6 @@ original@^1.0.0:
dependencies:
url-parse "^1.4.3"
-os-browserify@^0.3.0:
- version "0.3.0"
- resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27"
- integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=
-
p-cancelable@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc"
@@ -6749,7 +6021,7 @@ p-limit@^2.0.0, p-limit@^2.2.0:
dependencies:
p-try "^2.0.0"
-p-limit@^3.0.2:
+p-limit@^3.0.2, p-limit@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b"
integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==
@@ -6770,6 +6042,13 @@ p-locate@^4.1.0:
dependencies:
p-limit "^2.2.0"
+p-locate@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834"
+ integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==
+ dependencies:
+ p-limit "^3.0.2"
+
p-map@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175"
@@ -6804,20 +6083,6 @@ package-json@^6.3.0:
registry-url "^5.0.0"
semver "^6.2.0"
-pako@~1.0.5:
- version "1.0.11"
- resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf"
- integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==
-
-parallel-transform@^1.1.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/parallel-transform/-/parallel-transform-1.2.0.tgz#9049ca37d6cb2182c3b1d2c720be94d14a5814fc"
- integrity sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==
- dependencies:
- cyclist "^1.0.1"
- inherits "^2.0.3"
- readable-stream "^2.1.5"
-
param-case@^3.0.3:
version "3.0.4"
resolved "https://registry.yarnpkg.com/param-case/-/param-case-3.0.4.tgz#7d17fe4aa12bde34d4a77d91acfb6219caad01c5"
@@ -6833,17 +6098,6 @@ parent-module@^1.0.0:
dependencies:
callsites "^3.0.0"
-parse-asn1@^5.0.0, parse-asn1@^5.1.5:
- version "5.1.6"
- resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.6.tgz#385080a3ec13cb62a62d39409cb3e88844cdaed4"
- integrity sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==
- dependencies:
- asn1.js "^5.2.0"
- browserify-aes "^1.0.0"
- evp_bytestokey "^1.0.0"
- pbkdf2 "^3.0.3"
- safe-buffer "^5.1.1"
-
parse-entities@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-2.0.0.tgz#53c6eb5b9314a1f4ec99fa0fdf7ce01ecda0cbe8"
@@ -6856,14 +6110,6 @@ parse-entities@^2.0.0:
is-decimal "^1.0.0"
is-hexadecimal "^1.0.0"
-parse-json@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0"
- integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=
- dependencies:
- error-ex "^1.3.1"
- json-parse-better-errors "^1.0.1"
-
parse-json@^5.0.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd"
@@ -6907,11 +6153,6 @@ pascalcase@^0.1.1:
resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14"
integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=
-path-browserify@0.0.1:
- version "0.0.1"
- resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a"
- integrity sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==
-
path-dirname@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0"
@@ -6974,17 +6215,6 @@ path-type@^4.0.0:
resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b"
integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==
-pbkdf2@^3.0.3:
- version "3.1.1"
- resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.1.tgz#cb8724b0fada984596856d1a6ebafd3584654b94"
- integrity sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg==
- dependencies:
- create-hash "^1.1.2"
- create-hmac "^1.1.4"
- ripemd160 "^2.0.1"
- safe-buffer "^5.0.1"
- sha.js "^2.4.8"
-
picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.2.1:
version "2.2.2"
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad"
@@ -7033,13 +6263,6 @@ pkg-up@3.1.0:
dependencies:
find-up "^3.0.0"
-pnp-webpack-plugin@^1.6.4:
- version "1.6.4"
- resolved "https://registry.yarnpkg.com/pnp-webpack-plugin/-/pnp-webpack-plugin-1.6.4.tgz#c9711ac4dc48a685dabafc86f8b6dd9f8df84149"
- integrity sha512-7Wjy+9E3WwLOEL30D+m8TSTF7qJJUJLONBnwQp0518siuMxUQUbgZwssaFX+QKlZkjHZcw/IpZCt/H0srrntSg==
- dependencies:
- ts-pnp "^1.1.6"
-
portfinder@^1.0.26:
version "1.0.28"
resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.28.tgz#67c4622852bd5374dd1dd900f779f53462fac778"
@@ -7054,317 +6277,128 @@ posix-character-classes@^0.1.0:
resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab"
integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=
-postcss-attribute-case-insensitive@^4.0.1:
- version "4.0.2"
- resolved "https://registry.yarnpkg.com/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-4.0.2.tgz#d93e46b504589e94ac7277b0463226c68041a880"
- integrity sha512-clkFxk/9pcdb4Vkn0hAHq3YnxBQ2p0CGD1dy24jN+reBck+EWxMbxSUqN4Yj7t0w8csl87K6p0gxBe1utkJsYA==
+postcss-calc@^8.0.0:
+ version "8.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-8.0.0.tgz#a05b87aacd132740a5db09462a3612453e5df90a"
+ integrity sha512-5NglwDrcbiy8XXfPM11F3HeC6hoT9W7GUH/Zi5U/p7u3Irv4rHhdDcIZwG0llHXV4ftsBjpfWMXAnXNl4lnt8g==
dependencies:
- postcss "^7.0.2"
- postcss-selector-parser "^6.0.2"
-
-postcss-calc@^7.0.1:
- version "7.0.5"
- resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-7.0.5.tgz#f8a6e99f12e619c2ebc23cf6c486fdc15860933e"
- integrity sha512-1tKHutbGtLtEZF6PT4JSihCHfIVldU72mZ8SdZHIYriIZ9fh9k9aWSppaT8rHsyI3dX+KSR+W+Ix9BMY3AODrg==
- dependencies:
- postcss "^7.0.27"
postcss-selector-parser "^6.0.2"
postcss-value-parser "^4.0.2"
-postcss-color-functional-notation@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/postcss-color-functional-notation/-/postcss-color-functional-notation-2.0.1.tgz#5efd37a88fbabeb00a2966d1e53d98ced93f74e0"
- integrity sha512-ZBARCypjEDofW4P6IdPVTLhDNXPRn8T2s1zHbZidW6rPaaZvcnCS2soYFIQJrMZSxiePJ2XIYTlcb2ztr/eT2g==
- dependencies:
- postcss "^7.0.2"
- postcss-values-parser "^2.0.0"
-
-postcss-color-gray@^5.0.0:
+postcss-colormin@^5.0.0:
version "5.0.0"
- resolved "https://registry.yarnpkg.com/postcss-color-gray/-/postcss-color-gray-5.0.0.tgz#532a31eb909f8da898ceffe296fdc1f864be8547"
- integrity sha512-q6BuRnAGKM/ZRpfDascZlIZPjvwsRye7UDNalqVz3s7GDxMtqPY6+Q871liNxsonUw8oC61OG+PSaysYpl1bnw==
+ resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-5.0.0.tgz#283b8934c8bdbc531e7648aeb0970107f6d06d0e"
+ integrity sha512-Yt84+5V6CgS/AhK7d7MA58vG8dSZ7+ytlRtWLaQhag3HXOncTfmYpuUOX4cDoXjvLfw1sHRCHMiBjYhc35CymQ==
dependencies:
- "@csstools/convert-colors" "^1.4.0"
- postcss "^7.0.5"
- postcss-values-parser "^2.0.0"
+ browserslist "^4.16.0"
+ color "^3.1.1"
+ postcss-value-parser "^4.1.0"
-postcss-color-hex-alpha@^5.0.3:
- version "5.0.3"
- resolved "https://registry.yarnpkg.com/postcss-color-hex-alpha/-/postcss-color-hex-alpha-5.0.3.tgz#a8d9ca4c39d497c9661e374b9c51899ef0f87388"
- integrity sha512-PF4GDel8q3kkreVXKLAGNpHKilXsZ6xuu+mOQMHWHLPNyjiUBOr75sp5ZKJfmv1MCus5/DWUGcK9hm6qHEnXYw==
- dependencies:
- postcss "^7.0.14"
- postcss-values-parser "^2.0.1"
-
-postcss-color-mod-function@^3.0.3:
- version "3.0.3"
- resolved "https://registry.yarnpkg.com/postcss-color-mod-function/-/postcss-color-mod-function-3.0.3.tgz#816ba145ac11cc3cb6baa905a75a49f903e4d31d"
- integrity sha512-YP4VG+xufxaVtzV6ZmhEtc+/aTXH3d0JLpnYfxqTvwZPbJhWqp8bSY3nfNzNRFLgB4XSaBA82OE4VjOOKpCdVQ==
- dependencies:
- "@csstools/convert-colors" "^1.4.0"
- postcss "^7.0.2"
- postcss-values-parser "^2.0.0"
-
-postcss-color-rebeccapurple@^4.0.1:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-4.0.1.tgz#c7a89be872bb74e45b1e3022bfe5748823e6de77"
- integrity sha512-aAe3OhkS6qJXBbqzvZth2Au4V3KieR5sRQ4ptb2b2O8wgvB3SJBsdG+jsn2BZbbwekDG8nTfcCNKcSfe/lEy8g==
- dependencies:
- postcss "^7.0.2"
- postcss-values-parser "^2.0.0"
-
-postcss-colormin@^4.0.3:
- version "4.0.3"
- resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-4.0.3.tgz#ae060bce93ed794ac71264f08132d550956bd381"
- integrity sha512-WyQFAdDZpExQh32j0U0feWisZ0dmOtPl44qYmJKkq9xFWY3p+4qnRzCHeNrkeRhwPHz9bQ3mo0/yVkaply0MNw==
- dependencies:
- browserslist "^4.0.0"
- color "^3.0.0"
- has "^1.0.0"
- postcss "^7.0.0"
- postcss-value-parser "^3.0.0"
-
-postcss-convert-values@^4.0.1:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-4.0.1.tgz#ca3813ed4da0f812f9d43703584e449ebe189a7f"
- integrity sha512-Kisdo1y77KUC0Jmn0OXU/COOJbzM8cImvw1ZFsBgBgMgb1iL23Zs/LXRe3r+EZqM3vGYKdQ2YJVQ5VkJI+zEJQ==
- dependencies:
- postcss "^7.0.0"
- postcss-value-parser "^3.0.0"
-
-postcss-custom-media@^7.0.8:
- version "7.0.8"
- resolved "https://registry.yarnpkg.com/postcss-custom-media/-/postcss-custom-media-7.0.8.tgz#fffd13ffeffad73621be5f387076a28b00294e0c"
- integrity sha512-c9s5iX0Ge15o00HKbuRuTqNndsJUbaXdiNsksnVH8H4gdc+zbLzr/UasOwNG6CTDpLFekVY4672eWdiiWu2GUg==
- dependencies:
- postcss "^7.0.14"
-
-postcss-custom-properties@^8.0.11:
- version "8.0.11"
- resolved "https://registry.yarnpkg.com/postcss-custom-properties/-/postcss-custom-properties-8.0.11.tgz#2d61772d6e92f22f5e0d52602df8fae46fa30d97"
- integrity sha512-nm+o0eLdYqdnJ5abAJeXp4CEU1c1k+eB2yMCvhgzsds/e0umabFrN6HoTy/8Q4K5ilxERdl/JD1LO5ANoYBeMA==
- dependencies:
- postcss "^7.0.17"
- postcss-values-parser "^2.0.1"
-
-postcss-custom-selectors@^5.1.2:
- version "5.1.2"
- resolved "https://registry.yarnpkg.com/postcss-custom-selectors/-/postcss-custom-selectors-5.1.2.tgz#64858c6eb2ecff2fb41d0b28c9dd7b3db4de7fba"
- integrity sha512-DSGDhqinCqXqlS4R7KGxL1OSycd1lydugJ1ky4iRXPHdBRiozyMHrdu0H3o7qNOCiZwySZTUI5MV0T8QhCLu+w==
- dependencies:
- postcss "^7.0.2"
- postcss-selector-parser "^5.0.0-rc.3"
-
-postcss-dir-pseudo-class@^5.0.0:
+postcss-convert-values@^5.0.0:
version "5.0.0"
- resolved "https://registry.yarnpkg.com/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-5.0.0.tgz#6e3a4177d0edb3abcc85fdb6fbb1c26dabaeaba2"
- integrity sha512-3pm4oq8HYWMZePJY+5ANriPs3P07q+LW6FAdTlkFH2XqDdP4HeeJYMOzn0HYLhRSjBO3fhiqSwwU9xEULSrPgw==
+ resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-5.0.0.tgz#cd77e1d23ebe8fcf508640551eed08e232784cba"
+ integrity sha512-V5kmYm4xoBAjNs+eHY/6XzXJkkGeg4kwNf2ocfqhLb1WBPEa4oaSmoi1fnVO7Dkblqvus9h+AenDvhCKUCK7uQ==
dependencies:
- postcss "^7.0.2"
- postcss-selector-parser "^5.0.0-rc.3"
+ postcss-value-parser "^4.1.0"
-postcss-discard-comments@^4.0.2:
- version "4.0.2"
- resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-4.0.2.tgz#1fbabd2c246bff6aaad7997b2b0918f4d7af4033"
- integrity sha512-RJutN259iuRf3IW7GZyLM5Sw4GLTOH8FmsXBnv8Ab/Tc2k4SR4qbV4DNbyyY4+Sjo362SyDmW2DQ7lBSChrpkg==
+postcss-discard-comments@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-5.0.0.tgz#6c27310e0657c0b9e38a6175ad001b5aa28964bc"
+ integrity sha512-Umig6Gxs8m20RihiXY6QkePd6mp4FxkA1Dg+f/Kd6uw0gEMfKRjDeQOyFkLibexbJJGHpE3lrN/Q0R9SMrUMbQ==
+
+postcss-discard-duplicates@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-5.0.0.tgz#6a2c4f779e8d20da6781e90730f234f9e650c51c"
+ integrity sha512-vEJJ+Y3pFUnO1FyCBA6PSisGjHtnphL3V6GsNvkASq/VkP3OX5/No5RYXXLxHa2QegStNzg6HYrYdo71uR4caQ==
+
+postcss-discard-empty@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-5.0.0.tgz#0f0a9baee415f5f7be4ae046ba235e98626ba821"
+ integrity sha512-+wigy099Y1xZxG36WG5L1f2zeH1oicntkJEW4TDIqKKDO2g9XVB3OhoiHTu08rDEjLnbcab4rw0BAccwi2VjiQ==
+
+postcss-discard-overridden@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-5.0.0.tgz#ac00f695a60001eda52135a11fac87376b8da9ee"
+ integrity sha512-hybnScTaZM2iEA6kzVQ6Spozy7kVdLw+lGw8hftLlBEzt93uzXoltkYp9u0tI8xbfhxDLTOOzHsHQCkYdmzRUg==
+
+postcss-discard-unused@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-discard-unused/-/postcss-discard-unused-5.0.0.tgz#6aad1061a53088d4b4d4363496d85b9b0de34f7e"
+ integrity sha512-C+bchjnGRoGlSQjACMts/FlpY3LMDEUS5+9rHKxvl/NFUY/5OYWjkA1AEUo9HDWnFB44CFgcm6khLMSIbrjVEQ==
dependencies:
- postcss "^7.0.0"
+ postcss-selector-parser "^6.0.4"
-postcss-discard-duplicates@^4.0.2:
- version "4.0.2"
- resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-4.0.2.tgz#3fe133cd3c82282e550fc9b239176a9207b784eb"
- integrity sha512-ZNQfR1gPNAiXZhgENFfEglF93pciw0WxMkJeVmw8eF+JZBbMD7jp6C67GqJAXVZP2BWbOztKfbsdmMp/k8c6oQ==
- dependencies:
- postcss "^7.0.0"
-
-postcss-discard-empty@^4.0.1:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-4.0.1.tgz#c8c951e9f73ed9428019458444a02ad90bb9f765"
- integrity sha512-B9miTzbznhDjTfjvipfHoqbWKwd0Mj+/fL5s1QOz06wufguil+Xheo4XpOnc4NqKYBCNqqEzgPv2aPBIJLox0w==
- dependencies:
- postcss "^7.0.0"
-
-postcss-discard-overridden@^4.0.1:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-4.0.1.tgz#652aef8a96726f029f5e3e00146ee7a4e755ff57"
- integrity sha512-IYY2bEDD7g1XM1IDEsUT4//iEYCxAmP5oDSFMVU/JVvT7gh+l4fmjciLqGgwjdWpQIdb0Che2VX00QObS5+cTg==
- dependencies:
- postcss "^7.0.0"
-
-postcss-discard-unused@^4.0.1:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/postcss-discard-unused/-/postcss-discard-unused-4.0.1.tgz#ee7cc66af8c7e8c19bd36f12d09c4bde4039abea"
- integrity sha512-/3vq4LU0bLH2Lj4NYN7BTf2caly0flUB7Xtrk9a5K3yLuXMkHMqMO/x3sDq8W2b1eQFSCyY0IVz2L+0HP8kUUA==
- dependencies:
- postcss "^7.0.0"
- postcss-selector-parser "^3.0.0"
- uniqs "^2.0.0"
-
-postcss-double-position-gradients@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/postcss-double-position-gradients/-/postcss-double-position-gradients-1.0.0.tgz#fc927d52fddc896cb3a2812ebc5df147e110522e"
- integrity sha512-G+nV8EnQq25fOI8CH/B6krEohGWnF5+3A6H/+JEpOncu5dCnkS1QQ6+ct3Jkaepw1NGVqqOZH6lqrm244mCftA==
- dependencies:
- postcss "^7.0.5"
- postcss-values-parser "^2.0.0"
-
-postcss-env-function@^2.0.2:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/postcss-env-function/-/postcss-env-function-2.0.2.tgz#0f3e3d3c57f094a92c2baf4b6241f0b0da5365d7"
- integrity sha512-rwac4BuZlITeUbiBq60h/xbLzXY43qOsIErngWa4l7Mt+RaSkT7QBjXVGTcBHupykkblHMDrBFh30zchYPaOUw==
- dependencies:
- postcss "^7.0.2"
- postcss-values-parser "^2.0.0"
-
-postcss-focus-visible@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/postcss-focus-visible/-/postcss-focus-visible-4.0.0.tgz#477d107113ade6024b14128317ade2bd1e17046e"
- integrity sha512-Z5CkWBw0+idJHSV6+Bgf2peDOFf/x4o+vX/pwcNYrWpXFrSfTkQ3JQ1ojrq9yS+upnAlNRHeg8uEwFTgorjI8g==
- dependencies:
- postcss "^7.0.2"
-
-postcss-focus-within@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/postcss-focus-within/-/postcss-focus-within-3.0.0.tgz#763b8788596cee9b874c999201cdde80659ef680"
- integrity sha512-W0APui8jQeBKbCGZudW37EeMCjDeVxKgiYfIIEo8Bdh5SpB9sxds/Iq8SEuzS0Q4YFOlG7EPFulbbxujpkrV2w==
- dependencies:
- postcss "^7.0.2"
-
-postcss-font-variant@^4.0.0:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/postcss-font-variant/-/postcss-font-variant-4.0.1.tgz#42d4c0ab30894f60f98b17561eb5c0321f502641"
- integrity sha512-I3ADQSTNtLTTd8uxZhtSOrTCQ9G4qUVKPjHiDk0bV75QSxXjVWiJVJ2VLdspGUi9fbW9BcjKJoRvxAH1pckqmA==
- dependencies:
- postcss "^7.0.2"
-
-postcss-gap-properties@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/postcss-gap-properties/-/postcss-gap-properties-2.0.0.tgz#431c192ab3ed96a3c3d09f2ff615960f902c1715"
- integrity sha512-QZSqDaMgXCHuHTEzMsS2KfVDOq7ZFiknSpkrPJY6jmxbugUPTuSzs/vuE5I3zv0WAS+3vhrlqhijiprnuQfzmg==
- dependencies:
- postcss "^7.0.2"
-
-postcss-image-set-function@^3.0.1:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/postcss-image-set-function/-/postcss-image-set-function-3.0.1.tgz#28920a2f29945bed4c3198d7df6496d410d3f288"
- integrity sha512-oPTcFFip5LZy8Y/whto91L9xdRHCWEMs3e1MdJxhgt4jy2WYXfhkng59fH5qLXSCPN8k4n94p1Czrfe5IOkKUw==
- dependencies:
- postcss "^7.0.2"
- postcss-values-parser "^2.0.0"
-
-postcss-initial@^3.0.0:
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/postcss-initial/-/postcss-initial-3.0.2.tgz#f018563694b3c16ae8eaabe3c585ac6319637b2d"
- integrity sha512-ugA2wKonC0xeNHgirR4D3VWHs2JcU08WAi1KFLVcnb7IN89phID6Qtg2RIctWbnvp1TM2BOmDtX8GGLCKdR8YA==
- dependencies:
- lodash.template "^4.5.0"
- postcss "^7.0.2"
-
-postcss-lab-function@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/postcss-lab-function/-/postcss-lab-function-2.0.1.tgz#bb51a6856cd12289ab4ae20db1e3821ef13d7d2e"
- integrity sha512-whLy1IeZKY+3fYdqQFuDBf8Auw+qFuVnChWjmxm/UhHWqNHZx+B99EwxTvGYmUBqe3Fjxs4L1BoZTJmPu6usVg==
- dependencies:
- "@csstools/convert-colors" "^1.4.0"
- postcss "^7.0.2"
- postcss-values-parser "^2.0.0"
-
-postcss-loader@^4.1.0:
- version "4.2.0"
- resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-4.2.0.tgz#f6993ea3e0f46600fb3ee49bbd010448123a7db4"
- integrity sha512-mqgScxHqbiz1yxbnNcPdKYo/6aVt+XExURmEbQlviFVWogDbM4AJ0A/B+ZBpYsJrTRxKw7HyRazg9x0Q9SWwLA==
+postcss-loader@^5.2.0:
+ version "5.3.0"
+ resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-5.3.0.tgz#1657f869e48d4fdb018a40771c235e499ee26244"
+ integrity sha512-/+Z1RAmssdiSLgIZwnJHwBMnlABPgF7giYzTN2NOfr9D21IJZ4mQC1R2miwp80zno9M4zMD/umGI8cR+2EL5zw==
dependencies:
cosmiconfig "^7.0.0"
klona "^2.0.4"
- loader-utils "^2.0.0"
- schema-utils "^3.0.0"
semver "^7.3.4"
-postcss-logical@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/postcss-logical/-/postcss-logical-3.0.0.tgz#2495d0f8b82e9f262725f75f9401b34e7b45d5b5"
- integrity sha512-1SUKdJc2vuMOmeItqGuNaC+N8MzBWFWEkAnRnLpFYj1tGGa7NqyVBujfRtgNa2gXR+6RkGUiB2O5Vmh7E2RmiA==
+postcss-merge-idents@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-merge-idents/-/postcss-merge-idents-5.0.0.tgz#13b6598912a96e93552c778bbfeaaf2cfaf46b68"
+ integrity sha512-s8wwhAB/SJDPkcVxj31s2SGzgrO66ktUYjWh6j4qwY67Mzxx3/TkK+m/+v6tU/xyW4TmGd4yuyTXsHaaLC0jLg==
dependencies:
- postcss "^7.0.2"
+ cssnano-utils "^2.0.0"
+ postcss-value-parser "^4.1.0"
-postcss-media-minmax@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/postcss-media-minmax/-/postcss-media-minmax-4.0.0.tgz#b75bb6cbc217c8ac49433e12f22048814a4f5ed5"
- integrity sha512-fo9moya6qyxsjbFAYl97qKO9gyre3qvbMnkOZeZwlsW6XYFsvs2DMGDlchVLfAd8LHPZDxivu/+qW2SMQeTHBw==
+postcss-merge-longhand@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-5.0.1.tgz#1a008ff72d14cd3e2f3d32accc2ad37948bcabf4"
+ integrity sha512-H1RO8le5deFGumQzuhJjuL0bIXPRysa+w7xtk5KrHe38oiaSS9ksPXDo24+IOS3SETPhip0J5+1uCOW+ALs3Yw==
dependencies:
- postcss "^7.0.2"
+ css-color-names "^1.0.1"
+ postcss-value-parser "^4.1.0"
+ stylehacks "^5.0.0"
-postcss-merge-idents@^4.0.1:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/postcss-merge-idents/-/postcss-merge-idents-4.0.1.tgz#b7df282a92f052ea0a66c62d8f8812e6d2cbed23"
- integrity sha512-43S/VNdF6II0NZ31YxcvNYq4gfURlPAAsJW/z84avBXQCaP4I4qRHUH18slW/SOlJbcxxCobflPNUApYDddS7A==
+postcss-merge-rules@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-5.0.0.tgz#e0d0c0d45c98376f4adb49eb1f1dfe2aebfd7048"
+ integrity sha512-TfsXbKjNYCGfUPEXGIGPySnMiJbdS+3gcVeV8gwmJP4RajyKZHW8E0FYDL1WmggTj3hi+m+WUCAvqRpX2ut4Kg==
dependencies:
- cssnano-util-same-parent "^4.0.0"
- has "^1.0.0"
- postcss "^7.0.0"
- postcss-value-parser "^3.0.0"
-
-postcss-merge-longhand@^4.0.11:
- version "4.0.11"
- resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-4.0.11.tgz#62f49a13e4a0ee04e7b98f42bb16062ca2549e24"
- integrity sha512-alx/zmoeXvJjp7L4mxEMjh8lxVlDFX1gqWHzaaQewwMZiVhLo42TEClKaeHbRf6J7j82ZOdTJ808RtN0ZOZwvw==
- dependencies:
- css-color-names "0.0.4"
- postcss "^7.0.0"
- postcss-value-parser "^3.0.0"
- stylehacks "^4.0.0"
-
-postcss-merge-rules@^4.0.3:
- version "4.0.3"
- resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-4.0.3.tgz#362bea4ff5a1f98e4075a713c6cb25aefef9a650"
- integrity sha512-U7e3r1SbvYzO0Jr3UT/zKBVgYYyhAz0aitvGIYOYK5CPmkNih+WDSsS5tvPrJ8YMQYlEMvsZIiqmn7HdFUaeEQ==
- dependencies:
- browserslist "^4.0.0"
+ browserslist "^4.16.0"
caniuse-api "^3.0.0"
- cssnano-util-same-parent "^4.0.0"
- postcss "^7.0.0"
- postcss-selector-parser "^3.0.0"
- vendors "^1.0.0"
+ cssnano-utils "^2.0.0"
+ postcss-selector-parser "^6.0.4"
+ vendors "^1.0.3"
-postcss-minify-font-values@^4.0.2:
- version "4.0.2"
- resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-4.0.2.tgz#cd4c344cce474343fac5d82206ab2cbcb8afd5a6"
- integrity sha512-j85oO6OnRU9zPf04+PZv1LYIYOprWm6IA6zkXkrJXyRveDEuQggG6tvoy8ir8ZwjLxLuGfNkCZEQG7zan+Hbtg==
+postcss-minify-font-values@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-5.0.0.tgz#fee5d0fa192fae8757cb744870a0ad02be5f402e"
+ integrity sha512-zi2JhFaMOcIaNxhndX5uhsqSY1rexKDp23wV8EOmC9XERqzLbHsoRye3aYF716Zm+hkcR4loqKDt8LZlmihwAg==
dependencies:
- postcss "^7.0.0"
- postcss-value-parser "^3.0.0"
+ postcss-value-parser "^4.1.0"
-postcss-minify-gradients@^4.0.2:
- version "4.0.2"
- resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-4.0.2.tgz#93b29c2ff5099c535eecda56c4aa6e665a663471"
- integrity sha512-qKPfwlONdcf/AndP1U8SJ/uzIJtowHlMaSioKzebAXSG4iJthlWC9iSWznQcX4f66gIWX44RSA841HTHj3wK+Q==
+postcss-minify-gradients@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-5.0.0.tgz#95dbe61567a45c0cd7ab897d78fb65d5096844ed"
+ integrity sha512-/jPtNgs6JySMwgsE5dPOq8a2xEopWTW3RyqoB9fLqxgR+mDUNLSi7joKd+N1z7FXWgVkc4l/dEBMXHgNAaUbvg==
dependencies:
- cssnano-util-get-arguments "^4.0.0"
- is-color-stop "^1.0.0"
- postcss "^7.0.0"
- postcss-value-parser "^3.0.0"
+ cssnano-utils "^2.0.0"
+ is-color-stop "^1.1.0"
+ postcss-value-parser "^4.1.0"
-postcss-minify-params@^4.0.2:
- version "4.0.2"
- resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-4.0.2.tgz#6b9cef030c11e35261f95f618c90036d680db874"
- integrity sha512-G7eWyzEx0xL4/wiBBJxJOz48zAKV2WG3iZOqVhPet/9geefm/Px5uo1fzlHu+DOjT+m0Mmiz3jkQzVHe6wxAWg==
+postcss-minify-params@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-5.0.0.tgz#12c7f75d69b0b4827fafbd6649970a53784a9c24"
+ integrity sha512-KvZYIxTPBVKjdd+XgObq9A+Sfv8lMkXTpbZTsjhr42XbfWIeLaTItMlygsDWfjArEc3muUfDaUFgNSeDiJ5jug==
dependencies:
- alphanum-sort "^1.0.0"
- browserslist "^4.0.0"
- cssnano-util-get-arguments "^4.0.0"
- postcss "^7.0.0"
- postcss-value-parser "^3.0.0"
+ alphanum-sort "^1.0.2"
+ browserslist "^4.16.0"
+ cssnano-utils "^2.0.0"
+ postcss-value-parser "^4.1.0"
uniqs "^2.0.0"
-postcss-minify-selectors@^4.0.2:
- version "4.0.2"
- resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-4.0.2.tgz#e2e5eb40bfee500d0cd9243500f5f8ea4262fbd8"
- integrity sha512-D5S1iViljXBj9kflQo4YutWnJmwm8VvIsU1GeXJGiG9j8CIg9zs4voPMdQDUmIxetUOh60VilsNzCiAFTOqu3g==
+postcss-minify-selectors@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-5.0.0.tgz#d3e43d97fd0ba83ba0010950fc5acfa420f7caa9"
+ integrity sha512-cEM0O0eWwFIvmo6nfB0lH0vO/XFwgqIvymODbfPXZ1gTA3i76FKnb7TGUrEpiTxaXH6tgYQ6DcTHwRiRS+YQLQ==
dependencies:
- alphanum-sort "^1.0.0"
- has "^1.0.0"
- postcss "^7.0.0"
- postcss-selector-parser "^3.0.0"
+ alphanum-sort "^1.0.2"
+ postcss-selector-parser "^3.1.2"
postcss-modules-extract-imports@^3.0.0:
version "3.0.0"
@@ -7394,228 +6428,105 @@ postcss-modules-values@^4.0.0:
dependencies:
icss-utils "^5.0.0"
-postcss-nesting@^7.0.0:
- version "7.0.1"
- resolved "https://registry.yarnpkg.com/postcss-nesting/-/postcss-nesting-7.0.1.tgz#b50ad7b7f0173e5b5e3880c3501344703e04c052"
- integrity sha512-FrorPb0H3nuVq0Sff7W2rnc3SmIcruVC6YwpcS+k687VxyxO33iE1amna7wHuRVzM8vfiYofXSBHNAZ3QhLvYg==
- dependencies:
- postcss "^7.0.2"
+postcss-normalize-charset@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-5.0.0.tgz#59e1fe2094fb2e3371cc5b054cbc39828a41a710"
+ integrity sha512-pqsCkgo9KmQP0ew6DqSA+uP9YN6EfsW20pQ3JU5JoQge09Z6Too4qU0TNDsTNWuEaP8SWsMp+19l15210MsDZQ==
-postcss-normalize-charset@^4.0.1:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-4.0.1.tgz#8b35add3aee83a136b0471e0d59be58a50285dd4"
- integrity sha512-gMXCrrlWh6G27U0hF3vNvR3w8I1s2wOBILvA87iNXaPvSNo5uZAMYsZG7XjCUf1eVxuPfyL4TJ7++SGZLc9A3g==
+postcss-normalize-display-values@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-5.0.0.tgz#4ff2d3b3b5146a366de28ec9e24131a1868f1933"
+ integrity sha512-t4f2d//gH1f7Ns0Jq3eNdnWuPT7TeLuISZ6RQx4j8gpl5XrhkdshdNcOnlrEK48YU6Tcb6jqK7dorME3N4oOGA==
dependencies:
- postcss "^7.0.0"
+ cssnano-utils "^2.0.0"
+ postcss-value-parser "^4.1.0"
-postcss-normalize-display-values@^4.0.2:
- version "4.0.2"
- resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.2.tgz#0dbe04a4ce9063d4667ed2be476bb830c825935a"
- integrity sha512-3F2jcsaMW7+VtRMAqf/3m4cPFhPD3EFRgNs18u+k3lTJJlVe7d0YPO+bnwqo2xg8YiRpDXJI2u8A0wqJxMsQuQ==
+postcss-normalize-positions@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-5.0.0.tgz#fe1d9a8122dd385b9c6908bd2008140dea17750d"
+ integrity sha512-0o6/qU5ky74X/eWYj/tv4iiKCm3YqJnrhmVADpIMNXxzFZywsSQxl8F7cKs8jQEtF3VrJBgcDHTexZy1zgDoYg==
dependencies:
- cssnano-util-get-match "^4.0.0"
- postcss "^7.0.0"
- postcss-value-parser "^3.0.0"
+ postcss-value-parser "^4.1.0"
-postcss-normalize-positions@^4.0.2:
- version "4.0.2"
- resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-4.0.2.tgz#05f757f84f260437378368a91f8932d4b102917f"
- integrity sha512-Dlf3/9AxpxE+NF1fJxYDeggi5WwV35MXGFnnoccP/9qDtFrTArZ0D0R+iKcg5WsUd8nUYMIl8yXDCtcrT8JrdA==
+postcss-normalize-repeat-style@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.0.0.tgz#e11d88fbf63f89179c6a7391853b2fe7f46e589d"
+ integrity sha512-KRT14JbrXKcFMYuc4q7lh8lvv8u22wLyMrq+UpHKLtbx2H/LOjvWXYdoDxmNrrrJzomAWL+ViEXr48/IhSUJnQ==
dependencies:
- cssnano-util-get-arguments "^4.0.0"
- has "^1.0.0"
- postcss "^7.0.0"
- postcss-value-parser "^3.0.0"
+ cssnano-utils "^2.0.0"
+ postcss-value-parser "^4.1.0"
-postcss-normalize-repeat-style@^4.0.2:
- version "4.0.2"
- resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-4.0.2.tgz#c4ebbc289f3991a028d44751cbdd11918b17910c"
- integrity sha512-qvigdYYMpSuoFs3Is/f5nHdRLJN/ITA7huIoCyqqENJe9PvPmLhNLMu7QTjPdtnVf6OcYYO5SHonx4+fbJE1+Q==
+postcss-normalize-string@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-5.0.0.tgz#2ea08ff4cb8817ce160755e9fdc7e6ef6d495002"
+ integrity sha512-wSO4pf7GNcDZpmelREWYADF1+XZWrAcbFLQCOqoE92ZwYgaP/RLumkUTaamEzdT2YKRZAH8eLLKGWotU/7FNPw==
dependencies:
- cssnano-util-get-arguments "^4.0.0"
- cssnano-util-get-match "^4.0.0"
- postcss "^7.0.0"
- postcss-value-parser "^3.0.0"
+ postcss-value-parser "^4.1.0"
-postcss-normalize-string@^4.0.2:
- version "4.0.2"
- resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-4.0.2.tgz#cd44c40ab07a0c7a36dc5e99aace1eca4ec2690c"
- integrity sha512-RrERod97Dnwqq49WNz8qo66ps0swYZDSb6rM57kN2J+aoyEAJfZ6bMx0sx/F9TIEX0xthPGCmeyiam/jXif0eA==
+postcss-normalize-timing-functions@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.0.0.tgz#380eb1c9b179f96efc307c659a8049116f16f381"
+ integrity sha512-TwPaDX+wl9wO3MUm23lzGmOzGCGKnpk+rSDgzB2INpakD5dgWR3L6bJq1P1LQYzBAvz8fRIj2NWdnZdV4EV98Q==
dependencies:
- has "^1.0.0"
- postcss "^7.0.0"
- postcss-value-parser "^3.0.0"
+ cssnano-utils "^2.0.0"
+ postcss-value-parser "^4.1.0"
-postcss-normalize-timing-functions@^4.0.2:
- version "4.0.2"
- resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-4.0.2.tgz#8e009ca2a3949cdaf8ad23e6b6ab99cb5e7d28d9"
- integrity sha512-acwJY95edP762e++00Ehq9L4sZCEcOPyaHwoaFOhIwWCDfik6YvqsYNxckee65JHLKzuNSSmAdxwD2Cud1Z54A==
+postcss-normalize-unicode@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-5.0.0.tgz#aa46a89c86ae51a01cbca13e73c1ed7b0b38807e"
+ integrity sha512-2CpVoz/67rXU5s9tsPZDxG1YGS9OFHwoY9gsLAzrURrCxTAb0H7Vp87/62LvVPgRWTa5ZmvgmqTp2rL8tlm72A==
dependencies:
- cssnano-util-get-match "^4.0.0"
- postcss "^7.0.0"
- postcss-value-parser "^3.0.0"
+ browserslist "^4.16.0"
+ postcss-value-parser "^4.1.0"
-postcss-normalize-unicode@^4.0.1:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-4.0.1.tgz#841bd48fdcf3019ad4baa7493a3d363b52ae1cfb"
- integrity sha512-od18Uq2wCYn+vZ/qCOeutvHjB5jm57ToxRaMeNuf0nWVHaP9Hua56QyMF6fs/4FSUnVIw0CBPsU0K4LnBPwYwg==
+postcss-normalize-url@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-5.0.0.tgz#626a4c7d30007f94466cdf245e7ed9f253f1dbd9"
+ integrity sha512-ICDaGFBqLgA3dlrCIRuhblLl80D13YtgEV9NJPTYJtgR72vu61KgxAHv+z/lKMs1EbwfSQa3ALjOFLSmXiE34A==
dependencies:
- browserslist "^4.0.0"
- postcss "^7.0.0"
- postcss-value-parser "^3.0.0"
+ is-absolute-url "^3.0.3"
+ normalize-url "^4.5.0"
+ postcss-value-parser "^4.1.0"
-postcss-normalize-url@^4.0.1:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-4.0.1.tgz#10e437f86bc7c7e58f7b9652ed878daaa95faae1"
- integrity sha512-p5oVaF4+IHwu7VpMan/SSpmpYxcJMtkGppYf0VbdH5B6hN8YNmVyJLuY9FmLQTzY3fag5ESUUHDqM+heid0UVA==
+postcss-normalize-whitespace@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.0.0.tgz#1faf147a4f8d3d93a3c75109d120b4eefa00589b"
+ integrity sha512-KRnxQvQAVkJfaeXSz7JlnD9nBN9sFZF9lrk9452Q2uRoqrRSkinqifF8Iex7wZGei2DZVG/qpmDFDmRvbNAOGA==
dependencies:
- is-absolute-url "^2.0.0"
- normalize-url "^3.0.0"
- postcss "^7.0.0"
- postcss-value-parser "^3.0.0"
+ postcss-value-parser "^4.1.0"
-postcss-normalize-whitespace@^4.0.2:
- version "4.0.2"
- resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-4.0.2.tgz#bf1d4070fe4fcea87d1348e825d8cc0c5faa7d82"
- integrity sha512-tO8QIgrsI3p95r8fyqKV+ufKlSHh9hMJqACqbv2XknufqEDhDvbguXGBBqxw9nsQoXWf0qOqppziKJKHMD4GtA==
+postcss-ordered-values@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-5.0.0.tgz#a50f224c5f40c566b338b0663655478737dcebee"
+ integrity sha512-dPr+SRObiHueCIc4IUaG0aOGQmYkuNu50wQvdXTGKy+rzi2mjmPsbeDsheLk5WPb9Zyf2tp8E+I+h40cnivm6g==
dependencies:
- postcss "^7.0.0"
- postcss-value-parser "^3.0.0"
+ cssnano-utils "^2.0.0"
+ postcss-value-parser "^4.1.0"
-postcss-ordered-values@^4.1.2:
- version "4.1.2"
- resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-4.1.2.tgz#0cf75c820ec7d5c4d280189559e0b571ebac0eee"
- integrity sha512-2fCObh5UanxvSxeXrtLtlwVThBvHn6MQcu4ksNT2tsaV2Fg76R2CV98W7wNSlX+5/pFwEyaDwKLLoEV7uRybAw==
+postcss-reduce-idents@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-reduce-idents/-/postcss-reduce-idents-5.0.0.tgz#a6fbc9369b955daa756fe578de2ed916c01eed56"
+ integrity sha512-wDth7wkXAZ91i7GNe+/PJKyC9NOR2n04U0t5nnqlvlkKhMhnRn/8NJLYQRa7ZZHPGOZcOfvugrhblioTTg2X8A==
dependencies:
- cssnano-util-get-arguments "^4.0.0"
- postcss "^7.0.0"
- postcss-value-parser "^3.0.0"
+ postcss-value-parser "^4.1.0"
-postcss-overflow-shorthand@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/postcss-overflow-shorthand/-/postcss-overflow-shorthand-2.0.0.tgz#31ecf350e9c6f6ddc250a78f0c3e111f32dd4c30"
- integrity sha512-aK0fHc9CBNx8jbzMYhshZcEv8LtYnBIRYQD5i7w/K/wS9c2+0NSR6B3OVMu5y0hBHYLcMGjfU+dmWYNKH0I85g==
+postcss-reduce-initial@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-5.0.0.tgz#c724e5513b0ae7f3d7bff16f0fc82133fb2f820a"
+ integrity sha512-wR6pXUaFbSMG1oCKx8pKVA+rnSXCHlca5jMrlmkmif+uig0HNUTV9oGN5kjKsM3mATQAldv2PF9Tbl2vqLFjnA==
dependencies:
- postcss "^7.0.2"
-
-postcss-page-break@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/postcss-page-break/-/postcss-page-break-2.0.0.tgz#add52d0e0a528cabe6afee8b46e2abb277df46bf"
- integrity sha512-tkpTSrLpfLfD9HvgOlJuigLuk39wVTbbd8RKcy8/ugV2bNBUW3xU+AIqyxhDrQr1VUj1RmyJrBn1YWrqUm9zAQ==
- dependencies:
- postcss "^7.0.2"
-
-postcss-place@^4.0.1:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/postcss-place/-/postcss-place-4.0.1.tgz#e9f39d33d2dc584e46ee1db45adb77ca9d1dcc62"
- integrity sha512-Zb6byCSLkgRKLODj/5mQugyuj9bvAAw9LqJJjgwz5cYryGeXfFZfSXoP1UfveccFmeq0b/2xxwcTEVScnqGxBg==
- dependencies:
- postcss "^7.0.2"
- postcss-values-parser "^2.0.0"
-
-postcss-preset-env@^6.7.0:
- version "6.7.0"
- resolved "https://registry.yarnpkg.com/postcss-preset-env/-/postcss-preset-env-6.7.0.tgz#c34ddacf8f902383b35ad1e030f178f4cdf118a5"
- integrity sha512-eU4/K5xzSFwUFJ8hTdTQzo2RBLbDVt83QZrAvI07TULOkmyQlnYlpwep+2yIK+K+0KlZO4BvFcleOCCcUtwchg==
- dependencies:
- autoprefixer "^9.6.1"
- browserslist "^4.6.4"
- caniuse-lite "^1.0.30000981"
- css-blank-pseudo "^0.1.4"
- css-has-pseudo "^0.10.0"
- css-prefers-color-scheme "^3.1.1"
- cssdb "^4.4.0"
- postcss "^7.0.17"
- postcss-attribute-case-insensitive "^4.0.1"
- postcss-color-functional-notation "^2.0.1"
- postcss-color-gray "^5.0.0"
- postcss-color-hex-alpha "^5.0.3"
- postcss-color-mod-function "^3.0.3"
- postcss-color-rebeccapurple "^4.0.1"
- postcss-custom-media "^7.0.8"
- postcss-custom-properties "^8.0.11"
- postcss-custom-selectors "^5.1.2"
- postcss-dir-pseudo-class "^5.0.0"
- postcss-double-position-gradients "^1.0.0"
- postcss-env-function "^2.0.2"
- postcss-focus-visible "^4.0.0"
- postcss-focus-within "^3.0.0"
- postcss-font-variant "^4.0.0"
- postcss-gap-properties "^2.0.0"
- postcss-image-set-function "^3.0.1"
- postcss-initial "^3.0.0"
- postcss-lab-function "^2.0.1"
- postcss-logical "^3.0.0"
- postcss-media-minmax "^4.0.0"
- postcss-nesting "^7.0.0"
- postcss-overflow-shorthand "^2.0.0"
- postcss-page-break "^2.0.0"
- postcss-place "^4.0.1"
- postcss-pseudo-class-any-link "^6.0.0"
- postcss-replace-overflow-wrap "^3.0.0"
- postcss-selector-matches "^4.0.0"
- postcss-selector-not "^4.0.0"
-
-postcss-pseudo-class-any-link@^6.0.0:
- version "6.0.0"
- resolved "https://registry.yarnpkg.com/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-6.0.0.tgz#2ed3eed393b3702879dec4a87032b210daeb04d1"
- integrity sha512-lgXW9sYJdLqtmw23otOzrtbDXofUdfYzNm4PIpNE322/swES3VU9XlXHeJS46zT2onFO7V1QFdD4Q9LiZj8mew==
- dependencies:
- postcss "^7.0.2"
- postcss-selector-parser "^5.0.0-rc.3"
-
-postcss-reduce-idents@^4.0.2:
- version "4.0.2"
- resolved "https://registry.yarnpkg.com/postcss-reduce-idents/-/postcss-reduce-idents-4.0.2.tgz#30447a6ec20941e78e21bd4482a11f569c4f455b"
- integrity sha512-Tz70Ri10TclPoCtFfftjFVddx3fZGUkr0dEDbIEfbYhFUOFQZZ77TEqRrU0e6TvAvF+Wa5VVzYTpFpq0uwFFzw==
- dependencies:
- postcss "^7.0.0"
- postcss-value-parser "^3.0.0"
-
-postcss-reduce-initial@^4.0.3:
- version "4.0.3"
- resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-4.0.3.tgz#7fd42ebea5e9c814609639e2c2e84ae270ba48df"
- integrity sha512-gKWmR5aUulSjbzOfD9AlJiHCGH6AEVLaM0AV+aSioxUDd16qXP1PCh8d1/BGVvpdWn8k/HiK7n6TjeoXN1F7DA==
- dependencies:
- browserslist "^4.0.0"
+ browserslist "^4.16.0"
caniuse-api "^3.0.0"
- has "^1.0.0"
- postcss "^7.0.0"
-postcss-reduce-transforms@^4.0.2:
- version "4.0.2"
- resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-4.0.2.tgz#17efa405eacc6e07be3414a5ca2d1074681d4e29"
- integrity sha512-EEVig1Q2QJ4ELpJXMZR8Vt5DQx8/mo+dGWSR7vWXqcob2gQLyQGsionYcGKATXvQzMPn6DSN1vTN7yFximdIAg==
+postcss-reduce-transforms@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-5.0.0.tgz#5c820f71fbd4eec82b323523642b7b2d1c7d29ef"
+ integrity sha512-iHdGODW4YzM3WjVecBhPQt6fpJC4lGQZxJKjkBNHpp2b8dzmvj0ogKThqya+IRodQEFzjfXgYeESkf172FH5Lw==
dependencies:
- cssnano-util-get-match "^4.0.0"
- has "^1.0.0"
- postcss "^7.0.0"
- postcss-value-parser "^3.0.0"
+ cssnano-utils "^2.0.0"
+ postcss-value-parser "^4.1.0"
-postcss-replace-overflow-wrap@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-3.0.0.tgz#61b360ffdaedca84c7c918d2b0f0d0ea559ab01c"
- integrity sha512-2T5hcEHArDT6X9+9dVSPQdo7QHzG4XKclFT8rU5TzJPDN7RIRTbO9c4drUISOVemLj03aezStHCR2AIcr8XLpw==
- dependencies:
- postcss "^7.0.2"
-
-postcss-selector-matches@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/postcss-selector-matches/-/postcss-selector-matches-4.0.0.tgz#71c8248f917ba2cc93037c9637ee09c64436fcff"
- integrity sha512-LgsHwQR/EsRYSqlwdGzeaPKVT0Ml7LAT6E75T8W8xLJY62CE4S/l03BWIt3jT8Taq22kXP08s2SfTSzaraoPww==
- dependencies:
- balanced-match "^1.0.0"
- postcss "^7.0.2"
-
-postcss-selector-not@^4.0.0:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/postcss-selector-not/-/postcss-selector-not-4.0.1.tgz#263016eef1cf219e0ade9a913780fc1f48204cbf"
- integrity sha512-YolvBgInEK5/79C+bdFMyzqTg6pkYqDbzZIST/PDMqa/o3qtXenD05apBG2jLgT0/BQ77d4U2UK12jWpilqMAQ==
- dependencies:
- balanced-match "^1.0.0"
- postcss "^7.0.2"
-
-postcss-selector-parser@^3.0.0:
+postcss-selector-parser@^3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz#b310f5c4c0fdaf76f94902bbaa30db6aa84f5270"
integrity sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==
@@ -7624,15 +6535,6 @@ postcss-selector-parser@^3.0.0:
indexes-of "^1.0.1"
uniq "^1.0.1"
-postcss-selector-parser@^5.0.0-rc.3, postcss-selector-parser@^5.0.0-rc.4:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz#249044356697b33b64f1a8f7c80922dddee7195c"
- integrity sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==
- dependencies:
- cssesc "^2.0.0"
- indexes-of "^1.0.1"
- uniq "^1.0.1"
-
postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4:
version "6.0.4"
resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.4.tgz#56075a1380a04604c38b063ea7767a129af5c2b3"
@@ -7643,92 +6545,51 @@ postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4:
uniq "^1.0.1"
util-deprecate "^1.0.2"
-postcss-sort-media-queries@^1.7.26:
- version "1.31.21"
- resolved "https://registry.yarnpkg.com/postcss-sort-media-queries/-/postcss-sort-media-queries-1.31.21.tgz#3225ec6eb490402602284ac99963b80461783cee"
- integrity sha512-h+HbXXfOVFeLvCJOzl/Z9SqQ25MNpG/73k71756ftisaaJy75h06/Dn6KOwC4OCMN10ewT2PXMzHV03JNKwBbg==
+postcss-sort-media-queries@^3.8.9:
+ version "3.10.11"
+ resolved "https://registry.yarnpkg.com/postcss-sort-media-queries/-/postcss-sort-media-queries-3.10.11.tgz#9e06c220c752c69d3ea4a6d55ac7d4960e201c4a"
+ integrity sha512-78Ak5YSnalr+UTdZa2OCSNAxvEnHg3GRqWccStljJW7MqeU0cJtMA5OzaMmn+upM+iI5vykWzibVEAYaaAlSzw==
dependencies:
- postcss "^7.0.27"
- sort-css-media-queries "1.5.0"
+ sort-css-media-queries "1.5.4"
-postcss-svgo@^4.0.2:
- version "4.0.2"
- resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-4.0.2.tgz#17b997bc711b333bab143aaed3b8d3d6e3d38258"
- integrity sha512-C6wyjo3VwFm0QgBy+Fu7gCYOkCmgmClghO+pjcxvrcBKtiKt0uCF+hvbMO1fyv5BMImRK90SMb+dwUnfbGd+jw==
+postcss-svgo@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-5.0.0.tgz#c8d806e573394ab24f1e233cac5be4c199e9f1b2"
+ integrity sha512-M3/VS4sFI1Yp9g0bPL+xzzCNz5iLdRUztoFaugMit5a8sMfkVzzhwqbsOlD8IFFymCdJDmXmh31waYHWw1K4BA==
dependencies:
- is-svg "^3.0.0"
- postcss "^7.0.0"
- postcss-value-parser "^3.0.0"
- svgo "^1.0.0"
+ postcss-value-parser "^4.1.0"
+ svgo "^2.3.0"
-postcss-unique-selectors@^4.0.1:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-4.0.1.tgz#9446911f3289bfd64c6d680f073c03b1f9ee4bac"
- integrity sha512-+JanVaryLo9QwZjKrmJgkI4Fn8SBgRO6WXQBJi7KiAVPlmxikB5Jzc4EvXMT2H0/m0RjrVVm9rGNhZddm/8Spg==
+postcss-unique-selectors@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-5.0.0.tgz#17856278f6c38d024defc9694d568bb09dd7f771"
+ integrity sha512-o9l4pF8SRn7aCMTmzb/kNv/kjV7wPZpZ8Nlb1Gq8v/Qvw969K1wanz1RVA0ehHzWe9+wHXaC2DvZlak/gdMJ5w==
dependencies:
- alphanum-sort "^1.0.0"
- postcss "^7.0.0"
+ alphanum-sort "^1.0.2"
+ postcss-selector-parser "^6.0.2"
uniqs "^2.0.0"
-postcss-value-parser@^3.0.0:
- version "3.3.1"
- resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281"
- integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==
-
postcss-value-parser@^4.0.2, postcss-value-parser@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz#443f6a20ced6481a2bda4fa8532a6e55d789a2cb"
integrity sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==
-postcss-values-parser@^2.0.0, postcss-values-parser@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/postcss-values-parser/-/postcss-values-parser-2.0.1.tgz#da8b472d901da1e205b47bdc98637b9e9e550e5f"
- integrity sha512-2tLuBsA6P4rYTNKCXYG/71C7j1pU6pK503suYOmn4xYrQIzW+opD+7FAFNuGSdZC/3Qfy334QbeMu7MEb8gOxg==
+postcss-zindex@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-zindex/-/postcss-zindex-5.0.0.tgz#ffed3576b5a9f0001a9d78fdc075466e1da1839c"
+ integrity sha512-thJp90qNZedxzfljsAnu7V35L/Zue/nVvWzPDLKZuqHmwDuy1vd3xkFVYfEa8WZZQaetvHtsi3uwjVD3UJAVeg==
dependencies:
- flatten "^1.0.2"
- indexes-of "^1.0.1"
- uniq "^1.0.1"
-
-postcss-zindex@^4.0.1:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/postcss-zindex/-/postcss-zindex-4.0.1.tgz#8db6a4cec3111e5d3fd99ea70abeda61873d10c1"
- integrity sha512-d/8BlQcUdEugZNRM9AdCA2V4fqREUtn/wcixLN3L6ITgc2P/FMcVVYz8QZkhItWT9NB5qr8wuN2dJCE4/+dlrA==
- dependencies:
- has "^1.0.0"
- postcss "^7.0.0"
+ has "^1.0.3"
uniqs "^2.0.0"
-postcss@^6.0.23:
- version "6.0.23"
- resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.23.tgz#61c82cc328ac60e677645f979054eb98bc0e3324"
- integrity sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==
- dependencies:
- chalk "^2.4.1"
- source-map "^0.6.1"
- supports-color "^5.4.0"
-
-postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.17, postcss@^7.0.2, postcss@^7.0.27, postcss@^7.0.32, postcss@^7.0.5, postcss@^7.0.6:
- version "7.0.35"
- resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.35.tgz#d2be00b998f7f211d8a276974079f2e92b970e24"
- integrity sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==
- dependencies:
- chalk "^2.4.2"
- source-map "^0.6.1"
- supports-color "^6.1.0"
-
-postcss@^8.2.7, postcss@^8.2.8:
- version "8.2.8"
- resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.2.8.tgz#0b90f9382efda424c4f0f69a2ead6f6830d08ece"
- integrity sha512-1F0Xb2T21xET7oQV9eKuctbM9S7BC0fetoHCc4H13z0PT6haiRLP4T0ZY4XWh7iLP0usgqykT6p9B2RtOf4FPw==
+postcss@^8.2.10, postcss@^8.2.4, postcss@^8.2.8, postcss@^8.2.9:
+ version "8.3.0"
+ resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.3.0.tgz#b1a713f6172ca427e3f05ef1303de8b65683325f"
+ integrity sha512-+ogXpdAjWGa+fdYY5BQ96V/6tAo+TdSSIMP5huJBIygdWwKtVoB5JWZ7yUd4xZ8r+8Kvvx4nyg/PQ071H4UtcQ==
dependencies:
colorette "^1.2.2"
- nanoid "^3.1.20"
- source-map "^0.6.1"
-
-prepend-http@^1.0.0:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc"
- integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=
+ nanoid "^3.1.23"
+ source-map-js "^0.6.2"
prepend-http@^2.0.0:
version "2.0.0"
@@ -7765,16 +6626,6 @@ process-nextick-args@~2.0.0:
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
-process@^0.11.10:
- version "0.11.10"
- resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
- integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI=
-
-promise-inflight@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3"
- integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM=
-
promise@^7.1.1:
version "7.3.1"
resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf"
@@ -7819,26 +6670,6 @@ prr@~1.0.1:
resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476"
integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY=
-public-encrypt@^4.0.0:
- version "4.0.3"
- resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0"
- integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==
- dependencies:
- bn.js "^4.1.0"
- browserify-rsa "^4.0.0"
- create-hash "^1.1.0"
- parse-asn1 "^5.0.0"
- randombytes "^2.0.1"
- safe-buffer "^5.1.2"
-
-pump@^2.0.0:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909"
- integrity sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==
- dependencies:
- end-of-stream "^1.1.0"
- once "^1.3.1"
-
pump@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64"
@@ -7847,21 +6678,12 @@ pump@^3.0.0:
end-of-stream "^1.1.0"
once "^1.3.1"
-pumpify@^1.3.3:
- version "1.5.1"
- resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.5.1.tgz#36513be246ab27570b1a374a5ce278bfd74370ce"
- integrity sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==
- dependencies:
- duplexify "^3.6.0"
- inherits "^2.0.3"
- pump "^2.0.0"
-
punycode@1.3.2:
version "1.3.2"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d"
integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=
-punycode@^1.2.4, punycode@^1.3.2:
+punycode@^1.3.2:
version "1.4.1"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
integrity sha1-wNWmOycYgArY4esPpSachN1BhF4=
@@ -7893,19 +6715,6 @@ qs@6.7.0:
resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc"
integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==
-query-string@^4.1.0:
- version "4.3.4"
- resolved "https://registry.yarnpkg.com/query-string/-/query-string-4.3.4.tgz#bbb693b9ca915c232515b228b1a02b609043dbeb"
- integrity sha1-u7aTucqRXCMlFbIosaArYJBD2+s=
- dependencies:
- object-assign "^4.1.0"
- strict-uri-encode "^1.0.0"
-
-querystring-es3@^0.2.0:
- version "0.2.1"
- resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73"
- integrity sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=
-
querystring@0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620"
@@ -7921,21 +6730,13 @@ queue-microtask@^1.2.2:
resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==
-randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0:
+randombytes@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a"
integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==
dependencies:
safe-buffer "^5.1.0"
-randomfill@^1.0.3:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458"
- integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==
- dependencies:
- randombytes "^2.0.5"
- safe-buffer "^5.1.0"
-
range-parser@1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e"
@@ -8056,10 +6857,10 @@ react-lifecycles-compat@^3.0.4:
resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"
integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==
-react-loadable-ssr-addon@^0.3.0:
- version "0.3.0"
- resolved "https://registry.yarnpkg.com/react-loadable-ssr-addon/-/react-loadable-ssr-addon-0.3.0.tgz#ae9b2d3b11721930f8d8255476d288c0e9f9290f"
- integrity sha512-E+lnmDakV0k6ut6R2J77vurwCOwTKEwKlHs9S62G8ez+ujecLPcqjt3YAU8M58kIGjp2QjFlZ7F9QWkq/mr6Iw==
+react-loadable-ssr-addon-v5-slorber@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/react-loadable-ssr-addon-v5-slorber/-/react-loadable-ssr-addon-v5-slorber-1.0.1.tgz#2cdc91e8a744ffdf9e3556caabeb6e4278689883"
+ integrity sha512-lq3Lyw1lGku8zUEJPDxsNm1AfYHBrO9Y1+olAYwpUJ2IGFBskM0DMKok97A6LWUpHm+o7IvQBOWu9MLenp9Z+A==
dependencies:
"@babel/runtime" "^7.10.3"
@@ -8128,13 +6929,6 @@ react-textarea-autosize@^8.3.2:
use-composed-ref "^1.0.0"
use-latest "^1.0.0"
-react-toggle@^4.1.2:
- version "4.1.2"
- resolved "https://registry.yarnpkg.com/react-toggle/-/react-toggle-4.1.2.tgz#b00500832f925ad524356d909821821ae39f6c52"
- integrity sha512-4Ohw31TuYQdhWfA6qlKafeXx3IOH7t4ZHhmRdwsm1fQREwOBGxJT+I22sgHqR/w8JRdk+AeMCJXPImEFSrNXow==
- dependencies:
- classnames "^2.2.5"
-
react@^16.10.2, react@^16.3.1:
version "16.14.0"
resolved "https://registry.yarnpkg.com/react/-/react-16.14.0.tgz#94d776ddd0aaa37da3eda8fc5b6b18a4c9a3114d"
@@ -8144,7 +6938,7 @@ react@^16.10.2, react@^16.3.1:
object-assign "^4.1.1"
prop-types "^15.6.2"
-"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6:
+readable-stream@^2.0.1, readable-stream@^2.0.2:
version "2.3.7"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==
@@ -8157,7 +6951,7 @@ react@^16.10.2, react@^16.3.1:
string_decoder "~1.1.1"
util-deprecate "~1.0.1"
-readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.6.0:
+readable-stream@^3.0.6, readable-stream@^3.1.1:
version "3.6.0"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==
@@ -8477,7 +7271,7 @@ rgba-regex@^1.0.0:
resolved "https://registry.yarnpkg.com/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3"
integrity sha1-QzdOLiyglosO8VI0YLfXMP8i7rM=
-rimraf@^2.5.4, rimraf@^2.6.3:
+rimraf@^2.6.3:
version "2.7.1"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec"
integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==
@@ -8491,24 +7285,21 @@ rimraf@^3.0.2:
dependencies:
glob "^7.1.3"
-ripemd160@^2.0.0, ripemd160@^2.0.1:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c"
- integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==
- dependencies:
- hash-base "^3.0.0"
- inherits "^2.0.1"
+rtl-detect@^1.0.2:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/rtl-detect/-/rtl-detect-1.0.3.tgz#42145b9a4f9cf0b94c4542aba90d57f0d18559bf"
+ integrity sha512-2sMcZO60tL9YDEFe24gqddg3hJ+xSmJFN8IExcQUxeHxQzydQrN6GHPL+yAWgzItXSI7es53hcZC9pJneuZDKA==
-rtlcss@^2.6.2:
- version "2.6.2"
- resolved "https://registry.yarnpkg.com/rtlcss/-/rtlcss-2.6.2.tgz#55b572b52c70015ba6e03d497e5c5cb8137104b4"
- integrity sha512-06LFAr+GAPo+BvaynsXRfoYTJvSaWRyOhURCQ7aeI1MKph9meM222F+Zkt3bDamyHHJuGi3VPtiRkpyswmQbGA==
+rtlcss@^3.1.2:
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/rtlcss/-/rtlcss-3.1.2.tgz#4800d3d03525791a720f676a8ad2c6acf8efdfb2"
+ integrity sha512-b04YSX37siupPOWUEguEBReWX2w4QT89C0PI9g2JzZycbq7zrgPmTr1DA1pizSWpKRFdCjjnrx/SSvU4fOHmGg==
dependencies:
- "@choojs/findup" "^0.2.1"
- chalk "^2.4.2"
- mkdirp "^0.5.1"
- postcss "^6.0.23"
- strip-json-comments "^2.0.0"
+ chalk "^4.1.0"
+ find-up "^5.0.0"
+ mkdirp "^1.0.4"
+ postcss "^8.2.4"
+ strip-json-comments "^3.1.1"
run-parallel@^1.1.9:
version "1.2.0"
@@ -8517,13 +7308,6 @@ run-parallel@^1.1.9:
dependencies:
queue-microtask "^1.2.2"
-run-queue@^1.0.0, run-queue@^1.0.3:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47"
- integrity sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=
- dependencies:
- aproba "^1.1.1"
-
rxjs@^6.6.3:
version "6.6.6"
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.6.tgz#14d8417aa5a07c5e633995b525e1e3c0dec03b70"
@@ -8536,7 +7320,7 @@ safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
-safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0:
+safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@~5.2.0:
version "5.2.1"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
@@ -8548,7 +7332,7 @@ safe-regex@^1.1.0:
dependencies:
ret "~0.1.10"
-"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.1.0:
+"safer-buffer@>= 2.1.2 < 3":
version "2.1.2"
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
@@ -8575,7 +7359,7 @@ schema-utils@^1.0.0:
ajv-errors "^1.0.0"
ajv-keywords "^3.1.0"
-schema-utils@^2.0.0, schema-utils@^2.6.5:
+schema-utils@^2.6.5:
version "2.7.1"
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.1.tgz#1ca4f32d1b24c590c203b8e7a50bf0ea4cd394d7"
integrity sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==
@@ -8666,13 +7450,6 @@ send@0.17.1:
range-parser "~1.2.1"
statuses "~1.5.0"
-serialize-javascript@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-4.0.0.tgz#b525e1238489a5ecfc42afacc3fe99e666f4b1aa"
- integrity sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==
- dependencies:
- randombytes "^2.1.0"
-
serialize-javascript@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-5.0.1.tgz#7886ec848049a462467a97d3d918ebb2aaf934f4"
@@ -8732,7 +7509,7 @@ set-value@^2.0.0, set-value@^2.0.1:
is-plain-object "^2.0.3"
split-string "^3.0.1"
-setimmediate@^1.0.4, setimmediate@^1.0.5:
+setimmediate@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285"
integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=
@@ -8747,13 +7524,12 @@ setprototypeof@1.1.1:
resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683"
integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==
-sha.js@^2.4.0, sha.js@^2.4.8:
- version "2.4.11"
- resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7"
- integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==
+shallow-clone@^3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3"
+ integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==
dependencies:
- inherits "^2.0.1"
- safe-buffer "^5.0.1"
+ kind-of "^6.0.2"
shebang-command@^1.2.0:
version "1.2.0"
@@ -8885,23 +7661,21 @@ sockjs@^0.3.21:
uuid "^3.4.0"
websocket-driver "^0.7.4"
-sort-css-media-queries@1.5.0:
- version "1.5.0"
- resolved "https://registry.yarnpkg.com/sort-css-media-queries/-/sort-css-media-queries-1.5.0.tgz#8f605ad372caad0b81be010311882c046e738093"
- integrity sha512-QofNE7CEVH1AKdhS7L9IPbV9UtyQYNXyw++8lC+xG6iOLlpzsmncZRiKbihTAESvZ8wOhwnPoesHbMrehrQyyw==
+sort-css-media-queries@1.5.4:
+ version "1.5.4"
+ resolved "https://registry.yarnpkg.com/sort-css-media-queries/-/sort-css-media-queries-1.5.4.tgz#24182b12002a13d01ba943ddf74f5098d7c244ce"
+ integrity sha512-YP5W/h4Sid/YP7Lp87ejJ5jP13/Mtqt2vx33XyhO+IAugKlufRPbOrPlIiEUuxmpNBSBd3EeeQpFhdu3RfI2Ag==
-sort-keys@^1.0.0:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-1.1.2.tgz#441b6d4d346798f1b4e49e8920adfba0e543f9ad"
- integrity sha1-RBttTTRnmPG05J6JIK37oOVD+a0=
- dependencies:
- is-plain-obj "^1.0.0"
-
-source-list-map@^2.0.0:
+source-list-map@^2.0.0, source-list-map@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34"
integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==
+source-map-js@^0.6.2:
+ version "0.6.2"
+ resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-0.6.2.tgz#0bb5de631b41cfbda6cfba8bd05a80efdfd2385e"
+ integrity sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug==
+
source-map-resolve@^0.5.0:
version "0.5.3"
resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a"
@@ -8936,7 +7710,7 @@ source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1:
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
-source-map@^0.7.3, source-map@~0.7.2:
+source-map@~0.7.2:
version "0.7.3"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383"
integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==
@@ -8981,20 +7755,6 @@ sprintf-js@~1.0.2:
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=
-ssri@^6.0.1:
- version "6.0.1"
- resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.1.tgz#2a3c41b28dd45b62b63676ecb74001265ae9edd8"
- integrity sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==
- dependencies:
- figgy-pudding "^3.5.1"
-
-ssri@^8.0.1:
- version "8.0.1"
- resolved "https://registry.yarnpkg.com/ssri/-/ssri-8.0.1.tgz#638e4e439e2ffbd2cd289776d5ca457c4f51a2af"
- integrity sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==
- dependencies:
- minipass "^3.1.1"
-
stable@^0.1.8:
version "0.1.8"
resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf"
@@ -9025,43 +7785,6 @@ std-env@^2.2.1:
dependencies:
ci-info "^3.0.0"
-stream-browserify@^2.0.1:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b"
- integrity sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==
- dependencies:
- inherits "~2.0.1"
- readable-stream "^2.0.2"
-
-stream-each@^1.1.0:
- version "1.2.3"
- resolved "https://registry.yarnpkg.com/stream-each/-/stream-each-1.2.3.tgz#ebe27a0c389b04fbcc233642952e10731afa9bae"
- integrity sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==
- dependencies:
- end-of-stream "^1.1.0"
- stream-shift "^1.0.0"
-
-stream-http@^2.7.2:
- version "2.8.3"
- resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.3.tgz#b2d242469288a5a27ec4fe8933acf623de6514fc"
- integrity sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==
- dependencies:
- builtin-status-codes "^3.0.0"
- inherits "^2.0.1"
- readable-stream "^2.3.6"
- to-arraybuffer "^1.0.0"
- xtend "^4.0.0"
-
-stream-shift@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d"
- integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==
-
-strict-uri-encode@^1.0.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713"
- integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=
-
string-width@^3.0.0, string-width@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961"
@@ -9096,7 +7819,7 @@ string.prototype.trimstart@^1.0.4:
call-bind "^1.0.2"
define-properties "^1.1.3"
-string_decoder@^1.0.0, string_decoder@^1.1.1:
+string_decoder@^1.1.1:
version "1.3.0"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e"
integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==
@@ -9155,7 +7878,12 @@ strip-final-newline@^2.0.0:
resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad"
integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==
-strip-json-comments@^2.0.0, strip-json-comments@~2.0.1:
+strip-json-comments@^3.1.1:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
+ integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
+
+strip-json-comments@~2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo=
@@ -9167,16 +7895,15 @@ style-to-object@0.3.0, style-to-object@^0.3.0:
dependencies:
inline-style-parser "0.1.1"
-stylehacks@^4.0.0:
- version "4.0.3"
- resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-4.0.3.tgz#6718fcaf4d1e07d8a1318690881e8d96726a71d5"
- integrity sha512-7GlLk9JwlElY4Y6a/rmbH2MhVlTyVmiJd1PfTCqFaIBEGMYNsrO/v3SeGTdhBThLg4Z+NbOk/qFMwCa+J+3p/g==
+stylehacks@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-5.0.0.tgz#c49b0b2cf9917fe37dc030b96a4c34698b932933"
+ integrity sha512-QOWm6XivDLb+fqffTZP8jrmPmPITVChl2KCY2R05nsCWwLi3VGhCdVc3IVGNwd1zzTt1jPd67zIKjpQfxzQZeA==
dependencies:
- browserslist "^4.0.0"
- postcss "^7.0.0"
- postcss-selector-parser "^3.0.0"
+ browserslist "^4.16.0"
+ postcss-selector-parser "^6.0.4"
-supports-color@^5.3.0, supports-color@^5.4.0:
+supports-color@^5.3.0:
version "5.5.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
@@ -9202,7 +7929,7 @@ svg-parser@^2.0.2:
resolved "https://registry.yarnpkg.com/svg-parser/-/svg-parser-2.0.4.tgz#fdc2e29e13951736140b76cb122c8ee6630eb6b5"
integrity sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==
-svgo@^1.0.0, svgo@^1.2.2:
+svgo@^1.2.2:
version "1.3.2"
resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.3.2.tgz#b6dc511c063346c9e415b81e43401145b96d4167"
integrity sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw==
@@ -9221,54 +7948,42 @@ svgo@^1.0.0, svgo@^1.2.2:
unquote "~1.1.1"
util.promisify "~1.0.0"
-tapable@^1.0.0, tapable@^1.1.3:
+svgo@^2.3.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/svgo/-/svgo-2.3.0.tgz#6b3af81d0cbd1e19c83f5f63cec2cb98c70b5373"
+ integrity sha512-fz4IKjNO6HDPgIQxu4IxwtubtbSfGEAJUq/IXyTPIkGhWck/faiiwfkvsB8LnBkKLvSoyNNIY6d13lZprJMc9Q==
+ dependencies:
+ "@trysound/sax" "0.1.1"
+ chalk "^4.1.0"
+ commander "^7.1.0"
+ css-select "^3.1.2"
+ css-tree "^1.1.2"
+ csso "^4.2.0"
+ stable "^0.1.8"
+
+tapable@^1.0.0:
version "1.1.3"
resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2"
integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==
-tar@^6.0.2:
- version "6.1.0"
- resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.0.tgz#d1724e9bcc04b977b18d5c573b333a2207229a83"
- integrity sha512-DUCttfhsnLCjwoDoFcI+B2iJgYa93vBnDUATYEeRx6sntCTdN01VnqsIuTlALXla/LWooNg0yEGeB+Y8WdFxGA==
- dependencies:
- chownr "^2.0.0"
- fs-minipass "^2.0.0"
- minipass "^3.0.0"
- minizlib "^2.1.1"
- mkdirp "^1.0.3"
- yallist "^4.0.0"
+tapable@^2.0.0, tapable@^2.1.1, tapable@^2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.0.tgz#5c373d281d9c672848213d0e037d1c4165ab426b"
+ integrity sha512-FBk4IesMV1rBxX2tfiK8RAmogtWn53puLOQlvO8XuwlgxcYbP4mVPS9Ph4aeamSyyVjOl24aYWAuc8U5kCVwMw==
-terser-webpack-plugin@^1.4.3:
- version "1.4.5"
- resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz#a217aefaea330e734ffacb6120ec1fa312d6040b"
- integrity sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==
+terser-webpack-plugin@^5.1.1:
+ version "5.1.2"
+ resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.1.2.tgz#51d295eb7cc56785a67a372575fdc46e42d5c20c"
+ integrity sha512-6QhDaAiVHIQr5Ab3XUWZyDmrIPCHMiqJVljMF91YKyqwKkL5QHnYMkrMBy96v9Z7ev1hGhSEw1HQZc2p/s5Z8Q==
dependencies:
- cacache "^12.0.2"
- find-cache-dir "^2.1.0"
- is-wsl "^1.1.0"
- schema-utils "^1.0.0"
- serialize-javascript "^4.0.0"
- source-map "^0.6.1"
- terser "^4.1.2"
- webpack-sources "^1.4.0"
- worker-farm "^1.7.0"
-
-terser-webpack-plugin@^4.1.0:
- version "4.2.3"
- resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-4.2.3.tgz#28daef4a83bd17c1db0297070adc07fc8cfc6a9a"
- integrity sha512-jTgXh40RnvOrLQNgIkwEKnQ8rmHjHK4u+6UBEi+W+FPmvb+uo+chJXntKe7/3lW5mNysgSWD60KyesnhW8D6MQ==
- dependencies:
- cacache "^15.0.5"
- find-cache-dir "^3.3.1"
- jest-worker "^26.5.0"
- p-limit "^3.0.2"
+ jest-worker "^26.6.2"
+ p-limit "^3.1.0"
schema-utils "^3.0.0"
serialize-javascript "^5.0.1"
source-map "^0.6.1"
- terser "^5.3.4"
- webpack-sources "^1.4.3"
+ terser "^5.7.0"
-terser@^4.1.2, terser@^4.6.3:
+terser@^4.6.3:
version "4.8.0"
resolved "https://registry.yarnpkg.com/terser/-/terser-4.8.0.tgz#63056343d7c70bb29f3af665865a46fe03a0df17"
integrity sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==
@@ -9277,10 +7992,10 @@ terser@^4.1.2, terser@^4.6.3:
source-map "~0.6.1"
source-map-support "~0.5.12"
-terser@^5.3.4:
- version "5.6.1"
- resolved "https://registry.yarnpkg.com/terser/-/terser-5.6.1.tgz#a48eeac5300c0a09b36854bf90d9c26fb201973c"
- integrity sha512-yv9YLFQQ+3ZqgWCUk+pvNJwgUTdlIxUk1WTN+RnaFJe2L7ipG2csPT0ra2XRm7Cs8cxN7QXmK1rFzEwYEQkzXw==
+terser@^5.7.0:
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/terser/-/terser-5.7.0.tgz#a761eeec206bc87b605ab13029876ead938ae693"
+ integrity sha512-HP5/9hp2UaZt5fYkuhNBR8YyRcT8juw8+uFbAme53iN9hblvKnLUTKkmwJG6ocWpIKf8UK4DoeWG4ty0J6S6/g==
dependencies:
commander "^2.20.0"
source-map "~0.7.2"
@@ -9291,26 +8006,11 @@ text-table@0.2.0, text-table@^0.2.0:
resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=
-through2@^2.0.0:
- version "2.0.5"
- resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd"
- integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==
- dependencies:
- readable-stream "~2.3.6"
- xtend "~4.0.1"
-
thunky@^1.0.2:
version "1.1.0"
resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d"
integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==
-timers-browserify@^2.0.4:
- version "2.0.12"
- resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.12.tgz#44a45c11fbf407f34f97bccd1577c652361b00ee"
- integrity sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==
- dependencies:
- setimmediate "^1.0.4"
-
timsort@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4"
@@ -9331,11 +8031,6 @@ tiny-warning@^1.0.0, tiny-warning@^1.0.3:
resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754"
integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==
-to-arraybuffer@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43"
- integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=
-
to-fast-properties@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
@@ -9408,11 +8103,6 @@ ts-essentials@^2.0.3:
resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-2.0.12.tgz#c9303f3d74f75fa7528c3d49b80e089ab09d8745"
integrity sha512-3IVX4nI6B5cc31/GFFE+i8ey/N2eA0CZDbo6n0yrz0zDX8ZJ8djmU1p+XRz7G3is0F3bB3pu2pAroFdAWQKU3w==
-ts-pnp@^1.1.6:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.2.0.tgz#a500ad084b0798f1c3071af391e65912c86bca92"
- integrity sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw==
-
tslib@^1.9.0:
version "1.14.1"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
@@ -9423,10 +8113,10 @@ tslib@^2.0.3:
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.1.0.tgz#da60860f1c2ecaa5703ab7d39bc05b6bf988b97a"
integrity sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==
-tty-browserify@0.0.0:
- version "0.0.0"
- resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6"
- integrity sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=
+tslib@^2.1.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.2.0.tgz#fb2c475977e35e241311ede2693cee1ec6698f5c"
+ integrity sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==
type-fest@^0.20.2:
version "0.20.2"
@@ -9453,11 +8143,6 @@ typedarray-to-buffer@^3.1.5:
dependencies:
is-typedarray "^1.0.0"
-typedarray@^0.0.6:
- version "0.0.6"
- resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
- integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
-
ua-parser-js@^0.7.18:
version "0.7.25"
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.25.tgz#67689fa263a87a52dabbc251ede89891f59156ce"
@@ -9547,20 +8232,6 @@ uniqs@^2.0.0:
resolved "https://registry.yarnpkg.com/uniqs/-/uniqs-2.0.0.tgz#ffede4b36b25290696e6e165d4a59edb998e6b02"
integrity sha1-/+3ks2slKQaW5uFl1KWe25mOawI=
-unique-filename@^1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230"
- integrity sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==
- dependencies:
- unique-slug "^2.0.0"
-
-unique-slug@^2.0.0:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.2.tgz#baabce91083fc64e945b0f3ad613e264f7cd4e6c"
- integrity sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==
- dependencies:
- imurmurhash "^0.1.4"
-
unique-string@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-2.0.0.tgz#39c6451f81afb2749de2b233e3f7c5e8843bd89d"
@@ -9747,14 +8418,6 @@ util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1:
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
-util.promisify@1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.0.tgz#440f7165a459c9a16dc145eb8e72f35687097030"
- integrity sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==
- dependencies:
- define-properties "^1.1.2"
- object.getownpropertydescriptors "^2.0.3"
-
util.promisify@~1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.1.tgz#6baf7774b80eeb0f7520d8b81d07982a59abbaee"
@@ -9765,20 +8428,6 @@ util.promisify@~1.0.0:
has-symbols "^1.0.1"
object.getownpropertydescriptors "^2.1.0"
-util@0.10.3:
- version "0.10.3"
- resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9"
- integrity sha1-evsa/lCAUkZInj23/g7TeTNqwPk=
- dependencies:
- inherits "2.0.1"
-
-util@^0.11.0:
- version "0.11.1"
- resolved "https://registry.yarnpkg.com/util/-/util-0.11.1.tgz#3236733720ec64bb27f6e26f421aaa2e1b588d61"
- integrity sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==
- dependencies:
- inherits "2.0.3"
-
utila@~0.4:
version "0.4.0"
resolved "https://registry.yarnpkg.com/utila/-/utila-0.4.0.tgz#8a16a05d445657a3aea5eecc5b12a4fa5379772c"
@@ -9809,7 +8458,7 @@ vary@~1.1.2:
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=
-vendors@^1.0.0:
+vendors@^1.0.3:
version "1.0.4"
resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.4.tgz#e2b800a53e7a29b93506c3cf41100d16c4c4ad8e"
integrity sha512-/juG65kTL4Cy2su4P8HjtkTxk6VmJDiOPBufWniqQ6wknac6jNiXS9vU+hO3wgusiyqWlzTbVHi0dyJqRONg3w==
@@ -9837,11 +8486,6 @@ vfile@^4.0.0:
unist-util-stringify-position "^2.0.0"
vfile-message "^2.0.0"
-vm-browserify@^1.0.1:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0"
- integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==
-
wait-on@^5.2.1:
version "5.3.0"
resolved "https://registry.yarnpkg.com/wait-on/-/wait-on-5.3.0.tgz#584e17d4b3fe7b46ac2b9f8e5e102c005c2776c7"
@@ -9853,23 +8497,13 @@ wait-on@^5.2.1:
minimist "^1.2.5"
rxjs "^6.6.3"
-watchpack-chokidar2@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/watchpack-chokidar2/-/watchpack-chokidar2-2.0.1.tgz#38500072ee6ece66f3769936950ea1771be1c957"
- integrity sha512-nCFfBIPKr5Sh61s4LPpy1Wtfi0HE8isJ3d2Yb5/Ppw2P2B/3eVSEBjKfN0fmHJSK14+31KwMKmcrzs2GM4P0Ww==
- dependencies:
- chokidar "^2.1.8"
-
-watchpack@^1.7.4:
- version "1.7.5"
- resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.7.5.tgz#1267e6c55e0b9b5be44c2023aed5437a2c26c453"
- integrity sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ==
+watchpack@^2.0.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.2.0.tgz#47d78f5415fe550ecd740f99fe2882323a58b1ce"
+ integrity sha512-up4YAn/XHgZHIxFBVCdlMiWDj6WaLKpwVeGQk2I5thdYxF/KmF0aaz6TfJZ/hfl1h/XlcDr7k1KH7ThDagpFaA==
dependencies:
+ glob-to-regexp "^0.4.1"
graceful-fs "^4.1.2"
- neo-async "^2.5.0"
- optionalDependencies:
- chokidar "^3.4.1"
- watchpack-chokidar2 "^2.0.1"
wbuf@^1.1.0, wbuf@^1.7.3:
version "1.7.3"
@@ -9956,14 +8590,15 @@ webpack-log@^2.0.0:
ansi-colors "^3.0.0"
uuid "^3.3.2"
-webpack-merge@^4.2.2:
- version "4.2.2"
- resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-4.2.2.tgz#a27c52ea783d1398afd2087f547d7b9d2f43634d"
- integrity sha512-TUE1UGoTX2Cd42j3krGYqObZbOD+xF7u28WB7tfUordytSjbWTIjK/8V0amkBfTYN4/pB/GIDlJZZ657BGG19g==
+webpack-merge@^5.7.3:
+ version "5.7.3"
+ resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.7.3.tgz#2a0754e1877a25a8bbab3d2475ca70a052708213"
+ integrity sha512-6/JUQv0ELQ1igjGDzHkXbVDRxkfA57Zw7PfiupdLFJYrgFqY5ZP8xxbpp2lU3EPwYx89ht5Z/aDkD40hFCm5AA==
dependencies:
- lodash "^4.17.15"
+ clone-deep "^4.0.1"
+ wildcard "^2.0.0"
-webpack-sources@^1.1.0, webpack-sources@^1.4.0, webpack-sources@^1.4.1, webpack-sources@^1.4.3:
+webpack-sources@^1.1.0, webpack-sources@^1.4.3:
version "1.4.3"
resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933"
integrity sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==
@@ -9971,34 +8606,42 @@ webpack-sources@^1.1.0, webpack-sources@^1.4.0, webpack-sources@^1.4.1, webpack-
source-list-map "^2.0.0"
source-map "~0.6.1"
-webpack@^4.44.1:
- version "4.46.0"
- resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.46.0.tgz#bf9b4404ea20a073605e0a011d188d77cb6ad542"
- integrity sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q==
+webpack-sources@^2.1.1:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-2.2.0.tgz#058926f39e3d443193b6c31547229806ffd02bac"
+ integrity sha512-bQsA24JLwcnWGArOKUxYKhX3Mz/nK1Xf6hxullKERyktjNMC4x8koOeaDNTA2fEJ09BdWLbM/iTW0ithREUP0w==
dependencies:
- "@webassemblyjs/ast" "1.9.0"
- "@webassemblyjs/helper-module-context" "1.9.0"
- "@webassemblyjs/wasm-edit" "1.9.0"
- "@webassemblyjs/wasm-parser" "1.9.0"
- acorn "^6.4.1"
- ajv "^6.10.2"
- ajv-keywords "^3.4.1"
+ source-list-map "^2.0.1"
+ source-map "^0.6.1"
+
+webpack@^5.28.0:
+ version "5.37.1"
+ resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.37.1.tgz#2deb5acd350583c1ab9338471f323381b0b0c14b"
+ integrity sha512-btZjGy/hSjCAAVHw+cKG+L0M+rstlyxbO2C+BOTaQ5/XAnxkDrP5sVbqWhXgo4pL3X2dcOib6rqCP20Zr9PLow==
+ dependencies:
+ "@types/eslint-scope" "^3.7.0"
+ "@types/estree" "^0.0.47"
+ "@webassemblyjs/ast" "1.11.0"
+ "@webassemblyjs/wasm-edit" "1.11.0"
+ "@webassemblyjs/wasm-parser" "1.11.0"
+ acorn "^8.2.1"
+ browserslist "^4.14.5"
chrome-trace-event "^1.0.2"
- enhanced-resolve "^4.5.0"
- eslint-scope "^4.0.3"
+ enhanced-resolve "^5.8.0"
+ es-module-lexer "^0.4.0"
+ eslint-scope "^5.1.1"
+ events "^3.2.0"
+ glob-to-regexp "^0.4.1"
+ graceful-fs "^4.2.4"
json-parse-better-errors "^1.0.2"
- loader-runner "^2.4.0"
- loader-utils "^1.2.3"
- memory-fs "^0.4.1"
- micromatch "^3.1.10"
- mkdirp "^0.5.3"
- neo-async "^2.6.1"
- node-libs-browser "^2.2.1"
- schema-utils "^1.0.0"
- tapable "^1.1.3"
- terser-webpack-plugin "^1.4.3"
- watchpack "^1.7.4"
- webpack-sources "^1.4.1"
+ loader-runner "^4.2.0"
+ mime-types "^2.1.27"
+ neo-async "^2.6.2"
+ schema-utils "^3.0.0"
+ tapable "^2.1.1"
+ terser-webpack-plugin "^5.1.1"
+ watchpack "^2.0.0"
+ webpack-sources "^2.1.1"
webpackbar@^5.0.0-3:
version "5.0.0-3"
@@ -10065,12 +8708,10 @@ widest-line@^3.1.0:
dependencies:
string-width "^4.0.0"
-worker-farm@^1.7.0:
- version "1.7.0"
- resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.7.0.tgz#26a94c5391bbca926152002f69b84a4bf772e5a8"
- integrity sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==
- dependencies:
- errno "~0.1.7"
+wildcard@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.0.tgz#a77d20e5200c6faaac979e4b3aadc7b3dd7f8fec"
+ integrity sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==
worker-rpc@^0.1.0:
version "0.1.1"
@@ -10136,7 +8777,7 @@ xml-js@^1.6.11:
dependencies:
sax "^1.2.4"
-xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.1:
+xtend@^4.0.0, xtend@^4.0.1:
version "4.0.2"
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==
@@ -10146,11 +8787,6 @@ y18n@^4.0.0:
resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.1.tgz#8db2b83c31c5d75099bb890b23f3094891e247d4"
integrity sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==
-yallist@^3.0.2:
- version "3.1.1"
- resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"
- integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==
-
yallist@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"