🚚 move unreal plugin to separate repository

This commit is contained in:
Ondrej Samohel 2023-05-17 12:20:43 +02:00
parent c85ebbfac2
commit 9112b87ba6
No known key found for this signature in database
GPG key ID: 02376E18990A97C6
125 changed files with 0 additions and 5525 deletions

View file

@ -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.

View 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

View file

@ -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"
}
]
}

View file

@ -1,2 +0,0 @@
[/Script/Ayon.AyonSettings]
FolderColor=(R=91,G=197,B=220,A=255)

View file

@ -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

View file

@ -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()

View file

@ -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

View file

@ -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 ...
}
);
}
}

View file

@ -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)

View file

@ -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);
}
}
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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

View file

@ -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;
}

View file

@ -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;
};

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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());
}

View file

@ -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;
}

View file

@ -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

View file

@ -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();
};

View file

@ -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);
};

View file

@ -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;
};

View file

@ -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";
}

View file

@ -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);
};

View file

@ -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
};

View file

@ -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;
};

View file

@ -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;
};

View file

@ -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);
};

View file

@ -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;
};

View file

@ -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;
};

View file

@ -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();
};

View file

@ -1,4 +0,0 @@
// Copyright 2023, Ayon, All rights reserved.
#pragma once
DEFINE_LOG_CATEGORY_STATIC(LogCommandletOPGenerateProject, Log, All);

View file

@ -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
};

View file

@ -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"

View file

@ -1 +0,0 @@
cmd /k "BuildPlugin_4-27.bat"

View file

@ -1,8 +0,0 @@
/Saved
/DerivedDataCache
/Intermediate
/Content
/Config
/Binaries
/.idea
/.vs

View file

@ -1,12 +0,0 @@
{
"FileVersion": 3,
"EngineAssociation": "4.27",
"Category": "",
"Description": "",
"Plugins": [
{
"Name": "Ayon",
"Enabled": true
}
]
}

View 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

View file

@ -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"
}
]
}

View file

@ -1,2 +0,0 @@
[/Script/Ayon.AyonSettings]
FolderColor=(R=91,G=197,B=220,A=255)

View file

@ -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

View file

@ -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()

View file

@ -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

View file

@ -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 ...
}
);
}
}

View file

@ -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)

View file

@ -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);
}
}
}

View file

@ -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;
}

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -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;
}

View file

@ -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;
};

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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());
}

View file

@ -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;
}

View file

@ -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

View file

@ -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;
};

View file

@ -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);
};

View file

@ -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;
};

View file

@ -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;
};

View file

@ -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";
}

View file

@ -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);
};

View file

@ -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
};

View file

@ -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;
};

View file

@ -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;
};

View file

@ -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);
};

View file

@ -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;
};

View file

@ -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;
};

View file

@ -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();
};

View file

@ -1,4 +0,0 @@
// Copyright 2023, Ayon, All rights reserved.
#pragma once
DEFINE_LOG_CATEGORY_STATIC(LogCommandletAyonGenerateProject, Log, All);

View file

@ -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
};

View file

@ -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"

View file

@ -1 +0,0 @@
cmd /k "BuildPlugin_5-0.bat"

View file

@ -1,41 +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
/Saved
/DerivedDataCache
/Intermediate
/Binaries
/Content
/Config
/.idea
/.vs

View file

@ -1,20 +0,0 @@
{
"FileVersion": 3,
"EngineAssociation": "5.0",
"Category": "",
"Description": "",
"Plugins": [
{
"Name": "ModelingToolsEditorMode",
"Enabled": true,
"TargetAllowList": [
"Editor"
]
},
{
"Name": "Ayon",
"Enabled": true,
"Type": "Editor"
}
]
}

View 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

View file

@ -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"
}
]
}

View file

@ -1,2 +0,0 @@
[/Script/Ayon.AyonSettings]
FolderColor=(R=91,G=197,B=220,A=255)

View file

@ -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

View file

@ -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()

View file

@ -1,3 +0,0 @@
# Ayon Unreal Integration plugin - UE 5.1
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

View file

@ -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 ...
}
);
}
}

View file

@ -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)

View file

@ -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.GetObjectPathString();
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.GetObjectPathString();
// 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.GetObjectPathString();
// 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);
}
}
}

View file

@ -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;
}

View file

@ -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

View file

@ -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;
}

View file

@ -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.GetSoftObjectPath().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

View file

@ -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;
}

Some files were not shown because too many files have changed in this diff Show more