public LuaTable CreateModuleFromTypes(IEnumerable<Type> types, string moduleName = "") { LuaTable module = new LuaTable(); StringBuilder moduleDocs = new StringBuilder(); foreach(Type t in types) { if (t.GetCustomAttributes(true).OfType<LuaExcludeAttribute>().Any()) continue; string typeName = t.Name; moduleDocs.AppendLine(typeName); StringBuilder typeDoc = new StringBuilder(); LuaTable subModule = new LuaTable(); LuaTable metatable = new LuaTable(); metatable.SetNameValue("__index", metatable); subModule.MetaTable = metatable; // Create a constructor where appropriate ConstructorInfo constructorInfo = null; if (t.IsValueType) { subModule.Register("new", (args) => { return ObjectToLua(Activator.CreateInstance(t)); }); typeDoc.AppendFormat("new() - creates a new instance of the {0} type.\n", typeName); } else { if ((constructorInfo = t.GetConstructor(new Type[] { })) != null) { subModule.Register("new", (args) => { try { return ObjectToLua(constructorInfo.Invoke(new object[] { })); } catch (Exception e) { Console.Error.WriteLine("Lua constructor for {0} threw an exception of type {1}: {2}", t.Name, e.GetType().Name, e.Message); if (e.InnerException != null) Console.Error.WriteLine("Inner exception of type {0}: {1}", e.InnerException.GetType().Name, e.InnerException.Message); } return LuaNil.Nil; }); } else if ((constructorInfo = t.GetConstructor(new Type[] { typeof(LuaValue[]) })) != null) { subModule.Register("new", (args) => { try { return ObjectToLua(constructorInfo.Invoke(new object[] { args })); } catch (Exception e) { Console.Error.WriteLine("Lua constructor for {0} threw an exception of type {1}: {2}", t.Name, e.GetType().Name, e.Message); if (e.InnerException != null) Console.Error.WriteLine("Inner exception of type {0}: {1}", e.InnerException.GetType().Name, e.InnerException.Message); } return LuaNil.Nil; }); } if (constructorInfo != null) { if (constructorInfo.GetCustomAttributes(true).OfType<LuaCommandUsageAttribute>().Any()) { var attribute = constructorInfo.GetCustomAttributes(true).OfType<LuaCommandUsageAttribute>().Single(); typeDoc.Append(attribute.Usage); } else { typeDoc.AppendFormat("new() - creates a new instance of the {0} type.\n", typeName); } } } // Create member accessors var members = from m in t.GetMembers(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public) where (m.MemberType == MemberTypes.Field || m.MemberType == MemberTypes.Property || m.MemberType == MemberTypes.Method) select m; foreach(MemberInfo member in members) { bool excludeGetter = false, excludeSetter = false; if (member.GetCustomAttributes(true).OfType<LuaExcludeAttribute>().Any()) { LuaExcludeAttribute exclude = member.GetCustomAttributes(true).OfType<LuaExcludeAttribute>().Single(); excludeSetter = true; if (!exclude.ReadOnly) excludeGetter = true; } var field = member as FieldInfo; var prop = member as PropertyInfo; var method = member as MethodInfo; string memberType = ""; if (field != null) { memberType = field.FieldType.Name; } else if (prop != null) { memberType = prop.PropertyType.Name; } else if (method != null) { memberType = method.DeclaringType.Name; } LuaFunction func = excludeSetter ? null : GetLuaFunc(member as MethodInfo); if(func != null) { // It's a function, and we'll register it. No way to create // documentation for it, so ideally it also makes use of the // LuaCommandUsage attribute for documentation. metatable.SetNameValue(member.Name, func); if (member.GetCustomAttributes(true).OfType<LuaCommandUsageAttribute>().Any()) { LuaCommandUsageAttribute usage = member.GetCustomAttributes(true).OfType<LuaCommandUsageAttribute>().Single(); typeDoc.AppendLine(String.Format("{0}:{1} - {2}", t.Name, member.Name, usage.Usage)); } else { typeDoc.AppendLine(member.Name); } } LuaFunction getter = excludeGetter ? null : GetAccessorLuaFunction(member); if(getter != null) { typeDoc.AppendFormat("{0} - Gets a {1} value from the {2} struct\n", "Get" + member.Name, memberType, typeName); metatable.SetNameValue("Get" + member.Name, getter); } LuaFunction setter = excludeSetter ? null : GetSetterLuaFunction(member); if(setter != null) { typeDoc.AppendFormat("{0} - Sets a {1} value to the {2} struct\n", "Set" + member.Name, memberType, typeName); metatable.SetNameValue("Set" + member.Name, setter); } } // Register the type metatable and help docs _environment.SetMetatableForType(t, metatable); module.SetNameValue(typeName, subModule); LuaEnvironment.RegisterNewUsage(moduleName + "." + typeName, typeDoc.ToString()); } // Register the module's documentation LuaEnvironment.RegisterNewUsage(moduleName, moduleDocs.ToString()); return module; }
/// <summary> /// LoadContent will be called once per game and is the place to load /// all of your content. /// </summary> protected override void LoadContent() { // Create a new SpriteBatch, which can be used to draw textures. spriteBatch = new SpriteBatch(GraphicsDevice); // TODO: use this.Content to load your game content here m_env = new Env(); m_sunImg = Content.Load<Texture2D>("sun"); string sunSpriteSer = @" {Sprites:[ {Offset:{X:0,Y:0},Rectangle:{Height:122,Width:158,X:0,Y:0}}, {Offset:{X:4,Y:0},Rectangle:{Height:122,Width:135,X:158,Y:0}} ]} "; MemoryStream ms = new MemoryStream(); StreamWriter sw = new StreamWriter(ms); sw.Write(sunSpriteSer); sw.Flush(); ms.Flush(); ms.Seek(0, SeekOrigin.Begin); System.Runtime.Serialization.Json.DataContractJsonSerializer serializer = new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(SpriteSheet)); m_sunSS = (SpriteSheet)serializer.ReadObject(ms); m_sun = new Item(m_sunImg, m_sunSS); string script = "a != b"; /* string script = @" item.SetSprite((env.GetTimeMs() / 200) % 2); item.SetSprite = 0; "; */ Parser parser = new Parser(); TextInput ti = new TextInput(script); bool succ; m_script = parser.ParseChunk(ti, out succ); if (!succ) Debug.WriteLine(parser.GetEorrorMessages()); m_globals = new LuaTable(); LuaTable methods = new LuaTable(); methods.SetNameValue("__index", methods); methods.SetNameValue("__newindex", methods); methods.Register("SetSprite", m_sun.SetSprite_FromScript); m_globals.SetNameValue("item", new Language.Lua.LuaUserdata(m_sun, methods)); methods = new LuaTable(); methods.SetNameValue("__index", methods); methods.Register("GetTimeMs", m_env.GetTimeMs); m_globals.SetNameValue("env", new LuaUserdata(m_env, methods)); m_env.TimeMs = 0; }