Browse Source

JSComponent fields with default values

Josh Engebretson 10 years ago
parent
commit
194c6ccf17

+ 5 - 1
Source/AtomicJS/Javascript/JSAPI.cpp

@@ -214,6 +214,10 @@ void js_to_variant(duk_context* ctx, int variantIdx, Variant &v)
 {
     v.Clear();
 
+    // convert to abs index
+    if (variantIdx < 0)
+        variantIdx = duk_get_top(ctx) + variantIdx;
+
     if (duk_is_boolean(ctx, variantIdx))
     {
         v = duk_to_boolean(ctx, variantIdx) ? true : false;
@@ -273,7 +277,7 @@ void js_to_variant(duk_context* ctx, int variantIdx, Variant &v)
             v4.y_ = duk_to_number(ctx, -1);
             duk_get_prop_index(ctx, variantIdx, 2);
             v4.z_ = duk_to_number(ctx, -1);
-            duk_get_prop_index(ctx, variantIdx, 2);
+            duk_get_prop_index(ctx, variantIdx, 3);
             v4.w_ = duk_to_number(ctx, -1);
             duk_pop_n(ctx, 4);
             v = v4;

+ 1 - 19
Source/AtomicJS/Javascript/JSComponent.cpp

@@ -180,25 +180,7 @@ void JSComponent::InitModule()
             else
             {
                 Variant v;
-
-                switch (itr->second_)
-                {
-                case VAR_BOOL:
-                    v = false;
-                    break;
-                case VAR_STRING:
-                    v = "";
-                    break;
-                case VAR_FLOAT:
-                    v = 0.0f;
-                    break;
-                case VAR_VECTOR3:
-                    v = Vector3::ZERO;
-                    break;
-                default:
-                    break;
-                }
-
+                componentFile_->GetDefaultFieldValue(itr->first_, v);
                 js_push_variant(ctx,  v);
                 duk_put_prop_string(ctx, -2, itr->first_.CString());
             }

+ 146 - 33
Source/AtomicJS/Javascript/JSComponentFile.cpp

@@ -28,6 +28,7 @@
 #include <Atomic/IO/Serializer.h>
 
 #include "JSComponentFile.h"
+#include "JSVM.h"
 
 namespace Atomic
 {
@@ -47,9 +48,47 @@ void JSComponentFile::RegisterObject(Context* context)
     context->RegisterFactory<JSComponentFile>();
 }
 
+void JSComponentFile::GetDefaultFieldValue(const String& name, Variant& v)
+{
+    v = Variant::EMPTY;
+
+    VariantMap::ConstIterator itr = defaultFieldValues_.Find(name);
+
+    if (itr == defaultFieldValues_.End())
+    {
+        HashMap<String, VariantType>::ConstIterator citr = fields_.Find(name);
+        if (citr == fields_.End())
+            return;
+
+        switch (citr->second_)
+        {
+        case VAR_BOOL:
+            v = false;
+            break;
+        case VAR_STRING:
+            v = "";
+            break;
+        case VAR_FLOAT:
+            v = 0.0f;
+            break;
+        case VAR_VECTOR3:
+            v = Vector3::ZERO;
+            break;
+        default:
+            break;
+        }
+
+        return;
+
+    }
+
+    v = itr->second_;
+
+}
+
 bool JSComponentFile::BeginLoad(Deserializer& source)
 {
-    // TODO: cache these for non-editor builds
+    // TODO: cache these for player builds
 
     unsigned dataSize = source.GetSize();
     if (!dataSize && !source.GetName().Empty())
@@ -64,56 +103,130 @@ bool JSComponentFile::BeginLoad(Deserializer& source)
     buffer[dataSize] = '\0';
 
     String text = buffer.Get();
+    text.Replace("\r", "");
     Vector<String> lines = text.Split('\n');
 
+    String eval;
+    bool valid = false;
     for (unsigned i = 0; i < lines.Size(); i++)
     {
-        String line = lines[i].Trimmed();
+        String line = lines[i];
 
-        if (line[0] != '\"')
-            continue;
+        if (!eval.Length())
+        {
+            line = line.Trimmed();
+
+            if (line.StartsWith("exports.fields"))
+            {
+                eval = line.Substring(8);
+                if (line.Contains("}"))
+                {
+                    valid = true;
+                    break;
+                }
+            }
+        }
+        else
+        {
+            eval += line;
+        }
 
-        unsigned pos = line.Find("\";");
-        if (pos == String::NPOS)
-            continue;
+        if (line.Contains("}") && eval.Length())
+        {
+            valid = true;
+            break;
+        }
 
-        text = line.Substring(1, pos - 1);
+    }
 
-        Vector<String> field = text.Split(' ');
+    if (valid)
+    {
+        JSVM* vm = JSVM::GetJSVM(NULL);
 
-        if (field.Size() != 2 || !field[0].Length() || !field[1].Length())
-            continue;
+        if (!vm)
+            return true;
 
-        String name = field[0];
-        String stringType = field[1];
+        duk_context* ctx = vm->GetJSContext();
 
-        VariantType variantType = VAR_NONE;
+        int top = duk_get_top(ctx);
 
-        if (stringType == "boolean")
+        duk_push_string(ctx, eval.CString());
+        duk_push_string(ctx, "eval");
+        duk_compile(ctx, DUK_COMPILE_EVAL);
+        if (duk_is_function(ctx, -1) && duk_pcall(ctx, 0) == DUK_EXEC_SUCCESS)
         {
-            variantType = VAR_BOOL;
-        }
-        else if (stringType == "string")
-        {
-            variantType = VAR_STRING;
-        }
-        else if (stringType == "number")
-        {
-            variantType = VAR_FLOAT;
-        }
-        else if (stringType == "Vector3")
-        {
-            variantType = VAR_VECTOR3;
-        }
+            if (duk_is_object(ctx, -1))
+            {
+                duk_enum(ctx, -1, DUK_ENUM_OWN_PROPERTIES_ONLY);
+
+                while (duk_next(ctx, -1, 1)) {
+
+                    String name = duk_get_string(ctx, -2);
+
+                    VariantType variantType = VAR_NONE;
+                    Variant defaultValue;
+
+                    if (duk_is_string(ctx, -1))
+                    {
+                        variantType = VAR_STRING;
+                        defaultValue = duk_to_string(ctx, -1);
+                    }
+                    else if (duk_is_number(ctx, -1))
+                    {
+                        variantType = VAR_FLOAT;
+                        defaultValue = (float) duk_to_number(ctx, -1);
+                    }
+                    else if (duk_is_array(ctx, -1))
+                    {
+                        if (duk_get_length(ctx, -1) > 0)
+                        {
+                            duk_get_prop_index(ctx, -1, 0);
+
+                            // TODO: class types
+                            variantType = (VariantType) duk_require_number(ctx, -1);
 
-        if (variantType == VAR_NONE)
-            continue;
+                            duk_pop(ctx);
+                        }
 
-        fields_[name] = variantType;
+                        if (duk_get_length(ctx, -1) > 1)
+                        {
+                            duk_get_prop_index(ctx, -1, 1);
+                            // default value
+                            js_to_variant(ctx, -1, defaultValue);
+
+                            duk_pop(ctx);
+                        }
+
+                    }
+                    else if (duk_is_boolean(ctx, -1))
+                    {
+                        variantType = VAR_BOOL;
+                        defaultValue = duk_to_boolean(ctx, -1) ? true : false;
+                    }
+
+
+                    if (defaultValue.GetType() != VAR_NONE)
+                    {
+                        defaultFieldValues_[name] = defaultValue;
+
+                    }
+
+                    if (variantType != VAR_NONE)
+                        fields_[name] = variantType;
+
+                    duk_pop_2(ctx);  // pop key value
+                }
+
+                duk_pop(ctx);  // pop enum object
+
+            }
+
+        }
 
+        duk_set_top(ctx, top);
     }
 
-    SetMemoryUse(dataSize);
+    SetMemoryUse(0);
 
     return true;
 }

+ 3 - 0
Source/AtomicJS/Javascript/JSComponentFile.h

@@ -48,9 +48,12 @@ public:
     /// Save resource
     virtual bool Save(Serializer& dest) const;
 
+    void GetDefaultFieldValue(const String& name, Variant& v);
+
 private:
 
     HashMap<String, VariantType> fields_;
+    VariantMap defaultFieldValues_;
 
 };
 

+ 1 - 19
Source/AtomicJS/Javascript/JSSceneSerializable.cpp

@@ -163,26 +163,8 @@ static int Serializable_GetAttribute(duk_context* ctx)
             }
             else
             {
-                HashMap<String, VariantType>::ConstIterator itr = fields.Find(name);
                 Variant v;
-                switch (itr->second_)
-                {
-                case VAR_BOOL:
-                    v = false;
-                    break;
-                case VAR_STRING:
-                    v = "";
-                    break;
-                case VAR_FLOAT:
-                    v = 0.0f;
-                    break;
-                case VAR_VECTOR3:
-                    v = Vector3::ZERO;
-                    break;
-                default:
-                    break;
-                }
-
+                file->GetDefaultFieldValue(name, v);
                 js_push_variant(ctx,  v);
                 return 1;
             }

+ 2 - 0
Source/AtomicJS/Javascript/JSVM.cpp

@@ -52,6 +52,8 @@ void JSVM::InitJSContext()
     // create root Atomic Object
     duk_push_global_object(ctx_);
     duk_push_object(ctx_);
+    duk_push_boolean(ctx_, context_->GetEditorContext() ? 1 : 0);
+    duk_put_prop_string(ctx_, -2, "editor");
     duk_put_prop_string(ctx_, -2, "Atomic");
     duk_pop(ctx_);