ScriptCodeManager.cs 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. using System.Text;
  2. using BansheeEngine;
  3. namespace BansheeEditor
  4. {
  5. /// <summary>
  6. /// Handles various operations related to script code in the active project, like compilation and code editor syncing.
  7. /// </summary>
  8. public sealed class ScriptCodeManager
  9. {
  10. private bool isGameAssemblyDirty;
  11. private bool isEditorAssemblyDirty;
  12. private CompilerInstance compilerInstance;
  13. /// <summary>
  14. /// Constructs a new script code manager.
  15. /// </summary>
  16. internal ScriptCodeManager()
  17. {
  18. ProjectLibrary.OnEntryAdded += OnEntryAdded;
  19. ProjectLibrary.OnEntryRemoved += OnEntryRemoved;
  20. ProjectLibrary.OnEntryImported += OnEntryImported;
  21. }
  22. /// <summary>
  23. /// Triggers required compilation or code editor syncing if needed.
  24. /// </summary>
  25. internal void Update()
  26. {
  27. if (CodeEditor.IsSolutionDirty)
  28. CodeEditor.SyncSolution();
  29. if (compilerInstance == null)
  30. {
  31. string outputDir = EditorApplication.ScriptAssemblyPath;
  32. if (isGameAssemblyDirty)
  33. {
  34. compilerInstance = ScriptCompiler.CompileAsync(
  35. ScriptAssemblyType.Game, BuildManager.ActivePlatform, true, outputDir);
  36. EditorApplication.SetStatusCompiling(true);
  37. isGameAssemblyDirty = false;
  38. }
  39. else if (isEditorAssemblyDirty)
  40. {
  41. compilerInstance = ScriptCompiler.CompileAsync(
  42. ScriptAssemblyType.Editor, BuildManager.ActivePlatform, true, outputDir);
  43. EditorApplication.SetStatusCompiling(true);
  44. isEditorAssemblyDirty = false;
  45. }
  46. }
  47. else
  48. {
  49. if (compilerInstance.IsDone)
  50. {
  51. if (compilerInstance.HasErrors)
  52. {
  53. foreach (var msg in compilerInstance.WarningMessages)
  54. Debug.LogError(FormMessage(msg));
  55. foreach (var msg in compilerInstance.ErrorMessages)
  56. Debug.LogError(FormMessage(msg));
  57. }
  58. compilerInstance.Dispose();
  59. compilerInstance = null;
  60. EditorApplication.SetStatusCompiling(false);
  61. EditorApplication.ReloadAssemblies();
  62. }
  63. }
  64. }
  65. /// <summary>
  66. /// Triggered when a new resource is added to the project library.
  67. /// </summary>
  68. /// <param name="path">Path of the added resource, relative to the project's resource folder.</param>
  69. private void OnEntryAdded(string path)
  70. {
  71. if (IsCodeEditorFile(path))
  72. CodeEditor.MarkSolutionDirty();
  73. }
  74. /// <summary>
  75. /// Triggered when a resource is removed from the project library.
  76. /// </summary>
  77. /// <param name="path">Path of the removed resource, relative to the project's resource folder.</param>
  78. private void OnEntryRemoved(string path)
  79. {
  80. if (IsCodeEditorFile(path))
  81. CodeEditor.MarkSolutionDirty();
  82. }
  83. /// <summary>
  84. /// Triggered when a resource is (re)imported in the project library.
  85. /// </summary>
  86. /// <param name="path">Path of the imported resource, relative to the project's resource folder.</param>
  87. private void OnEntryImported(string path)
  88. {
  89. LibraryEntry entry = ProjectLibrary.GetEntry(path);
  90. if (entry == null || entry.Type != LibraryEntryType.File)
  91. return;
  92. FileEntry fileEntry = (FileEntry)entry;
  93. if (fileEntry.ResType != ResourceType.ScriptCode)
  94. return;
  95. ScriptCode codeFile = ProjectLibrary.Load<ScriptCode>(path);
  96. if(codeFile == null)
  97. return;
  98. if(codeFile.EditorScript)
  99. isEditorAssemblyDirty = true;
  100. else
  101. isGameAssemblyDirty = true;
  102. }
  103. /// <summary>
  104. /// Checks is the resource at the provided path a file relevant to the code editor.
  105. /// </summary>
  106. /// <param name="path">Path to the resource, absolute or relative to the project's resources folder.</param>
  107. /// <returns>True if the file is relevant to the code editor, false otherwise.</returns>
  108. private bool IsCodeEditorFile(string path)
  109. {
  110. LibraryEntry entry = ProjectLibrary.GetEntry(path);
  111. if (entry != null && entry.Type == LibraryEntryType.File)
  112. {
  113. FileEntry fileEntry = (FileEntry)entry;
  114. foreach (var codeType in CodeEditor.CodeTypes)
  115. {
  116. if (fileEntry.ResType == codeType)
  117. return true;
  118. }
  119. }
  120. return false;
  121. }
  122. /// <summary>
  123. /// Converts data reported by the compiler into a readable string.
  124. /// </summary>
  125. /// <param name="msg">Message data as reported by the compiler.</param>
  126. /// <returns>Readable message string.</returns>
  127. private string FormMessage(CompilerMessage msg)
  128. {
  129. StringBuilder sb = new StringBuilder();
  130. if (msg.type == CompilerMessageType.Error)
  131. sb.AppendLine("Compiler error: " + msg.message);
  132. else
  133. sb.AppendLine("Compiler warning: " + msg.message);
  134. sb.AppendLine("\tin " + msg.file + "[" + msg.line + ":" + msg.column + "]");
  135. return sb.ToString();
  136. }
  137. }
  138. }