private void ClearCanvas() { for (int i = Canvas.Components.Count - 1; i >= 0; --i) { Canvas.Components[i].Delete(); } // Reset savefile hash Canvas.SetAsSaved(); }
/// <summary> /// Callback to be executed after PlayChallengeMessageBox. /// Unfreezes the canvas and closes the message box. /// Positive trigger clears the current circuit and loads a challenge from JSON. /// </summary> /// <param name="triggerData">Data to pass from the trigger source to the trigger target.</param> public void Trigger(MessageBoxTriggerData triggerData) { if (triggerData.ButtonPressed == UIMessageBox.MessageBoxButtonType.Positive) { // Check for unsaved changes if (triggerData.Sender.GetType() == typeof(PlayChallengeMessageBox) && Canvas.IsUnsaved) { // Ask for confirmation of unsaved changes, save filename SelectedFilenameStash.Push(triggerData.TextInput); MessageBoxFactory.MakeFromConfig(UnsavedChangesMessageBoxConfig, this); Destroy(triggerData.Sender.gameObject); return; } else if (triggerData.Sender.GetType() == typeof(ConfirmMessageBox)) { // Confirmation received, pop filename triggerData.TextInput = SelectedFilenameStash.Pop(); SelectedFilenameStash.Clear(); } string fullpath = Directories.CHALLENGE_FOLDER_FULL_PATH + "/" + triggerData.TextInput + ".json"; // Read from file Debug.Log("Opening circuit from " + fullpath); string data; try { data = File.ReadAllText(fullpath); } catch (Exception e) { Debug.LogException(e); MessageBoxFactory.MakeFromConfig(OpenErrorMessageBoxConfig); Canvas.Frozen = false; Destroy(triggerData.Sender.gameObject); return; } // Parse JSON into configs var circuitConfig = JsonUtility.FromJson <CircuitConfig>(data); var componentConfigs = circuitConfig.logic_components; var edgeConfigs = circuitConfig.edges; var togglerConfigs = circuitConfig.toggles; var numberedTogglerConfigs = circuitConfig.numbered_toggles; var testCaseConfigs = circuitConfig.test_cases; var clockConfigs = circuitConfig.clocks; var titleText = circuitConfig.title_text; var bodyText = circuitConfig.body_text; var testCaseStepsRun = circuitConfig.test_case_steps_run; Assert.AreNotEqual(circuitConfig.game_mode, GameMode.Sandbox); // Clear the canvas for (int i = Canvas.Components.Count - 1; i >= 0; --i) { Canvas.Components[i].Delete(); } var logicComponentFactory = new SPLogicComponentFactory(Canvas.Foreground); // Build components whilst populating GUID map Dictionary <Guid, SPLogicComponent> guidMap = componentConfigs.ToDictionary( config => config.Guid, config => logicComponentFactory.MakeFromConfig(config)); Canvas.Components.AddRange(guidMap.Values); // Restore state for input togglers foreach (var config in togglerConfigs) { Guid guid = Guid.Parse(config.guid_string); SPInputToggler inputToggler = (SPInputToggler)guidMap[guid]; if (((InputComponent)inputToggler.LogicComponent).value != config.value) { inputToggler.ToggleValue(); } } foreach (var config in numberedTogglerConfigs) { Guid guid = Guid.Parse(config.guid_string); SPNumberedInputToggler inputToggler = (SPNumberedInputToggler)guidMap[guid]; if (((InputComponent)inputToggler.LogicComponent).value != config.value) { inputToggler.ToggleValue(); } } // Restore state for clock components foreach (var config in clockConfigs) { Guid guid = Guid.Parse(config.guid_string); SPClock clock = (SPClock)guidMap[guid]; ((Clock)clock.LogicComponent).Period = config.period; } // Build edges using GUID map foreach (var config in edgeConfigs) { Canvas.StartEdge(guidMap[config.ComponentGuids[0]].InConnectors[config.connector_ids[0]]); Canvas.FinishEdge(guidMap[config.ComponentGuids[1]].OutConnectors[config.connector_ids[1]]); } // Set all initial components to immutable foreach (var component in Canvas.Components) { component.Immutable = true; } foreach (var edge in Canvas.Edges) { edge.Immutable = true; } // TODO: USE THE TEST CASES GENERATED. foreach (TestCaseConfig testCase in testCaseConfigs) { foreach (KeyValuePair <uint, bool> kvp in testCase.GetAllInputs()) { Debug.Log("Input: " + kvp.Key.ToString() + ": " + kvp.Value.ToString()); } foreach (KeyValuePair <uint, bool> kvp in testCase.GetAllOutputs()) { Debug.Log("Output: " + kvp.Key.ToString() + ": " + kvp.Value.ToString()); } } // Load the test cases into SPCanvas Canvas.TestCases = testCaseConfigs; // Load how many test case steps to run: Canvas.TestCaseStepsRun = testCaseStepsRun; // Put the canvas into challenge mode Canvas.CurrentMode = circuitConfig.game_mode; Canvas.ChallengeCompleted = false; Canvas.SetAsSaved(); FindObjectOfType <UIOverlayControlVerifyChallengeButton>().GetComponent <RectTransform>().sizeDelta = new Vector2 { x = 40, y = 40 }; // Set the Info Panel information. Canvas.InfoPanelTitle = titleText; Canvas.InfoPanelText = bodyText; InfoPanel.SetInfoTarget(Canvas); InfoPanel.Show(); } Canvas.Frozen = false; Destroy(triggerData.Sender.gameObject); }
/// <summary> /// Callback to be executed after SaveCircuitMessageBox. /// Unfreezes the canvas and closes the message box. /// Positive trigger saves the circuit as JSON. /// </summary> /// <param name="triggerData">Data to pass from the trigger source to the trigger target.</param> public void Trigger(MessageBoxTriggerData triggerData) { if (triggerData.ButtonPressed == UIMessageBox.MessageBoxButtonType.Positive) { // Bind a GUID for each component Dictionary <SPLogicComponent, Guid> guidMap = Canvas.Components .ToDictionary(c => c, c => Guid.NewGuid()); // Generate configs for components List <LogicComponentConfig> componentConfigs = guidMap .Select(kvp => kvp.Key.GenerateConfig(kvp.Value)) .ToList(); // Generate configs for edges, mapping connected components using GUIDs List <EdgeConfig> edgeConfigs = Canvas.Edges .Select(e => e.GenerateConfig(guidMap)) .ToList(); // Generate additional configs to save state of input togglers List <InputToggleConfig> toggleConfigs = guidMap .Where(kvp => kvp.Key.GetType() == typeof(SPInputToggler)) .Select(kvp => new InputToggleConfig { guid_string = kvp.Value.ToString(), value = ((InputComponent)kvp.Key.LogicComponent).value }) .ToList(); List <InputToggleConfig> numberedToggleConfigs = guidMap .Where(kvp => kvp.Key.GetType() == typeof(SPNumberedInputToggler)) .Select(kvp => new InputToggleConfig { guid_string = kvp.Value.ToString(), value = ((InputComponent)kvp.Key.LogicComponent).value }) .ToList(); // Generate additional configs to save state of clock components List <ClockComponentConfig> clockConfigs = guidMap .Where(kvp => kvp.Key.GetType() == typeof(SPClock)) .Select(kvp => new ClockComponentConfig { guid_string = kvp.Value.ToString(), period = ((Clock)kvp.Key.LogicComponent).Period }) .ToList(); // Generate an empty test cases config: List <TestCaseConfig> testCaseConfigs = new List <TestCaseConfig>(); // Build savefile CircuitConfig spConfig = new CircuitConfig( componentConfigs, edgeConfigs, toggleConfigs, numberedToggleConfigs, clockConfigs, testCaseConfigs, mode: GameMode.Sandbox); #if DEVELOPMENT_BUILD string saveData = JsonUtility.ToJson(spConfig, prettyPrint: true); #else string saveData = JsonUtility.ToJson(spConfig, prettyPrint: false); #endif // Build full file path string filename = triggerData.TextInput + ".json"; string fullpath = Directories.SAVEFILE_FOLDER_FULL_PATH + "/" + filename; // Write to file Debug.Log("Saving to " + fullpath); try { Directory.CreateDirectory(Directories.SAVEFILE_FOLDER_FULL_PATH); File.WriteAllText(fullpath, saveData); Canvas.SetAsSaved(); } catch (Exception e) { // uh oh Debug.LogException(e); MessageBoxFactory.MakeFromConfig(SaveErrorMessageBoxConfig); } } else if (triggerData.ButtonPressed == UIMessageBox.MessageBoxButtonType.Neutral) { // Bind a GUID for each component Dictionary <SPLogicComponent, Guid> guidMap = Canvas.Components .ToDictionary(c => c, c => Guid.NewGuid()); // Generate configs for components List <LogicComponentConfig> componentConfigs = guidMap .Select(kvp => kvp.Key.GenerateConfig(kvp.Value)) .ToList(); // Generate configs for edges, mapping connected components using GUIDs List <EdgeConfig> edgeConfigs = Canvas.Edges .Select(e => e.GenerateConfig(guidMap)) .ToList(); // Generate additional configs to save state of input togglers List <InputToggleConfig> toggleConfigs = guidMap .Where(kvp => kvp.Key.GetType() == typeof(SPInputToggler)) .Select(kvp => new InputToggleConfig { guid_string = kvp.Value.ToString(), value = ((InputComponent)kvp.Key.LogicComponent).value }) .ToList(); List <InputToggleConfig> numberedToggleConfigs = guidMap .Where(kvp => kvp.Key.GetType() == typeof(SPNumberedInputToggler)) .Select(kvp => new InputToggleConfig { guid_string = kvp.Value.ToString(), value = ((InputComponent)kvp.Key.LogicComponent).value }) .ToList(); // Generate test cases config: List <TestCaseConfig> testCaseConfigs = new List <TestCaseConfig>(); // Generate one based on Circuit: // Just a dummy one so you have a template on how to modify it. TestCaseConfig testCase = new TestCaseConfig(); foreach (var kvp in Canvas.NumberedInputs) { InputComponent inputComponent = kvp.Value.LogicComponent as InputComponent; testCase.SetInput(kvp.Key, inputComponent.value); } foreach (var kvp in Canvas.NumberedOutputs) { Output output = kvp.Value.LogicComponent as Output; testCase.SetOutput(kvp.Key, output.Value); } testCaseConfigs.Add(testCase); // Generate additional configs to save state of clock components List <ClockComponentConfig> clockConfigs = guidMap .Where(kvp => kvp.Key.GetType() == typeof(SPClock)) .Select(kvp => new ClockComponentConfig { guid_string = kvp.Value.ToString(), period = ((Clock)kvp.Key.LogicComponent).Period }) .ToList(); // Generate default title strings. String titleText = "Objective"; String bodyText = "Your aim is to turn all the lights on.\nYou can not delete pre-placed components.\nAll components placed must use all endpoints and contribute to at least one output light."; // Build savefile CircuitConfig spConfig = new CircuitConfig( componentConfigs, edgeConfigs, toggleConfigs, numberedToggleConfigs, clockConfigs, testCaseConfigs, GameMode.ActivateAllOutputsChallenge, titleText: titleText, bodyText: bodyText); #if DEVELOPMENT_BUILD string saveData = JsonUtility.ToJson(spConfig, prettyPrint: true); #else string saveData = JsonUtility.ToJson(spConfig, prettyPrint: false); #endif // Build full file path string filename = triggerData.TextInput + ".json"; string fullpath = Directories.CHALLENGE_FOLDER_FULL_PATH + "/" + filename; // Write to file Debug.Log("Saving to " + fullpath); try { Directory.CreateDirectory(Directories.CHALLENGE_FOLDER_FULL_PATH); File.WriteAllText(fullpath, saveData); Canvas.SetAsSaved(); } catch (Exception e) { // uh oh Debug.LogException(e); MessageBoxFactory.MakeFromConfig(SaveErrorMessageBoxConfig); } } Canvas.Frozen = false; Destroy(triggerData.Sender.gameObject); }
/// <summary> /// Callback to be executed after OpenCircuitMessageBox. /// Unfreezes the canvas and closes the message box. /// Positive trigger clears the current circuit and loads a saved one from JSON. /// </summary> /// <param name="triggerData">Data to pass from the trigger source to the trigger target.</param> public void Trigger(MessageBoxTriggerData triggerData) { if (triggerData.ButtonPressed == UIMessageBox.MessageBoxButtonType.Positive) { // Check for unsaved changes if (triggerData.Sender.GetType() == typeof(OpenCircuitMessageBox) && Canvas.IsUnsaved) { // Ask for confirmation of unsaved changes, save filename SelectedFilenameStash.Push(triggerData.TextInput); MessageBoxFactory.MakeFromConfig(UnsavedChangesMessageBoxConfig, this); Destroy(triggerData.Sender.gameObject); return; } else if (triggerData.Sender.GetType() == typeof(ConfirmMessageBox)) { // Confirmation received, pop filename triggerData.TextInput = SelectedFilenameStash.Pop(); SelectedFilenameStash.Clear(); } string fullpath = Directories.SAVEFILE_FOLDER_FULL_PATH + "/" + triggerData.TextInput + ".json"; // Read from file Debug.Log("Opening circuit from " + fullpath); string data; try { data = File.ReadAllText(fullpath); } catch (Exception e) { Debug.LogException(e); MessageBoxFactory.MakeFromConfig(OpenErrorMessageBoxConfig); Canvas.Frozen = false; Destroy(triggerData.Sender.gameObject); return; } // Parse JSON into configs var circuitConfig = JsonUtility.FromJson <CircuitConfig>(data); var componentConfigs = circuitConfig.logic_components; var edgeConfigs = circuitConfig.edges; var togglerConfigs = circuitConfig.toggles; var numberedTogglerConfigs = circuitConfig.numbered_toggles; var clockConfigs = circuitConfig.clocks; Assert.AreEqual(circuitConfig.game_mode, GameMode.Sandbox); // Clear the canvas for (int i = Canvas.Components.Count - 1; i >= 0; --i) { Canvas.Components[i].Delete(); } var logicComponentFactory = new SPLogicComponentFactory(Canvas.Foreground); // Build components whilst populating GUID map Dictionary <Guid, SPLogicComponent> guidMap = componentConfigs.ToDictionary( config => config.Guid, config => logicComponentFactory.MakeFromConfig(config)); Canvas.Components.AddRange(guidMap.Values); // Restore state for input togglers foreach (var config in togglerConfigs) { Guid guid = Guid.Parse(config.guid_string); SPInputToggler inputToggler = (SPInputToggler)guidMap[guid]; if (((InputComponent)inputToggler.LogicComponent).value != config.value) { inputToggler.ToggleValue(); } } foreach (var config in numberedTogglerConfigs) { Guid guid = Guid.Parse(config.guid_string); SPNumberedInputToggler inputToggler = (SPNumberedInputToggler)guidMap[guid]; if (((InputComponent)inputToggler.LogicComponent).value != config.value) { inputToggler.ToggleValue(); } } // Restore state for clock components foreach (var config in clockConfigs) { Guid guid = Guid.Parse(config.guid_string); SPClock clock = (SPClock)guidMap[guid]; ((Clock)clock.LogicComponent).Period = config.period; } // Build edges using GUID map foreach (var config in edgeConfigs) { Canvas.StartEdge(guidMap[config.ComponentGuids[0]].InConnectors[config.connector_ids[0]]); Canvas.FinishEdge(guidMap[config.ComponentGuids[1]].OutConnectors[config.connector_ids[1]]); } // Loading a circuit means the circuit that was just loaded is "saved" Canvas.CurrentMode = GameMode.Sandbox; Canvas.SetAsSaved(); FindObjectOfType <UIOverlayControlVerifyChallengeButton>().GetComponent <RectTransform>().sizeDelta = new Vector2 { x = 0, y = 0 }; } Canvas.Frozen = false; Destroy(triggerData.Sender.gameObject); }