LADXHD/InGame/Things/DrawHelper.cs
2023-12-14 17:21:22 -05:00

201 lines
9.7 KiB
C#

using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using ProjectZ.InGame.Map;
using ProjectZ.InGame.SaveLoad;
namespace ProjectZ.InGame.Things
{
class DrawHelper
{
// more then 1000 will only make sense on a high resolution with a small game scale
public const int MaxShadowIndices = 1000;
public static int CurrentShadowIndex;
public static short[] IndexDataShadow = new short[MaxShadowIndices * 6];
public static float ShadowHeight;
public static float ShadowOffset;
public static Texture2D LastShadowTexture;
private static Matrix projectionMatrix;
private static Matrix outMatrix;
public static VertexPositionPositionColorTexture[] ShadowVertexArray = new VertexPositionPositionColorTexture[MaxShadowIndices * 4];
public static void StartShadowDrawing()
{
//projectionMatrix = Matrix.CreateOrthographicOffCenter(0,
// Game1.Graphics.PreferredBackBufferWidth, Game1.Graphics.PreferredBackBufferHeight, 0, 0, -1);
//outMatrix = MapManager.Camera.TransformMatrix * projectionMatrix;
//Resources.NextShadowEffect.Parameters["WorldViewProjection"].SetValue(outMatrix);
//Game1.SpriteBatch.Begin(SpriteSortMode.Deferred, null, null, null, null, Resources.NextShadowEffect, MapManager.Camera.TransformMatrix);
LastShadowTexture = null;
CurrentShadowIndex = 0;
}
public static void EndShadowDrawing()
{
//Game1.SpriteBatch.End();
if (CurrentShadowIndex > 0)
DrawIndexedDataNew();
}
// TODO_End: this should be done using normal spritebatch.Draw()
public static void DrawShadow(Texture2D sprImage, Vector2 drawPosition, Rectangle sourceRectangle,
float drawWidth, float drawHeight, bool mirror, float height, float rotation, Color color)
{
//Game1.SpriteBatch.Draw(sprImage, drawPosition, sourceRectangle, color);
if (LastShadowTexture != null && (LastShadowTexture != sprImage ||
CurrentShadowIndex >= MaxShadowIndices || ShadowHeight != height || ShadowOffset != rotation))
{
// draw the stored data
DrawIndexedDataNew();
CurrentShadowIndex = 0;
}
SetVertexPtIndexed(ShadowVertexArray, CurrentShadowIndex * 4, drawPosition, sourceRectangle,
drawWidth, drawHeight, sprImage.Width, sprImage.Height, mirror, color);
SetIndexBuffer(IndexDataShadow, CurrentShadowIndex * 6, CurrentShadowIndex * 4);
CurrentShadowIndex++;
ShadowHeight = height;
ShadowOffset = rotation;
LastShadowTexture = sprImage;
}
public struct VertexPositionPositionColorTexture : IVertexType
{
public Vector2 Position;
public Vector2 TextureCoordinate;
public Vector2 UpperLeftPosition;
public Vector2 SourceSize;
public Color Color;
public VertexPositionPositionColorTexture(
Vector2 position, Vector2 textureCoordinate, Vector2 upperLeftPosition, Vector2 sourceSize, Color color)
{
Position = position;
TextureCoordinate = textureCoordinate;
UpperLeftPosition = upperLeftPosition;
SourceSize = sourceSize;
Color = color;
}
public static readonly VertexDeclaration VertexDeclaration;
VertexDeclaration IVertexType.VertexDeclaration => VertexDeclaration;
static VertexPositionPositionColorTexture()
{
var elements = new[]
{
new VertexElement(0, VertexElementFormat.Vector2, VertexElementUsage.Position, 0),
new VertexElement(8, VertexElementFormat.Vector2, VertexElementUsage.TextureCoordinate, 0),
new VertexElement(16, VertexElementFormat.Vector2, VertexElementUsage.TextureCoordinate, 1),
new VertexElement(24, VertexElementFormat.Vector2, VertexElementUsage.TextureCoordinate, 2),
new VertexElement(32, VertexElementFormat.Color, VertexElementUsage.Color, 0),
};
VertexDeclaration = new VertexDeclaration(elements);
}
}
public static void SetVertexPtIndexed(
VertexPositionPositionColorTexture[] buffer, int index,
Vector2 position, Rectangle sourceRectangle, float drawWidth, float drawHeight,
int textureWidth, int textureHeight, bool mirror, Color color)
{
var posLeft = position.X;
var posRight = position.X + drawWidth;// sourceRectangle.Width;
var posTop = position.Y;
var posBottom = position.Y + drawHeight;// sourceRectangle.Height;
var left = (!mirror ? sourceRectangle.X : sourceRectangle.Right) / (float)textureWidth;
var right = (!mirror ? sourceRectangle.Right : sourceRectangle.X) / (float)textureWidth;
var top = sourceRectangle.Y / (float)textureHeight;
var bottom = sourceRectangle.Bottom / (float)textureHeight;
buffer[index + 0] = new VertexPositionPositionColorTexture(
new Vector2(posLeft, posTop), new Vector2(left, top), position,
new Vector2(sourceRectangle.Width, sourceRectangle.Height), color);
buffer[index + 1] = new VertexPositionPositionColorTexture(
new Vector2(posRight, posTop), new Vector2(right, top), position,
new Vector2(sourceRectangle.Width, sourceRectangle.Height), color);
buffer[index + 2] = new VertexPositionPositionColorTexture(
new Vector2(posLeft, posBottom), new Vector2(left, bottom), position,
new Vector2(sourceRectangle.Width, sourceRectangle.Height), color);
buffer[index + 3] = new VertexPositionPositionColorTexture(
new Vector2(posRight, posBottom), new Vector2(right, bottom), position,
new Vector2(sourceRectangle.Width, sourceRectangle.Height), color);
}
public static void DrawIndexedDataNew()
{
projectionMatrix = Matrix.CreateOrthographicOffCenter(0,
Game1.GameManager.CurrentRenderWidth, Game1.GameManager.CurrentRenderHeight, 0, 0, -1);
outMatrix = MapManager.Camera.TransformMatrix * projectionMatrix;
Resources.FullShadowEffect.Parameters["xViewProjection"].SetValue(outMatrix);
Resources.FullShadowEffect.Parameters["height"].SetValue(ShadowHeight);
Resources.FullShadowEffect.Parameters["offsetX"].SetValue(ShadowOffset);
foreach (var pass in Resources.FullShadowEffect.CurrentTechnique.Passes)
{
pass.Apply();
Game1.Graphics.GraphicsDevice.Textures[0] = LastShadowTexture;
Game1.Graphics.GraphicsDevice.DrawUserIndexedPrimitives(
PrimitiveType.TriangleList, ShadowVertexArray, 0, CurrentShadowIndex * 4, IndexDataShadow, 0, CurrentShadowIndex * 2);
}
}
public static void SetIndexBuffer(short[] buffer, int position, int offset)
{
buffer[position + 0] = (short)(offset + 0);
buffer[position + 1] = (short)(offset + 1);
buffer[position + 2] = (short)(offset + 2);
buffer[position + 3] = (short)(offset + 2);
buffer[position + 4] = (short)(offset + 1);
buffer[position + 5] = (short)(offset + 3);
}
public static void DrawLight(SpriteBatch spriteBatch, Rectangle lightRectangle, Color lightColor)
{
spriteBatch.Draw(Resources.SprLight, lightRectangle, lightColor);
}
public static void DrawCenter(SpriteBatch spriteBatch, Texture2D sprTexture, Point offset,
Rectangle centerRectangle, Rectangle sourceRectangle, int scale)
{
spriteBatch.Draw(sprTexture, new Rectangle(
offset.X + (centerRectangle.X + centerRectangle.Width / 2 - sourceRectangle.Width / 2) * scale,
offset.Y + (centerRectangle.Y + centerRectangle.Height / 2 - sourceRectangle.Height / 2) * scale,
sourceRectangle.Width * scale,
sourceRectangle.Height * scale), sourceRectangle, Color.White);
}
public static void DrawNormalized(SpriteBatch spriteBatch, Texture2D texture,
Vector2 position, Rectangle sourceRectangle, Color color, float scale = 1.0f)
{
var normalizedPosition = new Vector2(
(float)Math.Round(position.X * MapManager.Camera.Scale) / MapManager.Camera.Scale,
(float)Math.Round(position.Y * MapManager.Camera.Scale) / MapManager.Camera.Scale);
spriteBatch.Draw(texture, normalizedPosition, sourceRectangle, color, 0, Vector2.Zero, new Vector2(scale), SpriteEffects.None, 0);
}
public static void DrawNormalized(SpriteBatch spriteBatch, DictAtlasEntry sprite, Vector2 position, Color color)
{
var normalizedPosition = new Vector2(
(float)Math.Round(position.X * MapManager.Camera.Scale) / MapManager.Camera.Scale,
(float)Math.Round(position.Y * MapManager.Camera.Scale) / MapManager.Camera.Scale);
spriteBatch.Draw(sprite.Texture, normalizedPosition, sprite.ScaledRectangle, color, 0, sprite.Origin, new Vector2(sprite.Scale), SpriteEffects.None, 0);
}
}
}