Lua向C#逻辑迁移 一期 #13

将整个插件代码上传
This commit is contained in:
2025-10-26 21:48:39 +08:00
parent 56994b3927
commit 648386cd73
785 changed files with 53683 additions and 2 deletions

View File

@ -0,0 +1,31 @@
#include "CSAssetTypeAction_CSBlueprint.h"
#include "TypeGenerator/CSBlueprint.h"
UClass* FCSAssetTypeAction_CSBlueprint::GetSupportedClass() const
{
return UCSBlueprint::StaticClass();
}
#if ENGINE_MAJOR_VERSION * 100 + ENGINE_MINOR_VERSION < 505
void FCSAssetTypeAction_CSBlueprint::OpenAssetEditor(const TArray<UObject*>& InObjects, const EAssetTypeActivationOpenedMethod OpenedMethod, TSharedPtr<IToolkitHost> EditWithinLevelEditor)
#else
void FCSAssetTypeAction_CSBlueprint::OpenAssetEditor(const TArray<UObject*>& InObjects, TSharedPtr<class IToolkitHost> EditWithinLevelEditor)
#endif
{
UCSBlueprint* Blueprint = Cast<UCSBlueprint>(InObjects[0]);
// TODO: Add support for opening the file in an external editor.
// Currently Rider doesn't support opening files from the command line as it opens the file in every instance of Rider, even if I have specified the solution to open it in.
// A ticket has been created to try to get it fixed.
}
bool FCSAssetTypeAction_CSBlueprint::SupportsOpenedMethod(const EAssetTypeActivationOpenedMethod OpenedMethod) const
{
// Always return false for now. Same issue as above.
return false;
}
FText FCSAssetTypeAction_CSBlueprint::GetName() const
{
return FText::FromString(FString::Printf(TEXT("C# Class")));
}

View File

@ -0,0 +1,17 @@
#pragma once
#include "AssetTypeActions/AssetTypeActions_Blueprint.h"
class FCSAssetTypeAction_CSBlueprint : public FAssetTypeActions_Blueprint
{
public:
// IAssetTypeActions interface
virtual UClass* GetSupportedClass() const override;
#if ENGINE_MAJOR_VERSION * 100 + ENGINE_MINOR_VERSION < 505
virtual void OpenAssetEditor(const TArray<UObject*>& InObjects, const EAssetTypeActivationOpenedMethod OpenedMethod, TSharedPtr<IToolkitHost> EditWithinLevelEditor = TSharedPtr<IToolkitHost>()) override;
#else
virtual void OpenAssetEditor(const TArray<UObject*>& InObjects, TSharedPtr<class IToolkitHost> EditWithinLevelEditor = TSharedPtr<IToolkitHost>()) override;
#endif
virtual bool SupportsOpenedMethod(const EAssetTypeActivationOpenedMethod OpenedMethod) const override;
virtual FText GetName() const override;
// End of IAssetTypeActions interface
};

View File

@ -0,0 +1,57 @@
#include "CSStyle.h"
#include "Framework/Application/SlateApplication.h"
#include "Styling/SlateStyleRegistry.h"
#include "Interfaces/IPluginManager.h"
#include "Styling/SlateStyleMacros.h"
#define RootToContentDir Style->RootToContentDir
TSharedPtr<FSlateStyleSet> FCSStyle::StyleInstance = nullptr;
void FCSStyle::Initialize()
{
if (!StyleInstance.IsValid())
{
StyleInstance = Create();
FSlateStyleRegistry::RegisterSlateStyle(*StyleInstance);
}
}
void FCSStyle::Shutdown()
{
FSlateStyleRegistry::UnRegisterSlateStyle(*StyleInstance);
ensure(StyleInstance.IsUnique());
StyleInstance.Reset();
}
void FCSStyle::ReloadTextures()
{
if (FSlateApplication::IsInitialized())
{
FSlateApplication::Get().GetRenderer()->ReloadTextureResources();
}
}
const ISlateStyle& FCSStyle::Get()
{
return *StyleInstance;
}
FName FCSStyle::GetStyleSetName()
{
static FName StyleSetName(TEXT("UnrealSharpStyle"));
return StyleSetName;
}
TSharedRef<FSlateStyleSet> FCSStyle::Create()
{
const FVector2D Icon40x40(40.0f, 40.0f);
TSharedRef<FSlateStyleSet> Style = MakeShareable(new FSlateStyleSet("UnrealSharpStyle"));
Style->SetContentRoot(IPluginManager::Get().FindPlugin(UE_PLUGIN_NAME)->GetBaseDir() / TEXT("Resources"));
Style->Set("UnrealSharp.Toolbar", new IMAGE_BRUSH(TEXT("Icon_Default_40x"), Icon40x40));
Style->Set("UnrealSharp.Toolbar.Modified", new IMAGE_BRUSH(TEXT("Icon_Modified_40x"), Icon40x40));
Style->Set("UnrealSharp.Toolbar.Fail", new IMAGE_BRUSH(TEXT("Icon_Fail_40x"), Icon40x40));
return Style;
}

View File

@ -0,0 +1,20 @@
#pragma once
class FCSStyle
{
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<FSlateStyleSet> StyleInstance;
};

View File

@ -0,0 +1,32 @@
#include "CSUnrealSharpEditorCommands.h"
#include "CSStyle.h"
#define LOCTEXT_NAMESPACE "FCSCommandsModule"
FCSUnrealSharpEditorCommands::FCSUnrealSharpEditorCommands() : TCommands<FCSUnrealSharpEditorCommands>(
TEXT("CSCommands"),
NSLOCTEXT("Contexts", "UnrealSharpCommands", "UnrealSharp"),
NAME_None,
FCSStyle::GetStyleSetName())
{
}
void FCSUnrealSharpEditorCommands::RegisterCommands()
{
UI_COMMAND(CreateNewProject, "Create C# Project", "Create a new C# project with all necessary dependencies and initial setup", EUserInterfaceActionType::Button, FInputChord());
UI_COMMAND(CompileManagedCode, "Force Compile C#", "Trigger a hot reload to recompile the project's C# code", EUserInterfaceActionType::Button, FInputChord(EKeys::F10, EModifierKey::Control | EModifierKey::Alt));
UI_COMMAND(ReloadManagedCode, "Force Reload Modules", "Reloads the built modules in case they were built externally (for example from your IDE)", EUserInterfaceActionType::Button, FInputChord(EKeys::F9, EModifierKey::Control | EModifierKey::Alt));
UI_COMMAND(RegenerateSolution, "Regenerate Solution", "Rebuild the C# solution file to reflect the latest project changes", EUserInterfaceActionType::Button, FInputChord());
UI_COMMAND(OpenSolution, "Open C# Solution", "Launch the project's C# solution file in the default IDE", EUserInterfaceActionType::Button, FInputChord());
UI_COMMAND(MergeManagedSlnAndNativeSln, "Merge Managed and Native Solution", "Merges the managed sln and native sln into one mixed.sln, coding in one IDE instance. This will create a new sln in the root folder of your project", EUserInterfaceActionType::Button, FInputChord());
UI_COMMAND(PackageProject, "Package Project", "Package the C# project to the archived directory", EUserInterfaceActionType::Button, FInputChord());
UI_COMMAND(OpenSettings, "Open Settings...", "Open the Editor Settings", EUserInterfaceActionType::Button, FInputChord());
UI_COMMAND(OpenDocumentation, "Open Documentation", "Open the Documentation website", EUserInterfaceActionType::Button, FInputChord());
UI_COMMAND(ReportBug, "Report a Bug", "Open the Issues Github page", EUserInterfaceActionType::Button, FInputChord());
UI_COMMAND(RefreshRuntimeGlue, "Refresh Runtime Glue", "Refresh the generated runtime glue such as the GameplayTags, AssetIds, AssetTypes, TraceChannel", EUserInterfaceActionType::Button, FInputChord());
UI_COMMAND(RepairComponents, "Repair Components", "Transfers data from the old component system to the new one. This tool is only relevant if you see double instances of the same component in your BPs.", EUserInterfaceActionType::Button, FInputChord());
}
#undef LOCTEXT_NAMESPACE

View File

@ -0,0 +1,25 @@
#pragma once
class FCSUnrealSharpEditorCommands : public TCommands<FCSUnrealSharpEditorCommands>
{
public:
FCSUnrealSharpEditorCommands();
// TCommands<> interface
virtual void RegisterCommands() override;
// End
TSharedPtr<FUICommandInfo> CreateNewProject;
TSharedPtr<FUICommandInfo> CompileManagedCode;
TSharedPtr<FUICommandInfo> ReloadManagedCode;
TSharedPtr<FUICommandInfo> RegenerateSolution;
TSharedPtr<FUICommandInfo> OpenSolution;
TSharedPtr<FUICommandInfo> MergeManagedSlnAndNativeSln;
TSharedPtr<FUICommandInfo> PackageProject;
TSharedPtr<FUICommandInfo> OpenSettings;
TSharedPtr<FUICommandInfo> OpenDocumentation;
TSharedPtr<FUICommandInfo> ReportBug;
TSharedPtr<FUICommandInfo> RefreshRuntimeGlue;
TSharedPtr<FUICommandInfo> RepairComponents;
};

View File

@ -0,0 +1,16 @@
#include "CSUnrealSharpEditorSettings.h"
UCSUnrealSharpEditorSettings::UCSUnrealSharpEditorSettings()
{
CategoryName = "Plugins";
}
FString UCSUnrealSharpEditorSettings::GetBuildConfigurationString() const
{
return StaticEnum<ECSBuildConfiguration>()->GetNameStringByValue(BuildConfiguration);
}
FString UCSUnrealSharpEditorSettings::GetLogVerbosityString() const
{
return StaticEnum<ECSLoggerVerbosity>()->GetNameStringByValue(LogVerbosity);
}

View File

@ -0,0 +1,75 @@
#pragma once
#include "CoreMinimal.h"
#include "Engine/DeveloperSettings.h"
#include "CSUnrealSharpEditorSettings.generated.h"
UENUM()
enum EAutomaticHotReloadMethod : uint8
{
// Automatically Hot Reloads when script changes are saved
OnScriptSave,
// Automatically Hot Reloads when the built .NET modules changed (build the C# project in your IDE and UnrealSharp will automatically reload)
OnModuleChange,
// Wait for the Editor to gain focus before Hot Reloading
OnEditorFocus,
// Will not Hot Reload automatically
Off,
};
UENUM()
enum ECSBuildConfiguration : uint8
{
Debug,
Release,
};
UENUM()
enum ECSLoggerVerbosity : uint8
{
// The most minimal output
Quiet,
// Relatively little output
Minimal,
// Standard output. This should be the default if verbosity level is not set
Normal,
// Relatively verbose, but not exhaustive
Detailed,
// The most verbose and informative verbosity
Diagnostic
};
UCLASS(config = EditorPerProjectUserSettings, meta = (DisplayName = "UnrealSharp Editor Settings"))
class UNREALSHARPEDITOR_API UCSUnrealSharpEditorSettings : public UDeveloperSettings
{
GENERATED_BODY()
public:
UCSUnrealSharpEditorSettings();
// Whether Hot Reload should automatically start on script save, gaining Editor focus, or not at all.
UPROPERTY(EditDefaultsOnly, config, Category = "UnrealSharp | Hot Reload")
TEnumAsByte<EAutomaticHotReloadMethod> AutomaticHotReloading = OnScriptSave;
// The build configuration to use when building the C# project in the editor.
UPROPERTY(EditDefaultsOnly, config, Category = "UnrealSharp | Hot Reload")
TEnumAsByte<ECSBuildConfiguration> BuildConfiguration = ECSBuildConfiguration::Debug;
// The verbosity level of the logs generated by MSBuild when building the C# project in the editor.
UPROPERTY(EditDefaultsOnly, config, Category = "UnrealSharp | Hot Reload")
TEnumAsByte<ECSLoggerVerbosity> LogVerbosity = ECSLoggerVerbosity::Normal;
// Should we suffix generated types' DisplayName with "TypeName (C#)"?
// Needs restart to take effect.
UPROPERTY(EditDefaultsOnly, config, Category = "UnrealSharp | Type Generation")
bool bSuffixGeneratedTypes = false;
FString GetBuildConfigurationString() const;
FString GetLogVerbosityString() const;
};

View File

@ -0,0 +1,49 @@
#pragma once
#include "CoreMinimal.h"
#include "EditorSubsystem.h"
#include "CSEditorSubsystem.generated.h"
UCLASS(Blueprintable, BlueprintType, Abstract)
class UCSEditorSubsystem : public UEditorSubsystem
{
GENERATED_BODY()
// USubsystem Begin
virtual void Initialize(FSubsystemCollectionBase& Collection) override
{
Super::Initialize(Collection);
K2_Initialize();
}
virtual void Deinitialize() override
{
Super::Deinitialize();
K2_Deinitialize();
}
virtual bool ShouldCreateSubsystem(UObject* Outer) const override
{
if (!Super::ShouldCreateSubsystem(Outer))
{
return false;
}
return K2_ShouldCreateSubsystem();
}
// End
protected:
UFUNCTION(BlueprintImplementableEvent, meta = (ScriptName = "ShouldCreateSubsystem"), Category = "Managed Subsystems")
bool K2_ShouldCreateSubsystem() const;
UFUNCTION(BlueprintImplementableEvent, meta = (ScriptName = "Initialize"), Category = "Managed Subsystems")
void K2_Initialize();
UFUNCTION(BlueprintImplementableEvent, meta = (ScriptName = "Deinitialize"), Category = "Managed Subsystems")
void K2_Deinitialize();
};

View File

@ -0,0 +1,35 @@
#include "CSPluginTemplateDescription.h"
#include "Interfaces/IPluginManager.h"
#include "UnrealSharpEditor/UnrealSharpEditor.h"
void FCSPluginTemplateDescription::OnPluginCreated(const TSharedPtr<IPlugin> NewPlugin)
{
FPluginTemplateDescription::OnPluginCreated(NewPlugin);
const FString ModuleName = FString::Printf(TEXT("Managed%s"), *NewPlugin->GetName());
const FString ProjectPath = NewPlugin->GetBaseDir() / "Script";
const FString GlueProjectName = FString::Printf(TEXT("%s.Glue"), *NewPlugin->GetName());
if (bRequiresGlue)
{
CreateCodeModule(GlueProjectName, ProjectPath, GlueProjectName, NewPlugin->GetBaseDir(), false);
}
CreateCodeModule(ModuleName, ProjectPath, GlueProjectName, NewPlugin->GetBaseDir(), bRequiresGlue);
}
void FCSPluginTemplateDescription::CreateCodeModule(const FString& ModuleName, const FString& ProjectPath,
const FString& GlueProjectName, const FString& PluginPath, const bool bIncludeGlueProject)
{
TMap<FString, FString> Arguments;
Arguments.Add(TEXT("GlueProjectName"), GlueProjectName);
if (!bIncludeGlueProject)
{
Arguments.Add(TEXT("SkipIncludeProjectGlue"), TEXT("true"));
}
FUnrealSharpEditorModule::Get().AddNewProject(ModuleName, ProjectPath, PluginPath, Arguments);
}

View File

@ -0,0 +1,26 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Features/IPluginsEditorFeature.h"
/**
*
*/
class UNREALSHARPEDITOR_API FCSPluginTemplateDescription final : public FPluginTemplateDescription
{
public:
FCSPluginTemplateDescription(FText InName, FText InDescription, FString InOnDiskPath, const bool InCanContainContent,
const EHostType::Type InModuleDescriptorType, const ELoadingPhase::Type InLoadingPhase = ELoadingPhase::Default, const bool InRequiresGlue = true)
: FPluginTemplateDescription(MoveTemp(InName), MoveTemp(InDescription), MoveTemp(InOnDiskPath), InCanContainContent, InModuleDescriptorType, InLoadingPhase), bRequiresGlue(InRequiresGlue)
{
}
virtual void OnPluginCreated(TSharedPtr<IPlugin> NewPlugin) override;
private:
static void CreateCodeModule(const FString& ModuleName, const FString& ProjectPath, const FString& GlueProjectName, const FString& PluginPath, bool bIncludeGlueProject);
bool bRequiresGlue;
};

View File

@ -0,0 +1,307 @@
#include "CSNewProjectWizard.h"
#include "CSManager.h"
#include "DesktopPlatformModule.h"
#include "IDesktopPlatform.h"
#include "Interfaces/IPluginManager.h"
#include "Runtime/AppFramework/Public/Widgets/Workflow/SWizard.h"
#include "UnrealSharpEditor/UnrealSharpEditor.h"
#include "UnrealSharpProcHelper/CSProcHelper.h"
#define LOCTEXT_NAMESPACE "UnrealSharpEditor"
void SCSNewProjectDialog::Construct(const FArguments& InArgs)
{
static FName ProjectDestination(TEXT("<ProjectDestination>"));
const FString ScriptPath = FPaths::ConvertRelativePathToFull(FCSProcHelper::GetScriptFolderDirectory());
FText ProjectDestinationName = FText::FromString(FString::Printf(TEXT("%s (This Project)"), FApp::GetProjectName()));
ProjectDestinations.Add(MakeShared<FCSProjectDestination>(ProjectDestination, ProjectDestinationName, FApp::GetProjectName(), ScriptPath, 0));
IPluginManager& PluginManager = IPluginManager::Get();
TArray<TSharedRef<IPlugin>> EnabledPlugins = PluginManager.GetEnabledPlugins();
for (const TSharedRef<IPlugin>& Plugin : EnabledPlugins)
{
const FString PluginFilePath = FPaths::ConvertRelativePathToFull(Plugin->GetBaseDir());
if (!FPaths::IsUnderDirectory(PluginFilePath, FCSProcHelper::GetPluginsDirectory()) || Plugin->GetName() == UE_PLUGIN_NAME)
{
continue;
}
FString ScriptDirectory = PluginFilePath / "Script";
ProjectDestinations.Add(MakeShared<FCSProjectDestination>(FName(Plugin->GetName()),
FText::FromString(Plugin->GetFriendlyName()), Plugin->GetName(), ScriptDirectory, ProjectDestinations.Num(), Plugin));
}
SelectedProjectDestinationIndex = 0;
ChildSlot
[
SNew(SWizard)
.ShowPageList(false)
.FinishButtonText(LOCTEXT("CreateProject", "Create C# Project"))
.FinishButtonToolTip(LOCTEXT("CreateProjectTooltip", "Create a new C# project with the specified settings"))
.OnCanceled(this, &SCSNewProjectDialog::OnCancel)
.OnFinished(this, &SCSNewProjectDialog::OnFinish)
.CanFinish(this, &SCSNewProjectDialog::CanFinish)
+ SWizard::Page()
[
SNew(SOverlay)
+ SOverlay::Slot()
.HAlign(HAlign_Center)
.VAlign(VAlign_Center)
[
SNew(SVerticalBox)
+ SVerticalBox::Slot()
.Padding(0, 0, 0, 10)
[
SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
.AutoWidth()
.VAlign(VAlign_Center)
.Padding(0, 0, 10, 0)
[
SNew(STextBlock)
.Text(LOCTEXT("NewProjectName", "Name"))
]
+ SHorizontalBox::Slot()
.FillWidth(1)
[
SAssignNew(NameTextBox, SEditableTextBox)
]
]
+ SVerticalBox::Slot()
.Padding(0, 0, 0, 10)
[
SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
.AutoWidth()
.VAlign(VAlign_Center)
.Padding(0, 0, 10, 0)
[
SNew(STextBlock)
.Text(LOCTEXT("NewProjectOwner", "Owner"))
]
+ SHorizontalBox::Slot()
.FillWidth(1)
[
SAssignNew(ProjectDestinationComboBox, SComboBox<TSharedRef<FCSProjectDestination>>)
.OptionsSource(&ProjectDestinations)
.InitiallySelectedItem(ProjectDestinations[SelectedProjectDestinationIndex])
.OnSelectionChanged(this, &SCSNewProjectDialog::OnProjectDestinationChanged)
.OnGenerateWidget_Static(&SCSNewProjectDialog::OnGenerateProjectDestinationWidget)
.Content()
[
SNew(STextBlock).Text_Lambda([this]
{
if (SelectedProjectDestinationIndex == INDEX_NONE)
{
return FText();
}
return ProjectDestinations[SelectedProjectDestinationIndex]->GetDisplayName();
})
]
]
]
+ SVerticalBox::Slot()
.Padding(0, 0, 0, 10)
[
SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
.AutoWidth()
.VAlign(VAlign_Center)
.Padding(0, 0, 10, 0)
[
SNew(STextBlock)
.Text(LOCTEXT("NewProjectLocation", "Location"))
]
+ SHorizontalBox::Slot()
.FillWidth(1)
[
SAssignNew(PathTextBox, SEditableTextBox)
.Text(FText::FromString(ScriptPath))
]
+ SHorizontalBox::Slot()
.AutoWidth()
[
SNew(SButton)
.VAlign(VAlign_Center)
.ButtonStyle(FAppStyle::Get(), "SimpleButton")
.OnClicked(this, &SCSNewProjectDialog::OnExplorerButtonClicked)
[
SNew(SImage)
.Image(FAppStyle::Get().GetBrush("Icons.FolderClosed"))
.ColorAndOpacity(FSlateColor::UseForeground())
]
]
]
]
]
];
OnProjectDestinationChanged(ProjectDestinations[SelectedProjectDestinationIndex], ESelectInfo::Direct);
}
void SCSNewProjectDialog::OnProjectDestinationChanged(TSharedPtr<FCSProjectDestination> NewProjectDestination, ESelectInfo::Type)
{
if (NewProjectDestination == nullptr)
{
SelectedProjectDestinationIndex = INDEX_NONE;
return;
}
SelectedProjectDestinationIndex = NewProjectDestination->GetIndex();
PathTextBox->SetText(FText::FromString(NewProjectDestination->GetPath()));
FString ManagedName = TEXT("Managed") + NewProjectDestination->GetName();
NameTextBox->SetText(FText::FromString(ManagedName));
}
TSharedRef<SWidget> SCSNewProjectDialog::OnGenerateProjectDestinationWidget(TSharedRef<FCSProjectDestination> Destination)
{
return SNew(STextBlock)
.Text(Destination->GetDisplayName());
}
void SCSNewProjectDialog::OnPathSelected(const FString& NewPath)
{
if (NewPath.IsEmpty())
{
return;
}
PathTextBox->SetText(FText::FromString(NewPath));
}
FReply SCSNewProjectDialog::OnExplorerButtonClicked()
{
IDesktopPlatform* DesktopPlatform = FDesktopPlatformModule::Get();
if (!DesktopPlatform)
{
return FReply::Handled();
}
TSharedPtr<SWindow> ParentWindow = FSlateApplication::Get().FindWidgetWindow(AsShared());
void* ParentWindowWindowHandle = ParentWindow.IsValid() ? ParentWindow->GetNativeWindow()->GetOSWindowHandle() : nullptr;
FString FolderName;
const FString Title = TEXT("Choose a location for new project");
if (DesktopPlatform->OpenDirectoryDialog(ParentWindowWindowHandle, Title,FCSProcHelper::GetScriptFolderDirectory(), FolderName))
{
if (!FolderName.EndsWith(TEXT("/")) )
{
FolderName += TEXT("/");
}
}
if (FolderName.IsEmpty())
{
return FReply::Handled();
}
PathTextBox->SetText(FText::FromString(FolderName));
return FReply::Handled();
}
void SCSNewProjectDialog::OnCancel()
{
CloseWindow();
}
void SCSNewProjectDialog::OnFinish()
{
TMap<FString, FString> Arguments;
FString ModuleName = NameTextBox->GetText().ToString();
FString ProjectParentFolder = PathTextBox->GetText().ToString();
FString ProjectRoot;
FString GlueProjectLocation;
FString GlueProjectName;
auto MakeGlueNameAndLocation = [](FString& GlueLocation, FString& GlueName, const FString& PluginName, const FString& CsProjFolder)
{
GlueName = FString::Printf(TEXT("%s.Glue"), *PluginName);
GlueLocation = FPaths::Combine(CsProjFolder, FString::Printf(TEXT("%s.csproj"), *GlueName));
};
if (ProjectDestinations.IsValidIndex(SelectedProjectDestinationIndex) && SelectedProjectDestinationIndex > 0)
{
const TSharedRef<FCSProjectDestination>& Destination = ProjectDestinations[SelectedProjectDestinationIndex];
const TSharedPtr<IPlugin>& Plugin = Destination->GetPlugin();
ProjectRoot = Plugin->GetBaseDir();
MakeGlueNameAndLocation(GlueProjectLocation, GlueProjectName, Plugin->GetName(), FPaths::Combine(Destination->GetPath(), GlueProjectName));
}
else
{
ProjectRoot = FPaths::ProjectDir();
MakeGlueNameAndLocation(GlueProjectLocation, GlueProjectName, FApp::GetProjectName(), FCSProcHelper::GetProjectGlueFolderPath());
}
if (!FPaths::FileExists(GlueProjectLocation))
{
Arguments.Add(TEXT("SkipIncludeProjectGlue"), TEXT("true"));
}
Arguments.Add(TEXT("GlueProjectName"), GlueProjectName);
FUnrealSharpEditorModule::Get().AddNewProject(ModuleName, ProjectParentFolder, ProjectRoot, Arguments);
CloseWindow();
}
bool SCSNewProjectDialog::CanFinish() const
{
FString Name = NameTextBox->GetText().ToString();
FString Path = PathTextBox->GetText().ToString();
FString Filename = Name + ".csproj";
FString AbsolutePath = Path / Filename;
// Path can't be empty, name can't be empty, and path must contain the script path
if (Path.IsEmpty() || Name.IsEmpty() || SelectedProjectDestinationIndex == INDEX_NONE
|| !Path.Contains(ProjectDestinations[SelectedProjectDestinationIndex]->GetPath()))
{
return false;
}
// Name can't contain spaces
if (Name.Contains(TEXT(" ")))
{
return false;
}
// Path must be a valid directory
if (FPaths::DirectoryExists(Path / Name))
{
return false;
}
// File must not already exist
IFileManager& FileManager = IFileManager::Get();
TArray<FString> AssemblyPaths;
FileManager.FindFiles(AssemblyPaths, *Path, TEXT(".csproj"));
for (const FString& AssemblyPath : AssemblyPaths)
{
FString ProjectName = FPaths::GetBaseFilename(AssemblyPath);
if (ProjectName == Name)
{
return false;
}
}
return true;
}
void SCSNewProjectDialog::CloseWindow()
{
TSharedPtr<SWindow> ContainingWindow = FSlateApplication::Get().FindWidgetWindow(AsShared());
if (ContainingWindow.IsValid())
{
ContainingWindow->RequestDestroyWindow();
}
}
#undef LOCTEXT_NAMESPACE

View File

@ -0,0 +1,63 @@
#pragma once
struct FCSProjectDestination
{
FCSProjectDestination(const FName InKey, FText InDisplayName, FString InName, FString InPath, const int32 Index, TSharedPtr<IPlugin> Plugin = nullptr) :
Key(InKey), DisplayName(MoveTemp(InDisplayName)), Name(MoveTemp(InName)), Path(MoveTemp(InPath)), Index(Index), Plugin(MoveTemp(Plugin)) {}
FName GetKey() const { return Key; }
const FText& GetDisplayName() const { return DisplayName; }
const FString& GetName() const { return Name; }
const FString& GetPath() const { return Path; }
int32 GetIndex() const { return Index; }
const TSharedPtr<IPlugin>& GetPlugin() const { return Plugin; }
private:
FName Key;
FText DisplayName;
FString Name;
FString Path;
int32 Index;
TSharedPtr<IPlugin> Plugin;
friend uint32 GetTypeHash(const FCSProjectDestination& ProjectDestination)
{
return GetTypeHash(ProjectDestination.Key);
}
};
class SCSNewProjectDialog : public SCompoundWidget
{
public:
SLATE_BEGIN_ARGS(SCSNewProjectDialog) {}
SLATE_END_ARGS()
void Construct(const FArguments& InArgs);
private:
void OnProjectDestinationChanged(TSharedPtr<FCSProjectDestination> NewProjectDestination, ESelectInfo::Type SelectInfo);
static TSharedRef<SWidget> OnGenerateProjectDestinationWidget(TSharedRef<FCSProjectDestination> Destination);
void OnPathSelected(const FString& NewPath);
FReply OnExplorerButtonClicked();
void OnCancel();
void OnFinish();
bool CanFinish() const;
void CloseWindow();
private:
TSharedPtr<SEditableTextBox> PathTextBox;
TSharedPtr<SComboBox<TSharedRef<FCSProjectDestination>>> ProjectDestinationComboBox;
TSharedPtr<SEditableTextBox> NameTextBox;
FString SuggestedProjectName;
TArray<TSharedRef<FCSProjectDestination>> ProjectDestinations;
int32 SelectedProjectDestinationIndex = INDEX_NONE;
};

View File

@ -0,0 +1,51 @@
using UnrealBuildTool;
public class UnrealSharpEditor : ModuleRules
{
public UnrealSharpEditor(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
PublicDependencyModuleNames.AddRange(
new string[]
{
"Core",
"UnrealSharpBinds"
}
);
PrivateDependencyModuleNames.AddRange(
new string[]
{
"CoreUObject",
"Engine",
"Slate",
"SlateCore",
"EditorSubsystem",
"UnrealSharpCore",
"UnrealEd",
"UnrealSharpProcHelper",
"BlueprintGraph",
"ToolMenus",
"EditorFramework",
"InputCore",
"AppFramework",
"EditorStyle",
"Projects",
"GameplayTags",
"DeveloperSettings",
"UnrealSharpBlueprint",
"Kismet",
"KismetCompiler",
"BlueprintEditorLibrary",
"SubobjectDataInterface",
"AssetTools",
"UnrealSharpRuntimeGlue",
"PluginBrowser",
"UnrealSharpUtilities",
}
);
PublicDefinitions.Add("SkipGlueGeneration");
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,156 @@
#pragma once
#include "CoreMinimal.h"
#include "Modules/ModuleManager.h"
#include "Containers/Ticker.h"
#ifdef __clang__
#pragma clang diagnostic ignored "-Wignored-attributes"
#endif
class UCSAssembly;
struct FPluginTemplateDescription;
enum ECSLoggerVerbosity : uint8;
class UCSInterface;
class UCSEnum;
class UCSClass;
class UCSScriptStruct;
class UCSManager;
class IAssetTools;
class FCSScriptBuilder;
enum HotReloadStatus
{
// Not Hot Reloading
Inactive,
// When the DirectoryWatcher picks up on new code changes that haven't been Hot Reloaded yet
PendingReload,
// Actively Hot Reloading
Active,
// Failed to unload an assembly during Hot Reload
FailedToUnload
};
struct FCSManagedUnrealSharpEditorCallbacks
{
FCSManagedUnrealSharpEditorCallbacks() : Build(nullptr), ForceManagedGC(nullptr), OpenSolution(nullptr), AddProjectToCollection(nullptr)
{
}
using FBuildProject = bool(__stdcall*)(const TCHAR*, const TCHAR*, const TCHAR*, ECSLoggerVerbosity, void*, bool);
using FForceManagedGC = void(__stdcall*)();
using FOpenSolution = bool(__stdcall*)(const TCHAR*, void*);
using FAddProjectToCollection = void(__stdcall*)(const TCHAR*);
FBuildProject Build;
FForceManagedGC ForceManagedGC;
FOpenSolution OpenSolution;
FAddProjectToCollection AddProjectToCollection;
};
DECLARE_LOG_CATEGORY_EXTERN(LogUnrealSharpEditor, Log, All);
class FUnrealSharpEditorModule : public IModuleInterface
{
public:
static FUnrealSharpEditorModule& Get();
// IModuleInterface interface begin
virtual void StartupModule() override;
virtual void ShutdownModule() override;
// End
void OnCSharpCodeModified(const TArray<struct FFileChangeData>& ChangedFiles);
void StartHotReload(bool bRebuild = true, bool bPromptPlayerWithNewProject = true);
void InitializeUnrealSharpEditorCallbacks(FCSManagedUnrealSharpEditorCallbacks Callbacks);
bool IsHotReloading() const { return HotReloadStatus == Active; }
bool HasPendingHotReloadChanges() const { return HotReloadStatus == PendingReload; }
bool HasHotReloadFailed() const { return bHotReloadFailed; }
FUICommandList& GetUnrealSharpCommands() const { return *UnrealSharpCommands; }
void OpenSolution();
void AddDirectoryToWatch(const FString& Directory);
void AddNewProject(const FString& ModuleName, const FString& ProjectParentFolder, const FString& ProjectRoot, const TMap<FString, FString>& Arguments = {});
FCSManagedUnrealSharpEditorCallbacks& GetManagedUnrealSharpEditorCallbacks()
{
return ManagedUnrealSharpEditorCallbacks;
}
static bool FillTemplateFile(const FString& TemplateName, TMap<FString, FString>& Replacements, const FString& Path);
static void RepairComponents();
private:
static FString SelectArchiveDirectory();
static void RunGame(FString ExecutablePath);
static void CopyProperties(UActorComponent* Source, UActorComponent* Target);
static void OnCreateNewProject();
static void OnCompileManagedCode();
static void OnReloadManagedCode();
void OnRegenerateSolution();
void OnOpenSolution();
static void OnPackageProject();
static void OnMergeManagedSlnAndNativeSln();
static void OnOpenSettings();
static void OnOpenDocumentation();
static void OnReportBug();
static void OnRefreshRuntimeGlue();
static void OnRepairComponents();
static void OnExploreArchiveDirectory(FString ArchiveDirectory);
static void PackageProject();
TSharedRef<SWidget> GenerateUnrealSharpMenu();
static void OpenNewProjectDialog();
static void SuggestProjectSetup();
bool Tick(float DeltaTime);
void RegisterCommands();
void RegisterMenu();
void RegisterPluginTemplates();
void UnregisterPluginTemplates();
void OnPIEShutdown(bool IsSimulating);
void OnStructRebuilt(UCSScriptStruct* NewStruct);
void OnClassRebuilt(UCSClass* NewClass);
void OnEnumRebuilt(UCSEnum* NewEnum);
bool IsPinAffectedByReload(const FEdGraphPinType& PinType) const;
bool IsNodeAffectedByReload(UEdGraphNode* Node) const;
void RefreshAffectedBlueprints();
FSlateIcon GetMenuIcon() const;
FCSManagedUnrealSharpEditorCallbacks ManagedUnrealSharpEditorCallbacks;
HotReloadStatus HotReloadStatus = Inactive;
bool bHotReloadFailed = false;
bool bHasQueuedHotReload = false;
UCSAssembly* EditorAssembly;
FTickerDelegate TickDelegate;
FTSTicker::FDelegateHandle TickDelegateHandle;
TSharedPtr<FUICommandList> UnrealSharpCommands;
TArray<TSharedRef<FPluginTemplateDescription>> PluginTemplates;
TSet<UCSScriptStruct*> RebuiltStructs;
TSet<UCSClass*> RebuiltClasses;
TSet<UCSEnum*> RebuiltEnums;
UCSManager* Manager = nullptr;
TArray<FString> WatchingDirectories;
};

View File

@ -0,0 +1,13 @@
#include "UnrealSharpEditorModuleExporter.h"
#include "UnrealSharpProcHelper/CSProcHelper.h"
void UFUnrealSharpEditorModuleExporter::InitializeUnrealSharpEditorCallbacks(FCSManagedUnrealSharpEditorCallbacks Callbacks)
{
FUnrealSharpEditorModule::Get().InitializeUnrealSharpEditorCallbacks(Callbacks);
}
void UFUnrealSharpEditorModuleExporter::GetProjectPaths(TArray<FString>* Paths)
{
FCSProcHelper::GetAllProjectPaths(*Paths, true);
}

View File

@ -0,0 +1,19 @@
#pragma once
#include "CoreMinimal.h"
#include "UnrealSharpEditor.h"
#include "UnrealSharpBinds/Public/CSBindsManager.h"
#include "UObject/Object.h"
#include "UnrealSharpEditorModuleExporter.generated.h"
UCLASS()
class UNREALSHARPEDITOR_API UFUnrealSharpEditorModuleExporter : public UObject
{
GENERATED_BODY()
public:
UNREALSHARP_FUNCTION()
static void InitializeUnrealSharpEditorCallbacks(FCSManagedUnrealSharpEditorCallbacks Callbacks);
UNREALSHARP_FUNCTION()
static void GetProjectPaths(TArray<FString>* Paths);
};