Exemple #1
0
        /// <summary>
        /// Inverts quaternion
        /// </summary>
        /// <returns>
        /// inverted quaternion
        /// </returns>
        public JsValue QuatInv(CpuBlock c, JsValue thizArg, JsValue[] x)
        {
            var thiz = ((ObjectInstance)thizArg);
            var q1   = BlockUtils.ToQuat(thiz);

            return(BlockUtils.Quat2Obj(c, Quaternion.Inverse(q1)));
        }
Exemple #2
0
        public ApiObjectConstructor(CpuBlock c, string name, List <CpuApiProperty> staticProps) : base(c.Interp, new JsString(name))
        {
            cpu   = c;
            Props = staticProps?.ToDictionary(x => x.Name);
            var properties = new PropertyDictionary(Props?.Count ?? 0, checkExistingKeys: false);

            if (Props != null)
            {
                foreach (var kp in Props)
                {
                    if (kp.Value is CpuApiFunc f)
                    {
                        if (f.Name == ConstructorMethodName)
                        {
                            Constructor = f.Implementation;
                        }
                        else
                        {
                            properties[kp.Key] = new PropertyDescriptor(new ClrFunctionInstance(Engine, kp.Key, (t, a) => WrappedApi(t, a, f.Implementation), f.Arguments.Count, PropertyFlag.Configurable), PropertyFlag.Configurable);
                        }
                    }
                    else if (kp.Value is CpuApiValue v)
                    {
                        properties[kp.Key] = new PropertyDescriptor(v.Value, PropertyFlag.Configurable);
                    }
                }
            }
            SetProperties(properties);
        }
        /// <summary>
        /// Magnitude of 3d Vector
        /// </summary>
        /// <param name="c"></param>
        /// <param name="thizArg"></param>
        /// <param name="x"></param>
        /// <returns>
        /// The magnitude of Vector3
        /// </returns>
        public JsValue VecMag(CpuBlock c, JsValue thizArg, JsValue[] x)
        {
            var     vobj = ((ObjectInstance)thizArg);
            Vector3 v    = BlockUtils.ToVector3(vobj);

            return(v.magnitude);
        }
Exemple #4
0
 public JsValue Float(CpuBlock c, JsValue ctx, JsValue[] x)
 {
     if (x.Length < 1 || !BlockUtils.TryGetFloat(x[0], out float v))
     {
         throw new Exception("Invalid value");
     }
     return(v);
 }
Exemple #5
0
 public JsValue Str(CpuBlock c, JsValue ctx, JsValue[] x)
 {
     if (x.Length < 1)
     {
         throw new Exception("Invalid value");
     }
     return(x[0]?.ToString());
 }
Exemple #6
0
 // Legacy APIs
 public JsValue Int(CpuBlock c, JsValue ctx, JsValue[] x)
 {
     if (x.Length < 1 || !BlockUtils.TryGetLong(x[0], out long v))
     {
         throw new Exception("Invalid value");
     }
     return(v);
 }
Exemple #7
0
        public static ApiObjectPrototype CreatePrototypeObject(CpuBlock block, ApiObjectConstructor constructor, List <CpuApiProperty> props)
        {
            var obj = new ApiObjectPrototype(block, props)
            {
                _prototype   = block.Interp.Object.PrototypeObject,
                _constructor = constructor
            };

            return(obj);
        }
Exemple #8
0
        public static ApiObjectConstructor CreateApiConstructor(CpuBlock cpu, string name, List <CpuApiProperty> staticProps, List <CpuApiProperty> instanceProps)
        {
            var obj = new ApiObjectConstructor(cpu, name, staticProps)
            {
                _prototype = cpu.Interp.Function.PrototypeObject,
            };

            obj.PrototypeObject      = ApiObjectPrototype.CreatePrototypeObject(cpu, obj, instanceProps);
            obj._prototypeDescriptor = new PropertyDescriptor(obj.PrototypeObject, PropertyFlag.AllForbidden);
            return(obj);
        }
        /// <summary>
        /// Calculates the vector cross product
        /// </summary>
        /// <param name="c"></param>
        /// <param name="thizArg"></param>
        /// <param name="x"></param>
        /// <returns>
        /// The cross product of two 3D vectors.
        /// </returns>
        public JsValue VecCross(CpuBlock c, JsValue thizArg, JsValue[] x)
        {
            if (x.Length < 1)
            {
                throw new Exception("Invalid value");
            }

            var     v1obj = ((ObjectInstance)thizArg);
            var     v2obj = ((ObjectInstance)x[0]);
            Vector3 v1    = BlockUtils.ToVector3(v1obj);
            Vector3 v2    = BlockUtils.ToVector3(v2obj);

            return(BlockUtils.Vec2Obj(c, Vector3.Cross(v1, v2)));
        }
Exemple #10
0
        public JsValue CreateThis(CpuBlock c, JsValue thizArg, JsValue[] args)
        {
            var thiz  = ((ObjectInstance)thizArg);
            var instf = InstanceFields;

            for (int i = 0; i < 3; ++i)
            {
                if (i >= args.Length)
                {
                    return(thizArg);
                }
                float value = BlockUtils.TryGetFloat(args[i], out value) ? value : 0;
                thiz.Set(instf[i].Name, value);
            }
            return(thizArg);
        }
Exemple #11
0
        /// <summary>
        /// Multiply vector3 by scalar
        /// </summary>
        /// <param name="c"></param>
        /// <param name="thizArg"></param>
        /// <param name="x"></param>
        /// <returns>
        /// The result of a vector3 multiplied by scalar.
        /// </returns>
        public JsValue VecMul(CpuBlock c, JsValue thizArg, JsValue[] x)
        {
            if (x.Length < 1)
            {
                throw new Exception("Invalid value");
            }

            var   vobj = ((ObjectInstance)thizArg);
            float f;

            if (!BlockUtils.TryGetFloat(x[0], out f))
            {
                throw new Exception("Invalid value");
            }
            Vector3 v = BlockUtils.ToVector3(vobj);

            return(BlockUtils.Vec2Obj(c, v * f));
        }
Exemple #12
0
        public void OnGUI()
        {
            if (Game.IsSimulating)
            {
                return;
            }

            if (textStyle == null)
            {
                InitFont();
            }

            var mach = Machine.Active();

            if (mach == null || !MachineHandlers.ContainsKey(mach))
            {
                return;
            }

            SelectedCpu = MachineHandlers[mach].GetCpus().Where(x => x.Key.IsModifying).Select(x => x.Value).FirstOrDefault();
            if (SelectedCpu != null)
            {
                if (PrevCpu != SelectedCpu)
                {
                    PrevCpu              = SelectedCpu;
                    sourceScript         = editedScript = SelectedCpu.Script.Value;
                    lastScriptChangeTime = Time.time;
                    editHistory          = new HistoryBuffer <string>(50);
                    editHistory.Add(sourceScript);
                }
                uiRect = GUILayout.Window(windowId, uiRect, GuiFunc, "CPU edit");
            }
            else
            {
                if (KeyTexts.Count > 0)
                {
                    KeyTexts = new Dictionary <MExtKey, string>();
                }
            }
        }
Exemple #13
0
        /// <summary>
        /// Multiply quaternion with either another quaternion or a 3d vector.
        /// </summary>
        /// <returns>
        /// Vector if second argument is vector and quaternion if second argument is quaternion
        /// </returns>
        public JsValue QuatMult(CpuBlock c, JsValue thizArg, JsValue[] x)
        {
            if (x.Length < 1)
            {
                throw new Exception("Invalid value");
            }

            var q1obj = ((ObjectInstance)thizArg);
            var q2obj = ((ObjectInstance)x[0]);
            var q1    = BlockUtils.ToQuat(q1obj);

            if (q2obj.HasProperty("w"))
            {
                var q2 = BlockUtils.ToQuat(q2obj);
                return(BlockUtils.Quat2Obj(c, q1 * q2));
            }
            else
            {
                var v = BlockUtils.ToVector3(q2obj);
                return(BlockUtils.Vec2Obj(c, q1 * v));
            }
        }
Exemple #14
0
        public void Attach(CpuBlock block)
        {
            foreach (var api in RootApi)
            {
                block.Interp.SetValue(api.Key, (t, a) => api.Value.Implementation(block, t, a));
            }

            foreach (var kp in ApiNamespaces)
            {
                var obj = block.Interp.Global.Get(kp.Key) as ObjectInstance;
                if (obj != null)
                {
                    throw new Exception($"Runtime error: namespace {kp.Key} already exists");
                }

                obj = ApiObjectConstructor.CreateApiConstructor(block, kp.Key, kp.Value.StaticFields, kp.Value.InstanceFields);
                block.Interp.Global.Set(kp.Key, obj);
            }
            // Legacy crutch
            var math = block.Interp.Global.Get("Math") as ObjectInstance;

            math.Set("newton", block.Interp.Global.Get("MathExt").Get("newton"));
        }
Exemple #15
0
        public void Awake()
        {
            // Loading
            var engine = new Jint.Engine();

            //var logic = new Interpreter();
            Registers   = new Dictionary <Type, Action <BlockBehaviour, KeyInputController> >();
            Unregisters = new Dictionary <Type, Action <BlockBehaviour> >();

            ModConsole.RegisterCommand("script", args => {
                var text = string.Join(" ", args);
                //var func = logic.PrepareScript(text);
                //logic.AddExtFunc(func, "print", (ctx, x) => { ModConsole.Log(x[0]?.ToString()); return null; }, true);
                //logic.SetScript(func);
                //var res = logic.ContinueScript(1000);
                Func <JsValue, JsValue[], JsValue> printCb = (thiz, x) => {
                    ModConsole.Log(x[0]?.ToObject().ToString());
                    return(x[0]);
                };

                JsValue curV = null;
                Func <JsValue, JsValue[], JsValue> irqv = (thiz, x) => {
                    curV = x[0];
                    return(null);
                };
                var script = new JavaScriptParser(text, Jint.Engine.DefaultParserOptions).ParseScript();
                engine.SetValue("print", printCb);
                engine.SetValue("irqv", irqv);
                engine.SetScript(script);
                engine.Executor.OnLog = (x) => ModConsole.Log(x?.ToString());
                bool cli = false;
                engine.Executor.OnNextStatement = () =>
                {
                    if (cli)
                    {
                        return;
                    }
                    cli = true;
                    try
                    {
                        if (curV != null)
                        {
                            engine.Invoke(curV);
                        }
                    }
                    finally
                    {
                        cli = false;
                    }
                };
                var res = engine.ContinueScript(1000);
                ModConsole.Log(res?.ToString());
            }, "exec script");

            ModConsole.RegisterCommand("cpuapi", args =>
            {
                foreach (var line in SingleInstance <Blocks.Api.CpuApi> .Instance.GetHelp())
                {
                    ModConsole.Log(line);
                }
            }, "print cpu api list");

            ModConsole.RegisterCommand("sensordbg", args =>
            {
                DrawSensorDebug = args.Length < 1 ? false : args[0] == "true";
            }, "print sensor debug points");

            CpuBlock.Create(this);
            // These creator functions find corresponding block in game prefabs
            // and replace it with inheritor
            ExtLogicGate.Create(this);
            ExtAltimeterBlock.Create(this);
            ExtSpeedometerBlock.Create(this);
            ExtAnglometerBlock.Create(this);
            ExtSensorBlock.Create(this);
            ModConsole.Log($"Logic mod Awake");

            Events.OnMachineSimulationToggle += Events_OnMachineSimulationToggle;
            LineMaterial           = new Material(Shader.Find("Hidden/Internal-Colored"));
            LineMaterial.hideFlags = HideFlags.HideAndDontSave;
            LineMaterial.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
            LineMaterial.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
            LineMaterial.SetInt("_Cull", (int)UnityEngine.Rendering.CullMode.Off);
            LineMaterial.SetInt("_ZWrite", 0);

            Camera.onPostRender += DrawConnectingLines;
            Events.OnBlockInit  += InitBlock;

            CpuInfoMessage = ModNetworking.CreateMessageType(new DataType[]
            {
                DataType.Block,
                DataType.ByteArray
            });

            CpuLogMessage = ModNetworking.CreateMessageType(new DataType[]
            {
                DataType.Block,
                DataType.String
            });

            ModNetworking.Callbacks[CpuInfoMessage] += (Action <Message>)((msg) =>
            {
                Player localPlayer = Player.GetLocalPlayer();
                if (msg == null || localPlayer == null || !localPlayer.IsHost)
                {
                    return;
                }

                var block = msg.GetData(0) as Modding.Blocks.Block;
                if (!(block?.BlockScript is CpuBlock cpu))
                {
                    return;
                }

                if (block.Machine == localPlayer.Machine)
                {
                    return; // don't read updates for MY machine!
                }
                cpu.AfterEdit_ServerRecv((byte[])msg.GetData(1));
            });

            ModNetworking.Callbacks[CpuLogMessage] += (Action <Message>)((msg) =>
            {
                if (msg == null)
                {
                    return;
                }

                var block = msg.GetData(0) as Modding.Blocks.Block;
                if (!(block?.BlockScript is CpuBlock cpu))
                {
                    return;
                }

                cpu.LogMessage((string)msg.GetData(1));
            });
        }
 public void RemoveCpuBlock(CpuBlock c)
 {
     CpuBlocks.Remove(c.BlockBehaviour);
 }
 public void AddCpuBlock(CpuBlock c)
 {
     CpuBlocks[c.BlockBehaviour] = c;
 }
Exemple #18
0
        // Find a zero of a real or complex function using the Newton-Raphson
        // (or secant or Halley’s) method.
        //
        // Math.newton(func, x0, fprime=null, tol=1.48e-08, maxiter=50, fprime2=null,
        // x1, rtol=0.0, full_output=false)
        //
        // Mimicks scipy's implementation of scipy.optimize.newton
        //
        // Parameters
        // func: function
        //      The function whose zero is wanted. It must be a function of a
        //      single variable
        // x0: float
        //      An initial estimate of the zero that should be somewhere near
        //     the actual zero.
        // fprime : function, optional
        //      The derivative of the function when available and convenient. If it
        //      is null (default), then the secant method is used.
        // tol : float, optional
        //      The allowable error of the zero value.
        // maxiter : int, optional
        //      Maximum number of iterations.
        // fprime2 : function, optional
        //      The second order derivative of the function when available and
        //      convenient. If it is null (default), then the normal Newton-Raphson
        //      or the secant method is used. If it is not null, then Halley's method
        //      is used.
        // x1 : float, optional
        //      Another estimate of the zero that should be somewhere near the
        //      actual zero. Used if `fprime` is not provided.
        // rtol : float, optional
        //      Tolerance (relative) for termination.
        // full_output : bool, optional
        //      If `full_output` is false (default), the root is returned.
        //      If true, the dictionary {{"root": root}, {"converged": true/false},
        //      {"iter": numIter}} is returned.
        public JsValue Newton(CpuBlock cpu, JsValue ctx, JsValue[] x)
        {
            var eng = cpu.Interp;
            int l   = x.Length;

            // Arguments and their default values:
            FunctionInstance func;
            float            x0;
            JsValue          fprime      = null;
            float            tol         = 1.48e-08F;
            long             maxiter     = 50;
            JsValue          fprime2     = null;
            float            x1          = 0;
            float            rtol        = 0.0F;
            bool             full_output = false;

            bool x1Provided = false;

            JsValue[] args = new JsValue[1];

            if (l < 2)
            {
                throw new Exception("Invalid value");
            }

            // Conditionally initialize the arguments
            void Parse()
            {
                int curArgIndex = 0;

                func = x[curArgIndex++] as FunctionInstance;

                if (!BlockUtils.TryGetFloat(x[curArgIndex++], out x0))
                {
                    throw new Exception("Invalid value");
                }

                if (curArgIndex >= l)
                {
                    return;
                }
                fprime = x[curArgIndex++];

                if (curArgIndex >= l)
                {
                    return;
                }
                if (!BlockUtils.TryGetFloat(x[curArgIndex++], out tol))
                {
                    throw new Exception("Invalid value");
                }

                if (curArgIndex >= l)
                {
                    return;
                }
                if (!BlockUtils.TryGetLong(x[curArgIndex++], out maxiter))
                {
                    throw new Exception("Invalid value");
                }

                if (curArgIndex >= l)
                {
                    return;
                }
                fprime2 = x[curArgIndex++];

                if (curArgIndex >= l)
                {
                    return;
                }
                x1Provided = BlockUtils.TryGetFloat(x[curArgIndex++], out x1);

                if (curArgIndex >= l)
                {
                    return;
                }
                if (!BlockUtils.TryGetFloat(x[curArgIndex++], out rtol))
                {
                    throw new Exception("Invalid value");
                }

                if (curArgIndex >= l)
                {
                    return;
                }
                full_output = BlockUtils.GetBool(x[curArgIndex++]);
            }

            Parse();

            if (tol <= 0)
            {
                throw new Exception("tol too small (" + tol + " <= 0)");
            }
            if (maxiter < 1)
            {
                throw new Exception("maxiter must be greater than 0");
            }
            float p0  = x0;
            long  itr = 0;
            float p   = 0;

            if (fprime is FunctionInstance fprimeFunc)
            {
                // Newton - Raphson method
                for (; itr < maxiter; ++itr)
                {
                    // first evaluate fval
                    args[0] = p0;
                    float fval = (float)TypeConverter.ToNumber(func.Call(ctx, args));
                    // if fval is 0, a root has been found, then terminate
                    if (fval == 0)
                    {
                        return(_newton_result_select(eng, full_output, p0, itr, converged: true));
                    }
                    float fder = (float)TypeConverter.ToNumber(fprimeFunc.Call(ctx, args));
                    // stop iterating if the derivative is zero
                    if (fder == 0)
                    {
                        return(_newton_result_select(eng, full_output, p0, itr + 1, converged: false));
                    }

                    // Newton step
                    float newton_step = fval / fder;
                    if (fprime2 is FunctionInstance fp2func)
                    {
                        float fder2 = (float)TypeConverter.ToNumber(fp2func.Call(ctx, args));
                        // Halley's method:
                        // newton_step /= (1.0 - 0.5 * newton_step * fder2 / fder)
                        // Only do it if denominator stays close enough to 1
                        // Rationale:  If 1-adj < 0, then Halley sends x in the
                        // opposite direction to Newton.  Doesn't happen if x is close
                        // enough to root.
                        float adj = newton_step * fder2 / fder / 2;
                        if (Math.Abs(adj) < 1)
                        {
                            newton_step /= 1.0F - adj;
                        }
                    }
                    p = p0 - newton_step;
                    if (WithinTol(p, p0, atol: tol, rtol: rtol))
                    {
                        return(_newton_result_select(eng, full_output, p, itr + 1, converged: true));
                    }
                    p0 = p;
                }
            }
            else
            {
                // secant method
                float p1, q0, q1;
                if (x1Provided)
                {
                    if (x1 == x0)
                    {
                        throw new Exception("x1 and x0 must be different");
                    }
                    p1 = x1;
                }
                else
                {
                    float eps = 1e-4F;
                    p1  = x0 * (1 + eps);
                    p1 += (p1 >= 0 ? eps : -eps);
                }
                args[0] = p0;
                q0      = (float)TypeConverter.ToNumber(func.Call(ctx, args));
                args[0] = p1;
                q1      = (float)TypeConverter.ToNumber(func.Call(ctx, args));
                if (Math.Abs(q1) < Math.Abs(q0))
                {
                    float temp = q1;
                    q1 = q0;
                    q0 = temp;

                    temp = p0;
                    p0   = p1;
                    p1   = temp;
                }
                for (; itr < maxiter; ++itr)
                {
                    if (q0 == q1)
                    {
                        p = (p1 + p0) / 2.0F;
                        if (p1 != p0)
                        {
                            return(_newton_result_select(eng, full_output, p, itr + 1, converged: false));
                        }
                        else
                        {
                            return(_newton_result_select(eng, full_output, p, itr + 1, converged: true));
                        }
                    }
                    else
                    {
                        // Secant Step
                        if (Math.Abs(q1) > Math.Abs(q0))
                        {
                            p = (-q0 / q1 * p1 + p0) / (1.0F - q0 / q1);
                        }
                        else
                        {
                            p = (-q1 / q0 * p0 + p1) / (1.0F - q1 / q0);
                        }
                    }
                    if (WithinTol(p, p1, atol: tol, rtol: rtol))
                    {
                        return(_newton_result_select(eng, full_output, p, itr + 1, converged: true));
                    }

                    p0      = p1;
                    q0      = q1;
                    p1      = p;
                    args[0] = p1;
                    q1      = (float)TypeConverter.ToNumber(func.Call(ctx, args));
                }
            }
            return(_newton_result_select(eng, full_output, p, itr + 1, converged: false));
        }
Exemple #19
0
 private ApiObjectPrototype(CpuBlock block, List <CpuApiProperty> props) : base(block.Interp)
 {
     cpu   = block;
     Props = props?.ToDictionary(x => x.Name);
 }