ETransformGizmoInteractionType ABaseTransformGizmo::GetInteractionType( UActorComponent* DraggedComponent, TOptional<FTransformGizmoHandlePlacement>& OutHandlePlacement )
{
	OutHandlePlacement.Reset();
	if ( DraggedComponent != nullptr )
	{
		UStaticMeshComponent* DraggedMesh = Cast<UStaticMeshComponent>( DraggedComponent );
		if ( DraggedMesh != nullptr )
		{
			ETransformGizmoInteractionType ResultInteractionType;

			for ( UGizmoHandleGroup* HandleGroup : AllHandleGroups )
			{
				if ( HandleGroup != nullptr )
				{
					int32 HandIndex = HandleGroup->GetDraggedHandleIndex( DraggedMesh );
					if ( HandIndex != INDEX_NONE )
					{
						HandleGroup->GetHandleIndexInteractionType( HandIndex, ResultInteractionType, OutHandlePlacement );
						return ResultInteractionType;
					}
				}
			}
		}
	}

	OutHandlePlacement.Reset();
	return ETransformGizmoInteractionType::Translate;
}
Пример #2
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> 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>();
}
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());
}
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);
}
/** 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>();
}
void FAssetSourceFilenameCache::HandleOnAssetRenamed(const FAssetData& AssetData, const FString& OldPath)
{
	TOptional<FAssetImportInfo> ImportData = ExtractAssetImportInfo(AssetData.TagsAndValues);
	if (ImportData.IsSet())
	{
		FName OldPathName = *OldPath;

		for (auto& SourceFile : ImportData->SourceFiles)
		{
			FString CleanFilename = FPaths::GetCleanFilename(SourceFile.RelativeFilename);

			if (auto* Objects = SourceFileToObjectPathCache.Find(CleanFilename))
			{
				Objects->Remove(OldPathName);
				if (Objects->Num() == 0)
				{
					SourceFileToObjectPathCache.Remove(CleanFilename);
				}
			}

			SourceFileToObjectPathCache.FindOrAdd(CleanFilename).Add(AssetData.ObjectPath);
		}
	}

	AssetRenamedEvent.Broadcast(AssetData, OldPath);
}
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;
	}
}
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());
}
/** Generate a config from the specified options, to pass to FFileCache on construction */
DirectoryWatcher::FFileCacheConfig GenerateFileCacheConfig(const FString& InPath, const DirectoryWatcher::FMatchRules& InMatchRules, const FString& InMountedContentPath)
{
	FString Directory = FPaths::ConvertRelativePathToFull(InPath);

	const FString& HashString = InMountedContentPath.IsEmpty() ? Directory : InMountedContentPath;
	const uint32 CRC = FCrc::MemCrc32(*HashString, HashString.Len()*sizeof(TCHAR));	
	FString CacheFilename = FPaths::ConvertRelativePathToFull(FPaths::GameIntermediateDir()) / TEXT("ReimportCache") / FString::Printf(TEXT("%u.bin"), CRC);

	DirectoryWatcher::FFileCacheConfig Config(Directory, MoveTemp(CacheFilename));
	Config.Rules = InMatchRules;
	// We always store paths inside content folders relative to the folder
	Config.PathType = DirectoryWatcher::EPathType::Relative;

	Config.bDetectChangesSinceLastRun = GetDefault<UEditorLoadingSavingSettings>()->bDetectChangesOnStartup;

	// It's safe to assume the asset registry is not re-loadable
	IAssetRegistry* Registry = &FModuleManager::LoadModuleChecked<FAssetRegistryModule>(AssetRegistryConstants::ModuleName).Get();
	Config.CustomChangeLogic = [Directory, Registry](const DirectoryWatcher::FImmutableString& InRelativePath, const DirectoryWatcher::FFileData& FileData) -> TOptional<bool> {

		int32 TotalNumReferencingAssets = 0;

		TArray<FAssetData> Assets = FAssetSourceFilenameCache::Get().GetAssetsPertainingToFile(*Registry, Directory / InRelativePath.Get());

		if (Assets.Num() == 0)
		{
			return TOptional<bool>();
		}

		// We need to consider this as a changed file if the hash doesn't match any asset imported from that file
		for (FAssetData& Asset : Assets)
		{
			TOptional<FAssetImportInfo> Info = FAssetSourceFilenameCache::ExtractAssetImportInfo(Asset.TagsAndValues);

			// Check if the source file that this asset last imported was the same as the one we're going to reimport.
			// If it is, there's no reason to auto-reimport it
			if (Info.IsSet() && Info->SourceFiles.Num() == 1)
			{
				if (Info->SourceFiles[0].FileHash != FileData.FileHash)
				{
					return true;
				}
			}
		}

		return TOptional<bool>();
	};

	// We only detect changes for when the file *contents* have changed (not its timestamp)
	Config
		.DetectMoves(true)
		.DetectChangesFor(DirectoryWatcher::FFileCacheConfig::Timestamp, false)
		.DetectChangesFor(DirectoryWatcher::FFileCacheConfig::FileHash, true);

	return Config;
}
Пример #11
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);
}
void FAssetSourceFilenameCache::HandleOnAssetAdded(const FAssetData& AssetData)
{
	TOptional<FAssetImportInfo> ImportData = ExtractAssetImportInfo(AssetData.TagsAndValues);
	if (ImportData.IsSet())
	{
		for (const auto& SourceFile : ImportData->SourceFiles)
		{
			SourceFileToObjectPathCache.FindOrAdd(FPaths::GetCleanFilename(SourceFile.RelativeFilename)).Add(AssetData.ObjectPath);
		}
	}
}
	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());
	}
	/** 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>();
	}
Пример #15
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());
		}
	}
}
Пример #16
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;
}
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 );
	}
}
	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>();
	}
Пример #19
0
FVector2D FSlateDrawElement::GetRotationPoint(const FPaintGeometry& PaintGeometry, const TOptional<FVector2D>& UserRotationPoint, ERotationSpace RotationSpace)
{
	FVector2D RotationPoint(0, 0);

	const FVector2D& LocalSize = PaintGeometry.GetLocalSize();

	switch (RotationSpace)
	{
	case RelativeToElement:
	{
		// If the user did not specify a rotation point, we rotate about the center of the element
		RotationPoint = UserRotationPoint.Get(LocalSize * 0.5f);
	}
		break;
	case RelativeToWorld:
	{
		// its in world space, must convert the point to local space.
		RotationPoint = TransformPoint(Inverse(PaintGeometry.GetAccumulatedRenderTransform()), UserRotationPoint.Get(FVector2D::ZeroVector));
	}
		break;
	default:
		check(0);
		break;
	}

	return RotationPoint;
}
Пример #20
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;
			}
		}
	}
Пример #21
0
EActiveTimerReturnType SProgressBar::ActiveTick(double InCurrentTime, float InDeltaTime)
{
	MarqueeOffset = InCurrentTime - FMath::FloorToDouble(InCurrentTime);
	
	TOptional<float> PrecentFracton = Percent.Get();
	if (PrecentFracton.IsSet())
	{
		SetActiveTimerTickRate(MinimumTickRate);
	}
	else
	{
		SetActiveTimerTickRate(0.0f);
	}

	return EActiveTimerReturnType::Continue;
}
Пример #22
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);
		}
	}
}
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));
}
void FAssetSourceFilenameCache::HandleOnAssetRemoved(const FAssetData& AssetData)
{
	TOptional<FAssetImportInfo> ImportData = ExtractAssetImportInfo(AssetData.TagsAndValues);
	if (ImportData.IsSet())
	{
		for (auto& SourceFile : ImportData->SourceFiles)
		{
			FString CleanFilename = FPaths::GetCleanFilename(SourceFile.RelativeFilename);
			if (auto* Objects = SourceFileToObjectPathCache.Find(CleanFilename))
			{
				Objects->Remove(AssetData.ObjectPath);
				if (Objects->Num() == 0)
				{
					SourceFileToObjectPathCache.Remove(CleanFilename);
				}
			}
		}
	}
}
Пример #25
0
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;
}
Пример #26
0
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>();
}
	FString GetExportScriptPath(const FLocalizationTargetSettings& Target, const TOptional<FString> CultureName)
	{
		const FString ConfigFileDirectory = GetScriptDirectory();
		FString ConfigFilePath;
		if (CultureName.IsSet())
		{
			ConfigFilePath = ConfigFileDirectory / FString::Printf( TEXT("%s_Export_%s.%s"), *Target.Name, *CultureName.GetValue(), TEXT("ini") );
		}
		else
		{
			ConfigFilePath = ConfigFileDirectory / FString::Printf( TEXT("%s_Export.%s"), *Target.Name, TEXT("ini") );
		}
		return ConfigFilePath;
	}
Пример #28
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);
}
Пример #29
0
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<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>();
}