/// <summary> /// Function to load in the gaming device driver plug ins. /// </summary> /// <returns>A list of gaming device driver plug ins.</returns> private static IReadOnlyList <IGorgonGamingDeviceDriver> GetGamingDeviceDrivers() { GorgonExample.PlugInLocationDirectory = new DirectoryInfo(Settings.Default.InputPlugInPath); // Access our plugin cache. _pluginCache = new GorgonMefPlugInCache(GorgonApplication.Log); // Get the files from the plugin directory. // The plugin directory can be changed in the configuration file // to point at wherever you'd like. If a {0} place holder is // in the path, it will be replaced with whatever the build // configuration is set to (i.e. DEBUG or RELEASE). _pluginCache.LoadPlugInAssemblies(GorgonExample.GetPlugInPath().FullName, "Gorgon.Input.*.dll"); if (_pluginCache.PlugInAssemblies.Count == 0) { return(Array.Empty <IGorgonGamingDeviceDriver>()); } // Create our plugin service. IGorgonPlugInService pluginService = new GorgonMefPlugInService(_pluginCache); // Create our input service factory. var factory = new GorgonGamingDeviceDriverFactory(pluginService, GorgonApplication.Log); // Retrieve the list of driver plug ins from the input service factory. return(factory.LoadAllDrivers()); }
/// <summary> /// Function to load our useless image codec plug in. /// </summary> /// <returns><b>true</b> if successful, <b>false</b> if not.</returns> private bool LoadCodec() { const string pluginName = "Gorgon.Graphics.Example.TvImageCodecPlugIn"; _pluginCache = new GorgonMefPlugInCache(GorgonApplication.Log); // Load our plug in. _pluginCache.LoadPlugInAssemblies(GorgonApplication.StartupPath.FullName, "TVImageCodec.dll"); // Activate the plugin service. IGorgonPlugInService pluginService = new GorgonMefPlugInService(_pluginCache); // Find the plugin. GorgonImageCodecPlugIn plugIn = pluginService.GetPlugIn <GorgonImageCodecPlugIn>(pluginName); if ((plugIn == null) || (plugIn.Codecs.Count == 0)) { return(false); } // Normally you would enumerate the plug ins, but in this case we know there's only one. _customCodec = plugIn.CreateCodec(plugIn.Codecs[0].Name); return(_customCodec != null); }
/// <summary> /// Function to load the Gorgon pack file provider plugin. /// </summary> /// <returns>The file system provider.</returns> private IGorgonFileSystemProvider LoadGorPackProvider() { // The Gorgon packed file provider plug in dll. const string gorPackDll = "Gorgon.FileSystem.GorPack.dll"; // The name of the Gorgon packed file plugin. const string gorPackPlugInName = "Gorgon.IO.GorPack.GorPackProvider"; // Like the zip file example, we'll just create the plugin infrastructure, grab the provider object // and get rid of the plugin stuff since we won't need it again. _assemblyCache = new GorgonMefPlugInCache(GorgonApplication.Log); _assemblyCache.LoadPlugInAssemblies(GorgonExample.GetPlugInPath().FullName, gorPackDll); var plugIns = new GorgonMefPlugInService(_assemblyCache); return(plugIns.GetPlugIn <GorgonFileSystemProvider>(gorPackPlugInName)); }
/// <summary> /// Raises the <see cref="E:System.Windows.Forms.Form.Load" /> event. /// </summary> /// <param name="e">An <see cref="T:System.EventArgs" /> that contains the event data.</param> protected override void OnLoad(EventArgs e) { base.OnLoad(e); try { GorgonExample.PlugInLocationDirectory = new DirectoryInfo(Settings.Default.PlugInLocation); // Create the assembly cache. _assemblies = new GorgonMefPlugInCache(GorgonApplication.Log); _assemblies.LoadPlugInAssemblies(GorgonExample.GetPlugInPath().FullName, "Gorgon.Input.XInput.dll"); // Create the plug services. IGorgonPlugInService pluginService = new GorgonMefPlugInService(_assemblies); // Create the gaming device driver factory. var factory = new GorgonGamingDeviceDriverFactory(pluginService, GorgonApplication.Log); // Create our factory. _driver = factory.LoadDriver("Gorgon.Input.XInput.GorgonXInputDriver"); _stickPosition = new PointF[3]; _sprayStates = new SprayCan[3]; // Get our list of active controllers. UpdateActiveControllers(); // Get the graphics interface for our panel. _surface = new DrawingSurface(panelDisplay); // Set up our idle loop. GorgonApplication.IdleMethod += Idle; // Launch a background task to check for connected devices. Task.Run(CheckForConnectedDevices); } catch (Exception ex) { // We do this here instead of just calling the dialog because this // function will send the exception to the Gorgon log file. GorgonExample.HandleException(ex); GorgonApplication.Quit(); } }
/// <summary> /// Function to load the zip file system provider. /// </summary> private void LoadZipFileSystemProvider() { // Name of our zip provider plugin. const string zipProviderPlugInName = "Gorgon.IO.Zip.ZipProvider"; // We can load the objects we need and discard the plugin system after. // This works because we keep the references to the objects that our // plugin creates, even after the plugin is gone. using (var pluginAssemblies = new GorgonMefPlugInCache(Program.Log)) { pluginAssemblies.LoadPlugInAssemblies(Program.PlugInPath, "Gorgon.FileSystem.Zip.DLL"); var providerFactory = new GorgonFileSystemProviderFactory( new GorgonMefPlugInService(pluginAssemblies), Program.Log); _fileSystem = new GorgonFileSystem(providerFactory.CreateProvider(zipProviderPlugInName), Program.Log); } }
/// <summary>Releases the unmanaged resources used by the <see cref="T:System.Windows.Forms.ApplicationContext" /> and optionally releases the managed resources.</summary> /// <param name="disposing"> /// <see langword="true" /> to release both managed and unmanaged resources; <see langword="false" /> to release only unmanaged resources. </param> protected override void Dispose(bool disposing) { AppDomain.CurrentDomain.AssemblyResolve -= CurrentDomain_AssemblyResolve; ToolPlugInService toolPlugIns = Interlocked.Exchange(ref _toolPlugIns, null); ContentPlugInService contentPlugIns = Interlocked.Exchange(ref _contentPlugIns, null); GraphicsContext context = Interlocked.Exchange(ref _graphicsContext, null); GorgonMefPlugInCache pluginCache = Interlocked.Exchange(ref _pluginCache, null); FormMain mainForm = Interlocked.Exchange(ref _mainForm, null); FormSplash splash = Interlocked.Exchange(ref _splash, null); toolPlugIns?.Dispose(); contentPlugIns?.Dispose(); context?.Dispose(); pluginCache?.Dispose(); mainForm?.Dispose(); splash?.Dispose(); base.Dispose(disposing); }
/// <summary> /// The main entry point for the application. /// </summary> private static void Main() { _log = new GorgonLog("FileSystemProviders", "Tape_Worm"); _log.LogStart(); // Create a plugin assembly cache to hold our plugin assemblies. _pluginAssemblies = new GorgonMefPlugInCache(_log); // Create the plugin service. _pluginService = new GorgonMefPlugInService(_pluginAssemblies); try { Console.WriteLine("Gorgon is capable of mounting virtual file systems for file access. A virtual"); Console.WriteLine("file system root can be a folder on a hard drive, a zip file, or any data store"); Console.WriteLine("(assuming there's a provider for it).\n"); Console.WriteLine("In Gorgon, the types of data that can be mounted as a virtual file system are"); Console.WriteLine("managed by objects called providers. By default, the file system has a folder"); Console.WriteLine("provider. This allows a folder to be mounted as the root of a virtual file\nsystem.\n"); Console.WriteLine("This example will show how to load extra providers that can be used in a file\nsystem.\n"); Console.ForegroundColor = ConsoleColor.White; // Get our file system providers. Console.WriteLine("Found {0} external file system plug ins.\n", LoadFileSystemProviders()); // Loop through each provider and print some info. for (int i = 0; i < _providers.Count; ++i) { // Print some info about the file system provider. Console.ForegroundColor = ConsoleColor.Cyan; Console.WriteLine("{0}. {1}", i + 1, _providers[i].Name); Console.ForegroundColor = ConsoleColor.Gray; Console.WriteLine(" Description: {0}", _providers[i].Description); // Gather the preferred extensions. // File system providers that use a file (like a Zip file) as its root // have a list of file extensions that are preferred. For example, the // Zip provider, expects to find *.zip files. These are merely here // for the convenience of the developer and are formatted like a common // dialog file mask so they can be easily dropped into that control. // In this case, we're going to just strip out the relevant part and // concatenate each preferred extension description into a single string. // // Note that a provider may have multiple preferred extensions. string[] extensionList = (from preferred in _providers[i].PreferredExtensions select $"*.{preferred.Extension}").ToArray(); if (extensionList.Length > 0) { Console.WriteLine(" Preferred Extensions: {0}", string.Join(", ", extensionList)); } } Console.ResetColor(); Console.WriteLine("\nPress any key to close."); Console.ReadKey(); } catch (Exception ex) { ex.Catch(_ => { Console.Clear(); Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Exception:\n{0}\n\nStack Trace:{1}", _.Message, _.StackTrace); }, _log); Console.ResetColor(); #if DEBUG Console.ReadKey(); #endif } finally { // Always call dispose so we can unload our temporary application domain. _pluginAssemblies.Dispose(); _log.LogEnd(); } }
/// <summary> /// Function to initialize the application. /// </summary> private static async Task InitializeAsync(FormMain window) { try { GorgonExample.ResourceBaseDirectory = new DirectoryInfo(Settings.Default.ResourceLocation); GorgonExample.PlugInLocationDirectory = new DirectoryInfo(Settings.Default.PlugInLocation); // Load our packed file system plug in. window.UpdateStatus("Loading plugins..."); IGorgonPlugInService plugIns = await Task.Run(() => { _assemblyCache = new GorgonMefPlugInCache(GorgonApplication.Log); _assemblyCache.LoadPlugInAssemblies(GorgonExample.GetPlugInPath().FullName, "Gorgon.FileSystem.GorPack.dll"); return(new GorgonMefPlugInService(_assemblyCache)); }); window.UpdateStatus("Initializing graphics..."); // Retrieve the list of video adapters. We can do this on a background thread because there's no interaction between other threads and the // underlying D3D backend yet. IReadOnlyList <IGorgonVideoAdapterInfo> videoDevices = await Task.Run(() => GorgonGraphics.EnumerateAdapters(log: GorgonApplication.Log)); if (videoDevices.Count == 0) { throw new GorgonException(GorgonResult.CannotCreate, "Gorgon requires at least a Direct3D 11.4 capable video device.\nThere is no suitable device installed on the system."); } // Find the best video device. _graphics = new GorgonGraphics(videoDevices.OrderByDescending(item => item.FeatureSet).First()); _screen = new GorgonSwapChain(_graphics, window, new GorgonSwapChainInfo("Gorgon2D Space Scene Example") { Width = Settings.Default.Resolution.Width, Height = Settings.Default.Resolution.Height, Format = BufferFormat.R8G8B8A8_UNorm }); // Create a secondary render target for our scene. We use 16 bit floating point for the effect fidelity. // We'll lock our resolution to 1920x1080 (pretty common resolution for most people). _mainRtv = GorgonRenderTarget2DView.CreateRenderTarget(_graphics, new GorgonTexture2DInfo("Main RTV") { Width = (int)_baseResolution.X, Height = (int)_baseResolution.Y, Format = BufferFormat.R16G16B16A16_Float, Binding = TextureBinding.ShaderResource }); _mainSrv = _mainRtv.GetShaderResourceView(); _mainRtvAspect = _mainRtv.Width < _mainRtv.Height ? new DX.Vector2(1, (float)_mainRtv.Height / _mainRtv.Width) : new DX.Vector2((float)_mainRtv.Width / _mainRtv.Height, 1); // Initialize the renderer so that we are able to draw stuff. _renderer = new Gorgon2D(_graphics); // Set up our raw input. _input = new GorgonRawInput(window, GorgonApplication.Log); _keyboard = new GorgonRawKeyboard(); _keyboard.KeyUp += Keyboard_KeyUp; _input.RegisterDevice(_keyboard); GorgonExample.LoadResources(_graphics); // Now for the fun stuff, load our asset resources. We can load this data by mounting a directory (which I did while developing), or use a packed file. // // The resource manager will hold all the data we need for the scene. Including 3D meshes, post processing effects, etc... _resources = new ResourceManagement(_renderer, plugIns); _resources.Load(Path.Combine(GorgonExample.GetResourcePath(@"FileSystems").FullName, "SpaceScene.gorPack")); window.UpdateStatus("Loading resources..."); await _resources.LoadResourcesAsync(); SetupScene(); // Build up a font to use for rendering any GUI text. _helpFont = GorgonExample.Fonts.GetFont(new GorgonFontInfo("Segoe UI", 10.0f, FontHeightMode.Points, "Segoe UI 10pt") { OutlineSize = 2, Characters = (Resources.Instructions + "S:1234567890x").Distinct().ToArray(), FontStyle = FontStyle.Bold, AntiAliasingMode = FontAntiAliasMode.AntiAlias, OutlineColor1 = GorgonColor.Black, OutlineColor2 = GorgonColor.Black }); _textSprite = new GorgonTextSprite(_helpFont) { Position = new DX.Vector2(0, 64), DrawMode = TextDrawMode.OutlinedGlyphs, Color = GorgonColor.YellowPure }; GorgonExample.ShowStatistics = true; // Set the idle here. We don't want to try and render until we're done loading. GorgonApplication.IdleMethod = Idle; } finally { GorgonExample.EndInit(); } }
/// <summary> /// Function to perform the boot strapping operation. /// </summary> /// <returns>The main application window.</returns> public async void BootStrap() { AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve; try { // Get our initial context. SynchronizationContext.SetSynchronizationContext(new WindowsFormsSynchronizationContext()); Program.Log.Print("Booting application...", LoggingLevel.All); Cursor.Current = Cursors.WaitCursor; await ShowSplashAsync(); // Initalize the common resources. EditorCommonResources.LoadResources(); _folderBrowser = new FileSystemFolderBrowseService(); _commonServices = new ViewModelInjection(Program.Log, new WaitCursorBusyState(), new MessageBoxService()); _pluginCache = new GorgonMefPlugInCache(Program.Log); _graphicsContext = GraphicsContext.Create(Program.Log); _plugInLocation = new DirectoryInfo(Path.Combine(GorgonApplication.StartupPath.FullName, "PlugIns")); if (!_plugInLocation.Exists) { Program.Log.Print($"[ERROR] Plug in path '{_plugInLocation.FullName}' was not found. No plug ins will be loaded.", LoggingLevel.Simple); GorgonDialogs.ErrorBox(null, Resources.GOREDIT_ERR_LOADING_PLUGINS); } // Get any application settings we might have. _settings = LoadSettings(); // Load our file system import/export plugins. FileSystemProviders fileSystemProviders = LoadFileSystemPlugIns(); // Load our tool plug ins. _toolPlugIns = LoadToolPlugIns(); // Load our content service plugins. _contentPlugIns = LoadContentPlugIns(); // Create the project manager for the application _projectManager = new ProjectManager(fileSystemProviders); _mainForm = new FormMain { Location = new Point(_settings.WindowBounds.Value.X, _settings.WindowBounds.Value.Y), Size = new Size(_settings.WindowBounds.Value.Width, _settings.WindowBounds.Value.Height), WindowState = FormWindowState.Normal }; await HideSplashAsync(); MainForm = _mainForm; var factory = new ViewModelFactory(_settings, fileSystemProviders, _contentPlugIns, _toolPlugIns, _projectManager, _commonServices, new ClipboardService(), new DirectoryLocateService(), new FileScanService(_contentPlugIns), _folderBrowser); FormWindowState windowState; // Ensure the window state values fall into an acceptable range. if (!Enum.IsDefined(typeof(FormWindowState), _settings.WindowState)) { windowState = FormWindowState.Maximized; } else { windowState = (FormWindowState)_settings.WindowState; } _mainForm.GraphicsContext = _graphicsContext; _mainForm.SetDataContext(factory.CreateMainViewModel(_graphicsContext.Graphics.VideoAdapter.Name)); _mainForm.Show(); _mainForm.WindowState = windowState; } finally { Cursor.Current = Cursors.Default; } }
/// <summary> /// Raises the <see cref="E:System.Windows.Forms.Form.Load"></see> event. /// </summary> /// <param name="e">An <see cref="T:System.EventArgs"></see> that contains the event data.</param> protected override void OnLoad(EventArgs e) { base.OnLoad(e); try { GorgonExample.PlugInLocationDirectory = new DirectoryInfo(Settings.Default.PlugInLocation); // Load the assembly. _assemblyCache = new GorgonMefPlugInCache(GorgonApplication.Log); // Create the plugin service. IGorgonPlugInService plugInService = new GorgonMefPlugInService(_assemblyCache); // Create the factory to retrieve gaming device drivers. var factory = new GorgonGamingDeviceDriverFactory(plugInService); // Create the raw input interface. _input = new GorgonRawInput(this, GorgonApplication.Log); // Get available gaming device driver plug ins. _assemblyCache.LoadPlugInAssemblies(GorgonExample.GetPlugInPath().FullName, "Gorgon.Input.DirectInput.dll"); _assemblyCache.LoadPlugInAssemblies(GorgonExample.GetPlugInPath().FullName, "Gorgon.Input.XInput.dll"); _drivers = factory.LoadAllDrivers(); _joystickList = new List <IGorgonGamingDevice>(); // Get all gaming devices from the drivers. foreach (IGorgonGamingDeviceDriver driver in _drivers) { IReadOnlyList <IGorgonGamingDeviceInfo> infoList = driver.EnumerateGamingDevices(true); foreach (IGorgonGamingDeviceInfo info in infoList) { IGorgonGamingDevice device = driver.CreateGamingDevice(info); // Turn off dead zones for this example. foreach (GorgonGamingDeviceAxis axis in device.Axis) { axis.DeadZone = GorgonRange.Empty; } _joystickList.Add(device); } } // Create mouse. _mouse = new GorgonRawMouse(); // Create the graphics interface. ClientSize = Settings.Default.Resolution; IReadOnlyList <IGorgonVideoAdapterInfo> adapters = GorgonGraphics.EnumerateAdapters(); _graphics = new GorgonGraphics(adapters[0], log: GorgonApplication.Log); _screen = new GorgonSwapChain(_graphics, this, new GorgonSwapChainInfo("INeedYourInput Swapchain") { Width = Settings.Default.Resolution.Width, Height = Settings.Default.Resolution.Height, Format = BufferFormat.R8G8B8A8_UNorm }); _graphics.SetRenderTarget(_screen.RenderTargetView); if (!Settings.Default.IsWindowed) { _screen.EnterFullScreen(); } // For the backup image. Used to make it as large as the monitor that we're on. var currentScreen = Screen.FromHandle(Handle); // Relocate the window to the center of the screen. Location = new Point(currentScreen.Bounds.Left + (currentScreen.WorkingArea.Width / 2) - (ClientSize.Width / 2), currentScreen.Bounds.Top + (currentScreen.WorkingArea.Height / 2) - (ClientSize.Height / 2)); // Create the 2D renderer. _2D = new Gorgon2D(_graphics); // Create the text font. var fontFactory = new GorgonFontFactory(_graphics); _font = fontFactory.GetFont(new GorgonFontInfo("Arial", 9.0f, FontHeightMode.Points, "Arial 9pt") { FontStyle = FontStyle.Bold, AntiAliasingMode = FontAntiAliasMode.AntiAlias }); // Create text sprite. _messageSprite = new GorgonTextSprite(_font, "Using mouse and keyboard (Windows Forms).") { Color = Color.Black }; // Create a back buffer. _backBuffer = GorgonRenderTarget2DView.CreateRenderTarget(_graphics, new GorgonTexture2DInfo("Backbuffer storage") { Width = _screen.Width, Height = _screen.Height, Format = _screen.Format }); _backBuffer.Clear(Color.White); _backBufferView = _backBuffer.GetShaderResourceView(); // Clear our backup image to white to match our primary screen. using (IGorgonImage image = new GorgonImage(new GorgonImageInfo(ImageType.Image2D, _screen.Format) { Width = _screen.Width, Height = _screen.Height, Format = _screen.Format })) { image.Buffers[0].Fill(0xff); _backupImage = image.ToTexture2D(_graphics, new GorgonTexture2DLoadOptions { Binding = TextureBinding.None, Usage = ResourceUsage.Staging }); } // Set gorgon events. _screen.BeforeSwapChainResized += BeforeSwapChainResized; _screen.AfterSwapChainResized += AfterSwapChainResized; // Enable the mouse. Cursor = Cursors.Cross; _mouse.MouseButtonDown += MouseInput; _mouse.MouseMove += MouseInput; _mouse.MouseWheelMove += (sender, args) => { _radius += args.WheelDelta.Sign(); if (_radius < 2.0f) { _radius = 2.0f; } if (_radius > 10.0f) { _radius = 10.0f; } }; // Set the mouse position. _mouse.Position = new Point(ClientSize.Width / 2, ClientSize.Height / 2); _noBlending = _blendBuilder.BlendState(GorgonBlendState.NoBlending) .Build(); _inverted = _blendBuilder.BlendState(GorgonBlendState.Inverted) .Build(); // Set up blending states for our pen. var blendStateBuilder = new GorgonBlendStateBuilder(); _currentBlend = _drawModulatedBlend = _blendBuilder.BlendState(blendStateBuilder .ResetTo(GorgonBlendState.Default) .DestinationBlend(alpha: Blend.One) .Build()) .Build(); _drawAdditiveBlend = _blendBuilder.BlendState(blendStateBuilder .ResetTo(GorgonBlendState.Additive) .DestinationBlend(alpha: Blend.One) .Build()) .Build(); _drawNoBlend = _blendBuilder.BlendState(blendStateBuilder .ResetTo(GorgonBlendState.NoBlending) .DestinationBlend(alpha: Blend.One) .Build()) .Build(); GorgonApplication.IdleMethod = Gorgon_Idle; } catch (ReflectionTypeLoadException refEx) { string refErr = string.Join("\n", refEx.LoaderExceptions.Select(item => item.Message)); GorgonDialogs.ErrorBox(this, refErr); } catch (Exception ex) { GorgonExample.HandleException(ex); GorgonApplication.Quit(); } }
/// <summary> /// Function to initialize the application. /// </summary> /// <returns>The main window for the application.</returns> private static FormMain Initialize() { GorgonExample.ResourceBaseDirectory = new DirectoryInfo(Settings.Default.ResourceLocation); GorgonExample.PlugInLocationDirectory = new DirectoryInfo(Settings.Default.PlugInLocation); FormMain window = GorgonExample.Initialize(new DX.Size2(Settings.Default.Resolution.Width, Settings.Default.Resolution.Height), "Depth"); try { IReadOnlyList <IGorgonVideoAdapterInfo> videoDevices = GorgonGraphics.EnumerateAdapters(log: GorgonApplication.Log); if (videoDevices.Count == 0) { throw new GorgonException(GorgonResult.CannotCreate, "Gorgon requires at least a Direct3D 11.4 capable video device.\nThere is no suitable device installed on the system."); } // Find the best video device. _graphics = new GorgonGraphics(videoDevices.OrderByDescending(item => item.FeatureSet).First()); _screen = new GorgonSwapChain(_graphics, window, new GorgonSwapChainInfo("Gorgon2D Depth Buffer Example") { Width = Settings.Default.Resolution.Width, Height = Settings.Default.Resolution.Height, Format = BufferFormat.R8G8B8A8_UNorm }); _depthBuffer = GorgonDepthStencil2DView.CreateDepthStencil(_graphics, new GorgonTexture2DInfo(_screen.RenderTargetView) { Binding = TextureBinding.DepthStencil, Format = BufferFormat.D24_UNorm_S8_UInt }); // Tell the graphics API that we want to render to the "screen" swap chain. _graphics.SetRenderTarget(_screen.RenderTargetView, _depthBuffer); // Initialize the renderer so that we are able to draw stuff. _renderer = new Gorgon2D(_graphics); GorgonExample.LoadResources(_graphics); // Load our packed file system plug in. _assemblyCache = new GorgonMefPlugInCache(GorgonApplication.Log); _assemblyCache.LoadPlugInAssemblies(GorgonExample.GetPlugInPath().FullName, "Gorgon.FileSystem.GorPack.dll"); IGorgonPlugInService plugIns = new GorgonMefPlugInService(_assemblyCache); // Load the file system containing our application data (sprites, images, etc...) IGorgonFileSystemProviderFactory providerFactory = new GorgonFileSystemProviderFactory(plugIns, GorgonApplication.Log); IGorgonFileSystemProvider provider = providerFactory.CreateProvider("Gorgon.IO.GorPack.GorPackProvider"); IGorgonFileSystem fileSystem = new GorgonFileSystem(provider, GorgonApplication.Log); // We can load the editor file system directly. // This is handy for switching a production environment where your data may be stored // as a compressed file, and a development environment where your data consists of loose // files. // fileSystem.Mount(@"D:\unpak\scratch\DeepAsAPuddle.gorPack\fs\"); // For now though, we'll load the packed file. fileSystem.Mount(Path.Combine(GorgonExample.GetResourcePath(@"FileSystems").FullName, "Depth.gorPack")); // Get our sprites. These make up the frames of animation for our Guy. // If and when there's an animation editor, we'll only need to create a single sprite and load the animation. IGorgonVirtualFile[] spriteFiles = fileSystem.FindFiles("/Sprites/", "*", true).ToArray(); // Load our sprite data (any associated textures will be loaded as well). Dictionary <string, GorgonSprite> sprites = new Dictionary <string, GorgonSprite>(StringComparer.OrdinalIgnoreCase); for (int i = 0; i < spriteFiles.Length; i++) { IGorgonVirtualFile file = spriteFiles[i]; (GorgonSprite sprite, GorgonTexture2D texture) = fileSystem.LoadSprite(_renderer, file.FullPath); // The LoadSprite extension method will automatically find and load your associated texture if you're using // a Gorgon editor file system. So it's important that you leep track of your textures, disposing of just // the associated GorgonTexture2DView won't cut it here, so you'll need to dispose the actual texture resource // when you're done with it. if (!_textures.Contains(texture)) { _textures.Add(texture); } // At super duper resolution, the example graphics would be really hard to see, so we'll scale them up. sprite.Scale = new DX.Vector2((_screen.Width / (_screen.Height / 2)) * 2.0f); sprites[file.Name] = sprite; } _snowTile = sprites["Snow"]; _snowTile.Depth = 0.5f; _icicle = sprites["Icicle"]; _icicle.Depth = 0.2f; _guySprite = sprites["Guy_Up_0"]; _guySprite.Depth = 0.1f; _guyPosition = new DX.Vector2(_screen.Width / 2 + _guySprite.ScaledSize.Width * 1.25f, _screen.Height / 2 + _guySprite.ScaledSize.Height); BuildAnimations(sprites); } finally { GorgonExample.EndInit(); } return(window); }
/// <summary>Function to load all the specified plug in assemblies.</summary> /// <param name="pluginCache">The plugin cache that will hold the plug in assembies.</param> /// <param name="pluginAssemblyFiles">The list of plug in assembly paths to load.</param> /// <param name="log">The application logging interface.</param> /// <returns>A list of <see cref="PlugInAssemblyState"/> objects for each plug in assembly loaded.</returns> /// <exception cref="ArgumentNullException">Thrown when the <paramref name="pluginAssemblyFiles" /> parameter is <b>null</b></exception> public static IReadOnlyList <PlugInAssemblyState> ValidateAndLoadAssemblies(this GorgonMefPlugInCache pluginCache, IEnumerable <FileInfo> pluginAssemblyFiles, IGorgonLog log) { if (pluginAssemblyFiles == null) { throw new ArgumentNullException(nameof(pluginAssemblyFiles)); } var records = new List <PlugInAssemblyState>(); // We use this to determine whether the plug in can be loaded into the current platform. AssemblyPlatformType currentPlatform = IntPtr.Size == 8 ? AssemblyPlatformType.x64 : AssemblyPlatformType.x86; foreach (FileInfo file in pluginAssemblyFiles) { // If we've already got the assembly loaded into this cache, then there's no need to try and load it. if (pluginCache.PlugInAssemblies?.Any(item => string.Equals(item, file.FullName, StringComparison.OrdinalIgnoreCase)) ?? false) { continue; } if (!file.Exists) { log.Print($"[ERROR] Plug in '{file.FullName}' was not found.", LoggingLevel.Verbose); records.Add(new PlugInAssemblyState(file.FullName, Resources.GOREDIT_PLUGIN_LOAD_FAIL_NOT_FOUND, false)); continue; } (bool isManaged, AssemblyPlatformType platformType) = GorgonMefPlugInCache.IsManagedAssembly(file.FullName); if ((!isManaged) || (platformType == AssemblyPlatformType.Unknown)) { log.Print($"[WARNING] Skipping '{file.FullName}'. Not a valid .NET assembly.", LoggingLevel.Verbose); records.Add(new PlugInAssemblyState(file.FullName, string.Format(Resources.GOREDIT_PLUGIN_LOAD_FAIL_NOT_DOT_NET, file.Name), false)); continue; } // Ensure that our platform type matches (AnyCPU is exempt and will always run, and DLLs don't allow Prefer 32 bit). if ((currentPlatform == AssemblyPlatformType.x86) && (platformType == AssemblyPlatformType.x64)) { log.Print($"[ERROR] Cannot load assembly '{file.FullName}', currently executing in an x86 environment, but the assembly is x64.", LoggingLevel.Simple); records.Add(new PlugInAssemblyState(file.FullName, string.Format(Resources.GOREDIT_PLUGIN_LOAD_FAIL_PLATFORM_MISMATCH, file.Name, platformType, currentPlatform), true)); continue; } if ((currentPlatform == AssemblyPlatformType.x64) && (platformType == AssemblyPlatformType.x86)) { log.Print($"[ERROR] Cannot load assembly '{file.FullName}', currently executing in an x64 environment, but the assembly is x86.", LoggingLevel.Simple); records.Add(new PlugInAssemblyState(file.FullName, string.Format(Resources.GOREDIT_PLUGIN_LOAD_FAIL_PLATFORM_MISMATCH, file.Name, platformType, currentPlatform), true)); continue; } try { log.Print($"Loading plug in assembly '{file.FullName}'...", LoggingLevel.Simple); pluginCache.LoadPlugInAssemblies(file.DirectoryName, file.Name); records.Add(new PlugInAssemblyState(file.FullName, string.Empty, true)); } catch (Exception ex) { log.Print($"ERROR: Cannot load plug in assembly '{file.FullName}'.", LoggingLevel.Simple); log.LogException(ex); records.Add(new PlugInAssemblyState(file.FullName, string.Format(Resources.GOREDIT_PLUGIN_LOAD_FAIL_EXCEPTION, file.Name, ex.Message), true)); } } return(records); }
/// <summary> /// The main entry point for the application. /// </summary> private static void Main() { _log = new GorgonLog("ZipFileSystem", "Tape_Worm"); _log.LogStart(); // Create the plugin assembly cache. _pluginAssemblies = new GorgonMefPlugInCache(_log); // Create the plugin service. _pluginService = new GorgonMefPlugInService(_pluginAssemblies); try { Console.WindowHeight = 28; Console.BufferHeight = Console.WindowHeight; Console.ForegroundColor = ConsoleColor.White; Console.WriteLine("This example will mount a zip file as the root of a virtual file system. The"); Console.WriteLine("virtual file system is capable of mounting various types of data such as a zip,"); Console.WriteLine("a file system folder, etc... as the root or a sub directory. You can even"); Console.WriteLine("mount a zip file as the root, and a physical file system directory as a virtual"); Console.WriteLine("sub directory in the same virtual file system and access them as a single"); Console.WriteLine("unified file system."); // Unlike the folder file system example, we need to load // a provider to handle zip files before trying to mount // one. if (!LoadZipProviderPlugIn()) { return; } // Set the following zip file as root on the virtual file system. // // If we wanted to, we could mount a zip file as a sub directory of // the root of the virtual file system. For example, mounting the // directory D:\Dir\zipFile.zip with Mount(@"D:\Dir", "/VFSDir"); would mount // the contents of the D:\Dir\zipFile.zip directory under /VFSDir. // // It's also important to point out that the old Gorgon "file system" // would load files from the system into memory when mounting a // directory. While this version only loads directory and file // information when mounting. This is considerably more efficient. string physicalPath = GetResourcePath(@"FileSystem.zip"); _fileSystem.Mount(physicalPath); Console.Write("\nMounted: "); Console.ForegroundColor = ConsoleColor.Cyan; Console.Write("'{0}'", physicalPath.Ellipses(Console.WindowWidth - 20, true)); Console.ForegroundColor = ConsoleColor.White; Console.Write(" as "); Console.ForegroundColor = ConsoleColor.Cyan; Console.WriteLine("'/'\n"); Console.ForegroundColor = ConsoleColor.White; // Get a count of all sub directories and files under the root directory. IGorgonVirtualDirectory[] directoryList = _fileSystem.FindDirectories("*").ToArray(); // Display directories. Console.WriteLine("Virtual file system contents:"); for (int i = -1; i < directoryList.Length; i++) { IGorgonVirtualDirectory directory = _fileSystem.RootDirectory; // Go into the sub directories under root. if (i > -1) { directory = directoryList[i]; } Console.ForegroundColor = ConsoleColor.Cyan; Console.WriteLine("{0}", directory.FullPath); Console.ForegroundColor = ConsoleColor.Yellow; foreach (IGorgonVirtualFile file in directory.Files) { Console.Write(" {0}", file.Name); // Align the size to the same place. Console.CursorLeft = 65; Console.WriteLine("{0}", file.Size.FormatMemory()); } } Console.ResetColor(); Console.WriteLine("\nPress any key to close."); Console.ReadKey(); } catch (Exception ex) { ex.Catch(_ => { Console.Clear(); Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Exception:\n{0}\n\nStack Trace:{1}", _.Message, _.StackTrace); Console.ResetColor(); #if DEBUG Console.ReadKey(); #endif }); } finally { // Always dispose the cache to clean up the temporary app domain it creates. _pluginAssemblies.Dispose(); _log.LogEnd(); } }
/// <summary>Initializes a new instance of the ImageContentVmParameters class.</summary> /// <param name="settings">The settings for the image editor.</param> /// <param name="codecs">The codecs loaded into the system.</param> /// <param name="codecDialog">The file dialog used to locate codec assemblies.</param> /// <param name="pluginService">The service used to manage content and importer plug ins.</param> /// <param name="plugInCache">The cache for plug in assemblies.</param> /// <param name="commonServices">Common application services.</param> /// <exception cref="ArgumentNullException">Thrown when any of the parameters are <b>null</b>.</exception> public SettingsParameters(ImageEditorSettings settings, ICodecRegistry codecs, IFileDialogService codecDialog, IContentPlugInService pluginService, GorgonMefPlugInCache plugInCache, IViewModelInjection commonServices) : base(commonServices) { Settings = settings ?? throw new ArgumentNullException(nameof(settings)); Codecs = codecs ?? throw new ArgumentNullException(nameof(codecs)); CodecFileDialog = codecDialog ?? throw new ArgumentNullException(nameof(codecDialog)); PlugInService = pluginService ?? throw new ArgumentNullException(nameof(pluginService)); PlugInCache = plugInCache ?? throw new ArgumentNullException(nameof(plugInCache)); }
/// <summary> /// Function to load the file system provider plug ins. /// </summary> /// <param name="pluginCache">The MEF plug in cache used to load the file system plug ins.</param> /// <param name="pluginDir">The plug in directory.</param> /// <exception cref="ArgumentNullException">Thrown when the <paramref name="pluginCache"/>, or the <paramref name="pluginDir"/> parameter is <b>null</b>.</exception> public void LoadProviders(GorgonMefPlugInCache pluginCache, DirectoryInfo pluginDir) { if (pluginCache == null) { throw new ArgumentNullException(nameof(pluginCache)); } if (pluginDir == null) { throw new ArgumentNullException(nameof(pluginDir)); } IReadOnlyList <PlugInAssemblyState> assemblies = pluginCache.ValidateAndLoadAssemblies(pluginDir.GetFiles("*.dll"), Program.Log); if (assemblies.Count > 0) { foreach (PlugInAssemblyState record in assemblies.Where(item => !item.IsAssemblyLoaded && item.IsManaged)) { _disabled[Path.GetFileName(record.Path)] = new DisabledPlugIn(DisabledReasonCode.Error, Path.GetFileName(record.Path), record.LoadFailureReason, record.Path); } } IGorgonPlugInService plugins = new GorgonMefPlugInService(pluginCache); IReadOnlyList <GorgonFileSystemProvider> readers = plugins.GetPlugIns <GorgonFileSystemProvider>(); IReadOnlyList <FileWriterPlugIn> writers = plugins.GetPlugIns <FileWriterPlugIn>(); // Get readers. foreach (IGorgonFileSystemProvider reader in readers) { try { Program.Log.Print($"Creating file system reader plug in '{reader.Name}'...", LoggingLevel.Simple); _readers[reader.Name] = reader; } catch (Exception ex) { Program.Log.Print($"ERROR: Cannot create file system reader plug in '{reader.Name}'.", LoggingLevel.Simple); Program.Log.LogException(ex); _disabled[reader.Name] = new DisabledPlugIn(DisabledReasonCode.Error, reader.Name, string.Format(Resources.GOREDIT_DISABLE_FILE_PROVIDER_EXCEPTION, ex.Message), reader.ProviderPath); } } // Get writers foreach (FileWriterPlugIn writer in writers) { IReadOnlyList <string> disabled = writer.IsPlugInAvailable(); try { Program.Log.Print($"Creating file system writer plug in '{writer.Name}'...", LoggingLevel.Simple); if (disabled.Count != 0) { Program.Log.Print($"WARNING: The file system writer plug in '{writer.Name}' is disabled:", LoggingLevel.Simple); foreach (string reason in disabled) { Program.Log.Print($"WARNING: {reason}", LoggingLevel.Verbose); } _disabled[writer.Name] = new DisabledPlugIn(DisabledReasonCode.ValidationError, writer.Name, string.Join("\n", disabled), writer.PlugInPath); continue; } writer.AssignCommonServices(_commonServices); _writers[writer.GetType().FullName] = writer; } catch (Exception ex) { Program.Log.Print($"ERROR: Cannot create file system writer plug in '{writer.Name}'.", LoggingLevel.Simple); Program.Log.LogException(ex); _disabled[writer.Name] = new DisabledPlugIn(DisabledReasonCode.Error, writer.Name, string.Format(Resources.GOREDIT_DISABLE_FILE_PROVIDER_EXCEPTION, ex.Message), writer.PlugInPath); } } }
private static void Main(string[] args) { _log = new GorgonLog("Example 004", "Tape_Worm", typeof(Program).Assembly.GetName().Version); // Set up the assembly cache. // We'll need the assemblies loaded into this object in order to load our plugin types. var pluginCache = new GorgonMefPlugInCache(_log); // Create our plugin service. // This takes the cache of assemblies we just created. IGorgonPlugInService pluginService = new GorgonMefPlugInService(pluginCache); try { Console.Title = "Gorgon Example #4 - PlugIns."; Console.ForegroundColor = ConsoleColor.White; Console.WriteLine("This is an example to show how to create and use custom plugins."); Console.WriteLine("The plugin interface in Gorgon is quite flexible and gives the developer"); Console.WriteLine("the ability to allow extensions to their own applications.\n"); Console.ResetColor(); pluginCache.LoadPlugInAssemblies(Path.GetDirectoryName(Environment.GetCommandLineArgs()[0]).FormatDirectory(Path.DirectorySeparatorChar), "Example004.*PlugIn.dll"); Console.WriteLine("{0} plugin assemblies found.", pluginCache.PlugInAssemblies.Count); if (pluginCache.PlugInAssemblies.Count == 0) { return; } // Our text writer plugin interfaces. IList <TextColorWriter> writers = new List <TextColorWriter>(); // Create our plugin instances, we'll limit to 9 entries just for giggles. TextColorPlugIn[] plugins = (from pluginName in pluginService.GetPlugInNames() let plugin = pluginService.GetPlugIn <TextColorPlugIn>(pluginName) where plugin != null select plugin).ToArray(); // Display a list of the available plugins. Console.WriteLine("\n{0} Plug-ins loaded:\n", plugins.Length); for (int i = 0; i < plugins.Length; i++) { // Here's where we make use of our description. Console.WriteLine("{0}. {1} ({2})", i + 1, plugins[i].Description, plugins[i].GetType().FullName); // Create the text writer interface and add it to the list. writers.Add(plugins[i].CreateWriter()); } Console.Write("0. Quit\n\nSelect a plugin: "); // Loop until we quit. while (true) { if (!Console.KeyAvailable) { continue; } Console.ResetColor(); // Remember our cursor coordinates. int cursorX = Console.CursorLeft; // Cursor position. int cursorY = Console.CursorTop; ConsoleKeyInfo keyValue = Console.ReadKey(false); if (char.IsNumber(keyValue.KeyChar)) { if (keyValue.KeyChar == '0') { break; } // Move to the next line and clear the previous line of text. Console.WriteLine(); Console.Write(new string(' ', Console.BufferWidth - 1)); Console.CursorLeft = 0; // Call our text color writer to print the text in the plugin color. int writerIndex = keyValue.KeyChar - '0'; writers[writerIndex - 1].WriteString($"You pressed #{writerIndex}."); } Console.CursorTop = cursorY; Console.CursorLeft = cursorX; } } catch (Exception ex) { ex.Catch(_ => { Console.Clear(); Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Exception:\n{0}\n\nStack Trace:{1}", ex.Message, ex.StackTrace); }, _log); Console.ResetColor(); #if DEBUG Console.ReadKey(true); #endif } finally { // Always call dispose so we can unload our temporary application domain. //pluginAssemblies.Dispose(); pluginCache.Dispose(); _log.LogEnd(); } }