Browse Source

Merge pull request #1061 from AtomicGameEngine/JME-ATOMIC-780

Adds a prompt for breaking prefabs so changes aren't unintentionally lost
JoshEngebretson 9 years ago
parent
commit
eba5bceb4e

+ 6 - 0
Resources/EditorData/AtomicEditor/editor/skin/skin.tb.txt

@@ -210,6 +210,12 @@ elements
 		min-width 140
 		min-width 140
 		max-width 140
 		max-width 140
 
 
+	InspectorPrefabTextAttrName
+		padding 4
+		text-color #aaaaaa
+		min-width 110
+		max-width 110
+
 	HierarchyPrefabText
 	HierarchyPrefabText
 		text-color #11aaaa
 		text-color #11aaaa
 	HierarchyPrefabText.selected
 	HierarchyPrefabText.selected

+ 6 - 0
Resources/EditorData/AtomicEditor/editor/skin_light/skin.tb.txt

@@ -210,6 +210,12 @@ elements
 		min-width 140
 		min-width 140
 		max-width 140
 		max-width 140
 
 
+	InspectorPrefabTextAttrName
+		padding 4
+		text-color #2c2c2c
+		min-width 110
+		max-width 110
+
 	HierarchyPrefabText
 	HierarchyPrefabText
 		text-color #2c2c2c
 		text-color #2c2c2c
 	HierarchyPrefabText.selected
 	HierarchyPrefabText.selected

+ 8 - 0
Resources/EditorData/AtomicEditor/editor/ui/breakprefab.tb.txt

@@ -0,0 +1,8 @@
+TBLayout: axis: y, distribution: gravity, position: left
+	TBLayout:
+		TBEditField: multiline: 1, readonly: 1, id: message
+			lp: min-width: 640
+	TBSeparator: gravity: left right, skin: AESeparator
+	TBLayout:
+		TBButton: text: Break Prefab Connection, id: breakprefab
+		TBButton: text: Cancel, id: cancel

+ 90 - 20
Script/AtomicEditor/ui/frames/inspector/SelectionPrefabWidget.ts

@@ -20,6 +20,9 @@
 // THE SOFTWARE.
 // THE SOFTWARE.
 //
 //
 
 
+import EditorUI = require("../../EditorUI");
+
+var breakMode = true;
 
 
 class SelectionPrefabWidget extends Atomic.UILayout {
 class SelectionPrefabWidget extends Atomic.UILayout {
 
 
@@ -44,7 +47,7 @@ class SelectionPrefabWidget extends Atomic.UILayout {
 
 
         var name = new Atomic.UITextField();
         var name = new Atomic.UITextField();
         name.textAlign = Atomic.UI_TEXT_ALIGN_LEFT;
         name.textAlign = Atomic.UI_TEXT_ALIGN_LEFT;
-        name.skinBg = "InspectorTextAttrName";
+        name.skinBg = "InspectorPrefabTextAttrName";
         name.text = "Prefab";
         name.text = "Prefab";
         name.fontDescription = fd;
         name.fontDescription = fd;
 
 
@@ -70,32 +73,26 @@ class SelectionPrefabWidget extends Atomic.UILayout {
         };
         };
 
 
         var breakButton = new Atomic.UIButton();
         var breakButton = new Atomic.UIButton();
-        breakButton.text = "Break";
+        breakButton.text = "Edit Break";
+        breakButton.toggleMode = true;
+        breakButton.value = breakMode ? 1 : 0;
         breakButton.fontDescription = fd;
         breakButton.fontDescription = fd;
+        breakButton.tooltip  = "Prompt to remove prefab connection";
 
 
         breakButton.onClick = () => {
         breakButton.onClick = () => {
-
-            this.node.scene.sendEvent("SceneEditPrefabBreak", {node : this.node});
+            breakMode = breakButton.value == 1 ? true : false;
             return true;
             return true;
         };
         };
 
 
-        var copyButton = new Atomic.UIButton();
-        copyButton.text = "Copy";
-        copyButton.fontDescription = fd;
+        this.subscribeToEvent("ComponentEditEnd", () => {
 
 
-        copyButton.onClick = () => {
-            this.node.scene.sendEvent("SceneEditPrefabCopy", {node : this.node });
-            return true;
-        };
+            if (breakMode && this.node) {
 
 
-        var pasteButton = new Atomic.UIButton();
-        pasteButton.text = "Paste";
-        pasteButton.fontDescription = fd;
+                var window = new ConfirmPrefabBreak(this.node);
+                window.show();
+            }
 
 
-        pasteButton.onClick = () => {
-            this.node.scene.sendEvent("SceneEditPrefabPaste", {node : this.node });
-            return true;
-        };
+        });
 
 
         var noticeName = new Atomic.UITextField();
         var noticeName = new Atomic.UITextField();
         noticeName.textAlign = Atomic.UI_TEXT_ALIGN_LEFT;
         noticeName.textAlign = Atomic.UI_TEXT_ALIGN_LEFT;
@@ -116,8 +113,6 @@ class SelectionPrefabWidget extends Atomic.UILayout {
         widgetLayout.addChild(saveButton);
         widgetLayout.addChild(saveButton);
         widgetLayout.addChild(undoButton);
         widgetLayout.addChild(undoButton);
         widgetLayout.addChild(breakButton);
         widgetLayout.addChild(breakButton);
-        widgetLayout.addChild(copyButton);
-        widgetLayout.addChild(pasteButton);
 
 
         this.addChild(this.widgetLayout);
         this.addChild(this.widgetLayout);
         this.addChild(this.noticeLayout);
         this.addChild(this.noticeLayout);
@@ -176,4 +171,79 @@ class SelectionPrefabWidget extends Atomic.UILayout {
 
 
 }
 }
 
 
+class ConfirmPrefabBreak extends Atomic.UIWindow {
+
+    constructor(node:Atomic.Node) {
+
+        super();
+
+        this.node = node;
+
+        this.settings = Atomic.UI_WINDOW_SETTINGS_DEFAULT & ~Atomic.UI_WINDOW_SETTINGS_CLOSE_BUTTON;
+
+        this.text = "Break Prefab Connection";
+        this.load("AtomicEditor/editor/ui/breakprefab.tb.txt");
+
+        var message = <Atomic.UIEditField>this.getWidget("message");
+        message.text = "Editing this node will break the prefab connection.\nThis operation cannot be undone, do you want to continue?";
+
+        this.resizeToFitContent();
+        this.center();
+
+        this.dimmer = new Atomic.UIDimmer();
+
+        this.subscribeToEvent("WidgetEvent", (ev) => { this.handleWidgetEvent(ev); });
+
+    }
+
+    handleWidgetEvent(ev: Atomic.UIWidgetEvent) {
+
+        if (ev.type == Atomic.UI_EVENT_TYPE_CLICK) {
+
+            var id = ev.target.id;
+
+            if (id == "breakprefab") {
+
+                this.hide();
+
+                this.node.scene.sendEvent("SceneEditPrefabBreak", {node : this.node});
+
+                return true;
+            }
+
+            if (id == "cancel") {
+
+                this.hide();
+
+                this.node.scene.sendEvent("SceneEditPrefabRevert", {node : this.node});
+
+                return true;
+            }
+
+        }
+    }
+
+    show() {
+
+        var view = EditorUI.getView();
+        view.addChild(this.dimmer);
+        view.addChild(this);
+
+    }
+
+    hide() {
+
+        if (this.dimmer.parent)
+            this.dimmer.parent.removeChild(this.dimmer, false);
+
+        if (this.parent)
+            this.parent.removeChild(this, false);
+
+    }
+
+    node: Atomic.Node;
+    dimmer: Atomic.UIDimmer;
+
+}
+
 export = SelectionPrefabWidget;
 export = SelectionPrefabWidget;

+ 8 - 1
Script/AtomicEditor/ui/frames/inspector/SerializableEditType.ts

@@ -87,6 +87,8 @@ class SerializableEditType {
 
 
     onAttributeInfoEdited(attrInfo: Atomic.AttributeInfo, value: any, index: number = -1, genEdit: boolean = true) {
     onAttributeInfoEdited(attrInfo: Atomic.AttributeInfo, value: any, index: number = -1, genEdit: boolean = true) {
 
 
+        let editTypeName = this.objects.length > 0 ? this.objects[0].typeName : "";
+
         for (var i in this.objects) {
         for (var i in this.objects) {
 
 
             var object = this.objects[i];
             var object = this.objects[i];
@@ -125,9 +127,14 @@ class SerializableEditType {
             node = <Atomic.Node>this.objects[0];
             node = <Atomic.Node>this.objects[0];
         }
         }
 
 
-        if (node)
+        if (node) {
             node.scene.sendEvent("SceneEditEnd");
             node.scene.sendEvent("SceneEditEnd");
 
 
+            if (editTypeName != "Node") {
+                node.scene.sendEvent("ComponentEditEnd");
+            }
+        }
+
     }
     }
 
 
     compareTypes(otherType: SerializableEditType, multiSelect:boolean = false): boolean {
     compareTypes(otherType: SerializableEditType, multiSelect:boolean = false): boolean {

+ 1 - 4
Source/AtomicNET/NETScript/CSComponent.cpp

@@ -52,11 +52,8 @@ void CSComponent::RegisterObject(Context* context)
 {
 {
     context->RegisterFactory<CSComponent>(LOGIC_CATEGORY);
     context->RegisterFactory<CSComponent>(LOGIC_CATEGORY);
 
 
-    ATOMIC_ACCESSOR_ATTRIBUTE("Is Enabled", IsEnabled, SetEnabled, bool, true, AM_DEFAULT);
-
-    ATOMIC_ATTRIBUTE("FieldValues", VariantMap, fieldValues_, Variant::emptyVariantMap, AM_FILE);
-
     ATOMIC_ACCESSOR_ATTRIBUTE("Class", GetComponentClassName, SetComponentClassName, String, String::EMPTY, AM_DEFAULT);
     ATOMIC_ACCESSOR_ATTRIBUTE("Class", GetComponentClassName, SetComponentClassName, String, String::EMPTY, AM_DEFAULT);
+    ATOMIC_COPY_BASE_ATTRIBUTES(ScriptComponent);
 
 
 }
 }
 
 

+ 11 - 2
Source/ToolCore/Assets/PrefabImporter.cpp

@@ -34,7 +34,8 @@
 namespace ToolCore
 namespace ToolCore
 {
 {
 
 
-PrefabImporter::PrefabImporter(Context* context, Asset* asset) : AssetImporter(context, asset)
+PrefabImporter::PrefabImporter(Context* context, Asset* asset) : AssetImporter(context, asset),
+    lastFileStamp_(0xFFFFFFFF)
 {
 {
     SubscribeToEvent(E_PREFABSAVE, ATOMIC_HANDLER(PrefabImporter, HandlePrefabSave));
     SubscribeToEvent(E_PREFABSAVE, ATOMIC_HANDLER(PrefabImporter, HandlePrefabSave));
 }
 }
@@ -140,12 +141,21 @@ void PrefabImporter::HandlePrefabSave(StringHash eventType, VariantMap& eventDat
     FileSystem* fs = GetSubsystem<FileSystem>();
     FileSystem* fs = GetSubsystem<FileSystem>();
     fs->Copy(asset_->GetPath(), asset_->GetCachePath());
     fs->Copy(asset_->GetPath(), asset_->GetCachePath());
 
 
+    asset_->UpdateFileTimestamp();
+    lastFileStamp_ = asset_->GetFileTimestamp();
+
     OnPrefabFileChanged();
     OnPrefabFileChanged();
 
 
 }
 }
 
 
 bool PrefabImporter::Import()
 bool PrefabImporter::Import()
 {
 {
+
+    // The asset database will see the file changed, when the file watcher catches it
+    // though we already loaded/imported in OnPrefabFileChanged
+    if (lastFileStamp_ == asset_->GetFileTimestamp())
+        return true;
+
     FileSystem* fs = GetSubsystem<FileSystem>();
     FileSystem* fs = GetSubsystem<FileSystem>();
 
 
     fs->Copy(asset_->GetPath(), asset_->GetCachePath());
     fs->Copy(asset_->GetPath(), asset_->GetCachePath());
@@ -158,7 +168,6 @@ bool PrefabImporter::Import()
 void PrefabImporter::OnPrefabFileChanged()
 void PrefabImporter::OnPrefabFileChanged()
 {
 {
     // reload it immediately so it is ready for use
     // reload it immediately so it is ready for use
-    // TODO: The resource cache is reloading after this reload due to catching the file cache
     ResourceCache* cache = GetSubsystem<ResourceCache>();
     ResourceCache* cache = GetSubsystem<ResourceCache>();
     XMLFile* xmlfile = cache->GetResource<XMLFile>(asset_->GetGUID());
     XMLFile* xmlfile = cache->GetResource<XMLFile>(asset_->GetGUID());
     cache->ReloadResource(xmlfile);
     cache->ReloadResource(xmlfile);

+ 4 - 1
Source/ToolCore/Assets/PrefabImporter.h

@@ -62,7 +62,10 @@ private:
 
 
     void HandlePrefabSave(StringHash eventType, VariantMap& eventData);
     void HandlePrefabSave(StringHash eventType, VariantMap& eventData);
 
 
-   SharedPtr<Atomic::Scene> preloadResourceScene_;
+    SharedPtr<Atomic::Scene> preloadResourceScene_;
+
+    /// The last time the file was access, to avoid double loading based on saving prefabs
+    unsigned lastFileStamp_;
 
 
 };
 };