1272 lines
54 KiB
C#
1272 lines
54 KiB
C#
|
#if USE_CELTX
|
|||
|
using System.Collections.Generic;
|
|||
|
using System.Linq;
|
|||
|
using System.Reflection;
|
|||
|
using System.Text;
|
|||
|
using UnityEngine;
|
|||
|
|
|||
|
namespace PixelCrushers.DialogueSystem.Celtx
|
|||
|
{
|
|||
|
/// <summary>
|
|||
|
/// This class does the actual work of converting Celtx Data (Raw) into a dialogue database.
|
|||
|
/// </summary>
|
|||
|
public class CeltxToDialogueDatabase
|
|||
|
{
|
|||
|
Template template = Template.FromDefault();
|
|||
|
DialogueDatabase database;
|
|||
|
CeltxData celtxData;
|
|||
|
|
|||
|
public DialogueDatabase ProcessRawCeltxData(CeltxDataRaw celtxDataRaw, DialogueDatabase database, bool importGameplayScriptText, bool importBreakdownCatalogContent, bool checkSequenceSyntax)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
this.database = database;
|
|||
|
celtxData = new CeltxData();
|
|||
|
|
|||
|
List<CxContent> docContentList = celtxDataRaw.doc.content;
|
|||
|
|
|||
|
Debug.Log("Converting Celtx Data to Dialogue System database");
|
|||
|
|
|||
|
CxContent cxMetadata = docContentList.Find(c => c.type.Equals("cxmetadata"));
|
|||
|
ProcessCxCatalog(cxMetadata);
|
|||
|
ProcessCxVariables(cxMetadata);
|
|||
|
ProcessCxConditions(cxMetadata);
|
|||
|
|
|||
|
List<CxContent> sequenceList = docContentList.Where(c => c.type.Equals("cxsequence")).ToList();
|
|||
|
ProcessSequenceList(sequenceList);
|
|||
|
|
|||
|
if (checkSequenceSyntax) CheckSequenceSyntax();
|
|||
|
|
|||
|
ConvertBlankNodesToGroupNodes();
|
|||
|
}
|
|||
|
catch (System.Exception e)
|
|||
|
{
|
|||
|
LogError(MethodBase.GetCurrentMethod(), e);
|
|||
|
}
|
|||
|
|
|||
|
return database;
|
|||
|
}
|
|||
|
|
|||
|
private void ProcessCxCatalog(CxContent cxMetadata)
|
|||
|
{
|
|||
|
List<CxContent> cxCatalogContent;
|
|||
|
try
|
|||
|
{
|
|||
|
cxCatalogContent = cxMetadata.content.Find(c => c.type.Equals("cxcatalog")).content;
|
|||
|
}
|
|||
|
catch (System.Exception)
|
|||
|
{
|
|||
|
Debug.Log("Skipping catalog because it is null or empty");
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
foreach (CxContent contentObject in cxCatalogContent)
|
|||
|
{
|
|||
|
switch (contentObject.attrs.type)
|
|||
|
{
|
|||
|
case "character":
|
|||
|
ConvertCharacterCatalogEntryToDSActor(contentObject.attrs);
|
|||
|
break;
|
|||
|
|
|||
|
case "location":
|
|||
|
ConvertLocationCatalogEntryToDSLocation(contentObject.attrs);
|
|||
|
break;
|
|||
|
|
|||
|
case "item":
|
|||
|
ConvertItemCatalogEntryToDSItem(contentObject.attrs);
|
|||
|
break;
|
|||
|
|
|||
|
case "branch":
|
|||
|
case "jump":
|
|||
|
case "sequence":
|
|||
|
ExtractCustomVarsList(contentObject.attrs);
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void ProcessCxVariables(CxContent cxMetadata)
|
|||
|
{
|
|||
|
List<CxVariable> cxVariablesList;
|
|||
|
try
|
|||
|
{
|
|||
|
cxVariablesList = cxMetadata.content.Find(c => c.type.Equals("cxconditions")).attrs.variables;
|
|||
|
}
|
|||
|
catch (System.Exception)
|
|||
|
{
|
|||
|
Debug.Log("Skipping variables because there are none");
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
foreach (CxVariable variableObject in cxVariablesList)
|
|||
|
{
|
|||
|
ConvertCeltxVariableToDSVariable(variableObject);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void ProcessCxConditions(CxContent cxMetadata)
|
|||
|
{
|
|||
|
List<CxContent> cxConditionsContent;
|
|||
|
try
|
|||
|
{
|
|||
|
cxConditionsContent = cxMetadata.content.Find(c => c.type.Equals("cxconditions")).content;
|
|||
|
}
|
|||
|
catch (System.Exception)
|
|||
|
{
|
|||
|
Debug.Log("Skipping variables because there are none");
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
foreach (CxContent contentObject in cxConditionsContent)
|
|||
|
{
|
|||
|
ExtractCeltxCondition(contentObject.attrs);
|
|||
|
}
|
|||
|
|
|||
|
foreach (CeltxCondition condition in celtxData.conditions)
|
|||
|
{
|
|||
|
GenerateLuaCondition(condition);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void AppendToField(List<Field> fields, string title, string value, FieldType fieldType)
|
|||
|
{
|
|||
|
string currentFieldValue = Field.LookupValue(fields, title);
|
|||
|
if (value == null || value.Equals("") || currentFieldValue != null && currentFieldValue.Equals(value)) { return; }
|
|||
|
|
|||
|
string updatedString;
|
|||
|
if (currentFieldValue == null || currentFieldValue.Equals("") || currentFieldValue.Equals("[]")) { updatedString = value; }
|
|||
|
else { updatedString = currentFieldValue + " " + value; }
|
|||
|
Field.SetValue(fields, title, updatedString, fieldType);
|
|||
|
}
|
|||
|
|
|||
|
#region CxSequence Processing
|
|||
|
|
|||
|
private void ProcessSequenceList(List<CxContent> sequenceList)
|
|||
|
{
|
|||
|
sequenceList.ForEach(c => ExtractSequenceLinkingData(c));
|
|||
|
|
|||
|
celtxData.sequenceLinkingDataList.ForEach(i => CheckIfRoot(i));
|
|||
|
List<SequenceLinkingData> rootItems = celtxData.sequenceLinkingDataList.Where(i => i.isRoot).ToList();
|
|||
|
|
|||
|
rootItems.ForEach(i => ProcessConversation(i, sequenceList));
|
|||
|
}
|
|||
|
|
|||
|
private void ExtractSequenceLinkingData(CxContent cxSequenceContentObject)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
SequenceLinkingData sequenceLinkingData = new SequenceLinkingData();
|
|||
|
sequenceLinkingData.id = cxSequenceContentObject.attrs.id;
|
|||
|
sequenceLinkingData.name = cxSequenceContentObject.attrs.name;
|
|||
|
|
|||
|
if (cxSequenceContentObject.attrs.transitions != null && cxSequenceContentObject.attrs.transitions.Count == 1 && cxSequenceContentObject.attrs.transitions[0].id != null)
|
|||
|
{
|
|||
|
sequenceLinkingData.linkedIds.Add(cxSequenceContentObject.attrs.transitions[0].id);
|
|||
|
}
|
|||
|
|
|||
|
List<CxContent> cxBranches = cxSequenceContentObject.content[0].content.Where(c => c.type.Equals("cxbranch")).ToList();
|
|||
|
if (cxBranches != null && cxBranches.Count > 0)
|
|||
|
{
|
|||
|
foreach (CxContent branch in cxBranches)
|
|||
|
{
|
|||
|
foreach (CxLinked linkedItem in branch.attrs.linked)
|
|||
|
{
|
|||
|
sequenceLinkingData.linkedIds.Add(linkedItem.id);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
List<CxContent> cxJumps = cxSequenceContentObject.content[0].content.Where(c => c.type.Equals("cxjump")).ToList();
|
|||
|
if (cxJumps != null && cxJumps.Count > 0)
|
|||
|
{
|
|||
|
foreach (CxContent jump in cxJumps)
|
|||
|
{
|
|||
|
sequenceLinkingData.linkedIds.Add(jump.attrs.linked_jump.id);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
celtxData.idsWithIncomingLinks.AddRange(sequenceLinkingData.linkedIds);
|
|||
|
|
|||
|
celtxData.sequenceLinkingDataList.Add(sequenceLinkingData);
|
|||
|
}
|
|||
|
catch (System.Exception e)
|
|||
|
{
|
|||
|
LogError(MethodBase.GetCurrentMethod(), e, cxSequenceContentObject.attrs.id);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public void CheckIfRoot(SequenceLinkingData sequenceLinkingData)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
if (!celtxData.idsWithIncomingLinks.Contains(sequenceLinkingData.id))
|
|||
|
{
|
|||
|
sequenceLinkingData.isRoot = true;
|
|||
|
}
|
|||
|
}
|
|||
|
catch (System.Exception e)
|
|||
|
{
|
|||
|
LogError(MethodBase.GetCurrentMethod(), e, sequenceLinkingData.id);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public void ProcessConversation(SequenceLinkingData sequenceLinkingData, List<CxContent> sequenceList)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
string sequenceId = sequenceLinkingData.id;
|
|||
|
CxContent cxSequenceContentObject = sequenceList.Find(c => c.attrs.id.Equals(sequenceLinkingData.id));
|
|||
|
DialogueEntry conversationStartNode = ProcessConversationRootSequence(cxSequenceContentObject, sequenceId);
|
|||
|
if (conversationStartNode == null) return;
|
|||
|
|
|||
|
ProcessConversationChildSequences(sequenceId, conversationStartNode, sequenceLinkingData, sequenceList);
|
|||
|
}
|
|||
|
catch (System.Exception e)
|
|||
|
{
|
|||
|
LogError(MethodBase.GetCurrentMethod(), e, sequenceLinkingData.id);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private DialogueEntry ProcessConversationRootSequence(CxContent cxSequenceContentObject, string sequenceId)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
string sequenceName = cxSequenceContentObject.attrs.name;
|
|||
|
string sequenceCatalogId = cxSequenceContentObject.attrs.catalog_id;
|
|||
|
|
|||
|
List<CxContent> pageContents = GetSequencePageContents(cxSequenceContentObject);
|
|||
|
if (pageContents == null)
|
|||
|
{
|
|||
|
LogWarning("Skipping this sequence map because the Conversation Root node's page is null or empty. Please ensure the node has 2 characters",
|
|||
|
cxSequenceContentObject.attrs.id, cxSequenceContentObject.attrs.name);
|
|||
|
return null;
|
|||
|
}
|
|||
|
|
|||
|
List<CxContent> characters = pageContents.FindAll(c => c.type.Equals("cxcharacter"));
|
|||
|
|
|||
|
if (characters == null || characters.Count < 2)
|
|||
|
{
|
|||
|
LogWarning("Skipping this sequence map because the Conversation Root node has less than 2 characters. Please ensure the node has 2 characters",
|
|||
|
cxSequenceContentObject.attrs.id, cxSequenceContentObject.attrs.name);
|
|||
|
return null;
|
|||
|
}
|
|||
|
|
|||
|
Conversation conversation = template.CreateConversation(template.GetNextConversationID(database), sequenceName);
|
|||
|
database.conversations.Add(conversation);
|
|||
|
|
|||
|
conversation.ActorID = GetActorIdForCharacter(characters[0]);
|
|||
|
conversation.ConversantID = GetActorIdForCharacter(characters[1]);
|
|||
|
|
|||
|
DialogueEntry startNode = CreateNextDialogueEntryForConversation(conversation, "START", sequenceId);
|
|||
|
startNode.Sequence = "None()";
|
|||
|
AddSetVariableScript(startNode, sequenceCatalogId);
|
|||
|
|
|||
|
return startNode;
|
|||
|
}
|
|||
|
catch (System.Exception e)
|
|||
|
{
|
|||
|
LogError(MethodBase.GetCurrentMethod(), e, cxSequenceContentObject.attrs.id);
|
|||
|
return null;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public void ProcessConversationChildSequences(string sourceCxId, DialogueEntry lastCreatedDialogueEntry, SequenceLinkingData sequenceLinkingData, List<CxContent> sequenceList)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
foreach (string linkedSequenceId in sequenceLinkingData.linkedIds)
|
|||
|
{
|
|||
|
if (sequenceLinkingData.linksProcessed.Contains(linkedSequenceId))
|
|||
|
{
|
|||
|
continue;
|
|||
|
}
|
|||
|
SequenceLinkingData targetSequenceLinkingData = celtxData.sequenceLinkingDataList.Find(o => o.id.Equals(linkedSequenceId));
|
|||
|
if (!targetSequenceLinkingData.isRoot)
|
|||
|
{
|
|||
|
CxContent targetCxSequenceContentObject = sequenceList.Find(c => c.attrs.id.Equals(targetSequenceLinkingData.id));
|
|||
|
|
|||
|
DialogueEntry targetSequenceLastCreatedDialogueEntry = ProcessTargetConversationSequence(targetCxSequenceContentObject, targetSequenceLinkingData, lastCreatedDialogueEntry, sourceCxId);
|
|||
|
if (targetSequenceLastCreatedDialogueEntry != null)
|
|||
|
{
|
|||
|
ProcessConversationChildSequences(targetCxSequenceContentObject.attrs.id, targetSequenceLastCreatedDialogueEntry, targetSequenceLinkingData, sequenceList);
|
|||
|
}
|
|||
|
}
|
|||
|
sequenceLinkingData.linksProcessed.Add(linkedSequenceId);
|
|||
|
}
|
|||
|
sequenceLinkingData.sequenceProcessingComplete = true;
|
|||
|
}
|
|||
|
catch (System.Exception e)
|
|||
|
{
|
|||
|
LogError(MethodBase.GetCurrentMethod(), e, sequenceLinkingData.id);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private DialogueEntry ProcessTargetConversationSequence(CxContent targetSequenceContentObject, SequenceLinkingData sequenceLinkingData, DialogueEntry parentDialogueEntry, string sourceCxId)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
string sequenceId = sequenceLinkingData.id;
|
|||
|
|
|||
|
string sequenceName = targetSequenceContentObject.attrs.name;
|
|||
|
string sequenceCatalogId = targetSequenceContentObject.attrs.catalog_id;
|
|||
|
|
|||
|
int conversationId = -1;
|
|||
|
conversationId = parentDialogueEntry.conversationID;
|
|||
|
Conversation conversation = database.GetConversation(conversationId);
|
|||
|
|
|||
|
DialogueEntry targetEntry = null;
|
|||
|
|
|||
|
foreach (DialogueEntry entry in conversation.dialogueEntries)
|
|||
|
{
|
|||
|
if (Field.LookupValue(entry.fields, CeltxFields.CeltxId).Equals(sequenceId))
|
|||
|
{
|
|||
|
targetEntry = entry;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (targetEntry == null)
|
|||
|
{
|
|||
|
targetEntry = CreateNextDialogueEntryForConversation(conversation, sequenceName, sequenceId);
|
|||
|
AddSetVariableScript(targetEntry, sequenceCatalogId);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
string linkConditionId = GetLinkConditionId(sourceCxId, sequenceId);
|
|||
|
if (parentDialogueEntry.outgoingLinks.Count > 0)
|
|||
|
{
|
|||
|
foreach (Link link in parentDialogueEntry.outgoingLinks)
|
|||
|
{
|
|||
|
string linkCxId = Field.LookupValue(conversation.GetDialogueEntry(link.destinationDialogueID).fields, CeltxFields.CeltxId);
|
|||
|
string targetLinkId = Field.LookupValue(parentDialogueEntry.fields, CeltxFields.CeltxId) + "-" + Field.LookupValue(targetEntry.fields, CeltxFields.CeltxId);
|
|||
|
if (linkCxId.Contains(targetLinkId))
|
|||
|
{
|
|||
|
return targetEntry;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
LinkDialogueEntries(parentDialogueEntry, targetEntry, GetLinkConditionId(sourceCxId, sequenceId));
|
|||
|
|
|||
|
// Process actual sequence node contents
|
|||
|
if (!sequenceLinkingData.sequenceProcessingComplete)
|
|||
|
{
|
|||
|
return ProcessSequenceNodeContents(targetEntry, targetSequenceContentObject);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
return null;
|
|||
|
}
|
|||
|
}
|
|||
|
catch (System.Exception e)
|
|||
|
{
|
|||
|
LogError(MethodBase.GetCurrentMethod(), e, targetSequenceContentObject.attrs.id);
|
|||
|
return null;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private List<CxContent> GetSequencePageContents(CxContent cxSequenceContentObject)
|
|||
|
{
|
|||
|
if (cxSequenceContentObject.content != null && cxSequenceContentObject.content.Count > 0)
|
|||
|
{
|
|||
|
CxContent page = cxSequenceContentObject.content[0];
|
|||
|
if (page.type.Equals("cxpage"))
|
|||
|
{
|
|||
|
return page.content;
|
|||
|
}
|
|||
|
}
|
|||
|
return null;
|
|||
|
}
|
|||
|
|
|||
|
private DialogueEntry ProcessSequenceNodeContents(DialogueEntry initialEntry, CxContent cxSequenceContentObject)
|
|||
|
{
|
|||
|
DialogueEntry currentEntry = initialEntry;
|
|||
|
Conversation conversation = database.GetConversation(currentEntry.conversationID);
|
|||
|
|
|||
|
try
|
|||
|
{
|
|||
|
List<CxContent> sequencePageContentList = cxSequenceContentObject.content[0].content;
|
|||
|
int entryCount = 1;
|
|||
|
bool createNewEntry = false;
|
|||
|
|
|||
|
|
|||
|
foreach (CxContent pageContentItem in sequencePageContentList)
|
|||
|
{
|
|||
|
if (!pageContentItem.type.Equals("cxgameplay") &&
|
|||
|
!pageContentItem.type.Equals("cxcharacter") &&
|
|||
|
!pageContentItem.type.Equals("cxparenthetical") &&
|
|||
|
!pageContentItem.type.Equals("cxdialog"))
|
|||
|
{
|
|||
|
continue;
|
|||
|
}
|
|||
|
string combinedText = GetCombinedText(pageContentItem.content);
|
|||
|
|
|||
|
if (createNewEntry)
|
|||
|
{
|
|||
|
entryCount += 1;
|
|||
|
currentEntry = CreateAdditionalEntryForSequence(conversation, currentEntry, initialEntry, entryCount);
|
|||
|
createNewEntry = false;
|
|||
|
}
|
|||
|
|
|||
|
switch (pageContentItem.type)
|
|||
|
{
|
|||
|
case "cxgameplay":
|
|||
|
if (StringStartsWithTag(combinedText, "[SEQ]"))
|
|||
|
{
|
|||
|
currentEntry.Sequence = GetTextWithoutTag(combinedText);
|
|||
|
}
|
|||
|
else if (StringStartsWithTag(combinedText, "[COND]"))
|
|||
|
{
|
|||
|
if (!string.IsNullOrEmpty(currentEntry.conditionsString)) currentEntry.conditionsString += ";\n";
|
|||
|
currentEntry.conditionsString += GetTextWithoutTag(combinedText);
|
|||
|
}
|
|||
|
else if (StringStartsWithTag(combinedText, "[SCRIPT]"))
|
|||
|
{
|
|||
|
if (!string.IsNullOrEmpty(currentEntry.userScript)) currentEntry.userScript += ";\n";
|
|||
|
currentEntry.userScript += GetTextWithoutTag(combinedText);
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case "cxcharacter":
|
|||
|
currentEntry.ActorID = GetActorIdForCharacter(pageContentItem);
|
|||
|
if (currentEntry.ActorID == conversation.ActorID)
|
|||
|
{
|
|||
|
currentEntry.ConversantID = conversation.ConversantID;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
currentEntry.ConversantID = conversation.ActorID;
|
|||
|
}
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
case "cxparenthetical":
|
|||
|
if (StringStartsWithTag(combinedText, "[C]"))
|
|||
|
{
|
|||
|
currentEntry.ConversantID = database.GetActor(GetTextWithoutTag(combinedText).ToUpper()).id;
|
|||
|
}
|
|||
|
else if (StringStartsWithTag(combinedText, "[VO]"))
|
|||
|
{
|
|||
|
AppendToField(currentEntry.fields, CeltxFields.VoiceOverFile, GetTextWithoutTag(combinedText), FieldType.Files);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
currentEntry.MenuText = combinedText;
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case "cxdialog":
|
|||
|
currentEntry.DialogueText = GetCombinedText(pageContentItem.content);
|
|||
|
|
|||
|
createNewEntry = true;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
catch (System.Exception e)
|
|||
|
{
|
|||
|
LogError(MethodBase.GetCurrentMethod(), e, cxSequenceContentObject.attrs.id);
|
|||
|
}
|
|||
|
|
|||
|
return currentEntry;
|
|||
|
}
|
|||
|
|
|||
|
private DialogueEntry CreateAdditionalEntryForSequence(Conversation conversation, DialogueEntry currentEntry, DialogueEntry initialEntry, int entryCount)
|
|||
|
{
|
|||
|
DialogueEntry newEntry = CreateNextDialogueEntryForConversation(conversation, initialEntry.Title + "-" + entryCount,
|
|||
|
Field.LookupValue(initialEntry.fields, CeltxFields.CeltxId) + "-" + entryCount);
|
|||
|
newEntry.ActorID = currentEntry.ActorID;
|
|||
|
newEntry.ConversantID = currentEntry.ConversantID;
|
|||
|
LinkDialogueEntries(currentEntry, newEntry, null);
|
|||
|
return newEntry;
|
|||
|
}
|
|||
|
|
|||
|
private void AddSetVariableScript(DialogueEntry entry, string sequenceCatalogId)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
if (celtxData.customVarListLookupByCxSequenceId.ContainsKey(sequenceCatalogId))
|
|||
|
{
|
|||
|
if (!celtxData.customVarListLookupByCxSequenceId.ContainsKey(sequenceCatalogId)) Debug.LogError("Celtx Import: Can't find custom variable list for sequence ID " + sequenceCatalogId);
|
|||
|
List<CxCustomVar> cxCustomVars = celtxData.customVarListLookupByCxSequenceId[sequenceCatalogId];
|
|||
|
StringBuilder luaScript = new StringBuilder();
|
|||
|
foreach (CxCustomVar cxCustomVar in cxCustomVars)
|
|||
|
{
|
|||
|
if (luaScript.Length != 0) { luaScript.Append("; "); }
|
|||
|
if (!celtxData.variableLookupByCeltxId.ContainsKey(cxCustomVar.id)) Debug.LogError("Celtx Import: Can't find variable with ID " + cxCustomVar.id);
|
|||
|
Variable var = database.GetVariable(celtxData.variableLookupByCeltxId[cxCustomVar.id]);
|
|||
|
if (var == null) Debug.LogError("Celtx Import: Dialogue database doesn't contain variable named " + celtxData.variableLookupByCeltxId[cxCustomVar.id]);
|
|||
|
StringBuilder stringBuilder = new StringBuilder();
|
|||
|
stringBuilder.Append("Variable");
|
|||
|
stringBuilder.Append("[\"" + var.Name + "\"]");
|
|||
|
stringBuilder.Append(" = ");
|
|||
|
|
|||
|
if (var.Type == FieldType.Boolean)
|
|||
|
{
|
|||
|
if (!cxCustomVar.boolVal.ToString().Equals(var.InitialValue)) { stringBuilder.Append(cxCustomVar.boolVal.ToString().ToLower()); }
|
|||
|
else { stringBuilder.Append(var.InitialValue); }
|
|||
|
}
|
|||
|
else if (var.Type == FieldType.Number)
|
|||
|
{
|
|||
|
if (!cxCustomVar.longVal.ToString().Equals(var.InitialValue)) { stringBuilder.Append(cxCustomVar.longVal.ToString()); }
|
|||
|
else { stringBuilder.Append(var.InitialValue); }
|
|||
|
}
|
|||
|
else if (var.Type == FieldType.Text)
|
|||
|
{
|
|||
|
if (cxCustomVar.type != null && cxCustomVar.type.Equals("radio"))
|
|||
|
{
|
|||
|
stringBuilder.Append(cxCustomVar.config.options[(int)cxCustomVar.longVal].strVal);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
if (cxCustomVar.strVal != null && !cxCustomVar.strVal.Equals(var.InitialValue)) { stringBuilder.Append("\"" + cxCustomVar.strVal + "\""); }
|
|||
|
else { stringBuilder.Append("\"" + var.InitialValue + "\""); }
|
|||
|
}
|
|||
|
}
|
|||
|
luaScript.Append(stringBuilder.ToString());
|
|||
|
}
|
|||
|
entry.userScript = luaScript.ToString();
|
|||
|
}
|
|||
|
}
|
|||
|
catch (System.Exception e)
|
|||
|
{
|
|||
|
LogError(MethodBase.GetCurrentMethod(), e, "SetVar[" + sequenceCatalogId + "]");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private int GetActorIdForCharacter(CxContent characterContentItem)
|
|||
|
{
|
|||
|
if (!celtxData.actorIdLookupByCxCharacterCatalogId.ContainsKey(characterContentItem.attrs.catalog_id)) Debug.LogError("Celtx Import: Lookup failed for actor with ID " + characterContentItem.attrs.catalog_id);
|
|||
|
return celtxData.actorIdLookupByCxCharacterCatalogId[characterContentItem.attrs.catalog_id];
|
|||
|
}
|
|||
|
|
|||
|
private DialogueEntry CreateNextDialogueEntryForConversation(Conversation conversation, string title, string celtxId, bool isGroup = false)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
DialogueEntry dialogueEntry = template.CreateDialogueEntry(template.GetNextDialogueEntryID(conversation), conversation.id, title);
|
|||
|
conversation.dialogueEntries.Add(dialogueEntry);
|
|||
|
dialogueEntry.isGroup = isGroup;
|
|||
|
dialogueEntry.ActorID = conversation.ActorID;
|
|||
|
dialogueEntry.ConversantID = conversation.ConversantID;
|
|||
|
if (celtxId != null)
|
|||
|
{
|
|||
|
Field.SetValue(dialogueEntry.fields, CeltxFields.CeltxId, celtxId);
|
|||
|
celtxData.dialogueEntryLookupByCeltxId.Add(celtxId, dialogueEntry);
|
|||
|
}
|
|||
|
return dialogueEntry;
|
|||
|
}
|
|||
|
catch (System.Exception e)
|
|||
|
{
|
|||
|
LogError(MethodBase.GetCurrentMethod(), e, celtxId, title);
|
|||
|
}
|
|||
|
return null;
|
|||
|
}
|
|||
|
|
|||
|
private void ConvertBlankNodesToGroupNodes()
|
|||
|
{
|
|||
|
foreach (Conversation conversation in database.conversations)
|
|||
|
{
|
|||
|
foreach (DialogueEntry entry in conversation.dialogueEntries)
|
|||
|
{
|
|||
|
var isBlankNode = string.IsNullOrEmpty(entry.DialogueText) &&
|
|||
|
string.IsNullOrEmpty(entry.MenuText) &&
|
|||
|
string.IsNullOrEmpty(entry.Sequence);
|
|||
|
if (isBlankNode)
|
|||
|
{
|
|||
|
entry.isGroup = true;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#endregion
|
|||
|
|
|||
|
#region Linking
|
|||
|
|
|||
|
private string GetLinkConditionId(string sourceCeltxId, string destinationCeltxId)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
foreach (CeltxCondition condition in celtxData.conditions)
|
|||
|
{
|
|||
|
foreach (CxOnObj onObj in condition.links)
|
|||
|
{
|
|||
|
if (onObj.from.Equals(sourceCeltxId) && onObj.to.Equals(destinationCeltxId))
|
|||
|
{
|
|||
|
return condition.id;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
catch (System.Exception e)
|
|||
|
{
|
|||
|
LogError(MethodBase.GetCurrentMethod(), e, sourceCeltxId + "-" + destinationCeltxId);
|
|||
|
}
|
|||
|
return null;
|
|||
|
}
|
|||
|
|
|||
|
private void LinkDialogueEntries(DialogueEntry source, DialogueEntry destination, string conditionId)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
if (conditionId == null)
|
|||
|
{
|
|||
|
source.outgoingLinks.Add(new Link(source.conversationID, source.id, destination.conversationID, destination.id));
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
CeltxCondition condition = celtxData.conditions.Find(c => c.id.Equals(conditionId));
|
|||
|
DialogueEntry entryToLinkToCondition = source;
|
|||
|
if (condition.delay)
|
|||
|
{
|
|||
|
DialogueEntry delayEntry = CreateNextDialogueEntryForConversation(database.GetConversation(source.conversationID),
|
|||
|
"[D]-" + condition.name,
|
|||
|
"D-" + Field.LookupValue(source.fields, CeltxFields.CeltxId) + "-" + Field.LookupValue(destination.fields, CeltxFields.CeltxId), true);
|
|||
|
source.outgoingLinks.Add(new Link(source.conversationID, source.id, delayEntry.conversationID, delayEntry.id));
|
|||
|
entryToLinkToCondition = delayEntry;
|
|||
|
}
|
|||
|
|
|||
|
DialogueEntry conditionEntry = CreateNextDialogueEntryForConversation(database.GetConversation(source.conversationID),
|
|||
|
"[COND]" + condition.name,
|
|||
|
"C-" + Field.LookupValue(source.fields, CeltxFields.CeltxId) + "-" + Field.LookupValue(destination.fields, CeltxFields.CeltxId), true);
|
|||
|
conditionEntry.conditionsString = condition.luaConditionString;
|
|||
|
entryToLinkToCondition.outgoingLinks.Add(new Link(entryToLinkToCondition.conversationID, entryToLinkToCondition.id, conditionEntry.conversationID, conditionEntry.id));
|
|||
|
conditionEntry.outgoingLinks.Add(new Link(conditionEntry.conversationID, conditionEntry.id, destination.conversationID, destination.id));
|
|||
|
}
|
|||
|
}
|
|||
|
catch (System.Exception e)
|
|||
|
{
|
|||
|
LogError(MethodBase.GetCurrentMethod(), e, source.Title + "-" + destination.Title + "-" + conditionId);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#endregion
|
|||
|
|
|||
|
#region Text Processing
|
|||
|
private bool StringStartsWithTag(string stringToCheck, string targetTag)
|
|||
|
{
|
|||
|
if (stringToCheck == null || targetTag == null) { return false; }
|
|||
|
|
|||
|
return stringToCheck.StartsWith(targetTag, System.StringComparison.OrdinalIgnoreCase);
|
|||
|
}
|
|||
|
|
|||
|
private string GetTextWithoutTag(string text)
|
|||
|
{
|
|||
|
if (string.IsNullOrEmpty(text)) { return ""; }
|
|||
|
|
|||
|
//return System.Text.RegularExpressions.Regex.Split(text, "(\\[.*\\])")[2].Trim();
|
|||
|
var endTagPos = text.IndexOf(']');
|
|||
|
return (endTagPos == -1) ? "" : text.Substring(endTagPos + 1);
|
|||
|
}
|
|||
|
|
|||
|
private string GetCombinedText(List<CxContent> contentList)
|
|||
|
{
|
|||
|
if (contentList == null) { return ""; }
|
|||
|
|
|||
|
StringBuilder stringBuilder = new StringBuilder();
|
|||
|
foreach (CxContent content in contentList)
|
|||
|
{
|
|||
|
if (content.type.Equals("text"))
|
|||
|
{
|
|||
|
stringBuilder.Append(GetTextWithMarks(content));
|
|||
|
}
|
|||
|
}
|
|||
|
return stringBuilder.ToString();
|
|||
|
}
|
|||
|
|
|||
|
private string GetTextWithMarks(CxContent textContent)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
string text = textContent.text;
|
|||
|
if (textContent.marks != null && textContent.marks.Count > 0)
|
|||
|
{
|
|||
|
string prependString = "";
|
|||
|
string appendString = "";
|
|||
|
foreach (CxContent mark in textContent.marks)
|
|||
|
{
|
|||
|
switch (mark.type)
|
|||
|
{
|
|||
|
case "strong":
|
|||
|
prependString = prependString + "<b>";
|
|||
|
appendString = "</b>" + appendString;
|
|||
|
break;
|
|||
|
|
|||
|
case "em":
|
|||
|
prependString = prependString + "<i>";
|
|||
|
appendString = "</i>" + appendString;
|
|||
|
break;
|
|||
|
|
|||
|
case "underline":
|
|||
|
prependString = prependString + "<u>";
|
|||
|
appendString = "</u>" + appendString;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
return prependString + text + appendString;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
return text;
|
|||
|
}
|
|||
|
}
|
|||
|
catch (System.Exception e)
|
|||
|
{
|
|||
|
LogError(MethodBase.GetCurrentMethod(), e, textContent.attrs.id);
|
|||
|
return "";
|
|||
|
}
|
|||
|
}
|
|||
|
#endregion
|
|||
|
|
|||
|
#region Catalog Data Processing
|
|||
|
|
|||
|
private void ConvertCharacterCatalogEntryToDSActor(CxAttrs catalogItemAttrs)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
Actor actor = database.GetActor(catalogItemAttrs.title);
|
|||
|
if (actor == null)
|
|||
|
{
|
|||
|
int actorID = template.GetNextActorID(database);
|
|||
|
actor = template.CreateActor(actorID, catalogItemAttrs.title, IsPlayerCharacter(catalogItemAttrs));
|
|||
|
database.actors.Add(actor);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
var originalActor = (database.syncInfo.syncActors && database.syncInfo.syncActorsDatabase != null)
|
|||
|
? database.syncInfo.syncActorsDatabase.GetActor(actor.Name) : null;
|
|||
|
if (originalActor != null)
|
|||
|
{
|
|||
|
AppendToField(originalActor.fields, CeltxFields.CatalogId, catalogItemAttrs.id, FieldType.Text);
|
|||
|
AppendToField(originalActor.fields, CeltxFields.Description, catalogItemAttrs.item_data.description, FieldType.Text);
|
|||
|
AppendToField(originalActor.fields, CeltxFields.Pictures, getPictureString(catalogItemAttrs), FieldType.Files);
|
|||
|
#if UNITY_EDITOR
|
|||
|
UnityEditor.EditorUtility.SetDirty(database.syncInfo.syncActorsDatabase);
|
|||
|
#endif
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
Debug.LogWarning("Celtx Import: Actor " + catalogItemAttrs.title + " was already added with Celtx ID " + actor.LookupValue(CeltxFields.CatalogId) + " but another actor with same name has Celtx ID " + catalogItemAttrs.id);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
AppendToField(actor.fields, CeltxFields.CatalogId, catalogItemAttrs.id, FieldType.Text);
|
|||
|
AppendToField(actor.fields, CeltxFields.Description, catalogItemAttrs.item_data.description, FieldType.Text);
|
|||
|
AppendToField(actor.fields, CeltxFields.Pictures, getPictureString(catalogItemAttrs), FieldType.Files);
|
|||
|
|
|||
|
celtxData.actorIdLookupByCxCharacterCatalogId[catalogItemAttrs.id] = actor.id;
|
|||
|
}
|
|||
|
catch (System.Exception e)
|
|||
|
{
|
|||
|
LogError(MethodBase.GetCurrentMethod(), e, catalogItemAttrs.id, catalogItemAttrs.title);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private bool IsPlayerCharacter(CxAttrs characterAttrs)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
if (characterAttrs.item_data == null)
|
|||
|
{
|
|||
|
LogWarning(GetNullDataString("attrs.item_data") +
|
|||
|
"Cannot determine if character is a player. Please ensure Character Type is set in the catalog", characterAttrs.id, characterAttrs.title);
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
if (characterAttrs.item_data.character_type == null)
|
|||
|
{
|
|||
|
LogWarning(GetNullDataString("attrs.item_data.character_type") +
|
|||
|
"Defaulting to non-player Actor. Please ensure Character Type is set in the catalog", characterAttrs.id, characterAttrs.title);
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
return characterAttrs.item_data.character_type.Equals("pc");
|
|||
|
}
|
|||
|
catch (System.Exception e)
|
|||
|
{
|
|||
|
LogError(MethodBase.GetCurrentMethod(), e, characterAttrs.id, characterAttrs.title);
|
|||
|
}
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
private string getPictureString(CxAttrs catalogItemAttrs)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
StringBuilder stringBuilder = new StringBuilder();
|
|||
|
stringBuilder.Append("[");
|
|||
|
if (catalogItemAttrs.item_data.media != null && catalogItemAttrs.item_data.media.Count > 0)
|
|||
|
{
|
|||
|
foreach (CxMedia media in catalogItemAttrs.item_data.media)
|
|||
|
{
|
|||
|
stringBuilder.Append(media.name);
|
|||
|
|
|||
|
if (media.Equals(catalogItemAttrs.item_data.media.Last()))
|
|||
|
{
|
|||
|
stringBuilder.Append("]");
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
stringBuilder.Append(";");
|
|||
|
}
|
|||
|
}
|
|||
|
return stringBuilder.ToString();
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
return "[]";
|
|||
|
}
|
|||
|
}
|
|||
|
catch (System.Exception e)
|
|||
|
{
|
|||
|
LogError(MethodBase.GetCurrentMethod(), e, catalogItemAttrs.id, catalogItemAttrs.title);
|
|||
|
}
|
|||
|
return "[]";
|
|||
|
}
|
|||
|
|
|||
|
private void ConvertLocationCatalogEntryToDSLocation(CxAttrs catalogItemAttrs)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
Location location = database.GetLocation(catalogItemAttrs.title);
|
|||
|
|
|||
|
if (location == null)
|
|||
|
{
|
|||
|
int locationId = template.GetNextLocationID(database);
|
|||
|
location = template.CreateLocation(locationId, catalogItemAttrs.title);
|
|||
|
database.locations.Add(location);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
var originalLocation = (database.syncInfo.syncLocations && database.syncInfo.syncLocationsDatabase != null)
|
|||
|
? database.syncInfo.syncLocationsDatabase.GetLocation(location.Name) : null;
|
|||
|
if (originalLocation != null)
|
|||
|
{
|
|||
|
AppendToField(originalLocation.fields, CeltxFields.CatalogId, catalogItemAttrs.id, FieldType.Text);
|
|||
|
AppendToField(originalLocation.fields, CeltxFields.Description, catalogItemAttrs.item_data.description, FieldType.Text);
|
|||
|
#if UNITY_EDITOR
|
|||
|
UnityEditor.EditorUtility.SetDirty(database.syncInfo.syncLocationsDatabase);
|
|||
|
#endif
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
AppendToField(location.fields, CeltxFields.CatalogId, catalogItemAttrs.id, FieldType.Text);
|
|||
|
AppendToField(location.fields, CeltxFields.Description, catalogItemAttrs.item_data.description, FieldType.Text);
|
|||
|
}
|
|||
|
catch (System.Exception e)
|
|||
|
{
|
|||
|
LogError(MethodBase.GetCurrentMethod(), e, catalogItemAttrs.id, catalogItemAttrs.title);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void ConvertItemCatalogEntryToDSItem(CxAttrs catalogItemAttrs)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
Item item = database.GetItem(catalogItemAttrs.title);
|
|||
|
|
|||
|
if (item == null)
|
|||
|
{
|
|||
|
int itemId = template.GetNextItemID(database);
|
|||
|
item = template.CreateItem(itemId, catalogItemAttrs.title);
|
|||
|
database.items.Add(item);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
var originalItem = (database.syncInfo.syncItems && database.syncInfo.syncItemsDatabase != null)
|
|||
|
? database.syncInfo.syncItemsDatabase.GetItem(item.Name) : null;
|
|||
|
if (originalItem != null)
|
|||
|
{
|
|||
|
AppendToField(originalItem.fields, CeltxFields.CatalogId, catalogItemAttrs.id, FieldType.Text);
|
|||
|
AppendToField(originalItem.fields, CeltxFields.Description, catalogItemAttrs.item_data.description, FieldType.Text);
|
|||
|
AppendToField(originalItem.fields, CeltxFields.ItemType, catalogItemAttrs.item_data.item_type, FieldType.Text);
|
|||
|
AppendToField(originalItem.fields, CeltxFields.ItemProperties, catalogItemAttrs.item_data.item_properties, FieldType.Text);
|
|||
|
AppendToField(originalItem.fields, CeltxFields.ItemAvailability, catalogItemAttrs.item_data.item_availability, FieldType.Text);
|
|||
|
#if UNITY_EDITOR
|
|||
|
UnityEditor.EditorUtility.SetDirty(database.syncInfo.syncItemsDatabase);
|
|||
|
#endif
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
AppendToField(item.fields, CeltxFields.CatalogId, catalogItemAttrs.id, FieldType.Text);
|
|||
|
AppendToField(item.fields, CeltxFields.Description, catalogItemAttrs.item_data.description, FieldType.Text);
|
|||
|
AppendToField(item.fields, CeltxFields.ItemType, catalogItemAttrs.item_data.item_type, FieldType.Text);
|
|||
|
AppendToField(item.fields, CeltxFields.ItemProperties, catalogItemAttrs.item_data.item_properties, FieldType.Text);
|
|||
|
AppendToField(item.fields, CeltxFields.ItemAvailability, catalogItemAttrs.item_data.item_availability, FieldType.Text);
|
|||
|
}
|
|||
|
catch (System.Exception e)
|
|||
|
{
|
|||
|
LogError(MethodBase.GetCurrentMethod(), e, catalogItemAttrs.id, catalogItemAttrs.title);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void ExtractCustomVarsList(CxAttrs catalogItemAttrs)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
string catalogId = catalogItemAttrs.id;
|
|||
|
List<CxCustomVar> customVars = catalogItemAttrs.custom_vars;
|
|||
|
|
|||
|
if (customVars != null && customVars.Count > 0)
|
|||
|
{
|
|||
|
celtxData.customVarListLookupByCxSequenceId.Add(catalogId, customVars);
|
|||
|
}
|
|||
|
}
|
|||
|
catch (System.Exception e)
|
|||
|
{
|
|||
|
LogError(MethodBase.GetCurrentMethod(), e, catalogItemAttrs.id, catalogItemAttrs.title);
|
|||
|
}
|
|||
|
}
|
|||
|
#endregion
|
|||
|
|
|||
|
#region Variables and Conditions
|
|||
|
|
|||
|
private void ConvertCeltxVariableToDSVariable(CxVariable variableObject)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
FieldType fieldType = FieldType.Text;
|
|||
|
string variableDefaultValue = "";
|
|||
|
List<Field> extraFields = new List<Field>();
|
|||
|
|
|||
|
switch (variableObject.type)
|
|||
|
{
|
|||
|
case "boolean":
|
|||
|
variableDefaultValue = variableObject.config.defaultBool.ToString();
|
|||
|
fieldType = FieldType.Boolean;
|
|||
|
break;
|
|||
|
|
|||
|
case "number":
|
|||
|
case "range":
|
|||
|
variableDefaultValue = variableObject.config.defaultNum.ToString();
|
|||
|
fieldType = FieldType.Number;
|
|||
|
break;
|
|||
|
|
|||
|
case "date":
|
|||
|
case "text":
|
|||
|
case "textarea":
|
|||
|
case "time":
|
|||
|
variableDefaultValue = variableObject.config.defaultString;
|
|||
|
fieldType = FieldType.Text;
|
|||
|
break;
|
|||
|
|
|||
|
case "radio":
|
|||
|
variableDefaultValue = variableObject.config.options[(int)variableObject.config.defaultNum].strVal;
|
|||
|
fieldType = FieldType.Text;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
var variable = database.GetVariable(variableObject.name);
|
|||
|
if (variable == null)
|
|||
|
{
|
|||
|
int variableId = template.GetNextVariableID(database);
|
|||
|
variable = template.CreateVariable(variableId, variableObject.name, variableDefaultValue, fieldType);
|
|||
|
database.variables.Add(variable);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
var originalVariable = (database.syncInfo.syncVariables && database.syncInfo.syncVariablesDatabase != null)
|
|||
|
? database.syncInfo.syncVariablesDatabase.GetVariable(variableObject.name) : null;
|
|||
|
if (originalVariable != null)
|
|||
|
{
|
|||
|
AppendToField(originalVariable.fields, CeltxFields.Description, variableObject.desc, FieldType.Text);
|
|||
|
#if UNITY_EDITOR
|
|||
|
UnityEditor.EditorUtility.SetDirty(database.syncInfo.syncVariablesDatabase);
|
|||
|
#endif
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
AppendToField(variable.fields, CeltxFields.Description, variableObject.desc, FieldType.Text);
|
|||
|
celtxData.variableLookupByCeltxId[variableObject.id] = variableObject.name;
|
|||
|
}
|
|||
|
catch (System.Exception e)
|
|||
|
{
|
|||
|
LogError(MethodBase.GetCurrentMethod(), e, variableObject.id, variableObject.name);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void ExtractCeltxCondition(CxAttrs conditionItemAttrs)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
CeltxCondition condition = new CeltxCondition();
|
|||
|
condition.id = conditionItemAttrs.id;
|
|||
|
condition.catalogId = conditionItemAttrs.catalog_id;
|
|||
|
condition.name = conditionItemAttrs.name;
|
|||
|
if (conditionItemAttrs.desc != null)
|
|||
|
{
|
|||
|
condition.delay = conditionItemAttrs.desc.Contains("[D]");
|
|||
|
}
|
|||
|
if (condition.delay) condition.description = conditionItemAttrs.desc.Substring(0, "[D]".Length);
|
|||
|
|
|||
|
condition.links = conditionItemAttrs.on;
|
|||
|
condition.literals = conditionItemAttrs.literals;
|
|||
|
SetFollowingOperators(condition, conditionItemAttrs.clause);
|
|||
|
celtxData.conditions.Add(condition);
|
|||
|
}
|
|||
|
catch (System.Exception e)
|
|||
|
{
|
|||
|
LogError(MethodBase.GetCurrentMethod(), e, conditionItemAttrs.id, conditionItemAttrs.title);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void SetFollowingOperators(CeltxCondition condition, string clause)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
List<string> subSections = new List<string>();
|
|||
|
List<string> orSplit = new List<string>();
|
|||
|
subSections.AddRange(System.Text.RegularExpressions.Regex.Split(clause, "(\\+|\\.)"));
|
|||
|
|
|||
|
if (subSections.ElementAt(subSections.Count - 1).Equals("")) { subSections.RemoveAt(subSections.Count - 1); }
|
|||
|
|
|||
|
for (int i = 0; i < subSections.Count - 1; i += 2)
|
|||
|
{
|
|||
|
CxLiteral literal = condition.literals.Find(l => l.lit_name.Equals(subSections.ElementAt(i)));
|
|||
|
literal.followingOp = subSections.ElementAt(i + 1);
|
|||
|
}
|
|||
|
}
|
|||
|
catch (System.Exception e)
|
|||
|
{
|
|||
|
LogError(MethodBase.GetCurrentMethod(), e, condition.id, condition.name);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void GenerateLuaCondition(CeltxCondition condition)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
if (condition.literals == null)
|
|||
|
{
|
|||
|
LogMessage(LogLevel.W,
|
|||
|
"Condition has no literals(literals list is null). Lua script generation will be skipped for this condition. Please add literals to the condition in Celtx", condition.id);
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
StringBuilder conditionString = new StringBuilder();
|
|||
|
string followingOp = null;
|
|||
|
foreach (CxLiteral literal in condition.literals)
|
|||
|
{
|
|||
|
if (followingOp != null) { conditionString.Append(" " + followingOp + " "); }
|
|||
|
|
|||
|
if (literal.type.Equals("variable"))
|
|||
|
{
|
|||
|
conditionString.Append("Variable");
|
|||
|
conditionString.Append("[\"" + literal.name + "\"]");
|
|||
|
conditionString.Append(" " + GetLuaComparisonOperator(literal.comparisonOperator) + " ");
|
|||
|
string comparisonVal;
|
|||
|
if (literal.varType != null && literal.varType.Equals("radio"))
|
|||
|
{
|
|||
|
comparisonVal = literal.config.options[(int)literal.comparisonValue.longVal].strVal;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
comparisonVal = literal.comparisonValue.strVal;
|
|||
|
}
|
|||
|
|
|||
|
if (SurroundComparisonValueInQuotes(literal))
|
|||
|
{
|
|||
|
conditionString.Append("\"" + comparisonVal + "\"");
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
conditionString.Append(comparisonVal);
|
|||
|
}
|
|||
|
}
|
|||
|
else if (literal.type.Equals("condition"))
|
|||
|
{
|
|||
|
conditionString.Append("(");
|
|||
|
conditionString.Append(GetNestedConditionString(literal.conditionId));
|
|||
|
conditionString.Append(") == ");
|
|||
|
conditionString.Append(literal.comparisonValue.strVal);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
LogMessage(LogLevel.W,
|
|||
|
"Unsupported literal type(" + literal.type + ") in condition. Only variable and condition literal types are supported", literal.id);
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
if (literal.followingOp.Equals(".")) { followingOp = "and"; }
|
|||
|
else if (literal.followingOp.Equals("+")) { followingOp = "or"; }
|
|||
|
else
|
|||
|
{
|
|||
|
LogMessage(LogLevel.W,
|
|||
|
"Unsupported following operator(" + literal.followingOp + ") in condition. Only \".\"(AND) and \"+\"(OR) are supported", literal.id);
|
|||
|
continue;
|
|||
|
}
|
|||
|
}
|
|||
|
condition.luaConditionString = conditionString.ToString();
|
|||
|
}
|
|||
|
catch (System.Exception e)
|
|||
|
{
|
|||
|
LogError(MethodBase.GetCurrentMethod(), e, condition.id, condition.name);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private bool SurroundComparisonValueInQuotes(CxLiteral literal)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
string variableId = literal.id;
|
|||
|
if (!celtxData.variableLookupByCeltxId.ContainsKey(variableId)) Debug.LogError("Celtx Import: Can't find variable with ID " + variableId);
|
|||
|
Variable var = database.GetVariable(celtxData.variableLookupByCeltxId[variableId]);
|
|||
|
if (var == null) Debug.LogError("Celtx Import: Dialogue database doesn't contain variable named " + celtxData.variableLookupByCeltxId[variableId]);
|
|||
|
FieldType varType = var.Type;
|
|||
|
if (varType == FieldType.Text)
|
|||
|
{
|
|||
|
return true;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
return false;
|
|||
|
}
|
|||
|
}
|
|||
|
catch (System.Exception e)
|
|||
|
{
|
|||
|
LogError(MethodBase.GetCurrentMethod(), e, literal.id);
|
|||
|
}
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
private string GetNestedConditionString(string conditionId)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
CeltxCondition condition = celtxData.conditions.Find(c => c.id.Equals(conditionId));
|
|||
|
if (condition.luaConditionString == null)
|
|||
|
{
|
|||
|
GenerateLuaCondition(condition);
|
|||
|
}
|
|||
|
|
|||
|
return condition.luaConditionString;
|
|||
|
}
|
|||
|
catch (System.Exception e)
|
|||
|
{
|
|||
|
LogError(MethodBase.GetCurrentMethod(), e, conditionId);
|
|||
|
}
|
|||
|
return null;
|
|||
|
}
|
|||
|
|
|||
|
private string GetLuaComparisonOperator(string literalOp)
|
|||
|
{
|
|||
|
switch (literalOp)
|
|||
|
{
|
|||
|
case "<":
|
|||
|
case "<=":
|
|||
|
case ">":
|
|||
|
case ">=":
|
|||
|
return literalOp;
|
|||
|
|
|||
|
case "=":
|
|||
|
return "==";
|
|||
|
|
|||
|
case "!=":
|
|||
|
return "~=";
|
|||
|
|
|||
|
case "exists":
|
|||
|
LogMessage(LogLevel.W,
|
|||
|
"Literal operator(" + literalOp + ") not supported. Defaulting to \"==\"");
|
|||
|
return "==";
|
|||
|
|
|||
|
case "does not exist":
|
|||
|
LogMessage(LogLevel.W,
|
|||
|
"Literal operator(" + literalOp + ") not supported. Defaulting to \"~=\"");
|
|||
|
return "~=";
|
|||
|
|
|||
|
default:
|
|||
|
LogMessage(LogLevel.W,
|
|||
|
"Unknown comparison operator(" + literalOp + ") in literal. Defaulting to \"==\"");
|
|||
|
return "==";
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#endregion
|
|||
|
|
|||
|
#region Check Sequence Syntax
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Check syntax of all sequences in all dialogue entries in database.
|
|||
|
/// Log warning for any entries with syntax errors.
|
|||
|
/// </summary>
|
|||
|
private void CheckSequenceSyntax()
|
|||
|
{
|
|||
|
if (database == null) return;
|
|||
|
var parser = new SequenceParser();
|
|||
|
foreach (Conversation conversation in database.conversations)
|
|||
|
{
|
|||
|
foreach (DialogueEntry entry in conversation.dialogueEntries)
|
|||
|
{
|
|||
|
var sequence = entry.Sequence;
|
|||
|
if (string.IsNullOrEmpty(sequence)) continue;
|
|||
|
var result = parser.Parse(sequence);
|
|||
|
if (result == null || result.Count == 0)
|
|||
|
{
|
|||
|
var text = entry.Title;
|
|||
|
if (string.IsNullOrEmpty(text)) text = entry.subtitleText;
|
|||
|
LogWarning("Dialogue entry " + conversation.id + ":" + entry.id +
|
|||
|
" in conversation '" + conversation.Title + "' has syntax error in [SEQ] Sequence: " + sequence,
|
|||
|
Field.LookupValue(entry.fields, "Celtx ID"), entry.Title);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#endregion
|
|||
|
|
|||
|
#region Logging
|
|||
|
|
|||
|
private string GetNullDataString(string nullFieldName)
|
|||
|
{
|
|||
|
return nullFieldName + " is null - ";
|
|||
|
}
|
|||
|
|
|||
|
private string GetErrorString(MethodBase methodName, System.Exception ex)
|
|||
|
{
|
|||
|
return "Error in " + methodName + " : " + ex.ToString();
|
|||
|
}
|
|||
|
|
|||
|
private void LogError(MethodBase methodName, System.Exception ex, string celtxId = null, string name = null)
|
|||
|
{
|
|||
|
string messageCore = GetErrorString(methodName, ex);
|
|||
|
LogMessage(LogLevel.E, messageCore, celtxId, name);
|
|||
|
}
|
|||
|
|
|||
|
private void LogWarning(string messageCore, string celtxId, string name)
|
|||
|
{
|
|||
|
LogMessage(LogLevel.W, messageCore, celtxId, name);
|
|||
|
}
|
|||
|
|
|||
|
private void LogMessage(LogLevel logLevel, string messageCore, string celtxId = null, string name = null)
|
|||
|
{
|
|||
|
StringBuilder logMessage = new StringBuilder();
|
|||
|
if (celtxId != null) { logMessage.Append("Celtx Object : " + celtxId + "(" + name + ")"); }
|
|||
|
logMessage.Append(" | " + messageCore);
|
|||
|
if (logLevel == LogLevel.W)
|
|||
|
{
|
|||
|
Debug.LogWarning(logMessage.ToString());
|
|||
|
}
|
|||
|
else if (logLevel == LogLevel.E)
|
|||
|
{
|
|||
|
Debug.LogError(logMessage.ToString());
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
Debug.Log(logMessage.ToString());
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
enum LogLevel
|
|||
|
{
|
|||
|
W, E, I
|
|||
|
}
|
|||
|
|
|||
|
#endregion
|
|||
|
}
|
|||
|
}
|
|||
|
#endif
|