UE4源码中不常见但很有用的API(包含slate常用方法)(持续更新)

1.SNew

该函数在Slate层中经常使用,常用于创建一个Slate控件,相当于UObject层中的NewObject<>();

具体代码如下所示,后面.HAlign(HAlign_Right)这种都是设置这个Slate控件的样式,比如该Box是水平居中还是居右,比如Padding是什么比例等等

SNew(SBox)
		.HAlign(HAlign_Right)
			[
				SNew(SHorizontalBox)
				+SHorizontalBox::Slot()
				.Padding(FMargin(5.0f, 0.0f))
				.AutoWidth()
				[
					SNew(STextBlock)
					.Font(FEditorStyle::GetFontStyle("TinyText"))
					.Text(this, &FPaperTileMapDetailsCustomization::GetLayerSettingsHeadingText)
					.ToolTipText(LOCTEXT("LayerSettingsTooltip", "Properties specific to the currently selected layer"))
					]
				]

 

2.  TSharedRef<SWidget>  UWidget::TakeWidget();

是将UWidget转成SWidget的一种方式,SWidget在Slate层,UWidget在UObject层,UWidget套了一层SWidget,可以理解为UWidget只是个壳,平时跟一下源码就可以发现,在U开头的控件中,一般在构造函数等中通过SNew()方式创建Slate层中的控件,然后将该引用放在Private中

该函数的作用是:做了一个UMG通向Slate控件的桥梁,我们自定义的UMG控件可以通过该函数转成Slate中的SWidget

官方解释如下:

	/**
	 * Gets the underlying slate widget or constructs it if it doesn't exist.  If you're looking to replace
	 * what slate widget gets constructed look for RebuildWidget.  For extremely special cases where you actually
	 * need to change the the GC Root widget of the constructed User Widget - you need to use TakeDerivedWidget
	 * you must also take care to not call TakeWidget before calling TakeDerivedWidget, as that would put the wrong
	 * expected wrapper around the resulting widget being constructed.
	 */
	TSharedRef<SWidget> TakeWidget();

如何向Swidget转成UUserWidget?

 bool UMyBlueprintFunctionLibrary::TestUMGWidget(UUserWidget* InWidget)
 {
 
     TSharedRef<SWidget> Widget = InWidget->TakeWidget();
     
     TSharedRef<SObjectWidget> ObjWidget = StaticCastSharedRef<SObjectWidget>(Widget);
 
     return ObjWidget->GetWidgetObject() == InWidget;
 
 }

 

3.FSlateTexture2DRHIRef* FAssetThumbnailPool::AccessTexture( const FAssetData& AssetData, uint32 Width, uint32 Height )

该函数作用:设置好的AssetData和图片长宽高,用于将渲染好的缩略图数据返回成FSlateTexture2DRHIRef*

	/**
	 * Accesses the texture for an object.  If a thumbnail was recently rendered this function simply returns the thumbnail.  If it was not, it requests a new one be generated
	 * No assumptions should be made about whether or not it was rendered
	 *
	 * @param Asset The asset to get the thumbnail for
	 * @param Width	The width of the thumbnail
	 * @param Height The height of the thumbnail
	 * @return The thumbnail for the asset or NULL if one could not be produced
	 */
	FSlateTexture2DRHIRef* AccessTexture( const FAssetData& AssetData, uint32 Width, uint32 Height );

 

4.

const FObjectThumbnail* ThumbnailTools::FindCachedThumbnail( const FString& InFullName )

FObjectThumbnail* ThumbnailTools::GetThumbnailForObject( UObject* InObject )

传入UObject的引用或路径就可以拿到内存中渲染好的FObjectThumbnail

/** Searches for an object's thumbnail in memory and returns it if found */
    const FObjectThumbnail* FindCachedThumbnail( const FString& InFullName )

/** Returns the thumbnail for the specified object or NULL if one doesn't exist yet */
	FObjectThumbnail* GetThumbnailForObject( UObject* InObject )

 

5 ObjectType* TSharedPtr::Get()

在Slate层经常用TSharedPtr保存指针,但是如果函数返回一个TSharedPtr是不行的,因为它是只读的,不能赋值,我们可以通过Get()方法返回该对象的引用

	/**
	 * Returns the object referenced by this pointer, or nullptr if no object is reference
	 *
	 * @return  The object owned by this shared pointer, or nullptr
	 */
	FORCEINLINE ObjectType* Get() const
	{
		return Object;
	}

 

UTexture2D* FImageUtils::CreateTexture2D

(int32 SrcWidth, int32 SrcHeight, const TArray<FColor> &SrcData, UObject* Outer, const FString& Name, const EObjectFlags &Flags, const FCreateTexture2DParameters& InParams)

在FimageUtils类中封装了一些创建Texture2D,导入导出的函数

	/**
	 * Creates a 2D texture from a array of raw color data.
	 *
	 * @param SrcWidth		Source image width.
	 * @param SrcHeight		Source image height.
	 * @param SrcData		Source image data.
	 * @param Outer			Outer for the texture object.
	 * @param Name			Name for the texture object.
	 * @param Flags			Object flags for the texture object.
	 * @param InParams		Params about how to set up the texture.
	 * @return				Returns a pointer to the constructed 2D texture object.
	 *
	 */
	ENGINE_API static UTexture2D* CreateTexture2D(int32 SrcWidth, int32 SrcHeight, const TArray<FColor> &SrcData, UObject* Outer, const FString& Name, const EObjectFlags &Flags, const FCreateTexture2DParameters& InParams);

 

7 FString UObjectBaseUtility::GetPathName(  ) const

获取UObject中路径,UObjectBaseUtility是UObject的父类

/**
 * Returns the fully qualified pathname for this object, in the format:
 * 'Outermost.[Outer:]Name'
 *
 * @param	StopOuter	if specified, indicates that the output string should be relative to this object.  if StopOuter
 *						does not exist in this object's Outer chain, the result would be the same as passing NULL.
 *
 * @note	safe to call on NULL object pointers!
 */
FString UObjectBaseUtility::GetPathName( const UObject* StopOuter/*=NULL*/ ) const
{
	FString Result;
	GetPathName(StopOuter, Result);
	return Result;
}

 

FString UObjectBaseUtility::GetFullName(  ) const

获取UObject的名字

/**
 * Returns the fully qualified pathname for this object as well as the name of the class, in the format:
 * 'ClassName Outermost.[Outer:]Name'.
 *
 * @param	StopOuter	if specified, indicates that the output string should be relative to this object.  if StopOuter
 *						does not exist in this object's Outer chain, the result would be the same as passing NULL.
 *
 * @note	safe to call on NULL object pointers!
 */
FString UObjectBaseUtility::GetFullName( const UObject* StopOuter/*=NULL*/ ) const
{
	FString Result;  
	if( this != nullptr )
	{
		Result.Empty(128);
		GetClass()->AppendName(Result);
		Result += TEXT(" ");
		GetPathName( StopOuter, Result );
		// could possibly put a Result.Shrink() here, but this isn't used much in a shipping game
	}
	else
	{
		Result += TEXT("None");
	}
	return Result;  
}

 

9 FPaths:RootDir()

获取根路径

	/**
	 * Returns the root directory of the engine directory tree
	 *
	 * @return Root directory.
	 */
	static FString FPaths:RootDir();

该类下还封装有一些其他路径,比如相对路径和绝对路径转换

 static FString ConvertRelativePathToFull(const FString& InPath);

 

10  static FString FPaths:GetPath(const FString& InPath)

获取文件名之前的路径

	// Returns the path in front of the filename
	static FString FPaths:GetPath(const FString& InPath);

 

11 IModuleInterface& FModuleManager::LoadModuleChecked( const FName InModuleName )

加载一个指定模块,我们说ue4是多个模块一个个加载的

	/**
	 * Loads the specified module, checking to ensure it exists.
	 *
	 * @param InModuleName The base name of the module file.  Should not include path, extension or platform/configuration info.  This is just the "module name" part of the module file name.  Names should be globally unique.
	 * @return The loaded module, or nullptr if the load operation failed.
	 * @see AbandonModule, IsModuleLoaded, LoadModuleChecked, LoadModulePtr, LoadModuleWithFailureReason, UnloadModule
	 */
	IModuleInterface& LoadModuleChecked( const FName InModuleName );

用法:这个用法是拿到Image模块,然后创建一个JPEG的IMageWrapper指针

	IImageWrapperModule& ImageWrapperModule = FModuleManager::LoadModuleChecked<IImageWrapperModule>(FName("ImageWrapper"));
	TSharedPtr<IImageWrapper> ImageWrapper = ImageWrapperModule.CreateImageWrapper(EImageFormat::JPEG);

 

12 

bool FFileHelper::SaveArrayToFile(TArrayView<const uint8> Array, const TCHAR* Filename, IFileManager* FileManager /*= &IFileManager::Get()*/, uint32 WriteFlags)
 

用于将二进制数据存储成一个文件

	/**
	 * Save a binary array to a file.
	 */
	static bool SaveArrayToFile(TArrayView<const uint8> Array, const TCHAR* Filename, IFileManager* FileManager=&IFileManager::Get(), uint32 WriteFlags = 0);

用法:该函数是将ObjectThumbnail存储成一个图片格式

	FObjectThumbnail _objectThumnail;
	ThumbnailTools::RenderThumbnail(obj, _imageRes, _imageRes, ThumbnailTools::EThumbnailTextureFlushMode::AlwaysFlush, NULL, &_objectThumnail);
	TArray<uint8> _myData = _objectThumnail.GetUncompressedImageData();

	TArray<FColor> _imageRawColor;
	for (int i = 0; i < _myData.Num(); i += 4)
	{
		_imageRawColor.Add(FColor(_myData[i + 2], _myData[i + 1], _myData[i], _myData[i + 3]));
	}
	FString _fileName = OutputPath.ToString() +"/"+ obj->GetName() + FString(".jpg");
	IImageWrapperModule& ImageWrapperModule = FModuleManager::LoadModuleChecked<IImageWrapperModule>(FName("ImageWrapper"));
	TSharedPtr<IImageWrapper> ImageWrapper = ImageWrapperModule.CreateImageWrapper(EImageFormat::JPEG);
	ImageWrapper->SetRaw(_imageRawColor.GetData(), _imageRawColor.GetAllocatedSize(), _imageRes, _imageRes, ERGBFormat::BGRA, 8);
	const TArray<uint8>& _ImageData = ImageWrapper->GetCompressed(100); 	
 	FFileHelper::SaveArrayToFile(_ImageData, *_fileName);	

 

13 new FExtender()

new出一个容器,经常用于slate层,用来添加各种控件

 

14 

TSharedRef< const FExtensionBase > FExtender::AddToolBarExtension( FName ExtensionHook, EExtensionHook::Position HookPosition, const TSharedPtr< FUICommandList >& CommandList, const FToolBarExtensionDelegate& ToolBarExtensionDelegate )

TSharedRef< const FExtensionBase > FExtender::AddMenuExtension( FName ExtensionHook, EExtensionHook::Position HookPosition, const TSharedPtr< FUICommandList >& CommandList, const FMenuExtensionDelegate& MenuExtensionDelegate )
TSharedRef< const FExtensionBase > FExtender::AddMenuBarExtension( FName ExtensionHook, EExtensionHook::Position HookPosition, const TSharedPtr< FUICommandList >& CommandList, const FMenuBarExtensionDelegate& MenuBarExtensionDelegate )
常用的三种添加slate控件风格的方法,具体使用是先new一个容器,然后add这三种,最后在module里添加进来

	
	FLevelEditorModule& LevelEditorModule = FModuleManager::LoadModuleChecked<FLevelEditorModule>("LevelEditor");
	
	{
		TSharedPtr<FExtender> MenuExtender = MakeShareable(new FExtender());
		MenuExtender->AddMenuExtension("WindowLayout", EExtensionHook::After, PluginCommands, FMenuExtensionDelegate::CreateRaw(this, &FThumbnailExporterModule::AddMenuExtension));

		LevelEditorModule.GetMenuExtensibilityManager()->AddExtender(MenuExtender);
	}
	
	{
		TSharedPtr<FExtender> ToolbarExtender = MakeShareable(new FExtender);
		ToolbarExtender->AddToolBarExtension("Settings", EExtensionHook::After, PluginCommands, FToolBarExtensionDelegate::CreateRaw(this, &FThumbnailExporterModule::AddToolbarExtension));
		
		LevelEditorModule.GetToolBarExtensibilityManager()->AddExtender(ToolbarExtender);
	}

 

15 

FTabSpawnerEntry& FGlobalTabmanager::RegisterNomadTabSpawner( const FName TabId, const FOnSpawnTab& OnSpawnTab )

添加后还不行,还得注册,这样才能在slate层修改编辑器中的各种控件风格,具体代码如下

	FGlobalTabmanager::Get()->RegisterNomadTabSpawner(ThumbnailExporterTabName, FOnSpawnTab::CreateRaw(this, &FThumbnailExporterModule::OnSpawnPluginTab))
		.SetDisplayName(LOCTEXT("FThumbnailExporterTabTitle", "ThumbnailExporter"))
		.SetMenuType(ETabSpawnerMenuType::Hidden);

 

16 

bool UAssetManager::GetAssetDataForPath(const FSoftObjectPath& ObjectPath, FAssetData& AssetData) const

拿到AssetManager,通过资源路径获取该资源信息

官方解释如下:具体代码使用在第二段

	/** Gets the FAssetData at a specific path, handles redirectors and blueprint classes correctly. Returns true if it found a valid data */
	virtual bool GetAssetDataForPath(const FSoftObjectPath& ObjectPath, FAssetData& AssetData) const;
	UAssetManager& AssetManager = UAssetManager::Get();
	FAssetData MeshObjectAssetData;
	AssetManager.GetAssetDataForPath(MeshObject->GetPathName(), MeshObjectAssetData);

 

17

FAssetThumbnailPool::FAssetThumbnailPool( uint32 InNumInPool, const TAttribute<bool>& InAreRealTimeThumbnailsAllowed, double InMaxFrameTimeAllowance, uint32 InMaxRealTimeThumbnailsPerFrame )

个人感觉这个函数是new了一个线程池,该线程池专门用来渲染各种Thumbnail的

官方解释如下:

对FAssetThumbnailPool 的解释

/**
 * Utility class for keeping track of, rendering, and recycling thumbnails rendered in Slate              
 */
class FAssetThumbnailPool : public FTickableEditorObject

构造函数的各个参数含义:

	/**
	 * Constructor 
	 *
	 * @param InNumInPool						The number of thumbnails allowed in the pool
	 * @param InAreRealTimeThumbnailsAllowed	Attribute that determines if thumbnails should be rendered in real-time
	 * @param InMaxFrameTimeAllowance			The maximum number of seconds per tick to spend rendering thumbnails
	 * @param InMaxRealTimeThumbnailsPerFrame	The maximum number of real-time thumbnails to render per tick
	 */
	UNREALED_API FAssetThumbnailPool( uint32 InNumInPool, const TAttribute<bool>& InAreRealTimeThumbnailsAllowed = true, double InMaxFrameTimeAllowance = 0.005, uint32 InMaxRealTimeThumbnailsPerFrame = 3 );

使用代码如下:

	TSharedPtr<FAssetThumbnailPool> ThumbnailPool1 = MakeShareable(new FAssetThumbnailPool(50, true));

 

18

TSharedRef< ObjectType, Mode > ToSharedRef() const

将一个TSharedPtr转成TSharedRef

	/**
	 * Converts a shared pointer to a shared reference.  The pointer *must* be valid or an assertion will trigger.
	 *
	 * @return  Reference to the object
	 */
	// NOTE: The following is an Unreal extension to standard shared_ptr behavior
	FORCEINLINE TSharedRef< ObjectType, Mode > ToSharedRef() const
	{
 		// If this assert goes off, it means a shared reference was created from a shared pointer that was nullptr.
 		// Shared references are never allowed to be null.  Consider using TSharedPtr instead.
		check( IsValid() );
		return TSharedRef< ObjectType, Mode >( *this );
	}

用法:

	TSharedPtr<SWidget> MySWidget;
	TSharedRef<SWidget> MySWidgetRef=MySWidget.ToSharedRef();

 

19

UTexture2D* UKismetRenderingLibrary::ImportFileAsTexture2D(UObject* WorldContextObject, const FString& Filename)

UTexture2D* UKismetRenderingLibrary::ImportBufferAsTexture2D(UObject* WorldContextObject, const TArray<uint8>& Buffer)

用于传入图片路径或者图片Buffer,生成一张图片


UTexture2D* UKismetRenderingLibrary::ImportFileAsTexture2D(UObject* WorldContextObject, const FString& Filename)
{
	return FImageUtils::ImportFileAsTexture2D(Filename);
}

UTexture2D* UKismetRenderingLibrary::ImportBufferAsTexture2D(UObject* WorldContextObject, const TArray<uint8>& Buffer)

 

20

void UKismetRenderingLibrary::ExportTexture2D(UObject* WorldContextObject, UTexture2D* Texture, const FString& FilePath, const FString& FileName)

将一张Texture2D图片输出到磁盘上

	/**
	 * Exports a Texture2D as a HDR image onto the disk.
	 */
	UFUNCTION(BlueprintCallable, Category = "Rendering", meta = (Keywords = "ExportTexture2D", WorldContext = "WorldContextObject"))
	static ENGINE_API void ExportTexture2D(UObject* WorldContextObject, UTexture2D* Texture, const FString& FilePath, const FString& FileName);

 

21

UFunction*  UClass::FindFunction(FName InName) const

作用:通过函数名直接拿到一个UClass的函数指针

	/** 
	 * This signature intentionally hides the method declared in UObject to make it private.
	 * Call FindFunctionByName instead; This method will search for a function declared in UClass instead of the class it was called on
	 */
	UFunction* FindFunctionChecked(FName InName) const
	{
		return UObject::FindFunctionChecked(InName);
	}

用法:

	SkyDataAsset = FAssetData(SkyData);
	UFunction* SetSkyData = SkyController->FindFunction(TEXT("EditorSetSkyData"));
	SkyController->ProcessEvent(SetSkyData, &SkyData);

 

22

virtual void AActor::ProcessEvent(UFunction* Function, void* Parameters)

作用:

传入该函数具有的所有参数Struct和函数指针,直接调用该函数

该函数在cpp的实现如下,可见,调用的其实是父类的该函数

void AActor::ProcessEvent(UFunction* Function, void* Parameters)
{
	LLM_SCOPE(ELLMTag::EngineMisc);

	#if WITH_EDITOR
	static const FName CallInEditorMeta(TEXT("CallInEditor"));
	const bool bAllowScriptExecution = GAllowActorScriptExecutionInEditor || Function->GetBoolMetaData(CallInEditorMeta);
	#else
	const bool bAllowScriptExecution = GAllowActorScriptExecutionInEditor;
	#endif
	UWorld* MyWorld = GetWorld();
	if( ((MyWorld && (MyWorld->AreActorsInitialized() || bAllowScriptExecution)) || HasAnyFlags(RF_ClassDefaultObject)) && !IsGarbageCollecting() )
	{
#if !UE_BUILD_SHIPPING
		if (!ProcessEventDelegate.IsBound() || !ProcessEventDelegate.Execute(this, Function, Parameters))
		{
			Super::ProcessEvent(Function, Parameters);
		}
#else
		Super::ProcessEvent(Function, Parameters);
#endif
	}
}

父类是UObject,该函数实现如下,感觉有点晦涩,有空再研究

void UObject::ProcessEvent( UFunction* Function, void* Parms )
{
	checkf(!IsUnreachable(),TEXT("%s  Function: '%s'"), *GetFullName(), *Function->GetPathName());
	checkf(!FUObjectThreadContext::Get().IsRoutingPostLoad, TEXT("Cannot call UnrealScript (%s - %s) while PostLoading objects"), *GetFullName(), *Function->GetFullName());

#if LIGHTWEIGHT_PROCESS_EVENT_COUNTER
	CONDITIONAL_SCOPE_CYCLE_COUNTER(STAT_BlueprintTime, IsInGameThread() && ProcessEventCounter == 0);
	TGuardValue<int32> PECounter(ProcessEventCounter, ProcessEventCounter+1);
#endif

#if DO_BLUEPRINT_GUARD
	FBlueprintExceptionTracker& BlueprintExceptionTracker = FBlueprintExceptionTracker::Get();
	TGuardValue<int32> EntryCounter( BlueprintExceptionTracker.ScriptEntryTag, BlueprintExceptionTracker.ScriptEntryTag+1);

	CONDITIONAL_SCOPE_CYCLE_COUNTER(STAT_BlueprintTime, IsInGameThread() && BlueprintExceptionTracker.ScriptEntryTag == 1);
#endif

#if TOTAL_OVERHEAD_SCRIPT_STATS
	FBlueprintEventTimer::FScopedVMTimer VMTime;
#endif // TOTAL_OVERHEAD_SCRIPT_STATS

	// Reject.
	if (IsPendingKill())
	{
		return;
	}
	
#if WITH_EDITORONLY_DATA
	// Cannot invoke script events when the game thread is paused for debugging.
	if(GIntraFrameDebuggingGameThread)
	{
		if(GFirstFrameIntraFrameDebugging)
		{
			UE_LOG(LogScriptCore, Warning, TEXT("Cannot call UnrealScript (%s - %s) while stopped at a breakpoint."), *GetFullName(), *Function->GetFullName());
		}

		return;
	}
#endif	// WITH_EDITORONLY_DATA

	if ((Function->FunctionFlags & FUNC_Native) != 0)
	{
		int32 FunctionCallspace = GetFunctionCallspace(Function, Parms, NULL);
		if (FunctionCallspace & FunctionCallspace::Remote)
		{
			CallRemoteFunction(Function, Parms, NULL, NULL);
		}

		if ((FunctionCallspace & FunctionCallspace::Local) == 0)
		{
			return;
		}
	}
	else if (Function->Script.Num() == 0)
	{
		return;
	}
	checkSlow((Function->ParmsSize == 0) || (Parms != NULL));

#if PER_FUNCTION_SCRIPT_STATS
	const bool bShouldTrackFunction = Stats::IsThreadCollectingData();
	FScopeCycleCounterUObject FunctionScope(bShouldTrackFunction ? Function : nullptr);
#endif // PER_FUNCTION_SCRIPT_STATS

#if STATS || ENABLE_STATNAMEDEVENTS
	const bool bShouldTrackObject = GVerboseScriptStats && Stats::IsThreadCollectingData();
	FScopeCycleCounterUObject ContextScope(bShouldTrackObject ? this : nullptr);
#endif

#if UE_BLUEPRINT_EVENTGRAPH_FASTCALLS
	// Fast path for ubergraph calls
	int32 EventGraphParams;
	if (Function->EventGraphFunction != nullptr)
	{
		// Call directly into the event graph, skipping the stub thunk function
		EventGraphParams = Function->EventGraphCallOffset;
		Parms = &EventGraphParams;
		Function = Function->EventGraphFunction;

		// Validate assumptions required for this optimized path (EventGraphFunction should have only been filled out if these held)
		checkSlow(Function->ParmsSize == sizeof(EventGraphParams));
		checkSlow(Function->FirstPropertyToInit == nullptr);
		checkSlow(Function->PostConstructLink == nullptr);
	}
#endif

	// Scope required for scoped script stats.
	{
		uint8* Frame = NULL;
#if USE_UBER_GRAPH_PERSISTENT_FRAME
		if (Function->HasAnyFunctionFlags(FUNC_UbergraphFunction))
		{
			Frame = Function->GetOuterUClassUnchecked()->GetPersistentUberGraphFrame(this, Function);
		}
#endif
		const bool bUsePersistentFrame = (NULL != Frame);
		if (!bUsePersistentFrame)
		{
			Frame = (uint8*)FMemory_Alloca(Function->PropertiesSize);
			// zero the local property memory
			FMemory::Memzero(Frame + Function->ParmsSize, Function->PropertiesSize - Function->ParmsSize);
		}

		// initialize the parameter properties
		FMemory::Memcpy(Frame, Parms, Function->ParmsSize);

		// Create a new local execution stack.
		FFrame NewStack(this, Function, Frame, NULL, Function->Children);

		checkSlow(NewStack.Locals || Function->ParmsSize == 0);



		// if the function has out parameters, fill the stack frame's out parameter info with the info for those params 
		if ( Function->HasAnyFunctionFlags(FUNC_HasOutParms) )
		{
			FOutParmRec** LastOut = &NewStack.OutParms;
			for ( UProperty* Property = (UProperty*)Function->Children; Property && (Property->PropertyFlags&(CPF_Parm)) == CPF_Parm; Property = (UProperty*)Property->Next )
			{
				// this is used for optional parameters - the destination address for out parameter values is the address of the calling function
				// so we'll need to know which address to use if we need to evaluate the default parm value expression located in the new function's
				// bytecode
				if ( Property->HasAnyPropertyFlags(CPF_OutParm) )
				{
					CA_SUPPRESS(6263)
					FOutParmRec* Out = (FOutParmRec*)FMemory_Alloca(sizeof(FOutParmRec));
					// set the address and property in the out param info
					// note that since C++ doesn't support "optional out" we can ignore that here
					Out->PropAddr = Property->ContainerPtrToValuePtr<uint8>(Parms);
					Out->Property = Property;

					// add the new out param info to the stack frame's linked list
					if (*LastOut)
					{
						(*LastOut)->NextOutParm = Out;
						LastOut = &(*LastOut)->NextOutParm;
					}
					else
					{
						*LastOut = Out;
					}
				}
			}

			// set the next pointer of the last item to NULL to mark the end of the list
			if (*LastOut)
			{
				(*LastOut)->NextOutParm = NULL;
			}
		}

		if (!bUsePersistentFrame)
		{
			for (UProperty* LocalProp = Function->FirstPropertyToInit; LocalProp != NULL; LocalProp = (UProperty*)LocalProp->Next)
			{
				LocalProp->InitializeValue_InContainer(NewStack.Locals);
			}
		}

		// Call native function or UObject::ProcessInternal.
		const bool bHasReturnParam = Function->ReturnValueOffset != MAX_uint16;
		uint8* ReturnValueAddress = bHasReturnParam ? ((uint8*)Parms + Function->ReturnValueOffset) : nullptr;
		Function->Invoke(this, NewStack, ReturnValueAddress);

		if (!bUsePersistentFrame)
		{
			// Destroy local variables except function parameters.!! see also UObject::CallFunctionByNameWithArguments
			// also copy back constructed value parms here so the correct copy is destroyed when the event function returns
			for (UProperty* P = Function->DestructorLink; P; P = P->DestructorLinkNext)
			{
				if (!P->IsInContainer(Function->ParmsSize))
				{
					P->DestroyValue_InContainer(NewStack.Locals);
				}
				else if (!(P->PropertyFlags & CPF_OutParm))
				{
					FMemory::Memcpy(P->ContainerPtrToValuePtr<uint8>(Parms), P->ContainerPtrToValuePtr<uint8>(NewStack.Locals), P->ArrayDim * P->ElementSize);
				}
			}
		}
	}

#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
#if WITH_EDITORONLY_DATA
	FBlueprintCoreDelegates::OnScriptExecutionEnd.Broadcast();
#endif
#endif
}

 

23 

template< class ObjectType >
FORCEINLINE SharedPointerInternals::FRawPtrProxy< ObjectType > MakeShareable( ObjectType* InObject )

作用:将一个object的指针隐式转换成一个shared pointers

用法

TSharedRef<IDetailCustomization> FCWPVPActorDetailPanel::MakeInstance()
{
	return MakeShareable(new FCWPVPActorDetailPanel);
}

源码的解释:

/**
 * MakeShareable utility function.  Wrap object pointers with MakeShareable to allow them to be implicitly
 * converted to shared pointers!  This is useful in assignment operations, or when returning a shared
 * pointer from a function.
 */
// NOTE: The following is an Unreal extension to standard shared_ptr behavior
template< class ObjectType >
FORCEINLINE SharedPointerInternals::FRawPtrProxy< ObjectType > MakeShareable( ObjectType* InObject )
{
	return SharedPointerInternals::FRawPtrProxy< ObjectType >( InObject );
}

 

24

如果是编辑器已经加载过的资源,不通过loadobject方法加载该资源

如何从ue4编辑器内存中直接拿到该资源?

该方法是通过UAssetManager获取内存中已经加载过的所有资源,传入的是该资源的地址,拿到一个AssetData数据,通过FastGetAsset方法(参数为true表示该资源已load)获取UObject

	UAssetManager& AssetManaget = UAssetManager::Get();
	FSoftObjectPath SoftPath(*Path);
	FAssetData ObjectAssetData;
	bool bHaveGet = AssetManaget.GetAssetDataForPath(SoftPath, ObjectAssetData);
	if (bHaveGet)
	{
		return ObjectAssetData.FastGetAsset(true);
	}
	return nullptr;

 

25

UEditorAssetLibrary::SaveLoadedAsset(const TArray<UObject*>& AssetsToSave, bool bOnlyIfIsDirty = true);

用来保存编辑器中已加载过的资源,序列化数据到硬盘上

    /**
     * Save the packages the assets live in. All objects that live in the package will be saved. Will try to checkout the files.
     * @param    AssetToSaves        Assets that we want to save.
     * @param    bOnlyIfIsDirty        Only checkout asset that are dirty.
     * @return    True if the operation succeeds.
     */
    UFUNCTION(BlueprintCallable, Category = "Editor Scripting | Asset")
    static bool SaveLoadedAssets(const TArray<UObject*>& AssetsToSave, bool bOnlyIfIsDirty = true);

 

26 

UEditorAssetLibrary类中封装了对编辑器中已Load的资源的各种操作,如加载资源,拷贝资源,删除资源,根据路径获取FAssetData,判断资源是否存在,对资源的迁出保存等

  • 8
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值