Faction Test 100.4.0.0
This commit is contained in:
@@ -101,7 +101,7 @@ namespace Barotrauma.CharacterEditor
|
||||
{
|
||||
bool isSamePackage = contentPackage.GetFiles<CharacterFile>().Any(f => Path.GetFileNameWithoutExtension(f.Path.Value) == name);
|
||||
LocalizedString verificationText = isSamePackage ? GetCharacterEditorTranslation("existingcharacterfoundreplaceverification") : GetCharacterEditorTranslation("existingcharacterfoundoverrideverification");
|
||||
var msgBox = new GUIMessageBox("", verificationText, new LocalizedString[] { TextManager.Get("Yes"), TextManager.Get("No") })
|
||||
var msgBox = new GUIMessageBox("", verificationText, new LocalizedString[] { TextManager.Get("Yes"), TextManager.Get("No") }, type: GUIMessageBox.Type.Warning)
|
||||
{
|
||||
UserData = "verificationprompt"
|
||||
};
|
||||
@@ -356,7 +356,7 @@ namespace Barotrauma.CharacterEditor
|
||||
}
|
||||
if (ContentPackageManager.AllPackages.Any(cp => cp.Name.ToLower() == contentPackageNameElement.Text.ToLower()))
|
||||
{
|
||||
new GUIMessageBox("", TextManager.Get("charactereditor.contentpackagenameinuse", "leveleditorlevelobjnametaken"));
|
||||
new GUIMessageBox("", TextManager.Get("charactereditor.contentpackagenameinuse", "leveleditorlevelobjnametaken"), type: GUIMessageBox.Type.Warning);
|
||||
return false;
|
||||
}
|
||||
string modName = contentPackageNameElement.Text;
|
||||
@@ -428,17 +428,26 @@ namespace Barotrauma.CharacterEditor
|
||||
texturePathElement.Flash(useRectangleFlash: true);
|
||||
return false;
|
||||
}
|
||||
if (Name == CharacterPrefab.HumanSpeciesName && !IsCopy)
|
||||
{
|
||||
// Force a copy when trying to override a human, because handling the crash would be very difficult (we require humans to have certain definitions).
|
||||
if (!CharacterEditorScreen.Instance.SpawnedCharacter.IsHuman)
|
||||
{
|
||||
CharacterEditorScreen.Instance.SpawnCharacter(CharacterPrefab.HumanSpeciesName);
|
||||
}
|
||||
CharacterEditorScreen.Instance.PrepareCharacterCopy();
|
||||
}
|
||||
if (IsCopy)
|
||||
{
|
||||
SourceRagdoll.Texture = evaluatedTexturePath;
|
||||
SourceRagdoll.CanEnterSubmarine = CanEnterSubmarine;
|
||||
SourceRagdoll.CanWalk = CanWalk;
|
||||
SourceRagdoll.Serialize();
|
||||
Wizard.Instance.CreateCharacter(SourceRagdoll.MainElement, SourceCharacter.MainElement, SourceAnimations);
|
||||
Instance.CreateCharacter(SourceRagdoll.MainElement, SourceCharacter.MainElement, SourceAnimations);
|
||||
}
|
||||
else
|
||||
{
|
||||
Wizard.Instance.SelectTab(Tab.Ragdoll);
|
||||
Instance.SelectTab(Tab.Ragdoll);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
@@ -470,9 +479,6 @@ namespace Barotrauma.CharacterEditor
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.02f
|
||||
};
|
||||
// HTML
|
||||
GUIMessageBox htmlBox = null;
|
||||
var loadHtmlButton = new GUIButton(new RectTransform(new Point(content.Rect.Width / 3, elementSize), content.RectTransform), GetCharacterEditorTranslation("LoadFromHTML"));
|
||||
// Limbs
|
||||
var limbsElement = new GUIFrame(new RectTransform(new Vector2(1, 0.05f), content.RectTransform), style: null) { CanBeFocused = false };
|
||||
|
||||
@@ -689,69 +695,6 @@ namespace Barotrauma.CharacterEditor
|
||||
return true;
|
||||
}
|
||||
};
|
||||
loadHtmlButton.OnClicked = (b, d) =>
|
||||
{
|
||||
if (htmlBox == null)
|
||||
{
|
||||
htmlBox = new GUIMessageBox(GetCharacterEditorTranslation("LoadHTML"), string.Empty, new LocalizedString[] { TextManager.Get("Close"), TextManager.Get("Load") }, new Vector2(0.65f, 1f));
|
||||
htmlBox.Header.Font = GUIStyle.LargeFont;
|
||||
var element = new GUIFrame(new RectTransform(new Vector2(0.9f, 0.05f), htmlBox.Content.RectTransform), style: null, color: Color.Gray * 0.25f);
|
||||
//new GUITextBlock(new RectTransform(new Vector2(0.3f, 1), element.RectTransform), GetCharacterEditorTranslation("HTMLPath"));
|
||||
var htmlPathElement = new GUITextBox(new RectTransform(new Vector2(0.7f, 1), element.RectTransform, Anchor.TopRight), GetCharacterEditorTranslation("HTMLPath").Value);
|
||||
LocalizedString title = GetCharacterEditorTranslation("SelectFile");
|
||||
new GUIButton(new RectTransform(new Vector2(0.3f, 1), element.RectTransform), title)
|
||||
{
|
||||
OnClicked = (button, data) =>
|
||||
{
|
||||
FileSelection.OnFileSelected = (file) =>
|
||||
{
|
||||
htmlPathElement.Text = file;
|
||||
};
|
||||
FileSelection.ClearFileTypeFilters();
|
||||
FileSelection.AddFileTypeFilter("HTML", "*.html, *.htm");
|
||||
FileSelection.AddFileTypeFilter("All files", "*.*");
|
||||
FileSelection.SelectFileTypeFilter("*.html, *.htm");
|
||||
FileSelection.Open = true;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
var list = new GUIListBox(new RectTransform(new Vector2(1, 0.8f), htmlBox.Content.RectTransform));
|
||||
var htmlOutput = new GUITextBlock(new RectTransform(Vector2.One, list.Content.RectTransform), string.Empty) { CanBeFocused = false };
|
||||
htmlBox.Buttons[0].OnClicked += (_b, _d) =>
|
||||
{
|
||||
htmlBox.Close();
|
||||
return true;
|
||||
};
|
||||
htmlBox.Buttons[1].OnClicked += (_b, _d) =>
|
||||
{
|
||||
LimbGUIElements.ForEach(l => l.RectTransform.Parent = null);
|
||||
LimbGUIElements.Clear();
|
||||
JointGUIElements.ForEach(j => j.RectTransform.Parent = null);
|
||||
JointGUIElements.Clear();
|
||||
LimbXElements.Clear();
|
||||
JointXElements.Clear();
|
||||
ParseRagdollFromHTML(htmlPathElement.Text, (id, limbName, limbType, rect) =>
|
||||
{
|
||||
CreateLimbGUIElement(limbsList.Content.RectTransform, elementSize, id, limbName, limbType, rect);
|
||||
}, (id1, id2, anchor1, anchor2, jointName) =>
|
||||
{
|
||||
CreateJointGUIElement(jointsList.Content.RectTransform, elementSize, id1, id2, anchor1, anchor2, jointName);
|
||||
});
|
||||
htmlOutput.Text = new XDocument(new XElement("Ragdoll", new object[]
|
||||
{
|
||||
new XAttribute("type", Name), LimbXElements.Values, JointXElements
|
||||
})).ToString();
|
||||
htmlOutput.CalculateHeightFromText();
|
||||
list.UpdateScrollBarSize();
|
||||
return true;
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
GUIMessageBox.MessageBoxes.Add(htmlBox);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
// Previous
|
||||
box.Buttons[0].OnClicked += (b, d) =>
|
||||
{
|
||||
@@ -1070,7 +1013,6 @@ namespace Barotrauma.CharacterEditor
|
||||
// Rectangles
|
||||
colliderAttributes.Add(new XAttribute("height", (int)(height * 0.85f)));
|
||||
colliderAttributes.Add(new XAttribute("width", (int)(width * 0.85f)));
|
||||
idToCodeName.TryGetValue(id, out string notes);
|
||||
LimbXElements.Add(id.ToString(), new XElement("limb",
|
||||
new XAttribute("id", id),
|
||||
new XAttribute("name", limbName),
|
||||
@@ -1107,188 +1049,6 @@ namespace Barotrauma.CharacterEditor
|
||||
}
|
||||
}
|
||||
|
||||
Dictionary<int, string> idToCodeName = new Dictionary<int, string>();
|
||||
protected void ParseRagdollFromHTML(string path, Action<int, string, LimbType, Rectangle> limbCallback = null, Action<int, int, Vector2, Vector2, string> jointCallback = null)
|
||||
{
|
||||
// TODO: parse as xml files -> allows to load ragdolls onto the wizard.
|
||||
//XDocument doc = XMLExtensions.TryLoadXml(path);
|
||||
//var xElements = doc.Elements().ToArray();
|
||||
string html = string.Empty;
|
||||
try
|
||||
{
|
||||
html = File.ReadAllText(path);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
DebugConsole.ThrowError(GetCharacterEditorTranslation("FailedToReadHTML").Replace("[path]", path), e);
|
||||
return;
|
||||
}
|
||||
|
||||
var lines = html.Split(new string[] { "<div", "</div>", Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries)
|
||||
.Where(s => s.Contains("left") && s.Contains("top") && s.Contains("width") && s.Contains("height"));
|
||||
int id = 0;
|
||||
Dictionary<string, int> hierarchyToID = new Dictionary<string, int>();
|
||||
Dictionary<int, string> idToHierarchy = new Dictionary<int, string>();
|
||||
Dictionary<int, string> idToPositionCode = new Dictionary<int, string>();
|
||||
Dictionary<int, string> idToName = new Dictionary<int, string>();
|
||||
idToCodeName.Clear();
|
||||
foreach (var line in lines)
|
||||
{
|
||||
var codeNames = new string(line.SkipWhile(c => c != '>').Skip(1).ToArray()).Split(',');
|
||||
for (int i = 0; i < codeNames.Length; i++)
|
||||
{
|
||||
string codeName = codeNames[i].Trim();
|
||||
if (string.IsNullOrWhiteSpace(codeName)) { continue; }
|
||||
idToCodeName.Add(id, codeName);
|
||||
string limbName = new string(codeName.SkipWhile(c => c != '_').Skip(1).ToArray());
|
||||
if (string.IsNullOrWhiteSpace(limbName)) { continue; }
|
||||
idToName.Add(id, limbName);
|
||||
var parts = line.Split(' ');
|
||||
int ParseToInt(string selector)
|
||||
{
|
||||
string part = parts.First(p => p.Contains(selector));
|
||||
string s = new string(part.SkipWhile(c => c != ':').Skip(1).TakeWhile(c => char.IsNumber(c)).ToArray());
|
||||
int.TryParse(s, out int v);
|
||||
return v;
|
||||
};
|
||||
// example: 111311cr -> 111311
|
||||
string hierarchy = new string(codeName.TakeWhile(c => char.IsNumber(c)).ToArray());
|
||||
if (hierarchyToID.ContainsKey(hierarchy))
|
||||
{
|
||||
DebugConsole.ThrowError(GetCharacterEditorTranslation("MultipleItemsWithSameHierarchy").Replace("[hierarchy]", hierarchy).Replace("[name]", codeName));
|
||||
return;
|
||||
}
|
||||
hierarchyToID.Add(hierarchy, id);
|
||||
idToHierarchy.Add(id, hierarchy);
|
||||
string positionCode = new string(codeName.SkipWhile(c => char.IsNumber(c)).TakeWhile(c => c != '_').ToArray());
|
||||
idToPositionCode.Add(id, positionCode.ToLowerInvariant());
|
||||
int x = ParseToInt("left");
|
||||
int y = ParseToInt("top");
|
||||
int width = ParseToInt("width");
|
||||
int height = ParseToInt("height");
|
||||
// This is overridden when the data is loaded from the gui fields.
|
||||
LimbXElements.Add(hierarchy, new XElement("limb",
|
||||
new XAttribute("id", id),
|
||||
new XAttribute("name", limbName),
|
||||
new XAttribute("type", ParseLimbType(limbName).ToString()),
|
||||
new XElement("sprite",
|
||||
new XAttribute("texture", ""),
|
||||
new XAttribute("sourcerect", $"{x}, {y}, {width}, {height}"))
|
||||
));
|
||||
limbCallback?.Invoke(id, limbName, ParseLimbType(limbName), new Rectangle(x, y, width, height));
|
||||
id++;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < id; i++)
|
||||
{
|
||||
if (idToHierarchy.TryGetValue(i, out string hierarchy))
|
||||
{
|
||||
if (hierarchy != "0")
|
||||
{
|
||||
// NEW LOGIC: if hierarchy length == 1, parent to 0
|
||||
// Else parent to the last bone in the current hierarchy (11 is parented to 1, 212 is parented to 21 etc)
|
||||
string parent = hierarchy.Length > 1 ? hierarchy.Remove(hierarchy.Length - 1, 1) : "0";
|
||||
if (hierarchyToID.TryGetValue(parent, out int parentID))
|
||||
{
|
||||
Vector2 anchor1 = Vector2.Zero;
|
||||
Vector2 anchor2 = Vector2.Zero;
|
||||
idToName.TryGetValue(parentID, out string parentName);
|
||||
idToName.TryGetValue(i, out string limbName);
|
||||
string jointName = $"{GetCharacterEditorTranslation("Joint")} {parentName} - {limbName}";
|
||||
if (idToPositionCode.TryGetValue(i, out string positionCode))
|
||||
{
|
||||
float scalar = 0.8f;
|
||||
if (LimbXElements.TryGetValue(parent, out XElement parentElement))
|
||||
{
|
||||
Rectangle parentSourceRect = parentElement.Element("sprite").GetAttributeRect("sourcerect", Rectangle.Empty);
|
||||
float parentWidth = parentSourceRect.Width / 2 * scalar;
|
||||
float parentHeight = parentSourceRect.Height / 2 * scalar;
|
||||
switch (positionCode)
|
||||
{
|
||||
case "tl": // -1, 1
|
||||
anchor1 = new Vector2(-parentWidth, parentHeight);
|
||||
break;
|
||||
case "tc": // 0, 1
|
||||
anchor1 = new Vector2(0, parentHeight);
|
||||
break;
|
||||
case "tr": // -1, 1
|
||||
anchor1 = new Vector2(-parentWidth, parentHeight);
|
||||
break;
|
||||
case "cl": // -1, 0
|
||||
anchor1 = new Vector2(-parentWidth, 0);
|
||||
break;
|
||||
case "cr": // 1, 0
|
||||
anchor1 = new Vector2(parentWidth, 0);
|
||||
break;
|
||||
case "bl": // -1, -1
|
||||
anchor1 = new Vector2(-parentWidth, -parentHeight);
|
||||
break;
|
||||
case "bc": // 0, -1
|
||||
anchor1 = new Vector2(0, -parentHeight);
|
||||
break;
|
||||
case "br": // 1, -1
|
||||
anchor1 = new Vector2(parentWidth, -parentHeight);
|
||||
break;
|
||||
}
|
||||
if (LimbXElements.TryGetValue(hierarchy, out XElement element))
|
||||
{
|
||||
Rectangle sourceRect = element.Element("sprite").GetAttributeRect("sourcerect", Rectangle.Empty);
|
||||
float width = sourceRect.Width / 2 * scalar;
|
||||
float height = sourceRect.Height / 2 * scalar;
|
||||
switch (positionCode)
|
||||
{
|
||||
// Inverse
|
||||
case "tl":
|
||||
// br
|
||||
anchor2 = new Vector2(-width, -height);
|
||||
break;
|
||||
case "tc":
|
||||
// bc
|
||||
anchor2 = new Vector2(0, -height);
|
||||
break;
|
||||
case "tr":
|
||||
// bl
|
||||
anchor2 = new Vector2(-width, -height);
|
||||
break;
|
||||
case "cl":
|
||||
// cr
|
||||
anchor2 = new Vector2(width, 0);
|
||||
break;
|
||||
case "cr":
|
||||
// cl
|
||||
anchor2 = new Vector2(-width, 0);
|
||||
break;
|
||||
case "bl":
|
||||
// tr
|
||||
anchor2 = new Vector2(-width, height);
|
||||
break;
|
||||
case "bc":
|
||||
// tc
|
||||
anchor2 = new Vector2(0, height);
|
||||
break;
|
||||
case "br":
|
||||
// tl
|
||||
anchor2 = new Vector2(-width, height);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// This is overridden when the data is loaded from the gui fields.
|
||||
JointXElements.Add(new XElement("joint",
|
||||
new XAttribute("name", jointName),
|
||||
new XAttribute("limb1", parentID),
|
||||
new XAttribute("limb2", i),
|
||||
new XAttribute("limb1anchor", $"{anchor1.X.Format(2)}, {anchor1.Y.Format(2)}"),
|
||||
new XAttribute("limb2anchor", $"{anchor2.X.Format(2)}, {anchor2.Y.Format(2)}")
|
||||
));
|
||||
jointCallback?.Invoke(parentID, i, anchor1, anchor2, jointName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected LimbType ParseLimbType(string limbName)
|
||||
{
|
||||
var limbType = LimbType.None;
|
||||
|
||||
Reference in New Issue
Block a user