UE4插件,展示如何使用第三方庫制作UE4插件
如何調(diào)用第三方封裝好的庫制作UE4插件?
MyEEGPlugin.uplugin
{
"FileVersion": 3,
"Version": 1,
"VersionName": "1.0",
"FriendlyName": "MyEEGPlugin",
"Description": "",
"Category": "Other",
"CreatedBy": "",
"CreatedByURL": "",
"DocsURL": "",
"MarketplaceURL": "",
"SupportURL": "",
"CanContainContent": true,
"IsBetaVersion": false,
"Installed": false,
"Modules": [
{
"Name": "MyEEGPlugin",
"Type": "Runtime",
"LoadingPhase": "Default"
}
]
}
MyEEGPlugin.Build.cs
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
using UnrealBuildTool;
using System.IO;
public class MyEEGPlugin : ModuleRules
{
public MyEEGPlugin(TargetInfo Target)
{
PublicIncludePaths.AddRange(
new string[] {
"MyEEGPlugin/Public"
// ... add public include paths required here ...
}
);
PrivateIncludePaths.AddRange(
new string[] {
"MyEEGPlugin/Private",
// ... add other private include paths required here ...
}
);
PublicDependencyModuleNames.AddRange(
new string[]
{
"Core", "CoreUObject", "Engine", "InputCore", "Projects"
// ... add other public dependencies that you statically link with here ...
}
);
PrivateDependencyModuleNames.AddRange(
new string[]
{
// ... add private dependencies that you statically link with here ...
}
);
DynamicallyLoadedModuleNames.AddRange(
new string[]
{
// ... add any modules that your module loads dynamically here ...
}
);
LoadThinkGearLib(Target);//添加第三方庫
//LoadAlgoSdkDll(Target);//添加第三方庫
}
private string ThirdPartyPath
{
get
{
return Path.GetFullPath(Path.Combine(ModuleDirectory, "../ThirdParty/"));
}
}
public void LoadThinkGearLib(TargetInfo Target)
{
if ((Target.Platform == UnrealTargetPlatform.Win64) || (Target.Platform == UnrealTargetPlatform.Win32))
{
string PlatformString = (Target.Platform == UnrealTargetPlatform.Win64) ? "64" : "";
string LibrariesPath = Path.Combine(ThirdPartyPath, "ThinkGear", "lib");
//test your path
System.Console.WriteLine("... LibrariesPath -> " + LibrariesPath);
PublicIncludePaths.Add(Path.Combine(ThirdPartyPath, "ThinkGear", "include"));
PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "thinkgear" + PlatformString + ".lib"));
}
//Definitions.Add(string.Format("MY_DEFINE={0}", 0));
}
public void LoadAlgoSdkDll(TargetInfo Target)
{
if ((Target.Platform == UnrealTargetPlatform.Win64) || (Target.Platform == UnrealTargetPlatform.Win32))
{
string PlatformString = (Target.Platform == UnrealTargetPlatform.Win64) ? "64" : "";
string DllPath = Path.Combine(ThirdPartyPath, "bin", "AlgoSdkDll" + PlatformString + ".dll");
PublicIncludePaths.Add(Path.Combine(ThirdPartyPath, "EEGAlgoSDK", "include"));
PublicDelayLoadDLLs.Add(DllPath);
//RuntimeDependencies.Add(new RuntimeDependency(DllPath));
}
}
}
MyEEGPlugin.h
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
#pragma once
#include "ModuleManager.h"
class FMyEEGPluginModule : public IModuleInterface
{
public:
/** IModuleInterface implementation */
virtual void StartupModule() override;
virtual void ShutdownModule() override;
private:
/** Handle to the test dll we will load */
void* ExampleLibraryHandle;
};
MyEEGPlugin.cpp
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
#include "MyEEGPlugin.h"
#include "Core.h"
#include "ModuleManager.h"
#include "IPluginManager.h"
//#include "ExampleLibrary.h"
#define LOCTEXT_NAMESPACE "FMyEEGPluginModule"
void FMyEEGPluginModule::StartupModule()
{
// This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module
// Get the base directory of this plugin
FString BaseDir = IPluginManager::Get().FindPlugin("MyEEGPlugin")->GetBaseDir();
// Add on the relative location of the third party dll and load it
FString LibraryPath;
#if PLATFORM_WINDOWS
LibraryPath = FPaths::Combine(*BaseDir, TEXT("Binaries/ThirdParty/MyEEGPluginLibrary/Win64/ExampleLibrary.dll"));
#elif PLATFORM_MAC
LibraryPath = FPaths::Combine(*BaseDir, TEXT("Source/ThirdParty/MyEEGPluginLibrary/Mac/Release/libExampleLibrary.dylib"));
#endif // PLATFORM_WINDOWS
ExampleLibraryHandle = !LibraryPath.IsEmpty() ? FPlatformProcess::GetDllHandle(*LibraryPath) : nullptr;
if (ExampleLibraryHandle)
{
// Call the test function in the third party library that opens a message box
//ExampleLibraryFunction();
}
else
{
//FMessageDialog::Open(EAppMsgType::Ok, LOCTEXT("ThirdPartyLibraryError", "Failed to load example third party library"));
}
}
void FMyEEGPluginModule::ShutdownModule()
{
// This function may be called during shutdown to clean up your module. For modules that support dynamic reloading,
// we call this function before unloading the module.
// Free the dll handle
FPlatformProcess::FreeDllHandle(ExampleLibraryHandle);
ExampleLibraryHandle = nullptr;
}
#undef LOCTEXT_NAMESPACE
IMPLEMENT_MODULE(FMyEEGPluginModule, MyEEGPlugin)
MyEEGReceiver.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "Engine.h"
#include "GameFramework/Actor.h"
#include "MyEEGReceiver.generated.h"
UCLASS()
class AMyEEGReceiver : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor‘s properties
AMyEEGReceiver();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
int rawDataIndex;
int lerpDataIndex;
float totalAngle;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "EEG")
float v;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "EEG")
float s;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "EEG")
float a;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "EEG")
TArrayrawAttentions;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "EEG")
TArrayrawMeditations;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "EEG")
TArraylerpAttentions;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "EEG")
TArraylerpMeditations;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "EEG")
float attention1;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "EEG")
float attention2;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "EEG")
float meditation1;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "EEG")
float meditation2;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
/** Called whenever this actor is being removed from a level */
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
UFUNCTION(BlueprintImplementableEvent, Category = "EEG")
void BPEvent_GetNewAttention(float newAttention);
UFUNCTION(BlueprintCallable, Category = "EEG")
void IndexFunc();
UFUNCTION(BlueprintCallable, Category = "EEG")
void ComputeNewPos(float factor, UStaticMeshComponent* cube, float DeltaTime, float scaleFactorAtten=1, float scaleFactorMedi = 1, bool debug=false);
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "EEG")
int32 LatestMeditation; //*新放松度
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "EEG")
int32 LatestAttention; //*新專注度
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "EEG")
bool ShowOnScreenDebugMessages;
FORCEINLINE void ScreenMsg(const FString& Msg)
{
if (!ShowOnScreenDebugMessages) return;
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, *Msg);
}
FORCEINLINE void ScreenMsg(const FString& Msg, const int32 Value)
{
if (!ShowOnScreenDebugMessages) return;
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("%s %d"), *Msg, Value));
}
};
MyEEGReceiver.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "MyEEGPlugin.h"
#include "MyEEGReceiver.h"
#include "thinkgear.h"
#define NUM 3
// Sets default values
AMyEEGReceiver::AMyEEGReceiver()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don‘t need it.
PrimaryActorTick.bCanEverTick = true;
ShowOnScreenDebugMessages = true;
v = 0; a = 1; s = 0;
rawDataIndex = 0;
lerpDataIndex = 0;
rawAttentions.Init(0, NUM);
rawMeditations.Init(0, NUM);
totalAngle = 0;
}
long raw_data_count = 0;
short *raw_data = NULL;
bool bRunning = false;
bool bInited = false;
char *comPortName = NULL;
int dllVersion = 0;
int connectionId = -1;
int packetsRead = 0;
int errCode = 0;
bool bConnectedHeadset = false;
// Called when the game starts or when spawned
void AMyEEGReceiver::BeginPlay()
{
Super::BeginPlay();
/* Print driver version number */
dllVersion = TG_GetVersion();
ScreenMsg("ThinkGear DLL version:",dllVersion);
//GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("ThinkGear DLL version: %d\n"), dllVersion));
/* Get a connection ID handle to ThinkGear */
connectionId = TG_GetNewConnectionId();
if (connectionId < 0) {
ScreenMsg("Failed to new connection ID");
}
else {
/* Attempt to connect the connection ID handle to serial port "COM5" */
/* NOTE: On Windows, COM10 and higher must be preceded by \\.\, as in
* "\\\\.\\COM12" (must escape backslashes in strings). COM9
* and lower do not require the \\.\, but are allowed to include
* them. On Mac OS X, COM ports are named like
* "/dev/tty.MindSet-DevB-1".
*/
comPortName = "\\\\.\\COM6";
errCode = TG_Connect(connectionId,
comPortName,
TG_BAUD_57600,
TG_STREAM_PACKETS);
if (errCode < 0)
{
ScreenMsg("TG_Connect() failed", errCode);
}
else
{
ScreenMsg("TG_Connect OK",connectionId);
}
}
}
// Called every frame
void AMyEEGReceiver::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
v = v + a*DeltaTime;
s += v*DeltaTime;
/* Read all currently available Packets, one at a time... */
do {
/* Read a single Packet from the connection */
packetsRead = TG_ReadPackets(connectionId, 1);
/* If TG_ReadPackets() was able to read a Packet of data... */
if (packetsRead == 1) {
//ScreenMsg("TG_ReadPackets");
/* If the Packet containted a new raw wave value... */
if (TG_GetValueStatus(connectionId, TG_DATA_RAW) != 0) {
int rawData = (int)TG_GetValue(connectionId, TG_DATA_RAW);
//ScreenMsg("TG_DATA_RAW",rawData);
} /* end "If Packet contained a raw wave value..." */
if (TG_GetValueStatus(connectionId, TG_DATA_POOR_SIGNAL) != 0) {
int ps=TG_GetValue(connectionId, TG_DATA_POOR_SIGNAL);
//ScreenMsg("TG_DATA_POOR_SIGNAL",ps);
}
if (TG_GetValueStatus(connectionId, TG_DATA_MEDITATION) != 0) {
float medi = TG_GetValue(connectionId, TG_DATA_MEDITATION);
LatestMeditation = (int32)medi;
//ScreenMsg("TG_DATA_MEDITATION", LatestMeditation);
rawMeditations[rawDataIndex] = medi;
float total = 0;
for (int i = 0; i < NUM; i++)
total += rawMeditations[i];
float avg_medi = total / NUM;
lerpMeditations.Add(avg_medi);
}
if (TG_GetValueStatus(connectionId, TG_DATA_ATTENTION) != 0) {
float atten = TG_GetValue(connectionId, TG_DATA_ATTENTION);
LatestAttention = (int32)atten;
rawAttentions[rawDataIndex] = atten;
float total = 0;
for (int i = 0; i < NUM; i++)
total += rawAttentions[i];
float avg_atten = total / NUM;
lerpAttentions.Add(avg_atten);
rawDataIndex++;
if (rawDataIndex == NUM)
{
rawDataIndex = 0;
}
ScreenMsg("avg_atten", avg_atten);
//BPEvent_GetNewAttention(TG_GetValue(connectionId, TG_DATA_ATTENTION));
//float atten=TG_GetValue(connectionId, TG_DATA_ATTENTION);
//float delta = atten - s;
//a = delta;
ScreenMsg("TG_DATA_ATTENTION", LatestAttention);
//ScreenMsg("delta", delta);
//ScreenMsg("s", s);
}
} /* end "If TG_ReadPackets() was able to read a Packet..." */
} while (packetsRead > 0); /* Keep looping until all Packets read */
}
void AMyEEGReceiver::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
Super::EndPlay(EndPlayReason);
/* Clean up */
TG_FreeConnection(connectionId);
}
void AMyEEGReceiver::IndexFunc()
{
int lerpNum = lerpAttentions.Num();
if (lerpNum ==0)
return;
int idx1 = lerpDataIndex - 1;
int idx2 = lerpDataIndex;
idx1 = FMath::Max(idx1,0);
idx2 = FMath::Min(idx2, lerpNum-1);
attention1 = lerpAttentions[idx1];
attention2 = lerpAttentions[idx2];
meditation1 = lerpMeditations[idx1];
meditation2 = lerpMeditations[idx2];
if (lerpDataIndex < lerpNum-1)
{
lerpDataIndex++;
}
}
void AMyEEGReceiver::ComputeNewPos(float factor, UStaticMeshComponent* cube, float DeltaTime,
float scaleFactorAtten/*=1*/, float scaleFactorMedi/* = 1*/, bool debug/* = false*/)
{
float tmpAtten = FMath::Lerp(attention1, attention2, factor);
float tmpMedit = FMath::Lerp(meditation1, meditation2, factor);
static float testTime = 0;
if (debug)
{
tmpMedit = 50 + sin(testTime) * 50;
tmpAtten = 50 + sin(testTime) * 50; testTime += DeltaTime;
}
float s0 = tmpMedit*DeltaTime*scaleFactorMedi;
FVector oldPos = cube->GetComponentLocation();
float angle = FMath::Atan(s0 / (oldPos.Size()));
FVector normalVec = oldPos.GetSafeNormal();
FVector newPos = normalVec*(10000 + tmpAtten*scaleFactorAtten);
cube->SetWorldLocation(newPos.RotateAngleAxis(FMath::RadiansToDegrees(angle),FVector(0,1,0)));
FRotator Rotator = FRotator::ZeroRotator;
totalAngle += FMath::RadiansToDegrees(angle);
Rotator.Add(-totalAngle, 0, 0);
if (totalAngle >= 360)
{
totalAngle = 0;
}
cube->SetWorldRotation(Rotator);
UTextRenderComponent* text =
dynamic_cast
if (text)
{
FString t1 = FString::FromInt(tmpAtten);
FString t2 = FString::FromInt(tmpMedit);
FString t3 = FString::FromInt(totalAngle);
FString tmp(", ");
tmp = t1 + tmp + t2;
text->SetText(FText::FromString(tmp));
}
}
- 上一篇:Unity3D開源了,引擎和MONO編輯器的C#源代碼發(fā)布了 2018/3/28
- 下一篇:虛幻UE4如何鏈接第三方庫(lib和dll) 2018/3/20