├── Config ├── DefaultEditor.ini ├── DefaultGame.ini └── DefaultEngine.ini ├── Build ├── ScriptInstallServer.cmd ├── ScriptStartServer.cmd ├── package.json └── ServerNode.js ├── images └── image_1.png ├── Content ├── SampleLevel.umap ├── SampleLevel_BuiltData.uasset └── SampleWidgetBlueprint.uasset ├── .gitignore ├── Plugins └── HTML5SamplePlugin │ ├── Resources │ └── Icon128.png │ ├── Source │ └── HTML5SamplePlugin │ │ ├── Private │ │ ├── SampleHTML5.cpp │ │ ├── HTML5SamplePlugin.cpp │ │ └── HTML5SamplePluginBPLibrary.cpp │ │ ├── Public │ │ ├── SampleHTML5.h │ │ ├── HTML5SamplePlugin.h │ │ ├── SampleHTML5.js │ │ └── HTML5SamplePluginBPLibrary.h │ │ └── HTML5SamplePlugin.Build.cs │ └── HTML5SamplePlugin.uplugin ├── Source ├── UE4HTML5SamplePlugin │ ├── UE4HTML5SamplePlugin.h │ ├── UE4HTML5SamplePluginGameModeBase.cpp │ ├── UE4HTML5SamplePlugin.cpp │ ├── UE4HTML5SamplePluginGameModeBase.h │ └── UE4HTML5SamplePlugin.Build.cs ├── UE4HTML5SamplePlugin.Target.cs └── UE4HTML5SamplePluginEditor.Target.cs ├── UE4HTML5SamplePlugin.uproject └── README.md /Config/DefaultEditor.ini: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Build/ScriptInstallServer.cmd: -------------------------------------------------------------------------------- 1 | CALL npm install 2 | PAUSE 3 | -------------------------------------------------------------------------------- /images/image_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tgraupmann/UE4HTML5SamplePlugin/HEAD/images/image_1.png -------------------------------------------------------------------------------- /Content/SampleLevel.umap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tgraupmann/UE4HTML5SamplePlugin/HEAD/Content/SampleLevel.umap -------------------------------------------------------------------------------- /Build/ScriptStartServer.cmd: -------------------------------------------------------------------------------- 1 | start "" "http://localhost:5001/HTML5/UE4HTML5SamplePlugin.html" 2 | node ServerNode.js 3 | -------------------------------------------------------------------------------- /Config/DefaultGame.ini: -------------------------------------------------------------------------------- 1 | [/Script/EngineSettings.GeneralProjectSettings] 2 | ProjectID=C0931F7A459B7196A5453E9685C096A4 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | UE4HTML5SamplePlugin.sln 2 | .vs/ 3 | Binaries/ 4 | Intermediate/ 5 | Saved/ 6 | Build/package-lock.json 7 | Build/ 8 | -------------------------------------------------------------------------------- /Content/SampleLevel_BuiltData.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tgraupmann/UE4HTML5SamplePlugin/HEAD/Content/SampleLevel_BuiltData.uasset -------------------------------------------------------------------------------- /Content/SampleWidgetBlueprint.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tgraupmann/UE4HTML5SamplePlugin/HEAD/Content/SampleWidgetBlueprint.uasset -------------------------------------------------------------------------------- /Plugins/HTML5SamplePlugin/Resources/Icon128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tgraupmann/UE4HTML5SamplePlugin/HEAD/Plugins/HTML5SamplePlugin/Resources/Icon128.png -------------------------------------------------------------------------------- /Source/UE4HTML5SamplePlugin/UE4HTML5SamplePlugin.h: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | 7 | -------------------------------------------------------------------------------- /Source/UE4HTML5SamplePlugin/UE4HTML5SamplePluginGameModeBase.cpp: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | 4 | #include "UE4HTML5SamplePluginGameModeBase.h" 5 | 6 | -------------------------------------------------------------------------------- /Plugins/HTML5SamplePlugin/Source/HTML5SamplePlugin/Private/SampleHTML5.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2019 Epic Games, Inc. All Rights Reserved. 2 | #include "SampleHTML5.h" 3 | 4 | // make build systems happy. 5 | static bool SAMPLEHTML5NOOP() { return true; } 6 | -------------------------------------------------------------------------------- /UE4HTML5SamplePlugin.uproject: -------------------------------------------------------------------------------- 1 | { 2 | "FileVersion": 3, 3 | "EngineAssociation": "4.22", 4 | "Category": "", 5 | "Description": "", 6 | "Modules": [ 7 | { 8 | "Name": "UE4HTML5SamplePlugin", 9 | "Type": "Runtime", 10 | "LoadingPhase": "Default" 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /Source/UE4HTML5SamplePlugin/UE4HTML5SamplePlugin.cpp: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #include "UE4HTML5SamplePlugin.h" 4 | #include "Modules/ModuleManager.h" 5 | 6 | IMPLEMENT_PRIMARY_GAME_MODULE( FDefaultGameModuleImpl, UE4HTML5SamplePlugin, "UE4HTML5SamplePlugin" ); 7 | -------------------------------------------------------------------------------- /Plugins/HTML5SamplePlugin/Source/HTML5SamplePlugin/Public/SampleHTML5.h: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2019 Epic Games, Inc. All Rights Reserved. 2 | #pragma once 3 | 4 | extern "C" { 5 | void UE_InitSampleHTML5(); 6 | // register function to call from JS 7 | void SampleHTML5_RegisterStringFunction(void(*listener)(const char* str)); 8 | } 9 | -------------------------------------------------------------------------------- /Build/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "chromanode", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "express": "^4.14.0", 13 | "nodemon": "^1.11.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Build/ServerNode.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const app = express(); 3 | app.use(function (req, res, next) { 4 | res.setHeader('Access-Control-Allow-Origin', '*'); 5 | next(); 6 | }); 7 | 8 | app.use(express.static('.')); 9 | 10 | app.use(express.static('..')); 11 | 12 | app.listen(5001, function () { 13 | console.log('Example app listening on port 5001!'); 14 | }) 15 | -------------------------------------------------------------------------------- /Plugins/HTML5SamplePlugin/Source/HTML5SamplePlugin/Public/HTML5SamplePlugin.h: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2019 Epic Games, Inc. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "Modules/ModuleManager.h" 6 | 7 | class FHTML5SamplePluginModule : public IModuleInterface 8 | { 9 | public: 10 | 11 | /** IModuleInterface implementation */ 12 | virtual void StartupModule() override; 13 | virtual void ShutdownModule() override; 14 | }; 15 | -------------------------------------------------------------------------------- /Source/UE4HTML5SamplePlugin.Target.cs: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | using UnrealBuildTool; 4 | using System.Collections.Generic; 5 | 6 | public class UE4HTML5SamplePluginTarget : TargetRules 7 | { 8 | public UE4HTML5SamplePluginTarget(TargetInfo Target) : base(Target) 9 | { 10 | Type = TargetType.Game; 11 | 12 | ExtraModuleNames.AddRange( new string[] { "UE4HTML5SamplePlugin" } ); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Source/UE4HTML5SamplePlugin/UE4HTML5SamplePluginGameModeBase.h: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "GameFramework/GameModeBase.h" 7 | #include "UE4HTML5SamplePluginGameModeBase.generated.h" 8 | 9 | /** 10 | * 11 | */ 12 | UCLASS() 13 | class UE4HTML5SAMPLEPLUGIN_API AUE4HTML5SamplePluginGameModeBase : public AGameModeBase 14 | { 15 | GENERATED_BODY() 16 | 17 | }; 18 | -------------------------------------------------------------------------------- /Source/UE4HTML5SamplePluginEditor.Target.cs: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | using UnrealBuildTool; 4 | using System.Collections.Generic; 5 | 6 | public class UE4HTML5SamplePluginEditorTarget : TargetRules 7 | { 8 | public UE4HTML5SamplePluginEditorTarget(TargetInfo Target) : base(Target) 9 | { 10 | Type = TargetType.Editor; 11 | 12 | ExtraModuleNames.AddRange( new string[] { "UE4HTML5SamplePlugin" } ); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Plugins/HTML5SamplePlugin/HTML5SamplePlugin.uplugin: -------------------------------------------------------------------------------- 1 | { 2 | "FileVersion": 3, 3 | "Version": 1, 4 | "VersionName": "1.0", 5 | "FriendlyName": "HTML5SamplePlugin", 6 | "Description": "", 7 | "Category": "Other", 8 | "CreatedBy": "", 9 | "CreatedByURL": "", 10 | "DocsURL": "", 11 | "MarketplaceURL": "", 12 | "SupportURL": "", 13 | "CanContainContent": true, 14 | "IsBetaVersion": false, 15 | "Installed": false, 16 | "Modules": [ 17 | { 18 | "Name": "HTML5SamplePlugin", 19 | "Type": "Runtime", 20 | "LoadingPhase": "PreLoadingScreen" 21 | } 22 | ] 23 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # UE4 HTML5 Sample Plugin 2 | 3 | This repository holds an example UE4 project created in 4.22. 4 | 5 | The intent of this project is to include custom HTML5 (provided from a UE4 Plugin) and invoke JS methods from a button widget. 6 | 7 | ![image_1](images/image_1.png) 8 | 9 | ## See Also 10 | 11 | * [UE4HTML5SampleSource](https://github.com/tgraupmann/UE4HTML5SampleSource) - Include HTML5 from game source 12 | 13 | * [UE4HTML5SamplePlugin](https://github.com/tgraupmann/UE4HTML5SamplePlugin) - Include HTML5 from a UE4 plugin 14 | 15 | ## Support 16 | 17 | Support is available on Discord, you can reach me at `Tim Graupmann#0611`. 18 | -------------------------------------------------------------------------------- /Plugins/HTML5SamplePlugin/Source/HTML5SamplePlugin/Private/HTML5SamplePlugin.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2019 Epic Games, Inc. All Rights Reserved. 2 | 3 | #include "HTML5SamplePlugin.h" 4 | 5 | #define LOCTEXT_NAMESPACE "FHTML5SamplePluginModule" 6 | 7 | void FHTML5SamplePluginModule::StartupModule() 8 | { 9 | // This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module 10 | 11 | } 12 | 13 | void FHTML5SamplePluginModule::ShutdownModule() 14 | { 15 | // This function may be called during shutdown to clean up your module. For modules that support dynamic reloading, 16 | // we call this function before unloading the module. 17 | 18 | } 19 | 20 | #undef LOCTEXT_NAMESPACE 21 | 22 | IMPLEMENT_MODULE(FHTML5SamplePluginModule, HTML5SamplePlugin) -------------------------------------------------------------------------------- /Plugins/HTML5SamplePlugin/Source/HTML5SamplePlugin/Private/HTML5SamplePluginBPLibrary.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2019 Epic Games, Inc. All Rights Reserved. 2 | 3 | #include "HTML5SamplePluginBPLibrary.h" 4 | #include "HTML5SamplePlugin.h" 5 | #include "SampleHTML5.h" 6 | 7 | UHTML5SamplePluginBPLibrary::UHTML5SamplePluginBPLibrary(const FObjectInitializer& ObjectInitializer) 8 | : Super(ObjectInitializer) 9 | { 10 | 11 | } 12 | 13 | void UHTML5SamplePluginBPLibrary::SampleInit() 14 | { 15 | #ifdef __EMSCRIPTEN__ 16 | /* register the listener */ 17 | SampleHTML5_RegisterStringFunction(&Callback_RegisterStringFunction); 18 | #endif 19 | 20 | #if PLATFORM_HTML5 21 | UE_InitSampleHTML5(); 22 | #endif 23 | } 24 | 25 | void UHTML5SamplePluginBPLibrary::Callback_RegisterStringFunction(const char* str) 26 | { 27 | UE_LOG(LogTemp, Log, TEXT("UHTML5SamplePluginBPLibrary::Callback_RegisterStringFunction invoked\r\n")); 28 | } 29 | -------------------------------------------------------------------------------- /Source/UE4HTML5SamplePlugin/UE4HTML5SamplePlugin.Build.cs: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | using UnrealBuildTool; 4 | 5 | public class UE4HTML5SamplePlugin : ModuleRules 6 | { 7 | public UE4HTML5SamplePlugin(ReadOnlyTargetRules Target) : base(Target) 8 | { 9 | PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; 10 | 11 | PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore" }); 12 | 13 | PrivateDependencyModuleNames.AddRange(new string[] { }); 14 | 15 | // Uncomment if you are using Slate UI 16 | // PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" }); 17 | 18 | // Uncomment if you are using online features 19 | // PrivateDependencyModuleNames.Add("OnlineSubsystem"); 20 | 21 | // To include OnlineSubsystemSteam, add it to the plugins section in your uproject file with the Enabled attribute set to true 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Plugins/HTML5SamplePlugin/Source/HTML5SamplePlugin/Public/SampleHTML5.js: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2019 Epic Games, Inc. All Rights Reserved. 2 | 3 | var UE_SampleHTML5 = { 4 | // call from C++ to register function 5 | SampleHTML5_RegisterStringFunction: function (listener) { 6 | // save a reference to the listener to later call back into C++ 7 | UE_JSSampleHTML5.Callback_RegisterStringFunction = function (str) { 8 | var cname = _malloc(str.length + 1); 9 | stringToUTF8(str, cname, str.length + 1); 10 | Runtime.dynCall('vi', listener, [cname]); 11 | } 12 | }, 13 | // function to be called from C++ 14 | UE_InitSampleHTML5: function () { 15 | UE_JSSampleHTML5.UE_InitSampleHTML5(); 16 | }, 17 | // persistant OBJECT accessible within JS code 18 | $UE_JSSampleHTML5: { 19 | UE_InitSampleHTML5: function () { 20 | console.log('UE_InitSampleHTML5'); 21 | 22 | // Invoke C++ from JS 23 | this.Callback_RegisterStringFunction('Invoking callback!'); 24 | } 25 | } 26 | }; 27 | 28 | autoAddDeps(UE_SampleHTML5, '$UE_JSSampleHTML5'); 29 | mergeInto(LibraryManager.library, UE_SampleHTML5); 30 | -------------------------------------------------------------------------------- /Plugins/HTML5SamplePlugin/Source/HTML5SamplePlugin/HTML5SamplePlugin.Build.cs: -------------------------------------------------------------------------------- 1 | // Some copyright should be here... 2 | 3 | using UnrealBuildTool; 4 | 5 | public class HTML5SamplePlugin : ModuleRules 6 | { 7 | public HTML5SamplePlugin(ReadOnlyTargetRules Target) : base(Target) 8 | { 9 | PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; 10 | 11 | PublicIncludePaths.AddRange( 12 | new string[] { 13 | // ... add public include paths required here ... 14 | } 15 | ); 16 | 17 | 18 | PrivateIncludePaths.AddRange( 19 | new string[] { 20 | // ... add other private include paths required here ... 21 | } 22 | ); 23 | 24 | 25 | PublicDependencyModuleNames.AddRange( 26 | new string[] 27 | { 28 | "Core", 29 | // ... add other public dependencies that you statically link with here ... 30 | } 31 | ); 32 | 33 | 34 | PrivateDependencyModuleNames.AddRange( 35 | new string[] 36 | { 37 | "CoreUObject", 38 | "Engine", 39 | "Slate", 40 | "SlateCore", 41 | // ... add private dependencies that you statically link with here ... 42 | } 43 | ); 44 | 45 | 46 | DynamicallyLoadedModuleNames.AddRange( 47 | new string[] 48 | { 49 | // ... add any modules that your module loads dynamically here ... 50 | } 51 | ); 52 | 53 | if (Target.Platform == UnrealTargetPlatform.HTML5) 54 | { 55 | string path = System.IO.Path.Combine(ModuleDirectory, "Public/SampleHTML5.js").Replace("\\", "/"); 56 | System.Console.WriteLine("Include {0}", path); 57 | PublicAdditionalLibraries.Add(path); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /Plugins/HTML5SamplePlugin/Source/HTML5SamplePlugin/Public/HTML5SamplePluginBPLibrary.h: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2019 Epic Games, Inc. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "Kismet/BlueprintFunctionLibrary.h" 6 | #include "HTML5SamplePluginBPLibrary.generated.h" 7 | 8 | /* 9 | * Function library class. 10 | * Each function in it is expected to be static and represents blueprint node that can be called in any blueprint. 11 | * 12 | * When declaring function you can define metadata for the node. Key function specifiers will be BlueprintPure and BlueprintCallable. 13 | * BlueprintPure - means the function does not affect the owning object in any way and thus creates a node without Exec pins. 14 | * BlueprintCallable - makes a function which can be executed in Blueprints - Thus it has Exec pins. 15 | * DisplayName - full name of the node, shown when you mouse over the node and in the blueprint drop down menu. 16 | * Its lets you name the node using characters not allowed in C++ function names. 17 | * CompactNodeTitle - the word(s) that appear on the node. 18 | * Keywords - the list of keywords that helps you to find node when you search for it using Blueprint drop-down menu. 19 | * Good example is "Print String" node which you can find also by using keyword "log". 20 | * Category - the category your node will be under in the Blueprint drop-down menu. 21 | * 22 | * For more info on custom blueprint nodes visit documentation: 23 | * https://wiki.unrealengine.com/Custom_Blueprint_Node_Creation 24 | */ 25 | UCLASS() 26 | class UHTML5SamplePluginBPLibrary : public UBlueprintFunctionLibrary 27 | { 28 | GENERATED_UCLASS_BODY() 29 | 30 | UFUNCTION(BlueprintCallable, meta = (DisplayName = "SampleInit", Keywords = "Invoke Sample JS"), Category = "Sample") 31 | static void SampleInit(); 32 | 33 | static void Callback_RegisterStringFunction(const char* str); 34 | }; 35 | -------------------------------------------------------------------------------- /Config/DefaultEngine.ini: -------------------------------------------------------------------------------- 1 | [URL] 2 | [/Script/Engine.RendererSettings] 3 | r.DefaultFeature.AutoExposure.ExtendDefaultLuminanceRange=True 4 | 5 | [/Script/HardwareTargeting.HardwareTargetingSettings] 6 | TargetedHardwareClass=Desktop 7 | AppliedTargetedHardwareClass=Desktop 8 | DefaultGraphicsPerformance=Maximum 9 | AppliedDefaultGraphicsPerformance=Maximum 10 | 11 | [/Script/EngineSettings.GameMapsSettings] 12 | EditorStartupMap=/Game/SampleLevel.SampleLevel 13 | GameDefaultMap=/Game/SampleLevel.SampleLevel 14 | 15 | [/Script/Engine.PhysicsSettings] 16 | DefaultGravityZ=-980.000000 17 | DefaultTerminalVelocity=4000.000000 18 | DefaultFluidFriction=0.300000 19 | SimulateScratchMemorySize=262144 20 | RagdollAggregateThreshold=4 21 | TriangleMeshTriangleMinAreaThreshold=5.000000 22 | bEnableShapeSharing=False 23 | bEnablePCM=True 24 | bEnableStabilization=False 25 | bWarnMissingLocks=True 26 | bEnable2DPhysics=False 27 | PhysicErrorCorrection=(PingExtrapolation=0.100000,PingLimit=100.000000,ErrorPerLinearDifference=1.000000,ErrorPerAngularDifference=1.000000,MaxRestoredStateError=1.000000,MaxLinearHardSnapDistance=400.000000,PositionLerp=0.000000,AngleLerp=0.400000,LinearVelocityCoefficient=100.000000,AngularVelocityCoefficient=10.000000,ErrorAccumulationSeconds=0.500000,ErrorAccumulationDistanceSq=15.000000,ErrorAccumulationSimilarity=100.000000) 28 | LockedAxis=Invalid 29 | DefaultDegreesOfFreedom=Full3D 30 | BounceThresholdVelocity=200.000000 31 | FrictionCombineMode=Average 32 | RestitutionCombineMode=Average 33 | MaxAngularVelocity=3600.000000 34 | MaxDepenetrationVelocity=0.000000 35 | ContactOffsetMultiplier=0.020000 36 | MinContactOffset=2.000000 37 | MaxContactOffset=8.000000 38 | bSimulateSkeletalMeshOnDedicatedServer=True 39 | DefaultShapeComplexity=CTF_UseSimpleAndComplex 40 | bDefaultHasComplexCollision=True 41 | bSuppressFaceRemapTable=False 42 | bSupportUVFromHitResults=False 43 | bDisableActiveActors=False 44 | bDisableKinematicStaticPairs=False 45 | bDisableKinematicKinematicPairs=False 46 | bDisableCCD=False 47 | bEnableEnhancedDeterminism=False 48 | MaxPhysicsDeltaTime=0.033333 49 | bSubstepping=False 50 | bSubsteppingAsync=False 51 | MaxSubstepDeltaTime=0.016667 52 | MaxSubsteps=6 53 | SyncSceneSmoothingFactor=0.000000 54 | InitialAverageFrameRate=0.016667 55 | PhysXTreeRebuildRate=10 56 | DefaultBroadphaseSettings=(bUseMBPOnClient=False,bUseMBPOnServer=False,MBPBounds=(Min=(X=0.000000,Y=0.000000,Z=0.000000),Max=(X=0.000000,Y=0.000000,Z=0.000000),IsValid=0),MBPNumSubdivs=2) 57 | 58 | 59 | --------------------------------------------------------------------------------