ClassiCube/ClassicalSharp/Selections/SelectionManager.cs

89 lines
2.8 KiB
C#

using System;
using System.Collections.Generic;
using ClassicalSharp.GraphicsAPI;
using OpenTK;
namespace ClassicalSharp.Selections {
public class SelectionManager : IDisposable {
protected Game game;
public IGraphicsApi Graphics;
VertexPos3fCol4b[] vertices, lineVertices;
int vb, lineVb;
public SelectionManager( Game window ) {
game = window;
Graphics = window.Graphics;
window.Events.OnNewMap += OnNewMap;
}
List<SelectionBox> selections = new List<SelectionBox>( 256 );
public void AddSelection( byte id, Vector3I p1, Vector3I p2, FastColour col ) {
RemoveSelection( id );
SelectionBox selection = new SelectionBox( p1, p2, col );
selection.ID = id;
selections.Add( selection );
}
public void RemoveSelection( byte id ) {
for( int i = 0; i < selections.Count; i++ ) {
SelectionBox sel = selections[i];
if( sel.ID == id ) {
selections.RemoveAt( i );
break;
}
}
}
SelectionBoxComparer comparer = new SelectionBoxComparer();
public void Render( double delta ) {
Player player = game.LocalPlayer;
if( selections.Count == 0 ) return;
// TODO: Proper selection box sorting. But this is very difficult because
// we can have boxes within boxes, intersecting boxes, etc. Probably not worth it.
comparer.pos = game.Camera.GetCameraPos( player.EyePosition );
selections.Sort( comparer );
if( vertices == null )
InitData(); // lazy init as most servers don't use this.
int index = 0, lineIndex = 0;
for( int i = 0; i < selections.Count; i++ ) {
SelectionBox box = selections[i];
box.Render( delta, comparer.pos, vertices, lineVertices, ref index, ref lineIndex );
}
Graphics.SetBatchFormat( VertexFormat.Pos3fCol4b );
Graphics.UpdateDynamicVb( DrawMode.Lines, lineVb, lineVertices, selections.Count * LineVerticesCount );
Graphics.DepthWrite = false;
Graphics.AlphaBlending = true;
Graphics.UpdateDynamicIndexedVb( DrawMode.Triangles, vb, vertices,
selections.Count * VerticesCount, selections.Count * IndicesCount );
Graphics.DepthWrite = true;
Graphics.AlphaBlending = false;
}
public void Dispose() {
OnNewMap( null, null );
game.Events.OnNewMap -= OnNewMap;
if( lineVb > 0 ) {
Graphics.DeleteDynamicVb( vb );
Graphics.DeleteDynamicVb( lineVb );
}
}
const int VerticesCount = 6 * 4, LineVerticesCount = 12 * 2, IndicesCount = 6 * 6;
void InitData() {
vertices = new VertexPos3fCol4b[256 * VerticesCount];
lineVertices = new VertexPos3fCol4b[256 * LineVerticesCount];
vb = Graphics.CreateDynamicVb( VertexFormat.Pos3fCol4b, vertices.Length );
lineVb = Graphics.CreateDynamicVb( VertexFormat.Pos3fCol4b, lineVertices.Length );
}
void OnNewMap( object sender, EventArgs e ) {
selections.Clear();
}
}
}