Merge branch 'develop' into enhancement/OP-5808_Enhancement-3dsmax-rendering-time-data-from-instance
2
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
|
|
@ -35,6 +35,7 @@ body:
|
|||
label: Version
|
||||
description: What version are you running? Look to OpenPype Tray
|
||||
options:
|
||||
- 3.15.7-nightly.2
|
||||
- 3.15.7-nightly.1
|
||||
- 3.15.6
|
||||
- 3.15.6-nightly.3
|
||||
|
|
@ -134,7 +135,6 @@ body:
|
|||
- 3.14.1-nightly.3
|
||||
- 3.14.1-nightly.2
|
||||
- 3.14.1-nightly.1
|
||||
- 3.14.0
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
|
|
|
|||
|
|
@ -43,7 +43,24 @@ class MayaTemplateBuilder(AbstractTemplateBuilder):
|
|||
))
|
||||
|
||||
cmds.sets(name=PLACEHOLDER_SET, empty=True)
|
||||
new_nodes = cmds.file(path, i=True, returnNewNodes=True)
|
||||
new_nodes = cmds.file(
|
||||
path,
|
||||
i=True,
|
||||
returnNewNodes=True,
|
||||
preserveReferences=True,
|
||||
loadReferenceDepth="all",
|
||||
)
|
||||
|
||||
# make default cameras non-renderable
|
||||
default_cameras = [cam for cam in cmds.ls(cameras=True)
|
||||
if cmds.camera(cam, query=True, startupCamera=True)]
|
||||
for cam in default_cameras:
|
||||
if not cmds.attributeQuery("renderable", node=cam, exists=True):
|
||||
self.log.debug(
|
||||
"Camera {} has no attribute 'renderable'".format(cam)
|
||||
)
|
||||
continue
|
||||
cmds.setAttr("{}.renderable".format(cam), 0)
|
||||
|
||||
cmds.setAttr(PLACEHOLDER_SET + ".hiddenInOutliner", True)
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,6 @@ Supported Unreal Engine version is 4.26+ (mainly because of major Python changes
|
|||
|
||||
### Project naming
|
||||
Unreal doesn't support project names starting with non-alphabetic character. So names like `123_myProject` are
|
||||
invalid. If OpenPype detects such name it automatically prepends letter **P** to make it valid name, so `123_myProject`
|
||||
invalid. If Ayon detects such name it automatically prepends letter **P** to make it valid name, so `123_myProject`
|
||||
will become `P123_myProject`. There is also soft-limit on project name length to be shorter than 20 characters.
|
||||
Longer names will issue warning in Unreal Editor that there might be possible side effects.
|
||||
Longer names will issue warning in Unreal Editor that there might be possible side effects.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
import os
|
||||
from openpype.modules import OpenPypeModule, IHostAddon
|
||||
from pathlib import Path
|
||||
|
||||
from openpype.modules import IHostAddon, OpenPypeModule
|
||||
from .lib import get_compatible_integration
|
||||
|
||||
UNREAL_ROOT_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
|
|
@ -13,15 +16,22 @@ class UnrealAddon(OpenPypeModule, IHostAddon):
|
|||
|
||||
def add_implementation_envs(self, env, app):
|
||||
"""Modify environments to contain all required for implementation."""
|
||||
# Set OPENPYPE_UNREAL_PLUGIN required for Unreal implementation
|
||||
# Set AYON_UNREAL_PLUGIN required for Unreal implementation
|
||||
|
||||
ue_plugin = "UE_5.0" if app.name[:1] == "5" else "UE_4.7"
|
||||
ue_version = app.name.replace("-", ".")
|
||||
unreal_plugin_path = os.path.join(
|
||||
UNREAL_ROOT_DIR, "integration", ue_plugin, "OpenPype"
|
||||
UNREAL_ROOT_DIR, "integration", f"UE_{ue_version}", "Ayon"
|
||||
)
|
||||
if not env.get("OPENPYPE_UNREAL_PLUGIN") or \
|
||||
env.get("OPENPYPE_UNREAL_PLUGIN") != unreal_plugin_path:
|
||||
env["OPENPYPE_UNREAL_PLUGIN"] = unreal_plugin_path
|
||||
if not Path(unreal_plugin_path).exists():
|
||||
if compatible_versions := get_compatible_integration(
|
||||
ue_version, Path(UNREAL_ROOT_DIR) / "integration"
|
||||
):
|
||||
unreal_plugin_path = compatible_versions[-1] / "Ayon"
|
||||
unreal_plugin_path = unreal_plugin_path.as_posix()
|
||||
|
||||
if not env.get("AYON_UNREAL_PLUGIN") or \
|
||||
env.get("AYON_UNREAL_PLUGIN") != unreal_plugin_path:
|
||||
env["AYON_UNREAL_PLUGIN"] = unreal_plugin_path
|
||||
|
||||
# Set default environments if are not set via settings
|
||||
defaults = {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""Unreal Editor OpenPype host API."""
|
||||
"""Unreal Editor Ayon host API."""
|
||||
|
||||
from .plugin import (
|
||||
UnrealActorCreator,
|
||||
|
|
|
|||
|
|
@ -2,15 +2,15 @@
|
|||
import unreal # noqa
|
||||
|
||||
|
||||
class OpenPypeUnrealException(Exception):
|
||||
class AyonUnrealException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
@unreal.uclass()
|
||||
class OpenPypeHelpers(unreal.OpenPypeLib):
|
||||
"""Class wrapping some useful functions for OpenPype.
|
||||
class AyonHelpers(unreal.AyonLib):
|
||||
"""Class wrapping some useful functions for Ayon.
|
||||
|
||||
This class is extending native BP class in OpenPype Integration Plugin.
|
||||
This class is extending native BP class in Ayon Integration Plugin.
|
||||
|
||||
"""
|
||||
|
||||
|
|
@ -29,13 +29,13 @@ class OpenPypeHelpers(unreal.OpenPypeLib):
|
|||
|
||||
Example:
|
||||
|
||||
OpenPypeHelpers().set_folder_color(
|
||||
AyonHelpers().set_folder_color(
|
||||
"/Game/Path", unreal.LinearColor(a=1.0, r=1.0, g=0.5, b=0)
|
||||
)
|
||||
|
||||
Note:
|
||||
This will take effect only after Editor is restarted. I couldn't
|
||||
find a way to refresh it. Also this saves the color definition
|
||||
find a way to refresh it. Also, this saves the color definition
|
||||
into the project config, binding this path with color. So if you
|
||||
delete this path and later re-create, it will set this color
|
||||
again.
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ from openpype.pipeline import (
|
|||
register_creator_plugin_path,
|
||||
deregister_loader_plugin_path,
|
||||
deregister_creator_plugin_path,
|
||||
AVALON_CONTAINER_ID,
|
||||
AYON_CONTAINER_ID,
|
||||
)
|
||||
from openpype.tools.utils import host_tools
|
||||
import openpype.hosts.unreal
|
||||
|
|
@ -22,12 +22,13 @@ from openpype.host import HostBase, ILoadHost, IPublishHost
|
|||
|
||||
import unreal # noqa
|
||||
|
||||
# Rename to Ayon once parent module renames
|
||||
logger = logging.getLogger("openpype.hosts.unreal")
|
||||
|
||||
OPENPYPE_CONTAINERS = "OpenPypeContainers"
|
||||
CONTEXT_CONTAINER = "OpenPype/context.json"
|
||||
AYON_CONTAINERS = "AyonContainers"
|
||||
CONTEXT_CONTAINER = "Ayon/context.json"
|
||||
UNREAL_VERSION = semver.VersionInfo(
|
||||
*os.getenv("OPENPYPE_UNREAL_VERSION").split(".")
|
||||
*os.getenv("AYON_UNREAL_VERSION").split(".")
|
||||
)
|
||||
|
||||
HOST_DIR = os.path.dirname(os.path.abspath(openpype.hosts.unreal.__file__))
|
||||
|
|
@ -53,14 +54,14 @@ class UnrealHost(HostBase, ILoadHost, IPublishHost):
|
|||
def get_containers(self):
|
||||
return ls()
|
||||
|
||||
def show_tools_popup(self):
|
||||
@staticmethod
|
||||
def show_tools_popup():
|
||||
"""Show tools popup with actions leading to show other tools."""
|
||||
|
||||
show_tools_popup()
|
||||
|
||||
def show_tools_dialog(self):
|
||||
@staticmethod
|
||||
def show_tools_dialog():
|
||||
"""Show tools dialog with actions leading to show other tools."""
|
||||
|
||||
show_tools_dialog()
|
||||
|
||||
def update_context_data(self, data, changes):
|
||||
|
|
@ -72,9 +73,10 @@ class UnrealHost(HostBase, ILoadHost, IPublishHost):
|
|||
with open(op_ctx, "w+") as f:
|
||||
json.dump(data, f)
|
||||
break
|
||||
except IOError:
|
||||
except IOError as e:
|
||||
if i == attempts - 1:
|
||||
raise Exception("Failed to write context data. Aborting.")
|
||||
raise Exception(
|
||||
"Failed to write context data. Aborting.") from e
|
||||
unreal.log_warning("Failed to write context data. Retrying...")
|
||||
i += 1
|
||||
time.sleep(3)
|
||||
|
|
@ -95,19 +97,30 @@ def install():
|
|||
print("-=" * 40)
|
||||
logo = '''.
|
||||
.
|
||||
____________
|
||||
/ \\ __ \\
|
||||
\\ \\ \\/_\\ \\
|
||||
\\ \\ _____/ ______
|
||||
\\ \\ \\___// \\ \\
|
||||
\\ \\____\\ \\ \\_____\\
|
||||
\\/_____/ \\/______/ PYPE Club .
|
||||
·
|
||||
│
|
||||
·∙/
|
||||
·-∙•∙-·
|
||||
/ \\ /∙· / \\
|
||||
∙ \\ │ / ∙
|
||||
\\ \\ · / /
|
||||
\\\\ ∙ ∙ //
|
||||
\\\\/ \\//
|
||||
___
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│___│
|
||||
-·
|
||||
|
||||
·-─═─-∙ A Y O N ∙-─═─-·
|
||||
by YNPUT
|
||||
.
|
||||
'''
|
||||
print(logo)
|
||||
print("installing OpenPype for Unreal ...")
|
||||
print("installing Ayon for Unreal ...")
|
||||
print("-=" * 40)
|
||||
logger.info("installing OpenPype for Unreal")
|
||||
logger.info("installing Ayon for Unreal")
|
||||
pyblish.api.register_host("unreal")
|
||||
pyblish.api.register_plugin_path(str(PUBLISH_PATH))
|
||||
register_loader_plugin_path(str(LOAD_PATH))
|
||||
|
|
@ -117,7 +130,7 @@ def install():
|
|||
|
||||
|
||||
def uninstall():
|
||||
"""Uninstall Unreal configuration for Avalon."""
|
||||
"""Uninstall Unreal configuration for Ayon."""
|
||||
pyblish.api.deregister_plugin_path(str(PUBLISH_PATH))
|
||||
deregister_loader_plugin_path(str(LOAD_PATH))
|
||||
deregister_creator_plugin_path(str(CREATE_PATH))
|
||||
|
|
@ -125,14 +138,14 @@ def uninstall():
|
|||
|
||||
def _register_callbacks():
|
||||
"""
|
||||
TODO: Implement callbacks if supported by UE4
|
||||
TODO: Implement callbacks if supported by UE
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def _register_events():
|
||||
"""
|
||||
TODO: Implement callbacks if supported by UE4
|
||||
TODO: Implement callbacks if supported by UE
|
||||
"""
|
||||
pass
|
||||
|
||||
|
|
@ -146,32 +159,30 @@ def ls():
|
|||
"""
|
||||
ar = unreal.AssetRegistryHelpers.get_asset_registry()
|
||||
# UE 5.1 changed how class name is specified
|
||||
class_name = ["/Script/OpenPype", "AssetContainer"] if UNREAL_VERSION.major == 5 and UNREAL_VERSION.minor > 0 else "AssetContainer" # noqa
|
||||
openpype_containers = ar.get_assets_by_class(class_name, True)
|
||||
class_name = ["/Script/Ayon", "AyonAssetContainer"] if UNREAL_VERSION.major == 5 and UNREAL_VERSION.minor > 0 else "AyonAssetContainer" # noqa
|
||||
ayon_containers = ar.get_assets_by_class(class_name, True)
|
||||
|
||||
# get_asset_by_class returns AssetData. To get all metadata we need to
|
||||
# load asset. get_tag_values() work only on metadata registered in
|
||||
# Asset Registry Project settings (and there is no way to set it with
|
||||
# python short of editing ini configuration file).
|
||||
for asset_data in openpype_containers:
|
||||
for asset_data in ayon_containers:
|
||||
asset = asset_data.get_asset()
|
||||
data = unreal.EditorAssetLibrary.get_metadata_tag_values(asset)
|
||||
data["objectName"] = asset_data.asset_name
|
||||
data = cast_map_to_str_dict(data)
|
||||
|
||||
yield data
|
||||
yield cast_map_to_str_dict(data)
|
||||
|
||||
|
||||
def ls_inst():
|
||||
ar = unreal.AssetRegistryHelpers.get_asset_registry()
|
||||
# UE 5.1 changed how class name is specified
|
||||
class_name = [
|
||||
"/Script/OpenPype",
|
||||
"OpenPypePublishInstance"
|
||||
"/Script/Ayon",
|
||||
"AyonPublishInstance"
|
||||
] if (
|
||||
UNREAL_VERSION.major == 5
|
||||
and UNREAL_VERSION.minor > 0
|
||||
) else "OpenPypePublishInstance" # noqa
|
||||
) else "AyonPublishInstance" # noqa
|
||||
instances = ar.get_assets_by_class(class_name, True)
|
||||
|
||||
# get_asset_by_class returns AssetData. To get all metadata we need to
|
||||
|
|
@ -182,13 +193,11 @@ def ls_inst():
|
|||
asset = asset_data.get_asset()
|
||||
data = unreal.EditorAssetLibrary.get_metadata_tag_values(asset)
|
||||
data["objectName"] = asset_data.asset_name
|
||||
data = cast_map_to_str_dict(data)
|
||||
|
||||
yield data
|
||||
yield cast_map_to_str_dict(data)
|
||||
|
||||
|
||||
def parse_container(container):
|
||||
"""To get data from container, AssetContainer must be loaded.
|
||||
"""To get data from container, AyonAssetContainer must be loaded.
|
||||
|
||||
Args:
|
||||
container(str): path to container
|
||||
|
|
@ -217,7 +226,7 @@ def containerise(name, namespace, nodes, context, loader=None, suffix="_CON"):
|
|||
Unreal doesn't support *groups* of assets that you can add metadata to.
|
||||
But it does support folders that helps to organize asset. Unfortunately
|
||||
those folders are just that - you cannot add any additional information
|
||||
to them. OpenPype Integration Plugin is providing way out - Implementing
|
||||
to them. Ayon Integration Plugin is providing way out - Implementing
|
||||
`AssetContainer` Blueprint class. This class when added to folder can
|
||||
handle metadata on it using standard
|
||||
:func:`unreal.EditorAssetLibrary.set_metadata_tag()` and
|
||||
|
|
@ -226,30 +235,30 @@ def containerise(name, namespace, nodes, context, loader=None, suffix="_CON"):
|
|||
those assets is available as `assets` property.
|
||||
|
||||
This is list of strings starting with asset type and ending with its path:
|
||||
`Material /Game/OpenPype/Test/TestMaterial.TestMaterial`
|
||||
`Material /Game/Ayon/Test/TestMaterial.TestMaterial`
|
||||
|
||||
"""
|
||||
# 1 - create directory for container
|
||||
root = "/Game"
|
||||
container_name = "{}{}".format(name, suffix)
|
||||
container_name = f"{name}{suffix}"
|
||||
new_name = move_assets_to_path(root, container_name, nodes)
|
||||
|
||||
# 2 - create Asset Container there
|
||||
path = "{}/{}".format(root, new_name)
|
||||
path = f"{root}/{new_name}"
|
||||
create_container(container=container_name, path=path)
|
||||
|
||||
namespace = path
|
||||
|
||||
data = {
|
||||
"schema": "openpype:container-2.0",
|
||||
"id": AVALON_CONTAINER_ID,
|
||||
"schema": "ayon:container-2.0",
|
||||
"id": AYON_CONTAINER_ID,
|
||||
"name": new_name,
|
||||
"namespace": namespace,
|
||||
"loader": str(loader),
|
||||
"representation": context["representation"]["_id"],
|
||||
}
|
||||
# 3 - imprint data
|
||||
imprint("{}/{}".format(path, container_name), data)
|
||||
imprint(f"{path}/{container_name}", data)
|
||||
return path
|
||||
|
||||
|
||||
|
|
@ -257,7 +266,7 @@ def instantiate(root, name, data, assets=None, suffix="_INS"):
|
|||
"""Bundles *nodes* into *container*.
|
||||
|
||||
Marking it with metadata as publishable instance. If assets are provided,
|
||||
they are moved to new path where `OpenPypePublishInstance` class asset is
|
||||
they are moved to new path where `AyonPublishInstance` class asset is
|
||||
created and imprinted with metadata.
|
||||
|
||||
This can then be collected for publishing by Pyblish for example.
|
||||
|
|
@ -271,7 +280,7 @@ def instantiate(root, name, data, assets=None, suffix="_INS"):
|
|||
suffix (str): suffix string to append to instance name
|
||||
|
||||
"""
|
||||
container_name = "{}{}".format(name, suffix)
|
||||
container_name = f"{name}{suffix}"
|
||||
|
||||
# if we specify assets, create new folder and move them there. If not,
|
||||
# just create empty folder
|
||||
|
|
@ -280,10 +289,10 @@ def instantiate(root, name, data, assets=None, suffix="_INS"):
|
|||
else:
|
||||
new_name = create_folder(root, name)
|
||||
|
||||
path = "{}/{}".format(root, new_name)
|
||||
path = f"{root}/{new_name}"
|
||||
create_publish_instance(instance=container_name, path=path)
|
||||
|
||||
imprint("{}/{}".format(path, container_name), data)
|
||||
imprint(f"{path}/{container_name}", data)
|
||||
|
||||
|
||||
def imprint(node, data):
|
||||
|
|
@ -299,7 +308,7 @@ def imprint(node, data):
|
|||
loaded_asset, key, str(value)
|
||||
)
|
||||
|
||||
with unreal.ScopedEditorTransaction("OpenPype containerising"):
|
||||
with unreal.ScopedEditorTransaction("Ayon containerising"):
|
||||
unreal.EditorAssetLibrary.save_asset(node)
|
||||
|
||||
|
||||
|
|
@ -366,11 +375,11 @@ def create_folder(root: str, name: str) -> str:
|
|||
eal = unreal.EditorAssetLibrary
|
||||
index = 1
|
||||
while True:
|
||||
if eal.does_directory_exist("{}/{}".format(root, name)):
|
||||
name = "{}{}".format(name, index)
|
||||
if eal.does_directory_exist(f"{root}/{name}"):
|
||||
name = f"{name}{index}"
|
||||
index += 1
|
||||
else:
|
||||
eal.make_directory("{}/{}".format(root, name))
|
||||
eal.make_directory(f"{root}/{name}")
|
||||
break
|
||||
|
||||
return name
|
||||
|
|
@ -403,9 +412,7 @@ def move_assets_to_path(root: str, name: str, assets: List[str]) -> str:
|
|||
unreal.log(assets)
|
||||
for asset in assets:
|
||||
loaded = eal.load_asset(asset)
|
||||
eal.rename_asset(
|
||||
asset, "{}/{}/{}".format(root, name, loaded.get_name())
|
||||
)
|
||||
eal.rename_asset(asset, f"{root}/{name}/{loaded.get_name()}")
|
||||
|
||||
return name
|
||||
|
||||
|
|
@ -432,17 +439,16 @@ def create_container(container: str, path: str) -> unreal.Object:
|
|||
)
|
||||
|
||||
"""
|
||||
factory = unreal.AssetContainerFactory()
|
||||
factory = unreal.AyonAssetContainerFactory()
|
||||
tools = unreal.AssetToolsHelpers().get_asset_tools()
|
||||
|
||||
asset = tools.create_asset(container, path, None, factory)
|
||||
return asset
|
||||
return tools.create_asset(container, path, None, factory)
|
||||
|
||||
|
||||
def create_publish_instance(instance: str, path: str) -> unreal.Object:
|
||||
"""Helper function to create OpenPype Publish Instance on given path.
|
||||
"""Helper function to create Ayon Publish Instance on given path.
|
||||
|
||||
This behaves similarly as :func:`create_openpype_container`.
|
||||
This behaves similarly as :func:`create_ayon_container`.
|
||||
|
||||
Args:
|
||||
path (str): Path where to create Publish Instance.
|
||||
|
|
@ -460,10 +466,9 @@ def create_publish_instance(instance: str, path: str) -> unreal.Object:
|
|||
)
|
||||
|
||||
"""
|
||||
factory = unreal.OpenPypePublishInstanceFactory()
|
||||
factory = unreal.AyonPublishInstanceFactory()
|
||||
tools = unreal.AssetToolsHelpers().get_asset_tools()
|
||||
asset = tools.create_asset(instance, path, None, factory)
|
||||
return asset
|
||||
return tools.create_asset(instance, path, None, factory)
|
||||
|
||||
|
||||
def cast_map_to_str_dict(umap) -> dict:
|
||||
|
|
@ -494,11 +499,14 @@ def get_subsequences(sequence: unreal.LevelSequence):
|
|||
|
||||
"""
|
||||
tracks = sequence.get_master_tracks()
|
||||
subscene_track = None
|
||||
for t in tracks:
|
||||
if t.get_class() == unreal.MovieSceneSubTrack.static_class():
|
||||
subscene_track = t
|
||||
break
|
||||
subscene_track = next(
|
||||
(
|
||||
t
|
||||
for t in tracks
|
||||
if t.get_class() == unreal.MovieSceneSubTrack.static_class()
|
||||
),
|
||||
None,
|
||||
)
|
||||
if subscene_track is not None and subscene_track.get_sections():
|
||||
return subscene_track.get_sections()
|
||||
return []
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ from openpype.pipeline import (
|
|||
@six.add_metaclass(ABCMeta)
|
||||
class UnrealBaseCreator(Creator):
|
||||
"""Base class for Unreal creator plugins."""
|
||||
root = "/Game/OpenPype/PublishInstances"
|
||||
root = "/Game/Ayon/AyonPublishInstances"
|
||||
suffix = "_INS"
|
||||
|
||||
@staticmethod
|
||||
|
|
@ -243,5 +243,5 @@ class UnrealActorCreator(UnrealBaseCreator):
|
|||
|
||||
|
||||
class Loader(LoaderPlugin, ABC):
|
||||
"""This serves as skeleton for future OpenPype specific functionality"""
|
||||
"""This serves as skeleton for future Ayon specific functionality"""
|
||||
pass
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ def start_rendering():
|
|||
# instances = pipeline.ls_inst()
|
||||
instances = [
|
||||
a for a in assets
|
||||
if a.get_class().get_name() == "OpenPypePublishInstance"]
|
||||
if a.get_class().get_name() == "AyonPublishInstance"]
|
||||
|
||||
inst_data = []
|
||||
|
||||
|
|
@ -64,8 +64,9 @@ def start_rendering():
|
|||
project = os.environ.get("AVALON_PROJECT")
|
||||
anatomy = Anatomy(project)
|
||||
root = anatomy.roots['renders']
|
||||
except Exception:
|
||||
raise Exception("Could not find render root in anatomy settings.")
|
||||
except Exception as e:
|
||||
raise Exception(
|
||||
"Could not find render root in anatomy settings.") from e
|
||||
|
||||
render_dir = f"{root}/{project}"
|
||||
|
||||
|
|
@ -121,7 +122,7 @@ def start_rendering():
|
|||
job = queue.allocate_new_job(unreal.MoviePipelineExecutorJob)
|
||||
job.sequence = unreal.SoftObjectPath(i["master_sequence"])
|
||||
job.map = unreal.SoftObjectPath(i["master_level"])
|
||||
job.author = "OpenPype"
|
||||
job.author = "Ayon"
|
||||
|
||||
# If we have a saved configuration, copy it to the job.
|
||||
if config:
|
||||
|
|
@ -129,7 +130,7 @@ def start_rendering():
|
|||
|
||||
# User data could be used to pass data to the job, that can be
|
||||
# read in the job's OnJobFinished callback. We could,
|
||||
# for instance, pass the AvalonPublishInstance's path to the job.
|
||||
# for instance, pass the AyonPublishInstance's path to the job.
|
||||
# job.user_data = ""
|
||||
|
||||
output_dir = render_setting.get('output')
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ class ToolsDialog(QtWidgets.QDialog):
|
|||
def __init__(self, *args, **kwargs):
|
||||
super(ToolsDialog, self).__init__(*args, **kwargs)
|
||||
|
||||
self.setWindowTitle("OpenPype tools")
|
||||
self.setWindowTitle("Ayon tools")
|
||||
icon = QtGui.QIcon(resources.get_openpype_icon_filepath())
|
||||
self.setWindowIcon(icon)
|
||||
|
||||
|
|
|
|||
|
|
@ -186,15 +186,15 @@ class UnrealPrelaunchHook(PreLaunchHook):
|
|||
|
||||
project_path.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# Set "OPENPYPE_UNREAL_PLUGIN" to current process environment for
|
||||
# Set "AYON_UNREAL_PLUGIN" to current process environment for
|
||||
# execution of `create_unreal_project`
|
||||
|
||||
if self.launch_context.env.get("OPENPYPE_UNREAL_PLUGIN"):
|
||||
if self.launch_context.env.get("AYON_UNREAL_PLUGIN"):
|
||||
self.log.info((
|
||||
f"{self.signature} using OpenPype plugin from "
|
||||
f"{self.launch_context.env.get('OPENPYPE_UNREAL_PLUGIN')}"
|
||||
f"{self.signature} using Ayon plugin from "
|
||||
f"{self.launch_context.env.get('AYON_UNREAL_PLUGIN')}"
|
||||
))
|
||||
env_key = "OPENPYPE_UNREAL_PLUGIN"
|
||||
env_key = "AYON_UNREAL_PLUGIN"
|
||||
if self.launch_context.env.get(env_key):
|
||||
os.environ[env_key] = self.launch_context.env[env_key]
|
||||
|
||||
|
|
@ -213,7 +213,7 @@ class UnrealPrelaunchHook(PreLaunchHook):
|
|||
engine_path,
|
||||
project_path)
|
||||
|
||||
self.launch_context.env["OPENPYPE_UNREAL_VERSION"] = engine_version
|
||||
self.launch_context.env["AYON_UNREAL_VERSION"] = engine_version
|
||||
# Append project file to launch arguments
|
||||
self.launch_context.launch_args.append(
|
||||
f"\"{project_file.as_posix()}\"")
|
||||
|
|
|
|||
10
openpype/hosts/unreal/integration/README.md
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
# Building the plugin
|
||||
|
||||
In order to successfully build the plugin, make sure that the path to the UnrealBuildTool.exe is specified correctly.
|
||||
After the UBT path specify for which platform it will be compiled. in the -Project parameter, specify the path to the
|
||||
CommandletProject.uproject file. Next the build type has to be specified (DebugGame, Development, Package, etc.) and then the -TargetType (Editor, Runtime, etc.)
|
||||
|
||||
`BuildPlugin_[Ver].bat` runs the building process in the background. If you want to show the progress inside the
|
||||
command prompt, use the `BuildPlugin_[Ver]_Window.bat` file.
|
||||
|
||||
|
||||
23
openpype/hosts/unreal/integration/UE_4.27/Ayon/Ayon.uplugin
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"FileVersion": 3,
|
||||
"Version": 1,
|
||||
"VersionName": "1.0",
|
||||
"FriendlyName": "Ayon",
|
||||
"Description": "Ayon Integration",
|
||||
"Category": "Ayon.Integration",
|
||||
"CreatedBy": "Ondrej Samohel",
|
||||
"CreatedByURL": "https://ayon.ynput.io",
|
||||
"DocsURL": "https://ayon.ynput.io/docs/artist_hosts_unreal",
|
||||
"MarketplaceURL": "",
|
||||
"SupportURL": "https://ynput.io/",
|
||||
"EngineVersion": "4.27",
|
||||
"CanContainContent": true,
|
||||
"Installed": true,
|
||||
"Modules": [
|
||||
{
|
||||
"Name": "Ayon",
|
||||
"Type": "Editor",
|
||||
"LoadingPhase": "Default"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
[/Script/Ayon.AyonSettings]
|
||||
FolderColor=(R=91,G=197,B=220,A=255)
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
import unreal
|
||||
|
||||
ayon_detected = True
|
||||
try:
|
||||
from openpype.pipeline import install_host
|
||||
from openpype.hosts.unreal.api import UnrealHost
|
||||
|
||||
ayon_host = UnrealHost()
|
||||
except ImportError as exc:
|
||||
ayon_host = None
|
||||
ayon_detected = False
|
||||
unreal.log_error(f"OpenPype: cannot load Ayon [ {exc} ]")
|
||||
|
||||
if ayon_detected:
|
||||
install_host(ayon_host)
|
||||
|
||||
|
||||
@unreal.uclass()
|
||||
class AyonIntegration(unreal.AyonPythonBridge):
|
||||
@unreal.ufunction(override=True)
|
||||
def RunInPython_Popup(self):
|
||||
unreal.log_warning("Ayon: showing tools popup")
|
||||
if ayon_detected:
|
||||
ayon_host.show_tools_popup()
|
||||
|
||||
@unreal.ufunction(override=True)
|
||||
def RunInPython_Dialog(self):
|
||||
unreal.log_warning("Ayon: showing tools dialog")
|
||||
if ayon_detected:
|
||||
ayon_host.show_tools_dialog()
|
||||
3
openpype/hosts/unreal/integration/UE_4.27/Ayon/README.md
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# Ayon Unreal Integration plugin - UE 4.x
|
||||
|
||||
This is plugin for Unreal Editor, creating menu for [Ayon](https://github.com/ynput/OpenPype) tools to run.
|
||||
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 721 B |
|
After Width: | Height: | Size: 16 KiB |
|
|
@ -2,35 +2,37 @@
|
|||
|
||||
using UnrealBuildTool;
|
||||
|
||||
public class OpenPype : ModuleRules
|
||||
public class Ayon : ModuleRules
|
||||
{
|
||||
public OpenPype(ReadOnlyTargetRules Target) : base(Target)
|
||||
public Ayon(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
|
||||
|
||||
PublicIncludePaths.AddRange(
|
||||
new string[] {
|
||||
new string[]
|
||||
{
|
||||
// ... add public include paths required here ...
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
);
|
||||
|
||||
|
||||
PrivateIncludePaths.AddRange(
|
||||
new string[] {
|
||||
new string[]
|
||||
{
|
||||
// ... add other private include paths required here ...
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
);
|
||||
|
||||
|
||||
PublicDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"Core",
|
||||
// ... add other public dependencies that you statically link with here ...
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
);
|
||||
|
||||
|
||||
PrivateDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
|
|
@ -46,14 +48,14 @@ public class OpenPype : ModuleRules
|
|||
"AssetTools"
|
||||
// ... add private dependencies that you statically link with here ...
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
);
|
||||
|
||||
|
||||
DynamicallyLoadedModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
// ... add any modules that your module loads dynamically here ...
|
||||
}
|
||||
);
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,25 +1,26 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
#include "OpenPype.h"
|
||||
#include "Ayon.h"
|
||||
|
||||
#include "ISettingsContainer.h"
|
||||
#include "ISettingsModule.h"
|
||||
#include "ISettingsSection.h"
|
||||
#include "LevelEditor.h"
|
||||
#include "OpenPypePythonBridge.h"
|
||||
#include "OpenPypeSettings.h"
|
||||
#include "OpenPypeStyle.h"
|
||||
#include "AyonPythonBridge.h"
|
||||
#include "AyonSettings.h"
|
||||
#include "AyonStyle.h"
|
||||
#include "Modules/ModuleManager.h"
|
||||
|
||||
|
||||
static const FName OpenPypeTabName("OpenPype");
|
||||
static const FName AyonTabName("Ayon");
|
||||
|
||||
#define LOCTEXT_NAMESPACE "FOpenPypeModule"
|
||||
#define LOCTEXT_NAMESPACE "FAyonModule"
|
||||
|
||||
// This function is triggered when the plugin is staring up
|
||||
void FOpenPypeModule::StartupModule()
|
||||
void FAyonModule::StartupModule()
|
||||
{
|
||||
if (!IsRunningCommandlet()) {
|
||||
FOpenPypeStyle::Initialize();
|
||||
FOpenPypeStyle::SetIcon("Logo", "openpype40");
|
||||
FAyonStyle::Initialize();
|
||||
FAyonStyle::SetIcon("Logo", "ayon40");
|
||||
|
||||
// Create the Extender that will add content to the menu
|
||||
FLevelEditorModule& LevelEditorModule = FModuleManager::LoadModuleChecked<FLevelEditorModule>("LevelEditor");
|
||||
|
|
@ -31,13 +32,13 @@ void FOpenPypeModule::StartupModule()
|
|||
"LevelEditor",
|
||||
EExtensionHook::After,
|
||||
NULL,
|
||||
FMenuExtensionDelegate::CreateRaw(this, &FOpenPypeModule::AddMenuEntry)
|
||||
FMenuExtensionDelegate::CreateRaw(this, &FAyonModule::AddMenuEntry)
|
||||
);
|
||||
ToolbarExtender->AddToolBarExtension(
|
||||
"Settings",
|
||||
EExtensionHook::After,
|
||||
NULL,
|
||||
FToolBarExtensionDelegate::CreateRaw(this, &FOpenPypeModule::AddToobarEntry));
|
||||
FToolBarExtensionDelegate::CreateRaw(this, &FAyonModule::AddToobarEntry));
|
||||
|
||||
|
||||
LevelEditorModule.GetMenuExtensibilityManager()->AddExtender(MenuExtender);
|
||||
|
|
@ -47,56 +48,56 @@ void FOpenPypeModule::StartupModule()
|
|||
}
|
||||
}
|
||||
|
||||
void FOpenPypeModule::ShutdownModule()
|
||||
void FAyonModule::ShutdownModule()
|
||||
{
|
||||
FOpenPypeStyle::Shutdown();
|
||||
FAyonStyle::Shutdown();
|
||||
}
|
||||
|
||||
|
||||
void FOpenPypeModule::AddMenuEntry(FMenuBuilder& MenuBuilder)
|
||||
void FAyonModule::AddMenuEntry(FMenuBuilder& MenuBuilder)
|
||||
{
|
||||
// Create Section
|
||||
MenuBuilder.BeginSection("OpenPype", TAttribute<FText>(FText::FromString("OpenPype")));
|
||||
MenuBuilder.BeginSection("Ayon", TAttribute<FText>(FText::FromString("Ayon")));
|
||||
{
|
||||
// Create a Submenu inside of the Section
|
||||
MenuBuilder.AddMenuEntry(
|
||||
FText::FromString("Tools..."),
|
||||
FText::FromString("Pipeline tools"),
|
||||
FSlateIcon(FOpenPypeStyle::GetStyleSetName(), "OpenPype.Logo"),
|
||||
FUIAction(FExecuteAction::CreateRaw(this, &FOpenPypeModule::MenuPopup))
|
||||
FSlateIcon(FAyonStyle::GetStyleSetName(), "Ayon.Logo"),
|
||||
FUIAction(FExecuteAction::CreateRaw(this, &FAyonModule::MenuPopup))
|
||||
);
|
||||
|
||||
MenuBuilder.AddMenuEntry(
|
||||
FText::FromString("Tools dialog..."),
|
||||
FText::FromString("Pipeline tools dialog"),
|
||||
FSlateIcon(FOpenPypeStyle::GetStyleSetName(), "OpenPype.Logo"),
|
||||
FUIAction(FExecuteAction::CreateRaw(this, &FOpenPypeModule::MenuDialog))
|
||||
FSlateIcon(FAyonStyle::GetStyleSetName(), "Ayon.Logo"),
|
||||
FUIAction(FExecuteAction::CreateRaw(this, &FAyonModule::MenuDialog))
|
||||
);
|
||||
}
|
||||
MenuBuilder.EndSection();
|
||||
}
|
||||
|
||||
void FOpenPypeModule::AddToobarEntry(FToolBarBuilder& ToolbarBuilder)
|
||||
void FAyonModule::AddToobarEntry(FToolBarBuilder& ToolbarBuilder)
|
||||
{
|
||||
ToolbarBuilder.BeginSection(TEXT("OpenPype"));
|
||||
ToolbarBuilder.BeginSection(TEXT("Ayon"));
|
||||
{
|
||||
ToolbarBuilder.AddToolBarButton(
|
||||
FUIAction(
|
||||
FExecuteAction::CreateRaw(this, &FOpenPypeModule::MenuPopup),
|
||||
FExecuteAction::CreateRaw(this, &FAyonModule::MenuPopup),
|
||||
NULL,
|
||||
FIsActionChecked()
|
||||
|
||||
),
|
||||
NAME_None,
|
||||
LOCTEXT("OpenPype_label", "OpenPype"),
|
||||
LOCTEXT("OpenPype_tooltip", "OpenPype Tools"),
|
||||
FSlateIcon(FOpenPypeStyle::GetStyleSetName(), "OpenPype.Logo")
|
||||
LOCTEXT("Ayon_label", "Ayon"),
|
||||
LOCTEXT("Ayon_tooltip", "Ayon Tools"),
|
||||
FSlateIcon(FAyonStyle::GetStyleSetName(), "Ayon.Logo")
|
||||
);
|
||||
}
|
||||
ToolbarBuilder.EndSection();
|
||||
}
|
||||
|
||||
void FOpenPypeModule::RegisterSettings()
|
||||
void FAyonModule::RegisterSettings()
|
||||
{
|
||||
ISettingsModule& SettingsModule = FModuleManager::LoadModuleChecked<ISettingsModule>("Settings");
|
||||
|
||||
|
|
@ -104,10 +105,10 @@ void FOpenPypeModule::RegisterSettings()
|
|||
// TODO: After the movement of the plugin from the game to editor, it might be necessary to move this!
|
||||
ISettingsContainerPtr SettingsContainer = SettingsModule.GetContainer("Project");
|
||||
|
||||
UOpenPypeSettings* Settings = GetMutableDefault<UOpenPypeSettings>();
|
||||
UAyonSettings* Settings = GetMutableDefault<UAyonSettings>();
|
||||
|
||||
// Register the settings
|
||||
ISettingsSectionPtr SettingsSection = SettingsModule.RegisterSettings("Project", "OpenPype", "General",
|
||||
ISettingsSectionPtr SettingsSection = SettingsModule.RegisterSettings("Project", "Ayon", "General",
|
||||
LOCTEXT("RuntimeGeneralSettingsName",
|
||||
"General"),
|
||||
LOCTEXT("RuntimeGeneralSettingsDescription",
|
||||
|
|
@ -119,13 +120,13 @@ void FOpenPypeModule::RegisterSettings()
|
|||
// validate those or just act to settings changes.
|
||||
if (SettingsSection.IsValid())
|
||||
{
|
||||
SettingsSection->OnModified().BindRaw(this, &FOpenPypeModule::HandleSettingsSaved);
|
||||
SettingsSection->OnModified().BindRaw(this, &FAyonModule::HandleSettingsSaved);
|
||||
}
|
||||
}
|
||||
|
||||
bool FOpenPypeModule::HandleSettingsSaved()
|
||||
bool FAyonModule::HandleSettingsSaved()
|
||||
{
|
||||
UOpenPypeSettings* Settings = GetMutableDefault<UOpenPypeSettings>();
|
||||
UAyonSettings* Settings = GetMutableDefault<UAyonSettings>();
|
||||
bool ResaveSettings = false;
|
||||
|
||||
// You can put any validation code in here and resave the settings in case an invalid
|
||||
|
|
@ -140,16 +141,16 @@ bool FOpenPypeModule::HandleSettingsSaved()
|
|||
}
|
||||
|
||||
|
||||
void FOpenPypeModule::MenuPopup()
|
||||
void FAyonModule::MenuPopup()
|
||||
{
|
||||
UOpenPypePythonBridge* bridge = UOpenPypePythonBridge::Get();
|
||||
UAyonPythonBridge* bridge = UAyonPythonBridge::Get();
|
||||
bridge->RunInPython_Popup();
|
||||
}
|
||||
|
||||
void FOpenPypeModule::MenuDialog()
|
||||
void FAyonModule::MenuDialog()
|
||||
{
|
||||
UOpenPypePythonBridge* bridge = UOpenPypePythonBridge::Get();
|
||||
UAyonPythonBridge* bridge = UAyonPythonBridge::Get();
|
||||
bridge->RunInPython_Dialog();
|
||||
}
|
||||
|
||||
IMPLEMENT_MODULE(FOpenPypeModule, OpenPype)
|
||||
IMPLEMENT_MODULE(FAyonModule, Ayon)
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#include "AyonAssetContainer.h"
|
||||
#include "AssetRegistryModule.h"
|
||||
#include "Misc/PackageName.h"
|
||||
#include "Containers/UnrealString.h"
|
||||
|
||||
UAyonAssetContainer::UAyonAssetContainer(const FObjectInitializer& ObjectInitializer)
|
||||
: UAssetUserData(ObjectInitializer)
|
||||
{
|
||||
FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>("AssetRegistry");
|
||||
FString path = UAyonAssetContainer::GetPathName();
|
||||
UE_LOG(LogTemp, Warning, TEXT("UAyonAssetContainer %s"), *path);
|
||||
FARFilter Filter;
|
||||
Filter.PackagePaths.Add(FName(*path));
|
||||
|
||||
AssetRegistryModule.Get().OnAssetAdded().AddUObject(this, &UAyonAssetContainer::OnAssetAdded);
|
||||
AssetRegistryModule.Get().OnAssetRemoved().AddUObject(this, &UAyonAssetContainer::OnAssetRemoved);
|
||||
AssetRegistryModule.Get().OnAssetRenamed().AddUObject(this, &UAyonAssetContainer::OnAssetRenamed);
|
||||
}
|
||||
|
||||
void UAyonAssetContainer::OnAssetAdded(const FAssetData& AssetData)
|
||||
{
|
||||
TArray<FString> split;
|
||||
|
||||
// get directory of current container
|
||||
FString selfFullPath = UAyonAssetContainer::GetPathName();
|
||||
FString selfDir = FPackageName::GetLongPackagePath(*selfFullPath);
|
||||
|
||||
// get asset path and class
|
||||
FString assetPath = AssetData.GetFullName();
|
||||
FString assetFName = AssetData.AssetClass.ToString();
|
||||
|
||||
// split path
|
||||
assetPath.ParseIntoArray(split, TEXT(" "), true);
|
||||
|
||||
FString assetDir = FPackageName::GetLongPackagePath(*split[1]);
|
||||
|
||||
// take interest only in paths starting with path of current container
|
||||
if (assetDir.StartsWith(*selfDir))
|
||||
{
|
||||
// exclude self
|
||||
if (assetFName != "AyonAssetContainer")
|
||||
{
|
||||
assets.Add(assetPath);
|
||||
assetsData.Add(AssetData);
|
||||
UE_LOG(LogTemp, Log, TEXT("%s: asset added to %s"), *selfFullPath, *selfDir);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UAyonAssetContainer::OnAssetRemoved(const FAssetData& AssetData)
|
||||
{
|
||||
TArray<FString> split;
|
||||
|
||||
// get directory of current container
|
||||
FString selfFullPath = UAyonAssetContainer::GetPathName();
|
||||
FString selfDir = FPackageName::GetLongPackagePath(*selfFullPath);
|
||||
|
||||
// get asset path and class
|
||||
FString assetPath = AssetData.GetFullName();
|
||||
FString assetFName = AssetData.AssetClass.ToString();
|
||||
|
||||
// split path
|
||||
assetPath.ParseIntoArray(split, TEXT(" "), true);
|
||||
|
||||
FString assetDir = FPackageName::GetLongPackagePath(*split[1]);
|
||||
|
||||
// take interest only in paths starting with path of current container
|
||||
FString path = UAyonAssetContainer::GetPathName();
|
||||
FString lpp = FPackageName::GetLongPackagePath(*path);
|
||||
|
||||
if (assetDir.StartsWith(*selfDir))
|
||||
{
|
||||
// exclude self
|
||||
if (assetFName != "AyonAssetContainer")
|
||||
{
|
||||
// UE_LOG(LogTemp, Warning, TEXT("%s: asset removed"), *lpp);
|
||||
assets.Remove(assetPath);
|
||||
assetsData.Remove(AssetData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UAyonAssetContainer::OnAssetRenamed(const FAssetData& AssetData, const FString& str)
|
||||
{
|
||||
TArray<FString> split;
|
||||
|
||||
// get directory of current container
|
||||
FString selfFullPath = UAyonAssetContainer::GetPathName();
|
||||
FString selfDir = FPackageName::GetLongPackagePath(*selfFullPath);
|
||||
|
||||
// get asset path and class
|
||||
FString assetPath = AssetData.GetFullName();
|
||||
FString assetFName = AssetData.AssetClass.ToString();
|
||||
|
||||
// split path
|
||||
assetPath.ParseIntoArray(split, TEXT(" "), true);
|
||||
|
||||
FString assetDir = FPackageName::GetLongPackagePath(*split[1]);
|
||||
if (assetDir.StartsWith(*selfDir))
|
||||
{
|
||||
// exclude self
|
||||
if (assetFName != "AyonAssetContainer")
|
||||
{
|
||||
|
||||
assets.Remove(str);
|
||||
assets.Add(assetPath);
|
||||
assetsData.Remove(AssetData);
|
||||
// UE_LOG(LogTemp, Warning, TEXT("%s: asset renamed %s"), *lpp, *str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
#include "AyonAssetContainerFactory.h"
|
||||
#include "AyonAssetContainer.h"
|
||||
|
||||
UAyonAssetContainerFactory::UAyonAssetContainerFactory(const FObjectInitializer& ObjectInitializer)
|
||||
: UFactory(ObjectInitializer)
|
||||
{
|
||||
SupportedClass = UAyonAssetContainer::StaticClass();
|
||||
bCreateNew = false;
|
||||
bEditorImport = true;
|
||||
}
|
||||
|
||||
UObject* UAyonAssetContainerFactory::FactoryCreateNew(UClass* Class, UObject* InParent, FName Name, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn)
|
||||
{
|
||||
UAyonAssetContainer* AssetContainer = NewObject<UAyonAssetContainer>(InParent, Class, Name, Flags);
|
||||
return AssetContainer;
|
||||
}
|
||||
|
||||
bool UAyonAssetContainerFactory::ShouldShowInNewMenu() const {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
#include "OpenPypeLib.h"
|
||||
#include "AyonLib.h"
|
||||
|
||||
#include "AssetViewUtils.h"
|
||||
#include "Misc/Paths.h"
|
||||
|
|
@ -13,7 +13,7 @@
|
|||
* @warning This color will appear only after Editor restart. Is there a better way?
|
||||
*/
|
||||
|
||||
bool UOpenPypeLib::SetFolderColor(const FString& FolderPath, const FLinearColor& FolderColor, const bool& bForceAdd)
|
||||
bool UAyonLib::SetFolderColor(const FString& FolderPath, const FLinearColor& FolderColor, const bool& bForceAdd)
|
||||
{
|
||||
if (AssetViewUtils::DoesFolderExist(FolderPath))
|
||||
{
|
||||
|
|
@ -31,11 +31,11 @@ bool UOpenPypeLib::SetFolderColor(const FString& FolderPath, const FLinearColor&
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns all properties on given object
|
||||
* Returns all poperties on given object
|
||||
* @param cls - class
|
||||
* @return TArray of properties
|
||||
*/
|
||||
TArray<FString> UOpenPypeLib::GetAllProperties(UClass* cls)
|
||||
TArray<FString> UAyonLib::GetAllProperties(UClass* cls)
|
||||
{
|
||||
TArray<FString> Ret;
|
||||
if (cls != nullptr)
|
||||
|
|
@ -0,0 +1,203 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
// Deprecation warning: this is left here just for backwards compatibility
|
||||
// and will be removed in next versions of Ayon.
|
||||
#pragma once
|
||||
|
||||
#include "AyonPublishInstance.h"
|
||||
#include "AssetRegistryModule.h"
|
||||
#include "AyonLib.h"
|
||||
#include "AyonSettings.h"
|
||||
#include "Framework/Notifications/NotificationManager.h"
|
||||
#include "Widgets/Notifications/SNotificationList.h"
|
||||
|
||||
//Moves all the invalid pointers to the end to prepare them for the shrinking
|
||||
#define REMOVE_INVALID_ENTRIES(VAR) VAR.CompactStable(); \
|
||||
VAR.Shrink();
|
||||
|
||||
UAyonPublishInstance::UAyonPublishInstance(const FObjectInitializer& ObjectInitializer)
|
||||
: UPrimaryDataAsset(ObjectInitializer)
|
||||
{
|
||||
const FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<
|
||||
FAssetRegistryModule>("AssetRegistry");
|
||||
|
||||
const FPropertyEditorModule& PropertyEditorModule = FModuleManager::LoadModuleChecked<FPropertyEditorModule>(
|
||||
"PropertyEditor");
|
||||
|
||||
FString Left, Right;
|
||||
GetPathName().Split("/" + GetName(), &Left, &Right);
|
||||
|
||||
FARFilter Filter;
|
||||
Filter.PackagePaths.Emplace(FName(Left));
|
||||
|
||||
TArray<FAssetData> FoundAssets;
|
||||
AssetRegistryModule.GetRegistry().GetAssets(Filter, FoundAssets);
|
||||
|
||||
for (const FAssetData& AssetData : FoundAssets)
|
||||
OnAssetCreated(AssetData);
|
||||
|
||||
REMOVE_INVALID_ENTRIES(AssetDataInternal)
|
||||
REMOVE_INVALID_ENTRIES(AssetDataExternal)
|
||||
|
||||
AssetRegistryModule.Get().OnAssetAdded().AddUObject(this, &UAyonPublishInstance::OnAssetCreated);
|
||||
AssetRegistryModule.Get().OnAssetRemoved().AddUObject(this, &UAyonPublishInstance::OnAssetRemoved);
|
||||
AssetRegistryModule.Get().OnAssetUpdated().AddUObject(this, &UAyonPublishInstance::OnAssetUpdated);
|
||||
|
||||
#ifdef WITH_EDITOR
|
||||
ColorAyonDirs();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void UAyonPublishInstance::OnAssetCreated(const FAssetData& InAssetData)
|
||||
{
|
||||
TArray<FString> split;
|
||||
|
||||
UObject* Asset = InAssetData.GetAsset();
|
||||
|
||||
if (!IsValid(Asset))
|
||||
{
|
||||
UE_LOG(LogAssetData, Warning, TEXT("Asset \"%s\" is not valid! Skipping the addition."),
|
||||
*InAssetData.ObjectPath.ToString());
|
||||
return;
|
||||
}
|
||||
|
||||
const bool result = IsUnderSameDir(Asset) && Cast<UAyonPublishInstance>(Asset) == nullptr;
|
||||
|
||||
if (result)
|
||||
{
|
||||
if (AssetDataInternal.Emplace(Asset).IsValidId())
|
||||
{
|
||||
UE_LOG(LogTemp, Log, TEXT("Added an Asset to PublishInstance - Publish Instance: %s, Asset %s"),
|
||||
*this->GetName(), *Asset->GetName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UAyonPublishInstance::OnAssetRemoved(const FAssetData& InAssetData)
|
||||
{
|
||||
if (Cast<UAyonPublishInstance>(InAssetData.GetAsset()) == nullptr)
|
||||
{
|
||||
if (AssetDataInternal.Contains(nullptr))
|
||||
{
|
||||
AssetDataInternal.Remove(nullptr);
|
||||
REMOVE_INVALID_ENTRIES(AssetDataInternal)
|
||||
}
|
||||
else
|
||||
{
|
||||
AssetDataExternal.Remove(nullptr);
|
||||
REMOVE_INVALID_ENTRIES(AssetDataExternal)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UAyonPublishInstance::OnAssetUpdated(const FAssetData& InAssetData)
|
||||
{
|
||||
REMOVE_INVALID_ENTRIES(AssetDataInternal);
|
||||
REMOVE_INVALID_ENTRIES(AssetDataExternal);
|
||||
}
|
||||
|
||||
bool UAyonPublishInstance::IsUnderSameDir(const UObject* InAsset) const
|
||||
{
|
||||
FString ThisLeft, ThisRight;
|
||||
this->GetPathName().Split(this->GetName(), &ThisLeft, &ThisRight);
|
||||
|
||||
return InAsset->GetPathName().StartsWith(ThisLeft);
|
||||
}
|
||||
|
||||
#ifdef WITH_EDITOR
|
||||
|
||||
void UAyonPublishInstance::ColorAyonDirs()
|
||||
{
|
||||
FString PathName = this->GetPathName();
|
||||
|
||||
//Check whether the path contains the defined Ayon folder
|
||||
if (!PathName.Contains(TEXT("Ayon"))) return;
|
||||
|
||||
//Get the base path for open pype
|
||||
FString PathLeft, PathRight;
|
||||
PathName.Split(FString("Ayon"), &PathLeft, &PathRight);
|
||||
|
||||
if (PathLeft.IsEmpty() || PathRight.IsEmpty())
|
||||
{
|
||||
UE_LOG(LogAssetData, Error, TEXT("Failed to retrieve the base Ayon directory!"))
|
||||
return;
|
||||
}
|
||||
|
||||
PathName.RemoveFromEnd(PathRight, ESearchCase::CaseSensitive);
|
||||
|
||||
//Get the current settings
|
||||
const UAyonSettings* Settings = GetMutableDefault<UAyonSettings>();
|
||||
|
||||
//Color the base folder
|
||||
UAyonLib::SetFolderColor(PathName, Settings->GetFolderFColor(), false);
|
||||
|
||||
//Get Sub paths, iterate through them and color them according to the folder color in UAyonSettings
|
||||
const FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>(
|
||||
"AssetRegistry");
|
||||
|
||||
TArray<FString> PathList;
|
||||
|
||||
AssetRegistryModule.Get().GetSubPaths(PathName, PathList, true);
|
||||
|
||||
if (PathList.Num() > 0)
|
||||
{
|
||||
for (const FString& Path : PathList)
|
||||
{
|
||||
UAyonLib::SetFolderColor(Path, Settings->GetFolderFColor(), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UAyonPublishInstance::SendNotification(const FString& Text) const
|
||||
{
|
||||
FNotificationInfo Info{FText::FromString(Text)};
|
||||
|
||||
Info.bFireAndForget = true;
|
||||
Info.bUseLargeFont = false;
|
||||
Info.bUseThrobber = false;
|
||||
Info.bUseSuccessFailIcons = false;
|
||||
Info.ExpireDuration = 4.f;
|
||||
Info.FadeOutDuration = 2.f;
|
||||
|
||||
FSlateNotificationManager::Get().AddNotification(Info);
|
||||
|
||||
UE_LOG(LogAssetData, Warning,
|
||||
TEXT(
|
||||
"Removed duplicated asset from the AssetsDataExternal in Container \"%s\", Asset is already included in the AssetDataInternal!"
|
||||
), *GetName()
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
void UAyonPublishInstance::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
|
||||
{
|
||||
Super::PostEditChangeProperty(PropertyChangedEvent);
|
||||
|
||||
if (PropertyChangedEvent.ChangeType == EPropertyChangeType::ValueSet &&
|
||||
PropertyChangedEvent.Property->GetFName() == GET_MEMBER_NAME_CHECKED(
|
||||
UAyonPublishInstance, AssetDataExternal))
|
||||
{
|
||||
// Check for duplicated assets
|
||||
for (const auto& Asset : AssetDataInternal)
|
||||
{
|
||||
if (AssetDataExternal.Contains(Asset))
|
||||
{
|
||||
AssetDataExternal.Remove(Asset);
|
||||
return SendNotification(
|
||||
"You are not allowed to add assets into AssetDataExternal which are already included in AssetDataInternal!");
|
||||
}
|
||||
}
|
||||
|
||||
// Check if no UAyonPublishInstance type assets are included
|
||||
for (const auto& Asset : AssetDataExternal)
|
||||
{
|
||||
if (Cast<UAyonPublishInstance>(Asset.Get()) != nullptr)
|
||||
{
|
||||
AssetDataExternal.Remove(Asset);
|
||||
return SendNotification("You are not allowed to add publish instances!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
// Deprecation warning: this is left here just for backwards compatibility
|
||||
// and will be removed in next versions of Ayon.
|
||||
#include "AyonPublishInstanceFactory.h"
|
||||
#include "AyonPublishInstance.h"
|
||||
|
||||
UAyonPublishInstanceFactory::UAyonPublishInstanceFactory(const FObjectInitializer& ObjectInitializer)
|
||||
: UFactory(ObjectInitializer)
|
||||
{
|
||||
SupportedClass = UAyonPublishInstance::StaticClass();
|
||||
bCreateNew = false;
|
||||
bEditorImport = true;
|
||||
}
|
||||
|
||||
UObject* UAyonPublishInstanceFactory::FactoryCreateNew(UClass* InClass, UObject* InParent, FName InName, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn)
|
||||
{
|
||||
check(InClass->IsChildOf(UAyonPublishInstance::StaticClass()));
|
||||
return NewObject<UAyonPublishInstance>(InParent, InClass, InName, Flags);
|
||||
}
|
||||
|
||||
bool UAyonPublishInstanceFactory::ShouldShowInNewMenu() const {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
#include "AyonPythonBridge.h"
|
||||
|
||||
UAyonPythonBridge* UAyonPythonBridge::Get()
|
||||
{
|
||||
TArray<UClass*> AyonPythonBridgeClasses;
|
||||
GetDerivedClasses(UAyonPythonBridge::StaticClass(), AyonPythonBridgeClasses);
|
||||
int32 NumClasses = AyonPythonBridgeClasses.Num();
|
||||
if (NumClasses > 0)
|
||||
{
|
||||
return Cast<UAyonPythonBridge>(AyonPythonBridgeClasses[NumClasses - 1]->GetDefaultObject());
|
||||
}
|
||||
return nullptr;
|
||||
};
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
|
||||
#include "AyonSettings.h"
|
||||
|
||||
#include "Interfaces/IPluginManager.h"
|
||||
|
||||
/**
|
||||
* Mainly is used for initializing default values if the DefaultAyonSettings.ini file does not exist in the saved config
|
||||
*/
|
||||
UAyonSettings::UAyonSettings(const FObjectInitializer& ObjectInitializer)
|
||||
{
|
||||
|
||||
const FString ConfigFilePath = AYON_SETTINGS_FILEPATH;
|
||||
|
||||
// This has to be probably in the future set using the UE Reflection system
|
||||
FColor Color;
|
||||
GConfig->GetColor(TEXT("/Script/Ayon.AyonSettings"), TEXT("FolderColor"), Color, ConfigFilePath);
|
||||
|
||||
FolderColor = Color;
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
#include "AyonStyle.h"
|
||||
#include "Framework/Application/SlateApplication.h"
|
||||
#include "Styling/SlateStyle.h"
|
||||
#include "Styling/SlateStyleRegistry.h"
|
||||
|
||||
|
||||
TUniquePtr< FSlateStyleSet > FAyonStyle::AyonStyleInstance = nullptr;
|
||||
|
||||
void FAyonStyle::Initialize()
|
||||
{
|
||||
if (!AyonStyleInstance.IsValid())
|
||||
{
|
||||
AyonStyleInstance = Create();
|
||||
FSlateStyleRegistry::RegisterSlateStyle(*AyonStyleInstance);
|
||||
}
|
||||
}
|
||||
|
||||
void FAyonStyle::Shutdown()
|
||||
{
|
||||
if (AyonStyleInstance.IsValid())
|
||||
{
|
||||
FSlateStyleRegistry::UnRegisterSlateStyle(*AyonStyleInstance);
|
||||
AyonStyleInstance.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
FName FAyonStyle::GetStyleSetName()
|
||||
{
|
||||
static FName StyleSetName(TEXT("AyonStyle"));
|
||||
return StyleSetName;
|
||||
}
|
||||
|
||||
FName FAyonStyle::GetContextName()
|
||||
{
|
||||
static FName ContextName(TEXT("Ayon"));
|
||||
return ContextName;
|
||||
}
|
||||
|
||||
#define IMAGE_BRUSH(RelativePath, ...) FSlateImageBrush( Style->RootToContentDir( RelativePath, TEXT(".png") ), __VA_ARGS__ )
|
||||
|
||||
const FVector2D Icon40x40(40.0f, 40.0f);
|
||||
|
||||
TUniquePtr< FSlateStyleSet > FAyonStyle::Create()
|
||||
{
|
||||
TUniquePtr< FSlateStyleSet > Style = MakeUnique<FSlateStyleSet>(GetStyleSetName());
|
||||
Style->SetContentRoot(FPaths::EnginePluginsDir() / TEXT("Marketplace/Ayon/Resources"));
|
||||
|
||||
return Style;
|
||||
}
|
||||
|
||||
void FAyonStyle::SetIcon(const FString& StyleName, const FString& ResourcePath)
|
||||
{
|
||||
FSlateStyleSet* Style = AyonStyleInstance.Get();
|
||||
|
||||
FString Name(GetContextName().ToString());
|
||||
Name = Name + "." + StyleName;
|
||||
Style->Set(*Name, new FSlateImageBrush(Style->RootToContentDir(ResourcePath, TEXT(".png")), Icon40x40));
|
||||
|
||||
|
||||
FSlateApplication::Get().GetRenderer()->ReloadTextureResources();
|
||||
}
|
||||
|
||||
#undef IMAGE_BRUSH
|
||||
|
||||
const ISlateStyle& FAyonStyle::Get()
|
||||
{
|
||||
check(AyonStyleInstance);
|
||||
return *AyonStyleInstance;
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
|
||||
|
||||
#include "Commandlets/AyonActionResult.h"
|
||||
#include "Logging/Ayon_Log.h"
|
||||
|
||||
EAyon_ActionResult::Type& FAyon_ActionResult::GetStatus()
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
FText& FAyon_ActionResult::GetReason()
|
||||
{
|
||||
return Reason;
|
||||
}
|
||||
|
||||
FAyon_ActionResult::FAyon_ActionResult():Status(EAyon_ActionResult::Type::Ok)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
FAyon_ActionResult::FAyon_ActionResult(const EAyon_ActionResult::Type& InEnum):Status(InEnum)
|
||||
{
|
||||
TryLog();
|
||||
}
|
||||
|
||||
FAyon_ActionResult::FAyon_ActionResult(const EAyon_ActionResult::Type& InEnum, const FText& InReason):Status(InEnum), Reason(InReason)
|
||||
{
|
||||
TryLog();
|
||||
};
|
||||
|
||||
bool FAyon_ActionResult::IsProblem() const
|
||||
{
|
||||
return Status != EAyon_ActionResult::Ok;
|
||||
}
|
||||
|
||||
void FAyon_ActionResult::TryLog() const
|
||||
{
|
||||
if(IsProblem())
|
||||
UE_LOG(LogCommandletOPGenerateProject, Error, TEXT("%s"), *Reason.ToString());
|
||||
}
|
||||
|
|
@ -0,0 +1,141 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
#include "Commandlets/Implementations/AyonGenerateProjectCommandlet.h"
|
||||
|
||||
#include "Editor.h"
|
||||
#include "GameProjectUtils.h"
|
||||
#include "AyonConstants.h"
|
||||
#include "Commandlets/AyonActionResult.h"
|
||||
#include "ProjectDescriptor.h"
|
||||
|
||||
int32 UAyonGenerateProjectCommandlet::Main(const FString& CommandLineParams)
|
||||
{
|
||||
//Parses command line parameters & creates structure FProjectInformation
|
||||
const FAyonGenerateProjectParams ParsedParams = FAyonGenerateProjectParams(CommandLineParams);
|
||||
ProjectInformation = ParsedParams.GenerateUEProjectInformation();
|
||||
|
||||
//Creates .uproject & other UE files
|
||||
EVALUATE_AYON_ACTION_RESULT(TryCreateProject());
|
||||
|
||||
//Loads created .uproject
|
||||
EVALUATE_AYON_ACTION_RESULT(TryLoadProjectDescriptor());
|
||||
|
||||
//Adds needed plugin to .uproject
|
||||
AttachPluginsToProjectDescriptor();
|
||||
|
||||
//Saves .uproject
|
||||
EVALUATE_AYON_ACTION_RESULT(TrySave());
|
||||
|
||||
//When we are here, there should not be problems in generating Unreal Project for Ayon
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
FAyonGenerateProjectParams::FAyonGenerateProjectParams(): FAyonGenerateProjectParams("")
|
||||
{
|
||||
}
|
||||
|
||||
FAyonGenerateProjectParams::FAyonGenerateProjectParams(const FString& CommandLineParams): CommandLineParams(
|
||||
CommandLineParams)
|
||||
{
|
||||
UCommandlet::ParseCommandLine(*CommandLineParams, Tokens, Switches);
|
||||
}
|
||||
|
||||
FProjectInformation FAyonGenerateProjectParams::GenerateUEProjectInformation() const
|
||||
{
|
||||
FProjectInformation ProjectInformation = FProjectInformation();
|
||||
ProjectInformation.ProjectFilename = GetProjectFileName();
|
||||
|
||||
ProjectInformation.bShouldGenerateCode = IsSwitchPresent("GenerateCode");
|
||||
|
||||
return ProjectInformation;
|
||||
}
|
||||
|
||||
FString FAyonGenerateProjectParams::TryGetToken(const int32 Index) const
|
||||
{
|
||||
return Tokens.IsValidIndex(Index) ? Tokens[Index] : "";
|
||||
}
|
||||
|
||||
FString FAyonGenerateProjectParams::GetProjectFileName() const
|
||||
{
|
||||
return TryGetToken(0);
|
||||
}
|
||||
|
||||
bool FAyonGenerateProjectParams::IsSwitchPresent(const FString& Switch) const
|
||||
{
|
||||
return INDEX_NONE != Switches.IndexOfByPredicate([&Switch](const FString& Item) -> bool
|
||||
{
|
||||
return Item.Equals(Switch);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
UAyonGenerateProjectCommandlet::UAyonGenerateProjectCommandlet()
|
||||
{
|
||||
LogToConsole = true;
|
||||
}
|
||||
|
||||
FAyon_ActionResult UAyonGenerateProjectCommandlet::TryCreateProject() const
|
||||
{
|
||||
FText FailReason;
|
||||
FText FailLog;
|
||||
TArray<FString> OutCreatedFiles;
|
||||
|
||||
if (!GameProjectUtils::CreateProject(ProjectInformation, FailReason, FailLog, &OutCreatedFiles))
|
||||
return FAyon_ActionResult(EAyon_ActionResult::ProjectNotCreated, FailReason);
|
||||
return FAyon_ActionResult();
|
||||
}
|
||||
|
||||
FAyon_ActionResult UAyonGenerateProjectCommandlet::TryLoadProjectDescriptor()
|
||||
{
|
||||
FText FailReason;
|
||||
const bool bLoaded = ProjectDescriptor.Load(ProjectInformation.ProjectFilename, FailReason);
|
||||
|
||||
return FAyon_ActionResult(bLoaded ? EAyon_ActionResult::Ok : EAyon_ActionResult::ProjectNotLoaded, FailReason);
|
||||
}
|
||||
|
||||
void UAyonGenerateProjectCommandlet::AttachPluginsToProjectDescriptor()
|
||||
{
|
||||
FPluginReferenceDescriptor AyonPluginDescriptor;
|
||||
AyonPluginDescriptor.bEnabled = true;
|
||||
AyonPluginDescriptor.Name = AyonConstants::Ayon_PluginName;
|
||||
ProjectDescriptor.Plugins.Add(AyonPluginDescriptor);
|
||||
|
||||
FPluginReferenceDescriptor PythonPluginDescriptor;
|
||||
PythonPluginDescriptor.bEnabled = true;
|
||||
PythonPluginDescriptor.Name = AyonConstants::PythonScript_PluginName;
|
||||
ProjectDescriptor.Plugins.Add(PythonPluginDescriptor);
|
||||
|
||||
FPluginReferenceDescriptor SequencerScriptingPluginDescriptor;
|
||||
SequencerScriptingPluginDescriptor.bEnabled = true;
|
||||
SequencerScriptingPluginDescriptor.Name = AyonConstants::SequencerScripting_PluginName;
|
||||
ProjectDescriptor.Plugins.Add(SequencerScriptingPluginDescriptor);
|
||||
|
||||
FPluginReferenceDescriptor MovieRenderPipelinePluginDescriptor;
|
||||
MovieRenderPipelinePluginDescriptor.bEnabled = true;
|
||||
MovieRenderPipelinePluginDescriptor.Name = AyonConstants::MovieRenderPipeline_PluginName;
|
||||
ProjectDescriptor.Plugins.Add(MovieRenderPipelinePluginDescriptor);
|
||||
|
||||
FPluginReferenceDescriptor EditorScriptingPluginDescriptor;
|
||||
EditorScriptingPluginDescriptor.bEnabled = true;
|
||||
EditorScriptingPluginDescriptor.Name = AyonConstants::EditorScriptingUtils_PluginName;
|
||||
ProjectDescriptor.Plugins.Add(EditorScriptingPluginDescriptor);
|
||||
}
|
||||
|
||||
FAyon_ActionResult UAyonGenerateProjectCommandlet::TrySave()
|
||||
{
|
||||
FText FailReason;
|
||||
const bool bSaved = ProjectDescriptor.Save(ProjectInformation.ProjectFilename, FailReason);
|
||||
|
||||
return FAyon_ActionResult(bSaved ? EAyon_ActionResult::Ok : EAyon_ActionResult::ProjectNotSaved, FailReason);
|
||||
}
|
||||
|
||||
FAyonGenerateProjectParams UAyonGenerateProjectCommandlet::ParseParameters(const FString& Params) const
|
||||
{
|
||||
FAyonGenerateProjectParams ParamsResult;
|
||||
|
||||
TArray<FString> Tokens, Switches;
|
||||
ParseCommandLine(*Params, Tokens, Switches);
|
||||
|
||||
return ParamsResult;
|
||||
}
|
||||
|
|
@ -1,10 +1,12 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
// Deprecation warning: this is left here just for backwards compatibility
|
||||
// and will be removed in next versions of Ayon.
|
||||
#pragma once
|
||||
|
||||
#include "OpenPypePublishInstance.h"
|
||||
#include "AssetRegistryModule.h"
|
||||
#include "OpenPypeLib.h"
|
||||
#include "OpenPypeSettings.h"
|
||||
#include "AyonLib.h"
|
||||
#include "AyonSettings.h"
|
||||
#include "Framework/Notifications/NotificationManager.h"
|
||||
#include "Widgets/Notifications/SNotificationList.h"
|
||||
|
||||
|
|
@ -43,7 +45,7 @@ UOpenPypePublishInstance::UOpenPypePublishInstance(const FObjectInitializer& Obj
|
|||
#ifdef WITH_EDITOR
|
||||
ColorOpenPypeDirs();
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
|
||||
void UOpenPypePublishInstance::OnAssetCreated(const FAssetData& InAssetData)
|
||||
|
|
@ -124,12 +126,12 @@ void UOpenPypePublishInstance::ColorOpenPypeDirs()
|
|||
PathName.RemoveFromEnd(PathRight, ESearchCase::CaseSensitive);
|
||||
|
||||
//Get the current settings
|
||||
const UOpenPypeSettings* Settings = GetMutableDefault<UOpenPypeSettings>();
|
||||
const UAyonSettings* Settings = GetMutableDefault<UAyonSettings>();
|
||||
|
||||
//Color the base folder
|
||||
UOpenPypeLib::SetFolderColor(PathName, Settings->GetFolderFColor(), false);
|
||||
UAyonLib::SetFolderColor(PathName, Settings->GetFolderFColor(), false);
|
||||
|
||||
//Get Sub paths, iterate through them and color them according to the folder color in UOpenPypeSettings
|
||||
//Get Sub paths, iterate through them and color them according to the folder color in UAyonSettings
|
||||
const FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>(
|
||||
"AssetRegistry");
|
||||
|
||||
|
|
@ -141,7 +143,7 @@ void UOpenPypePublishInstance::ColorOpenPypeDirs()
|
|||
{
|
||||
for (const FString& Path : PathList)
|
||||
{
|
||||
UOpenPypeLib::SetFolderColor(Path, Settings->GetFolderFColor(), false);
|
||||
UAyonLib::SetFolderColor(Path, Settings->GetFolderFColor(), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,10 +2,8 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "Engine.h"
|
||||
|
||||
|
||||
class FOpenPypeModule : public IModuleInterface
|
||||
class FAyonModule : public IModuleInterface
|
||||
{
|
||||
public:
|
||||
virtual void StartupModule() override;
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/NoExportTypes.h"
|
||||
#include "Engine/AssetUserData.h"
|
||||
#include "AssetData.h"
|
||||
#include "AyonAssetContainer.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS(Blueprintable)
|
||||
class AYON_API UAyonAssetContainer : public UAssetUserData
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
UAyonAssetContainer(const FObjectInitializer& ObjectInitalizer);
|
||||
// ~UAyonAssetContainer();
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Assets")
|
||||
TArray<FString> assets;
|
||||
|
||||
// There seems to be no reflection option to expose array of FAssetData
|
||||
/*
|
||||
UPROPERTY(Transient, BlueprintReadOnly, Category = "Python", meta=(DisplayName="Assets Data"))
|
||||
TArray<FAssetData> assetsData;
|
||||
*/
|
||||
private:
|
||||
TArray<FAssetData> assetsData;
|
||||
void OnAssetAdded(const FAssetData& AssetData);
|
||||
void OnAssetRemoved(const FAssetData& AssetData);
|
||||
void OnAssetRenamed(const FAssetData& AssetData, const FString& str);
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Factories/Factory.h"
|
||||
#include "AyonAssetContainerFactory.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class AYON_API UAyonAssetContainerFactory : public UFactory
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UAyonAssetContainerFactory(const FObjectInitializer& ObjectInitializer);
|
||||
virtual UObject* FactoryCreateNew(UClass* Class, UObject* InParent, FName Name, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn) override;
|
||||
virtual bool ShouldShowInNewMenu() const override;
|
||||
};
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
|
||||
namespace AyonConstants
|
||||
{
|
||||
const FString Ayon_PluginName = "Ayon";
|
||||
const FString PythonScript_PluginName = "PythonScriptPlugin";
|
||||
const FString SequencerScripting_PluginName = "SequencerScripting";
|
||||
const FString MovieRenderPipeline_PluginName = "MovieRenderPipeline";
|
||||
const FString EditorScriptingUtils_PluginName = "EditorScriptingUtilities";
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1,12 +1,11 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
#pragma once
|
||||
|
||||
#include "Engine.h"
|
||||
#include "OpenPypeLib.generated.h"
|
||||
#include "AyonLib.generated.h"
|
||||
|
||||
|
||||
UCLASS(Blueprintable)
|
||||
class OPENPYPE_API UOpenPypeLib : public UBlueprintFunctionLibrary
|
||||
class AYON_API UAyonLib : public UBlueprintFunctionLibrary
|
||||
{
|
||||
|
||||
GENERATED_BODY()
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
// Deprecation warning: this is left here just for backwards compatibility
|
||||
// and will be removed in next versions of Ayon.
|
||||
#pragma once
|
||||
|
||||
#include "AyonPublishInstance.generated.h"
|
||||
|
||||
|
||||
UCLASS(Blueprintable)
|
||||
class AYON_API UAyonPublishInstance : public UPrimaryDataAsset
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
|
||||
public:
|
||||
/**
|
||||
* Retrieves all the assets which are monitored by the Publish Instance (Monitors assets in the directory which is
|
||||
* placed in)
|
||||
*
|
||||
* @return - Set of UObjects. Careful! They are returning raw pointers. Seems like an issue in UE5
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category="Python")
|
||||
TSet<UObject*> GetInternalAssets() const
|
||||
{
|
||||
//For some reason it can only return Raw Pointers? Seems like an issue which they haven't fixed.
|
||||
TSet<UObject*> ResultSet;
|
||||
|
||||
for (const auto& Asset : AssetDataInternal)
|
||||
ResultSet.Add(Asset.LoadSynchronous());
|
||||
|
||||
return ResultSet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves all the assets which have been added manually by the Publish Instance
|
||||
*
|
||||
* @return - TSet of assets (UObjects). Careful! They are returning raw pointers. Seems like an issue in UE5
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category="Python")
|
||||
TSet<UObject*> GetExternalAssets() const
|
||||
{
|
||||
//For some reason it can only return Raw Pointers? Seems like an issue which they haven't fixed.
|
||||
TSet<UObject*> ResultSet;
|
||||
|
||||
for (const auto& Asset : AssetDataExternal)
|
||||
ResultSet.Add(Asset.LoadSynchronous());
|
||||
|
||||
return ResultSet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function for returning all the assets in the container combined.
|
||||
*
|
||||
* @return Returns all the internal and externally added assets into one set (TSet of UObjects). Careful! They are
|
||||
* returning raw pointers. Seems like an issue in UE5
|
||||
*
|
||||
* @attention If the bAddExternalAssets variable is false, external assets won't be included!
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category="Python")
|
||||
TSet<UObject*> GetAllAssets() const
|
||||
{
|
||||
const TSet<TSoftObjectPtr<UObject>>& IteratedSet = bAddExternalAssets
|
||||
? AssetDataInternal.Union(AssetDataExternal)
|
||||
: AssetDataInternal;
|
||||
|
||||
//Create a new TSet only with raw pointers.
|
||||
TSet<UObject*> ResultSet;
|
||||
|
||||
for (auto& Asset : IteratedSet)
|
||||
ResultSet.Add(Asset.LoadSynchronous());
|
||||
|
||||
return ResultSet;
|
||||
}
|
||||
|
||||
private:
|
||||
UPROPERTY(VisibleAnywhere, Category="Assets")
|
||||
TSet<TSoftObjectPtr<UObject>> AssetDataInternal;
|
||||
|
||||
/**
|
||||
* This property allows exposing the array to include other assets from any other directory than what it's currently
|
||||
* monitoring. NOTE: that these assets have to be added manually! They are not automatically registered or added!
|
||||
*/
|
||||
UPROPERTY(EditAnywhere, Category = "Assets")
|
||||
bool bAddExternalAssets = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, meta=(EditCondition="bAddExternalAssets"), Category="Assets")
|
||||
TSet<TSoftObjectPtr<UObject>> AssetDataExternal;
|
||||
|
||||
|
||||
void OnAssetCreated(const FAssetData& InAssetData);
|
||||
void OnAssetRemoved(const FAssetData& InAssetData);
|
||||
void OnAssetUpdated(const FAssetData& InAssetData);
|
||||
|
||||
bool IsUnderSameDir(const UObject* InAsset) const;
|
||||
|
||||
#ifdef WITH_EDITOR
|
||||
|
||||
void ColorAyonDirs();
|
||||
|
||||
void SendNotification(const FString& Text) const;
|
||||
virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override;
|
||||
|
||||
#endif
|
||||
};
|
||||
|
|
@ -1,20 +1,22 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
// Deprecation warning: this is left here just for backwards compatibility
|
||||
// and will be removed in next versions of Ayon.
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Factories/Factory.h"
|
||||
#include "OpenPypePublishInstanceFactory.generated.h"
|
||||
#include "AyonPublishInstanceFactory.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class OPENPYPE_API UOpenPypePublishInstanceFactory : public UFactory
|
||||
class AYON_API UAyonPublishInstanceFactory : public UFactory
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UOpenPypePublishInstanceFactory(const FObjectInitializer& ObjectInitializer);
|
||||
UAyonPublishInstanceFactory(const FObjectInitializer& ObjectInitializer);
|
||||
virtual UObject* FactoryCreateNew(UClass* InClass, UObject* InParent, FName InName, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn) override;
|
||||
virtual bool ShouldShowInNewMenu() const override;
|
||||
};
|
||||
|
|
@ -1,16 +1,15 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
#pragma once
|
||||
#include "Engine.h"
|
||||
#include "OpenPypePythonBridge.generated.h"
|
||||
#include "AyonPythonBridge.generated.h"
|
||||
|
||||
UCLASS(Blueprintable)
|
||||
class UOpenPypePythonBridge : public UObject
|
||||
class UAyonPythonBridge : public UObject
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UFUNCTION(BlueprintCallable, Category = Python)
|
||||
static UOpenPypePythonBridge* Get();
|
||||
static UAyonPythonBridge* Get();
|
||||
|
||||
UFUNCTION(BlueprintImplementableEvent, Category = Python)
|
||||
void RunInPython_Popup() const;
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "AyonSettings.generated.h"
|
||||
|
||||
#define AYON_SETTINGS_FILEPATH IPluginManager::Get().FindPlugin("Ayon")->GetBaseDir() / TEXT("Config") / TEXT("DefaultAyonSettings.ini")
|
||||
|
||||
UCLASS(Config=AyonSettings, DefaultConfig)
|
||||
class AYON_API UAyonSettings : public UObject
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category = Settings)
|
||||
FColor GetFolderFColor() const
|
||||
{
|
||||
return FolderColor;
|
||||
}
|
||||
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category = Settings)
|
||||
FLinearColor GetFolderFLinearColor() const
|
||||
{
|
||||
return FLinearColor(FolderColor);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
UPROPERTY(config, EditAnywhere, Category = Folders)
|
||||
FColor FolderColor = FColor(25,45,223);
|
||||
};
|
||||
|
|
@ -6,7 +6,7 @@ class FSlateStyleSet;
|
|||
class ISlateStyle;
|
||||
|
||||
|
||||
class FOpenPypeStyle
|
||||
class FAyonStyle
|
||||
{
|
||||
public:
|
||||
static void Initialize();
|
||||
|
|
@ -19,5 +19,5 @@ public:
|
|||
|
||||
private:
|
||||
static TUniquePtr< FSlateStyleSet > Create();
|
||||
static TUniquePtr< FSlateStyleSet > OpenPypeStyleInstance;
|
||||
static TUniquePtr< FSlateStyleSet > AyonStyleInstance;
|
||||
};
|
||||
|
|
@ -3,23 +3,23 @@
|
|||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "OPActionResult.generated.h"
|
||||
#include "AyonActionResult.generated.h"
|
||||
|
||||
/**
|
||||
* @brief This macro returns error code when is problem or does nothing when there is no problem.
|
||||
* @param ActionResult FOP_ActionResult structure
|
||||
* @param ActionResult FAyon_ActionResult structure
|
||||
*/
|
||||
#define EVALUATE_OP_ACTION_RESULT(ActionResult) \
|
||||
#define EVALUATE_AYON_ACTION_RESULT(ActionResult) \
|
||||
if(ActionResult.IsProblem()) \
|
||||
return ActionResult.GetStatus();
|
||||
|
||||
/**
|
||||
* @brief This enum values are humanly readable mapping of error codes.
|
||||
* Here should be all error codes to be possible find what went wrong.
|
||||
* TODO: In the future a web document should exists with the mapped error code & what problem occurred & how to repair it...
|
||||
* TODO: In the future should exists an web document where is mapped error code & what problem occured & how to repair it...
|
||||
*/
|
||||
UENUM()
|
||||
namespace EOP_ActionResult
|
||||
namespace EAyon_ActionResult
|
||||
{
|
||||
enum Type
|
||||
{
|
||||
|
|
@ -27,11 +27,11 @@ namespace EOP_ActionResult
|
|||
ProjectNotCreated,
|
||||
ProjectNotLoaded,
|
||||
ProjectNotSaved,
|
||||
//....Here insert another values
|
||||
//....Here insert another values
|
||||
|
||||
//Do not remove!
|
||||
//Usable for looping through enum values
|
||||
__Last UMETA(Hidden)
|
||||
__Last UMETA(Hidden)
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -40,44 +40,44 @@ namespace EOP_ActionResult
|
|||
* @brief This struct holds action result enum and optionally reason of fail
|
||||
*/
|
||||
USTRUCT()
|
||||
struct FOP_ActionResult
|
||||
struct FAyon_ActionResult
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
/** @brief Default constructor usable when there is no problem */
|
||||
FOP_ActionResult();
|
||||
FAyon_ActionResult();
|
||||
|
||||
/**
|
||||
* @brief This constructor initializes variables & attempts to log when is error
|
||||
* @param InEnum Status
|
||||
*/
|
||||
FOP_ActionResult(const EOP_ActionResult::Type& InEnum);
|
||||
FAyon_ActionResult(const EAyon_ActionResult::Type& InEnum);
|
||||
|
||||
/**
|
||||
* @brief This constructor initializes variables & attempts to log when is error
|
||||
* @param InEnum Status
|
||||
* @param InReason Reason of potential fail
|
||||
*/
|
||||
FOP_ActionResult(const EOP_ActionResult::Type& InEnum, const FText& InReason);
|
||||
FAyon_ActionResult(const EAyon_ActionResult::Type& InEnum, const FText& InReason);
|
||||
|
||||
private:
|
||||
/** @brief Action status */
|
||||
EOP_ActionResult::Type Status;
|
||||
EAyon_ActionResult::Type Status;
|
||||
|
||||
/** @brief Optional reason of fail */
|
||||
FText Reason;
|
||||
FText Reason;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Checks if there is problematic state
|
||||
* @return true when status is not equal to EOP_ActionResult::Ok
|
||||
* @return true when status is not equal to EAyon_ActionResult::Ok
|
||||
*/
|
||||
bool IsProblem() const;
|
||||
EOP_ActionResult::Type& GetStatus();
|
||||
EAyon_ActionResult::Type& GetStatus();
|
||||
FText& GetReason();
|
||||
|
||||
private:
|
||||
private:
|
||||
void TryLog() const;
|
||||
};
|
||||
|
||||
|
|
@ -2,10 +2,10 @@
|
|||
#pragma once
|
||||
|
||||
#include "GameProjectUtils.h"
|
||||
#include "Commandlets/OPActionResult.h"
|
||||
#include "Commandlets/AyonActionResult.h"
|
||||
#include "ProjectDescriptor.h"
|
||||
#include "Commandlets/Commandlet.h"
|
||||
#include "OPGenerateProjectCommandlet.generated.h"
|
||||
#include "AyonGenerateProjectCommandlet.generated.h"
|
||||
|
||||
struct FProjectDescriptor;
|
||||
struct FProjectInformation;
|
||||
|
|
@ -14,7 +14,7 @@ struct FProjectInformation;
|
|||
* @brief Structure which parses command line parameters and generates FProjectInformation
|
||||
*/
|
||||
USTRUCT()
|
||||
struct FOPGenerateProjectParams
|
||||
struct FAyonGenerateProjectParams
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
|
@ -24,8 +24,8 @@ private:
|
|||
TArray<FString> Switches;
|
||||
|
||||
public:
|
||||
FOPGenerateProjectParams();
|
||||
FOPGenerateProjectParams(const FString& CommandLineParams);
|
||||
FAyonGenerateProjectParams();
|
||||
FAyonGenerateProjectParams(const FString& CommandLineParams);
|
||||
|
||||
FProjectInformation GenerateUEProjectInformation() const;
|
||||
|
||||
|
|
@ -37,7 +37,7 @@ private:
|
|||
};
|
||||
|
||||
UCLASS()
|
||||
class OPENPYPE_API UOPGenerateProjectCommandlet : public UCommandlet
|
||||
class AYON_API UAyonGenerateProjectCommandlet : public UCommandlet
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
|
@ -46,15 +46,15 @@ private:
|
|||
FProjectDescriptor ProjectDescriptor;
|
||||
|
||||
public:
|
||||
UOPGenerateProjectCommandlet();
|
||||
UAyonGenerateProjectCommandlet();
|
||||
|
||||
virtual int32 Main(const FString& CommandLineParams) override;
|
||||
|
||||
private:
|
||||
FOPGenerateProjectParams ParseParameters(const FString& Params) const;
|
||||
FOP_ActionResult TryCreateProject() const;
|
||||
FOP_ActionResult TryLoadProjectDescriptor();
|
||||
FAyonGenerateProjectParams ParseParameters(const FString& Params) const;
|
||||
FAyon_ActionResult TryCreateProject() const;
|
||||
FAyon_ActionResult TryLoadProjectDescriptor();
|
||||
void AttachPluginsToProjectDescriptor();
|
||||
FOP_ActionResult TrySave();
|
||||
FAyon_ActionResult TrySave();
|
||||
};
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
#pragma once
|
||||
|
||||
DEFINE_LOG_CATEGORY_STATIC(LogCommandletOPGenerateProject, Log, All);
|
||||
DEFINE_LOG_CATEGORY_STATIC(LogCommandletOPGenerateProject, Log, All);
|
||||
|
|
@ -1,12 +1,13 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
// Deprecation warning: this is left here just for backwards compatibility
|
||||
// and will be removed in next versions of Ayon.
|
||||
#pragma once
|
||||
|
||||
#include "Engine.h"
|
||||
#include "OpenPypePublishInstance.generated.h"
|
||||
|
||||
|
||||
UCLASS(Blueprintable)
|
||||
class OPENPYPE_API UOpenPypePublishInstance : public UPrimaryDataAsset
|
||||
class AYON_API UOpenPypePublishInstance : public UPrimaryDataAsset
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
|
||||
|
|
@ -48,7 +49,7 @@ public:
|
|||
|
||||
/**
|
||||
* Function for returning all the assets in the container combined.
|
||||
*
|
||||
*
|
||||
* @return Returns all the internal and externally added assets into one set (TSet of UObjects). Careful! They are
|
||||
* returning raw pointers. Seems like an issue in UE5
|
||||
*
|
||||
|
|
@ -94,7 +95,7 @@ private:
|
|||
#ifdef WITH_EDITOR
|
||||
|
||||
void ColorOpenPypeDirs();
|
||||
|
||||
|
||||
void SendNotification(const FString& Text) const;
|
||||
virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override;
|
||||
|
||||
|
|
@ -0,0 +1 @@
|
|||
D:\UE4\UE_4.27\Engine\Build\BatchFiles\RunUAT.bat BuildPlugin -plugin="D:\OpenPype\openpype\hosts\unreal\integration\UE_4.27\Ayon\Ayon.uplugin" -Package="D:\BuiltPlugins\4.27"
|
||||
|
|
@ -0,0 +1 @@
|
|||
cmd /k "BuildPlugin_4-27.bat"
|
||||
|
|
@ -5,7 +5,7 @@
|
|||
"Description": "",
|
||||
"Plugins": [
|
||||
{
|
||||
"Name": "OpenPype",
|
||||
"Name": "Ayon",
|
||||
"Enabled": true
|
||||
}
|
||||
]
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
[/Script/OpenPype.OpenPypeSettings]
|
||||
FolderColor=(R=91,G=197,B=220,A=255)
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
import unreal
|
||||
|
||||
openpype_detected = True
|
||||
try:
|
||||
from openpype.pipeline import install_host
|
||||
from openpype.hosts.unreal.api import UnrealHost
|
||||
|
||||
openpype_host = UnrealHost()
|
||||
except ImportError as exc:
|
||||
openpype_host = None
|
||||
openpype_detected = False
|
||||
unreal.log_error("OpenPype: cannot load OpenPype [ {} ]".format(exc))
|
||||
|
||||
if openpype_detected:
|
||||
install_host(openpype_host)
|
||||
|
||||
|
||||
@unreal.uclass()
|
||||
class OpenPypeIntegration(unreal.OpenPypePythonBridge):
|
||||
@unreal.ufunction(override=True)
|
||||
def RunInPython_Popup(self):
|
||||
unreal.log_warning("OpenPype: showing tools popup")
|
||||
if openpype_detected:
|
||||
openpype_host.show_tools_popup()
|
||||
|
||||
@unreal.ufunction(override=True)
|
||||
def RunInPython_Dialog(self):
|
||||
unreal.log_warning("OpenPype: showing tools dialog")
|
||||
if openpype_detected:
|
||||
openpype_host.show_tools_dialog()
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
{
|
||||
"FileVersion": 3,
|
||||
"Version": 1,
|
||||
"VersionName": "1.0",
|
||||
"FriendlyName": "OpenPype",
|
||||
"Description": "OpenPype Integration",
|
||||
"Category": "OpenPype.Integration",
|
||||
"CreatedBy": "Ondrej Samohel",
|
||||
"CreatedByURL": "https://openpype.io",
|
||||
"DocsURL": "https://openpype.io/docs/artist_hosts_unreal",
|
||||
"MarketplaceURL": "",
|
||||
"SupportURL": "https://pype.club/",
|
||||
"EngineVersion": "4.27",
|
||||
"CanContainContent": true,
|
||||
"Installed": true,
|
||||
"Modules": [
|
||||
{
|
||||
"Name": "OpenPype",
|
||||
"Type": "Editor",
|
||||
"LoadingPhase": "Default"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
# OpenPype Unreal Integration plugin - UE 4.x
|
||||
|
||||
This is plugin for Unreal Editor, creating menu for [OpenPype](https://github.com/getavalon) tools to run.
|
||||
|
||||
## How does this work
|
||||
|
||||
Plugin is creating basic menu items in **Window/OpenPype** section of Unreal Editor main menu and a button
|
||||
on the main toolbar with associated menu. Clicking on those menu items is calling callbacks that are
|
||||
declared in c++ but needs to be implemented during Unreal Editor
|
||||
startup in `Plugins/OpenPype/Content/Python/init_unreal.py` - this should be executed by Unreal Editor
|
||||
automatically.
|
||||
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 4.8 KiB |
|
Before Width: | Height: | Size: 84 KiB |
|
|
@ -1,141 +0,0 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
#include "Commandlets/Implementations/OPGenerateProjectCommandlet.h"
|
||||
|
||||
#include "Editor.h"
|
||||
#include "GameProjectUtils.h"
|
||||
#include "OPConstants.h"
|
||||
#include "Commandlets/OPActionResult.h"
|
||||
#include "ProjectDescriptor.h"
|
||||
|
||||
int32 UOPGenerateProjectCommandlet::Main(const FString& CommandLineParams)
|
||||
{
|
||||
//Parses command line parameters & creates structure FProjectInformation
|
||||
const FOPGenerateProjectParams ParsedParams = FOPGenerateProjectParams(CommandLineParams);
|
||||
ProjectInformation = ParsedParams.GenerateUEProjectInformation();
|
||||
|
||||
//Creates .uproject & other UE files
|
||||
EVALUATE_OP_ACTION_RESULT(TryCreateProject());
|
||||
|
||||
//Loads created .uproject
|
||||
EVALUATE_OP_ACTION_RESULT(TryLoadProjectDescriptor());
|
||||
|
||||
//Adds needed plugin to .uproject
|
||||
AttachPluginsToProjectDescriptor();
|
||||
|
||||
//Saves .uproject
|
||||
EVALUATE_OP_ACTION_RESULT(TrySave());
|
||||
|
||||
//When we are here, there should not be problems in generating Unreal Project for OpenPype
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
FOPGenerateProjectParams::FOPGenerateProjectParams(): FOPGenerateProjectParams("")
|
||||
{
|
||||
}
|
||||
|
||||
FOPGenerateProjectParams::FOPGenerateProjectParams(const FString& CommandLineParams): CommandLineParams(
|
||||
CommandLineParams)
|
||||
{
|
||||
UCommandlet::ParseCommandLine(*CommandLineParams, Tokens, Switches);
|
||||
}
|
||||
|
||||
FProjectInformation FOPGenerateProjectParams::GenerateUEProjectInformation() const
|
||||
{
|
||||
FProjectInformation ProjectInformation = FProjectInformation();
|
||||
ProjectInformation.ProjectFilename = GetProjectFileName();
|
||||
|
||||
ProjectInformation.bShouldGenerateCode = IsSwitchPresent("GenerateCode");
|
||||
|
||||
return ProjectInformation;
|
||||
}
|
||||
|
||||
FString FOPGenerateProjectParams::TryGetToken(const int32 Index) const
|
||||
{
|
||||
return Tokens.IsValidIndex(Index) ? Tokens[Index] : "";
|
||||
}
|
||||
|
||||
FString FOPGenerateProjectParams::GetProjectFileName() const
|
||||
{
|
||||
return TryGetToken(0);
|
||||
}
|
||||
|
||||
bool FOPGenerateProjectParams::IsSwitchPresent(const FString& Switch) const
|
||||
{
|
||||
return INDEX_NONE != Switches.IndexOfByPredicate([&Switch](const FString& Item) -> bool
|
||||
{
|
||||
return Item.Equals(Switch);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
UOPGenerateProjectCommandlet::UOPGenerateProjectCommandlet()
|
||||
{
|
||||
LogToConsole = true;
|
||||
}
|
||||
|
||||
FOP_ActionResult UOPGenerateProjectCommandlet::TryCreateProject() const
|
||||
{
|
||||
FText FailReason;
|
||||
FText FailLog;
|
||||
TArray<FString> OutCreatedFiles;
|
||||
|
||||
if (!GameProjectUtils::CreateProject(ProjectInformation, FailReason, FailLog, &OutCreatedFiles))
|
||||
return FOP_ActionResult(EOP_ActionResult::ProjectNotCreated, FailReason);
|
||||
return FOP_ActionResult();
|
||||
}
|
||||
|
||||
FOP_ActionResult UOPGenerateProjectCommandlet::TryLoadProjectDescriptor()
|
||||
{
|
||||
FText FailReason;
|
||||
const bool bLoaded = ProjectDescriptor.Load(ProjectInformation.ProjectFilename, FailReason);
|
||||
|
||||
return FOP_ActionResult(bLoaded ? EOP_ActionResult::Ok : EOP_ActionResult::ProjectNotLoaded, FailReason);
|
||||
}
|
||||
|
||||
void UOPGenerateProjectCommandlet::AttachPluginsToProjectDescriptor()
|
||||
{
|
||||
FPluginReferenceDescriptor OPPluginDescriptor;
|
||||
OPPluginDescriptor.bEnabled = true;
|
||||
OPPluginDescriptor.Name = OPConstants::OP_PluginName;
|
||||
ProjectDescriptor.Plugins.Add(OPPluginDescriptor);
|
||||
|
||||
FPluginReferenceDescriptor PythonPluginDescriptor;
|
||||
PythonPluginDescriptor.bEnabled = true;
|
||||
PythonPluginDescriptor.Name = OPConstants::PythonScript_PluginName;
|
||||
ProjectDescriptor.Plugins.Add(PythonPluginDescriptor);
|
||||
|
||||
FPluginReferenceDescriptor SequencerScriptingPluginDescriptor;
|
||||
SequencerScriptingPluginDescriptor.bEnabled = true;
|
||||
SequencerScriptingPluginDescriptor.Name = OPConstants::SequencerScripting_PluginName;
|
||||
ProjectDescriptor.Plugins.Add(SequencerScriptingPluginDescriptor);
|
||||
|
||||
FPluginReferenceDescriptor MovieRenderPipelinePluginDescriptor;
|
||||
MovieRenderPipelinePluginDescriptor.bEnabled = true;
|
||||
MovieRenderPipelinePluginDescriptor.Name = OPConstants::MovieRenderPipeline_PluginName;
|
||||
ProjectDescriptor.Plugins.Add(MovieRenderPipelinePluginDescriptor);
|
||||
|
||||
FPluginReferenceDescriptor EditorScriptingPluginDescriptor;
|
||||
EditorScriptingPluginDescriptor.bEnabled = true;
|
||||
EditorScriptingPluginDescriptor.Name = OPConstants::EditorScriptingUtils_PluginName;
|
||||
ProjectDescriptor.Plugins.Add(EditorScriptingPluginDescriptor);
|
||||
}
|
||||
|
||||
FOP_ActionResult UOPGenerateProjectCommandlet::TrySave()
|
||||
{
|
||||
FText FailReason;
|
||||
const bool bSaved = ProjectDescriptor.Save(ProjectInformation.ProjectFilename, FailReason);
|
||||
|
||||
return FOP_ActionResult(bSaved ? EOP_ActionResult::Ok : EOP_ActionResult::ProjectNotSaved, FailReason);
|
||||
}
|
||||
|
||||
FOPGenerateProjectParams UOPGenerateProjectCommandlet::ParseParameters(const FString& Params) const
|
||||
{
|
||||
FOPGenerateProjectParams ParamsResult;
|
||||
|
||||
TArray<FString> Tokens, Switches;
|
||||
ParseCommandLine(*Params, Tokens, Switches);
|
||||
|
||||
return ParamsResult;
|
||||
}
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
|
||||
|
||||
#include "Commandlets/OPActionResult.h"
|
||||
#include "Logging/OP_Log.h"
|
||||
|
||||
EOP_ActionResult::Type& FOP_ActionResult::GetStatus()
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
FText& FOP_ActionResult::GetReason()
|
||||
{
|
||||
return Reason;
|
||||
}
|
||||
|
||||
FOP_ActionResult::FOP_ActionResult():Status(EOP_ActionResult::Type::Ok)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
FOP_ActionResult::FOP_ActionResult(const EOP_ActionResult::Type& InEnum):Status(InEnum)
|
||||
{
|
||||
TryLog();
|
||||
}
|
||||
|
||||
FOP_ActionResult::FOP_ActionResult(const EOP_ActionResult::Type& InEnum, const FText& InReason):Status(InEnum), Reason(InReason)
|
||||
{
|
||||
TryLog();
|
||||
};
|
||||
|
||||
bool FOP_ActionResult::IsProblem() const
|
||||
{
|
||||
return Status != EOP_ActionResult::Ok;
|
||||
}
|
||||
|
||||
void FOP_ActionResult::TryLog() const
|
||||
{
|
||||
if(IsProblem())
|
||||
UE_LOG(LogCommandletOPGenerateProject, Error, TEXT("%s"), *Reason.ToString());
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
#include "Logging/OP_Log.h"
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
#include "OpenPypePublishInstanceFactory.h"
|
||||
#include "OpenPypePublishInstance.h"
|
||||
|
||||
UOpenPypePublishInstanceFactory::UOpenPypePublishInstanceFactory(const FObjectInitializer& ObjectInitializer)
|
||||
: UFactory(ObjectInitializer)
|
||||
{
|
||||
SupportedClass = UOpenPypePublishInstance::StaticClass();
|
||||
bCreateNew = false;
|
||||
bEditorImport = true;
|
||||
}
|
||||
|
||||
UObject* UOpenPypePublishInstanceFactory::FactoryCreateNew(UClass* InClass, UObject* InParent, FName InName, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn)
|
||||
{
|
||||
check(InClass->IsChildOf(UOpenPypePublishInstance::StaticClass()));
|
||||
return NewObject<UOpenPypePublishInstance>(InParent, InClass, InName, Flags);
|
||||
}
|
||||
|
||||
bool UOpenPypePublishInstanceFactory::ShouldShowInNewMenu() const {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
#include "OpenPypePythonBridge.h"
|
||||
|
||||
UOpenPypePythonBridge* UOpenPypePythonBridge::Get()
|
||||
{
|
||||
TArray<UClass*> OpenPypePythonBridgeClasses;
|
||||
GetDerivedClasses(UOpenPypePythonBridge::StaticClass(), OpenPypePythonBridgeClasses);
|
||||
int32 NumClasses = OpenPypePythonBridgeClasses.Num();
|
||||
if (NumClasses > 0)
|
||||
{
|
||||
return Cast<UOpenPypePythonBridge>(OpenPypePythonBridgeClasses[NumClasses - 1]->GetDefaultObject());
|
||||
}
|
||||
return nullptr;
|
||||
};
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
|
||||
#include "OpenPypeSettings.h"
|
||||
|
||||
#include "Interfaces/IPluginManager.h"
|
||||
|
||||
/**
|
||||
* Mainly is used for initializing default values if the DefaultOpenPypeSettings.ini file does not exist in the saved config
|
||||
*/
|
||||
UOpenPypeSettings::UOpenPypeSettings(const FObjectInitializer& ObjectInitializer)
|
||||
{
|
||||
|
||||
const FString ConfigFilePath = OPENPYPE_SETTINGS_FILEPATH;
|
||||
|
||||
// This has to be probably in the future set using the UE Reflection system
|
||||
FColor Color;
|
||||
GConfig->GetColor(TEXT("/Script/OpenPype.OpenPypeSettings"), TEXT("FolderColor"), Color, ConfigFilePath);
|
||||
|
||||
FolderColor = Color;
|
||||
}
|
||||
|
|
@ -1,70 +0,0 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
#include "OpenPypeStyle.h"
|
||||
#include "Framework/Application/SlateApplication.h"
|
||||
#include "Styling/SlateStyle.h"
|
||||
#include "Styling/SlateStyleRegistry.h"
|
||||
|
||||
|
||||
TUniquePtr< FSlateStyleSet > FOpenPypeStyle::OpenPypeStyleInstance = nullptr;
|
||||
|
||||
void FOpenPypeStyle::Initialize()
|
||||
{
|
||||
if (!OpenPypeStyleInstance.IsValid())
|
||||
{
|
||||
OpenPypeStyleInstance = Create();
|
||||
FSlateStyleRegistry::RegisterSlateStyle(*OpenPypeStyleInstance);
|
||||
}
|
||||
}
|
||||
|
||||
void FOpenPypeStyle::Shutdown()
|
||||
{
|
||||
if (OpenPypeStyleInstance.IsValid())
|
||||
{
|
||||
FSlateStyleRegistry::UnRegisterSlateStyle(*OpenPypeStyleInstance);
|
||||
OpenPypeStyleInstance.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
FName FOpenPypeStyle::GetStyleSetName()
|
||||
{
|
||||
static FName StyleSetName(TEXT("OpenPypeStyle"));
|
||||
return StyleSetName;
|
||||
}
|
||||
|
||||
FName FOpenPypeStyle::GetContextName()
|
||||
{
|
||||
static FName ContextName(TEXT("OpenPype"));
|
||||
return ContextName;
|
||||
}
|
||||
|
||||
#define IMAGE_BRUSH(RelativePath, ...) FSlateImageBrush( Style->RootToContentDir( RelativePath, TEXT(".png") ), __VA_ARGS__ )
|
||||
|
||||
const FVector2D Icon40x40(40.0f, 40.0f);
|
||||
|
||||
TUniquePtr< FSlateStyleSet > FOpenPypeStyle::Create()
|
||||
{
|
||||
TUniquePtr< FSlateStyleSet > Style = MakeUnique<FSlateStyleSet>(GetStyleSetName());
|
||||
Style->SetContentRoot(FPaths::EnginePluginsDir() / TEXT("Marketplace/OpenPype/Resources"));
|
||||
|
||||
return Style;
|
||||
}
|
||||
|
||||
void FOpenPypeStyle::SetIcon(const FString& StyleName, const FString& ResourcePath)
|
||||
{
|
||||
FSlateStyleSet* Style = OpenPypeStyleInstance.Get();
|
||||
|
||||
FString Name(GetContextName().ToString());
|
||||
Name = Name + "." + StyleName;
|
||||
Style->Set(*Name, new FSlateImageBrush(Style->RootToContentDir(ResourcePath, TEXT(".png")), Icon40x40));
|
||||
|
||||
|
||||
FSlateApplication::Get().GetRenderer()->ReloadTextureResources();
|
||||
}
|
||||
|
||||
#undef IMAGE_BRUSH
|
||||
|
||||
const ISlateStyle& FOpenPypeStyle::Get()
|
||||
{
|
||||
check(OpenPypeStyleInstance);
|
||||
return *OpenPypeStyleInstance;
|
||||
}
|
||||
|
|
@ -2,23 +2,23 @@
|
|||
"FileVersion": 3,
|
||||
"Version": 1,
|
||||
"VersionName": "1.0",
|
||||
"FriendlyName": "OpenPype",
|
||||
"Description": "OpenPype Integration",
|
||||
"Category": "OpenPype.Integration",
|
||||
"FriendlyName": "Ayon",
|
||||
"Description": "Ayon Integration",
|
||||
"Category": "Ayon.Integration",
|
||||
"CreatedBy": "Ondrej Samohel",
|
||||
"CreatedByURL": "https://openpype.io",
|
||||
"DocsURL": "https://openpype.io/docs/artist_hosts_unreal",
|
||||
"CreatedByURL": "https://ayon.ynput.io",
|
||||
"DocsURL": "https://ayon.ynput.io/docs/artist_hosts_unreal",
|
||||
"MarketplaceURL": "",
|
||||
"SupportURL": "https://pype.club/",
|
||||
"SupportURL": "https://ynput.io/",
|
||||
"CanContainContent": true,
|
||||
"EngineVersion": "5.0",
|
||||
"IsExperimentalVersion": false,
|
||||
"Installed": true,
|
||||
"Modules": [
|
||||
{
|
||||
"Name": "OpenPype",
|
||||
"Name": "Ayon",
|
||||
"Type": "Editor",
|
||||
"LoadingPhase": "Default"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
[/Script/Ayon.AyonSettings]
|
||||
FolderColor=(R=91,G=197,B=220,A=255)
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
import unreal
|
||||
|
||||
ayon_detected = True
|
||||
try:
|
||||
from openpype.pipeline import install_host
|
||||
from openpype.hosts.unreal.api import UnrealHost
|
||||
|
||||
ayon_host = UnrealHost()
|
||||
except ImportError as exc:
|
||||
ayon_host = None
|
||||
ayon_detected = False
|
||||
unreal.log_error(f"Ayon: cannot load Ayon integration [ {exc} ]")
|
||||
|
||||
if ayon_detected:
|
||||
install_host(ayon_host)
|
||||
|
||||
|
||||
@unreal.uclass()
|
||||
class AyonIntegration(unreal.AyonPythonBridge):
|
||||
@unreal.ufunction(override=True)
|
||||
def RunInPython_Popup(self):
|
||||
unreal.log_warning("Ayon: showing tools popup")
|
||||
if ayon_detected:
|
||||
ayon_host.show_tools_popup()
|
||||
|
||||
@unreal.ufunction(override=True)
|
||||
def RunInPython_Dialog(self):
|
||||
unreal.log_warning("Ayon: showing tools dialog")
|
||||
if ayon_detected:
|
||||
ayon_host.show_tools_dialog()
|
||||
3
openpype/hosts/unreal/integration/UE_5.0/Ayon/README.md
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# Ayon Unreal Integration plugin - UE 5.0
|
||||
|
||||
This is plugin for Unreal Editor, creating menu for [Ayon](https://github.com/ynput/OpenPype) tools to run.
|
||||
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 721 B |
|
After Width: | Height: | Size: 16 KiB |
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
using UnrealBuildTool;
|
||||
|
||||
public class OpenPype : ModuleRules
|
||||
public class Ayon : ModuleRules
|
||||
{
|
||||
public OpenPype(ReadOnlyTargetRules Target) : base(Target)
|
||||
public Ayon(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
DefaultBuildSettings = BuildSettingsVersion.V2;
|
||||
bLegacyPublicIncludePaths = false;
|
||||
|
|
@ -1,58 +1,57 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
#include "OpenPype.h"
|
||||
#include "Ayon.h"
|
||||
|
||||
#include "ISettingsContainer.h"
|
||||
#include "ISettingsModule.h"
|
||||
#include "ISettingsSection.h"
|
||||
#include "OpenPypeStyle.h"
|
||||
#include "OpenPypeCommands.h"
|
||||
#include "OpenPypePythonBridge.h"
|
||||
#include "OpenPypeSettings.h"
|
||||
#include "Misc/MessageDialog.h"
|
||||
#include "AyonStyle.h"
|
||||
#include "AyonCommands.h"
|
||||
#include "AyonPythonBridge.h"
|
||||
#include "AyonSettings.h"
|
||||
#include "ToolMenus.h"
|
||||
|
||||
|
||||
static const FName OpenPypeTabName("OpenPype");
|
||||
static const FName AyonTabName("Ayon");
|
||||
|
||||
#define LOCTEXT_NAMESPACE "FOpenPypeModule"
|
||||
#define LOCTEXT_NAMESPACE "FAyonModule"
|
||||
|
||||
// This function is triggered when the plugin is staring up
|
||||
void FOpenPypeModule::StartupModule()
|
||||
void FAyonModule::StartupModule()
|
||||
{
|
||||
FOpenPypeStyle::Initialize();
|
||||
FOpenPypeStyle::ReloadTextures();
|
||||
FOpenPypeCommands::Register();
|
||||
FAyonStyle::Initialize();
|
||||
FAyonStyle::ReloadTextures();
|
||||
FAyonCommands::Register();
|
||||
|
||||
PluginCommands = MakeShareable(new FUICommandList);
|
||||
|
||||
PluginCommands->MapAction(
|
||||
FOpenPypeCommands::Get().OpenPypeTools,
|
||||
FExecuteAction::CreateRaw(this, &FOpenPypeModule::MenuPopup),
|
||||
FAyonCommands::Get().AyonTools,
|
||||
FExecuteAction::CreateRaw(this, &FAyonModule::MenuPopup),
|
||||
FCanExecuteAction());
|
||||
PluginCommands->MapAction(
|
||||
FOpenPypeCommands::Get().OpenPypeToolsDialog,
|
||||
FExecuteAction::CreateRaw(this, &FOpenPypeModule::MenuDialog),
|
||||
FAyonCommands::Get().AyonToolsDialog,
|
||||
FExecuteAction::CreateRaw(this, &FAyonModule::MenuDialog),
|
||||
FCanExecuteAction());
|
||||
|
||||
UToolMenus::RegisterStartupCallback(
|
||||
FSimpleMulticastDelegate::FDelegate::CreateRaw(this, &FOpenPypeModule::RegisterMenus));
|
||||
FSimpleMulticastDelegate::FDelegate::CreateRaw(this, &FAyonModule::RegisterMenus));
|
||||
|
||||
RegisterSettings();
|
||||
}
|
||||
|
||||
void FOpenPypeModule::ShutdownModule()
|
||||
void FAyonModule::ShutdownModule()
|
||||
{
|
||||
UToolMenus::UnRegisterStartupCallback(this);
|
||||
|
||||
UToolMenus::UnregisterOwner(this);
|
||||
|
||||
FOpenPypeStyle::Shutdown();
|
||||
FAyonStyle::Shutdown();
|
||||
|
||||
FOpenPypeCommands::Unregister();
|
||||
FAyonCommands::Unregister();
|
||||
}
|
||||
|
||||
|
||||
void FOpenPypeModule::RegisterSettings()
|
||||
void FAyonModule::RegisterSettings()
|
||||
{
|
||||
ISettingsModule& SettingsModule = FModuleManager::LoadModuleChecked<ISettingsModule>("Settings");
|
||||
|
||||
|
|
@ -60,10 +59,10 @@ void FOpenPypeModule::RegisterSettings()
|
|||
// TODO: After the movement of the plugin from the game to editor, it might be necessary to move this!
|
||||
ISettingsContainerPtr SettingsContainer = SettingsModule.GetContainer("Project");
|
||||
|
||||
UOpenPypeSettings* Settings = GetMutableDefault<UOpenPypeSettings>();
|
||||
UAyonSettings* Settings = GetMutableDefault<UAyonSettings>();
|
||||
|
||||
// Register the settings
|
||||
ISettingsSectionPtr SettingsSection = SettingsModule.RegisterSettings("Project", "OpenPype", "General",
|
||||
ISettingsSectionPtr SettingsSection = SettingsModule.RegisterSettings("Project", "Ayon", "General",
|
||||
LOCTEXT("RuntimeGeneralSettingsName",
|
||||
"General"),
|
||||
LOCTEXT("RuntimeGeneralSettingsDescription",
|
||||
|
|
@ -75,13 +74,13 @@ void FOpenPypeModule::RegisterSettings()
|
|||
// validate those or just act to settings changes.
|
||||
if (SettingsSection.IsValid())
|
||||
{
|
||||
SettingsSection->OnModified().BindRaw(this, &FOpenPypeModule::HandleSettingsSaved);
|
||||
SettingsSection->OnModified().BindRaw(this, &FAyonModule::HandleSettingsSaved);
|
||||
}
|
||||
}
|
||||
|
||||
bool FOpenPypeModule::HandleSettingsSaved()
|
||||
bool FAyonModule::HandleSettingsSaved()
|
||||
{
|
||||
UOpenPypeSettings* Settings = GetMutableDefault<UOpenPypeSettings>();
|
||||
UAyonSettings* Settings = GetMutableDefault<UAyonSettings>();
|
||||
bool ResaveSettings = false;
|
||||
|
||||
// You can put any validation code in here and resave the settings in case an invalid
|
||||
|
|
@ -95,7 +94,7 @@ bool FOpenPypeModule::HandleSettingsSaved()
|
|||
return true;
|
||||
}
|
||||
|
||||
void FOpenPypeModule::RegisterMenus()
|
||||
void FAyonModule::RegisterMenus()
|
||||
{
|
||||
// Owner will be used for cleanup in call to UToolMenus::UnregisterOwner
|
||||
FToolMenuOwnerScoped OwnerScoped(this);
|
||||
|
|
@ -103,21 +102,21 @@ void FOpenPypeModule::RegisterMenus()
|
|||
{
|
||||
UToolMenu* Menu = UToolMenus::Get()->ExtendMenu("LevelEditor.MainMenu.Tools");
|
||||
{
|
||||
// FToolMenuSection& Section = Menu->FindOrAddSection("OpenPype");
|
||||
// FToolMenuSection& Section = Menu->FindOrAddSection("Ayon");
|
||||
FToolMenuSection& Section = Menu->AddSection(
|
||||
"OpenPype",
|
||||
TAttribute<FText>(FText::FromString("OpenPype")),
|
||||
"Ayon",
|
||||
TAttribute<FText>(FText::FromString("Ayon")),
|
||||
FToolMenuInsert("Programming", EToolMenuInsertType::Before)
|
||||
);
|
||||
Section.AddMenuEntryWithCommandList(FOpenPypeCommands::Get().OpenPypeTools, PluginCommands);
|
||||
Section.AddMenuEntryWithCommandList(FOpenPypeCommands::Get().OpenPypeToolsDialog, PluginCommands);
|
||||
Section.AddMenuEntryWithCommandList(FAyonCommands::Get().AyonTools, PluginCommands);
|
||||
Section.AddMenuEntryWithCommandList(FAyonCommands::Get().AyonToolsDialog, PluginCommands);
|
||||
}
|
||||
UToolMenu* ToolbarMenu = UToolMenus::Get()->ExtendMenu("LevelEditor.LevelEditorToolBar.PlayToolBar");
|
||||
{
|
||||
FToolMenuSection& Section = ToolbarMenu->FindOrAddSection("PluginTools");
|
||||
{
|
||||
FToolMenuEntry& Entry = Section.AddEntry(
|
||||
FToolMenuEntry::InitToolBarButton(FOpenPypeCommands::Get().OpenPypeTools));
|
||||
FToolMenuEntry::InitToolBarButton(FAyonCommands::Get().AyonTools));
|
||||
Entry.SetCommandList(PluginCommands);
|
||||
}
|
||||
}
|
||||
|
|
@ -125,16 +124,16 @@ void FOpenPypeModule::RegisterMenus()
|
|||
}
|
||||
|
||||
|
||||
void FOpenPypeModule::MenuPopup()
|
||||
void FAyonModule::MenuPopup()
|
||||
{
|
||||
UOpenPypePythonBridge* bridge = UOpenPypePythonBridge::Get();
|
||||
UAyonPythonBridge* bridge = UAyonPythonBridge::Get();
|
||||
bridge->RunInPython_Popup();
|
||||
}
|
||||
|
||||
void FOpenPypeModule::MenuDialog()
|
||||
void FAyonModule::MenuDialog()
|
||||
{
|
||||
UOpenPypePythonBridge* bridge = UOpenPypePythonBridge::Get();
|
||||
UAyonPythonBridge* bridge = UAyonPythonBridge::Get();
|
||||
bridge->RunInPython_Dialog();
|
||||
}
|
||||
|
||||
IMPLEMENT_MODULE(FOpenPypeModule, OpenPype)
|
||||
IMPLEMENT_MODULE(FAyonModule, Ayon)
|
||||
|
|
@ -1,31 +1,30 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#include "AssetContainer.h"
|
||||
#include "AyonAssetContainer.h"
|
||||
#include "AssetRegistry/AssetRegistryModule.h"
|
||||
#include "Misc/PackageName.h"
|
||||
#include "Engine.h"
|
||||
#include "Containers/UnrealString.h"
|
||||
|
||||
UAssetContainer::UAssetContainer(const FObjectInitializer& ObjectInitializer)
|
||||
UAyonAssetContainer::UAyonAssetContainer(const FObjectInitializer& ObjectInitializer)
|
||||
: UAssetUserData(ObjectInitializer)
|
||||
{
|
||||
FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>("AssetRegistry");
|
||||
FString path = UAssetContainer::GetPathName();
|
||||
UE_LOG(LogTemp, Warning, TEXT("UAssetContainer %s"), *path);
|
||||
FString path = UAyonAssetContainer::GetPathName();
|
||||
UE_LOG(LogTemp, Warning, TEXT("UAyonAssetContainer %s"), *path);
|
||||
FARFilter Filter;
|
||||
Filter.PackagePaths.Add(FName(*path));
|
||||
|
||||
AssetRegistryModule.Get().OnAssetAdded().AddUObject(this, &UAssetContainer::OnAssetAdded);
|
||||
AssetRegistryModule.Get().OnAssetRemoved().AddUObject(this, &UAssetContainer::OnAssetRemoved);
|
||||
AssetRegistryModule.Get().OnAssetRenamed().AddUObject(this, &UAssetContainer::OnAssetRenamed);
|
||||
AssetRegistryModule.Get().OnAssetAdded().AddUObject(this, &UAyonAssetContainer::OnAssetAdded);
|
||||
AssetRegistryModule.Get().OnAssetRemoved().AddUObject(this, &UAyonAssetContainer::OnAssetRemoved);
|
||||
AssetRegistryModule.Get().OnAssetRenamed().AddUObject(this, &UAyonAssetContainer::OnAssetRenamed);
|
||||
}
|
||||
|
||||
void UAssetContainer::OnAssetAdded(const FAssetData& AssetData)
|
||||
void UAyonAssetContainer::OnAssetAdded(const FAssetData& AssetData)
|
||||
{
|
||||
TArray<FString> split;
|
||||
|
||||
// get directory of current container
|
||||
FString selfFullPath = UAssetContainer::GetPathName();
|
||||
FString selfFullPath = UAyonAssetContainer::GetPathName();
|
||||
FString selfDir = FPackageName::GetLongPackagePath(*selfFullPath);
|
||||
|
||||
// get asset path and class
|
||||
|
|
@ -50,12 +49,12 @@ void UAssetContainer::OnAssetAdded(const FAssetData& AssetData)
|
|||
}
|
||||
}
|
||||
|
||||
void UAssetContainer::OnAssetRemoved(const FAssetData& AssetData)
|
||||
void UAyonAssetContainer::OnAssetRemoved(const FAssetData& AssetData)
|
||||
{
|
||||
TArray<FString> split;
|
||||
|
||||
// get directory of current container
|
||||
FString selfFullPath = UAssetContainer::GetPathName();
|
||||
FString selfFullPath = UAyonAssetContainer::GetPathName();
|
||||
FString selfDir = FPackageName::GetLongPackagePath(*selfFullPath);
|
||||
|
||||
// get asset path and class
|
||||
|
|
@ -68,7 +67,7 @@ void UAssetContainer::OnAssetRemoved(const FAssetData& AssetData)
|
|||
FString assetDir = FPackageName::GetLongPackagePath(*split[1]);
|
||||
|
||||
// take interest only in paths starting with path of current container
|
||||
FString path = UAssetContainer::GetPathName();
|
||||
FString path = UAyonAssetContainer::GetPathName();
|
||||
FString lpp = FPackageName::GetLongPackagePath(*path);
|
||||
|
||||
if (assetDir.StartsWith(*selfDir))
|
||||
|
|
@ -83,12 +82,12 @@ void UAssetContainer::OnAssetRemoved(const FAssetData& AssetData)
|
|||
}
|
||||
}
|
||||
|
||||
void UAssetContainer::OnAssetRenamed(const FAssetData& AssetData, const FString& str)
|
||||
void UAyonAssetContainer::OnAssetRenamed(const FAssetData& AssetData, const FString& str)
|
||||
{
|
||||
TArray<FString> split;
|
||||
|
||||
// get directory of current container
|
||||
FString selfFullPath = UAssetContainer::GetPathName();
|
||||
FString selfFullPath = UAyonAssetContainer::GetPathName();
|
||||
FString selfDir = FPackageName::GetLongPackagePath(*selfFullPath);
|
||||
|
||||
// get asset path and class
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
#include "AyonAssetContainerFactory.h"
|
||||
#include "AyonAssetContainer.h"
|
||||
|
||||
UAyonAssetContainerFactory::UAyonAssetContainerFactory(const FObjectInitializer& ObjectInitializer)
|
||||
: UFactory(ObjectInitializer)
|
||||
{
|
||||
SupportedClass = UAyonAssetContainer::StaticClass();
|
||||
bCreateNew = false;
|
||||
bEditorImport = true;
|
||||
}
|
||||
|
||||
UObject* UAyonAssetContainerFactory::FactoryCreateNew(UClass* Class, UObject* InParent, FName Name, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn)
|
||||
{
|
||||
UAyonAssetContainer* AssetContainer = NewObject<UAyonAssetContainer>(InParent, Class, Name, Flags);
|
||||
return AssetContainer;
|
||||
}
|
||||
|
||||
bool UAyonAssetContainerFactory::ShouldShowInNewMenu() const {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
|
||||
#include "AyonCommands.h"
|
||||
|
||||
#define LOCTEXT_NAMESPACE "FAyonModule"
|
||||
|
||||
void FAyonCommands::RegisterCommands()
|
||||
{
|
||||
UI_COMMAND(AyonTools, "Ayon Tools", "Pipeline tools", EUserInterfaceActionType::Button, FInputChord());
|
||||
UI_COMMAND(AyonToolsDialog, "Ayon Tools Dialog", "Pipeline tools dialog", EUserInterfaceActionType::Button, FInputChord());
|
||||
}
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
|
|
@ -1,9 +1,7 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
#include "OpenPypeLib.h"
|
||||
#include "AyonLib.h"
|
||||
|
||||
#include "AssetViewUtils.h"
|
||||
#include "Misc/Paths.h"
|
||||
#include "Misc/ConfigCacheIni.h"
|
||||
#include "UObject/UnrealType.h"
|
||||
|
||||
/**
|
||||
|
|
@ -13,7 +11,7 @@
|
|||
* @warning This color will appear only after Editor restart. Is there a better way?
|
||||
*/
|
||||
|
||||
bool UOpenPypeLib::SetFolderColor(const FString& FolderPath, const FLinearColor& FolderColor, const bool& bForceAdd)
|
||||
bool UAyonLib::SetFolderColor(const FString& FolderPath, const FLinearColor& FolderColor, const bool& bForceAdd)
|
||||
{
|
||||
if (AssetViewUtils::DoesFolderExist(FolderPath))
|
||||
{
|
||||
|
|
@ -31,11 +29,11 @@ bool UOpenPypeLib::SetFolderColor(const FString& FolderPath, const FLinearColor&
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns all properties on given object
|
||||
* Returns all poperties on given object
|
||||
* @param cls - class
|
||||
* @return TArray of properties
|
||||
*/
|
||||
TArray<FString> UOpenPypeLib::GetAllProperties(UClass* cls)
|
||||
TArray<FString> UAyonLib::GetAllProperties(UClass* cls)
|
||||
{
|
||||
TArray<FString> Ret;
|
||||
if (cls != nullptr)
|
||||
|
|
@ -0,0 +1,204 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
// Deprecation warning: this is left here just for backwards compatibility
|
||||
// and will be removed in next versions of Ayon.
|
||||
#pragma once
|
||||
|
||||
#include "AyonPublishInstance.h"
|
||||
#include "AssetRegistry/AssetRegistryModule.h"
|
||||
#include "AssetToolsModule.h"
|
||||
#include "Framework/Notifications/NotificationManager.h"
|
||||
#include "AyonLib.h"
|
||||
#include "AyonSettings.h"
|
||||
#include "Widgets/Notifications/SNotificationList.h"
|
||||
|
||||
|
||||
//Moves all the invalid pointers to the end to prepare them for the shrinking
|
||||
#define REMOVE_INVALID_ENTRIES(VAR) VAR.CompactStable(); \
|
||||
VAR.Shrink();
|
||||
|
||||
UAyonPublishInstance::UAyonPublishInstance(const FObjectInitializer& ObjectInitializer)
|
||||
: UPrimaryDataAsset(ObjectInitializer)
|
||||
{
|
||||
const FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<
|
||||
FAssetRegistryModule>("AssetRegistry");
|
||||
|
||||
const FPropertyEditorModule& PropertyEditorModule = FModuleManager::LoadModuleChecked<FPropertyEditorModule>(
|
||||
"PropertyEditor");
|
||||
|
||||
FString Left, Right;
|
||||
GetPathName().Split("/" + GetName(), &Left, &Right);
|
||||
|
||||
FARFilter Filter;
|
||||
Filter.PackagePaths.Emplace(FName(Left));
|
||||
|
||||
TArray<FAssetData> FoundAssets;
|
||||
AssetRegistryModule.GetRegistry().GetAssets(Filter, FoundAssets);
|
||||
|
||||
for (const FAssetData& AssetData : FoundAssets)
|
||||
OnAssetCreated(AssetData);
|
||||
|
||||
REMOVE_INVALID_ENTRIES(AssetDataInternal)
|
||||
REMOVE_INVALID_ENTRIES(AssetDataExternal)
|
||||
|
||||
AssetRegistryModule.Get().OnAssetAdded().AddUObject(this, &UAyonPublishInstance::OnAssetCreated);
|
||||
AssetRegistryModule.Get().OnAssetRemoved().AddUObject(this, &UAyonPublishInstance::OnAssetRemoved);
|
||||
AssetRegistryModule.Get().OnAssetUpdated().AddUObject(this, &UAyonPublishInstance::OnAssetUpdated);
|
||||
|
||||
#ifdef WITH_EDITOR
|
||||
ColorAyonDirs();
|
||||
#endif
|
||||
}
|
||||
|
||||
void UAyonPublishInstance::OnAssetCreated(const FAssetData& InAssetData)
|
||||
{
|
||||
TArray<FString> split;
|
||||
|
||||
UObject* Asset = InAssetData.GetAsset();
|
||||
|
||||
if (!IsValid(Asset))
|
||||
{
|
||||
UE_LOG(LogAssetData, Warning, TEXT("Asset \"%s\" is not valid! Skipping the addition."),
|
||||
*InAssetData.ObjectPath.ToString());
|
||||
return;
|
||||
}
|
||||
|
||||
const bool result = IsUnderSameDir(Asset) && Cast<UAyonPublishInstance>(Asset) == nullptr;
|
||||
|
||||
if (result)
|
||||
{
|
||||
if (AssetDataInternal.Emplace(Asset).IsValidId())
|
||||
{
|
||||
UE_LOG(LogTemp, Log, TEXT("Added an Asset to PublishInstance - Publish Instance: %s, Asset %s"),
|
||||
*this->GetName(), *Asset->GetName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UAyonPublishInstance::OnAssetRemoved(const FAssetData& InAssetData)
|
||||
{
|
||||
if (Cast<UAyonPublishInstance>(InAssetData.GetAsset()) == nullptr)
|
||||
{
|
||||
if (AssetDataInternal.Contains(nullptr))
|
||||
{
|
||||
AssetDataInternal.Remove(nullptr);
|
||||
REMOVE_INVALID_ENTRIES(AssetDataInternal)
|
||||
}
|
||||
else
|
||||
{
|
||||
AssetDataExternal.Remove(nullptr);
|
||||
REMOVE_INVALID_ENTRIES(AssetDataExternal)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UAyonPublishInstance::OnAssetUpdated(const FAssetData& InAssetData)
|
||||
{
|
||||
REMOVE_INVALID_ENTRIES(AssetDataInternal);
|
||||
REMOVE_INVALID_ENTRIES(AssetDataExternal);
|
||||
}
|
||||
|
||||
bool UAyonPublishInstance::IsUnderSameDir(const UObject* InAsset) const
|
||||
{
|
||||
FString ThisLeft, ThisRight;
|
||||
this->GetPathName().Split(this->GetName(), &ThisLeft, &ThisRight);
|
||||
|
||||
return InAsset->GetPathName().StartsWith(ThisLeft);
|
||||
}
|
||||
|
||||
#ifdef WITH_EDITOR
|
||||
|
||||
void UAyonPublishInstance::ColorAyonDirs()
|
||||
{
|
||||
FString PathName = this->GetPathName();
|
||||
|
||||
//Check whether the path contains the defined Ayon folder
|
||||
if (!PathName.Contains(TEXT("Ayon"))) return;
|
||||
|
||||
//Get the base path for open pype
|
||||
FString PathLeft, PathRight;
|
||||
PathName.Split(FString("Ayon"), &PathLeft, &PathRight);
|
||||
|
||||
if (PathLeft.IsEmpty() || PathRight.IsEmpty())
|
||||
{
|
||||
UE_LOG(LogAssetData, Error, TEXT("Failed to retrieve the base Ayon directory!"))
|
||||
return;
|
||||
}
|
||||
|
||||
PathName.RemoveFromEnd(PathRight, ESearchCase::CaseSensitive);
|
||||
|
||||
//Get the current settings
|
||||
const UAyonSettings* Settings = GetMutableDefault<UAyonSettings>();
|
||||
|
||||
//Color the base folder
|
||||
UAyonLib::SetFolderColor(PathName, Settings->GetFolderFColor(), false);
|
||||
|
||||
//Get Sub paths, iterate through them and color them according to the folder color in UAyonSettings
|
||||
const FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>(
|
||||
"AssetRegistry");
|
||||
|
||||
TArray<FString> PathList;
|
||||
|
||||
AssetRegistryModule.Get().GetSubPaths(PathName, PathList, true);
|
||||
|
||||
if (PathList.Num() > 0)
|
||||
{
|
||||
for (const FString& Path : PathList)
|
||||
{
|
||||
UAyonLib::SetFolderColor(Path, Settings->GetFolderFColor(), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UAyonPublishInstance::SendNotification(const FString& Text) const
|
||||
{
|
||||
FNotificationInfo Info{FText::FromString(Text)};
|
||||
|
||||
Info.bFireAndForget = true;
|
||||
Info.bUseLargeFont = false;
|
||||
Info.bUseThrobber = false;
|
||||
Info.bUseSuccessFailIcons = false;
|
||||
Info.ExpireDuration = 4.f;
|
||||
Info.FadeOutDuration = 2.f;
|
||||
|
||||
FSlateNotificationManager::Get().AddNotification(Info);
|
||||
|
||||
UE_LOG(LogAssetData, Warning,
|
||||
TEXT(
|
||||
"Removed duplicated asset from the AssetsDataExternal in Container \"%s\", Asset is already included in the AssetDataInternal!"
|
||||
), *GetName()
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
void UAyonPublishInstance::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
|
||||
{
|
||||
Super::PostEditChangeProperty(PropertyChangedEvent);
|
||||
|
||||
if (PropertyChangedEvent.ChangeType == EPropertyChangeType::ValueSet &&
|
||||
PropertyChangedEvent.Property->GetFName() == GET_MEMBER_NAME_CHECKED(
|
||||
UAyonPublishInstance, AssetDataExternal))
|
||||
{
|
||||
// Check for duplicated assets
|
||||
for (const auto& Asset : AssetDataInternal)
|
||||
{
|
||||
if (AssetDataExternal.Contains(Asset))
|
||||
{
|
||||
AssetDataExternal.Remove(Asset);
|
||||
return SendNotification(
|
||||
"You are not allowed to add assets into AssetDataExternal which are already included in AssetDataInternal!");
|
||||
}
|
||||
}
|
||||
|
||||
// Check if no UAyonPublishInstance type assets are included
|
||||
for (const auto& Asset : AssetDataExternal)
|
||||
{
|
||||
if (Cast<UAyonPublishInstance>(Asset.Get()) != nullptr)
|
||||
{
|
||||
AssetDataExternal.Remove(Asset);
|
||||
return SendNotification("You are not allowed to add publish instances!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
// Deprecation warning: this is left here just for backwards compatibility
|
||||
// and will be removed in next versions of Ayon.
|
||||
#include "AyonPublishInstanceFactory.h"
|
||||
#include "AyonPublishInstance.h"
|
||||
|
||||
UAyonPublishInstanceFactory::UAyonPublishInstanceFactory(const FObjectInitializer& ObjectInitializer)
|
||||
: UFactory(ObjectInitializer)
|
||||
{
|
||||
SupportedClass = UAyonPublishInstance::StaticClass();
|
||||
bCreateNew = false;
|
||||
bEditorImport = true;
|
||||
}
|
||||
|
||||
UObject* UAyonPublishInstanceFactory::FactoryCreateNew(UClass* InClass, UObject* InParent, FName InName, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn)
|
||||
{
|
||||
check(InClass->IsChildOf(UAyonPublishInstance::StaticClass()));
|
||||
return NewObject<UAyonPublishInstance>(InParent, InClass, InName, Flags);
|
||||
}
|
||||
|
||||
bool UAyonPublishInstanceFactory::ShouldShowInNewMenu() const {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
#include "AyonPythonBridge.h"
|
||||
|
||||
UAyonPythonBridge* UAyonPythonBridge::Get()
|
||||
{
|
||||
TArray<UClass*> AyonPythonBridgeClasses;
|
||||
GetDerivedClasses(UAyonPythonBridge::StaticClass(), AyonPythonBridgeClasses);
|
||||
int32 NumClasses = AyonPythonBridgeClasses.Num();
|
||||
if (NumClasses > 0)
|
||||
{
|
||||
return Cast<UAyonPythonBridge>(AyonPythonBridgeClasses[NumClasses - 1]->GetDefaultObject());
|
||||
}
|
||||
return nullptr;
|
||||
};
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
|
||||
#include "AyonSettings.h"
|
||||
|
||||
#include "Interfaces/IPluginManager.h"
|
||||
#include "UObject/UObjectGlobals.h"
|
||||
|
||||
/**
|
||||
* Mainly is used for initializing default values if the DefaultAyonSettings.ini file does not exist in the saved config
|
||||
*/
|
||||
UAyonSettings::UAyonSettings(const FObjectInitializer& ObjectInitializer)
|
||||
{
|
||||
|
||||
const FString ConfigFilePath = AYON_SETTINGS_FILEPATH;
|
||||
|
||||
// This has to be probably in the future set using the UE Reflection system
|
||||
FColor Color;
|
||||
GConfig->GetColor(TEXT("/Script/Ayon.AyonSettings"), TEXT("FolderColor"), Color, ConfigFilePath);
|
||||
|
||||
FolderColor = Color;
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
|
||||
#include "AyonStyle.h"
|
||||
#include "Framework/Application/SlateApplication.h"
|
||||
#include "Styling/SlateStyleRegistry.h"
|
||||
#include "Slate/SlateGameResources.h"
|
||||
#include "Interfaces/IPluginManager.h"
|
||||
#include "Styling/SlateStyleMacros.h"
|
||||
|
||||
#define RootToContentDir Style->RootToContentDir
|
||||
|
||||
TSharedPtr<FSlateStyleSet> FAyonStyle::AyonStyleInstance = nullptr;
|
||||
|
||||
void FAyonStyle::Initialize()
|
||||
{
|
||||
if (!AyonStyleInstance.IsValid())
|
||||
{
|
||||
AyonStyleInstance = Create();
|
||||
FSlateStyleRegistry::RegisterSlateStyle(*AyonStyleInstance);
|
||||
}
|
||||
}
|
||||
|
||||
void FAyonStyle::Shutdown()
|
||||
{
|
||||
FSlateStyleRegistry::UnRegisterSlateStyle(*AyonStyleInstance);
|
||||
ensure(AyonStyleInstance.IsUnique());
|
||||
AyonStyleInstance.Reset();
|
||||
}
|
||||
|
||||
FName FAyonStyle::GetStyleSetName()
|
||||
{
|
||||
static FName StyleSetName(TEXT("AyonStyle"));
|
||||
return StyleSetName;
|
||||
}
|
||||
|
||||
const FVector2D Icon16x16(16.0f, 16.0f);
|
||||
const FVector2D Icon20x20(20.0f, 20.0f);
|
||||
const FVector2D Icon40x40(40.0f, 40.0f);
|
||||
|
||||
TSharedRef< FSlateStyleSet > FAyonStyle::Create()
|
||||
{
|
||||
TSharedRef< FSlateStyleSet > Style = MakeShareable(new FSlateStyleSet("AyonStyle"));
|
||||
Style->SetContentRoot(IPluginManager::Get().FindPlugin("Ayon")->GetBaseDir() / TEXT("Resources"));
|
||||
|
||||
Style->Set("Ayon.AyonTools", new IMAGE_BRUSH(TEXT("ayon40"), Icon40x40));
|
||||
Style->Set("Ayon.AyonToolsDialog", new IMAGE_BRUSH(TEXT("ayon40"), Icon40x40));
|
||||
|
||||
return Style;
|
||||
}
|
||||
|
||||
void FAyonStyle::ReloadTextures()
|
||||
{
|
||||
if (FSlateApplication::IsInitialized())
|
||||
{
|
||||
FSlateApplication::Get().GetRenderer()->ReloadTextureResources();
|
||||
}
|
||||
}
|
||||
|
||||
const ISlateStyle& FAyonStyle::Get()
|
||||
{
|
||||
return *AyonStyleInstance;
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
|
||||
#include "Commandlets/AyonActionResult.h"
|
||||
#include "Logging/Ayon_Log.h"
|
||||
|
||||
EAyon_ActionResult::Type& FAyon_ActionResult::GetStatus()
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
FText& FAyon_ActionResult::GetReason()
|
||||
{
|
||||
return Reason;
|
||||
}
|
||||
|
||||
FAyon_ActionResult::FAyon_ActionResult():Status(EAyon_ActionResult::Type::Ok)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
FAyon_ActionResult::FAyon_ActionResult(const EAyon_ActionResult::Type& InEnum):Status(InEnum)
|
||||
{
|
||||
TryLog();
|
||||
}
|
||||
|
||||
FAyon_ActionResult::FAyon_ActionResult(const EAyon_ActionResult::Type& InEnum, const FText& InReason):Status(InEnum), Reason(InReason)
|
||||
{
|
||||
TryLog();
|
||||
};
|
||||
|
||||
bool FAyon_ActionResult::IsProblem() const
|
||||
{
|
||||
return Status != EAyon_ActionResult::Ok;
|
||||
}
|
||||
|
||||
void FAyon_ActionResult::TryLog() const
|
||||
{
|
||||
if(IsProblem())
|
||||
UE_LOG(LogCommandletAyonGenerateProject, Error, TEXT("%s"), *Reason.ToString());
|
||||
}
|
||||
|
|
@ -0,0 +1,140 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
#include "Commandlets/Implementations/AyonGenerateProjectCommandlet.h"
|
||||
|
||||
#include "GameProjectUtils.h"
|
||||
#include "AyonConstants.h"
|
||||
#include "Commandlets/AyonActionResult.h"
|
||||
#include "ProjectDescriptor.h"
|
||||
|
||||
int32 UAyonGenerateProjectCommandlet::Main(const FString& CommandLineParams)
|
||||
{
|
||||
//Parses command line parameters & creates structure FProjectInformation
|
||||
const FAyonGenerateProjectParams ParsedParams = FAyonGenerateProjectParams(CommandLineParams);
|
||||
ProjectInformation = ParsedParams.GenerateUEProjectInformation();
|
||||
|
||||
//Creates .uproject & other UE files
|
||||
EVALUATE_Ayon_ACTION_RESULT(TryCreateProject());
|
||||
|
||||
//Loads created .uproject
|
||||
EVALUATE_Ayon_ACTION_RESULT(TryLoadProjectDescriptor());
|
||||
|
||||
//Adds needed plugin to .uproject
|
||||
AttachPluginsToProjectDescriptor();
|
||||
|
||||
//Saves .uproject
|
||||
EVALUATE_Ayon_ACTION_RESULT(TrySave());
|
||||
|
||||
//When we are here, there should not be problems in generating Unreal Project for Ayon
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
FAyonGenerateProjectParams::FAyonGenerateProjectParams(): FAyonGenerateProjectParams("")
|
||||
{
|
||||
}
|
||||
|
||||
FAyonGenerateProjectParams::FAyonGenerateProjectParams(const FString& CommandLineParams): CommandLineParams(
|
||||
CommandLineParams)
|
||||
{
|
||||
UCommandlet::ParseCommandLine(*CommandLineParams, Tokens, Switches);
|
||||
}
|
||||
|
||||
FProjectInformation FAyonGenerateProjectParams::GenerateUEProjectInformation() const
|
||||
{
|
||||
FProjectInformation ProjectInformation = FProjectInformation();
|
||||
ProjectInformation.ProjectFilename = GetProjectFileName();
|
||||
|
||||
ProjectInformation.bShouldGenerateCode = IsSwitchPresent("GenerateCode");
|
||||
|
||||
return ProjectInformation;
|
||||
}
|
||||
|
||||
FString FAyonGenerateProjectParams::TryGetToken(const int32 Index) const
|
||||
{
|
||||
return Tokens.IsValidIndex(Index) ? Tokens[Index] : "";
|
||||
}
|
||||
|
||||
FString FAyonGenerateProjectParams::GetProjectFileName() const
|
||||
{
|
||||
return TryGetToken(0);
|
||||
}
|
||||
|
||||
bool FAyonGenerateProjectParams::IsSwitchPresent(const FString& Switch) const
|
||||
{
|
||||
return INDEX_NONE != Switches.IndexOfByPredicate([&Switch](const FString& Item) -> bool
|
||||
{
|
||||
return Item.Equals(Switch);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
UAyonGenerateProjectCommandlet::UAyonGenerateProjectCommandlet()
|
||||
{
|
||||
LogToConsole = true;
|
||||
}
|
||||
|
||||
FAyon_ActionResult UAyonGenerateProjectCommandlet::TryCreateProject() const
|
||||
{
|
||||
FText FailReason;
|
||||
FText FailLog;
|
||||
TArray<FString> OutCreatedFiles;
|
||||
|
||||
if (!GameProjectUtils::CreateProject(ProjectInformation, FailReason, FailLog, &OutCreatedFiles))
|
||||
return FAyon_ActionResult(EAyon_ActionResult::ProjectNotCreated, FailReason);
|
||||
return FAyon_ActionResult();
|
||||
}
|
||||
|
||||
FAyon_ActionResult UAyonGenerateProjectCommandlet::TryLoadProjectDescriptor()
|
||||
{
|
||||
FText FailReason;
|
||||
const bool bLoaded = ProjectDescriptor.Load(ProjectInformation.ProjectFilename, FailReason);
|
||||
|
||||
return FAyon_ActionResult(bLoaded ? EAyon_ActionResult::Ok : EAyon_ActionResult::ProjectNotLoaded, FailReason);
|
||||
}
|
||||
|
||||
void UAyonGenerateProjectCommandlet::AttachPluginsToProjectDescriptor()
|
||||
{
|
||||
FPluginReferenceDescriptor AyonPluginDescriptor;
|
||||
AyonPluginDescriptor.bEnabled = true;
|
||||
AyonPluginDescriptor.Name = AyonConstants::Ayon_PluginName;
|
||||
ProjectDescriptor.Plugins.Add(AyonPluginDescriptor);
|
||||
|
||||
FPluginReferenceDescriptor PythonPluginDescriptor;
|
||||
PythonPluginDescriptor.bEnabled = true;
|
||||
PythonPluginDescriptor.Name = AyonConstants::PythonScript_PluginName;
|
||||
ProjectDescriptor.Plugins.Add(PythonPluginDescriptor);
|
||||
|
||||
FPluginReferenceDescriptor SequencerScriptingPluginDescriptor;
|
||||
SequencerScriptingPluginDescriptor.bEnabled = true;
|
||||
SequencerScriptingPluginDescriptor.Name = AyonConstants::SequencerScripting_PluginName;
|
||||
ProjectDescriptor.Plugins.Add(SequencerScriptingPluginDescriptor);
|
||||
|
||||
FPluginReferenceDescriptor MovieRenderPipelinePluginDescriptor;
|
||||
MovieRenderPipelinePluginDescriptor.bEnabled = true;
|
||||
MovieRenderPipelinePluginDescriptor.Name = AyonConstants::MovieRenderPipeline_PluginName;
|
||||
ProjectDescriptor.Plugins.Add(MovieRenderPipelinePluginDescriptor);
|
||||
|
||||
FPluginReferenceDescriptor EditorScriptingPluginDescriptor;
|
||||
EditorScriptingPluginDescriptor.bEnabled = true;
|
||||
EditorScriptingPluginDescriptor.Name = AyonConstants::EditorScriptingUtils_PluginName;
|
||||
ProjectDescriptor.Plugins.Add(EditorScriptingPluginDescriptor);
|
||||
}
|
||||
|
||||
FAyon_ActionResult UAyonGenerateProjectCommandlet::TrySave()
|
||||
{
|
||||
FText FailReason;
|
||||
const bool bSaved = ProjectDescriptor.Save(ProjectInformation.ProjectFilename, FailReason);
|
||||
|
||||
return FAyon_ActionResult(bSaved ? EAyon_ActionResult::Ok : EAyon_ActionResult::ProjectNotSaved, FailReason);
|
||||
}
|
||||
|
||||
FAyonGenerateProjectParams UAyonGenerateProjectCommandlet::ParseParameters(const FString& Params) const
|
||||
{
|
||||
FAyonGenerateProjectParams ParamsResult;
|
||||
|
||||
TArray<FString> Tokens, Switches;
|
||||
ParseCommandLine(*Params, Tokens, Switches);
|
||||
|
||||
return ParamsResult;
|
||||
}
|
||||
|
|
@ -1,12 +1,14 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
// Deprecation warning: this is left here just for backwards compatibility
|
||||
// and will be removed in next versions of Ayon.
|
||||
#pragma once
|
||||
|
||||
#include "OpenPypePublishInstance.h"
|
||||
#include "AssetRegistry/AssetRegistryModule.h"
|
||||
#include "AssetToolsModule.h"
|
||||
#include "Framework/Notifications/NotificationManager.h"
|
||||
#include "OpenPypeLib.h"
|
||||
#include "OpenPypeSettings.h"
|
||||
#include "AyonLib.h"
|
||||
#include "AyonSettings.h"
|
||||
#include "Widgets/Notifications/SNotificationList.h"
|
||||
|
||||
|
||||
|
|
@ -125,10 +127,10 @@ void UOpenPypePublishInstance::ColorOpenPypeDirs()
|
|||
PathName.RemoveFromEnd(PathRight, ESearchCase::CaseSensitive);
|
||||
|
||||
//Get the current settings
|
||||
const UOpenPypeSettings* Settings = GetMutableDefault<UOpenPypeSettings>();
|
||||
const UAyonSettings* Settings = GetMutableDefault<UAyonSettings>();
|
||||
|
||||
//Color the base folder
|
||||
UOpenPypeLib::SetFolderColor(PathName, Settings->GetFolderFColor(), false);
|
||||
UAyonLib::SetFolderColor(PathName, Settings->GetFolderFColor(), false);
|
||||
|
||||
//Get Sub paths, iterate through them and color them according to the folder color in UOpenPypeSettings
|
||||
const FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>(
|
||||
|
|
@ -142,7 +144,7 @@ void UOpenPypePublishInstance::ColorOpenPypeDirs()
|
|||
{
|
||||
for (const FString& Path : PathList)
|
||||
{
|
||||
UOpenPypeLib::SetFolderColor(Path, Settings->GetFolderFColor(), false);
|
||||
UAyonLib::SetFolderColor(Path, Settings->GetFolderFColor(), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,10 +3,9 @@
|
|||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Modules/ModuleManager.h"
|
||||
|
||||
|
||||
class FOpenPypeModule : public IModuleInterface
|
||||
class FAyonModule : public IModuleInterface
|
||||
{
|
||||
public:
|
||||
virtual void StartupModule() override;
|
||||
|
|
@ -6,20 +6,17 @@
|
|||
#include "UObject/NoExportTypes.h"
|
||||
#include "Engine/AssetUserData.h"
|
||||
#include "AssetRegistry/AssetData.h"
|
||||
#include "AssetContainer.generated.h"
|
||||
#include "AyonAssetContainer.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS(Blueprintable)
|
||||
class OPENPYPE_API UAssetContainer : public UAssetUserData
|
||||
class AYON_API UAyonAssetContainer : public UAssetUserData
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
UAssetContainer(const FObjectInitializer& ObjectInitalizer);
|
||||
// ~UAssetContainer();
|
||||
UAyonAssetContainer(const FObjectInitializer& ObjectInitalizer);
|
||||
// ~UAyonAssetContainer();
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Assets")
|
||||
TArray<FString> assets;
|
||||
|
|
@ -4,18 +4,15 @@
|
|||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Factories/Factory.h"
|
||||
#include "AssetContainerFactory.generated.h"
|
||||
#include "AyonAssetContainerFactory.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class OPENPYPE_API UAssetContainerFactory : public UFactory
|
||||
class AYON_API UAyonAssetContainerFactory : public UFactory
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UAssetContainerFactory(const FObjectInitializer& ObjectInitializer);
|
||||
UAyonAssetContainerFactory(const FObjectInitializer& ObjectInitializer);
|
||||
virtual UObject* FactoryCreateNew(UClass* Class, UObject* InParent, FName Name, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn) override;
|
||||
virtual bool ShouldShowInNewMenu() const override;
|
||||
};
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Framework/Commands/Commands.h"
|
||||
#include "AyonStyle.h"
|
||||
|
||||
class FAyonCommands : public TCommands<FAyonCommands>
|
||||
{
|
||||
public:
|
||||
|
||||
FAyonCommands()
|
||||
: TCommands<FAyonCommands>(TEXT("Ayon"), NSLOCTEXT("Contexts", "Ayon", "Ayon Tools"), NAME_None, FAyonStyle::GetStyleSetName())
|
||||
{
|
||||
}
|
||||
|
||||
// TCommands<> interface
|
||||
virtual void RegisterCommands() override;
|
||||
|
||||
public:
|
||||
TSharedPtr< FUICommandInfo > AyonTools;
|
||||
TSharedPtr< FUICommandInfo > AyonToolsDialog;
|
||||
};
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
#pragma once
|
||||
|
||||
namespace OPConstants
|
||||
namespace AyonConstants
|
||||
{
|
||||
const FString OP_PluginName = "OpenPype";
|
||||
const FString Ayon_PluginName = "Ayon";
|
||||
const FString PythonScript_PluginName = "PythonScriptPlugin";
|
||||
const FString SequencerScripting_PluginName = "SequencerScripting";
|
||||
const FString MovieRenderPipeline_PluginName = "MovieRenderPipeline";
|
||||
|
|
@ -1,12 +1,11 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
#pragma once
|
||||
|
||||
#include "Engine.h"
|
||||
#include "OpenPypeLib.generated.h"
|
||||
#include "AyonLib.generated.h"
|
||||
|
||||
|
||||
UCLASS(Blueprintable)
|
||||
class OPENPYPE_API UOpenPypeLib : public UBlueprintFunctionLibrary
|
||||
class AYON_API UAyonLib : public UBlueprintFunctionLibrary
|
||||
{
|
||||
|
||||
GENERATED_BODY()
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
// Deprecation warning: this is left here just for backwards compatibility
|
||||
// and will be removed in next versions of Ayon.
|
||||
#pragma once
|
||||
|
||||
#include "AyonPublishInstance.generated.h"
|
||||
|
||||
|
||||
UCLASS(Blueprintable)
|
||||
class AYON_API UAyonPublishInstance : public UPrimaryDataAsset
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
|
||||
public:
|
||||
/**
|
||||
/**
|
||||
* Retrieves all the assets which are monitored by the Publish Instance (Monitors assets in the directory which is
|
||||
* placed in)
|
||||
*
|
||||
* @return - Set of UObjects. Careful! They are returning raw pointers. Seems like an issue in UE5
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category="Python")
|
||||
TSet<UObject*> GetInternalAssets() const
|
||||
{
|
||||
//For some reason it can only return Raw Pointers? Seems like an issue which they haven't fixed.
|
||||
TSet<UObject*> ResultSet;
|
||||
|
||||
for (const auto& Asset : AssetDataInternal)
|
||||
ResultSet.Add(Asset.LoadSynchronous());
|
||||
|
||||
return ResultSet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves all the assets which have been added manually by the Publish Instance
|
||||
*
|
||||
* @return - TSet of assets (UObjects). Careful! They are returning raw pointers. Seems like an issue in UE5
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category="Python")
|
||||
TSet<UObject*> GetExternalAssets() const
|
||||
{
|
||||
//For some reason it can only return Raw Pointers? Seems like an issue which they haven't fixed.
|
||||
TSet<UObject*> ResultSet;
|
||||
|
||||
for (const auto& Asset : AssetDataExternal)
|
||||
ResultSet.Add(Asset.LoadSynchronous());
|
||||
|
||||
return ResultSet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function for returning all the assets in the container combined.
|
||||
*
|
||||
* @return Returns all the internal and externally added assets into one set (TSet of UObjects). Careful! They are
|
||||
* returning raw pointers. Seems like an issue in UE5
|
||||
*
|
||||
* @attention If the bAddExternalAssets variable is false, external assets won't be included!
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category="Python")
|
||||
TSet<UObject*> GetAllAssets() const
|
||||
{
|
||||
const TSet<TSoftObjectPtr<UObject>>& IteratedSet = bAddExternalAssets
|
||||
? AssetDataInternal.Union(AssetDataExternal)
|
||||
: AssetDataInternal;
|
||||
|
||||
//Create a new TSet only with raw pointers.
|
||||
TSet<UObject*> ResultSet;
|
||||
|
||||
for (auto& Asset : IteratedSet)
|
||||
ResultSet.Add(Asset.LoadSynchronous());
|
||||
|
||||
return ResultSet;
|
||||
}
|
||||
|
||||
private:
|
||||
UPROPERTY(VisibleAnywhere, Category="Assets")
|
||||
TSet<TSoftObjectPtr<UObject>> AssetDataInternal;
|
||||
|
||||
/**
|
||||
* This property allows exposing the array to include other assets from any other directory than what it's currently
|
||||
* monitoring. NOTE: that these assets have to be added manually! They are not automatically registered or added!
|
||||
*/
|
||||
UPROPERTY(EditAnywhere, Category = "Assets")
|
||||
bool bAddExternalAssets = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, meta=(EditCondition="bAddExternalAssets"), Category="Assets")
|
||||
TSet<TSoftObjectPtr<UObject>> AssetDataExternal;
|
||||
|
||||
|
||||
void OnAssetCreated(const FAssetData& InAssetData);
|
||||
void OnAssetRemoved(const FAssetData& InAssetData);
|
||||
void OnAssetUpdated(const FAssetData& InAssetData);
|
||||
|
||||
bool IsUnderSameDir(const UObject* InAsset) const;
|
||||
|
||||
#ifdef WITH_EDITOR
|
||||
|
||||
void ColorAyonDirs();
|
||||
|
||||
void SendNotification(const FString& Text) const;
|
||||
virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override;
|
||||
|
||||
#endif
|
||||
};
|
||||
|
|
@ -1,20 +1,22 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
// Deprecation warning: this is left here just for backwards compatibility
|
||||
// and will be removed in next versions of Ayon.
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Factories/Factory.h"
|
||||
#include "OpenPypePublishInstanceFactory.generated.h"
|
||||
#include "AyonPublishInstanceFactory.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class OPENPYPE_API UOpenPypePublishInstanceFactory : public UFactory
|
||||
class AYON_API UAyonPublishInstanceFactory : public UFactory
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UOpenPypePublishInstanceFactory(const FObjectInitializer& ObjectInitializer);
|
||||
UAyonPublishInstanceFactory(const FObjectInitializer& ObjectInitializer);
|
||||
virtual UObject* FactoryCreateNew(UClass* InClass, UObject* InParent, FName InName, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn) override;
|
||||
virtual bool ShouldShowInNewMenu() const override;
|
||||
};
|
||||
|
|
@ -1,16 +1,15 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
#pragma once
|
||||
#include "Engine.h"
|
||||
#include "OpenPypePythonBridge.generated.h"
|
||||
#include "AyonPythonBridge.generated.h"
|
||||
|
||||
UCLASS(Blueprintable)
|
||||
class UOpenPypePythonBridge : public UObject
|
||||
class UAyonPythonBridge : public UObject
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UFUNCTION(BlueprintCallable, Category = Python)
|
||||
static UOpenPypePythonBridge* Get();
|
||||
static UAyonPythonBridge* Get();
|
||||
|
||||
UFUNCTION(BlueprintImplementableEvent, Category = Python)
|
||||
void RunInPython_Popup() const;
|
||||
|
|
@ -1,15 +1,15 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
// Copyright 2023, Ayon, All rights reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/Object.h"
|
||||
#include "OpenPypeSettings.generated.h"
|
||||
#include "AyonSettings.generated.h"
|
||||
|
||||
#define OPENPYPE_SETTINGS_FILEPATH IPluginManager::Get().FindPlugin("OpenPype")->GetBaseDir() / TEXT("Config") / TEXT("DefaultOpenPypeSettings.ini")
|
||||
#define AYON_SETTINGS_FILEPATH IPluginManager::Get().FindPlugin("Ayon")->GetBaseDir() / TEXT("Config") / TEXT("DefaultAyonSettings.ini")
|
||||
|
||||
UCLASS(Config=OpenPypeSettings, DefaultConfig)
|
||||
class OPENPYPE_API UOpenPypeSettings : public UObject
|
||||
UCLASS(Config=AyonSettings, DefaultConfig)
|
||||
class AYON_API UAyonSettings : public UObject
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
#include "CoreMinimal.h"
|
||||
#include "Styling/SlateStyle.h"
|
||||
|
||||
class FOpenPypeStyle
|
||||
class FAyonStyle
|
||||
{
|
||||
public:
|
||||
static void Initialize();
|
||||
|
|
@ -15,5 +15,5 @@ public:
|
|||
|
||||
private:
|
||||
static TSharedRef< class FSlateStyleSet > Create();
|
||||
static TSharedPtr< class FSlateStyleSet > OpenPypeStyleInstance;
|
||||
static TSharedPtr< class FSlateStyleSet > AyonStyleInstance;
|
||||
};
|
||||