Skip to content

Commit ebfb290

Browse files
authored
- F3 toggle Z level splicing (#87)
- ALT + Plus or Minus to go up or down a Z level - Shift hotkey has been added to decrease Z Level
1 parent 7f7d872 commit ebfb290

File tree

10 files changed

+260
-19
lines changed

10 files changed

+260
-19
lines changed

ACViewer/Config/MapViewerOptions.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ namespace ACViewer.Config
55
public class MapViewerOptions
66
{
77
public MapViewerMode Mode { get; set; }
8+
public bool EnableZSlicing { get; set; } = false;
9+
public int CurrentZLevel { get; set; } = 1;
10+
public float LevelHeight { get; set; } = 10.0f;
811

912
public MapViewerOptions()
1013
{

ACViewer/Extensions/CommandHandler.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Windows.Input;
3+
using ACViewer.Config;
34

45
namespace ACViewer.Extensions
56
{

ACViewer/Extensions/Vector3Extensions.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
using System;
22

3+
using Microsoft.Xna.Framework;
4+
5+
using System.Numerics;
6+
37
using ACE.Server.Physics;
48

59
namespace ACViewer
610
{
711
public static class Vector3Extensions
812
{
13+
914
public static System.Numerics.Vector3 ToNumerics(this Microsoft.Xna.Framework.Vector3 v)
1015
{
1116
return new System.Numerics.Vector3(v.X, v.Y, v.Z);

ACViewer/Model/VertexInstance.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@ namespace ACViewer.Model
55
{
66
public struct VertexInstance : IVertexType
77
{
8-
public Vector3 Position;
8+
public Vector3 Position { get; set; }
99
public Vector4 Orientation;
1010
public Vector3 Scale;
11+
1112

1213
public readonly static VertexDeclaration VertexDeclaration = new VertexDeclaration
1314
(

ACViewer/Render/Buffer.cs

Lines changed: 92 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Linq;
34

45
using Microsoft.Xna.Framework;
56
using Microsoft.Xna.Framework.Graphics;
67

78
using ACE.DatLoader.Entity;
89
using ACE.Server.Physics;
9-
10+
using ACViewer.Config;
11+
using ACViewer.Extensions;
1012
using ACViewer.Enum;
1113
using ACViewer.Model;
1214

@@ -86,6 +88,95 @@ public void Init()
8688

8789
AnimatedTextureAtlasChains = new Dictionary<TextureFormat, TextureAtlasChain>();
8890
}
91+
92+
private bool IsInCurrentZLevel(Vector3 position)
93+
{
94+
if (!ConfigManager.Config.MapViewer.EnableZSlicing)
95+
return true;
96+
97+
var config = ConfigManager.Config.MapViewer;
98+
float levelBottom = (config.CurrentZLevel - 1) * config.LevelHeight;
99+
float levelTop = levelBottom + config.LevelHeight;
100+
101+
return position.Z >= levelBottom && position.Z < levelTop;
102+
}
103+
104+
public void DrawWithZSlicing()
105+
{
106+
Effect.Parameters["xWorld"].SetValue(Matrix.Identity);
107+
Effect.Parameters["xLightDirection"].SetValue(-Vector3.UnitZ);
108+
Effect.Parameters["xAmbient"].SetValue(0.5f);
109+
110+
Effect_Clamp.Parameters["xWorld"].SetValue(Matrix.Identity);
111+
Effect_Clamp.Parameters["xLightDirection"].SetValue(-Vector3.UnitZ);
112+
Effect_Clamp.Parameters["xAmbient"].SetValue(0.5f);
113+
114+
PerfTimer.Start(ProfilerSection.Draw);
115+
116+
if (drawTerrain)
117+
{
118+
SetRasterizerState();
119+
TerrainBatch.DrawWithZFiltering(IsInCurrentZLevel);
120+
}
121+
122+
if (drawEnvCells)
123+
DrawBufferWithZSlicing(RB_EnvCell, true);
124+
125+
if (drawStaticObjs)
126+
DrawBufferWithZSlicing(RB_StaticObjs);
127+
128+
if (drawBuildings)
129+
DrawBufferWithZSlicing(RB_Buildings);
130+
131+
if (drawScenery)
132+
DrawBufferWithZSlicing(RB_Scenery);
133+
134+
if (drawInstances && Server.InstancesLoaded)
135+
DrawBufferWithZSlicing(RB_Instances);
136+
137+
if (drawEncounters && Server.EncountersLoaded)
138+
DrawBufferWithZSlicing(RB_Encounters);
139+
140+
DrawBufferWithZSlicing(RB_Animated);
141+
142+
if (Picker.HitVertices != null)
143+
Picker.DrawHitPoly();
144+
145+
PerfTimer.Stop(ProfilerSection.Draw);
146+
}
147+
148+
private void DrawBufferWithZSlicing(Dictionary<uint, GfxObjInstance_Shared> batches)
149+
{
150+
SetRasterizerState(CullMode.None);
151+
152+
foreach (var batch in batches.Values)
153+
batch.DrawFiltered(IsInCurrentZLevel);
154+
}
155+
156+
private void DrawBufferWithZSlicing(Dictionary<GfxObjTexturePalette, GfxObjInstance_Shared> batches)
157+
{
158+
SetRasterizerState(CullMode.None);
159+
160+
foreach (var batch in batches.Values)
161+
batch.DrawFiltered(IsInCurrentZLevel);
162+
}
163+
164+
private void DrawBufferWithZSlicing(Dictionary<TextureSet, InstanceBatch> batches, bool culling = false)
165+
{
166+
var cullMode = WorldViewer.Instance.DungeonMode || culling ?
167+
CullMode.CullClockwiseFace : CullMode.None;
168+
169+
SetRasterizerState(cullMode);
170+
171+
Effect.CurrentTechnique = Effect.Techniques["TexturedInstanceEnv"];
172+
Effect_Clamp.CurrentTechnique = Effect_Clamp.Techniques["TexturedInstanceEnv"];
173+
174+
foreach (var batch in batches.Values)
175+
{
176+
batch.DrawFiltered(IsInCurrentZLevel);
177+
}
178+
}
179+
89180

90181
public void ClearBuffer()
91182
{

ACViewer/Render/Camera.cs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,31 @@ public void Update(GameTime gameTime)
295295
Position -= Vector3.Cross(Up, Dir) * Speed;
296296
if (keyboardState.IsKeyDown(Keys.Space))
297297
Position += Up * Speed;
298+
// Shift key control for downward movement
299+
if (keyboardState.IsKeyDown(Keys.LeftShift) || keyboardState.IsKeyDown(Keys.RightShift))
300+
Position -= Up * Speed;
301+
302+
// Z-level controls
303+
if (keyboardState.IsKeyDown(Keys.F3) && LastKeyboardState != null && !LastKeyboardState.IsKeyDown(Keys.F3))
304+
{
305+
ConfigManager.Config.MapViewer.EnableZSlicing = !ConfigManager.Config.MapViewer.EnableZSlicing;
306+
ConfigManager.Config.MapViewer.CurrentZLevel = 1;
307+
}
308+
309+
// Z-level adjustment
310+
if (ConfigManager.Config.MapViewer.EnableZSlicing)
311+
{
312+
if ((keyboardState.IsKeyDown(Keys.LeftAlt) || keyboardState.IsKeyDown(Keys.RightAlt)))
313+
{
314+
var config = ConfigManager.Config.MapViewer;
315+
if (keyboardState.IsKeyDown(Keys.OemPlus) && !LastKeyboardState.IsKeyDown(Keys.OemPlus))
316+
config.CurrentZLevel = Math.Min(config.CurrentZLevel + 1, 20);
317+
if (keyboardState.IsKeyDown(Keys.OemMinus) && !LastKeyboardState.IsKeyDown(Keys.OemMinus))
318+
config.CurrentZLevel--;
319+
}
320+
}
321+
322+
LastKeyboardState = keyboardState;
298323

299324
// camera speed control
300325
if (mouseState.ScrollWheelValue != PrevMouseState.ScrollWheelValue)
@@ -368,6 +393,7 @@ public void Update(GameTime gameTime)
368393
//Console.WriteLine("Camera dir: " + GameView.Instance.Render.Camera.Dir);
369394
}
370395

396+
private KeyboardState LastKeyboardState;
371397
public int centerX => GameView.GraphicsDevice.Viewport.Width / 2;
372398
public int centerY => GameView.GraphicsDevice.Viewport.Height / 2;
373399

ACViewer/Render/GfxObjInstance_Shared.cs

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
using System.Collections.Generic;
2-
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
34
using Microsoft.Xna.Framework;
45
using Microsoft.Xna.Framework.Graphics;
56

@@ -25,9 +26,8 @@ public class GfxObjInstance_Shared
2526
public Dictionary<TextureFormatChain, GfxObjInstance_TextureFormat> BaseFormats_Alpha { get; set; }
2627

2728
public List<VertexPositionNormalTextures> Vertices { get; set; }
28-
29+
2930
public List<VertexInstance> Instances { get; set; }
30-
3131
public VertexInstance[] Instances_ { get; set; }
3232

3333
public VertexBuffer Shared_VB { get; set; }
@@ -39,9 +39,7 @@ public class GfxObjInstance_Shared
3939
public GfxObjInstance_Shared(GfxObj gfxObj, Dictionary<TextureFormat, TextureAtlasChain> textureAtlasChains, Dictionary<uint, uint> textureChanges = null, PaletteChanges paletteChanges = null)
4040
{
4141
GfxObj = gfxObj;
42-
4342
BuildStatic(gfxObj, textureAtlasChains, textureChanges, paletteChanges);
44-
4543
Instances = new List<VertexInstance>();
4644
}
4745

@@ -185,6 +183,51 @@ public void Draw()
185183
foreach (var baseFormat in BaseFormats_Alpha.Values)
186184
baseFormat.Draw(Instances.Count);
187185
}
186+
187+
public void DrawFiltered(Func<Vector3, bool> filter)
188+
{
189+
if (Bindings == null) return;
190+
191+
if (isDirty)
192+
{
193+
Instances_VB.SetData(Instances_);
194+
isDirty = false;
195+
}
196+
197+
// Store original instances
198+
var originalInstances = Instances_.ToArray();
199+
200+
// Filter instances
201+
var filteredInstances = Instances.Where(instance => filter(instance.Position)).ToArray();
202+
203+
if (filteredInstances.Length > 0)
204+
{
205+
// Update vertex buffer with filtered instances
206+
Instances_ = filteredInstances;
207+
Instances_VB.SetData(filteredInstances);
208+
209+
GraphicsDevice.SetVertexBuffers(Bindings);
210+
211+
Effect.CurrentTechnique = Effect.Techniques["TexturedInstance"];
212+
Effect_Clamp.CurrentTechnique = Effect_Clamp.Techniques["TexturedInstance"];
213+
214+
foreach (var baseFormat in BaseFormats_Solid.Values)
215+
baseFormat.Draw(filteredInstances.Length);
216+
217+
if (Buffer.drawAlpha)
218+
{
219+
Effect.CurrentTechnique = Effect.Techniques["TexturedInstanceAlpha"];
220+
Effect_Clamp.CurrentTechnique = Effect_Clamp.Techniques["TexturedInstanceAlpha"];
221+
}
222+
223+
foreach (var baseFormat in BaseFormats_Alpha.Values)
224+
baseFormat.Draw(filteredInstances.Length);
225+
}
226+
227+
// Restore original instances
228+
Instances_ = originalInstances;
229+
Instances_VB.SetData(originalInstances);
230+
}
188231

189232
public void Dispose()
190233
{

ACViewer/Render/InstanceBatch.cs

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
using System.Collections.Generic;
2-
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
34
using ACE.Entity.Enum;
4-
5+
using Microsoft.Xna.Framework;
56
using Microsoft.Xna.Framework.Graphics;
67

78
namespace ACViewer.Render
@@ -17,6 +18,28 @@ public class InstanceBatch
1718
public VertexBuffer InstanceBuffer { get; set; }
1819

1920
public R_Environment R_Environment { get; set; }
21+
22+
public void DrawFiltered(Func<Vector3, bool> filter)
23+
{
24+
// Store original instances
25+
var originalInstances = new List<VertexInstanceEnv>(Instances_Env);
26+
27+
// Filter instances based on Z position
28+
Instances_Env = Instances_Env.Where(instance => filter(instance.Position)).ToList();
29+
30+
if (Instances_Env.Count > 0)
31+
{
32+
// Rebuild instance buffer with filtered instances
33+
BuildInstanceBuffer();
34+
BuildBindings();
35+
Draw();
36+
}
37+
38+
// Restore original instances
39+
Instances_Env = originalInstances;
40+
BuildInstanceBuffer();
41+
BuildBindings();
42+
}
2043

2144
public InstanceBatch(R_EnvCell envCell)
2245
{

ACViewer/Render/Render.cs

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ public class Render
2525

2626
// multiple SamplerStates in the same .fx file apparently don't work
2727
public static Effect Effect_Clamp { get; set; }
28+
29+
// Add to existing properties
30+
private MapViewerOptions Config => ConfigManager.Config.MapViewer;
2831

2932
public Camera Camera
3033
{
@@ -67,21 +70,23 @@ public void SetRasterizerState(bool wireframe = true)
6770

6871
GraphicsDevice.RasterizerState = rs;
6972
}
70-
73+
7174
public void Draw()
7275
{
7376
GraphicsDevice.Clear(ConfigManager.Config.BackgroundColors.WorldViewer);
7477

7578
SetRasterizerState(false);
76-
79+
7780
Effect.Parameters["xView"].SetValue(Camera.ViewMatrix);
7881
Effect_Clamp.Parameters["xView"].SetValue(Camera.ViewMatrix);
7982

80-
//landblock.Draw();
81-
Buffer.Draw();
83+
if (ConfigManager.Config.MapViewer.EnableZSlicing)
84+
Buffer.DrawWithZSlicing();
85+
else
86+
Buffer.Draw();
8287

83-
//DrawEmitters_Naive();
8488
DrawEmitters_Batch();
89+
DrawHUD();
8590
}
8691

8792
public bool ParticlesInitted { get; set; }
@@ -186,14 +191,29 @@ public void DestroyEmitters()
186191

187192
private static readonly Vector2 TextPos = new Vector2(10, 10);
188193

194+
// DrawHUD to show Z-slice information
189195
public void DrawHUD()
190196
{
191-
var cameraPos = GameView.Camera.GetPosition();
197+
var text = "";
198+
199+
if (ConfigManager.Config.MapViewer.EnableZSlicing)
200+
{
201+
var config = ConfigManager.Config.MapViewer;
202+
string levelPrefix = config.CurrentZLevel < 0 ? "B" : ""; // Add "B" prefix for basement levels
203+
int displayLevel = config.CurrentZLevel < 0 ? -config.CurrentZLevel : config.CurrentZLevel;
204+
205+
text += $"Current Z-Level: {levelPrefix}{displayLevel}\n"; // Shows B1, B2, etc. for basement levels
206+
text += $"Height Range: {(config.CurrentZLevel - 1) * config.LevelHeight:F1}m - {config.CurrentZLevel * config.LevelHeight:F1}m\n";
207+
}
192208

209+
var cameraPos = Camera.GetPosition();
193210
if (cameraPos != null)
211+
text += $"Location: {cameraPos}";
212+
213+
if (!string.IsNullOrEmpty(text))
194214
{
195215
SpriteBatch.Begin(SpriteSortMode.Deferred, null, SamplerState.LinearClamp);
196-
SpriteBatch.DrawString(Font, $"Location: {cameraPos}", TextPos, Color.White);
216+
SpriteBatch.DrawString(Font, text, TextPos, Color.White);
197217
SpriteBatch.End();
198218
}
199219
}

0 commit comments

Comments
 (0)