public void GenerateForScript(string scriptText, Script scriptAsset, bool forceRebuild = false) { this.scriptAsset = scriptAsset; ScriptModified = false; // Prevent re-generating the editor after saving the script (applying the changes done in the editor). if (!forceRebuild && lastGeneratedTextHash == scriptText.GetHashCode()) { // Highlight played line if we're here after a hot-reload. if (Engine.Initialized && Engine.Behaviour is RuntimeBehaviour) { HighlightPlayedCommand(Engine.GetService <IScriptPlayer>()?.PlayedCommand); } return; } // Otherwise the script will generate twice when entering playmode. if (EditorApplication.isPlayingOrWillChangePlaymode && !EditorApplication.isPlaying) { return; } // Otherwise nullref could happen when recompiling with a script asset selected. EditorApplication.delayCall += GenerateDelayed; void GenerateDelayed() { var editorLocked = !config.HotReloadScripts && EditorApplication.isPlayingOrWillChangePlaymode; linesContainer.SetEnabled(!editorLocked); infoLabel.style.display = editorLocked ? DisplayStyle.None : DisplayStyle.Flex; LineTextField.ResetPerScriptStaticData(); Lines.Clear(); linesContainer.Clear(); var textLines = Helpers.SplitScriptText(scriptText); for (int i = 0; i < textLines.Length; i++) { if (textLines.Length > showLoadAt && (i % showLoadAt) == 0) // Update bar for each n processed items. { if (EditorUtility.DisplayCancelableProgressBar("Generating Visual Editor", "Processing naninovel script...", i / (float)textLines.Length)) { infoLabel.style.display = DisplayStyle.None; linesContainer.Clear(); EditorUtility.ClearProgressBar(); Add(new IMGUIContainer(() => EditorGUILayout.HelpBox("Visual editor generation has been canceled.", MessageType.Error))); return; } } var textLine = textLines[i]; if (string.IsNullOrEmpty(textLine)) { Lines.Add(null); // Skip empty lines. continue; } var lineView = CreateLineView(i, textLine); Lines.Add(lineView); if (ViewRange.Contains(i)) { linesContainer.Add(lineView); } } EditorUtility.ClearProgressBar(); if (Lines.Count > config.EditorPageLength) { paginationView.style.display = DisplayStyle.Flex; UpdatePaginationLabel(); } else { paginationView.style.display = DisplayStyle.None; } Engine.OnInitializationFinished -= HandleEngineInitialized; if (Engine.Initialized) { HandleEngineInitialized(); } else { Engine.OnInitializationFinished += HandleEngineInitialized; } if (textLines.Length > showLoadAt) { EditorUtility.DisplayProgressBar("Generating Visual Editor", "Building layout...", .5f); } EditorApplication.delayCall += EditorUtility.ClearProgressBar; var hotKeyInfo = config.InsertLineKey == KeyCode.None ? string.Empty : $" or {config.InsertLineKey}"; var modifierInfo = (config.InsertLineKey == KeyCode.None || config.InsertLineModifier == EventModifiers.None) ? string.Empty : $"{config.InsertLineModifier}+"; if (!string.IsNullOrEmpty(modifierInfo)) { hotKeyInfo = hotKeyInfo.Insert(4, modifierInfo); } infoLabel.text = $"Right-click{hotKeyInfo} to insert a new line"; infoLabel.tooltip = "Hotkeys can be changed in the script configuration menu (Naninovel -> Configuration -> Script)."; } }