Beispiel #1
0
        /// <summary>
        /// Finds the object end before and the object start after the break period.
        /// </summary>
        internal bool FindActualEnds(EventBreak b, out int actualStart, out int actualEnd)
        {
            HitObject prevObj, nextObj;

            int indexAfter  = hitObjectManager.BreakObjectAfter(b);
            int indexBefore = indexAfter - 1;

            prevObj = hitObjectManager.GetObject(indexBefore);

            //Get any object that may be extruding past start time
            int tempIndex;

            if (prevObj != null)
            {
                tempIndex = hitObjectManager.FindMaxOverlappedObject(Math.Min(prevObj.EndTime, b.StartTime), indexAfter);
            }
            else
            {
                tempIndex = hitObjectManager.FindMaxOverlappedObject(b.StartTime, indexAfter);
            }

            if (tempIndex >= 0)
            {
                indexBefore = tempIndex;
            }

            prevObj = hitObjectManager.GetObject(indexBefore);
            nextObj = hitObjectManager.GetObject(indexAfter);

            actualStart = getActualStart(prevObj);
            actualEnd   = getActualEnd(nextObj);

            return(actualStart >= 0 && actualEnd >= 0);
        }
Beispiel #2
0
        /// <remarks>See EventBreak.Update() for params.</remarks>
        internal void UpdateBreaks(bool updateOrder, bool findCustom, bool useMinimum = false, bool backup = true)
        {
            if (!BreakDirty)
            {
                return;
            }

            if (backup)
            {
                changeManager.BeginAction(ChangeType.Event);
                changeManager.PushAction(ActionType.MoveTimeline, Modifier.MoveBoth | Modifier.VariableChanges);
            }

            if (hitObjectManager.hitObjectsCount > 1)
            {
                //List can be modified inside Update call. Keep as for loop.
                for (int i = 0; i < eventManager.eventBreaks.Count; i++)
                {
                    EventBreak br = eventManager.eventBreaks[i];
                    if (!br.Update(updateOrder, findCustom, useMinimum, backup))
                    {
                        i--;
                    }
                }

                if (CheckInvalidBreaks)
                {
                    RemoveInvalidBreaks(backup);
                }

                fillLargeGaps(backup);
            }
            else if (eventManager.eventBreaks.Count > 0) //There needs to be at least 2 hitcircles to have a break time.
            {
                if (backup)
                {
                    changeManager.PushAction(ActionType.Remove);
                    changeManager.BackupData(eventManager.eventBreaks);
                }
                eventManager.RemoveAllBreaks();
            }

            //Set variables back to default
            BreakDirty         = false;
            UseMinimumLength   = false;
            CheckInvalidBreaks = false;

            if (!backup)
            {
                return;
            }

            if (FinishOnBreakUpdate)
            {
                FinishOnBreakUpdate = false;
                changeManager.FinishAction();
            }
        }
Beispiel #3
0
        internal void RemoveBreak(EventBreak b, bool backup = true)
        {
            if (backup)
            {
                changeManager.BeginAction(ChangeType.Event, ActionType.Remove, b);
            }

            eventManager.Remove(b);
        }
Beispiel #4
0
        internal void InsertBreak(EventBreak b, bool backup = true)
        {
            if (b.Length < EventBreak.MIN_BREAK_LENGTH)
            {
                return;
            }

            if (backup)
            {
                changeManager.BeginAction(ChangeType.Event, ActionType.Add, b);
            }

            eventManager.Add(b);
        }
Beispiel #5
0
        internal void InsertBreak(int time, bool alertOnFail, bool backup = true)
        {
            bool found;
            int  index = hitObjectManager.FindObjectNear(time, out found);

            //Object does not occupy space and is surrounded by objects
            if (!found && index > 0 && index < hitObjectManager.hitObjectsCount)
            {
                int startTime = hitObjectManager.GetObject(index - 1).EndTime;
                int endTime   = hitObjectManager.GetObject(index).StartTime;

                int tempIndex = hitObjectManager.FindMaxOverlappedObject(startTime, index);
                if (tempIndex >= 0)
                {
                    startTime = hitObjectManager.GetObject(tempIndex).EndTime;
                }

                if (startTime < time && endTime > time)
                {
                    bool breakFound = false;
                    //Space is large enough to contain a break and doesn't contain a break.
                    if (IsValidBreakLengthMax(startTime, endTime) && !(breakFound = FindBreakWithin(startTime, endTime) != null))
                    {
                        EventBreak b = new EventBreak(startTime, endTime, false);
                        if (b.Length >= EventBreak.MIN_BREAK_LENGTH)
                        {
                            InsertBreak(b, backup);
                            return;
                        }
                    }

                    if (breakFound)
                    {
                        return;
                    }
                }
            }

            if (alertOnFail)
            {
                NotificationManager.ShowMessageMassive(
                    LocalisationManager.GetString(OsuString.EditorModeCompose_NotEnoughRoomMessage),
                    3000);
            }
        }
        /// <summary>
        /// Is the local user active at [time]
        /// </summary>
        private bool isLocalUserActiveAt(int time)
        {
            if (EventManager.BreakMode || player.Passed || Player.Failed || player.Status != PlayerStatus.Playing)
            {
                return(true);
            }

            if (AudioEngine.Time >
                player.hitObjectManager.hitObjects[player.hitObjectManager.hitObjectsCount - 1].EndTime)
            {
                return(true);
            }

            EventBreak br = localUserActiveTime.Find(b => b.StartTime <= time && b.EndTime >= time);

            if (br == null)
            {
                return(false);
            }

            return(player.hitObjectManager.hitObjectsMinimal.FindIndex(
                       ho => (ho.TagNumeric == player.localPlayerMatchId || ho.TagNumeric == -2) &&
                       ho.EndTime <= br.EndTime + player.hitObjectManager.HitWindow50 && !ho.IsHit) >= 0);
        }
Beispiel #7
0
        /// <summary>
        /// Checks that the break bounds can fit within the actual space surrounding the break including preempt time.
        /// </summary>
        /// <param name="useNoBreakLength">if true compares break length with maximum allowed non break time</param>
        /// <returns>Actual break bounds are valid and exceeds a maximum break limit</returns>
        internal bool IsValidBreakLength(EventBreak b, bool useNoBreakLength = false)
        {
            if (b == null)
            {
                return(false);
            }

            if (b.Length < EventBreak.MIN_BREAK_LENGTH)
            {
                return(false);
            }

            int bStart, bEnd;

            FindActualEnds(b, out bStart, out bEnd);

            //Actual ends don't exist or preempt space is too small.
            if (bStart < 0 || bEnd < 0 || b.StartTime - bStart < EventBreak.PREEMPT_START || bEnd - b.EndTime < hitObjectManager.PreEmpt)
            {
                return(false);
            }

            return(IsValidBreakLengthMax(bStart, bEnd, useNoBreakLength));
        }
        /// <summary>
        /// Handle splitting up and labelling the hitObjects into different player's scopes.
        /// </summary>
        internal override void InitializeHitObjectPostProcessing()
        {
            bMatch match = PlayerVs.Match;

            usedPlayerSlots = new List <int>();

            int playerCount = 0;

            for (int i = 0; i < bMatch.MAX_PLAYERS; i++)
            {
                if ((match.slotStatus[i] & SlotStatus.Playing) > 0 &&
                    match.slotTeam[i] == match.slotTeam[player.localPlayerMatchId])
                {
                    usedPlayerSlots.Add(i);
                    playerCount++;
                }
            }

            HitObjectManager hitObjectManager = player.hitObjectManager;

            int currentPlayer = -1;

            localUserActiveTime = new List <EventBreak>();

            EventBreak currentBreak = null;

            bool firstCombo = true;
            bool customTagColor;

            if (customTagColor = MatchSetup.TagComboColour != Color.TransparentWhite)
            {
                GameBase.Scheduler.Add(delegate
                {
                    SkinManager.SliderRenderer.Tag = MatchSetup.TagComboColour;
                });
            }

            for (int i = 0; i < hitObjectManager.hitObjectsCount; i++)
            {
                HitObject h = hitObjectManager.hitObjects[i];
                //HitObject hLast = i > 0 ? hitObjectManager.hitObjects[i-1] : hitObjectManager.hitObjects[i];

                bool firstInCombo = h.NewCombo || firstCombo;

                bool spinner = h.IsType(HitObjectType.Spinner) || h is HitCircleFruitsSpin;

                if (firstInCombo)
                {
                    if (!spinner)
                    {
                        currentPlayer = (currentPlayer + 1) % playerCount;
                        firstCombo    = false;
                    }

                    if (spinner || usedPlayerSlots[currentPlayer] == player.localPlayerMatchId)
                    {
                        //The local player starts playing at this point.
                        int st = (i > 0
                                      ? Math.Max(h.StartTime - hitObjectManager.HitWindow50,
                                                 hitObjectManager.hitObjects[i - 1].EndTime + 1)
                                      : h.StartTime - hitObjectManager.HitWindow50);
                        int ed = h.EndTime;
                        currentBreak = new EventBreak(st, ed);
                        localUserActiveTime.Add(currentBreak);
                    }
                    else
                    {
                        //Another play has taken over.
                        currentBreak = null;
                    }
                }


                if (spinner || usedPlayerSlots[currentPlayer] == player.localPlayerMatchId)
                {
                    if (currentBreak != null)
                    {
                        //The local player finishes playing at this point (or further).
                        currentBreak.SetEndTime(h.EndTime + hitObjectManager.HitWindow50);
                    }

                    if (customTagColor)
                    {
                        h.SetColour(MatchSetup.TagComboColour);
                    }
                }
                else
                {
                    h.IsScorable = false;
                    h.SetColour(Color.Gray);
                }

                h.TagNumeric = spinner ? -2 : usedPlayerSlots[currentPlayer];
            }

            InitializeWarningArrows();
        }
Beispiel #9
0
        /// <summary>
        /// Validates and handles break drag changes.
        /// </summary>
        /// <param name="dragBreakEnd">Determines whether breakEnd or breakStart is being dragged.</param>
        /// <param name="newTime">The new time to apply to the current break end (or start)</param>
        /// <returns>Whether break has been changed or removed.</returns>
        internal bool UpdateBreakDrag(EventBreak b, bool dragBreakEnd, int newTime)
        {
            if (!BreakDirty || b == null)
            {
                return(false);
            }

            int actualStart, actualEnd;

            BreakDirty = false;
            if (dragBreakEnd)
            {
                int newEnd = newTime;
                int oldEnd = b.EndTime;

                if (newEnd == oldEnd)
                {
                    return(false);
                }

                if (newEnd < oldEnd) //Break is being dragged to the left
                {
                    if (FindActualEnds(b, out actualStart, out actualEnd))
                    {
                        int preEmptStart = actualStart + EventBreak.PREEMPT_START;

                        newEnd = Math.Max(newEnd, preEmptStart + EventBreak.PREFERRED_BREAK_LENGTH);

                        //Value exceeds allowed custom break distance.
                        if (newEnd < MaxBreakDragDistance)
                        {
                            return(false);
                        }

                        b.SetEndTime(newEnd);
                    }
                    else //This should never happen
                    {
                        RemoveBreak(b);
                        return(true);
                    }
                }
                else
                {
                    //We cannot drag past the preempt point
                    if (!b.CustomEnd)
                    {
                        return(false);
                    }

                    if (FindActualEnds(b, out actualStart, out actualEnd))
                    {
                        int preEmptEnd = actualEnd - hitObjectManager.PreEmpt;

                        newEnd = Math.Min(newEnd, preEmptEnd);
                        b.SetEndTime(newEnd);
                    }
                    else //This should never happen
                    {
                        RemoveBreak(b);
                        return(true);
                    }
                }
            }
            else
            {
                int oldStart = b.StartTime;
                int newStart = newTime;

                if (newStart == oldStart)
                {
                    return(false);
                }

                if (newStart < oldStart)
                {
                    //We cannot drag past the preempt point
                    if (!b.CustomStart)
                    {
                        return(false);
                    }

                    if (FindActualEnds(b, out actualStart, out actualEnd))
                    {
                        int preEmptStart = actualStart + EventBreak.PREEMPT_START;

                        newStart = Math.Max(newStart, preEmptStart);
                        b.SetStartTime(newStart);
                    }
                    else //This should never happen
                    {
                        RemoveBreak(b);
                        return(true);
                    }
                }
                else
                {
                    if (FindActualEnds(b, out actualStart, out actualEnd))
                    {
                        int preEmptEnd = actualEnd - hitObjectManager.PreEmpt;

                        newStart = Math.Min(newStart, preEmptEnd - EventBreak.PREFERRED_BREAK_LENGTH);

                        //Value exceeds allowed custom break distance.
                        if (newStart > MaxBreakDragDistance)
                        {
                            return(false);
                        }

                        b.SetStartTime(newStart);
                    }
                    else //This should never happen
                    {
                        RemoveBreak(b);
                        return(true);
                    }
                }
            }

            b.Update(!dragBreakEnd, true, true, false);
            return(true);
        }
Beispiel #10
0
        internal override void ChangeState(State undoState)
        {
            if (HasModifier(Modifier.VariableChanges))
            {
                if (HasModifier(Modifier.MoveBoth))
                {
                    bool isBreak = ((Event)changedObjects[0]).Type == EventTypes.Break;
                    int  index   = 0;
                    foreach (Event e in changedObjects)
                    {
                        ListHelper.Swap(startOffsets, index, ref e.StartTime);
                        ListHelper.Swap(endOffsets, index, ref e.EndTime);

                        if (isBreak)
                        {
                            EventBreak br = (EventBreak)e;
                            ListHelper.Swap(customStarts, index, ref br.CustomStart);
                            ListHelper.Swap(customEnds, index, ref br.CustomEnd);
                        }

                        index++;
                    }
                }
                else if (HasModifier(Modifier.MoveStart))
                {
                    bool isBreak = ((Event)changedObjects[0]).Type == EventTypes.Break;
                    int  index   = 0;
                    foreach (Event e in changedObjects)
                    {
                        ListHelper.Swap(startOffsets, index, ref e.StartTime);

                        if (isBreak)
                        {
                            EventBreak br = (EventBreak)e;
                            ListHelper.Swap(customStarts, index, ref br.CustomStart);
                        }

                        index++;
                    }
                }
                else
                {
                    bool isBreak = ((Event)changedObjects[0]).Type == EventTypes.Break;
                    int  index   = 0;
                    foreach (Event e in changedObjects)
                    {
                        ListHelper.Swap(endOffsets, index, ref e.EndTime);

                        if (isBreak)
                        {
                            EventBreak br = (EventBreak)e;
                            ListHelper.Swap(customEnds, index, ref br.CustomEnd);
                        }

                        index++;
                    }
                }
            }
            else
            {
                if (HasModifier(Modifier.None) || HasModifier(Modifier.MoveStart))
                {
                    Event e = (Event)changedObjects[0];

                    int offsetChange = e.StartTime - startOffset;
                    startOffset = e.StartTime;

                    foreach (Event e1 in changedObjects)
                    {
                        e1.StartTime -= offsetChange;
                    }
                }
                else if (HasModifier(Modifier.MoveBoth))
                {
                    Event e = (Event)changedObjects[0];

                    int offsetChange = e.StartTime - startOffset;
                    startOffset = e.StartTime;
                    endOffset   = e.EndTime;

                    foreach (Event e1 in changedObjects)
                    {
                        if (e1 is EventSample || e1 is EventSprite || e1 is EventAnimation || e1 is EventVideo)
                        {
                            e1.StartTime -= offsetChange;
                            e1.EndTime   -= offsetChange;
                            if (e1.Sprite != null)
                            {
                                foreach (Transformation t in e1.Sprite.Transformations)
                                {
                                    t.Time1 -= offsetChange;
                                    t.Time2 -= offsetChange;
                                }

                                if (e1.Sprite.Loops != null)
                                {
                                    foreach (TransformationLoop tl in e1.Sprite.Loops)
                                    {
                                        tl.StartTime -= offsetChange;
                                    }
                                }
                            }

                            foreach (List <TriggerLoop> ll in e1.EventLoopTriggers.Values)
                            {
                                foreach (TriggerLoop l in ll)
                                {
                                    l.StartTime        -= offsetChange;
                                    l.TriggerStartTime -= offsetChange;
                                    l.TriggerEndTime   -= offsetChange;
                                }
                            }
                        }
                    }
                }
            }
        }
Beispiel #11
0
        protected override void PostProcessing()
        {
            isPost = true;

            Beatmap.StackLeniency = 0;

            double  t            = firstObjectTime;
            int     i            = 0;
            Vector2 lastPosition = new Vector2(256, 197);

            double speed = 0;
            double angle = targetRandom.NextDouble() * Math.PI * 2;

            while (t < lastObjectTime)
            {
                double progress = (t - firstObjectTime) / (lastObjectTime - firstObjectTime);

                bool speedIncrease = i % 8 == 0;

                if (lastComboIndex < comboTimes.Count && t >= comboTimes[lastComboIndex])
                {
                    lastComboIndex++;
                }

                if (speedIncrease)
                {
                    speed = HitObjectRadius + (int)(progress * 40) / 40d * 333;
                }

                Vector2 movement;

                ControlPoint cp = Beatmap.ControlPointAt(t);

                double multiplier = cp.KiaiMode ? 1.2 : 1;

                if (speedIncrease)
                {
                    multiplier *= 1.5;
                }

                angle += (targetRandom.NextDouble() - 0.5) * 2;

                movement.X = lastPosition.X + (float)(speed * multiplier * Math.Cos(angle));
                movement.Y = lastPosition.Y + (float)(speed * multiplier * Math.Sin(angle));

                int tryCount = 0;
                while (movement.X < 0 || movement.Y < 0 || movement.X > 512 || movement.Y > 384 || (speed > HitObjectRadius && closeToRecent(movement, tryCount)))
                {
                    angle      = targetRandom.NextDouble() * Math.PI * 2;
                    movement.X = lastPosition.X + (float)(speed * multiplier * Math.Cos(angle));
                    movement.Y = lastPosition.Y + (float)(speed * multiplier * Math.Sin(angle));

                    if (++tryCount > 10)
                    {
                        multiplier *= 0.9;
                    }
                }

                lastPosition = movement;

                HitCircleOsuTarget h = new HitCircleOsuTarget(this, lastPosition + new Vector2(0, -10), (int)t, speedIncrease, HitObjectSoundType.Normal, 0);

                EventBreak b = eventManager.eventBreaks.Find(br => br.StartTime <= t && br.EndTime >= t);
                if (b == null)
                {
                    int found = intendedObjects.BinarySearch(h);
                    if (found < 0)
                    {
                        found = ~found - 1;
                    }

                    if (found >= 0 && found > lastUsedIntended && found < intendedObjects.Count)
                    {
                        lastUsedIntended = found;
                        HitObject closest = intendedObjects[found];
                        h.SampleSet          = closest.SampleSet;
                        h.SampleSetAdditions = closest.SampleSetAdditions;
                        h.SoundType          = closest.SoundType;
                        h.CustomSampleSet    = closest.CustomSampleSet;
                    }

                    foreach (pSprite p in h.SpriteCollection)
                    {
                        //physics.Add(p, new Vector2((float)(progress * (GameBase.random.NextDouble() - 0.5)), 0), true).weight = -100;
                        p.Transformations.Add(new Transformation(TransformationType.Scale, p.Scale * 0.5f, p.Scale, (int)t - PreEmpt, (int)t));
                    }
                    AddCircle(h);
                }

                i++;
                t += Beatmap.BeatLengthAt(t, false);
            }

            Sort(false);

            base.PostProcessing();
        }