diff --git a/Content/Scripts/TFPluginAPI.py b/Content/Scripts/TFPluginAPI.py deleted file mode 100644 index dc0b7bb..0000000 --- a/Content/Scripts/TFPluginAPI.py +++ /dev/null @@ -1,80 +0,0 @@ -import sys - -import tensorflow as tf -import unreal_engine as ue - -class TFPluginAPI(): - @classmethod - def getInstance(cls): - #This should return an instance of your class even if you subclassed it - return cls() - - ## Private - def __init__(self): - #class scoped variable for stopping - self.shouldStop = False #check this variable to stop training early - self.shouldRetrain = False #use this variable to force your training - self.stored = {} - - #internal don't need to override this - def _resetTrainingTrigger(self): - self.shouldStop = False - - #internal don't need to override this: early stopping - def _stopTraining(self): - self.shouldStop = True - self.onStopTraining() - - ## Public - - #call this inside your class to emit a custom event on gt, don't override the function - def callEvent(self, event, data = None, useJson = False): - self.tf_component.custom_event(event, data, useJson) - - #expected api: setup your model for training - def onSetup(self): - #setup or load your model and pass it into stored - - #Usually store session, graph, and model if using keras - #self.sess = tf.InteractiveSession() - #self.graph = tf.get_default_graph() - pass - - #expected api: storedModel and session, json inputs - def onJsonInput(self, jsonInput): - #e.g. our json input could be a pixel array - #pixelarray = jsonInput['pixels'] - - #run input on your graph - #e.g. sess.run(model['y'], feed_dict) - # where y is your result graph and feed_dict is {x:[input]} - - #... - - #return a json you will parse e.g. a prediction - result = {} - result['prediction'] = 0 - - return result - - - - #expected api: no params forwarded for training? TBC - def onBeginTraining(self): - #train here - - #... - - #inside your training loop check if we should stop early - #if(self.shouldStop): - # break - pass - - def onStopTraining(self): - #you should be listening to self.shouldStop, but you can also receive this call - pass - -#required function to get our api -def getApi(): - #return CLASSNAME.getInstance() - return TFPluginAPI.getInstance() \ No newline at end of file diff --git a/Content/Scripts/TensorFlowComponent.py b/Content/Scripts/TensorFlowComponent.py deleted file mode 100644 index 583d9d2..0000000 --- a/Content/Scripts/TensorFlowComponent.py +++ /dev/null @@ -1,170 +0,0 @@ -import unreal_engine as ue -import upythread as ut -import json -import sys -import importlib -import time -import imp - -class TensorFlowComponent: - - # constructor adding a component - Unused atm - #def __init__(self): - # ue.log('Component Init') - - # this is called on game start - def begin_play(self): - if(self.uobject.VerbosePythonLog): - ue.log('BeginPlay, importing TF module: ' + self.uobject.TensorFlowModule) - - #import the module - self.tfModule = importlib.import_module(self.uobject.TensorFlowModule) - imp.reload(self.tfModule) - - #tfc or the class instance holding the pluginAPI - self.tfapi = self.tfModule.getApi() - self.tfapi.tf_component = self - - #link default variables - self.tfapi.shouldRetrain = self.uobject.ShouldRetrain - - #Valid game world toggle for threading guards - self.ValidGameWorld = True - - #call our tfapi setup, typically on another thread - self.setup() - - def end_play(self, reason): - self.ValidGameWorld = False - self.stop_training() - - def stop_training(self): - self.tfapi._stopTraining() - - #multi-threaded call - def setup(self, args=None): - if(self.uobject.ShouldUseMultithreading): - try: - if(self.uobject.VerbosePythonLog): - ue.log('running setup on background thread') - ut.run_on_bt(self.setup_blocking) - except: - e = sys.exc_info()[0] - ue.log('TensorFlowComponent::setup error: ' + str(e)) - else: - self.setup_blocking() - - #multi-threaded call - def train(self, args=None): - #ensure our training trigger is reset - self.tfapi._resetTrainingTrigger() - - if(self.uobject.VerbosePythonLog): - ue.log(self.uobject.TensorFlowModule + ' training scheduled.') - - if(self.uobject.ShouldUseMultithreading): - try: - ut.run_on_bt(self.train_blocking) - except: - e = sys.exc_info()[0] - ue.log('TensorFlowComponent::train error: ' + str(e)) - else: - self.train_blocking() - - - #allow call custom functions on the tfapi object. Note all of these are synchronous - def custom_function(self, args=None): - #split our custom function call by first ',' - stringList = args.split(',', 1) - - #call our custom function with our passed variables and return result - return getattr(self.tfapi, stringList[0])(stringList[1]) - - def custom_event_gt(self, eventdata): - if(eventdata['useJson']): - data = json.dumps(eventdata['data']) - else: - data = eventdata['data'] - self.uobject.OnEventFunction(eventdata['event'], data) - - #pass back a custom event - def custom_event(self, event, data=None, useJson=False): - #embedd the data - eventdata = {} - eventdata['event'] = event - eventdata['data'] = data - eventdata['useJson'] = useJson - ue.run_on_gt(self.custom_event_gt, eventdata) - - #json input - def json_input(self, args): - if(self.uobject.VerbosePythonLog): - ue.log(self.uobject.TensorFlowModule + ' input passed: ' + args) - - #branch based on threading - if(self.uobject.ShouldUseMultithreading): - ut.run_on_bt(self.json_input_blocking, args) - else: - self.json_input_blocking(args) - - #setup blocking - def json_input_blocking(self, args): - #pass the raw json to the script to handle - resultJson = self.tfapi.onJsonInput(json.loads(args)) - - if(self.uobject.ShouldUseMultithreading): - #pass prediction json back - if(self.ValidGameWorld): - ue.run_on_gt(self.json_input_gt_callback, resultJson) - else: - self.json_input_gt_callback(resultJson) - - def json_input_gt_callback(self, resultJson): - self.uobject.OnResultsFunction(json.dumps(resultJson)) - - #setup blocking - def setup_blocking(self): - - #call the api setup (may be multi-threaded!) - self.tfapi.onSetup() - - #run callbacks only if we're still in a valid game world - if(self.ValidGameWorld): - ue.run_on_gt(self.setup_complete) - - #setup callback function - def setup_complete(self): - if(self.uobject.VerbosePythonLog): - ue.log('Setup complete!'); - - #train after setup has completed if toggled - if(self.uobject.ShouldTrainOnBeginPlay): - self.train() - - #single threaded call - def train_blocking(self): - if(self.uobject.VerbosePythonLog): - ue.log(self.uobject.TensorFlowModule + ' training started on bt thread.') - - #calculate the time it takes to train your network - start = time.time() - self.trained = self.tfapi.onBeginTraining() - stop = time.time() - - if hasattr(self.trained, 'summary'): - summary = self.trained['summary'] - else: - summary = {} - - summary['elapsed'] = stop-start - - #run callbacks only if we're still in a valid game world - if(self.ValidGameWorld): - ue.run_on_gt(self.training_complete, summary) - - #training callback function - def training_complete(self, summary): - if(self.uobject.VerbosePythonLog): - ue.log(self.uobject.TensorFlowModule + ' trained in ' + str(round(summary['elapsed'],2)) + ' seconds.') - - self.uobject.OnTrainingCompleteFunction(json.dumps(summary)) \ No newline at end of file diff --git a/Content/Scripts/upymodule.json b/Content/Scripts/upymodule.json index 39c244e..6b4402f 100644 --- a/Content/Scripts/upymodule.json +++ b/Content/Scripts/upymodule.json @@ -1,7 +1,6 @@ { "name" : "tensorflow-ue4", "pythonModules": { - "tensorflow": "1.12.0", - "h5py":"2.7.0" + "tensorflow": "1.15.0" } } diff --git a/Content/TensorflowComponent.uasset b/Content/TensorflowComponent.uasset index ebd0009..ba519d6 100644 Binary files a/Content/TensorflowComponent.uasset and b/Content/TensorflowComponent.uasset differ diff --git a/Source/TFAudioCapture/Private/FTFAudioCapture.cpp b/Source/TFAudioCapture/Private/FTFAudioCapture.cpp index 4370f67..b522e8b 100644 --- a/Source/TFAudioCapture/Private/FTFAudioCapture.cpp +++ b/Source/TFAudioCapture/Private/FTFAudioCapture.cpp @@ -1,6 +1,6 @@ #include "ITFAudioCapture.h" #include "TFAudioCaptureComponent.h" -#include "LambdaRunnable.h" +#include "CULambdaRunnable.h" #include "FWindowsAudioCapture.h" class FTFAudioCapture : public ITFAudioCapture @@ -43,7 +43,7 @@ void FTFAudioCapture::StartCapture(TFunction&, float)> TFunction&, float)> OnDataDelegate = [this, OnAudioData] (const TArray& AudioData, float AudioMaxLevel) { //Call each added component function inside game thread - FLambdaRunnable::RunShortLambdaOnGameThread([this, AudioData, OnAudioData, AudioMaxLevel] + FCULambdaRunnable::RunShortLambdaOnGameThread([this, AudioData, OnAudioData, AudioMaxLevel] { for (auto Delegate : Delegates) { @@ -61,7 +61,7 @@ void FTFAudioCapture::StartCapture(TFunction&, float)> TFunction&, float)> OnFinishedDelegate = [this, OnCaptureFinished](const TArray& AudioData, float AudioMaxLevel) { //Call each added component function inside game thread - FLambdaRunnable::RunShortLambdaOnGameThread([this, AudioData, OnCaptureFinished, AudioMaxLevel] + FCULambdaRunnable::RunShortLambdaOnGameThread([this, AudioData, OnCaptureFinished, AudioMaxLevel] { for (auto Delegate : Delegates) { diff --git a/Source/TFAudioCapture/Private/FWindowsAudioCapture.cpp b/Source/TFAudioCapture/Private/FWindowsAudioCapture.cpp index 63380bd..e7eced6 100644 --- a/Source/TFAudioCapture/Private/FWindowsAudioCapture.cpp +++ b/Source/TFAudioCapture/Private/FWindowsAudioCapture.cpp @@ -1,6 +1,7 @@ #include "FWindowsAudioCapture.h" -#include "LambdaRunnable.h" +#include "CULambdaRunnable.h" #include "CoreMinimal.h" +#include "HAL/ThreadSafeBool.h" #include "AllowWindowsPlatformTypes.h" #include @@ -26,7 +27,7 @@ void FWindowsAudioCapture::StartCapture(TFunction&, flo bRunLoopActive = true; FThreadSafeBool* bShouldRunPtr = &bRunLoopActive; - FLambdaRunnable::RunLambdaOnBackGroundThread([this, OnAudioData, OnCaptureFinished, bShouldRunPtr]() + FCULambdaRunnable::RunLambdaOnBackGroundThread([this, OnAudioData, OnCaptureFinished, bShouldRunPtr]() { HWAVEIN hWaveIn; MMRESULT result; diff --git a/Source/TensorFlow/Private/TensorFlow.cpp b/Source/TensorFlow/Private/TensorFlow.cpp index db477ab..2811746 100644 --- a/Source/TensorFlow/Private/TensorFlow.cpp +++ b/Source/TensorFlow/Private/TensorFlow.cpp @@ -2,7 +2,6 @@ #include "TensorFlow.h" #include "TensorFlowPrivatePCH.h" -#include "UnrealEnginePython.h" #include "IPluginManager.h" #define LOCTEXT_NAMESPACE "FTensorFlowModule" @@ -11,16 +10,6 @@ DEFINE_LOG_CATEGORY(TensorFlowLog); void FTensorFlowModule::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 python module and add self as a dependent - if (FUnrealEnginePythonModule::IsAvailable()) - { - FUnrealEnginePythonModule::Get().AddPythonDependentPlugin("TensorFlow"); - } - else - { - UE_LOG(TensorFlowLog, Warning, TEXT("UnrealEnginePython Plugin not found! Make sure you've enabled it in Edit->Plugins.")); - } } void FTensorFlowModule::ShutdownModule() diff --git a/Source/TensorFlow/TensorFlow.Build.cs b/Source/TensorFlow/TensorFlow.Build.cs index 4062a48..60ac47a 100644 --- a/Source/TensorFlow/TensorFlow.Build.cs +++ b/Source/TensorFlow/TensorFlow.Build.cs @@ -61,7 +61,7 @@ public TensorFlow(ReadOnlyTargetRules Target) : base(Target) "RHI", "RenderCore", "Engine", - "UnrealEnginePython" + "MachineLearningRemote" // ... add other public dependencies that you statically link with here ... } ); diff --git a/TensorFlow.uplugin b/TensorFlow.uplugin index 406192b..db214dd 100644 --- a/TensorFlow.uplugin +++ b/TensorFlow.uplugin @@ -1,7 +1,7 @@ { "FileVersion": 3, "Version": 1, - "VersionName": "0.14.0", + "VersionName": "1.0.0alpha", "FriendlyName": "TensorFlow", "Description": "Unofficial TensorFlow plugin for UE4. Enables state of the art machine learning via python and blueprints.", "Category": "Computing", @@ -25,7 +25,7 @@ }, { "Name": "TFAudioCapture", - "Type": "Developer", + "Type": "Runtime", "LoadingPhase": "Default", "WhitelistPlatforms": [ "Win64", @@ -35,11 +35,11 @@ ], "Plugins": [ { - "Name": "UnrealEnginePython", + "Name": "SocketIOClient", "Enabled": true }, { - "Name": "SocketIOClient", + "Name": "MachineLearningRemote", "Enabled": true } ]