//----------------------------------------------------------------------------------------------- public static Texture2D GetInfluenceMapAsTexture(WorkingMap map) { byte[] dataAsByte = new byte[map.Data.Length]; for (int pixelIndex = 0; pixelIndex < map.Data.Length; ++pixelIndex) { float influenceValue = map.Data[pixelIndex]; if (influenceValue < 0f) { dataAsByte[pixelIndex] = 0; } else if (influenceValue > 1f) { dataAsByte[pixelIndex] = 1; } else { dataAsByte[pixelIndex] = (byte)(map.Data[pixelIndex] * 255); } } Texture2D mapTexture = new Texture2D((int)BaseMap.INFLUENCE_MAP_RESOLUTION, (int)BaseMap.INFLUENCE_MAP_RESOLUTION, TextureFormat.Alpha8, false, false); mapTexture.LoadRawTextureData(dataAsByte); mapTexture.Apply(); return(mapTexture); }
//----------------------------------------------------------------------------------------------- private WorkingMap ConstructActiveMapFromMapFormula(int indexIntoFormulaList) { MapFormula formulaToUse = m_influenceSystemRef.InfluenceMapFormulas[indexIntoFormulaList]; WorkingMap activeMap = formulaToUse.ConstructMapFromFormula(); activeMap.Normalize(); return(activeMap); }
//----------------------------------------------------------------------------------------------- private WorkingMap ConstructActiveMapFromBaseMap(int indexIntoMapList) { WorkingMap activeMap = new WorkingMap(); activeMap.AddMap(m_influenceSystemRef.InfluenceMaps[indexIntoMapList], 1f); activeMap.Normalize(); return(activeMap); }
/// <summary> /// </summary> public EditorScreen(Qua map) { if (OnlineManager.IsSpectatingSomeone) { OnlineManager.Client?.StopSpectating(); } OriginalMap = map; WorkingMap = ObjectHelper.DeepClone(OriginalMap); FixInvalidHitObjectLayers(); MapManager.Selected.Value.Qua = WorkingMap; // Discord Rich Presence DiscordHelper.Presence.Details = WorkingMap.ToString(); DiscordHelper.Presence.State = "Editing"; DiscordHelper.Presence.StartTimestamp = (long)(TimeHelper.GetUnixTimestampMilliseconds() / 1000); DiscordHelper.Presence.EndTimestamp = 0; DiscordRpc.UpdatePresence(ref DiscordHelper.Presence); ActiveLayerInterface = new Bindable <EditorLayerInterface>(EditorLayerInterface.Composition) { Value = EditorLayerInterface.Composition }; ModManager.RemoveSpeedMods(); if (!LoadAudioTrack()) { return; } CustomAudioSampleCache.LoadSamples(MapManager.Selected.Value, MapManager.Selected.Value.Md5Checksum); SetHitSoundObjectIndex(); GameBase.Game.IsMouseVisible = true; GameBase.Game.GlobalUserInterface.Cursor.Visible = false; GameBase.Game.Window.FileDropped += OnFileDropped; if (MapManager.Selected.Value.Game == MapGame.Quaver) { BeginWatchingFiles(); } Metronome = new Metronome(WorkingMap); View = new EditorScreenView(this); CreateRuleset(); AppDomain.CurrentDomain.UnhandledException += OnCrash; if (File.Exists($"{ConfigManager.SongDirectory}/{MapManager.Selected.Value.Directory}/{MapManager.Selected.Value.Path}.autosave")) { DialogManager.Show(new EditorAutosaveDetectionDialog()); } }
/// <inheritdoc /> /// <summary> /// </summary> public void Undo() { WorkingMap.SliderVelocities.Remove(Velocity); WorkingMap.SortSliderVelocities(); var game = GameBase.Game as QuaverGame; var screen = game?.CurrentScreen as EditorScreen; var ruleset = screen?.Ruleset as EditorRulesetKeys; var graph = ruleset?.VisualizationGraphs[EditorVisualizationGraphType.Tick].GraphRaw as EditorTickGraph; graph?.RemoveSliderVelocityLine(Velocity); }
/// <inheritdoc /> /// <summary> /// </summary> public void Perform() { WorkingMap.HitObjects.Remove(HitObject); WorkingMap.Sort(); Container.RemoveHitObjectSprite(HitObject); Container.Ruleset.Screen.SetHitSoundObjectIndex(); var graphContainer = Container.Ruleset.VisualizationGraphs[EditorVisualizationGraphType.Density]; var graph = graphContainer?.GraphRaw as EditorNoteDensityGraph; graph?.RefreshSample(HitObject); graphContainer?.ForceRecache(); }
/// <inheritdoc /> /// <summary> /// </summary> public void Perform() { WorkingMap.TimingPoints.Add(TimingPoint); WorkingMap.SortTimingPoints(); var game = GameBase.Game as QuaverGame; var screen = game?.CurrentScreen as EditorScreen; var ruleset = screen?.Ruleset as EditorRulesetKeys; var graph = ruleset?.VisualizationGraphs[EditorVisualizationGraphType.Tick].GraphRaw as EditorTickGraph; graph?.AddTimingPointLine(TimingPoint); ruleset?.ScrollContainer.Timeline.CompletelyReinitialize(); }
/// <summary> /// Saves the map /// </summary> public void Save(bool exitAfter = false) { if (IsQuittingAfterSave) { return; } if (exitAfter) { IsQuittingAfterSave = true; } if (MapManager.Selected.Value.Game != MapGame.Quaver) { NotificationManager.Show(NotificationLevel.Error, "You cannot save a map loaded from another game."); return; } if (SaveInProgress) { NotificationManager.Show(NotificationLevel.Error, "Slow down! We're already saving your map."); return; } if (!MapDatabaseCache.MapsToUpdate.Contains(MapManager.Selected.Value)) { MapDatabaseCache.MapsToUpdate.Add(MapManager.Selected.Value); } // Impoortant. Save the last save action, so we know whether or not the user has made changes. Ruleset.ActionManager.LastSaveAction = Ruleset.ActionManager.UndoStack.Count == 0 ? null : Ruleset.ActionManager.UndoStack.Peek(); ThreadScheduler.Run(() => { var path = $"{ConfigManager.SongDirectory}/{MapManager.Selected.Value.Directory}/{MapManager.Selected.Value.Path}"; SaveInProgress = true; WorkingMap.Save(path); SaveInProgress = false; LastSaveTime = GameBase.Game.TimeRunning; if (exitAfter) { ExitToSelect(); } else { NotificationManager.Show(NotificationLevel.Success, "Successfully saved the map."); } }); }
/// <summary> /// Autosave when the game crashes. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void OnCrash(object sender, UnhandledExceptionEventArgs e) { if (MapManager.Selected.Value.Game != MapGame.Quaver) { return; } if (Ruleset.ActionManager.UndoStack.Count == 0) { return; } Logger.Important($"Detected game crash. Autosaving map", LogType.Runtime); var path = $"{ConfigManager.SongDirectory}/{MapManager.Selected.Value.Directory}/{MapManager.Selected.Value.Path}.autosave"; WorkingMap.Save(path); }
//----------------------------------------------------------------------------------------------- public override void Run() { OperatorParam influenceMapParamName = FindParamWithName("Influence"); // Can't exactly move if we don't have a goal if (influenceMapParamName == null) { return; } string[] mapIdentifiers = influenceMapParamName.Value.Split('_'); // Determine map type InfluenceSystem influenceSys = InfluenceSystem.GetInstance(); InfluenceMapPoint mapPoint; if (mapIdentifiers[0].Equals("Base", StringComparison.CurrentCultureIgnoreCase)) { WorkingMap queryMap = new WorkingMap(); queryMap.AddMap(influenceSys.GetInfluenceMapByIDWithTag(mapIdentifiers[1], mapIdentifiers[2])); queryMap.Normalize(); mapPoint = queryMap.GetPointOfHighestInfluence(); } else if (mapIdentifiers[0].Equals("Formula", StringComparison.CurrentCultureIgnoreCase)) { MapFormula formulaToUse = influenceSys.GetMapFormulaByID(mapIdentifiers[1]); WorkingMap queryMap = formulaToUse.ConstructMapFromFormula(); mapPoint = queryMap.GetPointOfHighestInfluence(); } else { throw new ArgumentException("Invalid name for influence map in move to operator!"); } InfluenceObjectWorldPoint worldPoint = influenceSys.ConvertMapPosToWorldPos(mapPoint); Vector2 newLocation = new Vector2(worldPoint.x, worldPoint.y); AgentToOperateOn.transform.position = newLocation; InfluenceGameManager influenceManager = GameObject.FindObjectOfType <InfluenceGameManager>(); influenceManager.UpdateInfluenceSystem(); }
/// <inheritdoc /> /// <summary> /// </summary> public void Perform() { var skin = SkinManager.Skin.Keys[WorkingMap.Mode]; foreach (var h in HitObjects) { h.Info.Lane = WorkingMap.GetKeyCount() - h.Info.Lane + 1; h.X = Container.ScreenRectangle.X + Container.LaneSize * (h.Info.Lane - 1) + Container.DividerLineWidth; var index = skin.ColorObjectsBySnapDistance ? HitObjectManager.GetBeatSnap(h.Info, h.Info.GetTimingPoint(WorkingMap.TimingPoints)) : 0; if (h.Info.IsLongNote) { var ln = (DrawableEditorHitObjectLong)h; if (ConfigManager.EditorViewLayers.Value) { h.Image = skin.EditorLayerNoteHitObjects[h.Info.Lane - 1]; ln.Body.Image = skin.EditorLayerNoteHoldBodies[h.Info.Lane - 1]; ln.Tail.Image = skin.EditorLayerNoteHoldEnds[h.Info.Lane - 1]; } else { h.Image = skin.NoteHoldHitObjects[h.Info.Lane - 1][index]; ln.Body.Image = skin.NoteHoldBodies[h.Info.Lane - 1].First(); ln.Tail.Image = skin.NoteHoldEnds[h.Info.Lane - 1]; } ln.ResizeLongNote(); } else { if (ConfigManager.EditorViewLayers.Value) { h.Image = skin.EditorLayerNoteHitObjects[h.Info.Lane - 1]; } else { h.Image = skin.NoteHitObjects[h.Info.Lane - 1][index]; } } } }
//----------------------------------------------------------------------------------------------- private WorkingMap ConstructMapAtIndex(int mapIndex) { if (mapIndex == 0) { return(null); } mapIndex -= 1; WorkingMap newMap = null; if (mapIndex >= m_influenceSystemRef.InfluenceMaps.Count) { mapIndex -= m_influenceSystemRef.InfluenceMaps.Count; newMap = ConstructActiveMapFromMapFormula(mapIndex); } else { newMap = ConstructActiveMapFromBaseMap(mapIndex); } return(newMap); }
/// <inheritdoc /> /// <summary> /// </summary> /// <param name="gameTime"></param> protected override void HandleInput(GameTime gameTime) { if (KeyboardManager.IsUniqueKeyPress(Microsoft.Xna.Framework.Input.Keys.PageUp)) { ConfigManager.EditorScrollSpeedKeys.Value++; } if (KeyboardManager.IsUniqueKeyPress(Microsoft.Xna.Framework.Input.Keys.PageDown)) { ConfigManager.EditorScrollSpeedKeys.Value--; } if (KeyboardManager.IsUniqueKeyPress(Microsoft.Xna.Framework.Input.Keys.Delete)) { DeleteSelectedHitObjects(); } // Clever way of handing key input with num keys since the enum values are 1 after each other. for (var i = 0; i < WorkingMap.GetKeyCount(); i++) { if (KeyboardManager.IsUniqueKeyPress(Microsoft.Xna.Framework.Input.Keys.D1 + i)) { PlaceObject(CompositionInputDevice.Keyboard, i + 1, AudioEngine.Track.Time); } } // Change between composition tools (only when shift isn't held down). // if shift is held down, then it'll change the beat snap. if (KeyboardManager.CurrentState.IsKeyUp(Microsoft.Xna.Framework.Input.Keys.LeftShift) && KeyboardManager.CurrentState.IsKeyUp(Microsoft.Xna.Framework.Input.Keys.RightShift)) { var index = (int)CompositionTool.Value; if (KeyboardManager.IsUniqueKeyPress(Microsoft.Xna.Framework.Input.Keys.Up)) { if (index - 1 >= 0) { CompositionTool.Value = (EditorCompositionTool)index - 1; } } if (KeyboardManager.IsUniqueKeyPress(Microsoft.Xna.Framework.Input.Keys.Down)) { if (index + 1 < Enum.GetNames(typeof(EditorCompositionTool)).Length) { CompositionTool.Value = (EditorCompositionTool)index + 1; } } SwitchGraphs(); } // Select all if (KeyboardManager.CurrentState.IsKeyDown(Microsoft.Xna.Framework.Input.Keys.LeftControl) || KeyboardManager.CurrentState.IsKeyDown(Microsoft.Xna.Framework.Input.Keys.RightControl)) { if (KeyboardManager.IsUniqueKeyPress(Microsoft.Xna.Framework.Input.Keys.A)) { SelectAllHitObjects(); } if (KeyboardManager.IsUniqueKeyPress(Microsoft.Xna.Framework.Input.Keys.C)) { CopySelectedHitObjects(); } if (KeyboardManager.IsUniqueKeyPress(Microsoft.Xna.Framework.Input.Keys.V)) { PasteHitObjects(); } if (KeyboardManager.IsUniqueKeyPress(Microsoft.Xna.Framework.Input.Keys.X)) { CutHitObjects(); } if (KeyboardManager.IsUniqueKeyPress(Microsoft.Xna.Framework.Input.Keys.H)) { FlipHitObjectsHorizontally(); } } HandleHitObjectSelection(); switch (CompositionTool.Value) { case EditorCompositionTool.Select: break; case EditorCompositionTool.Note: case EditorCompositionTool.LongNote: case EditorCompositionTool.Mine: HandleHitObjectMouseInput(); break; default: throw new ArgumentOutOfRangeException(); } // Right click/delete object. if (MouseManager.IsUniqueClick(MouseButton.Right) && !View.MenuBar.IsActive) { DeleteHoveredHitObject(); } }
/// <inheritdoc /> /// <summary> /// </summary> /// <returns></returns> public override UserClientStatus GetClientStatus() => new UserClientStatus(ClientStatus.Editing, -1, "", (byte)GameMode.Keys4, WorkingMap.ToString(), 0);
public JsonResult InitMap(int sizePlaingFaild) { WorkingMap.InitMap(sizePlaingFaild); return(new JsonResult("")); }
public void EditCell(int x, int y, GameObject cellClicked) // Place data into cell button { Debug.Log("Coords:" + x + "," + y + " SelectedTool: " + SelectedTool); Cell thisCell = WorkingMap.GetCell(x, y); switch (SelectedTool) // Special considerations for certain objects { case ToolTypes.Player: if (WorkingMap.PlayerSpawnCoordinate[1] < cellButtons.GetLength(1) && WorkingMap.PlayerSpawnCoordinate[0] < cellButtons.GetLength(0) && WorkingMap.PlayerSpawnCoordinate[0] >= 0 && WorkingMap.PlayerSpawnCoordinate[0] >= 0) { // Remove old spawn point GameObject oldSpawn = cellButtons[WorkingMap.PlayerSpawnCoordinate[0], WorkingMap.PlayerSpawnCoordinate[1]]; oldSpawn.GetComponent <Image>().color = groundColour; } if (WorkingMap.PlayerSpawn != thisCell) { if (WorkingMap.PlayerSpawn != null) { WorkingMap.PlayerSpawn.ObjectType = ObjectTypes.Ground; // Replacing old spawn points with ground } WorkingMap.PlayerSpawn = thisCell; WorkingMap.PlayerSpawnCoordinate = new int[] { x, y }; thisCell.ObjectType = ObjectTypes.Player; } cellClicked.transform.GetChild(1).gameObject.SetActive(false); cellClicked.GetComponent <Image>().color = playerColour; // Change button image display break; case ToolTypes.Enemy: if (thisCell.ObjectType == ObjectTypes.Enemy) { return; } thisCell.ObjectType = ObjectTypes.Enemy; cellClicked.transform.GetChild(1).gameObject.SetActive(true); cellClicked.GetComponent <Image>().color = enemyColour; // Set up special and colour break; case ToolTypes.Gate: cellClicked.transform.GetChild(1).gameObject.SetActive(true); if (thisCell.ObjectType == ObjectTypes.Gate) { return; } thisCell.ObjectType = ObjectTypes.Gate; cellClicked.GetComponent <Image>().color = gateColour; cellClicked.transform.GetChild(1).gameObject.SetActive(true); // Set up color break; case ToolTypes.Trigger: if (thisCell.ObjectType == ObjectTypes.Trigger) { return; } thisCell.ObjectType = ObjectTypes.Trigger; cellClicked.transform.GetChild(1).gameObject.SetActive(false); cellClicked.GetComponent <Image>().color = triggerColour; // Set up link and colour break; case ToolTypes.Ground: if (thisCell.ObjectType == ObjectTypes.Ground) { return; } thisCell.ObjectType = ObjectTypes.Ground; cellClicked.transform.GetChild(1).gameObject.SetActive(false); cellClicked.GetComponent <Image>().color = groundColour; // Ground with no object on it. break; case ToolTypes.End: if (WorkingMap.EndCellCoordinate[1] < cellButtons.GetLength(1) && WorkingMap.EndCellCoordinate[0] < cellButtons.GetLength(0) && WorkingMap.EndCellCoordinate[0] >= 0 && WorkingMap.EndCellCoordinate[0] >= 0) { // Remove old end point GameObject oldEnd = cellButtons[WorkingMap.EndCellCoordinate[0], WorkingMap.EndCellCoordinate[1]]; oldEnd.GetComponent <Image>().color = groundColour; } if (WorkingMap.EndCell != thisCell) { if (WorkingMap.EndCell != null) { WorkingMap.EndCell.ObjectType = ObjectTypes.Ground; // Replace old end point with ground } WorkingMap.EndCell = thisCell; WorkingMap.EndCellCoordinate = new int[] { x, y }; } thisCell.ObjectType = ObjectTypes.End; cellClicked.transform.GetChild(1).gameObject.SetActive(false); cellClicked.GetComponent <Image>().color = endColour; // Ground with no object on it. break; case ToolTypes.Void: if (thisCell.ObjectType == ObjectTypes.Void) { return; } thisCell.ObjectType = ObjectTypes.Void; cellClicked.transform.GetChild(1).gameObject.SetActive(false); cellClicked.GetComponent <Image>().color = Color.white; // Clear button and cell on map break; case ToolTypes.Edit: if (thisCell.ObjectType != ObjectTypes.Enemy && thisCell.ObjectType != ObjectTypes.Gate && thisCell.ObjectType != ObjectTypes.Trigger) { return; } //editDialog.SetActive(true); // TODO: Edit tool - colour return; case ToolTypes.Link: if (thisCell.ObjectType != ObjectTypes.Trigger) { return; } linkSource = new int[] { x, y }; ChangeTool(ToolTypes.Linking); // Set to link destination selection state return; case ToolTypes.Linking: if (linkSource[0] != -1 && linkSource[1] != -1 && !(linkSource[0] == x && linkSource[1] == y)) { if (thisCell.ObjectType != ObjectTypes.Gate) { Debug.Log("Link destination is not a gate"); return; } // check if link already exists (listStorage.Contains() does not match arrays properly) int[] newLink = new int[] { x, y, linkSource[0], linkSource[1] }; Text sourceText = cellButtons[linkSource[0], linkSource[1]].transform.GetChild(0).GetComponent <Text>(); Text destinationText = cellButtons[x, y].transform.GetChild(0).GetComponent <Text>(); // Cell link thisCell.Link.Add(linkSource.Clone() as int[]); WorkingMap.GetCell(linkSource).Link.Add(new int[2] { x, y }); int linkIndex = -1; foreach (int[] linked in linkStorage) { if (linked[0] == newLink[0] && linked[1] == newLink[1] && linked[2] == newLink[2] && linked[3] == newLink[3]) { Debug.Log("Link already exists. Removing link"); RemoveLink(linked); ChangeTool(ToolTypes.Link); // Reset tool to link return; } } // Destination cell link display linkStorage.Add(newLink); linkIndex = linkStorage.IndexOf(newLink, 0); if (destinationText.text != "") { destinationText.text += ", "; } destinationText.text += linkIndex.ToString(); // Source cell link display if (sourceText.text != "") { sourceText.text += ", "; } sourceText.text += linkIndex.ToString(); ChangeTool(ToolTypes.Link); // Set tool to original state return; } return; case ToolTypes.Rotate: if (thisCell.ObjectType != ObjectTypes.Enemy && thisCell.ObjectType != ObjectTypes.Gate && thisCell.ObjectType != ObjectTypes.Player) { Debug.Log("RotateTool: incorrect type"); return; } thisCell.Direction += 1; // Rotate clockwise if (thisCell.Direction > 3) { thisCell.Direction = 0; // Wrap around to 0 } cellClicked.transform.GetChild(1).gameObject.SetActive(true); cellClicked.transform.GetChild(1).rotation = Quaternion.Euler(0, 0, 45 - (thisCell.Direction * 90)); // Rotate button image // Rotate tool - only for certain objects return; default: Debug.Log("EditCell: reached default case"); return; } List <int[]> linkRemoval = new List <int[]>(); foreach (int[] linked in linkStorage) // Get all links to current cell { if ((linked[0] == x && linked[1] == y) || (linked[2] == x && linked[3] == y)) { linkRemoval.Add(linked); } } foreach (int[] linked in linkRemoval) // Remove all links to current cell { RemoveLink(linked); } thisCell.Direction = 0; thisCell.Link.Clear(); // Need to remove possible links to this object thisCell.Special = null; }