private void DrawSliderBody(BMAPI.v1.HitObjects.SliderObject hitObject, float alpha, int radius, int zindex, byte reverseArrowType) { float smallLength = hitObject.TotalLength; Color color = Color.White; float depthHigh = (zindex * 3 + 2) / 1000.0f; float depthMed = (zindex * 3 + 1) / 1000.0f; float depthLow = (zindex * 3) / 1000.0f; byte alphaByte = (byte)(255 * alpha); for (float i = 0; i < smallLength + 10; i += 10) { if (i > smallLength) { i = smallLength; } // TODO: flip when hardrock Vector2 pos = hitObject.PositionAtTime(i / smallLength); int diameter = this.circleDiameter; color.A = alphaByte; this.sliderEdgeTexture.Draw(pos, diameter, diameter, new Vector2(0.5f * diameter), color); //this.spriteBatch.Draw(this.sliderEdgeTexture, rect, null, color, 0f, Vector2.Zero, SpriteEffects.None, 0.4f + depthHigh); color.A = 255; //this.spriteBatch.Draw(this.sliderBodyTexture, rect, null, color, 0f, Vector2.Zero, SpriteEffects.None, 0.4f + depthMed); this.sliderBodyTexture.Draw(pos, diameter, diameter, new Vector2(0.5f * diameter), color); if (i == smallLength) { break; } } if (reverseArrowType != 0) { /* * color.A = alphaByte; * Rectangle mode; * float rotation; * if (reverseArrowType == 1) * { * mode = lastRect; * rotation = (float)Math.Atan2(lastRectDiff.Y - lastRect.Y, lastRectDiff.X - lastRect.X); * } * else * { * rotation = (float)Math.Atan2(firstRectDiff.Y - firstRect.Y, firstRectDiff.X - firstRect.X); * mode = firstRect; * } * mode.X += 52; * mode.Y += 52; * this.spriteBatch.Draw(this.reverseArrowTexture, mode, null, color, rotation, new Vector2(64.0f), SpriteEffects.None, 0.4f + depthLow); */ } }
private void DrawSlider(BMAPI.v1.HitObjects.SliderObject hitObject, float alpha, float approachCircleValue, bool isBackground) { float time = (float)(this.songPlayer.SongTime - hitObject.StartTime) / (float)((hitObject.SegmentEndTime - hitObject.StartTime) * hitObject.RepeatCount); byte reverseArrowType = (hitObject.RepeatCount > 1) ? (byte)1 : (byte)0; if (time < 0) { if (isBackground) { this.DrawSliderBody(hitObject, alpha, this.circleDiameter / 2, reverseArrowType); this.DrawHitcircle(hitObject, alpha); } else { this.DrawApproachCircle(hitObject, alpha, approachCircleValue); } return; } else if (time > 1) { time = 1; } time *= hitObject.RepeatCount; if (time > 1) { bool drawArrow = time - (hitObject.RepeatCount - 1) < 0; int order = 0; while (time > 1) { time -= 1; order++; reverseArrowType = drawArrow ? (byte)1 : (byte)0; } if (order % 2 != 0) { time = 1 - time; reverseArrowType = drawArrow ? (byte)2 : (byte)0; } } if (isBackground) { this.DrawSliderBody(hitObject, alpha, this.circleDiameter / 2, reverseArrowType); } else { Vector2 pos = hitObject.PositionAtTime(time); float diameter = this.circleDiameter * 2.0f; this.sliderFollowCircleTexture.Draw(pos, diameter, diameter, new Vector2(0.5f * diameter), new Color(1.0f, 1.0f, 1.0f, alpha)); } }
private void DrawSlider(BMAPI.v1.HitObjects.SliderObject hitObject, float alpha, int zindex, float approachCircleValue) { float time = (float)(this.songPlayer.SongTime - hitObject.StartTime) / (float)((hitObject.SegmentEndTime - hitObject.StartTime) * hitObject.RepeatCount); byte reverseArrowType = (hitObject.RepeatCount > 1) ? (byte)1 : (byte)0; if (time < 0) { this.DrawHitcircle(hitObject, alpha, zindex); this.DrawApproachCircle(hitObject, alpha, approachCircleValue); this.DrawSliderBody(hitObject, alpha, this.circleDiameter / 2, zindex, reverseArrowType); return; } else if (time > 1) { time = 1; } time *= hitObject.RepeatCount; if (time > 1) { bool drawArrow = time - (hitObject.RepeatCount - 1) < 0; int order = 0; while (time > 1) { time -= 1; order++; reverseArrowType = drawArrow ? (byte)1 : (byte)0; } if (order % 2 != 0) { time = 1 - time; reverseArrowType = drawArrow ? (byte)2 : (byte)0; } } this.DrawSliderBody(hitObject, alpha, this.circleDiameter / 2, zindex, reverseArrowType); Vector2 pos = this.InflateVector(hitObject.PositionAtTime(time), true); // 128x128 is the size of the sprite image for hitcircles int diameter = (int)(this.circleDiameter / 128f * this.sliderFollowCircleTexture.Width * this.Size.X / 512f); Rectangle rect = new Rectangle((int)pos.X, (int)pos.Y, diameter, diameter); rect.X -= rect.Width / 2; rect.Y -= rect.Height / 2; this.spriteBatch.Draw(this.sliderFollowCircleTexture, rect, null, new Color(1.0f, 1.0f, 1.0f, alpha), 0f, Vector2.Zero, SpriteEffects.None, 0f); }
private void DrawSliderBody(BMAPI.v1.HitObjects.SliderObject hitObject, float alpha, int radius, int zindex) { float smallLength = hitObject.TotalLength; Color color = Color.White; for (float i = 0; i < smallLength + 10; i += 10) { if (i > smallLength) { i = smallLength; } // TODO: flip when hardrock Vector2 pos = hitObject.PositionAtTime(i / smallLength); int diameter = this.circleDiameter; color.A = (byte)(255 * alpha); this.sliderEdgeTexture.Draw(pos, diameter, diameter, new Vector2(diameter * 0.5f), color); if (i == smallLength) { break; } } color.A = 255; for (float i = 0; i < smallLength + 10; i += 10) { if (i > smallLength) { i = smallLength; } // TODO: flip when hardrock Vector2 pos = hitObject.PositionAtTime(i / smallLength); int diameter = this.circleDiameter; this.sliderBodyTexture.Draw(pos, diameter, diameter, new Vector2(diameter * 0.5f), color); if (i == smallLength) { break; } } }
private void Draw(bool isBackground) { if (this.Visual_MapInvert) { GL.MatrixMode(MatrixMode.Projection); GL.PushMatrix(); this.MulFlipMatrix(); } //this.spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.NonPremultiplied); for (int b = this.nearbyHitObjects.Count - 1; b >= 0; b--) { BMAPI.v1.HitObjects.CircleObject hitObject = this.nearbyHitObjects[b]; // the song time relative to the hitobject start time float diff = (float)(hitObject.StartTime - this.songPlayer.SongTime); // transparency of hitobject float alpha = 1.0f; // a percentage of how open a slider is, 1.0 is closed, 0.0 is open float approachCircleValue = 0.0f; // length in time of hit object (only applies to sliders and spinners) int hitObjectLength = 0; // Use these types if the hitobject is a slider or spinner BMAPI.v1.HitObjects.SliderObject hitObjectAsSlider = null; BMAPI.v1.HitObjects.SpinnerObject hitObjectAsSpinner = null; if (hitObject.Type.HasFlag(BMAPI.v1.HitObjectType.Spinner)) { hitObjectAsSpinner = (BMAPI.v1.HitObjects.SpinnerObject)hitObject; hitObjectLength = (int)(hitObjectAsSpinner.EndTime - hitObjectAsSpinner.StartTime); } else if (hitObject.Type.HasFlag(BMAPI.v1.HitObjectType.Slider)) { hitObjectAsSlider = (BMAPI.v1.HitObjects.SliderObject)hitObject; hitObjectLength = (int)((hitObjectAsSlider.SegmentEndTime - hitObjectAsSlider.StartTime) * hitObjectAsSlider.RepeatCount); //hitObjectLength = 500; } // for reference: this.approachRate is the time in ms it takes for approach circle to close if (diff < this.approachRate + this.State_FadeTime && diff > -(hitObjectLength + this.State_FadeTime)) { if (diff < -hitObjectLength) { // fade out alpha = 1 - ((diff + hitObjectLength) / -(float)this.State_FadeTime); } else if (!hitObject.Type.HasFlag(BMAPI.v1.HitObjectType.Spinner) && diff >= this.approachRate && diff < this.approachRate + this.State_FadeTime) { // fade in alpha = 1 - (diff - this.approachRate) / (float)this.State_FadeTime; } else if (hitObject.Type.HasFlag(BMAPI.v1.HitObjectType.Spinner)) { // because spinners don't have an approach circle before they appear if (diff >= 0 && diff < this.State_FadeTime) { alpha = 1 - diff / (float)this.State_FadeTime; } else if (diff > 0) { alpha = 0; } } if (diff < this.approachRate + this.State_FadeTime && diff > 0) { // hitcircle percentage from open to closed approachCircleValue = diff / (float)(this.approachRate + this.State_FadeTime); } else if (diff > 0) { approachCircleValue = 1.0f; } if (hitObject.Type.HasFlag(BMAPI.v1.HitObjectType.Circle)) { if (isBackground) { this.DrawHitcircle(hitObject, alpha); } else { this.DrawApproachCircle(hitObject, alpha, approachCircleValue); } } else if (hitObject.Type.HasFlag(BMAPI.v1.HitObjectType.Slider)) { this.DrawSlider(hitObjectAsSlider, alpha, approachCircleValue, isBackground); } else if (hitObject.Type.HasFlag(BMAPI.v1.HitObjectType.Spinner)) { if (!isBackground) { this.DrawSpinner(hitObjectAsSpinner, alpha); this.DrawSpinnerApproachCircle(hitObjectAsSpinner, alpha, (float)(this.songPlayer.SongTime - hitObjectAsSpinner.StartTime) / (hitObjectAsSpinner.EndTime - hitObjectAsSpinner.StartTime)); } } } } if (this.Visual_MapInvert) { GL.MatrixMode(MatrixMode.Projection); GL.PopMatrix(); } if (!isBackground) { bool forceFlip = false; if (this.State_PlaybackMode == 0) { if (MainForm.self.CurrentReplays[this.State_ReplaySelected] != null) { forceFlip = MainForm.self.CurrentReplays[this.State_ReplaySelected].AxisFlip; } if (forceFlip) { GL.MatrixMode(MatrixMode.Projection); GL.PushMatrix(); this.MulFlipMatrix(); } Vector2 currentPos = Vector2.Zero; Vector2 lastPos = new Vector2(-222, 0); for (int i = 0; i < this.nearbyFrames[this.state_ReplaySelected].Count; i++) { ReplayAPI.ReplayFrame currentFrame = this.nearbyFrames[this.state_ReplaySelected][i]; float alpha = i / (float)this.nearbyFrames[this.state_ReplaySelected].Count; currentPos = new Vector2(currentFrame.X, currentFrame.Y); if (lastPos.X != -222) { this.DrawLine(lastPos, currentPos, new Color(1.0f, 0.0f, 0.0f, alpha)); } Color nodeColor = Color.Gray; if (currentFrame.Keys.HasFlag(ReplayAPI.Keys.K1)) { nodeColor = Color.Cyan; } else if (currentFrame.Keys.HasFlag(ReplayAPI.Keys.K2)) { nodeColor = Color.Magenta; } else if (currentFrame.Keys.HasFlag(ReplayAPI.Keys.M1)) { nodeColor = Color.Lime; } else if (currentFrame.Keys.HasFlag(ReplayAPI.Keys.M2)) { nodeColor = Color.Yellow; } this.nodeTexture.Draw(currentPos - new Vector2(5, 5), Vector2.Zero, nodeColor); lastPos = currentPos; } if (forceFlip) { GL.MatrixMode(MatrixMode.Projection); GL.PopMatrix(); } } else if (this.State_PlaybackMode == 1) { for (int i = 0; i < 7; i++) { if (this.nearbyFrames[i] != null && this.nearbyFrames[i].Count >= 1) { forceFlip = MainForm.self.CurrentReplays[i].AxisFlip; if (forceFlip) { GL.MatrixMode(MatrixMode.Projection); GL.PushMatrix(); this.MulFlipMatrix(); } Vector2 cursorPos = this.GetInterpolatedFrame(i); float diameter = 32.0f; this.cursorTexture.Draw(cursorPos, diameter, diameter, new Vector2(diameter * 0.5f), Canvas.Color_Cursor[i]); if (forceFlip) { GL.MatrixMode(MatrixMode.Projection); GL.PopMatrix(); } } } } if (this.ShowHelp != 0) { GL.MatrixMode(MatrixMode.Projection); GL.PushMatrix(); GL.LoadIdentity(); GL.Ortho(0.0, 1.0, 1.0, 0.0, 0.0, 1.0); this.helpTexture.Draw(Vector2.Zero, 1.0f, 1.0f, Vector2.Zero, Color.White); GL.MatrixMode(MatrixMode.Projection); GL.PopMatrix(); } } }
private void DrawSliderBody(BMAPI.v1.HitObjects.SliderObject hitObject, float alpha, int radius, int zindex, byte reverseArrowType) { float smallLength = hitObject.TotalLength; Color color = Color.White; float depthHigh = (zindex * 3 + 2) / 1000.0f; float depthMed = (zindex * 3 + 1) / 1000.0f; float depthLow = (zindex * 3) / 1000.0f; byte alphaByte = (byte)(255 * alpha); Rectangle firstRect = new Rectangle(-222, -222, 222, 222); Rectangle lastRect = new Rectangle(-222, -222, 222, 222); Rectangle firstRectDiff = new Rectangle(-222, -222, 222, 222); Rectangle lastRectDiff = new Rectangle(-222, -222, 222, 222); for (float i = 0; i < smallLength + 10; i += 10) { if (i > smallLength) { i = smallLength; } Vector2 pos = this.InflateVector(hitObject.PositionAtTime(i / smallLength), true); int diameter = (int)(this.circleDiameter * this.Size.X / 512f); Rectangle rect = new Rectangle((int)pos.X, (int)pos.Y, diameter, diameter); rect.X -= rect.Width / 2; rect.Y -= rect.Height / 2; if (firstRect.X == -222) { firstRect = rect; } else if (firstRectDiff.X == -222) { firstRectDiff = rect; } lastRectDiff = lastRect; lastRect = rect; color.A = alphaByte; this.spriteBatch.Draw(this.sliderEdgeTexture, rect, null, color, 0f, Vector2.Zero, SpriteEffects.None, 0.4f + depthHigh); color.A = 255; this.spriteBatch.Draw(this.sliderBodyTexture, rect, null, color, 0f, Vector2.Zero, SpriteEffects.None, 0.4f + depthMed); if (i == smallLength) { break; } } if (reverseArrowType != 0) { color.A = alphaByte; Rectangle mode; float rotation; if (reverseArrowType == 1) { mode = lastRect; rotation = (float)Math.Atan2(lastRectDiff.Y - lastRect.Y, lastRectDiff.X - lastRect.X); } else { rotation = (float)Math.Atan2(firstRectDiff.Y - firstRect.Y, firstRectDiff.X - firstRect.X); mode = firstRect; } mode.X += 52; mode.Y += 52; this.spriteBatch.Draw(this.reverseArrowTexture, mode, null, color, rotation, new Vector2(64.0f), SpriteEffects.None, 0.4f + depthLow); } }
protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(this.State_BackgroundColor); this.spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.NonPremultiplied); for (int b = this.nearbyHitObjects.Count - 1; b >= 0; b--) { BMAPI.v1.HitObjects.CircleObject hitObject = this.nearbyHitObjects[b]; // the song time relative to the hitobject start time float diff = (float)(hitObject.StartTime - this.songPlayer.SongTime); // transparency of hitobject float alpha = 1.0f; // a percentage of how open a slider is, 1.0 is closed, 0.0 is open float approachCircleValue = 0.0f; // length in time of hit object (only applies to sliders and spinners) int hitObjectLength = 0; // Use these types if the hitobject is a slider or spinner BMAPI.v1.HitObjects.SliderObject hitObjectAsSlider = null; BMAPI.v1.HitObjects.SpinnerObject hitObjectAsSpinner = null; if (hitObject.Type.HasFlag(BMAPI.v1.HitObjectType.Spinner)) { hitObjectAsSpinner = (BMAPI.v1.HitObjects.SpinnerObject)hitObject; hitObjectLength = (int)(hitObjectAsSpinner.EndTime - hitObjectAsSpinner.StartTime); } else if (hitObject.Type.HasFlag(BMAPI.v1.HitObjectType.Slider)) { hitObjectAsSlider = (BMAPI.v1.HitObjects.SliderObject)hitObject; hitObjectLength = (int)((hitObjectAsSlider.SegmentEndTime - hitObjectAsSlider.StartTime) * hitObjectAsSlider.RepeatCount); //hitObjectLength = 500; } // for reference: this.approachRate is the time in ms it takes for approach circle to close if (diff < this.approachRate + this.State_FadeTime && diff > -(hitObjectLength + this.State_FadeTime)) { if (diff < -hitObjectLength) { // fade out alpha = 1 - ((diff + hitObjectLength) / -(float)this.State_FadeTime); } else if (!hitObject.Type.HasFlag(BMAPI.v1.HitObjectType.Spinner) && diff >= this.approachRate && diff < this.approachRate + this.State_FadeTime) { // fade in alpha = 1 - (diff - this.approachRate) / (float)this.State_FadeTime; } else if (hitObject.Type.HasFlag(BMAPI.v1.HitObjectType.Spinner)) { // because spinners don't have an approach circle before they appear if (diff >= 0 && diff < this.State_FadeTime) { alpha = 1 - diff / (float)this.State_FadeTime; } else if (diff > 0) { alpha = 0; } } if (diff < this.approachRate + this.State_FadeTime && diff > 0) { // hitcircle percentage from open to closed approachCircleValue = diff / (float)(this.approachRate + this.State_FadeTime); } else if (diff > 0) { approachCircleValue = 1.0f; } if (hitObject.Type.HasFlag(BMAPI.v1.HitObjectType.Circle)) { this.DrawHitcircle(hitObject, alpha, b); this.DrawApproachCircle(hitObject, alpha, approachCircleValue); } else if (hitObject.Type.HasFlag(BMAPI.v1.HitObjectType.Slider)) { this.DrawSlider(hitObjectAsSlider, alpha, b, approachCircleValue); } else if (hitObject.Type.HasFlag(BMAPI.v1.HitObjectType.Spinner)) { this.DrawSpinner(hitObjectAsSpinner, alpha); this.DrawSpinnerApproachCircle(hitObjectAsSpinner, alpha, (float)(this.songPlayer.SongTime - hitObjectAsSpinner.StartTime) / (hitObjectAsSpinner.EndTime - hitObjectAsSpinner.StartTime)); } } } if (this.State_PlaybackMode == 0) { Vector2 currentPos = Vector2.Zero; Vector2 lastPos = new Vector2(-222, 0); for (int i = 0; i < this.nearbyFrames[this.state_ReplaySelected].Count; i++) { ReplayAPI.ReplayFrame currentFrame = this.nearbyFrames[this.state_ReplaySelected][i]; float alpha = i / (float)this.nearbyFrames[this.state_ReplaySelected].Count; currentPos = this.InflateVector(new Vector2(currentFrame.X, currentFrame.Y)); bool selected = false; if (this.selectedFrames != null) { selected = this.selectedFrames.Contains(currentFrame); } if (lastPos.X != -222) { Color linecolor; if (selected) { linecolor = Color.White; } else { linecolor = new Color(1.0f, 0.0f, 0.0f, alpha); } this.DrawLine(lastPos, currentPos, linecolor); } Color nodeColor = Color.Gray; if (currentFrame.Keys.HasFlag(ReplayAPI.Keys.K1)) { nodeColor = Color.Cyan; } else if (currentFrame.Keys.HasFlag(ReplayAPI.Keys.K2)) { nodeColor = Color.Magenta; } else if (currentFrame.Keys.HasFlag(ReplayAPI.Keys.M1)) { nodeColor = Color.Lime; } else if (currentFrame.Keys.HasFlag(ReplayAPI.Keys.M2)) { nodeColor = Color.Yellow; } if (!selected) { nodeColor.A = (byte)(alpha * 255); } this.spriteBatch.Draw(this.nodeTexture, currentPos - new Vector2(5, 5), nodeColor); lastPos = currentPos; } if (this.ToolRect.Width != 0 && this.ToolRect.Height != 0) { this.DrawTool(); } } else if (this.State_PlaybackMode == 1) { for (int i = 0; i < 7; i++) { if (this.nearbyFrames[i] != null && this.nearbyFrames[i].Count >= 1) { this.spriteBatch.Draw(this.cursorTexture, this.InflateVector(this.GetInterpolatedFrame(i)) - new Vector2(this.cursorTexture.Width, this.cursorTexture.Height) / 2f, Canvas.Color_Cursor[i]); } } } if (this.ShowHelp != 0) { this.spriteBatch.Draw(this.helpTexture, Vector2.Zero, Color.White); } this.spriteBatch.End(); base.Draw(gameTime); }