diff --git a/Vocaluxe/Base/CSongs.cs b/Vocaluxe/Base/CSongs.cs index 67a55e83..a6242d39 100644 --- a/Vocaluxe/Base/CSongs.cs +++ b/Vocaluxe/Base/CSongs.cs @@ -827,7 +827,7 @@ namespace Vocaluxe.Base Category = -1; _SongsLoaded = true; - if (CConfig.Renderer == ERenderer.TR_CONFIG_OPENGL) + if (CConfig.Renderer != ERenderer.TR_CONFIG_SOFTWARE) { CLog.StartBenchmark(2, "Load Cover"); for (int i = 0; i < _Songs.Count; i++) @@ -849,7 +849,7 @@ namespace Vocaluxe.Base public static void LoadCover(long WaitTime, int NumLoads) { - if (CConfig.Renderer == ERenderer.TR_CONFIG_OPENGL) + if (CConfig.Renderer != ERenderer.TR_CONFIG_SOFTWARE) return; //should be removed as soon as the other renderer are ready for queque if (!SongsLoaded) diff --git a/Vocaluxe/Lib/Draw/CDirect3D.cs b/Vocaluxe/Lib/Draw/CDirect3D.cs index d4e7e1f3..3bf614d5 100644 --- a/Vocaluxe/Lib/Draw/CDirect3D.cs +++ b/Vocaluxe/Lib/Draw/CDirect3D.cs @@ -36,6 +36,9 @@ namespace Vocaluxe.Lib.Draw private List _Textures; private List _D3DTextures; + private List _Queque; + + private Object MutexTexture = new Object(); private VertexBuffer _VertexBuffer; @@ -46,14 +49,20 @@ namespace Vocaluxe.Lib.Draw private Bitmap blankMap; private STexture blankTexture; + private Texture transparentTexture; #endregion private vars + /// + /// Creates a new Instance of the CDirect3D Class + /// public CDirect3D() { this.Icon = new System.Drawing.Icon(Path.Combine(System.Environment.CurrentDirectory, CSettings.sIcon)); _Textures = new List(); _D3DTextures = new List(); + _Queque = new List(); + _Keys = new CKeys(); _D3D = new Direct3D(); @@ -86,6 +95,8 @@ namespace Vocaluxe.Lib.Draw _PresentParameters.Multisample = MultisampleType.None; _PresentParameters.MultisampleQuality = 0; + //Apply antialiasing and check if antialiasing mode is supported + #region Antialiasing int quality = 0; if (CConfig.AAMode == EAntiAliasingModes.x0) { @@ -132,12 +143,15 @@ namespace Vocaluxe.Lib.Draw else CLog.LogError("[Direct3D] This AAMode is not supported by this device or driver, fallback to no AA"); } + #endregion Antialiasing - if(CConfig.VSync == EOffOn.TR_CONFIG_ON) + //Apply the VSync configuration + if (CConfig.VSync == EOffOn.TR_CONFIG_ON) _PresentParameters.PresentationInterval = PresentInterval.Default; else _PresentParameters.PresentationInterval = PresentInterval.Immediate; - + + //GMA 950 graphics devices can only process vertices in software mode Capabilities caps = _D3D.GetDeviceCaps(_D3D.Adapters.DefaultAdapter.Adapter, DeviceType.Hardware); CreateFlags flags = CreateFlags.None; if ((caps.DeviceCaps & DeviceCaps.HWTransformAndLight) != 0) @@ -147,14 +161,16 @@ namespace Vocaluxe.Lib.Draw _Device = new Device(_D3D, _D3D.Adapters.DefaultAdapter.Adapter, DeviceType.Hardware, Handle, flags, _PresentParameters); this.CenterToScreen(); - - blankMap = new Bitmap(1, 1); //Quick and Dirty, used for DrawColor + + //This creates a new white texture and adds it to the texture pool + //This texture is used for the DrawRect method + blankMap = new Bitmap(1, 1); Graphics g = Graphics.FromImage(blankMap); g.Clear(Color.White); g.Dispose(); blankTexture = AddTexture(blankMap); - h = ClientSize.Height; - w = ClientSize.Width; + + transparentTexture = new Texture(_Device, 1, 1, 0, Usage.None, Format.A8R8G8B8, Pool.Managed); blankMap.Dispose(); } @@ -186,9 +202,12 @@ namespace Vocaluxe.Lib.Draw RResize(); } #endregion form events - + /// + /// Resizes the viewport + /// private void RResize() { + // The window was minimized, so restore it to the last known size if (ClientSize.Width == 0 || ClientSize.Height == 0) { ClientSize = _SizeBeforeMinimize; @@ -202,28 +221,41 @@ namespace Vocaluxe.Lib.Draw if ((float)w / (float)h > CSettings.GetRenderAspect()) { + //The windows's width is too big w = (int)Math.Round((float)h * CSettings.GetRenderAspect()); x = (ClientSize.Width - w) / 2; } else { + //The windows's height is too big h = (int)Math.Round((float)w / CSettings.GetRenderAspect()); y = (ClientSize.Height - h) / 2; } + //Apply the new sizes to the PresentParameters _PresentParameters.BackBufferWidth = ClientSize.Width; _PresentParameters.BackBufferHeight = ClientSize.Height; ClearScreen(); + //To set new PresentParameters the device has to be resetted Reset(); + //All configurations got flushed due to Reset(), so apply them again Init(); + //Set the new Viewport _Device.Viewport = new Viewport(x, y, w, h); + //Store size so it can get restored after the window gets minimized _SizeBeforeMinimize = ClientSize; } } + /// + /// Triggers the Fullscreen mode + /// private void EnterFullScreen() { + //This currently not using real fullscreen mode but a borderless window + //Real fullscreen could be gained setting _PresentParameters.Windowed = true + //And calling Reset() and Init() after _OldSize = this.ClientSize; this.ClientSize = new Size(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height); this.FormBorderStyle = FormBorderStyle.None; @@ -237,7 +269,9 @@ namespace Vocaluxe.Lib.Draw CConfig.SaveConfig(); } - + /// + /// Triggers the windowed mode + /// private void LeaveFullScreen() { this.ClientSize = _OldSize; @@ -312,34 +346,45 @@ namespace Vocaluxe.Lib.Draw #region implementation + /// + /// Inits the Device + /// + /// True if it succeeded else false public bool Init() { - this.Text = CSettings.GetFullVersionText(); - Matrix translate = Matrix.Translation(new Vector3(-CSettings.iRenderW / 2, CSettings.iRenderH / 2, 0)); - Matrix projection = Matrix.OrthoOffCenterLH(-CSettings.iRenderW / 2, CSettings.iRenderW / 2, -CSettings.iRenderH / 2, CSettings.iRenderH / 2, CSettings.zNear, CSettings.zFar); - _VertexBuffer = new VertexBuffer(_Device, 4 * Marshal.SizeOf(typeof(TexturedColoredVertex)), Usage.WriteOnly | Usage.Dynamic, VertexFormat.Position | VertexFormat.Texture1 | VertexFormat.Diffuse, Pool.Default); - _Device.SetStreamSource(0, _VertexBuffer, 0, Marshal.SizeOf(typeof(TexturedColoredVertex))); - _Device.VertexDeclaration = TexturedColoredVertex.GetDeclaration(_Device); - _Device.SetTransform(TransformState.Projection, projection); - _Device.SetTransform(TransformState.World, translate); - _Device.SetRenderState(RenderState.CullMode, Cull.None); - _Device.SetRenderState(RenderState.AlphaBlendEnable, true); - _Device.SetRenderState(RenderState.Lighting, false); - _Device.SetRenderState(RenderState.DestinationBlend, Blend.InverseSourceAlpha); - _Device.SetRenderState(RenderState.SourceBlend, Blend.SourceAlpha); - if(_PresentParameters.Multisample != MultisampleType.None) - _Device.SetRenderState(RenderState.MultisampleAntialias, true); - _Device.SetSamplerState(0, SamplerState.MinFilter, TextureFilter.Linear); - _Device.SetSamplerState(0, SamplerState.MagFilter, TextureFilter.Linear); - _Device.SetSamplerState(0, SamplerState.MipFilter, TextureFilter.Linear); - _Device.SetSamplerState(0, SamplerState.AddressU, TextureAddress.Clamp); - _Device.SetSamplerState(0, SamplerState.AddressV, TextureAddress.Clamp); - _Device.SetTextureStageState(0, TextureStage.AlphaArg1, TextureArgument.Texture); - _Device.SetTextureStageState(0, TextureStage.AlphaArg2, TextureArgument.Diffuse); - _Device.SetTextureStageState(0, TextureStage.AlphaOperation, TextureOperation.Modulate); - return true; + if (!_Device.Disposed) + { + this.Text = CSettings.GetFullVersionText(); + Matrix translate = Matrix.Translation(new Vector3(-CSettings.iRenderW / 2, CSettings.iRenderH / 2, 0)); + Matrix projection = Matrix.OrthoOffCenterLH(-CSettings.iRenderW / 2, CSettings.iRenderW / 2, -CSettings.iRenderH / 2, CSettings.iRenderH / 2, CSettings.zNear, CSettings.zFar); + _VertexBuffer = new VertexBuffer(_Device, 4 * Marshal.SizeOf(typeof(TexturedColoredVertex)), Usage.WriteOnly | Usage.Dynamic, VertexFormat.Position | VertexFormat.Texture1 | VertexFormat.Diffuse, Pool.Default); + _Device.SetStreamSource(0, _VertexBuffer, 0, Marshal.SizeOf(typeof(TexturedColoredVertex))); + _Device.VertexDeclaration = TexturedColoredVertex.GetDeclaration(_Device); + _Device.SetTransform(TransformState.Projection, projection); + _Device.SetTransform(TransformState.World, translate); + _Device.SetRenderState(RenderState.CullMode, Cull.None); + _Device.SetRenderState(RenderState.AlphaBlendEnable, true); + _Device.SetRenderState(RenderState.Lighting, false); + _Device.SetRenderState(RenderState.DestinationBlend, Blend.InverseSourceAlpha); + _Device.SetRenderState(RenderState.SourceBlend, Blend.SourceAlpha); + if (_PresentParameters.Multisample != MultisampleType.None) + _Device.SetRenderState(RenderState.MultisampleAntialias, true); + _Device.SetSamplerState(0, SamplerState.MinFilter, TextureFilter.Linear); + _Device.SetSamplerState(0, SamplerState.MagFilter, TextureFilter.Linear); + _Device.SetSamplerState(0, SamplerState.MipFilter, TextureFilter.Linear); + _Device.SetSamplerState(0, SamplerState.AddressU, TextureAddress.Clamp); + _Device.SetSamplerState(0, SamplerState.AddressV, TextureAddress.Clamp); + _Device.SetTextureStageState(0, TextureStage.AlphaArg1, TextureArgument.Texture); + _Device.SetTextureStageState(0, TextureStage.AlphaArg2, TextureArgument.Diffuse); + _Device.SetTextureStageState(0, TextureStage.AlphaOperation, TextureOperation.Modulate); + return true; + } + else + return false; } - + /// + /// Starts the rendering + /// public void MainLoop() { _Run = true; @@ -358,36 +403,46 @@ namespace Vocaluxe.Lib.Draw if (_Run) { + //Clear the previous Frame ClearScreen(); + //We want to begin drawing _Device.BeginScene(); + CheckQueque(); _Run = _Run && CGraphics.Draw(); - _Run = CGraphics.UpdateGameLogic(_Keys, _Mouse); + //We finished drawing the frame _Device.EndScene(); + _Run = CGraphics.UpdateGameLogic(_Keys, _Mouse); try { + //Now push the frame to the Viewport _Device.Present(); } catch (Direct3D9Exception) { - if (_Device.TestCooperativeLevel() == ResultCode.DeviceNotReset) //Do only reset when the device in a resetable state! + //In Direct3D devices can get lost. + //This happens for example when opening the Task Manager in Vista/Windows 7 or if a UAC message is opening + //We need to reset the device to get it to workable state again + //After a reset Init() needs to be called because all data in the Direct3D default pool are lost and need to be recreated + if (_Device.TestCooperativeLevel() == ResultCode.DeviceNotReset) { Reset(); Init(); } } + //Apply fullscreen mode if ((CSettings.bFullScreen && !_fullscreen) || (!CSettings.bFullScreen && _fullscreen)) { if (!_fullscreen) EnterFullScreen(); else - LeaveFullScreen(); + LeaveFullScreen(); } if (CTime.IsRunning()) delay = (int)Math.Floor(CConfig.CalcCycleTime() - CTime.GetMilliseconds()); if (delay >= 1) System.Threading.Thread.Sleep(delay); - + //Calculate the FPS Rate and restart the timer after a frame CTime.CalculateFPS(); CTime.Restart(); } @@ -396,19 +451,28 @@ namespace Vocaluxe.Lib.Draw } } + /// + /// Resets the device, all objects in the Direct3D default pool get flushed and need to be recreated + /// public void Reset() { + //Dispose all objects in the default pool, those need to be recreated TexturedColoredVertex.GetDeclaration(_Device).Dispose(); _VertexBuffer.Dispose(); _Device.Reset(_PresentParameters); } + /// + /// Unloads all Textures and other objects used by Direct3D for rendering + /// + /// public bool Unload() { + //Dispose all textures for (int i = 0; i < _D3DTextures.Count; i++) { - _D3DTextures[i].Dispose(); - + if(_D3DTextures[i] != null) + _D3DTextures[i].Dispose(); } TexturedColoredVertex.GetDeclaration(_Device).Dispose(); _VertexBuffer.Dispose(); @@ -417,21 +481,40 @@ namespace Vocaluxe.Lib.Draw return true; } + /// + /// Gets the current viewport width + /// + /// The current viewport width public int GetScreenWidth() { return _Device.Viewport.Width; } + /// + /// Gets the current viewport height + /// + /// The current viewport height public int GetScreenHeight() { return _Device.Viewport.Height; } + /// + /// Calculates the bounds for a CText object + /// + /// The CText object of which the bounds should be calculated for + /// RectangleF object containing the bounds public RectangleF GetTextBounds(CText text) { return GetTextBounds(text, text.Height); } + /// + /// Calculates the bounds for a CText object + /// + /// The CText object of which the bounds should be calculated for + /// The height of the CText object + /// RectangleF object containing the bounds public RectangleF GetTextBounds(CText text, float Height) { CFonts.Height = Height; @@ -442,30 +525,48 @@ namespace Vocaluxe.Lib.Draw #region Basic Draw Methods + /// + /// Removes all textures from the screen + /// public void ClearScreen() { _Device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0); } + + /// + /// Not implemented yet + /// + /// public STexture CopyScreen() { + //FIXME STexture texture = new STexture(-1); return texture; } + /// + /// Not implemented yet + /// + /// public void CopyScreen(ref STexture Texture) { + //FIXME return; } + /// + /// Creates a Screenshot of the current frame + /// public void MakeScreenShot() { string file = "Screenshot_"; string path = Path.Combine(Environment.CurrentDirectory, CSettings.sFolderScreenshots); - + int i = 0; while (File.Exists(Path.Combine(path, file + i.ToString("00000") + ".bmp"))) i++; + //create a surface of the frame using (Surface surface = _Device.GetBackBuffer(0, 0)) { Bitmap screen = new Bitmap(Surface.ToStream(surface, ImageFileFormat.Bmp)); @@ -476,29 +577,74 @@ namespace Vocaluxe.Lib.Draw _Mouse.Visible = true; } + /// + /// Draws a line + /// + /// The alpha value from 0-255 + /// The red value from 0-255 + /// The red value from 0-255 + /// The red value from 0-255 + /// The width of the line + /// The start x-value + /// The start y-value + /// The end x-value + /// The end y-value public void DrawLine(int a, int r, int g, int b, int w, int x1, int y1, int x2, int y2) { SColorF color = new SColorF(a / 255, g / 255, b / 255, a / 255); DrawTexture(blankTexture, new SRectF(x1, y1, x2, y2, 1), color); } + /// + /// Draws a text string + /// + /// The text to be drawn + /// The text's x-position + /// The text's y-position + /// The text's height public void DrawText(string Text, int x, int y, int h) { DrawText(Text, x, y, h, 0f); } + /// + /// Draws a text string + /// + /// The text to be drawn + /// The text's x-position + /// The text's y-position + /// The text's height + /// The text's x-position public void DrawText(string Text, int x, int y, float h, float z) { CFonts.DrawText(Text, h, x, y, z, new SColorF(1f, 1f, 1f, 1f)); } + /// + /// Draws a colored rectangle + /// + /// The color in which the rectangle will be drawn in + /// The coordinates in a SRectF struct public void DrawColor(SColorF color, SRectF rect) { + //blankMap = new Bitmap(1, 1); + //Graphics g = Graphics.FromImage(blankMap); + //g.Clear(Color.White); + //g.Dispose(); + //blankTexture = AddTexture(blankMap); + //blankMap.Dispose(); + DrawTexture(blankTexture, rect, color); + //RemoveTexture(ref blankTexture); } #endregion Basic Draw Methods #region Textures + /// + /// Adds a texture and stores it in the VRam + /// + /// The texture's filepath + /// A STexture object containing the added texture public STexture AddTexture(string TexturePath) { if (System.IO.File.Exists(TexturePath)) @@ -519,18 +665,30 @@ namespace Vocaluxe.Lib.Draw return new STexture(-1); } + /// + /// Calculates the next power of two + /// + /// The value of which the next power of two will be calculated + /// The next power of two private static float NextPowerOfTwo(float n) { if (n < 0) throw new ArgumentOutOfRangeException("n", "Must be positive."); return (float)System.Math.Pow(2, System.Math.Ceiling(System.Math.Log((double)n, 2))); } + /// + /// Adds a texture and stores it in the Vram + /// + /// The Bitmap of which the texute will be created from + /// The path to the texture + /// A STexture object containing the added texture public STexture AddTexture(Bitmap bmp, string TexturePath) { STexture texture = new STexture(-1); if (bmp.Height == 0 || bmp.Width == 0) return texture; int MaxSize; + //Apply the right max size switch (CConfig.TextureQuality) { case ETextureQuality.TR_CONFIG_TEXTURE_LOWEST: @@ -571,10 +729,13 @@ namespace Vocaluxe.Lib.Draw texture.width = w; texture.height = h; + //Older graphics card can only handle textures with sizes being powers of two texture.w2 = (float)NextPowerOfTwo(w); texture.h2 = (float)NextPowerOfTwo(h); + //Create a new Bitmap with the new sizes Bitmap bmp2 = new Bitmap((int)texture.w2, (int)texture.h2); + //Scale the texture Graphics g = Graphics.FromImage(bmp2); g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; @@ -583,13 +744,17 @@ namespace Vocaluxe.Lib.Draw texture.width_ratio = 1f; texture.height_ratio = 1f; - + + //Fill the new Bitmap with the texture data BitmapData bmp_data = bmp2.LockBits(new Rectangle(0, 0, bmp2.Width, bmp2.Height), ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); byte[] Data = new byte[4 * bmp2.Width * bmp2.Height]; Marshal.Copy(bmp_data.Scan0, Data, 0, Data.Length); bmp2.UnlockBits(bmp_data); - + + //Create a new texture in the managed pool, which does not need to be recreated on a lost device + //because a copy of the texture is hold in the Ram Texture t = new Texture(_Device, (int)texture.w2, (int)texture.h2, 0, Usage.AutoGenerateMipMap, Format.A8R8G8B8, Pool.Managed); + //Lock the texture and fill it with the data DataRectangle rect = t.LockRectangle(0, LockFlags.None); for (int i = 0; i < Data.Length; ) { @@ -599,20 +764,29 @@ namespace Vocaluxe.Lib.Draw rect.Data.Position += rect.Pitch; } t.UnlockRectangle(0); - _D3DTextures.Add(t); + bmp2.Dispose(); bmp_data = null; // Add to Texture List - texture.index = _D3DTextures.Count - 1; texture.color = new SColorF(1f, 1f, 1f, 1f); texture.rect = new SRectF(0f, 0f, texture.width, texture.height, 0f); texture.TexturePath = String.Empty; - _Textures.Add(texture); - + lock (MutexTexture) + { + _D3DTextures.Add(t); + texture.index = _D3DTextures.Count - 1; + _Textures.Add(texture); + } + return texture; } + /// + /// Adds a texture and stores it in the Vram + /// + /// The Bitmap of which the texute will be created from + /// A STexture object containing the added texture public STexture AddTexture(Bitmap bmp) { return AddTexture(bmp, String.Empty); @@ -622,12 +796,27 @@ namespace Vocaluxe.Lib.Draw { byte[] PointerData = new Byte[4 * W * H]; Marshal.Copy(Data, PointerData, 0, PointerData.Length); - return AddTexture(W, H , ref PointerData); + return AddTexture(W, H, ref PointerData); } public STexture QuequeTexture(int W, int H, ref byte[] Data) { - return AddTexture(W, H, ref Data); + STexture texture = new STexture(-1); + STextureQueque queque = new STextureQueque(); + + queque.data = Data; + queque.height = H; + queque.width = W; + + lock (MutexTexture) + { + _D3DTextures.Add(null); + texture.index = _D3DTextures.Count - 1; + queque.ID = texture.index; + _Queque.Add(queque); + _Textures.Add(texture); + } + return texture; } public STexture AddTexture(int W, int H, ref byte[] Data) @@ -650,16 +839,26 @@ namespace Vocaluxe.Lib.Draw rect.Data.Position += rect.Pitch; } t.UnlockRectangle(0); - _D3DTextures.Add(t); - texture.index = _D3DTextures.Count - 1; texture.color = new SColorF(1f, 1f, 1f, 1f); texture.rect = new SRectF(0f, 0f, texture.width, texture.height, 0f); texture.TexturePath = String.Empty; - _Textures.Add(texture); + + lock (MutexTexture) + { + _D3DTextures.Add(t); + texture.index = _D3DTextures.Count - 1; + _Textures.Add(texture); + } return texture; } + /// + /// Updates the data of a texture + /// + /// The texture to update + /// A Pointer containing the data of which the texture should be updated + /// True if succeeded public bool UpdateTexture(ref STexture Texture, IntPtr Data) { byte[] PointerData = new Byte[4 * (int)Texture.width * (int)Texture.height]; @@ -668,9 +867,15 @@ namespace Vocaluxe.Lib.Draw return UpdateTexture(ref Texture, ref PointerData); } + /// + /// Updates the data of a texture + /// + /// The texture to update + /// A byte array containing the new texture's data + /// True if succeeded public bool UpdateTexture(ref STexture Texture, ref byte[] Data) { - if ((Texture.index >= 0) && (_Textures.Count > 0) && (_D3DTextures.Count > Texture.index)) + if ((Texture.index >= 0) && (_Textures.Count > 0) && (_D3DTextures.Count > Texture.index) && _TextureExists(ref Texture)) { DataRectangle rect = _D3DTextures[Texture.index].LockRectangle(0, LockFlags.None); for (int i = 0; i < Data.Length; ) @@ -684,77 +889,134 @@ namespace Vocaluxe.Lib.Draw Texture.height_ratio = Texture.height / NextPowerOfTwo(Texture.height); Texture.width_ratio = Texture.width / NextPowerOfTwo(Texture.width); + return true; } - return true; + else + return false; } - private bool _TextureExists(STexture Texture) + /// + /// Checks if a texture exists + /// + /// The texture to check + /// True if the texture exists + private bool _TextureExists(ref STexture Texture) { - if ((Texture.index > 0) && (_Textures.Count > 0)) + lock (MutexTexture) { for (int i = 0; i < _Textures.Count; i++) { - if (_Textures[i].index == Texture.index) + if (Texture.index == _Textures[i].index) { - return true; + if (_Textures[i].index >= 0) + { + Texture = _Textures[i]; + return true; + } + break; } } } return false; } + /// + /// Removes a texture from the Vram + /// + /// The texture to be removed public void RemoveTexture(ref STexture Texture) { - if ((Texture.index >= 0) && (_Textures.Count > 0)) + lock (MutexTexture) { - for (int i = 0; i < _Textures.Count; i++) + if ((Texture.index >= 0) && (_Textures.Count > 0)) { - if (_Textures[i].index == Texture.index) + for (int i = 0; i < _Textures.Count; i++) { - _D3DTextures[Texture.index].Dispose(); - _Textures.RemoveAt(i); - Texture.index = -1; - GC.Collect(); - break; + if (_Textures[i].index == Texture.index) + { + _D3DTextures[Texture.index].Dispose(); + _D3DTextures[Texture.index] = null; + _Textures.RemoveAt(i); + Texture.index = -1; + Texture.ID = -1; + } } } } } + /// + /// Draws a texture + /// + /// The texture to be drawn public void DrawTexture(STexture Texture) { if ((Texture.index >= 0) && (_Textures.Count > 0) && (_D3DTextures.Count > Texture.index)) DrawTexture(Texture, Texture.rect, Texture.color); } + /// + /// Draws a texture + /// + /// The texture to be drawn + /// A SRectF struct containing the destination coordinates public void DrawTexture(STexture Texture, SRectF rect) { if ((Texture.index >= 0) && (_Textures.Count > 0) && (_D3DTextures.Count > Texture.index)) DrawTexture(Texture, rect, Texture.color, false); } + /// + /// Draws a texture + /// + /// The texture to be drawn + /// A SRectF struct containing the destination coordinates + /// A SColorF struct containing a color which the texture will be colored in public void DrawTexture(STexture Texture, SRectF rect, SColorF color) { if ((Texture.index >= 0) && (_Textures.Count > 0) && (_D3DTextures.Count > Texture.index)) DrawTexture(Texture, rect, color, false); } + /// + /// Draws a texture + /// + /// The texture to be drawn + /// A SRectF struct containing the destination coordinates + /// A SColorF struct containing a color which the texture will be colored in + /// A SRectF struct containing which part of the texture should be drawn public void DrawTexture(STexture Texture, SRectF rect, SColorF color, SRectF bounds) { if ((Texture.index >= 0) && (_Textures.Count > 0) && (_D3DTextures.Count > Texture.index)) DrawTexture(Texture, rect, color, bounds, false); } + /// + /// Draws a texture + /// + /// The texture to be drawn + /// A SRectF struct containing the destination coordinates + /// A SColorF struct containing a color which the texture will be colored in + /// True if the texture should be mirrored public void DrawTexture(STexture Texture, SRectF rect, SColorF color, bool mirrored) { if ((Texture.index >= 0) && (_Textures.Count > 0) && (_D3DTextures.Count > Texture.index)) DrawTexture(Texture, rect, color, new SRectF(0, 0, CSettings.iRenderW, CSettings.iRenderH, rect.Z), mirrored); } + /// + /// Draws a texture + /// + /// The texture to be drawn + /// A SRectF struct containing the destination coordinates + /// A SColorF struct containing a color which the texture will be colored in + /// A SRectF struct containing which part of the texture should be drawn + /// True if the texture should be mirrored public void DrawTexture(STexture Texture, SRectF rect, SColorF color, SRectF bounds, bool mirrored) { - if ((Texture.index >= 0) && (_Textures.Count > 0) && (_D3DTextures.Count > Texture.index)) + if ((Texture.index >= 0) && (_Textures.Count > 0) && (_D3DTextures.Count > Texture.index) && _TextureExists(ref Texture)) { + //Calculate the position float x1 = (bounds.X - rect.X) / rect.W * Texture.width_ratio; float x2 = (bounds.X + bounds.W - rect.X) / rect.W * Texture.width_ratio; float y1 = (bounds.Y - rect.Y) / rect.H * Texture.height_ratio; @@ -772,6 +1034,7 @@ namespace Vocaluxe.Lib.Draw if (y2 > Texture.height_ratio) y2 = Texture.height_ratio; + //Calculate the size float rx1 = rect.X; float rx2 = rect.X + rect.W; float ry1 = rect.Y; @@ -789,7 +1052,8 @@ namespace Vocaluxe.Lib.Draw if (ry2 > bounds.Y + bounds.H) ry2 = bounds.Y + bounds.H; - rx1 -= 0.5f; // Align pixels + //Align the pixels because Direct3D expects the pixels to be the left top corner + rx1 -= 0.5f; ry1 -= 0.5f; rx2 -= 0.5f; ry2 -= 0.5f; @@ -801,6 +1065,8 @@ namespace Vocaluxe.Lib.Draw if (color.G >= 1f) color.G = 1f; + //Apply rotation + //FIXME: Rotated textures get distorted when they hit the border of the window if (rect.Rotation != 0) { rect.Rotation = rect.Rotation * (float)Math.PI / 180; @@ -812,36 +1078,45 @@ namespace Vocaluxe.Lib.Draw Matrix rotation = Matrix.RotationZ(-rect.Rotation); Matrix translationB = Matrix.Translation(centerX, centerY, 0); + //Multiplicate the matrices to get the real world matrix, + //First shift the texture into the center + //Rotate it and shift it back to the origin position + //Apply the originTranslation after Matrix result = translationA * rotation * translationB * originTranslation; _Device.SetTransform(TransformState.World, result); } Color c = Color.FromArgb((int)(color.A * 255 * CGraphics.GlobalAlpha), (int)(color.R * 255), (int)(color.G * 255), (int)(color.B * 255)); + + //Create new vertices and write them into a vertexbuffer DataStream stream = _VertexBuffer.Lock(0, 0, LockFlags.Discard); if (!mirrored) { stream.WriteRange(new[] { - new TexturedColoredVertex(new Vector3(rx1, -ry1, rect.Z + CGraphics.ZOffset), new Vector2(x1, y1), c.ToArgb()), - new TexturedColoredVertex(new Vector3(rx1, -ry2, rect.Z + CGraphics.ZOffset), new Vector2(x1, y2), c.ToArgb()), - new TexturedColoredVertex(new Vector3(rx2, -ry2, rect.Z + CGraphics.ZOffset), new Vector2(x2, y2), c.ToArgb()), - new TexturedColoredVertex(new Vector3(rx2, -ry1, rect.Z + CGraphics.ZOffset), new Vector2(x2, y1), c.ToArgb()), - }); + new TexturedColoredVertex(new Vector3(rx1, -ry1, rect.Z + CGraphics.ZOffset), new Vector2(x1, y1), c.ToArgb()), + new TexturedColoredVertex(new Vector3(rx1, -ry2, rect.Z + CGraphics.ZOffset), new Vector2(x1, y2), c.ToArgb()), + new TexturedColoredVertex(new Vector3(rx2, -ry2, rect.Z + CGraphics.ZOffset), new Vector2(x2, y2), c.ToArgb()), + new TexturedColoredVertex(new Vector3(rx2, -ry1, rect.Z + CGraphics.ZOffset), new Vector2(x2, y1), c.ToArgb()), + }); } else { stream.WriteRange(new[] { - new TexturedColoredVertex(new Vector3(rx1, -ry1, rect.Z + CGraphics.ZOffset), new Vector2(x1, -y1), c.ToArgb()), - new TexturedColoredVertex(new Vector3(rx1, -ry2, rect.Z + CGraphics.ZOffset), new Vector2(x1, -y2), c.ToArgb()), - new TexturedColoredVertex(new Vector3(rx2, -ry2, rect.Z + CGraphics.ZOffset), new Vector2(x2, -y2), c.ToArgb()), - new TexturedColoredVertex(new Vector3(rx2, -ry1, rect.Z + CGraphics.ZOffset), new Vector2(x2, -y1), c.ToArgb()), + new TexturedColoredVertex(new Vector3(rx1, -ry1, rect.Z + CGraphics.ZOffset), new Vector2(x1, -y1), c.ToArgb()), + new TexturedColoredVertex(new Vector3(rx1, -ry2, rect.Z + CGraphics.ZOffset), new Vector2(x1, -y2), c.ToArgb()), + new TexturedColoredVertex(new Vector3(rx2, -ry2, rect.Z + CGraphics.ZOffset), new Vector2(x2, -y2), c.ToArgb()), + new TexturedColoredVertex(new Vector3(rx2, -ry1, rect.Z + CGraphics.ZOffset), new Vector2(x2, -y1), c.ToArgb()), }); } _VertexBuffer.Unlock(); stream.Dispose(); + //Set the texture _Device.SetTexture(0, _D3DTextures[Texture.index]); + //Draw 2 triangles to build a quad _Device.DrawPrimitives(PrimitiveType.TriangleFan, 0, 2); + //Reapply old matrices if the texture was rotated if (rect.Rotation != 0) { Matrix originTranslation = Matrix.Translation(new Vector3(-CSettings.iRenderW / 2, CSettings.iRenderH / 2, 0)); @@ -850,112 +1125,258 @@ namespace Vocaluxe.Lib.Draw } } + /// + /// Draws a texture + /// + /// The texture to be drawn + /// A SRectF struct containing the destination coordinates + /// A SColorF struct containing a color which the texture will be colored in + /// A Value ranging from 0 to 1 containing the beginning of the texture + /// A Value ranging from 0 to 1 containing the ending of the texture + public void DrawTexture(STexture Texture, SRectF rect, SColorF color, float begin, float end) { - - float x1 = 0f + begin * Texture.width_ratio; - float x2 = Texture.width_ratio * end; - float y1 = 0f; - float y2 = Texture.height_ratio; - - float rx1 = rect.X + begin* rect.W; - float rx2 = rect.X + end * rect.W; - float ry1 = rect.Y; - float ry2 = rect.Y + rect.H; - - rx1 -= 0.5f; // Align pixels - ry1 -= 0.5f; - rx2 -= 0.5f; - ry2 -= 0.5f; - - Color c = Color.FromArgb((int)(color.A * 255 * CGraphics.GlobalAlpha), (int)(color.R * 255), (int)(color.G * 255), (int)(color.B * 255)); - DataStream stream = _VertexBuffer.Lock(0, 0, LockFlags.Discard); - stream.WriteRange(new[] { - new TexturedColoredVertex(new Vector3(rx1, ry1*-1f, rect.Z + CGraphics.ZOffset), new Vector2(x1, y1), c.ToArgb()), - new TexturedColoredVertex(new Vector3(rx1, ry2*-1f, rect.Z + CGraphics.ZOffset), new Vector2(x1, y2), c.ToArgb()), - new TexturedColoredVertex(new Vector3(rx2, ry2*-1f, rect.Z + CGraphics.ZOffset), new Vector2(x2, y2), c.ToArgb()), - new TexturedColoredVertex(new Vector3(rx2, ry1*-1f, rect.Z + CGraphics.ZOffset), new Vector2(x2, y1), c.ToArgb()), - }); - _VertexBuffer.Unlock(); - stream.Dispose(); - _Device.SetTexture(0, _D3DTextures[Texture.index]); - _Device.DrawPrimitives(PrimitiveType.TriangleFan, 0, 2); - } - - public void DrawTextureReflection(STexture Texture, SRectF rect, SColorF color, SRectF bounds, float space, float height) - { - if (rect.W == 0f || rect.H == 0f || bounds.H == 0f || bounds.W == 0f || color.A == 0f || height <= 0f) - return; - - if (bounds.X > rect.X + rect.W || bounds.X + bounds.W < rect.X) - return; - - if (bounds.Y > rect.Y + rect.H || bounds.Y + bounds.H < rect.Y) - return; - - if (height > bounds.H) - height = bounds.H; - - if (_TextureExists(Texture)) + if (_TextureExists(ref Texture)) { - float x1 = (bounds.X - rect.X) / rect.W * Texture.width_ratio; - float x2 = (bounds.X + bounds.W - rect.X) / rect.W * Texture.width_ratio; - float y1 = (bounds.Y - rect.Y + rect.H - height) / rect.H * Texture.height_ratio; - float y2 = (bounds.Y + bounds.H - rect.Y) / rect.H * Texture.height_ratio; + float x1 = 0f + begin * Texture.width_ratio; + float x2 = Texture.width_ratio * end; + float y1 = 0f; + float y2 = Texture.height_ratio; - if (x1 < 0) - x1 = 0f; + float rx1 = rect.X + begin * rect.W; + float rx2 = rect.X + end * rect.W; + float ry1 = rect.Y; + float ry2 = rect.Y + rect.H; - if (x2 > Texture.width_ratio) - x2 = Texture.width_ratio; - - if (y1 < 0) - y1 = 0f; - - if (y2 > Texture.height_ratio) - y2 = Texture.height_ratio; - - - float rx1 = rect.X; - float rx2 = rect.X + rect.W; - float ry1 = rect.Y + rect.H + space; - float ry2 = rect.Y + rect.H + space + height; - - if (rx1 < bounds.X) - rx1 = bounds.X; - - if (rx2 > bounds.X + bounds.W) - rx2 = bounds.X + bounds.W; - - if (ry1 < bounds.Y + space) - ry1 = bounds.Y + space; - - if (ry2 > bounds.Y + bounds.H + space + height) - ry2 = bounds.Y + bounds.H + space + height; - - rx1 -= 0.5f; // Align pixels + //Align the pixels because Direct3D expects the pixels to be the left top corner + rx1 -= 0.5f; ry1 -= 0.5f; rx2 -= 0.5f; ry2 -= 0.5f; - DataStream stream = _VertexBuffer.Lock(0, 0, LockFlags.Discard); - Color c = Color.FromArgb((int)(color.A * 255 * CGraphics.GlobalAlpha), (int)(color.R * 255), (int)(color.G * 255), (int)(color.B * 255)); - Color t = Color.FromArgb(0, (int)(color.R * 255), (int)(color.G * 255), (int)(color.B * 255)); + //Apply rotation + //FIXME: Rotated textures get distorted when they hit the border of the window + if (rect.Rotation != 0) + { + rect.Rotation = rect.Rotation * (float)Math.PI / 180; + float centerX = (rx1 + rx2) / 2f; + float centerY = -(ry1 + ry2) / 2f; + + Matrix originTranslation = _Device.GetTransform(TransformState.World); + Matrix translationA = Matrix.Translation(-centerX, -centerY, 0); + Matrix rotation = Matrix.RotationZ(-rect.Rotation); + Matrix translationB = Matrix.Translation(centerX, centerY, 0); + + //Multiplicate the matrices to get the real world matrix, + //First shift the texture into the center + //Rotate it and shift it back to the origin position + //Apply the originTranslation after + Matrix result = translationA * rotation * translationB * originTranslation; + + _Device.SetTransform(TransformState.World, result); + } + + //Create new vertices and write them into a vertexbuffer + DataStream stream = _VertexBuffer.Lock(0, 0, LockFlags.Discard); stream.WriteRange(new[] { - new TexturedColoredVertex(new Vector3(rx2, -ry1, rect.Z + CGraphics.ZOffset), new Vector2(x2, y2), c.ToArgb()), - new TexturedColoredVertex(new Vector3(rx2, -ry2, rect.Z + CGraphics.ZOffset), new Vector2(x2, y1), t.ToArgb()), - new TexturedColoredVertex(new Vector3(rx1, -ry2, rect.Z + CGraphics.ZOffset), new Vector2(x1, y1), t.ToArgb()), - new TexturedColoredVertex(new Vector3(rx1, -ry1, rect.Z + CGraphics.ZOffset), new Vector2(x1, y2), c.ToArgb()), + new TexturedColoredVertex(new Vector3(rx1, -ry1, rect.Z + CGraphics.ZOffset), new Vector2(x1, y1), c.ToArgb()), + new TexturedColoredVertex(new Vector3(rx1, -ry2, rect.Z + CGraphics.ZOffset), new Vector2(x1, y2), c.ToArgb()), + new TexturedColoredVertex(new Vector3(rx2, -ry2, rect.Z + CGraphics.ZOffset), new Vector2(x2, y2), c.ToArgb()), + new TexturedColoredVertex(new Vector3(rx2, -ry1, rect.Z + CGraphics.ZOffset), new Vector2(x2, y1), c.ToArgb()), }); _VertexBuffer.Unlock(); stream.Dispose(); + //Set the texture _Device.SetTexture(0, _D3DTextures[Texture.index]); + //Draw 2 triangles to build a quad _Device.DrawPrimitives(PrimitiveType.TriangleFan, 0, 2); + + //Reapply old matrices if the texture was rotated + if (rect.Rotation != 0) + { + Matrix originTranslation = Matrix.Translation(new Vector3(-CSettings.iRenderW / 2, CSettings.iRenderH / 2, 0)); + _Device.SetTransform(TransformState.World, originTranslation); + } } } + /// + /// Draws a reflection of a texture + /// + /// The texture of which a reflection should be drawn + /// A SRectF struct containing the destination coordinates + /// A SColorF struct containing a color which the texture will be colored in + /// A SRectF struct containing which part of the texture should be drawn + /// The space between the texture and the reflection + /// The height of the reflection + public void DrawTextureReflection(STexture Texture, SRectF rect, SColorF color, SRectF bounds, float space, float height) + { + if (_TextureExists(ref Texture)) + { + if (rect.W == 0f || rect.H == 0f || bounds.H == 0f || bounds.W == 0f || color.A == 0f || height <= 0f) + return; + + if (bounds.X > rect.X + rect.W || bounds.X + bounds.W < rect.X) + return; + + if (bounds.Y > rect.Y + rect.H || bounds.Y + bounds.H < rect.Y) + return; + + if (height > bounds.H) + height = bounds.H; + + if (_TextureExists(ref Texture)) + { + float x1 = (bounds.X - rect.X) / rect.W * Texture.width_ratio; + float x2 = (bounds.X + bounds.W - rect.X) / rect.W * Texture.width_ratio; + float y1 = (bounds.Y - rect.Y + rect.H - height) / rect.H * Texture.height_ratio; + float y2 = (bounds.Y + bounds.H - rect.Y) / rect.H * Texture.height_ratio; + + if (x1 < 0) + x1 = 0f; + + if (x2 > Texture.width_ratio) + x2 = Texture.width_ratio; + + if (y1 < 0) + y1 = 0f; + + if (y2 > Texture.height_ratio) + y2 = Texture.height_ratio; + + + float rx1 = rect.X; + float rx2 = rect.X + rect.W; + float ry1 = rect.Y + rect.H + space; + float ry2 = rect.Y + rect.H + space + height; + + if (rx1 < bounds.X) + rx1 = bounds.X; + + if (rx2 > bounds.X + bounds.W) + rx2 = bounds.X + bounds.W; + + if (ry1 < bounds.Y + space) + ry1 = bounds.Y + space; + + if (ry2 > bounds.Y + bounds.H + space + height) + ry2 = bounds.Y + bounds.H + space + height; + + //Align the pixels because Direct3D expects the pixels to be the left top corner + rx1 -= 0.5f; + ry1 -= 0.5f; + rx2 -= 0.5f; + ry2 -= 0.5f; + + //Apply rotation + //FIXME: Rotated textures get distorted when they hit the border of the window + if (rect.Rotation != 0) + { + rect.Rotation = rect.Rotation * (float)Math.PI / 180; + float centerX = (rx1 + rx2) / 2f; + float centerY = -(ry1 + ry2) / 2f; + + Matrix originTranslation = _Device.GetTransform(TransformState.World); + Matrix translationA = Matrix.Translation(-centerX, -centerY, 0); + Matrix rotation = Matrix.RotationZ(-rect.Rotation); + Matrix translationB = Matrix.Translation(centerX, centerY, 0); + + //Multiplicate the matrices to get the real world matrix, + //First shift the texture into the center + //Rotate it and shift it back to the origin position + //Apply the originTranslation after + Matrix result = translationA * rotation * translationB * originTranslation; + + _Device.SetTransform(TransformState.World, result); + } + + Color c = Color.FromArgb((int)(color.A * 255 * CGraphics.GlobalAlpha), (int)(color.R * 255), (int)(color.G * 255), (int)(color.B * 255)); + Color transparent = Color.FromArgb(0, (int)(color.R * 255), (int)(color.G * 255), (int)(color.B * 255)); + + //Create new vertices and write them into a vertexbuffer + DataStream stream = _VertexBuffer.Lock(0, 0, LockFlags.Discard); + stream.WriteRange(new[] { + new TexturedColoredVertex(new Vector3(rx2, -ry1, rect.Z + CGraphics.ZOffset), new Vector2(x2, y2), c.ToArgb()), + new TexturedColoredVertex(new Vector3(rx2, -ry2, rect.Z + CGraphics.ZOffset), new Vector2(x2, y1), transparent.ToArgb()), + new TexturedColoredVertex(new Vector3(rx1, -ry2, rect.Z + CGraphics.ZOffset), new Vector2(x1, y1), transparent.ToArgb()), + new TexturedColoredVertex(new Vector3(rx1, -ry1, rect.Z + CGraphics.ZOffset), new Vector2(x1, y2), c.ToArgb()), + }); + _VertexBuffer.Unlock(); + stream.Dispose(); + //Set the texture + _Device.SetTexture(0, _D3DTextures[Texture.index]); + //Draw 2 triangles to build a quad + _Device.DrawPrimitives(PrimitiveType.TriangleFan, 0, 2); + + //Reapply old matrices if the texture was rotated + if (rect.Rotation != 0) + { + Matrix originTranslation = Matrix.Translation(new Vector3(-CSettings.iRenderW / 2, CSettings.iRenderH / 2, 0)); + _Device.SetTransform(TransformState.World, originTranslation); + } + } + } + } + + private void CheckQueque() + { + lock (MutexTexture) + { + if (_Queque.Count == 0) + return; + + STextureQueque q = _Queque[0]; + STexture texture = new STexture(-1); + int index = -1; + for (int i = 0; i < _Textures.Count; i++) + { + if (_Textures[i].index == q.ID) + { + texture = _Textures[i]; + index = i; + break; + } + } + + if (texture.index < 0) + return; + + texture.width = q.width; + texture.height = q.height; + texture.w2 = NextPowerOfTwo(texture.width); + texture.h2 = NextPowerOfTwo(texture.height); + + texture.width_ratio = texture.width / texture.w2; + texture.height_ratio = texture.height / texture.h2; + + Texture t = new Texture(_Device, (int)texture.w2, (int)texture.h2, 0, Usage.AutoGenerateMipMap, Format.A8R8G8B8, Pool.Managed); + DataRectangle rect = t.LockRectangle(0, LockFlags.None); + for (int i = 0; i < q.data.Length; ) + { + rect.Data.Write(q.data, i, 4 * q.width); + i += 4 * q.width; + rect.Data.Position = rect.Data.Position - 4 * q.width; + rect.Data.Position += rect.Pitch; + } + t.UnlockRectangle(0); + _D3DTextures[q.ID] = t; + + // Add to Texture List + texture.color = new SColorF(1f, 1f, 1f, 1f); + texture.rect = new SRectF(0f, 0f, texture.width, texture.height, 0f); + texture.TexturePath = String.Empty; + + _Textures[index] = texture; + _Queque.RemoveAt(0); + } + } + + /// + /// Gets the count of current textures + /// + /// The amount of textures public int TextureCount() { return _Textures.Count; @@ -968,12 +1389,12 @@ namespace Vocaluxe.Lib.Draw { private static VertexDeclaration sDeclaration; public static VertexElement[] Elements = - { - new VertexElement(0, 0, DeclarationType.Float3, DeclarationMethod.Default, DeclarationUsage.Position, 0), - new VertexElement(0, sizeof(float) *3, DeclarationType.Float2, DeclarationMethod.Default, DeclarationUsage.TextureCoordinate, 0), - new VertexElement(0, sizeof(float) * 3 + sizeof(float)*2, DeclarationType.Color, DeclarationMethod.Default, DeclarationUsage.Color, 0), - VertexElement.VertexDeclarationEnd - }; + { + new VertexElement(0, 0, DeclarationType.Float3, DeclarationMethod.Default, DeclarationUsage.Position, 0), + new VertexElement(0, sizeof(float) *3, DeclarationType.Float2, DeclarationMethod.Default, DeclarationUsage.TextureCoordinate, 0), + new VertexElement(0, sizeof(float) * 3 + sizeof(float)*2, DeclarationType.Color, DeclarationMethod.Default, DeclarationUsage.Color, 0), + VertexElement.VertexDeclarationEnd + }; public Vector3 Position; public Vector2 Texture; diff --git a/Vocaluxe/Screens/CScreenSong.cs b/Vocaluxe/Screens/CScreenSong.cs index abc609de..68865476 100644 --- a/Vocaluxe/Screens/CScreenSong.cs +++ b/Vocaluxe/Screens/CScreenSong.cs @@ -65,13 +65,19 @@ namespace Vocaluxe.Screens if (KeyEvent.Handled) return true; + if (!Char.IsControl(KeyEvent.Unicode)) + { + JumpTo(KeyEvent.Unicode); + return true; + } + switch (KeyEvent.Key) { case Keys.Escape: if (CSongs.Category < 0 || CConfig.Tabs == EOffOn.TR_CONFIG_OFF) CGraphics.FadeTo(EScreens.ScreenMain); break; - + case Keys.Enter: if (CSongs.NumVisibleSongs > 0) StartSong(SongMenus[htSongMenus(SongMenu)].GetSelectedSong()); @@ -101,34 +107,34 @@ namespace Vocaluxe.Screens } break; - case Keys.A: - if (!_SearchActive && KeyEvent.Mod == Modifier.None) - { - StartRandomAllSongs(); - } - if (KeyEvent.Mod == Modifier.Ctrl) - { - StartRandomVisibleSongs(); - } - break; + //case Keys.A: + // if (!_SearchActive && KeyEvent.Mod == Modifier.None) + // { + // StartRandomAllSongs(); + // } + // if (KeyEvent.Mod == Modifier.Ctrl) + // { + // StartRandomVisibleSongs(); + // } + // break; - case Keys.F: - if (KeyEvent.Mod == Modifier.Ctrl){ - if (_SearchActive) - { - _SearchActive = false; - _SearchText = String.Empty; - ApplyNewSearchFilter(_SearchText); - } - else - { - _SearchActive = true; - } - } - break; + //case Keys.F: + // if (KeyEvent.Mod == Modifier.Ctrl){ + // if (_SearchActive) + // { + // _SearchActive = false; + // _SearchText = String.Empty; + // ApplyNewSearchFilter(_SearchText); + // } + // else + // { + // _SearchActive = true; + // } + // } + // break; case Keys.R: - if (CSongs.Category != -1) + if (CSongs.Category != -1 && KeyEvent.Mod == Modifier.Ctrl) { SongMenus[htSongMenus(SongMenu)].SetSelectedSong(CSongs.GetRandomSong()); } @@ -288,6 +294,23 @@ namespace Vocaluxe.Screens CGraphics.FadeTo(EScreens.ScreenNames); } + private void JumpTo(char Letter) + { + int song = SongMenus[htSongMenus(SongMenu)].GetSelectedSong(); + int id = -1; + if (song > -1 && song < CSongs.NumVisibleSongs) + { + id = CSongs.VisibleSongs[song].ID; + } + + Vocaluxe.Lib.Song.CSong s = Array.Find(CSongs.VisibleSongs, element => element.Artist.StartsWith(Letter.ToString(), StringComparison.OrdinalIgnoreCase)); + if (s != null && s.ID > -1) + { + id = s.ID; + SongMenus[htSongMenus(SongMenu)].SetSelectedSong(id); + } + } + private void ApplyNewSearchFilter(string NewFilterString) { int song = SongMenus[htSongMenus(SongMenu)].GetSelectedSong();