Beispiel #1
0
        public static KontrolRegistry CreateKSP()
        {
            KontrolRegistry registry = KontrolRegistry.CreateCore();

            registry.RegisterModule(KSPMathModule.Instance.module);

            KSPVessel.KSPVesselModule.DirectBindings();
            registry.RegisterModule(
                BindingGenerator.BindModule(typeof(KSPConsole.KSPConsoleModule)));
            registry.RegisterModule(
                BindingGenerator.BindModule(typeof(KSPGame.KSPGameModule)));
            registry.RegisterModule(
                BindingGenerator.BindModule(typeof(KSPGame.KSPGameWarpModule)));
            registry.RegisterModule(
                BindingGenerator.BindModule(typeof(KSPOrbit.KSPOrbitModule)));
            registry.RegisterModule(
                BindingGenerator.BindModule(typeof(KSPControl.KSPControlModule)));
            registry.RegisterModule(
                BindingGenerator.BindModule(typeof(KSPVessel.KSPVesselModule)));
            registry.RegisterModule(BindingGenerator.BindModule(typeof(KSPUI.KSPUIModule)));
            registry.RegisterModule(
                BindingGenerator.BindModule(typeof(KSPDebug.KSPDebugModule)));
            registry.RegisterModule(BindingGenerator.BindModule(typeof(KSPResource.KSPResourceModule)));
            registry.RegisterModule(BindingGenerator.BindModule(typeof(KSPAddons.KSPAddonsModule)));
            registry.RegisterModule(BindingGenerator.BindModule(typeof(Testing.KSPTesting)));

            return(registry);
        }
        public override bool Execute()
        {
            if (String.IsNullOrWhiteSpace(OutputLanguage))
            {
                OutputLanguage = DefaultOutputGenerator.Name;
            }

            BindingGenerator generator = GetBindingGenerator(OutputLanguage);

            if (generator == null)
            {
                Log.LogMessage($"Unknown binding output language '{OutputLanguage}', will use {DefaultOutputGenerator.Name} instead");
                generator = DefaultOutputGenerator.Creator();
            }

            if (generator == null)
            {
                // Should "never" happen
                Log.LogError($"Cannot find binding generator for language {OutputLanguage} or {DefaultOutputGenerator.Name}");
                Complete();
                return(false);
            }

            Log.LogDebugMessage($"Generating {generator.LanguageName} binding sources");
            if (Generate(generator))
            {
                Complete();
            }
            else
            {
                base.Execute();
            }

            return(!Log.HasLoggedErrors);
        }
		void GenerateSourceForLayoutGroup (BindingGenerator generator, LayoutGroup group, Action <string> pathAdder)
		{
			List<ITaskItem> resourceItems = group?.Items;
			if (resourceItems == null || resourceItems.Count == 0)
				return;

			ITaskItem item = resourceItems.FirstOrDefault ();
			if (item == null)
				return;

			string collectionKey;
			if (!GetRequiredMetadata (item, CalculateLayoutCodeBehind.WidgetCollectionKeyMetadata, out collectionKey))
				return;

			ICollection<LayoutWidget> widgets;
			if (!CalculateLayoutCodeBehind.LayoutWidgets.TryGetValue (collectionKey, out widgets) || widgets.Count == 0) {
				string inputPaths = String.Join ("; ", resourceItems.Select (i => i.ItemSpec));
				LogCodedWarning ("XA4222", Properties.Resources.XA4222, inputPaths);
				return;
			}

			string outputFileName;
			if (!GetRequiredMetadata (item, CalculateLayoutCodeBehind.LayoutBindingFileNameMetadata, out outputFileName))
				return;

			string fullClassName;
			if (!GetRequiredMetadata (item, CalculateLayoutCodeBehind.ClassNameMetadata, out fullClassName))
				return;

			string outputFilePath = Path.Combine (MonoAndroidCodeBehindDir, outputFileName);
			string classNamespace;
			string className;
			int idx = fullClassName.LastIndexOf ('.');
			if (idx < 0) {
				classNamespace = String.Empty;
				className = fullClassName;
			} else {
				bool fail = false;
				classNamespace = fullClassName.Substring (0, idx);
				if (String.IsNullOrEmpty (classNamespace)) {
					LogCodedError ("XA4223", Properties.Resources.XA4223, fullClassName);
					fail = true;
				}

				className = fullClassName.Substring (idx + 1);
				if (String.IsNullOrEmpty (className)) {
					LogCodedError ("XA4224", Properties.Resources.XA4224, fullClassName);
					fail = true;
				}

				if (fail)
					return;
			}

			if (!GenerateSource (generator, outputFilePath, widgets, classNamespace, className, group.Classes))
				return;

			pathAdder (outputFilePath);
		}
		bool GenerateSource (StreamWriter writer, BindingGenerator generator, ICollection <LayoutWidget> widgets, string classNamespace, string className, List<PartialClass> partialClasses)
		{
			bool havePartialClasses = partialClasses != null && partialClasses.Count > 0;
			string ns = AppNamespace == null ? String.Empty : $"{AppNamespace}.";

			if (havePartialClasses) {
				string fullBindingClassName = $"{classNamespace}.{className}";
				WriteToPartialClasses (pc => pc.State = generator.BeginPartialClassFile (pc.Writer, fullBindingClassName, pc.Namespace, pc.Name, AndroidFragmentType));
			}

			var state = generator.BeginBindingFile (writer, $"global::{ns}Resource.Layout.{className}", classNamespace, className, AndroidFragmentType);
			foreach (LayoutWidget widget in widgets) {
				DetermineWidgetType (widget, widget.Type == null);
				if (widget.Type == null) {
					widget.TypeFixups = null; // Not needed - we'll use decayed type
					string decayedType = null;
					switch (widget.WidgetType) {
						case LayoutWidgetType.View:
							decayedType = "global::Android.Views.View";
							break;

						case LayoutWidgetType.Fragment:
							decayedType = $"global::{AndroidFragmentType}";
							break;

						case LayoutWidgetType.Mixed:
							decayedType = "object";
							break;

						default:
							throw new InvalidOperationException ($"Widget {widget.Name} is of unknown type {widget.WidgetType}");
					}
					widget.Type = decayedType;
					LogCodedWarning ("XA4225", Properties.Resources.XA4225, widget.Name, className, decayedType);
				}

				if (String.IsNullOrWhiteSpace (widget.Type))
					throw new InvalidOperationException ($"Widget {widget.Name} does not have a type");

				generator.WriteBindingProperty (state, widget, ns);
				WriteToPartialClasses (pc => generator.WritePartialClassProperty (pc.State, widget));
			}
			generator.EndBindingFile (state);
			WriteToPartialClasses (pc => generator.EndPartialClassFile (pc.State));

			return true;

			void WriteToPartialClasses (Action<PartialClass> code)
			{
				if (!havePartialClasses)
					return;
				foreach (var pc in partialClasses) {
					if (pc == null)
						continue;
					code (pc);
				}
			}
		}
        public static KontrolRegistry CreateCore()
        {
            KontrolRegistry registry = new KontrolRegistry();

            registry.RegisterModule(BindingGenerator.BindModule(typeof(CoreLogging)));
            registry.RegisterModule(BindingGenerator.BindModule(typeof(CoreTesting)));
            registry.RegisterModule(BindingGenerator.BindModule(typeof(CoreBackground)));
            registry.RegisterModule(DirectBindingMath.Module);

            return(registry);
        }
		bool GenerateSource (BindingGenerator generator, string outputFilePath, ICollection <LayoutWidget> widgets, string classNamespace, string className, List<PartialClass> partialClasses)
		{
			bool result = false;
			var tempFile = Path.GetTempFileName ();
			try {
				if (partialClasses != null && partialClasses.Count > 0) {
					foreach (var pc in partialClasses) {
						if (pc == null)
							continue;

						pc.Stream = File.Open (pc.OutputFilePath, FileMode.Create);
						pc.Writer = new StreamWriter (pc.Stream, Encoding.UTF8);
					}
				}

				using (var fs = File.Open (tempFile, FileMode.Create)) {
					using (var sw = new StreamWriter (fs, Encoding.UTF8)) {
						result = GenerateSource (sw, generator, widgets, classNamespace, className, partialClasses);
					}
				}
				if (result)
					Files.CopyIfChanged (tempFile, outputFilePath);
			} finally {
				if (File.Exists (tempFile))
					File.Delete (tempFile);
				if (partialClasses != null && partialClasses.Count > 0) {
					foreach (var pc in partialClasses) {
						if (pc == null)
							continue;

						if (pc.Writer != null) {
							pc.Writer.Close ();
							pc.Writer.Dispose ();
						}

						if (pc.Stream == null)
							continue;

						pc.Stream.Close ();
						pc.Stream.Dispose ();
					}
				}
			}
			return result;
		}
Beispiel #7
0
        public override bool Execute()
        {
            Log.LogDebugMessage("GenerateLayoutBindings Task");
            Log.LogDebugMessage($"  OutputLanguage: {OutputLanguage}");
            Log.LogDebugMessage($"  MonoAndroidCodeBehindDir: {MonoAndroidCodeBehindDir}");
            Log.LogDebugMessage($"  AppNamespace: {AppNamespace}");
            Log.LogDebugTaskItems("  ResourceFiles:", ResourceFiles, true);
            Log.LogDebugTaskItems("  PartialClassFiles:", PartialClassFiles, true);

            if (String.IsNullOrWhiteSpace(OutputLanguage))
            {
                OutputLanguage = DefaultOutputGenerator.Name;
            }

            BindingGenerator generator = GetBindingGenerator(OutputLanguage);

            if (generator == null)
            {
                Log.LogMessage($"Unknown binding output language '{OutputLanguage}', will use {DefaultOutputGenerator.Name} instead");
                generator = DefaultOutputGenerator.Creator();
            }

            if (generator == null)
            {
                // Should "never" happen
                Log.LogError($"Cannot find binding generator for language {OutputLanguage} or {DefaultOutputGenerator.Name}");
                Complete();
                return(false);
            }

            Log.LogDebugMessage($"Generating {generator.LanguageName} binding sources");
            if (Generate(generator))
            {
                Complete();
            }
            else
            {
                base.Execute();
            }

            return(!Log.HasLoggedErrors);
        }
        KSPMathModule()
        {
            List <RealizedType> types = new List <RealizedType> {
                Vector2Binding.Vector2Type,
                Vector3Binding.Vector3Type,
                DirectionBinding.DirectionType,
                Matrix2x2Binding.Matrix2x2Type
            };

            BindingGenerator.RegisterTypeMapping(typeof(Vector2d), Vector2Binding.Vector2Type);
            BindingGenerator.RegisterTypeMapping(typeof(Vector3d), Vector3Binding.Vector3Type);
            BindingGenerator.RegisterTypeMapping(typeof(Direction), DirectionBinding.DirectionType);
            BindingGenerator.RegisterTypeMapping(typeof(Matrix2x2), Matrix2x2Binding.Matrix2x2Type);

            List <CompiledKontrolConstant> constants = new List <CompiledKontrolConstant>();

            List <CompiledKontrolFunction> functions = new List <CompiledKontrolFunction> {
                Direct.BindFunction(typeof(Vector2Binding), "Vec2", "Create a new 2-dimensional vector", typeof(double),
                                    typeof(double)),
                Direct.BindFunction(typeof(Vector3Binding), "Vec3", "Create a new 3-dimensional vector", typeof(double),
                                    typeof(double), typeof(double)),
                Direct.BindFunction(typeof(DirectionBinding), "Euler", "Create a Direction from euler angles in degree",
                                    typeof(double), typeof(double), typeof(double)),
                Direct.BindFunction(typeof(DirectionBinding), "AngleAxis",
                                    "Create a Direction from a given axis with rotation angle in degree", typeof(double),
                                    typeof(Vector3d)),
                Direct.BindFunction(typeof(DirectionBinding), "FromVectorToVector",
                                    "Create a Direction to rotate from one vector to another", typeof(Vector3d), typeof(Vector3d)),
                Direct.BindFunction(typeof(DirectionBinding), "LookDirUp",
                                    "Create a Direction from a fore-vector and an up-vector", typeof(Vector3d), typeof(Vector3d)),
                Direct.BindFunction(typeof(ExtraMath), "AngleDelta",
                                    "Calculate the difference between to angles in degree (-180 .. 180)", typeof(double),
                                    typeof(double)),
                Direct.BindFunction(typeof(Matrix2x2Binding), "Matrix2x2", "Create a new 2-dimensional matrix",
                                    typeof(double), typeof(double), typeof(double), typeof(double))
            };

            module = Direct.BindModule(ModuleName, "Collection of KSP/Unity related mathematical functions.", types,
                                       constants, functions);
        }
Beispiel #9
0
        bool Generate(BindingGenerator generator)
        {
            var         layoutGroups = new Dictionary <string, LayoutGroup> (StringComparer.Ordinal);
            string      layoutGroupName;
            LayoutGroup group;

            foreach (ITaskItem item in ResourceFiles)
            {
                if (item == null)
                {
                    continue;
                }

                if (!GetRequiredMetadata(item, CalculateLayoutCodeBehind.LayoutGroupMetadata, out layoutGroupName))
                {
                    return(true);                    // We need Complete() to be called by Execute above
                }
                if (!layoutGroups.TryGetValue(layoutGroupName, out group) || group == null)
                {
                    group = new LayoutGroup {
                        Items = new List <ITaskItem> ()
                    };
                    layoutGroups [layoutGroupName] = group;
                }
                group.Items.Add(item);
            }

            if (PartialClassFiles != null && PartialClassFiles.Length > 0)
            {
                foreach (ITaskItem item in PartialClassFiles)
                {
                    if (!GetRequiredMetadata(item, CalculateLayoutCodeBehind.LayoutGroupMetadata, out layoutGroupName))
                    {
                        return(true);
                    }
                    if (!layoutGroups.TryGetValue(layoutGroupName, out group) || group == null)
                    {
                        Log.LogError($"Partial class item without associated binding for layout group '{layoutGroupName}'");
                        return(true);
                    }

                    string partialClassName;
                    if (!GetRequiredMetadata(item, CalculateLayoutCodeBehind.PartialCodeBehindClassNameMetadata, out partialClassName))
                    {
                        return(true);
                    }

                    string outputFileName;
                    if (!GetRequiredMetadata(item, CalculateLayoutCodeBehind.LayoutPartialClassFileNameMetadata, out outputFileName))
                    {
                        return(true);
                    }

                    if (group.Classes == null)
                    {
                        group.Classes = new List <PartialClass> ();
                    }
                    if (group.ClassNames == null)
                    {
                        group.ClassNames = new HashSet <string> ();
                    }

                    if (group.ClassNames.Contains(partialClassName))
                    {
                        continue;
                    }

                    string shortName;
                    string namespaceName;
                    int    idx = partialClassName.LastIndexOf('.');
                    if (idx >= 0)
                    {
                        shortName     = partialClassName.Substring(idx + 1);
                        namespaceName = partialClassName.Substring(0, idx);
                    }
                    else
                    {
                        shortName     = partialClassName;
                        namespaceName = null;
                    }

                    group.Classes.Add(new PartialClass {
                        Name           = shortName,
                        Namespace      = namespaceName,
                        OutputFilePath = Path.Combine(MonoAndroidCodeBehindDir, outputFileName)
                    });
                    group.ClassNames.Add(partialClassName);
                }
            }

            IEnumerable <string> generatedFilePaths = null;
            bool needComplete = false;

            if (ResourceFiles.Length >= CalculateLayoutCodeBehind.ParallelGenerationThreshold)
            {
                // NOTE: Update the tests in $TOP_DIR/tests/CodeBehind/UnitTests/BuildTests.cs if this message
                // is changed!
                Log.LogDebugMessage($"Generating binding code in parallel (threshold of {CalculateLayoutCodeBehind.ParallelGenerationThreshold} layouts met)");
                var fileSet = new ConcurrentBag <string> ();
                TPL.ParallelOptions options = new TPL.ParallelOptions {
                    CancellationToken = Token,
                    TaskScheduler     = TPL.TaskScheduler.Default,
                };
                TPL.Task.Factory.StartNew(
                    () => TPL.Parallel.ForEach(layoutGroups, options, kvp => GenerateSourceForLayoutGroup(generator, kvp.Value, rpath => fileSet.Add(rpath))),
                    Token,
                    TPL.TaskCreationOptions.None,
                    TPL.TaskScheduler.Default
                    ).ContinueWith(t => Complete());
                generatedFilePaths = fileSet;
            }
            else
            {
                var fileSet = new List <string> ();
                foreach (var kvp in layoutGroups)
                {
                    GenerateSourceForLayoutGroup(generator, kvp.Value, rpath => fileSet.Add(rpath));
                }
                generatedFilePaths = fileSet;
                needComplete       = true;
            }

            GeneratedFiles = generatedFilePaths.Where(gfp => !String.IsNullOrEmpty(gfp)).Select(gfp => new TaskItem(gfp)).ToArray();
            if (GeneratedFiles.Length == 0)
            {
                Log.LogWarning("No layout binding source files generated");
            }
            Log.LogDebugTaskItems("  GeneratedFiles:", GeneratedFiles);
            return(needComplete);
        }
Beispiel #10
0
        public async override System.Threading.Tasks.Task RunTaskAsync()
        {
            if (String.IsNullOrWhiteSpace(OutputLanguage))
            {
                OutputLanguage = DefaultOutputGenerator.Name;
            }

            BindingGenerator generator = GetBindingGenerator(OutputLanguage);

            if (generator == null)
            {
                LogMessage($"Unknown binding output language '{OutputLanguage}', will use {DefaultOutputGenerator.Name} instead");
                generator = DefaultOutputGenerator.Creator();
            }

            if (generator == null)
            {
                // Should "never" happen
                LogCodedError("XA4219", Properties.Resources.XA4219, OutputLanguage, DefaultOutputGenerator.Name);
                return;
            }

            LogDebugMessage($"Generating {generator.LanguageName} binding sources");

            var         layoutGroups = new Dictionary <string, LayoutGroup> (StringComparer.Ordinal);
            string      layoutGroupName;
            LayoutGroup group;

            foreach (ITaskItem item in ResourceFiles)
            {
                if (item == null)
                {
                    continue;
                }

                if (!GetRequiredMetadata(item, CalculateLayoutCodeBehind.LayoutGroupMetadata, out layoutGroupName))
                {
                    return;
                }

                if (!layoutGroups.TryGetValue(layoutGroupName, out group) || group == null)
                {
                    group = new LayoutGroup {
                        Items = new List <ITaskItem> ()
                    };
                    layoutGroups [layoutGroupName] = group;
                }
                group.Items.Add(item);
            }

            if (PartialClassFiles != null && PartialClassFiles.Length > 0)
            {
                foreach (ITaskItem item in PartialClassFiles)
                {
                    if (!GetRequiredMetadata(item, CalculateLayoutCodeBehind.LayoutGroupMetadata, out layoutGroupName))
                    {
                        return;
                    }
                    if (!layoutGroups.TryGetValue(layoutGroupName, out group) || group == null)
                    {
                        LogCodedError("XA4220", Properties.Resources.XA4220, item.ItemSpec, layoutGroupName);
                        return;
                    }

                    string partialClassName;
                    if (!GetRequiredMetadata(item, CalculateLayoutCodeBehind.PartialCodeBehindClassNameMetadata, out partialClassName))
                    {
                        return;
                    }

                    string outputFileName;
                    if (!GetRequiredMetadata(item, CalculateLayoutCodeBehind.LayoutPartialClassFileNameMetadata, out outputFileName))
                    {
                        return;
                    }

                    if (group.Classes == null)
                    {
                        group.Classes = new List <PartialClass> ();
                    }
                    if (group.ClassNames == null)
                    {
                        group.ClassNames = new HashSet <string> ();
                    }

                    if (group.ClassNames.Contains(partialClassName))
                    {
                        continue;
                    }

                    string shortName;
                    string namespaceName;
                    int    idx = partialClassName.LastIndexOf('.');
                    if (idx >= 0)
                    {
                        shortName     = partialClassName.Substring(idx + 1);
                        namespaceName = partialClassName.Substring(0, idx);
                    }
                    else
                    {
                        shortName     = partialClassName;
                        namespaceName = null;
                    }

                    group.Classes.Add(new PartialClass {
                        Name           = shortName,
                        Namespace      = namespaceName,
                        OutputFilePath = Path.Combine(MonoAndroidCodeBehindDir, outputFileName)
                    });
                    group.ClassNames.Add(partialClassName);
                }
            }

            IEnumerable <string> generatedFilePaths = null;

            if (ResourceFiles.Length >= CalculateLayoutCodeBehind.ParallelGenerationThreshold)
            {
                // NOTE: Update the tests in $TOP_DIR/tests/CodeBehind/UnitTests/BuildTests.cs if this message
                // is changed!
                LogDebugMessage($"Generating binding code in parallel (threshold of {CalculateLayoutCodeBehind.ParallelGenerationThreshold} layouts met)");
                var fileSet = new ConcurrentBag <string> ();
                await this.WhenAll(layoutGroups, kvp => GenerateSourceForLayoutGroup(generator, kvp.Value, rpath => fileSet.Add(rpath)));

                generatedFilePaths = fileSet;
            }
            else
            {
                var fileSet = new List <string> ();
                foreach (var kvp in layoutGroups)
                {
                    GenerateSourceForLayoutGroup(generator, kvp.Value, rpath => fileSet.Add(rpath));
                }
                generatedFilePaths = fileSet;
            }

            GeneratedFiles = generatedFilePaths.Where(gfp => !String.IsNullOrEmpty(gfp)).Select(gfp => new TaskItem(gfp)).ToArray();
            if (GeneratedFiles.Length == 0)
            {
                LogCodedWarning("XA4221", Properties.Resources.XA4221);
            }
            LogDebugTaskItems("  GeneratedFiles:", GeneratedFiles);
        }
 public static void DirectBindings()
 {
     BindingGenerator.RegisterTypeMapping(typeof(FlightCtrlState),
                                          FlightCtrlStateBinding.FlightCtrlStateType);
 }