mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-24 21:04:40 +01:00
[Automated] Merged develop into main
This commit is contained in:
commit
ffcf2d1297
148 changed files with 277 additions and 5857 deletions
2
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
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.8-nightly.1
|
||||
- 3.15.7
|
||||
- 3.15.7-nightly.3
|
||||
- 3.15.7-nightly.2
|
||||
|
|
@ -134,7 +135,6 @@ body:
|
|||
- 3.14.2-nightly.1
|
||||
- 3.14.1
|
||||
- 3.14.1-nightly.4
|
||||
- 3.14.1-nightly.3
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
|
|
|
|||
5
.gitmodules
vendored
5
.gitmodules
vendored
|
|
@ -4,4 +4,7 @@
|
|||
|
||||
[submodule "tools/modules/powershell/PSWriteColor"]
|
||||
path = tools/modules/powershell/PSWriteColor
|
||||
url = https://github.com/EvotecIT/PSWriteColor.git
|
||||
url = https://github.com/EvotecIT/PSWriteColor.git
|
||||
[submodule "openpype/hosts/unreal/integration"]
|
||||
path = openpype/hosts/unreal/integration
|
||||
url = https://github.com/ynput/ayon-unreal-plugin.git
|
||||
|
|
|
|||
|
|
@ -60,9 +60,6 @@ class AfterEffectsHost(HostBase, IWorkfileHost, ILoadHost, IPublishHost):
|
|||
print("Not connected yet, ignoring")
|
||||
return
|
||||
|
||||
if not stub.get_active_document_name():
|
||||
return
|
||||
|
||||
self._stub = stub
|
||||
return self._stub
|
||||
|
||||
|
|
|
|||
|
|
@ -65,37 +65,19 @@ class CacheModelLoader(plugin.AssetLoader):
|
|||
|
||||
imported = lib.get_selection()
|
||||
|
||||
empties = [obj for obj in imported if obj.type == 'EMPTY']
|
||||
|
||||
container = None
|
||||
|
||||
for empty in empties:
|
||||
if not empty.parent:
|
||||
container = empty
|
||||
break
|
||||
|
||||
assert container, "No asset group found"
|
||||
|
||||
# Children must be linked before parents,
|
||||
# otherwise the hierarchy will break
|
||||
objects = []
|
||||
nodes = list(container.children)
|
||||
|
||||
for obj in nodes:
|
||||
for obj in imported:
|
||||
obj.parent = asset_group
|
||||
|
||||
bpy.data.objects.remove(container)
|
||||
|
||||
for obj in nodes:
|
||||
for obj in imported:
|
||||
objects.append(obj)
|
||||
nodes.extend(list(obj.children))
|
||||
imported.extend(list(obj.children))
|
||||
|
||||
objects.reverse()
|
||||
|
||||
for obj in objects:
|
||||
parent.objects.link(obj)
|
||||
collection.objects.unlink(obj)
|
||||
|
||||
for obj in objects:
|
||||
name = obj.name
|
||||
obj.name = f"{group_name}:{name}"
|
||||
|
|
@ -138,13 +120,14 @@ class CacheModelLoader(plugin.AssetLoader):
|
|||
group_name = plugin.asset_name(asset, subset, unique_number)
|
||||
namespace = namespace or f"{asset}_{unique_number}"
|
||||
|
||||
avalon_container = bpy.data.collections.get(AVALON_CONTAINERS)
|
||||
if not avalon_container:
|
||||
avalon_container = bpy.data.collections.new(name=AVALON_CONTAINERS)
|
||||
bpy.context.scene.collection.children.link(avalon_container)
|
||||
avalon_containers = bpy.data.collections.get(AVALON_CONTAINERS)
|
||||
if not avalon_containers:
|
||||
avalon_containers = bpy.data.collections.new(
|
||||
name=AVALON_CONTAINERS)
|
||||
bpy.context.scene.collection.children.link(avalon_containers)
|
||||
|
||||
asset_group = bpy.data.objects.new(group_name, object_data=None)
|
||||
avalon_container.objects.link(asset_group)
|
||||
avalon_containers.objects.link(asset_group)
|
||||
|
||||
objects = self._process(libpath, asset_group, group_name)
|
||||
|
||||
|
|
|
|||
|
|
@ -245,11 +245,15 @@ def reset_frame_range(fps: bool = True):
|
|||
fps_number = float(data_fps["data"]["fps"])
|
||||
rt.frameRate = fps_number
|
||||
frame_range = get_frame_range()
|
||||
frame_start = frame_range["frameStart"] - int(frame_range["handleStart"])
|
||||
frame_end = frame_range["frameEnd"] + int(frame_range["handleEnd"])
|
||||
frange_cmd = f"animationRange = interval {frame_start} {frame_end}"
|
||||
frame_start_handle = frame_range["frameStart"] - int(
|
||||
frame_range["handleStart"]
|
||||
)
|
||||
frame_end_handle = frame_range["frameEnd"] + int(frame_range["handleEnd"])
|
||||
frange_cmd = (
|
||||
f"animationRange = interval {frame_start_handle} {frame_end_handle}"
|
||||
)
|
||||
rt.execute(frange_cmd)
|
||||
set_render_frame_range(frame_start, frame_end)
|
||||
set_render_frame_range(frame_start_handle, frame_end_handle)
|
||||
|
||||
|
||||
def set_context_setting():
|
||||
|
|
|
|||
|
|
@ -20,28 +20,25 @@ class FbxLoader(load.LoaderPlugin):
|
|||
from pymxs import runtime as rt
|
||||
|
||||
filepath = os.path.normpath(self.fname)
|
||||
rt.FBXImporterSetParam("Animation", True)
|
||||
rt.FBXImporterSetParam("Camera", True)
|
||||
rt.FBXImporterSetParam("AxisConversionMethod", True)
|
||||
rt.FBXImporterSetParam("Preserveinstances", True)
|
||||
rt.importFile(
|
||||
filepath,
|
||||
rt.name("noPrompt"),
|
||||
using=rt.FBXIMP)
|
||||
|
||||
fbx_import_cmd = (
|
||||
f"""
|
||||
container = rt.getNodeByName(f"{name}")
|
||||
if not container:
|
||||
container = rt.container()
|
||||
container.name = f"{name}"
|
||||
|
||||
FBXImporterSetParam "Animation" true
|
||||
FBXImporterSetParam "Cameras" true
|
||||
FBXImporterSetParam "AxisConversionMethod" true
|
||||
FbxExporterSetParam "UpAxis" "Y"
|
||||
FbxExporterSetParam "Preserveinstances" true
|
||||
|
||||
importFile @"{filepath}" #noPrompt using:FBXIMP
|
||||
""")
|
||||
|
||||
self.log.debug(f"Executing command: {fbx_import_cmd}")
|
||||
rt.execute(fbx_import_cmd)
|
||||
|
||||
container_name = f"{name}_CON"
|
||||
|
||||
asset = rt.getNodeByName(f"{name}")
|
||||
for selection in rt.getCurrentSelection():
|
||||
selection.Parent = container
|
||||
|
||||
return containerise(
|
||||
name, [asset], context, loader=self.__class__.__name__)
|
||||
name, [container], context, loader=self.__class__.__name__)
|
||||
|
||||
def update(self, container, representation):
|
||||
from pymxs import runtime as rt
|
||||
|
|
|
|||
|
|
@ -21,26 +21,24 @@ class FbxModelLoader(load.LoaderPlugin):
|
|||
from pymxs import runtime as rt
|
||||
|
||||
filepath = os.path.normpath(self.fname)
|
||||
rt.FBXImporterSetParam("Animation", False)
|
||||
rt.FBXImporterSetParam("Cameras", False)
|
||||
rt.FBXImporterSetParam("Preserveinstances", True)
|
||||
rt.importFile(
|
||||
filepath,
|
||||
rt.name("noPrompt"),
|
||||
using=rt.FBXIMP)
|
||||
|
||||
fbx_import_cmd = (
|
||||
f"""
|
||||
container = rt.getNodeByName(f"{name}")
|
||||
if not container:
|
||||
container = rt.container()
|
||||
container.name = f"{name}"
|
||||
|
||||
FBXImporterSetParam "Animation" false
|
||||
FBXImporterSetParam "Cameras" false
|
||||
FBXImporterSetParam "AxisConversionMethod" true
|
||||
FbxExporterSetParam "UpAxis" "Y"
|
||||
FbxExporterSetParam "Preserveinstances" true
|
||||
|
||||
importFile @"{filepath}" #noPrompt using:FBXIMP
|
||||
""")
|
||||
|
||||
self.log.debug(f"Executing command: {fbx_import_cmd}")
|
||||
rt.execute(fbx_import_cmd)
|
||||
|
||||
asset = rt.getNodeByName(f"{name}")
|
||||
for selection in rt.getCurrentSelection():
|
||||
selection.Parent = container
|
||||
|
||||
return containerise(
|
||||
name, [asset], context, loader=self.__class__.__name__)
|
||||
name, [container], context, loader=self.__class__.__name__)
|
||||
|
||||
def update(self, container, representation):
|
||||
from pymxs import runtime as rt
|
||||
|
|
|
|||
|
|
@ -1,18 +1,11 @@
|
|||
import os
|
||||
import pyblish.api
|
||||
from openpype.pipeline import (
|
||||
publish,
|
||||
OptionalPyblishPluginMixin
|
||||
)
|
||||
from openpype.pipeline import publish, OptionalPyblishPluginMixin
|
||||
from pymxs import runtime as rt
|
||||
from openpype.hosts.max.api import (
|
||||
maintained_selection,
|
||||
get_all_children
|
||||
)
|
||||
from openpype.hosts.max.api import maintained_selection, get_all_children
|
||||
|
||||
|
||||
class ExtractCameraAlembic(publish.Extractor,
|
||||
OptionalPyblishPluginMixin):
|
||||
class ExtractCameraAlembic(publish.Extractor, OptionalPyblishPluginMixin):
|
||||
"""
|
||||
Extract Camera with AlembicExport
|
||||
"""
|
||||
|
|
@ -38,38 +31,33 @@ class ExtractCameraAlembic(publish.Extractor,
|
|||
path = os.path.join(stagingdir, filename)
|
||||
|
||||
# We run the render
|
||||
self.log.info("Writing alembic '%s' to '%s'" % (filename,
|
||||
stagingdir))
|
||||
self.log.info("Writing alembic '%s' to '%s'" % (filename, stagingdir))
|
||||
|
||||
export_cmd = (
|
||||
f"""
|
||||
AlembicExport.ArchiveType = #ogawa
|
||||
AlembicExport.CoordinateSystem = #maya
|
||||
AlembicExport.StartFrame = {start}
|
||||
AlembicExport.EndFrame = {end}
|
||||
AlembicExport.CustomAttributes = true
|
||||
|
||||
exportFile @"{path}" #noPrompt selectedOnly:on using:AlembicExport
|
||||
|
||||
""")
|
||||
|
||||
self.log.debug(f"Executing command: {export_cmd}")
|
||||
rt.AlembicExport.ArchiveType = rt.name("ogawa")
|
||||
rt.AlembicExport.CoordinateSystem = rt.name("maya")
|
||||
rt.AlembicExport.StartFrame = start
|
||||
rt.AlembicExport.EndFrame = end
|
||||
rt.AlembicExport.CustomAttributes = True
|
||||
|
||||
with maintained_selection():
|
||||
# select and export
|
||||
rt.select(get_all_children(rt.getNodeByName(container)))
|
||||
rt.execute(export_cmd)
|
||||
rt.exportFile(
|
||||
path,
|
||||
rt.name("noPrompt"),
|
||||
selectedOnly=True,
|
||||
using=rt.AlembicExport,
|
||||
)
|
||||
|
||||
self.log.info("Performing Extraction ...")
|
||||
if "representations" not in instance.data:
|
||||
instance.data["representations"] = []
|
||||
|
||||
representation = {
|
||||
'name': 'abc',
|
||||
'ext': 'abc',
|
||||
'files': filename,
|
||||
"name": "abc",
|
||||
"ext": "abc",
|
||||
"files": filename,
|
||||
"stagingDir": stagingdir,
|
||||
}
|
||||
instance.data["representations"].append(representation)
|
||||
self.log.info("Extracted instance '%s' to: %s" % (instance.name,
|
||||
path))
|
||||
self.log.info("Extracted instance '%s' to: %s" % (instance.name, path))
|
||||
|
|
|
|||
|
|
@ -1,18 +1,11 @@
|
|||
import os
|
||||
import pyblish.api
|
||||
from openpype.pipeline import (
|
||||
publish,
|
||||
OptionalPyblishPluginMixin
|
||||
)
|
||||
from openpype.pipeline import publish, OptionalPyblishPluginMixin
|
||||
from pymxs import runtime as rt
|
||||
from openpype.hosts.max.api import (
|
||||
maintained_selection,
|
||||
get_all_children
|
||||
)
|
||||
from openpype.hosts.max.api import maintained_selection, get_all_children
|
||||
|
||||
|
||||
class ExtractCameraFbx(publish.Extractor,
|
||||
OptionalPyblishPluginMixin):
|
||||
class ExtractCameraFbx(publish.Extractor, OptionalPyblishPluginMixin):
|
||||
"""
|
||||
Extract Camera with FbxExporter
|
||||
"""
|
||||
|
|
@ -33,43 +26,35 @@ class ExtractCameraFbx(publish.Extractor,
|
|||
filename = "{name}.fbx".format(**instance.data)
|
||||
|
||||
filepath = os.path.join(stagingdir, filename)
|
||||
self.log.info("Writing fbx file '%s' to '%s'" % (filename,
|
||||
filepath))
|
||||
self.log.info("Writing fbx file '%s' to '%s'" % (filename, filepath))
|
||||
|
||||
# Need to export:
|
||||
# Animation = True
|
||||
# Cameras = True
|
||||
# AxisConversionMethod
|
||||
fbx_export_cmd = (
|
||||
f"""
|
||||
|
||||
FBXExporterSetParam "Animation" true
|
||||
FBXExporterSetParam "Cameras" true
|
||||
FBXExporterSetParam "AxisConversionMethod" "Animation"
|
||||
FbxExporterSetParam "UpAxis" "Y"
|
||||
FbxExporterSetParam "Preserveinstances" true
|
||||
|
||||
exportFile @"{filepath}" #noPrompt selectedOnly:true using:FBXEXP
|
||||
|
||||
""")
|
||||
|
||||
self.log.debug(f"Executing command: {fbx_export_cmd}")
|
||||
rt.FBXExporterSetParam("Animation", True)
|
||||
rt.FBXExporterSetParam("Cameras", True)
|
||||
rt.FBXExporterSetParam("AxisConversionMethod", "Animation")
|
||||
rt.FBXExporterSetParam("UpAxis", "Y")
|
||||
rt.FBXExporterSetParam("Preserveinstances", True)
|
||||
|
||||
with maintained_selection():
|
||||
# select and export
|
||||
rt.select(get_all_children(rt.getNodeByName(container)))
|
||||
rt.execute(fbx_export_cmd)
|
||||
rt.exportFile(
|
||||
filepath,
|
||||
rt.name("noPrompt"),
|
||||
selectedOnly=True,
|
||||
using=rt.FBXEXP,
|
||||
)
|
||||
|
||||
self.log.info("Performing Extraction ...")
|
||||
if "representations" not in instance.data:
|
||||
instance.data["representations"] = []
|
||||
|
||||
representation = {
|
||||
'name': 'fbx',
|
||||
'ext': 'fbx',
|
||||
'files': filename,
|
||||
"name": "fbx",
|
||||
"ext": "fbx",
|
||||
"files": filename,
|
||||
"stagingDir": stagingdir,
|
||||
}
|
||||
instance.data["representations"].append(representation)
|
||||
self.log.info("Extracted instance '%s' to: %s" % (instance.name,
|
||||
filepath))
|
||||
self.log.info(
|
||||
"Extracted instance '%s' to: %s" % (instance.name, filepath)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,18 +1,11 @@
|
|||
import os
|
||||
import pyblish.api
|
||||
from openpype.pipeline import (
|
||||
publish,
|
||||
OptionalPyblishPluginMixin
|
||||
)
|
||||
from openpype.pipeline import publish, OptionalPyblishPluginMixin
|
||||
from pymxs import runtime as rt
|
||||
from openpype.hosts.max.api import (
|
||||
maintained_selection,
|
||||
get_all_children
|
||||
)
|
||||
from openpype.hosts.max.api import get_all_children
|
||||
|
||||
|
||||
class ExtractMaxSceneRaw(publish.Extractor,
|
||||
OptionalPyblishPluginMixin):
|
||||
class ExtractMaxSceneRaw(publish.Extractor, OptionalPyblishPluginMixin):
|
||||
"""
|
||||
Extract Raw Max Scene with SaveSelected
|
||||
"""
|
||||
|
|
@ -20,9 +13,7 @@ class ExtractMaxSceneRaw(publish.Extractor,
|
|||
order = pyblish.api.ExtractorOrder - 0.2
|
||||
label = "Extract Max Scene (Raw)"
|
||||
hosts = ["max"]
|
||||
families = ["camera",
|
||||
"maxScene",
|
||||
"model"]
|
||||
families = ["camera", "maxScene", "model"]
|
||||
optional = True
|
||||
|
||||
def process(self, instance):
|
||||
|
|
@ -37,26 +28,23 @@ class ExtractMaxSceneRaw(publish.Extractor,
|
|||
filename = "{name}.max".format(**instance.data)
|
||||
|
||||
max_path = os.path.join(stagingdir, filename)
|
||||
self.log.info("Writing max file '%s' to '%s'" % (filename,
|
||||
max_path))
|
||||
self.log.info("Writing max file '%s' to '%s'" % (filename, max_path))
|
||||
|
||||
if "representations" not in instance.data:
|
||||
instance.data["representations"] = []
|
||||
|
||||
# saving max scene
|
||||
with maintained_selection():
|
||||
# need to figure out how to select the camera
|
||||
rt.select(get_all_children(rt.getNodeByName(container)))
|
||||
rt.execute(f'saveNodes selection "{max_path}" quiet:true')
|
||||
nodes = get_all_children(rt.getNodeByName(container))
|
||||
rt.saveNodes(nodes, max_path, quiet=True)
|
||||
|
||||
self.log.info("Performing Extraction ...")
|
||||
|
||||
representation = {
|
||||
'name': 'max',
|
||||
'ext': 'max',
|
||||
'files': filename,
|
||||
"name": "max",
|
||||
"ext": "max",
|
||||
"files": filename,
|
||||
"stagingDir": stagingdir,
|
||||
}
|
||||
instance.data["representations"].append(representation)
|
||||
self.log.info("Extracted instance '%s' to: %s" % (instance.name,
|
||||
max_path))
|
||||
self.log.info(
|
||||
"Extracted instance '%s' to: %s" % (instance.name, max_path)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,18 +1,11 @@
|
|||
import os
|
||||
import pyblish.api
|
||||
from openpype.pipeline import (
|
||||
publish,
|
||||
OptionalPyblishPluginMixin
|
||||
)
|
||||
from openpype.pipeline import publish, OptionalPyblishPluginMixin
|
||||
from pymxs import runtime as rt
|
||||
from openpype.hosts.max.api import (
|
||||
maintained_selection,
|
||||
get_all_children
|
||||
)
|
||||
from openpype.hosts.max.api import maintained_selection, get_all_children
|
||||
|
||||
|
||||
class ExtractModel(publish.Extractor,
|
||||
OptionalPyblishPluginMixin):
|
||||
class ExtractModel(publish.Extractor, OptionalPyblishPluginMixin):
|
||||
"""
|
||||
Extract Geometry in Alembic Format
|
||||
"""
|
||||
|
|
@ -36,39 +29,36 @@ class ExtractModel(publish.Extractor,
|
|||
filepath = os.path.join(stagingdir, filename)
|
||||
|
||||
# We run the render
|
||||
self.log.info("Writing alembic '%s' to '%s'" % (filename,
|
||||
stagingdir))
|
||||
self.log.info("Writing alembic '%s' to '%s'" % (filename, stagingdir))
|
||||
|
||||
export_cmd = (
|
||||
f"""
|
||||
AlembicExport.ArchiveType = #ogawa
|
||||
AlembicExport.CoordinateSystem = #maya
|
||||
AlembicExport.CustomAttributes = true
|
||||
AlembicExport.UVs = true
|
||||
AlembicExport.VertexColors = true
|
||||
AlembicExport.PreserveInstances = true
|
||||
|
||||
exportFile @"{filepath}" #noPrompt selectedOnly:on using:AlembicExport
|
||||
|
||||
""")
|
||||
|
||||
self.log.debug(f"Executing command: {export_cmd}")
|
||||
rt.AlembicExport.ArchiveType = rt.name("ogawa")
|
||||
rt.AlembicExport.CoordinateSystem = rt.name("maya")
|
||||
rt.AlembicExport.CustomAttributes = True
|
||||
rt.AlembicExport.UVs = True
|
||||
rt.AlembicExport.VertexColors = True
|
||||
rt.AlembicExport.PreserveInstances = True
|
||||
|
||||
with maintained_selection():
|
||||
# select and export
|
||||
rt.select(get_all_children(rt.getNodeByName(container)))
|
||||
rt.execute(export_cmd)
|
||||
rt.exportFile(
|
||||
filepath,
|
||||
rt.name("noPrompt"),
|
||||
selectedOnly=True,
|
||||
using=rt.AlembicExport,
|
||||
)
|
||||
|
||||
self.log.info("Performing Extraction ...")
|
||||
if "representations" not in instance.data:
|
||||
instance.data["representations"] = []
|
||||
|
||||
representation = {
|
||||
'name': 'abc',
|
||||
'ext': 'abc',
|
||||
'files': filename,
|
||||
"name": "abc",
|
||||
"ext": "abc",
|
||||
"files": filename,
|
||||
"stagingDir": stagingdir,
|
||||
}
|
||||
instance.data["representations"].append(representation)
|
||||
self.log.info("Extracted instance '%s' to: %s" % (instance.name,
|
||||
filepath))
|
||||
self.log.info(
|
||||
"Extracted instance '%s' to: %s" % (instance.name, filepath)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,18 +1,11 @@
|
|||
import os
|
||||
import pyblish.api
|
||||
from openpype.pipeline import (
|
||||
publish,
|
||||
OptionalPyblishPluginMixin
|
||||
)
|
||||
from openpype.pipeline import publish, OptionalPyblishPluginMixin
|
||||
from pymxs import runtime as rt
|
||||
from openpype.hosts.max.api import (
|
||||
maintained_selection,
|
||||
get_all_children
|
||||
)
|
||||
from openpype.hosts.max.api import maintained_selection, get_all_children
|
||||
|
||||
|
||||
class ExtractModelFbx(publish.Extractor,
|
||||
OptionalPyblishPluginMixin):
|
||||
class ExtractModelFbx(publish.Extractor, OptionalPyblishPluginMixin):
|
||||
"""
|
||||
Extract Geometry in FBX Format
|
||||
"""
|
||||
|
|
@ -33,42 +26,38 @@ class ExtractModelFbx(publish.Extractor,
|
|||
|
||||
stagingdir = self.staging_dir(instance)
|
||||
filename = "{name}.fbx".format(**instance.data)
|
||||
filepath = os.path.join(stagingdir,
|
||||
filename)
|
||||
self.log.info("Writing FBX '%s' to '%s'" % (filepath,
|
||||
stagingdir))
|
||||
filepath = os.path.join(stagingdir, filename)
|
||||
self.log.info("Writing FBX '%s' to '%s'" % (filepath, stagingdir))
|
||||
|
||||
export_fbx_cmd = (
|
||||
f"""
|
||||
FBXExporterSetParam "Animation" false
|
||||
FBXExporterSetParam "Cameras" false
|
||||
FBXExporterSetParam "Lights" false
|
||||
FBXExporterSetParam "PointCache" false
|
||||
FBXExporterSetParam "AxisConversionMethod" "Animation"
|
||||
FbxExporterSetParam "UpAxis" "Y"
|
||||
FbxExporterSetParam "Preserveinstances" true
|
||||
|
||||
exportFile @"{filepath}" #noPrompt selectedOnly:true using:FBXEXP
|
||||
|
||||
""")
|
||||
|
||||
self.log.debug(f"Executing command: {export_fbx_cmd}")
|
||||
rt.FBXExporterSetParam("Animation", False)
|
||||
rt.FBXExporterSetParam("Cameras", False)
|
||||
rt.FBXExporterSetParam("Lights", False)
|
||||
rt.FBXExporterSetParam("PointCache", False)
|
||||
rt.FBXExporterSetParam("AxisConversionMethod", "Animation")
|
||||
rt.FBXExporterSetParam("UpAxis", "Y")
|
||||
rt.FBXExporterSetParam("Preserveinstances", True)
|
||||
|
||||
with maintained_selection():
|
||||
# select and export
|
||||
rt.select(get_all_children(rt.getNodeByName(container)))
|
||||
rt.execute(export_fbx_cmd)
|
||||
rt.exportFile(
|
||||
filepath,
|
||||
rt.name("noPrompt"),
|
||||
selectedOnly=True,
|
||||
using=rt.FBXEXP,
|
||||
)
|
||||
|
||||
self.log.info("Performing Extraction ...")
|
||||
if "representations" not in instance.data:
|
||||
instance.data["representations"] = []
|
||||
|
||||
representation = {
|
||||
'name': 'fbx',
|
||||
'ext': 'fbx',
|
||||
'files': filename,
|
||||
"name": "fbx",
|
||||
"ext": "fbx",
|
||||
"files": filename,
|
||||
"stagingDir": stagingdir,
|
||||
}
|
||||
instance.data["representations"].append(representation)
|
||||
self.log.info("Extracted instance '%s' to: %s" % (instance.name,
|
||||
filepath))
|
||||
self.log.info(
|
||||
"Extracted instance '%s' to: %s" % (instance.name, filepath)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,18 +1,11 @@
|
|||
import os
|
||||
import pyblish.api
|
||||
from openpype.pipeline import (
|
||||
publish,
|
||||
OptionalPyblishPluginMixin
|
||||
)
|
||||
from openpype.pipeline import publish, OptionalPyblishPluginMixin
|
||||
from pymxs import runtime as rt
|
||||
from openpype.hosts.max.api import (
|
||||
maintained_selection,
|
||||
get_all_children
|
||||
)
|
||||
from openpype.hosts.max.api import maintained_selection, get_all_children
|
||||
|
||||
|
||||
class ExtractModelObj(publish.Extractor,
|
||||
OptionalPyblishPluginMixin):
|
||||
class ExtractModelObj(publish.Extractor, OptionalPyblishPluginMixin):
|
||||
"""
|
||||
Extract Geometry in OBJ Format
|
||||
"""
|
||||
|
|
@ -33,27 +26,31 @@ class ExtractModelObj(publish.Extractor,
|
|||
|
||||
stagingdir = self.staging_dir(instance)
|
||||
filename = "{name}.obj".format(**instance.data)
|
||||
filepath = os.path.join(stagingdir,
|
||||
filename)
|
||||
self.log.info("Writing OBJ '%s' to '%s'" % (filepath,
|
||||
stagingdir))
|
||||
filepath = os.path.join(stagingdir, filename)
|
||||
self.log.info("Writing OBJ '%s' to '%s'" % (filepath, stagingdir))
|
||||
|
||||
with maintained_selection():
|
||||
# select and export
|
||||
rt.select(get_all_children(rt.getNodeByName(container)))
|
||||
rt.execute(f'exportFile @"{filepath}" #noPrompt selectedOnly:true using:ObjExp') # noqa
|
||||
rt.exportFile(
|
||||
filepath,
|
||||
rt.name("noPrompt"),
|
||||
selectedOnly=True,
|
||||
using=rt.ObjExp,
|
||||
)
|
||||
|
||||
self.log.info("Performing Extraction ...")
|
||||
if "representations" not in instance.data:
|
||||
instance.data["representations"] = []
|
||||
|
||||
representation = {
|
||||
'name': 'obj',
|
||||
'ext': 'obj',
|
||||
'files': filename,
|
||||
"name": "obj",
|
||||
"ext": "obj",
|
||||
"files": filename,
|
||||
"stagingDir": stagingdir,
|
||||
}
|
||||
|
||||
instance.data["representations"].append(representation)
|
||||
self.log.info("Extracted instance '%s' to: %s" % (instance.name,
|
||||
filepath))
|
||||
self.log.info(
|
||||
"Extracted instance '%s' to: %s" % (instance.name, filepath)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -41,10 +41,7 @@ import os
|
|||
import pyblish.api
|
||||
from openpype.pipeline import publish
|
||||
from pymxs import runtime as rt
|
||||
from openpype.hosts.max.api import (
|
||||
maintained_selection,
|
||||
get_all_children
|
||||
)
|
||||
from openpype.hosts.max.api import maintained_selection, get_all_children
|
||||
|
||||
|
||||
class ExtractAlembic(publish.Extractor):
|
||||
|
|
@ -66,35 +63,30 @@ class ExtractAlembic(publish.Extractor):
|
|||
path = os.path.join(parent_dir, file_name)
|
||||
|
||||
# We run the render
|
||||
self.log.info("Writing alembic '%s' to '%s'" % (file_name,
|
||||
parent_dir))
|
||||
self.log.info("Writing alembic '%s' to '%s'" % (file_name, parent_dir))
|
||||
|
||||
abc_export_cmd = (
|
||||
f"""
|
||||
AlembicExport.ArchiveType = #ogawa
|
||||
AlembicExport.CoordinateSystem = #maya
|
||||
AlembicExport.StartFrame = {start}
|
||||
AlembicExport.EndFrame = {end}
|
||||
|
||||
exportFile @"{path}" #noPrompt selectedOnly:on using:AlembicExport
|
||||
|
||||
""")
|
||||
|
||||
self.log.debug(f"Executing command: {abc_export_cmd}")
|
||||
rt.AlembicExport.ArchiveType = rt.name("ogawa")
|
||||
rt.AlembicExport.CoordinateSystem = rt.name("maya")
|
||||
rt.AlembicExport.StartFrame = start
|
||||
rt.AlembicExport.EndFrame = end
|
||||
|
||||
with maintained_selection():
|
||||
# select and export
|
||||
|
||||
rt.select(get_all_children(rt.getNodeByName(container)))
|
||||
rt.execute(abc_export_cmd)
|
||||
rt.exportFile(
|
||||
path,
|
||||
rt.name("noPrompt"),
|
||||
selectedOnly=True,
|
||||
using=rt.AlembicExport,
|
||||
)
|
||||
|
||||
if "representations" not in instance.data:
|
||||
instance.data["representations"] = []
|
||||
|
||||
representation = {
|
||||
'name': 'abc',
|
||||
'ext': 'abc',
|
||||
'files': file_name,
|
||||
"name": "abc",
|
||||
"ext": "abc",
|
||||
"files": file_name,
|
||||
"stagingDir": parent_dir,
|
||||
}
|
||||
instance.data["representations"].append(representation)
|
||||
|
|
|
|||
|
|
@ -190,6 +190,44 @@ def maintained_selection():
|
|||
cmds.select(clear=True)
|
||||
|
||||
|
||||
def get_custom_namespace(custom_namespace):
|
||||
"""Return unique namespace.
|
||||
|
||||
The input namespace can contain a single group
|
||||
of '#' number tokens to indicate where the namespace's
|
||||
unique index should go. The amount of tokens defines
|
||||
the zero padding of the number, e.g ### turns into 001.
|
||||
|
||||
Warning: Note that a namespace will always be
|
||||
prefixed with a _ if it starts with a digit
|
||||
|
||||
Example:
|
||||
>>> get_custom_namespace("myspace_##_")
|
||||
# myspace_01_
|
||||
>>> get_custom_namespace("##_myspace")
|
||||
# _01_myspace
|
||||
>>> get_custom_namespace("myspace##")
|
||||
# myspace01
|
||||
|
||||
"""
|
||||
split = re.split("([#]+)", custom_namespace, 1)
|
||||
|
||||
if len(split) == 3:
|
||||
base, padding, suffix = split
|
||||
padding = "%0{}d".format(len(padding))
|
||||
else:
|
||||
base = split[0]
|
||||
padding = "%02d" # default padding
|
||||
suffix = ""
|
||||
|
||||
return unique_namespace(
|
||||
base,
|
||||
format=padding,
|
||||
prefix="_" if not base or base[0].isdigit() else "",
|
||||
suffix=suffix
|
||||
)
|
||||
|
||||
|
||||
def unique_namespace(namespace, format="%02d", prefix="", suffix=""):
|
||||
"""Return unique namespace
|
||||
|
||||
|
|
@ -316,11 +354,13 @@ def collect_animation_data(fps=False):
|
|||
# get scene values as defaults
|
||||
frame_start = cmds.playbackOptions(query=True, minTime=True)
|
||||
frame_end = cmds.playbackOptions(query=True, maxTime=True)
|
||||
handle_start = cmds.playbackOptions(query=True, animationStartTime=True)
|
||||
handle_end = cmds.playbackOptions(query=True, animationEndTime=True)
|
||||
frame_start_handle = cmds.playbackOptions(
|
||||
query=True, animationStartTime=True
|
||||
)
|
||||
frame_end_handle = cmds.playbackOptions(query=True, animationEndTime=True)
|
||||
|
||||
handle_start = frame_start - handle_start
|
||||
handle_end = handle_end - frame_end
|
||||
handle_start = frame_start - frame_start_handle
|
||||
handle_end = frame_end_handle - frame_end
|
||||
|
||||
# build attributes
|
||||
data = OrderedDict()
|
||||
|
|
@ -3937,7 +3977,9 @@ def get_capture_preset(task_name, task_type, subset, project_settings, log):
|
|||
return capture_preset or {}
|
||||
|
||||
|
||||
def create_rig_animation_instance(nodes, context, namespace, log=None):
|
||||
def create_rig_animation_instance(
|
||||
nodes, context, namespace, options=None, log=None
|
||||
):
|
||||
"""Create an animation publish instance for loaded rigs.
|
||||
|
||||
See the RecreateRigAnimationInstance inventory action on how to use this
|
||||
|
|
@ -3947,12 +3989,16 @@ def create_rig_animation_instance(nodes, context, namespace, log=None):
|
|||
nodes (list): Member nodes of the rig instance.
|
||||
context (dict): Representation context of the rig container
|
||||
namespace (str): Namespace of the rig container
|
||||
options (dict, optional): Additional loader data
|
||||
log (logging.Logger, optional): Logger to log to if provided
|
||||
|
||||
Returns:
|
||||
None
|
||||
|
||||
"""
|
||||
if options is None:
|
||||
options = {}
|
||||
|
||||
output = next((node for node in nodes if
|
||||
node.endswith("out_SET")), None)
|
||||
controls = next((node for node in nodes if
|
||||
|
|
@ -3971,6 +4017,23 @@ def create_rig_animation_instance(nodes, context, namespace, log=None):
|
|||
asset = legacy_io.Session["AVALON_ASSET"]
|
||||
dependency = str(context["representation"]["_id"])
|
||||
|
||||
custom_subset = options.get("animationSubsetName")
|
||||
if custom_subset:
|
||||
formatting_data = {
|
||||
"asset_name": context['asset']['name'],
|
||||
"asset_type": context['asset']['type'],
|
||||
"subset": context['subset']['name'],
|
||||
"family": (
|
||||
context['subset']['data'].get('family') or
|
||||
context['subset']['data']['families'][0]
|
||||
)
|
||||
}
|
||||
namespace = get_custom_namespace(
|
||||
custom_subset.format(
|
||||
**formatting_data
|
||||
)
|
||||
)
|
||||
|
||||
if log:
|
||||
log.info("Creating subset: {}".format(namespace))
|
||||
|
||||
|
|
|
|||
|
|
@ -84,44 +84,6 @@ def get_reference_node_parents(ref):
|
|||
return parents
|
||||
|
||||
|
||||
def get_custom_namespace(custom_namespace):
|
||||
"""Return unique namespace.
|
||||
|
||||
The input namespace can contain a single group
|
||||
of '#' number tokens to indicate where the namespace's
|
||||
unique index should go. The amount of tokens defines
|
||||
the zero padding of the number, e.g ### turns into 001.
|
||||
|
||||
Warning: Note that a namespace will always be
|
||||
prefixed with a _ if it starts with a digit
|
||||
|
||||
Example:
|
||||
>>> get_custom_namespace("myspace_##_")
|
||||
# myspace_01_
|
||||
>>> get_custom_namespace("##_myspace")
|
||||
# _01_myspace
|
||||
>>> get_custom_namespace("myspace##")
|
||||
# myspace01
|
||||
|
||||
"""
|
||||
split = re.split("([#]+)", custom_namespace, 1)
|
||||
|
||||
if len(split) == 3:
|
||||
base, padding, suffix = split
|
||||
padding = "%0{}d".format(len(padding))
|
||||
else:
|
||||
base = split[0]
|
||||
padding = "%02d" # default padding
|
||||
suffix = ""
|
||||
|
||||
return lib.unique_namespace(
|
||||
base,
|
||||
format=padding,
|
||||
prefix="_" if not base or base[0].isdigit() else "",
|
||||
suffix=suffix
|
||||
)
|
||||
|
||||
|
||||
class Creator(LegacyCreator):
|
||||
defaults = ['Main']
|
||||
|
||||
|
|
@ -216,7 +178,7 @@ class ReferenceLoader(Loader):
|
|||
count = options.get("count") or 1
|
||||
|
||||
for c in range(0, count):
|
||||
namespace = get_custom_namespace(custom_namespace)
|
||||
namespace = lib.get_custom_namespace(custom_namespace)
|
||||
group_name = "{}:{}".format(
|
||||
namespace,
|
||||
custom_group_name
|
||||
|
|
|
|||
|
|
@ -223,7 +223,7 @@ class ReferenceLoader(openpype.hosts.maya.api.plugin.ReferenceLoader):
|
|||
def _post_process_rig(self, name, namespace, context, options):
|
||||
nodes = self[:]
|
||||
create_rig_animation_instance(
|
||||
nodes, context, namespace, log=self.log
|
||||
nodes, context, namespace, options=options, log=self.log
|
||||
)
|
||||
|
||||
def _lock_camera_transforms(self, nodes):
|
||||
|
|
|
|||
|
|
@ -2239,13 +2239,13 @@ class WorkfileSettings(object):
|
|||
handle_end = data["handleEnd"]
|
||||
|
||||
fps = float(data["fps"])
|
||||
frame_start = int(data["frameStart"]) - handle_start
|
||||
frame_end = int(data["frameEnd"]) + handle_end
|
||||
frame_start_handle = int(data["frameStart"]) - handle_start
|
||||
frame_end_handle = int(data["frameEnd"]) + handle_end
|
||||
|
||||
self._root_node["lock_range"].setValue(False)
|
||||
self._root_node["fps"].setValue(fps)
|
||||
self._root_node["first_frame"].setValue(frame_start)
|
||||
self._root_node["last_frame"].setValue(frame_end)
|
||||
self._root_node["first_frame"].setValue(frame_start_handle)
|
||||
self._root_node["last_frame"].setValue(frame_end_handle)
|
||||
self._root_node["lock_range"].setValue(True)
|
||||
|
||||
# setting active viewers
|
||||
|
|
|
|||
|
|
@ -1,8 +1,5 @@
|
|||
import os
|
||||
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__))
|
||||
|
||||
|
|
@ -17,10 +14,14 @@ class UnrealAddon(OpenPypeModule, IHostAddon):
|
|||
def add_implementation_envs(self, env, app):
|
||||
"""Modify environments to contain all required for implementation."""
|
||||
# Set AYON_UNREAL_PLUGIN required for Unreal implementation
|
||||
# Imports are in this method for Python 2 compatiblity of an addon
|
||||
from pathlib import Path
|
||||
|
||||
from .lib import get_compatible_integration
|
||||
|
||||
ue_version = app.name.replace("-", ".")
|
||||
unreal_plugin_path = os.path.join(
|
||||
UNREAL_ROOT_DIR, "integration", f"UE_{ue_version}", "Ayon"
|
||||
UNREAL_ROOT_DIR, "integration", "UE_{}".format(ue_version), "Ayon"
|
||||
)
|
||||
if not Path(unreal_plugin_path).exists():
|
||||
compatible_versions = get_compatible_integration(
|
||||
|
|
|
|||
1
openpype/hosts/unreal/integration
Submodule
1
openpype/hosts/unreal/integration
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit ff15c700771e719cc5f3d561ac5d6f7590623986
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
# 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.
|
||||
|
||||
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
# Prerequisites
|
||||
*.d
|
||||
|
||||
# Compiled Object files
|
||||
*.slo
|
||||
*.lo
|
||||
*.o
|
||||
*.obj
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
*.pch
|
||||
|
||||
# Compiled Dynamic libraries
|
||||
*.so
|
||||
*.dylib
|
||||
*.dll
|
||||
|
||||
# Fortran module files
|
||||
*.mod
|
||||
*.smod
|
||||
|
||||
# Compiled Static libraries
|
||||
*.lai
|
||||
*.la
|
||||
*.a
|
||||
*.lib
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
|
||||
/Binaries
|
||||
/Intermediate
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
{
|
||||
"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"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
[/Script/Ayon.AyonSettings]
|
||||
FolderColor=(R=91,G=197,B=220,A=255)
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
[FilterPlugin]
|
||||
; This section lists additional files which will be packaged along with your plugin. Paths should be listed relative to the root plugin directory, and
|
||||
; may include "...", "*", and "?" wildcards to match directories, files, and individual characters respectively.
|
||||
;
|
||||
; Examples:
|
||||
; /README.txt
|
||||
; /Extras/...
|
||||
; /Binaries/ThirdParty/*.dll
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
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()
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
# 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.
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 2.3 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 721 B |
Binary file not shown.
|
Before Width: | Height: | Size: 16 KiB |
|
|
@ -1,61 +0,0 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
|
||||
using UnrealBuildTool;
|
||||
|
||||
public class Ayon : ModuleRules
|
||||
{
|
||||
public Ayon(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
|
||||
|
||||
PublicIncludePaths.AddRange(
|
||||
new string[]
|
||||
{
|
||||
// ... add public include paths required here ...
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
PrivateIncludePaths.AddRange(
|
||||
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[]
|
||||
{
|
||||
"GameProjectGeneration",
|
||||
"Projects",
|
||||
"InputCore",
|
||||
"UnrealEd",
|
||||
"LevelEditor",
|
||||
"CoreUObject",
|
||||
"Engine",
|
||||
"Slate",
|
||||
"SlateCore",
|
||||
"AssetTools"
|
||||
// ... add private dependencies that you statically link with here ...
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
DynamicallyLoadedModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
// ... add any modules that your module loads dynamically here ...
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,156 +0,0 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
#include "Ayon.h"
|
||||
|
||||
#include "ISettingsContainer.h"
|
||||
#include "ISettingsModule.h"
|
||||
#include "ISettingsSection.h"
|
||||
#include "LevelEditor.h"
|
||||
#include "AyonPythonBridge.h"
|
||||
#include "AyonSettings.h"
|
||||
#include "AyonStyle.h"
|
||||
#include "Modules/ModuleManager.h"
|
||||
|
||||
|
||||
static const FName AyonTabName("Ayon");
|
||||
|
||||
#define LOCTEXT_NAMESPACE "FAyonModule"
|
||||
|
||||
// This function is triggered when the plugin is staring up
|
||||
void FAyonModule::StartupModule()
|
||||
{
|
||||
if (!IsRunningCommandlet()) {
|
||||
FAyonStyle::Initialize();
|
||||
FAyonStyle::SetIcon("Logo", "ayon40");
|
||||
|
||||
// Create the Extender that will add content to the menu
|
||||
FLevelEditorModule& LevelEditorModule = FModuleManager::LoadModuleChecked<FLevelEditorModule>("LevelEditor");
|
||||
|
||||
TSharedPtr<FExtender> MenuExtender = MakeShareable(new FExtender());
|
||||
TSharedPtr<FExtender> ToolbarExtender = MakeShareable(new FExtender());
|
||||
|
||||
MenuExtender->AddMenuExtension(
|
||||
"LevelEditor",
|
||||
EExtensionHook::After,
|
||||
NULL,
|
||||
FMenuExtensionDelegate::CreateRaw(this, &FAyonModule::AddMenuEntry)
|
||||
);
|
||||
ToolbarExtender->AddToolBarExtension(
|
||||
"Settings",
|
||||
EExtensionHook::After,
|
||||
NULL,
|
||||
FToolBarExtensionDelegate::CreateRaw(this, &FAyonModule::AddToobarEntry));
|
||||
|
||||
|
||||
LevelEditorModule.GetMenuExtensibilityManager()->AddExtender(MenuExtender);
|
||||
LevelEditorModule.GetToolBarExtensibilityManager()->AddExtender(ToolbarExtender);
|
||||
|
||||
RegisterSettings();
|
||||
}
|
||||
}
|
||||
|
||||
void FAyonModule::ShutdownModule()
|
||||
{
|
||||
FAyonStyle::Shutdown();
|
||||
}
|
||||
|
||||
|
||||
void FAyonModule::AddMenuEntry(FMenuBuilder& MenuBuilder)
|
||||
{
|
||||
// Create Section
|
||||
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(FAyonStyle::GetStyleSetName(), "Ayon.Logo"),
|
||||
FUIAction(FExecuteAction::CreateRaw(this, &FAyonModule::MenuPopup))
|
||||
);
|
||||
|
||||
MenuBuilder.AddMenuEntry(
|
||||
FText::FromString("Tools dialog..."),
|
||||
FText::FromString("Pipeline tools dialog"),
|
||||
FSlateIcon(FAyonStyle::GetStyleSetName(), "Ayon.Logo"),
|
||||
FUIAction(FExecuteAction::CreateRaw(this, &FAyonModule::MenuDialog))
|
||||
);
|
||||
}
|
||||
MenuBuilder.EndSection();
|
||||
}
|
||||
|
||||
void FAyonModule::AddToobarEntry(FToolBarBuilder& ToolbarBuilder)
|
||||
{
|
||||
ToolbarBuilder.BeginSection(TEXT("Ayon"));
|
||||
{
|
||||
ToolbarBuilder.AddToolBarButton(
|
||||
FUIAction(
|
||||
FExecuteAction::CreateRaw(this, &FAyonModule::MenuPopup),
|
||||
NULL,
|
||||
FIsActionChecked()
|
||||
|
||||
),
|
||||
NAME_None,
|
||||
LOCTEXT("Ayon_label", "Ayon"),
|
||||
LOCTEXT("Ayon_tooltip", "Ayon Tools"),
|
||||
FSlateIcon(FAyonStyle::GetStyleSetName(), "Ayon.Logo")
|
||||
);
|
||||
}
|
||||
ToolbarBuilder.EndSection();
|
||||
}
|
||||
|
||||
void FAyonModule::RegisterSettings()
|
||||
{
|
||||
ISettingsModule& SettingsModule = FModuleManager::LoadModuleChecked<ISettingsModule>("Settings");
|
||||
|
||||
// Create the new category
|
||||
// TODO: After the movement of the plugin from the game to editor, it might be necessary to move this!
|
||||
ISettingsContainerPtr SettingsContainer = SettingsModule.GetContainer("Project");
|
||||
|
||||
UAyonSettings* Settings = GetMutableDefault<UAyonSettings>();
|
||||
|
||||
// Register the settings
|
||||
ISettingsSectionPtr SettingsSection = SettingsModule.RegisterSettings("Project", "Ayon", "General",
|
||||
LOCTEXT("RuntimeGeneralSettingsName",
|
||||
"General"),
|
||||
LOCTEXT("RuntimeGeneralSettingsDescription",
|
||||
"Base configuration for Open Pype Module"),
|
||||
Settings
|
||||
);
|
||||
|
||||
// Register the save handler to your settings, you might want to use it to
|
||||
// validate those or just act to settings changes.
|
||||
if (SettingsSection.IsValid())
|
||||
{
|
||||
SettingsSection->OnModified().BindRaw(this, &FAyonModule::HandleSettingsSaved);
|
||||
}
|
||||
}
|
||||
|
||||
bool FAyonModule::HandleSettingsSaved()
|
||||
{
|
||||
UAyonSettings* Settings = GetMutableDefault<UAyonSettings>();
|
||||
bool ResaveSettings = false;
|
||||
|
||||
// You can put any validation code in here and resave the settings in case an invalid
|
||||
// value has been entered
|
||||
|
||||
if (ResaveSettings)
|
||||
{
|
||||
Settings->SaveConfig();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void FAyonModule::MenuPopup()
|
||||
{
|
||||
UAyonPythonBridge* bridge = UAyonPythonBridge::Get();
|
||||
bridge->RunInPython_Popup();
|
||||
}
|
||||
|
||||
void FAyonModule::MenuDialog()
|
||||
{
|
||||
UAyonPythonBridge* bridge = UAyonPythonBridge::Get();
|
||||
bridge->RunInPython_Dialog();
|
||||
}
|
||||
|
||||
IMPLEMENT_MODULE(FAyonModule, Ayon)
|
||||
|
|
@ -1,114 +0,0 @@
|
|||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
#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,53 +0,0 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
#include "AyonLib.h"
|
||||
|
||||
#include "AssetViewUtils.h"
|
||||
#include "Misc/Paths.h"
|
||||
#include "Misc/ConfigCacheIni.h"
|
||||
#include "UObject/UnrealType.h"
|
||||
|
||||
/**
|
||||
* Sets color on folder icon on given path
|
||||
* @param InPath - path to folder
|
||||
* @param InFolderColor - color of the folder
|
||||
* @warning This color will appear only after Editor restart. Is there a better way?
|
||||
*/
|
||||
|
||||
bool UAyonLib::SetFolderColor(const FString& FolderPath, const FLinearColor& FolderColor, const bool& bForceAdd)
|
||||
{
|
||||
if (AssetViewUtils::DoesFolderExist(FolderPath))
|
||||
{
|
||||
const TSharedPtr<FLinearColor> LinearColor = MakeShared<FLinearColor>(FolderColor);
|
||||
|
||||
AssetViewUtils::SaveColor(FolderPath, LinearColor, true);
|
||||
UE_LOG(LogAssetData, Display, TEXT("A color {%s} has been set to folder \"%s\""), *LinearColor->ToString(),
|
||||
*FolderPath)
|
||||
return true;
|
||||
}
|
||||
|
||||
UE_LOG(LogAssetData, Display, TEXT("Setting a color {%s} to folder \"%s\" has failed! Directory doesn't exist!"),
|
||||
*FolderColor.ToString(), *FolderPath)
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all poperties on given object
|
||||
* @param cls - class
|
||||
* @return TArray of properties
|
||||
*/
|
||||
TArray<FString> UAyonLib::GetAllProperties(UClass* cls)
|
||||
{
|
||||
TArray<FString> Ret;
|
||||
if (cls != nullptr)
|
||||
{
|
||||
for (TFieldIterator<FProperty> It(cls); It; ++It)
|
||||
{
|
||||
FProperty* Property = *It;
|
||||
if (Property->HasAnyPropertyFlags(EPropertyFlags::CPF_Edit))
|
||||
{
|
||||
Ret.Add(Property->GetName());
|
||||
}
|
||||
}
|
||||
}
|
||||
return Ret;
|
||||
}
|
||||
|
|
@ -1,203 +0,0 @@
|
|||
// 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
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
// 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;
|
||||
}
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
// 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;
|
||||
};
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
// 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;
|
||||
}
|
||||
|
|
@ -1,70 +0,0 @@
|
|||
// 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;
|
||||
}
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
// 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());
|
||||
}
|
||||
|
|
@ -1,141 +0,0 @@
|
|||
// 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,203 +0,0 @@
|
|||
// 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 "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();
|
||||
|
||||
UOpenPypePublishInstance::UOpenPypePublishInstance(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, &UOpenPypePublishInstance::OnAssetCreated);
|
||||
AssetRegistryModule.Get().OnAssetRemoved().AddUObject(this, &UOpenPypePublishInstance::OnAssetRemoved);
|
||||
AssetRegistryModule.Get().OnAssetUpdated().AddUObject(this, &UOpenPypePublishInstance::OnAssetUpdated);
|
||||
|
||||
#ifdef WITH_EDITOR
|
||||
ColorOpenPypeDirs();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void UOpenPypePublishInstance::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<UOpenPypePublishInstance>(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 UOpenPypePublishInstance::OnAssetRemoved(const FAssetData& InAssetData)
|
||||
{
|
||||
if (Cast<UOpenPypePublishInstance>(InAssetData.GetAsset()) == nullptr)
|
||||
{
|
||||
if (AssetDataInternal.Contains(nullptr))
|
||||
{
|
||||
AssetDataInternal.Remove(nullptr);
|
||||
REMOVE_INVALID_ENTRIES(AssetDataInternal)
|
||||
}
|
||||
else
|
||||
{
|
||||
AssetDataExternal.Remove(nullptr);
|
||||
REMOVE_INVALID_ENTRIES(AssetDataExternal)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UOpenPypePublishInstance::OnAssetUpdated(const FAssetData& InAssetData)
|
||||
{
|
||||
REMOVE_INVALID_ENTRIES(AssetDataInternal);
|
||||
REMOVE_INVALID_ENTRIES(AssetDataExternal);
|
||||
}
|
||||
|
||||
bool UOpenPypePublishInstance::IsUnderSameDir(const UObject* InAsset) const
|
||||
{
|
||||
FString ThisLeft, ThisRight;
|
||||
this->GetPathName().Split(this->GetName(), &ThisLeft, &ThisRight);
|
||||
|
||||
return InAsset->GetPathName().StartsWith(ThisLeft);
|
||||
}
|
||||
|
||||
#ifdef WITH_EDITOR
|
||||
|
||||
void UOpenPypePublishInstance::ColorOpenPypeDirs()
|
||||
{
|
||||
FString PathName = this->GetPathName();
|
||||
|
||||
//Check whether the path contains the defined OpenPype folder
|
||||
if (!PathName.Contains(TEXT("OpenPype"))) return;
|
||||
|
||||
//Get the base path for open pype
|
||||
FString PathLeft, PathRight;
|
||||
PathName.Split(FString("OpenPype"), &PathLeft, &PathRight);
|
||||
|
||||
if (PathLeft.IsEmpty() || PathRight.IsEmpty())
|
||||
{
|
||||
UE_LOG(LogAssetData, Error, TEXT("Failed to retrieve the base OpenPype 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 UOpenPypePublishInstance::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 UOpenPypePublishInstance::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
|
||||
{
|
||||
Super::PostEditChangeProperty(PropertyChangedEvent);
|
||||
|
||||
if (PropertyChangedEvent.ChangeType == EPropertyChangeType::ValueSet &&
|
||||
PropertyChangedEvent.Property->GetFName() == GET_MEMBER_NAME_CHECKED(
|
||||
UOpenPypePublishInstance, 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 UOpenPypePublishInstance type assets are included
|
||||
for (const auto& Asset : AssetDataExternal)
|
||||
{
|
||||
if (Cast<UOpenPypePublishInstance>(Asset.Get()) != nullptr)
|
||||
{
|
||||
AssetDataExternal.Remove(Asset);
|
||||
return SendNotification("You are not allowed to add publish instances!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
class FAyonModule : public IModuleInterface
|
||||
{
|
||||
public:
|
||||
virtual void StartupModule() override;
|
||||
virtual void ShutdownModule() override;
|
||||
|
||||
private:
|
||||
void RegisterSettings();
|
||||
bool HandleSettingsSaved();
|
||||
|
||||
void AddMenuEntry(FMenuBuilder& MenuBuilder);
|
||||
void AddToobarEntry(FToolBarBuilder& ToolbarBuilder);
|
||||
void MenuPopup();
|
||||
void MenuDialog();
|
||||
};
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
// 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);
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
// 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;
|
||||
};
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
// 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,19 +0,0 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
#pragma once
|
||||
|
||||
#include "AyonLib.generated.h"
|
||||
|
||||
|
||||
UCLASS(Blueprintable)
|
||||
class AYON_API UAyonLib : public UBlueprintFunctionLibrary
|
||||
{
|
||||
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UFUNCTION(BlueprintCallable, Category = Python)
|
||||
static bool SetFolderColor(const FString& FolderPath, const FLinearColor& FolderColor,const bool& bForceAdd);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = Python)
|
||||
static TArray<FString> GetAllProperties(UClass* cls);
|
||||
};
|
||||
|
|
@ -1,103 +0,0 @@
|
|||
// 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,22 +0,0 @@
|
|||
// 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 "AyonPublishInstanceFactory.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class AYON_API UAyonPublishInstanceFactory : public UFactory
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
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,20 +0,0 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
#pragma once
|
||||
#include "AyonPythonBridge.generated.h"
|
||||
|
||||
UCLASS(Blueprintable)
|
||||
class UAyonPythonBridge : public UObject
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UFUNCTION(BlueprintCallable, Category = Python)
|
||||
static UAyonPythonBridge* Get();
|
||||
|
||||
UFUNCTION(BlueprintImplementableEvent, Category = Python)
|
||||
void RunInPython_Popup() const;
|
||||
|
||||
UFUNCTION(BlueprintImplementableEvent, Category = Python)
|
||||
void RunInPython_Dialog() const;
|
||||
|
||||
};
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
// 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);
|
||||
};
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
#pragma once
|
||||
#include "CoreMinimal.h"
|
||||
|
||||
class FSlateStyleSet;
|
||||
class ISlateStyle;
|
||||
|
||||
|
||||
class FAyonStyle
|
||||
{
|
||||
public:
|
||||
static void Initialize();
|
||||
static void Shutdown();
|
||||
static const ISlateStyle& Get();
|
||||
static FName GetStyleSetName();
|
||||
static FName GetContextName();
|
||||
|
||||
static void SetIcon(const FString& StyleName, const FString& ResourcePath);
|
||||
|
||||
private:
|
||||
static TUniquePtr< FSlateStyleSet > Create();
|
||||
static TUniquePtr< FSlateStyleSet > AyonStyleInstance;
|
||||
};
|
||||
|
|
@ -1,83 +0,0 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "AyonActionResult.generated.h"
|
||||
|
||||
/**
|
||||
* @brief This macro returns error code when is problem or does nothing when there is no problem.
|
||||
* @param ActionResult FAyon_ActionResult structure
|
||||
*/
|
||||
#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 should exists an web document where is mapped error code & what problem occured & how to repair it...
|
||||
*/
|
||||
UENUM()
|
||||
namespace EAyon_ActionResult
|
||||
{
|
||||
enum Type
|
||||
{
|
||||
Ok,
|
||||
ProjectNotCreated,
|
||||
ProjectNotLoaded,
|
||||
ProjectNotSaved,
|
||||
//....Here insert another values
|
||||
|
||||
//Do not remove!
|
||||
//Usable for looping through enum values
|
||||
__Last UMETA(Hidden)
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief This struct holds action result enum and optionally reason of fail
|
||||
*/
|
||||
USTRUCT()
|
||||
struct FAyon_ActionResult
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
/** @brief Default constructor usable when there is no problem */
|
||||
FAyon_ActionResult();
|
||||
|
||||
/**
|
||||
* @brief This constructor initializes variables & attempts to log when is error
|
||||
* @param InEnum Status
|
||||
*/
|
||||
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
|
||||
*/
|
||||
FAyon_ActionResult(const EAyon_ActionResult::Type& InEnum, const FText& InReason);
|
||||
|
||||
private:
|
||||
/** @brief Action status */
|
||||
EAyon_ActionResult::Type Status;
|
||||
|
||||
/** @brief Optional reason of fail */
|
||||
FText Reason;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Checks if there is problematic state
|
||||
* @return true when status is not equal to EAyon_ActionResult::Ok
|
||||
*/
|
||||
bool IsProblem() const;
|
||||
EAyon_ActionResult::Type& GetStatus();
|
||||
FText& GetReason();
|
||||
|
||||
private:
|
||||
void TryLog() const;
|
||||
};
|
||||
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
#pragma once
|
||||
|
||||
#include "GameProjectUtils.h"
|
||||
#include "Commandlets/AyonActionResult.h"
|
||||
#include "ProjectDescriptor.h"
|
||||
#include "Commandlets/Commandlet.h"
|
||||
#include "AyonGenerateProjectCommandlet.generated.h"
|
||||
|
||||
struct FProjectDescriptor;
|
||||
struct FProjectInformation;
|
||||
|
||||
/**
|
||||
* @brief Structure which parses command line parameters and generates FProjectInformation
|
||||
*/
|
||||
USTRUCT()
|
||||
struct FAyonGenerateProjectParams
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
private:
|
||||
FString CommandLineParams;
|
||||
TArray<FString> Tokens;
|
||||
TArray<FString> Switches;
|
||||
|
||||
public:
|
||||
FAyonGenerateProjectParams();
|
||||
FAyonGenerateProjectParams(const FString& CommandLineParams);
|
||||
|
||||
FProjectInformation GenerateUEProjectInformation() const;
|
||||
|
||||
private:
|
||||
FString TryGetToken(const int32 Index) const;
|
||||
FString GetProjectFileName() const;
|
||||
|
||||
bool IsSwitchPresent(const FString& Switch) const;
|
||||
};
|
||||
|
||||
UCLASS()
|
||||
class AYON_API UAyonGenerateProjectCommandlet : public UCommandlet
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
private:
|
||||
FProjectInformation ProjectInformation;
|
||||
FProjectDescriptor ProjectDescriptor;
|
||||
|
||||
public:
|
||||
UAyonGenerateProjectCommandlet();
|
||||
|
||||
virtual int32 Main(const FString& CommandLineParams) override;
|
||||
|
||||
private:
|
||||
FAyonGenerateProjectParams ParseParameters(const FString& Params) const;
|
||||
FAyon_ActionResult TryCreateProject() const;
|
||||
FAyon_ActionResult TryLoadProjectDescriptor();
|
||||
void AttachPluginsToProjectDescriptor();
|
||||
FAyon_ActionResult TrySave();
|
||||
};
|
||||
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
#pragma once
|
||||
|
||||
DEFINE_LOG_CATEGORY_STATIC(LogCommandletOPGenerateProject, Log, All);
|
||||
|
|
@ -1,103 +0,0 @@
|
|||
// 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.generated.h"
|
||||
|
||||
|
||||
UCLASS(Blueprintable)
|
||||
class AYON_API UOpenPypePublishInstance : 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 ColorOpenPypeDirs();
|
||||
|
||||
void SendNotification(const FString& Text) const;
|
||||
virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override;
|
||||
|
||||
#endif
|
||||
};
|
||||
|
|
@ -1 +0,0 @@
|
|||
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"
|
||||
|
|
@ -1 +0,0 @@
|
|||
cmd /k "BuildPlugin_4-27.bat"
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
/Saved
|
||||
/DerivedDataCache
|
||||
/Intermediate
|
||||
/Content
|
||||
/Config
|
||||
/Binaries
|
||||
/.idea
|
||||
/.vs
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
{
|
||||
"FileVersion": 3,
|
||||
"EngineAssociation": "4.27",
|
||||
"Category": "",
|
||||
"Description": "",
|
||||
"Plugins": [
|
||||
{
|
||||
"Name": "Ayon",
|
||||
"Enabled": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
# Prerequisites
|
||||
*.d
|
||||
|
||||
# Compiled Object files
|
||||
*.slo
|
||||
*.lo
|
||||
*.o
|
||||
*.obj
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
*.pch
|
||||
|
||||
# Compiled Dynamic libraries
|
||||
*.so
|
||||
*.dylib
|
||||
*.dll
|
||||
|
||||
# Fortran module files
|
||||
*.mod
|
||||
*.smod
|
||||
|
||||
# Compiled Static libraries
|
||||
*.lai
|
||||
*.la
|
||||
*.a
|
||||
*.lib
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
|
||||
/Binaries
|
||||
/Intermediate
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
{
|
||||
"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/",
|
||||
"CanContainContent": true,
|
||||
"EngineVersion": "5.0",
|
||||
"IsExperimentalVersion": false,
|
||||
"Installed": true,
|
||||
"Modules": [
|
||||
{
|
||||
"Name": "Ayon",
|
||||
"Type": "Editor",
|
||||
"LoadingPhase": "Default"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
[/Script/Ayon.AyonSettings]
|
||||
FolderColor=(R=91,G=197,B=220,A=255)
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
[FilterPlugin]
|
||||
; This section lists additional files which will be packaged along with your plugin. Paths should be listed relative to the root plugin directory, and
|
||||
; may include "...", "*", and "?" wildcards to match directories, files, and individual characters respectively.
|
||||
;
|
||||
; Examples:
|
||||
; /README.txt
|
||||
; /Extras/...
|
||||
; /Binaries/ThirdParty/*.dll
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
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()
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
# 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.
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 2.3 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 721 B |
Binary file not shown.
|
Before Width: | Height: | Size: 16 KiB |
|
|
@ -1,65 +0,0 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
|
||||
using UnrealBuildTool;
|
||||
|
||||
public class Ayon : ModuleRules
|
||||
{
|
||||
public Ayon(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
DefaultBuildSettings = BuildSettingsVersion.V2;
|
||||
bLegacyPublicIncludePaths = false;
|
||||
ShadowVariableWarningLevel = WarningLevel.Error;
|
||||
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
|
||||
//IncludeOrderVersion = EngineIncludeOrderVersion.Unreal5_0;
|
||||
|
||||
PublicIncludePaths.AddRange(
|
||||
new string[] {
|
||||
// ... add public include paths required here ...
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
PrivateIncludePaths.AddRange(
|
||||
new string[] {
|
||||
// ... add other private include paths required here ...
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
PublicDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"Core",
|
||||
"CoreUObject"
|
||||
// ... add other public dependencies that you statically link with here ...
|
||||
}
|
||||
);
|
||||
|
||||
PrivateDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"GameProjectGeneration",
|
||||
"Projects",
|
||||
"InputCore",
|
||||
"EditorFramework",
|
||||
"UnrealEd",
|
||||
"ToolMenus",
|
||||
"LevelEditor",
|
||||
"CoreUObject",
|
||||
"Engine",
|
||||
"Slate",
|
||||
"SlateCore",
|
||||
"AssetTools"
|
||||
// ... add private dependencies that you statically link with here ...
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
DynamicallyLoadedModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
// ... add any modules that your module loads dynamically here ...
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,139 +0,0 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
#include "Ayon.h"
|
||||
|
||||
#include "ISettingsContainer.h"
|
||||
#include "ISettingsModule.h"
|
||||
#include "ISettingsSection.h"
|
||||
#include "AyonStyle.h"
|
||||
#include "AyonCommands.h"
|
||||
#include "AyonPythonBridge.h"
|
||||
#include "AyonSettings.h"
|
||||
#include "ToolMenus.h"
|
||||
|
||||
|
||||
static const FName AyonTabName("Ayon");
|
||||
|
||||
#define LOCTEXT_NAMESPACE "FAyonModule"
|
||||
|
||||
// This function is triggered when the plugin is staring up
|
||||
void FAyonModule::StartupModule()
|
||||
{
|
||||
FAyonStyle::Initialize();
|
||||
FAyonStyle::ReloadTextures();
|
||||
FAyonCommands::Register();
|
||||
|
||||
PluginCommands = MakeShareable(new FUICommandList);
|
||||
|
||||
PluginCommands->MapAction(
|
||||
FAyonCommands::Get().AyonTools,
|
||||
FExecuteAction::CreateRaw(this, &FAyonModule::MenuPopup),
|
||||
FCanExecuteAction());
|
||||
PluginCommands->MapAction(
|
||||
FAyonCommands::Get().AyonToolsDialog,
|
||||
FExecuteAction::CreateRaw(this, &FAyonModule::MenuDialog),
|
||||
FCanExecuteAction());
|
||||
|
||||
UToolMenus::RegisterStartupCallback(
|
||||
FSimpleMulticastDelegate::FDelegate::CreateRaw(this, &FAyonModule::RegisterMenus));
|
||||
|
||||
RegisterSettings();
|
||||
}
|
||||
|
||||
void FAyonModule::ShutdownModule()
|
||||
{
|
||||
UToolMenus::UnRegisterStartupCallback(this);
|
||||
|
||||
UToolMenus::UnregisterOwner(this);
|
||||
|
||||
FAyonStyle::Shutdown();
|
||||
|
||||
FAyonCommands::Unregister();
|
||||
}
|
||||
|
||||
|
||||
void FAyonModule::RegisterSettings()
|
||||
{
|
||||
ISettingsModule& SettingsModule = FModuleManager::LoadModuleChecked<ISettingsModule>("Settings");
|
||||
|
||||
// Create the new category
|
||||
// TODO: After the movement of the plugin from the game to editor, it might be necessary to move this!
|
||||
ISettingsContainerPtr SettingsContainer = SettingsModule.GetContainer("Project");
|
||||
|
||||
UAyonSettings* Settings = GetMutableDefault<UAyonSettings>();
|
||||
|
||||
// Register the settings
|
||||
ISettingsSectionPtr SettingsSection = SettingsModule.RegisterSettings("Project", "Ayon", "General",
|
||||
LOCTEXT("RuntimeGeneralSettingsName",
|
||||
"General"),
|
||||
LOCTEXT("RuntimeGeneralSettingsDescription",
|
||||
"Base configuration for Open Pype Module"),
|
||||
Settings
|
||||
);
|
||||
|
||||
// Register the save handler to your settings, you might want to use it to
|
||||
// validate those or just act to settings changes.
|
||||
if (SettingsSection.IsValid())
|
||||
{
|
||||
SettingsSection->OnModified().BindRaw(this, &FAyonModule::HandleSettingsSaved);
|
||||
}
|
||||
}
|
||||
|
||||
bool FAyonModule::HandleSettingsSaved()
|
||||
{
|
||||
UAyonSettings* Settings = GetMutableDefault<UAyonSettings>();
|
||||
bool ResaveSettings = false;
|
||||
|
||||
// You can put any validation code in here and resave the settings in case an invalid
|
||||
// value has been entered
|
||||
|
||||
if (ResaveSettings)
|
||||
{
|
||||
Settings->SaveConfig();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void FAyonModule::RegisterMenus()
|
||||
{
|
||||
// Owner will be used for cleanup in call to UToolMenus::UnregisterOwner
|
||||
FToolMenuOwnerScoped OwnerScoped(this);
|
||||
|
||||
{
|
||||
UToolMenu* Menu = UToolMenus::Get()->ExtendMenu("LevelEditor.MainMenu.Tools");
|
||||
{
|
||||
// FToolMenuSection& Section = Menu->FindOrAddSection("Ayon");
|
||||
FToolMenuSection& Section = Menu->AddSection(
|
||||
"Ayon",
|
||||
TAttribute<FText>(FText::FromString("Ayon")),
|
||||
FToolMenuInsert("Programming", EToolMenuInsertType::Before)
|
||||
);
|
||||
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(FAyonCommands::Get().AyonTools));
|
||||
Entry.SetCommandList(PluginCommands);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FAyonModule::MenuPopup()
|
||||
{
|
||||
UAyonPythonBridge* bridge = UAyonPythonBridge::Get();
|
||||
bridge->RunInPython_Popup();
|
||||
}
|
||||
|
||||
void FAyonModule::MenuDialog()
|
||||
{
|
||||
UAyonPythonBridge* bridge = UAyonPythonBridge::Get();
|
||||
bridge->RunInPython_Dialog();
|
||||
}
|
||||
|
||||
IMPLEMENT_MODULE(FAyonModule, Ayon)
|
||||
|
|
@ -1,113 +0,0 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#include "AyonAssetContainer.h"
|
||||
#include "AssetRegistry/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.ObjectPath.ToString();
|
||||
UE_LOG(LogTemp, Log, TEXT("asset name %s"), *assetFName);
|
||||
// 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 != "AssetContainer")
|
||||
{
|
||||
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.ObjectPath.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 != "AssetContainer")
|
||||
{
|
||||
// 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.ObjectPath.ToString();
|
||||
|
||||
// split path
|
||||
assetPath.ParseIntoArray(split, TEXT(" "), true);
|
||||
|
||||
FString assetDir = FPackageName::GetLongPackagePath(*split[1]);
|
||||
if (assetDir.StartsWith(*selfDir))
|
||||
{
|
||||
// exclude self
|
||||
if (assetFName != "AssetContainer")
|
||||
{
|
||||
|
||||
assets.Remove(str);
|
||||
assets.Add(assetPath);
|
||||
assetsData.Remove(AssetData);
|
||||
// UE_LOG(LogTemp, Warning, TEXT("%s: asset renamed %s"), *lpp, *str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
#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,13 +0,0 @@
|
|||
// 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,51 +0,0 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
#include "AyonLib.h"
|
||||
|
||||
#include "AssetViewUtils.h"
|
||||
#include "UObject/UnrealType.h"
|
||||
|
||||
/**
|
||||
* Sets color on folder icon on given path
|
||||
* @param InPath - path to folder
|
||||
* @param InFolderColor - color of the folder
|
||||
* @warning This color will appear only after Editor restart. Is there a better way?
|
||||
*/
|
||||
|
||||
bool UAyonLib::SetFolderColor(const FString& FolderPath, const FLinearColor& FolderColor, const bool& bForceAdd)
|
||||
{
|
||||
if (AssetViewUtils::DoesFolderExist(FolderPath))
|
||||
{
|
||||
const TSharedPtr<FLinearColor> LinearColor = MakeShared<FLinearColor>(FolderColor);
|
||||
|
||||
AssetViewUtils::SaveColor(FolderPath, LinearColor, true);
|
||||
UE_LOG(LogAssetData, Display, TEXT("A color {%s} has been set to folder \"%s\""), *LinearColor->ToString(),
|
||||
*FolderPath)
|
||||
return true;
|
||||
}
|
||||
|
||||
UE_LOG(LogAssetData, Display, TEXT("Setting a color {%s} to folder \"%s\" has failed! Directory doesn't exist!"),
|
||||
*FolderColor.ToString(), *FolderPath)
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all poperties on given object
|
||||
* @param cls - class
|
||||
* @return TArray of properties
|
||||
*/
|
||||
TArray<FString> UAyonLib::GetAllProperties(UClass* cls)
|
||||
{
|
||||
TArray<FString> Ret;
|
||||
if (cls != nullptr)
|
||||
{
|
||||
for (TFieldIterator<FProperty> It(cls); It; ++It)
|
||||
{
|
||||
FProperty* Property = *It;
|
||||
if (Property->HasAnyPropertyFlags(EPropertyFlags::CPF_Edit))
|
||||
{
|
||||
Ret.Add(Property->GetName());
|
||||
}
|
||||
}
|
||||
}
|
||||
return Ret;
|
||||
}
|
||||
|
|
@ -1,204 +0,0 @@
|
|||
// 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
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
// 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;
|
||||
}
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
// 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;
|
||||
};
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
// 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;
|
||||
}
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
// 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;
|
||||
}
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
// 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());
|
||||
}
|
||||
|
|
@ -1,140 +0,0 @@
|
|||
// 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,204 +0,0 @@
|
|||
// 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 "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();
|
||||
|
||||
UOpenPypePublishInstance::UOpenPypePublishInstance(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, &UOpenPypePublishInstance::OnAssetCreated);
|
||||
AssetRegistryModule.Get().OnAssetRemoved().AddUObject(this, &UOpenPypePublishInstance::OnAssetRemoved);
|
||||
AssetRegistryModule.Get().OnAssetUpdated().AddUObject(this, &UOpenPypePublishInstance::OnAssetUpdated);
|
||||
|
||||
#ifdef WITH_EDITOR
|
||||
ColorOpenPypeDirs();
|
||||
#endif
|
||||
}
|
||||
|
||||
void UOpenPypePublishInstance::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<UOpenPypePublishInstance>(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 UOpenPypePublishInstance::OnAssetRemoved(const FAssetData& InAssetData)
|
||||
{
|
||||
if (Cast<UOpenPypePublishInstance>(InAssetData.GetAsset()) == nullptr)
|
||||
{
|
||||
if (AssetDataInternal.Contains(nullptr))
|
||||
{
|
||||
AssetDataInternal.Remove(nullptr);
|
||||
REMOVE_INVALID_ENTRIES(AssetDataInternal)
|
||||
}
|
||||
else
|
||||
{
|
||||
AssetDataExternal.Remove(nullptr);
|
||||
REMOVE_INVALID_ENTRIES(AssetDataExternal)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UOpenPypePublishInstance::OnAssetUpdated(const FAssetData& InAssetData)
|
||||
{
|
||||
REMOVE_INVALID_ENTRIES(AssetDataInternal);
|
||||
REMOVE_INVALID_ENTRIES(AssetDataExternal);
|
||||
}
|
||||
|
||||
bool UOpenPypePublishInstance::IsUnderSameDir(const UObject* InAsset) const
|
||||
{
|
||||
FString ThisLeft, ThisRight;
|
||||
this->GetPathName().Split(this->GetName(), &ThisLeft, &ThisRight);
|
||||
|
||||
return InAsset->GetPathName().StartsWith(ThisLeft);
|
||||
}
|
||||
|
||||
#ifdef WITH_EDITOR
|
||||
|
||||
void UOpenPypePublishInstance::ColorOpenPypeDirs()
|
||||
{
|
||||
FString PathName = this->GetPathName();
|
||||
|
||||
//Check whether the path contains the defined OpenPype folder
|
||||
if (!PathName.Contains(TEXT("OpenPype"))) return;
|
||||
|
||||
//Get the base path for open pype
|
||||
FString PathLeft, PathRight;
|
||||
PathName.Split(FString("OpenPype"), &PathLeft, &PathRight);
|
||||
|
||||
if (PathLeft.IsEmpty() || PathRight.IsEmpty())
|
||||
{
|
||||
UE_LOG(LogAssetData, Error, TEXT("Failed to retrieve the base OpenPype 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 UOpenPypeSettings
|
||||
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 UOpenPypePublishInstance::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 UOpenPypePublishInstance::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
|
||||
{
|
||||
Super::PostEditChangeProperty(PropertyChangedEvent);
|
||||
|
||||
if (PropertyChangedEvent.ChangeType == EPropertyChangeType::ValueSet &&
|
||||
PropertyChangedEvent.Property->GetFName() == GET_MEMBER_NAME_CHECKED(
|
||||
UOpenPypePublishInstance, 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 UOpenPypePublishInstance type assets are included
|
||||
for (const auto& Asset : AssetDataExternal)
|
||||
{
|
||||
if (Cast<UOpenPypePublishInstance>(Asset.Get()) != nullptr)
|
||||
{
|
||||
AssetDataExternal.Remove(Asset);
|
||||
return SendNotification("You are not allowed to add publish instances!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
|
||||
|
||||
class FAyonModule : public IModuleInterface
|
||||
{
|
||||
public:
|
||||
virtual void StartupModule() override;
|
||||
virtual void ShutdownModule() override;
|
||||
|
||||
private:
|
||||
void RegisterMenus();
|
||||
void RegisterSettings();
|
||||
bool HandleSettingsSaved();
|
||||
|
||||
void MenuPopup();
|
||||
void MenuDialog();
|
||||
|
||||
private:
|
||||
TSharedPtr<class FUICommandList> PluginCommands;
|
||||
};
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
// 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 "AssetRegistry/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);
|
||||
};
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
// 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;
|
||||
};
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
// 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,13 +0,0 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
#pragma once
|
||||
|
||||
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,19 +0,0 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
#pragma once
|
||||
|
||||
#include "AyonLib.generated.h"
|
||||
|
||||
|
||||
UCLASS(Blueprintable)
|
||||
class AYON_API UAyonLib : public UBlueprintFunctionLibrary
|
||||
{
|
||||
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UFUNCTION(BlueprintCallable, Category = Python)
|
||||
static bool SetFolderColor(const FString& FolderPath, const FLinearColor& FolderColor,const bool& bForceAdd);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = Python)
|
||||
static TArray<FString> GetAllProperties(UClass* cls);
|
||||
};
|
||||
|
|
@ -1,104 +0,0 @@
|
|||
// 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,22 +0,0 @@
|
|||
// 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 "AyonPublishInstanceFactory.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class AYON_API UAyonPublishInstanceFactory : public UFactory
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
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,20 +0,0 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
#pragma once
|
||||
#include "AyonPythonBridge.generated.h"
|
||||
|
||||
UCLASS(Blueprintable)
|
||||
class UAyonPythonBridge : public UObject
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UFUNCTION(BlueprintCallable, Category = Python)
|
||||
static UAyonPythonBridge* Get();
|
||||
|
||||
UFUNCTION(BlueprintImplementableEvent, Category = Python)
|
||||
void RunInPython_Popup() const;
|
||||
|
||||
UFUNCTION(BlueprintImplementableEvent, Category = Python)
|
||||
void RunInPython_Dialog() const;
|
||||
|
||||
};
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/Object.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);
|
||||
};
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
#pragma once
|
||||
#include "CoreMinimal.h"
|
||||
#include "Styling/SlateStyle.h"
|
||||
|
||||
class FAyonStyle
|
||||
{
|
||||
public:
|
||||
static void Initialize();
|
||||
static void Shutdown();
|
||||
static void ReloadTextures();
|
||||
static const ISlateStyle& Get();
|
||||
static FName GetStyleSetName();
|
||||
|
||||
|
||||
private:
|
||||
static TSharedRef< class FSlateStyleSet > Create();
|
||||
static TSharedPtr< class FSlateStyleSet > AyonStyleInstance;
|
||||
};
|
||||
|
|
@ -1,83 +0,0 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "AyonActionResult.generated.h"
|
||||
|
||||
/**
|
||||
* @brief This macro returns error code when is problem or does nothing when there is no problem.
|
||||
* @param ActionResult FAyon_ActionResult structure
|
||||
*/
|
||||
#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 should exists an web document where is mapped error code & what problem occured & how to repair it...
|
||||
*/
|
||||
UENUM()
|
||||
namespace EAyon_ActionResult
|
||||
{
|
||||
enum Type
|
||||
{
|
||||
Ok,
|
||||
ProjectNotCreated,
|
||||
ProjectNotLoaded,
|
||||
ProjectNotSaved,
|
||||
//....Here insert another values
|
||||
|
||||
//Do not remove!
|
||||
//Usable for looping through enum values
|
||||
__Last UMETA(Hidden)
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief This struct holds action result enum and optionally reason of fail
|
||||
*/
|
||||
USTRUCT()
|
||||
struct FAyon_ActionResult
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
/** @brief Default constructor usable when there is no problem */
|
||||
FAyon_ActionResult();
|
||||
|
||||
/**
|
||||
* @brief This constructor initializes variables & attempts to log when is error
|
||||
* @param InEnum Status
|
||||
*/
|
||||
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
|
||||
*/
|
||||
FAyon_ActionResult(const EAyon_ActionResult::Type& InEnum, const FText& InReason);
|
||||
|
||||
private:
|
||||
/** @brief Action status */
|
||||
EAyon_ActionResult::Type Status;
|
||||
|
||||
/** @brief Optional reason of fail */
|
||||
FText Reason;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Checks if there is problematic state
|
||||
* @return true when status is not equal to EAyon_ActionResult::Ok
|
||||
*/
|
||||
bool IsProblem() const;
|
||||
EAyon_ActionResult::Type& GetStatus();
|
||||
FText& GetReason();
|
||||
|
||||
private:
|
||||
void TryLog() const;
|
||||
};
|
||||
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "GameProjectUtils.h"
|
||||
#include "Commandlets/AyonActionResult.h"
|
||||
#include "ProjectDescriptor.h"
|
||||
#include "Commandlets/Commandlet.h"
|
||||
#include "AyonGenerateProjectCommandlet.generated.h"
|
||||
|
||||
struct FProjectDescriptor;
|
||||
struct FProjectInformation;
|
||||
|
||||
/**
|
||||
* @brief Structure which parses command line parameters and generates FProjectInformation
|
||||
*/
|
||||
USTRUCT()
|
||||
struct FAyonGenerateProjectParams
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
private:
|
||||
FString CommandLineParams;
|
||||
TArray<FString> Tokens;
|
||||
TArray<FString> Switches;
|
||||
|
||||
public:
|
||||
FAyonGenerateProjectParams();
|
||||
FAyonGenerateProjectParams(const FString& CommandLineParams);
|
||||
|
||||
FProjectInformation GenerateUEProjectInformation() const;
|
||||
|
||||
private:
|
||||
FString TryGetToken(const int32 Index) const;
|
||||
FString GetProjectFileName() const;
|
||||
|
||||
bool IsSwitchPresent(const FString& Switch) const;
|
||||
};
|
||||
|
||||
UCLASS()
|
||||
class AYON_API UAyonGenerateProjectCommandlet : public UCommandlet
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
private:
|
||||
FProjectInformation ProjectInformation;
|
||||
FProjectDescriptor ProjectDescriptor;
|
||||
|
||||
public:
|
||||
UAyonGenerateProjectCommandlet();
|
||||
|
||||
virtual int32 Main(const FString& CommandLineParams) override;
|
||||
|
||||
private:
|
||||
FAyonGenerateProjectParams ParseParameters(const FString& Params) const;
|
||||
FAyon_ActionResult TryCreateProject() const;
|
||||
FAyon_ActionResult TryLoadProjectDescriptor();
|
||||
void AttachPluginsToProjectDescriptor();
|
||||
FAyon_ActionResult TrySave();
|
||||
};
|
||||
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
// Copyright 2023, Ayon, All rights reserved.
|
||||
#pragma once
|
||||
|
||||
DEFINE_LOG_CATEGORY_STATIC(LogCommandletAyonGenerateProject, Log, All);
|
||||
|
|
@ -1,104 +0,0 @@
|
|||
// 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.generated.h"
|
||||
|
||||
|
||||
UCLASS(Blueprintable)
|
||||
class AYON_API UOpenPypePublishInstance : 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 ColorOpenPypeDirs();
|
||||
|
||||
void SendNotification(const FString& Text) const;
|
||||
virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override;
|
||||
|
||||
#endif
|
||||
};
|
||||
|
|
@ -1 +0,0 @@
|
|||
"C:\Program Files\Epic Games\UE_5.0\Engine\Build\BatchFiles\RunUAT.bat" BuildPlugin -plugin="D:\OpenPype\openpype\hosts\unreal\integration\UE_5.0\Ayon\Ayon.uplugin" -Package="D:\BuiltPlugins\5.0"
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue