wip map importer stuff
This commit is contained in:
@@ -22,7 +22,15 @@ namespace Cabrito
|
||||
|
||||
protected TextLayoutOptions _layout;
|
||||
|
||||
public FontReference Font;
|
||||
private FontReference Font;
|
||||
|
||||
public int FontHeight
|
||||
{
|
||||
get
|
||||
{
|
||||
return Font.GetFont().Height;
|
||||
}
|
||||
}
|
||||
|
||||
public float LineSpacing = 1.0f;
|
||||
|
||||
@@ -65,12 +73,14 @@ namespace Cabrito
|
||||
{
|
||||
}
|
||||
|
||||
public ConsoleContentTextBox(ConsoleInputTextBox inputBox, float x, float y, float width, float height) : base(
|
||||
public ConsoleContentTextBox(FontReference font, ConsoleInputTextBox inputBox, float x, float y, float width, float height) : base(
|
||||
x, y, width, height)
|
||||
{
|
||||
this.inputBox = inputBox;
|
||||
Height = height;
|
||||
|
||||
Font = font;
|
||||
|
||||
_layout = TextLayoutOptions.Default;
|
||||
_layout.VerticalAlignment = TextAlignment.Near;
|
||||
_layout.TextWrapping = TextWrapping.WrapChars;
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using FlaxEditor;
|
||||
using FlaxEngine;
|
||||
using FlaxEngine.Assertions;
|
||||
using FlaxEngine.GUI;
|
||||
|
||||
namespace Cabrito
|
||||
@@ -85,13 +86,12 @@ namespace Cabrito
|
||||
if (consoleBox == null)
|
||||
{
|
||||
//consoleBox = new ConsoleContentTextBox(null, 0, 0, consoleSize.X, consoleSize.Y - fontHeight);
|
||||
consoleBox = new ConsoleContentTextBox(null, 0, 0, 0, 0);
|
||||
consoleBox = new ConsoleContentTextBox(fontReference, null, 0, 0, 0, 0);
|
||||
|
||||
|
||||
consoleBox.SetAnchorPreset(AnchorPresets.HorizontalStretchTop, true);
|
||||
//consoleBox.AnchorMax = new Vector2(1.0f, ConsoleHeight);
|
||||
//consoleBox.Height = consoleSize.Y - fontHeight;
|
||||
consoleBox.Font = fontReference;
|
||||
|
||||
//consoleBox.HorizontalAlignment = TextAlignment.Near;
|
||||
//consoleBox.VerticalAlignment = TextAlignment.Near;
|
||||
@@ -113,14 +113,12 @@ namespace Cabrito
|
||||
if (consoleNotifyBox == null)
|
||||
{
|
||||
//consoleBox = new ConsoleContentTextBox(null, 0, 0, consoleSize.X, consoleSize.Y - fontHeight);
|
||||
consoleNotifyBox = new ConsoleContentTextBox(null, 0, 0, 0, 0);
|
||||
consoleNotifyBox = new ConsoleContentTextBox(fontReference, null, 0, 0, 0, 0);
|
||||
consoleNotifyBox.HeightMultiplier = 0;
|
||||
consoleNotifyBox.Height = ConsoleNotifyLines * fontHeight;
|
||||
consoleNotifyBox.SetAnchorPreset(AnchorPresets.HorizontalStretchTop, true);
|
||||
//consoleBox.AnchorMax = new Vector2(1.0f, ConsoleHeight);
|
||||
|
||||
consoleNotifyBox.Font = fontReference;
|
||||
|
||||
//consoleBox.HorizontalAlignment = TextAlignment.Near;
|
||||
//consoleBox.VerticalAlignment = TextAlignment.Near;
|
||||
//consoleNotifyBox.HeightMultiplier = ConsoleHeight;
|
||||
@@ -263,11 +261,23 @@ namespace Cabrito
|
||||
|
||||
private void OnSendExceptionLog(Exception exception, FlaxEngine.Object obj)
|
||||
{
|
||||
Console.Print("[EXCEP] " + exception.Message);
|
||||
AssertionException assert = exception as AssertionException;
|
||||
if (assert != null)
|
||||
{
|
||||
var assertLines = assert.Message.Split('\n');
|
||||
if (assertLines.Length > 2)
|
||||
Console.Print("Assert Failure: " + assertLines[2]);
|
||||
else
|
||||
Console.Print("Assert Failure: " + assert.Message);
|
||||
}
|
||||
else
|
||||
Console.Print("[EXCEP] " + exception.Message);
|
||||
}
|
||||
|
||||
public override void OnDestroy()
|
||||
{
|
||||
base.OnDestroy();
|
||||
|
||||
//consoleInputEvent.Triggered -= OnConsoleInputEvent;
|
||||
consoleInputEvent?.Dispose();
|
||||
consoleBox?.Dispose();
|
||||
@@ -325,7 +335,6 @@ namespace Cabrito
|
||||
|
||||
public void OnConsoleClose()
|
||||
{
|
||||
Console.Print("closed console");
|
||||
Screen.CursorVisible = false;
|
||||
Screen.CursorLock = CursorLockMode.Locked;
|
||||
|
||||
@@ -383,7 +392,7 @@ namespace Cabrito
|
||||
}
|
||||
else if (!Console.IsOpen)
|
||||
{
|
||||
int fontHeight = (int) (consoleNotifyBox.Font.GetFont().Height / Platform.DpiScale);
|
||||
int fontHeight = (int) (consoleNotifyBox.FontHeight / Platform.DpiScale);
|
||||
if (location.Y < (-conHeight * ConsoleHeight) + fontHeight)
|
||||
{
|
||||
consoleNotifyBox.Visible = true;
|
||||
@@ -395,7 +404,7 @@ namespace Cabrito
|
||||
|
||||
public void OnPrint(string text)
|
||||
{
|
||||
int fontHeight = (int) (consoleNotifyBox.Font.GetFont().Height / Platform.DpiScale);
|
||||
int fontHeight = (int) (consoleNotifyBox.FontHeight / Platform.DpiScale);
|
||||
consoleNotifyBox.Height = Math.Min(ConsoleNotifyLines, Console.Lines.Count) * fontHeight;
|
||||
}
|
||||
|
||||
|
||||
497
Source/Game/MapParser/MapParser.cs
Normal file
497
Source/Game/MapParser/MapParser.cs
Normal file
@@ -0,0 +1,497 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using FlaxEngine;
|
||||
|
||||
// https://web.archive.org/web/20160316213335/http://forums.ubergames.net/topic/2658-understanding-the-quake-3-map-format/
|
||||
// https://web.archive.org/web/20210228125854/https://forums.thedarkmod.com/index.php?/topic/15668-plugin-request-save-map-in-quake-3-format/
|
||||
|
||||
namespace Game
|
||||
{
|
||||
public struct MapFacePlane
|
||||
{
|
||||
public Vector3 v1, v2, v3;
|
||||
public string texture;
|
||||
public Vector2 offset;
|
||||
public float rotation;
|
||||
public Vector2 scale;
|
||||
public int contentFlags, surfaceFlags, surfaceValue;
|
||||
}
|
||||
|
||||
public class MapBrush
|
||||
{
|
||||
public MapFacePlane[] planes;
|
||||
}
|
||||
|
||||
public class MapPatch
|
||||
{
|
||||
public string name;
|
||||
}
|
||||
|
||||
public struct PatchVertex
|
||||
{
|
||||
public Vector3 v;
|
||||
public Vector2 uv;
|
||||
}
|
||||
|
||||
public class MapEntity
|
||||
{
|
||||
public Dictionary<string, string> properties = new Dictionary<string, string>();
|
||||
public List<MapEntity> entities = new List<MapEntity>();
|
||||
public List<MapBrush> brushes = new List<MapBrush>();
|
||||
public List<MapPatch> patches = new List<MapPatch>();
|
||||
}
|
||||
|
||||
public static class MapParser
|
||||
{
|
||||
static public MapEntity Parse(byte[] data)
|
||||
{
|
||||
if (data.Length == 0)
|
||||
return null;
|
||||
|
||||
MapEntity rootEntity = new MapEntity();
|
||||
MapEntity currentEntity = rootEntity;
|
||||
|
||||
int level = 0;
|
||||
int index = 0;
|
||||
//for (int i=0; i<data.Length; i++)
|
||||
do
|
||||
{
|
||||
char c = (char) data[index];
|
||||
char c1 = (index + 1 < data.Length) ? (char) data[index + 1] : (char) 0;
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case '\n':
|
||||
case '\r':
|
||||
break;
|
||||
case '/':
|
||||
if (c1 == '/')
|
||||
ParseComment(data, ref index);
|
||||
else
|
||||
throw new Exception("unexpected character: '" + c + "'");
|
||||
break;
|
||||
case '{':
|
||||
{
|
||||
currentEntity = new MapEntity();
|
||||
rootEntity.entities.Add(currentEntity);
|
||||
|
||||
level++;
|
||||
|
||||
for (; index < data.Length; index++)
|
||||
{
|
||||
if (data[index] == '\n')
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
|
||||
ParseEntity(currentEntity, data, ref index);
|
||||
break;
|
||||
}
|
||||
case '}':
|
||||
{
|
||||
//currentEntity = rootEntity;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new Exception("unsupported character: '" + c + "'");
|
||||
}
|
||||
|
||||
//if (level < 0 || level > 2)
|
||||
// throw new Exception("Failed to parse .map file: unexpected entity found at line " + lineNumber.ToString());
|
||||
} while (++index < data.Length);
|
||||
|
||||
return rootEntity;
|
||||
}
|
||||
|
||||
static void ParseComment(byte[] data, ref int index)
|
||||
{
|
||||
for (; index < data.Length; index++)
|
||||
{
|
||||
if (data[index] == '\n')
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void ParseEntity(MapEntity currentEntity, byte[] data, ref int index)
|
||||
{
|
||||
bool entityParsed = false;
|
||||
do
|
||||
{
|
||||
char c = (char) data[index];
|
||||
char c1 = (index + 1 < data.Length) ? (char) data[index + 1] : (char) 0;
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case '\n':
|
||||
case '\r':
|
||||
break;
|
||||
|
||||
case '/':
|
||||
if (c1 == '/')
|
||||
ParseComment(data, ref index);
|
||||
else
|
||||
throw new Exception("unexpected character: '" + c + "'");
|
||||
break;
|
||||
|
||||
// "name" "value"
|
||||
case '"':
|
||||
{
|
||||
string propName = ParseQuotedString(data, ref index);
|
||||
string propValue = ParseQuotedString(data, ref index);
|
||||
|
||||
if (currentEntity.properties.ContainsKey(propName))
|
||||
throw new Exception("Failed to parse .map file: multiple properties defined for " +
|
||||
propName +
|
||||
" at line ?");// + lineNumber.ToString());
|
||||
currentEntity.properties.Add(propName, propValue);
|
||||
break;
|
||||
}
|
||||
|
||||
// brush
|
||||
case '{':
|
||||
{
|
||||
index++;
|
||||
for (; index < data.Length; index++)
|
||||
{
|
||||
if (data[index] != ' ' && data[index] != '\r' && data[index] != '\n')
|
||||
break;
|
||||
index++;
|
||||
}
|
||||
if (index >= data.Length)
|
||||
break;
|
||||
|
||||
if (data[index] == '(')
|
||||
currentEntity.brushes.Add(ParseBrush(data, ref index));
|
||||
else if (char.IsLetter((char)data[index]) || char.IsNumber((char)data[index]))
|
||||
currentEntity.patches.Add(ParsePatch(data, ref index));
|
||||
break;
|
||||
}
|
||||
case '}':
|
||||
{
|
||||
entityParsed = true;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
throw new Exception("unsupported character: '" + c + "'");
|
||||
}
|
||||
} while (index++ < data.Length && !entityParsed);
|
||||
}
|
||||
|
||||
static string ParseQuotedString(byte[] data, ref int index)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
index++;
|
||||
|
||||
for (; index < data.Length; index++)
|
||||
{
|
||||
if (data[index] == '"')
|
||||
break;
|
||||
sb.Append((char)data[index]);
|
||||
}
|
||||
index++;
|
||||
|
||||
while (index < data.Length)
|
||||
{
|
||||
if (data[index] != ' ')
|
||||
break;
|
||||
index++;
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
static string ParseString(byte[] data, ref int index)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
for (; index < data.Length; index++)
|
||||
{
|
||||
if (data[index] == ' ' || data[index] == '\r' || data[index] == '\n')
|
||||
break;
|
||||
sb.Append((char)data[index]);
|
||||
}
|
||||
index++;
|
||||
|
||||
while (index < data.Length)
|
||||
{
|
||||
if (data[index] != ' ')
|
||||
break;
|
||||
index++;
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
static float ParseFloat(byte[] data, ref int index)
|
||||
{
|
||||
string fs = ParseString(data, ref index);
|
||||
|
||||
if (float.TryParse(fs, NumberStyles.Float, CultureInfo.InvariantCulture, out float value))
|
||||
return value;
|
||||
//else if (float.TryParse(fs, CultureInfo.InvariantCulture, out intValue))
|
||||
// return intValue;
|
||||
else
|
||||
throw new Exception("failed to ParseFloat: " + fs);
|
||||
}
|
||||
|
||||
static int ParseInt(byte[] data, ref int index)
|
||||
{
|
||||
string fs = ParseString(data, ref index);
|
||||
|
||||
if (int.TryParse(fs, out int value))
|
||||
return value;
|
||||
else
|
||||
throw new Exception("failed to ParseInt: " + fs);
|
||||
}
|
||||
|
||||
static Vector3 ParseVector3(byte[] data, ref int index)
|
||||
{
|
||||
return new Vector3(
|
||||
ParseFloat(data, ref index),
|
||||
ParseFloat(data, ref index),
|
||||
ParseFloat(data, ref index)
|
||||
);
|
||||
}
|
||||
|
||||
static Vector2 ParseVector2(byte[] data, ref int index)
|
||||
{
|
||||
return new Vector2(
|
||||
ParseFloat(data, ref index),
|
||||
ParseFloat(data, ref index)
|
||||
);
|
||||
}
|
||||
|
||||
static Vector3 ParsePlaneVector3(byte[] data, ref int index)
|
||||
{
|
||||
index++;
|
||||
while (index < data.Length)
|
||||
{
|
||||
if (data[index] != ' ')
|
||||
break;
|
||||
index++;
|
||||
}
|
||||
|
||||
Vector3 vector = ParseVector3(data, ref index);
|
||||
|
||||
while (index < data.Length)
|
||||
{
|
||||
if (data[index] == ')')
|
||||
break;
|
||||
index++;
|
||||
}
|
||||
|
||||
index++;
|
||||
while (index < data.Length)
|
||||
{
|
||||
if (data[index] != ' ')
|
||||
break;
|
||||
index++;
|
||||
}
|
||||
|
||||
return vector;
|
||||
}
|
||||
|
||||
static MapBrush ParseBrush(byte[] data, ref int index)
|
||||
{
|
||||
MapBrush brush = new MapBrush();
|
||||
|
||||
List<MapFacePlane> planes = new List<MapFacePlane>(6);
|
||||
|
||||
bool brushParsed = false;
|
||||
do
|
||||
{
|
||||
char c = (char) data[index];
|
||||
//char c1 = (index + 1 < data.Length) ? (char) data[index + 1] : (char) 0;
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case '\r':
|
||||
case '\n':
|
||||
break;
|
||||
|
||||
// brush face
|
||||
// ( <v1> ) ( <v2> ) ( <v3> ) <shader> <x_shift> <y_shift> <rotation> <x_scale> <y_scale> <content_flags> <surface_flags> <value>
|
||||
case '(':
|
||||
{
|
||||
MapFacePlane plane;
|
||||
plane.v1 = ParsePlaneVector3(data, ref index);
|
||||
plane.v2 = ParsePlaneVector3(data, ref index);
|
||||
plane.v3 = ParsePlaneVector3(data, ref index);
|
||||
plane.texture = ParseString(data, ref index);
|
||||
plane.offset = ParseVector2(data, ref index);
|
||||
plane.rotation = ParseFloat(data, ref index);
|
||||
plane.scale = ParseVector2(data, ref index);
|
||||
plane.contentFlags = ParseInt(data, ref index);
|
||||
plane.surfaceFlags = ParseInt(data, ref index);
|
||||
plane.surfaceValue = ParseInt(data, ref index);
|
||||
|
||||
planes.Add(plane);
|
||||
break;
|
||||
}
|
||||
|
||||
case '}':
|
||||
{
|
||||
brushParsed = true;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
if (char.IsLetter(c) || char.IsNumber(c))
|
||||
{
|
||||
// patch name
|
||||
|
||||
}
|
||||
throw new Exception("unsupported character: '" + c + "'");
|
||||
}
|
||||
} while (index++ < data.Length && !brushParsed);
|
||||
|
||||
brush.planes = planes.ToArray();
|
||||
|
||||
return brush;
|
||||
}
|
||||
|
||||
static MapPatch ParsePatch(byte[] data, ref int index)
|
||||
{
|
||||
MapPatch patch = new MapPatch();
|
||||
|
||||
patch.name = ParseString(data, ref index);
|
||||
|
||||
bool patchParsed = false;
|
||||
do
|
||||
{
|
||||
char c = (char) data[index];
|
||||
//char c1 = (index + 1 < data.Length) ? (char) data[index + 1] : (char) 0;
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case '\r':
|
||||
case '\n':
|
||||
break;
|
||||
|
||||
case '{':
|
||||
{
|
||||
index++;
|
||||
ParsePatchInner(patch, data, ref index);
|
||||
break;
|
||||
}
|
||||
|
||||
case '}':
|
||||
{
|
||||
patchParsed = true;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
throw new Exception("unsupported character: '" + c + "'");
|
||||
}
|
||||
} while (index++ < data.Length && !patchParsed);
|
||||
|
||||
return patch;
|
||||
}
|
||||
|
||||
// unfinished and untested
|
||||
static void ParsePatchInner(MapPatch patch, byte[] data, ref int index)
|
||||
{
|
||||
string shaderName = ParseString(data, ref index);
|
||||
|
||||
while (index < data.Length)
|
||||
{
|
||||
if (data[index] == '(')
|
||||
break;
|
||||
index++;
|
||||
}
|
||||
index++;
|
||||
|
||||
int width = ParseInt(data, ref index);
|
||||
int height = ParseInt(data, ref index);
|
||||
int dummy1 = ParseInt(data, ref index);
|
||||
int dummy2 = ParseInt(data, ref index);
|
||||
int dummy3 = ParseInt(data, ref index);
|
||||
|
||||
while (index < data.Length)
|
||||
{
|
||||
if (data[index] == ')')
|
||||
break;
|
||||
index++;
|
||||
}
|
||||
index++;
|
||||
|
||||
while (index < data.Length)
|
||||
{
|
||||
if (data[index] == '(')
|
||||
break;
|
||||
index++;
|
||||
}
|
||||
index++;
|
||||
|
||||
PatchVertex[] vertices = new PatchVertex[width * height];
|
||||
|
||||
bool verticesParsed = false;
|
||||
int vertexIndex = 0;
|
||||
do
|
||||
{
|
||||
char c = (char) data[index];
|
||||
//char c1 = (index + 1 < data.Length) ? (char) data[index + 1] : (char) 0;
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case '\r':
|
||||
case '\n':
|
||||
break;
|
||||
|
||||
case '(':
|
||||
{
|
||||
index++;
|
||||
|
||||
for (int iw = 0; iw < width; iw++)
|
||||
{
|
||||
while (index < data.Length)
|
||||
{
|
||||
if (data[index] == '(')
|
||||
break;
|
||||
index++;
|
||||
}
|
||||
|
||||
index++;
|
||||
|
||||
while (index < data.Length)
|
||||
{
|
||||
if (data[index] != ' ')
|
||||
break;
|
||||
index++;
|
||||
}
|
||||
|
||||
vertices[vertexIndex].v = ParseVector3(data, ref index);
|
||||
vertices[vertexIndex].uv = new Vector2(ParseFloat(data, ref index), ParseFloat(data, ref index));
|
||||
vertexIndex++;
|
||||
|
||||
while (index < data.Length)
|
||||
{
|
||||
if (data[index] == ')')
|
||||
break;
|
||||
index++;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case '}':
|
||||
{
|
||||
verticesParsed = true;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
throw new Exception("unsupported character: '" + c + "'");
|
||||
}
|
||||
} while (index++ < data.Length && !verticesParsed);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,6 +7,8 @@ public class GameTarget : GameProjectTarget
|
||||
{
|
||||
base.Init();
|
||||
|
||||
//OutputName = "Goake";
|
||||
|
||||
// Reference the modules for game
|
||||
Modules.Add("Game");
|
||||
//Modules.Add("Cabrito");
|
||||
|
||||
Reference in New Issue
Block a user