private static bool DrawPatternGenerals(VibrationPattern pattern, float scale) { #if DEBUG ImGui.Text($"UUID: {pattern.Guid}"); if (ImGui.IsItemClicked(ImGuiMouseButton.Left)) { ImGui.SetClipboardText(pattern.Guid.ToString()); } #endif var changed = false; ImGui.SetNextItemWidth(175 * scale); var n = pattern.Name == "Nameless" ? "" : pattern.Name; if (ImGui.InputTextWithHint("##Pattern Name", "Name of Pattern", ref n, 20) && n.Trim() != "") { pattern.Name = n; changed = true; } ImGui.SameLine(); if (ImGui.Checkbox("Infinite", ref pattern.Infinite)) { changed = true; } if (pattern.Infinite) { return(changed); } ImGui.SameLine(); ImGui.SetNextItemWidth(75 * scale); if (ImGui.InputInt("Cycles", ref pattern.Cycles, 1)) { changed = true; } return(changed); }
/// <summary> /// Read the content from a given folder /// </summary> /// <param name="folder">The folder path to read</param> private void GetFiles(string folder) { DirectoryInfo dir = new DirectoryInfo(folder); FileInfo[] info = dir.GetFiles("*.json"); int patternNbLimit = 10; foreach (FileInfo f in info) { if (patternNbLimit-- < 0) { break; } string data = File.ReadAllText(f.FullName); string arrayData = data.Remove(1, data.IndexOf("\"motors\"") - 1); VibrationPattern vs = JsonUtility.FromJson <VibrationPattern>(data); vs.motors = JsonHelper.FromJson <Motor>(arrayData); RoukaViciController.instance.vibrationPatterns.Add(vs); } if (RoukaViciController.instance.vibrationPatterns.Count == 0) { // If no file were found, create a default one VibrationPattern vs = new VibrationPattern(); vs.duration = 0.5f; vs.name = "Default"; int i = 0; foreach (Motor f in vs.motors) { f.id = i++; f.pattern.Add(50); } RoukaViciController.instance.vibrationPatterns.Add(vs); } }
/// <summary> /// Updates every values to the first iteration's selected pattern /// </summary> /// <param name="editID">The ID of the pattern being edited</param> public void PrepareEditor(int editID) { dropdownIteration.value = 0; pattern = new VibrationPattern(); pattern.name = RoukaViciController.instance.vibrationPatterns[editID].name; pattern.duration = RoukaViciController.instance.vibrationPatterns[editID].duration; int j = 0; foreach (Motor f in RoukaViciController.instance.vibrationPatterns[editID].motors) { pattern.motors[j] = new Motor(); pattern.motors[j].pattern = new List <int>(f.pattern); pattern.motors[j].id = j; ++j; } currentPatternID = editID; dropdownIteration.options.Clear(); inputFieldPatternName.text = pattern.name; inputFieldPatternDuration.text = pattern.duration.ToString(); int count = pattern.motors[0].pattern.Count; for (int i = 0; i < count; ++i) { dropdownIteration.options.Add(new Dropdown.OptionData("Iteration " + (i + 1))); } }
public bool SequenceVibrateCmd(string device_name, VibrationPattern pattern) { if (!devices.ContainsKey(device_name)) { return(false); } return(devices[device_name].SendVibrateSequence(pattern)); }
private static bool DrawPatternSteps(VibrationPattern pattern, float scale) { var changed = false; ImGui.PushFont(UiBuilder.IconFont); if (ImGui.Button($"{FontAwesomeIcon.Plus.ToIconString()}##PatternStep", new Vector2(23 * scale, 23 * scale))) { pattern.Steps.Add(new VibrationPattern.Step(0, 0)); changed = true; } ImGui.PopFont(); var toRemoveSteps = new List <int>(); ImGui.SameLine(); ImGui.AlignTextToFramePadding(); ImGui.Text("Steps"); for (var i = 0; i < pattern.Steps.Count; i++) { ImGui.PushID(i); var s = pattern.Steps[i]; ImGui.AlignTextToFramePadding(); ImGui.Text($"{i + 1}"); ImGui.SameLine(); changed |= DrawHorizontalStep(scale, s); ImGui.SameLine(); if (DrawDeleteButton(FontAwesomeIcon.TrashAlt, new Vector2(23 * scale, 23 * scale), "Delete this Step.")) { toRemoveSteps.Add(i); changed = true; } ImGui.PopID(); } foreach (var i in toRemoveSteps) { pattern.Steps.RemoveAt(i); } ImGui.TreePop(); return(changed); }
/// <summary> /// Create a temporary VIbrationPattern object, and give it to the editor. /// Also displays the editor. /// </summary> public void AddPattern() { if (RoukaViciController.instance.patternButtons.Count >= patternNbLimit) { return; } VibrationPattern vs = new VibrationPattern(); vs.name = "My Pattern"; vs.duration = 0.3f; for (int i = 0; i < vs.motors.Length; ++i) { vs.motors[i] = new Motor(); vs.motors[i].id = i; vs.motors[i].pattern = new List <int>(); vs.motors[i].pattern.Add(50); } RoukaViciController.instance.vibrationPatterns.Add(vs); EditPattern(RoukaViciController.instance.vibrationPatterns.Count - 1); }
public ActionResult SequenceVibrateCmd(string name, [FromBody] VibrationPattern pattern) { var response = new BaseDeviceResponse("SequenceVibrateCmd", name); if (!Register.IsDevice(name)) { return(NotFound(response)); } //FIXME Need something better as return. if (pattern == null) { return(BadRequest(response)); } if (!Register.SequenceVibrateCmd(name, pattern)) { return(BadRequest(response)); } return(Ok(response)); }
private static bool DrawOnboarding(Configuration config, IEnumerable <ClassJob> jobs, IEnumerable <FFXIVAction> allActions, float scale) { var contentSize = ImGuiHelpers.MainViewport.Size; var modalSize = new Vector2(300 * scale, 100 * scale); var modalPosition = new Vector2(contentSize.X / 2 - modalSize.X / 2, contentSize.Y / 2 - modalSize.Y / 2); if (config.OnboardingStep == Onboarding.AskAboutExamplePatterns) { ImGui.OpenPopup("Create Example Patterns"); } var changed = false; ImGui.SetNextWindowSize(modalSize, ImGuiCond.Always); ImGuiHelpers.SetNextWindowPosRelativeMainViewport(modalPosition, ImGuiCond.Always); if (ImGui.BeginPopupModal("Create Example Patterns")) { ImGui.Text($"No vibration patterns found." + $"\nCreate some example patterns?"); if (ImGui.Button("No##ExamplePatterns")) { config.OnboardingStep = Onboarding.Done; changed = true; ImGui.CloseCurrentPopup(); } ImGui.SameLine(); if (ImGui.Button( "Yes##ExamplePatterns")) { #region Example Patterns var bothStrong = new VibrationPattern { Steps = new[] { new VibrationPattern.Step(100, 100, 300), }, Cycles = 1, Infinite = false, Name = "Both Strong" }; var lightPulse = new VibrationPattern { Steps = new[] { new VibrationPattern.Step(25, 25, 300), new VibrationPattern.Step(0, 0, 400) }, Infinite = true, Name = "Light pulse" }; var leftStrong = new VibrationPattern { Steps = new[] { new VibrationPattern.Step(100, 0, 300), }, Infinite = false, Cycles = 1, Name = "Left Strong" }; var rightStrong = new VibrationPattern { Steps = new[] { new VibrationPattern.Step(0, 100, 300), }, Infinite = false, Cycles = 1, Name = "Right Strong" }; var simpleRhythmic = new VibrationPattern { Steps = new[] { new VibrationPattern.Step(75, 75, 200), new VibrationPattern.Step(0, 0, 200), }, Infinite = false, Cycles = 3, Name = "Simple Rhythmic" }; config.Patterns.Add(lightPulse); config.Patterns.Add(bothStrong); config.Patterns.Add(leftStrong); config.Patterns.Add(rightStrong); config.Patterns.Add(simpleRhythmic); #endregion config.OnboardingStep = Onboarding.AskAboutExampleCooldownTriggers; changed = true; ImGui.CloseCurrentPopup(); } ImGui.EndPopup(); } if (config.OnboardingStep == Onboarding.AskAboutExampleCooldownTriggers) { ImGui.OpenPopup("Create Example Cooldown Triggers"); } ImGui.SetNextWindowSize(modalSize, ImGuiCond.Always); ImGuiHelpers.SetNextWindowPosRelativeMainViewport(modalPosition, ImGuiCond.Always); if (ImGui.BeginPopupModal("Create Example Cooldown Triggers")) { ImGui.Text($"No cooldown triggers found." + $"\nCreate some example triggers (Ninja and Paladin)?"); if (ImGui.Button("No##ExampleTriggers")) { config.OnboardingStep = Onboarding.Done; changed = true; ImGui.CloseCurrentPopup(); } ImGui.SameLine(); if (ImGui.Button( "Yes##ExampleTriggers")) { #region Example Triggers config.CooldownTriggers.Add(new CooldownTrigger( 30, "Dream Within a Dream", 3566, 16, 0, config.Patterns[1])); config.CooldownTriggers.Add(new CooldownTrigger( 30, "Mug", 2248, 18, 2, config.Patterns[3])); config.CooldownTriggers.Add(new CooldownTrigger( 19, "Fight or Flight", 20, 14, 3, config.Patterns[1])); #endregion config.OnboardingStep = Onboarding.AskAboutGCD; changed = true; ImGui.CloseCurrentPopup(); ImGui.OpenPopup("Create GCD Cooldown Triggers"); } ImGui.EndPopup(); } if (config.OnboardingStep == Onboarding.AskAboutGCD) { ImGui.OpenPopup("Create GCD Cooldown Triggers"); } ImGui.SetNextWindowSize(modalSize, ImGuiCond.Always); ImGuiHelpers.SetNextWindowPosRelativeMainViewport(modalPosition, ImGuiCond.Always); if (ImGui.BeginPopupModal("Create GCD Cooldown Triggers")) { ImGui.Text($"No GCD cooldown trigger found." + $"\nCreate a GCD trigger for each job?"); if (ImGui.Button("No##ExampleGCD")) { config.OnboardingStep = Onboarding.Done; changed = true; ImGui.CloseCurrentPopup(); } ImGui.SameLine(); if (ImGui.Button( "Yes##ExampleGCD")) { var gcdActionsCollection = allActions.Where(a => a.CooldownGroup == CooldownTrigger.GCDCooldownGroup); var gcdActions = gcdActionsCollection as FFXIVAction[] ?? gcdActionsCollection.ToArray(); foreach (var job in jobs) { var action = gcdActions.First(a => a.ClassJobCategory.Value.HasClass(job.RowId)); var lastTrigger = config.CooldownTriggers.LastOrDefault(); config.CooldownTriggers.Add( new CooldownTrigger( job.RowId, action.Name, action.RowId, action.CooldownGroup, lastTrigger?.Priority + 1 ?? 0, config.Patterns[0] )); } config.OnboardingStep = Onboarding.Done; changed = true; ImGui.CloseCurrentPopup(); } ImGui.EndPopup(); } return(changed); }
private static bool DrawPatternTab(Configuration config, float scale, ref IEnumerator <VibrationPattern.Step?>?patternEnumerator) { if (!ImGui.BeginTabItem("Patterns")) { return(false); } var changed = false; const string importExportPrefix = "GTP"; if (ImGui.Button("Add new Pattern")) { config.Patterns.Add(new VibrationPattern()); changed = true; } ImGui.SameLine(); if (ImGui.Button("Import from clipboard")) { var prefixedBase64 = ImGui.GetClipboardText(); try { if (prefixedBase64 is not null && prefixedBase64.StartsWith(importExportPrefix)) { var base64Bytes = Convert.FromBase64String(prefixedBase64.Substring(importExportPrefix.Length)); var json = Encoding.UTF8.GetString(base64Bytes); var p = JsonConvert.DeserializeObject <VibrationPattern>(json); if (p is not null) { p.Guid = Guid.NewGuid(); config.Patterns.Add(p); changed = true; } } } catch { // ignored } } ImGui.Separator(); var toRemovePatterns = new List <VibrationPattern>(); foreach (var pattern in config.Patterns) { ImGui.PushID(pattern.Guid.GetHashCode()); if (DrawDeleteButton(FontAwesomeIcon.TrashAlt)) { toRemovePatterns.Add(pattern); changed = true; } ImGui.SameLine(); ImGui.PushStyleColor(ImGuiCol.Button, Vector4.Zero); ImGui.PushFont(UiBuilder.IconFont); if (ImGui.Button(FontAwesomeIcon.Play.ToIconString())) { var p = new VibrationPattern() { Cycles = pattern.Infinite ? 4 : pattern.Cycles, Infinite = false, Steps = pattern.Steps, Name = pattern.Name }; patternEnumerator = p.GetEnumerator(); } ImGui.PopFont(); ImGui.PopStyleColor(); if (pattern.Infinite && ImGui.IsItemHovered()) { ImGui.BeginTooltip(); ImGui.Text("Infinite pattern will be repeated 4 times."); ImGui.EndTooltip(); } ImGui.SameLine(); var open = ImGui.TreeNodeEx($"{pattern.Name}###{pattern.Guid}", ImGuiTreeNodeFlags.AllowItemOverlap | ImGuiTreeNodeFlags.Bullet); ImGui.SameLine(300 * scale); if (ImGui.Button("Export to clipboard")) { var jsonOutput = JsonConvert.SerializeObject(pattern); if (jsonOutput is not null) { var prefixedBase64 = $"{importExportPrefix}{Convert.ToBase64String(Encoding.UTF8.GetBytes(jsonOutput))}"; ImGui.SetClipboardText(prefixedBase64); } } if (open) { changed |= DrawPatternGenerals(pattern, scale); changed |= DrawPatternSteps(pattern, scale); } ImGui.Separator(); ImGui.PopID(); } foreach (var pattern in toRemovePatterns) { config.Patterns.Remove(pattern); } ImGui.EndTabItem(); return(changed); }