some 3D mode rendering

This commit is contained in:
codeimp 2008-01-13 21:23:59 +00:00
parent dee7a72413
commit 3c43547c6c
41 changed files with 1192 additions and 1387 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 695 B

View file

@ -360,6 +360,7 @@
</ItemGroup>
<ItemGroup>
<Content Include="Resources\Builder.ico" />
<EmbeddedResource Include="Resources\MissingTexture3D.png" />
<None Include="Resources\MissingTexture.png" />
<None Include="Resources\UnknownImage.png" />
<None Include="Resources\treeview.png" />

View file

@ -36,22 +36,26 @@
<Reference Include="System.Windows.Forms" />
</ItemGroup>
<ItemGroup>
<Compile Include="Editing\BaseVisualMode.cs" />
<Compile Include="Editing\DragVerticesMode.cs" />
<Compile Include="Editing\LinedefsMode.cs" />
<Compile Include="Editing\TriangulatorMode.cs" />
<Compile Include="Editing\VisualObject.cs" />
<Compile Include="Editing\WAuthorMode.cs" />
<Compile Include="Editing\WAuthorTools.cs">
<Compile Include="VisualMode\BaseVisualMode.cs" />
<Compile Include="VisualMode\BaseVisualSector.cs" />
<Compile Include="VerticesMode\DragVerticesMode.cs" />
<Compile Include="LinedefsMode\LinedefsMode.cs" />
<Compile Include="VisualMode\VisualCeiling.cs" />
<Compile Include="VisualMode\VisualFloor.cs" />
<Compile Include="VisualMode\VisualLower.cs" />
<Compile Include="VisualMode\VisualMiddle.cs" />
<Compile Include="Testing\WAuthorMode.cs" />
<Compile Include="Testing\WAuthorTools.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Editing\WAuthorTools.Designer.cs">
<Compile Include="Testing\WAuthorTools.Designer.cs">
<DependentUpon>WAuthorTools.cs</DependentUpon>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Editing\SectorsMode.cs" />
<Compile Include="Editing\ThingsMode.cs" />
<Compile Include="Editing\VerticesMode.cs" />
<Compile Include="SectorsMode\SectorsMode.cs" />
<Compile Include="ThingsMode\ThingsMode.cs" />
<Compile Include="VerticesMode\VerticesMode.cs" />
<Compile Include="VisualMode\VisualUpper.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Builder.csproj">
@ -76,7 +80,7 @@
<EmbeddedResource Include="Resources\SectorsMode.png" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Editing\WAuthorTools.resx">
<EmbeddedResource Include="Testing\WAuthorTools.resx">
<SubType>Designer</SubType>
<DependentUpon>WAuthorTools.cs</DependentUpon>
</EmbeddedResource>
@ -85,9 +89,6 @@
<ItemGroup>
<EmbeddedResource Include="Resources\VisualMode.png" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Resources\TriangulatorMode.png" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.

View file

@ -1,535 +0,0 @@
#region ================== Copyright (c) 2007 Pascal vd Heiden
/*
* Copyright (c) 2007 Pascal vd Heiden, www.codeimp.com
* This program is released under GNU General Public License
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#endregion
#region ================== Namespaces
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Reflection;
using CodeImp.DoomBuilder.Interface;
using CodeImp.DoomBuilder.IO;
using CodeImp.DoomBuilder.Map;
using CodeImp.DoomBuilder.Rendering;
using CodeImp.DoomBuilder.Geometry;
using CodeImp.DoomBuilder.Editing;
using System.Threading;
using System.Drawing;
#endregion
namespace CodeImp.DoomBuilder.BuilderModes.Editing
{
#if DEBUG
[EditMode(SwitchAction = "triangulatormode", // Action name used to switch to this mode
ButtonDesc = "Triangulator Mode", // Description on the button in toolbar/menu
ButtonImage = "TriangulatorMode.png", // Image resource name for the button
ButtonOrder = int.MaxValue)] // Position of the button (lower is more to the left)
public class TriangulatorMode : ClassicMode
{
#region ================== Constants
#endregion
#region ================== Variables
// Highlighted item
private Sector highlighted;
#endregion
#region ================== Properties
#endregion
#region ================== Constructor / Disposer
// Constructor
public TriangulatorMode()
{
}
// Disposer
public override void Dispose()
{
// Not already disposed?
if(!isdisposed)
{
// Clean up
// Dispose base
base.Dispose();
}
}
#endregion
#region ================== Methods
// Cancel mode
public override void Cancel()
{
base.Cancel();
// Return to this mode
General.Map.ChangeMode(new SectorsMode());
}
// Mode engages
public override void Engage()
{
base.Engage();
}
// Mode disengages
public override void Disengage()
{
base.Disengage();
// Check which mode we are switching to
if(General.Map.NewMode is VerticesMode)
{
// Convert selection to vertices
// Clear selected sectors
General.Map.Map.ClearSelectedSectors();
}
else if(General.Map.NewMode is LinedefsMode)
{
// Convert selection to linedefs
// Clear selected sectors
General.Map.Map.ClearSelectedSectors();
}
// Hide highlight info
General.Interface.HideInfo();
}
// This redraws the display
public unsafe override void RedrawDisplay()
{
// Start with a clear display
if(renderer.Start(true, true))
{
// Do not show things
renderer.SetThingsRenderOrder(false);
// Render lines and vertices
renderer.RenderLinedefSet(General.Map.Map.Linedefs);
renderer.RenderVerticesSet(General.Map.Map.Vertices);
// Render highlighted item
if((highlighted != null) && !highlighted.IsDisposed)
renderer.RenderSector(highlighted, General.Colors.Highlight);
// Done
renderer.Finish();
}
}
// This highlights a new item
protected void Highlight(Sector s)
{
// Update display
if(renderer.Start(false, false))
{
// Undraw previous highlight
if((highlighted != null) && !highlighted.IsDisposed)
renderer.RenderSector(highlighted);
// Set new highlight
highlighted = s;
// Render highlighted item
if((highlighted != null) && !highlighted.IsDisposed)
renderer.RenderSector(highlighted, General.Colors.Highlight);
// Done
renderer.Finish();
}
// Show highlight info
if((highlighted != null) && !highlighted.IsDisposed)
General.Interface.ShowSectorInfo(highlighted);
else
General.Interface.HideInfo();
}
// Mouse moves
public override void MouseMove(MouseEventArgs e)
{
base.MouseMove(e);
// Find the nearest linedef within highlight range
Linedef l = General.Map.Map.NearestLinedef(mousemappos);
// Check on which side of the linedef the mouse is
float side = l.SideOfLine(mousemappos);
if(side > 0)
{
// Is there a sidedef here?
if(l.Back != null)
{
// Highlight if not the same
if(l.Back.Sector != highlighted) Highlight(l.Back.Sector);
}
else
{
// Highlight nothing
if(highlighted != null) Highlight(null);
}
}
else
{
// Is there a sidedef here?
if(l.Front != null)
{
// Highlight if not the same
if(l.Front.Sector != highlighted) Highlight(l.Front.Sector);
}
else
{
// Highlight nothing
if(highlighted != null) Highlight(null);
}
}
}
// Mouse leaves
public override void MouseLeave(EventArgs e)
{
base.MouseLeave(e);
// Highlight nothing
Highlight(null);
}
// Mouse button pressed
public override void MouseDown(MouseEventArgs e)
{
base.MouseDown(e);
bool front, back;
// Which button is used?
if(e.Button == EditMode.SELECT_BUTTON)
{
// Item highlighted?
if((highlighted != null) && !highlighted.IsDisposed)
{
// Flip selection
highlighted.Selected = !highlighted.Selected;
// Make update lines selection
foreach(Sidedef sd in highlighted.Sidedefs)
{
if(sd.Line.Front != null) front = sd.Line.Front.Sector.Selected; else front = false;
if(sd.Line.Back != null) back = sd.Line.Back.Sector.Selected; else back = false;
sd.Line.Selected = front | back;
}
// Update display
if(renderer.Start(false, false))
{
// Redraw highlight to show selection
renderer.RenderSector(highlighted);
renderer.Finish();
}
}
}
}
// Mouse released
public override void MouseUp(MouseEventArgs e)
{
ICollection<Sector> selected;
TriangleList triangles;
base.MouseUp(e);
// Item highlighted?
if((highlighted != null) && !highlighted.IsDisposed)
{
// Which button is used?
if(e.Button == EditMode.SELECT_BUTTON)
{
// Anything selected?
selected = General.Map.Map.GetSectorsSelection(true);
if(selected.Count > 0)
{
// Remove highlight
Highlight(null);
// Clear selection
General.Map.Map.ClearSelectedSectors();
General.Map.Map.ClearSelectedLinedefs();
General.Interface.RedrawDisplay();
// Get a triangulator and bind events
EarClipTriangulator t = new EarClipTriangulator();
t.OnShowLine = new EarClipTriangulator.ShowLine(ShowLine);
t.OnShowPolygon = new EarClipTriangulator.ShowPolygon(ShowPolygon);
t.OnShowPoint = new EarClipTriangulator.ShowPoint(ShowPoint);
t.OnShowEarClip = new EarClipTriangulator.ShowEarClip(ShowEarClip);
// Triangulate this now!
triangles = t.Triangulate(General.GetByIndex<Sector>(selected, 0));
// Start with a clear display
if(renderer.Start(true, true))
{
// Do not show things
renderer.SetThingsRenderOrder(false);
// Render lines and vertices
renderer.RenderLinedefSet(General.Map.Map.Linedefs);
renderer.RenderVerticesSet(General.Map.Map.Vertices);
// Go for all triangle vertices
for(int i = 0; i < triangles.Count; i += 3)
{
renderer.RenderLine(triangles[i + 0], triangles[i + 1], General.Colors.Selection);
renderer.RenderLine(triangles[i + 1], triangles[i + 2], General.Colors.Selection);
renderer.RenderLine(triangles[i + 2], triangles[i + 0], General.Colors.Selection);
}
// Done
renderer.Finish();
Thread.Sleep(200);
}
}
}
else
{
// Get a triangulator and bind events
EarClipTriangulator t = new EarClipTriangulator();
// Triangulate the whole map!
triangles = new TriangleList();
foreach(Sector s in General.Map.Map.Sectors)
triangles.AddRange(t.Triangulate(s));
// Start with a clear display
if(renderer.Start(true, true))
{
// Do not show things
renderer.SetThingsRenderOrder(false);
// Render lines and vertices
renderer.RenderLinedefSet(General.Map.Map.Linedefs);
renderer.RenderVerticesSet(General.Map.Map.Vertices);
// Go for all triangle vertices
for(int i = 0; i < triangles.Count; i += 3)
{
renderer.RenderLine(triangles[i + 0], triangles[i + 1], General.Colors.Selection);
renderer.RenderLine(triangles[i + 1], triangles[i + 2], General.Colors.Selection);
renderer.RenderLine(triangles[i + 2], triangles[i + 0], General.Colors.Selection);
}
// Done
renderer.Finish();
Thread.Sleep(200);
}
}
}
}
// This shows a point
private void ShowPoint(Vector2D v, int c)
{
for(int a = 0; a < 6; a++)
{
RedrawDisplay();
Thread.Sleep(10);
// Start with a clear display
if(renderer.Start(true, true))
{
// Do not show things
renderer.SetThingsRenderOrder(false);
// Render lines and vertices
renderer.RenderLinedefSet(General.Map.Map.Linedefs);
renderer.RenderVerticesSet(General.Map.Map.Vertices);
// Show the point
renderer.RenderVertexAt(v, c);
// Done
renderer.Finish();
}
// Wait a bit
Thread.Sleep(100);
}
}
// This shows a line
private void ShowLine(Vector2D v1, Vector2D v2, PixelColor c)
{
// Start with a clear display
if(renderer.Start(true, true))
{
// Do not show things
renderer.SetThingsRenderOrder(false);
// Render lines and vertices
renderer.RenderLinedefSet(General.Map.Map.Linedefs);
renderer.RenderVerticesSet(General.Map.Map.Vertices);
// Show the line
renderer.RenderLine(v1, v2, c);
// Done
renderer.Finish();
}
// Wait a bit
Thread.Sleep(200);
}
// This shows a polygon
private void ShowPolygon(Polygon p, PixelColor c)
{
LinkedListNode<EarClipVertex> v;
for(int a = 0; a < 5; a++)
{
RedrawDisplay();
Thread.Sleep(10);
// Start with a clear display
if(renderer.Start(true, true))
{
// Do not show things
renderer.SetThingsRenderOrder(false);
// Render lines and vertices
renderer.RenderLinedefSet(General.Map.Map.Linedefs);
renderer.RenderVerticesSet(General.Map.Map.Vertices);
// Go for all vertices in the polygon
v = p.First;
while(v != null)
{
// Show the line
if(v.Next != null) renderer.RenderLine(v.Value.Position, v.Next.Value.Position, c);
v = v.Next;
}
// Show last line as well
renderer.RenderLine(p.Last.Value.Position, p.First.Value.Position, c);
// Done
renderer.Finish();
}
// Wait a bit
Thread.Sleep(50);
}
}
// This shows a polygon
private void ShowEarClip(EarClipVertex[] found, LinkedList<EarClipVertex> remains)
{
EarClipVertex prev, first;
for(int a = 0; a < 5; a++)
{
// Start with a clear display
if(renderer.Start(true, true))
{
// Do not show things
renderer.SetThingsRenderOrder(false);
// Render lines and vertices
renderer.RenderLinedefSet(General.Map.Map.Linedefs);
renderer.RenderVerticesSet(General.Map.Map.Vertices);
// Go for all remaining vertices
prev = null; first = null;
foreach(EarClipVertex v in remains)
{
// Show the line
if(prev != null) renderer.RenderLine(v.Position, prev.Position, PixelColor.FromColor(Color.OrangeRed));
if(prev == null) first = v;
prev = v;
if(v.IsReflex)
renderer.RenderVertexAt(v.Position, ColorCollection.SELECTION);
else
renderer.RenderVertexAt(v.Position, ColorCollection.VERTICES);
}
if(first != null) renderer.RenderLine(first.Position, prev.Position, PixelColor.FromColor(Color.OrangeRed));
if(found != null)
{
renderer.RenderLine(found[0].Position, found[1].Position, PixelColor.FromColor(Color.SkyBlue));
renderer.RenderLine(found[1].Position, found[2].Position, PixelColor.FromColor(Color.SkyBlue));
renderer.RenderLine(found[2].Position, found[0].Position, PixelColor.FromColor(Color.SkyBlue));
renderer.RenderVertexAt(found[1].Position, ColorCollection.ASSOCIATION);
}
// Done
renderer.Finish();
}
Thread.Sleep(10);
// Start with a clear display
if(renderer.Start(true, true))
{
// Do not show things
renderer.SetThingsRenderOrder(false);
// Render lines and vertices
renderer.RenderLinedefSet(General.Map.Map.Linedefs);
renderer.RenderVerticesSet(General.Map.Map.Vertices);
// Go for all remaining vertices
prev = null; first = null;
foreach(EarClipVertex v in remains)
{
// Show the line
if(prev != null) renderer.RenderLine(v.Position, prev.Position, PixelColor.FromColor(Color.OrangeRed));
if(prev == null) first = v;
prev = v;
if(v.IsReflex)
renderer.RenderVertexAt(v.Position, ColorCollection.SELECTION);
else
renderer.RenderVertexAt(v.Position, ColorCollection.VERTICES);
}
if(first != null) renderer.RenderLine(first.Position, prev.Position, PixelColor.FromColor(Color.OrangeRed));
// Done
renderer.Finish();
}
Thread.Sleep(20);
}
}
#endregion
}
#endif
}

View file

@ -1,365 +0,0 @@
#region ================== Copyright (c) 2007 Pascal vd Heiden
/*
* Copyright (c) 2007 Pascal vd Heiden, www.codeimp.com
* This program is released under GNU General Public License
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#endregion
#region ================== Namespaces
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Reflection;
using CodeImp.DoomBuilder.Interface;
using CodeImp.DoomBuilder.IO;
using CodeImp.DoomBuilder.Map;
using CodeImp.DoomBuilder.Rendering;
using CodeImp.DoomBuilder.Geometry;
using CodeImp.DoomBuilder.Editing;
using CodeImp.DoomBuilder.Controls;
#endregion
namespace CodeImp.DoomBuilder.BuilderModes.Editing
{
[EditMode(SwitchAction = "wauthormode",
ButtonDesc = "WadAuthor Mode",
ButtonImage = "WAuthor.png",
ButtonOrder = int.MinValue + 4,
ConfigSpecific = true)]
public class WAuthorMode : ClassicMode
{
#region ================== Constants
protected const float LINEDEF_HIGHLIGHT_RANGE = 10f;
protected const float VERTEX_HIGHLIGHT_RANGE = 8f;
protected const float THING_HIGHLIGHT_RANGE = 2f;
#endregion
#region ================== Variables
// Tools
protected WAuthorTools tools;
// Highlighted item
protected object highlighted;
#endregion
#region ================== Properties
#endregion
#region ================== Constructor / Disposer
// Constructor
public WAuthorMode()
{
// Initialize
tools = new WAuthorTools();
// Enable this and you'll have a floating window
//tools.Show(General.Interface);
//General.Interface.Focus();
// We have no destructor
GC.SuppressFinalize(this);
}
// Disposer
public override void Dispose()
{
// Not already disposed?
if(!isdisposed)
{
// Clean up
tools.Dispose();
// Dispose base
base.Dispose();
}
}
#endregion
#region ================== Methods
// Cancel mode
public override void Cancel()
{
base.Cancel();
// Return to this mode
General.Map.ChangeMode(new WAuthorMode());
}
// Mode engages
public override void Engage()
{
base.Engage();
}
// Mode disengages
public override void Disengage()
{
base.Disengage();
// Clear selected vertices
General.Map.Map.ClearAllSelected();
// Hide highlight info
General.Interface.HideInfo();
}
// This redraws the display
public unsafe override void RedrawDisplay()
{
// Start with a clear display
if(renderer.Start(true, true))
{
// Render things
renderer.SetThingsRenderOrder(true);
renderer.RenderThingSet(General.Map.Map.Things);
// Render lines and vertices
renderer.RenderLinedefSet(General.Map.Map.Linedefs);
renderer.RenderVerticesSet(General.Map.Map.Vertices);
// Render highlighted item
if(highlighted != null) DrawHighlight(true);
// Done
renderer.Finish();
}
}
// This draws the highlighted item
protected void DrawHighlight(bool highlightcolor)
{
// With highlight color
if(highlightcolor)
{
// Vertex
if(highlighted is Vertex)
{
if((highlighted as Vertex).IsDisposed) return;
renderer.RenderVertex(highlighted as Vertex, ColorCollection.HIGHLIGHT);
}
// Linedef
else if(highlighted is Linedef)
{
if((highlighted as Linedef).IsDisposed) return;
renderer.RenderLinedef((highlighted as Linedef), General.Colors.Highlight);
renderer.RenderVertex((highlighted as Linedef).Start, renderer.DetermineVertexColor((highlighted as Linedef).Start));
renderer.RenderVertex((highlighted as Linedef).End, renderer.DetermineVertexColor((highlighted as Linedef).End));
}
// Sector
else if(highlighted is Sector)
{
if((highlighted as Sector).IsDisposed) return;
renderer.RenderSector((highlighted as Sector), General.Colors.Highlight);
}
// Thing
else if(highlighted is Thing)
{
if((highlighted as Thing).IsDisposed) return;
renderer.RenderThing((highlighted as Thing), General.Colors.Highlight);
}
}
// With original color
else
{
// Vertex
if(highlighted is Vertex)
{
if((highlighted as Vertex).IsDisposed) return;
renderer.RenderVertex(highlighted as Vertex, renderer.DetermineVertexColor(highlighted as Vertex));
}
// Linedef
else if(highlighted is Linedef)
{
if((highlighted as Linedef).IsDisposed) return;
renderer.RenderLinedef((highlighted as Linedef), renderer.DetermineLinedefColor((highlighted as Linedef)));
renderer.RenderVertex((highlighted as Linedef).Start, renderer.DetermineVertexColor((highlighted as Linedef).Start));
renderer.RenderVertex((highlighted as Linedef).End, renderer.DetermineVertexColor((highlighted as Linedef).End));
}
// Sector
else if(highlighted is Sector)
{
if((highlighted as Sector).IsDisposed) return;
renderer.RenderSector((highlighted as Sector));
}
// Thing
else if(highlighted is Thing)
{
if((highlighted as Thing).IsDisposed) return;
renderer.RenderThing((highlighted as Thing), renderer.DetermineThingColor((highlighted as Thing)));
}
}
}
// This highlights a new item
protected void Highlight(object h)
{
// Changes?
if(highlighted != h)
{
// Update display
if(renderer.Start(false, false))
{
// Undraw previous highlight
if(highlighted != null) DrawHighlight(false);
// Set new highlight
highlighted = h;
// Render highlighted item
if(highlighted != null) DrawHighlight(true);
// Done
renderer.Finish();
}
// Hide info
General.Interface.HideInfo();
// Anything highlighted?
if(highlighted != null)
{
// Show highlight info
if(highlighted is Vertex)
General.Interface.ShowVertexInfo(highlighted as Vertex);
else if(highlighted is Linedef)
General.Interface.ShowLinedefInfo(highlighted as Linedef);
else if(highlighted is Sector)
General.Interface.ShowSectorInfo(highlighted as Sector);
else if(highlighted is Thing)
General.Interface.ShowThingInfo(highlighted as Thing);
}
}
}
// Mouse moves
public override void MouseMove(MouseEventArgs e)
{
base.MouseMove(e);
// Not holding any buttons?
if(e.Button == MouseButtons.None)
{
// Find the nearest items within highlight range
Vertex v = General.Map.Map.NearestVertexSquareRange(mousemappos, VERTEX_HIGHLIGHT_RANGE / renderer.Scale);
Thing t = General.Map.Map.NearestThingSquareRange(mousemappos, THING_HIGHLIGHT_RANGE / renderer.Scale);
Linedef l = General.Map.Map.NearestLinedef(mousemappos);
Sector s;
// Check on which side of the linedef the mouse is
float side = l.SideOfLine(mousemappos);
if(side > 0)
{
// Is there a sidedef here?
if(l.Back != null) s = l.Back.Sector;
else s = null;
}
else
{
// Is there a sidedef here?
if(l.Front != null) s = l.Front.Sector;
else s = null;
}
// Both a vertex and thing in range?
if((v != null) && (t != null))
{
// Highlight closest
float vd = v.DistanceToSq(mousemappos);
float td = t.DistanceToSq(mousemappos);
if(vd < td) Highlight(v); else Highlight(t);
}
// Vertex in range?
else if(v != null)
{
// Highlight vertex
Highlight(v);
}
// Thing in range?
else if(t != null)
{
// Highlight thing
Highlight(t);
}
else
{
// Linedef within in range?
float ld = l.DistanceTo(mousemappos, true);
if(ld < (LINEDEF_HIGHLIGHT_RANGE / renderer.Scale))
{
// Highlight line
Highlight(l);
}
// Mouse inside a sector?
else if(s != null)
{
// Highlight sector
Highlight(s);
}
else
{
// Highlight nothing
Highlight(null);
}
}
}
}
// Maybe i'll finish this later, or not even include this mode at all, not sure yet.
// Mouse leaves
public override void MouseLeave(EventArgs e)
{
base.MouseLeave(e);
// Highlight nothing
Highlight(null);
}
// Mouse button pressed
public override void MouseDown(MouseEventArgs e)
{
base.MouseDown(e);
}
// Mouse released
public override void MouseUp(MouseEventArgs e)
{
base.MouseUp(e);
// This shows a popup menu
tools.LinedefPopup.Show(Cursor.Position);
}
// Mouse wants to drag
protected override void DragStart(MouseEventArgs e)
{
base.DragStart(e);
}
#endregion
}
}

View file

@ -1,116 +0,0 @@
namespace CodeImp.DoomBuilder.BuilderModes.Editing
{
partial class WAuthorTools
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if(disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.linedefpopup = new System.Windows.Forms.ContextMenuStrip(this.components);
this.propertiesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator();
this.deleteToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.splitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.flipToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.curveToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.linedefpopup.SuspendLayout();
this.SuspendLayout();
//
// linedefpopup
//
this.linedefpopup.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.propertiesToolStripMenuItem,
this.toolStripMenuItem1,
this.deleteToolStripMenuItem,
this.splitToolStripMenuItem,
this.flipToolStripMenuItem,
this.curveToolStripMenuItem});
this.linedefpopup.Name = "linedefpopup";
this.linedefpopup.Size = new System.Drawing.Size(147, 120);
//
// propertiesToolStripMenuItem
//
this.propertiesToolStripMenuItem.Name = "propertiesToolStripMenuItem";
this.propertiesToolStripMenuItem.Size = new System.Drawing.Size(146, 22);
this.propertiesToolStripMenuItem.Text = "Properties...";
//
// toolStripMenuItem1
//
this.toolStripMenuItem1.Name = "toolStripMenuItem1";
this.toolStripMenuItem1.Size = new System.Drawing.Size(143, 6);
//
// deleteToolStripMenuItem
//
this.deleteToolStripMenuItem.Name = "deleteToolStripMenuItem";
this.deleteToolStripMenuItem.Size = new System.Drawing.Size(146, 22);
this.deleteToolStripMenuItem.Text = "Delete";
//
// splitToolStripMenuItem
//
this.splitToolStripMenuItem.Name = "splitToolStripMenuItem";
this.splitToolStripMenuItem.Size = new System.Drawing.Size(146, 22);
this.splitToolStripMenuItem.Text = "Split";
//
// flipToolStripMenuItem
//
this.flipToolStripMenuItem.Name = "flipToolStripMenuItem";
this.flipToolStripMenuItem.Size = new System.Drawing.Size(146, 22);
this.flipToolStripMenuItem.Text = "Flip";
//
// curveToolStripMenuItem
//
this.curveToolStripMenuItem.Name = "curveToolStripMenuItem";
this.curveToolStripMenuItem.Size = new System.Drawing.Size(146, 22);
this.curveToolStripMenuItem.Text = "Curve...";
//
// WAuthorTools
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 14F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(243, 130);
this.ControlBox = false;
this.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "WAuthorTools";
this.Text = "WAuthorTools";
this.linedefpopup.ResumeLayout(false);
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.ContextMenuStrip linedefpopup;
private System.Windows.Forms.ToolStripMenuItem propertiesToolStripMenuItem;
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem1;
private System.Windows.Forms.ToolStripMenuItem deleteToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem splitToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem flipToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem curveToolStripMenuItem;
}
}

View file

@ -1,21 +0,0 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace CodeImp.DoomBuilder.BuilderModes.Editing
{
public partial class WAuthorTools : Form
{
// Tools
public ContextMenuStrip LinedefPopup { get { return linedefpopup; } }
// Constructor
public WAuthorTools()
{
InitializeComponent();
}
}
}

View file

@ -1,123 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="linedefpopup.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
</root>

View file

@ -58,13 +58,3 @@ wauthormode
allowmouse = true;
allowscroll = true;
}
triangulatormode
{
title = "Edit: Triangulator Mode";
description = "Switches to Triangulator testing mode.";
allowkeys = true;
allowmouse = true;
allowscroll = true;
debugonly = true;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 924 B

View file

@ -134,7 +134,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
// Render lines and vertices
renderer.RenderLinedefSet(General.Map.Map.Linedefs);
renderer.RenderVerticesSet(General.Map.Map.Vertices);
// Render highlighted item
if((highlighted != null) && !highlighted.IsDisposed)
renderer.RenderSector(highlighted, General.Colors.Highlight);

View file

@ -271,6 +271,19 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
// Start rendering
if(renderer.Start(true, false))
{
// Uncomment this to see triangulation
/*
foreach(Sector s in General.Map.Map.Sectors)
{
for(int i = 0; i < s.Triangles.Count; i += 3)
{
renderer.RenderLine(s.Triangles[i + 0], s.Triangles[i + 1], General.Colors.Selection);
renderer.RenderLine(s.Triangles[i + 1], s.Triangles[i + 2], General.Colors.Selection);
renderer.RenderLine(s.Triangles[i + 2], s.Triangles[i + 0], General.Colors.Selection);
}
}
*/
// Render lines and vertices
renderer.RenderLinedefSet(General.Map.Map.Linedefs);
renderer.RenderVerticesSet(unselectedverts);
@ -296,6 +309,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
if(MoveGeometryRelative(mousemappos - dragstartmappos, snaptogrid, snaptonearest))
{
// Update cached values
//General.Map.Map.Update(true, false);
General.Map.Map.Update();
// Redraw

View file

@ -0,0 +1,225 @@
#region ================== Copyright (c) 2007 Pascal vd Heiden
/*
* Copyright (c) 2007 Pascal vd Heiden, www.codeimp.com
* This program is released under GNU General Public License
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#endregion
#region ================== Namespaces
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Reflection;
using CodeImp.DoomBuilder.Interface;
using CodeImp.DoomBuilder.IO;
using CodeImp.DoomBuilder.Map;
using CodeImp.DoomBuilder.Rendering;
using CodeImp.DoomBuilder.Geometry;
using CodeImp.DoomBuilder.Editing;
#endregion
namespace CodeImp.DoomBuilder.BuilderModes.Editing
{
[EditMode(SwitchAction = "visualmode", // Action name used to switch to this mode
ButtonDesc = "Visual Mode", // Description on the button in toolbar/menu
ButtonImage = "VisualMode.png", // Image resource name for the button
ButtonOrder = 0)] // Position of the button (lower is more to the left)
public class BaseVisualMode : VisualMode
{
#region ================== Constants
#endregion
#region ================== Variables
// All constructed visual sectors
private Dictionary<Sector, BaseVisualSector> allsectors;
// List of visible sectors
private Dictionary<Sector, BaseVisualSector> visiblesectors;
#endregion
#region ================== Properties
#endregion
#region ================== Constructor / Disposer
// Constructor
public BaseVisualMode()
{
// Initialize
allsectors = new Dictionary<Sector, BaseVisualSector>(General.Map.Map.Sectors.Count);
visiblesectors = new Dictionary<Sector, BaseVisualSector>();
// We have no destructor
GC.SuppressFinalize(this);
}
// Diposer
public override void Dispose()
{
// Not already disposed?
if(!isdisposed)
{
// Clean up
foreach(KeyValuePair<Sector, BaseVisualSector> s in allsectors) s.Value.Dispose();
visiblesectors = null;
allsectors = null;
// Done
base.Dispose();
}
}
#endregion
#region ================== Private Tools
// This finds the nearest sector to the camera
private Sector FindStartSector(Vector2D campos)
{
float side;
Linedef l;
// Get nearest linedef
l = General.Map.Map.NearestLinedef(campos);
if(l != null)
{
// Check if we are on front or back side
side = l.SideOfLine(campos);
if(side > 0)
{
// Is there a sidedef here?
if(l.Back != null)
return l.Back.Sector;
else if(l.Front != null)
return l.Front.Sector;
else
return null;
}
else
{
// Is there a sidedef here?
if(l.Front != null)
return l.Front.Sector;
else if(l.Back != null)
return l.Back.Sector;
else
return null;
}
}
else
return null;
}
// This recursively finds and adds visible sectors
private void ProcessVisibleSectors(Sector start, Vector2D campos)
{
BaseVisualSector vs;
Sector os;
// Find the basesector and make it if needed
if(allsectors.ContainsKey(start))
{
// Take existing visualsector
vs = allsectors[start];
}
else
{
// Make new visualsector
vs = new BaseVisualSector(start);
allsectors.Add(start, vs);
}
// Add sector to visibility list
visiblesectors.Add(start, vs);
// Go for all sidedefs in the sector
foreach(Sidedef sd in start.Sidedefs)
{
// Doublesided and not referring to same sector?
if((sd.Other != null) && (sd.Other.Sector != sd.Sector))
{
// Get the other sector
os = sd.Other.Sector;
// Sector not yet added?
if(!visiblesectors.ContainsKey(os))
{
// TODO: Visiblity checking!
{
// Process this sector as well
ProcessVisibleSectors(os, campos);
}
}
}
}
}
#endregion
#region ================== Methods
// This draws a frame
public override void RedrawDisplay()
{
// Start drawing
if(renderer.Start())
{
// Begin with geometry
renderer.StartGeometry();
// Render all visible sectors
foreach(KeyValuePair<Sector, BaseVisualSector> vs in visiblesectors)
renderer.RenderGeometry(vs.Value);
// Done rendering geometry
renderer.FinishGeometry();
// Present!
renderer.Finish();
}
// Call base
base.RedrawDisplay();
}
// This processes a frame
public override void Process()
{
Vector2D campos;
// Process base class first
base.Process();
// Get the 2D camera position
campos = new Vector2D(base.CameraPosition.x, base.CameraPosition.y);
// Make new visibility list
visiblesectors = new Dictionary<Sector, BaseVisualSector>(General.Map.Map.Sectors.Count);
// Process all visible sectors starting with the nearest
ProcessVisibleSectors(FindStartSector(campos), campos);
}
#endregion
}
}

View file

@ -35,12 +35,7 @@ using CodeImp.DoomBuilder.Editing;
namespace CodeImp.DoomBuilder.BuilderModes.Editing
{
[EditMode(SwitchAction = "visualmode", // Action name used to switch to this mode
ButtonDesc = "Visual Mode", // Description on the button in toolbar/menu
ButtonImage = "VisualMode.png", // Image resource name for the button
ButtonOrder = 0)] // Position of the button (lower is more to the left)
public class BaseVisualMode : VisualMode
internal class BaseVisualSector : VisualSector
{
#region ================== Constants
@ -57,23 +52,24 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
#region ================== Constructor / Disposer
// Constructor
public BaseVisualMode()
public BaseVisualSector(Sector s) : base(s)
{
// Initialize
Rebuild();
// We have no destructor
GC.SuppressFinalize(this);
}
// Diposer
// Disposer
public override void Dispose()
{
// Not already disposed?
if(!isdisposed)
if(!IsDisposed)
{
// Clean up
// Done
// Dispose base
base.Dispose();
}
}
@ -81,31 +77,31 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
#endregion
#region ================== Methods
// This draws a frame
public override void RedrawDisplay()
// This (re)builds the visual sector, calculating all geometry from scratch
public void Rebuild()
{
VisualSector vs = new VisualSector(General.GetByIndex<Sector>(General.Map.Map.Sectors, 0));
VisualObject vo = new VisualObject();
vo.Texture = General.Map.Data.GetTextureImage("TEKGREN1");
vo.Visible = true;
vs.AddGeometry(vo);
// Forget old geometry
base.ClearGeometry();
// Make the floor and ceiling
base.AddGeometry(new VisualFloor(base.Sector));
base.AddGeometry(new VisualCeiling(base.Sector));
// Start drawing
if(renderer.Start())
// Go for all sidedefs
foreach(Sidedef sd in base.Sector.Sidedefs)
{
// Begin with geometry
renderer.StartGeometry();
renderer.RenderGeometry(vs);
renderer.FinishGeometry();
renderer.Finish();
// Make middle wall
base.AddGeometry(new VisualMiddle(sd));
// Check if upper and lower parts are possible at all
if(sd.Other != null)
{
// Make upper and lower walls
base.AddGeometry(new VisualLower(sd));
base.AddGeometry(new VisualUpper(sd));
}
}
// Call base
base.RedrawDisplay();
}
#endregion

View file

@ -0,0 +1,112 @@
#region ================== Copyright (c) 2007 Pascal vd Heiden
/*
* Copyright (c) 2007 Pascal vd Heiden, www.codeimp.com
* This program is released under GNU General Public License
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#endregion
#region ================== Namespaces
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Reflection;
using System.Drawing;
using System.ComponentModel;
using CodeImp.DoomBuilder.Map;
using CodeImp.DoomBuilder.Geometry;
using System.Drawing.Imaging;
using CodeImp.DoomBuilder.Data;
using CodeImp.DoomBuilder.Editing;
using CodeImp.DoomBuilder.IO;
using CodeImp.DoomBuilder.Rendering;
#endregion
namespace CodeImp.DoomBuilder.BuilderModes.Editing
{
internal class VisualCeiling : VisualGeometry
{
#region ================== Constants
#endregion
#region ================== Variables
#endregion
#region ================== Properties
#endregion
#region ================== Constructor / Disposer
// Constructor
public VisualCeiling(Sector s)
{
WorldVertex[] verts;
WorldVertex v;
PixelColor pc;
// Load floor texture
base.Texture = General.Map.Data.GetFlatImage(s.LongCeilTexture);
base.Texture.LoadImage();
// Make vertices
verts = new WorldVertex[s.Triangles.Count];
for(int i = 0; i < s.Triangles.Count; i++)
{
// Use sector brightness for color shading
//pc = new PixelColor(255, unchecked((byte)s.Brightness), unchecked((byte)s.Brightness), unchecked((byte)s.Brightness));
//verts[i].c = pc.ToInt();
verts[i].c = -1;
// Grid aligned texture coordinates
verts[i].u = s.Triangles[i].x / base.Texture.ScaledWidth;
verts[i].v = s.Triangles[i].y / base.Texture.ScaledHeight;
// Vertex coordinates
verts[i].x = s.Triangles[i].x;
verts[i].y = s.Triangles[i].y;
verts[i].z = (float)s.CeilHeight;
}
// The sector triangulation created clockwise triangles that
// are right up for the floor. For the ceiling we must flip
// the triangles upside down.
// Swap some vertices to flip all triangles
for(int i = 0; i < verts.Length; i += 3)
{
// Swap
v = verts[i];
verts[i] = verts[i + 1];
verts[i + 1] = v;
}
// Apply vertices
base.SetVertices(verts);
// We have no destructor
GC.SuppressFinalize(this);
}
#endregion
#region ================== Methods
#endregion
}
}

View file

@ -38,7 +38,7 @@ using CodeImp.DoomBuilder.Rendering;
namespace CodeImp.DoomBuilder.BuilderModes.Editing
{
internal class VisualObject : VisualGeometry
internal class VisualFloor : VisualGeometry
{
#region ================== Constants
@ -46,87 +46,50 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
#region ================== Variables
// Disposing
private bool isdisposed = false;
#endregion
#region ================== Properties
// Disposing
public bool IsDisposed { get { return isdisposed; } }
#endregion
#region ================== Constructor / Disposer
// Constructor
public VisualObject()
public VisualFloor(Sector s)
{
// Initialize
WorldVertex[] v = new WorldVertex[6];
WorldVertex[] verts;
PixelColor pc;
// Load floor texture
base.Texture = General.Map.Data.GetFlatImage(s.LongFloorTexture);
base.Texture.LoadImage();
// Make vertices
verts = new WorldVertex[s.Triangles.Count];
for(int i = 0; i < s.Triangles.Count; i++)
{
// Use sector brightness for color shading
//pc = new PixelColor(255, unchecked((byte)s.Brightness), unchecked((byte)s.Brightness), unchecked((byte)s.Brightness));
//verts[i].c = pc.ToInt();
verts[i].c = -1;
v[0].c = -1;
v[0].x = 0.0f;
v[0].y = 0.0f;
v[0].z = 0.0f;
v[0].u = 0.0f;
v[0].v = 1.0f;
v[1].c = -1;
v[1].x = 0.0f;
v[1].y = 0.0f;
v[1].z = 100.0f;
v[1].u = 0.0f;
v[1].v = 0.0f;
v[2].c = -1;
v[2].x = 100.0f;
v[2].y = 0.0f;
v[2].z = 100.0f;
v[2].u = 1.0f;
v[2].v = 0.0f;
v[3].c = -1;
v[3].x = 0.0f;
v[3].y = 0.0f;
v[3].z = 0.0f;
v[3].u = 0.0f;
v[3].v = 1.0f;
v[4].c = -1;
v[4].x = 100.0f;
v[4].y = 0.0f;
v[4].z = 100.0f;
v[4].u = 1.0f;
v[4].v = 0.0f;
v[5].c = -1;
v[5].x = 100.0f;
v[5].y = 0.0f;
v[5].z = 0.0f;
v[5].u = 1.0f;
v[5].v = 1.0f;
this.SetVertices(v);
// Grid aligned texture coordinates
verts[i].u = s.Triangles[i].x / base.Texture.ScaledWidth;
verts[i].v = s.Triangles[i].y / base.Texture.ScaledHeight;
// Vertex coordinates
verts[i].x = s.Triangles[i].x;
verts[i].y = s.Triangles[i].y;
verts[i].z = (float)s.FloorHeight;
}
// Apply vertices
base.SetVertices(verts);
// We have no destructor
GC.SuppressFinalize(this);
}
// Diposer
public void Dispose()
{
// Not already disposed?
if(!isdisposed)
{
// Clean up
// Done
isdisposed = true;
}
}
#endregion
#region ================== Methods

View file

@ -0,0 +1,126 @@
#region ================== Copyright (c) 2007 Pascal vd Heiden
/*
* Copyright (c) 2007 Pascal vd Heiden, www.codeimp.com
* This program is released under GNU General Public License
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#endregion
#region ================== Namespaces
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Reflection;
using System.Drawing;
using System.ComponentModel;
using CodeImp.DoomBuilder.Map;
using CodeImp.DoomBuilder.Geometry;
using System.Drawing.Imaging;
using CodeImp.DoomBuilder.Data;
using CodeImp.DoomBuilder.Editing;
using CodeImp.DoomBuilder.IO;
using CodeImp.DoomBuilder.Rendering;
#endregion
namespace CodeImp.DoomBuilder.BuilderModes.Editing
{
internal class VisualLower : VisualGeometry
{
#region ================== Constants
#endregion
#region ================== Variables
#endregion
#region ================== Properties
#endregion
#region ================== Constructor / Disposer
// Constructor
public VisualLower(Sidedef s)
{
WorldVertex[] verts;
PixelColor pc;
float geotop;
float geobottom;
float geoheight;
Vector2D v1, v2;
// Calculate size of this wall part
geotop = (float)s.Other.Sector.FloorHeight;
geobottom = (float)s.Sector.FloorHeight;
geoheight = geotop - geobottom;
if(geoheight > 0.001f)
{
// Texture given?
if((s.LowTexture.Length > 0) && (s.LowTexture[0] != '-'))
{
// Load texture
base.Texture = General.Map.Data.GetTextureImage(s.LongLowTexture);
base.Texture.LoadImage();
}
else
{
// Use missing texture
base.Texture = General.Map.Data.MissingTexture3D;
}
// Get coordinates
if(s.IsFront)
{
v1 = s.Line.Start.Position;
v2 = s.Line.End.Position;
}
else
{
v1 = s.Line.End.Position;
v2 = s.Line.Start.Position;
}
// Make vertices
verts = new WorldVertex[6];
verts[0] = new WorldVertex(v1.x, v1.y, geobottom, -1, 0.0f, 1.0f);
verts[1] = new WorldVertex(v1.x, v1.y, geotop, -1, 0.0f, 0.0f);
verts[2] = new WorldVertex(v2.x, v2.y, geotop, -1, 1.0f, 0.0f);
verts[3] = verts[0];
verts[4] = verts[2];
verts[5] = new WorldVertex(v2.x, v2.y, geobottom, -1, 1.0f, 1.0f);
}
else
{
// No geometry for invisible wall
verts = new WorldVertex[0];
}
// Apply vertices
base.SetVertices(verts);
// We have no destructor
GC.SuppressFinalize(this);
}
#endregion
#region ================== Methods
#endregion
}
}

View file

@ -0,0 +1,141 @@
#region ================== Copyright (c) 2007 Pascal vd Heiden
/*
* Copyright (c) 2007 Pascal vd Heiden, www.codeimp.com
* This program is released under GNU General Public License
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#endregion
#region ================== Namespaces
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Reflection;
using System.Drawing;
using System.ComponentModel;
using CodeImp.DoomBuilder.Map;
using CodeImp.DoomBuilder.Geometry;
using System.Drawing.Imaging;
using CodeImp.DoomBuilder.Data;
using CodeImp.DoomBuilder.Editing;
using CodeImp.DoomBuilder.IO;
using CodeImp.DoomBuilder.Rendering;
#endregion
namespace CodeImp.DoomBuilder.BuilderModes.Editing
{
internal class VisualMiddle : VisualGeometry
{
#region ================== Constants
#endregion
#region ================== Variables
#endregion
#region ================== Properties
#endregion
#region ================== Constructor / Disposer
// Constructor
public VisualMiddle(Sidedef s)
{
WorldVertex[] verts;
PixelColor pc;
float geotop;
float geobottom;
float geoheight;
bool texturegiven;
bool texturerequired;
Vector2D v1, v2;
// Calculate size of this wall part
geotop = (float)s.Sector.CeilHeight;
geobottom = (float)s.Sector.FloorHeight;
geoheight = geotop - geobottom;
if(geoheight > 0.001f)
{
// Check texture status
texturegiven = ((s.MiddleTexture.Length > 0) && (s.MiddleTexture[0] != '-'));
texturerequired = s.MiddleRequired();
// Only create wall when middle texture is set or the wall requires a texture
if(texturegiven || texturerequired)
{
// Texture given?
if(texturegiven)
{
// Load texture
base.Texture = General.Map.Data.GetTextureImage(s.LongMiddleTexture);
base.Texture.LoadImage();
}
else
{
// Use missing texture
base.Texture = General.Map.Data.MissingTexture3D;
}
// Get coordinates
if(s.IsFront)
{
v1 = s.Line.Start.Position;
v2 = s.Line.End.Position;
}
else
{
v1 = s.Line.End.Position;
v2 = s.Line.Start.Position;
}
// Make vertices
verts = new WorldVertex[6];
verts[0] = new WorldVertex(v1.x, v1.y, geobottom, -1, 0.0f, 1.0f);
verts[1] = new WorldVertex(v1.x, v1.y, geotop, -1, 0.0f, 0.0f);
verts[2] = new WorldVertex(v2.x, v2.y, geotop, -1, 1.0f, 0.0f);
verts[3] = verts[0];
verts[4] = verts[2];
verts[5] = new WorldVertex(v2.x, v2.y, geobottom, -1, 1.0f, 1.0f);
}
else
{
// No geometry for invisible wall
verts = new WorldVertex[0];
}
}
else
{
// No geometry for invisible wall
verts = new WorldVertex[0];
}
// Apply vertices
base.SetVertices(verts);
// We have no destructor
GC.SuppressFinalize(this);
}
#endregion
#region ================== Methods
#endregion
}
}

View file

@ -0,0 +1,126 @@
#region ================== Copyright (c) 2007 Pascal vd Heiden
/*
* Copyright (c) 2007 Pascal vd Heiden, www.codeimp.com
* This program is released under GNU General Public License
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#endregion
#region ================== Namespaces
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Reflection;
using System.Drawing;
using System.ComponentModel;
using CodeImp.DoomBuilder.Map;
using CodeImp.DoomBuilder.Geometry;
using System.Drawing.Imaging;
using CodeImp.DoomBuilder.Data;
using CodeImp.DoomBuilder.Editing;
using CodeImp.DoomBuilder.IO;
using CodeImp.DoomBuilder.Rendering;
#endregion
namespace CodeImp.DoomBuilder.BuilderModes.Editing
{
internal class VisualUpper : VisualGeometry
{
#region ================== Constants
#endregion
#region ================== Variables
#endregion
#region ================== Properties
#endregion
#region ================== Constructor / Disposer
// Constructor
public VisualUpper(Sidedef s)
{
WorldVertex[] verts;
PixelColor pc;
float geotop;
float geobottom;
float geoheight;
Vector2D v1, v2;
// Calculate size of this wall part
geotop = (float)s.Sector.CeilHeight;
geobottom = (float)s.Other.Sector.CeilHeight;
geoheight = geotop - geobottom;
if(geoheight > 0.001f)
{
// Texture given?
if((s.HighTexture.Length > 0) && (s.HighTexture[0] != '-'))
{
// Load texture
base.Texture = General.Map.Data.GetTextureImage(s.LongHighTexture);
base.Texture.LoadImage();
}
else
{
// Use missing texture
base.Texture = General.Map.Data.MissingTexture3D;
}
// Get coordinates
if(s.IsFront)
{
v1 = s.Line.Start.Position;
v2 = s.Line.End.Position;
}
else
{
v1 = s.Line.End.Position;
v2 = s.Line.Start.Position;
}
// Make vertices
verts = new WorldVertex[6];
verts[0] = new WorldVertex(v1.x, v1.y, geobottom, -1, 0.0f, 1.0f);
verts[1] = new WorldVertex(v1.x, v1.y, geotop, -1, 0.0f, 0.0f);
verts[2] = new WorldVertex(v2.x, v2.y, geotop, -1, 1.0f, 0.0f);
verts[3] = verts[0];
verts[4] = verts[2];
verts[5] = new WorldVertex(v2.x, v2.y, geobottom, -1, 1.0f, 1.0f);
}
else
{
// No geometry for invisible wall
verts = new WorldVertex[0];
}
// Apply vertices
base.SetVertices(verts);
// We have no destructor
GC.SuppressFinalize(this);
}
#endregion
#region ================== Methods
#endregion
}
}

View file

@ -33,6 +33,7 @@ namespace CodeImp.DoomBuilder.Controls
// Description
private string name;
private string shortname;
private string title;
private string description;
@ -52,6 +53,7 @@ namespace CodeImp.DoomBuilder.Controls
#region ================== Properties
public string Name { get { return name; } }
public string ShortName { get { return shortname; } }
public string Title { get { return title; } }
public string Description { get { return description; } }
public int ShortcutKey { get { return key; } }
@ -64,11 +66,12 @@ namespace CodeImp.DoomBuilder.Controls
#region ================== Constructor / Disposer
// Constructor
public Action(string name, string title, string description, int key,
public Action(string name, string shortname, string title, string description, int key,
bool allowkeys, bool allowmouse, bool allowscroll)
{
// Initialize
this.name = name;
this.shortname = shortname;
this.title = title;
this.description = description;
this.delegates = new List<ActionDelegate>();
@ -166,7 +169,8 @@ namespace CodeImp.DoomBuilder.Controls
// No method bound?
if(delegates.Count == 0)
{
General.WriteLogLine("Called action '" + name + "' has no methods bound");
// Ignore this since keys can also be handled through KeyDown and KeyUp in editing modes
//General.WriteLogLine("Called action '" + name + "' has no methods bound");
}
else
{

View file

@ -95,7 +95,7 @@ namespace CodeImp.DoomBuilder.Controls
Stream actionsdata;
StreamReader actionsreader;
Configuration cfg;
string name, title, desc;
string name, title, desc, shortname;
bool amouse, akeys, ascroll, debugonly;
string[] resnames;
AssemblyName asmname = asm.GetName();
@ -123,7 +123,8 @@ namespace CodeImp.DoomBuilder.Controls
foreach(DictionaryEntry a in cfg.Root)
{
// Get action properties
name = asmname.Name.ToLowerInvariant() + "_" + a.Key.ToString();
shortname = a.Key.ToString();
name = asmname.Name.ToLowerInvariant() + "_" + shortname;
title = cfg.ReadSetting(a.Key + ".title", "[" + name + "]");
desc = cfg.ReadSetting(a.Key + ".description", "");
akeys = cfg.ReadSetting(a.Key + ".allowkeys", false);
@ -135,7 +136,7 @@ namespace CodeImp.DoomBuilder.Controls
if(General.DebugBuild || !debugonly)
{
// Create an action
CreateAction(name, title, desc, akeys, amouse, ascroll);
CreateAction(name, shortname, title, desc, akeys, amouse, ascroll);
}
}
}
@ -143,7 +144,7 @@ namespace CodeImp.DoomBuilder.Controls
}
// This manually creates an action
private void CreateAction(string name, string title, string desc, bool allowkeys, bool allowmouse, bool allowscroll)
private void CreateAction(string name, string shortname, string title, string desc, bool allowkeys, bool allowmouse, bool allowscroll)
{
// Action does not exist yet?
if(!actions.ContainsKey(name))
@ -152,7 +153,7 @@ namespace CodeImp.DoomBuilder.Controls
int key = General.Settings.ReadSetting("shortcuts." + name, 0);
// Create an action
actions.Add(name, new Action(name, title, desc, key, allowkeys, allowmouse, allowscroll));
actions.Add(name, new Action(name, shortname, title, desc, key, allowkeys, allowmouse, allowscroll));
}
else
{
@ -198,7 +199,7 @@ namespace CodeImp.DoomBuilder.Controls
a.Value.SetShortcutKey(0);
}
// This will call the associated action for a keypress
// This will call the associated actions for a keypress
public void InvokeByKey(int key)
{
// Go for all actions
@ -213,6 +214,26 @@ namespace CodeImp.DoomBuilder.Controls
}
}
// This returns all action names for a given key
public string[] GetActionsByKey(int key)
{
List<string> actionnames = new List<string>();
// Go for all actions
foreach(KeyValuePair<string, Action> a in actions)
{
// This action is associated with this key?
if(a.Value.ShortcutKey == key)
{
// List short name
actionnames.Add(a.Value.ShortName);
}
}
// Return result;
return actionnames.ToArray();
}
#endregion
}
}

View file

@ -62,6 +62,9 @@ namespace CodeImp.DoomBuilder.Data
// Background loading
private Thread backgroundloader;
// Special images
private ImageData missingtexture3d;
// Disposing
private bool isdisposed = false;
@ -76,6 +79,7 @@ namespace CodeImp.DoomBuilder.Data
public List<string> FlatNames { get { return flatnames; } }
public bool IsDisposed { get { return isdisposed; } }
public bool IsLoading { get { return (backgroundloader != null) && backgroundloader.IsAlive; } }
public ImageData MissingTexture3D { get { return missingtexture3d; } }
#endregion
@ -86,6 +90,10 @@ namespace CodeImp.DoomBuilder.Data
{
// We have no destructor
GC.SuppressFinalize(this);
// Load special images
missingtexture3d = new ResourceImage("MissingTexture3D.png");
missingtexture3d.LoadImage();
}
// Disposer
@ -96,6 +104,8 @@ namespace CodeImp.DoomBuilder.Data
{
// Clean up
Unload();
missingtexture3d.Dispose();
missingtexture3d = null;
// Done
isdisposed = true;

View file

@ -87,6 +87,8 @@ namespace CodeImp.DoomBuilder.Data
// Get width and height from image
width = bitmap.Size.Width;
height = bitmap.Size.Height;
scaledwidth = (float)width * General.Map.Config.DefaultFlatScale;
scaledheight = (float)height * General.Map.Config.DefaultFlatScale;
}
else
{

View file

@ -203,7 +203,9 @@ namespace CodeImp.DoomBuilder.Editing
public void PerformUndo()
{
UndoSnapshot u, r;
Cursor oldcursor = Cursor.Current;
Cursor.Current = Cursors.WaitCursor;
// Anything to undo?
if(undos.Count > 0)
{
@ -228,6 +230,8 @@ namespace CodeImp.DoomBuilder.Editing
General.MainWindow.RedrawDisplay();
General.MainWindow.UpdateInterface();
}
Cursor.Current = oldcursor;
}
// This performs a redo
@ -235,7 +239,9 @@ namespace CodeImp.DoomBuilder.Editing
public void PerformRedo()
{
UndoSnapshot u, r;
Cursor oldcursor = Cursor.Current;
Cursor.Current = Cursors.WaitCursor;
// Anything to redo?
if(redos.Count > 0)
{
@ -260,6 +266,8 @@ namespace CodeImp.DoomBuilder.Editing
General.MainWindow.RedrawDisplay();
General.MainWindow.UpdateInterface();
}
Cursor.Current = oldcursor;
}
#endregion

View file

@ -45,8 +45,9 @@ namespace CodeImp.DoomBuilder.Editing
#region ================== Constants
private const float ANGLE_FROM_MOUSE = 0.0001f;
private const float MAX_ANGLEZ_UP = 80f / Angle2D.PIDEG;
private const float MAX_ANGLEZ_DOWN = (360f - 80f) / Angle2D.PIDEG;
private const float MAX_ANGLEZ_LOW = 100f / Angle2D.PIDEG;
private const float MAX_ANGLEZ_HIGH = (360f - 100f) / Angle2D.PIDEG;
private const float CAMERA_SPEED = 6f;
#endregion
@ -64,6 +65,12 @@ namespace CodeImp.DoomBuilder.Editing
private Vector3D camtarget;
private float camanglexy, camanglez;
// Input
private bool keyforward;
private bool keybackward;
private bool keyleft;
private bool keyright;
#endregion
#region ================== Properties
@ -83,6 +90,8 @@ namespace CodeImp.DoomBuilder.Editing
// Initialize
this.renderer = General.Map.Renderer3D;
this.renderer3d = (Renderer3D)General.Map.Renderer3D;
this.campos = new Vector3D(0.0f, 0.0f, 96.0f);
this.camanglez = Angle2D.PI;
}
// Diposer
@ -100,7 +109,7 @@ namespace CodeImp.DoomBuilder.Editing
#endregion
#region ================== Methods
#region ================== Start / Stop
// Mode is engaged
public override void Engage()
@ -116,9 +125,9 @@ namespace CodeImp.DoomBuilder.Editing
{
// Position camera here
modething.DetermineSector();
campos = modething.Position + new Vector3D(0, 0, 20);
camanglexy = modething.Angle;
camanglez = 0f;
campos = modething.Position + new Vector3D(0.0f, 0.0f, 96.0f);
camanglexy = modething.Angle + Angle2D.PI;
camanglez = Angle2D.PI;
}
// Start special input mode
@ -136,7 +145,7 @@ namespace CodeImp.DoomBuilder.Editing
{
// Position the thing to match camera
modething.Move((int)campos.x, (int)campos.y, 0);
modething.Rotate(camanglexy);
modething.Rotate(camanglexy - Angle2D.PI);
}
// Stop special input mode
@ -144,32 +153,98 @@ namespace CodeImp.DoomBuilder.Editing
General.Interface.StopExclusiveMouseInput();
}
#endregion
#region ================== Input
// Mouse input
public override void MouseInput(Vector2D delta)
{
base.MouseInput(delta);
// Change camera angles with the mouse changes
camanglexy += delta.x * ANGLE_FROM_MOUSE;
camanglez -= delta.y * ANGLE_FROM_MOUSE;
camanglexy -= delta.x * ANGLE_FROM_MOUSE;
camanglez += delta.y * ANGLE_FROM_MOUSE;
// Normalize angles
camanglexy = Angle2D.Normalized(camanglexy);
camanglez = Angle2D.Normalized(camanglez);
// Limit vertical angle
if(camanglez < MAX_ANGLEZ_UP) camanglez = MAX_ANGLEZ_UP;
if(camanglez > MAX_ANGLEZ_DOWN) camanglez = MAX_ANGLEZ_DOWN;
// Normalize horizontal angle
camanglexy = Angle2D.Normalized(camanglexy);
if(camanglez < MAX_ANGLEZ_LOW) camanglez = MAX_ANGLEZ_LOW;
if(camanglez > MAX_ANGLEZ_HIGH) camanglez = MAX_ANGLEZ_HIGH;
General.MainWindow.UpdateCoordinates(new Vector2D(camanglexy, camanglez));
}
// Key down
public override void KeyDown(KeyEventArgs e)
{
string[] actions;
base.KeyDown(e);
// Get the actions for this key
actions = General.Actions.GetActionsByKey((int)e.KeyData);
foreach(string a in actions)
{
// Check what key was pressed down
switch(a)
{
case "moveforward": keyforward = true; break;
case "movebackward": keybackward = true; break;
case "moveleft": keyleft = true; break;
case "moveright": keyright = true; break;
}
}
}
// Key up
public override void KeyUp(KeyEventArgs e)
{
string[] actions;
base.KeyUp(e);
// Get the actions for this key
actions = General.Actions.GetActionsByKey((int)e.KeyData);
foreach(string a in actions)
{
// Check what key was pressed down
switch(a)
{
case "moveforward": keyforward = false; break;
case "movebackward": keybackward = false; break;
case "moveleft": keyleft = false; break;
case "moveright": keyright = false; break;
}
}
}
#endregion
#region ================== Processing
// Processing
public override void Process()
{
Vector3D camvec;
Vector3D camvecstrafe;
base.Process();
// Calculate camera direction vectors
camvec = Vector3D.FromAngleXYZ(camanglexy, camanglez);
camvecstrafe = Vector3D.FromAngleXYZ(camanglexy + Angle2D.PIHALF, camanglez);
// Move the camera
if(keyforward) campos += camvec * CAMERA_SPEED;
if(keybackward) campos -= camvec * CAMERA_SPEED;
if(keyleft) campos -= camvecstrafe * CAMERA_SPEED;
if(keyright) campos += camvecstrafe * CAMERA_SPEED;
// Target the camera
camtarget = campos + Vector3D.FromAngleXYZ(camanglexy, camanglez);
camtarget = campos + camvec;
// Apply new camera matrices
renderer.PositionAndLookAt(campos, camtarget);

View file

@ -117,6 +117,9 @@ namespace CodeImp.DoomBuilder
// States
private static bool debugbuild;
// Tools
private static EarClipTriangulator earclipper;
#endregion
#region ================== Properties
@ -139,6 +142,7 @@ namespace CodeImp.DoomBuilder
internal static PluginManager Plugins { get { return plugins; } }
public static Clock Clock { get { return clock; } }
public static bool DebugBuild { get { return debugbuild; } }
internal static EarClipTriangulator EarClipper { get { return earclipper; } }
#endregion
@ -430,7 +434,7 @@ namespace CodeImp.DoomBuilder
{
// Create action manager
actions = new ActionManager();
// Bind static methods to actions
ActionAttribute.BindMethods(typeof(General));
@ -444,6 +448,9 @@ namespace CodeImp.DoomBuilder
mainwindow.Show();
mainwindow.Update();
// Create tools
earclipper = new EarClipTriangulator();
// Start Direct3D
General.WriteLogLine("Starting Direct3D graphics driver...");
Direct3D.Initialize();

View file

@ -36,7 +36,9 @@ namespace CodeImp.DoomBuilder.Geometry
/// Performs triangulation of sectors by using ear clipping.
/// </summary>
/// See: http://www.geometrictools.com/Documentation/TriangulationByEarClipping.pdf
public sealed class EarClipTriangulator : Triangulator
/// NOTE: This is not a derived class from Triangulator because
/// caching is not required (sectors cache their own triangles)
public sealed class EarClipTriangulator
{
#region ================== Delegates
@ -79,25 +81,12 @@ namespace CodeImp.DoomBuilder.Geometry
GC.SuppressFinalize(this);
}
// Diposer
public override void Dispose()
{
// Not already disposed?
if(!isdisposed)
{
// Clean up
// Done
base.Dispose();
}
}
#endregion
#region ================== Methods
// This triangulates a sector and stores it
protected override void PerformTriangulation(Sector sector)
public TriangleList PerformTriangulation(Sector sector)
{
TriangleList triangles = new TriangleList();
List<Polygon> polys;
@ -125,8 +114,8 @@ namespace CodeImp.DoomBuilder.Geometry
// EAR-CLIPPING
foreach(Polygon p in polys) triangles.AddRange(DoEarClip(p));
// STORE
base.StoreTriangles(sector, triangles);
// Return result
return triangles;
}
#endregion
@ -618,6 +607,9 @@ namespace CodeImp.DoomBuilder.Geometry
if(!v2.IsReflex && CheckValidEar(t2, reflexes)) v2.AddEarTip(eartips); else v2.RemoveEarTip();
}
// Dispose remaining vertices
foreach(EarClipVertex ecv in verts) ecv.Dispose();
// Return result
return result;
}

View file

@ -256,7 +256,7 @@ namespace CodeImp.DoomBuilder.IO
// Create new item
l = map.CreateLinedef(vertexlink[v1], vertexlink[v2]);
l.Update(flags, tag, action, Linedef.EMPTY_ARGS);
l.Update();
l.UpdateCache();
// Line has a front side?
if(s1 != ushort.MaxValue)

View file

@ -270,7 +270,7 @@ namespace CodeImp.DoomBuilder.IO
// Create new item
l = map.CreateLinedef(vertexlink[v1], vertexlink[v2]);
l.Update(flags, 0, action, args);
l.Update();
l.UpdateCache();
// Line has a front side?
if(s1 != ushort.MaxValue)

View file

@ -60,6 +60,7 @@ namespace CodeImp.DoomBuilder.Map
// Cache
private bool updateneeded;
private float lengthsq;
private float lengthsqinv;
private float length;
private float lengthinv;
private float angle;
@ -235,7 +236,7 @@ namespace CodeImp.DoomBuilder.Map
}
// This updates the line when changes have been made
public void Update()
public void UpdateCache()
{
Vector2D delta;
int l, t, r, b;
@ -250,6 +251,7 @@ namespace CodeImp.DoomBuilder.Map
lengthsq = delta.GetLengthSq();
length = (float)Math.Sqrt(lengthsq);
if(length > 0f) lengthinv = 1f / length; else lengthinv = 1f / 0.0000000001f;
if(lengthsq > 0f) lengthsqinv = 1f / lengthsq; else lengthsqinv = 1f / 0.0000000001f;
angle = delta.GetAngle();
l = Math.Min(start.X, end.X);
t = Math.Min(start.Y, end.Y);
@ -262,10 +264,15 @@ namespace CodeImp.DoomBuilder.Map
}
}
// This flags the line needs an update
// This flags the line needs an update because it moved
public void NeedUpdate()
{
// Update this line
updateneeded = true;
// Update sectors as well
if(front != null) front.Sector.UpdateNeeded = true;
if(back != null) back.Sector.UpdateNeeded = true;
}
#endregion
@ -297,7 +304,7 @@ namespace CodeImp.DoomBuilder.Map
Vector2D v2 = end.Position;
// Calculate intersection offset
float u = ((p.x - v1.x) * (v2.x - v1.x) + (p.y - v1.y) * (v2.y - v1.y)) / lengthsq;
float u = ((p.x - v1.x) * (v2.x - v1.x) + (p.y - v1.y) * (v2.y - v1.y)) * lengthsqinv;
// Limit intersection offset to the line
if(bounded) if(u < lengthinv) u = lengthinv; else if(u > (1f - lengthinv)) u = 1f - lengthinv;
@ -325,7 +332,7 @@ namespace CodeImp.DoomBuilder.Map
Vector2D v2 = end.Position;
// Calculate intersection offset
float u = ((p.x - v1.x) * (v2.x - v1.x) + (p.y - v1.y) * (v2.y - v1.y)) / lengthsq;
float u = ((p.x - v1.x) * (v2.x - v1.x) + (p.y - v1.y) * (v2.y - v1.y)) * lengthsqinv;
// Limit intersection offset to the line
if(bounded) if(u < 0f) u = 0f; else if(u > 1f) u = 1f;

View file

@ -345,9 +345,19 @@ namespace CodeImp.DoomBuilder.Map
// This updates all structures if needed
public void Update()
{
// Update all!
Update(true, true);
}
// This updates all structures if needed
public void Update(bool dolines, bool dosectors)
{
// Update all linedefs
foreach(Linedef l in linedefs) l.Update();
if(dolines) foreach(Linedef l in linedefs) l.UpdateCache();
// Update all sectors
if(dosectors) foreach(Sector s in sectors) s.UpdateCache();
}
// This updates all structures after a
@ -537,9 +547,9 @@ namespace CodeImp.DoomBuilder.Map
}
// This returns the cohen-sutherland field bits for a vertex in a rectangle area
private static byte GetCSFieldBits(Vertex v, ref Rectangle area)
private static int GetCSFieldBits(Vertex v, ref Rectangle area)
{
byte bits = 0;
int bits = 0;
if(v.Y < area.Top) bits |= 0x01;
if(v.Y > area.Bottom) bits |= 0x02;
if(v.X < area.Left) bits |= 0x04;
@ -603,8 +613,8 @@ namespace CodeImp.DoomBuilder.Map
// Join nearby vertices
stitches += MapSet.JoinVertices(fixedverts, movingverts, true, General.Settings.StitchDistance);
// Update cached values
Update();
// Update cached values of lines because we need their length/angle
Update(true, false);
// Split moving lines with unselected vertices
nearbyfixedverts = MapSet.FilterByArea(fixedverts, ref editarea);
@ -836,8 +846,8 @@ namespace CodeImp.DoomBuilder.Map
// Both lines must be updated because their new length
// is relevant for next iterations!
l.Update();
nl.Update();
l.UpdateCache();
nl.UpdateCache();
// Add both lines to changedlines
if(changedlines != null) changedlines.Add(l);
@ -852,6 +862,8 @@ namespace CodeImp.DoomBuilder.Map
}
// Will have to restart when splitted
// TODO: If we make (linked) lists from the collections first,
// we don't have to restart when splitted?
if(splitted) break;
}
}

View file

@ -22,6 +22,7 @@ using System.Collections.Generic;
using System.Globalization;
using System.Text;
using CodeImp.DoomBuilder.IO;
using CodeImp.DoomBuilder.Geometry;
#endregion
@ -65,6 +66,10 @@ namespace CodeImp.DoomBuilder.Map
// Cloning
private Sector clone;
// Triangulation
private bool updateneeded;
private TriangleList triangles;
// Disposing
private bool isdisposed = false;
@ -87,7 +92,9 @@ namespace CodeImp.DoomBuilder.Map
public int Tag { get { return tag; } set { tag = value; if((tag < 0) || (tag > MapSet.HIGHEST_TAG)) throw new ArgumentOutOfRangeException("Tag", "Invalid tag number"); } }
public int Brightness { get { return brightness; } }
public bool Selected { get { return selected; } set { selected = value; } }
public bool UpdateNeeded { get { return updateneeded; } set { updateneeded |= value; } }
public Sector Clone { get { return clone; } set { clone = value; } }
public TriangleList Triangles { get { return triangles; } set { triangles = value; } }
#endregion
@ -156,7 +163,11 @@ namespace CodeImp.DoomBuilder.Map
}
// This attaches a sidedef and returns the listitem
public LinkedListNode<Sidedef> AttachSidedef(Sidedef sd) { return sidedefs.AddLast(sd); }
public LinkedListNode<Sidedef> AttachSidedef(Sidedef sd)
{
updateneeded = true;
return sidedefs.AddLast(sd);
}
// This detaches a sidedef
public void DetachSidedef(LinkedListNode<Sidedef> l)
@ -165,6 +176,7 @@ namespace CodeImp.DoomBuilder.Map
if(!isdisposed)
{
// Remove sidedef
updateneeded = true;
sidedefs.Remove(l);
// No more sidedefs left?
@ -181,6 +193,20 @@ namespace CodeImp.DoomBuilder.Map
// This detaches a thing
public void DetachThing(LinkedListNode<Thing> l) { if(!isdisposed) things.Remove(l); }
// This updates the sector when changes have been made
public void UpdateCache()
{
// Update if needed
if(updateneeded)
{
// Triangulate sector again
triangles = General.EarClipper.PerformTriangulation(this);
// Updated
updateneeded = false;
}
}
#endregion

View file

@ -578,6 +578,8 @@ namespace CodeImp.DoomBuilder.Rendering
if(count > 0)
{
// Set renderstates for things rendering
graphics.Device.SetRenderState(RenderState.CullMode, Cull.None);
graphics.Device.SetRenderState(RenderState.ZEnable, false);
graphics.Device.SetRenderState(RenderState.AlphaBlendEnable, false);
graphics.Device.SetRenderState(RenderState.AlphaTestEnable, true);
graphics.Device.SetTexture(0, thingtexture.Texture);

View file

@ -133,7 +133,7 @@ namespace CodeImp.DoomBuilder.Rendering
anglez = delta.GetAngleZ();
// Make the view matrix
view = Matrix.LookAtRH(D3DDevice.V3(pos), D3DDevice.V3(lookat), new Vector3(0f, 0f, 1f));
view = Matrix.LookAtRH(D3DDevice.V3(pos), D3DDevice.V3(lookat), new Vector3(0f, 0f, -1f));
// Make the billboard matrix
billboard = Matrix.RotationYawPitchRoll(0f, anglexy, anglez - Angle2D.PIHALF);
@ -182,6 +182,13 @@ namespace CodeImp.DoomBuilder.Rendering
// This begins rendering world geometry
public void StartGeometry()
{
// Renderstates
graphics.Device.SetRenderState(RenderState.CullMode, Cull.CounterClockwise);
graphics.Device.SetRenderState(RenderState.ZEnable, true);
graphics.Device.SetRenderState(RenderState.ZWriteEnable, true);
graphics.Device.SetRenderState(RenderState.AlphaBlendEnable, false);
graphics.Device.SetRenderState(RenderState.AlphaTestEnable, true);
// Setup shader
graphics.Shaders.World3D.Begin();
graphics.Shaders.World3D.WorldViewProj = viewproj;
@ -216,36 +223,40 @@ namespace CodeImp.DoomBuilder.Rendering
// Update the sector if needed
if(s.NeedsUpdateGeo) s.Update();
// Set the buffer
graphics.Device.SetStreamSource(0, s.GeometryBuffer, 0, WorldVertex.Stride);
// Go for all geometry in this sector
foreach(VisualGeometry g in s.GeometryList)
// Only render when a vertexbuffer exists
if(s.GeometryBuffer != null)
{
// Change texture?
if(g.Texture != lasttexture)
{
// Now using this texture
lasttexture = g.Texture;
if(lasttexture != null)
{
// Load image and make texture
if(!lasttexture.IsLoaded) lasttexture.LoadImage();
if((lasttexture.Texture == null) || lasttexture.Texture.Disposed)
lasttexture.CreateTexture();
// Set the buffer
graphics.Device.SetStreamSource(0, s.GeometryBuffer, 0, WorldVertex.Stride);
// Apply texture
graphics.Shaders.World3D.Texture1 = lasttexture.Texture;
graphics.Shaders.World3D.ApplySettings();
// Go for all geometry in this sector
foreach(VisualGeometry g in s.GeometryList)
{
// Change texture?
if(g.Texture != lasttexture)
{
// Now using this texture
lasttexture = g.Texture;
if(lasttexture != null)
{
// Load image and make texture
if(!lasttexture.IsLoaded) lasttexture.LoadImage();
if((lasttexture.Texture == null) || lasttexture.Texture.Disposed)
lasttexture.CreateTexture();
// Apply texture
graphics.Shaders.World3D.Texture1 = lasttexture.Texture;
graphics.Shaders.World3D.ApplySettings();
}
}
// Render it!
graphics.Device.DrawPrimitives(PrimitiveType.TriangleList, g.VertexOffset, g.Triangles);
}
// Render it!
graphics.Device.DrawPrimitives(PrimitiveType.TriangleList, g.VertexOffset, g.Triangles);
// Remove references
graphics.Shaders.World3D.Texture1 = null;
}
// Remove references
graphics.Shaders.World3D.Texture1 = null;
}
#endregion

View file

@ -82,13 +82,10 @@ namespace CodeImp.DoomBuilder.Rendering
// Register as resource
General.Map.Graphics.RegisterResource(this);
// We have no destructor
GC.SuppressFinalize(this);
}
// Diposer
public void Dispose()
public virtual void Dispose()
{
// Not already disposed?
if(!isdisposed)
@ -112,7 +109,7 @@ namespace CodeImp.DoomBuilder.Rendering
// This is called before a device is reset
// (when resized or display adapter was changed)
public void UnloadResource()
public virtual void UnloadResource()
{
// Trash geometry buffer
if(geobuffer != null) geobuffer.Dispose();
@ -122,7 +119,7 @@ namespace CodeImp.DoomBuilder.Rendering
// This is called resets when the device is reset
// (when resized or display adapter was changed)
public void ReloadResource()
public virtual void ReloadResource()
{
// Make new geometry
//Update();
@ -137,6 +134,7 @@ namespace CodeImp.DoomBuilder.Rendering
// Trash geometry buffer
if(geobuffer != null) geobuffer.Dispose();
geobuffer = null;
// Sort the geo list by texture
geolist.Sort();
@ -144,21 +142,28 @@ namespace CodeImp.DoomBuilder.Rendering
// Count the number of vertices there are
foreach(VisualGeometry g in geolist) numverts += g.Vertices.Length;
// Make a new buffer
geobuffer = new VertexBuffer(General.Map.Graphics.Device, WorldVertex.Stride * numverts,
Usage.WriteOnly | Usage.Dynamic, VertexFormat.None, Pool.Default);
// Fill the buffer
bufferstream = geobuffer.Lock(0, WorldVertex.Stride * numverts, LockFlags.Discard);
foreach(VisualGeometry g in geolist)
// Any vertics?
if(numverts > 0)
{
bufferstream.WriteRange<WorldVertex>(g.Vertices, v, g.Vertices.Length);
g.VertexOffset = v;
v += g.Vertices.Length;
}
geobuffer.Unlock();
bufferstream.Dispose();
// Make a new buffer
geobuffer = new VertexBuffer(General.Map.Graphics.Device, WorldVertex.Stride * numverts,
Usage.WriteOnly | Usage.Dynamic, VertexFormat.None, Pool.Default);
// Fill the buffer
bufferstream = geobuffer.Lock(0, WorldVertex.Stride * numverts, LockFlags.Discard);
foreach(VisualGeometry g in geolist)
{
if(g.Vertices.Length > 0)
{
bufferstream.WriteRange<WorldVertex>(g.Vertices);
g.VertexOffset = v;
v += g.Vertices.Length;
}
}
geobuffer.Unlock();
bufferstream.Dispose();
}
// Done
updategeo = false;
}
@ -171,6 +176,14 @@ namespace CodeImp.DoomBuilder.Rendering
updategeo = true;
}
// This removes all geometry
public void ClearGeometry()
{
foreach(VisualGeometry g in geolist) g.Sector = null;
geolist.Clear();
updategeo = true;
}
#endregion
}
}

View file

@ -50,5 +50,49 @@ namespace CodeImp.DoomBuilder.Rendering
public int c;
public float u;
public float v;
// Constructor
public WorldVertex(float x, float y, float z, int c, float u, float v)
{
this.x = x;
this.y = y;
this.z = z;
this.c = c;
this.u = u;
this.v = v;
}
// Constructor
public WorldVertex(float x, float y, float z, float u, float v)
{
this.x = x;
this.y = y;
this.z = z;
this.c = -1;
this.u = u;
this.v = v;
}
// Constructor
public WorldVertex(float x, float y, float z, int c)
{
this.x = x;
this.y = y;
this.z = z;
this.c = c;
this.u = 0.0f;
this.v = 0.0f;
}
// Constructor
public WorldVertex(float x, float y, float z)
{
this.x = x;
this.y = y;
this.z = z;
this.c = -1;
this.u = 0.0f;
this.v = 0.0f;
}
}
}

View file

@ -134,7 +134,7 @@ scrolleast
scrollnorth
{
title = "2D: Scroll North";
description = "Scrolls the 2D map view to the north.";
description = "Scrolls the 2D map view to the up.";
allowkeys = true;
allowmouse = true;
allowscroll = true;
@ -143,7 +143,7 @@ scrollnorth
scrollsouth
{
title = "2D: Scroll South";
description = "Scrolls the 2D map view to the south.";
description = "Scrolls the 2D map view to the down.";
allowkeys = true;
allowmouse = true;
allowscroll = true;
@ -229,3 +229,39 @@ clearselection
allowmouse = true;
allowscroll = true;
}
moveforward
{
title = "3D: Move Forward";
description = "Moves the camera forward in 3D Visual Mode.";
allowkeys = true;
allowmouse = true;
allowscroll = true;
}
movebackward
{
title = "3D: Move Backward";
description = "Moves the camera backward in 3D Visual Mode.";
allowkeys = true;
allowmouse = true;
allowscroll = true;
}
moveleft
{
title = "3D: Move Left (strafe)";
description = "Strafes the camera left in 3D Visual Mode.";
allowkeys = true;
allowmouse = true;
allowscroll = true;
}
moveright
{
title = "3D: Move Right (strafe)";
description = "Strafes the camera right in 3D Visual Mode.";
allowkeys = true;
allowmouse = true;
allowscroll = true;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 695 B