void FSequencerTimeSliderController::SetViewRange( float NewRangeMin, float NewRangeMax, EViewRangeInterpolation Interpolation )
{
	TOptional<float> LocalClampMin = TimeSliderArgs.ClampMin.Get();
	TOptional<float> LocalClampMax = TimeSliderArgs.ClampMax.Get();

	// Clamp the range if clamp values are set
	if ( LocalClampMin.IsSet() && NewRangeMin < LocalClampMin.GetValue() )
	{
		NewRangeMin = LocalClampMin.GetValue();
	}
	
	if ( LocalClampMax.IsSet() && NewRangeMax > LocalClampMax.GetValue() )
	{
		NewRangeMax = LocalClampMax.GetValue();
	}

	const TRange<float> NewRange(NewRangeMin, NewRangeMax);

	TimeSliderArgs.OnViewRangeChanged.ExecuteIfBound( NewRange, Interpolation );

	if( !TimeSliderArgs.ViewRange.IsBound() )
	{	
		// The  output is not bound to a delegate so we'll manage the value ourselves (no animation)
		TimeSliderArgs.ViewRange.Set( NewRange );
	}
}
示例#2
0
void FVisualLoggerTimeSliderController::HorizontalScrollBar_OnUserScrolled(float ScrollOffset)
{
	if (!TimeSliderArgs.ViewRange.IsBound())
	{
		TRange<float> LocalViewRange = TimeSliderArgs.ViewRange.Get();
		float LocalViewRangeMin = LocalViewRange.GetLowerBoundValue();
		float LocalViewRangeMax = LocalViewRange.GetUpperBoundValue();
		TOptional<float> LocalClampMin = TimeSliderArgs.ClampMin.Get();
		TOptional<float> LocalClampMax = TimeSliderArgs.ClampMax.Get();

		float InThumbSizeFraction = (LocalViewRangeMax - LocalViewRangeMin) / (LocalClampMax.GetValue() - LocalClampMin.GetValue());

		float NewViewOutputMin = LocalClampMin.GetValue() + ScrollOffset * (LocalClampMax.GetValue() - LocalClampMin.GetValue());
		// The  output is not bound to a delegate so we'll manage the value ourselves
		float NewViewOutputMax = FMath::Min<float>(NewViewOutputMin + (LocalViewRangeMax - LocalViewRangeMin), LocalClampMax.GetValue());
		NewViewOutputMin = NewViewOutputMax - (LocalViewRangeMax - LocalViewRangeMin);

		float InOffsetFraction = (NewViewOutputMin - LocalClampMin.GetValue()) / (LocalClampMax.GetValue() - LocalClampMin.GetValue());
		//if (InOffsetFraction + InThumbSizeFraction <= 1)
		{
			TimeSliderArgs.ViewRange.Set(TRange<float>(NewViewOutputMin, NewViewOutputMax));
			Scrollbar->SetState(InOffsetFraction, InThumbSizeFraction);
		}
	}
}
/** Parse anything until we find an unescaped { */
TOptional<FExpressionError> ParseLiteral(FExpressionTokenConsumer& Consumer, bool bEmitErrors)
{
	// Include a leading { character - if it was a valid argument token it would have been picked up by a previous token definition
	bool bFirstChar = true;
	TOptional<FStringToken> Token = Consumer.GetStream().ParseToken([&](TCHAR C){
		if (C == '{' && !bFirstChar)
		{
			return EParseState::StopBefore;
		}
		else if (C == EscapeChar)
		{
			return EParseState::StopBefore;
		}
		else
		{
			bFirstChar = false;
			// Keep consuming
			return EParseState::Continue;
		}
	});

	if (Token.IsSet())
	{
		// Add the token to the consumer. This moves the read position in the stream to the end of the token.
		Consumer.Add(Token.GetValue(), FStringLiteral(Token.GetValue()));
	}
	return TOptional<FExpressionError>();
}
示例#4
0
bool UBlendSpaceBase::IsValidAdditiveInternal(EAdditiveAnimationType AdditiveType) const
{
    TOptional<bool> bIsAdditive;

    for (int32 I=0; I<SampleData.Num(); ++I)
    {
        const UAnimSequence* Animation = SampleData[I].Animation;

        // test animation to see if it matched additive type
        bool bAdditiveAnim = ( Animation && Animation->IsValidAdditive() && Animation->AdditiveAnimType == AdditiveType );

        // if already has value, but it does not match
        if ( bIsAdditive.IsSet() )
        {
            // it's inconsistent, we ignore this
            if (bIsAdditive.GetValue() != bAdditiveAnim)
            {
                return false;
            }
        }
        else
        {
            bIsAdditive = TOptional<bool>(bAdditiveAnim);
        }
    }

    return (bIsAdditive.IsSet() && bIsAdditive.GetValue());
}
void FWidgetNavigationCustomization::SetNav(UWidget* Widget, EUINavigation Nav, TOptional<EUINavigationRule> Rule, TOptional<FName> WidgetToFocus)
{
	Widget->Modify();

	UWidgetNavigation* WidgetNavigation = Widget->Navigation;
	if (!Widget->Navigation)
	{
		WidgetNavigation = NewObject<UWidgetNavigation>(Widget);
	}

	FWidgetNavigationData* DirectionNavigation = nullptr;

	switch ( Nav )
	{
	case EUINavigation::Left:
		DirectionNavigation = &WidgetNavigation->Left;
		break;
	case EUINavigation::Right:
		DirectionNavigation = &WidgetNavigation->Right;
		break;
	case EUINavigation::Up:
		DirectionNavigation = &WidgetNavigation->Up;
		break;
	case EUINavigation::Down:
		DirectionNavigation = &WidgetNavigation->Down;
		break;
	case EUINavigation::Next:
		DirectionNavigation = &WidgetNavigation->Next;
		break;
	case EUINavigation::Previous:
		DirectionNavigation = &WidgetNavigation->Previous;
		break;
	default:
		// Should not be possible.
		check(false);
		return;
	}

	if ( Rule.IsSet() )
	{
		DirectionNavigation->Rule = Rule.GetValue();
	}

	if ( WidgetToFocus.IsSet() )
	{
		DirectionNavigation->WidgetToFocus = WidgetToFocus.GetValue();
	}

	if ( WidgetNavigation->IsDefault() )
	{
		// If the navigation rules are all set to the defaults, remove the navigation
		// information from the widget.
		Widget->Navigation = nullptr;
	}
	else
	{
		Widget->Navigation = WidgetNavigation;
	}
}
示例#6
0
void FVisualLoggerTimeSliderController::SetTimeRange(float NewViewOutputMin, float NewViewOutputMax)
{
	TimeSliderArgs.ViewRange.Set(TRange<float>(NewViewOutputMin, NewViewOutputMax));

	TOptional<float> LocalClampMin = TimeSliderArgs.ClampMin.Get();
	TOptional<float> LocalClampMax = TimeSliderArgs.ClampMax.Get();

	const float InOffsetFraction = (NewViewOutputMin - LocalClampMin.GetValue()) / (LocalClampMax.GetValue() - LocalClampMin.GetValue());
	const float InThumbSizeFraction = (NewViewOutputMax - NewViewOutputMin) / (LocalClampMax.GetValue() - LocalClampMin.GetValue());
	Scrollbar->SetState(InOffsetFraction, InThumbSizeFraction);
}
	/** Consume a number from the specified consumer's stream, if one exists at the current read position */
	TOptional<FExpressionError> ConsumeNumber(FExpressionTokenConsumer& Consumer)
	{
		auto& Stream = Consumer.GetStream();

		TOptional<FStringToken> NumberToken = ExpressionParser::ParseNumber(Stream);
		
		if (NumberToken.IsSet())
		{
			Consumer.Add(NumberToken.GetValue(), FExpressionNode(FTextToken(NumberToken.GetValue().GetString(), ETextFilterTextComparisonMode::Partial, FTextToken::EInvertResult::No)));
		}

		return TOptional<FExpressionError>();
	}
示例#8
0
void FCameraDetails::UpdateAspectTextFromProperty()
{
	// Called whenever the actual aspect ratio property changes - clears the text box if the value no longer matches the current text
	TOptional<float> Value = GetAspectRatio();
	if (!Value.IsSet() || Value.GetValue() < LastParsedAspectRatioValue - DELTA || Value.GetValue() > LastParsedAspectRatioValue + DELTA)
	{
		LastParsedAspectRatioValue = -1.0f;
		if (!AspectTextBox->GetText().IsEmpty())
		{
			AspectTextBox->SetText(FText::GetEmpty());
		}
	}
}
bool LocalizationCommandletTasks::ImportTextForTargets(const TSharedRef<SWindow>& ParentWindow, const TArray<ULocalizationTarget*>& Targets, const TOptional<FString> DirectoryPath)
{
	TArray<LocalizationCommandletExecution::FTask> Tasks;

	for (ULocalizationTarget* Target : Targets)
	{
		const bool ShouldUseProjectFile = !Target->IsMemberOfEngineTargetSet();

		FFormatNamedArguments Arguments;
		Arguments.Add(TEXT("TargetName"), FText::FromString(Target->Settings.Name));

		const FText ImportTaskName = FText::Format(LOCTEXT("ImportTaskNameFormat", "Import Translations for {TargetName}"), Arguments);
		const FString ImportScriptPath = LocalizationConfigurationScript::GetImportTextConfigPath(Target, TOptional<FString>());
		const TOptional<FString> DirectoryPathForTarget = DirectoryPath.IsSet() ? DirectoryPath.GetValue() / Target->Settings.Name : TOptional<FString>();
		LocalizationConfigurationScript::GenerateImportTextConfigFile(Target, TOptional<FString>(), DirectoryPathForTarget).Write(ImportScriptPath);
		Tasks.Add(LocalizationCommandletExecution::FTask(ImportTaskName, ImportScriptPath, ShouldUseProjectFile));

		const FText ReportTaskName = FText::Format(LOCTEXT("ReportTaskNameFormat", "Generate Reports for {TargetName}"), Arguments);
		const FString ReportScriptPath = LocalizationConfigurationScript::GetWordCountReportConfigPath(Target);
		LocalizationConfigurationScript::GenerateWordCountReportConfigFile(Target).Write(ReportScriptPath);
		Tasks.Add(LocalizationCommandletExecution::FTask(ReportTaskName, ReportScriptPath, ShouldUseProjectFile));
	}

	return LocalizationCommandletExecution::Execute(ParentWindow, LOCTEXT("ImportForAllTargetsWindowTitle", "Import Translations for All Targets"), Tasks);
}
示例#10
0
FCursorReply SWidget::OnCursorQuery( const FGeometry& MyGeometry, const FPointerEvent& CursorEvent ) const
{
	TOptional<EMouseCursor::Type> TheCursor = Cursor.Get();
	return ( TheCursor.IsSet() )
		? FCursorReply::Cursor( TheCursor.GetValue() )
		: FCursorReply::Unhandled();
}
TOptional<FExpressionError> ParseEscapedChar(FExpressionTokenConsumer& Consumer)
{
	FTokenStream& Stream = Consumer.GetStream();

	TOptional<FStringToken> Token = Stream.ParseSymbol(EscapeChar);
	if (!Token.IsSet())
	{
		return TOptional<FExpressionError>();
	}

	FStringToken& TokenValue = Token.GetValue();

	// Accumulate the next character into the token
	TOptional<FStringToken> EscapedChar = Consumer.GetStream().ParseSymbol(&TokenValue);
	if (!EscapedChar.IsSet())
	{
		return TOptional<FExpressionError>();
	}

	// Check for a valid escape character
	const TCHAR Character = *EscapedChar->GetTokenStartPos();
	if (IsValidEscapeChar(Character))
	{
		// Add the token to the consumer - this moves the read position in the stream to the end of the token.
		Consumer.Add(TokenValue, FEscapedCharacter(Character));
	}

	return TOptional<FExpressionError>();
}
TOptional<FExpressionError> ParseLiteral(FExpressionTokenConsumer& Consumer)
{
	FTokenStream& Stream = Consumer.GetStream();

	TOptional<FStringToken> Token;
	{
		bool bFirstChar = true;
		Token = Stream.ParseToken([&](TCHAR C)
		{
			// Always include the first character, since if it was the start of a valid token then it would have been picked up by a higher priority token parser
			if (bFirstChar)
			{
				bFirstChar = false;
				return EParseState::Continue;
			}
			else if (!IsLiteralBreakChar(C))
			{
				return EParseState::Continue;
			}
			else
			{
				return EParseState::StopBefore;
			}
		});
	}

	if (Token.IsSet())
	{
		// Add the token to the consumer - this moves the read position in the stream to the end of the token
		FStringToken& TokenValue = Token.GetValue();
		Consumer.Add(TokenValue, FStringLiteral(TokenValue));
	}
	return TOptional<FExpressionError>();
}
FReply FSequencerTimeSliderController::OnMouseWheel( TSharedRef<SWidget> WidgetOwner, const FGeometry& MyGeometry, const FPointerEvent& MouseEvent )
{
	if ( TimeSliderArgs.AllowZoom )
	{
		const float ZoomDelta = -0.1f * MouseEvent.GetWheelDelta();

		{
			TRange<float> LocalViewRange = TimeSliderArgs.ViewRange.Get();
			float LocalViewRangeMax = LocalViewRange.GetUpperBoundValue();
			float LocalViewRangeMin = LocalViewRange.GetLowerBoundValue();
			const float OutputViewSize = LocalViewRangeMax - LocalViewRangeMin;
			const float OutputChange = OutputViewSize * ZoomDelta;

			float NewViewOutputMin = LocalViewRangeMin - (OutputChange * 0.5f);
			float NewViewOutputMax = LocalViewRangeMax + (OutputChange * 0.5f);

			if( FMath::Abs( OutputChange ) > 0.01f && NewViewOutputMin < NewViewOutputMax )
			{
				TOptional<float> LocalClampMin = TimeSliderArgs.ClampMin.Get();
				TOptional<float> LocalClampMax = TimeSliderArgs.ClampMax.Get();

				// Clamp the range if clamp values are set
				if ( LocalClampMin.IsSet() && NewViewOutputMin < LocalClampMin.GetValue() )
				{
					NewViewOutputMin = LocalClampMin.GetValue();
				}
				
				if ( LocalClampMax.IsSet() && NewViewOutputMax > LocalClampMax.GetValue() )
				{
					NewViewOutputMax = LocalClampMax.GetValue();
				}

				TimeSliderArgs.OnViewRangeChanged.ExecuteIfBound(TRange<float>(NewViewOutputMin, NewViewOutputMax));

				if( !TimeSliderArgs.ViewRange.IsBound() )
				{	
					// The  output is not bound to a delegate so we'll manage the value ourselves
					TimeSliderArgs.ViewRange.Set( TRange<float>( NewViewOutputMin, NewViewOutputMax ) );
				}
			}
		}

		return FReply::Handled();
	}

	return FReply::Unhandled();
}
TOptional<FVector4> FVectorPropertySection::GetPropertyValueAsVector4() const
{
	if (ChannelsUsed == 2)
	{
		TOptional<FVector2D> Vector = GetPropertyValue<FVector2D>();
		return Vector.IsSet() ? TOptional<FVector4>(FVector4(Vector.GetValue().X, Vector.GetValue().Y, 0, 0)) : TOptional<FVector4>();
	}
	else if (ChannelsUsed == 3)
	{
		TOptional<FVector> Vector = GetPropertyValue<FVector>();
		return Vector.IsSet() ? TOptional<FVector4>(FVector4(Vector.GetValue().X, Vector.GetValue().Y, Vector.GetValue().Z, 0)) : TOptional<FVector4>();
	}
	else // ChannelsUsed == 4
	{
		return GetPropertyValue<FVector4>();
	}
}
TOptional<FGuid> FActorReferencePropertySection::GetActorGuid() const
{
	TOptional<AActor*> CurrentActor = GetPropertyValue<AActor*>();
	if (CurrentActor.IsSet() && CurrentActor.GetValue() != nullptr)
	{
		return TOptional<FGuid>(GetSequencer()->GetFocusedMovieSceneSequenceInstance()->FindObjectId(*CurrentActor.GetValue()));
	}
	return TOptional<FGuid>(FGuid());
}
	LexResultType Lex(const TCHAR* InExpression, const FTokenDefinitions& TokenDefinitions)
	{
		FExpressionTokenConsumer TokenConsumer(InExpression);
		
		TOptional<FExpressionError> Error = TokenDefinitions.ConsumeTokens(TokenConsumer);
		if (Error.IsSet())
		{
			return MakeError(Error.GetValue());
		}

		return MakeValue(TokenConsumer.Extract());
	}
示例#17
0
EPopupMethod QueryPopupMethod(const FWidgetPath& PathToQuery)
{
	for (int32 WidgetIndex = PathToQuery.Widgets.Num() - 1; WidgetIndex >= 0; --WidgetIndex)
	{
		TOptional<EPopupMethod> PopupMethod = PathToQuery.Widgets[WidgetIndex].Widget->OnQueryPopupMethod();
		if (PopupMethod.IsSet())
		{
			return PopupMethod.GetValue();
		}
	}

	return EPopupMethod::CreateNewWindow;
}
/** Parse an escaped character */
TOptional<FExpressionError> ParseEscapedChar(FExpressionTokenConsumer& Consumer, bool bEmitErrors)
{
	static const TCHAR* ValidEscapeChars = TEXT("{`");

	TOptional<FStringToken> Token = Consumer.GetStream().ParseSymbol(EscapeChar);
	if (!Token.IsSet())
	{
		return TOptional<FExpressionError>();
	}

	// Accumulate the next character into the token
	TOptional<FStringToken> EscapedChar = Consumer.GetStream().ParseSymbol(&Token.GetValue());
	if (!EscapedChar.IsSet())
	{
		return TOptional<FExpressionError>();
	}

	// Check for a valid escape character
	const TCHAR Character = *EscapedChar->GetTokenStartPos();
	if (FCString::Strchr(ValidEscapeChars, Character))
	{
		// Add the token to the consumer. This moves the read position in the stream to the end of the token.
		Consumer.Add(Token.GetValue(), FEscapedCharacter(Character));
		return TOptional<FExpressionError>();
	}
	else if (bEmitErrors)
	{
		FString CharStr;
		CharStr += Character;
		FFormatOrderedArguments Args;
		Args.Add(FText::FromString(CharStr));
		return FExpressionError(FText::Format(LOCTEXT("InvalidEscapeCharacter", "Invalid escape character '{0}'"), Args));
	}
	else
	{
		return TOptional<FExpressionError>();
	}
}
TOptional<FSequencerSnapField::FSnapResult> FSequencerSnapField::Snap(const TArray<float>& InTimes, float Threshold) const
{
	TOptional<FSnapResult> ProspectiveSnap;
	float SnapDelta = 0.f;

	for (float Time : InTimes)
	{
		TOptional<float> ThisSnap = Snap(Time, Threshold);
		if (!ThisSnap.IsSet())
		{
			continue;
		}

		float ThisSnapDelta = ThisSnap.GetValue() - Time;
		if (!ProspectiveSnap.IsSet() || FMath::Abs(ThisSnapDelta) < FMath::Abs(SnapDelta))
		{
			ProspectiveSnap = FSnapResult{ Time, ThisSnap.GetValue() };
			SnapDelta = ThisSnapDelta;
		}
	}

	return ProspectiveSnap;
}
	TOptional<FExpressionError> ConsumeOperator(FExpressionTokenConsumer& Consumer)
	{
		auto& Stream = Consumer.GetStream();

		for (const TCHAR* Moniker : TSymbol::Monikers)
		{
			TOptional<FStringToken> OperatorToken = Stream.ParseToken(Moniker);
			if (OperatorToken.IsSet())
			{
				Consumer.Add(OperatorToken.GetValue(), TSymbol());
			}
		}

		return TOptional<FExpressionError>();
	}
TOptional<FExpressionError> ParseArgument(FExpressionTokenConsumer& Consumer)
{
	// An argument token looks like {ArgName}
	FTokenStream& Stream = Consumer.GetStream();

	TOptional<FStringToken> OpeningChar = Stream.ParseSymbol(ArgStartChar);
	if (!OpeningChar.IsSet())
	{
		return TOptional<FExpressionError>();
	}

	FStringToken& EntireToken = OpeningChar.GetValue();

	// Parse out the argument name
	TOptional<FStringToken> Identifier = Stream.ParseToken([](TCHAR InC)
	{
		if (InC == ArgEndChar)
		{
			return EParseState::StopBefore;
		}
		else
		{
			return EParseState::Continue;
		}
	}, &EntireToken);

	if (!Identifier.IsSet() || !Stream.ParseSymbol(ArgEndChar, &EntireToken).IsSet())
	{
		return TOptional<FExpressionError>();
	}

	// Add the token to the consumer - this moves the read position in the stream to the end of the token
	FStringToken& IdentifierValue = Identifier.GetValue();
	Consumer.Add(EntireToken, FArgumentTokenSpecifier(IdentifierValue));
	return TOptional<FExpressionError>();
}
示例#22
0
	/** Tick this state machine with the given time limit. Will continuously enumerate the machine until TimeLimit is reached */
	void Tick(const FTimeLimit& TimeLimit)
	{
		while (!TimeLimit.Exceeded())
		{
			const auto& State = Nodes[CurrentState];
			TOptional<TState> NewState = State.Endpoint(TimeLimit);
			if (NewState.IsSet())
			{
				CurrentState = NewState.GetValue();
			}
			else if (State.Type == EStateMachineNode::CallOnce)
			{
				break;
			}
		}
	}
TOptional<FExpressionError> FTokenDefinitions::ConsumeToken(FExpressionTokenConsumer& Consumer) const
{
	auto& Stream = Consumer.GetStream();
	
	// Skip over whitespace
	if (bIgnoreWhitespace)
	{
		TOptional<FStringToken> Whitespace = Stream.ParseWhitespace();
		if (Whitespace.IsSet())
		{
			Stream.SetReadPos(Whitespace.GetValue());
		}
	}

	if (Stream.IsEmpty())
	{
		// Trailing whitespace in the expression.
		return TOptional<FExpressionError>();
	}

	const auto* Pos = Stream.GetRead();

	// Try each token in turn. First come first served.
	for (const auto& Def : Definitions)
	{
		// Call the token definition
		auto Error = Def(Consumer);
		if (Error.IsSet())
		{
			return Error;
		}
		// If the stream has moved on, the definition added one or more tokens, so 
		else if (Stream.GetRead() != Pos)
		{
			return TOptional<FExpressionError>();
		}
	}

	// No token definition matched the stream at its current position - fatal error
	FFormatOrderedArguments Args;
	Args.Add(FText::FromString(Consumer.GetStream().GetErrorContext()));
	Args.Add(Consumer.GetStream().GetPosition());
	return FExpressionError(FText::Format(LOCTEXT("LexicalError", "Unrecognized token '{0}' at character {1}"), Args));
}
FCursorReply FUMGDragDropOp::OnCursorQuery()
{
	FCursorReply CursorReply = FGameDragDropOperation::OnCursorQuery();

	if ( !CursorReply.IsEventHandled() )
	{
		CursorReply = CursorReply.Cursor(EMouseCursor::Default);
	}

	if ( GameViewport )
	{
		TOptional<TSharedRef<SWidget>> CursorWidget = GameViewport->MapCursor(nullptr, CursorReply);
		if ( CursorWidget.IsSet() )
		{
			CursorReply.SetCursorWidget(GameViewport->GetWindow(), CursorWidget.GetValue());
		}
	}

	return CursorReply;
}
示例#25
0
void UAssetImportData::Serialize(FArchive& Ar)
{
	if (Ar.UE4Ver() >= VER_UE4_ASSET_IMPORT_DATA_AS_JSON)
	{
		FString Json;
		if (Ar.IsLoading())
		{
			Ar << Json;
			TOptional<FAssetImportInfo> Copy = FromJson(MoveTemp(Json));
			if (Copy.IsSet())
			{
				CopyFrom(Copy.GetValue());
			}
		}
		else if (Ar.IsSaving())
		{
			Json = ToJson();
			Ar << Json;
		}
	}

	Super::Serialize(Ar);
}
TOptional<FKeyHandle> FGroupedKeyArea::DuplicateKey(FKeyHandle KeyToDuplicate)
{
	FKeyGrouping* Group = FindGroup(KeyToDuplicate);
	if (!Group)
	{
		return TOptional<FKeyHandle>();
	}

	const float Time = Group->RepresentativeTime;

	const int32 NewGroupIndex = Groups.Num();
	Groups.Emplace(Time);
	
	for (const FKeyGrouping::FKeyIndex& Key : Group->Keys)
	{
		TOptional<FKeyHandle> NewKeyHandle = KeyAreas[Key.AreaIndex]->DuplicateKey(Key.KeyHandle);
		if (NewKeyHandle.IsSet())
		{
			Groups[NewGroupIndex].Keys.Emplace(Key.AreaIndex, NewKeyHandle.GetValue());
		}
	}

	// Update the global index with our new key
	FIndexEntry* IndexEntry = GlobalIndex.Find(IndexKey);
	if (IndexEntry)
	{
		FKeyHandle ThisGroupKeyHandle;

		IndexEntry->GroupHandles.Add(ThisGroupKeyHandle);
		IndexEntry->HandleToGroup.Add(ThisGroupKeyHandle, NewGroupIndex);
		IndexEntry->RepresentativeTimes.Add(Time);

		return ThisGroupKeyHandle;
	}

	return TOptional<FKeyHandle>();
}
TOptional<FExpressionError> ParseArgumentModifier(FExpressionTokenConsumer& Consumer)
{
	// An argument modifier token looks like |keyword(args, ...)
	FTokenStream& Stream = Consumer.GetStream();

	TOptional<FStringToken> PipeToken = Stream.ParseSymbol(ArgModChar);
	if (!PipeToken.IsSet())
	{
		return TOptional<FExpressionError>();
	}

	FStringToken& EntireToken = PipeToken.GetValue();

	// Parse out the argument modifier name
	TOptional<FStringToken> Identifier = Stream.ParseToken([](TCHAR InC)
	{
		if (InC == '(')
		{
			return EParseState::StopBefore;
		}
		else if (FChar::IsIdentifier(InC))
		{
			return EParseState::Continue;
		}
		else
		{
			return EParseState::Cancel;
		}
	}, &EntireToken);

	if (!Identifier.IsSet() || !Stream.ParseSymbol(TEXT('('), &EntireToken).IsSet())
	{
		return TOptional<FExpressionError>();
	}

	// Valid modifier name?
	FStringToken& IdentifierValue = Identifier.GetValue();
	FTextFormatter::FCompileTextArgumentModifierFuncPtr CompileTextArgumentModifierFunc = FTextFormatter::Get().FindTextArgumentModifier(FTextFormatString::MakeReference(IdentifierValue.GetTokenStartPos(), IdentifierValue.GetTokenEndPos() - IdentifierValue.GetTokenStartPos()));
	if (!CompileTextArgumentModifierFunc)
	{
		return TOptional<FExpressionError>();
	}

	// Parse out the argument modifier parameter text
	TOptional<FStringToken> Parameters;
	{
		TCHAR QuoteChar = 0;
		int32 NumConsecutiveSlashes = 0;
		Parameters = Stream.ParseToken([&](TCHAR InC)
		{
			if (InC == ')' && QuoteChar == 0)
			{
				return EParseState::StopBefore;
			}
			else if (InC == '"')
			{
				if (InC == QuoteChar)
				{
					if (NumConsecutiveSlashes%2 == 0)
					{
						QuoteChar = 0;
					}
				}
				else
				{
					QuoteChar = InC;
				}
			}
			
			if (InC == '\\')
			{
				++NumConsecutiveSlashes;
			}
			else
			{
				NumConsecutiveSlashes = 0;
			}

			return EParseState::Continue;
		}, &EntireToken);
	}

	if (!Parameters.IsSet() || !Stream.ParseSymbol(TEXT(')'), &EntireToken).IsSet())
	{
		return TOptional<FExpressionError>();
	}

	// Compile the parameters for this argument modifier
	FStringToken& ParametersValue = Parameters.GetValue();
	TSharedPtr<ITextFormatArgumentModifier> CompiledTextArgumentModifier = CompileTextArgumentModifierFunc(FTextFormatString::MakeReference(ParametersValue.GetTokenStartPos(), ParametersValue.GetTokenEndPos() - ParametersValue.GetTokenStartPos()));
	if (!CompiledTextArgumentModifier.IsValid())
	{
		return TOptional<FExpressionError>();
	}

	// Add the token to the consumer - this moves the read position in the stream to the end of the token
	Consumer.Add(EntireToken, FArgumentModifierTokenSpecifier(CompiledTextArgumentModifier.ToSharedRef()));
	return TOptional<FExpressionError>();
}
FReply FSequencerTimeSliderController::OnMouseMove( TSharedRef<SWidget> WidgetOwner, const FGeometry& MyGeometry, const FPointerEvent& MouseEvent )
{
	if ( WidgetOwner->HasMouseCapture() )
	{
		if (MouseEvent.IsMouseButtonDown( EKeys::RightMouseButton ))
		{
			if (!bPanning)
			{
				DistanceDragged += FMath::Abs( MouseEvent.GetCursorDelta().X );
				if ( DistanceDragged > FSlateApplication::Get().GetDragTriggerDistnace() )
				{
					bPanning = true;
				}
			}
			else
			{
				TRange<float> LocalViewRange = TimeSliderArgs.ViewRange.Get();
				float LocalViewRangeMin = LocalViewRange.GetLowerBoundValue();
				float LocalViewRangeMax = LocalViewRange.GetUpperBoundValue();

				FScrubRangeToScreen ScaleInfo( LocalViewRange, MyGeometry.Size );
				FVector2D ScreenDelta = MouseEvent.GetCursorDelta();
				FVector2D InputDelta;
				InputDelta.X = ScreenDelta.X/ScaleInfo.PixelsPerInput;

				float NewViewOutputMin = LocalViewRangeMin - InputDelta.X;
				float NewViewOutputMax = LocalViewRangeMax - InputDelta.X;

				TOptional<float> LocalClampMin = TimeSliderArgs.ClampMin.Get();
				TOptional<float> LocalClampMax = TimeSliderArgs.ClampMax.Get();

				// Clamp the range if clamp values are set
				if ( LocalClampMin.IsSet() && NewViewOutputMin < LocalClampMin.GetValue() )
				{
					NewViewOutputMin = LocalClampMin.GetValue();
				}
			
				if ( LocalClampMax.IsSet() && NewViewOutputMax > LocalClampMax.GetValue() )
				{
					NewViewOutputMax = LocalClampMax.GetValue();
				}

				TimeSliderArgs.OnViewRangeChanged.ExecuteIfBound(TRange<float>(NewViewOutputMin, NewViewOutputMax));

				if( !TimeSliderArgs.ViewRange.IsBound() )
				{	
					// The  output is not bound to a delegate so we'll manage the value ourselves
					TimeSliderArgs.ViewRange.Set( TRange<float>( NewViewOutputMin, NewViewOutputMax ) );
				}
			}
		}
		else if (MouseEvent.IsMouseButtonDown( EKeys::LeftMouseButton ))
		{
			if ( !bDraggingScrubber )
			{
				DistanceDragged += FMath::Abs( MouseEvent.GetCursorDelta().X );
				if ( DistanceDragged > FSlateApplication::Get().GetDragTriggerDistnace() )
				{
					bDraggingScrubber = true;
					TimeSliderArgs.OnBeginScrubberMovement.ExecuteIfBound();
				}
			}
			else
			{
				FScrubRangeToScreen RangeToScreen( TimeSliderArgs.ViewRange.Get(), MyGeometry.Size );
				FVector2D CursorPos = MyGeometry.AbsoluteToLocal( MouseEvent.GetLastScreenSpacePosition() );
				float NewValue = RangeToScreen.LocalXToInput( CursorPos.X );

				const USequencerSnapSettings* SnapSettings = GetDefault<USequencerSnapSettings>();
				if ( SnapSettings->GetIsSnapEnabled() && SnapSettings->GetSnapPlayTimeToInterval() )
				{
					NewValue = SnapSettings->SnapToInterval(NewValue);
				}

				CommitScrubPosition( NewValue, /*bIsScrubbing=*/true );
			}
		}
		return FReply::Handled();
	}

	return FReply::Unhandled();
}
	/** Consume the text from the specified consumer's stream */
	TOptional<FExpressionError> ConsumeTextImpl(FExpressionTokenConsumer& Consumer, const TFunctionRef<bool(TCHAR)> IsBreakingCharacter)
	{
		auto& Stream = Consumer.GetStream();

		FString FinalString;
		FString CurrentQuotedString;

		TCHAR QuoteChar = 0;
		int32 NumConsecutiveSlashes = 0;
		TOptional<FStringToken> TextToken = Stream.ParseToken([&](TCHAR InC)
		{
			if (QuoteChar == 0) // Parsing a non-quoted string...
			{
				// Are we starting a quoted sub-string?
				if (InC == '"' || InC == '\'')
				{
					CurrentQuotedString.AppendChar(InC);
					QuoteChar = InC;
					NumConsecutiveSlashes = 0;
				}
				else
				{
					// Consume until we hit a breaking character
					if (IsBreakingCharacter(InC))
					{
						return EParseState::StopBefore;
					}

					FinalString.AppendChar(InC);
				}
			}
			else // Parsing a quoted sub-string...
			{
				CurrentQuotedString.AppendChar(InC);

				// Are we ending a quoted sub-string?
				if (InC == QuoteChar && NumConsecutiveSlashes%2 == 0)
				{
					UnescapeQuotedString(CurrentQuotedString, QuoteChar);
					FinalString.Append(CurrentQuotedString);

					CurrentQuotedString.Reset();
					QuoteChar = 0;
				}

				if (InC == '\\')
				{
					NumConsecutiveSlashes++;
				}
				else
				{
					NumConsecutiveSlashes = 0;
				}
			}

			return EParseState::Continue;
		});

		if (TextToken.IsSet())
		{
			Consumer.Add(TextToken.GetValue(), CreateTextTokenFromUnquotedString(MoveTemp(FinalString)));
		}

		return TOptional<FExpressionError>();
	}
示例#30
0
int32 SProgressBar::OnPaint( const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyClippingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled ) const
{
	// Used to track the layer ID we will return.
	int32 RetLayerId = LayerId;

	bool bEnabled = ShouldBeEnabled( bParentEnabled );
	const ESlateDrawEffect::Type DrawEffects = bEnabled ? ESlateDrawEffect::None : ESlateDrawEffect::DisabledEffect;
	
	const FSlateBrush* CurrentFillImage = GetFillImage();
	
	const FLinearColor FillColorAndOpacitySRGB(InWidgetStyle.GetColorAndOpacityTint() * FillColorAndOpacity.Get().GetColor(InWidgetStyle) * CurrentFillImage->GetTint(InWidgetStyle));
	const FLinearColor ColorAndOpacitySRGB = InWidgetStyle.GetColorAndOpacityTint();

	TOptional<float> ProgressFraction = Percent.Get();	

	// Paint inside the border only. 
	// Pre-snap the clipping rect to try and reduce common jitter, since the padding is typically only a single pixel.
	FSlateRect SnappedClippingRect = FSlateRect(FMath::RoundToInt(MyClippingRect.Left), FMath::RoundToInt(MyClippingRect.Top), FMath::RoundToInt(MyClippingRect.Right), FMath::RoundToInt(MyClippingRect.Bottom));
	const FSlateRect ForegroundClippingRect = SnappedClippingRect.InsetBy(FMargin(BorderPadding.Get().X, BorderPadding.Get().Y));
	
	const FSlateBrush* CurrentBackgroundImage = GetBackgroundImage();

	FSlateDrawElement::MakeBox(
		OutDrawElements,
		RetLayerId++,
		AllottedGeometry.ToPaintGeometry(),
		CurrentBackgroundImage,
		SnappedClippingRect,
		DrawEffects,
		InWidgetStyle.GetColorAndOpacityTint() * CurrentBackgroundImage->GetTint( InWidgetStyle )
	);	
	
	if( ProgressFraction.IsSet() )
	{
		const float ClampedFraction = FMath::Clamp(ProgressFraction.GetValue(), 0.0f, 1.0f);

		switch (BarFillType)
		{
			case EProgressBarFillType::RightToLeft:
			{
				FSlateRect ClippedAllotedGeometry = FSlateRect(AllottedGeometry.AbsolutePosition, AllottedGeometry.AbsolutePosition + AllottedGeometry.Size * AllottedGeometry.Scale);
				ClippedAllotedGeometry.Left = ClippedAllotedGeometry.Right - ClippedAllotedGeometry.GetSize().X * ClampedFraction;

				// Draw Fill
				FSlateDrawElement::MakeBox(
					OutDrawElements,
					RetLayerId++,
					AllottedGeometry.ToPaintGeometry(
						FVector2D::ZeroVector,
						FVector2D( AllottedGeometry.Size.X, AllottedGeometry.Size.Y )),
					CurrentFillImage,
					ForegroundClippingRect.IntersectionWith(ClippedAllotedGeometry),
					DrawEffects,
					FillColorAndOpacitySRGB
					);
				break;
			}
			case EProgressBarFillType::FillFromCenter:
			{
				// Draw Fill
				FSlateDrawElement::MakeBox(
					OutDrawElements,
					RetLayerId++,
					AllottedGeometry.ToPaintGeometry(
						FVector2D( (AllottedGeometry.Size.X * 0.5f) - ((AllottedGeometry.Size.X * ( ClampedFraction ))*0.5), 0.0f),
						FVector2D( AllottedGeometry.Size.X * ( ClampedFraction ) , AllottedGeometry.Size.Y )),
					CurrentFillImage,
					ForegroundClippingRect,
					DrawEffects,
					FillColorAndOpacitySRGB
					);
				break;
			}
			case EProgressBarFillType::TopToBottom:
			{
				FSlateRect ClippedAllotedGeometry = FSlateRect(AllottedGeometry.AbsolutePosition, AllottedGeometry.AbsolutePosition + AllottedGeometry.Size * AllottedGeometry.Scale);
				ClippedAllotedGeometry.Bottom = ClippedAllotedGeometry.Top + ClippedAllotedGeometry.GetSize().Y * ClampedFraction;

				// Draw Fill
				FSlateDrawElement::MakeBox(
					OutDrawElements,
					RetLayerId++,
					AllottedGeometry.ToPaintGeometry(
						FVector2D::ZeroVector,
						FVector2D( AllottedGeometry.Size.X, AllottedGeometry.Size.Y )),
					CurrentFillImage,
					ForegroundClippingRect.IntersectionWith(ClippedAllotedGeometry),
					DrawEffects,
					FillColorAndOpacitySRGB
					);
				break;
			}
			case EProgressBarFillType::BottomToTop:
			{
				FSlateRect ClippedAllotedGeometry = FSlateRect(AllottedGeometry.AbsolutePosition, AllottedGeometry.AbsolutePosition + AllottedGeometry.Size * AllottedGeometry.Scale);
				ClippedAllotedGeometry.Top = ClippedAllotedGeometry.Bottom - ClippedAllotedGeometry.GetSize().Y * ClampedFraction;

				// Draw Fill
				FSlateDrawElement::MakeBox(
					OutDrawElements,
					RetLayerId++,
					AllottedGeometry.ToPaintGeometry(
						FVector2D::ZeroVector,
						FVector2D( AllottedGeometry.Size.X, AllottedGeometry.Size.Y )),
					CurrentFillImage,
					ForegroundClippingRect.IntersectionWith(ClippedAllotedGeometry),
					DrawEffects,
					FillColorAndOpacitySRGB
					);
				break;
			}
			case EProgressBarFillType::LeftToRight:
			default:
			{
				FSlateRect ClippedAllotedGeometry = FSlateRect(AllottedGeometry.AbsolutePosition, AllottedGeometry.AbsolutePosition + AllottedGeometry.Size * AllottedGeometry.Scale);
				ClippedAllotedGeometry.Right = ClippedAllotedGeometry.Left + ClippedAllotedGeometry.GetSize().X * ClampedFraction;

				// Draw Fill
				FSlateDrawElement::MakeBox(
					OutDrawElements,
					RetLayerId++,
					AllottedGeometry.ToPaintGeometry(
						FVector2D::ZeroVector,
						FVector2D( AllottedGeometry.Size.X, AllottedGeometry.Size.Y )),
					CurrentFillImage,
					ForegroundClippingRect.IntersectionWith(ClippedAllotedGeometry),
					DrawEffects,
					FillColorAndOpacitySRGB
					);
				break;
			}
		}
	}
	else
	{
		const FSlateBrush* CurrentMarqueeImage = GetMarqueeImage();
		
		// Draw Marquee
		const float MarqueeAnimOffset = CurrentMarqueeImage->ImageSize.X * MarqueeOffset;
		const float MarqueeImageSize = CurrentMarqueeImage->ImageSize.X;

		FSlateDrawElement::MakeBox(
			OutDrawElements,
			RetLayerId++,
			AllottedGeometry.ToPaintGeometry(
				FVector2D( MarqueeAnimOffset - MarqueeImageSize, 0.0f ),
				FVector2D( AllottedGeometry.Size.X + MarqueeImageSize, AllottedGeometry.Size.Y )),
			CurrentMarqueeImage,
			ForegroundClippingRect,
			DrawEffects,
			ColorAndOpacitySRGB
			);

	}

	return RetLayerId - 1;
}