示例#1
0
文件: GLCSharp.cs 项目: h3tch/ProtoFX
        /// <summary>
        /// Create a new external class instance by processing the specified compiler block.
        /// </summary>
        /// <param name="block"></param>
        /// <param name="scene"></param>
        /// <param name="err"></param>
        /// <returns></returns>
        internal static object CreateInstance(Compiler.Block block, Dict scene, CompileException err)
        {
            // GET CLASS COMMAND
            var cmds = block["class"].ToList();

            if (cmds.Count == 0)
            {
                err.Add("Instance must specify a 'class' command " +
                        "(e.g., class csharp_name class_name).", block);
                return(null);
            }
            var cmd = cmds.First();

            // check command
            if (cmd.ArgCount < 1)
            {
                err.Add("'class' command must specify a csharp object name.", cmd);
                return(null);
            }

            // FIND CSHARP CLASS DEFINITION
            var csharp = scene.GetValueOrDefault <GLCsharp>(cmd[0].Text);

            if (csharp == null)
            {
                err.Add($"Could not find csharp code '{cmd[0].Text}' of command '{cmd.Text}' ", cmd);
                return(null);
            }

            // INSTANTIATE CSHARP CLASS
            return(csharp.CreateInstance(block, cmd, scene, err));
        }
示例#2
0
文件: Compiler.cs 项目: h3tch/ProtoFX
            /// <summary>
            /// Parse the command and extract arguments as values.
            /// </summary>
            /// <param name="types">List of argument types.</param>
            /// <param name="mandatory">Specifies which of this arguments are mandatory.</param>
            /// <param name="unusedArgs">List of arguments the where not parsed.</param>
            /// <param name="scene">Dictionary of scene objects.</param>
            /// <param name="err"></param>
            /// <returns>List of objects values. If a value could not be
            /// parsed, the returned value will be null.</returns>
            public (object[], string[]) Parse(Type[] types, bool[][] mandatory, Dict scene,
                                              CompileException err = null)
            {
                var values = new object[types.Length];

                // parse command arguments
                var lastArgUsed = 0;

                for (var a = 0; a < Length; a++)
                {
                    var arg = this[a];
                    var I   = values
                              .Zip(Enumerable.Range(0, types.Length), (x, i) => x == null ? i : -1)
                              .Where(x => x >= 0);
                    foreach (var i in I)
                    {
                        try
                        {
                            values[i] = types[i].IsSubclassOf(typeof(GLObject))
                                ? scene.GetValueOrDefault <GLObject>(arg.Text)
                                : types[i].IsEnum
                                    ? Enum.Parse(types[i], arg.Text, true)
                                    : Convert.ChangeType(arg.Text, types[i],
                                                         CultureInfo.CurrentCulture);
                            if (values[i] != null)
                            {
                                lastArgUsed = a;
                                break;
                            }
                        }
                        catch { }
                    }
                }

                // return list of unused arguments
                var unusedArgs = this.Skip(lastArgUsed + 1).Select(x => x.Text).ToArray();

                // check for errors
                var valid = values.Select(x => x != null);

                for (int i = 0; i < mandatory.Length; i++)
                {
                    if (mandatory[i].Zip(valid, (m, v) => !m | v).All(x => x))
                    {
                        return(values, unusedArgs);
                    }
                }

                err?.Add("Command has one or more invalid arguments.", this);
                return(values, unusedArgs);
            }
示例#3
0
文件: GLCSharp.cs 项目: h3tch/ProtoFX
        /// <summary>
        /// Create a new external method-call by processing the specified compiler command.
        /// </summary>
        /// <param name="cmd"></param>
        /// <param name="err"></param>
        /// <returns></returns>
        internal static MethodInfo GetMethod(Compiler.Command cmd, Dict scene, CompileException err)
        {
            // check command
            if (cmd.ArgCount < 1)
            {
                err.Add("'class' command must specify a csharp object name.", cmd);
                return(null);
            }

            // FIND CSHARP CLASS DEFINITION
            var csharp = scene.GetValueOrDefault <GLCsharp>(cmd[0].Text);

            if (csharp == null)
            {
                err.Add($"Could not find csharp code '{cmd[0].Text}' of command '{cmd.Text}' ", cmd);
                return(null);
            }

            // INSTANTIATE CSHARP CLASS
            return(csharp.GetMethod(cmd, err));
        }
示例#4
0
        /// <summary>
        /// Parse command line and attach the buffer object
        /// to the specified unit (output stream).
        /// </summary>
        /// <param name="unit">Vertex output stream unit.</param>
        /// <param name="cmd">Command line to process.</param>
        /// <param name="scene">Dictionary of scene objects.</param>
        /// <param name="err">Compiler exception collector.</param>
        private void Attach(int unit, Compiler.Command cmd, Dict scene, CompileException err)
        {
            if (cmd.ArgCount == 0)
            {
                err.Add("Command buff needs at least one attribute (e.g. 'buff buff_name')", cmd);
                return;
            }

            // get buffer
            var buf = scene.GetValueOrDefault <GLBuffer>(cmd[0].Text);

            if (buf == null)
            {
                err.Add($"The name '{cmd[0]}' does not reference an object of type 'buffer'.", cmd);
                return;
            }

            // parse offset
            int offset = 0;

            if (cmd.ArgCount > 1 && int.TryParse(cmd[1].Text, out offset) == false)
            {
                err.Add($"The second parameter (offset) of buff {unit} is invalid.", cmd);
                return;
            }

            // parse size
            int size = buf.Size;

            if (cmd.ArgCount > 2 && int.TryParse(cmd[2].Text, out size) == false)
            {
                err.Add($"The third parameter (size) of buff {unit} is invalid.", cmd);
                return;
            }

            // bind buffer to transform feedback
            GL.BindBufferRange(BufferRangeTarget.TransformFeedbackBuffer,
                               unit, buf.glname, (IntPtr)offset, (IntPtr)size);
        }
示例#5
0
        /// <summary>
        /// Create class instance of a C# class compiled through GLCSharp.
        /// </summary>
        /// <param name="params">Input parameters for GLObject creation.</param>
        public GLInstance(Compiler.Block block, Dict scene, bool debugging)
            : base(block.Name, block.Anno)
        {
            var err = new CompileException($"instance '{Name}'");

            // INSTANTIATE CSHARP CLASS FROM CODE BLOCK
            Instance = GLCsharp.CreateInstance(block, scene, err);
            if (err.HasErrors)
            {
                throw err;
            }

            // get Bind method from main class instance
            update = Instance.GetType().GetMethod("Update", new[] {
                typeof(int), typeof(int), typeof(int), typeof(int), typeof(int)
            });

            // get Unbind method from main class instance
            endpass = Instance.GetType().GetMethod("EndPass", new[] { typeof(int) });

            // get Delete method from main class instance
            delete = Instance.GetType().GetMethod("Delete");

            // get all public methods and check whether
            // they can be used as event handlers for glControl
            var reference = scene.GetValueOrDefault <GLReference>(GraphicControl.nullname);
            var glControl = (GraphicControl)reference.Reference;
            var methods   = Instance.GetType().GetMethods(BindingFlags.Public | BindingFlags.Instance);

            foreach (var method in methods)
            {
                var info = glControl.GetType().GetEvent(method.Name);
                if (info != null)
                {
                    var csmethod = Delegate.CreateDelegate(info.EventHandlerType, Instance, method.Name);
                    info.AddEventHandler(glControl, csmethod);
                }
            }
        }