/// <summary>Adds default items to the pod's seats.</summary> /// <remarks>Items are only added to a part created in the editor. Thus, reacting on the editor /// event.</remarks> /// <param name="type">Unused.</param> /// <param name="p">A target part.</param> void OnEditPartCreate(ConstructionEventType type, Part p) { if (type != ConstructionEventType.PartCreated && type != ConstructionEventType.PartCopied) { return; } var inventories = p.GetComponents <ModuleKISInventory>(); foreach (var inventory in inventories) { if (inventory.podSeat == 0 && ModuleKISInventory.defaultItemsForTheFirstSeat.Count > 0) { Debug.LogFormat("Adding default item(s) into the first seat of part {0}: {1}", p.name, DbgFormatter.C2S(ModuleKISInventory.defaultItemsForTheFirstSeat)); AddItems(inventory, ModuleKISInventory.defaultItemsForTheFirstSeat); } if (inventory.podSeat != -1 && ModuleKISInventory.defaultItemsForAllSeats.Count > 0) { Debug.LogFormat( "Adding default item(s) into seat's {0} inventory of part {1}: {2}", inventory.podSeat, p.name, DbgFormatter.C2S(ModuleKISInventory.defaultItemsForAllSeats)); AddItems(inventory, ModuleKISInventory.defaultItemsForAllSeats); } } }
/// <inheritdoc/> public override void OnDebugAdjustablesUpdated() { base.OnDebugAdjustablesUpdated(); if (isLinked) { var checks = CheckConstraints(linkSource, linkTarget); if (checks.Length == 0) { // Given all checks are green, we can simply recreate the joint to update it. HostedDebugLog.Warning( this, "New settings fit the current link. Refreshing the joint..."); DropJoint(); CreateJoint(dbgLinkSource, dbgLinkTarget); } else { // STOP! The joint, once broken, won't re-establish with the new settings. HostedDebugLog.Warning(this, "New settings DON'T fit the current link:\n{0}" + "\n\nNot refershing the joint, re-link manually to update.", DbgFormatter.C2S(checks, separator: "\n")); } } else { // No joint, not update. However, it makes sense to note it. HostedDebugLog.Warning( this, "No link esatblished, only update the module settings"); } }
/// <inheritdoc/> public virtual bool CheckCanLinkTo(ILinkTarget target, bool checkStates = true, bool reportToGui = false, bool reportToLog = true) { var errors = new List <string>() .Concat(CheckBasicLinkConditions(target, checkStates)) .Concat(linkRenderer.CheckColliderHits(nodeTransform, target.nodeTransform)) .Concat(linkJoint.CheckConstraints(this, target)) .ToArray(); if (errors.Length > 0) { if (reportToGui || reportToLog) { HostedDebugLog.Warning( this, "Cannot link a part of type={0} with: part={1}, type={2}, errors={3}", cfgLinkType, target.part, target.cfgLinkType, DbgFormatter.C2S(errors)); } if (reportToGui) { ShowStatusMessage(DbgFormatter.C2S(errors, separator: "\n"), isError: true); } } return(errors.Length == 0); }
/// <summary>Throws if enum value is not in the expected set.</summary> /// <typeparam name="T">Type of value to check.</typeparam> /// <param name="arg">The value to check.</param> /// <param name="message">An optional message to present in the error.</param> /// <param name="context">The optional "owner" object.</param> /// <param name="values">The acceptable values of the enum.</param> /// <exception cref="InvalidOperationException">If condition fails.</exception> public static void OneOf <T>(T arg, T[] values, string message = null, object context = null) { if (!values.Contains(arg)) { throw new InvalidOperationException( Preconditions.MakeContextError( context, "Not one of: {1}. {2}", DbgFormatter.C2S(values), message)); } }
/// <summary>Throws if enum value is not in the expected set.</summary> /// <typeparam name="T">Type of value to check.</typeparam> /// <param name="arg">The argument value to check.</param> /// <param name="argName">The argument name.</param> /// <param name="values">The acceptable values of the enum.</param> /// <param name="message">An optional message to present in the error.</param> /// <param name="context">The optional "owner" object.</param> /// <exception cref="ArgumentOutOfRangeException"> /// If the argument is not one of the specified. /// </exception> public static void OneOf <T>(T arg, string argName, T[] values, string message = null, object context = null) { if (!values.Contains(arg)) { throw new ArgumentOutOfRangeException( argName, arg, Preconditions.MakeContextError( context, "Not one of: {1}. {2}", DbgFormatter.C2S(values), message)); } }
/// <inheritdoc/> public virtual bool CreateJoint(ILinkSource source, ILinkTarget target) { if (isLinked) { HostedDebugLog.Error( this, "Cannot link the joint which is already linked to: {0}", linkTarget); return(false); } if (!CheckCoupled(source, target)) { var errors = CheckConstraints(source, target); if (errors.Length > 0) { HostedDebugLog.Error(this, "Cannot create joint:\n{0}", DbgFormatter.C2S(errors)); return(false); } } else { HostedDebugLog.Fine(this, "The parts are coupled. Skip the constraints check"); } linkSource = source; linkTarget = target; if (!originalLength.HasValue) { SetOrigianlLength(Vector3.Distance( GetSourcePhysicalAnchor(source), GetTargetPhysicalAnchor(source, target))); } isLinked = true; // If the parts are already coupled at this moment, then the mode must be set as such. coupleOnLinkMode |= isCoupled; // Ensure the coupling can be done. coupleOnLinkMode &= linkSource.coupleNode != null && linkTarget.coupleNode != null; if (coupleOnLinkMode) { CoupleParts(); } else { AttachParts(); } return(true); }
void WaitAndApplyTweaks() { var roots = UnityEngine.SceneManagement.SceneManager.GetActiveScene().GetRootGameObjects(); foreach (var root in roots) { if (logAllObjects) { DebugEx.Fine("Objects at the root:\n{0}", DbgFormatter.C2S(Hierarchy.ListHirerahcy(root.transform), separator: "\n")); } foreach (var tweak in modelTweaks) { var names = tweak.modelNamePattern.Split('/'); var reducedNames = names.Skip(1).ToArray(); // Try first name part separately since the scene objects don't have a single root. if (names[0] == "**") { reducedNames = names; // Try all children in the root. } else if (!Hierarchy.PatternMatch(names[0], root.transform.name)) { continue; } var objTransform = Hierarchy.FindTransformByPath(root.transform, reducedNames); if (objTransform != null) { DebugEx.Info("Tweak '{0}' matched kerbal model: {1}", tweak.tweakName, objTransform); tweak.itemNames.ToList().ForEach(x => { var item = new TweakEquippableItem(x, tweak.matchMeshesBySuffix); item.ApplyTweak(objTransform.gameObject); sceneTweaks.Add(item); }); } } } }
/// <summary>Invokes a callback with the original value of an attribute argument.</summary> /// <param name="member">The attributed member.</param> /// <param name="attrType">The type of the attribute.</param> /// <param name="argName">The name of the attribute argument.</param> /// <param name="setupFn"> /// The callback that is called if the specified argument in the attribute is found. /// </param> static void SetupArgumentFromAttribute( MemberInfo member, Type attrType, string argName, Action <string> setupFn) { var fieldAttr = member.CustomAttributes.FirstOrDefault(x => x.AttributeType == attrType); if (fieldAttr == null) { DebugEx.Error("Attribute not found: attrType={0}, member={1}.{2}", attrType, member.DeclaringType, member.Name); return; } var namedArgument = fieldAttr.NamedArguments? .FirstOrDefault(x => x.MemberName == argName); if (namedArgument == null) { DebugEx.Error("Cannot fetch named argument: attrType={0}, member={1}.{2}, argName={3}", attrType, member.DeclaringType, member.Name, argName); DebugEx.Warning("Available arguments for attribute {0}: {1}", DbgFormatter.C2S(fieldAttr.NamedArguments, predicate: x => x.MemberName)); return; } setupFn((string)namedArgument.Value.TypedValue.Value); }