Created
February 2, 2017 16:50
-
-
Save emrahgunduz/02c70c25da68e0f1d414d1c030dc0038 to your computer and use it in GitHub Desktop.
Javascript - Unreal connection via tick message calls
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function Act () { | |
this.name = "null"; | |
this.type = 0; | |
this.message = ""; | |
} | |
var actions = []; | |
var currentAction; | |
/** | |
* Add an action | |
* @param name string | |
* @param type int 0 - has no message, 1 - with message | |
* @param message | |
*/ | |
function actionAdd ( name, type, message ) { | |
var a = new Act(); | |
a.name = name; | |
if ( !!type ) | |
a.type = type; | |
if ( !!message ) | |
a.message = JSON.stringify( message ); | |
actions.push( a ); | |
} | |
function actionCount () { | |
return actions.length; | |
} | |
function actionLoadNext () { | |
currentAction = actions.shift(); | |
} | |
function actionType () { | |
return currentAction.type; | |
} | |
function actionName () { | |
return currentAction.name; | |
} | |
function actionMessage () { | |
return currentAction.message; | |
} | |
function actionReset () { | |
actions = []; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Fill out your copyright notice in the Description page of Project Settings. | |
#include "ExpoKid.h" | |
#include "JavascriptCaller.h" | |
#include <string> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <algorithm> | |
UJavascriptCaller::UJavascriptCaller(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer) | |
{ | |
JsonInObjectData = MakeShareable(new FJsonObject()); | |
JsonOutObjectData = MakeShareable(new FJsonObject()); | |
} | |
UJavascriptCaller *UJavascriptCaller::Tick() | |
{ | |
#ifdef EMSCRIPTEN | |
int actionCount = emscripten_run_script_int("actionCount()"); | |
if (actionCount > 0) { | |
int currentIndex = 0; | |
while (currentIndex < actionCount) { | |
emscripten_run_script("actionLoadNext()"); | |
int actionType = emscripten_run_script_int("actionType()"); | |
char *aAction = emscripten_run_script_string("actionName()"); | |
const char* aActionChar = reinterpret_cast<const char*>(aAction); | |
std::string aActionStr(aActionChar); | |
FString aActionFStr = UTF8_TO_TCHAR(aActionStr.c_str()); | |
if (actionType == 1) { | |
// Action has message | |
char *aMessage = emscripten_run_script_string("actionMessage()"); | |
const char* aMessageChar = reinterpret_cast<const char*>(aMessage); | |
std::string aMessageStr(aMessageChar); | |
FString ReceivedString = UTF8_TO_TCHAR(aMessageStr.c_str()); | |
UE_LOG(EXPOKID, Warning, TEXT("[JavascriptCaller::Tick] > Answer for action %s : %s"), UTF8_TO_TCHAR(aActionStr.c_str()), UTF8_TO_TCHAR(aMessageStr.c_str())); | |
JsonInObjectData = MakeShareable(new FJsonObject()); | |
TSharedRef<TJsonReader<TCHAR>> JsonReader = TJsonReaderFactory<TCHAR>::Create(ReceivedString); | |
bool isDeserialized = FJsonSerializer::Deserialize(JsonReader, JsonInObjectData); | |
if (!(isDeserialized && JsonInObjectData.IsValid())) { | |
UE_LOG(EXPOKID, Error, TEXT("[JavascriptCaller::Tick] > JSON is not valid")); | |
} | |
} | |
else { | |
UE_LOG(EXPOKID, Warning, TEXT("[JavascriptCaller::Tick] > Answer for action %s"), UTF8_TO_TCHAR(aActionStr.c_str())); | |
} | |
OnJavascriptActionReceived.Broadcast(aActionFStr); | |
currentIndex++; | |
} | |
} | |
#endif | |
return this; | |
} | |
UJavascriptCaller *UJavascriptCaller::CallJavascript(FString jsMethodName) | |
{ | |
std::string jsMethodNameStr(TCHAR_TO_UTF8(*jsMethodName)); | |
jsMethodNameStr.append("()"); | |
UE_LOG(EXPOKID, Error, TEXT("[UJavascriptCaller::CallJavascript] > A javascript method is called: %s"), UTF8_TO_TCHAR(jsMethodNameStr.c_str())); | |
#ifdef EMSCRIPTEN | |
const char * jsMethodNameChar = jsMethodNameStr.c_str(); | |
char *Buffer; | |
Buffer = emscripten_run_script_string(jsMethodNameChar); | |
const char* buf = reinterpret_cast<const char*>(Buffer); | |
std::string cstr(buf); | |
FString ReceivedString = UTF8_TO_TCHAR(cstr.c_str()); | |
UE_LOG(EXPOKID, Error, TEXT("[UJavascriptCaller::CallJavascript] > Returned answer for %s : %s"), UTF8_TO_TCHAR(jsMethodNameStr.c_str()), UTF8_TO_TCHAR(cstr.c_str())); | |
JsonInObjectData = MakeShareable(new FJsonObject()); | |
TSharedRef<TJsonReader<TCHAR>> JsonReader = TJsonReaderFactory<TCHAR>::Create(ReceivedString); | |
bool isDeserialized = FJsonSerializer::Deserialize(JsonReader, JsonInObjectData); | |
if (!(isDeserialized && JsonInObjectData.IsValid())) { | |
UE_LOG(EXPOKID, Error, TEXT("[UJavascriptCaller::CallJavascript] > JavascriptCaller::CallJavascript JSON is not valid")); | |
} | |
#endif | |
return this; | |
} | |
UJavascriptCaller *UJavascriptCaller::CallJavascriptVoid(FString jsMethodName) | |
{ | |
std::string jsMethodNameStr(TCHAR_TO_UTF8(*jsMethodName)); | |
jsMethodNameStr.append("()"); | |
UE_LOG(EXPOKID, Error, TEXT("[UJavascriptCaller::CallJavascriptVoid] > A javascript method is called: %s"), UTF8_TO_TCHAR(jsMethodNameStr.c_str())); | |
#ifdef EMSCRIPTEN | |
const char * jsMethodNameChar = jsMethodNameStr.c_str(); | |
emscripten_run_script(jsMethodNameChar); | |
#endif | |
return this; | |
} | |
UJavascriptCaller *UJavascriptCaller::CallJavascriptWithMessage(FString jsMethodName) | |
{ | |
if (!JsonOutObjectData.IsValid()) { | |
UE_LOG(EXPOKID, Error, TEXT("[UJavascriptCaller::CallJavascriptWithMessage] > Outgoing JSON is not valid")); | |
return this; | |
} | |
FString OutputString; | |
TSharedRef<TJsonWriter<TCHAR>> JsonWriter = TJsonWriterFactory<TCHAR>::Create(&OutputString); | |
WriteObject(JsonWriter, "", new FJsonValueObject(JsonOutObjectData)); | |
JsonWriter->Close(); | |
std::string OutputStringStr(TCHAR_TO_UTF8(*OutputString)); | |
std::string jsMethodNameStr(TCHAR_TO_UTF8(*jsMethodName)); | |
jsMethodNameStr.append("('" + OutputStringStr + "')"); | |
jsMethodNameStr.erase(std::remove(jsMethodNameStr.begin(), jsMethodNameStr.end(), '\n'), jsMethodNameStr.end()); | |
jsMethodNameStr.erase(std::remove(jsMethodNameStr.begin(), jsMethodNameStr.end(), '\r'), jsMethodNameStr.end()); | |
jsMethodNameStr.erase(std::remove(jsMethodNameStr.begin(), jsMethodNameStr.end(), '\t'), jsMethodNameStr.end()); | |
UE_LOG(EXPOKID, Error, TEXT("[UJavascriptCaller::CallJavascriptWithMessage] > A javascript method is called: %s"), UTF8_TO_TCHAR(jsMethodNameStr.c_str())); | |
#ifdef EMSCRIPTEN | |
const char * jsMethodNameChar = jsMethodNameStr.c_str(); | |
char *Buffer; | |
Buffer = emscripten_run_script_string(jsMethodNameChar); | |
const char* buf = reinterpret_cast<const char*>(Buffer); | |
std::string cstr(buf); | |
FString ReceivedString = UTF8_TO_TCHAR(cstr.c_str()); | |
UE_LOG(EXPOKID, Error, TEXT("[UJavascriptCaller::CallJavascriptWithMessage] > Returned answer for %s : %s"), UTF8_TO_TCHAR(jsMethodNameStr.c_str()), UTF8_TO_TCHAR(cstr.c_str())); | |
JsonInObjectData = MakeShareable(new FJsonObject()); | |
TSharedRef<TJsonReader<TCHAR>> JsonReader = TJsonReaderFactory<TCHAR>::Create(ReceivedString); | |
bool isDeserialized = FJsonSerializer::Deserialize(JsonReader, JsonInObjectData); | |
if (!(isDeserialized && JsonInObjectData.IsValid())) { | |
UE_LOG(EXPOKID, Error, TEXT("[UJavascriptCaller::CallJavascriptWithMessage] > JavascriptCaller::CallJavascriptWithMessage JSON is not valid")); | |
} | |
#endif | |
return this; | |
} | |
UJavascriptCaller *UJavascriptCaller::CallJavascriptWithMessageVoid(FString jsMethodName) | |
{ | |
if (!JsonOutObjectData.IsValid()) { | |
UE_LOG(EXPOKID, Error, TEXT("[UJavascriptCaller::CallJavascriptWithMessageVoid] > Outgoing JSON is not valid")); | |
return this; | |
} | |
FString OutputString; | |
TSharedRef<TJsonWriter<TCHAR>> JsonWriter = TJsonWriterFactory<TCHAR>::Create(&OutputString); | |
WriteObject(JsonWriter, "", new FJsonValueObject(JsonOutObjectData)); | |
JsonWriter->Close(); | |
std::string OutputStringStr(TCHAR_TO_UTF8(*OutputString)); | |
std::string jsMethodNameStr(TCHAR_TO_UTF8(*jsMethodName)); | |
jsMethodNameStr.append("('" + OutputStringStr + "')"); | |
jsMethodNameStr.erase(std::remove(jsMethodNameStr.begin(), jsMethodNameStr.end(), '\n'), jsMethodNameStr.end()); | |
jsMethodNameStr.erase(std::remove(jsMethodNameStr.begin(), jsMethodNameStr.end(), '\r'), jsMethodNameStr.end()); | |
jsMethodNameStr.erase(std::remove(jsMethodNameStr.begin(), jsMethodNameStr.end(), '\t'), jsMethodNameStr.end()); | |
UE_LOG(EXPOKID, Error, TEXT("[UJavascriptCaller::CallJavascriptWithMessageVoid] > A javascript method is called: %s"), UTF8_TO_TCHAR(jsMethodNameStr.c_str())); | |
#ifdef EMSCRIPTEN | |
const char * jsMethodNameChar = jsMethodNameStr.c_str(); | |
emscripten_run_script(jsMethodNameChar); | |
#endif | |
return this; | |
} | |
UJavascriptCaller *UJavascriptCaller::JavascriptJsonMessageInit() | |
{ | |
JsonOutObjectData.Reset(); | |
JsonOutObjectData = MakeShareable(new FJsonObject()); | |
return this; | |
} | |
UJavascriptCaller *UJavascriptCaller::JavascriptJsonMessageSetString(const FString &key, const FString &value) | |
{ | |
JsonOutObjectData->SetStringField(*key, *value); | |
return this; | |
} | |
UJavascriptCaller *UJavascriptCaller::JavascriptJsonMessageGetString(const FString &key, FString &value) | |
{ | |
value = JsonInObjectData->GetStringField(key); | |
return this; | |
} | |
UJavascriptCaller *UJavascriptCaller::JavascriptJsonMessageGetInteger(const FString &key, int32 &value) | |
{ | |
value = (int32)JsonInObjectData->GetNumberField(key); | |
return this; | |
} | |
UJavascriptCaller *UJavascriptCaller::JavascriptJsonMessageGetFloat(const FString &key, float &value) | |
{ | |
value = (float)JsonInObjectData->GetNumberField(key); | |
return this; | |
} | |
UJavascriptCaller *UJavascriptCaller::JavascriptJsonMessageGetBoolean(const FString &key, bool &value) | |
{ | |
value = JsonInObjectData->GetBoolField(key); | |
return this; | |
} | |
TArray<FString> UJavascriptCaller::JavascriptJsonMessageGetStringArray(const FString &key) | |
{ | |
TArray<FString> stringArray; | |
const TArray<TSharedPtr<FJsonValue>> *arrayPtr; | |
if (JsonInObjectData->TryGetArrayField(*key, arrayPtr)) { | |
for (int32 i = 0; i < arrayPtr->Num(); i++) { | |
stringArray.Add((*arrayPtr)[i]->AsString()); | |
} | |
} | |
return stringArray; | |
} | |
TArray<int32> UJavascriptCaller::JavascriptJsonMessageGetIntegerArray(const FString &key) | |
{ | |
TArray<int32> stringArray; | |
const TArray<TSharedPtr<FJsonValue>> *arrayPtr; | |
if (JsonInObjectData->TryGetArrayField(*key, arrayPtr)) { | |
for (int32 i = 0; i < arrayPtr->Num(); i++) { | |
stringArray.Add((int const &)(*arrayPtr)[i]->AsNumber()); | |
} | |
} | |
return stringArray; | |
} | |
TArray<float> UJavascriptCaller::JavascriptJsonMessageGetFloatArray(const FString &key) | |
{ | |
TArray<float> floatArray; | |
const TArray<TSharedPtr<FJsonValue>> *arrayPtr; | |
if (JsonInObjectData->TryGetArrayField(*key, arrayPtr)) { | |
for (int32 i = 0; i < arrayPtr->Num(); i++) { | |
floatArray.Add((float const &)(*arrayPtr)[i]->AsNumber()); | |
} | |
} | |
return floatArray; | |
} | |
void UJavascriptCaller::WriteObject(TSharedRef<TJsonWriter<TCHAR>> writer, FString key, FJsonValue *value) | |
{ | |
if (value->Type == EJson::String) { | |
// Write simple string entry, don't need a key when it isn't set | |
if (key.Len() > 0) { | |
writer->WriteValue(key, value->AsString()); | |
} | |
else { | |
writer->WriteValue(value->AsString()); | |
} | |
} | |
else if (value->Type == EJson::Object) { | |
// Write object entry | |
if (key.Len() > 0) { | |
writer->WriteObjectStart(key); | |
} | |
else { | |
writer->WriteObjectStart(); | |
} | |
// Loop through all the values in the object data | |
TSharedPtr<FJsonObject> objectData = value->AsObject(); | |
for (auto objectValue = objectData->Values.CreateIterator(); objectValue; ++objectValue) { | |
// Using recursion to write the key and value to the writer | |
WriteObject(writer, objectValue.Key(), objectValue.Value().Get()); | |
} | |
writer->WriteObjectEnd(); | |
} | |
else if (value->Type == EJson::Array) { | |
// Process array entry | |
writer->WriteArrayStart(key); | |
TArray<TSharedPtr<FJsonValue>> objectArray = value->AsArray(); | |
for (int32 i = 0; i < objectArray.Num(); i++) { | |
// Use recursion with an empty key to process all the values in the array | |
WriteObject(writer, "", objectArray[i].Get()); | |
} | |
writer->WriteArrayEnd(); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#ifdef EMSCRIPTEN | |
#include <emscripten.h> | |
#endif | |
#include "Delegate.h" | |
#include "Object.h" | |
#include "JavascriptCaller.generated.h" | |
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FJavascriptCaller_OnAction, FString, action); | |
UCLASS(Blueprintable, BlueprintType) | |
class EXPOKID_API UJavascriptCaller : public UObject | |
{ | |
GENERATED_UCLASS_BODY() | |
public: | |
UPROPERTY(BlueprintAssignable, Category = "Javascript") | |
FJavascriptCaller_OnAction OnJavascriptActionReceived; | |
UFUNCTION(BlueprintCallable, Category = "Javascript") | |
UJavascriptCaller *Tick(); | |
UFUNCTION(BlueprintCallable, Category = "Javascript") | |
UJavascriptCaller *CallJavascript(FString jsMethodName); | |
UFUNCTION(BlueprintCallable, Category = "Javascript") | |
UJavascriptCaller *CallJavascriptVoid(FString jsMethodName); | |
UFUNCTION(BlueprintCallable, Category = "Javascript") | |
UJavascriptCaller *CallJavascriptWithMessage(FString jsMethodName); | |
UFUNCTION(BlueprintCallable, Category = "Javascript") | |
UJavascriptCaller *CallJavascriptWithMessageVoid(FString jsMethodName); | |
UFUNCTION(BlueprintCallable, Category = "Javascript") | |
UJavascriptCaller *JavascriptJsonMessageGetString(const FString &key, FString &value); | |
UFUNCTION(BlueprintCallable, Category = "Javascript") | |
UJavascriptCaller *JavascriptJsonMessageGetInteger(const FString &key, int32 &value); | |
UFUNCTION(BlueprintCallable, Category = "Javascript") | |
UJavascriptCaller *JavascriptJsonMessageGetFloat(const FString &key, float &value); | |
UFUNCTION(BlueprintCallable, Category = "Javascript") | |
UJavascriptCaller *JavascriptJsonMessageGetBoolean(const FString &key, bool &value); | |
UFUNCTION(BlueprintCallable, Category = "Javascript") | |
TArray<FString> JavascriptJsonMessageGetStringArray(const FString &key); | |
UFUNCTION(BlueprintCallable, Category = "Javascript") | |
TArray<int32> JavascriptJsonMessageGetIntegerArray(const FString &key); | |
UFUNCTION(BlueprintCallable, Category = "Javascript") | |
TArray<float> JavascriptJsonMessageGetFloatArray(const FString &key); | |
UFUNCTION(BlueprintCallable, Category = "Javascript") | |
UJavascriptCaller *JavascriptJsonMessageInit(); | |
UFUNCTION(BlueprintCallable, Category = "Javascript") | |
UJavascriptCaller *JavascriptJsonMessageSetString(const FString &key, const FString &value); | |
private: | |
TSharedPtr<FJsonObject> JsonInObjectData; | |
TSharedPtr<FJsonObject> JsonOutObjectData; | |
void WriteObject(TSharedRef<TJsonWriter<TCHAR>> writer, FString key, FJsonValue *value); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment