Skip to content

Commit

Permalink
[Editor] Allow drag and drop of EntityComponent (#1921)
Browse files Browse the repository at this point in the history
  • Loading branch information
Eideren authored Oct 11, 2023
1 parent e672d91 commit 5870713
Show file tree
Hide file tree
Showing 8 changed files with 39 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,12 @@ public static string GetFullNamespace(this ISymbol symbol)
}
}

public class ScriptSourceCodeResolver : IScriptSourceCodeResolver
public class EntityComponentSourceCodeResolver : IEntityComponentSourceCodeResolver
{
private ProjectWatcher watcher;
private readonly Dictionary<string, List<Type>> typesForPath = new Dictionary<string, List<Type>>();

public ScriptSourceCodeResolver()
public EntityComponentSourceCodeResolver()
{
}

Expand Down Expand Up @@ -72,35 +72,40 @@ public async Task AnalyzeProject(SessionViewModel session, Project project, Canc

var assemblyFullName = gameProjectCompilation.Assembly.Name;

var strideScriptType = typeof(ScriptComponent);
var strideComponentType = typeof(EntityComponent);

var symbols = gameProjectCompilation.GetSymbolsWithName(x => true, SymbolFilter.Type).Cast<ITypeSymbol>().ToList();
if (!symbols.Any())
{
return;
}

var assembly = AssemblyRegistry.FindAll()?.FirstOrDefault(x => x.GetName().Name == assemblyFullName);
var assembly = AssemblyRegistry.FindAll().FirstOrDefault(x => x.GetName().Name == assemblyFullName);
if (assembly == null)
{
return;
}

var types = assembly.GetTypes();

var nonScriptsPaths = new HashSet<string>();
var typesDict = new Dictionary<string, List<Type>>();

foreach (var symbol in symbols)
{
var realType = types.FirstOrDefault(x => x.Name == symbol.Name && x.Namespace == symbol.GetFullNamespace());

if (!strideComponentType.IsAssignableFrom(realType))
{
foreach (var location in symbol.Locations)
nonScriptsPaths.Add(location.SourceTree.FilePath);
continue;
}

//find the script paths, (could be multiple in the case of partial)
foreach (var location in symbol.Locations)
{
var csPath = new UFile(location.SourceTree.FilePath);

//find the real type, and add to the dictionary
var realType = types.FirstOrDefault(x => x.Name == symbol.Name && x.Namespace == symbol.GetFullNamespace());
if (!strideScriptType.IsAssignableFrom(realType))
continue;
var csPath = new UFile(location.SourceTree.FilePath); // Normalize directory separator

if (!typesDict.ContainsKey(csPath))
{
Expand All @@ -115,12 +120,18 @@ public async Task AnalyzeProject(SessionViewModel session, Project project, Canc

lock (this)
{
// Ensure files that were previously components but not anymore are properly cleaned up
foreach (var nonScriptsPath in nonScriptsPaths)
{
typesForPath.Remove(nonScriptsPath);
}

foreach (var x in typesDict)
{
typesForPath[x.Key] = x.Value;
}

//clean up paths that do not exist anymore
// Clean up paths that do not exist anymore
var toRemove = typesForPath.Where(x => !File.Exists(x.Key)).Select(x => x.Key).ToList();
typesForPath.RemoveWhere(x => toRemove.Contains(x.Key));
}
Expand Down Expand Up @@ -152,7 +163,7 @@ public IEnumerable<Type> GetTypesFromSourceFile(UFile file)

lock (this)
{
return !typesForPath.ContainsKey(file) ? Enumerable.Empty<Type>() : typesForPath[file];
return typesForPath.TryGetValue(file, out var types) ? types : Enumerable.Empty<Type>();
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@

namespace Stride.Assets.Presentation.AssetEditors.EntityHierarchyEditor.ViewModels
{
internal class AddScriptSourceFileAssetPolicy : CreateComponentPolicyBase<ScriptSourceFileAsset, ScriptSourceFileAssetViewModel>
internal class AddEntityComponentFileAssetPolicy : CreateComponentPolicyBase<ScriptSourceFileAsset, ScriptSourceFileAssetViewModel>
{
/// <inheritdoc />
protected override bool CanAddOrInsert(EntityHierarchyItemViewModel parent, ScriptSourceFileAssetViewModel asset, AddChildModifiers modifiers, int index, out string message, params object[] messageArgs)
{
var scriptType = FindScriptType(asset.ServiceProvider, asset.AssetItem)?.FirstOrDefault();
if (scriptType == null)
{
message = $"No scripts inheriting from {nameof(ScriptComponent)} found in asset {asset.Url}";
message = $"No class inheriting from {nameof(EntityComponent)} found in file {asset.Url}";
return false;
}

Expand Down Expand Up @@ -51,7 +51,7 @@ protected override EntityComponent CreateComponentFromAsset(EntityHierarchyItemV
[CanBeNull]
private static IEnumerable<Type> FindScriptType([NotNull] IViewModelServiceProvider serviceProvider, [NotNull] AssetItem scriptAsset)
{
return serviceProvider.TryGet<IScriptSourceCodeResolver>()?.GetTypesFromSourceFile(scriptAsset.FullPath);
return serviceProvider.TryGet<IEntityComponentSourceCodeResolver>()?.GetTypesFromSourceFile(scriptAsset.FullPath);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ protected EntityHierarchyItemViewModel([NotNull] EntityHierarchyEditorViewModel
new AddModelAssetPolicy<ProceduralModelAsset>(),
new AddPrefabAssetPolicy(),
new AddSceneAssetPolicy(),
new AddScriptSourceFileAssetPolicy(),
new AddEntityComponentFileAssetPolicy(),
new AddSpriteSheetAssetPolicy(),
new AddSpriteStudioModelAssetPolicy(),
new AddTextureAssetPolicy(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,11 @@ namespace Stride.Assets.Presentation.AssetEditors
/// <summary>
/// Provides information about scripts in loaded assemblies.
/// </summary>
public interface IScriptSourceCodeResolver
public interface IEntityComponentSourceCodeResolver
{
/// <summary>
/// Gets script types that exist in a source file.
/// </summary>
/// <param name="file"></param>
/// <returns></returns>
IEnumerable<Type> GetTypesFromSourceFile(UFile file);

Compilation LatestCompilation { get; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public partial class VisualScriptEditorViewModel : AssetEditorViewModel

private GraphViewModel properties;

private IScriptSourceCodeResolver sourceResolver;
private IEntityComponentSourceCodeResolver sourceResolver;
private SemanticModel semanticModel;

private bool symbolSearchOpen;
Expand Down Expand Up @@ -85,7 +85,7 @@ public VisualScriptEditorViewModel(IVisualScriptViewModelService visualScriptVie
/// <inheritdoc/>
public sealed override async Task<bool> Initialize()
{
sourceResolver = ServiceProvider.Get<IScriptSourceCodeResolver>();
sourceResolver = ServiceProvider.Get<IEntityComponentSourceCodeResolver>();
if (sourceResolver.LatestCompilation == null)
{
// Wait for initial compilation to be done before continuing initialization
Expand Down Expand Up @@ -400,7 +400,7 @@ class SymbolSearchHelper : IDisposable
{
private const int MaxResults = 100;
private readonly VisualScriptEditorViewModel viewModel;
private readonly IScriptSourceCodeResolver sourceResolver;
private readonly IEntityComponentSourceCodeResolver sourceResolver;
private CancellationTokenSource symbolSearchCancellationToken;

public SymbolSearchHelper(VisualScriptEditorViewModel viewModel)
Expand All @@ -411,7 +411,7 @@ public SymbolSearchHelper(VisualScriptEditorViewModel viewModel)
viewModel.SymbolSearchValues.Clear();
viewModel.SymbolSearchOpen = true;

sourceResolver = viewModel.ServiceProvider.Get<IScriptSourceCodeResolver>();
sourceResolver = viewModel.ServiceProvider.Get<IEntityComponentSourceCodeResolver>();

// Start initial search
symbolSearchCancellationToken = new CancellationTokenSource();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ protected override async void ExecuteSync(INodePresenter nodePresenter, object p
var session = assetPresenter.Asset.Session;
var serviceProvider = assetPresenter.Asset.ServiceProvider;

var scriptSourceCodeProvider = serviceProvider.TryGet<IScriptSourceCodeResolver>();
var scriptSourceCodeProvider = serviceProvider.TryGet<IEntityComponentSourceCodeResolver>();

if (scriptSourceCodeProvider == null)
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ public async Task RegenerateSlots()
public async Task RegenerateSlots(Block block, ILogger log = null)
{
var newSlots = new List<Slot>(block.Slots.Count);
var sourceResolver = ServiceProvider.Get<IScriptSourceCodeResolver>();
var sourceResolver = ServiceProvider.Get<IEntityComponentSourceCodeResolver>();

try
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public class DebuggingViewModel : DispatcherViewModel, IDisposable
private readonly IDebugService debugService;
private readonly GameStudioViewModel editor;
private readonly Dictionary<PackageLoadedAssembly, ModifiedAssembly> modifiedAssemblies;
private readonly ScriptSourceCodeResolver scriptsSorter;
private readonly EntityComponentSourceCodeResolver entityComponentsSorter;
private readonly CancellationTokenSource assemblyTrackingCancellation;
private readonly LoggerResult assemblyReloadLogger = new LoggerResult();
private bool assemblyChangesPending;
Expand Down Expand Up @@ -73,8 +73,8 @@ public DebuggingViewModel(GameStudioViewModel editor, IDebugService debugService
assemblyTrackingCancellation = new CancellationTokenSource();

// Create script resolver
scriptsSorter = new ScriptSourceCodeResolver();
ServiceProvider.RegisterService(scriptsSorter);
entityComponentsSorter = new EntityComponentSourceCodeResolver();
ServiceProvider.RegisterService(entityComponentsSorter);

assemblyReloadLogger.MessageLogged += (sender, e) => Dispatcher.InvokeAsync(() => OutputTitle = outputTitleBase + '*');
editor.Session.PropertyChanged += SessionPropertyChanged;
Expand All @@ -83,7 +83,7 @@ public DebuggingViewModel(GameStudioViewModel editor, IDebugService debugService
Task.Run(async () =>
{
var watcher = await editor.StrideAssets.Code.ProjectWatcher;
await scriptsSorter.Initialize(editor.Session, watcher, assemblyTrackingCancellation.Token);
await entityComponentsSorter.Initialize(editor.Session, watcher, assemblyTrackingCancellation.Token);
PullAssemblyChanges(watcher);
});
}
Expand Down Expand Up @@ -281,7 +281,7 @@ private async Task ReloadAssemblies()
{
foreach (var assemblyToReload in assemblyToAnalyze)
{
await scriptsSorter.AnalyzeProject(Session, assemblyToReload.Key, assemblyTrackingCancellation.Token);
await entityComponentsSorter.AnalyzeProject(Session, assemblyToReload.Key, assemblyTrackingCancellation.Token);
}
UpdateCommands();
}, () =>
Expand Down

0 comments on commit 5870713

Please sign in to comment.