From a0f654b60331a112ae77e40518fd6d33f37f6d01 Mon Sep 17 00:00:00 2001 From: tinygrox Date: Mon, 4 May 2020 18:35:18 +0800 Subject: [PATCH 01/46] Update zh-cn.cfg --- Lang/zh-cn.cfg | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Lang/zh-cn.cfg b/Lang/zh-cn.cfg index b64ae500f..cdc00f3f6 100644 --- a/Lang/zh-cn.cfg +++ b/Lang/zh-cn.cfg @@ -614,5 +614,10 @@ Localization // KAS parts filter in the editor. #kasLOC_99009 = 坎巴拉附件系统 + + // Regular crew corridor (MdCorridor). + #kasLOC_99010 = 走廊-1000 + // Large crew corridor (LgCorridor). + #kasLOC_99011 = 走廊-1500 } } From a51031d1c2986e7919f611dc84b478a31c431e70 Mon Sep 17 00:00:00 2001 From: tinygrox Date: Mon, 4 May 2020 20:14:22 +0800 Subject: [PATCH 02/46] Update zh-cn.cfg --- Lang/zh-cn.cfg | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/Lang/zh-cn.cfg b/Lang/zh-cn.cfg index cdc00f3f6..37f0c9133 100644 --- a/Lang/zh-cn.cfg +++ b/Lang/zh-cn.cfg @@ -1,5 +1,10 @@ -// Version: 1 (2019-06-28) -//Author:facther +// Version: 5 (2020-05-04) +//Author:facther tinygrox +//Suggestions for Chinese translators (2020-05-04 by tinygrox): +//翻译是需要基础的,正所谓万丈高楼平地起,你没有良好的英语基础,仅仅靠着百度、有道等翻译工具来翻译,这种文字是没有灵魂的。 +//翻译不是一种文字到另一种文字之间的转换,而是一种文化到一种文化之间的转换。所以这也意味着你不仅英文要好,母语也要好。 +//翻译讲究信、达、雅。"信"——意思不违背原文;"达"——词句通顺能读;"雅"——语境贴切原文。 +//翻译要灵活,直译不行就换意译,必要时补充说明。翻译的目的是为了让人能够看懂,而不是简单地把英文换成中文。 Localization { zh-cn @@ -7,23 +12,23 @@ Localization // ********** Part: KAS.CH1 - #KAS_CH1_Part_title = CH-1 缆绳挂钩 + #KAS_CH1_Part_title = CH-1 缆索挂钩 #KAS_CH1_Part_manufacturer = KAS Labs, Inc. - #KAS_CH1_Part_description = 可以将缆绳挂在上面的钩子。这是“把这些东西放在一起”解决方案的另一半。 + #KAS_CH1_Part_description = 一个用来固定缆索的挂钩。这能解决另一半关于"如何把东西拼在一起"的问题。 #KAS_CH1_Part_tags = KIS KAS cable rope tie cck-kas // ********** Part: KAS.JS1 - #KAS_JS1_Part_title = JS-1 连接基座 + #KAS_JS1_Part_title = JS-1 套接底座 #KAS_JS1_Part_manufacturer = KAS Labs, Inc. - #KAS_JS1_Part_description = 这个多用途的基座有多种功能:它允许牢固的连接,并提供资源传输!安装此插座需要一名具有多年经验的认证工程师,但一旦安装,即使是清洁工也可以使用它来连接容器。 + #KAS_JS1_Part_description = 这个多用途的底座用途很多:建立牢固的连接,传输资源!虽然安装该底座需要一名经验老道的认证工程师,但一旦安装完毕,即使是个清洁工也能用它来连接2个航天器。 #KAS_JS1_Part_tags = KIS KAS pipe tube cck-kas // ********** Part: KAS.PCB1 - #KAS_PCB1_Part_title = PCB-1 便携缆绳绞盘 + #KAS_PCB1_Part_title = PCB-1 便携式缆索绞盘 #KAS_PCB1_Part_manufacturer = KAS Labs, Inc. - #KAS_PCB1_Part_description = 这是一个带有一根钢丝绳的简单的手动绞盘,只要相距不太远就可以连接东西。 但是,另一个容器上必须有一个挂钩,用于连接缆绳,因此这种绞盘只解决了一半的问题。 + #KAS_PCB1_Part_description = 这是一个十分简单的手摇式钢索绞盘,内置了一小段钢缆,只要2个物体相距不太远就可以用其进行连接。 但是,另一个物体上必须有一个挂钩来固定缆索,所以才说这个绞盘只解决了一半的问题。 #KAS_PCB1_Part_tags = KIS KAS cable rope tie cck-kas #KAS_PCB1_Part_LinkBreak = 断开连接 #KAS_PCB1_Part_LinkStart = 连接 @@ -64,7 +69,7 @@ Localization #KAS_TJ1_Part_title = TJ-1 固定伸缩杆 #KAS_TJ1_Part_manufacturer = KAS Labs, Inc. - #KAS_TJ1_Part_description = 这种简单的伸缩式杆可以牢固地连接两个容器。 最大连接距离比较短,但其强度足够。 设计的灵感来自Jeb在二手商店购买的自拍杆。 + #KAS_TJ1_Part_description = 这种简单的伸缩式杆可以牢固地连接两个航天器。 最大连接距离比较短,但其强度足够。 设计的灵感来自Jeb在二手商店购买的自拍杆。 #KAS_TJ1_Part_tags = KIS KAS pipe tube cck-kas #KAS_TJ1_Part_LinkBreak = 断开连接 #KAS_TJ1_Part_LinkStart = 连接 @@ -76,7 +81,7 @@ Localization #KAS_TJ2_Part_title = TJ-2 自由伸缩杆 #KAS_TJ2_Part_manufacturer = KAS Labs, Inc. - #KAS_TJ2_Part_description = 除了铰链是解锁的,和TJ-1“自拍棒”相同。真正的最佳解决方案是保持联系船只相互分散,但也不过度限制其运动。 + #KAS_TJ2_Part_description = 除了铰链是解锁的,和TJ-1“自拍杆”相同。真正的最佳解决方案是保持联系船只相互分散,但也不过度限制其运动。 #KAS_TJ2_Part_tags = KIS KAS pipe tube cck-kas #KAS_TJ2_Part_LinkBreak = 断开连接 #KAS_TJ2_Part_LinkStart = 连接 From 72b12d7392ea255dc317d3a06af52729a7d51107 Mon Sep 17 00:00:00 2001 From: tinygrox Date: Tue, 5 May 2020 00:39:53 +0800 Subject: [PATCH 03/46] Update zh-cn.cfg --- Lang/zh-cn.cfg | 58 +++++++++++++++++++++++++------------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/Lang/zh-cn.cfg b/Lang/zh-cn.cfg index 37f0c9133..29ce7a3af 100644 --- a/Lang/zh-cn.cfg +++ b/Lang/zh-cn.cfg @@ -2,8 +2,8 @@ //Author:facther tinygrox //Suggestions for Chinese translators (2020-05-04 by tinygrox): //翻译是需要基础的,正所谓万丈高楼平地起,你没有良好的英语基础,仅仅靠着百度、有道等翻译工具来翻译,这种文字是没有灵魂的。 -//翻译不是一种文字到另一种文字之间的转换,而是一种文化到一种文化之间的转换。所以这也意味着你不仅英文要好,母语也要好。 -//翻译讲究信、达、雅。"信"——意思不违背原文;"达"——词句通顺能读;"雅"——语境贴切原文。 +//翻译不是一种文字到另一种文字之间的转换,而是一种文化到另一种文化之间的转换。所以这也意味着你不仅英语要好,母语也要好。 +//翻译讲究信、达、雅。"信"——意思不违背原文;"达"——词句通顺能读;"雅"——语境贴切原文。达不到,就要改。不会,就要问。 //翻译要灵活,直译不行就换意译,必要时补充说明。翻译的目的是为了让人能够看懂,而不是简单地把英文换成中文。 Localization { @@ -37,28 +37,28 @@ Localization #KAS_PortPylon_Part_title = GP-20 塔架 #KAS_PortPylon_Part_manufacturer = KAS Labs, Inc. - #KAS_PortPylon_Part_description = 我们的RTS-1产品线非常成功!不过,也有一些问题,事实证明,有时管道不够长!为了解决这个问题,我们开发了一个新的部件:一个带有连接基座的轻型塔架,它可以充当扩展器。因此,长距离资源传输是可行的,尽管可能需要建造额外的塔架。杰布真的想在中空的内部增加一个科巴可乐冰箱,但由于严格的20公斤的质量限制,研发部不得不拒绝他的建议。 + #KAS_PortPylon_Part_description = 我们的RTS-1产品系列非常成功!不过,也还是萌生了一些抱怨的声音,原来,有时连接管道它的长度刚好就是差了那么一点!为了解决这个问题,我们研发了一个新的部件:一个内置管道套接基座的轻型塔架,还可以充当扩展部件。可见,长距离的资源传输是完全可行的,虽然要这么做的话,你可能得要建造安装一堆塔架。Jeb非常想在中空的位置那里放一个坎口可乐冰箱,但由于严格的20公斤的质量限制,研发部门不得不拒绝他的建议。 #KAS_PortPylon_Part_tags = KAS resource fuel transfer cck-kas // ********** Part: KAS.PortPylonPwr #KAS_PortPylonPwr_Part_title = BGP-400 增强版塔架 #KAS_PortPylonPwr_Part_manufacturer = KAS Labs, Inc. - #KAS_PortPylonPwr_Part_description = 这个部件的设计灵感来自于GP-20。我们的工程师想知道:塔架的内部容积真的能被利用吗?结果证明是可以的!因此,他们决定给它装上一些Z-100电池和一个简单的控制模块。 它不像杰巴所要求的那个酷酷的科巴可乐冰箱,但它仍然非常实用。请放心,所用电池的质量是最好的,而不是从回收站回收的。 + #KAS_PortPylonPwr_Part_description = 这个部件的设计灵感来自于GP-20。我们的工程师想知道:塔架内部的空间真的能被继续利用吗?结果证明是可以的!就这样,他们决定在那里装满Z-100电池,再放一个简单的控制模块。 它不像Jeb所要求的那个酷酷的坎口可乐冰箱,但它仍然非常实用。请放心,所用电池的质量是最好的,而不是从垃圾桶里捡的。 #KAS_PortPylonPwr_Part_tags = KAS resource fuel transfer cck-kas // ********** Part: KAS.RTS1 - #KAS_RTS1_Part_title = RTS-1 资源传输管道绞盘 + #KAS_RTS1_Part_title = RTS-1 资源传输绞盘 #KAS_RTS1_Part_manufacturer = KAS Labs, Inc. - #KAS_RTS1_Part_description = 该管道可以在飞船之间转移资源。 直径并没有那么大,但正如一个小绿家伙曾经说过的,“大小无关紧要。” 我们的专利技术允许通过它传输任何数量的东西,包括但不限于:岩石,燃料,零食,甚至是坎巴拉人。在后一种情况下,保修无效。 + #KAS_RTS1_Part_description = 里面的管道用于在不同的航天器之间传输资源。 直径大小并没有那么惊人,但正如一个小绿家伙曾经说过的,“大小不是问题。” 我们的专利技术能让它传输任意数量的东西,能传输的东西包括但不限于:岩石,燃料,零食,甚至是坎巴拉人。在后一种情况下,保修无效。 #KAS_RTS1_Part_tags = KIS KAS resource fuel transfer cck-kas // ********** Part: KAS.TB60 #KAS_TB60_Part_title = TB-60 牵引杆 #KAS_TB60_Part_manufacturer = KAS Labs, Inc. - #KAS_TB60_Part_description = 这是一种拖曳一艘不能自行移动的飞船的解决方案。如果使用一根简易的绳索,那么被牵引的飞船在刹车或操纵时可能会撞击牵引船,但使用牵引杆时就不会发生这种情况。此外,当条件符合时,它还可以操纵被拖飞船。一定要保证电量充足,否则主动转向将不起作用。 + #KAS_TB60_Part_description = 可以用来拖拽失去移动能力的航天器。如果单单只用一根简单的绳子来这样做的话,那么被拖拽的航天器在你制动或执行机动操作时就有可能撞到前面的航天器,但如果你使用的是牵引杆,那就不会发生这种情况。此外,当条件符合时,它还可以帮被拖的航天器转向。一定要保证电量充足,否则主动转向功能将不起作用。 #KAS_TB60_Part_tags = KIS KAS pipe tube tow towbar cck-kas #KAS_TB60_Part_LinkBreak = 断开连接 #KAS_TB60_Part_LinkStart = 连接 @@ -69,7 +69,7 @@ Localization #KAS_TJ1_Part_title = TJ-1 固定伸缩杆 #KAS_TJ1_Part_manufacturer = KAS Labs, Inc. - #KAS_TJ1_Part_description = 这种简单的伸缩式杆可以牢固地连接两个航天器。 最大连接距离比较短,但其强度足够。 设计的灵感来自Jeb在二手商店购买的自拍杆。 + #KAS_TJ1_Part_description = 这种简单的伸缩式杆可以牢固地连接两个航天器。 虽说最大连接距离比较短,但好在其强度十分足够。 设计的灵感来自Jeb在二手商店购买的自拍杆。 #KAS_TJ1_Part_tags = KIS KAS pipe tube cck-kas #KAS_TJ1_Part_LinkBreak = 断开连接 #KAS_TJ1_Part_LinkStart = 连接 @@ -81,7 +81,7 @@ Localization #KAS_TJ2_Part_title = TJ-2 自由伸缩杆 #KAS_TJ2_Part_manufacturer = KAS Labs, Inc. - #KAS_TJ2_Part_description = 除了铰链是解锁的,和TJ-1“自拍杆”相同。真正的最佳解决方案是保持联系船只相互分散,但也不过度限制其运动。 + #KAS_TJ2_Part_description = 除了铰链是可运动的,和TJ-1“自拍杆”没什么两样。保证了连接的航天器不会相撞,又不会过度限制其运动,此乃最佳解决方案。 #KAS_TJ2_Part_tags = KIS KAS pipe tube cck-kas #KAS_TJ2_Part_LinkBreak = 断开连接 #KAS_TJ2_Part_LinkStart = 连接 @@ -93,14 +93,14 @@ Localization #KAS_W1_Part_title = W-50 绞盘 #KAS_W1_Part_manufacturer = KAS Labs, Inc. - #KAS_W1_Part_description = 一位古老的圣人曾经说过:“给我一个正确的基座和绞盘,我能拉动Kerbin”。 这种绞盘并不是那么强大,尽管它可以抬起或牵引一艘相当庞大的飞船。 请确保目标飞船上有兼容的基座。 此外,确保飞船上有足够的电力:绞盘很费电! + #KAS_W1_Part_description = 一位古老的圣人曾经说过:“给我一个强大的基座,我用绞盘能拉动整个Kerbin”。 这个绞盘并没有强大到能拉动Kerbin,不过它可以抬起或牵引一艘相当庞大的航天器。 请记得在目标航天器上安装好兼容的连接底座。 此外,确保飞船上有足够的电力:绞盘很费电! #KAS_W1_Part_tags = KIS KAS winch cable connector cck-kas // ********** Part: KAS.W2 #KAS_W2_Part_title = HW-80 绞盘 #KAS_W2_Part_manufacturer = KAS Labs, Inc. - #KAS_W2_Part_description = W-50绞车型号的重型版本。它有额外的电缆和增强的连接强度。然而,它仍然不能拉动Kerbin。注意:如果绞车用于绞车开关,则保修无效,无论是哪个绞车还是哪个开关。 + #KAS_W2_Part_description = W-50绞盘型号的重型版本。增加了缆索的长度,缆索的连接强度也被增强。但是,它仍然不能拉动Kerbin。注意:如果绞盘用于绞死女巫,则保修无效,不管是用的哪个绞盘还是绞死的哪个女巫。 #KAS_W2_Part_tags = KIS KAS winch cable connector heavyduty cck-kas // ********** Type: KAS.AbstractJoint, KSPDev Messages @@ -173,7 +173,7 @@ Localization #kasLOC_07000 = 连接与以下对象冲突: <<1>> // Message to display when the link strut orientation cannot be changed due to it // would hit the surface. - #kasLOC_07001 = 连接与表面冲突 + #kasLOC_07001 = 连接与地面发生碰撞 // ********** Type: KAS.ControllerWinchRemote, KSPDev Messages @@ -206,15 +206,15 @@ Localization // reason. #kasLOC_11011 = 未连接 // The GUI hint to explain the OFFLINE state. - #kasLOC_11012 = 无法和绞盘联络。飞船是可控的吗? + #kasLOC_11012 = 无法访问绞盘。飞船是否可控? // The text for the winch status that tells that the main winch attach node is // occupied by an incompatible (non-KAS) part. #kasLOC_11013 = 被阻挡 // The GUI hint to explain the BLOCKED state. - #kasLOC_11014 = 绞盘连接节点被另一个部件阻挡 + #kasLOC_11014 = 绞盘连接节点被其他部件阻挡 // The text for the winch status that tells that the cable connector is locked to // the winch, and the cable length is zero. - #kasLOC_11015 = 回收 + #kasLOC_11015 = 收回 // The GUI hint to explain the RETRACTED state. #kasLOC_11016 = 接头被锁定在绞盘中。 // The GUI hint of the button that triggers retracting of the cable. The cable will @@ -306,18 +306,18 @@ Localization // an angle type. // Example usage: // Tow bar is locking: diff 1.5° - #kasLOC_05000 = 牵引杆正在锁定:移动中 <<1>> + #kasLOC_05000 = 锁定牵引杆中:移动中 <<1>> // Message to display when a tow bar locking process successfully ends with locking. #kasLOC_05001 = 牵引杆被锁定! // A string in the context menu that tells that the active steering mode is not // enabled. - #kasLOC_05002 =禁用 + #kasLOC_05002 = 禁用 // A string in the context menu that tells that the active steering mode is ready // and working. - #kasLOC_05003 = 活动的 + #kasLOC_05003 = 可用 // A string in the context menu that tells that the active steering mode cannot work // due to the bar's target vessel is currently under player's control. - #kasLOC_05004 = 目标是移动的飞船 + #kasLOC_05004 = 目标已处于控制状态 // A string in the context menu that tells that the active steering mode cannot work // due to the linked vessel is remotely controlled. #kasLOC_05005 = 目标无法控制 @@ -330,7 +330,7 @@ Localization #kasLOC_05008 = 已锁定 // A string in the context menu that tells that the bar joints are unlocked but the // part is trying to lock them. - #kasLOC_05009 = 正在锁定 + #kasLOC_05009 = 锁定中 // ********** Type: KAS.KASLinkResourceConnector, KSP Events @@ -382,7 +382,7 @@ Localization // the speed of the reasource transfer. #kasLOC_12009 = 自动改变传输速度 // The GUI hint that explains what will happen if the auto-speed options is chosen. - #kasLOC_12010 = 将设置速度,以便在 <<1>> 秒内完成传输 + #kasLOC_12010 = 将自动设置速度,以便在 <<1>> 秒内完成传输 // The hint text to explain the button action that starts transferring the resource // from the connected vessel to the owner of the resource transfer part. #kasLOC_12011 = 开始从目标转移到本体 @@ -418,7 +418,7 @@ Localization // Argument <<1>> is the type string from the part's config. #kasLOC_02004 = 按基座类型连接: <<1>> // Title of the module to present in the editor details window. - #kasLOC_02005 = KAS 接头来源 + #kasLOC_02005 = KAS 源接头 // The name of the part's context menu event that triggers a separtation of the // linked parts into two different vessels if they are coupled thru this link. At // the same time, the name of the event gives a currently selected state. @@ -438,10 +438,10 @@ Localization #kasLOC_01000 = 单击以建立连接 (长度 <<1>>) // The message to display as a help string when an interactive linking mode has // started. - #kasLOC_01001 = 选择兼容的基座或按Esc键 + #kasLOC_01001 = 选择兼容的基座否则按Esc键退出 // The message to present when the player requests a docking mode for the link via // UI, but the source or target part is rejecting the action. - #kasLOC_01002 =无法对接:不支持该模式 + #kasLOC_01002 = 无法对接:不支持该模式 // ********** Type: KAS.KASLinkSourcePhysical, KSP Events @@ -449,7 +449,7 @@ Localization #kasLOC_13007 = 抓取接头 // A context menu event that detaches the connector from the kerbal and puts it back // to the winch. - #kasLOC_13008 = 返回接头 + #kasLOC_13008 = 放回接头 // Context menu item to break the currently established link. #kasLOC_13009 = 分离接头 // Advanced tweakable. Context menu item to instantly lock the deployed connector @@ -471,14 +471,14 @@ Localization #kasLOC_13001 = 已部署 // A string in the context menu that tells that the connector is plugged in a socked // or is being carried by a kerbal, and attached to the part via a cable. - #kasLOC_13002 = 接通电源 + #kasLOC_13002 = 已接入 // A string in the context menu that tells that the connector is rigidly attached in // the winch socked, and the vessel on the connector is docked to the part owner // vessel. #kasLOC_13003 = 已对接 // A message to display when a link between the part and the connector has broke due // to the unexpected external forces or actions. - #kasLOC_13004 = 接头和零件之间的连接已断开 + #kasLOC_13004 = 接头和部件之间的连接已断开 // The error message to present when a part is being attached externally to the // source's attach node, and it's not a valid link target for the source. // Argument <<1>> is the name of the part being attached. @@ -556,7 +556,7 @@ Localization #kasLOC_08002 = 接头已锁定! // Info message to present when a cable connector has successfully docked to the // winch. - #kasLOC_08003 = 连接到绞车的接头 + #kasLOC_08003 = 连接到绞盘的接头 // An info message to present when the cable is extended at its maximum length. // Argument <<1>> is the current cable length of type DistanceType. // Example usage: @@ -594,7 +594,7 @@ Localization #kasLOC_04000 = 连接与以下对象冲突: <<1>> // Message to display when the link strut orientation cannot be changed due to it // would hit the surface. - #kasLOC_04001 = 连接与表面冲突 + #kasLOC_04001 = 连接与地面相碰撞 // ********** Global strings From 156c09ca8d51527dc037ebbf0558ccce6a460d69 Mon Sep 17 00:00:00 2001 From: ihsoft Date: Sun, 19 Jul 2020 20:00:28 -0700 Subject: [PATCH 04/46] Start v1.7 --- CHANGELOG.md | 2 ++ Source/Properties/AssemblyInfo.cs | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c55283bc0..c79c8d3a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,5 @@ +# 1.7 (pre-release): + # 1.6 (April 26th, 2020): * [Fix #289] RTS-1 docking mode is not reset on decoupling. * [Change] Stop complaining about KSP minor version change. diff --git a/Source/Properties/AssemblyInfo.cs b/Source/Properties/AssemblyInfo.cs index e26a46a82..4b841557f 100644 --- a/Source/Properties/AssemblyInfo.cs +++ b/Source/Properties/AssemblyInfo.cs @@ -27,7 +27,7 @@ // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion ("1.6.*")] -[assembly: AssemblyInformationalVersion ("1.6 for KSP v1")] -[assembly: KSPAssembly ("KAS", 1, 6)] +[assembly: AssemblyVersion ("1.7.*")] +[assembly: AssemblyInformationalVersion ("1.7 for KSP v1")] +[assembly: KSPAssembly ("KAS", 1, 7)] [assembly: AssemblyFlags (AssemblyNameFlags.PublicKey)] From 7662494cc3ec462730f6ace876efa77d50444d27 Mon Sep 17 00:00:00 2001 From: ihsoft Date: Sun, 19 Jul 2020 20:01:07 -0700 Subject: [PATCH 05/46] Fix #297 --- Source/modules/KASLinkSourceBase.cs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Source/modules/KASLinkSourceBase.cs b/Source/modules/KASLinkSourceBase.cs index 9ddeeabcc..11e4af9d8 100644 --- a/Source/modules/KASLinkSourceBase.cs +++ b/Source/modules/KASLinkSourceBase.cs @@ -229,23 +229,25 @@ public virtual void ToggleVesselsDockModeEvent() { #region AbstractLinkPeer overrides /// Reacts on a part de-coupling and adjusts the docking mode. /// - /// If active mode was "DOCKING", and the coupling hasn't restored, then reset the mode since it - /// erroneous now. + /// This is a cleanup method that verifies that all links in the DOCKED mode remained coupled + /// after decoupling of the part. If it's not the case, the DOCKED mode is reset to ATTACHED. In + /// the normal case the joint module takes care of restoring the affected couplings, and this + /// method becomes NO-OP. /// /// The part that has decoupled. void OnPartDeCoupleCompleteEvent(Part originator) { - if (!isLinked || !linkJoint.coupleOnLinkMode) { + if (!isLinked || !linkJoint.coupleOnLinkMode || linkTarget.part.vessel == vessel) { return; // Not interested. } // Wait for one frame to allow joint logic to restore the coupling, and then check. AsyncCall.CallOnEndOfFrame( this, () => { - if (isLinked && vessel != originator.vessel) { + if (isLinked && linkJoint.coupleOnLinkMode && linkTarget.part.vessel != vessel) { HostedDebugLog.Fine( this, "Coupling has not been restored, resetting the docking mode: {0} <=> {1}", - part, originator); + part, linkTarget.part); linkJoint.SetCoupleOnLinkMode(false); UpdateContextMenu(); } From 65245b4b9bc55a02cd21192fd3e4a6333be7baa6 Mon Sep 17 00:00:00 2001 From: ihsoft Date: Sun, 19 Jul 2020 20:50:26 -0700 Subject: [PATCH 06/46] Don't use DestroyImmediate It causes errors in case of the part dies. --- Source/modules/KASJointCableBase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/modules/KASJointCableBase.cs b/Source/modules/KASJointCableBase.cs index 6089cb766..98f055101 100644 --- a/Source/modules/KASJointCableBase.cs +++ b/Source/modules/KASJointCableBase.cs @@ -187,7 +187,7 @@ public virtual void StopPhysicalHead() { headRb = null; headSource = null; headPhysicalAnchor = null; - DestroyImmediate(cableJoint); + Destroy(cableJoint); cableJoint = null; SetOrigianlLength(null); } From 978cdfaf37268882b15b151dba0ea24080b7b850 Mon Sep 17 00:00:00 2001 From: ihsoft Date: Sun, 19 Jul 2020 21:10:34 -0700 Subject: [PATCH 07/46] Fix Utils method name Typo in the method name. --- Source/KSPDev_candidates/Hierarchy2.cs | 43 ++++++++++++++++++++++++++ Source/modules/KASRendererPipe.cs | 6 ++-- 2 files changed, 46 insertions(+), 3 deletions(-) create mode 100644 Source/KSPDev_candidates/Hierarchy2.cs diff --git a/Source/KSPDev_candidates/Hierarchy2.cs b/Source/KSPDev_candidates/Hierarchy2.cs new file mode 100644 index 000000000..e5de63804 --- /dev/null +++ b/Source/KSPDev_candidates/Hierarchy2.cs @@ -0,0 +1,43 @@ +// Kerbal Development tools. +// Author: igor.zavoychinskiy@gmail.com +// This software is distributed under Public domain license. +using UnityEngine; + +namespace KSPDev.ModelUtils { + +/// Various tools to deal with game object hierarchy. +public static class Hierarchy2 { + /// Destroys the object in a way which is safe for physical callback methods. + /// + /// The Unity UnityEngine.Object.Destroy method only marks object for deletion, but before + /// the next fixed frame cycle completed, the object still can be found in the hierarchy. And it + /// may trigger physics before the final cleanup. This method ensures that none of these + /// side-effects happen and it doesn't use physics incompatible DestroyImmediate + /// method. + /// + /// The object to destroy. Can be null. + public static void SafeDestroy(Transform obj) { + if (obj != null) { + SafeDestroy(obj.gameObject); + } + } + + /// + public static void SafeDestroy(GameObject obj) { + if (obj != null) { + obj.transform.SetParent(null, worldPositionStays: false); + obj.name = "$disposed"; + obj.SetActive(false); + UnityEngine.Object.Destroy(obj); + } + } + + /// + public static void SafeDestroy(Component obj) { + if (obj != null) { + SafeDestroy(obj.gameObject); + } + } +} + +} // namespace diff --git a/Source/modules/KASRendererPipe.cs b/Source/modules/KASRendererPipe.cs index 69c0eff99..c1de8ca31 100644 --- a/Source/modules/KASRendererPipe.cs +++ b/Source/modules/KASRendererPipe.cs @@ -462,7 +462,7 @@ protected virtual void UpdateJointNode(ModelPipeEndNode node, Transform alignTo) sphere.GetComponent().sharedMaterial = pipeMaterial; // For performance. RescalePipeTexture(sphere, sphere.localScale.z * config.sphereDiameter * 2.0f); } else if (sphere != null) { - Hierarchy.SafeDestory(sphere); + Hierarchy2.SafeDestroy(sphere); } // Parking position, if defined. @@ -474,7 +474,7 @@ protected virtual void UpdateJointNode(ModelPipeEndNode node, Transform alignTo) newPosition: config.parkAttachAt.pos, newRotation: config.parkAttachAt.rot); } else if (parkAttach != null) { - Hierarchy.SafeDestory(parkAttach); + Hierarchy2.SafeDestroy(parkAttach); } // Place prefab between the part and the pipe if specified. @@ -517,7 +517,7 @@ protected virtual void UpdateJointNode(ModelPipeEndNode node, Transform alignTo) arm.transform.localRotation = Quaternion.LookRotation(Vector3.forward); RescalePipeTexture(arm.transform, arm.localScale.z * config.sphereOffset); } else if (arm != null) { - Hierarchy.SafeDestory(arm); + Hierarchy2.SafeDestroy(arm); } // Adjust to the new target. From 516765c39f528e215501e36d146bb0cba16ef9fd Mon Sep 17 00:00:00 2001 From: ihsoft Date: Sun, 19 Jul 2020 21:26:21 -0700 Subject: [PATCH 08/46] Avoid using DestroyImmediate as much as possible Switch to a new Meshes2 util. --- Source/KSPDev_candidates/Meshes2.cs | 92 +++++++++++++++++++ .../modules/KASInternalPhysicalConnector.cs | 4 +- Source/modules/KASRendererPipe.cs | 12 +-- 3 files changed, 99 insertions(+), 9 deletions(-) create mode 100644 Source/KSPDev_candidates/Meshes2.cs diff --git a/Source/KSPDev_candidates/Meshes2.cs b/Source/KSPDev_candidates/Meshes2.cs new file mode 100644 index 000000000..31b602415 --- /dev/null +++ b/Source/KSPDev_candidates/Meshes2.cs @@ -0,0 +1,92 @@ +// Kerbal Development tools. +// Author: igor.zavoychinskiy@gmail.com +// This software is distributed under Public domain license. + +using UnityEngine; + +// ReSharper disable once CheckNamespace +namespace KSPDev.ModelUtils { + +/// Various tools to deal with procedural meshes. +public static class Meshes2 { + /// Creates a cylinder. + /// XY of the cylinder. + /// Z-axis of the cylinder. + /// Material for the primitive. + /// Parent transform to attach primitive to. + /// Type of the collider to create on the primitive. + /// Sphere game object. + /// Unity3D: Material + /// + /// Unity3D: Transform + /// + public static GameObject CreateCylinder( + float diameter, float length, Material material, Transform parent, + Colliders.PrimitiveCollider colliderType = Colliders.PrimitiveCollider.None) { + // Default length scale is 2.0. + var obj = CreatePrimitive( + PrimitiveType.Cylinder, new Vector3(diameter, diameter, length / 2), + material, parent: parent); + Colliders.AdjustCollider( + obj, new Vector3(diameter, diameter, length), + colliderType, shapeType: PrimitiveType.Cylinder); + return obj; + } + + /// Creates an ideal sphere. + /// Diameter of the sphere. + /// Material for the primitive. + /// Parent transform to attach primitive to. + /// Type of the collider to create on the primitive. + /// Sphere game object. + /// Unity3D: Material + /// + /// Unity3D: Transform + /// + public static GameObject CreateSphere( + float diameter, Material material, Transform parent, + Colliders.PrimitiveCollider colliderType = Colliders.PrimitiveCollider.None) { + var scale = new Vector3(diameter, diameter, diameter); + var obj = CreatePrimitive(PrimitiveType.Sphere, scale, material, parent: parent); + Colliders.AdjustCollider(obj, scale, colliderType, shapeType: PrimitiveType.Sphere); + return obj; + } + + /// Creates a primitive mesh and attaches it to the model. + /// + /// For Z and Y axis will be swapped to make Z "the length". + /// + /// Collider on the primitive will be destroyed. Consider using + /// to setup the right collider when needed. + /// + /// + /// The type of the primitive. + /// + /// The scale to bring all the mesh vertices to. The scale is applied on the mesh, i.e. it's + /// applied on the vertices, not the transform. + /// + /// The material to use for the primitive. + /// The parent transform to attach the primitive to. + /// The game object of the new primitive. + /// + /// Unity3D: GameObject.CreatePrimitive + /// Unity3D: Material + /// + public static GameObject CreatePrimitive( + PrimitiveType type, Vector3 meshScale, Material material, Transform parent) { + var primitive = GameObject.CreatePrimitive(type); + var collider = primitive.GetComponent(); + collider.enabled = false; + Object.Destroy(collider); + Hierarchy.MoveToParent(primitive.transform, parent); + primitive.GetComponent().material = material; + + // Make object's Z axis its length. For this rotate around X axis. + var meshRotation = + type == PrimitiveType.Cylinder ? Quaternion.Euler(90, 0, 0) : Quaternion.identity; + Meshes.TranslateMesh(primitive, rotation: meshRotation, scale: meshScale); + return primitive; + } +} + +} // namespace diff --git a/Source/modules/KASInternalPhysicalConnector.cs b/Source/modules/KASInternalPhysicalConnector.cs index 7664b46bb..729b52f5d 100644 --- a/Source/modules/KASInternalPhysicalConnector.cs +++ b/Source/modules/KASInternalPhysicalConnector.cs @@ -50,15 +50,13 @@ public static KASInternalPhysicalConnector Promote( if (interactionDistance > 0) { // This mesh is placed on a special layer which is not rendered in the game. It's only // used to detect the special zones triggers, so keep it simple. - var interactionTriggerObj = Meshes.CreatePrimitive( PrimitiveType.Quad, Vector3.one, null, obj.transform); - //interactionTriggerObj.SetActive(true); + var interactionTriggerObj = Meshes2.CreatePrimitive( interactionTriggerObj.name = InteractionAreaCollider; var collider = interactionTriggerObj.AddComponent(); collider.isTrigger = true; collider.radius = interactionDistance; interactionTriggerObj.layer = (int) KspLayer.TriggerCollider; - interactionTriggerObj.gameObject.GetComponent().isTrigger = true; connectorModule.interactionTriggerObj = interactionTriggerObj; } diff --git a/Source/modules/KASRendererPipe.cs b/Source/modules/KASRendererPipe.cs index c1de8ca31..d0884710d 100644 --- a/Source/modules/KASRendererPipe.cs +++ b/Source/modules/KASRendererPipe.cs @@ -454,8 +454,8 @@ protected virtual void UpdateJointNode(ModelPipeEndNode node, Transform alignTo) var sphere = node.pipeAttach.Find(sphereName); if (config.sphereDiameter > float.Epsilon && makeProceduralModels) { if (sphere == null) { - sphere = Meshes.CreateSphere(config.sphereDiameter, pipeMaterial, node.pipeAttach, - colliderType: Colliders.PrimitiveCollider.Shape).transform; + sphere = Meshes2.CreateSphere(config.sphereDiameter, pipeMaterial, node.pipeAttach, + colliderType: Colliders.PrimitiveCollider.Shape).transform; sphere.name = sphereName; sphere.rotation = Quaternion.LookRotation(node.partAttach.up, node.partAttach.forward); } @@ -507,9 +507,9 @@ protected virtual void UpdateJointNode(ModelPipeEndNode node, Transform alignTo) if (config.armDiameter > float.Epsilon && config.sphereOffset > float.Epsilon && makeProceduralModels) { if (arm == null) { - arm = Meshes.CreateCylinder(config.armDiameter, config.sphereOffset, pipeMaterial, - node.pipeAttach, - colliderType: Colliders.PrimitiveCollider.Shape).transform; + arm = Meshes2.CreateCylinder(config.armDiameter, config.sphereOffset, pipeMaterial, + node.pipeAttach, + colliderType: Colliders.PrimitiveCollider.Shape).transform; arm.name = armName; } arm.GetComponent().sharedMaterial = pipeMaterial; // For performance. @@ -534,7 +534,7 @@ protected virtual void CreateLinkPipe() { var colliderType = pipeColliderIsPhysical ? Colliders.PrimitiveCollider.Shape : Colliders.PrimitiveCollider.None; - pipeTransform = Meshes.CreateCylinder( + pipeTransform = Meshes2.CreateCylinder( pipeDiameter, 1.0f, pipeMaterial, sourceTransform, colliderType: colliderType).transform; pipeTransform.GetComponent().sharedMaterial = pipeMaterial; pipeMeshRenderer = pipeTransform.GetComponent(); // To speedup OnUpdate() handling. From b9359a48aae19cf3875c820ac550397e1335563d Mon Sep 17 00:00:00 2001 From: ihsoft Date: Sun, 19 Jul 2020 21:27:14 -0700 Subject: [PATCH 09/46] Use Cube default shape for the connector trigger Unity doesn't like non-convex shapes in trigger state. --- Source/modules/KASInternalPhysicalConnector.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/modules/KASInternalPhysicalConnector.cs b/Source/modules/KASInternalPhysicalConnector.cs index 729b52f5d..35896ef7d 100644 --- a/Source/modules/KASInternalPhysicalConnector.cs +++ b/Source/modules/KASInternalPhysicalConnector.cs @@ -50,8 +50,8 @@ public static KASInternalPhysicalConnector Promote( if (interactionDistance > 0) { // This mesh is placed on a special layer which is not rendered in the game. It's only // used to detect the special zones triggers, so keep it simple. - PrimitiveType.Quad, Vector3.one, null, obj.transform); var interactionTriggerObj = Meshes2.CreatePrimitive( + PrimitiveType.Cube, Vector3.one, null, obj.transform); interactionTriggerObj.name = InteractionAreaCollider; var collider = interactionTriggerObj.AddComponent(); collider.isTrigger = true; From 112889398d8c8adf2e364e326434556f674640c2 Mon Sep 17 00:00:00 2001 From: ihsoft Date: Mon, 20 Jul 2020 23:11:33 -0700 Subject: [PATCH 10/46] Fix files description --- Source/api_impl/AttachNodesUtilsImpl.cs | 3 +-- Source/api_impl/CommonConfigImpl.cs | 3 +-- Source/api_impl/JointUtilsImpl.cs | 3 +-- Source/api_impl/KASAPILauncher.cs | 3 +-- Source/api_impl/KasEventsImpl.cs | 3 +-- Source/api_impl/KasLinkEventImpl.cs | 3 +-- Source/api_impl/LinkUtilsImpl.cs | 3 +-- Source/api_impl/PhysicsUtilsImpl.cs | 3 +-- Source/modules/AbstractJoint.cs | 3 +-- Source/modules/AbstractLinkPeer.cs | 3 +-- Source/modules/AbstractProceduralModel.cs | 3 +-- Source/modules/KASInternalBrokenJointListener.cs | 3 +-- Source/modules/KASInternalPhysicalConnector.cs | 3 +-- Source/modules/KASJointCableBase.cs | 3 +-- Source/modules/KASJointRigid.cs | 3 +-- Source/modules/KASJointTowBar.cs | 3 +-- Source/modules/KASJointTwoEndsSphere.cs | 3 +-- Source/modules/KASLinkResourceConnector.cs | 3 +-- Source/modules/KASLinkSourceBase.cs | 3 +-- Source/modules/KASLinkSourceInteractive.cs | 3 +-- Source/modules/KASLinkTargetBase.cs | 3 +-- Source/modules/KASLinkTargetKerbal.cs | 4 ++-- Source/modules/KASLinkWinch.cs | 3 +-- Source/modules/KASRendererBezierPipe.cs | 1 - Source/modules/KASRendererTelescopicPipe.cs | 3 +-- 25 files changed, 25 insertions(+), 49 deletions(-) diff --git a/Source/api_impl/AttachNodesUtilsImpl.cs b/Source/api_impl/AttachNodesUtilsImpl.cs index 1e18cdb99..6527602b4 100644 --- a/Source/api_impl/AttachNodesUtilsImpl.cs +++ b/Source/api_impl/AttachNodesUtilsImpl.cs @@ -1,6 +1,5 @@ // Kerbal Attachment System API -// Mod idea: KospY (http://forum.kerbalspaceprogram.com/index.php?/profile/33868-kospy/) -// API design and implemenation: igor.zavoychinskiy@gmail.com +// Author: igor.zavoychinskiy@gmail.com // License: Public Domain using KSPDev.LogUtils; diff --git a/Source/api_impl/CommonConfigImpl.cs b/Source/api_impl/CommonConfigImpl.cs index 91928120e..581438ce7 100644 --- a/Source/api_impl/CommonConfigImpl.cs +++ b/Source/api_impl/CommonConfigImpl.cs @@ -1,6 +1,5 @@ // Kerbal Attachment System -// Mod idea: KospY (http://forum.kerbalspaceprogram.com/index.php?/profile/33868-kospy/) -// Module author: igor.zavoychinskiy@gmail.com +// Author: igor.zavoychinskiy@gmail.com // License: Public Domain using KASAPIv2; diff --git a/Source/api_impl/JointUtilsImpl.cs b/Source/api_impl/JointUtilsImpl.cs index b3a4698f2..5bb5e50dd 100644 --- a/Source/api_impl/JointUtilsImpl.cs +++ b/Source/api_impl/JointUtilsImpl.cs @@ -1,6 +1,5 @@ // Kerbal Attachment System API -// Mod idea: KospY (http://forum.kerbalspaceprogram.com/index.php?/profile/33868-kospy/) -// API design and implemenation: igor.zavoychinskiy@gmail.com +// Author: igor.zavoychinskiy@gmail.com // License: Public Domain using KSPDev.LogUtils; diff --git a/Source/api_impl/KASAPILauncher.cs b/Source/api_impl/KASAPILauncher.cs index 3a60849e2..c59c02ccd 100644 --- a/Source/api_impl/KASAPILauncher.cs +++ b/Source/api_impl/KASAPILauncher.cs @@ -1,6 +1,5 @@ // Kerbal Attachment System API -// Mod idea: KospY (http://forum.kerbalspaceprogram.com/index.php?/profile/33868-kospy/) -// API design and implemenation: igor.zavoychinskiy@gmail.com +// Author: igor.zavoychinskiy@gmail.com // License: Public Domain using KSPDev.FSUtils; diff --git a/Source/api_impl/KasEventsImpl.cs b/Source/api_impl/KasEventsImpl.cs index 3044e5072..50c9fb752 100644 --- a/Source/api_impl/KasEventsImpl.cs +++ b/Source/api_impl/KasEventsImpl.cs @@ -1,6 +1,5 @@ // Kerbal Attachment System -// Mod idea: KospY (http://forum.kerbalspaceprogram.com/index.php?/profile/33868-kospy/) -// Module author: igor.zavoychinskiy@gmail.com +// Author: igor.zavoychinskiy@gmail.com // License: Public Domain using KASAPIv2; diff --git a/Source/api_impl/KasLinkEventImpl.cs b/Source/api_impl/KasLinkEventImpl.cs index 0f7668bbc..2451c1b76 100644 --- a/Source/api_impl/KasLinkEventImpl.cs +++ b/Source/api_impl/KasLinkEventImpl.cs @@ -1,6 +1,5 @@ // Kerbal Attachment System -// Mod idea: KospY (http://forum.kerbalspaceprogram.com/index.php?/profile/33868-kospy/) -// Module author: igor.zavoychinskiy@gmail.com +// Author: igor.zavoychinskiy@gmail.com // License: Public Domain namespace KASAPIv2 { diff --git a/Source/api_impl/LinkUtilsImpl.cs b/Source/api_impl/LinkUtilsImpl.cs index 4e7ef4ade..af2f8da81 100644 --- a/Source/api_impl/LinkUtilsImpl.cs +++ b/Source/api_impl/LinkUtilsImpl.cs @@ -1,6 +1,5 @@ // Kerbal Attachment System API -// Mod idea: KospY (http://forum.kerbalspaceprogram.com/index.php?/profile/33868-kospy/) -// API design and implemenation: igor.zavoychinskiy@gmail.com +// Author: igor.zavoychinskiy@gmail.com // License: Public Domain using KASAPIv2; diff --git a/Source/api_impl/PhysicsUtilsImpl.cs b/Source/api_impl/PhysicsUtilsImpl.cs index 091a1910a..cf7ce5f27 100644 --- a/Source/api_impl/PhysicsUtilsImpl.cs +++ b/Source/api_impl/PhysicsUtilsImpl.cs @@ -1,6 +1,5 @@ // Kerbal Attachment System API -// Mod idea: KospY (http://forum.kerbalspaceprogram.com/index.php?/profile/33868-kospy/) -// API design and implemenation: igor.zavoychinskiy@gmail.com +// Author: igor.zavoychinskiy@gmail.com // License: Public Domain using KASAPIv2; diff --git a/Source/modules/AbstractJoint.cs b/Source/modules/AbstractJoint.cs index 4ba6eaf0e..aaac6f563 100644 --- a/Source/modules/AbstractJoint.cs +++ b/Source/modules/AbstractJoint.cs @@ -1,6 +1,5 @@ // Kerbal Attachment System -// Mod idea: KospY (http://forum.kerbalspaceprogram.com/index.php?/profile/33868-kospy/) -// Module author: igor.zavoychinskiy@gmail.com +// Author: igor.zavoychinskiy@gmail.com // License: Public Domain using KASAPIv2; diff --git a/Source/modules/AbstractLinkPeer.cs b/Source/modules/AbstractLinkPeer.cs index 6f4174cb7..891611a23 100644 --- a/Source/modules/AbstractLinkPeer.cs +++ b/Source/modules/AbstractLinkPeer.cs @@ -1,6 +1,5 @@ // Kerbal Attachment System -// Mod idea: KospY (http://forum.kerbalspaceprogram.com/index.php?/profile/33868-kospy/) -// Module author: igor.zavoychinskiy@gmail.com +// Author: igor.zavoychinskiy@gmail.com // License: Public Domain using KASAPIv2; diff --git a/Source/modules/AbstractProceduralModel.cs b/Source/modules/AbstractProceduralModel.cs index b78420ffa..a88851033 100644 --- a/Source/modules/AbstractProceduralModel.cs +++ b/Source/modules/AbstractProceduralModel.cs @@ -1,6 +1,5 @@ // Kerbal Attachment System -// Mod idea: KospY (http://forum.kerbalspaceprogram.com/index.php?/profile/33868-kospy/) -// Module author: igor.zavoychinskiy@gmail.com +// Author: igor.zavoychinskiy@gmail.com // License: Public Domain using System; diff --git a/Source/modules/KASInternalBrokenJointListener.cs b/Source/modules/KASInternalBrokenJointListener.cs index f6f7eecab..b307c4485 100644 --- a/Source/modules/KASInternalBrokenJointListener.cs +++ b/Source/modules/KASInternalBrokenJointListener.cs @@ -1,6 +1,5 @@ // Kerbal Attachment System -// Mod idea: KospY (http://forum.kerbalspaceprogram.com/index.php?/profile/33868-kospy/) -// Module author: igor.zavoychinskiy@gmail.com +// Author: igor.zavoychinskiy@gmail.com // License: Public Domain using KASAPIv2; diff --git a/Source/modules/KASInternalPhysicalConnector.cs b/Source/modules/KASInternalPhysicalConnector.cs index 35896ef7d..b884ce81f 100644 --- a/Source/modules/KASInternalPhysicalConnector.cs +++ b/Source/modules/KASInternalPhysicalConnector.cs @@ -1,6 +1,5 @@ // Kerbal Attachment System -// Mod idea: KospY (http://forum.kerbalspaceprogram.com/index.php?/profile/33868-kospy/) -// Module author: igor.zavoychinskiy@gmail.com +// Author: igor.zavoychinskiy@gmail.com // License: Public Domain using KASAPIv2; diff --git a/Source/modules/KASJointCableBase.cs b/Source/modules/KASJointCableBase.cs index 98f055101..97d4d5de8 100644 --- a/Source/modules/KASJointCableBase.cs +++ b/Source/modules/KASJointCableBase.cs @@ -1,6 +1,5 @@ // Kerbal Attachment System -// Mod idea: KospY (http://forum.kerbalspaceprogram.com/index.php?/profile/33868-kospy/) -// Module author: igor.zavoychinskiy@gmail.com +// Author: igor.zavoychinskiy@gmail.com // License: Public Domain using KASAPIv2; diff --git a/Source/modules/KASJointRigid.cs b/Source/modules/KASJointRigid.cs index 99b529f1b..3b2776cdd 100644 --- a/Source/modules/KASJointRigid.cs +++ b/Source/modules/KASJointRigid.cs @@ -1,6 +1,5 @@ // Kerbal Attachment System -// Mod idea: KospY (http://forum.kerbalspaceprogram.com/index.php?/profile/33868-kospy/) -// Module author: igor.zavoychinskiy@gmail.com +// Author: igor.zavoychinskiy@gmail.com // License: Public Domain using KSPDev.LogUtils; diff --git a/Source/modules/KASJointTowBar.cs b/Source/modules/KASJointTowBar.cs index 0896859c2..0716c21c9 100644 --- a/Source/modules/KASJointTowBar.cs +++ b/Source/modules/KASJointTowBar.cs @@ -1,6 +1,5 @@ // Kerbal Attachment System -// Mod idea: KospY (http://forum.kerbalspaceprogram.com/index.php?/profile/33868-kospy/) -// Module author: igor.zavoychinskiy@gmail.com +// Author: igor.zavoychinskiy@gmail.com // License: Public Domain using KASAPIv2; diff --git a/Source/modules/KASJointTwoEndsSphere.cs b/Source/modules/KASJointTwoEndsSphere.cs index 151d88134..c60e324d4 100644 --- a/Source/modules/KASJointTwoEndsSphere.cs +++ b/Source/modules/KASJointTwoEndsSphere.cs @@ -1,6 +1,5 @@ // Kerbal Attachment System -// Mod idea: KospY (http://forum.kerbalspaceprogram.com/index.php?/profile/33868-kospy/) -// Module author: igor.zavoychinskiy@gmail.com +// Author: igor.zavoychinskiy@gmail.com // License: Public Domain using KASAPIv2; diff --git a/Source/modules/KASLinkResourceConnector.cs b/Source/modules/KASLinkResourceConnector.cs index 3d55a3044..5afa0aae0 100644 --- a/Source/modules/KASLinkResourceConnector.cs +++ b/Source/modules/KASLinkResourceConnector.cs @@ -1,6 +1,5 @@ // Kerbal Attachment System -// Mod idea: KospY (http://forum.kerbalspaceprogram.com/index.php?/profile/33868-kospy/) -// Module author: igor.zavoychinskiy@gmail.com +// Author: igor.zavoychinskiy@gmail.com // License: Public Domain using KSPDev.ConfigUtils; diff --git a/Source/modules/KASLinkSourceBase.cs b/Source/modules/KASLinkSourceBase.cs index 11e4af9d8..2850dca10 100644 --- a/Source/modules/KASLinkSourceBase.cs +++ b/Source/modules/KASLinkSourceBase.cs @@ -1,6 +1,5 @@ // Kerbal Attachment System -// Mod idea: KospY (http://forum.kerbalspaceprogram.com/index.php?/profile/33868-kospy/) -// Module author: igor.zavoychinskiy@gmail.com +// Author: igor.zavoychinskiy@gmail.com // License: Public Domain using KASAPIv2; diff --git a/Source/modules/KASLinkSourceInteractive.cs b/Source/modules/KASLinkSourceInteractive.cs index 56548b400..7e187ddab 100644 --- a/Source/modules/KASLinkSourceInteractive.cs +++ b/Source/modules/KASLinkSourceInteractive.cs @@ -1,6 +1,5 @@ // Kerbal Attachment System -// Mod idea: KospY (http://forum.kerbalspaceprogram.com/index.php?/profile/33868-kospy/) -// Module author: igor.zavoychinskiy@gmail.com +// Author: igor.zavoychinskiy@gmail.com // License: Public Domain using KASAPIv2; diff --git a/Source/modules/KASLinkTargetBase.cs b/Source/modules/KASLinkTargetBase.cs index b95d27a24..13a88ba32 100644 --- a/Source/modules/KASLinkTargetBase.cs +++ b/Source/modules/KASLinkTargetBase.cs @@ -1,6 +1,5 @@ // Kerbal Attachment System -// Mod idea: KospY (http://forum.kerbalspaceprogram.com/index.php?/profile/33868-kospy/) -// Module author: igor.zavoychinskiy@gmail.com +// Author: igor.zavoychinskiy@gmail.com // License: Public Domain using KASAPIv2; diff --git a/Source/modules/KASLinkTargetKerbal.cs b/Source/modules/KASLinkTargetKerbal.cs index 302c04f2a..232e6d55b 100644 --- a/Source/modules/KASLinkTargetKerbal.cs +++ b/Source/modules/KASLinkTargetKerbal.cs @@ -1,5 +1,5 @@ -// Mod idea: KospY (http://forum.kerbalspaceprogram.com/index.php?/profile/33868-kospy/) -// Module author: igor.zavoychinskiy@gmail.com +// Kerbal Attachment System +// Author: igor.zavoychinskiy@gmail.com // License: Public Domain using KASAPIv2; diff --git a/Source/modules/KASLinkWinch.cs b/Source/modules/KASLinkWinch.cs index a63dc7d08..8b571471b 100644 --- a/Source/modules/KASLinkWinch.cs +++ b/Source/modules/KASLinkWinch.cs @@ -1,6 +1,5 @@ // Kerbal Attachment System -// Mod idea: KospY (http://forum.kerbalspaceprogram.com/index.php?/profile/33868-kospy/) -// Module author: igor.zavoychinskiy@gmail.com +// Author: igor.zavoychinskiy@gmail.com // License: Public Domain using KASAPIv2; diff --git a/Source/modules/KASRendererBezierPipe.cs b/Source/modules/KASRendererBezierPipe.cs index 723f27ca6..6c6e667ed 100644 --- a/Source/modules/KASRendererBezierPipe.cs +++ b/Source/modules/KASRendererBezierPipe.cs @@ -1,5 +1,4 @@ // Kerbal Attachment System -// https://forum.kerbalspaceprogram.com/index.php?/topic/142594-15-kerbal-attachment-system-kas-v11 // Author: igor.zavoychinskiy@gmail.com // License: Public Domain diff --git a/Source/modules/KASRendererTelescopicPipe.cs b/Source/modules/KASRendererTelescopicPipe.cs index 0980b15ac..e3e7d16b3 100644 --- a/Source/modules/KASRendererTelescopicPipe.cs +++ b/Source/modules/KASRendererTelescopicPipe.cs @@ -1,6 +1,5 @@ // Kerbal Attachment System -// Mod idea: KospY (http://forum.kerbalspaceprogram.com/index.php?/profile/33868-kospy/) -// Module author: igor.zavoychinskiy@gmail.com +// Author: igor.zavoychinskiy@gmail.com // License: Public Domain using KASAPIv2; From 2b083550497fb2c0e0e00ada4c8e01f326f927dd Mon Sep 17 00:00:00 2001 From: ihsoft Date: Mon, 20 Jul 2020 23:31:00 -0700 Subject: [PATCH 11/46] Drop dead and unneeded code --- Source/KSPDev_candidates/Hierarchy2.cs | 2 +- Source/api_impl/LinkUtilsImpl.cs | 1 - Source/api_impl/PhysicsUtilsImpl.cs | 2 +- Source/controllers/ControllerPartEditorTool.cs | 3 --- Source/controllers/ControllerWinchRemote.cs | 3 +-- Source/modules/AbstractJoint.cs | 4 ++-- Source/modules/AbstractLinkPeer.cs | 4 ++-- Source/modules/AbstractPipeRenderer.cs | 3 --- Source/modules/KASJointCableBase.cs | 15 ++------------- Source/modules/KASJointTwoEndsSphere.cs | 1 - Source/modules/KASLinkResourceConnector.cs | 3 +-- Source/modules/KASLinkSourceBase.cs | 3 +-- Source/modules/KASLinkSourceInteractive.cs | 2 +- Source/modules/KASLinkSourcePhysical.cs | 2 -- Source/modules/KASLinkTargetBase.cs | 12 ------------ Source/modules/KASLinkWinch.cs | 2 +- Source/modules/KASRendererBezierPipe.cs | 3 --- Source/modules/KASRendererPipe.cs | 6 +++--- Source/modules/KASRendererTelescopicPipe.cs | 2 +- 19 files changed, 17 insertions(+), 56 deletions(-) diff --git a/Source/KSPDev_candidates/Hierarchy2.cs b/Source/KSPDev_candidates/Hierarchy2.cs index e5de63804..3fedbbbb8 100644 --- a/Source/KSPDev_candidates/Hierarchy2.cs +++ b/Source/KSPDev_candidates/Hierarchy2.cs @@ -28,7 +28,7 @@ public static void SafeDestroy(GameObject obj) { obj.transform.SetParent(null, worldPositionStays: false); obj.name = "$disposed"; obj.SetActive(false); - UnityEngine.Object.Destroy(obj); + Object.Destroy(obj); } } diff --git a/Source/api_impl/LinkUtilsImpl.cs b/Source/api_impl/LinkUtilsImpl.cs index af2f8da81..b016138cd 100644 --- a/Source/api_impl/LinkUtilsImpl.cs +++ b/Source/api_impl/LinkUtilsImpl.cs @@ -71,7 +71,6 @@ public Part CoupleParts(AttachNode sourceNode, AttachNode targetNode, var srcVessel = srcPart.vessel; KASAPI.AttachNodesUtils.AddNode(srcPart, sourceNode); var tgtPart = targetNode.owner; - var tgtVessel = tgtPart.vessel; KASAPI.AttachNodesUtils.AddNode(tgtPart, targetNode); sourceNode.attachedPart = tgtPart; diff --git a/Source/api_impl/PhysicsUtilsImpl.cs b/Source/api_impl/PhysicsUtilsImpl.cs index cf7ce5f27..ff413456d 100644 --- a/Source/api_impl/PhysicsUtilsImpl.cs +++ b/Source/api_impl/PhysicsUtilsImpl.cs @@ -20,7 +20,7 @@ public void ApplyGravity(Rigidbody rb, Vessel vessel, double rbAirDragMult = 1.0 var pseudoReDragMult = 1; //FIXME: find out what it is var d = 0.0005 * pseudoReDragMult * vessel.atmDensity * rbAirDragMult * (rb.velocity + Krakensbane.GetFrameVelocity()).sqrMagnitude - * (double)PhysicsGlobals.DragMultiplier; + * PhysicsGlobals.DragMultiplier; if (!double.IsNaN(d) && !double.IsInfinity(d)) { var atmDragForce = -(rb.velocity + Krakensbane.GetFrameVelocity()).normalized * d; if (PhysicsGlobals.DragUsesAcceleration) { diff --git a/Source/controllers/ControllerPartEditorTool.cs b/Source/controllers/ControllerPartEditorTool.cs index 68a3c5b91..e6a3d833b 100644 --- a/Source/controllers/ControllerPartEditorTool.cs +++ b/Source/controllers/ControllerPartEditorTool.cs @@ -5,9 +5,6 @@ using KSPDev.ConfigUtils; using KSPDev.DebugUtils; using KSPDev.GUIUtils; -using KSPDev.LogUtils; -using System.Collections.Generic; -using System.Linq; using UnityEngine; namespace KAS.Debug { diff --git a/Source/controllers/ControllerWinchRemote.cs b/Source/controllers/ControllerWinchRemote.cs index 4f55563a0..fcd8138cb 100644 --- a/Source/controllers/ControllerWinchRemote.cs +++ b/Source/controllers/ControllerWinchRemote.cs @@ -8,7 +8,6 @@ using KSPDev.GUIUtils.TypeFormatters; using KSPDev.LogUtils; using System.Collections.Generic; -using System; using System.Linq; using UnityEngine; @@ -22,7 +21,7 @@ namespace KAS { /// // Next localization ID: #kasLOC_11028. [KSPAddon(KSPAddon.Startup.Flight, false /*once*/)] -[PersistentFieldsDatabase("KAS/settings/KASConfig", "")] +[PersistentFieldsDatabase("KAS/settings/KASConfig")] sealed class ControllerWinchRemote : MonoBehaviour, IHasGUI { #region Localizable GUI strings. /// diff --git a/Source/modules/AbstractJoint.cs b/Source/modules/AbstractJoint.cs index aaac6f563..d9bad49b9 100644 --- a/Source/modules/AbstractJoint.cs +++ b/Source/modules/AbstractJoint.cs @@ -555,13 +555,13 @@ public virtual bool SetCoupleOnLinkMode(bool isCoupleOnLink) { // Couple the parts, and drop the other link(s). HostedDebugLog.Info(this, "Change coupling mode: ATTACHED => COUPLED"); DetachParts(); - coupleOnLinkMode = isCoupleOnLink; + coupleOnLinkMode = true; CoupleParts(); } else if (!isCoupleOnLink && isCoupled) { // Decouple the parts, and make the non-coupling link(s). HostedDebugLog.Info(this, "Change coupling mode: COUPLED => ATTACHED"); DecoupleParts(); - coupleOnLinkMode = isCoupleOnLink; + coupleOnLinkMode = false; AttachParts(); } else { coupleOnLinkMode = isCoupleOnLink; // Simply change the mode. diff --git a/Source/modules/AbstractLinkPeer.cs b/Source/modules/AbstractLinkPeer.cs index 891611a23..a57080db6 100644 --- a/Source/modules/AbstractLinkPeer.cs +++ b/Source/modules/AbstractLinkPeer.cs @@ -431,7 +431,7 @@ protected virtual void SetOtherPeer(ILinkPeer peer) { var oldPeer = _otherPeer; _otherPeer = peer; if (_otherPeer != null) { - persistedLinkPartId = _otherPeer != null ? _otherPeer.part.flightID : 0; + persistedLinkPartId = (uint) _otherPeer?.part.flightID; persistedLinkNodeName = _otherPeer.cfgAttachNodeName; } else { persistedLinkPartId = 0; @@ -445,7 +445,7 @@ protected virtual void SetOtherPeer(ILinkPeer peer) { /// public virtual void OnKASLinkedState(IKasLinkEvent info, bool isLinked) { var peer = info.source.part == part - ? info.source as ILinkPeer + ? info.source : info.target as ILinkPeer; if (!ReferenceEquals(peer, this) && (peer.cfgAttachNodeName == attachNodeName diff --git a/Source/modules/AbstractPipeRenderer.cs b/Source/modules/AbstractPipeRenderer.cs index a833dfd37..93f7f3448 100644 --- a/Source/modules/AbstractPipeRenderer.cs +++ b/Source/modules/AbstractPipeRenderer.cs @@ -9,7 +9,6 @@ using KSPDev.LogUtils; using KSPDev.ModelUtils; using KSPDev.PartUtils; -using System; using System.Collections; using System.Collections.Generic; using System.Linq; @@ -453,8 +452,6 @@ void CheckHitsForCapsule(Vector3 startPos, Vector3 endPos, float diameter, Transform target, HashSet hits) { var tgtPart = target.root.GetComponent(); var otherVessel = tgtPart != null ? tgtPart.vessel : null; - var linkVector = endPos - startPos; - var linkLength = linkVector.magnitude; Collider[] colliders; colliders = Physics.OverlapCapsule( startPos, endPos, diameter / 2.0f, diff --git a/Source/modules/KASJointCableBase.cs b/Source/modules/KASJointCableBase.cs index 97d4d5de8..5c7cbb335 100644 --- a/Source/modules/KASJointCableBase.cs +++ b/Source/modules/KASJointCableBase.cs @@ -5,11 +5,8 @@ using KASAPIv2; using KSPDev.GUIUtils; using KSPDev.GUIUtils.TypeFormatters; -using KSPDev.KSPInterfaces; using KSPDev.LogUtils; using KSPDev.ProcessingUtils; -using System; -using System.Collections; using System.Text; using UnityEngine; @@ -24,11 +21,9 @@ namespace KAS { // Next localization ID: #kasLOC_09002. public class KASJointCableBase : AbstractJoint, // KSP interfaces. - IModuleInfo, IJointLockState, + IJointLockState, // KAS interfaces. - ILinkCableJoint, - // KSPDev syntax sugar interfaces. - IKSPDevModuleInfo { + ILinkCableJoint { #region Localizable GUI strings. /// @@ -117,10 +112,6 @@ public float realCableLength { /// The source, or null if the head is not started. /// protected ILinkSource headSource { get; private set; } - - /// Head's transform at which the cable is attached. - /// The anchor of the physical head, or null if the head is not started. - protected Transform headPhysicalAnchor { get; private set; } #endregion #region AbstractJoint overrides @@ -174,7 +165,6 @@ public virtual void StartPhysicalHead(ILinkSource source, Transform headObjAncho return; } headSource = source; - headPhysicalAnchor = headObjAnchor; // Attach the head to the source. CreateDistanceJoint(source, headRb, headObjAnchor.position); @@ -185,7 +175,6 @@ public virtual void StartPhysicalHead(ILinkSource source, Transform headObjAncho public virtual void StopPhysicalHead() { headRb = null; headSource = null; - headPhysicalAnchor = null; Destroy(cableJoint); cableJoint = null; SetOrigianlLength(null); diff --git a/Source/modules/KASJointTwoEndsSphere.cs b/Source/modules/KASJointTwoEndsSphere.cs index c60e324d4..264e10af0 100644 --- a/Source/modules/KASJointTwoEndsSphere.cs +++ b/Source/modules/KASJointTwoEndsSphere.cs @@ -5,7 +5,6 @@ using KASAPIv2; using KSPDev.KSPInterfaces; using KSPDev.LogUtils; -using System; using UnityEngine; namespace KAS { diff --git a/Source/modules/KASLinkResourceConnector.cs b/Source/modules/KASLinkResourceConnector.cs index 5afa0aae0..18b307e54 100644 --- a/Source/modules/KASLinkResourceConnector.cs +++ b/Source/modules/KASLinkResourceConnector.cs @@ -10,7 +10,6 @@ using KSPDev.ModelUtils; using KSPDev.PartUtils; using KSPDev.ResourceUtils; -using System; using System.Collections.Generic; using System.Linq; using UnityEngine; @@ -20,7 +19,7 @@ namespace KAS { /// Module which trasnfer resources between two linked vessels. /// // Next localization ID: #kasLOC_12017 -[PersistentFieldsDatabase("KAS/settings/KASConfig", "")] +[PersistentFieldsDatabase("KAS/settings/KASConfig")] public sealed class KASLinkResourceConnector : KASLinkSourcePhysical, // KAS interfaces. IHasGUI { diff --git a/Source/modules/KASLinkSourceBase.cs b/Source/modules/KASLinkSourceBase.cs index 2850dca10..03fc4c898 100644 --- a/Source/modules/KASLinkSourceBase.cs +++ b/Source/modules/KASLinkSourceBase.cs @@ -3,7 +3,6 @@ // License: Public Domain using KASAPIv2; -using KSPDev.DebugUtils; using KSPDev.GUIUtils; using KSPDev.KSPInterfaces; using KSPDev.LogUtils; @@ -371,7 +370,7 @@ protected override void CheckCoupleNode() { .OfType() .FirstOrDefault(t => t.cfgLinkType == cfgLinkType && t.linkState == LinkState.Available && t.coupleNode != null && t.coupleNode.attachedPart == part - && CheckCanLinkTo(t, reportToLog: true)); + && CheckCanLinkTo(t)); if (target != null) { HostedDebugLog.Fine(this, "Linking with the preattached part: {0}", target); LinkToTarget(LinkActorType.API, target); diff --git a/Source/modules/KASLinkSourceInteractive.cs b/Source/modules/KASLinkSourceInteractive.cs index 7e187ddab..c0021820d 100644 --- a/Source/modules/KASLinkSourceInteractive.cs +++ b/Source/modules/KASLinkSourceInteractive.cs @@ -164,7 +164,7 @@ public override void OnUpdate() { } /// - public override void OnStart(PartModule.StartState state) { + public override void OnStart(StartState state) { base.OnStart(state); // Infinity duration doesn't mean the message will be shown forever. It must be refreshed in the // Update method. diff --git a/Source/modules/KASLinkSourcePhysical.cs b/Source/modules/KASLinkSourcePhysical.cs index e471b76d2..dce93e0d8 100644 --- a/Source/modules/KASLinkSourcePhysical.cs +++ b/Source/modules/KASLinkSourcePhysical.cs @@ -238,8 +238,6 @@ public virtual void GrabConnectorEvent() { public virtual void ReturnConnectorEvent() { if (FlightGlobals.ActiveVessel.isEVA && linkTarget != null && linkTarget.part.vessel == FlightGlobals.ActiveVessel) { - var kerbalTarget = FlightGlobals.ActiveVessel.rootPart.Modules.OfType() - .FirstOrDefault(t => ReferenceEquals(t.linkSource, this)); BreakCurrentLink(LinkActorType.Player); SetConnectorState(ConnectorState.Locked); HostedDebugLog.Info( diff --git a/Source/modules/KASLinkTargetBase.cs b/Source/modules/KASLinkTargetBase.cs index 13a88ba32..99f4e032f 100644 --- a/Source/modules/KASLinkTargetBase.cs +++ b/Source/modules/KASLinkTargetBase.cs @@ -4,7 +4,6 @@ using KASAPIv2; using KSPDev.GUIUtils; -using KSPDev.DebugUtils; using KSPDev.KSPInterfaces; using KSPDev.LogUtils; using KSPDev.ProcessingUtils; @@ -265,17 +264,6 @@ protected virtual bool CheckCanLinkWith(ILinkSource source) { #endregion #region Local untility methods - /// Finds a compatible source linked to the EVA kerbal. - /// The source or null if nothing found. - ILinkTarget FindEvaTargetWithConnector() { - if (!HighLogic.LoadedSceneIsFlight || !FlightGlobals.ActiveVessel.isEVA) { - return null; - } - return FlightGlobals.ActiveVessel - .FindPartModulesImplementing() - .FirstOrDefault(t => t.isLinked && t.cfgLinkType == cfgLinkType); - } - /// Sets the highlighter state on the part. /// /// Does nothing if the settings is set to false. diff --git a/Source/modules/KASLinkWinch.cs b/Source/modules/KASLinkWinch.cs index 8b571471b..6e1ba1578 100644 --- a/Source/modules/KASLinkWinch.cs +++ b/Source/modules/KASLinkWinch.cs @@ -405,7 +405,7 @@ protected override void InitModuleSettings() { resHandler.inputResources.Add(moduleResource); } moduleResource.title = KSPUtil.PrintModuleName(StockResourceNames.ElectricCharge); - moduleResource.rate = (double) motorPowerDrain; + moduleResource.rate = motorPowerDrain; } /// diff --git a/Source/modules/KASRendererBezierPipe.cs b/Source/modules/KASRendererBezierPipe.cs index 6c6e667ed..528c823fe 100644 --- a/Source/modules/KASRendererBezierPipe.cs +++ b/Source/modules/KASRendererBezierPipe.cs @@ -2,12 +2,9 @@ // Author: igor.zavoychinskiy@gmail.com // License: Public Domain -using System; using System.Linq; using UnityEngine; -using KSPDev.LogUtils; - namespace KAS { /// diff --git a/Source/modules/KASRendererPipe.cs b/Source/modules/KASRendererPipe.cs index d0884710d..798c8edcb 100644 --- a/Source/modules/KASRendererPipe.cs +++ b/Source/modules/KASRendererPipe.cs @@ -79,21 +79,21 @@ public class JointConfig { /// [PersistentField("sphereOffset")] [Debug.KASDebugAdjustable("Sphere offset")] - public float sphereOffset; + public float sphereOffset = 0; /// Diameter of the sphere to place at the pipe joint. /// It must be zero or positive. /// [PersistentField("sphereDiameter")] [Debug.KASDebugAdjustable("Sphere diameter")] - public float sphereDiameter; + public float sphereDiameter = 0; /// Diameter of the pipe that connects the attach node and the pipe joint. /// It must be zero or positive. /// [PersistentField("armDiameter")] [Debug.KASDebugAdjustable("Arm diameter")] - public float armDiameter; + public float armDiameter = 0; /// Path to the prefab model that represents the joint. /// diff --git a/Source/modules/KASRendererTelescopicPipe.cs b/Source/modules/KASRendererTelescopicPipe.cs index e3e7d16b3..5b571d156 100644 --- a/Source/modules/KASRendererTelescopicPipe.cs +++ b/Source/modules/KASRendererTelescopicPipe.cs @@ -54,7 +54,7 @@ public sealed class KASRendererTelescopicPipe : AbstractProceduralModel, /// Extended length of the unlinked strut. /// [KSPField(isPersistant = true)] - public float persistedParkedLength = 0; // If 0 then minimum link length will be used. + public float persistedParkedLength; // If 0 then minimum link length will be used. #endregion #region Part's config fields From 23b913ea8cfbffe7dc250e8f7ee632b979c0b70e Mon Sep 17 00:00:00 2001 From: ihsoft Date: Tue, 21 Jul 2020 00:04:03 -0700 Subject: [PATCH 12/46] Fix special tags file location --- .../controllers/ControllerPartEditorTool.cs | 2 +- Source/controllers/ControllerWinchRemote.cs | 58 +++++++-------- Source/modules/AbstractJoint.cs | 70 +++++++++---------- Source/modules/AbstractLinkPeer.cs | 16 ++--- Source/modules/AbstractPipeRenderer.cs | 18 ++--- Source/modules/AbstractProceduralModel.cs | 8 +-- Source/modules/KASJointCableBase.cs | 10 +-- Source/modules/KASJointTowBar.cs | 34 ++++----- Source/modules/KASJointTwoEndsSphere.cs | 4 +- Source/modules/KASLinkResourceConnector.cs | 46 ++++++------ Source/modules/KASLinkSourceBase.cs | 28 ++++---- Source/modules/KASLinkSourceInteractive.cs | 22 +++--- Source/modules/KASLinkSourcePhysical.cs | 44 ++++++------ Source/modules/KASLinkTargetBase.cs | 8 +-- Source/modules/KASLinkTargetKerbal.cs | 12 ++-- Source/modules/KASLinkWinch.cs | 62 ++++++++-------- Source/modules/KASRendererBezierPipe.cs | 8 +-- Source/modules/KASRendererPipe.cs | 32 ++++----- Source/modules/KASRendererTelescopicPipe.cs | 28 ++++---- 19 files changed, 255 insertions(+), 255 deletions(-) diff --git a/Source/controllers/ControllerPartEditorTool.cs b/Source/controllers/ControllerPartEditorTool.cs index e6a3d833b..ebd6f2113 100644 --- a/Source/controllers/ControllerPartEditorTool.cs +++ b/Source/controllers/ControllerPartEditorTool.cs @@ -20,7 +20,7 @@ sealed class ControllerPartEditorTool : MonoBehaviour, #region Configuration settings /// Keyboard key to trigger the GUI. - /// + /// [PersistentField("Debug/partAlignToolKey")] public string openGUIKey = ""; #endregion diff --git a/Source/controllers/ControllerWinchRemote.cs b/Source/controllers/ControllerWinchRemote.cs index fcd8138cb..c752b17e3 100644 --- a/Source/controllers/ControllerWinchRemote.cs +++ b/Source/controllers/ControllerWinchRemote.cs @@ -24,7 +24,7 @@ namespace KAS { [PersistentFieldsDatabase("KAS/settings/KASConfig")] sealed class ControllerWinchRemote : MonoBehaviour, IHasGUI { #region Localizable GUI strings. - /// + /// static readonly Message WindowTitleTxt = new Message( "#kasLOC_11000", defaultTemplate: "Winch Remote Control (<<1>>)", @@ -32,142 +32,142 @@ sealed class ControllerWinchRemote : MonoBehaviour, IHasGUI { + " sequence that brings the GUI up." + "\nArgument <<1>> is the keyboard even of type KeyboardEventType."); - /// + /// static readonly Message ReleaseBtn = new Message( "#kasLOC_11001", defaultTemplate: "Release", description: "The caption of the button that triggers cable release."); - /// + /// static readonly Message ReleaseBtnHint = new Message( "#kasLOC_11002", defaultTemplate: "Release the connector and set cable length to the maximum", description: "The GUI hint to explain the effect of the release button."); - /// + /// static readonly Message StretchBtn = new Message( "#kasLOC_11003", defaultTemplate: "Stretch", description: "The caption of the button that stretches teeh cable."); - /// + /// static readonly Message StretchBtnHint = new Message( "#kasLOC_11004", defaultTemplate: "Set the cable length to the actual distance", description: "The GUI hint to explain the effect of the stretch button."); - /// + /// static readonly Message DetachBtn = new Message( "#kasLOC_11005", defaultTemplate: "Detach", description: "The caption of the button that deatches the cable from the target."); - /// + /// static readonly Message DetachBtnHint = new Message( "#kasLOC_11006", defaultTemplate: "Detach the cable from the target part", description: "The GUI hint to explain the effect of the detach button."); - /// + /// static readonly Message CloseBtn = new Message( "#kasLOC_11007", defaultTemplate: "Close", description: "The caption of the button that closes the GUI dialog."); - /// + /// static readonly Message CloseBtnHint = new Message( "#kasLOC_11008", defaultTemplate: "Close GUI", description: "The GUI hint to explain the effect of the close button."); - /// static readonly Message HightlightWinchBtn = new Message( + /// "#kasLOC_11009", defaultTemplate: "H", description: "The caption for the toggle control (button style) which tells if the winch" + " should be highlighted in the scene. It's better keep the text as short as possible."); - /// static readonly Message HightlightWinchBtnHint = new Message( + /// "#kasLOC_11010", defaultTemplate: "Highlight the winch in the scene", description: "The GUI hint to explain the effect of toggling the control."); - /// + /// static readonly Message WinchModeOfflineTxt = new Message( "#kasLOC_11011", defaultTemplate: "Offline", description: "The text for the winch status in which it cannot be remotely operated for any" + " reason."); - /// + /// static readonly Message WinchModeOfflineTxtHint = new Message( "#kasLOC_11012", defaultTemplate: "Cannot contact the winch. Is the vessel controllable?", description: "The GUI hint to explain the OFFLINE state."); - /// + /// static readonly Message WinchModeBlockedTxt = new Message( "#kasLOC_11013", defaultTemplate: "Blocked", description: "The text for the winch status that tells that the main winch attach node is" + " occupied by an incompatible (non-KAS) part."); - /// + /// static readonly Message WinchModeBlockedTxtHint = new Message( "#kasLOC_11014", defaultTemplate: "Winch attach node is blocked by another part", description: "The GUI hint to explain the BLOCKED state."); - /// + /// static readonly Message WinchModeRetractedTxt = new Message( "#kasLOC_11015", defaultTemplate: "Retracted", description: "The text for the winch status that tells that the cable connector is locked to" + " the winch, and the cable length is zero."); - /// + /// static readonly Message WinchModeRetractedTxtHint = new Message( "#kasLOC_11016", defaultTemplate: "The connector is locked into the winch", description: "The GUI hint to explain the RETRACTED state."); - /// + /// static readonly Message StartRetractingCableBtnHint = new Message( "#kasLOC_11017", defaultTemplate: "Start retracting the cable", description: "The GUI hint of the button that triggers retracting of the cable. The cable" + " will be retracting until the motor status is changed or the connector get locked."); - /// + /// static readonly Message StartExtendingCableBtnHint = new Message( "#kasLOC_11018", defaultTemplate: "Start extending the cable", description: "The GUI hint of the button that triggers deploying of the cable. The cable will" + " be deploying until the motor status is changed."); - /// + /// static readonly Message RetractCableBtnHint = new Message( "#kasLOC_11019", defaultTemplate: "Retract the cable", description: "The GUI hint of the button that retracts the cable. The cable will be" + " retracting as long as the button is pressed."); - /// + /// static readonly Message ExtendCableBtnHint = new Message( "#kasLOC_11020", defaultTemplate: "Extend the cable", description: "The GUI hint of the button that extends the cable. The cable will be" + " extending as long as the button is pressed."); - /// + /// static readonly Message MotorSpeedSettingsTxtHint = new Message( "#kasLOC_11021", defaultTemplate: "Motor speed setting", description: "The GUI hint to show for the control that changes the motor speed. It's the" + " maximum speed which the motor can reach when retracting or extending the cable."); - /// + /// static readonly Message CableLengthTxtHint = new Message( "#kasLOC_11022", defaultTemplate: "The deployed/real length of the cable", @@ -175,7 +175,7 @@ sealed class ControllerWinchRemote : MonoBehaviour, IHasGUI { + " length and the real distance between the winch and the target (connector or part). The" + " values are presented as a pair, separated by symbol '/'."); - /// + /// static readonly Message MotorSpeedStatusTxtHint = new Message( "#kasLOC_11023", defaultTemplate: "Current motor speed / Motor speed setting", @@ -183,14 +183,14 @@ sealed class ControllerWinchRemote : MonoBehaviour, IHasGUI { + " speed and the maximum possible motor speed. The values are presented as a pair, separated" + " by symbol '/'."); - /// + /// static readonly Message NoContentTxt = new Message( "#kasLOC_11024", defaultTemplate: "No winches found in the scene!", description: "The string to present when the dialog is opened, but no KAS winches found in" + " the scene."); - /// + /// static readonly Message RelaxedCableLengthTxt = new Message( "#kasLOC_11025", @@ -200,7 +200,7 @@ sealed class ControllerWinchRemote : MonoBehaviour, IHasGUI { + "\nArgument <<1>> is the length, allowed by the winch of type DistanceType." + "\nArgument <<1>> is the real cable length of type DistanceType."); - /// + /// static readonly Message StrainedCableLengthTxt = new Message( "#kasLOC_11026", @@ -210,7 +210,7 @@ sealed class ControllerWinchRemote : MonoBehaviour, IHasGUI { + "\nArgument <<1>> is the length, allowed by the winch of type DistanceType." + "\nArgument <<2>> is the real cable length of type DistanceType."); - /// + /// static readonly Message MotorSpeedTxt = new Message( "#kasLOC_11027", @@ -222,7 +222,7 @@ sealed class ControllerWinchRemote : MonoBehaviour, IHasGUI { #region Configuration settings /// Keyboard key to trigger the GUI. - /// + /// [PersistentField("Winch/remoteControlKey")] public string openGUIKey = "&P"; // Alt+P #endregion diff --git a/Source/modules/AbstractJoint.cs b/Source/modules/AbstractJoint.cs index d9bad49b9..d632d9075 100644 --- a/Source/modules/AbstractJoint.cs +++ b/Source/modules/AbstractJoint.cs @@ -42,9 +42,9 @@ public abstract class AbstractJoint : AbstractPartModule, IsPackable, IKSPDevModuleInfo, IKSPActivateOnDecouple { #region Localizable GUI strings - /// - /// readonly static Message MinLengthLimitReachedMsg = + /// + /// new Message( "#kasLOC_00000", defaultTemplate: "Link is too short: <<1>> < <<2>>", @@ -54,9 +54,9 @@ public abstract class AbstractJoint : AbstractPartModule, + "\nArgument <<2>> is the part's config setting of type DistanceType.", example: "Link is too short: 1.22 m < 2.33 m"); - /// - /// readonly static Message MaxLengthLimitReachedMsg = + /// + /// new Message( "#kasLOC_00001", defaultTemplate: "Link is too long: <<1>> > <<2>>", @@ -66,9 +66,9 @@ public abstract class AbstractJoint : AbstractPartModule, + "\nArgument <<2>> is the part's config setting of type DistanceType.", example: "Link is too long: 2.33 m > 1.22 m"); - /// - /// readonly static Message SourceNodeAngleLimitReachedMsg = + /// + /// new Message( "#kasLOC_00002", defaultTemplate: "Source angle limit reached: <<1>> > <<2>>", @@ -78,9 +78,9 @@ public abstract class AbstractJoint : AbstractPartModule, + "\nArgument <<2>> is the part's config setting of type AngleType.", example: "Source angle limit reached: 3° > 2.5°"); - /// - /// readonly static Message TargetNodeAngleLimitReachedMsg = + /// + /// new Message( "#kasLOC_00003", defaultTemplate: "Target angle limit reached: <<1>> > <<2>>", @@ -90,27 +90,27 @@ public abstract class AbstractJoint : AbstractPartModule, + "\nArgument <<2>> is the part's config setting of type AngleType.", example: "Target angle limit reached: 3° > 2.5°"); - /// - /// readonly static Message LinkLinearStrengthInfo = new Message( + /// + /// "#kasLOC_00004", defaultTemplate: "Link break force: <<1>>", description: "Info string in the editor for the link break force setting. The argument is of" + " type ForceType.", example: "Link break force: 1.2 kN"); - /// - /// readonly static Message LinkBreakStrengthInfo = new Message( + /// + /// "#kasLOC_00005", defaultTemplate: "Link torque force: <<1>>", description: "Info string in the editor for the link break torque setting. The argument is of" + " type ForceType.", example: "Link torque force: 1.2 kN"); - /// - /// readonly static Message MinimumLinkLengthInfo = + /// + /// new Message( "#kasLOC_00006", defaultTemplate: "Minimum link length: <<1>>", @@ -118,9 +118,9 @@ public abstract class AbstractJoint : AbstractPartModule, + "\nArgument <<1>> is the part's config setting of type DistanceType.", example: "Minimum link length: 1.22 m"); - /// - /// readonly static Message MaximumLinkLengthInfo = + /// + /// new Message( "#kasLOC_00007", defaultTemplate: "Maximum link length: <<1>>", @@ -128,26 +128,26 @@ public abstract class AbstractJoint : AbstractPartModule, + "\nArgument <<1>> is the part's config setting of type DistanceType.", example: "Maximum link length: 1.22 m"); - /// - /// readonly static Message SourceJointFreedomInfo = new Message( + /// + /// "#kasLOC_00008", defaultTemplate: "Source angle limit: <<1>>", description: "Info string in the editor for the maximum allowed angle at the source." + "\nArgument <<1>> is the part's config setting of type AngleType.", example: "Source angle limit: 1.2°"); - /// - /// readonly static Message TargetJointFreedomInfo = new Message( + /// + /// "#kasLOC_00009", defaultTemplate: "Target angle limit: <<1>>", description: "Info string in the editor for the maximum allowed angle at the target." + "\nArgument <<1>> is the part's config setting of type AngleType.", example: "Target angle limit: 1.2°"); - /// readonly static Message ModuleTitle = new Message( + /// "#kasLOC_00010", defaultTemplate: "KAS Joint", description: "Title of the module to present in the editor details window."); @@ -160,7 +160,7 @@ public abstract class AbstractJoint : AbstractPartModule, #region Part's config fields /// See . - /// + /// [KSPField] public string jointName = ""; @@ -169,7 +169,7 @@ public abstract class AbstractJoint : AbstractPartModule, /// Force is in kilonewtons. If 0, then the joint strength infinite. /// /// - /// + /// [KSPField] [Debug.KASDebugAdjustable("Break force")] public float linkBreakForce; @@ -179,7 +179,7 @@ public abstract class AbstractJoint : AbstractPartModule, /// Force is in kilonewtons. If 0, then the joint strength is infinite. /// /// - /// + /// [KSPField] [Debug.KASDebugAdjustable("Break torque")] public float linkBreakTorque; @@ -189,7 +189,7 @@ public abstract class AbstractJoint : AbstractPartModule, /// /// Angle is in degrees. If 0, then the angle is not checked. /// - /// + /// [KSPField] [Debug.KASDebugAdjustable("Source angle limit")] public int sourceLinkAngleLimit; @@ -199,7 +199,7 @@ public abstract class AbstractJoint : AbstractPartModule, /// /// Angle is in degrees. If 0, then the angle is not checked. /// - /// + /// [KSPField] [Debug.KASDebugAdjustable("Target angle limit")] public int targetLinkAngleLimit; @@ -209,7 +209,7 @@ public abstract class AbstractJoint : AbstractPartModule, /// Distance is in meters. If 0, then no limit for the minimum value is applied. /// /// - /// + /// [KSPField] [Debug.KASDebugAdjustable("MIN link length")] public float minLinkLength; @@ -219,7 +219,7 @@ public abstract class AbstractJoint : AbstractPartModule, /// Distance is in meters. If 0, then no limit for the minimum value is applied. /// /// - /// + /// [KSPField] [Debug.KASDebugAdjustable("MAX link length")] public float maxLinkLength; @@ -229,7 +229,7 @@ public abstract class AbstractJoint : AbstractPartModule, /// /// /// - /// + /// [KSPField] [Debug.KASDebugAdjustable("Anchor at source")] public Vector3 anchorAtSource = Vector3.zero; @@ -239,7 +239,7 @@ public abstract class AbstractJoint : AbstractPartModule, /// /// /// - /// + /// [KSPField] [Debug.KASDebugAdjustable("Anchor at target")] public Vector3 anchorAtTarget = Vector3.zero; @@ -251,18 +251,18 @@ public abstract class AbstractJoint : AbstractPartModule, /// different vessels. /// /// - /// - /// + /// + /// [KSPField(isPersistant = true)] public bool coupleWhenLinked; /// Vessel info of the source part. - /// + /// [PersistentField("persistedSrcVesselInfo", group = StdPersistentGroups.PartPersistant)] public DockedVesselInfo persistedSrcVesselInfo; /// Vessel info of the target part. - /// + /// [PersistentField("persistedTgtVesselInfo", group = StdPersistentGroups.PartPersistant)] public DockedVesselInfo persistedTgtVesselInfo; @@ -271,7 +271,7 @@ public abstract class AbstractJoint : AbstractPartModule, /// This value is used to restore the link state, but only if it's greater than zero. If it's /// less, then the implementation should decide which length to set when the joint is created. /// - /// + /// [KSPField(isPersistant = true)] public float persistedLinkLength = -1.0f; #endregion diff --git a/Source/modules/AbstractLinkPeer.cs b/Source/modules/AbstractLinkPeer.cs index a57080db6..b2378c6ba 100644 --- a/Source/modules/AbstractLinkPeer.cs +++ b/Source/modules/AbstractLinkPeer.cs @@ -29,7 +29,7 @@ public abstract class AbstractLinkPeer : AbstractPartModule, #region Part's config fields /// See . - /// + /// [KSPField] [Debug.KASDebugAdjustable("Link type")] public string linkType = ""; @@ -37,7 +37,7 @@ public abstract class AbstractLinkPeer : AbstractPartModule, /// The localized string to display for the link type. /// If mising or empty, then the types is show "as-is". /// - /// + /// [KSPField] public string linkTypeDisplayName = ""; @@ -49,7 +49,7 @@ public abstract class AbstractLinkPeer : AbstractPartModule, /// This node will not be available in the editor or in the flight for the third-party mods /// (like KIS). /// - /// + /// /// [KSPField] [Debug.KASDebugAdjustable("Attach node definition")] @@ -60,7 +60,7 @@ public abstract class AbstractLinkPeer : AbstractPartModule, /// If an attach node with this name is existing on the part, then it will be used. Otherwise, it /// will be assumed that the node needs to be created/removed automatically as needed. /// - /// + /// /// [KSPField] [Debug.KASDebugAdjustable("Attach node name")] @@ -77,7 +77,7 @@ public abstract class AbstractLinkPeer : AbstractPartModule, /// possible to define a group of peer modules which only allow linking of a single module at the /// time. /// - /// + /// /// [KSPField] [Debug.KASDebugAdjustable("Dependent nodes")] @@ -93,21 +93,21 @@ public abstract class AbstractLinkPeer : AbstractPartModule, #region Persistent fields /// The link state in the last save action. /// Normally, the base class handles it. - /// + /// /// [KSPField(isPersistant = true)] public LinkState persistedLinkState = LinkState.Available; /// The other peer's part flight ID in the last save action. /// It's 0 if the peer is not linked. - /// + /// /// [KSPField(isPersistant = true)] public uint persistedLinkPartId; /// The other peer's module attach node name. /// It's null if the peer is not linked. - /// + /// /// /// [KSPField(isPersistant = true)] diff --git a/Source/modules/AbstractPipeRenderer.cs b/Source/modules/AbstractPipeRenderer.cs index 93f7f3448..5aeaa4a10 100644 --- a/Source/modules/AbstractPipeRenderer.cs +++ b/Source/modules/AbstractPipeRenderer.cs @@ -23,7 +23,7 @@ public abstract class AbstractPipeRenderer : AbstractProceduralModel, ILinkRenderer { #region Localizable GUI strings - /// + /// public static readonly Message LinkCollidesWithObjectMsg = new Message( "#kasLOC_07000", defaultTemplate: "Link collides with: <<1>>", @@ -31,7 +31,7 @@ public abstract class AbstractPipeRenderer : AbstractProceduralModel, + "\nArgument <<1>> is the part that would collide with the proposed link.", example: "Link collides with: Mk2 Cockpit"); - /// + /// public static readonly Message LinkCollidesWithSurfaceMsg = new Message( "#kasLOC_07001", defaultTemplate: "Link collides with the surface", @@ -74,12 +74,12 @@ public enum PipeTextureRescaleMode { /// /// /// - /// + /// [KSPField] public string rendererName = ""; /// Diameter of the pipe in meters. - /// + /// [KSPField] [Debug.KASDebugAdjustable("Pipe diameter")] public float pipeDiameter = 0.7f; @@ -87,14 +87,14 @@ public enum PipeTextureRescaleMode { /// Main texture to use for the pipe. /// /// - /// + /// [KSPField] [Debug.KASDebugAdjustable("Pipe texture")] public string pipeTexturePath = ""; /// Normals for the main texture. If empty string, then no normals used. /// - /// + /// [KSPField] [Debug.KASDebugAdjustable("Pipe texture NRM")] public string pipeNormalsTexturePath = ""; @@ -108,7 +108,7 @@ public enum PipeTextureRescaleMode { /// /// /// - /// + /// [KSPField] [Debug.KASDebugAdjustable("Texture samples per meter")] public float pipeTextureSamplesPerMeter = 1.0f; @@ -116,7 +116,7 @@ public enum PipeTextureRescaleMode { /// Defines how the texture should cover the pipe. /// /// - /// + /// [KSPField] [Debug.KASDebugAdjustable("Texture rescale mode")] public PipeTextureRescaleMode pipeTextureRescaleMode = PipeTextureRescaleMode.Stretch; @@ -126,7 +126,7 @@ public enum PipeTextureRescaleMode { /// If this setting is false the link mesh won't have colliders. It affects how player can /// select the part in the scene. /// - /// + /// [KSPField] [Debug.KASDebugAdjustable("Physical collider")] public bool pipeColliderIsPhysical; diff --git a/Source/modules/AbstractProceduralModel.cs b/Source/modules/AbstractProceduralModel.cs index a88851033..422b91d95 100644 --- a/Source/modules/AbstractProceduralModel.cs +++ b/Source/modules/AbstractProceduralModel.cs @@ -78,20 +78,20 @@ protected float baseScale { #region Part's config fields /// Shader to use for meshes by default. - /// + /// [KSPField] [Debug.KASDebugAdjustable("Shader name")] public string shaderName = KspPartShaderName; /// Main material color to use for meshes by default. - /// + /// [KSPField] [Debug.KASDebugAdjustable("Material color")] public Color materialColor = Color.white; /// Tells if the normals map should be used as bump specular map. /// The texture must be made in appropriate way to be compatible! - /// + /// /// /// [KSPField] @@ -104,7 +104,7 @@ protected float baseScale { /// value -1.0 means "don't set anything". Whatever is the default value of the shader, it /// will be used. /// - /// + /// [KSPField] [Debug.KASDebugAdjustable("Material shininess")] public float materialShininess = -1f; diff --git a/Source/modules/KASJointCableBase.cs b/Source/modules/KASJointCableBase.cs index 5c7cbb335..3411a3a02 100644 --- a/Source/modules/KASJointCableBase.cs +++ b/Source/modules/KASJointCableBase.cs @@ -26,17 +26,17 @@ public class KASJointCableBase : AbstractJoint, ILinkCableJoint { #region Localizable GUI strings. - /// - /// readonly static Message CableSpringStrengthInfo = new Message( + /// + /// "#kasLOC_09000", defaultTemplate: "Spring force: <<1>>", description: "Info string in the editor for the cable spring force setting." + "\nArgument <<1>> is the force of type ForceType.", example: "Spring force: 1.2 kN"); - /// readonly static Message ModuleTitle = new Message( + /// "#kasLOC_09001", defaultTemplate: "KAS Cable", description: "Title of the module to present in the editor details window."); @@ -48,14 +48,14 @@ public class KASJointCableBase : AbstractJoint, /// It's a force per meter of the strected distance to keep the objects distance below the maximum /// distance. The force is measured in kilonewtons. /// - /// + /// [KSPField] [Debug.KASDebugAdjustable("Cable spring force")] public float cableSpringForce; /// Damper force to apply to stop the oscillations. /// The force is measured in kilonewtons. - /// + /// [KSPField] [Debug.KASDebugAdjustable("Cable spring damper")] public float cableSpringDamper = 1f; diff --git a/Source/modules/KASJointTowBar.cs b/Source/modules/KASJointTowBar.cs index 0716c21c9..8d9885175 100644 --- a/Source/modules/KASJointTowBar.cs +++ b/Source/modules/KASJointTowBar.cs @@ -30,7 +30,7 @@ public sealed class KASJointTowBar : KASJointTwoEndsSphere, IHasContextMenu { #region Localizable strings - /// + /// static readonly Message LockingStatusMsg = new Message( "#kasLOC_05000", defaultTemplate: "Tow bar is locking: diff <<1>>", @@ -39,7 +39,7 @@ public sealed class KASJointTowBar : KASJointTwoEndsSphere, + " The <<1>> argument shows the current locking error and is formatted as an angle type.", example: "Tow bar is locking: diff 1.5°"); - /// + /// static readonly Message LockedStatusMsg = new Message( "#kasLOC_05001", defaultTemplate: "Tow bar is LOCKED!", @@ -47,36 +47,36 @@ public sealed class KASJointTowBar : KASJointTwoEndsSphere, + " locking."); #region SteeringStatus enum values - /// static readonly Message SteeringStatusMsg_Disabled = new Message( + /// "#kasLOC_05002", defaultTemplate: "Disabled", description: "A string in the context menu that tells that the active steering mode is not" + " enabled."); - /// static readonly Message SteeringStatusMsg_Active = new Message( + /// "#kasLOC_05003", defaultTemplate: "Active", description: "A string in the context menu that tells that the active steering mode is ready" + " and working."); - /// static readonly Message SteeringStatusMsg_CurrentVesselIsTarget = new Message( + /// "#kasLOC_05004", defaultTemplate: "Target is active vessel", description: "A string in the context menu that tells that the active steering mode cannot" + " work due to the bar's target vessel is currently under player's control."); - /// static readonly Message SteeringStatusMsg_TargetIsNotControllable = new Message( + /// "#kasLOC_05005", defaultTemplate: "Target is uncontrollable", description: "A string in the context menu that tells that the active steering mode cannot" + " work due to the linked vessel is remotely controlled."); - /// static readonly Message SteeringStatusMsg_NotLocked = new Message( + /// "#kasLOC_05006", defaultTemplate: "Not locked", description: "A string in the context menu that tells that the active steering mode is" @@ -94,20 +94,20 @@ public sealed class KASJointTowBar : KASJointTwoEndsSphere, }); #region LockMode enum values - /// static readonly Message LockStatusMsg_Disabled = new Message( + /// "#kasLOC_05007", defaultTemplate: "Disabled", description: "A string in the context menu that tells that the bar joints are unlocked."); - /// static readonly Message LockStatusMsg_Locked = new Message( + /// "#kasLOC_05008", defaultTemplate: "Locked", description: "A string in the context menu that tells that the bar joints are locked."); - /// static readonly Message LockStatusMsg_Locking = new Message( + /// "#kasLOC_05009", defaultTemplate: "Locking", description: "A string in the context menu that tells that the bar joints are unlocked but" @@ -137,7 +137,7 @@ public sealed class KASJointTowBar : KASJointTwoEndsSphere, /// general, this setting defines the maximum comfort speed of towing: the lower values are good /// for the higher speed towing. /// - /// + /// [KSPField] [Debug.KASDebugAdjustable("Max steering angle")] public float maxSteeringAngle = 1.0f; // We don't want it be zero. @@ -158,19 +158,19 @@ public sealed class KASJointTowBar : KASJointTwoEndsSphere, /// If the mode is enabled it doesn't mean it's active. There are the conditions that affect when /// the mode can actually start affecting the target vessel. /// - /// + /// [KSPField(isPersistant = true)] public bool persistedActiveSteeringEnabled; /// Current locking mode of the tow bar. - /// + /// [KSPField(isPersistant = true)] public LockMode persistedLockingMode = LockMode.Disabled; #endregion #region The context menu fields /// Status field to display current lock state. - /// + /// [KSPField] [LocalizableItem( tag = "#kasLOC_05010", @@ -179,7 +179,7 @@ public sealed class KASJointTowBar : KASJointTwoEndsSphere, public string lockStatus = ""; /// Status field to display current steering status. - /// + /// [KSPField] [LocalizableItem( tag = "#kasLOC_05011", @@ -188,7 +188,7 @@ public sealed class KASJointTowBar : KASJointTwoEndsSphere, public string steeringStatus = ""; /// Defines responsiveness of the towed vessel to the steering. - /// + /// [KSPField(guiFormat = "0.0", isPersistant = true), UI_FloatRange(controlEnabled = true, scene = UI_Scene.All, stepIncrement = 0.01f, maxValue = 2f, minValue = 0.1f)] @@ -200,7 +200,7 @@ public sealed class KASJointTowBar : KASJointTwoEndsSphere, public float steeringSensitivity = 1.0f; /// Inverts steering angle calculated in active steering mode. - /// + /// [KSPField(isPersistant = true)] [UI_Toggle(scene = UI_Scene.All)] [LocalizableItem( diff --git a/Source/modules/KASJointTwoEndsSphere.cs b/Source/modules/KASJointTwoEndsSphere.cs index 264e10af0..1004d4a6b 100644 --- a/Source/modules/KASJointTwoEndsSphere.cs +++ b/Source/modules/KASJointTwoEndsSphere.cs @@ -29,13 +29,13 @@ public class KASJointTwoEndsSphere : AbstractJoint, #region Part's config fields /// Spring force of the prismatic joint that limits the distance. - /// + /// [KSPField] [Debug.KASDebugAdjustable("Strut spring force")] public float strutSpringForce = Mathf.Infinity; /// Damper force of the spring that limits the distance. - /// + /// [KSPField] [Debug.KASDebugAdjustable("Strut damper ratio")] public float strutSpringDamperRatio = 0.1f; // 10% of the force. diff --git a/Source/modules/KASLinkResourceConnector.cs b/Source/modules/KASLinkResourceConnector.cs index 18b307e54..4861635ff 100644 --- a/Source/modules/KASLinkResourceConnector.cs +++ b/Source/modules/KASLinkResourceConnector.cs @@ -25,14 +25,14 @@ public sealed class KASLinkResourceConnector : KASLinkSourcePhysical, IHasGUI { #region Localizable GUI strings. - /// + /// static readonly Message WindowTitleTxt = new Message( "#kasLOC_12000", defaultTemplate: "Resource Transfer", description: "The title of the resource transfer dialog."); - /// static readonly Message resourceName = new Message( + /// "#kasLOC_12001", defaultTemplate: "<<1>>", description: "The resource in the transfer options table. Its main purpose is dealing" @@ -40,8 +40,8 @@ public sealed class KASLinkResourceConnector : KASLinkSourcePhysical, + "\nArgument <<1>> is the full localized resource name with the Lingoona modifiers" + " (if any)."); - /// static readonly Message compoundResourceName = + /// new Message( "#kasLOC_12002", defaultTemplate: "<<1>> <<2>>", @@ -52,8 +52,8 @@ public sealed class KASLinkResourceConnector : KASLinkSourcePhysical, + "modifiers (if any).", example: "45 % Ox"); - /// static readonly Message resourceAmounts = + /// new Message( "#kasLOC_12003", defaultTemplate: "<<1>> / <<2>>", @@ -64,20 +64,20 @@ public sealed class KASLinkResourceConnector : KASLinkSourcePhysical, + "\nArgument <<1>> is the maximum amount (capacity) of type CompactNumberType.", example: "2.56 / 1,234"); - /// + /// static readonly Message TransferSpeedTxt = new Message( "#kasLOC_12004", defaultTemplate: "Current transfer speed: <<1>> units per second", description: "The information string that tells what is the selected or calculated tarnsfer" + " speed is."); - /// + /// static readonly Message CloseDialogBtn = new Message( "#kasLOC_12005", defaultTemplate: "Close dialog", description: "The caption on the button that closes the trsnafer dialog."); - /// + /// static readonly Message OwnerVesselTxt = new Message( "#kasLOC_12006", defaultTemplate: "Owner (left): <<1>>", @@ -85,7 +85,7 @@ public sealed class KASLinkResourceConnector : KASLinkSourcePhysical, + " are displayed on the left side of the dialog." + "\nArgument <<1>> is the name of the owner vessel."); - /// + /// static readonly Message ConnectedVesselTxt = new Message( "#kasLOC_12007", defaultTemplate: "Connected (right): <<1>>", @@ -93,50 +93,50 @@ public sealed class KASLinkResourceConnector : KASLinkSourcePhysical, + " Its stats are displayed on the right side of the dialog." + "\nArgument <<1>> is the name of the connected vessel."); - /// + /// static readonly Message MixtureHint = new Message( "#kasLOC_12008", defaultTemplate: "A mixture of components: <<1>>", description: "The hint to explain the mixture of the fuel components to transfer." + "\nArgument <<1>> is the comma-separated list of the component names."); - /// + /// static readonly Message AutoScaleToggleTxt = new Message( "#kasLOC_12009", defaultTemplate: "Auto scale transfer speed", description: "The caption for the control that enables the mode, which automatically deducts" + " the speed of the reasource transfer."); - /// + /// static readonly Message AutoScaleToggleHint = new Message( "#kasLOC_12010", defaultTemplate: "The speed will be set so that the transfer is complete in <<1>> seconds", description: "The GUI hint that explains what will happen if the auto-speed options is" + " chosen."); - /// static readonly Message LeftToRigthToggleHint = new Message( + /// "#kasLOC_12011", defaultTemplate: "Trigger transfer from the connected vessel to the owner", description: "The hint text to explain the button action that starts transferring the" + " resource from the connected vessel to the owner of the resource transfer part."); - /// static readonly Message LeftToRigthButtonHint = new Message( + /// "#kasLOC_12012", defaultTemplate: "Transfer from the connected vessel to the owner", description: "The hint text to explain the button action that does transferring the" + " resource from the connected vessel to the owner of the resource transfer part. When the" + " button is released, the transfer stops."); - /// + /// static readonly Message RightToLeftToggleHint = new Message( "#kasLOC_12013", defaultTemplate: "Trigger transfer from the owner vessel to the connected vessel", description: "The hint text to explain the button action that starts transferring the" + " resource from the owner of the resources transfer part to the connected vessel."); - /// + /// static readonly Message RightToLeftButtonHint = new Message( "#kasLOC_12014", defaultTemplate: "Transfer from the owner vessel to the connected vessel", @@ -144,7 +144,7 @@ public sealed class KASLinkResourceConnector : KASLinkSourcePhysical, + " resource from the owner of the resource transfer part to the connected vessel. When the" + " button is released, the transfer stops."); - /// + /// static readonly Message NotAvailableInDockedMode = new Message( "#kasLOC_12016", defaultTemplate: "Not available in the docked mode", @@ -154,7 +154,7 @@ public sealed class KASLinkResourceConnector : KASLinkSourcePhysical, #region Part's config fields /// The maximum allowed speed of transferring a resource. - /// + /// [KSPField] [Debug.KASDebugAdjustable("Transfer speed")] public float maxTransferSpeed = 20.0f; @@ -162,7 +162,7 @@ public sealed class KASLinkResourceConnector : KASLinkSourcePhysical, /// /// The duration of the complete transfer when the speed is selected automatically. /// - /// + /// [KSPField] [Debug.KASDebugAdjustable("Auto speed duration threshold")] public float autoSpeedTransferDuration = 4.0f; @@ -171,7 +171,7 @@ public sealed class KASLinkResourceConnector : KASLinkSourcePhysical, /// Pattern to find the model which will be rotating around X-axis when the hose is /// extended/retracted. /// - /// + /// [KSPField] public string rotatingWinchCylinderModel = ""; @@ -179,7 +179,7 @@ public sealed class KASLinkResourceConnector : KASLinkSourcePhysical, /// The total length of the cylinder on the outer radius. It's used to calculate the ratio of how /// significantly the cylinder need to rotate when 1m of hose is extended/retracted. /// - /// + /// [KSPField] [Debug.KASDebugAdjustable("Rotating winch model perimeter")] public float cylinderPerimeterLength = 1.0f; @@ -191,7 +191,7 @@ public sealed class KASLinkResourceConnector : KASLinkSourcePhysical, /// /// is ignored when the allowed resources list is set. /// - /// + /// [PersistentField("allowedResource", isCollection = true, group = StdPersistentGroups.PartConfigLoadGroup)] public List allowedResource = new List(); @@ -221,7 +221,7 @@ public sealed class KASLinkResourceConnector : KASLinkSourcePhysical, /// /// /// - /// + /// [PersistentField("resourceOverride", isCollection = true, group = StdPersistentGroups.PartConfigLoadGroup)] public List resourceOverride = new List(); @@ -257,7 +257,7 @@ public class FuelMixture { #endregion #region Context menu events/actions - /// + /// [KSPEvent(guiActive = true, guiActiveUnfocused = true)] [LocalizableItem( tag = "#kasLOC_12015", diff --git a/Source/modules/KASLinkSourceBase.cs b/Source/modules/KASLinkSourceBase.cs index 03fc4c898..89a172928 100644 --- a/Source/modules/KASLinkSourceBase.cs +++ b/Source/modules/KASLinkSourceBase.cs @@ -41,46 +41,46 @@ public class KASLinkSourceBase : AbstractLinkPeer, IsPartDeathListener, IKSPDevModuleInfo, IHasContextMenu { #region Localizable GUI strings - /// readonly static Message IncompatibleTargetLinkTypeMsg = new Message( + /// "#kasLOC_02000", defaultTemplate: "Incompatible target link type", description: "Message to display when the target link type doesn't match the source type."); - /// readonly static Message SourceIsNotAvailableForLinkMsg = new Message( + /// "#kasLOC_02001", defaultTemplate: "Source is not available for a link", description: "Message to display when a source is refusing to start the link."); - /// readonly static Message TargetDoesntAcceptLinksMsg = new Message( + /// "#kasLOC_02002", defaultTemplate: "Target doesn't accept links", description: "Message to display when the target is refusing to accept the link."); - /// readonly static Message CannotRestoreLinkMsg = new Message( + /// "#kasLOC_02003", defaultTemplate: "Cannot restore link for: <<1>>", description: "Message to display when a linked source and target cannot be matched on load." + "\nArgument <<1>> is a name of the SOURCE part.", example: "Cannot restore link for: KAS.TJ1"); - /// readonly static Message LinksWithSocketTypeInfo = new Message( + /// "#kasLOC_02004", defaultTemplate: "Links with socket type: <<1>>", description: "Info string in the editor for the link type setting." + "\nArgument <<1>> is the type string from the part's config."); - /// readonly static Message ModuleTitleInfo = new Message( + /// "#kasLOC_02005", defaultTemplate: "KAS Joint Source", description: "Title of the module to present in the editor details window."); - /// + /// static readonly Message DockedModeMenuTxt = new Message( "#kasLOC_02006", defaultTemplate: "Link mode: DOCKED", @@ -88,7 +88,7 @@ public class KASLinkSourceBase : AbstractLinkPeer, + " linked parts into two different vessels if they are coupled thru this link. At the same" + " time, the name of the event gives a currently selected state."); - /// + /// static readonly Message UndockedModeMenuTxt = new Message( "#kasLOC_02007", defaultTemplate: "Link mode: UNDOCKED", @@ -145,25 +145,25 @@ public enum CoupleMode { /// /// /// - /// + /// [KSPField] [Debug.KASDebugAdjustable("Renderer name")] public string linkRendererName = ""; /// Name of the joint to use with this source. - /// + /// [KSPField] [Debug.KASDebugAdjustable("Joint name")] public string jointName = ""; /// Audio sample to play when the parts are docked by the player. - /// + /// [KSPField] [Debug.KASDebugAdjustable("Sound - part dock")] public string sndPathDock = ""; /// Audio sample to play when the parts are undocked by the player. - /// + /// [KSPField] [Debug.KASDebugAdjustable("Sound - part undock")] public string sndPathUndock = ""; @@ -174,7 +174,7 @@ public enum CoupleMode { /// support coupling. If they don't, then the coupling will be made without using the attach /// nodes. An error will be logged, and the further behavior of the assembly is undetermined. /// - /// + /// [KSPField] [Debug.KASDebugAdjustable("Coupling mode")] public CoupleMode coupleMode = CoupleMode.NeverCouple; @@ -209,7 +209,7 @@ public enum CoupleMode { #region Context menu events/actions // Keep the events that may change their visibility states at the bottom. When an item goes out // of the menu, its height is reduced, but the lower left corner of the dialog is retained. - /// + /// [KSPEvent(guiActive = true, guiActiveUncommand = true, guiActiveUnfocused = true)] [LocalizableItem(tag = null)] public virtual void ToggleVesselsDockModeEvent() { diff --git a/Source/modules/KASLinkSourceInteractive.cs b/Source/modules/KASLinkSourceInteractive.cs index c0021820d..77ec4b04b 100644 --- a/Source/modules/KASLinkSourceInteractive.cs +++ b/Source/modules/KASLinkSourceInteractive.cs @@ -27,8 +27,8 @@ namespace KAS { public sealed class KASLinkSourceInteractive : KASLinkSourceBase { #region Localizable GUI strings - /// - /// + /// + /// static readonly Message CanBeConnectedMsg = new Message( "#kasLOC_01000", defaultTemplate: "Click to establish a link (length <<1>>)", @@ -37,14 +37,14 @@ public sealed class KASLinkSourceInteractive : KASLinkSourceBase { + "\nArgument <<1>> is the possible link length of type DistanceType.", example: "Click to establish a link (length 1.22 m)"); - /// + /// static readonly Message LinkingInProgressMsg = new Message( "#kasLOC_01001", defaultTemplate: "Select a compatible socket or press ESC", description: "The message to display as a help string when an interactive linking mode has" + " started."); - /// + /// static readonly Message CannotDockMsg = new Message( "#kasLOC_01002", defaultTemplate: "Cannot dock: the mode is not supported", @@ -54,31 +54,31 @@ public sealed class KASLinkSourceInteractive : KASLinkSourceBase { #region Part's config fields /// Audio sample to play when the parts are attached by the player. - /// + /// [KSPField] [Debug.KASDebugAdjustable("Sound - plug")] public string sndPathPlug = ""; /// Audio sample to play when the parts are detached by the player. - /// + /// [KSPField] [Debug.KASDebugAdjustable("Sound - unplug")] public string sndPathUnplug = ""; /// Audio sample to play when the link is broken by the physics events. - /// + /// [KSPField] [Debug.KASDebugAdjustable("Sound - broke")] public string sndPathBroke = ""; /// Name of the menu item to start linking mode. - /// + /// [KSPField] [Debug.KASDebugAdjustable("Start link menu text")] public string startLinkMenu = ""; /// Name of the menu item to break currently established link. - /// + /// [KSPField] [Debug.KASDebugAdjustable("Break link menu text")] public string breakLinkMenu = ""; @@ -86,7 +86,7 @@ public sealed class KASLinkSourceInteractive : KASLinkSourceBase { #region Context menu events/actions /// Event handler. Initiates a link that must be completed by a mouse click. - /// + /// [KSPEvent(guiActiveUnfocused = true)] [LocalizableItem(tag = null)] public void StartLinkContextMenuAction() { @@ -94,7 +94,7 @@ public void StartLinkContextMenuAction() { } /// Event handler. Breaks current link between source and target. - /// + /// [KSPEvent(guiActiveUnfocused = true)] [LocalizableItem(tag = null)] public void BreakLinkContextMenuAction() { diff --git a/Source/modules/KASLinkSourcePhysical.cs b/Source/modules/KASLinkSourcePhysical.cs index dce93e0d8..0df86c65c 100644 --- a/Source/modules/KASLinkSourcePhysical.cs +++ b/Source/modules/KASLinkSourcePhysical.cs @@ -40,33 +40,33 @@ namespace KAS { /// /// /// -/// +/// // Next localization ID: #kasLOC_13011. public class KASLinkSourcePhysical : KASLinkSourceBase { #region Localizable GUI strings. - /// + /// static readonly Message ConnectorStateMsg_Locked = new Message( "#kasLOC_13000", defaultTemplate: "Locked", description: "A string in the context menu that tells that the connector is rigidly attached" + " to the part and is not movable."); - /// + /// static readonly Message ConnectorStateMsg_Deployed = new Message( "#kasLOC_13001", defaultTemplate: "Deployed", description: "A string in the context menu that tells that the connector is deployed and" + " attached to the part via a cable."); - /// + /// static readonly Message ConnectorStateMsg_Plugged = new Message( "#kasLOC_13002", defaultTemplate: "Plugged in", description: "A string in the context menu that tells that the connector is plugged in" + " a socked or is being carried by a kerbal, and attached to the part via a cable."); - /// + /// static readonly Message ConnectorStateMsg_Docked = new Message( "#kasLOC_13003", defaultTemplate: "Docked", @@ -83,14 +83,14 @@ public class KASLinkSourcePhysical : KASLinkSourceBase { {ConnectorState.Docked, ConnectorStateMsg_Docked}, }); - /// + /// static readonly Message CableLinkBrokenMsg = new Message( "#kasLOC_13004", defaultTemplate: "The link between the connector and the part has broke", description: "A message to display when a link between the part and the connector has broke" + " due to the unexpected external forces or actions."); - /// + /// static readonly Message CannotLinkToPreattached = new Message( "#kasLOC_13005", defaultTemplate: "Cannot link with: <<1>>", @@ -106,7 +106,7 @@ public class KASLinkSourcePhysical : KASLinkSourceBase { /// it must not be greater then the total part's mass. Also, try to avoid making the connector /// heavier than the part iteself - the Unity physics may start behaving awkward. /// - /// + /// [KSPField] [Debug.KASDebugAdjustable("Connector mass")] public float connectorMass = 0.01f; @@ -118,37 +118,37 @@ public class KASLinkSourcePhysical : KASLinkSourceBase { public float connectorInteractDistance = 0.3f; /// URL of the sound for the event of returning the connector to the winch. - /// + /// [KSPField] [Debug.KASDebugAdjustable("Sound - lock connector")] public string sndPathLockConnector = ""; /// URL of the sound for the event of docking the connector to the winch. - /// + /// [KSPField] [Debug.KASDebugAdjustable("Sound - dock connector")] public string sndPathDockConnector = ""; /// URL of the sound for the event of acquiring the connector by an EVA kerbal. - /// + /// [KSPField] [Debug.KASDebugAdjustable("Sound - grab connector")] public string sndPathGrabConnector = ""; /// URL of the sound for the event of plugging the connector into a socket. - /// + /// [KSPField] [Debug.KASDebugAdjustable("Sound - plug connector")] public string sndPathPlugConnector = ""; /// URL of the sound for the event of unplugging the connector from a socket. - /// + /// [KSPField] [Debug.KASDebugAdjustable("Sound - unplug connector")] public string sndPathUnplugConnector = ""; /// URL of the sound for the event of cable emergency detachment (link broken). - /// + /// [KSPField] [Debug.KASDebugAdjustable("Sound - link broke")] public string sndPathBroke = ""; @@ -156,7 +156,7 @@ public class KASLinkSourcePhysical : KASLinkSourceBase { /// /// Tells if an incompatible target at the connector's node should be immediately decoupled. /// - /// + /// [KSPField] [Debug.KASDebugAdjustable("Decouple incompatible targets")] public bool decoupleIncompatibleTargets; @@ -164,13 +164,13 @@ public class KASLinkSourcePhysical : KASLinkSourceBase { #region Persistent fields /// Connector state in the last save action. - /// + /// [KSPField(isPersistant = true)] public bool persistedIsConnectorLocked = true; /// Position and rotation of the deployed connector. /// It's relative to the source part. - /// + /// [PersistentField("connectorPosAndRot", group = StdPersistentGroups.PartPersistant)] public PosAndRot persistedConnectorPosAndRot; #endregion @@ -178,7 +178,7 @@ public class KASLinkSourcePhysical : KASLinkSourceBase { #region The context menu fields /// Status field to display the current connector status in the context menu. /// - /// + /// [KSPField(guiActive = true)] [LocalizableItem( tag = "#kasLOC_13006", @@ -191,7 +191,7 @@ public class KASLinkSourcePhysical : KASLinkSourceBase { #region Context menu events/actions /// Context menu to instantly lock the deployed connector. /// It's a hack, but sometimes it's the only way to recover the connector. - /// + /// [KSPEvent(guiActive = true, guiActiveUnfocused = true, advancedTweakable = true)] [LocalizableItem( tag = "#kasLOC_13010", @@ -208,7 +208,7 @@ public virtual void InstantLockConnectorEvent() { // of the menu, its height is reduced, but the lower left corner of the dialog is retained. /// Attaches the connector to the EVA kerbal. /// The active vessel must be a kerbal. - /// + /// [KSPEvent(guiActiveUnfocused = true)] [LocalizableItem( tag = "#kasLOC_13007", @@ -228,7 +228,7 @@ public virtual void GrabConnectorEvent() { /// Detaches the connector from the kerbal and puts it back to the winch. /// The active vessel must be a kerbal holding a connector of this winch. - /// + /// [KSPEvent(guiActiveUnfocused = true)] [LocalizableItem( tag = "#kasLOC_13008", @@ -246,7 +246,7 @@ public virtual void ReturnConnectorEvent() { } /// Context menu item to break the currently established link. - /// + /// [KSPEvent(guiActive = true, guiActiveUnfocused = true)] [LocalizableItem( tag = "#kasLOC_13009", diff --git a/Source/modules/KASLinkTargetBase.cs b/Source/modules/KASLinkTargetBase.cs index 99f4e032f..40a8f9c70 100644 --- a/Source/modules/KASLinkTargetBase.cs +++ b/Source/modules/KASLinkTargetBase.cs @@ -35,14 +35,14 @@ public class KASLinkTargetBase : IsPartDeathListener, IKSPDevModuleInfo { #region Localizable GUI strings - /// + /// static readonly Message AcceptsLinkTypeInfo = new Message( "#kasLOC_03000", defaultTemplate: "Accepts link type: <<1>>", description: "Info string in the editor for the link type setting." + "\nArgument <<1>> is the type string from the part's config."); - /// + /// static readonly Message ModuleTitleInfo = new Message( "#kasLOC_03001", defaultTemplate: "KAS Joint Target", @@ -61,13 +61,13 @@ public virtual ILinkSource linkSource { /// /// Tells if compatible targets should highlight themselves when linking mode started. /// - /// + /// [KSPField] [Debug.KASDebugAdjustable("Highlight parts")] public bool highlightCompatibleTargets = true; /// Defines highlight color for the compatible targets. - /// + /// [KSPField] [Debug.KASDebugAdjustable("Highlight color")] public Color highlightColor = Color.cyan; diff --git a/Source/modules/KASLinkTargetKerbal.cs b/Source/modules/KASLinkTargetKerbal.cs index 232e6d55b..a696d71bf 100644 --- a/Source/modules/KASLinkTargetKerbal.cs +++ b/Source/modules/KASLinkTargetKerbal.cs @@ -26,7 +26,7 @@ public sealed class KASLinkTargetKerbal : KASLinkTargetBase, // KSPDev sugar interafces. IHasGUI { #region Localizable GUI strings. - /// + /// static readonly Message DropConnectorHintMsg= new Message( "#kasLOC_100001", defaultTemplate: "To drop the connector press: [<<1>>]", @@ -34,7 +34,7 @@ public sealed class KASLinkTargetKerbal : KASLinkTargetBase, + "cable connector.\nArgument <<1>> is the current key binding of type KeyboardEventType.", example: "To drop the connector press: [Ctrl+Y]"); - /// + /// static readonly Message PickupConnectorHintMsg= new Message( "#kasLOC_100002", defaultTemplate: "[<<1>>]: Pickup connector", @@ -43,7 +43,7 @@ public sealed class KASLinkTargetKerbal : KASLinkTargetBase, + "KeyboardEventType.", example: "[Y]: Pickup connector"); - /// + /// static readonly Message attachConnectorMenu = new Message( "#kasLOC_10003", defaultTemplate: "Attach connector", @@ -56,13 +56,13 @@ public sealed class KASLinkTargetKerbal : KASLinkTargetBase, /// /// If set to black (0, 0, 0), then the closests connector will not be highlighted. /// - /// + /// [KSPField] [Debug.KASDebugAdjustable("Connectors highlight color")] public Color closestConnectorHighlightColor = Color.cyan; /// Name of the bone within the skinned mesh to bind the attach the node to. - /// + /// [KSPField] [Debug.KASDebugAdjustable("Equip bone name")] public string equipBoneName = ""; @@ -71,7 +71,7 @@ public sealed class KASLinkTargetKerbal : KASLinkTargetBase, /// Position and rotation at the bone to move the to. /// /// The node transform will be dynamically adjusted to the bone movements. - /// + /// [PersistentField("equipPosAndRot", group = StdPersistentGroups.PartConfigLoadGroup)] [Debug.KASDebugAdjustable("Equip pos&rot")] PosAndRot equipPosAndRot = new PosAndRot(); diff --git a/Source/modules/KASLinkWinch.cs b/Source/modules/KASLinkWinch.cs index 6e1ba1578..07da644fc 100644 --- a/Source/modules/KASLinkWinch.cs +++ b/Source/modules/KASLinkWinch.cs @@ -47,35 +47,35 @@ public class KASLinkWinch : KASLinkSourcePhysical, IsPhysicalObject { #region Localizable GUI strings. - /// + /// static readonly Message NoEnergyMsg = new Message( "#kasLOC_08000", defaultTemplate: "No energy!", description: "Error message to present when the electricity charge has exhausted."); - /// + /// static readonly Message LockConnectorNotAlignedMsg = new Message( "#kasLOC_08001", defaultTemplate: "Cannot lock the connector: not aligned", description: "Error message to present when an improperly aligned cable connector has" + " attempted to lock with the winch."); - /// + /// static readonly Message ConnectorLockedMsg = new Message( "#kasLOC_08002", defaultTemplate: "Connector locked!", description: "Info message to present when a cable connector has successfully locked to the" + " winch."); - /// + /// static readonly Message ConnectorDockedMsg = new Message( "#kasLOC_08003", defaultTemplate: "Connector docked to the winch", description: "Info message to present when a cable connector has successfully docked to the" + " winch."); - /// - /// + /// + /// static readonly Message MaxLengthReachedMsg = new Message( "#kasLOC_08004", defaultTemplate: "Maximum cable length reached: <<1>>", @@ -83,38 +83,38 @@ public class KASLinkWinch : KASLinkSourcePhysical, + "\nArgument <<1>> is the current cable length of type DistanceType.", example: "Maximum cable length reached: 1.23 m"); - /// + /// static readonly Message StopExtendingMenuTxt = new Message( "#kasLOC_08005", defaultTemplate: "Stop extending", description: "Name of the context menu item that stops the cable extending."); - /// + /// static readonly Message ExtendCableMenuTxt = new Message( "#kasLOC_08006", defaultTemplate: "Extend cable", description: "Name of the context menu item that starts the cable extending."); - /// + /// static readonly Message StopRetractingMenuTxt = new Message( "#kasLOC_08007", defaultTemplate: "Stop retracting", description: "Name of the context menu item that stops the cable retracting."); - /// + /// static readonly Message RetractCableMenuTxt = new Message( "#kasLOC_08008", defaultTemplate: "Retract cable", description: "Name of the context menu item that starts the cable retracting."); - /// readonly static Message ModuleTitleInfo = new Message( + /// "#kasLOC_08013", defaultTemplate: "KAS Winch", description: "Title of the module to present in the editor details window."); - /// readonly static Message MotorSpeedInfo = new Message( + /// "#kasLOC_08014", defaultTemplate: "Max motor speed: <<1>>", description: "Info string that tells how fast the winch can extend or retract the cable." @@ -130,7 +130,7 @@ public class KASLinkWinch : KASLinkSourcePhysical, /// increase the force at which the connector hits the winch on locking. A too small value of the /// allowed error will make the locking harder, up to not being able to lock at all. /// - /// + /// [KSPField] [Debug.KASDebugAdjustable("Connector lock distance error")] public float connectorLockMaxErrorDist = 0.05f; @@ -144,14 +144,14 @@ public class KASLinkWinch : KASLinkSourcePhysical, /// forward and up vectors of the connector can differ from the winch's attach node /// direction. /// - /// - /// + /// + /// [KSPField] [Debug.KASDebugAdjustable("Connector lock direction error")] public float connectorLockMaxErrorDir = 1; /// Maximum target speed of the motor. Meters per second. - /// + /// [KSPField] [Debug.KASDebugAdjustable("Motor max speed")] public float motorMaxSpeed = 2; @@ -160,32 +160,32 @@ public class KASLinkWinch : KASLinkSourcePhysical, /// Acceleration to apply to reach the target motor speed. Meters per second squared. /// /// It must not be 0, since in this case the motor will never start. - /// + /// [KSPField] [Debug.KASDebugAdjustable("Motor acceleration")] public float motorAcceleration = 0.4f; /// Amount of the electricity to consume each second of the motor activity. - /// + /// [KSPField] [Debug.KASDebugAdjustable("Motor power drain")] public double motorPowerDrain = 0.5f; /// URL of the sound for the working winch motor. /// This sound will be looped while the motor is active. - /// + /// [KSPField] [Debug.KASDebugAdjustable("Sound - motor running")] public string sndPathMotor = ""; /// URL of the sound for the starting winch motor. - /// + /// [KSPField] [Debug.KASDebugAdjustable("Sound - motor started")] public string sndPathMotorStart = ""; /// URL of the sound for the stopping winch motor. - /// + /// [KSPField] [Debug.KASDebugAdjustable("Sound - motor stopped")] public string sndPathMotorStop = ""; @@ -194,7 +194,7 @@ public class KASLinkWinch : KASLinkSourcePhysical, #region The context menu fields /// A context menu item that presents the deployed cable length. /// - /// + /// [KSPField(guiActive = true)] [LocalizableItem( tag = "#kasLOC_08009", @@ -209,7 +209,7 @@ public class KASLinkWinch : KASLinkSourcePhysical, // of the menu, its height is reduced, but the lower left corner of the dialog is retained. /// A context menu item that opens the winches GUI. - /// + /// [KSPEvent(guiActive = true, guiActiveUnfocused = true, guiActiveUncommand = true)] [LocalizableItem( tag = "#kasLOC_08010", @@ -226,7 +226,7 @@ public virtual void OpenGUIEvent() { /// be extended for any reason. /// /// - /// + /// [KSPEvent(guiActive = true, guiActiveUnfocused = true)] [LocalizableItem(tag = null)] public virtual void ToggleExtendCableEvent() { @@ -239,7 +239,7 @@ public virtual void ToggleExtendCableEvent() { /// the connector. It does nothing is the cable cannot be retracted for any reason. /// /// - /// + /// [KSPEvent(guiActive = true, guiActiveUnfocused = true)] [LocalizableItem(tag = null)] public virtual void ToggleRetractCableEvent() { @@ -250,7 +250,7 @@ public virtual void ToggleRetractCableEvent() { /// A context menu item that sets the cable length to the maximum, and unlocks the connector if it /// was locked. /// - /// + /// [KSPEvent(guiActive = true, guiActiveUnfocused = true)] [LocalizableItem( tag = "#kasLOC_08011", @@ -265,7 +265,7 @@ public virtual void ReleaseCableEvent() { /// /// A context menu event that sets the cable length to the current distance to the connector. /// - /// + /// [KSPEvent(guiActive = true, guiActiveUnfocused = true)] [LocalizableItem( tag = "#kasLOC_08012", @@ -277,7 +277,7 @@ public virtual void InstantStretchEvent() { } /// Action that starts the cable extending. - /// + /// [KSPAction(null)] [LocalizableItem( tag = "#kasLOC_08015", @@ -288,7 +288,7 @@ public virtual void ExtendCableAction(KSPActionParam unused) { } /// Action that starts the cable retracting. - /// + /// [KSPAction(null)] [LocalizableItem( tag = "#kasLOC_08016", @@ -299,7 +299,7 @@ public virtual void RetractCableAction(KSPActionParam unused) { } /// Action that stops any motor activity. - /// + /// [KSPAction(null)] [LocalizableItem( tag = "#kasLOC_08017", @@ -312,7 +312,7 @@ public virtual void StopMotorAction(KSPActionParam unused) { /// /// Action that sets the cable length to the maximum, and unlocks the connector if it was locked. /// - /// + /// [KSPAction(null)] [LocalizableItem( tag = "#kasLOC_08018", diff --git a/Source/modules/KASRendererBezierPipe.cs b/Source/modules/KASRendererBezierPipe.cs index 528c823fe..b4f00c048 100644 --- a/Source/modules/KASRendererBezierPipe.cs +++ b/Source/modules/KASRendererBezierPipe.cs @@ -31,7 +31,7 @@ public sealed class KASRendererBezierPipe : KASRendererPipe { /// greater than 0.0. No maximum limit, but keep it reasonable. Rule of thumb is to keep /// it equal to or greater than the pipe's diameter. /// - /// + /// /// [KSPField] [Debug.KASDebugAdjustable("Pipe bend resistance")] @@ -44,7 +44,7 @@ public sealed class KASRendererBezierPipe : KASRendererPipe { /// create exactly this many sections. This setting defines the "baseline" of the renderer /// performance and visual quality. The actual quality settings can affect this value. /// - /// + /// [KSPField] [Debug.KASDebugAdjustable("Pipe mesh sections")] public int pipeMeshSections = 21; @@ -56,7 +56,7 @@ public sealed class KASRendererBezierPipe : KASRendererPipe { /// create exactly this many sections. This setting defines the "baseline" of the renderer /// performance and visual quality. The actual quality settings can affect this value. /// - /// + /// [KSPField] [Debug.KASDebugAdjustable("Pipe shape smoothness")] public int pipeShapeSmoothness = 16; @@ -67,7 +67,7 @@ public sealed class KASRendererBezierPipe : KASRendererPipe { /// distinguishable patterns, like text. For the monotonic textures using of just one sample is /// good enough. /// - /// + /// [KSPField] [Debug.KASDebugAdjustable("Texture wraps")] public int pipeTextureWraps = 2; diff --git a/Source/modules/KASRendererPipe.cs b/Source/modules/KASRendererPipe.cs index 798c8edcb..c5e771116 100644 --- a/Source/modules/KASRendererPipe.cs +++ b/Source/modules/KASRendererPipe.cs @@ -61,8 +61,8 @@ namespace KAS { /// /// /// -/// -/// +/// +/// public class KASRendererPipe : AbstractPipeRenderer, // KPSDev sugar interfaces. IsDestroyable { @@ -76,21 +76,21 @@ public class JointConfig { /// It can be negative to shift the "joint" point in the opposite direction. If prefab model is /// defined, then the offset is counted relative to . /// - /// + /// [PersistentField("sphereOffset")] [Debug.KASDebugAdjustable("Sphere offset")] public float sphereOffset = 0; /// Diameter of the sphere to place at the pipe joint. /// It must be zero or positive. - /// + /// [PersistentField("sphereDiameter")] [Debug.KASDebugAdjustable("Sphere diameter")] public float sphereDiameter = 0; /// Diameter of the pipe that connects the attach node and the pipe joint. /// It must be zero or positive. - /// + /// [PersistentField("armDiameter")] [Debug.KASDebugAdjustable("Arm diameter")] public float armDiameter = 0; @@ -102,21 +102,21 @@ public class JointConfig { /// the same model is needed for the other purposes, add a copy via a MODEL tag in the /// part's config. /// - /// - /// + /// + /// [PersistentField("model")] public string modelPath = ""; /// Position and rotation at which the model will attach to the target part. - /// - /// + /// + /// [PersistentField("modelPartAttachAt")] [Debug.KASDebugAdjustable("Prefab PART attach pos&rot")] public PosAndRot modelPartAttachAt = new PosAndRot(); /// Position and rotation at which the node's model will attach to the pipe. - /// - /// + /// + /// [PersistentField("modelPipeAttachAt")] [Debug.KASDebugAdjustable("Prefab PIPE attach pos&rot")] public PosAndRot modelPipeAttachAt = new PosAndRot(); @@ -128,8 +128,8 @@ public class JointConfig { /// It's the location at the source part. /// If it's null, then the model will be simply hidden on the renderer stop. /// - /// - /// + /// + /// [PersistentField("parkAttachAt")] [Debug.KASDebugAdjustable("Park location pos&rot")] public PosAndRot parkAttachAt; @@ -255,13 +255,13 @@ public void AlignToTransform(Transform target) { #region Part's config settings loaded via ConfigAccessor /// Configuration of the source joint model. - /// + /// [PersistentField("sourceJoint", group = StdPersistentGroups.PartConfigLoadGroup)] [Debug.KASDebugAdjustable("Source joint config")] public JointConfig sourceJointConfig = new JointConfig(); /// Configuration of the target joint model. - /// + /// [PersistentField("targetJoint", group = StdPersistentGroups.PartConfigLoadGroup)] [Debug.KASDebugAdjustable("Target joint config")] public JointConfig targetJointConfig = new JointConfig(); @@ -283,7 +283,7 @@ public void AlignToTransform(Transform target) { /// /// /// - /// + /// protected Renderer pipeMeshRenderer; /// Pipe ending node at the source. diff --git a/Source/modules/KASRendererTelescopicPipe.cs b/Source/modules/KASRendererTelescopicPipe.cs index 5b571d156..9ef530c1d 100644 --- a/Source/modules/KASRendererTelescopicPipe.cs +++ b/Source/modules/KASRendererTelescopicPipe.cs @@ -29,7 +29,7 @@ public sealed class KASRendererTelescopicPipe : AbstractProceduralModel, IHasContextMenu, IHasDebugAdjustables { #region Localizable GUI strings - /// + /// static readonly Message LinkCollidesWithObjectMsg = new Message( "#kasLOC_04000", defaultTemplate: "Link collides with: <<1>>", @@ -37,7 +37,7 @@ public sealed class KASRendererTelescopicPipe : AbstractProceduralModel, + "\nArgument <<1>> is the part that would collide with the proposed link.", example: "Link collides with: Mk2 Cockpit"); - /// + /// static readonly Message LinkCollidesWithSurfaceMsg = new Message( "#kasLOC_04001", defaultTemplate: "Link collides with the surface", @@ -47,12 +47,12 @@ public sealed class KASRendererTelescopicPipe : AbstractProceduralModel, #region Persistent fields /// Orientation of the unlinked strut. - /// + /// [KSPField(isPersistant = true)] public Vector3 persistedParkedOrientation = Vector3.forward; /// Extended length of the unlinked strut. - /// + /// [KSPField(isPersistant = true)] public float persistedParkedLength; // If 0 then minimum link length will be used. #endregion @@ -64,14 +64,14 @@ public sealed class KASRendererTelescopicPipe : AbstractProceduralModel, /// /// /// - /// + /// [KSPField] public string rendererName = ""; /// /// Model for a joint lever at the source part. Two such models are used to form a complete joint. /// - /// + /// [KSPField] [Debug.KASDebugAdjustable("SOURCE lever model")] public string sourceJointModel = "KAS/Models/Joint/model"; @@ -79,7 +79,7 @@ public sealed class KASRendererTelescopicPipe : AbstractProceduralModel, /// /// Model for a joint lever at the target part. Two such models are used to form a complete joint. /// - /// + /// [KSPField] [Debug.KASDebugAdjustable("TARGET lever model")] public string targetJointModel = "KAS/Models/Joint/model"; @@ -89,13 +89,13 @@ public sealed class KASRendererTelescopicPipe : AbstractProceduralModel, /// The piston model will be scaled to the part's model scale. When it's not desirable, use /// to compensate the scale change. /// - /// + /// [KSPField] [Debug.KASDebugAdjustable("PISTON model")] public string pistonModel = "KAS/Models/Piston/model"; /// Number of pistons in the link. - /// + /// [KSPField] [Debug.KASDebugAdjustable("Number of pistons")] public int pistonsCount = 3; @@ -108,7 +108,7 @@ public sealed class KASRendererTelescopicPipe : AbstractProceduralModel, /// NOTE: as of now X and Y scales must be equal. Otherwise pipe model will get broken. /// /// - /// + /// [KSPField] [Debug.KASDebugAdjustable("Piston model scale")] public Vector3 pistonModelScale = Vector3.one; @@ -122,7 +122,7 @@ public sealed class KASRendererTelescopicPipe : AbstractProceduralModel, /// affects the length. Note that if X and Y are not equal you may want to disable /// . /// - /// + /// [KSPField] [Debug.KASDebugAdjustable("Randomize pistons rotation")] public bool pistonModelRandomRotation = true; @@ -141,7 +141,7 @@ public sealed class KASRendererTelescopicPipe : AbstractProceduralModel, /// /// /// - /// + /// [KSPField] [Debug.KASDebugAdjustable("Piston diameter scale delta")] public float pistonDiameterScaleDelta = 0.1f; @@ -158,7 +158,7 @@ public sealed class KASRendererTelescopicPipe : AbstractProceduralModel, /// 2.0, then the actual shift will be 0.04m. /// /// - /// + /// [KSPField] [Debug.KASDebugAdjustable("Piston min shift")] public float pistonMinShift = 0.02f; @@ -177,7 +177,7 @@ public class Orientation { } /// List of the available menu items for the unlinked pipe oriaentation. - /// + /// [PersistentField("parkedOrientation", isCollection = true, group = StdPersistentGroups.PartConfigLoadGroup)] public List parkedOrientations = new List(); From 5766e6e2fbd03fef608394512fdff67745925d22 Mon Sep 17 00:00:00 2001 From: ihsoft Date: Tue, 21 Jul 2020 00:18:04 -0700 Subject: [PATCH 13/46] Minor visibility refactoring --- Source/api_impl/AttachNodesUtilsImpl.cs | 2 +- Source/api_impl/KASAPILauncher.cs | 2 +- Source/compatibility/PatchFilesProcessor.cs | 2 +- Source/controllers/ControllerPartEditorTool.cs | 2 +- Source/controllers/ControllerWinchRemote.cs | 2 +- Source/modules/KASInternalBrokenJointListener.cs | 2 +- Source/modules/KASInternalPhysicalConnector.cs | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Source/api_impl/AttachNodesUtilsImpl.cs b/Source/api_impl/AttachNodesUtilsImpl.cs index 6527602b4..a3f273ddb 100644 --- a/Source/api_impl/AttachNodesUtilsImpl.cs +++ b/Source/api_impl/AttachNodesUtilsImpl.cs @@ -11,7 +11,7 @@ namespace KASImpl { /// Implements KASAPIv2.IAttachNodesUtils. -class AttachNodesUtilsImpl : KASAPIv2.IAttachNodesUtils { +internal class AttachNodesUtilsImpl : KASAPIv2.IAttachNodesUtils { /// public AttachNode CreateNode(Part part, string nodeName, Transform nodeTransform) { ArgumentGuard.NotNull(part, "part"); diff --git a/Source/api_impl/KASAPILauncher.cs b/Source/api_impl/KASAPILauncher.cs index c59c02ccd..0061c356b 100644 --- a/Source/api_impl/KASAPILauncher.cs +++ b/Source/api_impl/KASAPILauncher.cs @@ -9,7 +9,7 @@ namespace KASAPIv2 { [KSPAddon(KSPAddon.Startup.Instantly, true /*once*/)] -sealed class KASAPILauncher : MonoBehaviour { +internal sealed class KASAPILauncher : MonoBehaviour { void Awake() { if (!KASAPI.isLoaded) { KASAPI.JointUtils = new KASImpl.JointUtilsImpl(); diff --git a/Source/compatibility/PatchFilesProcessor.cs b/Source/compatibility/PatchFilesProcessor.cs index 0eb36cfda..bd8181179 100644 --- a/Source/compatibility/PatchFilesProcessor.cs +++ b/Source/compatibility/PatchFilesProcessor.cs @@ -14,7 +14,7 @@ namespace SaveUpgradePipeline.KAS { [UpgradeModule(LoadContext.SFS | LoadContext.Craft, sfsNodeUrl = "GAME/FLIGHTSTATE/VESSEL/PART", craftNodeUrl = "PART")] -sealed class PatchFilesProcessor : UpgradeScript { +internal sealed class PatchFilesProcessor : UpgradeScript { /// Patches per part name. /// The patches are ordered by timestamp. diff --git a/Source/controllers/ControllerPartEditorTool.cs b/Source/controllers/ControllerPartEditorTool.cs index ebd6f2113..08ff6e340 100644 --- a/Source/controllers/ControllerPartEditorTool.cs +++ b/Source/controllers/ControllerPartEditorTool.cs @@ -14,7 +14,7 @@ namespace KAS.Debug { /// [KSPAddon(KSPAddon.Startup.FlightAndEditor, false /*once*/)] [PersistentFieldsDatabase("KAS/settings/KASConfig")] -sealed class ControllerPartEditorTool : MonoBehaviour, +internal sealed class ControllerPartEditorTool : MonoBehaviour, // KSPDev interfaces IHasGUI { diff --git a/Source/controllers/ControllerWinchRemote.cs b/Source/controllers/ControllerWinchRemote.cs index c752b17e3..e95ec4fdb 100644 --- a/Source/controllers/ControllerWinchRemote.cs +++ b/Source/controllers/ControllerWinchRemote.cs @@ -22,7 +22,7 @@ namespace KAS { // Next localization ID: #kasLOC_11028. [KSPAddon(KSPAddon.Startup.Flight, false /*once*/)] [PersistentFieldsDatabase("KAS/settings/KASConfig")] -sealed class ControllerWinchRemote : MonoBehaviour, IHasGUI { +internal sealed class ControllerWinchRemote : MonoBehaviour, IHasGUI { #region Localizable GUI strings. /// static readonly Message WindowTitleTxt = new Message( diff --git a/Source/modules/KASInternalBrokenJointListener.cs b/Source/modules/KASInternalBrokenJointListener.cs index b307c4485..86879b59f 100644 --- a/Source/modules/KASInternalBrokenJointListener.cs +++ b/Source/modules/KASInternalBrokenJointListener.cs @@ -26,7 +26,7 @@ namespace KAS { /// overcome this limitation, an extra game object and this component can be used: /// /// -sealed class KASInternalBrokenJointListener : MonoBehaviour, +internal sealed class KASInternalBrokenJointListener : MonoBehaviour, // KSP syntax sugar interfaces. IJointEventsListener { diff --git a/Source/modules/KASInternalPhysicalConnector.cs b/Source/modules/KASInternalPhysicalConnector.cs index b884ce81f..9d02ae839 100644 --- a/Source/modules/KASInternalPhysicalConnector.cs +++ b/Source/modules/KASInternalPhysicalConnector.cs @@ -23,7 +23,7 @@ namespace KAS { /// /// /// -sealed class KASInternalPhysicalConnector : MonoBehaviour { +internal sealed class KASInternalPhysicalConnector : MonoBehaviour { #region Factory methods (static) /// Promotes the specified object into a physical connector object. /// From bd235043b3d63df0c0894ce53539ab92819541f2 Mon Sep 17 00:00:00 2001 From: ihsoft Date: Tue, 21 Jul 2020 00:30:46 -0700 Subject: [PATCH 14/46] Minor style fix Modifiers order --- Source/modules/AbstractJoint.cs | 22 +++++++++++----------- Source/modules/KASJointCableBase.cs | 4 ++-- Source/modules/KASLinkSourceBase.cs | 12 ++++++------ Source/modules/KASLinkWinch.cs | 4 ++-- 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/Source/modules/AbstractJoint.cs b/Source/modules/AbstractJoint.cs index d632d9075..088604859 100644 --- a/Source/modules/AbstractJoint.cs +++ b/Source/modules/AbstractJoint.cs @@ -42,7 +42,7 @@ public abstract class AbstractJoint : AbstractPartModule, IsPackable, IKSPDevModuleInfo, IKSPActivateOnDecouple { #region Localizable GUI strings - readonly static Message MinLengthLimitReachedMsg = + static readonly Message MinLengthLimitReachedMsg = /// /// new Message( @@ -54,7 +54,7 @@ public abstract class AbstractJoint : AbstractPartModule, + "\nArgument <<2>> is the part's config setting of type DistanceType.", example: "Link is too short: 1.22 m < 2.33 m"); - readonly static Message MaxLengthLimitReachedMsg = + static readonly Message MaxLengthLimitReachedMsg = /// /// new Message( @@ -66,7 +66,7 @@ public abstract class AbstractJoint : AbstractPartModule, + "\nArgument <<2>> is the part's config setting of type DistanceType.", example: "Link is too long: 2.33 m > 1.22 m"); - readonly static Message SourceNodeAngleLimitReachedMsg = + static readonly Message SourceNodeAngleLimitReachedMsg = /// /// new Message( @@ -78,7 +78,7 @@ public abstract class AbstractJoint : AbstractPartModule, + "\nArgument <<2>> is the part's config setting of type AngleType.", example: "Source angle limit reached: 3° > 2.5°"); - readonly static Message TargetNodeAngleLimitReachedMsg = + static readonly Message TargetNodeAngleLimitReachedMsg = /// /// new Message( @@ -90,27 +90,27 @@ public abstract class AbstractJoint : AbstractPartModule, + "\nArgument <<2>> is the part's config setting of type AngleType.", example: "Target angle limit reached: 3° > 2.5°"); - readonly static Message LinkLinearStrengthInfo = new Message( /// /// + static readonly Message LinkLinearStrengthInfo = new Message( "#kasLOC_00004", defaultTemplate: "Link break force: <<1>>", description: "Info string in the editor for the link break force setting. The argument is of" + " type ForceType.", example: "Link break force: 1.2 kN"); - readonly static Message LinkBreakStrengthInfo = new Message( /// /// + static readonly Message LinkBreakStrengthInfo = new Message( "#kasLOC_00005", defaultTemplate: "Link torque force: <<1>>", description: "Info string in the editor for the link break torque setting. The argument is of" + " type ForceType.", example: "Link torque force: 1.2 kN"); - readonly static Message MinimumLinkLengthInfo = /// /// + static readonly Message MinimumLinkLengthInfo = new Message( "#kasLOC_00006", defaultTemplate: "Minimum link length: <<1>>", @@ -118,7 +118,7 @@ public abstract class AbstractJoint : AbstractPartModule, + "\nArgument <<1>> is the part's config setting of type DistanceType.", example: "Minimum link length: 1.22 m"); - readonly static Message MaximumLinkLengthInfo = + static readonly Message MaximumLinkLengthInfo = /// /// new Message( @@ -128,26 +128,26 @@ public abstract class AbstractJoint : AbstractPartModule, + "\nArgument <<1>> is the part's config setting of type DistanceType.", example: "Maximum link length: 1.22 m"); - readonly static Message SourceJointFreedomInfo = new Message( /// /// + static readonly Message SourceJointFreedomInfo = new Message( "#kasLOC_00008", defaultTemplate: "Source angle limit: <<1>>", description: "Info string in the editor for the maximum allowed angle at the source." + "\nArgument <<1>> is the part's config setting of type AngleType.", example: "Source angle limit: 1.2°"); - readonly static Message TargetJointFreedomInfo = new Message( /// /// + static readonly Message TargetJointFreedomInfo = new Message( "#kasLOC_00009", defaultTemplate: "Target angle limit: <<1>>", description: "Info string in the editor for the maximum allowed angle at the target." + "\nArgument <<1>> is the part's config setting of type AngleType.", example: "Target angle limit: 1.2°"); - readonly static Message ModuleTitle = new Message( /// + static readonly Message ModuleTitle = new Message( "#kasLOC_00010", defaultTemplate: "KAS Joint", description: "Title of the module to present in the editor details window."); diff --git a/Source/modules/KASJointCableBase.cs b/Source/modules/KASJointCableBase.cs index 3411a3a02..fbf1070d7 100644 --- a/Source/modules/KASJointCableBase.cs +++ b/Source/modules/KASJointCableBase.cs @@ -26,17 +26,17 @@ public class KASJointCableBase : AbstractJoint, ILinkCableJoint { #region Localizable GUI strings. - readonly static Message CableSpringStrengthInfo = new Message( /// /// + static readonly Message CableSpringStrengthInfo = new Message( "#kasLOC_09000", defaultTemplate: "Spring force: <<1>>", description: "Info string in the editor for the cable spring force setting." + "\nArgument <<1>> is the force of type ForceType.", example: "Spring force: 1.2 kN"); - readonly static Message ModuleTitle = new Message( /// + static readonly Message ModuleTitle = new Message( "#kasLOC_09001", defaultTemplate: "KAS Cable", description: "Title of the module to present in the editor details window."); diff --git a/Source/modules/KASLinkSourceBase.cs b/Source/modules/KASLinkSourceBase.cs index 89a172928..630a193dd 100644 --- a/Source/modules/KASLinkSourceBase.cs +++ b/Source/modules/KASLinkSourceBase.cs @@ -41,41 +41,41 @@ public class KASLinkSourceBase : AbstractLinkPeer, IsPartDeathListener, IKSPDevModuleInfo, IHasContextMenu { #region Localizable GUI strings - readonly static Message IncompatibleTargetLinkTypeMsg = new Message( /// + static readonly Message IncompatibleTargetLinkTypeMsg = new Message( "#kasLOC_02000", defaultTemplate: "Incompatible target link type", description: "Message to display when the target link type doesn't match the source type."); - readonly static Message SourceIsNotAvailableForLinkMsg = new Message( /// + static readonly Message SourceIsNotAvailableForLinkMsg = new Message( "#kasLOC_02001", defaultTemplate: "Source is not available for a link", description: "Message to display when a source is refusing to start the link."); - readonly static Message TargetDoesntAcceptLinksMsg = new Message( /// + static readonly Message TargetDoesntAcceptLinksMsg = new Message( "#kasLOC_02002", defaultTemplate: "Target doesn't accept links", description: "Message to display when the target is refusing to accept the link."); - readonly static Message CannotRestoreLinkMsg = new Message( /// + static readonly Message CannotRestoreLinkMsg = new Message( "#kasLOC_02003", defaultTemplate: "Cannot restore link for: <<1>>", description: "Message to display when a linked source and target cannot be matched on load." + "\nArgument <<1>> is a name of the SOURCE part.", example: "Cannot restore link for: KAS.TJ1"); - readonly static Message LinksWithSocketTypeInfo = new Message( /// + static readonly Message LinksWithSocketTypeInfo = new Message( "#kasLOC_02004", defaultTemplate: "Links with socket type: <<1>>", description: "Info string in the editor for the link type setting." + "\nArgument <<1>> is the type string from the part's config."); - readonly static Message ModuleTitleInfo = new Message( /// + static readonly Message ModuleTitleInfo = new Message( "#kasLOC_02005", defaultTemplate: "KAS Joint Source", description: "Title of the module to present in the editor details window."); diff --git a/Source/modules/KASLinkWinch.cs b/Source/modules/KASLinkWinch.cs index 07da644fc..1919fed60 100644 --- a/Source/modules/KASLinkWinch.cs +++ b/Source/modules/KASLinkWinch.cs @@ -107,14 +107,14 @@ public class KASLinkWinch : KASLinkSourcePhysical, defaultTemplate: "Retract cable", description: "Name of the context menu item that starts the cable retracting."); - readonly static Message ModuleTitleInfo = new Message( /// + static readonly Message ModuleTitleInfo = new Message( "#kasLOC_08013", defaultTemplate: "KAS Winch", description: "Title of the module to present in the editor details window."); - readonly static Message MotorSpeedInfo = new Message( /// + static readonly Message MotorSpeedInfo = new Message( "#kasLOC_08014", defaultTemplate: "Max motor speed: <<1>>", description: "Info string that tells how fast the winch can extend or retract the cable." From b4cdefe1960067f109a51fada8b74a2460c6f66d Mon Sep 17 00:00:00 2001 From: ihsoft Date: Tue, 21 Jul 2020 00:47:51 -0700 Subject: [PATCH 15/46] Fix typos in strings --- Source/api_impl/JointUtilsImpl.cs | 2 +- Source/compatibility/PatchFilesProcessor.cs | 2 +- Source/controllers/ControllerWinchRemote.cs | 10 +++++----- Source/debug/KASDebugAdjustableAttribute.cs | 2 +- Source/modules/AbstractJoint.cs | 8 ++++---- Source/modules/AbstractLinkPeer.cs | 14 ++++++------- Source/modules/AbstractPipeRenderer.cs | 18 ++++++++--------- Source/modules/AbstractProceduralModel.cs | 12 +++++------ .../modules/KASInternalPhysicalConnector.cs | 10 +++++----- Source/modules/KASJointCableBase.cs | 2 +- Source/modules/KASJointRigid.cs | 2 +- Source/modules/KASJointTowBar.cs | 12 +++++------ Source/modules/KASJointTwoEndsSphere.cs | 2 +- Source/modules/KASLinkResourceConnector.cs | 14 ++++++------- Source/modules/KASLinkSourceBase.cs | 14 ++++++------- Source/modules/KASLinkSourceInteractive.cs | 2 +- Source/modules/KASLinkSourcePhysical.cs | 18 ++++++++--------- Source/modules/KASLinkTargetBase.cs | 6 +++--- Source/modules/KASLinkTargetKerbal.cs | 10 +++++----- Source/modules/KASLinkWinch.cs | 8 ++++---- Source/modules/KASRendererBezierPipe.cs | 16 +++++++-------- Source/modules/KASRendererPipe.cs | 12 +++++------ Source/modules/KASRendererTelescopicPipe.cs | 20 +++++++++---------- 23 files changed, 108 insertions(+), 108 deletions(-) diff --git a/Source/api_impl/JointUtilsImpl.cs b/Source/api_impl/JointUtilsImpl.cs index 5bb5e50dd..4802a027e 100644 --- a/Source/api_impl/JointUtilsImpl.cs +++ b/Source/api_impl/JointUtilsImpl.cs @@ -234,7 +234,7 @@ static string Dump(SoftJointLimitSpring limitSpring) { } static string Dump(SoftJointLimit limit) { - return string.Format("SoftJointLimit(limit={0}, boinciness={1}, contactDistance={2})", + return string.Format("SoftJointLimit(limit={0}, bounciness={1}, contactDistance={2})", limit.limit, limit.bounciness, limit.contactDistance); } diff --git a/Source/compatibility/PatchFilesProcessor.cs b/Source/compatibility/PatchFilesProcessor.cs index bd8181179..1567f83d3 100644 --- a/Source/compatibility/PatchFilesProcessor.cs +++ b/Source/compatibility/PatchFilesProcessor.cs @@ -68,7 +68,7 @@ public override void OnUpgrade(ConfigNode node, LoadContext loadContext, ConfigN } foreach (var badPatch in badPatches) { applyPatches.Remove(badPatch); - DebugEx.Error("Patch has't fixed the part, disabling it: {0}", badPatch); + DebugEx.Error("Patch hasn't fixed the part, disabling it: {0}", badPatch); } } diff --git a/Source/controllers/ControllerWinchRemote.cs b/Source/controllers/ControllerWinchRemote.cs index e95ec4fdb..470ee9728 100644 --- a/Source/controllers/ControllerWinchRemote.cs +++ b/Source/controllers/ControllerWinchRemote.cs @@ -48,7 +48,7 @@ internal sealed class ControllerWinchRemote : MonoBehaviour, IHasGUI { static readonly Message StretchBtn = new Message( "#kasLOC_11003", defaultTemplate: "Stretch", - description: "The caption of the button that stretches teeh cable."); + description: "The caption of the button that stretches the cable."); /// static readonly Message StretchBtnHint = new Message( @@ -60,7 +60,7 @@ internal sealed class ControllerWinchRemote : MonoBehaviour, IHasGUI { static readonly Message DetachBtn = new Message( "#kasLOC_11005", defaultTemplate: "Detach", - description: "The caption of the button that deatches the cable from the target."); + description: "The caption of the button that detaches the cable from the target."); /// static readonly Message DetachBtnHint = new Message( @@ -179,7 +179,7 @@ internal sealed class ControllerWinchRemote : MonoBehaviour, IHasGUI { static readonly Message MotorSpeedStatusTxtHint = new Message( "#kasLOC_11023", defaultTemplate: "Current motor speed / Motor speed setting", - description: "The GUI hint to show for the area which displays two values: the current motro" + description: "The GUI hint to show for the area which displays two values: the current motor" + " speed and the maximum possible motor speed. The values are presented as a pair, separated" + " by symbol '/'."); @@ -421,7 +421,7 @@ void ConsoleWindowFunc(int windowId) { actionsList: guiActions); } - // Cable lenght/status column. + // Cable length/status column. if (!winch.part.vessel.IsControllable) { guiWinchTable.AddTextColumn( winchModeOfflineCnt, guiNoWrapCenteredStyle, minWidth: winchCableStatusMinWidth); @@ -597,7 +597,7 @@ void MaybeUpdateModules() { } /// - /// Forces an update of the list of the cached wiches. It's an expensive operation. + /// Forces an update of the list of the cached winches. It's an expensive operation. /// void OnVesselUpdated(Vessel v) { modulesNeedUpdate = true; diff --git a/Source/debug/KASDebugAdjustableAttribute.cs b/Source/debug/KASDebugAdjustableAttribute.cs index 58433d9b7..ada22a932 100644 --- a/Source/debug/KASDebugAdjustableAttribute.cs +++ b/Source/debug/KASDebugAdjustableAttribute.cs @@ -17,7 +17,7 @@ public class KASDebugAdjustableAttribute : DebugAdjustableAttribute { public const string DebugGroup = "KAS"; /// Creates an attribute that marks a KAS tweakable member. - /// The user freindly string to present in GUI. + /// The user friendly string to present in GUI. public KASDebugAdjustableAttribute(string caption) : base(caption, DebugGroup) { } } diff --git a/Source/modules/AbstractJoint.cs b/Source/modules/AbstractJoint.cs index 088604859..969ca26d8 100644 --- a/Source/modules/AbstractJoint.cs +++ b/Source/modules/AbstractJoint.cs @@ -174,7 +174,7 @@ public abstract class AbstractJoint : AbstractPartModule, [Debug.KASDebugAdjustable("Break force")] public float linkBreakForce; - /// Breaking torque for the sttrut connecting the two parts. + /// Breaking torque for the strut connecting the two parts. /// /// Force is in kilonewtons. If 0, then the joint strength is infinite. /// @@ -395,13 +395,13 @@ public override void OnDebugAdjustablesUpdated() { } 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.", + + "\n\nNot refreshing 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"); + this, "No link established, only update the module settings"); } } #endregion @@ -934,7 +934,7 @@ static DockedVesselInfo GetVesselInfo(Vessel v) { /// /// The source and target parts need to be separated, but the logical link still need to exist. /// On restore the vessel info will be cleared on the module. Alas, when the link is broken - /// extrenally, the root vessel part cannot be properly restored. + /// externally, the root vessel part cannot be properly restored. /// void RestorePartialVesselInfo(ILinkSource source, ILinkTarget target, bool weDecouple) { AsyncCall.CallOnEndOfFrame(this, () => { diff --git a/Source/modules/AbstractLinkPeer.cs b/Source/modules/AbstractLinkPeer.cs index b2378c6ba..2f5e6f0d2 100644 --- a/Source/modules/AbstractLinkPeer.cs +++ b/Source/modules/AbstractLinkPeer.cs @@ -16,7 +16,7 @@ namespace KAS { /// Base class that handles the basic functionality of the link's end. /// /// This module doesn't define how the link is created, but it does the heavy lifting to keep it, -/// once it's established. The descendants are resposible for determining what peers can link with +/// once it's established. The descendants are responsible for determining what peers can link with /// each other. /// public abstract class AbstractLinkPeer : AbstractPartModule, @@ -35,7 +35,7 @@ public abstract class AbstractLinkPeer : AbstractPartModule, public string linkType = ""; /// The localized string to display for the link type. - /// If mising or empty, then the types is show "as-is". + /// If missing or empty, then the types is show "as-is". /// /// [KSPField] @@ -83,7 +83,7 @@ public abstract class AbstractLinkPeer : AbstractPartModule, [Debug.KASDebugAdjustable("Dependent nodes")] public string dependentNodes = ""; - /// Specifies if this peer can couple (dock) into the vessel's hirerachy. + /// Specifies if this peer can couple (dock) into the vessel's hierarchy. /// [KSPField] [Debug.KASDebugAdjustable("Allow coupling")] @@ -192,7 +192,7 @@ public bool isNodeBlocked { #region Inheritable fields & properties /// - /// State machine that controls the source state tranistions and defines the reaction on these + /// State machine that controls the source state transitions and defines the reaction on these /// changes. /// /// @@ -359,7 +359,7 @@ public virtual void OnPartPack() { /// This method is called asynchronously at the end of frame. The triggering of this call doesn't /// mean the node state has changed. It only means that it could have changed, and something has /// either coupled with or decoupled from the node. The code is responsible to verify it and act - /// accordignly. + /// accordingly. /// /// This callback is called regardless to the settings. If the peer, /// being checked, cannot afford coupling, it must break the link. @@ -407,8 +407,8 @@ protected virtual void OnPeerChange(ILinkPeer oldPeer) { /// Finds the other peer of the link. /// - /// The decendants may override this method to react on the link loading. If the link must not be - /// restorted, just reset to null. + /// The descendants may override this method to react on the link loading. If the link must not be + /// restored, just reset to null. /// /// protected virtual void RestoreOtherPeer() { diff --git a/Source/modules/AbstractPipeRenderer.cs b/Source/modules/AbstractPipeRenderer.cs index 5aeaa4a10..d48160685 100644 --- a/Source/modules/AbstractPipeRenderer.cs +++ b/Source/modules/AbstractPipeRenderer.cs @@ -202,9 +202,9 @@ protected Material pipeMaterial { } Material _pipeMaterial; - /// Part that owns the target tarnsform. + /// Part that owns the target transform. /// - /// It can be null if the traget is not a part or the renderer is not started. + /// It can be null if the target is not a part or the renderer is not started. /// /// protected Part targetPart { get; private set; } @@ -300,7 +300,7 @@ public virtual void StopRenderer() { linkUpdateCoroutine = null; } - // Sync the renderers settinsg to the source part to handle the highlights. + // Sync the renderers settings to the source part to handle the highlights. if (isStarted) { sourceTransform.GetComponentsInChildren().ToList() .ForEach(r => r.SetPropertyBlock(part.mpb)); @@ -380,7 +380,7 @@ public string[] CheckColliderHits(Transform source, Transform target) { /// /// All the meshes are expected to belong to either or /// . If it's not the case, then the creator must handle collision - /// ignores and highligher modules. Same applies to the meshes created outside of this method, + /// ignores and highlighter modules. Same applies to the meshes created outside of this method, /// even when they belong to the proper source or target transform. /// /// @@ -414,7 +414,7 @@ public string[] CheckColliderHits(Transform source, Transform target) { protected abstract Vector3[] GetPipePath(Transform start, Transform end); /// Updates the pipe material(s) to the current module's state. - /// It is called when the meterial mutable settings are changed. + /// It is called when the material mutable settings are changed. /// /// protected abstract void UpdateMaterialOverrides(); @@ -441,7 +441,7 @@ public string[] CheckColliderHits(Transform source, Transform target) { #endregion #region Local utility methods - /// Checks if a capsule collider between the points hit's anything. + /// Checks if a capsule collider between the points hits anything. /// Hits with own vessel models or models of the other vessel are ignored. /// The starting point of the link. /// The ending point of the link. @@ -503,7 +503,7 @@ void OnPartCoupleCompleteEvent(GameEvents.FromToAction action) { /// /// This information will be used down the stream to detect if the collisions should be adjusted. /// - /// The part that has dcoupled. + /// The part that has decoupled. void OnPartDeCoupleEvent(Part originator) { if (targetPart != null && targetPart.vessel != vessel && originator.vessel == targetPart.vessel) { @@ -513,7 +513,7 @@ void OnPartDeCoupleEvent(Part originator) { /// Reacts on a part de-coupling and adjusts its colliders as needed. /// - /// When a part is leaving the target vessel, the collsions between this part and the pipe meshes + /// When a part is leaving the target vessel, the collisions between this part and the pipe meshes /// must be restored. /// /// The part that has decoupled. @@ -538,7 +538,7 @@ IEnumerator UpdateLinkCoroutine() { UpdateLink(); yield return null; } - // The coroitine is expected to be terminated explicitly! + // The coroutine is expected to be terminated explicitly! HostedDebugLog.Warning(this, "Terminate coroutine on renderer stop!"); } #endregion diff --git a/Source/modules/AbstractProceduralModel.cs b/Source/modules/AbstractProceduralModel.cs index 422b91d95..c7c7d3877 100644 --- a/Source/modules/AbstractProceduralModel.cs +++ b/Source/modules/AbstractProceduralModel.cs @@ -41,7 +41,7 @@ public abstract class AbstractProceduralModel : AbstractPartModule { /// Returns a cached part's model root transform. /// The part's root model. /// - /// Attach all your meshes to this transform (eitehr directly or via parents). Otherwise, the new + /// Attach all your meshes to this transform (either directly or via parents). Otherwise, the new /// meshes will be ignored by the part's model! /// protected Transform partModelTransform { @@ -57,7 +57,7 @@ protected Transform partModelTransform { /// The scale of the part models. /// /// The scale of the part must be "even", i.e. all the components in the scale vector must be - /// equal. If they are not, then the renderer's behavior may be inconsistent. + /// equal. If they are not, then the renderer behavior may be inconsistent. /// /// The scale to be applied to all the components. protected float baseScale { @@ -73,7 +73,7 @@ protected float baseScale { return _baseScale; } } - float _baseScale = -1; // Negative means unintialized. + float _baseScale = -1; // Negative means uninitialized. #endregion #region Part's config fields @@ -175,20 +175,20 @@ protected Shader GetShader(string overrideShaderName = null) { return shader; } - /// Gets the texture from either a KSP gamebase or the internal cache. + /// Gets the texture from either a KSP game base or the internal cache. /// /// It's OK to call this method in the performance demanding code since once the texture is /// successfully returned it's cached internally. The subsequent calls won't issue expensive game /// database requests. /// /// - /// Filename of the texture file. The path is realtive to GameData folder. The name must + /// Filename of the texture file. The path is relative to GameData folder. The name must /// not have the file extension. /// /// If true then the texture will be loaded as a bumpmap. /// /// The color of the simulated texture in case of the asset was not found in the game database. By - /// defaut a red colored texture will be created. + /// default a red colored texture will be created. /// /// /// The texture. Note that it's a shared object. Don't execute actions on it which you don't want diff --git a/Source/modules/KASInternalPhysicalConnector.cs b/Source/modules/KASInternalPhysicalConnector.cs index 9d02ae839..c65dfb5a7 100644 --- a/Source/modules/KASInternalPhysicalConnector.cs +++ b/Source/modules/KASInternalPhysicalConnector.cs @@ -16,7 +16,7 @@ namespace KAS { /// mod. The module must only be created thru the factory method. /// /// -/// The promoted object becomes independent from the creator. When the module is destoyed, its +/// The promoted object becomes independent from the creator. When the module is destroyed, its /// rigidbody gets destroyed as well, and the model returns back to the owner part. The position has /// to be adjusted by the caller. /// @@ -100,14 +100,14 @@ public static bool Demote(GameObject obj, bool cleanupMode) { #endregion #region Public methods - /// Highglights the conenctor model or removes the highlighting. + /// Highlights the connector model or removes the highlighting. /// /// /// When color is set to null, the behavior is "cleanup", i.e. it's OK to call this method /// multiple times and in any object state. /// /// - /// In order for the highglighting to work, the object must have a highlighter component (a KSP + /// In order for the highlighting to work, the object must have a highlighter component (a KSP /// specific component). If one doesn't exist on the object, then it's created. /// /// @@ -191,7 +191,7 @@ void CleanupModule(bool destroyImmediate = true) { } /// - /// Makes the connector object physical and ensures it's not atatched to any parent model. + /// Makes the connector object physical and ensures it's not attached to any parent model. /// /// The vessel which went physical. void OnVesselGoOffRails(Vessel vessel) { @@ -202,7 +202,7 @@ void OnVesselGoOffRails(Vessel vessel) { } /// - /// Freezes the physics on the connector and ensures the model is atatched to the owner. + /// Freezes the physics on the connector and ensures the model is attached to the owner. /// /// The vessel which went kinematic. void OnVesselGoOnRails(Vessel vessel) { diff --git a/Source/modules/KASJointCableBase.cs b/Source/modules/KASJointCableBase.cs index fbf1070d7..1ab1e8231 100644 --- a/Source/modules/KASJointCableBase.cs +++ b/Source/modules/KASJointCableBase.cs @@ -45,7 +45,7 @@ public class KASJointCableBase : AbstractJoint, #region Part's config fields /// Spring force of the cable which connects the two parts. /// - /// It's a force per meter of the strected distance to keep the objects distance below the maximum + /// It's a force per meter of the stretched distance to keep the objects distance below the maximum /// distance. The force is measured in kilonewtons. /// /// diff --git a/Source/modules/KASJointRigid.cs b/Source/modules/KASJointRigid.cs index 3b2776cdd..b2e8cf3f4 100644 --- a/Source/modules/KASJointRigid.cs +++ b/Source/modules/KASJointRigid.cs @@ -34,7 +34,7 @@ void MaybeCreateStockJoint() { } } - /// Creates a stock-alike joint between the unrealted parts. + /// Creates a stock-alike joint between the unrelated parts. /// The physical joints will be controlled by the module. void CreateCustomJoint() { HostedDebugLog.Fine( diff --git a/Source/modules/KASJointTowBar.cs b/Source/modules/KASJointTowBar.cs index 8d9885175..4c60871e0 100644 --- a/Source/modules/KASJointTowBar.cs +++ b/Source/modules/KASJointTowBar.cs @@ -143,10 +143,10 @@ public sealed class KASJointTowBar : KASJointTwoEndsSphere, public float maxSteeringAngle = 1.0f; // We don't want it be zero. /// - /// The maximum angle between the port normal and the link vector to consdier the locking process + /// The maximum angle between the port normal and the link vector to consider the locking process /// is done. /// - /// Once the angle decreases down to this value, the towbar will lock down. + /// Once the angle decreases down to this value, the tow bar will lock down. [KSPField] [Debug.KASDebugAdjustable("Lock angle threshold")] public float lockAngleThreshold = 3f; @@ -225,7 +225,7 @@ public sealed class KASJointTowBar : KASJointTwoEndsSphere, #region Internal properties /// Current locking mode. - /// It's declared public only to make the KSP peristense working. + /// It's declared public only to make the KSP persistence working. public enum LockMode { /// Not requested. Disabled, @@ -250,7 +250,7 @@ enum SteeringStatus { } /// - /// Minumal angle between port normal and the link vector to continue apply steering commands. + /// Minimal angle between port normal and the link vector to continue apply steering commands. /// /// The angles below this value don't affect the towed vessel. const float ZeroSteeringAngle = 0.05f; @@ -348,8 +348,8 @@ public void FixedUpdate() { if (persistedLockingMode == LockMode.Locking) { var yaw = GetTargetYawAngle(); var absYaw = Mathf.Abs(yaw); - // Reaching zero is too hard to achieve, so wait for a minimum ange and simply lock. - // It will trigger sime jitter and momentum, though. + // Reaching zero is too hard to achieve, so wait for a minimum angle and simply lock. + // It will trigger some jitter and momentum, though. if (absYaw < lockAngleThreshold) { SetLockingMode(LockMode.Locked); } else { diff --git a/Source/modules/KASJointTwoEndsSphere.cs b/Source/modules/KASJointTwoEndsSphere.cs index 1004d4a6b..2e095daf7 100644 --- a/Source/modules/KASJointTwoEndsSphere.cs +++ b/Source/modules/KASJointTwoEndsSphere.cs @@ -57,7 +57,7 @@ public class KASJointTwoEndsSphere : AbstractJoint, /// Object that connects two sphere joints together. /// /// Both the and the are bound to this object's - /// rigidbody. To minimize the physical effect of this artifical RB, its mass is set to the bare + /// rigidbody. To minimize the physical effect of this artificial RB, its mass is set to the bare /// minimum, which is 0.001t. /// /// The game object. diff --git a/Source/modules/KASLinkResourceConnector.cs b/Source/modules/KASLinkResourceConnector.cs index 4861635ff..1cf4bb0ba 100644 --- a/Source/modules/KASLinkResourceConnector.cs +++ b/Source/modules/KASLinkResourceConnector.cs @@ -16,7 +16,7 @@ namespace KAS { -/// Module which trasnfer resources between two linked vessels. +/// Module which transfer resources between two linked vessels. /// // Next localization ID: #kasLOC_12017 [PersistentFieldsDatabase("KAS/settings/KASConfig")] @@ -68,14 +68,14 @@ public sealed class KASLinkResourceConnector : KASLinkSourcePhysical, static readonly Message TransferSpeedTxt = new Message( "#kasLOC_12004", defaultTemplate: "Current transfer speed: <<1>> units per second", - description: "The information string that tells what is the selected or calculated tarnsfer" + description: "The information string that tells what is the selected or calculated transfer" + " speed is."); /// static readonly Message CloseDialogBtn = new Message( "#kasLOC_12005", defaultTemplate: "Close dialog", - description: "The caption on the button that closes the trsnafer dialog."); + description: "The caption on the button that closes the transfer dialog."); /// static readonly Message OwnerVesselTxt = new Message( @@ -105,7 +105,7 @@ public sealed class KASLinkResourceConnector : KASLinkSourcePhysical, "#kasLOC_12009", defaultTemplate: "Auto scale transfer speed", description: "The caption for the control that enables the mode, which automatically deducts" - + " the speed of the reasource transfer."); + + " the speed of the resource transfer."); /// static readonly Message AutoScaleToggleHint = new Message( @@ -216,7 +216,7 @@ public sealed class KASLinkResourceConnector : KASLinkSourcePhysical, /// /// /// The simplest example is ElectricCharge resource, which is not material (no volume). - /// To allow it on the part, add a positive override: +ElectricCharge. Similary, to + /// To allow it on the part, add a positive override: +ElectricCharge. Similarly, to /// disallow a resource, add a negative override: -LiquidFuel. /// /// @@ -242,7 +242,7 @@ public class FuelMixtureComponent { /// Container for the fuel mixture. public class FuelMixture { - /// The mixuture components. + /// The mixture components. [PersistentField("component", isCollection = true)] public List components = new List(); } @@ -321,7 +321,7 @@ public void OpenGUIEvent() { /// Last time the resources counts were updated in GUI. float lastResourcesGUIUpdate; - /// The timeout to update the resoucres countes in GUI in seconds. + /// The timeout to update the resources counters in GUI in seconds. /// It's a performance affecting settings. const float TRANSFER_STATE_UPDATE_PERIOD = 0.1f; #endregion diff --git a/Source/modules/KASLinkSourceBase.cs b/Source/modules/KASLinkSourceBase.cs index 630a193dd..04fed1bd0 100644 --- a/Source/modules/KASLinkSourceBase.cs +++ b/Source/modules/KASLinkSourceBase.cs @@ -84,7 +84,7 @@ public class KASLinkSourceBase : AbstractLinkPeer, static readonly Message DockedModeMenuTxt = new Message( "#kasLOC_02006", defaultTemplate: "Link mode: DOCKED", - description: "The name of the part's context menu event that triggers a separtation of the" + description: "The name of the part's context menu event that triggers a separation of the" + " linked parts into two different vessels if they are coupled thru this link. At the same" + " time, the name of the event gives a currently selected state."); @@ -266,7 +266,7 @@ public override void OnInitialize() { if (isLinked && linkTarget.part.vessel != vessel) { // When the target is at the different vessel, there is no automatic collision ignore set. AsyncCall.CallOnFixedUpdate(this, () => { - // Copied from KervalEVA.OnVesselGoOffRails() method. + // Copied from KerbalEVA.OnVesselGoOffRails() method. // There must be a delay for at least 3 fixed frames. if (isLinked) { // Link may get broken during the physics easyment. CollisionManager.IgnoreCollidersOnVessel( @@ -372,7 +372,7 @@ protected override void CheckCoupleNode() { && t.coupleNode != null && t.coupleNode.attachedPart == part && CheckCanLinkTo(t)); if (target != null) { - HostedDebugLog.Fine(this, "Linking with the preattached part: {0}", target); + HostedDebugLog.Fine(this, "Linking with the pre-attached part: {0}", target); LinkToTarget(LinkActorType.API, target); } if (!isLinked) { @@ -381,7 +381,7 @@ protected override void CheckCoupleNode() { coupleNode.attachedPart); AsyncCall.CallOnEndOfFrame(this, () => { if (linkState == LinkState.Available && coupleNode.attachedPart != null) { - HostedDebugLog.Warning(this, "Cannot link to the preattached part: from={0}, to={1}", + HostedDebugLog.Warning(this, "Cannot link to the pre-attached part: from={0}, to={1}", KASAPI.AttachNodesUtils.NodeId(coupleNode), KASAPI.AttachNodesUtils.NodeId(coupleNode.FindOpposingNode())); SetLinkState(LinkState.NodeIsBlocked); @@ -642,12 +642,12 @@ protected virtual void LogicalLink(ILinkTarget target) { } /// - /// Logically unlinks the source and the current target, and stops the renderer. + /// Logically un-links the source and the current target, and stops the renderer. /// /// It's always called after the physical link updates. - /// The actor which has intiated the unlinking. + /// The actor which has initiated the un-linking. protected virtual void LogicalUnlink(LinkActorType actorType) { - HostedDebugLog.Info(this, "Unlinking from target: {0}, actor={1}", linkTarget, actorType); + HostedDebugLog.Info(this, "Un-linking from target: {0}, actor={1}", linkTarget, actorType); linkActor = actorType; var linkInfo = new KasLinkEventImpl(this, linkTarget, actorType); linkRenderer.StopRenderer(); diff --git a/Source/modules/KASLinkSourceInteractive.cs b/Source/modules/KASLinkSourceInteractive.cs index 77ec4b04b..f359ac002 100644 --- a/Source/modules/KASLinkSourceInteractive.cs +++ b/Source/modules/KASLinkSourceInteractive.cs @@ -112,7 +112,7 @@ public void BreakLinkContextMenuAction() { /// The lock name that restricts anything but the camera positioning. const string TotalControlLock = "KASInteractiveJointUberLock"; - /// Shader that reders the pipe during linking. + /// Shader that renders the pipe during linking. const string InteractiveShaderName = "Transparent/Diffuse"; /// The compatible target under the mouse cursor. diff --git a/Source/modules/KASLinkSourcePhysical.cs b/Source/modules/KASLinkSourcePhysical.cs index 0df86c65c..1b9d2bfe0 100644 --- a/Source/modules/KASLinkSourcePhysical.cs +++ b/Source/modules/KASLinkSourcePhysical.cs @@ -25,8 +25,8 @@ namespace KAS { /// In this concept there is a "connector", a physical object that is connected to the source part /// via a cable. An EVA kerbal can pick it up and carry to the target part. Then, the connector /// can be plugged into the compatible socked, and this will make the link. The EVA kerbal can also -/// unplug the plugged connectors, breaking the link. The connector unplug function is also availabe -/// to the unmanned vessels, but they must be fully controllable. +/// unplug the plugged connectors, breaking the link. The connector unplug function is also +/// available to the unmanned vessels, but they must be fully controllable. /// /// /// This module doesn't tolerate an incompatible target at its connector node. If there is one @@ -102,9 +102,9 @@ public class KASLinkSourcePhysical : KASLinkSourceBase { #region Part's config fields /// Mass of the connector of the winch. /// - /// It's substracted from the part's mass on deploy, and added back on the lock. For this reason + /// It's subtracted from the part's mass on deploy, and added back on the lock. For this reason /// it must not be greater then the total part's mass. Also, try to avoid making the connector - /// heavier than the part iteself - the Unity physics may start behaving awkward. + /// heavier than the part itself - the Unity physics may start behaving awkward. /// /// [KSPField] @@ -270,7 +270,7 @@ protected enum ConnectorState { /// /// The connector is non-physical and is merged to the owner part's model. There is a part - /// attached to it, which is meregd (docked) to the parent vessel. + /// attached to it, which is merged (docked) to the parent vessel. /// /// This state can only exist if the link source is linked to a target. Docked, @@ -486,7 +486,7 @@ public override void OnPartDie() { base.OnPartDie(); // Make sure the connector is locked into the winch to not leave it behind. if (connectorObj != null) { - // Don't relay on the connector state machine, it will try to destory immediately. + // Don't relay on the connector state machine, it will try to destroy immediately. KASInternalPhysicalConnector.Demote(connectorObj.gameObject, true); } SetConnectorState(ConnectorState.Locked); @@ -684,7 +684,7 @@ public override void UpdateContextMenu() { #region Inheritable utility methods /// Changes the connector state /// - /// It's a convinience method. The caller can change the state of the connector state machine + /// It's a convenience method. The caller can change the state of the connector state machine /// instead. /// /// The new state. @@ -714,7 +714,7 @@ protected Transform GetConnectorModel() { return linkRenderer.GetMeshByName(KASRendererPipe.TargetNodeMesh); } - /// Returns connector's anchor, at wich it attaches to the pipe. + /// Returns connector's anchor, at which it attaches to the pipe. /// The anchor object. It's never null. /// If model cannot be retrieved. protected Transform GetConnectorModelPipeAnchor() { @@ -729,7 +729,7 @@ protected Transform GetConnectorModelPartAnchor() { } /// Finds model by path or logs&throws. - /// Just a convinience method to avoid unclear NREs. + /// Just a convenience method to avoid unclear NREs. /// The model. It's never null. /// If model cannot be retrieved. protected Transform FindModelOrThrow(Transform root, string path) { diff --git a/Source/modules/KASLinkTargetBase.cs b/Source/modules/KASLinkTargetBase.cs index 40a8f9c70..85010c69b 100644 --- a/Source/modules/KASLinkTargetBase.cs +++ b/Source/modules/KASLinkTargetBase.cs @@ -222,7 +222,7 @@ public string GetPrimaryField() { #region KASEvents listeners /// - /// Fires when this module can link, and there is a source that has actived the linking mode. + /// Fires when this module can link, and there is a source that has activated the linking mode. /// /// KAS events listener. /// @@ -245,8 +245,8 @@ protected virtual void OnStopLinkingKASEvent(ILinkSource connectionSource) { #region New inheritable methods /// Verifies that part can link with the source. /// - /// It only checks if the source is eligibile to link with this target, not the actual - /// conditions. The source is responsible to verify all the conditions before finiliszing the link. + /// It only checks if the source is eligible to link with this target, not the actual + /// conditions. The source is responsible to verify all the conditions before finalizing the link. /// /// Source to check against. /// diff --git a/Source/modules/KASLinkTargetKerbal.cs b/Source/modules/KASLinkTargetKerbal.cs index a696d71bf..7f8d2702a 100644 --- a/Source/modules/KASLinkTargetKerbal.cs +++ b/Source/modules/KASLinkTargetKerbal.cs @@ -23,7 +23,7 @@ namespace KAS { public sealed class KASLinkTargetKerbal : KASLinkTargetBase, // KAS interfaces. IHasContextMenu, - // KSPDev sugar interafces. + // KSPDev sugar interfaces. IHasGUI { #region Localizable GUI strings. /// @@ -54,7 +54,7 @@ public sealed class KASLinkTargetKerbal : KASLinkTargetBase, #region Part's config fields /// Color to use to highlight the closest connector that can be picked up. /// - /// If set to black (0, 0, 0), then the closests connector will not be highlighted. + /// If set to black (0, 0, 0), then the closest connector will not be highlighted. /// /// [KSPField] @@ -107,7 +107,7 @@ KASInternalPhysicalConnector closestConnector { /// It's set from the part's config. static Event dropConnectorKeyEvent; - /// Keyboard event to react to pucik up a dropped connector. + /// Keyboard event to react to pick up a dropped connector. /// It's set from the part's config. static Event pickupConnectorKeyEvent; @@ -128,7 +128,7 @@ KASInternalPhysicalConnector closestConnector { /// Connector that is currently highlighted as the pickup candidate. KASInternalPhysicalConnector focusedPickupConnector; - /// Transform object of the bone which the atatch node needs to follow. + /// Transform object of the bone which the attach node needs to follow. /// /// Kerbal's model is tricky, and many objects live at the unusual layers. To not get affected by /// this logic, the attach node is not connected to the bone as a child. Instead, a runtime code @@ -410,7 +410,7 @@ void LinkCarriedConnector(ILinkPeer peer) { /// Helper method to create a part's context menu. /// The peer module to create an action for. /// The GUI name of the menu item. - /// The action to exectue when the menu item is triggered. + /// The action to execute when the menu item is triggered. /// The new event. It's not automatically injected into the part. BaseEvent MakeEvent(ILinkPeer peer, Message guiName, Action action) { var ev = new BaseEvent( diff --git a/Source/modules/KASLinkWinch.cs b/Source/modules/KASLinkWinch.cs index 1919fed60..c4170361d 100644 --- a/Source/modules/KASLinkWinch.cs +++ b/Source/modules/KASLinkWinch.cs @@ -140,7 +140,7 @@ public class KASLinkWinch : KASLinkSourcePhysical, /// degrees. /// /// - /// This value is always positive, and it determines how significantly the deriction of + /// This value is always positive, and it determines how significantly the direction of the /// forward and up vectors of the connector can differ from the winch's attach node /// direction. /// @@ -556,7 +556,7 @@ void UpdateMotor() { } /// - /// Checks if the cable connector can be locked without triggering significant physical froces. + /// Checks if the cable connector can be locked without triggering significant physical forces. /// /// /// If true then the result of the check will be logged. @@ -571,7 +571,7 @@ bool CheckIsConnectorAligned(bool logCheckResult) { || cableJoint.realCableLength > connectorLockMaxErrorDist) { // Not close enough. if (logCheckResult) { HostedDebugLog.Info(this, "Connector cannot lock, the preconditions failed:" - + " maxLengh={0}, realLength={1}, isLinked={2}", + + " maxLength={0}, realLength={1}, isLinked={2}", cableJoint.deployedCableLength, cableJoint.realCableLength, isLinked); @@ -585,7 +585,7 @@ bool CheckIsConnectorAligned(bool logCheckResult) { } return true; } - // Check if the alignment error is small enough to not awake Krakken on dock. + // Check if the alignment error is small enough to not awake Kraken on dock. var fwdAngleErr = 180 - Vector3.Angle(GetConnectorModelPipeAnchor().forward, nodeTransform.forward); if (fwdAngleErr > connectorLockMaxErrorDir) { diff --git a/Source/modules/KASRendererBezierPipe.cs b/Source/modules/KASRendererBezierPipe.cs index b4f00c048..07fbaa76c 100644 --- a/Source/modules/KASRendererBezierPipe.cs +++ b/Source/modules/KASRendererBezierPipe.cs @@ -8,7 +8,7 @@ namespace KAS { /// -/// Module for the felxible pipes that bend at a curve, close to the real physical behavior. +/// Module for the flexible pipes that bend at a curve, close to the real physical behavior. /// /// /// The form of the pipe is calculated using the Cubic Bezier curves. This renderer is CPU @@ -40,7 +40,7 @@ public sealed class KASRendererBezierPipe : KASRendererPipe { /// Recommended number of the adjustable sections in the pipe mesh. /// /// The bigger values will give better visual quality but impact the performance. This value is - /// used only as a recommendation for the setting. The implemenation is not required to + /// used only as a recommendation for the setting. The implementation is not required to /// create exactly this many sections. This setting defines the "baseline" of the renderer /// performance and visual quality. The actual quality settings can affect this value. /// @@ -52,7 +52,7 @@ public sealed class KASRendererBezierPipe : KASRendererPipe { /// Number of the segments in the pipe perimeter shape. /// /// The bigger values will give better visual quality but impact the performance. This value is - /// used only as a recommendation for the setting. The implemenation is not required to + /// used only as a recommendation for the setting. The implementation is not required to /// create exactly this many sections. This setting defines the "baseline" of the renderer /// performance and visual quality. The actual quality settings can affect this value. /// @@ -109,7 +109,7 @@ SkinnedMeshRenderer pipeSkinnedMeshRenderer { #region KASRendererPipe overrides /// protected override void SetupPipe(Transform fromObj, Transform toObj) { - // Purposely not calling the base since it would try to align a stright pipe. + // Purposely not calling the base since it would try to align a straight pipe. AlignToCurve(fromObj, toObj); } @@ -233,7 +233,7 @@ protected override Vector3[] GetPipePath(Transform start, Transform end) { /// end attach nodes. /// /// - /// This is a simplified implementation of the Bezier Curve algorythm. We only need 3 points + /// This is a simplified implementation of the Bezier Curve algorithm. We only need 3 points /// (cubic curves), so it can be programmed plain simple. /// /// @@ -261,7 +261,7 @@ void AlignToCurve(Transform fromObj, Transform toObj) { var elementPos = p02pos + elementVector * t; section.transform.position = elementPos; - // Use UP vector from the previous node to reduce artefacts when the pipe is bend at a sharp + // Use UP vector from the previous node to reduce artifacts when the pipe is bend at a sharp // angle. section.transform.rotation = Quaternion.LookRotation( elementDir, i == 0 ? fromObj.up : bones[i - 1].up); @@ -277,7 +277,7 @@ void AlignToCurve(Transform fromObj, Transform toObj) { /// Adjusts the texture on the pipe object to fit the rescale mode. /// - /// It makes sure the texture is properly distrubited thru all the pipe mesh sections. + /// It makes sure the texture is properly distributed thru all the pipe mesh sections. /// void RescaleMeshSectionTextures() { // Find out the real length of the pipe. @@ -344,7 +344,7 @@ void UpdateColliders() { var capsule = colliders[i]; var boneDistance = (bones[i].position - bones[i + 1].position).magnitude; capsule.center = new Vector3(0, 0, boneDistance / 2); - // The capsules from the adjustent bones should "connect" at the half-sphere center. + // The capsules from the adjacent bones should "connect" at the half-sphere center. capsule.height = boneDistance + pipeDiameter; } } diff --git a/Source/modules/KASRendererPipe.cs b/Source/modules/KASRendererPipe.cs index c5e771116..e61ce1b84 100644 --- a/Source/modules/KASRendererPipe.cs +++ b/Source/modules/KASRendererPipe.cs @@ -18,7 +18,7 @@ namespace KAS { /// /// At each end of the pipe a model can be drawn to make the connection look nicer, it's /// configured separately for the pipe source and target. If nothing is configured, then the pipe -/// (which is a cylinder mesh) simply toches the attach nodes of the parts. If the pipe diameter +/// (which is a cylinder mesh) simply touches the attach nodes of the parts. If the pipe diameter /// is big, then it may look bad since the edges of the cylinder won't mix nicely with the part /// meshes. /// @@ -41,7 +41,7 @@ namespace KAS { /// Finally, a complete prefab model can be inserted! This model will be inserted between the part /// and the sphere. The model path is defined via model setting. To properly orient the /// model, two extra parameters are needed: modelPartAttachAt, which defines how the model -/// attches to the part; and modelPipeAttachAt, which defines where the pipe attaches to the +/// attaches to the part; and modelPipeAttachAt, which defines where the pipe attaches to the /// model. If sphere or offsets were set, they will be counter relative to modelPipeAttachAt. /// /// @@ -217,7 +217,7 @@ protected class ModelPipeEndNode { /// Object that becomes parent when the model is parked. /// - /// This obejct must never be null. Set it to the part's model when unsure what to + /// This object must never be null. Set it to the part's model when unsure what to /// provide. /// public Transform parkRootObject; @@ -232,7 +232,7 @@ public ModelPipeEndNode(string name, JointConfig config) { /// Updates the node's state to the target transform. /// - /// The transfrom to align the node to. If null, then the model will be "parked". + /// The transform to align the node to. If null, then the model will be "parked". /// /// public void AlignToTransform(Transform target) { @@ -420,7 +420,7 @@ protected override void SetCollisionIgnores(Part otherPart, bool ignore) { /// Builds a model for the joint end basing on the configuration. /// The node to setup. /// - /// The object to align the conenctor to. If it's null, then the model will be parked. + /// The object to align the connector to. If it's null, then the model will be parked. /// protected virtual void UpdateJointNode(ModelPipeEndNode node, Transform alignTo) { var config = node.config; @@ -573,7 +573,7 @@ protected virtual void SetupPipe(Transform fromObj, Transform toObj) { /// The mesh UV coordinates are expected to be distributed over its full length from 0.0 to /// 1.0. Such configuration ensures that texture covers the entire mesh, and /// stretches/shrinks as the mesh changes its length. However, in the tiling modes, the texture - /// must be distributed over the mesh lengh so that it's not changing its ratio. This method + /// must be distributed over the mesh length so that it's not changing its ratio. This method /// checks the renderer stretching mode and adjusts the texture scale. /// /// This method is intentionally not virtual, since it's a utility method. Any part specific logic diff --git a/Source/modules/KASRendererTelescopicPipe.cs b/Source/modules/KASRendererTelescopicPipe.cs index 9ef530c1d..b627fc5a8 100644 --- a/Source/modules/KASRendererTelescopicPipe.cs +++ b/Source/modules/KASRendererTelescopicPipe.cs @@ -115,7 +115,7 @@ public sealed class KASRendererTelescopicPipe : AbstractProceduralModel, /// /// Allows random rotation of pistons relative to each other around Z (length) axis. If piston's - /// model has a complex texture this setting may be used to make telescopic pipe less repeatative. + /// model has a complex texture this setting may be used to make telescopic pipe less repetitive. /// /// /// Piston's model from prefab will be scaled by this value. X&Y axes affect diameter, Z @@ -176,7 +176,7 @@ public class Orientation { public string title = ""; } - /// List of the available menu items for the unlinked pipe oriaentation. + /// List of the available menu items for the unlinked pipe orientation. /// [PersistentField("parkedOrientation", isCollection = true, group = StdPersistentGroups.PartConfigLoadGroup)] @@ -277,7 +277,7 @@ private set { #endregion #region Model name constants - /// A transform that is a root for the whole pipe modelset. + /// A transform that is a root for the whole pipe model set. /// It doesn't have to match part's attach node transform. const string AttachNodeObjName = "plugNode"; @@ -401,7 +401,7 @@ float strutScale { /// The root node for the telescopic strut. /// /// All the components are built relative to this node. It's also used to determine the part's - /// model scale, whic is important for rednering the proper meshes. + /// model scale, which is important for rendering the proper meshes. /// Transform plugNodeTransform { get { @@ -427,7 +427,7 @@ bool isLinked { #region IHasDebugAdjustables implementation /// Dumps basic constraints of the renderer. - [Debug.KASDebugAdjustable("Dump render link contstrains")] + [Debug.KASDebugAdjustable("Dump render link constraints")] public void DbgEventDumpLinkSettings() { HostedDebugLog.Warning(this, "Procedural model: minLinkLength={0}, maxLinkLength={1}, attachNodePosition.Y={2}," @@ -696,11 +696,11 @@ void UpdateValuesFromModel() { } /// - /// Creates a new model from the existing one. Resets all local settinsg to default. + /// Creates a new model from the existing one. Resets all local settings to default. /// /// /// Same model in this part is copied several times, and they are organized into a hierarchy. So - /// if there were any scale or rotation adjustments they will accumulate thru the hirerachy + /// if there were any scale or rotation adjustments they will accumulate thru the hierarchy /// breaking the whole model. That's why all local transformations must be default. /// /// Model to copy. @@ -804,7 +804,7 @@ void CreatePistonModels() { } /// Returns the world position of the source link "pivot". - /// The transfrom to count the position relative to. + /// The transform to count the position relative to. /// The position in world coordinates. Vector3 GetLinkVectorSourcePos(Transform refTransform) { // Don't use the stock translation methods since the handle length is already scaled. We don't @@ -813,7 +813,7 @@ Vector3 GetLinkVectorSourcePos(Transform refTransform) { } /// Returns the world position of the target link "pivot". - /// The transfrom to count the position relative to. + /// The transform to count the position relative to. /// The position in world coordinates. Vector3 GetLinkVectorTargetPos(Transform refTransform) { // Don't use the stock translation methods since the handle length is already scaled. We don't @@ -823,7 +823,7 @@ Vector3 GetLinkVectorTargetPos(Transform refTransform) { /// Creates the telescopic pipe meshes. /// - /// If there were meshes created alreadym they will be destroyed. So this method can be called to + /// If there were meshes created already, they will be destroyed. So this method can be called to /// refresh the part settings. /// void CreatePipeMeshes(bool recreate) { From 9f1eca86eda76fe33990469ec5ab230ef8338a59 Mon Sep 17 00:00:00 2001 From: ihsoft Date: Tue, 21 Jul 2020 01:32:52 -0700 Subject: [PATCH 16/46] Minor fix line positions --- Source/modules/AbstractJoint.cs | 10 +++++----- Source/modules/KASLinkResourceConnector.cs | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Source/modules/AbstractJoint.cs b/Source/modules/AbstractJoint.cs index 969ca26d8..d0d17c0ba 100644 --- a/Source/modules/AbstractJoint.cs +++ b/Source/modules/AbstractJoint.cs @@ -42,9 +42,9 @@ public abstract class AbstractJoint : AbstractPartModule, IsPackable, IKSPDevModuleInfo, IKSPActivateOnDecouple { #region Localizable GUI strings - static readonly Message MinLengthLimitReachedMsg = /// /// + static readonly Message MinLengthLimitReachedMsg = new Message( "#kasLOC_00000", defaultTemplate: "Link is too short: <<1>> < <<2>>", @@ -54,9 +54,9 @@ public abstract class AbstractJoint : AbstractPartModule, + "\nArgument <<2>> is the part's config setting of type DistanceType.", example: "Link is too short: 1.22 m < 2.33 m"); - static readonly Message MaxLengthLimitReachedMsg = /// /// + static readonly Message MaxLengthLimitReachedMsg = new Message( "#kasLOC_00001", defaultTemplate: "Link is too long: <<1>> > <<2>>", @@ -66,9 +66,9 @@ public abstract class AbstractJoint : AbstractPartModule, + "\nArgument <<2>> is the part's config setting of type DistanceType.", example: "Link is too long: 2.33 m > 1.22 m"); - static readonly Message SourceNodeAngleLimitReachedMsg = /// /// + static readonly Message SourceNodeAngleLimitReachedMsg = new Message( "#kasLOC_00002", defaultTemplate: "Source angle limit reached: <<1>> > <<2>>", @@ -78,9 +78,9 @@ public abstract class AbstractJoint : AbstractPartModule, + "\nArgument <<2>> is the part's config setting of type AngleType.", example: "Source angle limit reached: 3° > 2.5°"); - static readonly Message TargetNodeAngleLimitReachedMsg = /// /// + static readonly Message TargetNodeAngleLimitReachedMsg = new Message( "#kasLOC_00003", defaultTemplate: "Target angle limit reached: <<1>> > <<2>>", @@ -118,9 +118,9 @@ public abstract class AbstractJoint : AbstractPartModule, + "\nArgument <<1>> is the part's config setting of type DistanceType.", example: "Minimum link length: 1.22 m"); - static readonly Message MaximumLinkLengthInfo = /// /// + static readonly Message MaximumLinkLengthInfo = new Message( "#kasLOC_00007", defaultTemplate: "Maximum link length: <<1>>", diff --git a/Source/modules/KASLinkResourceConnector.cs b/Source/modules/KASLinkResourceConnector.cs index 1cf4bb0ba..4373161dd 100644 --- a/Source/modules/KASLinkResourceConnector.cs +++ b/Source/modules/KASLinkResourceConnector.cs @@ -114,15 +114,15 @@ public sealed class KASLinkResourceConnector : KASLinkSourcePhysical, description: "The GUI hint that explains what will happen if the auto-speed options is" + " chosen."); - static readonly Message LeftToRigthToggleHint = new Message( /// + static readonly Message LeftToRightToggleHint = new Message( "#kasLOC_12011", defaultTemplate: "Trigger transfer from the connected vessel to the owner", description: "The hint text to explain the button action that starts transferring the" + " resource from the connected vessel to the owner of the resource transfer part."); - static readonly Message LeftToRigthButtonHint = new Message( /// + static readonly Message LeftToRightButtonHint = new Message( "#kasLOC_12012", defaultTemplate: "Transfer from the connected vessel to the owner", description: "The hint text to explain the button action that does transferring the" From 8c6b72bb5dd0716939a30dd11b726f683c5f6f61 Mon Sep 17 00:00:00 2001 From: ihsoft Date: Tue, 21 Jul 2020 01:43:38 -0700 Subject: [PATCH 17/46] Convert to auto-properties --- Source/api_impl/KasEventsImpl.cs | 20 ++++---- Source/api_impl/KasLinkEventImpl.cs | 15 +++--- Source/compatibility/PatchFilesProcessor.cs | 27 +++-------- Source/modules/AbstractJoint.cs | 18 ++----- Source/modules/AbstractLinkPeer.cs | 52 ++++++--------------- Source/modules/AbstractPipeRenderer.cs | 6 +-- Source/modules/KASJointCableBase.cs | 8 ++-- Source/modules/KASLinkSourceBase.cs | 4 +- Source/modules/KASLinkSourcePhysical.cs | 12 ++--- Source/modules/KASLinkWinch.cs | 8 ++-- Source/modules/KASRendererBezierPipe.cs | 4 +- Source/modules/KASRendererTelescopicPipe.cs | 14 ++---- 12 files changed, 57 insertions(+), 131 deletions(-) diff --git a/Source/api_impl/KasEventsImpl.cs b/Source/api_impl/KasEventsImpl.cs index 50c9fb752..e4206ec3e 100644 --- a/Source/api_impl/KasEventsImpl.cs +++ b/Source/api_impl/KasEventsImpl.cs @@ -11,24 +11,20 @@ namespace KASImpl { /// impact performance at the moment of actual event triggering. public class KasEventsImpl : IKasEvents { /// - public EventData OnStartLinking { get { return _onStartLinking; } } - readonly EventData _onStartLinking = - new EventData("KASOnStartLinking"); + public EventData OnStartLinking { get; } = + new EventData("KASOnStartLinking"); /// - public EventData OnStopLinking { get { return _onStopLinking; } } - readonly EventData _onStopLinking = - new EventData("KASOnStopLinking"); + public EventData OnStopLinking { get; } = + new EventData("KASOnStopLinking"); /// - public EventData OnLinkCreated { get { return _onLinkCreated; } } - readonly EventData _onLinkCreated = - new EventData("KASOnLinkCreated"); + public EventData OnLinkCreated { get; } = + new EventData("KASOnLinkCreated"); /// - public EventData OnLinkBroken { get { return _onLinkBroken; } } - readonly EventData _onLinkBroken = - new EventData("KASOnLinkBroken"); + public EventData OnLinkBroken { get; } = + new EventData("KASOnLinkBroken"); } } // namespace diff --git a/Source/api_impl/KasLinkEventImpl.cs b/Source/api_impl/KasLinkEventImpl.cs index 2451c1b76..43ff7cee3 100644 --- a/Source/api_impl/KasLinkEventImpl.cs +++ b/Source/api_impl/KasLinkEventImpl.cs @@ -7,16 +7,13 @@ namespace KASAPIv2 { /// A holder for simple source-to-target event. public struct KasLinkEventImpl : IKasLinkEvent { /// - public ILinkSource source { get { return _source; } } - readonly ILinkSource _source; + public ILinkSource source { get; } /// - public ILinkTarget target { get { return _target; } } - readonly ILinkTarget _target; + public ILinkTarget target { get; } /// - public LinkActorType actor { get { return _actor; } } - LinkActorType _actor; + public LinkActorType actor { get; } /// Creates an event info. /// The source that initiated the link. @@ -24,9 +21,9 @@ public struct KasLinkEventImpl : IKasLinkEvent { /// The actor that did the change. public KasLinkEventImpl(ILinkSource source, ILinkTarget target, LinkActorType actorType = LinkActorType.API) { - _source = source; - _target = target; - _actor = actorType; + this.source = source; + this.target = target; + actor = actorType; } } diff --git a/Source/compatibility/PatchFilesProcessor.cs b/Source/compatibility/PatchFilesProcessor.cs index 1567f83d3..4f6746c54 100644 --- a/Source/compatibility/PatchFilesProcessor.cs +++ b/Source/compatibility/PatchFilesProcessor.cs @@ -73,33 +73,18 @@ public override void OnUpgrade(ConfigNode node, LoadContext loadContext, ConfigN } /// - public override string Name { - get { - return "KAS parts patcher v1.0"; - } - } + public override string Name => "KAS parts patcher v1.0"; /// - public override string Description { - get { - return "Applies a KAS compatibility scripts on the parts"; - } - } + public override string Description => "Applies a KAS compatibility scripts on the parts"; /// - public override Version EarliestCompatibleVersion { - get { - return new Version(0, 21, 0); - } - } + public override Version EarliestCompatibleVersion => new Version(0, 21, 0); /// - public override Version TargetVersion { - get { - // Always needs to run. - return new Version(Versioning.version_major, Versioning.version_minor, Versioning.Revision); - } - } + // Always needs to run. + public override Version TargetVersion => new Version( + Versioning.version_major, Versioning.version_minor, Versioning.Revision); #endregion #region UpgradeScript oevrrides diff --git a/Source/modules/AbstractJoint.cs b/Source/modules/AbstractJoint.cs index d0d17c0ba..2d95646c7 100644 --- a/Source/modules/AbstractJoint.cs +++ b/Source/modules/AbstractJoint.cs @@ -155,7 +155,7 @@ public abstract class AbstractJoint : AbstractPartModule, #region ILinkJoint CFG properties /// - public string cfgJointName { get { return jointName; } } + public string cfgJointName => jointName; #endregion #region Part's config fields @@ -302,19 +302,13 @@ public bool coupleOnLinkMode { /// Distance in meters or null. The null value means that this joint doesn't care /// about the particular length in the current state, and it's up to the implementation. /// - protected float? originalLength { - get { return persistedLinkLength < 0 ? (float?) null : persistedLinkLength; } - } + protected float? originalLength => persistedLinkLength < 0 ? (float?) null : persistedLinkLength; /// Tells if the parts of the link are coupled in the vessels hierarchy. /// /// true if either the source part is coupled to the target, or the vise versa. /// - protected bool isCoupled { - get { - return isLinked && CheckCoupled(linkSource, linkTarget); - } - } + protected bool isCoupled => isLinked && CheckCoupled(linkSource, linkTarget); /// Returns the PartJoint which manages this connection. /// The joint or null if the link is not established or not coupled. @@ -354,15 +348,13 @@ protected List joints { /// /// /// - protected List customJoints { get { return _customJoints; } } - readonly List _customJoints = new List(); + protected List customJoints { get; } = new List(); /// The objects that were used by the custom joints. /// These objects will be destoyed on the joints clean up. /// /// - protected List customExtraObjects { get { return _customObjects; } } - readonly List _customObjects = new List(); + protected List customExtraObjects { get; } = new List(); #endregion #region Local members diff --git a/Source/modules/AbstractLinkPeer.cs b/Source/modules/AbstractLinkPeer.cs index 2f5e6f0d2..132c873e8 100644 --- a/Source/modules/AbstractLinkPeer.cs +++ b/Source/modules/AbstractLinkPeer.cs @@ -116,78 +116,52 @@ public abstract class AbstractLinkPeer : AbstractPartModule, #region ILinkPeer properties implementation /// - public string cfgLinkType { get { return linkType; } } + public string cfgLinkType => linkType; /// - public string cfgAttachNodeName { get { return attachNodeName; } } + public string cfgAttachNodeName => attachNodeName; /// - public string[] cfgDependentNodeNames { - get { - if (_dependentNodeNames == null) { - _dependentNodeNames = dependentNodes.Split(new[] {','}); - } - return _dependentNodeNames; - } - } + public string[] cfgDependentNodeNames => + _dependentNodeNames ?? (_dependentNodeNames = dependentNodes.Split(',')); string[] _dependentNodeNames; /// /// - public LinkState linkState { - get { - return linkStateMachine.currentState ?? persistedLinkState; - } - } + public LinkState linkState => linkStateMachine.currentState ?? persistedLinkState; /// /// /// /// - public virtual ILinkPeer otherPeer { - get { return _otherPeer; } - } + public virtual ILinkPeer otherPeer => _otherPeer; ILinkPeer _otherPeer; /// - public uint linkPartId { - get { return persistedLinkPartId; } - } + public uint linkPartId => persistedLinkPartId; /// - public string linkNodeName { - get { return persistedLinkNodeName; } - } + public string linkNodeName => persistedLinkNodeName; /// public Transform nodeTransform { get; private set; } /// - public AttachNode coupleNode { - get { return allowCoupling ? parsedAttachNode : null; } - } + public AttachNode coupleNode => allowCoupling ? parsedAttachNode : null; /// - public AttachNode attachNode { - get { return parsedAttachNode; } - } + public AttachNode attachNode => parsedAttachNode; /// - public bool isLinked { - get { return linkState == LinkState.Linked; } - } + public bool isLinked => linkState == LinkState.Linked; /// /// - public bool isLocked { - get { return linkState == LinkState.Locked; } - } + public bool isLocked => linkState == LinkState.Locked; /// /// - public bool isNodeBlocked { - get { return linkState == LinkState.NodeIsBlocked; } - } + public bool isNodeBlocked => linkState == LinkState.NodeIsBlocked; #endregion #region Inheritable fields & properties diff --git a/Source/modules/AbstractPipeRenderer.cs b/Source/modules/AbstractPipeRenderer.cs index d48160685..7a5941189 100644 --- a/Source/modules/AbstractPipeRenderer.cs +++ b/Source/modules/AbstractPipeRenderer.cs @@ -134,7 +134,7 @@ public enum PipeTextureRescaleMode { #region ILinkRenderer properties /// - public string cfgRendererName { get { return rendererName; } } + public string cfgRendererName => rendererName; /// public virtual Color? colorOverride { @@ -167,9 +167,7 @@ public virtual bool isPhysicalCollider { bool _isPhysicalCollider = true; // It's a "forced OFF" setting. /// - public bool isStarted { - get { return sourceTransform != null && targetTransform != null; } - } + public bool isStarted => sourceTransform != null && targetTransform != null; /// public Transform sourceTransform { get; private set; } diff --git a/Source/modules/KASJointCableBase.cs b/Source/modules/KASJointCableBase.cs index 1ab1e8231..780240ac5 100644 --- a/Source/modules/KASJointCableBase.cs +++ b/Source/modules/KASJointCableBase.cs @@ -70,7 +70,7 @@ public bool IsJointUnlocked() { #region ILinkCableJoint CFG properties /// - public float cfgMaxCableLength { get { return maxLinkLength; } } + public float cfgMaxCableLength => maxLinkLength; #endregion #region ILinkCableJoint properties @@ -78,9 +78,7 @@ public bool IsJointUnlocked() { public Rigidbody headRb { get; private set; } /// - public float deployedCableLength { - get { return cableJoint != null ? cableJoint.linearLimit.limit : 0; } - } + public float deployedCableLength => cableJoint != null ? cableJoint.linearLimit.limit : 0; /// public float realCableLength { @@ -102,7 +100,7 @@ public float realCableLength { #region Inheritable properties /// Tells if the physical head is started and active. /// The status of the physical head. - protected bool isHeadStarted { get { return headSource != null; } } + protected bool isHeadStarted => headSource != null; /// Physical joint object that connects source to the target. /// The PhysX joint that connects the parts. diff --git a/Source/modules/KASLinkSourceBase.cs b/Source/modules/KASLinkSourceBase.cs index 04fed1bd0..d8b1b5bff 100644 --- a/Source/modules/KASLinkSourceBase.cs +++ b/Source/modules/KASLinkSourceBase.cs @@ -99,9 +99,7 @@ public class KASLinkSourceBase : AbstractLinkPeer, #region ILinkSource properties implementation /// - public ILinkTarget linkTarget { - get { return otherPeer as ILinkTarget; } - } + public ILinkTarget linkTarget => otherPeer as ILinkTarget; /// /// diff --git a/Source/modules/KASLinkSourcePhysical.cs b/Source/modules/KASLinkSourcePhysical.cs index 1b9d2bfe0..a2a6f0889 100644 --- a/Source/modules/KASLinkSourcePhysical.cs +++ b/Source/modules/KASLinkSourcePhysical.cs @@ -298,25 +298,21 @@ protected enum ConnectorState { /// /// /// - protected float currentCableLength { get { return cableJoint.deployedCableLength; } } + protected float currentCableLength => cableJoint.deployedCableLength; /// /// Maximum allowed distance between the owner part and the connector to establish a link. /// /// Distance in meters. It's constant and doesn't depend on the joint state. /// - protected float cfgMaxCableLength { get { return cableJoint.cfgMaxCableLength; } } + protected float cfgMaxCableLength => cableJoint.cfgMaxCableLength; /// /// Tells if the connector is physicsless, and its model is a child of the owning part. /// /// The status of the connector model. - protected bool isConnectorLocked { - get { - return connectorState == ConnectorState.Locked - || connectorState == ConnectorState.Docked; - } - } + protected bool isConnectorLocked => connectorState == ConnectorState.Locked + || connectorState == ConnectorState.Docked; /// State of the connector head. /// The connector state. diff --git a/Source/modules/KASLinkWinch.cs b/Source/modules/KASLinkWinch.cs index c4170361d..75aeda033 100644 --- a/Source/modules/KASLinkWinch.cs +++ b/Source/modules/KASLinkWinch.cs @@ -326,7 +326,7 @@ public virtual void ReleaseCableAction(KSPActionParam unused) { #region IWinchControl properties /// - public float cfgMotorMaxSpeed { get { return motorMaxSpeed; } } + public float cfgMotorMaxSpeed => motorMaxSpeed; /// public float motorTargetSpeed { get; private set; } @@ -349,13 +349,13 @@ private set { float _motorCurrentSpeed; /// - public new bool isConnectorLocked { get { return base.isConnectorLocked; } } + public new bool isConnectorLocked => base.isConnectorLocked; /// - public new float currentCableLength { get { return base.currentCableLength; } } + public new float currentCableLength => base.currentCableLength; /// - public new float cfgMaxCableLength { get { return base.cfgMaxCableLength; } } + public new float cfgMaxCableLength => base.cfgMaxCableLength; #endregion #region Local fields & properties diff --git a/Source/modules/KASRendererBezierPipe.cs b/Source/modules/KASRendererBezierPipe.cs index 07fbaa76c..7e1069f71 100644 --- a/Source/modules/KASRendererBezierPipe.cs +++ b/Source/modules/KASRendererBezierPipe.cs @@ -76,9 +76,7 @@ public sealed class KASRendererBezierPipe : KASRendererPipe { #region Local fields and properties /// Skinned renderer for the pipe. /// The skinned renderer or null if none exists. - SkinnedMeshRenderer pipeSkinnedMeshRenderer { - get { return pipeMeshRenderer as SkinnedMeshRenderer; } - } + SkinnedMeshRenderer pipeSkinnedMeshRenderer => pipeMeshRenderer as SkinnedMeshRenderer; /// The t parameter of the Bezier Curve. Per mesh bone. /// diff --git a/Source/modules/KASRendererTelescopicPipe.cs b/Source/modules/KASRendererTelescopicPipe.cs index b627fc5a8..2c936f6a1 100644 --- a/Source/modules/KASRendererTelescopicPipe.cs +++ b/Source/modules/KASRendererTelescopicPipe.cs @@ -214,7 +214,7 @@ public void RetractToMinMenuAction() { #region ILinkRenderer properties /// - public string cfgRendererName { get { return rendererName; } } + public string cfgRendererName => rendererName; /// public Color? colorOverride { @@ -370,12 +370,8 @@ private set { /// Prefab for the piston models. /// A model reference from the part's model. It's not a copy! - GameObject pistonPrefab { - get { - return GameDatabase.Instance.GetModelPrefab(pistonModel).transform - .Find(PistonModelName).gameObject; - } - } + GameObject pistonPrefab => GameDatabase.Instance.GetModelPrefab(pistonModel).transform + .Find(PistonModelName).gameObject; /// The scale of the strut models. /// @@ -415,9 +411,7 @@ Transform plugNodeTransform { /// Tells if the source on the part is linked. /// The current state of the link. - bool isLinked { - get { return sourceTransform != null && targetTransform != null; } - } + bool isLinked => sourceTransform != null && targetTransform != null; #endregion #region Local fields & properties From 0457275953effa5a33cb54cc09d07a745e43eab0 Mon Sep 17 00:00:00 2001 From: ihsoft Date: Tue, 21 Jul 2020 01:47:30 -0700 Subject: [PATCH 18/46] Minor code refactoring --- Source/api_impl/PhysicsUtilsImpl.cs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/Source/api_impl/PhysicsUtilsImpl.cs b/Source/api_impl/PhysicsUtilsImpl.cs index ff413456d..e04c2531a 100644 --- a/Source/api_impl/PhysicsUtilsImpl.cs +++ b/Source/api_impl/PhysicsUtilsImpl.cs @@ -9,7 +9,7 @@ namespace KASImpl { class PhysicsUtilsImpl : IPhysicsUtils { /// - public void ApplyGravity(Rigidbody rb, Vessel vessel, double rbAirDragMult = 1.0) { + public void ApplyGravity(Rigidbody rb, Vessel vessel, double rbAirDragMultiplier = 1.0) { // Apply the gravity as it's done in FlightIntegrator for the physical object. var geeForce = FlightGlobals.getGeeForceAtPosition(vessel.CoMD, vessel.mainBody) + FlightGlobals.getCoriolisAcc(vessel.velocityD, vessel.mainBody) @@ -17,17 +17,16 @@ public void ApplyGravity(Rigidbody rb, Vessel vessel, double rbAirDragMult = 1.0 rb.AddForce(geeForce * PhysicsGlobals.GraviticForceMultiplier, ForceMode.Acceleration); // Apply the atmosphere drag force as it's done in FlightIntegrator for the physical object. if (PhysicsGlobals.ApplyDrag && vessel.atmDensity > 0) { - var pseudoReDragMult = 1; //FIXME: find out what it is - var d = 0.0005 * pseudoReDragMult * vessel.atmDensity * rbAirDragMult + const int pseudoReDragMultiplier = 1; //TODO(ihsoft): find out what it is + var d = 0.0005 * pseudoReDragMultiplier * vessel.atmDensity * rbAirDragMultiplier * (rb.velocity + Krakensbane.GetFrameVelocity()).sqrMagnitude * PhysicsGlobals.DragMultiplier; if (!double.IsNaN(d) && !double.IsInfinity(d)) { var atmDragForce = -(rb.velocity + Krakensbane.GetFrameVelocity()).normalized * d; - if (PhysicsGlobals.DragUsesAcceleration) { - rb.AddForce(atmDragForce, ForceMode.Acceleration); - } else { - rb.AddForce(atmDragForce, ForceMode.Force); - } + rb.AddForce( + atmDragForce, PhysicsGlobals.DragUsesAcceleration + ? ForceMode.Acceleration + : ForceMode.Force); } } } From 66964f6faa57ed7da0446074321ce2f8e84b3f8b Mon Sep 17 00:00:00 2001 From: ihsoft Date: Tue, 21 Jul 2020 01:50:44 -0700 Subject: [PATCH 19/46] Minor code refactoring --- Source/modules/AbstractJoint.cs | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/Source/modules/AbstractJoint.cs b/Source/modules/AbstractJoint.cs index 2d95646c7..0ab5eb353 100644 --- a/Source/modules/AbstractJoint.cs +++ b/Source/modules/AbstractJoint.cs @@ -405,7 +405,7 @@ public virtual void DecoupleAction(string nodeName, bool weDecouple) { && linkSource.coupleNode != null && linkSource.coupleNode.id == nodeName) { // Do the link cleanup. RestorePartialVesselInfo(linkSource, linkTarget, weDecouple); - MaybeBreakLink(linkSource, linkTarget); + MaybeBreakLink(linkSource); } } #endregion @@ -421,10 +421,11 @@ public virtual void OnJointBreak(float breakForce) { // Calculate relative position and rotation of the part to properly restore the coupling. parentPart = part.parent; var root = vessel.rootPart.transform; + var rootRotation = root.rotation; var thisPartPos = root.TransformPoint(part.orgPos); - var thisPartRot = root.rotation * part.orgRot; + var thisPartRot = rootRotation * part.orgRot; var parentPartPos = root.TransformPoint(parentPart.orgPos); - var parentPartRot = root.rotation * parentPart.orgRot; + var parentPartRot = rootRotation * parentPart.orgRot; relPos = parentPartRot.Inverse() * (thisPartPos - parentPartPos); relRot = parentPartRot.Inverse() * thisPartRot; } @@ -437,9 +438,11 @@ public virtual void OnJointBreak(float breakForce) { // It was KAS joint that broke. Restore the part attachment and break KAS link. if (parentPart != null) { HostedDebugLog.Fine(this, "Restore coupling with: {0}", parentPart); - part.transform.position = - parentPart.transform.position + parentPart.transform.rotation * relPos; - part.transform.rotation = parentPart.transform.rotation * relRot; + var parentPartTransform = parentPart.transform; + var parentPartRotation = parentPartTransform.rotation; + var partTransform = part.transform; + partTransform.position = parentPartTransform.position + parentPartRotation * relPos; + partTransform.rotation = parentPartRotation * relRot; part.Couple(parentPart); } HostedDebugLog.Info(this, "KAS joint is broken, unlink the parts"); @@ -713,7 +716,7 @@ protected Vector3 GetSourcePhysicalAnchor(ILinkSource source) { /// If there are other custom joints existing, they will be cleaned up. This method triggers /// , so keep it in mind when setting up the custom joints. /// - /// + /// /// The new joints. If null, then the old joints will be cleaned up and no new joints will /// be added. /// @@ -723,11 +726,11 @@ protected Vector3 GetSourcePhysicalAnchor(ILinkSource source) { /// /// /// - protected void SetCustomJoints(IEnumerable joints, + protected void SetCustomJoints(IEnumerable newJoints, IEnumerable extraObjects = null) { CleanupPhysXJoints(); - if (joints != null) { - customJoints.AddRange(joints); + if (newJoints != null) { + customJoints.AddRange(newJoints); } if (extraObjects != null) { customExtraObjects.AddRange(extraObjects); @@ -900,9 +903,8 @@ void OnVesselRename(GameEvents.HostedFromToAction action) { /// The actual changes are delyed till the end of frame. So it's safe to call this method from an /// event handler. /// - /// The link source at the moemnt of cleanup. - /// The link target at the moment of cleanup. - void MaybeBreakLink(ILinkSource source, ILinkTarget target) { + /// The link source at the moment of cleanup. + void MaybeBreakLink(ILinkSource source) { // Delay the nodes cleanup to let the other logic work smoothly. Copy the properties since // they will be null'ed on the link destruction. AsyncCall.CallOnEndOfFrame(this, () => { From 0c20b88a9edb3c15026a7ce217d77ff0f689a5b0 Mon Sep 17 00:00:00 2001 From: ihsoft Date: Tue, 21 Jul 2020 01:56:16 -0700 Subject: [PATCH 20/46] Tiny code refactoring --- Source/modules/AbstractLinkPeer.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Source/modules/AbstractLinkPeer.cs b/Source/modules/AbstractLinkPeer.cs index 132c873e8..1914cfdeb 100644 --- a/Source/modules/AbstractLinkPeer.cs +++ b/Source/modules/AbstractLinkPeer.cs @@ -216,7 +216,7 @@ public virtual void DecoupleAction(string nodeName, bool weDecouple) { /// public override void OnAwake() { base.OnAwake(); - linkStateMachine = new SimpleStateMachine(true /* strict */); + linkStateMachine = new SimpleStateMachine(); SetupStateMachine(); RegisterGameEventListener(GameEvents.onPartCouple, OnPartCoupleEvent); } @@ -228,7 +228,7 @@ public override void OnDestroy() { } /// - public override void OnStart(PartModule.StartState state) { + public override void OnStart(StartState state) { base.OnStart(state); // Adjust state of a newly added module. @@ -246,7 +246,7 @@ public override void OnStart(PartModule.StartState state) { } /// - public override void OnStartFinished(PartModule.StartState state) { + public override void OnStartFinished(StartState state) { base.OnStartFinished(state); // Prevent the third-party logic on the auto node. See OnLoad. if ((HighLogic.LoadedSceneIsFlight || HighLogic.LoadedSceneIsEditor) @@ -417,7 +417,7 @@ protected virtual void SetOtherPeer(ILinkPeer peer) { #region ILinkStateEventListener implementation /// - public virtual void OnKASLinkedState(IKasLinkEvent info, bool isLinked) { + public virtual void OnKASLinkedState(IKasLinkEvent info, bool isLinkedState) { var peer = info.source.part == part ? info.source : info.target as ILinkPeer; @@ -425,9 +425,9 @@ public virtual void OnKASLinkedState(IKasLinkEvent info, bool isLinked) { && (peer.cfgAttachNodeName == attachNodeName || cfgDependentNodeNames.Contains(peer.cfgAttachNodeName))) { // Only act when it's about (un)locking. Don't affect the state in all other cases. - if (isLinked && linkState != LinkState.NodeIsBlocked) { + if (isLinkedState && linkState != LinkState.NodeIsBlocked) { SetLinkState(LinkState.Locked); - } else if (!isLinked && linkState == LinkState.Locked) { + } else if (!isLinkedState && linkState == LinkState.Locked) { SetLinkState(LinkState.Available); } } From d963f5317f2bd06089df0812e8af32a4b9029dcf Mon Sep 17 00:00:00 2001 From: ihsoft Date: Tue, 21 Jul 2020 02:05:01 -0700 Subject: [PATCH 21/46] Refactor to shader property index --- Source/modules/AbstractProceduralModel.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Source/modules/AbstractProceduralModel.cs b/Source/modules/AbstractProceduralModel.cs index c7c7d3877..b0ec1ca23 100644 --- a/Source/modules/AbstractProceduralModel.cs +++ b/Source/modules/AbstractProceduralModel.cs @@ -34,7 +34,10 @@ public abstract class AbstractProceduralModel : AbstractPartModule { public const string BumpSpecMapProp = "_BumpSpecMap"; /// Name of the material shininess in the renderer. - public const string ShininessProp = "_Shininess"; + public const string ShininessPropName = "_Shininess"; + + /// Shininess property index in the renderer. + public static readonly int ShininessProp = Shader.PropertyToID(ShininessPropName); #endregion #region Inhertable utility methods From 2a216ba103314e79b26d0eb70b0f2046aab119b3 Mon Sep 17 00:00:00 2001 From: ihsoft Date: Tue, 21 Jul 2020 02:05:34 -0700 Subject: [PATCH 22/46] Minor style refactoring --- Source/modules/AbstractProceduralModel.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Source/modules/AbstractProceduralModel.cs b/Source/modules/AbstractProceduralModel.cs index b0ec1ca23..715d2a0a2 100644 --- a/Source/modules/AbstractProceduralModel.cs +++ b/Source/modules/AbstractProceduralModel.cs @@ -26,12 +26,12 @@ public abstract class AbstractProceduralModel : AbstractPartModule { /// Name of bump map property in the renderer. /// Only bump shaders support it. /// - public const string BumpMapProp = "_BumpMap"; + public const string BumpMapPropName = "_BumpMap"; /// Name of bump map with specular property in the renderer. /// Only bump specular shaders support it. /// - public const string BumpSpecMapProp = "_BumpSpecMap"; + public const string BumpSpecMapPropName = "_BumpSpecMap"; /// Name of the material shininess in the renderer. public const string ShininessPropName = "_Shininess"; @@ -95,8 +95,8 @@ protected float baseScale { /// Tells if the normals map should be used as bump specular map. /// The texture must be made in appropriate way to be compatible! /// - /// - /// + /// + /// [KSPField] [Debug.KASDebugAdjustable("Use NRM texture as bump specular")] public bool isBumpSpecMap; @@ -146,7 +146,7 @@ protected virtual Material CreateMaterial(Texture2D mainTex, material.color = overrideColor ?? materialColor; if (mainTexNrm != null) { material.EnableKeyword("_NORMALMAP"); - material.SetTexture(isBumpSpecMap ? BumpSpecMapProp : BumpMapProp, mainTexNrm); + material.SetTexture(isBumpSpecMap ? BumpSpecMapPropName : BumpMapPropName, mainTexNrm); } if (materialShininess >= 0) { material.SetFloat(ShininessProp, materialShininess); @@ -239,7 +239,7 @@ protected Texture2D GetNormalMap(string textureFileName) { /// /// protected void SetBumpMap(Material material, Action an) { - var propName = isBumpSpecMap ? BumpSpecMapProp : BumpMapProp; + var propName = isBumpSpecMap ? BumpSpecMapPropName : BumpMapPropName; if (material.HasProperty(propName)) { an(propName); } From 2fef06e915c000ef1e98a55de5514f8d00e9cae2 Mon Sep 17 00:00:00 2001 From: ihsoft Date: Tue, 21 Jul 2020 02:16:51 -0700 Subject: [PATCH 23/46] Fix protected method typo --- Source/modules/AbstractJoint.cs | 8 ++++---- Source/modules/KASJointCableBase.cs | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Source/modules/AbstractJoint.cs b/Source/modules/AbstractJoint.cs index 0ab5eb353..a24f083cd 100644 --- a/Source/modules/AbstractJoint.cs +++ b/Source/modules/AbstractJoint.cs @@ -480,7 +480,7 @@ public virtual bool CreateJoint(ILinkSource source, ILinkTarget target) { linkSource = source; linkTarget = target; if (!originalLength.HasValue) { - SetOrigianlLength(Vector3.Distance( + SetOriginalLength(Vector3.Distance( GetSourcePhysicalAnchor(source), GetTargetPhysicalAnchor(source, target))); } isLinked = true; @@ -506,7 +506,7 @@ public virtual void DropJoint() { } } SetCustomJoints(null); - SetOrigianlLength(null); + SetOriginalLength(null); linkSource = null; linkTarget = null; isLinked = false; @@ -634,8 +634,8 @@ public virtual void OnPartPack() { /// length to set on the joint creation. /// /// - protected void SetOrigianlLength(float? newLength) { - persistedLinkLength = newLength.HasValue ? newLength.Value : -1; + protected void SetOriginalLength(float? newLength) { + persistedLinkLength = newLength ?? -1; } /// Creates the actual PhysX joints between the rigid objects. diff --git a/Source/modules/KASJointCableBase.cs b/Source/modules/KASJointCableBase.cs index 780240ac5..02ca41534 100644 --- a/Source/modules/KASJointCableBase.cs +++ b/Source/modules/KASJointCableBase.cs @@ -166,7 +166,7 @@ public virtual void StartPhysicalHead(ILinkSource source, Transform headObjAncho // Attach the head to the source. CreateDistanceJoint(source, headRb, headObjAnchor.position); - SetOrigianlLength(deployedCableLength); + SetOriginalLength(deployedCableLength); } /// @@ -175,13 +175,13 @@ public virtual void StopPhysicalHead() { headSource = null; Destroy(cableJoint); cableJoint = null; - SetOrigianlLength(null); + SetOriginalLength(null); } /// public virtual void SetCableLength(float length) { if (cableJoint == null) { - SetOrigianlLength(null); // Just in case. + SetOriginalLength(null); // Just in case. return; } if (float.IsPositiveInfinity(length)) { @@ -190,7 +190,7 @@ public virtual void SetCableLength(float length) { length = Mathf.Min(realCableLength, deployedCableLength); } ArgumentGuard.InRange(length, "length", 0, cfgMaxCableLength, context: this); - SetOrigianlLength(length); + SetOriginalLength(length); cableJoint.linearLimit = new SoftJointLimit() { limit = length }; } From e63e2289e4869f3ccd3a9607c3466272a5f6e0ff Mon Sep 17 00:00:00 2001 From: ihsoft Date: Tue, 21 Jul 2020 02:18:34 -0700 Subject: [PATCH 24/46] Tiny method name fix --- Source/modules/AbstractPipeRenderer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/modules/AbstractPipeRenderer.cs b/Source/modules/AbstractPipeRenderer.cs index 7a5941189..1c7b1e2de 100644 --- a/Source/modules/AbstractPipeRenderer.cs +++ b/Source/modules/AbstractPipeRenderer.cs @@ -222,7 +222,7 @@ protected Material pipeMaterial { /// Logs all the part's model objects. [Debug.KASDebugAdjustable("Dump part's model hierarchy")] - public void ShowHirerachyDbgAction() { + public void ShowHierarchyDbgAction() { HostedDebugLog.Warning(this, "Part's model hierarchy:"); DebugGui.DumpHierarchy(partModelTransform, partModelTransform); if (targetTransform != null) { From e35a5ee0c471e942ba054a2fca5521ae5f24c05c Mon Sep 17 00:00:00 2001 From: ihsoft Date: Tue, 21 Jul 2020 02:19:42 -0700 Subject: [PATCH 25/46] Tiny style refactroing --- Source/modules/KASJointTwoEndsSphere.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Source/modules/KASJointTwoEndsSphere.cs b/Source/modules/KASJointTwoEndsSphere.cs index 2e095daf7..7e9717dd2 100644 --- a/Source/modules/KASJointTwoEndsSphere.cs +++ b/Source/modules/KASJointTwoEndsSphere.cs @@ -143,8 +143,7 @@ protected override void SetupPhysXJoints() { collisionJoint.zMotion = ConfigurableJointMotion.Free; collisionJoint.connectedBody = linkTarget.part.rb; - SetCustomJoints(new[] {srcJoint, trgJoint, collisionJoint}, - extraObjects: new[] {middleObj}); + SetCustomJoints(new[] {srcJoint, trgJoint, collisionJoint}, extraObjects: new[] {middleObj}); } #endregion From f8214f7c0af526d3966bc8869ce928a2fee97dc4 Mon Sep 17 00:00:00 2001 From: ihsoft Date: Tue, 21 Jul 2020 02:22:55 -0700 Subject: [PATCH 26/46] Null propagation style fix --- Source/modules/KASLinkTargetKerbal.cs | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/Source/modules/KASLinkTargetKerbal.cs b/Source/modules/KASLinkTargetKerbal.cs index 7f8d2702a..7633b478b 100644 --- a/Source/modules/KASLinkTargetKerbal.cs +++ b/Source/modules/KASLinkTargetKerbal.cs @@ -169,15 +169,10 @@ public void PickupConnectorEvent() { HostedDebugLog.Info(this, "Try picking up a physical connector of: {0}...", closestSource); if (closestSource.LinkToTarget(LinkActorType.Player, this)) { var cableJoint = closestSource.linkJoint as ILinkCableJoint; - if (cableJoint != null) { - // By default, the cable joints set the length limit to the actual distance. - cableJoint.SetCableLength(float.PositiveInfinity); - } - var updatableMenu = closestSource as IHasContextMenu; - if (updatableMenu != null) { - // Let the module know that we've changed the values. - updatableMenu.UpdateContextMenu(); - } + cableJoint?.SetCableLength(float.PositiveInfinity); + // Let the module know that we've changed the values. + var updateableMenu = closestSource as IHasContextMenu; + updateableMenu?.UpdateContextMenu(); } else { UISoundPlayer.instance.Play(KASAPI.CommonConfig.sndPathBipWrong); } From 42ed0f2c1b6cf8a4402ddb8cafdc3328c95b386f Mon Sep 17 00:00:00 2001 From: ihsoft Date: Thu, 30 Jul 2020 16:03:15 -0700 Subject: [PATCH 27/46] Cleanup resharper hints --- Source/KSPDev_candidates/Hierarchy2.cs | 1 + Source/api_impl/AttachNodesUtilsImpl.cs | 2 ++ Source/api_impl/CommonConfigImpl.cs | 3 +++ Source/api_impl/JointUtilsImpl.cs | 2 ++ Source/api_impl/KASAPILauncher.cs | 4 ++++ Source/api_impl/KasEventsImpl.cs | 1 + Source/api_impl/KasLinkEventImpl.cs | 2 ++ Source/api_impl/LinkUtilsImpl.cs | 1 + Source/api_impl/PhysicsUtilsImpl.cs | 1 + Source/compatibility/PatchFilesProcessor.cs | 2 ++ Source/controllers/ControllerPartEditorTool.cs | 1 + Source/controllers/ControllerWinchRemote.cs | 2 ++ Source/debug/KASDebugAdjustableAttribute.cs | 1 + Source/modules/AbstractJoint.cs | 3 +++ Source/modules/AbstractLinkPeer.cs | 2 ++ Source/modules/AbstractPipeRenderer.cs | 2 ++ Source/modules/AbstractProceduralModel.cs | 2 ++ Source/modules/KASInternalBrokenJointListener.cs | 2 ++ Source/modules/KASInternalPhysicalConnector.cs | 3 +++ Source/modules/KASJointCableBase.cs | 3 +++ Source/modules/KASJointRigid.cs | 2 ++ Source/modules/KASJointTowBar.cs | 2 ++ Source/modules/KASJointTwoEndsSphere.cs | 4 ++++ Source/modules/KASLinkResourceConnector.cs | 10 ++++++++++ Source/modules/KASLinkSourceBase.cs | 4 ++++ Source/modules/KASLinkSourceInteractive.cs | 2 ++ Source/modules/KASLinkSourcePhysical.cs | 4 ++++ Source/modules/KASLinkTargetBase.cs | 6 ++++++ Source/modules/KASLinkTargetKerbal.cs | 3 +++ Source/modules/KASLinkWinch.cs | 4 ++++ Source/modules/KASRendererBezierPipe.cs | 2 ++ Source/modules/KASRendererPipe.cs | 6 ++++++ Source/modules/KASRendererTelescopicPipe.cs | 3 +++ 33 files changed, 92 insertions(+) diff --git a/Source/KSPDev_candidates/Hierarchy2.cs b/Source/KSPDev_candidates/Hierarchy2.cs index 3fedbbbb8..0d3f91170 100644 --- a/Source/KSPDev_candidates/Hierarchy2.cs +++ b/Source/KSPDev_candidates/Hierarchy2.cs @@ -3,6 +3,7 @@ // This software is distributed under Public domain license. using UnityEngine; +// ReSharper disable once CheckNamespace namespace KSPDev.ModelUtils { /// Various tools to deal with game object hierarchy. diff --git a/Source/api_impl/AttachNodesUtilsImpl.cs b/Source/api_impl/AttachNodesUtilsImpl.cs index a3f273ddb..12dd94b20 100644 --- a/Source/api_impl/AttachNodesUtilsImpl.cs +++ b/Source/api_impl/AttachNodesUtilsImpl.cs @@ -8,6 +8,8 @@ using System; using UnityEngine; +// ReSharper disable UseStringInterpolation +// ReSharper disable once CheckNamespace namespace KASImpl { /// Implements KASAPIv2.IAttachNodesUtils. diff --git a/Source/api_impl/CommonConfigImpl.cs b/Source/api_impl/CommonConfigImpl.cs index 581438ce7..8582ad007 100644 --- a/Source/api_impl/CommonConfigImpl.cs +++ b/Source/api_impl/CommonConfigImpl.cs @@ -5,6 +5,9 @@ using KASAPIv2; using KSPDev.ConfigUtils; +// ReSharper disable FieldCanBeMadeReadOnly.Local +// ReSharper disable ConvertToConstant.Local +// ReSharper disable once CheckNamespace namespace KASImpl { /// Container for the various global settings of the mod. diff --git a/Source/api_impl/JointUtilsImpl.cs b/Source/api_impl/JointUtilsImpl.cs index 4802a027e..52bf23377 100644 --- a/Source/api_impl/JointUtilsImpl.cs +++ b/Source/api_impl/JointUtilsImpl.cs @@ -6,6 +6,8 @@ using System.Text; using UnityEngine; +// ReSharper disable UseStringInterpolation +// ReSharper disable once CheckNamespace namespace KASImpl { class JointUtilsImpl : KASAPIv2.IJointUtils { diff --git a/Source/api_impl/KASAPILauncher.cs b/Source/api_impl/KASAPILauncher.cs index 0061c356b..57f781bc8 100644 --- a/Source/api_impl/KASAPILauncher.cs +++ b/Source/api_impl/KASAPILauncher.cs @@ -6,9 +6,13 @@ using KSPDev.LogUtils; using UnityEngine; +// ReSharper disable once CheckNamespace +// ReSharper disable once IdentifierTypo namespace KASAPIv2 { [KSPAddon(KSPAddon.Startup.Instantly, true /*once*/)] +// ReSharper disable once InconsistentNaming +// ReSharper disable once IdentifierTypo internal sealed class KASAPILauncher : MonoBehaviour { void Awake() { if (!KASAPI.isLoaded) { diff --git a/Source/api_impl/KasEventsImpl.cs b/Source/api_impl/KasEventsImpl.cs index e4206ec3e..030853c75 100644 --- a/Source/api_impl/KasEventsImpl.cs +++ b/Source/api_impl/KasEventsImpl.cs @@ -4,6 +4,7 @@ using KASAPIv2; +// ReSharper disable once CheckNamespace namespace KASImpl { /// Defines global events that are triggered by KAS. diff --git a/Source/api_impl/KasLinkEventImpl.cs b/Source/api_impl/KasLinkEventImpl.cs index 43ff7cee3..220d2fe05 100644 --- a/Source/api_impl/KasLinkEventImpl.cs +++ b/Source/api_impl/KasLinkEventImpl.cs @@ -2,6 +2,8 @@ // Author: igor.zavoychinskiy@gmail.com // License: Public Domain +// ReSharper disable once CheckNamespace +// ReSharper disable once IdentifierTypo namespace KASAPIv2 { /// A holder for simple source-to-target event. diff --git a/Source/api_impl/LinkUtilsImpl.cs b/Source/api_impl/LinkUtilsImpl.cs index b016138cd..25c38849d 100644 --- a/Source/api_impl/LinkUtilsImpl.cs +++ b/Source/api_impl/LinkUtilsImpl.cs @@ -6,6 +6,7 @@ using KSPDev.LogUtils; using System.Linq; +// ReSharper disable once CheckNamespace namespace KASImpl { class LinkUtilsImpl : ILinkUtils { diff --git a/Source/api_impl/PhysicsUtilsImpl.cs b/Source/api_impl/PhysicsUtilsImpl.cs index e04c2531a..26f1b78fa 100644 --- a/Source/api_impl/PhysicsUtilsImpl.cs +++ b/Source/api_impl/PhysicsUtilsImpl.cs @@ -5,6 +5,7 @@ using KASAPIv2; using UnityEngine; +// ReSharper disable once CheckNamespace namespace KASImpl { class PhysicsUtilsImpl : IPhysicsUtils { diff --git a/Source/compatibility/PatchFilesProcessor.cs b/Source/compatibility/PatchFilesProcessor.cs index 4f6746c54..8171fff0b 100644 --- a/Source/compatibility/PatchFilesProcessor.cs +++ b/Source/compatibility/PatchFilesProcessor.cs @@ -8,12 +8,14 @@ using System; using System.Linq; +// ReSharper disable once CheckNamespace namespace SaveUpgradePipeline.KAS { /// Class that fixes incompatible KAS part in the saved games. [UpgradeModule(LoadContext.SFS | LoadContext.Craft, sfsNodeUrl = "GAME/FLIGHTSTATE/VESSEL/PART", craftNodeUrl = "PART")] +// ReSharper disable once UnusedType.Global internal sealed class PatchFilesProcessor : UpgradeScript { /// Patches per part name. diff --git a/Source/controllers/ControllerPartEditorTool.cs b/Source/controllers/ControllerPartEditorTool.cs index 08ff6e340..ba1f4895b 100644 --- a/Source/controllers/ControllerPartEditorTool.cs +++ b/Source/controllers/ControllerPartEditorTool.cs @@ -7,6 +7,7 @@ using KSPDev.GUIUtils; using UnityEngine; +// ReSharper disable once CheckNamespace namespace KAS.Debug { /// diff --git a/Source/controllers/ControllerWinchRemote.cs b/Source/controllers/ControllerWinchRemote.cs index 470ee9728..bd8b97903 100644 --- a/Source/controllers/ControllerWinchRemote.cs +++ b/Source/controllers/ControllerWinchRemote.cs @@ -11,6 +11,7 @@ using System.Linq; using UnityEngine; +// ReSharper disable once CheckNamespace namespace KAS { /// Unity module that simulates remote control for the winches in the scene. @@ -230,6 +231,7 @@ internal sealed class ControllerWinchRemote : MonoBehaviour, IHasGUI { #region Internal helper types /// Storage for the cached winch state. class WinchState { + // ReSharper disable once InconsistentNaming public string vesselGUID; public string vesselName; public IWinchControl winchModule; diff --git a/Source/debug/KASDebugAdjustableAttribute.cs b/Source/debug/KASDebugAdjustableAttribute.cs index ada22a932..d1b9254a8 100644 --- a/Source/debug/KASDebugAdjustableAttribute.cs +++ b/Source/debug/KASDebugAdjustableAttribute.cs @@ -11,6 +11,7 @@ namespace KAS.Debug { /// Annotate fields, properties and methods with this attribute to have them revealed in the KAS /// part adjustment tool, a KAS built-in ability to tweak the parts in flight. /// +// ReSharper disable once InconsistentNaming public class KASDebugAdjustableAttribute : DebugAdjustableAttribute { /// Debug controls group fro the KAS modules. diff --git a/Source/modules/AbstractJoint.cs b/Source/modules/AbstractJoint.cs index a24f083cd..36aeb70ce 100644 --- a/Source/modules/AbstractJoint.cs +++ b/Source/modules/AbstractJoint.cs @@ -15,6 +15,8 @@ using System.Text; using UnityEngine; +// ReSharper disable InheritdocInvalidUsage +// ReSharper disable once CheckNamespace namespace KAS { /// Module that implements basic logic for a physical joint on a KAS part. @@ -354,6 +356,7 @@ protected List joints { /// These objects will be destoyed on the joints clean up. /// /// + // ReSharper disable once MemberCanBePrivate.Global protected List customExtraObjects { get; } = new List(); #endregion diff --git a/Source/modules/AbstractLinkPeer.cs b/Source/modules/AbstractLinkPeer.cs index 1914cfdeb..ff197440d 100644 --- a/Source/modules/AbstractLinkPeer.cs +++ b/Source/modules/AbstractLinkPeer.cs @@ -11,6 +11,8 @@ using System.Linq; using UnityEngine; +// ReSharper disable InheritdocInvalidUsage +// ReSharper disable once CheckNamespace namespace KAS { /// Base class that handles the basic functionality of the link's end. diff --git a/Source/modules/AbstractPipeRenderer.cs b/Source/modules/AbstractPipeRenderer.cs index 1c7b1e2de..dcf284c3a 100644 --- a/Source/modules/AbstractPipeRenderer.cs +++ b/Source/modules/AbstractPipeRenderer.cs @@ -14,6 +14,7 @@ using System.Linq; using UnityEngine; +// ReSharper disable once CheckNamespace namespace KAS { /// Base class for the renderers that represent the links as a "pipe". @@ -205,6 +206,7 @@ protected Material pipeMaterial { /// It can be null if the target is not a part or the renderer is not started. /// /// + // ReSharper disable once MemberCanBePrivate.Global protected Part targetPart { get; private set; } #endregion diff --git a/Source/modules/AbstractProceduralModel.cs b/Source/modules/AbstractProceduralModel.cs index 715d2a0a2..7ab137f90 100644 --- a/Source/modules/AbstractProceduralModel.cs +++ b/Source/modules/AbstractProceduralModel.cs @@ -10,6 +10,8 @@ using KSPDev.ProcessingUtils; using UnityEngine; +// ReSharper disable MemberCanBePrivate.Global +// ReSharper disable once CheckNamespace namespace KAS { /// Base class for the parts that dynamically create their model on the game load. diff --git a/Source/modules/KASInternalBrokenJointListener.cs b/Source/modules/KASInternalBrokenJointListener.cs index 86879b59f..c4978749b 100644 --- a/Source/modules/KASInternalBrokenJointListener.cs +++ b/Source/modules/KASInternalBrokenJointListener.cs @@ -7,6 +7,7 @@ using KSPDev.LogUtils; using UnityEngine; +// ReSharper disable once CheckNamespace namespace KAS { /// @@ -26,6 +27,7 @@ namespace KAS { /// overcome this limitation, an extra game object and this component can be used: /// /// +// ReSharper disable once InconsistentNaming internal sealed class KASInternalBrokenJointListener : MonoBehaviour, // KSP syntax sugar interfaces. IJointEventsListener { diff --git a/Source/modules/KASInternalPhysicalConnector.cs b/Source/modules/KASInternalPhysicalConnector.cs index c65dfb5a7..bebcb508d 100644 --- a/Source/modules/KASInternalPhysicalConnector.cs +++ b/Source/modules/KASInternalPhysicalConnector.cs @@ -7,6 +7,7 @@ using KSPDev.PartUtils; using UnityEngine; +// ReSharper disable once CheckNamespace namespace KAS { /// Module for handling physics on a flexible link connector. @@ -23,6 +24,7 @@ namespace KAS { /// /// /// +// ReSharper disable once InconsistentNaming internal sealed class KASInternalPhysicalConnector : MonoBehaviour { #region Factory methods (static) /// Promotes the specified object into a physical connector object. @@ -68,6 +70,7 @@ public static KASInternalPhysicalConnector Promote( /// Tells the owner part is being cleaned up and the object don't need to die immediately. /// /// false if the connector was not physical. + // ReSharper disable once UnusedMethodReturnValue.Global public static bool Demote(GameObject obj, bool cleanupMode) { var connectorModule = obj.GetComponent(); if (connectorModule == null) { diff --git a/Source/modules/KASJointCableBase.cs b/Source/modules/KASJointCableBase.cs index 02ca41534..974ed1cf4 100644 --- a/Source/modules/KASJointCableBase.cs +++ b/Source/modules/KASJointCableBase.cs @@ -10,6 +10,7 @@ using System.Text; using UnityEngine; +// ReSharper disable once CheckNamespace namespace KAS { /// Module that controls a physical cable joint on a KAS part. @@ -19,6 +20,8 @@ namespace KAS { /// by default, i.e. the source and the target can collide. /// // Next localization ID: #kasLOC_09002. +// ReSharper disable once ClassWithVirtualMembersNeverInherited.Global +// ReSharper disable once InconsistentNaming public class KASJointCableBase : AbstractJoint, // KSP interfaces. IJointLockState, diff --git a/Source/modules/KASJointRigid.cs b/Source/modules/KASJointRigid.cs index b2e8cf3f4..bb5b5b7d4 100644 --- a/Source/modules/KASJointRigid.cs +++ b/Source/modules/KASJointRigid.cs @@ -4,10 +4,12 @@ using KSPDev.LogUtils; +// ReSharper disable once CheckNamespace namespace KAS { /// Module that controls a stock-alike physical joint on a KAS part. /// This module handles all the stock attach node settings. +// ReSharper disable once InconsistentNaming public class KASJointRigid : AbstractJoint { #region AbstractLinkJoint overrides diff --git a/Source/modules/KASJointTowBar.cs b/Source/modules/KASJointTowBar.cs index 4c60871e0..8470a2c45 100644 --- a/Source/modules/KASJointTowBar.cs +++ b/Source/modules/KASJointTowBar.cs @@ -10,6 +10,7 @@ using System.Collections.Generic; using UnityEngine; +// ReSharper disable once CheckNamespace namespace KAS { /// Flexible link joint designed specifically for towing vessels. @@ -23,6 +24,7 @@ namespace KAS { /// /// // Next localization ID: #kasLOC_05020. +// ReSharper disable once InconsistentNaming public sealed class KASJointTowBar : KASJointTwoEndsSphere, // KSPDev sugar interfaces. IsPhysicalObject, diff --git a/Source/modules/KASJointTwoEndsSphere.cs b/Source/modules/KASJointTwoEndsSphere.cs index 7e9717dd2..68a25aa81 100644 --- a/Source/modules/KASJointTwoEndsSphere.cs +++ b/Source/modules/KASJointTwoEndsSphere.cs @@ -7,6 +7,8 @@ using KSPDev.LogUtils; using UnityEngine; +// ReSharper disable InheritdocInvalidUsage +// ReSharper disable once CheckNamespace namespace KAS { /// Module that offers a highly configurable setup of two PhysX joints. @@ -19,12 +21,14 @@ namespace KAS { /// /// /// PhysX: Spherical joint +// ReSharper disable once InconsistentNaming public class KASJointTwoEndsSphere : AbstractJoint, // KSP interfaces. IJointLockState, // KAS interfaces. IKasJointEventsListener, // KSPDev syntax sugar interfaces. + // ReSharper disable once RedundantExtendsListEntry IsDestroyable, IKSPDevJointLockState { #region Part's config fields diff --git a/Source/modules/KASLinkResourceConnector.cs b/Source/modules/KASLinkResourceConnector.cs index 4373161dd..fca452992 100644 --- a/Source/modules/KASLinkResourceConnector.cs +++ b/Source/modules/KASLinkResourceConnector.cs @@ -14,12 +14,14 @@ using System.Linq; using UnityEngine; +// ReSharper disable once CheckNamespace namespace KAS { /// Module which transfer resources between two linked vessels. /// // Next localization ID: #kasLOC_12017 [PersistentFieldsDatabase("KAS/settings/KASConfig")] +// ReSharper disable once InconsistentNaming public sealed class KASLinkResourceConnector : KASLinkSourcePhysical, // KAS interfaces. IHasGUI { @@ -227,9 +229,12 @@ public sealed class KASLinkResourceConnector : KASLinkSourcePhysical, public List resourceOverride = new List(); /// Container for the fuel mixutre component. + // ReSharper disable once ClassNeverInstantiated.Global public class FuelMixtureComponent { /// Name of the resource. [PersistentField("name")] + // ReSharper disable once FieldCanBeMadeReadOnly.Global + // ReSharper disable once ConvertToConstant.Global public string name = ""; /// @@ -237,13 +242,18 @@ public class FuelMixtureComponent { /// 1.0 to get the percentage. /// [PersistentField("ratio")] + // ReSharper disable once FieldCanBeMadeReadOnly.Global + // ReSharper disable once ConvertToConstant.Global public double ratio; } /// Container for the fuel mixture. + // ReSharper disable once ClassNeverInstantiated.Global public class FuelMixture { /// The mixture components. [PersistentField("component", isCollection = true)] + // ReSharper disable once CollectionNeverUpdated.Global + // ReSharper disable once FieldCanBeMadeReadOnly.Global public List components = new List(); } diff --git a/Source/modules/KASLinkSourceBase.cs b/Source/modules/KASLinkSourceBase.cs index d8b1b5bff..81af3383c 100644 --- a/Source/modules/KASLinkSourceBase.cs +++ b/Source/modules/KASLinkSourceBase.cs @@ -14,6 +14,8 @@ using System.Text; using UnityEngine; +// ReSharper disable InheritdocInvalidUsage +// ReSharper disable once CheckNamespace namespace KAS { /// Base link source module. Does all the job on making two parts linked. @@ -32,6 +34,7 @@ namespace KAS { // Next localization ID: #kasLOC_02008. // TODO(ihsoft): Handle KIS actions. // TODO(ihsoft): Handle part staged action. +// ReSharper disable once InconsistentNaming public class KASLinkSourceBase : AbstractLinkPeer, // KSP interfaces. IModuleInfo, @@ -685,6 +688,7 @@ protected virtual void PhysicalUnlink() { /// /// An empty array if the link can be created, or a list of user friendly errors otherwise. /// + // ReSharper disable once VirtualMemberNeverOverridden.Global protected virtual string[] CheckBasicLinkConditions(ILinkTarget target, bool checkStates) { var errors = new List(); if (checkStates) { diff --git a/Source/modules/KASLinkSourceInteractive.cs b/Source/modules/KASLinkSourceInteractive.cs index f359ac002..c7dd149eb 100644 --- a/Source/modules/KASLinkSourceInteractive.cs +++ b/Source/modules/KASLinkSourceInteractive.cs @@ -12,6 +12,7 @@ using System.Linq; using UnityEngine; +// ReSharper disable once CheckNamespace namespace KAS { /// Module that allows connecting the parts by a mouse via GUI. @@ -24,6 +25,7 @@ namespace KAS { /// /// // Next localization ID: #kasLOC_01003. +// ReSharper disable once InconsistentNaming public sealed class KASLinkSourceInteractive : KASLinkSourceBase { #region Localizable GUI strings diff --git a/Source/modules/KASLinkSourcePhysical.cs b/Source/modules/KASLinkSourcePhysical.cs index a2a6f0889..7f10fc04f 100644 --- a/Source/modules/KASLinkSourcePhysical.cs +++ b/Source/modules/KASLinkSourcePhysical.cs @@ -17,6 +17,7 @@ using System.Linq; using UnityEngine; +// ReSharper disable once CheckNamespace namespace KAS { /// Module that allows connecting the parts via an EVA kerbal. @@ -42,6 +43,7 @@ namespace KAS { /// /// // Next localization ID: #kasLOC_13011. +// ReSharper disable once InconsistentNaming public class KASLinkSourcePhysical : KASLinkSourceBase { #region Localizable GUI strings. @@ -365,6 +367,7 @@ protected ILinkCableJoint cableJoint { /// /// The object or null if the connector is not physical. /// + // ReSharper disable once MemberCanBePrivate.Global protected Transform connectorObj { get; private set; } #endregion @@ -756,6 +759,7 @@ protected Transform FindModelOrThrow(Transform root, string path) { /// /// /// + // ReSharper disable once VirtualMemberNeverOverridden.Global protected virtual void SetCableLength(float length) { if (cableJoint != null) { if (!float.IsInfinity(length)) { diff --git a/Source/modules/KASLinkTargetBase.cs b/Source/modules/KASLinkTargetBase.cs index 85010c69b..cdfc90454 100644 --- a/Source/modules/KASLinkTargetBase.cs +++ b/Source/modules/KASLinkTargetBase.cs @@ -12,6 +12,8 @@ using System.Text; using UnityEngine; +// ReSharper disable InheritdocInvalidUsage +// ReSharper disable once CheckNamespace namespace KAS { /// Base link target module. Only controls target link state. @@ -26,6 +28,7 @@ namespace KAS { /// /// // Next localization ID: #kasLOC_03002. +// ReSharper disable once InconsistentNaming public class KASLinkTargetBase : // KSP parents. AbstractLinkPeer, IModuleInfo, @@ -226,6 +229,7 @@ public string GetPrimaryField() { /// /// KAS events listener. /// + // ReSharper disable once VirtualMemberNeverOverridden.Global protected virtual void OnStartLinkingKASEvent(ILinkSource source) { if (CheckCanLinkWith(source)) { SetLinkState(LinkState.AcceptingLinks); @@ -235,6 +239,7 @@ protected virtual void OnStartLinkingKASEvent(ILinkSource source) { /// Cancels the linking mode on this module. /// KAS events listener. /// + // ReSharper disable once VirtualMemberNeverOverridden.Global protected virtual void OnStopLinkingKASEvent(ILinkSource connectionSource) { if (!isLocked) { SetLinkState(LinkState.Available); @@ -253,6 +258,7 @@ protected virtual void OnStopLinkingKASEvent(ILinkSource connectionSource) { /// true if link is technically possible. It's not guaranteed that the link will /// succeed. /// + // ReSharper disable once VirtualMemberNeverOverridden.Global protected virtual bool CheckCanLinkWith(ILinkSource source) { // Cannot attach to itself or incompatible link type. if (part != source.part && cfgLinkType == source.cfgLinkType) { diff --git a/Source/modules/KASLinkTargetKerbal.cs b/Source/modules/KASLinkTargetKerbal.cs index 7633b478b..7338eb489 100644 --- a/Source/modules/KASLinkTargetKerbal.cs +++ b/Source/modules/KASLinkTargetKerbal.cs @@ -16,10 +16,12 @@ using System.Collections.Generic; using UnityEngine; +// ReSharper disable once CheckNamespace namespace KAS { /// Module for the kerbal vessel that allows carrying the cable heads. // Next localization ID: #kasLOC_10004. +// ReSharper disable once InconsistentNaming public sealed class KASLinkTargetKerbal : KASLinkTargetBase, // KAS interfaces. IHasContextMenu, @@ -75,6 +77,7 @@ public sealed class KASLinkTargetKerbal : KASLinkTargetBase, [PersistentField("equipPosAndRot", group = StdPersistentGroups.PartConfigLoadGroup)] [Debug.KASDebugAdjustable("Equip pos&rot")] PosAndRot equipPosAndRot = new PosAndRot(); + // ReSharper disable once FieldCanBeMadeReadOnly.Local #endregion #region Local fields and properties diff --git a/Source/modules/KASLinkWinch.cs b/Source/modules/KASLinkWinch.cs index 75aeda033..f6040a5a4 100644 --- a/Source/modules/KASLinkWinch.cs +++ b/Source/modules/KASLinkWinch.cs @@ -15,6 +15,7 @@ using System.Text; using UnityEngine; +// ReSharper disable once CheckNamespace namespace KAS { /// Module for a simple winch with a deployable connector and a motor. @@ -40,6 +41,8 @@ namespace KAS { /// /// // Next localization ID: #kasLOC_08019. +// ReSharper disable once InconsistentNaming +// ReSharper disable once ClassWithVirtualMembersNeverInherited.Global public class KASLinkWinch : KASLinkSourcePhysical, // KAS interfaces. IWinchControl, @@ -609,6 +612,7 @@ bool CheckIsConnectorAligned(bool logCheckResult) { /// If true then the failed attempt will be logged to GUI. /// /// true if the connector was successfully locked. + // ReSharper disable once UnusedMethodReturnValue.Local bool TryLockingConnector(bool reportIfCannot = true) { if (isLinked && linkTarget.part.vessel.isEVA) { return false; // Silently don't allow docking with a kerbal. diff --git a/Source/modules/KASRendererBezierPipe.cs b/Source/modules/KASRendererBezierPipe.cs index 7e1069f71..def85ab7b 100644 --- a/Source/modules/KASRendererBezierPipe.cs +++ b/Source/modules/KASRendererBezierPipe.cs @@ -5,6 +5,7 @@ using System.Linq; using UnityEngine; +// ReSharper disable once CheckNamespace namespace KAS { /// @@ -22,6 +23,7 @@ namespace KAS { /// /// /// +// ReSharper disable once InconsistentNaming public sealed class KASRendererBezierPipe : KASRendererPipe { #region Part's config fields diff --git a/Source/modules/KASRendererPipe.cs b/Source/modules/KASRendererPipe.cs index e61ce1b84..c1c4d6b47 100644 --- a/Source/modules/KASRendererPipe.cs +++ b/Source/modules/KASRendererPipe.cs @@ -10,6 +10,9 @@ using System; using UnityEngine; +// ReSharper disable FieldCanBeMadeReadOnly.Global +// ReSharper disable ConvertToConstant.Global +// ReSharper disable once CheckNamespace namespace KAS { /// Module that draws a pipe between two nodes. @@ -63,8 +66,10 @@ namespace KAS { /// /// /// +// ReSharper disable once InconsistentNaming public class KASRendererPipe : AbstractPipeRenderer, // KPSDev sugar interfaces. + // ReSharper disable once RedundantExtendsListEntry IsDestroyable { #region Public config types @@ -422,6 +427,7 @@ protected override void SetCollisionIgnores(Part otherPart, bool ignore) { /// /// The object to align the connector to. If it's null, then the model will be parked. /// + // ReSharper disable once VirtualMemberNeverOverridden.Global protected virtual void UpdateJointNode(ModelPipeEndNode node, Transform alignTo) { var config = node.config; var makeProceduralModels = alignTo != null || !config.parkPrefabOnly; diff --git a/Source/modules/KASRendererTelescopicPipe.cs b/Source/modules/KASRendererTelescopicPipe.cs index 2c936f6a1..7d8e6a5d3 100644 --- a/Source/modules/KASRendererTelescopicPipe.cs +++ b/Source/modules/KASRendererTelescopicPipe.cs @@ -15,6 +15,8 @@ using System.Linq; using UnityEngine; +// ReSharper disable RedundantExtendsListEntry +// ReSharper disable once CheckNamespace namespace KAS { /// @@ -22,6 +24,7 @@ namespace KAS { /// the part that can link to another part. /// // Next localization ID: #kasLOC_04004. +// ReSharper disable once InconsistentNaming public sealed class KASRendererTelescopicPipe : AbstractProceduralModel, // KAS interfaces. ILinkRenderer, From 7a86763810e1c1abdaf7dd9336ddfa06d1dae05f Mon Sep 17 00:00:00 2001 From: ihsoft Date: Thu, 30 Jul 2020 16:58:21 -0700 Subject: [PATCH 28/46] Style refactoring - Variable names. - In-place initialization. - Code simplification. --- Source/api_impl/AttachNodesUtilsImpl.cs | 7 +- Source/compatibility/PatchFilesProcessor.cs | 10 +- .../controllers/ControllerPartEditorTool.cs | 29 +- Source/controllers/ControllerWinchRemote.cs | 263 +++++++------- Source/modules/AbstractJoint.cs | 36 +- Source/modules/AbstractPipeRenderer.cs | 49 ++- Source/modules/AbstractProceduralModel.cs | 13 +- .../modules/KASInternalPhysicalConnector.cs | 24 +- Source/modules/KASJointTowBar.cs | 46 +-- Source/modules/KASLinkResourceConnector.cs | 325 +++++++++--------- Source/modules/KASLinkSourceBase.cs | 34 +- Source/modules/KASLinkSourceInteractive.cs | 64 ++-- Source/modules/KASLinkSourcePhysical.cs | 79 ++--- Source/modules/KASLinkTargetBase.cs | 20 +- Source/modules/KASLinkTargetKerbal.cs | 116 ++++--- Source/modules/KASLinkWinch.cs | 40 +-- Source/modules/KASRendererBezierPipe.cs | 75 ++-- Source/modules/KASRendererPipe.cs | 44 ++- Source/modules/KASRendererTelescopicPipe.cs | 244 +++++++------ 19 files changed, 772 insertions(+), 746 deletions(-) diff --git a/Source/api_impl/AttachNodesUtilsImpl.cs b/Source/api_impl/AttachNodesUtilsImpl.cs index 12dd94b20..d197fe79d 100644 --- a/Source/api_impl/AttachNodesUtilsImpl.cs +++ b/Source/api_impl/AttachNodesUtilsImpl.cs @@ -89,9 +89,10 @@ public AttachNode ParseNodeFromString(Part ownerPart, string def, string nodeId) message: "Unexpected number of components", context: ownerPart); try { // The logic is borrowed from PartLoader.ParsePart. - var attachNode = new AttachNode(); - attachNode.owner = ownerPart; - attachNode.id = nodeId; + var attachNode = new AttachNode { + owner = ownerPart, + id = nodeId + }; var factor = ownerPart.rescaleFactor; attachNode.position = new Vector3( float.Parse(array[0]), float.Parse(array[1]), float.Parse(array[2])) * factor; diff --git a/Source/compatibility/PatchFilesProcessor.cs b/Source/compatibility/PatchFilesProcessor.cs index 8171fff0b..2f2c5bb38 100644 --- a/Source/compatibility/PatchFilesProcessor.cs +++ b/Source/compatibility/PatchFilesProcessor.cs @@ -20,7 +20,7 @@ internal sealed class PatchFilesProcessor : UpgradeScript { /// Patches per part name. /// The patches are ordered by timestamp. - Dictionary> partPatches; + Dictionary> _partPatches; #region implemented abstract members of UpgradeScript /// @@ -34,7 +34,7 @@ public override TestResult OnTest(ConfigNode node, LoadContext loadContext, ref } List patches; var hasMatches = false; - if (partPatches.TryGetValue(partName, out patches)) { + if (_partPatches.TryGetValue(partName, out patches)) { for (var i = patches.Count - 1; i >= 0; --i) { var patch = patches[i]; try { @@ -54,7 +54,7 @@ public override void OnUpgrade(ConfigNode node, LoadContext loadContext, ConfigN var partName = PartNodePatcher.GetPartNameFromUpgradeNode(node, loadContext); DebugEx.Warning("Patch saved game state for part: {0}", partName); var badPatches = new List(); - var applyPatches = partPatches[partName]; + var applyPatches = _partPatches[partName]; foreach (var patch in applyPatches) { try { PartNodePatcher.PatchNode(node, patch, loadContext); @@ -92,14 +92,14 @@ public override void OnUpgrade(ConfigNode node, LoadContext loadContext, ConfigN #region UpgradeScript oevrrides /// protected override void OnInit() { - partPatches = PartNodePatcher.GetPatches("KAS") + _partPatches = PartNodePatcher.GetPatches("KAS") .GroupBy(x => x.testSection.partTests.GetValue("name")) .ToDictionary( x => x.Key, x => x.OrderBy(n => n.patchCreationTimestamp) .ThenBy(n => n.modName) .ToList()); - DebugEx.Fine("Loaded {0} part patch nodes", partPatches.Count); + DebugEx.Fine("Loaded {0} part patch nodes", _partPatches.Count); } /// diff --git a/Source/controllers/ControllerPartEditorTool.cs b/Source/controllers/ControllerPartEditorTool.cs index ba1f4895b..baa64ac61 100644 --- a/Source/controllers/ControllerPartEditorTool.cs +++ b/Source/controllers/ControllerPartEditorTool.cs @@ -23,7 +23,7 @@ internal sealed class ControllerPartEditorTool : MonoBehaviour, /// Keyboard key to trigger the GUI. /// [PersistentField("Debug/partAlignToolKey")] - public string openGUIKey = ""; + public string openGuiKey = ""; #endregion #region Local fields @@ -31,24 +31,25 @@ internal sealed class ControllerPartEditorTool : MonoBehaviour, const string DialogTitle = "KAS part adjustment tool"; /// Dialogs instance. There must be only one in the game. - static PartDebugAdjustmentDialog dlg; + static PartDebugAdjustmentDialog _dlg; /// Keyboard event that opens/closes the remote GUI. - static Event openGUIEvent; + static Event _openGuiEvent; #endregion #region IHasGUI implementation /// public void OnGUI() { - if (openGUIEvent != null && Event.current.Equals(openGUIEvent)) { - Event.current.Use(); - if (dlg == null) { - dlg = DebugGui.MakePartDebugDialog( - DialogTitle, group: Debug.KASDebugAdjustableAttribute.DebugGroup); - } else { - DebugGui.DestroyPartDebugDialog(dlg); - dlg = null; - } + if (_openGuiEvent == null || !Event.current.Equals(_openGuiEvent)) { + return; + } + Event.current.Use(); + if (_dlg == null) { + _dlg = DebugGui.MakePartDebugDialog( + DialogTitle, group: KASDebugAdjustableAttribute.DebugGroup); + } else { + DebugGui.DestroyPartDebugDialog(_dlg); + _dlg = null; } } #endregion @@ -56,8 +57,8 @@ public void OnGUI() { #region MonoBehavour methods void Awake() { ConfigAccessor.ReadFieldsInType(GetType(), instance: this); - if (!string.IsNullOrEmpty(openGUIKey)) { - openGUIEvent = Event.KeyboardEvent(openGUIKey); + if (!string.IsNullOrEmpty(openGuiKey)) { + _openGuiEvent = Event.KeyboardEvent(openGuiKey); } } #endregion diff --git a/Source/controllers/ControllerWinchRemote.cs b/Source/controllers/ControllerWinchRemote.cs index bd8b97903..430007e7d 100644 --- a/Source/controllers/ControllerWinchRemote.cs +++ b/Source/controllers/ControllerWinchRemote.cs @@ -81,15 +81,15 @@ internal sealed class ControllerWinchRemote : MonoBehaviour, IHasGUI { defaultTemplate: "Close GUI", description: "The GUI hint to explain the effect of the close button."); - static readonly Message HightlightWinchBtn = new Message( /// + static readonly Message HighlightWinchBtn = new Message( "#kasLOC_11009", defaultTemplate: "H", description: "The caption for the toggle control (button style) which tells if the winch" + " should be highlighted in the scene. It's better keep the text as short as possible."); - static readonly Message HightlightWinchBtnHint = new Message( /// + static readonly Message HighlightWinchBtnHint = new Message( "#kasLOC_11010", defaultTemplate: "Highlight the winch in the scene", description: "The GUI hint to explain the effect of toggling the control."); @@ -225,7 +225,7 @@ internal sealed class ControllerWinchRemote : MonoBehaviour, IHasGUI { /// Keyboard key to trigger the GUI. /// [PersistentField("Winch/remoteControlKey")] - public string openGUIKey = "&P"; // Alt+P + public string openGuiKey = "&P"; // Alt+P #endregion #region Internal helper types @@ -246,63 +246,63 @@ class WinchState { #endregion #region GUI styles and contents - GUIStyle guiNoWrapStyle; - GUIStyle guiNoWrapCenteredStyle; + GUIStyle _guiNoWrapStyle; + GUIStyle _guiNoWrapCenteredStyle; // These fields are set/updated in LoadLocalizedContent. - GUIContent highlightWinchCnt; - GUIContent startRetractingCnt; - GUIContent startExtendingCnt; - GUIContent retractCnt; - GUIContent extendCnt; - GUIContent winchModeOfflineCnt; - GUIContent winchModeBlockedCnt; - GUIContent winchModeRetractedCnt; - GUIContent motorSpeedSettingsCnt; - GUIContent cableStatusCnt; - GUIContent motorSpeedCnt; - GUIContent releaseBtnCnt; - GUIContent stretchBtnCnt; - GUIContent detachBtnCnt; - GUIContent closeGuiCnt; - float winchCableStatusMinWidth = 0; + GUIContent _highlightWinchCnt; + GUIContent _startRetractingCnt; + GUIContent _startExtendingCnt; + GUIContent _retractCnt; + GUIContent _extendCnt; + GUIContent _winchModeOfflineCnt; + GUIContent _winchModeBlockedCnt; + GUIContent _winchModeRetractedCnt; + GUIContent _motorSpeedSettingsCnt; + GUIContent _cableStatusCnt; + GUIContent _motorSpeedCnt; + GUIContent _releaseBtnCnt; + GUIContent _stretchBtnCnt; + GUIContent _detachBtnCnt; + GUIContent _closeGuiCnt; + float _winchCableStatusMinWidth; #endregion #region Local fields /// Cached module states. /// The key is the part's flight ID. - Dictionary sceneModules = new Dictionary(); + Dictionary _sceneModules = new Dictionary(); /// Ordered collection to use to draw the list in GUI. - WinchState[] sortedSceneModules; + WinchState[] _sortedSceneModules; /// Actual screen position of the console window. /// TODO(ihsoft): Persist and restore. - static Rect windowRect = new Rect(100, 100, 1, 1); + static Rect _windowRect = new Rect(100, 100, 1, 1); /// A title bar location. - static Rect titleBarRect = new Rect(0, 0, 10000, 20); + static readonly Rect TitleBarRect = new Rect(0, 0, 10000, 20); /// A list of actions to apply at the end of the GUI frame. - static readonly GuiActionsList guiActions = new GuiActionsList(); + static readonly GuiActionsList GuiActions = new GuiActionsList(); /// Style to draw a control of the minimum size. static readonly GUILayoutOption MinSizeLayout = GUILayout.ExpandWidth(false); /// Keyboard event that opens/closes the remote GUI. - static Event openGUIEvent; + static Event _openGuiEvent; - static ControllerWinchRemote instance; + static ControllerWinchRemote _instance; /// Tells if GUI is open. - bool isGUIOpen; + bool _isGuiOpen; /// Tells if the list of cached winches needs to be refreshed. /// This value is ched on every frame update, so don't update it too frequently - bool modulesNeedUpdate; + bool _modulesNeedUpdate; /// GUI table to align winch status fields. /// Cable status + Motor status - readonly GUILayoutStringTable guiWinchTable = new GUILayoutStringTable(2); + readonly GUILayoutStringTable _guiWinchTable = new GUILayoutStringTable(2); #endregion #region IHasGUI implementation @@ -311,13 +311,13 @@ public void OnGUI() { if (Time.timeScale <= float.Epsilon) { return; // No events and menu in the paused mode. } - if (Event.current.Equals(openGUIEvent)) { + if (Event.current.Equals(_openGuiEvent)) { Event.current.Use(); - ToggleGUI(!isGUIOpen); + ToggleGui(!_isGuiOpen); } - if (isGUIOpen) { - windowRect = GUILayout.Window( - GetInstanceID(), windowRect, ConsoleWindowFunc, WindowTitleTxt.Format(openGUIEvent), + if (_isGuiOpen) { + _windowRect = GUILayout.Window( + GetInstanceID(), _windowRect, ConsoleWindowFunc, WindowTitleTxt.Format(_openGuiEvent), GUILayout.MaxHeight(1), GUILayout.MaxWidth(1)); } } @@ -325,16 +325,17 @@ public void OnGUI() { #region Methods for the outer modules /// Open the winches GUI. - public static void ToggleGUI(bool isVisible) { - if (instance != null) { - if (isVisible) { - instance.isGUIOpen = true; - instance.modulesNeedUpdate = true; - } else { - instance.isGUIOpen = false; - } - DebugEx.Fine("Toggle winch remote control GUI: {0}", instance.isGUIOpen); + public static void ToggleGui(bool isVisible) { + if (_instance == null) { + return; + } + if (isVisible) { + _instance._isGuiOpen = true; + _instance._modulesNeedUpdate = true; + } else { + _instance._isGuiOpen = false; } + DebugEx.Fine("Toggle winch remote control GUI: {0}", _instance._isGuiOpen); } #endregion @@ -342,8 +343,8 @@ public static void ToggleGUI(bool isVisible) { void Awake() { DebugEx.Info("Winch remote controller created"); ConfigAccessor.ReadFieldsInType(GetType(), this); - openGUIEvent = Event.KeyboardEvent(openGUIKey); - instance = this; + _openGuiEvent = Event.KeyboardEvent(openGuiKey); + _instance = this; LoadLocalizedContent(); GameEvents.onLanguageSwitched.Add(LoadLocalizedContent); GameEvents.onVesselWasModified.Add(OnVesselUpdated); @@ -353,7 +354,7 @@ void Awake() { void OnDestroy() { DebugEx.Info("Winch remote controller destroyed"); - instance = null; + _instance = null; GameEvents.onLanguageSwitched.Remove(LoadLocalizedContent); GameEvents.onVesselWasModified.Remove(OnVesselUpdated); GameEvents.onVesselDestroy.Remove(OnVesselUpdated); @@ -366,30 +367,29 @@ void OnDestroy() { void ConsoleWindowFunc(int windowId) { MakeGuiStyles(); - if (guiActions.ExecutePendingGuiActions()) { + if (GuiActions.ExecutePendingGuiActions()) { MaybeUpdateModules(); - guiWinchTable.UpdateFrame(); + _guiWinchTable.UpdateFrame(); } - if (sortedSceneModules.Length == 0) { - GUILayout.Label(NoContentTxt, guiNoWrapStyle); + if (_sortedSceneModules.Length == 0) { + GUILayout.Label(NoContentTxt, _guiNoWrapStyle); } // TODO(ihsoft): Add paging and the setting for the number of items per page. // Render the winch items if any. - for (var i = 0; i < sortedSceneModules.Length; i++) { - var winchState = sortedSceneModules[i]; + foreach (var winchState in _sortedSceneModules) { var winch = winchState.winchModule; var winchCable = winchState.winchModule.linkJoint as ILinkCableJoint; - var disableWinchGUI = + var disableWinchGui = !winch.part.vessel.IsControllable || winch.isNodeBlocked || winch.isLocked; var motorSpeed = winchState.motorSpeedSetting * winch.cfgMotorMaxSpeed; - guiWinchTable.StartNewRow(); + _guiWinchTable.StartNewRow(); using (new GUILayout.HorizontalScope(GUI.skin.box)) { // Winch highlighting column. winchState.highlighted = GUILayoutButtons.Toggle( - winchState.highlighted, highlightWinchCnt, GUI.skin.button, null, + winchState.highlighted, _highlightWinchCnt, GUI.skin.button, null, fnOn: () => { winch.part.SetHighlight(true, false); winch.part.SetHighlightType(Part.HighlightType.AlwaysOn); @@ -397,91 +397,92 @@ void ConsoleWindowFunc(int windowId) { fnOff: () => { winch.part.SetHighlightDefault(); }, - actionsList: guiActions); + actionsList: GuiActions); // Cable retracting controls. - using (new GuiEnabledStateScope(!disableWinchGUI && winchCable.realCableLength > 0)) { + using (new GuiEnabledStateScope(!disableWinchGui && winchCable.realCableLength > 0)) { // Start retracting the cable column. winchState.retractBtnPressed &= winch.motorTargetSpeed < 0; winchState.retractBtnPressed = GUILayoutButtons.Toggle( winchState.retractBtnPressed, - startRetractingCnt, + _startRetractingCnt, GUI.skin.button, new[] {MinSizeLayout}, fnOn: () => winch.SetMotor(-motorSpeed), fnOff: () => winch.SetMotor(0), - actionsList: guiActions); + actionsList: GuiActions); // Retract the cable column. winchState.retracting &= winch.motorTargetSpeed < 0; winchState.retracting = GUILayoutButtons.Push( winchState.retracting, - retractCnt, + _retractCnt, GUI.skin.button, new[] {MinSizeLayout}, fnPush: () => winch.SetMotor(-motorSpeed), fnRelease: () => winch.SetMotor(0), - actionsList: guiActions); + actionsList: GuiActions); } // Cable length/status column. if (!winch.part.vessel.IsControllable) { - guiWinchTable.AddTextColumn( - winchModeOfflineCnt, guiNoWrapCenteredStyle, minWidth: winchCableStatusMinWidth); + _guiWinchTable.AddTextColumn( + _winchModeOfflineCnt, _guiNoWrapCenteredStyle, minWidth: _winchCableStatusMinWidth); } else if (winch.isNodeBlocked || winch.isLocked) { - guiWinchTable.AddTextColumn( - winchModeBlockedCnt, guiNoWrapCenteredStyle, minWidth: winchCableStatusMinWidth); + _guiWinchTable.AddTextColumn( + _winchModeBlockedCnt, _guiNoWrapCenteredStyle, minWidth: _winchCableStatusMinWidth); } else if (winch.isConnectorLocked) { - guiWinchTable.AddTextColumn( - winchModeRetractedCnt, guiNoWrapCenteredStyle, minWidth: winchCableStatusMinWidth); + _guiWinchTable.AddTextColumn( + _winchModeRetractedCnt, _guiNoWrapCenteredStyle, minWidth: _winchCableStatusMinWidth); } else { - cableStatusCnt.text = winchCable.realCableLength <= winch.currentCableLength + _cableStatusCnt.text = winchCable.realCableLength <= winch.currentCableLength ? RelaxedCableLengthTxt.Format(winch.currentCableLength, winchCable.realCableLength) : StrainedCableLengthTxt.Format(winch.currentCableLength, winchCable.realCableLength); - guiWinchTable.AddTextColumn( - cableStatusCnt, guiNoWrapCenteredStyle, minWidth: winchCableStatusMinWidth); + _guiWinchTable.AddTextColumn( + _cableStatusCnt, _guiNoWrapCenteredStyle, minWidth: _winchCableStatusMinWidth); } // Cable extending controls. using (new GuiEnabledStateScope( - !disableWinchGUI && winchCable.deployedCableLength < winch.cfgMaxCableLength)) { + !disableWinchGui && winchCable.deployedCableLength < winch.cfgMaxCableLength)) { // Start extending the cable column. winchState.extendBtnPressed &= winch.motorTargetSpeed > 0; winchState.extendBtnPressed = GUILayoutButtons.Toggle( winchState.extendBtnPressed, - startExtendingCnt, + _startExtendingCnt, GUI.skin.button, new[] {MinSizeLayout}, fnOn: () => winch.SetMotor(motorSpeed), fnOff: () => winch.SetMotor(0), - actionsList: guiActions); + actionsList: GuiActions); // Extend the cable column. winchState.extending &= winch.motorTargetSpeed > 0; winchState.extending = GUILayoutButtons.Push( winchState.extending, - extendCnt, + _extendCnt, GUI.skin.button, new[] {MinSizeLayout}, fnPush: () => winch.SetMotor(motorSpeed), fnRelease: () => winch.SetMotor(0), - actionsList: guiActions); + actionsList: GuiActions); } - using (new GuiEnabledStateScope(!disableWinchGUI)) { + using (new GuiEnabledStateScope(!disableWinchGui)) { // Motor speed settings column. - using (new GUILayout.VerticalScope(motorSpeedSettingsCnt, GUI.skin.label)) { + using (new GUILayout.VerticalScope(_motorSpeedSettingsCnt, GUI.skin.label)) { GUI.changed = false; GUILayout.FlexibleSpace(); var newMotorSpeedSetting = GUILayout.HorizontalSlider( winchState.motorSpeedSetting, 0.1f, 1.0f, GUILayout.Width(100f)); if (GUI.changed) { - guiActions.Add(() => { - winchState.motorSpeedSetting = newMotorSpeedSetting; + var state = winchState; + GuiActions.Add(() => { + state.motorSpeedSetting = newMotorSpeedSetting; var newSpeed = newMotorSpeedSetting * winch.cfgMotorMaxSpeed; - if (winchState.extending || winchState.extendBtnPressed) { + if (state.extending || state.extendBtnPressed) { winch.SetMotor(newSpeed); } - if (winchState.retracting || winchState.retractBtnPressed) { + if (state.retracting || state.retractBtnPressed) { winch.SetMotor(-newSpeed); } }); @@ -490,81 +491,83 @@ void ConsoleWindowFunc(int windowId) { } // Motor speed info column. - motorSpeedCnt.text = MotorSpeedTxt.Format(Mathf.Abs(winch.motorCurrentSpeed), motorSpeed); - guiWinchTable.AddTextColumn( - motorSpeedCnt, guiNoWrapCenteredStyle, minWidth: MotorSpeedTxt.guiTags.minWidth); + _motorSpeedCnt.text = MotorSpeedTxt.Format(Mathf.Abs(winch.motorCurrentSpeed), motorSpeed); + _guiWinchTable.AddTextColumn( + _motorSpeedCnt, _guiNoWrapCenteredStyle, minWidth: MotorSpeedTxt.guiTags.minWidth); // Release cable column. using (new GuiEnabledStateScope( - !disableWinchGUI && winch.currentCableLength < winch.cfgMaxCableLength)) { - if (GUILayout.Button(releaseBtnCnt, GUI.skin.button, MinSizeLayout)) { - guiActions.Add(winch.ReleaseCable); + !disableWinchGui && winch.currentCableLength < winch.cfgMaxCableLength)) { + if (GUILayout.Button(_releaseBtnCnt, GUI.skin.button, MinSizeLayout)) { + GuiActions.Add(winch.ReleaseCable); } } // Stretch cable column. - using (new GuiEnabledStateScope(!disableWinchGUI && !winch.isConnectorLocked)) { - if (GUILayout.Button(stretchBtnCnt, GUI.skin.button, MinSizeLayout)) { - guiActions.Add(winch.StretchCable); + using (new GuiEnabledStateScope(!disableWinchGui && !winch.isConnectorLocked)) { + if (GUILayout.Button(_stretchBtnCnt, GUI.skin.button, MinSizeLayout)) { + GuiActions.Add(winch.StretchCable); } } // Disconnect connector column. - using (new GuiEnabledStateScope(!disableWinchGUI && winch.isLinked)) { - if (GUILayout.Button(detachBtnCnt, GUI.skin.button, MinSizeLayout)) { - guiActions.Add(() => winch.BreakCurrentLink(LinkActorType.Player)); + using (new GuiEnabledStateScope(!disableWinchGui && winch.isLinked)) { + if (GUILayout.Button(_detachBtnCnt, GUI.skin.button, MinSizeLayout)) { + GuiActions.Add(() => winch.BreakCurrentLink(LinkActorType.Player)); } } } } using (new GUILayout.HorizontalScope()) { - if (GUILayout.Button(closeGuiCnt, MinSizeLayout)) { - guiActions.Add(() => isGUIOpen = false); + if (GUILayout.Button(_closeGuiCnt, MinSizeLayout)) { + GuiActions.Add(() => _isGuiOpen = false); } GUILayout.Label(""); GUI.Label(GUILayoutUtility.GetLastRect(), GUI.tooltip); } // Allow the window to be dragged by its title bar. - GuiWindow.DragWindow(ref windowRect, titleBarRect); + GuiWindow.DragWindow(ref _windowRect, TitleBarRect); } /// Creates the styles. Only does it once. void MakeGuiStyles() { - if (guiNoWrapStyle == null) { - guiNoWrapStyle = new GUIStyle(GUI.skin.label); - guiNoWrapStyle.stretchHeight = true; - guiNoWrapStyle.wordWrap = false; - guiNoWrapStyle.alignment = TextAnchor.MiddleLeft; - guiNoWrapCenteredStyle = new GUIStyle(guiNoWrapStyle); - guiNoWrapCenteredStyle.alignment = TextAnchor.MiddleCenter; + if (_guiNoWrapStyle == null) { + _guiNoWrapStyle = new GUIStyle(GUI.skin.label) { + stretchHeight = true, + wordWrap = false, + alignment = TextAnchor.MiddleLeft + }; + _guiNoWrapCenteredStyle = new GUIStyle(_guiNoWrapStyle) { + alignment = TextAnchor.MiddleCenter + }; } } /// Prepares or updates the localizable GUI strings. void LoadLocalizedContent() { - highlightWinchCnt = new GUIContent(HightlightWinchBtn, HightlightWinchBtnHint); - startRetractingCnt = new GUIContent("<<", StartRetractingCableBtnHint); - startExtendingCnt = new GUIContent(">>", StartExtendingCableBtnHint); - retractCnt = new GUIContent("<", RetractCableBtnHint); - extendCnt = new GUIContent(">", ExtendCableBtnHint); - releaseBtnCnt = new GUIContent(ReleaseBtn, ReleaseBtnHint); - stretchBtnCnt = new GUIContent(StretchBtn, StretchBtnHint); - detachBtnCnt = new GUIContent(DetachBtn, DetachBtnHint); - closeGuiCnt = new GUIContent(CloseBtn, CloseBtnHint); - - motorSpeedSettingsCnt = new GUIContent("", MotorSpeedSettingsTxtHint); - cableStatusCnt = new GUIContent("", CableLengthTxtHint); - motorSpeedCnt = new GUIContent("", MotorSpeedStatusTxtHint); + _highlightWinchCnt = new GUIContent(HighlightWinchBtn, HighlightWinchBtnHint); + _startRetractingCnt = new GUIContent("<<", StartRetractingCableBtnHint); + _startExtendingCnt = new GUIContent(">>", StartExtendingCableBtnHint); + _retractCnt = new GUIContent("<", RetractCableBtnHint); + _extendCnt = new GUIContent(">", ExtendCableBtnHint); + _releaseBtnCnt = new GUIContent(ReleaseBtn, ReleaseBtnHint); + _stretchBtnCnt = new GUIContent(StretchBtn, StretchBtnHint); + _detachBtnCnt = new GUIContent(DetachBtn, DetachBtnHint); + _closeGuiCnt = new GUIContent(CloseBtn, CloseBtnHint); + + _motorSpeedSettingsCnt = new GUIContent("", MotorSpeedSettingsTxtHint); + _cableStatusCnt = new GUIContent("", CableLengthTxtHint); + _motorSpeedCnt = new GUIContent("", MotorSpeedStatusTxtHint); MotorSpeedTxt.LoadLocalization(); // To update guiTags. - winchModeOfflineCnt = new GUIContent(WinchModeOfflineTxt, WinchModeOfflineTxtHint); - winchModeBlockedCnt = new GUIContent(WinchModeBlockedTxt, WinchModeBlockedTxtHint); - winchModeRetractedCnt = new GUIContent(WinchModeRetractedTxt, WinchModeRetractedTxtHint); + _winchModeOfflineCnt = new GUIContent(WinchModeOfflineTxt, WinchModeOfflineTxtHint); + _winchModeBlockedCnt = new GUIContent(WinchModeBlockedTxt, WinchModeBlockedTxtHint); + _winchModeRetractedCnt = new GUIContent(WinchModeRetractedTxt, WinchModeRetractedTxtHint); RelaxedCableLengthTxt.LoadLocalization(); // To update guiTags. StrainedCableLengthTxt.LoadLocalization(); // To update guiTags. - winchCableStatusMinWidth = Mathf.Max( + _winchCableStatusMinWidth = Mathf.Max( RelaxedCableLengthTxt.guiTags.minWidth, StrainedCableLengthTxt.guiTags.minWidth, WinchModeOfflineTxt.guiTags.minWidth, @@ -574,17 +577,17 @@ void LoadLocalizedContent() { /// Checks if the cached list of the winch controllers needs to be refreshed. void MaybeUpdateModules() { - if (!modulesNeedUpdate) { + if (!_modulesNeedUpdate) { return; } - modulesNeedUpdate = false; + _modulesNeedUpdate = false; DebugEx.Fine("Updating winch modules..."); - sortedSceneModules = FlightGlobals.VesselsLoaded + _sortedSceneModules = FlightGlobals.VesselsLoaded .Where(v => !v.packed) .SelectMany(v => v.parts) .SelectMany(p => p.Modules.OfType()) - .Select(w => sceneModules.ContainsKey(w.part.flightID) - ? sceneModules[w.part.flightID] + .Select(w => _sceneModules.ContainsKey(w.part.flightID) + ? _sceneModules[w.part.flightID] : new WinchState() { vesselGUID = w.part.vessel.id.ToString(), vesselName = w.part.vessel.vesselName, @@ -594,15 +597,15 @@ void MaybeUpdateModules() { .OrderBy(s => s.vesselGUID) .ThenBy(s => s.flightId) .ToArray(); - sceneModules = sortedSceneModules.ToDictionary(s => s.flightId); - DebugEx.Fine("Found {0} winch modules", sortedSceneModules.Length); + _sceneModules = _sortedSceneModules.ToDictionary(s => s.flightId); + DebugEx.Fine("Found {0} winch modules", _sortedSceneModules.Length); } /// /// Forces an update of the list of the cached winches. It's an expensive operation. /// void OnVesselUpdated(Vessel v) { - modulesNeedUpdate = true; + _modulesNeedUpdate = true; } } diff --git a/Source/modules/AbstractJoint.cs b/Source/modules/AbstractJoint.cs index 36aeb70ce..3137238eb 100644 --- a/Source/modules/AbstractJoint.cs +++ b/Source/modules/AbstractJoint.cs @@ -366,14 +366,14 @@ protected List joints { #endregion #region IHasDebugAdjustables implementation - ILinkSource dbgLinkSource; - ILinkTarget dbgLinkTarget; + ILinkSource _dbgLinkSource; + ILinkTarget _dbgLinkTarget; /// public override void OnBeforeDebugAdjustablesUpdate() { base.OnBeforeDebugAdjustablesUpdate(); - dbgLinkSource = linkSource; - dbgLinkTarget = linkTarget; + _dbgLinkSource = linkSource; + _dbgLinkTarget = linkTarget; } /// @@ -386,7 +386,7 @@ public override void OnDebugAdjustablesUpdated() { HostedDebugLog.Warning( this, "New settings fit the current link. Refreshing the joint..."); DropJoint(); - CreateJoint(dbgLinkSource, dbgLinkTarget); + 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}" @@ -920,10 +920,11 @@ void MaybeBreakLink(ILinkSource source) { /// Updates the vessel info on the part if it has the relevant module. /// The vessel to capture the info for. static DockedVesselInfo GetVesselInfo(Vessel v) { - var vesselInfo = new DockedVesselInfo(); - vesselInfo.name = v.vesselName; - vesselInfo.vesselType = v.vesselType; - vesselInfo.rootPartUId = v.rootPart.flightID; + var vesselInfo = new DockedVesselInfo { + name = v.vesselName, + vesselType = v.vesselType, + rootPartUId = v.rootPart.flightID + }; return vesselInfo; } @@ -964,13 +965,18 @@ void RestorePartialVesselInfo(ILinkSource source, ILinkTarget target, bool weDec void DelegateCouplingRole(Part tgtPart) { AsyncCall.CallOnEndOfFrame(this, () => { var candidates = new List() - .Concat(vessel.parts - .SelectMany(p => p.Modules.OfType()) - .Where(j => !ReferenceEquals(j, this) && j.coupleOnLinkMode && j.isLinked + .Concat( + vessel.parts + .SelectMany(p => p.Modules.OfType()) + .Where( + j => !ReferenceEquals(j, this) && j.coupleOnLinkMode && j.isLinked && j.linkTarget.part.vessel == tgtPart.vessel)) - .Concat(tgtPart.vessel.parts - .SelectMany(p => p.Modules.OfType()) - .Where(j => j.coupleOnLinkMode && j.isLinked && j.linkTarget.part.vessel == vessel)); + .Concat( + tgtPart.vessel.parts + .SelectMany(p => p.Modules.OfType()) + .Where( + j => j.coupleOnLinkMode && j.isLinked && j.linkTarget.part.vessel == vessel)) + .ToList(); foreach (var joint in candidates) { HostedDebugLog.Fine(this, "Trying to couple via: {0}", joint); if (joint.SetCoupleOnLinkMode(true)) { diff --git a/Source/modules/AbstractPipeRenderer.cs b/Source/modules/AbstractPipeRenderer.cs index dcf284c3a..49cee4b44 100644 --- a/Source/modules/AbstractPipeRenderer.cs +++ b/Source/modules/AbstractPipeRenderer.cs @@ -184,9 +184,7 @@ public virtual bool isPhysicalCollider { /// The name is guaranteed to be unique in the part's hierarchy, so it can always be looked up /// once the object is created. /// - protected string ModelBasename { - get { return "$rendererRoot-" + rendererName; } - } + protected string modelBasename => "$rendererRoot-" + rendererName; /// Material to use for the pipe elements. /// It doesn't consider shader or color overrides. @@ -215,12 +213,12 @@ protected Material pipeMaterial { /// /// The only thing it does is calling on every frame update. /// - Coroutine linkUpdateCoroutine; + Coroutine _linkUpdateCoroutine; #endregion #region IHasDebugAdjustables overrides - Transform dbgOldSource; - Transform dbgOldTarget; + Transform _dbgOldSource; + Transform _dbgOldTarget; /// Logs all the part's model objects. [Debug.KASDebugAdjustable("Dump part's model hierarchy")] @@ -236,8 +234,8 @@ public void ShowHierarchyDbgAction() { /// public override void OnBeforeDebugAdjustablesUpdate() { base.OnBeforeDebugAdjustablesUpdate(); - dbgOldSource = sourceTransform; - dbgOldTarget = targetTransform; + _dbgOldSource = sourceTransform; + _dbgOldTarget = targetTransform; StopRenderer(); } @@ -245,10 +243,10 @@ public override void OnBeforeDebugAdjustablesUpdate() { public override void OnDebugAdjustablesUpdated() { _pipeMaterial = null; base.OnDebugAdjustablesUpdated(); - if (dbgOldSource != null && dbgOldTarget != null) { + if (_dbgOldSource != null && _dbgOldTarget != null) { HostedDebugLog.Warning( - this, "Restart renderer: src={0}, tgt={1}", dbgOldSource, dbgOldTarget); - StartRenderer(dbgOldSource, dbgOldTarget); + this, "Restart renderer: src={0}, tgt={1}", _dbgOldSource, _dbgOldTarget); + StartRenderer(_dbgOldSource, _dbgOldTarget); } } #endregion @@ -288,16 +286,16 @@ public virtual void StartRenderer(Transform source, Transform target) { RegisterGameEventListener(GameEvents.onPartDeCouple, OnPartDeCoupleEvent); RegisterGameEventListener(GameEvents.onPartDeCoupleComplete, OnPartDeCoupleCompleteEvent); - linkUpdateCoroutine = StartCoroutine(UpdateLinkCoroutine()); + _linkUpdateCoroutine = StartCoroutine(UpdateLinkCoroutine()); } /// public virtual void StopRenderer() { // Stop meshes updates. - if (linkUpdateCoroutine != null) { + if (_linkUpdateCoroutine != null) { HostedDebugLog.Fine(this, "Stopping renderer updates..."); - StopCoroutine(linkUpdateCoroutine); - linkUpdateCoroutine = null; + StopCoroutine(_linkUpdateCoroutine); + _linkUpdateCoroutine = null; } // Sync the renderers settings to the source part to handle the highlights. @@ -338,7 +336,7 @@ public string[] CheckColliderHits(Transform source, Transform target) { } // HACK: Start the renderer before getting the pipes. var oldStartState = isStarted; - var oldPhyscalState = isPhysicalCollider; + var oldPhysicalState = isPhysicalCollider; if (!isStarted) { isPhysicalCollider = false; StartRenderer(source, target); @@ -348,7 +346,7 @@ public string[] CheckColliderHits(Transform source, Transform target) { var points = GetPipePath(source, target); if (!oldStartState) { StopRenderer(); - isPhysicalCollider = oldPhyscalState; + isPhysicalCollider = oldPhysicalState; } var hitParts = new HashSet(); @@ -452,8 +450,7 @@ void CheckHitsForCapsule(Vector3 startPos, Vector3 endPos, float diameter, Transform target, HashSet hits) { var tgtPart = target.root.GetComponent(); var otherVessel = tgtPart != null ? tgtPart.vessel : null; - Collider[] colliders; - colliders = Physics.OverlapCapsule( + var colliders = Physics.OverlapCapsule( startPos, endPos, diameter / 2.0f, (int)(KspLayerMask.Part | KspLayerMask.SurfaceCollider | KspLayerMask.Kerbal), QueryTriggerInteraction.Ignore); @@ -475,7 +472,7 @@ void CheckHitsForCapsule(Vector3 startPos, Vector3 endPos, float diameter, /// Intermediate field to save the vessel between starting and ending of the part decoupling /// event. /// - Vessel formerTargetVessel; + Vessel _formerTargetVessel; /// Reacts on a part coupling and adjusts its colliders as needed. /// @@ -507,7 +504,7 @@ void OnPartCoupleCompleteEvent(GameEvents.FromToAction action) { void OnPartDeCoupleEvent(Part originator) { if (targetPart != null && targetPart.vessel != vessel && originator.vessel == targetPart.vessel) { - formerTargetVessel = originator.vessel; + _formerTargetVessel = originator.vessel; } } @@ -518,19 +515,19 @@ void OnPartDeCoupleEvent(Part originator) { /// /// The part that has decoupled. void OnPartDeCoupleCompleteEvent(Part originator) { - if (formerTargetVessel != null && originator.vessel != formerTargetVessel) { - // It's either the traget part has decoupled from its vessel, or the owner vessel has + if (_formerTargetVessel != null && originator.vessel != _formerTargetVessel) { + // It's either the target part has decoupled from its vessel, or the owner vessel has // abandoned the target part. - var leavingVessel = originator == targetPart ? formerTargetVessel : originator.vessel; + var leavingVessel = originator == targetPart ? _formerTargetVessel : originator.vessel; HostedDebugLog.Fine(this, "Restore collision ignores on: {0}", leavingVessel); leavingVessel.parts .ForEach(p => SetCollisionIgnores(p, false)); } - formerTargetVessel = null; + _formerTargetVessel = null; } /// Calls renderer updates as long as the renderer is started. - /// + /// /// IEnumerator UpdateLinkCoroutine() { HostedDebugLog.Fine(this, "Staring renderer updates..."); diff --git a/Source/modules/AbstractProceduralModel.cs b/Source/modules/AbstractProceduralModel.cs index 7ab137f90..2f88914ef 100644 --- a/Source/modules/AbstractProceduralModel.cs +++ b/Source/modules/AbstractProceduralModel.cs @@ -117,7 +117,7 @@ protected float baseScale { #region Local fields and properties // Internal cache of the textures used by this renderer (and its descendants). - readonly Dictionary textures = new Dictionary(); + readonly Dictionary _textures = new Dictionary(); /// The shader to sue if no suitable shaders were found. /// @@ -143,9 +143,10 @@ protected virtual Material CreateMaterial(Texture2D mainTex, Texture2D mainTexNrm = null, string overrideShaderName = null, Color? overrideColor = null) { - var material = new Material(GetShader(overrideShaderName: overrideShaderName)); - material.mainTexture = mainTex; - material.color = overrideColor ?? materialColor; + var material = new Material(GetShader(overrideShaderName: overrideShaderName)) { + mainTexture = mainTex, + color = overrideColor ?? materialColor + }; if (mainTexNrm != null) { material.EnableKeyword("_NORMALMAP"); material.SetTexture(isBumpSpecMap ? BumpSpecMapPropName : BumpMapPropName, mainTexNrm); @@ -204,7 +205,7 @@ protected Shader GetShader(string overrideShaderName = null) { protected Texture2D GetTexture(string textureFileName, bool asNormalMap = false, Color? notFoundFillColor = null) { Texture2D texture; - if (!textures.TryGetValue(textureFileName, out texture)) { + if (!_textures.TryGetValue(textureFileName, out texture)) { texture = GameDatabase.Instance.GetTexture(textureFileName, asNormalMap); if (texture == null) { // Use a "red" texture if no file found. @@ -214,7 +215,7 @@ protected Texture2D GetTexture(string textureFileName, bool asNormalMap = false, texture.Apply(); texture.Compress(highQuality: false); } - textures[textureFileName] = texture; + _textures[textureFileName] = texture; } return texture; } diff --git a/Source/modules/KASInternalPhysicalConnector.cs b/Source/modules/KASInternalPhysicalConnector.cs index bebcb508d..ea33e73a9 100644 --- a/Source/modules/KASInternalPhysicalConnector.cs +++ b/Source/modules/KASInternalPhysicalConnector.cs @@ -58,7 +58,7 @@ public static KASInternalPhysicalConnector Promote( collider.isTrigger = true; collider.radius = interactionDistance; interactionTriggerObj.layer = (int) KspLayer.TriggerCollider; - connectorModule.interactionTriggerObj = interactionTriggerObj; + connectorModule._interactionTriggerObj = interactionTriggerObj; } return connectorModule; @@ -119,12 +119,15 @@ public static bool Demote(GameObject obj, bool cleanupMode) { /// be removed. /// public void SetHighlighting(Color? color) { - if (!color.HasValue && connectorRb != null) { + if (connectorRb == null) { + return; + } + if (!color.HasValue) { var headHighlighter = connectorRb.gameObject.GetComponent(); if (headHighlighter != null) { headHighlighter.ConstantOff(); } - } else if (connectorRb != null) { + } else { var headHighlighter = connectorRb.gameObject.GetComponent() ?? connectorRb.gameObject.AddComponent(); headHighlighter.ReinitMaterials(); @@ -133,16 +136,17 @@ public void SetHighlighting(Color? color) { } #endregion - GameObject interactionTriggerObj; + GameObject _interactionTriggerObj; #region MonoBehaviour messages void Awake() { connectorRb = GetComponent(); // Update the highlighters. For this we need changing the hierarchy. - var oldParent = connectorRb.gameObject.transform.parent; - connectorRb.gameObject.transform.parent = null; + var connectorObj = connectorRb.gameObject; + var oldParent = connectorObj.transform.parent; + connectorObj.transform.parent = null; PartModel.UpdateHighlighters(oldParent); - PartModel.UpdateHighlighters(connectorRb.gameObject.transform); + PartModel.UpdateHighlighters(connectorObj.transform); if (connectorRb.isKinematic) { // The kinematic RB must be parented, or else it's considered static. connectorRb.transform.parent = ownerModule.gameObject.transform; @@ -183,12 +187,12 @@ void CleanupModule(bool destroyImmediate = true) { } if (destroyImmediate) { DestroyImmediate(connectorRb); - DestroyImmediate(interactionTriggerObj); + DestroyImmediate(_interactionTriggerObj); } else { Destroy(connectorRb); - Destroy(interactionTriggerObj); + Destroy(_interactionTriggerObj); } - interactionTriggerObj = null; + _interactionTriggerObj = null; connectorRb = null; ownerModule = null; } diff --git a/Source/modules/KASJointTowBar.cs b/Source/modules/KASJointTowBar.cs index 8470a2c45..26a1d88a8 100644 --- a/Source/modules/KASJointTowBar.cs +++ b/Source/modules/KASJointTowBar.cs @@ -49,36 +49,36 @@ public sealed class KASJointTowBar : KASJointTwoEndsSphere, + " locking."); #region SteeringStatus enum values - static readonly Message SteeringStatusMsg_Disabled = new Message( /// + static readonly Message SteeringStatusMsgDisabled = new Message( "#kasLOC_05002", defaultTemplate: "Disabled", description: "A string in the context menu that tells that the active steering mode is not" + " enabled."); - static readonly Message SteeringStatusMsg_Active = new Message( /// + static readonly Message SteeringStatusMsgActive = new Message( "#kasLOC_05003", defaultTemplate: "Active", description: "A string in the context menu that tells that the active steering mode is ready" + " and working."); - static readonly Message SteeringStatusMsg_CurrentVesselIsTarget = new Message( /// + static readonly Message SteeringStatusMsgCurrentVesselIsTarget = new Message( "#kasLOC_05004", defaultTemplate: "Target is active vessel", description: "A string in the context menu that tells that the active steering mode cannot" + " work due to the bar's target vessel is currently under player's control."); - static readonly Message SteeringStatusMsg_TargetIsNotControllable = new Message( /// + static readonly Message SteeringStatusMsgTargetIsNotControllable = new Message( "#kasLOC_05005", defaultTemplate: "Target is uncontrollable", description: "A string in the context menu that tells that the active steering mode cannot" + " work due to the linked vessel is remotely controlled."); - static readonly Message SteeringStatusMsg_NotLocked = new Message( /// + static readonly Message SteeringStatusMsgNotLocked = new Message( "#kasLOC_05006", defaultTemplate: "Not locked", description: "A string in the context menu that tells that the active steering mode is" @@ -88,28 +88,28 @@ public sealed class KASJointTowBar : KASJointTwoEndsSphere, /// Translates enum into a localized message. static readonly MessageLookup SteeringStatusMsgLookup = new MessageLookup(new Dictionary() { - {SteeringStatus.Disabled, SteeringStatusMsg_Disabled}, - {SteeringStatus.Active, SteeringStatusMsg_Active}, - {SteeringStatus.CurrentVesselIsTarget, SteeringStatusMsg_CurrentVesselIsTarget}, - {SteeringStatus.TargetIsNotControllable, SteeringStatusMsg_TargetIsNotControllable}, - {SteeringStatus.NotLocked, SteeringStatusMsg_NotLocked}, + {SteeringStatus.Disabled, SteeringStatusMsgDisabled}, + {SteeringStatus.Active, SteeringStatusMsgActive}, + {SteeringStatus.CurrentVesselIsTarget, SteeringStatusMsgCurrentVesselIsTarget}, + {SteeringStatus.TargetIsNotControllable, SteeringStatusMsgTargetIsNotControllable}, + {SteeringStatus.NotLocked, SteeringStatusMsgNotLocked}, }); #region LockMode enum values - static readonly Message LockStatusMsg_Disabled = new Message( /// + static readonly Message LockStatusMsgDisabled = new Message( "#kasLOC_05007", defaultTemplate: "Disabled", description: "A string in the context menu that tells that the bar joints are unlocked."); - static readonly Message LockStatusMsg_Locked = new Message( /// + static readonly Message LockStatusMsgLocked = new Message( "#kasLOC_05008", defaultTemplate: "Locked", description: "A string in the context menu that tells that the bar joints are locked."); - static readonly Message LockStatusMsg_Locking = new Message( /// + static readonly Message LockStatusMsgLocking = new Message( "#kasLOC_05009", defaultTemplate: "Locking", description: "A string in the context menu that tells that the bar joints are unlocked but" @@ -119,13 +119,13 @@ public sealed class KASJointTowBar : KASJointTwoEndsSphere, /// Translates enum into a localized message. static readonly MessageLookup LockStatusMsgLookup = new MessageLookup(new Dictionary() { - {LockMode.Disabled, LockStatusMsg_Disabled}, - {LockMode.Locked, LockStatusMsg_Locked}, - {LockMode.Locking, LockStatusMsg_Locking}, + {LockMode.Disabled, LockStatusMsgDisabled}, + {LockMode.Locked, LockStatusMsgLocked}, + {LockMode.Locking, LockStatusMsgLocking}, }); /// Status screen message to be displayed during the locking process. - ScreenMessage lockStatusScreenMessage; + ScreenMessage _lockStatusScreenMessage; #endregion #region Part's config fields @@ -268,7 +268,7 @@ public override void OnLoad(ConfigNode node) { /// public override void OnStart(StartState state) { base.OnStart(state); - lockStatusScreenMessage = new ScreenMessage( + _lockStatusScreenMessage = new ScreenMessage( "", ScreenMessaging.DefaultMessageTimeout, ScreenMessageStyle.UPPER_LEFT); if (HighLogic.LoadedSceneIsFlight) { // Trigger updates with the loaded value. @@ -336,7 +336,7 @@ public void ActiveSteeringAction() { tag = "#kasLOC_05017", defaultTemplate = "Disable active steering", description = "A context menu event that disables the active steering mode.")] - public void DeactiveSteeringAction() { + public void DeactivateSteeringAction() { SetActiveSteeringState(false); } #endregion @@ -360,8 +360,8 @@ public void FixedUpdate() { angularLimit.limit = absYaw; trgJoint.angularZLimit = angularLimit; } - lockStatusScreenMessage.message = LockingStatusMsg.Format(yaw); - ScreenMessages.PostScreenMessage(lockStatusScreenMessage); + _lockStatusScreenMessage.message = LockingStatusMsg.Format(yaw); + ScreenMessages.PostScreenMessage(_lockStatusScreenMessage); } } if (persistedActiveSteeringEnabled) { @@ -385,7 +385,7 @@ public void UpdateContextMenu() { this, UnlockAction, e => e.active = isLinked && persistedLockingMode != LockMode.Disabled); PartModuleUtils.SetupEvent( - this, DeactiveSteeringAction, + this, DeactivateSteeringAction, e => e.active = isLinked && persistedActiveSteeringEnabled); PartModuleUtils.SetupEvent( this, ActiveSteeringAction, @@ -427,7 +427,7 @@ void SetLockingMode(LockMode mode, bool updateUi = true) { ScreenMessageStyle.UPPER_LEFT); } if (updateUi && (mode == LockMode.Disabled || mode == LockMode.Locked)) { - ScreenMessages.RemoveMessage(lockStatusScreenMessage); + ScreenMessages.RemoveMessage(_lockStatusScreenMessage); } if (mode == LockMode.Disabled) { SetActiveSteeringState(false); // No active steering in unlocked mode. diff --git a/Source/modules/KASLinkResourceConnector.cs b/Source/modules/KASLinkResourceConnector.cs index fca452992..3230723e3 100644 --- a/Source/modules/KASLinkResourceConnector.cs +++ b/Source/modules/KASLinkResourceConnector.cs @@ -33,8 +33,8 @@ public sealed class KASLinkResourceConnector : KASLinkSourcePhysical, defaultTemplate: "Resource Transfer", description: "The title of the resource transfer dialog."); - static readonly Message resourceName = new Message( /// + static readonly Message ResourceName = new Message( "#kasLOC_12001", defaultTemplate: "<<1>>", description: "The resource in the transfer options table. Its main purpose is dealing" @@ -42,8 +42,8 @@ public sealed class KASLinkResourceConnector : KASLinkSourcePhysical, + "\nArgument <<1>> is the full localized resource name with the Lingoona modifiers" + " (if any)."); - static readonly Message compoundResourceName = /// + static readonly Message CompoundResourceName = new Message( "#kasLOC_12002", defaultTemplate: "<<1>> <<2>>", @@ -54,8 +54,8 @@ public sealed class KASLinkResourceConnector : KASLinkSourcePhysical, + "modifiers (if any).", example: "45 % Ox"); - static readonly Message resourceAmounts = /// + static readonly Message ResourceAmounts = new Message( "#kasLOC_12003", defaultTemplate: "<<1>> / <<2>>", @@ -273,11 +273,11 @@ public class FuelMixture { tag = "#kasLOC_12015", defaultTemplate = "Open GUI", description = "The context menu event that opens the resources transfer GUI.")] - public void OpenGUIEvent() { - if (isLinked && !isGUIOpen) { - isGUIOpen = true; + public void OpenGuiEvent() { + if (isLinked && !_isGuiOpen) { + _isGuiOpen = true; SetPendingTransferOption(null); - resourceListNeedsUpdate = true; + _resourceListNeedsUpdate = true; MaybeUpdateResourceOptionList(); } } @@ -285,75 +285,75 @@ public void OpenGUIEvent() { #region Local fields & properties /// Actual screen position of the console window. - Rect windowRect = new Rect(100, 100, 1, 1); + Rect _windowRect = new Rect(100, 100, 1, 1); /// A title bar location. - Rect titleBarRect = new Rect(0, 0, 10000, 20); + readonly Rect _titleBarRect = new Rect(0, 0, 10000, 20); /// A list of actions to apply at the end of the GUI frame. - readonly GuiActionsList guiActions = new GuiActionsList(); + readonly GuiActionsList _guiActions = new GuiActionsList(); /// Style to draw a control of the minimum size. static readonly GUILayoutOption MinSizeLayout = GUILayout.ExpandWidth(false); /// Tells if GUI is open. - bool isGUIOpen; + bool _isGuiOpen; /// GUI table to align resource names and quantities. /// Left Name + Left Amount + Right Amount + Right Name - readonly GUILayoutStringTable guiResourcesTable = new GUILayoutStringTable(4); + readonly GUILayoutStringTable _guiResourcesTable = new GUILayoutStringTable(4); /// Definition of all the resources for the both linked vessels. - ResourceTransferOption[] resourceRows = new ResourceTransferOption[0]; + ResourceTransferOption[] _resourceRows = new ResourceTransferOption[0]; /// Index of the vessels resources. - Dictionary resourceRowsHash = + Dictionary _resourceRowsHash = new Dictionary(); /// The currently behaving resource transfer. - ResourceTransferOption pendingOption; + ResourceTransferOption _pendingOption; - /// The current resource transafer speed. - float transferSpeed = 1.0f; + /// The current resource transfer speed. + float _transferSpeed = 1.0f; /// Tells if the transfer speed can be managed by the code. - bool autoScaleSpeed; + bool _autoScaleSpeed; /// Model of the cylinder to rotate when the hose is extended/retracted. /// Can be null. - Transform rotaingCylinder; + Transform _rotatingCylinder; /// /// Tells if the resources options need to be refreshed from the attached vessels. /// - bool resourceListNeedsUpdate; + bool _resourceListNeedsUpdate; /// Last time the resources counts were updated in GUI. - float lastResourcesGUIUpdate; + float _lastResourcesGuiUpdate; /// The timeout to update the resources counters in GUI in seconds. /// It's a performance affecting settings. - const float TRANSFER_STATE_UPDATE_PERIOD = 0.1f; + const float TransferStateUpdatePeriod = 0.1f; #endregion #region Cached values - Part currentFromPart; - double[] currentFromPartCapacities; - double[] currentFromPartAmounts; - Part currentToPart; - double[] currentToPartCapacities; - double[] currentToPartAmounts; + Part _currentFromPart; + double[] _currentFromPartCapacities; + double[] _currentFromPartAmounts; + Part _currentToPart; + double[] _currentToPartCapacities; + double[] _currentToPartAmounts; #endregion #region GUI styles & contents - GUIStyle guiNoWrapCenteredStyle; - GUIStyle guiResourceStyle; - GUIStyle guiTransferBtnStyle; - GUIContent autoScaleToggleCnt; - GUIContent leftToRigthToggleCnt; - GUIContent leftToRigthButtonCnt; - GUIContent rightToLeftToggleCnt; - GUIContent rightToLeftButtonCnt; + GUIStyle _guiNoWrapCenteredStyle; + GUIStyle _guiResourceStyle; + GUIStyle _guiTransferBtnStyle; + GUIContent _autoScaleToggleCnt; + GUIContent _leftToRightToggleCnt; + GUIContent _leftToRightButtonCnt; + GUIContent _rightToLeftToggleCnt; + GUIContent _rightToLeftButtonCnt; #endregion #region Local types @@ -373,7 +373,7 @@ class ResourceTransferOption { public bool canMoveLeftToRight; public double previousUpdate; - readonly int hashCode; + readonly int _hashCode; public bool leftToRightTransferToggle { get { return _leftToRightTransferToggle; } @@ -401,16 +401,16 @@ public bool rightToLeftTransferPress { /// public override int GetHashCode() { - return hashCode; + return _hashCode; } /// Makes the transfer option. - /// + /// /// public ResourceTransferOption( - IEnumerable availabeResources, IEnumerable resourceRatio) { - resources = availabeResources.ToArray(); - hashCode = resources.Aggregate((t, v) => ((t << 3) | (t >> 29)) ^ v); + IEnumerable availableResources, IEnumerable resourceRatio) { + resources = availableResources.ToArray(); + _hashCode = resources.Aggregate((t, v) => ((t << 3) | (t >> 29)) ^ v); resourceRatios = resourceRatio.ToArray(); leftAmounts = new double[resources.Length]; leftCapacities = new double[resources.Length]; @@ -422,13 +422,13 @@ public ResourceTransferOption( /// Updates the GUI strings that don't depend on the amounts/capacities. public void UpdateStaticStrings() { if (resources.Length == 1) { - caption.text = resourceName.Format( + caption.text = ResourceName.Format( StockResourceNames.GetResourceTitle(resources[0], removeLingoonaTags: false)); } else { var texts = new string[resources.Length]; var totalAmount = resourceRatios.Sum(); for (var i = 0; i < resources.Length; i++) { - texts[i] = compoundResourceName.Format( + texts[i] = CompoundResourceName.Format( resourceRatios[i] / totalAmount, StockResourceNames.GetResourceAbbreviation(resources[i], removeLingoonaTags: false)); } @@ -474,18 +474,18 @@ public override void OnAwake() { /// public override void OnLoad(ConfigNode node) { base.OnLoad(node); - rotaingCylinder = Hierarchy.FindPartModelByPath(part, rotatingWinchCylinderModel); + _rotatingCylinder = Hierarchy.FindPartModelByPath(part, rotatingWinchCylinderModel); ConfigAccessor.ReadFieldsInType(GetType(), this); } /// public override void OnUpdate() { base.OnUpdate(); - if (rotaingCylinder != null) { + if (_rotatingCylinder != null) { if (cableJoint.realCableLength > float.Epsilon) { var angle = 360.0f * (cableJoint.realCableLength % cylinderPerimeterLength) / cylinderPerimeterLength; - rotaingCylinder.localRotation = Quaternion.Euler(angle, 0, 0); + _rotatingCylinder.localRotation = Quaternion.Euler(angle, 0, 0); } } } @@ -493,25 +493,25 @@ public override void OnUpdate() { /// public override void LocalizeModule() { base.LocalizeModule(); - resourceRows.ToList().ForEach(x => x.UpdateStaticStrings()); + _resourceRows.ToList().ForEach(x => x.UpdateStaticStrings()); - autoScaleToggleCnt = new GUIContent( + _autoScaleToggleCnt = new GUIContent( AutoScaleToggleTxt, AutoScaleToggleHint.Format(autoSpeedTransferDuration)); - leftToRigthToggleCnt = new GUIContent("<<", LeftToRigthToggleHint); - leftToRigthButtonCnt = new GUIContent("<", LeftToRigthButtonHint); - rightToLeftToggleCnt = new GUIContent(">>", RightToLeftToggleHint); - rightToLeftButtonCnt = new GUIContent(">", RightToLeftButtonHint); + _leftToRightToggleCnt = new GUIContent("<<", LeftToRightToggleHint); + _leftToRightButtonCnt = new GUIContent("<", LeftToRightButtonHint); + _rightToLeftToggleCnt = new GUIContent(">>", RightToLeftToggleHint); + _rightToLeftButtonCnt = new GUIContent(">", RightToLeftButtonHint); // Force the strings loading since their guiTags are used in GUI. - resourceName.LoadLocalization(); - resourceAmounts.LoadLocalization(); + ResourceName.LoadLocalization(); + ResourceAmounts.LoadLocalization(); } /// public override void UpdateContextMenu() { base.UpdateContextMenu(); - PartModuleUtils.SetupEvent(this, OpenGUIEvent, e => { + PartModuleUtils.SetupEvent(this, OpenGuiEvent, e => { e.active = linkTarget != null && linkTarget.part != null && !linkTarget.part.vessel.isEVA; }); } @@ -526,13 +526,13 @@ protected override void PhysicalLink() { #region IHasGUI implementation /// public void OnGUI() { - isGUIOpen &= linkTarget != null; + _isGuiOpen &= linkTarget != null; if (Time.timeScale <= float.Epsilon) { return; // No events and menu in the paused mode. } - if (isGUIOpen) { - windowRect = GUILayout.Window( - GetInstanceID(), windowRect, TransferResourcesWindowFunc, WindowTitleTxt, + if (_isGuiOpen) { + _windowRect = GUILayout.Window( + GetInstanceID(), _windowRect, TransferResourcesWindowFunc, WindowTitleTxt, GUILayout.MaxHeight(1), GUILayout.MaxWidth(1)); } } @@ -543,7 +543,7 @@ public void OnGUI() { /// Window ID. void TransferResourcesWindowFunc(int windowId) { // Allow the window to be dragged by its title bar. - GuiWindow.DragWindow(ref windowRect, titleBarRect); + GuiWindow.DragWindow(ref _windowRect, _titleBarRect); MakeGuiStyles(); @@ -551,16 +551,16 @@ void TransferResourcesWindowFunc(int windowId) { if (vessel == linkTarget.part.vessel) { GUILayout.Label(NotAvailableInDockedMode, new GUIStyle(GUI.skin.label) { wordWrap = false }); if (GUILayout.Button(CloseDialogBtn, MinSizeLayout)) { - isGUIOpen = false; + _isGuiOpen = false; } SetPendingTransferOption(null); // Cancel all transfers. return; } - if (guiActions.ExecutePendingGuiActions()) { + if (_guiActions.ExecutePendingGuiActions()) { MaybeUpdateResourceOptionList(); - guiResourcesTable.UpdateFrame(); - if (pendingOption != null) { + _guiResourcesTable.UpdateFrame(); + if (_pendingOption != null) { if (!DoTransfer()) { SetPendingTransferOption(null); // Cancel all transfers. } @@ -570,52 +570,52 @@ void TransferResourcesWindowFunc(int windowId) { GUILayout.Label(OwnerVesselTxt.Format(vessel.vesselName), GUI.skin.box); GUILayout.Label(ConnectedVesselTxt.Format(linkTarget.part.vessel.vesselName), GUI.skin.box); - for (var i = resourceRows.Length - 1; i >= 0; i--) { - var row = resourceRows[i]; - guiResourcesTable.StartNewRow(); + for (var i = _resourceRows.Length - 1; i >= 0; i--) { + var row = _resourceRows[i]; + _guiResourcesTable.StartNewRow(); using (new GUILayout.HorizontalScope()) { - guiResourcesTable.AddTextColumn( - row.caption, guiResourceStyle, minWidth: resourceName.guiTags.minWidth); - guiResourcesTable.AddTextColumn( - row.leftInfo, guiNoWrapCenteredStyle, minWidth: resourceAmounts.guiTags.minWidth); + _guiResourcesTable.AddTextColumn( + row.caption, _guiResourceStyle, minWidth: ResourceName.guiTags.minWidth); + _guiResourcesTable.AddTextColumn( + row.leftInfo, _guiNoWrapCenteredStyle, minWidth: ResourceAmounts.guiTags.minWidth); using (new GuiEnabledStateScope(row.canMoveRightToLeft)) { row.rightToLeftTransferToggle = GUILayoutButtons.Toggle( - row.rightToLeftTransferToggle, leftToRigthToggleCnt, guiTransferBtnStyle, null, - GuiActionUpdateTransferItem, GuiActionUpdateTransferItem, guiActions); + row.rightToLeftTransferToggle, _leftToRightToggleCnt, _guiTransferBtnStyle, null, + GuiActionUpdateTransferItem, GuiActionUpdateTransferItem, _guiActions); row.rightToLeftTransferPress = GUILayoutButtons.Push( - row.rightToLeftTransferPress, leftToRigthButtonCnt, guiTransferBtnStyle, null, - GuiActionUpdateTransferItem, GuiActionUpdateTransferItem, guiActions); + row.rightToLeftTransferPress, _leftToRightButtonCnt, _guiTransferBtnStyle, null, + GuiActionUpdateTransferItem, GuiActionUpdateTransferItem, _guiActions); } using (new GuiEnabledStateScope(row.canMoveLeftToRight)) { row.leftToRightTransferPress = GUILayoutButtons.Push( - row.leftToRightTransferPress, rightToLeftButtonCnt, guiTransferBtnStyle, null, - GuiActionUpdateTransferItem, GuiActionUpdateTransferItem, guiActions); + row.leftToRightTransferPress, _rightToLeftButtonCnt, _guiTransferBtnStyle, null, + GuiActionUpdateTransferItem, GuiActionUpdateTransferItem, _guiActions); row.leftToRightTransferToggle = GUILayoutButtons.Toggle( - row.leftToRightTransferToggle, rightToLeftToggleCnt, guiTransferBtnStyle, null, - GuiActionUpdateTransferItem, GuiActionUpdateTransferItem, guiActions); + row.leftToRightTransferToggle, _rightToLeftToggleCnt, _guiTransferBtnStyle, null, + GuiActionUpdateTransferItem, GuiActionUpdateTransferItem, _guiActions); } - guiResourcesTable.AddTextColumn( - row.rightInfo, guiNoWrapCenteredStyle, minWidth: resourceAmounts.guiTags.minWidth); - guiResourcesTable.AddTextColumn( - row.caption, guiResourceStyle, minWidth: resourceName.guiTags.minWidth); + _guiResourcesTable.AddTextColumn( + row.rightInfo, _guiNoWrapCenteredStyle, minWidth: ResourceAmounts.guiTags.minWidth); + _guiResourcesTable.AddTextColumn( + row.caption, _guiResourceStyle, minWidth: ResourceName.guiTags.minWidth); } } // Resource transfer speed. - autoScaleSpeed = GUILayoutButtons.Toggle( - autoScaleSpeed, autoScaleToggleCnt, GUI.skin.toggle, null, - MaybeAutoScaleSpeed, null, guiActions); - using (new GuiEnabledStateScope(!autoScaleSpeed)) { - transferSpeed = GUILayout.HorizontalSlider(transferSpeed, 0f, maxTransferSpeed); - if (transferSpeed < float.Epsilon && pendingOption != null) { - guiActions.Add(() => SetPendingTransferOption(null)); // Cancel all transfers. + _autoScaleSpeed = GUILayoutButtons.Toggle( + _autoScaleSpeed, _autoScaleToggleCnt, GUI.skin.toggle, null, + MaybeAutoScaleSpeed, null, _guiActions); + using (new GuiEnabledStateScope(!_autoScaleSpeed)) { + _transferSpeed = GUILayout.HorizontalSlider(_transferSpeed, 0f, maxTransferSpeed); + if (_transferSpeed < float.Epsilon && _pendingOption != null) { + _guiActions.Add(() => SetPendingTransferOption(null)); // Cancel all transfers. } } - GUILayout.Label(TransferSpeedTxt.Format(transferSpeed)); + GUILayout.Label(TransferSpeedTxt.Format(_transferSpeed)); using (new GUILayout.HorizontalScope()) { if (GUILayout.Button(CloseDialogBtn, MinSizeLayout)) { - guiActions.Add(() => isGUIOpen = false); + _guiActions.Add(() => _isGuiOpen = false); } GUILayout.Label(""); GUI.Label(GUILayoutUtility.GetLastRect(), GUI.tooltip); @@ -624,8 +624,8 @@ void TransferResourcesWindowFunc(int windowId) { /// Finds the currently active option and makes it active. void GuiActionUpdateTransferItem() { - var row = resourceRows.FirstOrDefault(r => - r != pendingOption && (r.leftToRightTransferPress || r.leftToRightTransferToggle + var row = _resourceRows.FirstOrDefault(r => + r != _pendingOption && (r.leftToRightTransferPress || r.leftToRightTransferToggle || r.rightToLeftTransferPress || r.rightToLeftTransferToggle)); SetPendingTransferOption(row); MaybeAutoScaleSpeed(); @@ -633,15 +633,18 @@ void GuiActionUpdateTransferItem() { /// Creates the styles. Only does it once. void MakeGuiStyles() { - if (guiNoWrapCenteredStyle == null) { - guiNoWrapCenteredStyle = new GUIStyle(GUI.skin.box); - guiNoWrapCenteredStyle.wordWrap = false; - guiNoWrapCenteredStyle.alignment = TextAnchor.MiddleCenter; - guiResourceStyle = new GUIStyle(guiNoWrapCenteredStyle); - guiTransferBtnStyle = new GUIStyle(GUI.skin.button); - guiTransferBtnStyle.alignment = TextAnchor.MiddleCenter; - guiTransferBtnStyle.stretchHeight = true; + if (_guiNoWrapCenteredStyle != null) { + return; } + _guiNoWrapCenteredStyle = new GUIStyle(GUI.skin.box) { + wordWrap = false, + alignment = TextAnchor.MiddleCenter + }; + _guiResourceStyle = new GUIStyle(_guiNoWrapCenteredStyle); + _guiTransferBtnStyle = new GUIStyle(GUI.skin.button) { + alignment = TextAnchor.MiddleCenter, + stretchHeight = true + }; } #endregion @@ -651,32 +654,32 @@ void MakeGuiStyles() { /// will be transferred in a definite duration. /// void MaybeAutoScaleSpeed() { - if (!autoScaleSpeed || pendingOption == null) { + if (!_autoScaleSpeed || _pendingOption == null) { return; } // Determine the maximum unscaled amount to transfer. var maxUnscaledAmount = double.PositiveInfinity; - for (var i = pendingOption.resources.Length - 1; i >= 0; i--) { - var unit = pendingOption.resourceRatios[i]; - var resource = pendingOption.resources[i]; - var amount = currentFromPartAmounts[i] / unit; + for (var i = _pendingOption.resources.Length - 1; i >= 0; i--) { + var unit = _pendingOption.resourceRatios[i]; + var resource = _pendingOption.resources[i]; + var amount = _currentFromPartAmounts[i] / unit; if (amount < maxUnscaledAmount) { maxUnscaledAmount = amount; } - var capacity = (currentToPartCapacities[i] - currentToPartAmounts[i]) / unit; + var capacity = (_currentToPartCapacities[i] - _currentToPartAmounts[i]) / unit; if (capacity < maxUnscaledAmount) { maxUnscaledAmount = capacity; } } - transferSpeed = Mathf.Min(maxTransferSpeed, (float) maxUnscaledAmount / autoSpeedTransferDuration); + _transferSpeed = Mathf.Min(maxTransferSpeed, (float) maxUnscaledAmount / autoSpeedTransferDuration); } /// Does actual resource transfer on the selected option. /// This method must be performance optimized since it called each frame. bool DoTransfer() { - var updateDelta = Planetarium.GetUniversalTime() - pendingOption.previousUpdate; - pendingOption.previousUpdate = Planetarium.GetUniversalTime(); + var updateDelta = Planetarium.GetUniversalTime() - _pendingOption.previousUpdate; + _pendingOption.previousUpdate = Planetarium.GetUniversalTime(); if (updateDelta < float.Epsilon) { return true; // Cannot do transfer, but the state must not be reset yet. } @@ -684,26 +687,26 @@ bool DoTransfer() { // Below a tricky logic starts. It's intended to properly work with the mixtures of multiple // resources. When moving a mixture, we should know in advance how much amount of each component // can be transferred before the capacity/reserve limit hit. - var resources = pendingOption.resources; - var moveAmounts = new double[pendingOption.resources.Length]; + var resources = _pendingOption.resources; + var moveAmounts = new double[_pendingOption.resources.Length]; for (var i = moveAmounts.Length - 1; i >= 0; i--) { - moveAmounts[i] = transferSpeed * pendingOption.resourceRatios[i] * updateDelta; + moveAmounts[i] = _transferSpeed * _pendingOption.resourceRatios[i] * updateDelta; } // Now, check if each component request transfer can be fulfilled. var scale = 1.0; for (var i = moveAmounts.Length - 1; i >= 0; i--) { - currentFromPart.GetConnectedResourceTotals( + _currentFromPart.GetConnectedResourceTotals( resources[i], ResourceFlowMode.ALL_VESSEL_BALANCE, - out currentFromPartAmounts[i], out currentFromPartCapacities[i]); - currentToPart.GetConnectedResourceTotals( + out _currentFromPartAmounts[i], out _currentFromPartCapacities[i]); + _currentToPart.GetConnectedResourceTotals( resources[i], ResourceFlowMode.ALL_VESSEL_BALANCE, - out currentToPartAmounts[i], out currentToPartCapacities[i]); + out _currentToPartAmounts[i], out _currentToPartCapacities[i]); var amount = moveAmounts[i]; - if (amount > currentFromPartAmounts[i]) { - amount = currentFromPartAmounts[i]; + if (amount > _currentFromPartAmounts[i]) { + amount = _currentFromPartAmounts[i]; } - if (amount > currentToPartCapacities[i] - currentToPartAmounts[i]) { - amount = currentToPartCapacities[i] - currentToPartAmounts[i]; + if (amount > _currentToPartCapacities[i] - _currentToPartAmounts[i]) { + amount = _currentToPartCapacities[i] - _currentToPartAmounts[i]; } var newScale = amount / moveAmounts[i]; if (newScale < scale) { @@ -714,9 +717,9 @@ bool DoTransfer() { for (var i = moveAmounts.Length - 1; i >= 0; i--) { var resource = resources[i]; var amount = scale * moveAmounts[i]; - var actualAmount = currentFromPart.RequestResource( + var actualAmount = _currentFromPart.RequestResource( resource, amount, ResourceFlowMode.ALL_VESSEL_BALANCE); - currentToPart.RequestResource( + _currentToPart.RequestResource( resource, -actualAmount, ResourceFlowMode.ALL_VESSEL_BALANCE); } return Mathd.AreSame(scale, 1.0); @@ -729,12 +732,12 @@ bool DoTransfer() { /// /// Tells if GUI must be upadted regardless to the timer. void UpdateResourcesTransferGui(bool force = false) { - if (!force && Time.unscaledTime - lastResourcesGUIUpdate < TRANSFER_STATE_UPDATE_PERIOD) { + if (!force && Time.unscaledTime - _lastResourcesGuiUpdate < TransferStateUpdatePeriod) { return; } - lastResourcesGUIUpdate = Time.unscaledTime; - for (var i = resourceRows.Length - 1; i >= 0; i--) { - UpdateOptionTransferGui(resourceRows[i]); + _lastResourcesGuiUpdate = Time.unscaledTime; + for (var i = _resourceRows.Length - 1; i >= 0; i--) { + UpdateOptionTransferGui(_resourceRows[i]); } } @@ -779,10 +782,10 @@ void UpdateOptionTransferGui(ResourceTransferOption resOption) { /// /// This is a very expensive operation. void MaybeUpdateResourceOptionList() { - if (!resourceListNeedsUpdate) { + if (!_resourceListNeedsUpdate) { return; // Nothing to do. } - resourceListNeedsUpdate = false; + _resourceListNeedsUpdate = false; HostedDebugLog.Fine(this, "Refreshing resources..."); // Gather all the resources that *both* vessel have. @@ -844,45 +847,45 @@ void MaybeUpdateResourceOptionList() { mixture.components.Select(x => x.ratio).ToArray())); } - resourceRows = movableResources - .Select(resource => resourceRowsHash.ContainsKey(resource.GetHashCode()) - ? resourceRowsHash[resource.GetHashCode()] + _resourceRows = movableResources + .Select(resource => _resourceRowsHash.ContainsKey(resource.GetHashCode()) + ? _resourceRowsHash[resource.GetHashCode()] : resource) .ToArray(); - resourceRowsHash = resourceRows.ToDictionary(r => r.GetHashCode()); + _resourceRowsHash = _resourceRows.ToDictionary(r => r.GetHashCode()); } /// Sets the currently transferring option. Erasing the previous one. /// The new option or null. void SetPendingTransferOption(ResourceTransferOption newOption) { - if (newOption != pendingOption && pendingOption != null) { - pendingOption.StopAllTransfers(); - } - pendingOption = newOption; - if (pendingOption == null && autoScaleSpeed) { - transferSpeed = 1.0f; - } - if (pendingOption != null) { - if (pendingOption.leftToRightTransferPress || pendingOption.leftToRightTransferToggle) { - currentFromPart = part; - currentFromPartCapacities = pendingOption.leftCapacities; - currentFromPartAmounts = pendingOption.leftAmounts; - currentToPart = linkTarget.part; - currentToPartCapacities = pendingOption.rightCapacities; - currentToPartAmounts = pendingOption.rightAmounts; + if (newOption != _pendingOption && _pendingOption != null) { + _pendingOption.StopAllTransfers(); + } + _pendingOption = newOption; + if (_pendingOption == null && _autoScaleSpeed) { + _transferSpeed = 1.0f; + } + if (_pendingOption != null) { + if (_pendingOption.leftToRightTransferPress || _pendingOption.leftToRightTransferToggle) { + _currentFromPart = part; + _currentFromPartCapacities = _pendingOption.leftCapacities; + _currentFromPartAmounts = _pendingOption.leftAmounts; + _currentToPart = linkTarget.part; + _currentToPartCapacities = _pendingOption.rightCapacities; + _currentToPartAmounts = _pendingOption.rightAmounts; } else { - currentFromPart = linkTarget.part; - currentFromPartCapacities = pendingOption.rightCapacities; - currentFromPartAmounts = pendingOption.rightAmounts; - currentToPart = part; - currentToPartCapacities = pendingOption.leftCapacities; - currentToPartAmounts = pendingOption.leftAmounts; + _currentFromPart = linkTarget.part; + _currentFromPartCapacities = _pendingOption.rightCapacities; + _currentFromPartAmounts = _pendingOption.rightAmounts; + _currentToPart = part; + _currentToPartCapacities = _pendingOption.leftCapacities; + _currentToPartAmounts = _pendingOption.leftAmounts; } } else { - currentFromPartCapacities = null; - currentFromPartAmounts = null; - currentToPartCapacities = null; - currentToPartAmounts = null; + _currentFromPartCapacities = null; + _currentFromPartAmounts = null; + _currentToPartCapacities = null; + _currentToPartAmounts = null; } UpdateResourcesTransferGui(force: true); } @@ -891,7 +894,7 @@ void SetPendingTransferOption(ResourceTransferOption newOption) { /// Forces an update of the list of the available resources. It's an expensive operation. /// void OnVesselUpdated(Vessel v) { - resourceListNeedsUpdate = true; + _resourceListNeedsUpdate = true; } #endregion } diff --git a/Source/modules/KASLinkSourceBase.cs b/Source/modules/KASLinkSourceBase.cs index 81af3383c..4721e44c6 100644 --- a/Source/modules/KASLinkSourceBase.cs +++ b/Source/modules/KASLinkSourceBase.cs @@ -122,7 +122,7 @@ public enum CoupleMode { /// target parts must be enabled for coupling in order to be able to dock. IF any of the peers /// doesn't allow it, there will be no context menu option. /// - SetViaGUI, + SetViaGui, /// The link is always established in docked mode. /// @@ -255,7 +255,7 @@ void OnPartDeCoupleCompleteEvent(Part originator) { } /// - public override void OnStart(PartModule.StartState state) { + public override void OnStart(StartState state) { base.OnStart(state); InitStartState(); RegisterGameEventListener(GameEvents.onPartDeCoupleComplete, OnPartDeCoupleCompleteEvent); @@ -427,8 +427,8 @@ protected override void InitModuleSettings() { #endregion #region IHasDebugAdjustables implementation - ILinkTarget dbgOldTarget; - float dbgOldCableLength; + ILinkTarget _dbgOldTarget; + float _dbgOldCableLength; /// public override void OnBeforeDebugAdjustablesUpdate() { @@ -436,12 +436,12 @@ public override void OnBeforeDebugAdjustablesUpdate() { if (linkState != LinkState.Linked && linkState != LinkState.Available) { throw new InvalidOperationException("Cannot adjust value in link state: " + linkState); } - dbgOldTarget = linkTarget; - dbgOldCableLength = -1; + _dbgOldTarget = linkTarget; + _dbgOldCableLength = -1; if (isLinked) { var cableJoint = linkJoint as ILinkCableJoint; if (cableJoint != null) { - dbgOldCableLength = cableJoint.deployedCableLength; + _dbgOldCableLength = cableJoint.deployedCableLength; } BreakCurrentLink(LinkActorType.Player); } @@ -457,13 +457,13 @@ public override void OnDebugAdjustablesUpdated() { InitModuleSettings(); InitStartState(); UpdateContextMenu(); - if (dbgOldTarget != null) { - HostedDebugLog.Warning(this, "Relinking to target: {0}", dbgOldTarget); - LinkToTarget(LinkActorType.Player, dbgOldTarget); + if (_dbgOldTarget != null) { + HostedDebugLog.Warning(this, "Relinking to target: {0}", _dbgOldTarget); + LinkToTarget(LinkActorType.Player, _dbgOldTarget); var cableJoint = linkJoint as ILinkCableJoint; if (cableJoint != null) { - HostedDebugLog.Warning(this, "Restoring cable length: {0}", dbgOldCableLength); - cableJoint.SetCableLength(dbgOldCableLength); + HostedDebugLog.Warning(this, "Restoring cable length: {0}", _dbgOldCableLength); + cableJoint.SetCableLength(_dbgOldCableLength); } } }, @@ -544,7 +544,7 @@ public virtual bool LinkToTarget(ILinkTarget target) { HostedDebugLog.Error(this, "Cannot link in state: {0}", linkState); return false; } - if (!CheckCanLinkTo(target, reportToGUI: linkActor == LinkActorType.Player)) { + if (!CheckCanLinkTo(target, reportToGui: linkActor == LinkActorType.Player)) { return false; } if (coupleMode == CoupleMode.AlwaysCoupled @@ -582,19 +582,19 @@ public virtual void BreakCurrentLink(LinkActorType actorType) { /// public virtual bool CheckCanLinkTo(ILinkTarget target, bool checkStates = true, - bool reportToGUI = false, bool reportToLog = true) { + bool reportToGui = false, bool reportToLog = true) { var errors = new List() .Concat(CheckBasicLinkConditions(target, checkStates)) .Concat(linkRenderer.CheckColliderHits(nodeTransform, target.nodeTransform)) .Concat(linkJoint.CheckConstraints(this, target)) .ToArray(); if (errors.Length > 0) { - if (reportToGUI || reportToLog) { + 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) { + if (reportToGui) { ShowStatusMessage(DbgFormatter.C2S(errors, separator: "\n"), isError: true); } } @@ -608,7 +608,7 @@ public virtual void UpdateContextMenu() { PartModuleUtils.SetupEvent(this, ToggleVesselsDockModeEvent, e => { if (linkJoint != null) { e.guiName = linkJoint.coupleOnLinkMode ? DockedModeMenuTxt : UndockedModeMenuTxt; - if (coupleMode == CoupleMode.SetViaGUI) { + if (coupleMode == CoupleMode.SetViaGui) { e.active = coupleNode != null && (linkTarget == null || linkTarget.coupleNode != null); } else if (isLinked) { // Just in case show GUI if the link is established, and its couple mode contradicts the diff --git a/Source/modules/KASLinkSourceInteractive.cs b/Source/modules/KASLinkSourceInteractive.cs index c7dd149eb..deb2b724a 100644 --- a/Source/modules/KASLinkSourceInteractive.cs +++ b/Source/modules/KASLinkSourceInteractive.cs @@ -118,23 +118,23 @@ public void BreakLinkContextMenuAction() { const string InteractiveShaderName = "Transparent/Diffuse"; /// The compatible target under the mouse cursor. - ILinkTarget targetCandidate; + ILinkTarget _targetCandidate; /// Tells if the connection with the candidate will be successful. - bool targetCandidateIsGood; + bool _targetCandidateIsGood; /// /// The last known hovered part. Used to trigger the detection of the target candidate. /// - Part lastHoveredPart; + Part _lastHoveredPart; /// The message, displayed during the interactive linking. - ScreenMessage statusScreenMessage; + ScreenMessage _statusScreenMessage; /// /// A variable to store the auto save state before starting the interactive mode. /// - bool canAutoSaveState; + bool _canAutoSaveState; #endregion #region KASLinkSourceBase overrides @@ -156,8 +156,8 @@ public override void OnUpdate() { } // Handle link action (mouse click). if (Input.GetKeyDown(KeyCode.Mouse0)) { - if (targetCandidateIsGood ) { - AsyncCall.CallOnEndOfFrame(this, () => LinkToTarget(targetCandidate)); + if (_targetCandidateIsGood ) { + AsyncCall.CallOnEndOfFrame(this, () => LinkToTarget(_targetCandidate)); } else { UISoundPlayer.instance.Play(KASAPI.CommonConfig.sndPathBipWrong); } @@ -170,7 +170,7 @@ public override void OnStart(StartState state) { base.OnStart(state); // Infinity duration doesn't mean the message will be shown forever. It must be refreshed in the // Update method. - statusScreenMessage = new ScreenMessage("", Mathf.Infinity, ScreenMessageStyle.UPPER_CENTER); + _statusScreenMessage = new ScreenMessage("", Mathf.Infinity, ScreenMessageStyle.UPPER_CENTER); UpdateContextMenu(); } @@ -205,7 +205,7 @@ protected override void SetupStateMachine() { enterHandler: x => { InputLockManager.SetControlLock( ControlTypes.All & ~ControlTypes.CAMERACONTROLS, TotalControlLock); - canAutoSaveState = HighLogic.CurrentGame.Parameters.Flight.CanAutoSave; + _canAutoSaveState = HighLogic.CurrentGame.Parameters.Flight.CanAutoSave; HighLogic.CurrentGame.Parameters.Flight.CanAutoSave = false; linkRenderer.shaderNameOverride = InteractiveShaderName; linkRenderer.colorOverride = BadLinkColor; @@ -216,10 +216,10 @@ protected override void SetupStateMachine() { linkRenderer.shaderNameOverride = null; linkRenderer.colorOverride = null; linkRenderer.isPhysicalCollider = true; - ScreenMessages.RemoveMessage(statusScreenMessage); + ScreenMessages.RemoveMessage(_statusScreenMessage); InputLockManager.RemoveControlLock(TotalControlLock); - HighLogic.CurrentGame.Parameters.Flight.CanAutoSave = canAutoSaveState; - lastHoveredPart = null; + HighLogic.CurrentGame.Parameters.Flight.CanAutoSave = _canAutoSaveState; + _lastHoveredPart = null; }); linkStateMachine.AddStateHandlers( LinkState.Linked, @@ -246,35 +246,35 @@ protected override void SetupStateMachine() { /// Displays linking status in real time. void UpdateLinkingState() { // Catch the hovered part, a possible target on it, and the link feasibility. - if (Mouse.HoveredPart != lastHoveredPart) { - lastHoveredPart = Mouse.HoveredPart; - targetCandidateIsGood = false; - if (lastHoveredPart == null ) { - targetCandidate = null; + if (Mouse.HoveredPart != _lastHoveredPart) { + _lastHoveredPart = Mouse.HoveredPart; + _targetCandidateIsGood = false; + if (_lastHoveredPart == null ) { + _targetCandidate = null; } else { - targetCandidate = lastHoveredPart.Modules.OfType() + _targetCandidate = _lastHoveredPart.Modules.OfType() .FirstOrDefault(x => x.cfgLinkType == cfgLinkType && x.linkState == LinkState.AcceptingLinks); - if (targetCandidate != null) { + if (_targetCandidate != null) { var linkStatusErrors = new List() - .Concat(CheckBasicLinkConditions(targetCandidate, checkStates: true)) - .Concat(linkRenderer.CheckColliderHits(nodeTransform, targetCandidate.nodeTransform)) - .Concat(linkJoint.CheckConstraints(this, targetCandidate)) + .Concat(CheckBasicLinkConditions(_targetCandidate, checkStates: true)) + .Concat(linkRenderer.CheckColliderHits(nodeTransform, _targetCandidate.nodeTransform)) + .Concat(linkJoint.CheckConstraints(this, _targetCandidate)) .ToArray(); if (linkStatusErrors.Length == 0) { - targetCandidateIsGood = true; - statusScreenMessage.message = CanBeConnectedMsg.Format( - Vector3.Distance(nodeTransform.position, targetCandidate.nodeTransform.position)); + _targetCandidateIsGood = true; + _statusScreenMessage.message = CanBeConnectedMsg.Format( + Vector3.Distance(nodeTransform.position, _targetCandidate.nodeTransform.position)); } else { - statusScreenMessage.message = ScreenMessaging.SetColorToRichText( + _statusScreenMessage.message = ScreenMessaging.SetColorToRichText( String.Join("\n", linkStatusErrors), ScreenMessaging.ErrorColor); } } } // Show the possible link or indicate the error. - if (targetCandidate != null) { - linkRenderer.colorOverride = targetCandidateIsGood ? GoodLinkColor : BadLinkColor; - linkRenderer.StartRenderer(nodeTransform, targetCandidate.nodeTransform); + if (_targetCandidate != null) { + linkRenderer.colorOverride = _targetCandidateIsGood ? GoodLinkColor : BadLinkColor; + linkRenderer.StartRenderer(nodeTransform, _targetCandidate.nodeTransform); } else { linkRenderer.colorOverride = BadLinkColor; linkRenderer.StopRenderer(); @@ -282,10 +282,10 @@ void UpdateLinkingState() { } // Update linking messages (it needs to be refreshed to not go out by timeout). - if (targetCandidate == null) { - statusScreenMessage.message = LinkingInProgressMsg; + if (_targetCandidate == null) { + _statusScreenMessage.message = LinkingInProgressMsg; } - ScreenMessages.PostScreenMessage(statusScreenMessage); + ScreenMessages.PostScreenMessage(_statusScreenMessage); } /// Helper method to execute context menu updates on vessel switch. diff --git a/Source/modules/KASLinkSourcePhysical.cs b/Source/modules/KASLinkSourcePhysical.cs index 7f10fc04f..a97c0ee5e 100644 --- a/Source/modules/KASLinkSourcePhysical.cs +++ b/Source/modules/KASLinkSourcePhysical.cs @@ -48,28 +48,28 @@ public class KASLinkSourcePhysical : KASLinkSourceBase { #region Localizable GUI strings. /// - static readonly Message ConnectorStateMsg_Locked = new Message( + static readonly Message ConnectorStateMsgLocked = new Message( "#kasLOC_13000", defaultTemplate: "Locked", description: "A string in the context menu that tells that the connector is rigidly attached" + " to the part and is not movable."); /// - static readonly Message ConnectorStateMsg_Deployed = new Message( + static readonly Message ConnectorStateMsgDeployed = new Message( "#kasLOC_13001", defaultTemplate: "Deployed", description: "A string in the context menu that tells that the connector is deployed and" + " attached to the part via a cable."); /// - static readonly Message ConnectorStateMsg_Plugged = new Message( + static readonly Message ConnectorStateMsgPlugged = new Message( "#kasLOC_13002", defaultTemplate: "Plugged in", description: "A string in the context menu that tells that the connector is plugged in" + " a socked or is being carried by a kerbal, and attached to the part via a cable."); /// - static readonly Message ConnectorStateMsg_Docked = new Message( + static readonly Message ConnectorStateMsgDocked = new Message( "#kasLOC_13003", defaultTemplate: "Docked", description: "A string in the context menu that tells that the connector is rigidly" @@ -79,10 +79,10 @@ public class KASLinkSourcePhysical : KASLinkSourceBase { /// Translates enum into a localized message. static readonly MessageLookup ConnectorStatesMsgLookup = new MessageLookup(new Dictionary() { - {ConnectorState.Locked, ConnectorStateMsg_Locked}, - {ConnectorState.Deployed, ConnectorStateMsg_Deployed}, - {ConnectorState.Plugged, ConnectorStateMsg_Plugged}, - {ConnectorState.Docked, ConnectorStateMsg_Docked}, + {ConnectorState.Locked, ConnectorStateMsgLocked}, + {ConnectorState.Deployed, ConnectorStateMsgDeployed}, + {ConnectorState.Plugged, ConnectorStateMsgPlugged}, + {ConnectorState.Docked, ConnectorStateMsgDocked}, }); /// @@ -93,7 +93,7 @@ public class KASLinkSourcePhysical : KASLinkSourceBase { + " due to the unexpected external forces or actions."); /// - static readonly Message CannotLinkToPreattached = new Message( + static readonly Message CannotLinkToPreAttached = new Message( "#kasLOC_13005", defaultTemplate: "Cannot link with: <<1>>", description: "The error message to present when a part is being attached externally to the" @@ -374,21 +374,21 @@ protected ILinkCableJoint cableJoint { #region Local fields & properties /// Connector grab event to inject into the linked target. /// - BaseEvent GrabConnectorEventInject; + BaseEvent _grabConnectorEventInject; #endregion #region IHasDebugAdjustables implementation - PosAndRot dbgOldConnectorPosAndRot; - ConnectorState dbgOldConnectorState; - float dbgOldCableLength; + PosAndRot _dbgOldConnectorPosAndRot; + ConnectorState _dbgOldConnectorState; + float _dbgOldCableLength; /// public override void OnBeforeDebugAdjustablesUpdate() { - dbgOldConnectorState = connectorState; + _dbgOldConnectorState = connectorState; if (connectorState == ConnectorState.Deployed) { - dbgOldCableLength = currentCableLength; + _dbgOldCableLength = currentCableLength; SaveConnectorModelPosAndRot(); - dbgOldConnectorPosAndRot = persistedConnectorPosAndRot; + _dbgOldConnectorPosAndRot = persistedConnectorPosAndRot; SetConnectorState(ConnectorState.Locked); } base.OnBeforeDebugAdjustablesUpdate(); @@ -400,13 +400,13 @@ public override void OnDebugAdjustablesUpdated() { AsyncCall.CallOnEndOfFrame( this, () => { - if (dbgOldConnectorState == ConnectorState.Deployed) { + if (_dbgOldConnectorState == ConnectorState.Deployed) { HostedDebugLog.Warning( this, "Restoring connector: state={0}, at={1}, length={2}", - dbgOldConnectorState, dbgOldConnectorPosAndRot, dbgOldCableLength); - persistedConnectorPosAndRot = dbgOldConnectorPosAndRot; - SetConnectorState(dbgOldConnectorState); - SetCableLength(dbgOldCableLength); + _dbgOldConnectorState, _dbgOldConnectorPosAndRot, _dbgOldCableLength); + persistedConnectorPosAndRot = _dbgOldConnectorPosAndRot; + SetConnectorState(_dbgOldConnectorState); + SetCableLength(_dbgOldCableLength); } }, skipFrames: 1); // To match the base class delay. @@ -419,14 +419,15 @@ public override void OnAwake() { base.OnAwake(); // The GUI name of this event is copied from GrabConnectorEvent in UpdateContextMenu. - GrabConnectorEventInject = new BaseEvent( + // ReSharper disable once UseObjectOrCollectionInitializer + _grabConnectorEventInject = new BaseEvent( Events, "autoEventAttach" + part.Modules.IndexOf(this), ClaimLinkedConnector, new KSPEvent()); - GrabConnectorEventInject.guiActive = true; - GrabConnectorEventInject.guiActiveUncommand = true; - GrabConnectorEventInject.guiActiveUnfocused = true; + _grabConnectorEventInject.guiActive = true; + _grabConnectorEventInject.guiActiveUncommand = true; + _grabConnectorEventInject.guiActiveUnfocused = true; RegisterGameEventListener(GameEvents.onVesselChange, OnVesselChange); } @@ -474,9 +475,7 @@ protected override void RestoreOtherPeer() { base.RestoreOtherPeer(); if (otherPeer == null) { persistedIsConnectorLocked = true; - if (linkJoint != null) { - linkJoint.DropJoint(); // Cleanup the joints state. - } + linkJoint?.DropJoint(); // Cleanup the joints state. } } @@ -500,12 +499,12 @@ protected override void SetupStateMachine() { enterHandler: oldState => { var module = linkTarget as PartModule; PartModuleUtils.InjectEvent(this, DetachConnectorEvent, module); - PartModuleUtils.AddEvent(module, GrabConnectorEventInject); + PartModuleUtils.AddEvent(module, _grabConnectorEventInject); }, leaveHandler: newState => { var module = linkTarget as PartModule; PartModuleUtils.WithdrawEvent(this, DetachConnectorEvent, module); - PartModuleUtils.DropEvent(module, GrabConnectorEventInject); + PartModuleUtils.DropEvent(module, _grabConnectorEventInject); }); linkStateMachine.AddStateHandlers( LinkState.NodeIsBlocked, @@ -516,7 +515,7 @@ protected override void SetupStateMachine() { coupleNode.FindOpposingNode().attachedPart); UISoundPlayer.instance.Play(KASAPI.CommonConfig.sndPathBipWrong); ShowStatusMessage( - CannotLinkToPreattached.Format(coupleNode.attachedPart), isError: true); + CannotLinkToPreAttached.Format(coupleNode.attachedPart), isError: true); KASAPI.LinkUtils.DecoupleParts(part, coupleNode.attachedPart); } }, @@ -524,7 +523,7 @@ protected override void SetupStateMachine() { // The default state is "Locked". All the enter state handlers rely on it, and all the exit // state handlers reset the state back to the default. - connectorStateMachine = new SimpleStateMachine(strict: true); + connectorStateMachine = new SimpleStateMachine(); connectorStateMachine.onAfterTransition += (start, end) => { if (end != null) { // Do nothing on state machine shutdown. persistedIsConnectorLocked = isConnectorLocked; @@ -659,8 +658,8 @@ public override void UpdateContextMenu() { }); PartModuleUtils.SetupEvent(this, GrabConnectorEvent, e => { e.active = connectorState == ConnectorState.Locked && linkState != LinkState.NodeIsBlocked; - if (GrabConnectorEventInject != null) { - GrabConnectorEventInject.guiName = e.guiName; + if (_grabConnectorEventInject != null) { + _grabConnectorEventInject.guiName = e.guiName; } }); PartModuleUtils.SetupEvent(this, ReturnConnectorEvent, e => { @@ -672,8 +671,8 @@ public override void UpdateContextMenu() { PartModuleUtils.SetupEvent(this, InstantLockConnectorEvent, e => { e.active = connectorState == ConnectorState.Deployed; }); - if (GrabConnectorEventInject != null) { - GrabConnectorEventInject.active = linkTarget != null + if (_grabConnectorEventInject != null) { + _grabConnectorEventInject.active = linkTarget != null && connectorState == ConnectorState.Plugged && FlightGlobals.ActiveVessel != linkTarget.part.vessel; } @@ -785,7 +784,7 @@ void ClaimLinkedConnector() { var kerbalTarget = FlightGlobals.ActiveVessel.rootPart.Modules.OfType() .FirstOrDefault(t => t.cfgLinkType == cfgLinkType && t.linkState == LinkState.Available); if (kerbalTarget != null - && CheckCanLinkTo(kerbalTarget, reportToGUI: true, checkStates: false)) { + && CheckCanLinkTo(kerbalTarget, reportToGui: true, checkStates: false)) { BreakCurrentLink(LinkActorType.API); if (LinkToTarget(LinkActorType.Player, kerbalTarget)) { SetCableLength(float.PositiveInfinity); @@ -813,7 +812,9 @@ void SaveConnectorModelPosAndRot(bool saveNonPhysical = false) { // a deployed connector at an arbitrary location. return; } - var connector = connectorObj ?? GetConnectorModel(); + var connector = connectorObj + ? connectorObj + : GetConnectorModel(); persistedConnectorPosAndRot = gameObject.transform.InverseTransformPosAndRot( new PosAndRot(connector.position, connector.rotation.eulerAngles)); } @@ -848,7 +849,7 @@ void StartPhysicsOnConnector() { part.rb.mass -= connectorMass; linkRenderer.StartRenderer(nodeTransform, physPartAttach); - Colliders.UpdateColliders(connectorModel.gameObject, isEnabled: true); + Colliders.UpdateColliders(connectorModel.gameObject); cableJoint.StartPhysicalHead(this, physPipeAttachObj); SaveConnectorModelPosAndRot(); } diff --git a/Source/modules/KASLinkTargetBase.cs b/Source/modules/KASLinkTargetBase.cs index cdfc90454..2bd666a36 100644 --- a/Source/modules/KASLinkTargetBase.cs +++ b/Source/modules/KASLinkTargetBase.cs @@ -141,16 +141,18 @@ protected override void CheckCoupleNode() { if (linkState == LinkState.Available && parsedAttachNode != null && parsedAttachNode.attachedPart != null) { SetLinkState(LinkState.NodeIsBlocked); - } else if (linkState == LinkState.NodeIsBlocked && parsedAttachNode.attachedPart == null) { - SetLinkState(LinkState.Available); + } else { + if (linkState == LinkState.NodeIsBlocked && parsedAttachNode.attachedPart == null) { + SetLinkState(LinkState.Available); + } } }); } #endregion #region IHasDebugAdjustables implementation - ILinkSource dbgOldSource; - float cableLength; + ILinkSource _dbgOldSource; + float _cableLength; /// public override void OnBeforeDebugAdjustablesUpdate() { @@ -158,11 +160,11 @@ public override void OnBeforeDebugAdjustablesUpdate() { if (linkState != LinkState.Linked && linkState != LinkState.Available) { throw new InvalidOperationException("Cannot adjust value in link state: " + linkState); } - dbgOldSource = linkSource; + _dbgOldSource = linkSource; if (isLinked) { var cableJoint = linkSource.linkJoint as ILinkCableJoint; if (cableJoint != null) { - cableLength = cableJoint.deployedCableLength; + _cableLength = cableJoint.deployedCableLength; } linkSource.BreakCurrentLink(LinkActorType.Player); } @@ -175,11 +177,9 @@ public override void OnDebugAdjustablesUpdated() { this, () => { InitModuleSettings(); - if (dbgOldSource != null && dbgOldSource.LinkToTarget(LinkActorType.Player, this)) { + if (_dbgOldSource != null && _dbgOldSource.LinkToTarget(LinkActorType.Player, this)) { var cableJoint = linkSource.linkJoint as ILinkCableJoint; - if (cableJoint != null) { - cableJoint.SetCableLength(cableLength); - } + cableJoint?.SetCableLength(_cableLength); } }, skipFrames: 2); // The link's logic is asynchronous, give it 2 frames to settle. diff --git a/Source/modules/KASLinkTargetKerbal.cs b/Source/modules/KASLinkTargetKerbal.cs index 7338eb489..ffcd6865a 100644 --- a/Source/modules/KASLinkTargetKerbal.cs +++ b/Source/modules/KASLinkTargetKerbal.cs @@ -46,7 +46,7 @@ public sealed class KASLinkTargetKerbal : KASLinkTargetBase, example: "[Y]: Pickup connector"); /// - static readonly Message attachConnectorMenu = new Message( + static readonly Message AttachConnectorMenu = new Message( "#kasLOC_10003", defaultTemplate: "Attach connector", description: "Context menu item that appear on the target part and transfers the EVA carried" @@ -76,8 +76,8 @@ public sealed class KASLinkTargetKerbal : KASLinkTargetBase, /// [PersistentField("equipPosAndRot", group = StdPersistentGroups.PartConfigLoadGroup)] [Debug.KASDebugAdjustable("Equip pos&rot")] - PosAndRot equipPosAndRot = new PosAndRot(); // ReSharper disable once FieldCanBeMadeReadOnly.Local + PosAndRot _equipPosAndRot = new PosAndRot(); #endregion #region Local fields and properties @@ -88,13 +88,13 @@ public sealed class KASLinkTargetKerbal : KASLinkTargetBase, /// Connector module or null. KASInternalPhysicalConnector closestConnector { get { - return connectorsInRange - .Where(x => x != null && x.ownerModule as ILinkSource != null && x.connectorRb != null) - .Where(x => (x.ownerModule as ILinkSource).linkState == LinkState.Available) + return _connectorsInRange + .Where(x => x != null && x.ownerModule is ILinkSource && x.connectorRb != null) + .Where(x => ((ILinkSource) x.ownerModule).linkState == LinkState.Available) .OrderBy(x => Vector3.Distance(gameObject.transform.position, x.connectorRb.transform.position)) .Take(1) - .FirstOrDefault(x => (x.ownerModule as ILinkSource).cfgLinkType == linkType); + .FirstOrDefault(x => ((ILinkSource) x.ownerModule).cfgLinkType == linkType); } } @@ -103,33 +103,33 @@ KASInternalPhysicalConnector closestConnector { /// This collection must be a list since the items in it can become null in case of Unity /// has destroyed the owner object. So no sets! /// - readonly List connectorsInRange = + readonly List _connectorsInRange = new List(); /// Keyboard event to react to drop the carried connector. /// It's set from the part's config. - static Event dropConnectorKeyEvent; + static Event _dropConnectorKeyEvent; /// Keyboard event to react to pick up a dropped connector. /// It's set from the part's config. - static Event pickupConnectorKeyEvent; + static Event _pickupConnectorKeyEvent; /// Message to show when there is a dropped connector in the pickup range. /// /// The message appears in the middle of the screen, and stays as long as there are connectors in /// range. /// - ScreenMessage dropConnectorMessage; + ScreenMessage _dropConnectorMessage; /// Message to show when there is a dropped connector in the pickup range. /// /// The message appears in the middle of the screen, and stays as long as there are connectors in /// range. /// - ScreenMessage pickupConnectorMessage; + ScreenMessage _pickupConnectorMessage; /// Connector that is currently highlighted as the pickup candidate. - KASInternalPhysicalConnector focusedPickupConnector; + KASInternalPhysicalConnector _focusedPickupConnector; /// Transform object of the bone which the attach node needs to follow. /// @@ -137,7 +137,7 @@ KASInternalPhysicalConnector closestConnector { /// this logic, the attach node is not connected to the bone as a child. Instead, a runtime code /// adjusts the position on every frame to follow the bone. /// - Transform attachBoneTransform; + Transform _attachBoneTransform; /// Helper container for the injected items. class InjectedEvent { @@ -153,7 +153,7 @@ class InjectedEvent { /// /// It's updated in the GUI menu callbacks and gets wiped out when the vessel looses focus. /// - Dictionary> targetCandidates = + readonly Dictionary> _targetCandidates = new Dictionary>(); #endregion @@ -171,6 +171,7 @@ public void PickupConnectorEvent() { var closestSource = connector.ownerModule as ILinkSource; HostedDebugLog.Info(this, "Try picking up a physical connector of: {0}...", closestSource); if (closestSource.LinkToTarget(LinkActorType.Player, this)) { + // By default, the cable joints set the length limit to the actual distance. var cableJoint = closestSource.linkJoint as ILinkCableJoint; cableJoint?.SetCableLength(float.PositiveInfinity); // Let the module know that we've changed the values. @@ -189,12 +190,12 @@ public override void OnAwake() { base.OnAwake(); linkStateMachine.onAfterTransition += (start, end) => UpdateContextMenu(); - dropConnectorKeyEvent = Event.KeyboardEvent(KASAPI.CommonConfig.keyDropConnector); - pickupConnectorKeyEvent = Event.KeyboardEvent(KASAPI.CommonConfig.keyPickupConnector); + _dropConnectorKeyEvent = Event.KeyboardEvent(KASAPI.CommonConfig.keyDropConnector); + _pickupConnectorKeyEvent = Event.KeyboardEvent(KASAPI.CommonConfig.keyPickupConnector); useGUILayout = false; - dropConnectorMessage = new ScreenMessage( + _dropConnectorMessage = new ScreenMessage( "", ScreenMessaging.DefaultMessageTimeout, ScreenMessageStyle.UPPER_CENTER); - pickupConnectorMessage = new ScreenMessage( + _pickupConnectorMessage = new ScreenMessage( "", ScreenMessaging.DefaultMessageTimeout, ScreenMessageStyle.LOWER_CENTER); if (HighLogic.LoadedSceneIsFlight) { RegisterGameEventListener(GameEvents.onPartActionUICreate, OnPartGUIStart); @@ -204,8 +205,8 @@ public override void OnAwake() { } /// - public override void OnStart(PartModule.StartState state) { - // The EVA parts don't get the load method called. So, to complete the initalization, pretend + public override void OnStart(StartState state) { + // The EVA parts don't get the load method called. So, to complete the initialization, pretend // the method was called with no config provided. This is needed to make the parent working. Load(new ConfigNode()); @@ -224,8 +225,8 @@ protected override void SetupStateMachine() { /// protected override void InitModuleSettings() { base.InitModuleSettings(); - attachBoneTransform = Hierarchy.FindTransformByPath(part.transform, equipBoneName); - if (attachBoneTransform == null) { + _attachBoneTransform = Hierarchy.FindTransformByPath(part.transform, equipBoneName); + if (_attachBoneTransform == null) { HostedDebugLog.Error(this, "Cannot find bone for: {0}", equipBoneName); } } @@ -238,23 +239,23 @@ public void OnGUI() { var pickupConnector = thisVesselIsActive && linkState == LinkState.Available ? closestConnector : null; - if (pickupConnector != focusedPickupConnector) { - if (focusedPickupConnector != null) { - focusedPickupConnector.SetHighlighting(null); + if (pickupConnector != _focusedPickupConnector) { + if (_focusedPickupConnector != null) { + _focusedPickupConnector.SetHighlighting(null); } - focusedPickupConnector = pickupConnector; - if (focusedPickupConnector != null && closestConnectorHighlightColor != Color.black) { - focusedPickupConnector.SetHighlighting(closestConnectorHighlightColor); + _focusedPickupConnector = pickupConnector; + if (_focusedPickupConnector != null && closestConnectorHighlightColor != Color.black) { + _focusedPickupConnector.SetHighlighting(closestConnectorHighlightColor); } } // Remove hints if any. if (!isLinked || !thisVesselIsActive) { - ScreenMessages.RemoveMessage(dropConnectorMessage); + ScreenMessages.RemoveMessage(_dropConnectorMessage); UpdateContextMenu(); } if (pickupConnector == null) { - ScreenMessages.RemoveMessage(pickupConnectorMessage); + ScreenMessages.RemoveMessage(_pickupConnectorMessage); UpdateContextMenu(); } if (!thisVesselIsActive) { @@ -262,23 +263,23 @@ public void OnGUI() { } // Handle the cable head drop/pickup events. - if (Event.current.Equals(dropConnectorKeyEvent) && isLinked) { + if (Event.current.Equals(_dropConnectorKeyEvent) && isLinked) { Event.current.Use(); linkSource.BreakCurrentLink(LinkActorType.Player); } - if (Event.current.Equals(pickupConnectorKeyEvent) && pickupConnector != null) { + if (Event.current.Equals(_pickupConnectorKeyEvent) && pickupConnector != null) { Event.current.Use(); PickupConnectorEvent(); } // Show the head drop hint message. if (isLinked) { - dropConnectorMessage.message = DropConnectorHintMsg.Format(dropConnectorKeyEvent); - ScreenMessages.PostScreenMessage(dropConnectorMessage); + _dropConnectorMessage.message = DropConnectorHintMsg.Format(_dropConnectorKeyEvent); + ScreenMessages.PostScreenMessage(_dropConnectorMessage); } if (pickupConnector != null) { - pickupConnectorMessage.message = PickupConnectorHintMsg.Format(pickupConnectorKeyEvent); - ScreenMessages.PostScreenMessage(pickupConnectorMessage); + _pickupConnectorMessage.message = PickupConnectorHintMsg.Format(_pickupConnectorKeyEvent); + ScreenMessages.PostScreenMessage(_pickupConnectorMessage); } UpdateContextMenu(); @@ -303,7 +304,7 @@ void OnTriggerEnter(Collider other) { if (other.name == KASInternalPhysicalConnector.InteractionAreaCollider) { var connector = other.gameObject.GetComponentInParent(); if (connector != null) { - connectorsInRange.Add(connector); + _connectorsInRange.Add(connector); } } } @@ -315,7 +316,7 @@ void OnTriggerExit(Collider other) { if (other.name == KASInternalPhysicalConnector.InteractionAreaCollider) { var connector = other.gameObject.GetComponentInParent(); if (connector != null) { - connectorsInRange.Remove(connector); + _connectorsInRange.Remove(connector); } } } @@ -341,25 +342,25 @@ void OnTriggerExit(Collider other) { void OnPartGUIStart(Part menuOwnerPart) { if (FlightGlobals.ActiveVessel != vessel) { // If the EVA part has lost the focus, then cleanup all the caches. - if (targetCandidates.Count > 0) { - targetCandidates + if (_targetCandidates.Count > 0) { + _targetCandidates .SelectMany(t => t.Value) .Where(ie => ie.baseEvent != null) .ToList() .ForEach(ie => PartModuleUtils.DropEvent(ie.module as PartModule, ie.baseEvent)); - targetCandidates.Clear(); + _targetCandidates.Clear(); } return; } // Check if the menu injects need to be added/removed on the monitored parts. List injects; - if (!targetCandidates.TryGetValue(menuOwnerPart.flightID, out injects)) { + if (!_targetCandidates.TryGetValue(menuOwnerPart.flightID, out injects)) { injects = menuOwnerPart.Modules.OfType() .Where(t => t.cfgLinkType == cfgLinkType) .Select(t => new InjectedEvent() { module = t, baseEvent = null }) .ToList(); - targetCandidates.Add(menuOwnerPart.flightID, injects); + _targetCandidates.Add(menuOwnerPart.flightID, injects); } foreach (var inject in injects) { var target = inject.module; @@ -368,7 +369,7 @@ void OnPartGUIStart(Part menuOwnerPart) { PartModuleUtils.DropEvent(target as PartModule, inject.baseEvent); inject.baseEvent = null; } else if (canLink && inject.baseEvent == null) { - inject.baseEvent = MakeEvent(target, attachConnectorMenu, LinkCarriedConnector); + inject.baseEvent = MakeEvent(target, AttachConnectorMenu, LinkCarriedConnector); PartModuleUtils.AddEvent(target as PartModule, inject.baseEvent); } } @@ -379,11 +380,11 @@ void OnPartGUIStart(Part menuOwnerPart) { /// void OnPartGUIStop(Part menuOwnerPart) { List injects; - if (targetCandidates.TryGetValue(menuOwnerPart.flightID, out injects)) { + if (_targetCandidates.TryGetValue(menuOwnerPart.flightID, out injects)) { injects .Where(ie => ie.baseEvent != null).ToList() .ForEach(ie => PartModuleUtils.DropEvent(ie.module as PartModule, ie.baseEvent)); - targetCandidates.Remove(menuOwnerPart.flightID); + _targetCandidates.Remove(menuOwnerPart.flightID); } } @@ -412,22 +413,23 @@ void LinkCarriedConnector(ILinkPeer peer) { /// The new event. It's not automatically injected into the part. BaseEvent MakeEvent(ILinkPeer peer, Message guiName, Action action) { var ev = new BaseEvent( - peer.part.Events, - "autoEventAttach" + peer.part.Modules.IndexOf(peer as PartModule), - () => action.Invoke(peer), - new KSPEvent()); - ev.guiActive = true; - ev.guiActiveUncommand = true; - ev.guiActiveUnfocused = true; - ev.guiName = guiName; + peer.part.Events, + "autoEventAttach" + peer.part.Modules.IndexOf(peer as PartModule), + () => action.Invoke(peer), + new KSPEvent()) { + guiActive = true, + guiActiveUncommand = true, + guiActiveUnfocused = true, + guiName = guiName + }; return ev; } /// Aligns the node transform to the bone while the link is active. IEnumerator FollowTheBone() { - while (attachBoneTransform != null && isLinked) { - nodeTransform.rotation = attachBoneTransform.rotation * equipPosAndRot.rot; - nodeTransform.position = attachBoneTransform.TransformPoint(equipPosAndRot.pos); + while (_attachBoneTransform != null && isLinked) { + nodeTransform.rotation = _attachBoneTransform.rotation * _equipPosAndRot.rot; + nodeTransform.position = _attachBoneTransform.TransformPoint(_equipPosAndRot.pos); yield return null; } } diff --git a/Source/modules/KASLinkWinch.cs b/Source/modules/KASLinkWinch.cs index f6040a5a4..db7db0acc 100644 --- a/Source/modules/KASLinkWinch.cs +++ b/Source/modules/KASLinkWinch.cs @@ -219,8 +219,8 @@ public class KASLinkWinch : KASLinkSourcePhysical, defaultTemplate = "Open winches GUI", description = "A context menu item that opens the remote control GUI to operate the winches" + " in the scene.")] - public virtual void OpenGUIEvent() { - ControllerWinchRemote.ToggleGUI(true); + public virtual void OpenGuiEvent() { + ControllerWinchRemote.ToggleGui(true); } /// A context menu item that starts/stops extending the cable. @@ -339,12 +339,12 @@ public float motorCurrentSpeed { get { return _motorCurrentSpeed; } private set { if (Mathf.Abs(value) < float.Epsilon && Mathf.Abs(_motorCurrentSpeed) > float.Epsilon) { - sndMotorStop.Play(); - sndMotor.Stop(); + _sndMotorStop.Play(); + _sndMotor.Stop(); } if (Mathf.Abs(value) > float.Epsilon && Mathf.Abs(_motorCurrentSpeed) < float.Epsilon) { - sndMotorStart.Play(); - sndMotor.Play(); + _sndMotorStart.Play(); + _sndMotor.Play(); } _motorCurrentSpeed = value; } @@ -364,15 +364,15 @@ private set { #region Local fields & properties /// Sound to play when the motor is active. /// - AudioSource sndMotor; + AudioSource _sndMotor; /// Sounds to play when the motor starts. /// - AudioSource sndMotorStart; + AudioSource _sndMotorStart; /// Sounds to play when the motor stops. /// - AudioSource sndMotorStop; + AudioSource _sndMotorStop; #endregion #region KASLikSourcePhysical overrides @@ -392,19 +392,20 @@ public override string GetInfo() { /// protected override void InitModuleSettings() { base.InitModuleSettings(); - Destroy(sndMotor); - sndMotor = SpatialSounds.Create3dSound(part.gameObject, sndPathMotor, loop: true); - Destroy(sndMotorStart); - sndMotorStart = SpatialSounds.Create3dSound(part.gameObject, sndPathMotorStart); - Destroy(sndMotorStop); - sndMotorStop = SpatialSounds.Create3dSound(part.gameObject, sndPathMotorStop); + Destroy(_sndMotor); + _sndMotor = SpatialSounds.Create3dSound(part.gameObject, sndPathMotor, loop: true); + Destroy(_sndMotorStart); + _sndMotorStart = SpatialSounds.Create3dSound(part.gameObject, sndPathMotorStart); + Destroy(_sndMotorStop); + _sndMotorStop = SpatialSounds.Create3dSound(part.gameObject, sndPathMotorStop); var moduleResource = resHandler.inputResources .FirstOrDefault(x => x.name == StockResourceNames.ElectricCharge); if (moduleResource == null) { - moduleResource = new ModuleResource(); - moduleResource.name = StockResourceNames.ElectricCharge; - moduleResource.id = StockResourceNames.ElectricCharge.GetHashCode(); + moduleResource = new ModuleResource { + name = StockResourceNames.ElectricCharge, + id = StockResourceNames.ElectricCharge.GetHashCode() + }; resHandler.inputResources.Add(moduleResource); } moduleResource.title = KSPUtil.PrintModuleName(StockResourceNames.ElectricCharge); @@ -440,8 +441,7 @@ public virtual void FixedUpdate() { /// public override void UpdateContextMenu() { base.UpdateContextMenu(); - deployedCableLengthMenuInfo = DistanceType.Format( - cableJoint != null ? cableJoint.deployedCableLength : 0); + deployedCableLengthMenuInfo = DistanceType.Format(cableJoint?.deployedCableLength ?? 0); PartModuleUtils.SetupEvent(this, ToggleExtendCableEvent, e => { e.active = linkState != LinkState.NodeIsBlocked; diff --git a/Source/modules/KASRendererBezierPipe.cs b/Source/modules/KASRendererBezierPipe.cs index def85ab7b..99e0ccab4 100644 --- a/Source/modules/KASRendererBezierPipe.cs +++ b/Source/modules/KASRendererBezierPipe.cs @@ -95,7 +95,7 @@ public sealed class KASRendererBezierPipe : KASRendererPipe { /// /// /// - float[] boneOffsets; + float[] _boneOffsets; /// Colliders, assigned to the bones. /// @@ -103,7 +103,7 @@ public sealed class KASRendererBezierPipe : KASRendererPipe { /// member is null for the non-physical renderers, of if the renderer is not started yet. /// /// - CapsuleCollider[] colliders; + CapsuleCollider[] _colliders; #endregion #region KASRendererPipe overrides @@ -115,18 +115,18 @@ protected override void SetupPipe(Transform fromObj, Transform toObj) { /// protected override void CreateLinkPipe() { - // Relacing the base that creates a stright pipe. + // Replacing the base that creates a straight pipe. DestroyPipeMesh(); MakeBoneSamples(); - pipeTransform = new GameObject(ModelBasename + "-pipe").transform; + pipeTransform = new GameObject(modelBasename + "-pipe").transform; pipeTransform.parent = sourceTransform; // Make the boned cylinder vertices. To properly wrap the texture we need an extra vertex. - int VertexCount = (pipeShapeSmoothness + 1) * pipeMeshSections; - var vertices = new Vector3[VertexCount]; - var normals = new Vector3[VertexCount]; - var uv = new Vector2[VertexCount]; - var boneWeights = new BoneWeight[VertexCount]; + var vertexCount = (pipeShapeSmoothness + 1) * pipeMeshSections; + var vertices = new Vector3[vertexCount]; + var normals = new Vector3[vertexCount]; + var uv = new Vector2[vertexCount]; + var boneWeights = new BoneWeight[vertexCount]; var vertexIdx = 0; var angleStep = 2.0f * Mathf.PI / pipeShapeSmoothness; var radius = pipeDiameter / 2; @@ -135,7 +135,7 @@ protected override void CreateLinkPipe() { vertices[vertexIdx] = new Vector3( radius * Mathf.Sin(angleStep * i), radius * Mathf.Cos(angleStep * i), - boneOffsets[j]); + _boneOffsets[j]); normals[vertexIdx] = new Vector3( radius * Mathf.Sin(angleStep * i), radius * Mathf.Cos(angleStep * i), 0); if (pipeTextureRescaleMode == PipeTextureRescaleMode.TileFromTarget) { @@ -178,20 +178,21 @@ protected override void CreateLinkPipe() { bones[j] = new GameObject("bone" + j).transform; bones[j].parent = pipeTransform; bones[j].localRotation = Quaternion.identity; - bones[j].localPosition = Vector3.forward * boneOffsets[j]; + bones[j].localPosition = Vector3.forward * _boneOffsets[j]; bindPoses[j] = bones[j].worldToLocalMatrix * pipeTransform.localToWorldMatrix; } pipeMeshRenderer = pipeTransform.gameObject.AddComponent(); pipeSkinnedMeshRenderer.sharedMaterial = pipeMaterial; - var mesh = new Mesh(); - mesh.vertices = vertices; - mesh.normals = normals; - mesh.uv = uv; - mesh.triangles = triangles; - mesh.boneWeights = boneWeights; - mesh.bindposes = bindPoses; + var mesh = new Mesh { + vertices = vertices, + normals = normals, + uv = uv, + triangles = triangles, + boneWeights = boneWeights, + bindposes = bindPoses + }; pipeSkinnedMeshRenderer.bones = bones; pipeSkinnedMeshRenderer.sharedMesh = mesh; @@ -215,7 +216,7 @@ protected override void CreateLinkPipe() { /// protected override void DestroyPipeMesh() { base.DestroyPipeMesh(); - colliders = null; + _colliders = null; } /// @@ -242,23 +243,23 @@ void AlignToCurve(Transform fromObj, Transform toObj) { var p1 = p0 + fromObj.forward * pipeBendResistance; var p3 = toObj.position; var p2 = p3 + toObj.forward * pipeBendResistance; - var p0vector = p1 - p0; - var p1vector = p2 - p1; - var p2vector = p3 - p2; + var p0Vector = p1 - p0; + var p1Vector = p2 - p1; + var p2Vector = p3 - p2; var bones = pipeSkinnedMeshRenderer.bones; for (var i = 0; i < bones.Length; i++) { var section = bones[i]; - var t = boneOffsets[i]; + var t = _boneOffsets[i]; // Simplified implementation for the cubic curves. - var p01pos = p0 + p0vector * t; - var p12pos = p1 + p1vector * t; - var p23pos = p2 + p2vector * t; - var p02pos = p01pos + (p12pos - p01pos) * t; - var p13pos = p12pos + (p23pos - p12pos) * t; - var elementVector = p13pos - p02pos; + var p01Pos = p0 + p0Vector * t; + var p12Pos = p1 + p1Vector * t; + var p23Pos = p2 + p2Vector * t; + var p02Pos = p01Pos + (p12Pos - p01Pos) * t; + var p13Pos = p12Pos + (p23Pos - p12Pos) * t; + var elementVector = p13Pos - p02Pos; var elementDir = elementVector.normalized; - var elementPos = p02pos + elementVector * t; + var elementPos = p02Pos + elementVector * t; section.transform.position = elementPos; // Use UP vector from the previous node to reduce artifacts when the pipe is bend at a sharp @@ -270,7 +271,7 @@ void AlignToCurve(Transform fromObj, Transform toObj) { // Have the texture rescale setting adjusted. RescaleMeshSectionTextures(); - if (colliders != null) { + if (_colliders != null) { UpdateColliders(); } } @@ -314,12 +315,12 @@ void RescaleMeshSectionTextures() { } /// Creates the Bezier Curve arguments (the t parameter). - /// + /// void MakeBoneSamples() { var k = pipeMeshSections - 1; - boneOffsets = new float[pipeMeshSections]; + _boneOffsets = new float[pipeMeshSections]; for (var n = 0; n < pipeMeshSections; n++) { - boneOffsets[n] = (float)n / k; + _boneOffsets[n] = (float)n / k; } } @@ -327,13 +328,13 @@ void MakeBoneSamples() { void CreateColliders() { var bones = pipeSkinnedMeshRenderer.bones; // TODO(ihsoft): Capsules will hit extra things at the ends of the pipe. Find a way to fix it. - colliders = new CapsuleCollider[bones.Length - 1]; + _colliders = new CapsuleCollider[bones.Length - 1]; for (var i = 0; i < bones.Length - 1; ++i) { var capsule = bones[i].transform.gameObject.AddComponent(); capsule.direction = 2; // Z-axis capsule.radius = pipeDiameter / 2; capsule.height = pipeDiameter; - colliders[i] = capsule; + _colliders[i] = capsule; } } @@ -341,7 +342,7 @@ void CreateColliders() { void UpdateColliders() { var bones = pipeSkinnedMeshRenderer.bones; for (var i = 0; i < bones.Length - 1; ++i) { - var capsule = colliders[i]; + var capsule = _colliders[i]; var boneDistance = (bones[i].position - bones[i + 1].position).magnitude; capsule.center = new Vector3(0, 0, boneDistance / 2); // The capsules from the adjacent bones should "connect" at the half-sphere center. diff --git a/Source/modules/KASRendererPipe.cs b/Source/modules/KASRendererPipe.cs index c1c4d6b47..40b51d650 100644 --- a/Source/modules/KASRendererPipe.cs +++ b/Source/modules/KASRendererPipe.cs @@ -137,7 +137,7 @@ public class JointConfig { /// [PersistentField("parkAttachAt")] [Debug.KASDebugAdjustable("Park location pos&rot")] - public PosAndRot parkAttachAt; + public PosAndRot parkAttachAt = new PosAndRot(); /// /// Tells if the only prefab model, but not the procedural models must be parked on renderer @@ -440,7 +440,7 @@ protected virtual void UpdateJointNode(ModelPipeEndNode node, Transform alignTo) node.parkRootObject = partModelTransform; // Create basic setup. - var nodeName = ModelBasename + "-pipeNode" + node.name; + var nodeName = modelBasename + "-pipeNode" + node.name; node.rootModel = partModelTransform.Find(nodeName) ?? new GameObject(nodeName).transform; node.rootModel.parent = partModelTransform; @@ -472,10 +472,12 @@ protected virtual void UpdateJointNode(ModelPipeEndNode node, Transform alignTo) } // Parking position, if defined. - var parkObjectName = ModelBasename + "-park" + node.name; + var parkObjectName = modelBasename + "-park" + node.name; var parkAttach = partModelTransform.Find(parkObjectName); if (config.parkAttachAt != null) { - node.parkAttach = parkAttach ?? new GameObject(parkObjectName).transform; + node.parkAttach = parkAttach + ? parkAttach + : new GameObject(parkObjectName).transform; Hierarchy.MoveToParent(node.parkAttach, partModelTransform, newPosition: config.parkAttachAt.pos, newRotation: config.parkAttachAt.rot); @@ -519,9 +521,10 @@ protected virtual void UpdateJointNode(ModelPipeEndNode node, Transform alignTo) arm.name = armName; } arm.GetComponent().sharedMaterial = pipeMaterial; // For performance. - arm.transform.localPosition = new Vector3(0, 0, -config.sphereOffset / 2); - arm.transform.localRotation = Quaternion.LookRotation(Vector3.forward); - RescalePipeTexture(arm.transform, arm.localScale.z * config.sphereOffset); + var armTransform = arm.transform; + armTransform.localPosition = new Vector3(0, 0, -config.sphereOffset / 2); + armTransform.localRotation = Quaternion.LookRotation(Vector3.forward); + RescalePipeTexture(armTransform, arm.localScale.z * config.sphereOffset); } else if (arm != null) { Hierarchy2.SafeDestroy(arm); } @@ -559,16 +562,19 @@ protected virtual void CreateLinkPipe() { /// The object to draw pipe to. /// protected virtual void SetupPipe(Transform fromObj, Transform toObj) { - pipeTransform.position = (fromObj.position + toObj.position) / 2; - if (pipeTextureRescaleMode == PipeTextureRescaleMode.TileFromTarget) { - pipeTransform.LookAt(fromObj); - } else { - pipeTransform.LookAt(toObj); - } - pipeTransform.localScale = new Vector3( - pipeTransform.localScale.x, - pipeTransform.localScale.y, - Vector3.Distance(fromObj.position, toObj.position) / baseScale); + var fromObjPosition = fromObj.position; + var toObjPosition = toObj.position; + pipeTransform.position = (fromObjPosition + toObjPosition) / 2; + pipeTransform.LookAt( + pipeTextureRescaleMode == PipeTextureRescaleMode.TileFromTarget + ? fromObj + : toObj); + var localScale = pipeTransform.localScale; + localScale = new Vector3( + localScale.x, + localScale.y, + Vector3.Distance(fromObjPosition, toObjPosition) / baseScale); + pipeTransform.localScale = localScale; if (pipeTextureRescaleMode != PipeTextureRescaleMode.Stretch) { RescalePipeTexture(pipeTransform, pipeTransform.localScale.z, renderer: pipeMeshRenderer); } @@ -599,7 +605,9 @@ protected virtual void SetupPipe(Transform fromObj, Transform toObj) { /// protected void RescalePipeTexture(Transform obj, float length, Renderer renderer = null) { var newScale = length * pipeTextureSamplesPerMeter / baseScale; - var material = (renderer ?? obj.GetComponent()).material; + var material = (renderer + ? renderer + : obj.GetComponent()).material; material.mainTextureScale = new Vector2(material.mainTextureScale.x, newScale); SetBumpMap(material, propName => { var nrmScale = material.GetTextureScale(propName); diff --git a/Source/modules/KASRendererTelescopicPipe.cs b/Source/modules/KASRendererTelescopicPipe.cs index 7d8e6a5d3..fd39bf653 100644 --- a/Source/modules/KASRendererTelescopicPipe.cs +++ b/Source/modules/KASRendererTelescopicPipe.cs @@ -189,7 +189,7 @@ public class Orientation { // FIXME: check colliders. #region Context menu events/actions /// Event handler. Extends unlinked strut at maximum length. - /// + /// [KSPEvent(guiActiveUnfocused = true, guiActiveEditor = true, active = false)] [LocalizableItem( tag = "#kasLOC_04002", @@ -197,12 +197,12 @@ public class Orientation { description = "A context menu item that expands a non-linked telescopic pipe to its maximum" + " length.")] public void ExtendAtMaxMenuAction() { - persistedParkedLength = maxLinkLength; + persistedParkedLength = _maxLinkLength; UpdateLinkLengthAndOrientation(); } /// Event handler. Retracts unlinked strut to the minimum length. - /// + /// [KSPEvent(guiActiveUnfocused = true, guiActiveEditor = true, active = false)] [LocalizableItem( tag = "#kasLOC_04003", @@ -210,7 +210,7 @@ public void ExtendAtMaxMenuAction() { description = "A context menu item that shrinks a non-linked telescopic pipe to its minimum" + " length.")] public void RetractToMinMenuAction() { - persistedParkedLength = minLinkLength; + persistedParkedLength = _minLinkLength; UpdateLinkLengthAndOrientation(); } #endregion @@ -224,7 +224,7 @@ public Color? colorOverride { get { return _colorOverride; } set { _colorOverride = value; - Meshes.UpdateMaterials(srcPartJoint.gameObject, newColor: _colorOverride ?? materialColor); + Meshes.UpdateMaterials(_srcPartJoint.gameObject, newColor: _colorOverride ?? materialColor); } } Color? _colorOverride; @@ -238,7 +238,7 @@ public string shaderNameOverride { // Only update shader on the source joint object since all other objects (pistons and target // joint) are children and will be updated hierarchically. Meshes.UpdateMaterials( - srcPartJoint.gameObject, newShaderName: _shaderNameOverride ?? shaderName); + _srcPartJoint.gameObject, newShaderName: _shaderNameOverride ?? shaderName); } } string _shaderNameOverride; @@ -248,15 +248,13 @@ public bool isPhysicalCollider { get { return _isPhysicalCollider; } set { _isPhysicalCollider = value; - Colliders.UpdateColliders(srcPartJoint.gameObject, isEnabled: value); + Colliders.UpdateColliders(_srcPartJoint.gameObject, isEnabled: value); } } bool _isPhysicalCollider; /// - public bool isStarted { - get { return sourceTransform != null && targetTransform != null; } - } + public bool isStarted => sourceTransform != null && targetTransform != null; /// public Transform sourceTransform { @@ -314,62 +312,62 @@ private set { #region Model transforms & properties /// Model that represents a joint at the source part. /// An object in the part's model. It's never null. - Transform srcPartJoint; + Transform _srcPartJoint; /// Pivot axis object on the source joint. /// An object in the part's model. It's never null. - Transform srcPartJointPivot; + Transform _srcPartJointPivot; /// Model at the pipe's start that connects to the source joint pivot. /// An object in the part's model. It's never null. /// It's orientation is reversed. I.e .it "looks" at the source joint pivot. - Transform srcStrutJoint; + Transform _srcStrutJoint; /// Model at the pipe's end that connects to the target joint pivot. /// An object in the part's model. It's never null. - Transform tgtStrutJoint; + Transform _tgtStrutJoint; /// Pivot axis object at the pipe's end. /// An object in the part's model. It's never null. - Transform tgtStrutJointPivot; + Transform _tgtStrutJointPivot; /// Pistons that form the strut pipe. /// A list of meshes. - GameObject[] pistons; + GameObject[] _pistons; /// /// Distance of the source part joint pivot from it's base. It's calculated from the model. /// /// The distance in meters. - float srcJointHandleLength; + float _srcJointHandleLength; /// /// Distance of the target part joint pivot from it's base. It's calculated from the model. /// /// The distance in meters. - float tgtJointHandleLength; + float _tgtJointHandleLength; /// /// The minimum length to which the telescopic pipe can shrink. It's calculated from the model. /// /// The distance in meters. - float minLinkLength; + float _minLinkLength; /// /// The maximum length to which the telescopic pipe can expand. It's calculated from the model. /// /// The distance in meters. - float maxLinkLength; + float _maxLinkLength; /// Diameter of the outer piston. It's calculated from the model. /// The diameter in metters. /// It's primarily used to cast a collider. /// - float outerPistonDiameter; + float _outerPistonDiameter; /// Length of a single piston. It's calculated from the model. /// The distance in meters. - float pistonLength; + float _pistonLength; /// Prefab for the piston models. /// A model reference from the part's model. It's not a copy! @@ -419,7 +417,7 @@ Transform plugNodeTransform { #region Local fields & properties /// Instances of the events, that were created for orientation menu items. - readonly List injectedOrientationEvents = new List(); + readonly List _injectedOrientationEvents = new List(); #endregion #region IHasDebugAdjustables implementation @@ -429,9 +427,9 @@ public void DbgEventDumpLinkSettings() { HostedDebugLog.Warning(this, "Procedural model: minLinkLength={0}, maxLinkLength={1}, attachNodePosition.Y={2}," + " pistonLength={3}, outerPistonDiameter={4}", - minLinkLength, maxLinkLength, - Hierarchy.FindTransformInChildren(srcStrutJoint, PivotAxleTransformName).position.y, - pistonLength, outerPistonDiameter); + _minLinkLength, _maxLinkLength, + Hierarchy.FindTransformInChildren(_srcStrutJoint, PivotAxleTransformName).position.y, + _pistonLength, _outerPistonDiameter); } /// @@ -455,7 +453,7 @@ public override void OnLoad(ConfigNode node) { } /// - public override void OnStart(PartModule.StartState state) { + public override void OnStart(StartState state) { base.OnStart(state); InjectOrientationMenuItems(); @@ -476,24 +474,24 @@ protected override void InitModuleSettings() { CreatePipeMeshes(recreate: false); // Source pivot. - srcPartJoint = Hierarchy.FindTransformByPath( + _srcPartJoint = Hierarchy.FindTransformByPath( partModelTransform, AttachNodeObjName + "/" + SrcPartJointObjName); - srcPartJointPivot = Hierarchy.FindTransformInChildren(srcPartJoint, PivotAxleTransformName); + _srcPartJointPivot = Hierarchy.FindTransformInChildren(_srcPartJoint, PivotAxleTransformName); // Source strut joint. - srcStrutJoint = Hierarchy.FindTransformInChildren(srcPartJointPivot, SrcStrutJointObjName); - var srcStrutPivot = Hierarchy.FindTransformInChildren(srcStrutJoint, PivotAxleTransformName); - srcJointHandleLength = Vector3.Distance(srcStrutJoint.position, srcStrutPivot.position); + _srcStrutJoint = Hierarchy.FindTransformInChildren(_srcPartJointPivot, SrcStrutJointObjName); + var srcStrutPivot = Hierarchy.FindTransformInChildren(_srcStrutJoint, PivotAxleTransformName); + _srcJointHandleLength = Vector3.Distance(_srcStrutJoint.position, srcStrutPivot.position); // Target strut joint. - tgtStrutJoint = Hierarchy.FindTransformInChildren(srcPartJointPivot, TgtStrutJointObjName); - tgtStrutJointPivot = Hierarchy.FindTransformInChildren(tgtStrutJoint, PivotAxleTransformName); - tgtJointHandleLength = Vector3.Distance(tgtStrutJoint.position, tgtStrutJointPivot.position); + _tgtStrutJoint = Hierarchy.FindTransformInChildren(_srcPartJointPivot, TgtStrutJointObjName); + _tgtStrutJointPivot = Hierarchy.FindTransformInChildren(_tgtStrutJoint, PivotAxleTransformName); + _tgtJointHandleLength = Vector3.Distance(_tgtStrutJoint.position, _tgtStrutJointPivot.position); // Pistons. - pistons = new GameObject[pistonsCount]; + _pistons = new GameObject[pistonsCount]; for (var i = 0; i < pistonsCount; ++i) { - pistons[i] = Hierarchy.FindTransformInChildren(partModelTransform, "piston" + i).gameObject; + _pistons[i] = Hierarchy.FindTransformInChildren(partModelTransform, "piston" + i).gameObject; } UpdateValuesFromModel(); @@ -503,8 +501,8 @@ protected override void InitModuleSettings() { /// public override void LocalizeModule() { base.LocalizeModule(); - for (var i = 0; i < parkedOrientations.Count && i < injectedOrientationEvents.Count; i++) { - injectedOrientationEvents[i].guiName = parkedOrientations[i].title; + for (var i = 0; i < parkedOrientations.Count && i < _injectedOrientationEvents.Count; i++) { + _injectedOrientationEvents[i].guiName = parkedOrientations[i].title; } } #endregion @@ -535,7 +533,7 @@ public string[] CheckColliderHits(Transform source, Transform target) { var sourcePos = GetLinkVectorSourcePos(source); var linkVector = GetLinkVectorTargetPos(target) - sourcePos; var hits = Physics.SphereCastAll( - sourcePos, outerPistonDiameter / 2, linkVector, GetClampedLinkLength(linkVector), + sourcePos, _outerPistonDiameter / 2, linkVector, GetClampedLinkLength(linkVector), (int)(KspLayerMask.Part | KspLayerMask.SurfaceCollider | KspLayerMask.Kerbal), QueryTriggerInteraction.Ignore); foreach (var hit in hits) { @@ -559,7 +557,7 @@ public Transform GetMeshByName(string meshName) { #region IHasContextMenu implemenation /// public void UpdateContextMenu() { - injectedOrientationEvents.ForEach(e => e.active = !isLinked); + _injectedOrientationEvents.ForEach(e => e.active = !isLinked); PartModuleUtils.SetupEvent(this, ExtendAtMaxMenuAction, x => x.active = !isLinked); PartModuleUtils.SetupEvent(this, RetractToMinMenuAction, x => x.active = !isLinked); } @@ -569,13 +567,13 @@ public void UpdateContextMenu() { /// Adjusts link models to the changed target position. void UpdateLinkLengthAndOrientation() { if (!isStarted) { - // Simply align everyting along Z axis, and rotate source pivot according to the settings. - srcPartJoint.localRotation = Quaternion.identity; - srcPartJointPivot.localRotation = Quaternion.LookRotation(persistedParkedOrientation); - tgtStrutJoint.localPosition = - GetUnscaledStrutVector(new Vector3(0, 0, persistedParkedLength - tgtJointHandleLength)); - tgtStrutJoint.localRotation = Quaternion.identity; - tgtStrutJointPivot.localRotation = Quaternion.identity; + // Simply align everything along Z axis, and rotate source pivot according to the settings. + _srcPartJoint.localRotation = Quaternion.identity; + _srcPartJointPivot.localRotation = Quaternion.LookRotation(persistedParkedOrientation); + _tgtStrutJoint.localPosition = + GetUnscaledStrutVector(new Vector3(0, 0, persistedParkedLength - _tgtJointHandleLength)); + _tgtStrutJoint.localRotation = Quaternion.identity; + _tgtStrutJointPivot.localRotation = Quaternion.identity; } else { var linkVector = GetLinkVectorTargetPos(targetTransform) - GetLinkVectorSourcePos(sourceTransform); @@ -585,35 +583,35 @@ void UpdateLinkLengthAndOrientation() { // connected with a common pivot axle which is parallel to their X axis. // 1. Rotate srcPartJoint around Z axis so what its pivot axle (X) is perpendicular to // the link vector. - srcPartJoint.rotation = Quaternion.LookRotation(srcPartJoint.forward, -linkVector); + _srcPartJoint.rotation = Quaternion.LookRotation(_srcPartJoint.forward, -linkVector); // 2. Rotate srcPivot around X axis (pivot axle) so what its forward vector points to the // target part attach node. - srcPartJointPivot.localRotation = - Quaternion.Euler(Vector3.Angle(linkVector, srcPartJoint.forward), 0, 0); + _srcPartJointPivot.localRotation = + Quaternion.Euler(Vector3.Angle(linkVector, _srcPartJoint.forward), 0, 0); // 3. Shift tgtStrutJoint along Z axis so what it touches the vector end position with the // tgtPivot pivot axle. - tgtStrutJoint.localPosition = GetUnscaledStrutVector( - new Vector3(0, 0, GetClampedLinkLength(linkVector) - tgtJointHandleLength)); + _tgtStrutJoint.localPosition = GetUnscaledStrutVector( + new Vector3(0, 0, GetClampedLinkLength(linkVector) - _tgtJointHandleLength)); // 4. Rotate tgtStrutJoint around Z axis so what its pivot axle (X) is perpendicular to // the target part attach node. - tgtStrutJoint.rotation = - Quaternion.LookRotation(tgtStrutJoint.forward, targetTransform.forward); + _tgtStrutJoint.rotation = + Quaternion.LookRotation(_tgtStrutJoint.forward, targetTransform.forward); // 5. Rotate tgtPivot around X axis (pivot axle) so that its forward vector points along // target attach node direction. - tgtStrutJointPivot.localRotation = - Quaternion.Euler(Vector3.Angle(tgtStrutJoint.forward, -targetTransform.forward), 0, 0); + _tgtStrutJointPivot.localRotation = + Quaternion.Euler(Vector3.Angle(_tgtStrutJoint.forward, -targetTransform.forward), 0, 0); } - // Distribute pistons between the first and the last while keepin the direction. - if (pistons.Length > 2) { - var offset = pistons[0].transform.localPosition.z; - var scalablePistons = pistons.Length - 1; + // Distribute pistons between the first and the last while keeping the direction. + if (_pistons.Length > 2) { + var offset = _pistons[0].transform.localPosition.z; + var scalablePistons = _pistons.Length - 1; var step = GetUnscaledStrutVector( - pistons.Last().transform.position - pistons[0].transform.position).magnitude + _pistons.Last().transform.position - _pistons[0].transform.position).magnitude / scalablePistons; for (var i = 1; i < scalablePistons; ++i) { - offset -= step; // Pistons are distributed to -Z direction of the pviot. - pistons[i].transform.localPosition = new Vector3(0, 0, offset); + offset -= step; // Pistons are distributed to -Z direction of the pivot. + _pistons[i].transform.localPosition = new Vector3(0, 0, offset); } } } @@ -623,34 +621,35 @@ void UpdateLinkLengthAndOrientation() { void InjectOrientationMenuItems() { foreach (var orientation in parkedOrientations) { var eventInject = new BaseEvent( - Events, - "autoEventOrientation" + part.Modules.IndexOf(this), - () => { - persistedParkedOrientation = orientation.direction; - UpdateLinkLengthAndOrientation(); - }, - new KSPEvent()); - eventInject.guiName = orientation.title; - eventInject.guiActive = false; - eventInject.guiActiveEditor = true; - eventInject.guiActiveUnfocused = true; + Events, + "autoEventOrientation" + part.Modules.IndexOf(this), + () => { + persistedParkedOrientation = orientation.direction; + UpdateLinkLengthAndOrientation(); + }, + new KSPEvent()) { + guiName = orientation.title, + guiActive = false, + guiActiveEditor = true, + guiActiveUnfocused = true + }; PartModuleUtils.AddEvent(this, eventInject); - injectedOrientationEvents.Add(eventInject); + _injectedOrientationEvents.Add(eventInject); } } /// Returns link length. Adjusts it to min/max length. /// Link vector. /// Clamped link length - /// - /// + /// + /// float GetClampedLinkLength(Vector3 linkVector) { var linkLength = linkVector.magnitude; - if (linkLength < minLinkLength) { - return minLinkLength; + if (linkLength < _minLinkLength) { + return _minLinkLength; } - if (linkLength > maxLinkLength) { - return maxLinkLength; + if (linkLength > _maxLinkLength) { + return _maxLinkLength; } return linkLength; } @@ -680,16 +679,16 @@ Vector3 GetUnscaledStrutVector(Vector3 scaledLength) { void UpdateValuesFromModel() { var pistonSize = GetScaledStrutVector( Vector3.Scale(pistonPrefab.GetComponent().bounds.size, pistonModelScale)); - pistonLength = pistonSize.y; - outerPistonDiameter = Mathf.Max(pistonSize.x, pistonSize.z); - minLinkLength = - srcJointHandleLength - + pistonLength + (pistonsCount - 1) * pistonMinShift * strutScale - + tgtJointHandleLength; - maxLinkLength = - srcJointHandleLength - + pistonsCount * (pistonLength - pistonMinShift * strutScale) - + tgtJointHandleLength; + _pistonLength = pistonSize.y; + _outerPistonDiameter = Mathf.Max(pistonSize.x, pistonSize.z); + _minLinkLength = + _srcJointHandleLength + + _pistonLength + (pistonsCount - 1) * pistonMinShift * strutScale + + _tgtJointHandleLength; + _maxLinkLength = + _srcJointHandleLength + + pistonsCount * (_pistonLength - pistonMinShift * strutScale) + + _tgtJointHandleLength; } /// @@ -720,8 +719,7 @@ GameObject MakeJointModel(GameObject jointPrefab) { jointModel.name = JointModelName; var jointModelPivot = jointPrefab.transform.Find(PivotAxleTransformName); - jointModelPivot = Instantiate(jointModelPivot); - jointModelPivot.parent = jointModel.transform; + jointModelPivot = Instantiate(jointModelPivot, jointModel.transform, true); jointModelPivot.name = PivotAxleTransformName; return jointModel; @@ -733,31 +731,31 @@ void CreateLeverModels() { var srcJointModel = MakeJointModel(GameDatabase.Instance.GetModelPrefab(sourceJointModel)); // Source part joint model. - srcPartJoint = CloneModel(srcJointModel, SrcPartJointObjName).transform; - Hierarchy.MoveToParent(srcPartJoint, plugNodeTransform); - srcPartJointPivot = Hierarchy.FindTransformInChildren(srcPartJoint, PivotAxleTransformName); + _srcPartJoint = CloneModel(srcJointModel, SrcPartJointObjName).transform; + Hierarchy.MoveToParent(_srcPartJoint, plugNodeTransform); + _srcPartJointPivot = Hierarchy.FindTransformInChildren(_srcPartJoint, PivotAxleTransformName); // Source strut joint model. - srcStrutJoint = CloneModel(srcJointModel, SrcStrutJointObjName).transform; - var srcStrutPivot = Hierarchy.FindTransformInChildren(srcStrutJoint, PivotAxleTransformName); - srcJointHandleLength = Vector3.Distance(srcStrutJoint.position, srcStrutPivot.position); - Hierarchy.MoveToParent(srcStrutJoint, srcPartJointPivot, - newPosition: new Vector3(0, 0, srcJointHandleLength), + _srcStrutJoint = CloneModel(srcJointModel, SrcStrutJointObjName).transform; + var srcStrutPivot = Hierarchy.FindTransformInChildren(_srcStrutJoint, PivotAxleTransformName); + _srcJointHandleLength = Vector3.Distance(_srcStrutJoint.position, srcStrutPivot.position); + Hierarchy.MoveToParent(_srcStrutJoint, _srcPartJointPivot, + newPosition: new Vector3(0, 0, _srcJointHandleLength), newRotation: Quaternion.LookRotation(Vector3.back)); var tgtJointModel = MakeJointModel(GameDatabase.Instance.GetModelPrefab(targetJointModel)); // Target strut joint model. - tgtStrutJoint = CloneModel(tgtJointModel, TgtStrutJointObjName).transform; - tgtStrutJointPivot = Hierarchy.FindTransformInChildren(tgtStrutJoint, PivotAxleTransformName); - tgtJointHandleLength = Vector3.Distance(tgtStrutJoint.position, tgtStrutJointPivot.position); - Hierarchy.MoveToParent(tgtStrutJoint, srcPartJointPivot); + _tgtStrutJoint = CloneModel(tgtJointModel, TgtStrutJointObjName).transform; + _tgtStrutJointPivot = Hierarchy.FindTransformInChildren(_tgtStrutJoint, PivotAxleTransformName); + _tgtJointHandleLength = Vector3.Distance(_tgtStrutJoint.position, _tgtStrutJointPivot.position); + Hierarchy.MoveToParent(_tgtStrutJoint, _srcPartJointPivot); // Target part joint model. var tgtPartJoint = CloneModel(tgtJointModel, TgtPartJointObjName).transform; - var tgtPartJointPivot = Hierarchy.FindTransformInChildren(tgtPartJoint, PivotAxleTransformName); - Hierarchy.MoveToParent(tgtPartJoint, tgtStrutJointPivot, - newPosition: new Vector3(0, 0, tgtJointHandleLength), + Hierarchy.FindTransformInChildren(tgtPartJoint, PivotAxleTransformName); + Hierarchy.MoveToParent(tgtPartJoint, _tgtStrutJointPivot, + newPosition: new Vector3(0, 0, _tgtJointHandleLength), newRotation: Quaternion.LookRotation(Vector3.back)); // Joint template models are not needed anymore. @@ -768,12 +766,12 @@ void CreateLeverModels() { /// Creates piston models from a prefab in a separate model file. void CreatePistonModels() { UpdateValuesFromModel(); - pistons = new GameObject[pistonsCount]; + _pistons = new GameObject[pistonsCount]; var pistonDiameterScale = 1f; var random = new System.Random(0xbeef); // Just some seed value to make values consistent. var randomRotation = Quaternion.identity; for (var i = 0; i < pistonsCount; ++i) { - var piston = UnityEngine.Object.Instantiate(pistonPrefab, srcStrutJoint) as GameObject; + var piston = Instantiate(pistonPrefab, _srcStrutJoint); piston.name = "piston" + i; if (pistonModelRandomRotation) { // Add a bit of randomness to the pipe model textures. Keep rotation diff above 30 degrees. @@ -788,15 +786,15 @@ void CreatePistonModels() { pistonModelScale.z * pistonDiameterScale, // Model's Z is game's Y. pistonModelScale.y); pistonDiameterScale -= pistonDiameterScaleDelta; - pistons[i] = piston; + _pistons[i] = piston; } // First piston rigidly attached at the bottom of the source joint model. - pistons[0].transform.localPosition = - GetUnscaledStrutVector(new Vector3(0, 0, -pistonLength / 2)); + _pistons[0].transform.localPosition = + GetUnscaledStrutVector(new Vector3(0, 0, -_pistonLength / 2)); // Last piston rigidly attached at the bottom of the target joint model. - randomRotation = Quaternion.Euler(0, 0, pistons.Last().transform.localRotation.eulerAngles.z); - Hierarchy.MoveToParent(pistons.Last().transform, tgtStrutJoint, - newPosition: GetUnscaledStrutVector(new Vector3(0, 0, -pistonLength / 2)), + randomRotation = Quaternion.Euler(0, 0, _pistons.Last().transform.localRotation.eulerAngles.z); + Hierarchy.MoveToParent(_pistons.Last().transform, _tgtStrutJoint, + newPosition: GetUnscaledStrutVector(new Vector3(0, 0, -_pistonLength / 2)), newRotation: randomRotation * Quaternion.LookRotation(Vector3.forward)); } @@ -806,7 +804,7 @@ void CreatePistonModels() { Vector3 GetLinkVectorSourcePos(Transform refTransform) { // Don't use the stock translation methods since the handle length is already scaled. We don't // want the scale to be counted twice. - return refTransform.position + refTransform.rotation * new Vector3(0, 0, srcJointHandleLength); + return refTransform.position + refTransform.rotation * new Vector3(0, 0, _srcJointHandleLength); } /// Returns the world position of the target link "pivot". @@ -815,7 +813,7 @@ Vector3 GetLinkVectorSourcePos(Transform refTransform) { Vector3 GetLinkVectorTargetPos(Transform refTransform) { // Don't use the stock translation methods since the handle length is already scaled. We don't // want the scale to be counted twice. - return refTransform.position + refTransform.rotation * new Vector3(0, 0, tgtJointHandleLength); + return refTransform.position + refTransform.rotation * new Vector3(0, 0, _tgtJointHandleLength); } /// Creates the telescopic pipe meshes. @@ -842,10 +840,10 @@ void CreatePipeMeshes(bool recreate) { if (parkedOrientations.Count > 0 && !isLinked) { persistedParkedOrientation = parkedOrientations[0].direction; } - if (persistedParkedLength < minLinkLength) { - persistedParkedLength = minLinkLength; - } else if (persistedParkedLength > maxLinkLength) { - persistedParkedLength = maxLinkLength; + if (persistedParkedLength < _minLinkLength) { + persistedParkedLength = _minLinkLength; + } else if (persistedParkedLength > _maxLinkLength) { + persistedParkedLength = _maxLinkLength; } UpdateLinkLengthAndOrientation(); From c7f826ca36031948617230bda983acd15026c538 Mon Sep 17 00:00:00 2001 From: ihsoft Date: Thu, 30 Jul 2020 17:12:49 -0700 Subject: [PATCH 29/46] Fix typos in docs --- Source/controllers/ControllerWinchRemote.cs | 4 +++- Source/modules/AbstractJoint.cs | 8 ++++---- Source/modules/KASLinkResourceConnector.cs | 2 +- Source/modules/KASRendererTelescopicPipe.cs | 2 +- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/Source/controllers/ControllerWinchRemote.cs b/Source/controllers/ControllerWinchRemote.cs index 430007e7d..0f39d0a94 100644 --- a/Source/controllers/ControllerWinchRemote.cs +++ b/Source/controllers/ControllerWinchRemote.cs @@ -297,7 +297,9 @@ class WinchState { bool _isGuiOpen; /// Tells if the list of cached winches needs to be refreshed. - /// This value is ched on every frame update, so don't update it too frequently + /// + /// This value is checked on every frame update, so don't update it too frequently. + /// bool _modulesNeedUpdate; /// GUI table to align winch status fields. diff --git a/Source/modules/AbstractJoint.cs b/Source/modules/AbstractJoint.cs index 3137238eb..af6fd3fef 100644 --- a/Source/modules/AbstractJoint.cs +++ b/Source/modules/AbstractJoint.cs @@ -353,7 +353,7 @@ protected List joints { protected List customJoints { get; } = new List(); /// The objects that were used by the custom joints. - /// These objects will be destoyed on the joints clean up. + /// These objects will be destroyed on the joints clean up. /// /// // ReSharper disable once MemberCanBePrivate.Global @@ -724,8 +724,8 @@ protected Vector3 GetSourcePhysicalAnchor(ILinkSource source) { /// be added. /// /// - /// The Unity objects that need to be destoyed after the joints are cleaned up. They can be - /// anything. + /// The Unity objects that need to be destroyed after the joints are cleaned up. They can + /// be anything. /// /// /// @@ -903,7 +903,7 @@ void OnVesselRename(GameEvents.HostedFromToAction action) { /// Cleans up the attach nodes and, optionally, breaks the link. /// - /// The actual changes are delyed till the end of frame. So it's safe to call this method from an + /// The actual changes are delayed till the end of frame. So it's safe to call this method from an /// event handler. /// /// The link source at the moment of cleanup. diff --git a/Source/modules/KASLinkResourceConnector.cs b/Source/modules/KASLinkResourceConnector.cs index 3230723e3..c180a1348 100644 --- a/Source/modules/KASLinkResourceConnector.cs +++ b/Source/modules/KASLinkResourceConnector.cs @@ -228,7 +228,7 @@ public sealed class KASLinkResourceConnector : KASLinkSourcePhysical, group = StdPersistentGroups.PartConfigLoadGroup)] public List resourceOverride = new List(); - /// Container for the fuel mixutre component. + /// Container for the fuel mixture component. // ReSharper disable once ClassNeverInstantiated.Global public class FuelMixtureComponent { /// Name of the resource. diff --git a/Source/modules/KASRendererTelescopicPipe.cs b/Source/modules/KASRendererTelescopicPipe.cs index fd39bf653..179f584a1 100644 --- a/Source/modules/KASRendererTelescopicPipe.cs +++ b/Source/modules/KASRendererTelescopicPipe.cs @@ -360,7 +360,7 @@ private set { float _maxLinkLength; /// Diameter of the outer piston. It's calculated from the model. - /// The diameter in metters. + /// The diameter in meters. /// It's primarily used to cast a collider. /// float _outerPistonDiameter; From b35f230c7da37c8bc610df820e1399d22fb57e55 Mon Sep 17 00:00:00 2001 From: ihsoft Date: Thu, 30 Jul 2020 17:13:52 -0700 Subject: [PATCH 30/46] Add missing files to project --- Source/KAS.csproj | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Source/KAS.csproj b/Source/KAS.csproj index 5ff56e093..9c94699ef 100644 --- a/Source/KAS.csproj +++ b/Source/KAS.csproj @@ -96,7 +96,6 @@ - @@ -114,6 +113,8 @@ + + From 3d9ea321e0fb650127941a1275f4e8584c44eb5a Mon Sep 17 00:00:00 2001 From: ihsoft Date: Thu, 30 Jul 2020 17:14:38 -0700 Subject: [PATCH 31/46] Upgrade to Utils 2.4 --- ...Dev_Utils.2.2.dll => KSPDev_Utils.2.4.dll} | Bin 135168 -> 135168 bytes ...Dev_Utils.2.2.xml => KSPDev_Utils.2.4.xml} | 10 +++++----- .../Examples/KAS-API-Examples.csproj | 4 ++-- Source/KAS.csproj | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) rename Binaries/{KSPDev_Utils.2.2.dll => KSPDev_Utils.2.4.dll} (58%) rename Binaries/{KSPDev_Utils.2.2.xml => KSPDev_Utils.2.4.xml} (99%) diff --git a/Binaries/KSPDev_Utils.2.2.dll b/Binaries/KSPDev_Utils.2.4.dll similarity index 58% rename from Binaries/KSPDev_Utils.2.2.dll rename to Binaries/KSPDev_Utils.2.4.dll index ddd5e6d902ea426dfbc36d5d654312935af850a5..ddaceb38082fe3676468cc2f86b4b8dbf52d8120 100644 GIT binary patch delta 24162 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 M|2J1C(mvDw0nSG*9smFU delta 23843 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 diff --git a/Binaries/KSPDev_Utils.2.2.xml b/Binaries/KSPDev_Utils.2.4.xml similarity index 99% rename from Binaries/KSPDev_Utils.2.2.xml rename to Binaries/KSPDev_Utils.2.4.xml index 25b9d33b6..eaefca14a 100644 --- a/Binaries/KSPDev_Utils.2.2.xml +++ b/Binaries/KSPDev_Utils.2.4.xml @@ -1,7 +1,7 @@ - KSPDev_Utils.2.2 + KSPDev_Utils.2.4 @@ -906,7 +906,7 @@ Copies the custom part fields from the prefab into the instance. The consumer code must call this method from the OnAwake method to ensure the custom - fields are properly intialized. + fields are properly initialized. The module to copy the fields into. @@ -2808,8 +2808,8 @@ Localizes the items. - The localizable items must be declared as non-static public members. The following items are - supported: + The localizable items must be declared as non-static public or protected members. The + following items are supported: . This type may have multiple localization items: for guiName @@ -4606,7 +4606,7 @@ The EventSystem logic is not in sync with MonoBehaviour.Update, so the event system handlers should provide the pressed button explicitly. The callers from the Update method don't need to do so since the right action button can be extracted from - . + Input. Tells if only the modifiers in the event need to be checked. This is how a "precondition" can diff --git a/Source-API/docs_project/Examples/KAS-API-Examples.csproj b/Source-API/docs_project/Examples/KAS-API-Examples.csproj index 6ef4c503b..1bdec6c1a 100644 --- a/Source-API/docs_project/Examples/KAS-API-Examples.csproj +++ b/Source-API/docs_project/Examples/KAS-API-Examples.csproj @@ -66,8 +66,8 @@ ..\..\..\Binaries\KAS-API-v2.dll - - ..\..\..\Binaries\KSPDev_Utils.2.2.dll + + ..\..\..\Binaries\KSPDev_Utils.2.4.dll Q:\KSP_x64_Data\Managed\UnityEngine.dll diff --git a/Source/KAS.csproj b/Source/KAS.csproj index 9c94699ef..ec7f9ef1e 100644 --- a/Source/KAS.csproj +++ b/Source/KAS.csproj @@ -58,8 +58,8 @@ ..\Binaries\KAS-API-v2.dll - - ..\Binaries\KSPDev_Utils.2.2.dll + + ..\Binaries\KSPDev_Utils.2.4.dll 4.0 From 69d5d9a15f16254edf7dfdde81e8d01a5e6d77b9 Mon Sep 17 00:00:00 2001 From: ihsoft Date: Thu, 30 Jul 2020 17:16:15 -0700 Subject: [PATCH 32/46] Fix doc tags path --- Source/modules/AbstractLinkPeer.cs | 2 +- Source/modules/KASLinkSourcePhysical.cs | 2 +- Source/modules/KASLinkTargetKerbal.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/modules/AbstractLinkPeer.cs b/Source/modules/AbstractLinkPeer.cs index ff197440d..2c2029fe8 100644 --- a/Source/modules/AbstractLinkPeer.cs +++ b/Source/modules/AbstractLinkPeer.cs @@ -190,7 +190,7 @@ public abstract class AbstractLinkPeer : AbstractPartModule, /// /// /// The state machine instance. - /// + /// protected SimpleStateMachine linkStateMachine { get; private set; } /// Attach node loaded from the part's config. diff --git a/Source/modules/KASLinkSourcePhysical.cs b/Source/modules/KASLinkSourcePhysical.cs index a97c0ee5e..e6864bbdb 100644 --- a/Source/modules/KASLinkSourcePhysical.cs +++ b/Source/modules/KASLinkSourcePhysical.cs @@ -356,7 +356,7 @@ protected ILinkCableJoint cableJoint { /// be changed on the part load, consider overriding . /// /// The state machine instance. It's never null. - /// + /// protected SimpleStateMachine connectorStateMachine { get; private set; } /// The physical object of the connector. diff --git a/Source/modules/KASLinkTargetKerbal.cs b/Source/modules/KASLinkTargetKerbal.cs index ffcd6865a..62ec290dd 100644 --- a/Source/modules/KASLinkTargetKerbal.cs +++ b/Source/modules/KASLinkTargetKerbal.cs @@ -159,7 +159,7 @@ class InjectedEvent { #region Context menu events/actions /// A context menu item that picks up the cable connector in range. - /// + /// [KSPEvent(guiActive = true)] [LocalizableItem( tag = "#kasLOC_10000", From fd93af09e24263af65c5ad54f48f90ae25650195 Mon Sep 17 00:00:00 2001 From: ihsoft Date: Thu, 30 Jul 2020 17:44:16 -0700 Subject: [PATCH 33/46] Update changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c79c8d3a7..94587b392 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,7 @@ # 1.7 (pre-release): +* [Change] Better react on the attached part(s) destruction to properly reset the link state. +* [Change] Some performance improvement for the winch connector handling. +* [Fix #297] Decoupling near winch connected in editor causes the winch to break in to two separate vessels. # 1.6 (April 26th, 2020): * [Fix #289] RTS-1 docking mode is not reset on decoupling. From 5b040e9a81a1112adbba9fa15f8982c402a8910a Mon Sep 17 00:00:00 2001 From: ihsoft Date: Thu, 30 Jul 2020 17:58:33 -0700 Subject: [PATCH 34/46] Update deps --- Deps/CommunityCategoryKit/CCK.dll | Bin 9216 -> 9728 bytes Deps/CommunityCategoryKit/CCK.version | 38 +++++++++++++------------- Deps/ModuleManager.4.1.3.dll | Bin 141824 -> 0 bytes Deps/ModuleManager.4.1.4.dll | Bin 0 -> 141312 bytes 4 files changed, 19 insertions(+), 19 deletions(-) delete mode 100644 Deps/ModuleManager.4.1.3.dll create mode 100644 Deps/ModuleManager.4.1.4.dll diff --git a/Deps/CommunityCategoryKit/CCK.dll b/Deps/CommunityCategoryKit/CCK.dll index 1f56e9c6e645335129ab5b1cc2addaa6b58f0070..eb7bdd0447dae50d5f6034f5a6c50e2635a983c1 100644 GIT binary patch literal 9728 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 HKN0wEg8hbe literal 9216 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

HDdjZLpEwTiApEIg?#7Br=*bsWBu*{K{ic9dhr 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 RSZv6bG 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 IzoWqa2Q=HRn*aa+ diff --git a/Deps/ModuleManager.4.1.4.dll b/Deps/ModuleManager.4.1.4.dll new file mode 100644 index 0000000000000000000000000000000000000000..b47a6da15edd2330867ffa438c4b89d65b9503ec GIT binary patch literal 141312 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

  • ;$=am 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 Date: Thu, 30 Jul 2020 18:00:14 -0700 Subject: [PATCH 35/46] Tiny style fix --- Source/api_impl/KasEventsImpl.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Source/api_impl/KasEventsImpl.cs b/Source/api_impl/KasEventsImpl.cs index 030853c75..df8dd863b 100644 --- a/Source/api_impl/KasEventsImpl.cs +++ b/Source/api_impl/KasEventsImpl.cs @@ -13,19 +13,19 @@ namespace KASImpl { public class KasEventsImpl : IKasEvents { /// public EventData OnStartLinking { get; } = - new EventData("KASOnStartLinking"); + new EventData("KASOnStartLinking"); /// public EventData OnStopLinking { get; } = - new EventData("KASOnStopLinking"); + new EventData("KASOnStopLinking"); /// public EventData OnLinkCreated { get; } = - new EventData("KASOnLinkCreated"); + new EventData("KASOnLinkCreated"); /// public EventData OnLinkBroken { get; } = - new EventData("KASOnLinkBroken"); + new EventData("KASOnLinkBroken"); } } // namespace From 134608b34e90166743cda9bd1a94e70dc1774103 Mon Sep 17 00:00:00 2001 From: ihsoft Date: Thu, 30 Jul 2020 18:00:52 -0700 Subject: [PATCH 36/46] Add null asserts --- Source/controllers/ControllerWinchRemote.cs | 1 + Source/modules/KASLinkTargetBase.cs | 2 ++ Source/modules/KASLinkTargetKerbal.cs | 1 + 3 files changed, 4 insertions(+) diff --git a/Source/controllers/ControllerWinchRemote.cs b/Source/controllers/ControllerWinchRemote.cs index 0f39d0a94..51ae73f9c 100644 --- a/Source/controllers/ControllerWinchRemote.cs +++ b/Source/controllers/ControllerWinchRemote.cs @@ -402,6 +402,7 @@ void ConsoleWindowFunc(int windowId) { actionsList: GuiActions); // Cable retracting controls. + System.Diagnostics.Debug.Assert(winchCable != null, nameof(winchCable) + " != null"); using (new GuiEnabledStateScope(!disableWinchGui && winchCable.realCableLength > 0)) { // Start retracting the cable column. winchState.retractBtnPressed &= winch.motorTargetSpeed < 0; diff --git a/Source/modules/KASLinkTargetBase.cs b/Source/modules/KASLinkTargetBase.cs index 2bd666a36..c2ae89a33 100644 --- a/Source/modules/KASLinkTargetBase.cs +++ b/Source/modules/KASLinkTargetBase.cs @@ -137,6 +137,8 @@ protected override void CheckCoupleNode() { base.CheckCoupleNode(); // The source is responsible to handle the link, which may be done at the end of frame. So put // our check at the end of the frame queue to go behind any delayed actions. + System.Diagnostics.Debug.Assert( + parsedAttachNode != null, nameof(parsedAttachNode) + " != null"); AsyncCall.CallOnEndOfFrame(this, () => { if (linkState == LinkState.Available && parsedAttachNode != null && parsedAttachNode.attachedPart != null) { diff --git a/Source/modules/KASLinkTargetKerbal.cs b/Source/modules/KASLinkTargetKerbal.cs index 62ec290dd..0a20cbfef 100644 --- a/Source/modules/KASLinkTargetKerbal.cs +++ b/Source/modules/KASLinkTargetKerbal.cs @@ -170,6 +170,7 @@ public void PickupConnectorEvent() { if (connector != null) { var closestSource = connector.ownerModule as ILinkSource; HostedDebugLog.Info(this, "Try picking up a physical connector of: {0}...", closestSource); + System.Diagnostics.Debug.Assert(closestSource != null, nameof(closestSource) + " != null"); if (closestSource.LinkToTarget(LinkActorType.Player, this)) { // By default, the cable joints set the length limit to the actual distance. var cableJoint = closestSource.linkJoint as ILinkCableJoint; From 10d941595613440cf8036a49551062040dac470a Mon Sep 17 00:00:00 2001 From: ihsoft Date: Thu, 30 Jul 2020 18:03:27 -0700 Subject: [PATCH 37/46] Fix release tool to MSBuild v14 --- Tools/make_binary.cmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tools/make_binary.cmd b/Tools/make_binary.cmd index e60dddf90..218e9e99f 100644 --- a/Tools/make_binary.cmd +++ b/Tools/make_binary.cmd @@ -1,4 +1,4 @@ @echo off REM Until new major version of C# is released the build number in the path will keep counting. REM KAS *requires* .NET compiler version 4.0 or higher. Don't get confused with KSP run-time requirement of 3.5. -C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild ..\Source\KAS.csproj /t:Clean,Build /p:Configuration=Release +"C:\Program Files (x86)\MSBuild\14.0\bin\MSBuild.exe" ..\Source\KAS.csproj /t:Clean,Build /p:Configuration=Release From 509562b1c2802040031e7f96ae4b977bf5b4e7bc Mon Sep 17 00:00:00 2001 From: ihsoft Date: Thu, 30 Jul 2020 18:04:07 -0700 Subject: [PATCH 38/46] Fix #295 --- Binaries/MiniAVC-V2.dll | Bin 0 -> 45568 bytes .../{KSP-AVC.version => MiniAVC-V2.version} | 19 +++++++----------- Binaries/MiniAVC.dll | Bin 42496 -> 0 bytes CHANGELOG.md | 1 + Tools/release_setup.json | 2 +- 5 files changed, 9 insertions(+), 13 deletions(-) create mode 100644 Binaries/MiniAVC-V2.dll rename Binaries/{KSP-AVC.version => MiniAVC-V2.version} (53%) delete mode 100644 Binaries/MiniAVC.dll diff --git a/Binaries/MiniAVC-V2.dll b/Binaries/MiniAVC-V2.dll new file mode 100644 index 0000000000000000000000000000000000000000..f390ef810a1fe68a386442eea521ddefd610327f GIT binary patch literal 45568 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 literal 0 HcmV?d00001 diff --git a/Binaries/KSP-AVC.version b/Binaries/MiniAVC-V2.version similarity index 53% rename from Binaries/KSP-AVC.version rename to Binaries/MiniAVC-V2.version index 687797d31..98803f4f9 100644 --- a/Binaries/KSP-AVC.version +++ b/Binaries/MiniAVC-V2.version @@ -1,25 +1,20 @@ { - "NAME": "KSP-AVC Plugin", - "URL": "http://ksp.spacetux.net/avc/KSP-AVC", + "NAME": "MiniAVC-V2 Plugin", + "URL": "http://ksp.spacetux.net/avc/MiniAVC-V2", "DOWNLOAD": "https://github.com/linuxgurugamer/KSPAddonVersionChecker/releases", "GITHUB": { "USERNAME": "linuxgurugamer", "REPOSITORY": "KSPAddonVersionChecker" }, "VERSION": { - "MAJOR": 1, - "MINOR": 3, + "MAJOR": 2, + "MINOR": 0, "PATCH": 0, - "BUILD": 3 - }, - "KSP_VERSION": { - "MAJOR": 1, - "MINOR": 5, - "PATCH": 1 + "BUILD": 0 }, "KSP_VERSION_MIN": { "MAJOR": 1, - "MINOR": 5, - "PATCH": 1 + "MINOR": 8, + "PATCH": 0 } } diff --git a/Binaries/MiniAVC.dll b/Binaries/MiniAVC.dll deleted file mode 100644 index b7844da9b34a6d1832082c9c5bf3215ea309e7bc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 42496 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 Date: Thu, 30 Jul 2020 18:15:56 -0700 Subject: [PATCH 39/46] Fix typos in lang descriptions --- Lang/en-us.cfg | 14 +++++++------- Lang/ru.cfg | 14 +++++++------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Lang/en-us.cfg b/Lang/en-us.cfg index 2ddb7d673..82acf6ef4 100644 --- a/Lang/en-us.cfg +++ b/Lang/en-us.cfg @@ -185,11 +185,11 @@ Localization #kasLOC_11001 = Release // The GUI hint to explain the effect of the release button. #kasLOC_11002 = Release the connector and set cable length to the maximum - // The caption of the button that stretches teeh cable. + // The caption of the button that stretches the cable. #kasLOC_11003 = Stretch // The GUI hint to explain the effect of the stretch button. #kasLOC_11004 = Set the cable length to the actual distance - // The caption of the button that deatches the cable from the target. + // The caption of the button that detaches the cable from the target. #kasLOC_11005 = Detach // The GUI hint to explain the effect of the detach button. #kasLOC_11006 = Detach the cable from the target part @@ -236,7 +236,7 @@ Localization // length and the real distance between the winch and the target (connector or // part). The values are presented as a pair, separated by symbol '/'. #kasLOC_11022 = The deployed/real length of the cable - // The GUI hint to show for the area which displays two values: the current motro + // The GUI hint to show for the area which displays two values: the current motor // speed and the maximum possible motor speed. The values are presented as a pair, // separated by symbol '/'. #kasLOC_11023 = Current motor speed / Motor speed setting @@ -362,10 +362,10 @@ Localization // Example usage: // 2.56 / 1,234 #kasLOC_12003 = <<1>> / <<2>> - // The information string that tells what is the selected or calculated tarnsfer + // The information string that tells what is the selected or calculated transfer // speed is. #kasLOC_12004 = Current transfer speed: <<1>> units per second - // The caption on the button that closes the trsnafer dialog. + // The caption on the button that closes the transfer dialog. #kasLOC_12005 = Close dialog // The string that tells which vessels owns the resource transfer part. Its stats // are displayed on the left side of the dialog. @@ -379,7 +379,7 @@ Localization // Argument <<1>> is the comma-separated list of the component names. #kasLOC_12008 = A mixture of components: <<1>> // The caption for the control that enables the mode, which automatically deducts - // the speed of the reasource transfer. + // the speed of the resource transfer. #kasLOC_12009 = Auto scale transfer speed // The GUI hint that explains what will happen if the auto-speed options is chosen. #kasLOC_12010 = The speed will be set so that the transfer is complete in <<1>> seconds @@ -419,7 +419,7 @@ Localization #kasLOC_02004 = Links with socket type: <<1>> // Title of the module to present in the editor details window. #kasLOC_02005 = KAS Joint Source - // The name of the part's context menu event that triggers a separtation of the + // The name of the part's context menu event that triggers a separation of the // linked parts into two different vessels if they are coupled thru this link. At // the same time, the name of the event gives a currently selected state. #kasLOC_02006 = Link mode: DOCKED diff --git a/Lang/ru.cfg b/Lang/ru.cfg index 00e0b13e4..d59dc5d96 100644 --- a/Lang/ru.cfg +++ b/Lang/ru.cfg @@ -185,11 +185,11 @@ Localization #kasLOC_11001 = Выпустить // The GUI hint to explain the effect of the release button. #kasLOC_11002 = Выпустить трос лебёдки на максимальную длину - // The caption of the button that stretches teeh cable. + // The caption of the button that stretches the cable. #kasLOC_11003 = Натянуть // The GUI hint to explain the effect of the stretch button. #kasLOC_11004 = Подтянуть трос до реального расстояния до присоединённого аппарата - // The caption of the button that deatches the cable from the target. + // The caption of the button that detaches the cable from the target. #kasLOC_11005 = Отсоединить // The GUI hint to explain the effect of the detach button. #kasLOC_11006 = Отсоединить разъём от присоединённого аппарата @@ -236,7 +236,7 @@ Localization // length and the real distance between the winch and the target (connector or // part). The values are presented as a pair, separated by symbol '/'. #kasLOC_11022 = Выпущенная/реальная длина троса (он может растягиваться под нагрузкой) - // The GUI hint to show for the area which displays two values: the current motro + // The GUI hint to show for the area which displays two values: the current motor // speed and the maximum possible motor speed. The values are presented as a pair, // separated by symbol '/'. #kasLOC_11023 = Текущая/максимальная скорость мотора @@ -362,10 +362,10 @@ Localization // Example usage: // 2.56 / 1,234 #kasLOC_12003 = <<1>> / <<2>> - // The information string that tells what is the selected or calculated tarnsfer + // The information string that tells what is the selected or calculated transfer // speed is. #kasLOC_12004 = Скорость переноса: <<1>> единиц в секунду - // The caption on the button that closes the trsnafer dialog. + // The caption on the button that closes the transfer dialog. #kasLOC_12005 = Закрыть диалог // The string that tells which vessels owns the resource transfer part. Its stats // are displayed on the left side of the dialog. @@ -379,7 +379,7 @@ Localization // Argument <<1>> is the comma-separated list of the component names. #kasLOC_12008 = Смесь компонентов: <<1>> // The caption for the control that enables the mode, which automatically deducts - // the speed of the reasource transfer. + // the speed of the resource transfer. #kasLOC_12009 = Автоматически подбирать скорость переноса // The GUI hint that explains what will happen if the auto-speed options is chosen. #kasLOC_12010 = Выбирать скорость так, чтобы завершить перенос за <<1>> секунд @@ -419,7 +419,7 @@ Localization #kasLOC_02004 = Для гнезда: <<1>> // Title of the module to present in the editor details window. #kasLOC_02005 = Разъём - // The name of the part's context menu event that triggers a separtation of the + // The name of the part's context menu event that triggers a separation of the // linked parts into two different vessels if they are coupled thru this link. At // the same time, the name of the event gives a currently selected state. #kasLOC_02006 = Cтыковать аппараты: ДА From ccae2855ed3e8f776f2aa95d2db809799769d1b1 Mon Sep 17 00:00:00 2001 From: ihsoft Date: Thu, 30 Jul 2020 19:40:19 -0700 Subject: [PATCH 40/46] Fix regression Public enums must not be blindly changed. It may be not the question of the code only. --- Source/modules/KASLinkSourceBase.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Source/modules/KASLinkSourceBase.cs b/Source/modules/KASLinkSourceBase.cs index 4721e44c6..5d76b72db 100644 --- a/Source/modules/KASLinkSourceBase.cs +++ b/Source/modules/KASLinkSourceBase.cs @@ -115,6 +115,9 @@ public class KASLinkSourceBase : AbstractLinkPeer, #region Part's config fields ///

    Specifies how/if the parts should be coupled on link. + /// + /// Never change the existing values since they may be used in the part configs. + /// public enum CoupleMode { /// The docking state of the link is determined from the persistent state. /// @@ -122,7 +125,8 @@ public enum CoupleMode { /// target parts must be enabled for coupling in order to be able to dock. IF any of the peers /// doesn't allow it, there will be no context menu option. /// - SetViaGui, + // ReSharper disable once InconsistentNaming + SetViaGUI, /// The link is always established in docked mode. /// @@ -608,7 +612,7 @@ public virtual void UpdateContextMenu() { PartModuleUtils.SetupEvent(this, ToggleVesselsDockModeEvent, e => { if (linkJoint != null) { e.guiName = linkJoint.coupleOnLinkMode ? DockedModeMenuTxt : UndockedModeMenuTxt; - if (coupleMode == CoupleMode.SetViaGui) { + if (coupleMode == CoupleMode.SetViaGUI) { e.active = coupleNode != null && (linkTarget == null || linkTarget.coupleNode != null); } else if (isLinked) { // Just in case show GUI if the link is established, and its couple mode contradicts the From c898eda1f85b98abcb91918d476b1acb967c204e Mon Sep 17 00:00:00 2001 From: ihsoft Date: Thu, 30 Jul 2020 19:42:09 -0700 Subject: [PATCH 41/46] Unify lang files headers --- Lang/en-us.cfg | 11 +++++------ Lang/es-es.cfg | 9 +++------ Lang/fr-fr.cfg | 15 +++++---------- Lang/it-it.cfg | 13 +++---------- Lang/pt-br.cfg | 11 ++++------- Lang/ru.cfg | 8 ++------ Lang/zh-cn.cfg | 6 ++++-- 7 files changed, 26 insertions(+), 47 deletions(-) diff --git a/Lang/en-us.cfg b/Lang/en-us.cfg index 82acf6ef4..8e8f8f5b4 100644 --- a/Lang/en-us.cfg +++ b/Lang/en-us.cfg @@ -1,10 +1,9 @@ // Version: 5 (2020-04-26) -// If this file is EN-US localization, then only change the version when a new -// string is added or an existing removed. -// If it's any other language, then this number tells if there are differences. -// Go thru the file and sync it with the EN-US file so that the number and the -// values of the localization tags match. Once this is done, sync the version. -// Author: Supercheese +// Do NOT change the version unless a new string is added or an existing one was deleted. +// A simple string update is not a new version! The version number is used to keep all +// the localizations in sync. The EN-US localization file is the primary file, and all the +// other languages should catch-up as the version is increasing. +// Authors: Supercheese Localization { en-us diff --git a/Lang/es-es.cfg b/Lang/es-es.cfg index 9297141fa..0dbce5593 100644 --- a/Lang/es-es.cfg +++ b/Lang/es-es.cfg @@ -1,10 +1,7 @@ -// Version: 4 (2019-03-26) -// If this file is EN-US localization, then only change the version when a new -// string is added or an existing removed. -// If it's any other language, then this number tells if there are differences. -// Go thru the file and sync it with the EN-US file so that the number and the -// values of the localization tags match. Once this is done, sync the version. +// Version: 4 +// Before changing the version, read the instructions in the en-us.cfg file! // Author: Fitiales +// Last updated: 03/26/2019 Localization { es-es diff --git a/Lang/fr-fr.cfg b/Lang/fr-fr.cfg index e8a1f0ee7..cac9a8b1e 100644 --- a/Lang/fr-fr.cfg +++ b/Lang/fr-fr.cfg @@ -1,16 +1,11 @@ -// Version: 3 (2018-09-18) -// If this file is EN-US localization, then only change the version when a new -// string is added or an existing removed. -// If it's any other language, then this number tells if there are differences. -// Go thru the file and sync it with the EN-US file so that the number and the -// values of the localization tags match. Once this is done, sync the version. -// Author: Supercheese - +// Version: 3 +// Before changing the version, read the instructions in the en-us.cfg file! +// Author: Samche2000 +// Last updated: 09/18/2018 +// // Ce fichier contient en commentaire un copier-coller de la version anglaise // pour avoir une référence rapide au fichier original pendant tout le process // de traduction -// Samche2000 - Localization { fr-fr diff --git a/Lang/it-it.cfg b/Lang/it-it.cfg index 86b402131..5f495d300 100644 --- a/Lang/it-it.cfg +++ b/Lang/it-it.cfg @@ -1,14 +1,7 @@ -// Total strings: 189 -// -// Version: 3 (2018-09-21) -// If this file is EN-US localization, then only change the version when a new -// string is added or an existing removed. -// If it's any other language, then this number tells if there are differences. -// Go thru the file and sync it with the EN-US file so that the number and the -// values of the localization tags match. Once this is done, sync the version. -// -// Creation Date: 2018-07-10 +// Version: 3 +// Before changing the version, read the instructions in the en-us.cfg file! // Author: Carlo Rossi (CRL42) +// Last updated: 07/10/2018 Localization { it-it diff --git a/Lang/pt-br.cfg b/Lang/pt-br.cfg index 4e1f87901..05ea08b72 100644 --- a/Lang/pt-br.cfg +++ b/Lang/pt-br.cfg @@ -1,10 +1,7 @@ -// Version: 3 (2018-09-18) -// If this file is EN-US localization, then only change the version when a new -// string is added or an existing removed. -// If it's any other language, then this number tells if there are differences. -// Go thru the file and sync it with the EN-US file so that the number and the -// values of the localization tags match. Once this is done, sync the version. -// Author: Supercheese +// Version: 3 +// Before changing the version, read the instructions in the en-us.cfg file! +// Author: rfelipe200 +// Last updated: 09/18/2018 Localization { pt-br diff --git a/Lang/ru.cfg b/Lang/ru.cfg index d59dc5d96..3d573bf8d 100644 --- a/Lang/ru.cfg +++ b/Lang/ru.cfg @@ -1,10 +1,6 @@ // Version: 4 (2020-04-26) -// If this file is EN-US localization, then only change the version when a new -// string is added or an existing removed. -// If it's any other language, then this number tells if there are differences. -// Go thru the file and sync it with the EN-US file so that the number and the -// values of the localization tags match. Once this is done, sync the version. -// Author: IgorZ +// Before changing the version, read the instructions in the en-us.cfg file! +// Author: Igor Zavoychinskiy (IgorZ) Localization { ru diff --git a/Lang/zh-cn.cfg b/Lang/zh-cn.cfg index b64ae500f..9afb5d239 100644 --- a/Lang/zh-cn.cfg +++ b/Lang/zh-cn.cfg @@ -1,5 +1,7 @@ -// Version: 1 (2019-06-28) -//Author:facther +// Version: 1 +// Before changing the version, read the instructions in the en-us.cfg file! +// Author: facther +// Last updated: 06/28/2019 Localization { zh-cn From 7280d0ea8ab05080c260acc88c9fee4adfe59595 Mon Sep 17 00:00:00 2001 From: ihsoft Date: Thu, 30 Jul 2020 20:01:45 -0700 Subject: [PATCH 42/46] Use localization in the error reporting --- CHANGELOG.md | 1 + Lang/en-us.cfg | 6 +++++- Lang/ru.cfg | 6 +++++- Source/modules/KASLinkSourceBase.cs | 12 +++++++++--- 4 files changed, 20 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e9858c6c..8ec4ee63e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # 1.7 (pre-release): * [Change] Better react on the attached part(s) destruction to properly reset the link state. * [Change] Some performance improvement for the winch connector handling. +* [Change] Update EN/RU localizations to version `6`. * [Fix #295] Stop using `MiniAVC.dll` in favor of `MiniAVC-V2.dll`. * [Fix #297] Decoupling near winch connected in editor causes the winch to break in to two separate vessels. diff --git a/Lang/en-us.cfg b/Lang/en-us.cfg index 8e8f8f5b4..1cb29d71c 100644 --- a/Lang/en-us.cfg +++ b/Lang/en-us.cfg @@ -1,9 +1,10 @@ -// Version: 5 (2020-04-26) +// Version: 6 // Do NOT change the version unless a new string is added or an existing one was deleted. // A simple string update is not a new version! The version number is used to keep all // the localizations in sync. The EN-US localization file is the primary file, and all the // other languages should catch-up as the version is increasing. // Authors: Supercheese +// Last updated: 30/07/2020 Localization { en-us @@ -426,6 +427,9 @@ Localization // parts if they were not coupled before. At the same time, the name of the event // gives a currently selected state. #kasLOC_02007 = Link mode: UNDOCKED + // Message to display when the target is refusing to couple (dock) with the link + // source. + #kasLOC_02008 = Target cannot couple // ********** Type: KAS.KASLinkSourceInteractive, KSPDev Messages diff --git a/Lang/ru.cfg b/Lang/ru.cfg index 3d573bf8d..ff081c52a 100644 --- a/Lang/ru.cfg +++ b/Lang/ru.cfg @@ -1,6 +1,7 @@ -// Version: 4 (2020-04-26) +// Version: 6 // Before changing the version, read the instructions in the en-us.cfg file! // Author: Igor Zavoychinskiy (IgorZ) +// Last updated: 30/07/2020 Localization { ru @@ -423,6 +424,9 @@ Localization // parts if they were not coupled before. At the same time, the name of the event // gives a currently selected state. #kasLOC_02007 = Cтыковать аппараты: НЕТ + // Message to display when the target is refusing to couple (dock) with the link + // source. + #kasLOC_02008 = Гнездо не может пристыковаться // ********** Type: KAS.KASLinkSourceInteractive, KSPDev Messages diff --git a/Source/modules/KASLinkSourceBase.cs b/Source/modules/KASLinkSourceBase.cs index 5d76b72db..6ea8dec73 100644 --- a/Source/modules/KASLinkSourceBase.cs +++ b/Source/modules/KASLinkSourceBase.cs @@ -31,7 +31,7 @@ namespace KAS { /// KSP: IActivateOnDecouple /// /// -// Next localization ID: #kasLOC_02008. +// Next localization ID: #kasLOC_02009. // TODO(ihsoft): Handle KIS actions. // TODO(ihsoft): Handle part staged action. // ReSharper disable once InconsistentNaming @@ -98,6 +98,13 @@ public class KASLinkSourceBase : AbstractLinkPeer, description: "The name of the part's context menu event that triggers a merging of the" + " linked parts if they were not coupled before. At the same time, the name of the event" + " gives a currently selected state."); + + /// + static readonly Message TargetCannotCoupleMsg = new Message( + "#kasLOC_02008", + defaultTemplate: "Target cannot couple", + description: "Message to display when the target is refusing to couple (dock) with the link" + + " source."); #endregion #region ILinkSource properties implementation @@ -709,8 +716,7 @@ protected virtual string[] CheckBasicLinkConditions(ILinkTarget target, bool che errors.Add(IncompatibleTargetLinkTypeMsg); } if (coupleMode == CoupleMode.AlwaysCoupled && target.coupleNode == null) { - Message TargetCannotCouple = "Target cannot couple"; //FIXME - errors.Add(TargetCannotCouple); + errors.Add(TargetCannotCoupleMsg); } return errors.ToArray(); } From 490645bd6670f0339f4ae9837402741b8b31050c Mon Sep 17 00:00:00 2001 From: ihsoft Date: Thu, 30 Jul 2020 20:51:59 -0700 Subject: [PATCH 43/46] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ec4ee63e..1d67e4eb0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ * [Change] Better react on the attached part(s) destruction to properly reset the link state. * [Change] Some performance improvement for the winch connector handling. * [Change] Update EN/RU localizations to version `6`. +* [Change] Update Chinese localization. * [Fix #295] Stop using `MiniAVC.dll` in favor of `MiniAVC-V2.dll`. * [Fix #297] Decoupling near winch connected in editor causes the winch to break in to two separate vessels. From 095a8474dd18c0fd43ce19b9f396bf8efe4db267 Mon Sep 17 00:00:00 2001 From: ihsoft Date: Thu, 30 Jul 2020 20:53:47 -0700 Subject: [PATCH 44/46] Release v1.7 --- CHANGELOG.md | 2 +- KAS.version | 6 +++--- Tools/publish_curseforge_args.txt | 2 +- Tools/publish_github_args.txt | 2 +- Tools/publish_spacedock_args.txt | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d67e4eb0..4644dd45e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -# 1.7 (pre-release): +# 1.7 (July 30th, 2020): * [Change] Better react on the attached part(s) destruction to properly reset the link state. * [Change] Some performance improvement for the winch connector handling. * [Change] Update EN/RU localizations to version `6`. diff --git a/KAS.version b/KAS.version index 3a59414a1..35ced7582 100644 --- a/KAS.version +++ b/KAS.version @@ -23,9 +23,9 @@ "NAME": "KAS", "URL": "https://github.com/ihsoft/KAS/blob/master/KAS.version", "VERSION": { - "BUILD": 34540, + "BUILD": 37587, "MAJOR": 1, - "MINOR": 6, - "PATCH": 7421 + "MINOR": 7, + "PATCH": 7516 } } \ No newline at end of file diff --git a/Tools/publish_curseforge_args.txt b/Tools/publish_curseforge_args.txt index 10aedeeb8..9a7698e6d 100644 --- a/Tools/publish_curseforge_args.txt +++ b/Tools/publish_curseforge_args.txt @@ -4,4 +4,4 @@ --github=ihsoft/KAS --versions=latest_all_builds --title=KAS {tag} ---archive=../KAS_v1.6.zip +--archive=../KAS_v1.7.zip diff --git a/Tools/publish_github_args.txt b/Tools/publish_github_args.txt index d9d9f1f65..462ec45a8 100644 --- a/Tools/publish_github_args.txt +++ b/Tools/publish_github_args.txt @@ -4,4 +4,4 @@ --changelog=../CHANGELOG.md --as_draft --title=KAS v{tag} ---archive=../KAS_v1.6.zip +--archive=../KAS_v1.7.zip diff --git a/Tools/publish_spacedock_args.txt b/Tools/publish_spacedock_args.txt index e1e890b10..6e5ad5ab6 100644 --- a/Tools/publish_spacedock_args.txt +++ b/Tools/publish_spacedock_args.txt @@ -3,4 +3,4 @@ --changelog=../CHANGELOG.md --github=ihsoft/KAS --ksp_version=latest ---archive=../KAS_v1.6.zip +--archive=../KAS_v1.7.zip From 2627f999391d2df39b9af0021b47373aa82bd322 Mon Sep 17 00:00:00 2001 From: ihsoft Date: Thu, 30 Jul 2020 20:55:01 -0700 Subject: [PATCH 45/46] Fix merge leftover --- Lang/zh-cn.cfg | 1 - 1 file changed, 1 deletion(-) diff --git a/Lang/zh-cn.cfg b/Lang/zh-cn.cfg index 3864c5ce4..62eefa8a5 100644 --- a/Lang/zh-cn.cfg +++ b/Lang/zh-cn.cfg @@ -1,4 +1,3 @@ -<<<<<<< HEAD // Version: 5 // Before changing the version, read the instructions in the en-us.cfg file! // Author: facther, tinygrox From 0465b8f73fbee0687265ebcc099a91c96b0356a8 Mon Sep 17 00:00:00 2001 From: ihsoft Date: Thu, 30 Jul 2020 20:55:52 -0700 Subject: [PATCH 46/46] Release v1.7-proper --- KAS.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/KAS.version b/KAS.version index 35ced7582..d9d2a6363 100644 --- a/KAS.version +++ b/KAS.version @@ -23,7 +23,7 @@ "NAME": "KAS", "URL": "https://github.com/ihsoft/KAS/blob/master/KAS.version", "VERSION": { - "BUILD": 37587, + "BUILD": 37663, "MAJOR": 1, "MINOR": 7, "PATCH": 7516