using System; using System.Threading.Tasks; using JD.Adobe.Service.API; using JD.Adobe.Service.TargetMemories; using JD.Nas.Service; using JD.Shotgun.Service; using Orbit.Module.Actions; using Orbit.Module.Actions.PhotoshopActions; using Orbit.Module.View; using Orbit.Module.ViewModel; using Plume.Application.WPF.LongTasks; using Plume.Core.Logging; using Plume.Interfaces.Modules; using Plume.Interfaces.WPF.LongTasks; using Plume.Interfaces.WPF.Modules; using Plume.Interfaces.WPF.Notifications; using Plume.Interfaces.WPF.Window; using Plume.Perforce.Service.Api; using Shuttle.Servers; using ShuttleInstaller; using ShuttleInstaller.InstallerFromNas; using UbiStudio; using UbiStudio.StudioObjects; namespace Orbit.Module { public class OrbitModule : IWpfModule { private IPerforceService _perforceService; private ITaskManager _taskManager; private IPhotoshopService _photoshopService; private INasService _nasService; private IShotgunService _shotgunService; private IShuttleInstaller _shuttleInstaller; private INotificationManager _notificationManager; private string _shuttleNasPath; private OrbitPhotoshopView _orbitPhotoshopView; private FolderExplorerViewModel _folderExplorerViewModel; private MapsViewModel _mapsViewModel; private ConnectionWatcherViewModel _connectionWatcherViewModel; private ActionPanelsViewModel _actionPanelsViewModel; private AutoTargetMemory _targetMemory; private string _nasRootPath; private string _studioCodeName; private readonly CurrentStudioDetector _currentStudioDetector = new CurrentStudioDetector(); public ILogger Logger { get; private set; } public void Dispose() { _mapsViewModel.MapChanged -= OnMapChanged; _taskManager.OnTaskFinished -= OnTaskFinished; _targetMemory.OnTargetChanged -= OnTargetChanged; _folderExplorerViewModel.PropertyChanged -= FolderExplorerViewModelSelectedIndexTopFoldersChanged; _orbitPhotoshopView.Dispose(); } public void Setup(IModuleSetup setup) { if (setup == null) { throw new ArgumentNullException(nameof(setup)); } if (!(setup is OrbitModuleSetup configuration)) { throw new ArgumentException($"Expecting an {nameof(OrbitModuleSetup)} not a {setup.GetType()}", nameof(setup)); } _shuttleNasPath = configuration.ShuttleNasPath; if (string.IsNullOrEmpty(_shuttleNasPath)) { throw new InvalidOperationException($"The value for {nameof(configuration.ShuttleNasPath)} cannot be null or empty!"); } _nasRootPath = configuration.NasRootPath; if (string.IsNullOrEmpty(_nasRootPath)) { throw new InvalidOperationException($"The value for {nameof(configuration.NasRootPath)} cannot be null or empty!"); } // Get the studio code by UbiStudio library. // For now I have to use a separate task to run the request in sync mode until we make the Plume Setup async StudioInfo studioInfo = Task.Run(async () => await _currentStudioDetector.GetCurrentStudio()).Result; _studioCodeName = studioInfo?.GetMainCodeName(); if (string.IsNullOrEmpty(_studioCodeName)) { throw new InvalidOperationException($"The value for {nameof(_studioCodeName)} cannot be null or empty!"); } } public void Initialize(IWpfModuleContext context) { InitManagers(context); InitServices(context); //Members _taskManager = new TaskManager(Logger, context.StatusBarManager, context.NotificationManager); _taskManager.OnTaskFinished += OnTaskFinished; _targetMemory = new AutoTargetMemory(Logger, _photoshopService); _targetMemory.OnTargetChanged += OnTargetChanged; _shuttleInstaller = new NasShuttleInstaller(_shuttleNasPath); _nasService.SetRoot(_nasRootPath); //UI-related _mapsViewModel = new MapsViewModel(_perforceService, Logger); _folderExplorerViewModel = new FolderExplorerViewModel(Logger); _connectionWatcherViewModel = new ConnectionWatcherViewModel(_targetMemory, _photoshopService); _actionPanelsViewModel = new ActionPanelsViewModel(context.ActionManager, _targetMemory, _shuttleInstaller, _mapsViewModel); _folderExplorerViewModel.PropertyChanged += FolderExplorerViewModelSelectedIndexTopFoldersChanged; _mapsViewModel.MapChanged += OnMapChanged; var orbitPhotoshopViewModel = new OrbitPhotoshopViewModel { MapsViewModel = _mapsViewModel, FolderExplorerViewModel = _folderExplorerViewModel, ConnectionWatcherViewModel = _connectionWatcherViewModel, ActionPanelsViewModel = _actionPanelsViewModel }; _orbitPhotoshopView = new OrbitPhotoshopView { DataContext = orbitPhotoshopViewModel }; InitActions(context, _taskManager, _mapsViewModel); context.WindowManager.AddToolWindow("FolderExplorer", "Asset Explorer", null,_orbitPhotoshopView,DockingSide.Top, null); } private void FolderExplorerViewModelSelectedIndexTopFoldersChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) { if (!(sender is FolderExplorerViewModel viewModel)) return; if (e.PropertyName == nameof(viewModel.SelectedIndexTopFolders)) { //get the top folder name string topFolderName = viewModel.TopFolders.Count == 0 ? null : viewModel.TopFolders[viewModel.SelectedIndexTopFolders].Name; _actionPanelsViewModel.SelectedTopFolder = topFolderName; _actionPanelsViewModel.Refresh(); } } private void OnMapChanged(object sender, MapChangedEventArgs e) { _orbitPhotoshopView.Dispatcher?.Invoke(() => _folderExplorerViewModel.OnSelectedMapChanged(e.SelectedMap)); _orbitPhotoshopView.Dispatcher?.Invoke(_actionPanelsViewModel.Refresh); } public async void OnApplicationReady() { await _mapsViewModel.RefreshMaps(); } private void OnTargetChanged(TargetAppInfo targetAppInfo) { if (targetAppInfo == TargetAppInfo.Empty) _notificationManager.ShowWarning("Disconnected from Photoshop. Photoshop actions won't be available"); else _notificationManager.ShowInformation($"Connected to {targetAppInfo.AppType}, connection-Id: {targetAppInfo.ConnectionId}"); _orbitPhotoshopView.Dispatcher?.Invoke(_folderExplorerViewModel.Refresh); _orbitPhotoshopView.Dispatcher?.Invoke(_actionPanelsViewModel.Refresh); } private void OnTaskFinished(string taskName, bool success) { _orbitPhotoshopView.Dispatcher?.Invoke(_folderExplorerViewModel.Refresh); _orbitPhotoshopView.Dispatcher?.Invoke(_actionPanelsViewModel.Refresh); } private void InitManagers(IWpfModuleContext context) { Logger = context.Logger ?? throw new ArgumentNullException(nameof(context.Logger)); _notificationManager = context.NotificationManager ?? throw new ArgumentNullException(nameof(context.NotificationManager)); } private void InitServices(IWpfModuleContext context) { _perforceService = context.GetService() ?? throw new ArgumentNullException(nameof(IPerforceService)); _photoshopService = context.GetService() ?? throw new ArgumentNullException(nameof(IPhotoshopService)); _nasService = context.GetService() ?? throw new ArgumentNullException(nameof(INasService)); _shotgunService = context.GetService() ?? throw new ArgumentNullException(nameof(IShotgunService)); } private void InitActions(IWpfModuleContext context, ITaskManager taskManager, IMapExplorer mapExplorer) { var psActionContext = new PhotoshopActionContext { ShuttleInstaller = _shuttleInstaller, PhotoshopService = _photoshopService, TaskManager = _taskManager, TargetMemory = _targetMemory, AppContext = _folderExplorerViewModel }; context.ActionManager.Register(() => new OpenPhotoshopAction(psActionContext)); context.ActionManager.Register(() => new GenerateCoachesTextures(psActionContext)); context.ActionManager.Register(() => new GenerateCover1280Action(psActionContext)); context.ActionManager.Register(() => new GenerateCoverAlbumCoachAction(psActionContext)); context.ActionManager.Register(() => new GenerateMapBackgroundAction(psActionContext)); context.ActionManager.Register(() => new GenerateCoverGenericAction(psActionContext)); context.ActionManager.Register(() => new GenerateTexturesAction(psActionContext)); context.ActionManager.Register(() => new GenerateBackgroundsToNasAction(psActionContext, _nasService, _shotgunService, _studioCodeName)); context.ActionManager.Register(() => new GetLatestArtDataAction(taskManager, mapExplorer)); context.ActionManager.Register(() => new ShowInGameAction(taskManager, mapExplorer)); context.ActionManager.Register(() => new ShowExpositionInGameAction(taskManager, mapExplorer)); var installLogger = context.LoggerManager.GetOrCreateLogger(_shuttleInstaller.GetType().Name); context.ActionManager.Register(() => new InstallShuttlePluginAction(_shuttleInstaller, installLogger, taskManager)); //Context menu actions context.ActionManager.Register(); context.ActionManager.Register(); context.ActionManager.Register(() => new PlaceInPhotoshopAction(psActionContext)); } } }