The Issue
- Upon changing the resolution from 1920x1080 to 800x600 (both fullscreen) the skin textures/sprites are not reloaded, and given that I don't have a cursor.png, but only a cursor@2x.png file in my skin, and I switched from a resolution that uses @2x (HD) files to a resolution that uses SD files, osu! basically didn't re-assign the correct sprite. (Nor did it swap to the default skin's cursor.png either.) Causing an invisible cursor.
Now, while having an invisible cursor is pretty bad already, I thought i'd have some fun and try to play a map like this, but osu! just crashed giving me a null exception for some texture/sprite stuff (it's pretty obvious why).
Crash Log
System.ArgumentNullException: This method does not accept null for this parameter.
Parameter name: texture
at Microsoft.Xna.Framework.Graphics.SpriteBatch.InternalDraw(Texture2D texture, Vector4& destination, Boolean scaleDestination, Nullable`1& sourceRectangle, Color color, Single rotation, Vector2& origin, SpriteEffects effects, Single depth)
at Microsoft.Xna.Framework.Graphics.SpriteBatch.Draw(Texture2D texture, Vector2 position, Nullable`1 sourceRectangle, Color color, Single rotation, Vector2 origin, Vector2 scale, SpriteEffects effects, Single layerDepth)
at #jj.#om.Draw()
at #jj.#qp.Draw()
at #Di.#Ci.Draw()
at #4h.#3h.#xR()
at #4h.#3h.Draw()
at #tb.#zb.Draw()
at #Lg.#Ng.Draw()
at #tb.#zb.#8s()
at #tb.#zb.#jt(Object , EventArgs )
at #tb.#Db.#Dt()
at #tb.#Tb.#Rv(Object , EventArgs )
at System.Windows.Forms.Application.ThreadContext.System.Windows.Forms.UnsafeNativeMethods.IMsoComponent.FDoIdle(Int32 grfidlef)
at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.Run(Form mainForm)
at #tb.#Tb.Run()
at #tb.#zb.Run()
at #Lg.#mp.#Hyb(String , Boolean , Boolean )
Video(Excuse the weird 'cut-off', my Dxtory was still set to record at 1280x720.)
(When the video ends osu! basically just crashed.)
(When the video ends osu! basically just crashed.)
Proper Explanation
- So let me just explain WHY this happens a bit more clearly...
For resolutions of 800 pixels in height and above osu! will use @2x (referred to as HD) sprites.
Resolutions lower than that will use the 'default' files without @2x behind them (referred to as SD).
Now, because I'm basically telling osu! to switch from a resolution that uses HD sprites to one that uses SD sprites,
it should re-load the sprites, which it does, as long as there is a SD version of the sprite in the skin folder.
If there is not, however, it doesn't assign the default sprite to it, like it generally should.
And what you get is basically what this post is all about.
Replication Steps
- Use a resolution higher than ?x800
- Use a skin with ONLY a @2x version of the cursor sprite. So DO HAVE a cursor@2x.png and NO cursor.png.
- In-game, change the resolution to anything LOWER than ?x800. (So 800x600, for example.)
- Observe as bad things happen. (Sprite misalignment, default sprite not getting assigned, and potentially osu! crashing.)
More Information / Notes
- I can replicate this on both Stable & CE.
- Yes, it's a bit dodgy skinning on my part, but regardless, it should still assign the default skin's sprite if there is none in the skin folder.
- Also, this has the same root cause as probably this thread.
(So if this get fixed, both threads/issues should simultaneously be resolved.) - Also see other people's posts.