Browse Source

LicenseSystem updates

Josh Engebretson 10 years ago
parent
commit
057bd20caa
32 changed files with 334 additions and 91 deletions
  1. 4 7
      Resources/EditorData/AtomicEditor/editor/ui/platformsinfo.tb.txt
  2. 0 16
      Resources/EditorData/AtomicEditor/editor/ui/sourceinfo.tb.txt
  3. 13 6
      Script/AtomicEditor/editor/EditorLicense.ts
  4. 33 17
      Script/AtomicEditor/ui/modal/About.ts
  5. 15 3
      Script/AtomicEditor/ui/modal/ModalOps.ts
  6. 12 4
      Script/AtomicEditor/ui/modal/build/BuildSettingsWindow.ts
  7. 1 9
      Script/AtomicEditor/ui/modal/license/ActivationWindow.ts
  8. 6 16
      Script/AtomicEditor/ui/modal/license/Pro3DWindow.ts
  9. 75 0
      Script/AtomicEditor/ui/modal/license/ProPlatformWindow.ts
  10. 7 0
      Script/TypeScript/AtomicWork.d.ts
  11. 7 0
      Source/Atomic/IPC/IPCEvents.h
  12. 3 1
      Source/Atomic/UI/SystemUI/MessageBox.cpp
  13. 14 0
      Source/Atomic/UI/UI.cpp
  14. 6 0
      Source/Atomic/UI/UI.h
  15. 9 0
      Source/Atomic/UI/UIEditField.cpp
  16. 2 0
      Source/Atomic/UI/UIEditField.h
  17. 10 0
      Source/Atomic/UI/UIWidget.cpp
  18. 1 0
      Source/Atomic/UI/UIWidget.h
  19. 9 0
      Source/AtomicEditor/EditorMode/AEEditorMode.cpp
  20. 62 5
      Source/AtomicEditor/PlayerMode/AEPlayerMode.cpp
  21. 9 0
      Source/AtomicEditor/PlayerMode/AEPlayerMode.h
  22. 2 0
      Source/ThirdParty/TurboBadger/tb_editfield.h
  23. 1 1
      Source/ThirdParty/TurboBadger/tb_style_edit.cpp
  24. 6 6
      Source/ToolCore/License/LicenseSystem.h
  25. 2 0
      Source/ToolCore/Platform/Platform.h
  26. 7 0
      Source/ToolCore/Platform/PlatformAndroid.cpp
  27. 2 0
      Source/ToolCore/Platform/PlatformAndroid.h
  28. 8 0
      Source/ToolCore/Platform/PlatformIOS.cpp
  29. 2 0
      Source/ToolCore/Platform/PlatformIOS.h
  30. 2 0
      Source/ToolCore/Platform/PlatformMac.h
  31. 2 0
      Source/ToolCore/Platform/PlatformWeb.h
  32. 2 0
      Source/ToolCore/Platform/PlatformWindows.h

+ 4 - 7
Resources/EditorData/AtomicEditor/editor/ui/platformsinfo.tb.txt

@@ -1,13 +1,10 @@
 TBLayout: axis: y, distribution: gravity
 	TBImageWidget: filename: "AtomicEditor/editor/images/platforms_header.png"
-		lp: width: 512, height: 167
-	TBEditField: multiline: 1, styling: 1, gravity: all, id: info, readonly: 1
+		lp: width: 512, height: 167, min-width: 512, min-height: 167
+	TBEditField: multiline: 1, styling: 1, gravity: all, id: info, readonly: 1, adapt-to-content: 0
 		font: size: 14
-		text: "Atomic Game Engine Pro is required to deploy apps to this platform.\n\n" \
-				"<color #76D6FF>Available platform licenses:</color>\n\n" \
-				"<widget TBSkinImage: skin: 'LogoHTML5-Small'> <widget TBSkinImage: skin: 'LogoAndroid-Small'> " \
-				"<widget TBSkinImage: skin: 'LogoIOS-Small'>"
-		lp: min-width: 480, min-height: 160
+		lp: min-width: 480, min-height: 280
+		text: "..."
 	TBSeparator: gravity: left right, skin: AESeparator
 	TBLayout:
 		TBButton: text: OK, id: ok

+ 0 - 16
Resources/EditorData/AtomicEditor/editor/ui/sourceinfo.tb.txt

@@ -1,16 +0,0 @@
-TBLayout: axis: y, distribution: gravity
-	TBImageWidget: filename: "AtomicEditor/editor/images/source_header.jpg"
-		lp: width: 512, height: 167
-	TBEditField: multiline: 1, styling: 1, gravity: all, id: info, readonly: 1, scroll-mode: off
-		font: size: 14
-		text: "\nAtomic Pro is required for <color #76D6FF>GitHub development snapshots</color> and <color #76D6FF>custom engine builds</color>.\n\n" \
-		"\nPlease download the binary release or <color #D4FB79>upgrade to Atomic Pro</color>.\n\n"
-		lp: min-width: 480, min-height: 160
-	TBSeparator: gravity: left right, skin: AESeparator
-	TBLayout:
-		TBButton: text: Quit, id: quit
-			lp: min-width: 64, min-height: 64	
-		TBButton: text: Download Binary, id: download
-			lp: min-width: 128, min-height: 64
-		TBButton: text: Get Pro for Full Source, id: purchase, skin: TBButton.greentext
-			lp: min-width: 128, min-height: 64

+ 13 - 6
Script/AtomicEditor/editor/EditorLicense.ts

@@ -11,6 +11,19 @@ class EditorLicense extends Atomic.ScriptObject {
         this.subscribeToEvent("LicenseActivationRequired", (eventData) => this.handleLicenseActivationRequired(eventData));
         this.subscribeToEvent("LicenseSuccess", (eventData) => this.handleLicenseSuccess(eventData));
 
+        this.subscribeToEvent("IPCMessage", (eventData:Atomic.IPCMessageEvent) => this.handleIPCMessage(eventData));
+
+    }
+
+    handleIPCMessage(eventData:Atomic.IPCMessageEvent) {
+
+      if (eventData.message == "3D Module License Required") {
+
+        var ops = EditorUI.getModelOps();
+        ops.showPro3DWindow();
+
+      }
+
     }
 
     handleLicenseEulaRequired(eventData) {
@@ -29,12 +42,6 @@ class EditorLicense extends Atomic.ScriptObject {
 
     handleLicenseSuccess(eventData) {
 
-        if (ToolCore.licenseSystem.sourceBuild && ToolCore.licenseSystem.isStandardLicense()) {
-
-          var ops = EditorUI.getModelOps();
-          ops.showProWindow("AtomicEditor/editor/ui/sourceinfo.tb.txt");
-
-        }
 
     }
 

+ 33 - 17
Script/AtomicEditor/ui/modal/About.ts

@@ -14,10 +14,10 @@ class About extends ModalWindow {
         this.text = "About the Atomic Game Engine";
         this.load("AtomicEditor/editor/ui/about.tb.txt");
 
-        this.age_license = <Atomic.UIEditField> this.getWidget("age_license");
-        this.thirdparty_license = <Atomic.UIEditField> this.getWidget("thirdparty_license");
-        this.externaltool_license = <Atomic.UIEditField> this.getWidget("externaltool_license");
-        this.about_text = <Atomic.UIEditField> this.getWidget("about_text");
+        this.age_license = <Atomic.UIEditField>this.getWidget("age_license");
+        this.thirdparty_license = <Atomic.UIEditField>this.getWidget("thirdparty_license");
+        this.externaltool_license = <Atomic.UIEditField>this.getWidget("externaltool_license");
+        this.about_text = <Atomic.UIEditField>this.getWidget("about_text");
 
         var cache = Atomic.cache;
 
@@ -32,7 +32,7 @@ class About extends ModalWindow {
 
         this.about_text.text = this.generateAboutText();
 
-        var get_pro = <Atomic.UIButton> this.getWidget("purchase_pro");
+        var get_pro = <Atomic.UIButton>this.getWidget("purchase_pro");
         if (get_pro) {
             get_pro.onClick = function() {
                 Atomic.fileSystem.systemOpen("https://store.atomicgameengine.com/site");
@@ -70,19 +70,35 @@ class About extends ModalWindow {
 
         text += "<color #D4FB79>Installed platforms and modules:</color>\n\n";
 
-        if (ToolCore.licenseSystem.isStandardLicense()) {
-            text += "    <widget TBSkinImage: skin: 'LogoMac-Small'> <widget TBSkinImage: skin: 'LogoWindows-Small'> <widget TBSkinImage: skin: 'Module2D-Small'>\n\n\n";
+        var licenseSystem = ToolCore.licenseSystem;
+
+        var installedText = "    <widget TBSkinImage: skin: 'LogoMac-Small'> <widget TBSkinImage: skin: 'LogoWindows-Small'> <widget TBSkinImage: skin: 'LogoHTML5-Small'> ";
+        var availableText = "   ";
+
+        if (licenseSystem.licenseAndroid)
+            installedText += "<widget TBSkinImage: skin: 'LogoAndroid-Small'> ";
+        else
+            availableText += "<widget TBSkinImage: skin: 'LogoAndroid-Small'> ";
+
+            if (licenseSystem.licenseIOS)
+                installedText += "<widget TBSkinImage: skin: 'LogoIOS-Small'> ";
+            else
+                availableText += "<widget TBSkinImage: skin: 'LogoIOS-Small'> ";
+
+        installedText += "<widget TBSkinImage: skin: 'Module2D-Small'> ";
+
+        if (licenseSystem.licenseModule3D)
+            installedText += "<widget TBSkinImage: skin: 'Module3D-Small'> ";
+        else
+            availableText += "<widget TBSkinImage: skin: 'Module3D-Small'> ";
+
+        text += installedText + "\n\n\n";
+
+        if (!licenseSystem.licenseIOS || !licenseSystem.licenseAndroid || !licenseSystem.licenseModule3D) {
+          text += "<color #76D6FF>Available platforms and modules:</color>\n\n";
+          text += availableText + "\n\n\n";
+      }
 
-            text += "<color #76D6FF>Available platforms and modules:</color>\n\n \
-    <widget TBSkinImage: skin: 'LogoHTML5-Small'> <widget TBSkinImage: skin: 'LogoAndroid-Small'>  \
-<widget TBSkinImage: skin: 'LogoIOS-Small'> <widget TBSkinImage: skin: 'Module3D-Small'> \
-<widget TBButton: text: 'Get Pro' skin: 'TBButton.greentext' id: 'purchase_pro' >\n\n\n";
-        }
-        else {
-            text += "    <widget TBSkinImage: skin: 'LogoMac-Small'> <widget TBSkinImage: skin: 'LogoWindows-Small'> \
-<widget TBSkinImage: skin: 'LogoHTML5-Small'> <widget TBSkinImage: skin: 'LogoAndroid-Small'>  \
-<widget TBSkinImage: skin: 'LogoIOS-Small'> <widget TBSkinImage: skin: 'Module2D-Small'> <widget TBSkinImage: skin: 'Module3D-Small'>\n\n";
-        }
 
         text += "<color #76D6FF>Special Thanks:</color>\n\n";
         text += "    The Urho3D Project - http://urho3d.github.io\n\n";

+ 15 - 3
Script/AtomicEditor/ui/modal/ModalOps.ts

@@ -8,7 +8,8 @@ import EULAWindow = require("./license/EULAWindow");
 import ActivationWindow = require("./license/ActivationWindow");
 import ActivationSuccessWindow = require("./license/ActivationSuccessWindow");
 import ManageLicense = require("./license/ManageLicense");
-import ProWindow = require("./license/ProWindow");
+import Pro3DWindow = require("./license/Pro3DWindow");
+import ProPlatformWindow = require("./license/ProPlatformWindow");
 
 import BuildWindow = require("./build/BuildWindow");
 import BuildOutput = require("./build/BuildOutput");
@@ -148,16 +149,27 @@ class ModalOps extends Atomic.ScriptObject {
 
     }
 
-    showProWindow(uiPath: string) {
+    showPro3DWindow() {
 
         if (this.show()) {
 
-            this.opWindow = new ProWindow(uiPath);
+            this.opWindow = new Pro3DWindow();
 
         }
 
     }
 
+    showProPlatformWindow() {
+
+        if (this.show()) {
+
+            this.opWindow = new ProPlatformWindow();
+
+        }
+
+    }
+
+
     showAbout() {
 
         if (this.show()) {

+ 12 - 4
Script/AtomicEditor/ui/modal/build/BuildSettingsWindow.ts

@@ -76,10 +76,10 @@ class BuildSettingsWindow extends ModalWindow {
 
     commitBuildSettings() {
 
-      for (var name in this.platformInfo) {
+        for (var name in this.platformInfo) {
 
-          <BuildSettingsWidget>(this.platformInfo[name].widget).storeValues();
-      }
+            <BuildSettingsWidget>(this.platformInfo[name].widget).storeValues();
+        }
 
         ToolCore.toolSystem.project.saveBuildSettings();
 
@@ -123,7 +123,15 @@ class BuildSettingsWindow extends ModalWindow {
 
                     if (info.index == index) {
 
-                        toolSystem.setCurrentPlatform(toolSystem.getPlatformByName(name).platformID);
+                        var platform = toolSystem.getPlatformByName(name);
+
+                        if (platform.license) {
+                            this.hide();
+                            EditorUI.getModelOps().showProPlatformWindow();
+                            return true;
+                        }
+
+                        toolSystem.setCurrentPlatform(platform.platformID);
 
                         return true;
                     }

+ 1 - 9
Script/AtomicEditor/ui/modal/license/ActivationWindow.ts

@@ -49,16 +49,8 @@ class ActivationWindow extends ModalWindow {
 
         this.hide();
 
-        if (ToolCore.licenseSystem.sourceBuild && ToolCore.licenseSystem.isStandardLicense()) {
+        EditorUI.getModelOps().showActivationSuccessWindow();
 
-            // show pro window
-            EditorUI.getModelOps().showProWindow("AtomicEditor/editor/ui/sourceinfo.tb.txt");
-
-        } else {
-
-            EditorUI.getModelOps().showActivationSuccessWindow();
-
-        }
 
     }
 

+ 6 - 16
Script/AtomicEditor/ui/modal/license/ProWindow.ts → Script/AtomicEditor/ui/modal/license/Pro3DWindow.ts

@@ -4,13 +4,13 @@ import EditorUI = require("ui/EditorUI");
 import ModalWindow = require("../ModalWindow");
 import ProgressModal = require("../ProgressModal");
 
-class ProWindow extends ModalWindow {
+class Pro3DWindow extends ModalWindow {
 
-    constructor(uiPath: string) {
+    constructor() {
 
-        super(true);
+        super(false);
 
-        this.init("Atomic Pro Required", uiPath);
+        this.init("3D Module License Required", "AtomicEditor/editor/ui/infomodule3d.tb.txt");
 
     }
 
@@ -24,17 +24,7 @@ class ProWindow extends ModalWindow {
 
                 Atomic.fileSystem.systemOpen("https://store.atomicgameengine.com/site");
 
-            } else if (id == "download") {
-
-                Atomic.fileSystem.systemOpen("http://atomicgameengine.com/download");
-
-            } else if (id == "quit") {
-
-                Atomic.ui.requestExit();
-
-            }
-
-            if (id == "ok") {
+            } else if (id == "ok") {
 
                 this.hide();
 
@@ -48,4 +38,4 @@ class ProWindow extends ModalWindow {
 
 }
 
-export = ProWindow;
+export = Pro3DWindow;

+ 75 - 0
Script/AtomicEditor/ui/modal/license/ProPlatformWindow.ts

@@ -0,0 +1,75 @@
+
+import EditorEvents = require("editor/EditorEvents");
+import EditorUI = require("ui/EditorUI");
+import ModalWindow = require("../ModalWindow");
+import ProgressModal = require("../ProgressModal");
+
+class ProPlatformWindow extends ModalWindow {
+
+    constructor() {
+
+        super(false);
+
+        this.init("Platform License Required", "AtomicEditor/editor/ui/platformsinfo.tb.txt");
+
+        var editField = <Atomic.UIEditField> this.getWidget("info");
+
+        var text = "\nAtomic Game Engine Pro is required to deploy apps to this platform.\n\n<color #D4FB79>Installed platforms:</color>\n\n";
+
+        var licenseSystem = ToolCore.licenseSystem;
+
+        var installedText = "    <widget TBSkinImage: skin: 'LogoMac-Small'> <widget TBSkinImage: skin: 'LogoWindows-Small'> <widget TBSkinImage: skin: 'LogoHTML5-Small'> ";
+        var availableText = "   ";
+
+        if (licenseSystem.licenseAndroid)
+            installedText += "<widget TBSkinImage: skin: 'LogoAndroid-Small'> ";
+        else
+            availableText += "<widget TBSkinImage: skin: 'LogoAndroid-Small'> ";
+
+            if (licenseSystem.licenseIOS)
+                installedText += "<widget TBSkinImage: skin: 'LogoIOS-Small'> ";
+            else
+                availableText += "<widget TBSkinImage: skin: 'LogoIOS-Small'> ";
+
+        text += installedText + "\n\n\n";
+
+        if (!licenseSystem.licenseIOS || !licenseSystem.licenseAndroid || !licenseSystem.licenseModule3D) {
+          text += "<color #76D6FF>Available platforms:</color>\n\n";
+          text += availableText + "\n\n\n";
+      }
+
+      editField.text = text;
+
+      this.resizeToFitContent();
+      this.center();
+
+      editField.reformat();
+
+
+    }
+
+    handleWidgetEvent(ev: Atomic.UIWidgetEvent) {
+
+        if (ev.type == Atomic.UI_EVENT_TYPE_CLICK) {
+
+            var id = ev.target.id;
+
+            if (id == 'purchase') {
+
+                Atomic.fileSystem.systemOpen("https://store.atomicgameengine.com/site");
+
+            } else if (id == "ok") {
+
+                this.hide();
+
+                return true;
+            }
+
+            return false;
+
+        }
+    }
+
+}
+
+export = ProPlatformWindow;

+ 7 - 0
Script/TypeScript/AtomicWork.d.ts

@@ -155,6 +155,13 @@ declare module Atomic {
 
     }
 
+
+    export interface IPCMessageEvent {
+
+        message: string;
+        value: number;
+    }
+
     export interface AttributeInfo {
 
         type: VariantType;

+ 7 - 0
Source/Atomic/IPC/IPCEvents.h

@@ -31,5 +31,12 @@ EVENT(E_IPCWORKERLOG, IPCWorkerLog)
     PARAM(P_MESSAGE, Message);  // string
 }
 
+/// Worker Log
+EVENT(E_IPCMESSAGE, IPCMessage)
+{
+    PARAM(P_MESSAGE, Message);  // string
+    PARAM(P_VALUE, Value);  // int
+}
+
 
 }

+ 3 - 1
Source/Atomic/UI/SystemUI/MessageBox.cpp

@@ -142,7 +142,9 @@ void MessageBox::HandleMessageAcknowledged(StringHash eventType, VariantMap& eve
     newEventData[P_OK] = eventData[Released::P_ELEMENT] == okButton_;
     SendEvent(E_MESSAGEACK, newEventData);
 
-    this->ReleaseRef();
+    // ATOMIC BEGIN
+    // this->ReleaseRef();
+    // ATOMIC END
 }
 
 }

+ 14 - 0
Source/Atomic/UI/UI.cpp

@@ -63,6 +63,7 @@ using namespace tb;
 #include "SystemUI/SystemUIEvents.h"
 #include "SystemUI/DebugHud.h"
 #include "SystemUI/Console.h"
+#include "SystemUI/MessageBox.h"
 
 namespace tb
 {
@@ -763,4 +764,17 @@ void UI::HandleConsoleClosed(StringHash eventType, VariantMap& eventData)
     consoleVisible_ = false;
 }
 
+SystemUI::MessageBox* UI::ShowSystemMessageBox(const String& title, const String& message)
+{
+
+    ResourceCache* cache = GetSubsystem<ResourceCache>();
+    XMLFile* xmlFile = cache->GetResource<XMLFile>("UI/DefaultStyle.xml");
+
+    SystemUI::MessageBox* messageBox = new SystemUI::MessageBox(context_, message, title, 0, xmlFile);
+
+    return messageBox;
+
+
+}
+
 }

+ 6 - 0
Source/Atomic/UI/UI.h

@@ -13,6 +13,11 @@ class VertexBuffer;
 class UIRenderer;
 class UIWidget;
 
+namespace SystemUI
+{
+    class MessageBox;
+}
+
 class UI : public Object, private tb::TBWidgetListener
 {
     OBJECT(UI)
@@ -65,6 +70,7 @@ public:
 
     void GetTBIDString(unsigned id, String& value);
 
+    SystemUI::MessageBox *ShowSystemMessageBox(const String& title, const String& message);
     void ShowDebugHud(bool value);
     void ToggleDebugHud();
 

+ 9 - 0
Source/Atomic/UI/UIEditField.cpp

@@ -140,6 +140,15 @@ bool UIEditField::GetAdaptToContentSize() const
 
 }
 
+void UIEditField::Reformat(bool update_fragments)
+{
+    if (!widget_)
+        return;
+
+    TBEditField* w = (TBEditField*) widget_;
+    w->Reformat(update_fragments);
+}
+
 
 void UIEditField::SetTextAlign(UI_TEXT_ALIGN align)
 {

+ 2 - 0
Source/Atomic/UI/UIEditField.h

@@ -40,6 +40,8 @@ public:
     void SetStyling(bool styling);
     void SetMultiline(bool multiline);
 
+    void Reformat(bool update_fragments = false);
+
     void ScrollTo(int x, int y);
 
     void SetWrapping(bool wrap);

+ 10 - 0
Source/Atomic/UI/UIWidget.cpp

@@ -690,4 +690,14 @@ bool UIWidget::OnEvent(const tb::TBWidgetEvent &ev)
     return false;
 }
 
+void UIWidget::InvalidateLayout()
+{
+    if (!widget_)
+        return;
+
+    widget_->InvalidateLayout(tb::TBWidget::INVALIDATE_LAYOUT_TARGET_ONLY);
+
+}
+
+
 }

+ 1 - 0
Source/Atomic/UI/UIWidget.h

@@ -212,6 +212,7 @@ class UIWidget : public Object, public tb::TBWidgetDelegate
     /// This takes a relative Z and insert the child before or after the given reference widget.
     void AddChildRelative(UIWidget* child, UI_WIDGET_Z_REL z, UIWidget* reference);
 
+    void InvalidateLayout();
 
     tb::TBWidget* GetInternalWidget() { return widget_; }
 

+ 9 - 0
Source/AtomicEditor/EditorMode/AEEditorMode.cpp

@@ -7,6 +7,7 @@
 
 #include <ToolCore/ToolEnvironment.h>
 #include <ToolCore/ToolSystem.h>
+#include <ToolCore/License/LicenseSystem.h>
 #include <ToolCore/Project/Project.h>
 
 #include <AtomicJS/Javascript/JSIPCEvents.h>
@@ -33,9 +34,17 @@ EditorMode::~EditorMode()
 
 void EditorMode::HandleIPCWorkerStarted(StringHash eventType, VariantMap& eventData)
 {
+    LicenseSystem* licenseSystem = GetSubsystem<LicenseSystem>();
+
     VariantMap startupData;
     SystemUI::DebugHud* debugHud = GetSubsystem<SystemUI::DebugHud>();
 
+// BEGIN LICENSE MANAGEMENT
+
+    startupData["license3D"] = licenseSystem->GetLicenseModule3D();
+
+// END LICENSE MANAGEMENT
+
     startupData["debugHudMode"] = debugHud ? debugHud->GetMode() : (unsigned) 0;
 
     playerBroker_->PostMessage(E_IPCINITIALIZE, startupData);

+ 62 - 5
Source/AtomicEditor/PlayerMode/AEPlayerMode.cpp

@@ -3,7 +3,11 @@
 #include <Atomic/IO/Log.h>
 #include <Atomic/Input/InputEvents.h>
 #include <Atomic/Core/ProcessUtils.h>
+#include <Atomic/Graphics/GraphicsEvents.h>
+#include <Atomic/Graphics/Camera.h>
 #include <Atomic/UI/SystemUI/DebugHud.h>
+#include <Atomic/UI/SystemUI/SystemUIEvents.h>
+#include <Atomic/UI/UI.h>
 #include <Atomic/IPC/IPCEvents.h>
 #include <Atomic/IPC/IPCWorker.h>
 
@@ -19,7 +23,8 @@ namespace AtomicEditor
 PlayerMode::PlayerMode(Context* context) :
     Object(context),
     brokerActive_(false),
-    launchedByEditor_(false)
+    launchedByEditor_(false),
+    licenseModule3D_(false)
 {
     fd_[0] = INVALID_IPCHANDLE_VALUE;
     fd_[1] = INVALID_IPCHANDLE_VALUE;
@@ -28,6 +33,10 @@ PlayerMode::PlayerMode(Context* context) :
 
     SubscribeToEvent(E_LOGMESSAGE, HANDLER(PlayerMode, HandleLogMessage));
     SubscribeToEvent(E_JSERROR, HANDLER(PlayerMode, HandleJSError));
+
+    // BEGIN LICENSE MANAGEMENT
+    SubscribeToEvent(E_BEGINVIEWRENDER, HANDLER(PlayerMode, HandleViewRender));
+    // END LICENSE MANAGEMENT
 }
 
 PlayerMode::~PlayerMode()
@@ -46,6 +55,12 @@ void PlayerMode::HandleIPCInitialize(StringHash eventType, VariantMap& eventData
         SendEvent(E_EXITREQUESTED);
     }
 
+    // BEGIN LICENSE MANAGEMENT
+
+    licenseModule3D_ = eventData["license3D"].GetBool();
+
+    // END LICENSE MANAGEMENT
+
     SystemUI::DebugHud* debugHud = GetSubsystem<SystemUI::DebugHud>();
     if (debugHud)
         debugHud->SetMode(eventData["debugHudMode"].GetUInt());
@@ -70,7 +85,7 @@ void PlayerMode::ProcessArguments() {
                 Vector<String> idc = argument.Split(argument.CString(), '=');
                 if (idc.Size() == 2)
 
-                id = ToInt(idc[1].CString());
+                    id = ToInt(idc[1].CString());
             }
 
             else if (argument.StartsWith("--ipc-server=") || argument.StartsWith("--ipc-client="))
@@ -84,7 +99,7 @@ void PlayerMode::ProcessArguments() {
                     if (argument.StartsWith("--ipc-server="))
                     {
 #ifdef ATOMIC_PLATFORM_WINDOWS
-						// clientRead
+                        // clientRead
                         WString wipc(ipc[1]);
                         HANDLE pipe = reinterpret_cast<HANDLE>(_wtoi64(wipc.CString()));
                         fd_[0] = pipe;
@@ -96,7 +111,7 @@ void PlayerMode::ProcessArguments() {
                     else
                     {
 #ifdef ATOMIC_PLATFORM_WINDOWS
-						// clientWrite
+                        // clientWrite
                         WString wipc(ipc[1]);
                         HANDLE pipe = reinterpret_cast<HANDLE>(_wtoi64(wipc.CString()));
                         fd_[1] = pipe;
@@ -114,7 +129,7 @@ void PlayerMode::ProcessArguments() {
     }
 
     if (id > 0 && fd_[0] != INVALID_IPCHANDLE_VALUE && fd_[1] != INVALID_IPCHANDLE_VALUE)
-    {        
+    {
         launchedByEditor_ = true;
         SubscribeToEvent(E_IPCINITIALIZE, HANDLER(PlayerMode, HandleIPCInitialize));
         ipc_->InitWorker((unsigned) id, fd_[0], fd_[1]);
@@ -168,5 +183,47 @@ void PlayerMode::HandleLogMessage(StringHash eventType, VariantMap& eventData)
 
 }
 
+void PlayerMode::HandleMessageAck(StringHash eventType, VariantMap& eventData)
+{
+    messageBox_ = 0;
+    GetSubsystem<UI>()->RequestExit();
+}
+
+void PlayerMode::HandleViewRender(StringHash eventType, VariantMap& eventData)
+{
+// BEGIN LICENSE MANAGEMENT
+    static bool done = false;
+
+    if (licenseModule3D_)
+        return;
+
+    Camera* camera = static_cast<Camera*>(eventData[BeginViewRender::P_CAMERA].GetPtr());
+
+    if (!camera || camera->IsOrthographic())
+        return;
+
+    if (!done) {
+
+        done = true;
+
+        messageBox_ = GetSubsystem<UI>()->ShowSystemMessageBox("3D Module License Required", "A 3D Module License is required to display 3D content.\n\nUpgrade to Atomic Pro for all features and platforms.");
+        SubscribeToEvent(messageBox_, SystemUI::E_MESSAGEACK, HANDLER(PlayerMode, HandleMessageAck));
+
+        if (brokerActive_)
+        {
+
+            if (ipc_.Null())
+                return;
+
+            VariantMap msgEvent;
+            msgEvent[IPCMessage::P_MESSAGE] = String("3D Module License Required");
+            ipc_->SendEventToBroker(E_IPCMESSAGE, msgEvent);
+        }
+    }
+
+// END LICENSE MANAGEMENT
+
+}
+
 
 }

+ 9 - 0
Source/AtomicEditor/PlayerMode/AEPlayerMode.h

@@ -5,6 +5,8 @@
 #include <Atomic/IPC/IPC.h>
 #include <Atomic/IPC/IPCTypes.h>
 
+#include <Atomic/UI/SystemUI/MessageBox.h>
+
 using namespace Atomic;
 
 namespace AtomicEditor
@@ -32,6 +34,13 @@ private:
     void HandleJSError(StringHash eventType, VariantMap& eventData);
     void HandleLogMessage(StringHash eventType, VariantMap& eventData);
     void HandleIPCInitialize(StringHash eventType, VariantMap& eventData);
+    void HandleViewRender(StringHash eventType, VariantMap& eventData);
+
+// BEGIN LICENSE MANAGEMENT
+    void HandleMessageAck(StringHash eventType, VariantMap& eventData);
+    bool licenseModule3D_;
+    SharedPtr<SystemUI::MessageBox> messageBox_;
+// END LICENSE MANAGEMENT
 
     IPCHandle fd_[2];
     WeakPtr<IPC> ipc_;

+ 2 - 0
Source/ThirdParty/TurboBadger/tb_editfield.h

@@ -175,6 +175,8 @@ public:
 
 	virtual PreferredSize OnCalculatePreferredContentSize(const SizeConstraints &constraints);
 
+    void Reformat(bool update_fragments) { m_style_edit.Reformat(update_fragments); }
+
 	virtual void OnMessageReceived(TBMessage *msg);
 private:
 	TBScrollBar m_scrollbar_x;

+ 1 - 1
Source/ThirdParty/TurboBadger/tb_style_edit.cpp

@@ -2139,7 +2139,7 @@ bool TBStyleEdit::SetText(const char *text, int text_len, TB_CARET_POS pos)
 	ScrollIfNeeded(true, false);
 
 	if (pos == TB_CARET_POS_END)
-		caret.Place(blocks.GetLast(), blocks.GetLast()->str_len);
+        caret.Place(blocks.GetLast(), blocks.GetLast()->str_len);
 
 	listener->OnChange();
 	return true;

+ 6 - 6
Source/ToolCore/License/LicenseSystem.h

@@ -50,12 +50,12 @@ public:
 
     bool GetSourceBuild();
 
-    bool LicenseWindows() { return licenseWindows_; }
-    bool LicenseMac() { return licenseMac_; }
-    bool LicenseAndroid() { return licenseAndroid_; }
-    bool LicenseIOS() { return licenseIOS_; }
-    bool LicenseHTML5() { return licenseHTML5_; }
-    bool LicenseModule3D() { return licenseModule3D_; }
+    bool GetLicenseWindows() { return licenseWindows_; }
+    bool GetLicenseMac() { return licenseMac_; }
+    bool GetLicenseAndroid() { return licenseAndroid_; }
+    bool GetLicenseIOS() { return licenseIOS_; }
+    bool GetLicenseHTML5() { return licenseHTML5_; }
+    bool GetLicenseModule3D() { return licenseModule3D_; }
 
     /// Returns whether there are any platform licenses available
     bool IsStandardLicense();

+ 2 - 0
Source/ToolCore/Platform/Platform.h

@@ -30,6 +30,8 @@ public:
     Platform(Context* context);
     virtual ~Platform();
 
+    virtual bool GetLicense() = 0;
+
     virtual String GetName() = 0;
     virtual PlatformID GetPlatformID() = 0;
 

+ 7 - 0
Source/ToolCore/Platform/PlatformAndroid.cpp

@@ -4,6 +4,7 @@
 
 #include "../ToolEnvironment.h"
 #include "../Subprocess/SubprocessSystem.h"
+#include "../License/LicenseSystem.h"
 #include "../Build/BuildAndroid.h"
 
 #include "PlatformAndroid.h"
@@ -139,5 +140,11 @@ String PlatformAndroid::GetAndroidCommand() const
 
 }
 
+bool PlatformAndroid::GetLicense()
+{
+// BEGIN LICENSE MANAGEMENT
+    return GetSubsystem<LicenseSystem>()->GetLicenseAndroid();
+// END LICENSE MANAGEMENT
+}
 
 }

+ 2 - 0
Source/ToolCore/Platform/PlatformAndroid.h

@@ -26,6 +26,8 @@ public:
     PlatformAndroid(Context* context);
     virtual ~PlatformAndroid();
 
+    virtual bool GetLicense();
+
     String GetName() { return "ANDROID"; }
     PlatformID GetPlatformID() { return PLATFORMID_ANDROID; }
 

+ 8 - 0
Source/ToolCore/Platform/PlatformIOS.cpp

@@ -2,6 +2,7 @@
 #include <ThirdParty/PugiXml/src/pugixml.hpp>
 
 #include "../Build/BuildIOS.h"
+#include "../License/LicenseSystem.h"
 #include "PlatformIOS.h"
 
 #ifdef ATOMIC_PLATFORM_OSX
@@ -82,5 +83,12 @@ BuildBase* PlatformIOS::NewBuild(Project *project)
     return new BuildIOS(context_, project);
 }
 
+bool PlatformIOS::GetLicense()
+{
+// BEGIN LICENSE MANAGEMENT
+    return GetSubsystem<LicenseSystem>()->GetLicenseIOS();
+// END LICENSE MANAGEMENT
+}
+
 
 }

+ 2 - 0
Source/ToolCore/Platform/PlatformIOS.h

@@ -22,6 +22,8 @@ public:
 
     String ParseProvisionAppIdentifierPrefix(const String& provisionFile);
 
+    bool GetLicense();
+
 };
 
 }

+ 2 - 0
Source/ToolCore/Platform/PlatformMac.h

@@ -20,6 +20,8 @@ public:
 
     BuildBase* NewBuild(Project* project);
 
+    virtual bool GetLicense() { return true; }
+
 };
 
 }

+ 2 - 0
Source/ToolCore/Platform/PlatformWeb.h

@@ -20,6 +20,8 @@ public:
 
     BuildBase* NewBuild(Project *project);
 
+    virtual bool GetLicense() { return true; }
+
 };
 
 }

+ 2 - 0
Source/ToolCore/Platform/PlatformWindows.h

@@ -20,6 +20,8 @@ public:
 
     BuildBase* NewBuild(Project* project);
 
+    virtual bool GetLicense() { return true; }
+
 };
 
 }