├── GameData └── ProceduralFairings │ ├── Config │ ├── PF_FilterExtensions_Config.cfg │ ├── PF_Settings_Config.cfg │ └── PF_Squad_Config.cfg │ ├── Parts │ ├── base_ring.cfg │ ├── base_ring.dds │ ├── base_ring.mu │ ├── base_ring_black.dds │ ├── base_standard.cfg │ ├── base_standard.dds │ ├── base_standard.mu │ ├── fairing.dds │ ├── fairing_NRM.dds │ ├── fairing_side.mu │ ├── fairing_side_A.cfg │ ├── fairing_side_B.cfg │ ├── interstage_adapter.cfg │ ├── thrust_plate.cfg │ ├── thrust_plate.dds │ ├── thrust_plate.mu │ └── thrust_plate_NRM.dds │ ├── Plugins │ └── ProceduralFairings.dll │ ├── ProceduralFairings.version │ ├── Textures │ ├── fairing.dds │ ├── fairing_NRM.dds │ ├── fairing_fuselage.dds │ └── fairing_generic_NRM.dds │ ├── changelog.txt │ ├── license.txt │ └── readme.txt ├── Misc ├── baseRingTex.psd ├── baseTex.psd ├── fairing1.psd ├── fuselage1.psd ├── thrustPlate1.psd └── thrustPlate1bump.psd ├── Source ├── ProceduralFairings.sln └── ProceduralFairings │ ├── FairingBase.cs │ ├── FairingDecoupler.cs │ ├── FairingShielding.cs │ ├── FairingSide.cs │ ├── NodeNumberTweaker.cs │ ├── PFKMJoint.cs │ ├── PayloadScan.cs │ ├── ProcAdapter.cs │ ├── ProceduralFairings.csproj │ ├── Properties │ └── AssemblyInfo.cs │ ├── Resizers.cs │ └── Utilities.cs └── Unity ├── FairingBase.blend ├── FairingBaseRing.blend ├── FairingSide.blend ├── Materials ├── Material.mat ├── No Name.mat ├── baseRingTex.mat ├── baseTex.mat ├── fairing1.mat └── thrustPlate1.mat ├── ThrustPlate.blend ├── baseRingTex.png ├── baseTex.png ├── fairing1.png ├── scene.unity ├── thrustPlate1.png ├── thrustPlate1bump.png └── thrustPlate1bump_Normal.png /GameData/ProceduralFairings/Config/PF_FilterExtensions_Config.cfg: -------------------------------------------------------------------------------- 1 | // ================================================== 2 | // Add bulkhead profiles to all parts for FilterExtensions 3 | // compatibility. 4 | // ================================================== 5 | 6 | @PART[*]:HAS[@MODULE[ProceduralFairing*]]:FOR[ProceduralFairings]:NEEDS[FilterExtension] 7 | { 8 | @bulkheadProfiles ^= :$:,proc: 9 | } 10 | 11 | @PART[KzThrustPlate]:FOR[ProceduralFairings]:NEEDS[FilterExtension] 12 | { 13 | @bulkheadProfiles ^= :$:,proc: 14 | } 15 | -------------------------------------------------------------------------------- /GameData/ProceduralFairings/Config/PF_Settings_Config.cfg: -------------------------------------------------------------------------------- 1 | // ================================================== 2 | // Global procedural fairings settings. 3 | // ================================================== 4 | 5 | PROCFAIRINGS_MINDIAMETER 6 | { 7 | start = 1.0 8 | miniaturization = 0.4 9 | sandbox = 0.1 10 | } 11 | 12 | PROCFAIRINGS_MAXDIAMETER 13 | { 14 | start = 1.50 15 | specializedConstruction = 2.75 16 | advAerodynamics = 4.0 17 | heavyAerodynamics = 12.0 18 | experimentalAerodynamics = 30.0 19 | sandbox = 50.0 20 | } 21 | 22 | PROCROCKET_MINDIAMETER 23 | { 24 | start = 1.0 25 | miniaturization = 0.4 26 | sandbox = 0.1 27 | } 28 | 29 | PROCROCKET_MAXDIAMETER 30 | { 31 | start = 1.5 32 | advConstruction = 4.0 33 | metaMaterials = 12.0 34 | aerospaceTech = 30.0 35 | sandbox = 50.0 36 | } 37 | 38 | // ================================================== 39 | // Dummy parts to represent Procedural Fairings 40 | // upgrades in the tech tree. 41 | // ================================================== 42 | 43 | PART 44 | { 45 | name = pf_tech_fairing04m 46 | module = Part 47 | author = Starstrider42 (config), e-dog (model) 48 | 49 | MODEL 50 | { 51 | model = ProceduralFairings/Parts/base_standard 52 | } 53 | 54 | TechRequired = miniaturization 55 | entryCost = 0 56 | cost = 0 57 | category = none 58 | title = Procedural Fairings Upgrade 59 | manufacturer = Keramzit Engineering 60 | description = Allows fairings and plates to be made as small as 0.4 meters. 61 | } 62 | 63 | PART 64 | { 65 | name = pf_tech_fairing2_75m 66 | module = Part 67 | author = Starstrider42 (config), e-dog (model) 68 | 69 | MODEL 70 | { 71 | model = ProceduralFairings/Parts/base_standard 72 | } 73 | 74 | TechRequired = specializedConstruction 75 | entryCost = 0 76 | cost = 0 77 | category = none 78 | title = Procedural Fairings Upgrade 79 | manufacturer = Keramzit Engineering 80 | description = Allows fairings bases up to 2.75 meters. 81 | } 82 | 83 | PART 84 | { 85 | name = pf_tech_fairing4m 86 | module = Part 87 | author = Starstrider42 (config), e-dog (model) 88 | 89 | MODEL 90 | { 91 | model = ProceduralFairings/Parts/base_standard 92 | } 93 | 94 | TechRequired = advAerodynamics 95 | entryCost = 0 96 | cost = 0 97 | category = none 98 | title = Procedural Fairings Upgrade 99 | manufacturer = Keramzit Engineering 100 | description = Allows fairing bases up to 4 meters size. 101 | } 102 | 103 | PART 104 | { 105 | name = pf_tech_fairing12m 106 | module = Part 107 | author = Starstrider42 (config), e-dog (model) 108 | 109 | description = 110 | 111 | MODEL 112 | { 113 | model = ProceduralFairings/Parts/base_standard 114 | } 115 | 116 | TechRequired = heavyAerodynamics 117 | entryCost = 0 118 | cost = 0 119 | category = none 120 | title = Procedural Fairings Upgrade 121 | manufacturer = Keramzit Engineering 122 | description = Allows fairing bases up to 12 meters size. 123 | } 124 | 125 | PART 126 | { 127 | name = pf_tech_fairing30m 128 | module = Part 129 | author = Starstrider42 (config), e-dog (model) 130 | 131 | MODEL 132 | { 133 | model = ProceduralFairings/Parts/base_standard 134 | } 135 | 136 | TechRequired = experimentalAerodynamics 137 | entryCost = 0 138 | cost = 0 139 | category = none 140 | title = Procedural Fairings Upgrade 141 | manufacturer = Keramzit Engineering 142 | description = Allows fairing bases up to 30 meters size. 143 | } 144 | 145 | PART 146 | { 147 | name = pf_tech_rocket12m 148 | module = Part 149 | author = Starstrider42 (config), e-dog (model) 150 | 151 | MODEL 152 | { 153 | model = ProceduralFairings/Parts/thrust_plate 154 | } 155 | 156 | TechRequired = metaMaterials 157 | entryCost = 0 158 | cost = 0 159 | category = none 160 | title = Procedural Fairings Upgrade 161 | manufacturer = Keramzit Engineering 162 | description = Allows thrust plates up to 12 meters size. 163 | } 164 | 165 | PART 166 | { 167 | name = pf_tech_rocket30m 168 | module = Part 169 | author = Starstrider42 (config), e-dog (model) 170 | 171 | MODEL 172 | { 173 | model = ProceduralFairings/Parts/thrust_plate 174 | } 175 | 176 | TechRequired = aerospaceTech 177 | entryCost = 0 178 | cost = 0 179 | category = none 180 | title = Procedural Fairings Upgrade 181 | manufacturer = Keramzit Engineering 182 | description = Allows thrust plates up to 30 meters size. 183 | } 184 | -------------------------------------------------------------------------------- /GameData/ProceduralFairings/Config/PF_Squad_Config.cfg: -------------------------------------------------------------------------------- 1 | // ================================================== 2 | // Replace the stock procedural fairings with ours. 3 | // ================================================== 4 | 5 | @PART[fairingSize1]:FOR[ProceduralFairings]:NEEDS[!PFFE] 6 | { 7 | !MODEL,*{} 8 | 9 | MODEL 10 | { 11 | model = Squad/Parts/Aero/fairings/fairingSize1 12 | scale = 0.8275, 0.8275, 0.8275 13 | position = 0.0, -0.115, 0.0 14 | } 15 | 16 | @node_stack_top = 0.0, 0.0725, 0.0, 0.0, 1.0, 0.0, 0 17 | @node_stack_bottom = 0.0, -0.265, 0.0, 0.0, -1.0, 0.0, 1 18 | 19 | %node_stack_connect01 = 0.5, 0.1, 0.0, 0.0, 1.0, 0.0, 0 20 | %node_stack_connect02 = 0.5, 0.1, 0.0, 0.0, 1.0, 0.0, 0 21 | %node_stack_connect03 = 0.5, 0.1, 0.0, 0.0, 1.0, 0.0, 0 22 | %node_stack_connect04 = 0.5, 0.1, 0.0, 0.0, 1.0, 0.0, 0 23 | %node_stack_connect05 = 0.5, 0.1, 0.0, 0.0, 1.0, 0.0, 0 24 | %node_stack_connect06 = 0.5, 0.1, 0.0, 0.0, 1.0, 0.0, 0 25 | %node_stack_connect07 = 0.5, 0.1, 0.0, 0.0, 1.0, 0.0, 0 26 | %node_stack_connect08 = 0.5, 0.1, 0.0, 0.0, 1.0, 0.0, 0 27 | 28 | %fx_gasBurst_white = 0.0, 0.0725, 0.0, 0.0, 1.0, 0.0, decouple 29 | 30 | %sound_vent_large = decouple 31 | 32 | @title = AE-FF-PF Airstream Protective Shell 33 | @tags ^=:$: procedural 34 | 35 | !MODULE[ModuleProceduralFairing],*{} 36 | 37 | !MODULE[ModuleCargoBay],*{} 38 | 39 | !MODULE[ModuleStructuralNode*],*{} 40 | 41 | !MODULE[ModulePartVariants],*{} 42 | 43 | MODULE 44 | { 45 | name = ProceduralFairingBase 46 | baseSize = 1.15 47 | sideThickness = 0.05 48 | verticalStep = 0.1 49 | } 50 | 51 | MODULE 52 | { 53 | name = KzNodeNumberTweaker 54 | nodePrefix = connect 55 | maxNumber = 8 56 | numNodes = 2 57 | radius = 0.625 58 | shouldResizeNodes = False 59 | } 60 | 61 | MODULE 62 | { 63 | name = KzFairingBaseResizer 64 | size = 1.25 65 | costPerTonne = 1000 66 | specificMass = 0.007, 0.026, 0.010, 0 67 | specificBreakingForce = 1280 68 | specificBreakingTorque = 1280 69 | dragAreaScale = 1.5 70 | } 71 | 72 | MODULE 73 | { 74 | name = KzFairingBaseShielding 75 | } 76 | 77 | MODULE 78 | { 79 | name = ModuleDecouple 80 | isOmniDecoupler = False 81 | ejectionForce = 250 82 | ejectionForcePercent = 100 83 | menuName = Decoupler Staging 84 | stagingEnabled = False 85 | stagingEnableText = Decoupler: Disabled 86 | stagingDisableText = Decoupler: Enabled 87 | } 88 | 89 | MODULE 90 | { 91 | name = ModuleToggleCrossfeed 92 | crossfeedStatus = False 93 | toggleEditor = True 94 | toggleFlight = True 95 | enableText = Enable Crossfeed 96 | disableText = Disable Crossfeed 97 | } 98 | } 99 | 100 | // ================================================== 101 | // Hide the rest of the bases. 102 | // ================================================== 103 | 104 | @PART[fairingSize2]:FOR[ProceduralFairings]:NEEDS[!PFFE] 105 | { 106 | @TechRequired = none 107 | %TechHidden = True 108 | @category = none 109 | } 110 | 111 | @PART[fairingSize3]:FOR[ProceduralFairings]:NEEDS[!PFFE] 112 | { 113 | @TechRequired = none 114 | %TechHidden = True 115 | @category = none 116 | } 117 | -------------------------------------------------------------------------------- /GameData/ProceduralFairings/Parts/base_ring.cfg: -------------------------------------------------------------------------------- 1 | PART 2 | { 3 | name = KzResizableFairingBaseRing 4 | module = Part 5 | author = e-dog 6 | 7 | MODEL 8 | { 9 | model = ProceduralFairings/Parts/base_ring 10 | scale = 1.0, 1.0, 1.0 11 | } 12 | 13 | scale = 1.0 14 | rescaleFactor = 1.0 15 | 16 | node_stack_top = 0.0, 0.2, 0.0, 0.0, 1.0, 0.0, 1 17 | node_stack_bottom = 0.0, 0.0, 0.0, 0.0, -1.0, 0.0, 1 18 | 19 | node_stack_connect01 = 0.5, 0.1, 0.0, 0.0, 1.0, 0.0, 0 20 | node_stack_connect02 = 0.5, 0.1, 0.0, 0.0, 1.0, 0.0, 0 21 | node_stack_connect03 = 0.5, 0.1, 0.0, 0.0, 1.0, 0.0, 0 22 | node_stack_connect04 = 0.5, 0.1, 0.0, 0.0, 1.0, 0.0, 0 23 | node_stack_connect05 = 0.5, 0.1, 0.0, 0.0, 1.0, 0.0, 0 24 | node_stack_connect06 = 0.5, 0.1, 0.0, 0.0, 1.0, 0.0, 0 25 | node_stack_connect07 = 0.5, 0.1, 0.0, 0.0, 1.0, 0.0, 0 26 | node_stack_connect08 = 0.5, 0.1, 0.0, 0.0, 1.0, 0.0, 0 27 | 28 | attachRules = 1,0,1,1,0 29 | 30 | fx_gasBurst_white = 0.0, 0.3, 0.0, 0.0, 1.0, 0.0, decouple 31 | 32 | sound_decoupler_fire = decouple 33 | 34 | TechRequired = aerodynamicSystems 35 | cost = 100 36 | entryCost = 4600 37 | category = Payload 38 | subcategory = 0 39 | title = Procedural Fairing Base Ring 40 | manufacturer = Keramzit Engineering 41 | description = Structural base for mounting side fairings and your payload. Ring style. 42 | 43 | mass = 0 44 | dragModelType = default 45 | maximum_drag = 0.2 46 | minimum_drag = 0.2 47 | angularDrag = 2 48 | crashTolerance = 12 49 | breakingForce = 2000 50 | breakingTorque = 2000 51 | maxTemp = 2600 52 | explosionPotential = 0 53 | fuelCrossFeed = True 54 | thermalMassModifier = 2.0 55 | skinMassPerArea = 4.0 56 | skinInternalConductionMult = 0.25 57 | emissiveConstant = 0.8 58 | stackSymmetry = 7 59 | stageOffset = 1 60 | childStageOffset = 1 61 | bulkheadProfiles = size1 62 | tags = aero )cap cargo cone contain drag fairing hollow inter nose payload procedural protect rocket shroud stage (stor transport 63 | 64 | MODULE 65 | { 66 | name = ProceduralFairingBase 67 | baseSize = 1.15 68 | sideThickness = 0.05 69 | verticalStep = 0.1 70 | } 71 | 72 | MODULE 73 | { 74 | name = KzNodeNumberTweaker 75 | nodePrefix = connect 76 | maxNumber = 8 77 | numNodes = 2 78 | radius = 0.625 79 | shouldResizeNodes = False 80 | } 81 | 82 | MODULE 83 | { 84 | name = KzFairingBaseResizer 85 | size = 1.25 86 | costPerTonne = 1000 87 | specificMass = 0.006, 0.013, 0.010, 0 88 | specificBreakingForce = 1280 89 | specificBreakingTorque = 1280 90 | dragAreaScale = 1.5 91 | } 92 | 93 | MODULE 94 | { 95 | name = KzFairingBaseShielding 96 | } 97 | 98 | MODULE 99 | { 100 | name = ModuleDecouple 101 | explosiveNodeID = top 102 | isOmniDecoupler = False 103 | ejectionForce = 250 104 | ejectionForcePercent = 100 105 | menuName = Decoupler Staging 106 | stagingEnabled = False 107 | stagingEnableText = Decoupler: Disabled 108 | stagingDisableText = Decoupler: Enabled 109 | } 110 | 111 | MODULE 112 | { 113 | name = ModuleToggleCrossfeed 114 | crossfeedStatus = False 115 | toggleEditor = True 116 | toggleFlight = True 117 | enableText = Enable Crossfeed 118 | disableText = Disable Crossfeed 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /GameData/ProceduralFairings/Parts/base_ring.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsparkyc/ProceduralFairings/fbbefcd1545e8cd904c1ed102856d7fe60de50c0/GameData/ProceduralFairings/Parts/base_ring.dds -------------------------------------------------------------------------------- /GameData/ProceduralFairings/Parts/base_ring.mu: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsparkyc/ProceduralFairings/fbbefcd1545e8cd904c1ed102856d7fe60de50c0/GameData/ProceduralFairings/Parts/base_ring.mu -------------------------------------------------------------------------------- /GameData/ProceduralFairings/Parts/base_ring_black.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsparkyc/ProceduralFairings/fbbefcd1545e8cd904c1ed102856d7fe60de50c0/GameData/ProceduralFairings/Parts/base_ring_black.dds -------------------------------------------------------------------------------- /GameData/ProceduralFairings/Parts/base_standard.cfg: -------------------------------------------------------------------------------- 1 | PART 2 | { 3 | name = KzResizableFairingBase 4 | module = Part 5 | author = e-dog 6 | 7 | MODEL 8 | { 9 | model = ProceduralFairings/Parts/base_standard 10 | scale = 1.0, 1.0, 1.0 11 | } 12 | 13 | scale = 1.0 14 | rescaleFactor = 1.0 15 | 16 | node_stack_top = 0.0, 0.5, 0.0, 0.0, 1.0, 0.0, 1 17 | node_stack_bottom = 0.0, 0.0, 0.0, 0.0, -1.0, 0.0, 1 18 | 19 | node_stack_connect01 = 0.5, 0.1, 0.0, 0.0, 1.0, 0.0, 0 20 | node_stack_connect02 = 0.5, 0.1, 0.0, 0.0, 1.0, 0.0, 0 21 | node_stack_connect03 = 0.5, 0.1, 0.0, 0.0, 1.0, 0.0, 0 22 | node_stack_connect04 = 0.5, 0.1, 0.0, 0.0, 1.0, 0.0, 0 23 | node_stack_connect05 = 0.5, 0.1, 0.0, 0.0, 1.0, 0.0, 0 24 | node_stack_connect06 = 0.5, 0.1, 0.0, 0.0, 1.0, 0.0, 0 25 | node_stack_connect07 = 0.5, 0.1, 0.0, 0.0, 1.0, 0.0, 0 26 | node_stack_connect08 = 0.5, 0.1, 0.0, 0.0, 1.0, 0.0, 0 27 | 28 | node_stack_interstage01 = 0.0, 1.20, 0.0, 0.0, -1.0, 0.0, 1 29 | node_stack_interstage01u = 0.0, 1.20, 0.0, 0.0, 1.0, 0.0, 1 30 | node_stack_interstage02 = 0.0, 1.90, 0.0, 0.0, -1.0, 0.0, 1 31 | node_stack_interstage02u = 0.0, 1.90, 0.0, 0.0, 1.0, 0.0, 1 32 | node_stack_interstage03 = 0.0, 2.60, 0.0, 0.0, -1.0, 0.0, 1 33 | node_stack_interstage03u = 0.0, 2.60, 0.0, 0.0, 1.0, 0.0, 1 34 | node_stack_interstage04 = 0.0, 3.30, 0.0, 0.0, -1.0, 0.0, 1 35 | node_stack_interstage04u = 0.0, 3.30, 0.0, 0.0, 1.0, 0.0, 1 36 | node_stack_interstage05 = 0.0, 4.00, 0.0, 0.0, -1.0, 0.0, 1 37 | node_stack_interstage05u = 0.0, 4.00, 0.0, 0.0, 1.0, 0.0, 1 38 | node_stack_interstage06 = 0.0, 4.70, 0.0, 0.0, -1.0, 0.0, 1 39 | node_stack_interstage06u = 0.0, 4.70, 0.0, 0.0, 1.0, 0.0, 1 40 | node_stack_interstage07 = 0.0, 5.40, 0.0, 0.0, -1.0, 0.0, 1 41 | node_stack_interstage07u = 0.0, 5.40, 0.0, 0.0, 1.0, 0.0, 1 42 | node_stack_interstage08 = 0.0, 6.10, 0.0, 0.0, -1.0, 0.0, 1 43 | node_stack_interstage08u = 0.0, 6.10, 0.0, 0.0, 1.0, 0.0, 1 44 | 45 | attachRules = 1,0,1,1,0 46 | 47 | fx_gasBurst_white = 0.0, 0.3, 0.0, 0.0, 1.0, 0.0, decouple 48 | 49 | sound_vent_large = decouple 50 | 51 | TechRequired = aviation 52 | cost = 100 53 | entryCost = 4600 54 | category = Payload 55 | subcategory = 0 56 | title = Procedural Fairing Base 57 | manufacturer = Keramzit Engineering 58 | description = Structural base for mounting side fairings and your payload. Raised surface can ease loading. 59 | 60 | mass = 0 61 | dragModelType = default 62 | maximum_drag = 0.2 63 | minimum_drag = 0.2 64 | angularDrag = 2 65 | crashTolerance = 12 66 | breakingForce = 2000 67 | breakingTorque = 2000 68 | maxTemp = 2600 69 | fuelCrossFeed = True 70 | thermalMassModifier = 2.0 71 | skinMassPerArea = 4.0 72 | skinInternalConductionMult = 0.25 73 | emissiveConstant = 0.8 74 | stackSymmetry = 7 75 | stageOffset = 1 76 | childStageOffset = 1 77 | bulkheadProfiles = size1 78 | tags = aero )cap cargo cone contain drag fairing hollow inter nose payload procedural protect rocket shroud stage (stor transport 79 | 80 | MODULE 81 | { 82 | name = ProceduralFairingBase 83 | baseSize = 1.15 84 | sideThickness = 0.05 85 | verticalStep = 0.1 86 | } 87 | 88 | MODULE 89 | { 90 | name = KzNodeNumberTweaker 91 | nodePrefix = connect 92 | maxNumber = 8 93 | numNodes = 2 94 | radius = 0.625 95 | shouldResizeNodes = False 96 | } 97 | 98 | MODULE 99 | { 100 | name = KzFairingBaseResizer 101 | size = 1.25 102 | costPerTonne = 1000 103 | specificMass = 0.007, 0.026, 0.010, 0 104 | specificBreakingForce = 1280 105 | specificBreakingTorque = 1280 106 | dragAreaScale = 1.5 107 | } 108 | 109 | MODULE 110 | { 111 | name = KzFairingBaseShielding 112 | } 113 | 114 | MODULE 115 | { 116 | name = ModuleDecouple 117 | explosiveNodeID = top 118 | isOmniDecoupler = False 119 | ejectionForce = 250 120 | ejectionForcePercent = 100 121 | menuName = Decoupler Staging 122 | stagingEnabled = False 123 | stagingEnableText = Decoupler: Disabled 124 | stagingDisableText = Decoupler: Enabled 125 | } 126 | 127 | MODULE 128 | { 129 | name = ModuleToggleCrossfeed 130 | crossfeedStatus = False 131 | toggleEditor = True 132 | toggleFlight = True 133 | enableText = Enable Crossfeed 134 | disableText = Disable Crossfeed 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /GameData/ProceduralFairings/Parts/base_standard.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsparkyc/ProceduralFairings/fbbefcd1545e8cd904c1ed102856d7fe60de50c0/GameData/ProceduralFairings/Parts/base_standard.dds -------------------------------------------------------------------------------- /GameData/ProceduralFairings/Parts/base_standard.mu: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsparkyc/ProceduralFairings/fbbefcd1545e8cd904c1ed102856d7fe60de50c0/GameData/ProceduralFairings/Parts/base_standard.mu -------------------------------------------------------------------------------- /GameData/ProceduralFairings/Parts/fairing.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsparkyc/ProceduralFairings/fbbefcd1545e8cd904c1ed102856d7fe60de50c0/GameData/ProceduralFairings/Parts/fairing.dds -------------------------------------------------------------------------------- /GameData/ProceduralFairings/Parts/fairing_NRM.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsparkyc/ProceduralFairings/fbbefcd1545e8cd904c1ed102856d7fe60de50c0/GameData/ProceduralFairings/Parts/fairing_NRM.dds -------------------------------------------------------------------------------- /GameData/ProceduralFairings/Parts/fairing_side.mu: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsparkyc/ProceduralFairings/fbbefcd1545e8cd904c1ed102856d7fe60de50c0/GameData/ProceduralFairings/Parts/fairing_side.mu -------------------------------------------------------------------------------- /GameData/ProceduralFairings/Parts/fairing_side_A.cfg: -------------------------------------------------------------------------------- 1 | PART 2 | { 3 | name = KzProcFairingSide1 4 | module = Part 5 | author = e-dog 6 | 7 | MODEL 8 | { 9 | model = ProceduralFairings/Parts/fairing_side 10 | texture = fairing, ProceduralFairings/Textures/fairing 11 | texture = fairing_NRM, ProceduralFairings/Textures/fairing_NRM 12 | } 13 | 14 | scale = 1.0 15 | rescaleFactor = 1.0 16 | 17 | node_stack_connect = 0.0, 0.5, 0.0, 0.0, -1.0, 0.0, 0 18 | 19 | attachRules = 1,0,0,1,1 20 | 21 | TechRequired = aviation 22 | cost = 100 23 | entryCost = 4600 24 | category = Payload 25 | subcategory = 0 26 | title = Procedural Fairing (Ogive) 27 | manufacturer = Keramzit Engineering 28 | description = Made from the finest materials found in the fields around the Space Center. Can be set to any shape required. 29 | 30 | mass = 0 31 | dragModelType = default 32 | maximum_drag = 0.1 33 | minimum_drag = 0.1 34 | angularDrag = 2 35 | crashTolerance = 8 36 | breakingForce = 200 37 | breakingTorque = 200 38 | maxTemp = 2600 39 | thermalMassModifier = 2.0 40 | skinMassPerArea = 4.0 41 | skinInternalConductionMult = 0.25 42 | emissiveConstant = 0.8 43 | fuelCrossFeed = False 44 | stageOffset = 1 45 | childStageOffset = 1 46 | stagingIcon = FUEL_TANK 47 | bulkheadProfiles = size0 48 | tags = aero )cap cargo cone contain drag fairing hollow inter nose payload procedural protect rocket shroud stage (stor transport 49 | 50 | MODULE 51 | { 52 | name = ProceduralFairingSide 53 | density = 0.1 54 | costPerTonne = 5000 55 | specificBreakingForce = 2000 56 | specificBreakingTorque = 2000 57 | noseHeightRatio = 2.0 58 | baseConeShape = 0.3, 0.2, 1.0, 0.5 59 | noseConeShape = 0.5, 0.0, 1.0, 0.7 60 | baseConeSegments = 7 61 | noseConeSegments = 11 62 | mappingScale = 1024, 1024 63 | stripMapping = 992, 1024 64 | horMapping = 10, 490, 500, 980 65 | vertMapping = 10, 170, 694, 1014 66 | } 67 | 68 | MODULE 69 | { 70 | name = ProceduralFairingDecoupler 71 | } 72 | 73 | MODULE 74 | { 75 | name = ModulePartVariants 76 | primaryColor = #FAFAFA 77 | secondaryColor = #DCBE87 78 | baseDisplayName = Original 79 | 80 | VARIANT 81 | { 82 | name = Fuselage 83 | displayName = Fuselage 84 | primaryColor = #D7D7D7 85 | secondaryColor = #B9B9B9 86 | 87 | TEXTURE 88 | { 89 | mainTextureURL = ProceduralFairings/Textures/fairing_fuselage 90 | _BumpMap = ProceduralFairings/Textures/fairing_generic_NRM 91 | } 92 | } 93 | } 94 | 95 | MODULE 96 | { 97 | name = ModuleSeeThroughObject 98 | transformName = model 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /GameData/ProceduralFairings/Parts/fairing_side_B.cfg: -------------------------------------------------------------------------------- 1 | PART 2 | { 3 | name = KzProcFairingSide2 4 | module = Part 5 | author = e-dog 6 | 7 | MODEL 8 | { 9 | model = ProceduralFairings/Parts/fairing_side 10 | texture = fairing, ProceduralFairings/Textures/fairing 11 | texture = fairing_NRM, ProceduralFairings/Textures/fairing_NRM 12 | } 13 | 14 | scale = 1.0 15 | rescaleFactor = 1.0 16 | 17 | node_stack_connect = 0.0, 0.5, 0.0, 0.0, -1.0, 0.0, 0 18 | 19 | attachRules = 1,0,0,1,1 20 | 21 | TechRequired = aviation 22 | cost = 100 23 | entryCost = 4600 24 | category = Payload 25 | subcategory = 0 26 | title = Procedural Fairing (Conic) 27 | manufacturer = Keramzit Engineering 28 | description = Made from the finest materials found in the fields around the Space Center. Can be set to any shape required. 29 | 30 | mass = 0 31 | dragModelType = default 32 | maximum_drag = 0.1 33 | minimum_drag = 0.1 34 | angularDrag = 2 35 | crashTolerance = 8 36 | breakingForce = 200 37 | breakingTorque = 200 38 | maxTemp = 2600 39 | thermalMassModifier = 2.0 40 | skinMassPerArea = 4.0 41 | skinInternalConductionMult = 0.25 42 | emissiveConstant = 0.8 43 | fuelCrossFeed = False 44 | stageOffset = 1 45 | childStageOffset = 1 46 | stagingIcon = FUEL_TANK 47 | bulkheadProfiles = size0 48 | tags = aero )cap cargo cone contain drag fairing hollow inter nose payload procedural protect rocket shroud stage (stor transport 49 | 50 | MODULE 51 | { 52 | name = ProceduralFairingSide 53 | density = 0.1 54 | costPerTonne = 5000 55 | specificBreakingForce = 2000 56 | specificBreakingTorque = 2000 57 | noseHeightRatio = 2.0 58 | baseConeShape = 0.3, 0.3, 0.7, 0.7 59 | noseConeShape = 0.1, 0.0, 0.7, 0.7 60 | baseConeSegments = 7 61 | noseConeSegments = 11 62 | mappingScale = 1024, 1024 63 | stripMapping = 992, 1024 64 | horMapping = 10, 490, 500, 980 65 | vertMapping = 10, 170, 694, 1014 66 | } 67 | 68 | MODULE 69 | { 70 | name = ProceduralFairingDecoupler 71 | } 72 | 73 | MODULE 74 | { 75 | name = ModulePartVariants 76 | primaryColor = #FAFAFA 77 | secondaryColor = #DCBE87 78 | baseDisplayName = Original 79 | 80 | VARIANT 81 | { 82 | name = Fuselage 83 | displayName = Fuselage 84 | primaryColor = #D7D7D7 85 | secondaryColor = #B9B9B9 86 | 87 | TEXTURE 88 | { 89 | mainTextureURL = ProceduralFairings/Textures/fairing_fuselage 90 | _BumpMap = ProceduralFairings/Textures/fairing_generic_NRM 91 | } 92 | } 93 | } 94 | 95 | MODULE 96 | { 97 | name = ModuleSeeThroughObject 98 | transformName = model 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /GameData/ProceduralFairings/Parts/interstage_adapter.cfg: -------------------------------------------------------------------------------- 1 | PART 2 | { 3 | name = KzInterstageAdapter2 4 | module = Part 5 | author = e-dog 6 | 7 | MODEL 8 | { 9 | model = ProceduralFairings/Parts/base_ring 10 | scale = 1.0, 1.0, 1.0 11 | texture = base_ring, ProceduralFairings/Parts/base_ring_black 12 | } 13 | 14 | scale = 1.0 15 | rescaleFactor = 1.0 16 | 17 | node_stack_top = 0.0, 0.2, 0.0, 0.0, 1.0, 0.0, 1 18 | node_stack_top1 = 0.0, 2.0, 0.0, 0.0, 1.0, 0.0, 1 19 | node_stack_bottom = 0.0, 0.0, 0.0, 0.0, -1.0, 0.0, 1 20 | 21 | node_stack_connect01 = -0.5, 0.1, 0.0, 0.0, 1.0, 0.0, 0 22 | node_stack_connect02 = 0.0, 0.1, 0.5, 0.0, 1.0, 0.0, 0 23 | node_stack_connect03 = 0.5, 0.1, 0.0, 0.0, 1.0, 0.0, 0 24 | node_stack_connect04 = 0.0, 0.1, -0.5, 0.0, 1.0, 0.0, 0 25 | node_stack_connect05 = -0.5, 0.1, 0.0, 0.0, 1.0, 0.0, 0 26 | node_stack_connect06 = 0.0, 0.1, 0.5, 0.0, 1.0, 0.0, 0 27 | node_stack_connect07 = 0.5, 0.1, 0.0, 0.0, 1.0, 0.0, 0 28 | node_stack_connect08 = 0.0, 0.1, -0.5, 0.0, 1.0, 0.0, 0 29 | 30 | node_stack_interstage01 = 0.0, 0.425, 0.0, 0.0, -1.0, 0.0, 0 31 | node_stack_interstage01u = 0.0, 0.425, 0.0, 0.0, 1.0, 0.0, 0 32 | node_stack_interstage02 = 0.0, 0.650, 0.0, 0.0, -1.0, 0.0, 0 33 | node_stack_interstage02u = 0.0, 0.650, 0.0, 0.0, 1.0, 0.0, 0 34 | node_stack_interstage03 = 0.0, 0.875, 0.0, 0.0, -1.0, 0.0, 0 35 | node_stack_interstage03u = 0.0, 0.875, 0.0, 0.0, 1.0, 0.0, 0 36 | node_stack_interstage04 = 0.0, 1.100, 0.0, 0.0, -1.0, 0.0, 0 37 | node_stack_interstage04u = 0.0, 1.100, 0.0, 0.0, 1.0, 0.0, 0 38 | node_stack_interstage05 = 0.0, 1.325, 0.0, 0.0, -1.0, 0.0, 0 39 | node_stack_interstage05u = 0.0, 1.325, 0.0, 0.0, 1.0, 0.0, 0 40 | node_stack_interstage06 = 0.0, 1.550, 0.0, 0.0, -1.0, 0.0, 0 41 | node_stack_interstage06u = 0.0, 1.550, 0.0, 0.0, 1.0, 0.0, 0 42 | node_stack_interstage07 = 0.0, 1.775, 0.0, 0.0, -1.0, 0.0, 0 43 | node_stack_interstage07u = 0.0, 1.775, 0.0, 0.0, 1.0, 0.0, 0 44 | 45 | attachRules = 1,0,1,1,0 46 | 47 | fx_gasBurst_white = 0.0, 0.3, 0.0, 0.0, 1.0, 0.0, decouple 48 | 49 | sound_vent_large = decouple 50 | 51 | TechRequired = advConstruction 52 | cost = 100 53 | entryCost = 4600 54 | category = Payload 55 | subcategory = 0 56 | title = Procedural Interstage Fairing Adapter 57 | manufacturer = Keramzit Engineering 58 | description = Enables side fairings to hold the part at the top. 59 | 60 | mass = 0 61 | dragModelType = default 62 | maximum_drag = 0.2 63 | minimum_drag = 0.2 64 | angularDrag = 2 65 | crashTolerance = 12 66 | breakingForce = 2000 67 | breakingTorque = 2000 68 | maxTemp = 2600 69 | fuelCrossFeed = True 70 | thermalMassModifier = 2.0 71 | skinMassPerArea = 4.0 72 | skinInternalConductionMult = 0.25 73 | emissiveConstant = 0.8 74 | stackSymmetry = 7 75 | stageOffset = 1 76 | childStageOffset = 1 77 | bulkheadProfiles = size1 78 | tags = aero )cap cargo cone contain drag fairing hollow inter nose payload procedural protect rocket shroud stage (stor transport 79 | 80 | MODULE 81 | { 82 | name = ProceduralFairingAdapter 83 | baseSize = 1.25 84 | topSize = 1.25 85 | height = 2.0 86 | costPerTonne = 1000 87 | specificMass = 0.006, 0.013, 0.010, 0 88 | specificBreakingForce = 6050 89 | specificBreakingTorque = 6050 90 | dragAreaScale = 1.5 91 | topNodeDecouplesWhenFairingsGone = False 92 | } 93 | 94 | MODULE 95 | { 96 | name = ProceduralFairingBase 97 | baseSize = 1.15 98 | sideThickness = 0.05 99 | verticalStep = 0.1 100 | } 101 | 102 | MODULE 103 | { 104 | name = KzNodeNumberTweaker 105 | nodePrefix = connect 106 | maxNumber = 8 107 | numNodes = 4 108 | radius = 0.625 109 | shouldResizeNodes = False 110 | } 111 | 112 | MODULE 113 | { 114 | name = KzFairingBaseShielding 115 | } 116 | 117 | MODULE 118 | { 119 | name = ModuleDecouple 120 | explosiveNodeID = top1 121 | isOmniDecoupler = False 122 | ejectionForce = 250 123 | ejectionForcePercent = 100 124 | menuName = Decouple Top Node 125 | stagingEnableText = Decoupler: Disabled 126 | stagingDisableText = Decoupler: Enabled 127 | } 128 | 129 | MODULE 130 | { 131 | name = ModuleToggleCrossfeed 132 | crossfeedStatus = False 133 | toggleEditor = True 134 | toggleFlight = True 135 | enableText = Enable Crossfeed 136 | disableText = Disable Crossfeed 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /GameData/ProceduralFairings/Parts/thrust_plate.cfg: -------------------------------------------------------------------------------- 1 | PART 2 | { 3 | name = KzThrustPlate 4 | module = Part 5 | author = e-dog 6 | 7 | MODEL 8 | { 9 | model = ProceduralFairings/Parts/thrust_plate 10 | scale = 1.0, 1.0, 1.0 11 | } 12 | 13 | scale = 1.0 14 | rescaleFactor = 1.0 15 | 16 | node_stack_top = 0.0, 0.1, 0.0, 0.0, 1.0, 0.0, 1 17 | node_stack_bottom = 0.0, 0.0, 0.0, 0.0, -1.0, 0.0, 1 18 | 19 | node_stack_bottom01 = 0.5, 0.0, 0.0, 0.0, -1.0, 0.0, 1 20 | node_stack_bottom02 = 0.5, 0.0, 0.0, 0.0, -1.0, 0.0, 1 21 | node_stack_bottom03 = 0.5, 0.0, 0.0, 0.0, -1.0, 0.0, 1 22 | node_stack_bottom04 = 0.5, 0.0, 0.0, 0.0, -1.0, 0.0, 1 23 | node_stack_bottom05 = 0.5, 0.0, 0.0, 0.0, -1.0, 0.0, 1 24 | node_stack_bottom06 = 0.5, 0.0, 0.0, 0.0, -1.0, 0.0, 1 25 | node_stack_bottom07 = 0.5, 0.0, 0.0, 0.0, -1.0, 0.0, 1 26 | node_stack_bottom08 = 0.5, 0.0, 0.0, 0.0, -1.0, 0.0, 1 27 | node_stack_bottom09 = 0.5, 0.0, 0.0, 0.0, -1.0, 0.0, 1 28 | node_stack_bottom10 = 0.5, 0.0, 0.0, 0.0, -1.0, 0.0, 1 29 | node_stack_bottom11 = 0.5, 0.0, 0.0, 0.0, -1.0, 0.0, 1 30 | node_stack_bottom12 = 0.5, 0.0, 0.0, 0.0, -1.0, 0.0, 1 31 | node_stack_bottom13 = 0.5, 0.0, 0.0, 0.0, -1.0, 0.0, 1 32 | node_stack_bottom14 = 0.5, 0.0, 0.0, 0.0, -1.0, 0.0, 1 33 | node_stack_bottom15 = 0.5, 0.0, 0.0, 0.0, -1.0, 0.0, 1 34 | node_stack_bottom16 = 0.5, 0.0, 0.0, 0.0, -1.0, 0.0, 1 35 | 36 | TechRequired = advConstruction 37 | cost = 100 38 | entryCost = 4200 39 | category = Structural 40 | subcategory = 0 41 | title = Procedural Thrust Plate Adapter 42 | manufacturer = Keramzit Engineering 43 | description = When quad-adapter just isn't enough, Keramzit Engineering has you covered with its wonderful Multi-adapter! Designed for building engine clusters, it also found its uses in multiple payload attachment and space bars. 44 | attachRules = 1,0,1,1,0 45 | 46 | mass = 0 47 | dragModelType = default 48 | maximum_drag = 0.2 49 | minimum_drag = 0.2 50 | angularDrag = 2 51 | crashTolerance = 12 52 | breakingForce = 2000 53 | breakingTorque = 2000 54 | maxTemp = 2000 55 | explosionPotential = 0 56 | fuelCrossFeed = False 57 | bulkheadProfiles = size1 58 | NoCrossFeedNodeKey = bottom 59 | 60 | MODULE 61 | { 62 | name = KzNodeNumberTweaker 63 | nodePrefix = bottom 64 | maxNumber = 16 65 | numNodes = 4 66 | radius = 0.625 67 | } 68 | 69 | MODULE 70 | { 71 | name = KzThrustPlateResizer 72 | size = 1.25 73 | costPerTonne = 1000 74 | specificMass = 0.007, 0.026, 0.01, 0 75 | specificBreakingForce = 1536 76 | specificBreakingTorque = 1536 77 | minSizeName = PROCROCKET_MINDIAMETER 78 | maxSizeName = PROCROCKET_MAXDIAMETER 79 | } 80 | 81 | MODULE 82 | { 83 | name = ModuleToggleCrossfeed 84 | crossfeedStatus = False 85 | toggleEditor = True 86 | toggleFlight = True 87 | enableText = Enable Crossfeed 88 | disableText = Disable Crossfeed 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /GameData/ProceduralFairings/Parts/thrust_plate.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsparkyc/ProceduralFairings/fbbefcd1545e8cd904c1ed102856d7fe60de50c0/GameData/ProceduralFairings/Parts/thrust_plate.dds -------------------------------------------------------------------------------- /GameData/ProceduralFairings/Parts/thrust_plate.mu: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsparkyc/ProceduralFairings/fbbefcd1545e8cd904c1ed102856d7fe60de50c0/GameData/ProceduralFairings/Parts/thrust_plate.mu -------------------------------------------------------------------------------- /GameData/ProceduralFairings/Parts/thrust_plate_NRM.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsparkyc/ProceduralFairings/fbbefcd1545e8cd904c1ed102856d7fe60de50c0/GameData/ProceduralFairings/Parts/thrust_plate_NRM.dds -------------------------------------------------------------------------------- /GameData/ProceduralFairings/Plugins/ProceduralFairings.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsparkyc/ProceduralFairings/fbbefcd1545e8cd904c1ed102856d7fe60de50c0/GameData/ProceduralFairings/Plugins/ProceduralFairings.dll -------------------------------------------------------------------------------- /GameData/ProceduralFairings/ProceduralFairings.version: -------------------------------------------------------------------------------- 1 | { 2 | "NAME" : "Procedural Fairings", 3 | "DOWNLOAD" : "https://github.com/rsparkyc/ProceduralFairings/releases/", 4 | "URL" : "https://raw.githubusercontent.com/rsparkyc/ProceduralFairings/master/GameData/ProceduralFairings/ProceduralFairings.version", 5 | "GITHUB" : { 6 | "USERNAME" : "rsparkyc", 7 | "REPOSITORY" : "ProceduralFairings" 8 | }, 9 | "VERSION" : { 10 | "MAJOR" : 1, 11 | "MINOR" : 5, 12 | "PATCH" : 0, 13 | "BUILD" : 5 14 | }, 15 | "KSP_VERSION_MIN" : { 16 | "MAJOR" : 1, 17 | "MINOR" : 5, 18 | "PATCH" : 0 19 | }, 20 | "KSP_VERSION_MAX" : { 21 | "MAJOR" : 1, 22 | "MINOR" : 5, 23 | "PATCH" : 0 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /GameData/ProceduralFairings/Textures/fairing.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsparkyc/ProceduralFairings/fbbefcd1545e8cd904c1ed102856d7fe60de50c0/GameData/ProceduralFairings/Textures/fairing.dds -------------------------------------------------------------------------------- /GameData/ProceduralFairings/Textures/fairing_NRM.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsparkyc/ProceduralFairings/fbbefcd1545e8cd904c1ed102856d7fe60de50c0/GameData/ProceduralFairings/Textures/fairing_NRM.dds -------------------------------------------------------------------------------- /GameData/ProceduralFairings/Textures/fairing_fuselage.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsparkyc/ProceduralFairings/fbbefcd1545e8cd904c1ed102856d7fe60de50c0/GameData/ProceduralFairings/Textures/fairing_fuselage.dds -------------------------------------------------------------------------------- /GameData/ProceduralFairings/Textures/fairing_generic_NRM.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsparkyc/ProceduralFairings/fbbefcd1545e8cd904c1ed102856d7fe60de50c0/GameData/ProceduralFairings/Textures/fairing_generic_NRM.dds -------------------------------------------------------------------------------- /GameData/ProceduralFairings/changelog.txt: -------------------------------------------------------------------------------- 1 | ======================================================= 2 | ProceduralFairings v1.5.0.5 for KSP 1.5.0 (2018-10-18) 3 | ======================================================= 4 | 5 | • Recompiled for KSP 1.5.0. 6 | 7 | ======================================================= 8 | ProceduralFairings v1.4.5.5 for KSP 1.4.5 (2018-08-27) 9 | ======================================================= 10 | 11 | • Recompiled for KSP 1.4.5. 12 | • Added support for 2.75 meter parts 13 | 14 | ======================================================= 15 | ProceduralFairings v1.4.3.4 for KSP 1.4.3 (2018-05-30) 16 | ======================================================= 17 | 18 | • Interstage adapter was trying to remove the fairing around any engine connected above it, which was breaking in KSP 1.4 19 | 20 | ======================================================= 21 | ProceduralFairings v1.4.3-1 for KSP 1.4.3 (2018-05-02) 22 | ======================================================= 23 | 24 | • Recompiled for KSP 1.4.3. 25 | • Fixed the fairing decouplers breaking the MechJeb delta-v calculations. 26 | • Fixed (possibly) the UI of the Fairing Bases and Interstage Adapters locking up and being unable to toggle between automatic and manual fairing side shape. 27 | 28 | ======================================================= 29 | ProceduralFairings v1.4.1-1 for KSP 1.4.1 (2018-03-14) 30 | ======================================================= 31 | 32 | • Recompiled for KSP 1.4.1. 33 | • Added compatibility for FilterExtensions to all parts. 34 | • Added the ability to toggle the fairing side decoupler (no more separate "Fairing" and "Fuselage" sides). 35 | • Added texture switching for the fairing side textures. 36 | • The base and nose shapes of fairing sides can now be independently changed in the editor, without requiring separate part configs. 37 | • Updated the part configs for compatibility with the latest KSP versions. 38 | • Added decoupler modules to the fairing bases (can be toggled and the decoupling force be set manually if required). 39 | • Fairings now will turn invisible in the editor when hovering over them. 40 | • Repackaged the distribution for the components to be in their own directories. 41 | • Changed the versioning system to use a - format (Kopernicus-style). 42 | 43 | ======================================================= 44 | ProceduralFairings v3.21 for KSP 1.2 (2017-06-07) 45 | ======================================================= 46 | 47 | • With the help of user sarbian, reverse engineered some changes from user KortexM. 48 | • Wait for part.editorStarted or part.started, then call an update to reset attached procedural parts (fixes the part shifting upon craft loading). 49 | 50 | ======================================================= 51 | ProceduralFairings v3.20 for KSP 1.2 (2016-11-08) 52 | ======================================================= 53 | 54 | Added the following changes by user KortexM: 55 | 56 | • Ready for KSP 1.2 (recompiled, small changes to configs). 57 | • Added Interstage Nodes (but no trusses) to Fairings and Interstage Fairing, two connections possible on each node (up & down). 58 | • A few code cleanups (ForEach to For mostly). 59 | • Fixed fuel cross feed (be aware that flow to or from the interstage nodes is affected too!). 60 | • Fixed ghost nodes appearing when adding a new fairing base in the VAB/SPH. 61 | • Fixed blue ghost lines (invalid fairing outline) when having multiple fairing bases in VAB/SPH. 62 | • Fixed interstage nodes positions for Interstage Adapter when resized. 63 | • Some UI fixes. 64 | • Code cleanups (deLINQing etc). 65 | • All other bugs/features untouched (hopefully...). 66 | 67 | ======================================================= 68 | ProceduralFairings v3.17 for KSP 1.1.2 (2016-05-08) 69 | ======================================================= 70 | 71 | • Rebuilt for KSP 1.1.2. 72 | • Fixed thermal issues with FAR (patch by user NathanKell). 73 | • Fixed procedural mass issues (patch by user NathanKell). 74 | • Fixed auto-strut joint issue (connecting to the same rigid body). 75 | • Improved payload auto-strut performance (strut heaviest part only). 76 | 77 | ======================================================= 78 | ProceduralFairings v3.16 for KSP 1.1 (2016-04-20) 79 | ======================================================= 80 | 81 | • Updated for KSP 1.1 (build 1230). 82 | 83 | ======================================================= 84 | ProceduralFairings v3.15 for KSP 1.0.4 (2015-06-27) 85 | ======================================================= 86 | 87 | • Updated for KSP 1.0.4. 88 | • Merged pull request for Procedural Parts bug fix. 89 | • Adjusted thermal parameters for KSP 1.0.4 (hopefully). 90 | 91 | ======================================================= 92 | ProceduralFairings v3.14 for KSP 1.0.2 (2015-05-10) 93 | ======================================================= 94 | 95 | • Updated for the new FAR. 96 | • Reduced fairing shape update rate in the editor to 2 times per second. 97 | • Adjusted default fairing decoupler value to avoid "vessel changed" messages spammed by bugged KSP sliders. 98 | 99 | ======================================================= 100 | ProceduralFairings v3.13 for KSP 1.0.2 (2015-05-03) 101 | ======================================================= 102 | 103 | • Updated for KSP 1.0.2. 104 | • Rewrote automatic payload struts, strutting all shielded parts now. 105 | • Fixed bug when it was impossible to revert sometimes. 106 | • Fixed slowdown in the editor when tweaking fairing sides. 107 | • Fixed thrust plate mass parameters. 108 | 109 | ======================================================= 110 | ProceduralFairings v3.12 for KSP 1.0 (2015-04-28) 111 | ======================================================= 112 | 113 | • Updated for KSP 1.0. 114 | • Procedural fairings now use new stock air stream shielding and drag cube rendering. 115 | • Inline fairings now check if the top is closed by a single big part of the same vessel. Make sure that's the case or the shielding won't work. 116 | • Changed and rearranged tech limits for the new tech tree. 117 | • Converted textures to DDS. 118 | • Fixed manual shape UI issues. 119 | • Number of shielded parts is now displayed in the right-click menu for the fairing base. It might be inaccurate in the editor. 120 | • Removed old deprecated parts (non-resizable fairing bases etc). 121 | 122 | ======================================================= 123 | ProceduralFairings v3.11 for KSP 0.90 (2014-12-17) 124 | ======================================================= 125 | 126 | • Updated for KSP 0.90. 127 | • Added optional manual fairing shape controls. 128 | • Fixed tech restrictions checking in science mode (patch by user Zwa333). 129 | 130 | ======================================================= 131 | ProceduralFairings v3.10 for KSP 0.25 (2014-10-11) 132 | ======================================================= 133 | 134 | • Rebuilt for KSP 0.25. 135 | 136 | ======================================================= 137 | ProceduralFairings v3.09 for KSP 0.24.2 (2014-08-03) 138 | ======================================================= 139 | 140 | • Updated KAE DLL. 141 | 142 | ======================================================= 143 | ProceduralFairings v3.08 for KSP 0.24.2 (2014-07-26) 144 | ======================================================= 145 | 146 | • Updated KAE DLL for KSP 0.24.2. 147 | 148 | ======================================================= 149 | ProceduralFairings v3.07 for KSP 0.24 (2014-07-25) 150 | ======================================================= 151 | 152 | • Decoupler workaround. 153 | 154 | ======================================================= 155 | ProceduralFairings v3.06 for KSP 0.24 (2014-07-20) 156 | ======================================================= 157 | 158 | • Updated for KSP 0.24. 159 | 160 | ======================================================= 161 | ProceduralFairings v3.05 for KSP 0.23.5 (2014-06-17) 162 | ======================================================= 163 | 164 | • Fixed collider bug introduced in 3.04. 165 | 166 | ======================================================= 167 | ProceduralFairings v3.03 for KSP 0.23.5 (2014-06-17) 168 | ======================================================= 169 | 170 | • Added fake parts to make tech upgrades visible in the tech tree. 171 | • Restored TechRequired for old parts to avoid issues with loading old designs in career mode. 172 | • Fixed bug that allowed to cheat tech limits in career mode. 173 | • Reduced default fairing ejection torque. 174 | 175 | ======================================================= 176 | ProceduralFairings v3.03 for KSP 0.23.5 (2014-06-06) 177 | ======================================================= 178 | 179 | • Added "sandbox" tech to specify minimum and maximum sizes in sandbox mode (see "common.cfg"). 180 | • Changed mass formula for all parts except side fairings. Generally, larger sizes are significantly lighter now. 181 | • Part mass is now displayed when you right-click the part in VAB. 182 | • Rebuilding side fairing mesh only when really needed (faster in VAB, especially with FAR). 183 | 184 | ======================================================= 185 | ProceduralFairings v3.02 for KSP 0.23.5 (2014-05-22) 186 | ======================================================= 187 | 188 | • Updated KSPAPIExtensions, should work with Procedural Parts now. 189 | • A bit less restrictive tech, allowing sizes a bit larger and smaller than stock ones. 190 | • Trying to avoid moving attached parts after loading design or saved game. 191 | • Fixed wrong size of newly added side nodes. 192 | 193 | ======================================================= 194 | ProceduralFairings v3.01 for KSP 0.23.5 (2014-05-14) 195 | ======================================================= 196 | 197 | • Updated KSPAPIExtensions. 198 | • Added size step parameters for RSS. 199 | 200 | ======================================================= 201 | ProceduralFairings v3.00 for KSP 0.23.5 (2014-05-13) 202 | ======================================================= 203 | 204 | • Moved files up to GameData folder (no "Keramzit" folder anymore). Make sure to delete old mod before installing (which is a good practice anyway). 205 | • Added new resizable fairing bases with configurable number of side nodes. 206 | • Old parts (bases and adapter) are deprecated. Launched vessels should be fine, but you might have trouble loading old designs in VAB/SPH in career mode. 207 | • Added new part: Thrust Plate Multi-Adapter. 208 | • Using KSPAPIExtensions for better tweakables. 209 | • Removed old keyboard-based tweaks - use new tweakables. 210 | • Tweaking outer diameter (with fairings), instead of inner radius. 211 | • Added fairing decoupler torque tweakable. 212 | • Side nodes (for attaching fairings) get larger with the base size to make them more sturdy in KSP 0.23.5+ 213 | • Tech limits are not checked in sandbox mode anymore. 214 | • Extra payload radius is now zero by default. 215 | • Fixed interstage adapter decoupling with fuselage fairings. 216 | 217 | ======================================================= 218 | ProceduralFairings v2.4.4 for KSP 0.23 (2014-03-31) 219 | ======================================================= 220 | 221 | • Added tweakables. 222 | • Rearranged tech tree, added 3.75m and 5m parts. 223 | • Interstage adapter is available earlier now, but its radius is limited by aerodynamics tech. 224 | • Launch clamps are ignored in payload scanning now. 225 | • Payload scanning doesn't follow surface attachment to the parent part anymore. 226 | • Improved interstage fairing shape when its top is inside payload. 227 | • Added base cone angle limit to make fairings look better. 228 | • Part descriptions and readme text copy edited by user Duxwing. 229 | 230 | ======================================================= 231 | ProceduralFairings v2.4.3 for KSP 0.23 (2013-12-18) 232 | ======================================================= 233 | 234 | • Improved payload scanning for interstage adapter. 235 | • Recompiled for KSP 0.23. 236 | 237 | ======================================================= 238 | ProceduralFairings v2.4.2 for KSP 0.22 (2013-10-19) 239 | ======================================================= 240 | 241 | • Zero-radius payload is now used when no payload attached, so fairings will always reshape. 242 | • Added parts to the tech tree. 243 | • Moved fuselage shrouds to Structural tab. 244 | • Changing adapter attachment node size with radius. 245 | 246 | ======================================================= 247 | ProceduralFairings v2.4.1 for KSP 0.21.1 (2013-08-22) 248 | ======================================================= 249 | 250 | • Disabled fuel cross feed on the interstage adapter - enable at your own risk, it confuses Engineer Redux to death. 251 | • Added stock decoupler module to the interstage adapter topmost node to help with delta-v calculations. 252 | • Improved fairing shape for interstage adapter when fairing top is inside payload. 253 | 254 | ======================================================= 255 | ProceduralFairings v2.4 for KSP 0.21.1 (2013-08-20) 256 | ======================================================= 257 | 258 | • Added procedural interstage fairing adapter with adjustable radii and height which decouples from the top part when fairings are ejected. 259 | • Added conic fuselage. 260 | • Fixed another inline fairing shape bug. 261 | 262 | ======================================================= 263 | ProceduralFairings v2.3 for KSP 0.21.1 (2013-08-07) 264 | ======================================================= 265 | 266 | • Changed fuselage texture to distinguish it from fairings. 267 | • You can now lock fairing shape: mouse over the side fairing/fuselage and press L. 268 | • Reduced side nodes size for smaller base rings and 0.625m fairing base (for easier placement). 269 | • Fixed inline fairings making a top cone when there should be just a cylinder. 270 | 271 | ======================================================= 272 | ProceduralFairings v2.2 for KSP 0.21.1 (2013-07-30) 273 | ======================================================= 274 | 275 | • Added experimental egg-shaped fuselage (a side fairing without decoupler). 276 | • Moved fairing decoupler code to separate PartModule. 277 | • Auto-struts are now created between the top inline base and side fairings as well. NOTE: if you payload is wobbly, the sides might still wobble. 278 | • Fixed bug with misplaced fairings on new ring bases. 279 | 280 | ======================================================= 281 | ProceduralFairings v2.1 for KSP 0.21.1 (2013-07-28) 282 | ======================================================= 283 | 284 | • Added low-profile fairing bases (base rings), intended for inline fairings. All of them have 4 side fairing attachment points. 285 | • Replaced base model with one that looks more lightweight. It has the same size etc., so it won't break your existing ships. 286 | • You can now toggle fuel cross feed for fairing base: mouse over and press G in editor or use right-click menu in flight. 287 | • You can now disable auto-struts between side fairings: mouse over the base and press T. 288 | • Fixed inline fairings not connecting with the top base sometimes. 289 | • Fixed nested inline fairings not connecting to the proper base. 290 | • Fairing outline (blue lines) is not displayed now for inline fairings if sides are attached to any of the two bases. 291 | 292 | ======================================================= 293 | ProceduralFairings v2.0 for KSP 0.21.1 (2013-07-24) 294 | ======================================================= 295 | 296 | • Inline truncated fairings are now created between two bases (one must be flipped). It won't work properly for off-center bases. If you want it off-center, tell me what for and how it should look. 297 | • You can now change ejection force by pressing F when mouse is over the side fairing. 298 | • Fixed rapid unplanned disassembly of side fairings when going out of time warp sometimes. 299 | 300 | ======================================================= 301 | ProceduralFairings v1.3 for KSP 0.20.2 (2013-07-14) 302 | ======================================================= 303 | 304 | • Fixed ejection direction bug - it shouldn't matter how you place fairings now. 305 | 306 | ======================================================= 307 | ProceduralFairings v1.2 for KSP 0.20.2 (2013-07-12) 308 | ======================================================= 309 | 310 | • Added invisible automatically placed struts between side fairings to mostly eliminate wobble. 311 | • Replaced ejectionNoseDv with ejectionTorque so that all ejected fairings have the same motion, regardless of shape. 312 | • Improved payload scanning for better fitting of mesh and box colliders. 313 | • You can now adjust radius by moving the mouse over the base part while holding R (the default key, can be changed in part .cfg file). 314 | • Fixed "recursion" bug which caused misplaced fairings to grow out of control. (It's also a foundation for future inline fairings). 315 | • Using a (hopefully) better method to offset side fairing center of mass. 316 | • Using proportionally smaller part of texture for 1/3 (and smaller) side fairings to reduce texture stretching. 317 | • Renamed "capsule-shaped" fairings to "egg-shaped" to be more Kerbal. 318 | 319 | ======================================================= 320 | ProceduralFairings v1.1 for KSP 0.20.2 (2013-07-10) 321 | ======================================================= 322 | 323 | • Fix for future FAR compatibility (needs fixed FAR version to actually work). 324 | • Less rotation on eject to reduce collisions with payload and lower stages. 325 | • Conic side fairings added, original ones are made a bit more capsule-shaped. 326 | 327 | ======================================================= 328 | ProceduralFairings v1.0 for KSP 0.20.2 (2013-07-09) 329 | ======================================================= 330 | 331 | • Initial release. 332 | -------------------------------------------------------------------------------- /GameData/ProceduralFairings/license.txt: -------------------------------------------------------------------------------- 1 | Attribution 4.0 International 2 | 3 | ======================================================================= 4 | 5 | Creative Commons Corporation ("Creative Commons") is not a law firm and 6 | does not provide legal services or legal advice. Distribution of 7 | Creative Commons public licenses does not create a lawyer-client or 8 | other relationship. Creative Commons makes its licenses and related 9 | information available on an "as-is" basis. Creative Commons gives no 10 | warranties regarding its licenses, any material licensed under their 11 | terms and conditions, or any related information. Creative Commons 12 | disclaims all liability for damages resulting from their use to the 13 | fullest extent possible. 14 | 15 | Using Creative Commons Public Licenses 16 | 17 | Creative Commons public licenses provide a standard set of terms and 18 | conditions that creators and other rights holders may use to share 19 | original works of authorship and other material subject to copyright 20 | and certain other rights specified in the public license below. The 21 | following considerations are for informational purposes only, are not 22 | exhaustive, and do not form part of our licenses. 23 | 24 | Considerations for licensors: Our public licenses are 25 | intended for use by those authorized to give the public 26 | permission to use material in ways otherwise restricted by 27 | copyright and certain other rights. Our licenses are 28 | irrevocable. Licensors should read and understand the terms 29 | and conditions of the license they choose before applying it. 30 | Licensors should also secure all rights necessary before 31 | applying our licenses so that the public can reuse the 32 | material as expected. Licensors should clearly mark any 33 | material not subject to the license. This includes other CC- 34 | licensed material, or material used under an exception or 35 | limitation to copyright. More considerations for licensors: 36 | wiki.creativecommons.org/Considerations_for_licensors 37 | 38 | Considerations for the public: By using one of our public 39 | licenses, a licensor grants the public permission to use the 40 | licensed material under specified terms and conditions. If 41 | the licensor's permission is not necessary for any reason--for 42 | example, because of any applicable exception or limitation to 43 | copyright--then that use is not regulated by the license. Our 44 | licenses grant only permissions under copyright and certain 45 | other rights that a licensor has authority to grant. Use of 46 | the licensed material may still be restricted for other 47 | reasons, including because others have copyright or other 48 | rights in the material. A licensor may make special requests, 49 | such as asking that all changes be marked or described. 50 | Although not required by our licenses, you are encouraged to 51 | respect those requests where reasonable. More_considerations 52 | for the public: 53 | wiki.creativecommons.org/Considerations_for_licensees 54 | 55 | ======================================================================= 56 | 57 | Creative Commons Attribution 4.0 International Public License 58 | 59 | By exercising the Licensed Rights (defined below), You accept and agree 60 | to be bound by the terms and conditions of this Creative Commons 61 | Attribution 4.0 International Public License ("Public License"). To the 62 | extent this Public License may be interpreted as a contract, You are 63 | granted the Licensed Rights in consideration of Your acceptance of 64 | these terms and conditions, and the Licensor grants You such rights in 65 | consideration of benefits the Licensor receives from making the 66 | Licensed Material available under these terms and conditions. 67 | 68 | 69 | Section 1 -- Definitions. 70 | 71 | a. Adapted Material means material subject to Copyright and Similar 72 | Rights that is derived from or based upon the Licensed Material 73 | and in which the Licensed Material is translated, altered, 74 | arranged, transformed, or otherwise modified in a manner requiring 75 | permission under the Copyright and Similar Rights held by the 76 | Licensor. For purposes of this Public License, where the Licensed 77 | Material is a musical work, performance, or sound recording, 78 | Adapted Material is always produced where the Licensed Material is 79 | synched in timed relation with a moving image. 80 | 81 | b. Adapter's License means the license You apply to Your Copyright 82 | and Similar Rights in Your contributions to Adapted Material in 83 | accordance with the terms and conditions of this Public License. 84 | 85 | c. Copyright and Similar Rights means copyright and/or similar rights 86 | closely related to copyright including, without limitation, 87 | performance, broadcast, sound recording, and Sui Generis Database 88 | Rights, without regard to how the rights are labeled or 89 | categorized. For purposes of this Public License, the rights 90 | specified in Section 2(b)(1)-(2) are not Copyright and Similar 91 | Rights. 92 | 93 | d. Effective Technological Measures means those measures that, in the 94 | absence of proper authority, may not be circumvented under laws 95 | fulfilling obligations under Article 11 of the WIPO Copyright 96 | Treaty adopted on December 20, 1996, and/or similar international 97 | agreements. 98 | 99 | e. Exceptions and Limitations means fair use, fair dealing, and/or 100 | any other exception or limitation to Copyright and Similar Rights 101 | that applies to Your use of the Licensed Material. 102 | 103 | f. Licensed Material means the artistic or literary work, database, 104 | or other material to which the Licensor applied this Public 105 | License. 106 | 107 | g. Licensed Rights means the rights granted to You subject to the 108 | terms and conditions of this Public License, which are limited to 109 | all Copyright and Similar Rights that apply to Your use of the 110 | Licensed Material and that the Licensor has authority to license. 111 | 112 | h. Licensor means the individual(s) or entity(ies) granting rights 113 | under this Public License. 114 | 115 | i. Share means to provide material to the public by any means or 116 | process that requires permission under the Licensed Rights, such 117 | as reproduction, public display, public performance, distribution, 118 | dissemination, communication, or importation, and to make material 119 | available to the public including in ways that members of the 120 | public may access the material from a place and at a time 121 | individually chosen by them. 122 | 123 | j. Sui Generis Database Rights means rights other than copyright 124 | resulting from Directive 96/9/EC of the European Parliament and of 125 | the Council of 11 March 1996 on the legal protection of databases, 126 | as amended and/or succeeded, as well as other essentially 127 | equivalent rights anywhere in the world. 128 | 129 | k. You means the individual or entity exercising the Licensed Rights 130 | under this Public License. Your has a corresponding meaning. 131 | 132 | 133 | Section 2 -- Scope. 134 | 135 | a. License grant. 136 | 137 | 1. Subject to the terms and conditions of this Public License, 138 | the Licensor hereby grants You a worldwide, royalty-free, 139 | non-sublicensable, non-exclusive, irrevocable license to 140 | exercise the Licensed Rights in the Licensed Material to: 141 | 142 | a. reproduce and Share the Licensed Material, in whole or 143 | in part; and 144 | 145 | b. produce, reproduce, and Share Adapted Material. 146 | 147 | 2. Exceptions and Limitations. For the avoidance of doubt, where 148 | Exceptions and Limitations apply to Your use, this Public 149 | License does not apply, and You do not need to comply with 150 | its terms and conditions. 151 | 152 | 3. Term. The term of this Public License is specified in Section 153 | 6(a). 154 | 155 | 4. Media and formats; technical modifications allowed. The 156 | Licensor authorizes You to exercise the Licensed Rights in 157 | all media and formats whether now known or hereafter created, 158 | and to make technical modifications necessary to do so. The 159 | Licensor waives and/or agrees not to assert any right or 160 | authority to forbid You from making technical modifications 161 | necessary to exercise the Licensed Rights, including 162 | technical modifications necessary to circumvent Effective 163 | Technological Measures. For purposes of this Public License, 164 | simply making modifications authorized by this Section 2(a) 165 | (4) never produces Adapted Material. 166 | 167 | 5. Downstream recipients. 168 | 169 | a. Offer from the Licensor -- Licensed Material. Every 170 | recipient of the Licensed Material automatically 171 | receives an offer from the Licensor to exercise the 172 | Licensed Rights under the terms and conditions of this 173 | Public License. 174 | 175 | b. No downstream restrictions. You may not offer or impose 176 | any additional or different terms or conditions on, or 177 | apply any Effective Technological Measures to, the 178 | Licensed Material if doing so restricts exercise of the 179 | Licensed Rights by any recipient of the Licensed 180 | Material. 181 | 182 | 6. No endorsement. Nothing in this Public License constitutes or 183 | may be construed as permission to assert or imply that You 184 | are, or that Your use of the Licensed Material is, connected 185 | with, or sponsored, endorsed, or granted official status by, 186 | the Licensor or others designated to receive attribution as 187 | provided in Section 3(a)(1)(A)(i). 188 | 189 | b. Other rights. 190 | 191 | 1. Moral rights, such as the right of integrity, are not 192 | licensed under this Public License, nor are publicity, 193 | privacy, and/or other similar personality rights; however, to 194 | the extent possible, the Licensor waives and/or agrees not to 195 | assert any such rights held by the Licensor to the limited 196 | extent necessary to allow You to exercise the Licensed 197 | Rights, but not otherwise. 198 | 199 | 2. Patent and trademark rights are not licensed under this 200 | Public License. 201 | 202 | 3. To the extent possible, the Licensor waives any right to 203 | collect royalties from You for the exercise of the Licensed 204 | Rights, whether directly or through a collecting society 205 | under any voluntary or waivable statutory or compulsory 206 | licensing scheme. In all other cases the Licensor expressly 207 | reserves any right to collect such royalties. 208 | 209 | 210 | Section 3 -- License Conditions. 211 | 212 | Your exercise of the Licensed Rights is expressly made subject to the 213 | following conditions. 214 | 215 | a. Attribution. 216 | 217 | 1. If You Share the Licensed Material (including in modified 218 | form), You must: 219 | 220 | a. retain the following if it is supplied by the Licensor 221 | with the Licensed Material: 222 | 223 | i. identification of the creator(s) of the Licensed 224 | Material and any others designated to receive 225 | attribution, in any reasonable manner requested by 226 | the Licensor (including by pseudonym if 227 | designated); 228 | 229 | ii. a copyright notice; 230 | 231 | iii. a notice that refers to this Public License; 232 | 233 | iv. a notice that refers to the disclaimer of 234 | warranties; 235 | 236 | v. a URI or hyperlink to the Licensed Material to the 237 | extent reasonably practicable; 238 | 239 | b. indicate if You modified the Licensed Material and 240 | retain an indication of any previous modifications; and 241 | 242 | c. indicate the Licensed Material is licensed under this 243 | Public License, and include the text of, or the URI or 244 | hyperlink to, this Public License. 245 | 246 | 2. You may satisfy the conditions in Section 3(a)(1) in any 247 | reasonable manner based on the medium, means, and context in 248 | which You Share the Licensed Material. For example, it may be 249 | reasonable to satisfy the conditions by providing a URI or 250 | hyperlink to a resource that includes the required 251 | information. 252 | 253 | 3. If requested by the Licensor, You must remove any of the 254 | information required by Section 3(a)(1)(A) to the extent 255 | reasonably practicable. 256 | 257 | 4. If You Share Adapted Material You produce, the Adapter's 258 | License You apply must not prevent recipients of the Adapted 259 | Material from complying with this Public License. 260 | 261 | 262 | Section 4 -- Sui Generis Database Rights. 263 | 264 | Where the Licensed Rights include Sui Generis Database Rights that 265 | apply to Your use of the Licensed Material: 266 | 267 | a. for the avoidance of doubt, Section 2(a)(1) grants You the right 268 | to extract, reuse, reproduce, and Share all or a substantial 269 | portion of the contents of the database; 270 | 271 | b. if You include all or a substantial portion of the database 272 | contents in a database in which You have Sui Generis Database 273 | Rights, then the database in which You have Sui Generis Database 274 | Rights (but not its individual contents) is Adapted Material; and 275 | 276 | c. You must comply with the conditions in Section 3(a) if You Share 277 | all or a substantial portion of the contents of the database. 278 | 279 | For the avoidance of doubt, this Section 4 supplements and does not 280 | replace Your obligations under this Public License where the Licensed 281 | Rights include other Copyright and Similar Rights. 282 | 283 | 284 | Section 5 -- Disclaimer of Warranties and Limitation of Liability. 285 | 286 | a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE 287 | EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS 288 | AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF 289 | ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, 290 | IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, 291 | WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR 292 | PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, 293 | ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT 294 | KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT 295 | ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. 296 | 297 | b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE 298 | TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, 299 | NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, 300 | INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, 301 | COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR 302 | USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN 303 | ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR 304 | DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR 305 | IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. 306 | 307 | c. The disclaimer of warranties and limitation of liability provided 308 | above shall be interpreted in a manner that, to the extent 309 | possible, most closely approximates an absolute disclaimer and 310 | waiver of all liability. 311 | 312 | 313 | Section 6 -- Term and Termination. 314 | 315 | a. This Public License applies for the term of the Copyright and 316 | Similar Rights licensed here. However, if You fail to comply with 317 | this Public License, then Your rights under this Public License 318 | terminate automatically. 319 | 320 | b. Where Your right to use the Licensed Material has terminated under 321 | Section 6(a), it reinstates: 322 | 323 | 1. automatically as of the date the violation is cured, provided 324 | it is cured within 30 days of Your discovery of the 325 | violation; or 326 | 327 | 2. upon express reinstatement by the Licensor. 328 | 329 | For the avoidance of doubt, this Section 6(b) does not affect any 330 | right the Licensor may have to seek remedies for Your violations 331 | of this Public License. 332 | 333 | c. For the avoidance of doubt, the Licensor may also offer the 334 | Licensed Material under separate terms or conditions or stop 335 | distributing the Licensed Material at any time; however, doing so 336 | will not terminate this Public License. 337 | 338 | d. Sections 1, 5, 6, 7, and 8 survive termination of this Public 339 | License. 340 | 341 | 342 | Section 7 -- Other Terms and Conditions. 343 | 344 | a. The Licensor shall not be bound by any additional or different 345 | terms or conditions communicated by You unless expressly agreed. 346 | 347 | b. Any arrangements, understandings, or agreements regarding the 348 | Licensed Material not stated herein are separate from and 349 | independent of the terms and conditions of this Public License. 350 | 351 | 352 | Section 8 -- Interpretation. 353 | 354 | a. For the avoidance of doubt, this Public License does not, and 355 | shall not be interpreted to, reduce, limit, restrict, or impose 356 | conditions on any use of the Licensed Material that could lawfully 357 | be made without permission under this Public License. 358 | 359 | b. To the extent possible, if any provision of this Public License is 360 | deemed unenforceable, it shall be automatically reformed to the 361 | minimum extent necessary to make it enforceable. If the provision 362 | cannot be reformed, it shall be severed from this Public License 363 | without affecting the enforceability of the remaining terms and 364 | conditions. 365 | 366 | c. No term or condition of this Public License will be waived and no 367 | failure to comply consented to unless expressly agreed to by the 368 | Licensor. 369 | 370 | d. Nothing in this Public License constitutes or may be interpreted 371 | as a limitation upon, or waiver of, any privileges and immunities 372 | that apply to the Licensor or You, including from the legal 373 | processes of any jurisdiction or authority. 374 | 375 | 376 | ======================================================================= 377 | 378 | Creative Commons is not a party to its public 379 | licenses. Notwithstanding, Creative Commons may elect to apply one of 380 | its public licenses to material it publishes and in those instances 381 | will be considered the “Licensor.” The text of the Creative Commons 382 | public licenses is dedicated to the public domain under the CC0 Public 383 | Domain Dedication. Except for the limited purpose of indicating that 384 | material is shared under a Creative Commons public license or as 385 | otherwise permitted by the Creative Commons policies published at 386 | creativecommons.org/policies, Creative Commons does not authorize the 387 | use of the trademark "Creative Commons" or any other trademark or logo 388 | of Creative Commons without its prior written consent including, 389 | without limitation, in connection with any unauthorized modifications 390 | to any of its public licenses or any other arrangements, 391 | understandings, or agreements concerning use of licensed material. For 392 | the avoidance of doubt, this paragraph does not form part of the 393 | public licenses. 394 | 395 | Creative Commons may be contacted at creativecommons.org. 396 | -------------------------------------------------------------------------------- /GameData/ProceduralFairings/readme.txt: -------------------------------------------------------------------------------- 1 | ================================================== 2 | Procedural Fairings 3 | ================================================== 4 | 5 | Procedural Fairings is a mod for Kerbal Space Program (KSP) that creates fairings that can automatically reshape for any attached payload. 6 | 7 | Original KSP forum thread: http://forum.kerbalspaceprogram.com/index.php?showtopic=36371 8 | 9 | Installation: 10 | 11 | Extract the contents of the ProceduralFairings .zip file and then drop the ProceduralFairings folder into the GameData folder. 12 | Note: if you are upgrading then make sure that any previous Procedural Fairings installation has been completely removed beforehand. 13 | 14 | Usage: 15 | 16 | 1. Put a fairing base under your payload (all Procedural Fairings parts are placed under the **Payload** tab) and enable the decoupler if necessary. 17 | 2. Attached fairings automatically reshape for your payload. 18 | 3. Enabling symmetry on fairings will encapsulate your payload 19 | 4. Rearrange the stages to jettison fairings at the proper stage. 20 | 21 | Notes: 22 | 23 | • All part tweakables are accessible via the right-click part action windows (diameter, length, shape, staging, textures etc). 24 | • Flipping another fairing base over and adding it above the payload will cause any side fairings to stick to it instead of creating a nose cone, thereby creating inline fairings between two bases. 25 | • Procedural Fairings includes low-profile base rings intended for inline fairings. Separate interstage bases are also included. 26 | • Procedural Fairings are fully integrated with the career mode. The minimum and maximum part sizes are limited by the available tech (see **PF_Settings.cfg** for more details). 27 | 28 | Credits: 29 | 30 | • e-dog for creating the Procedural Fairings mod: https://github.com/e-dog 31 | • rsparkyc for maintaining it the absence of e-dog: https://github.com/rsparkyc 32 | 33 | License: 34 | 35 | Procedural Fairings is licensed under a Creative Commons Attribution 4.0 (CC-BY 4.0) license. 36 | 37 | You should have received a copy of the license along with this work. If not, visit the official Creative Commons web page: https://creativecommons.org/licenses/by/4.0/legalcode 38 | 39 | Note that the above license does not cover mod packs. Redistributing this work via a mod pack is not allowed. 40 | -------------------------------------------------------------------------------- /Misc/baseRingTex.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsparkyc/ProceduralFairings/fbbefcd1545e8cd904c1ed102856d7fe60de50c0/Misc/baseRingTex.psd -------------------------------------------------------------------------------- /Misc/baseTex.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsparkyc/ProceduralFairings/fbbefcd1545e8cd904c1ed102856d7fe60de50c0/Misc/baseTex.psd -------------------------------------------------------------------------------- /Misc/fairing1.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsparkyc/ProceduralFairings/fbbefcd1545e8cd904c1ed102856d7fe60de50c0/Misc/fairing1.psd -------------------------------------------------------------------------------- /Misc/fuselage1.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsparkyc/ProceduralFairings/fbbefcd1545e8cd904c1ed102856d7fe60de50c0/Misc/fuselage1.psd -------------------------------------------------------------------------------- /Misc/thrustPlate1.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsparkyc/ProceduralFairings/fbbefcd1545e8cd904c1ed102856d7fe60de50c0/Misc/thrustPlate1.psd -------------------------------------------------------------------------------- /Misc/thrustPlate1bump.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsparkyc/ProceduralFairings/fbbefcd1545e8cd904c1ed102856d7fe60de50c0/Misc/thrustPlate1bump.psd -------------------------------------------------------------------------------- /Source/ProceduralFairings.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2012 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProceduralFairings", "ProceduralFairings\ProceduralFairings.csproj", "{51CE67F2-5981-4AD2-97E8-0E2B44792AB2}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Any CPU = Debug|Any CPU 9 | Release|Any CPU = Release|Any CPU 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {51CE67F2-5981-4AD2-97E8-0E2B44792AB2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 13 | {51CE67F2-5981-4AD2-97E8-0E2B44792AB2}.Debug|Any CPU.Build.0 = Debug|Any CPU 14 | {51CE67F2-5981-4AD2-97E8-0E2B44792AB2}.Release|Any CPU.ActiveCfg = Release|Any CPU 15 | {51CE67F2-5981-4AD2-97E8-0E2B44792AB2}.Release|Any CPU.Build.0 = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(MonoDevelopProperties) = preSolution 18 | BaseDirectory = .. 19 | outputpath = References 20 | Policies = $0 21 | $0.DotNetNamingPolicy = $1 22 | $1.DirectoryNamespaceAssociation = None 23 | $1.ResourceNamePolicy = FileFormatDefault 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /Source/ProceduralFairings/FairingDecoupler.cs: -------------------------------------------------------------------------------- 1 | // ================================================== 2 | // Procedural Fairings plug-in by Alexey Volynskov. 3 | 4 | // Licensed under CC-BY-4.0 terms: https://creativecommons.org/licenses/by/4.0/legalcode 5 | // ================================================== 6 | 7 | using KSP.UI.Screens; 8 | using System; 9 | using UnityEngine; 10 | 11 | namespace Keramzit 12 | { 13 | public class ProceduralFairingDecoupler : PartModule 14 | { 15 | [KSPField] public float ejectionDv = 15; 16 | [KSPField] public float ejectionTorque = 10; 17 | [KSPField] public float ejectionLowDv; 18 | [KSPField] public float ejectionLowTorque; 19 | 20 | [KSPField (isPersistant = true)] bool decoupled; 21 | 22 | bool didForce; 23 | 24 | bool decouplerStagingSet = true; 25 | 26 | [KSPField] public string ejectSoundUrl = "Squad/Sounds/sound_decoupler_fire"; 27 | public FXGroup ejectFx; 28 | 29 | [KSPField] public string transformName = "nose_collider"; 30 | [KSPField] public Vector3 forceVector = Vector3.right; 31 | [KSPField] public Vector3 torqueVector = -Vector3.forward; 32 | 33 | [KSPField (isPersistant = true, guiActiveEditor = true, guiName = "Ejection power")] 34 | [UI_FloatRange (minValue = 0, maxValue = 1, stepIncrement = 0.01f)] 35 | public float ejectionPower = 0.32f; 36 | 37 | [KSPField (isPersistant = true, guiActiveEditor = true, guiName = "Ejection torque")] 38 | [UI_FloatRange (minValue = 0, maxValue = 1, stepIncrement = 0.01f)] 39 | public float torqueAmount = 0.01f; 40 | 41 | [KSPField (isPersistant = true, guiActiveEditor = true, guiName = "Fairing Decoupler")] 42 | [UI_Toggle (disabledText = "Off", enabledText = "On", affectSymCounterparts = UI_Scene.All)] 43 | public bool fairingStaged = true; 44 | 45 | [KSPAction ("Jettison Fairing", actionGroup = KSPActionGroup.None)] 46 | public void ActionJettison (KSPActionParam param) 47 | { 48 | OnJettisonFairing (); 49 | } 50 | 51 | public void FixedUpdate () 52 | { 53 | // More hacky-hacky: for some reason the staging icons cannot be updated correctly 54 | // via the OnStart () method but require an additional update here. This snippet 55 | // sets the staging icon states one more time after transitioning a scene. 56 | 57 | if (HighLogic.LoadedSceneIsFlight || HighLogic.LoadedSceneIsEditor) 58 | { 59 | if (decouplerStagingSet) 60 | { 61 | OnSetStagingIcons (); 62 | 63 | decouplerStagingSet = false; 64 | } 65 | } 66 | 67 | if (decoupled) 68 | { 69 | if (part.parent) 70 | { 71 | var pfa = part.parent.GetComponent(); 72 | 73 | for (int i = 0; i < part.parent.children.Count; i++) 74 | { 75 | var p = part.parent.children [i]; 76 | 77 | // Check if the top node allows decoupling when the fairing is also decoupled. 78 | 79 | if (pfa) 80 | { 81 | if (!pfa.topNodeDecouplesWhenFairingsGone) 82 | { 83 | var isFairing = p.GetComponent(); 84 | 85 | if (!isFairing) 86 | { 87 | continue; 88 | } 89 | } 90 | } 91 | 92 | var joints = p.GetComponents(); 93 | 94 | for (int j = 0; j < joints.Length; j++) 95 | { 96 | var joint = joints [j]; 97 | 98 | if (joint != null && (joint.GetComponent() == part.Rigidbody || joint.connectedBody == part.Rigidbody)) 99 | { 100 | Destroy (joint); 101 | } 102 | } 103 | } 104 | 105 | part.decouple (0); 106 | 107 | ejectFx.audio.Play (); 108 | } 109 | else if (!didForce) 110 | { 111 | var tr = part.FindModelTransform (transformName); 112 | 113 | if (tr) 114 | { 115 | part.Rigidbody.AddForce (tr.TransformDirection (forceVector) * Mathf.Lerp (ejectionLowDv, ejectionDv, ejectionPower), ForceMode.VelocityChange); 116 | part.Rigidbody.AddTorque (tr.TransformDirection (torqueVector) * Mathf.Lerp (ejectionLowTorque, ejectionTorque, torqueAmount), ForceMode.VelocityChange); 117 | } 118 | else 119 | { 120 | Debug.LogError ("[PF]: No '" + transformName + "' transform in part!", part); 121 | } 122 | 123 | didForce = true; 124 | decoupled = false; 125 | } 126 | } 127 | } 128 | 129 | public override void OnActive () 130 | { 131 | OnJettisonFairing (); 132 | } 133 | 134 | [KSPEvent (name = "Jettison", active = true, guiActive = true, guiActiveUnfocused = false, guiName = "Jettison Fairing")] 135 | public void OnJettisonFairing () 136 | { 137 | decoupled |= fairingStaged; 138 | } 139 | 140 | public override void OnLoad (ConfigNode node) 141 | { 142 | base.OnLoad (node); 143 | 144 | didForce = decoupled; 145 | } 146 | 147 | public void OnSetStagingIcons () 148 | { 149 | // Set the staging icon for the parent part. 150 | 151 | if (fairingStaged) 152 | { 153 | part.stackIcon.CreateIcon (); 154 | } 155 | else 156 | { 157 | part.stackIcon.RemoveIcon (); 158 | } 159 | 160 | // Hacky, hacky? Five dollars... 161 | 162 | foreach (Part FairingSide in part.symmetryCounterparts) 163 | { 164 | if (fairingStaged) 165 | { 166 | FairingSide.stackIcon.CreateIcon (); 167 | } 168 | else 169 | { 170 | FairingSide.stackIcon.RemoveIcon (); 171 | } 172 | } 173 | 174 | // Reorder the staging icons. 175 | 176 | StageManager.Instance.SortIcons (true); 177 | } 178 | 179 | public override void OnStart (StartState state) 180 | { 181 | if (state == StartState.None) 182 | { 183 | return; 184 | } 185 | 186 | if (state == StartState.Editor) 187 | { 188 | // Set up the GUI editor update callback. 189 | 190 | ((UI_Toggle) Fields["fairingStaged"].uiControlEditor).onFieldChanged += OnUpdateUI; 191 | } 192 | 193 | ejectFx.audio = part.gameObject.AddComponent(); 194 | ejectFx.audio.volume = GameSettings.SHIP_VOLUME; 195 | ejectFx.audio.rolloffMode = AudioRolloffMode.Logarithmic; 196 | ejectFx.audio.maxDistance = 100; 197 | ejectFx.audio.loop = false; 198 | ejectFx.audio.playOnAwake = false; 199 | ejectFx.audio.dopplerLevel = 0f; 200 | ejectFx.audio.spatialBlend = 1.0f; 201 | ejectFx.audio.panStereo = 0f; 202 | 203 | if (GameDatabase.Instance.ExistsAudioClip (ejectSoundUrl)) 204 | { 205 | ejectFx.audio.clip = GameDatabase.Instance.GetAudioClip (ejectSoundUrl); 206 | } 207 | else 208 | { 209 | Debug.LogError ("[PF]: Cannot find decoupler sound: " + ejectSoundUrl, this); 210 | } 211 | 212 | // Set the state of the "Jettison Fairing" PAW button. 213 | 214 | Events["OnJettisonFairing"].guiActive = fairingStaged; 215 | 216 | // Update the staging icon sequence. 217 | 218 | OnSetStagingIcons (); 219 | } 220 | 221 | void OnUpdateUI (BaseField bf, object obj) 222 | { 223 | // Update the staging icon sequence. 224 | 225 | OnSetStagingIcons (); 226 | } 227 | } 228 | } 229 | -------------------------------------------------------------------------------- /Source/ProceduralFairings/FairingShielding.cs: -------------------------------------------------------------------------------- 1 | // ================================================== 2 | // Procedural Fairings plug-in by Alexey Volynskov. 3 | 4 | // Licensed under CC-BY-4.0 terms: https://creativecommons.org/licenses/by/4.0/legalcode 5 | // ================================================== 6 | 7 | using System; 8 | using System.Collections.Generic; 9 | using UnityEngine; 10 | 11 | namespace Keramzit 12 | { 13 | public class KzFairingBaseShielding : PartModule, IAirstreamShield 14 | { 15 | List shieldedParts; 16 | 17 | ProceduralFairingSide sideFairing; 18 | 19 | float boundCylY0, boundCylY1, boundCylRad; 20 | float lookupRad; 21 | 22 | Vector3 lookupCenter; 23 | Vector3 [] shape; 24 | 25 | [KSPField (isPersistant = false, guiActive = true, guiActiveEditor = true, guiName = "Parts shielded")] 26 | public int numShieldedDisplay; 27 | 28 | bool needReset; 29 | 30 | public bool ClosedAndLocked () { return true; } 31 | public Vessel GetVessel () { return vessel; } 32 | public Part GetPart () { return part; } 33 | 34 | public override void OnAwake () 35 | { 36 | shieldedParts = new List(); 37 | } 38 | 39 | public override void OnStart (StartState state) 40 | { 41 | if (!HighLogic.LoadedSceneIsEditor && !HighLogic.LoadedSceneIsFlight) 42 | { 43 | return; 44 | } 45 | 46 | reset (); 47 | 48 | GameEvents.onVesselWasModified.Add (new EventData.OnEvent (onVesselModified)); 49 | GameEvents.onVesselGoOffRails.Add (new EventData.OnEvent (onVesselUnpack)); 50 | GameEvents.onPartDie.Add (new EventData.OnEvent (OnPartDestroyed)); 51 | } 52 | 53 | void OnDestroy () 54 | { 55 | GameEvents.onVesselWasModified.Remove (new EventData.OnEvent (onVesselModified)); 56 | GameEvents.onVesselGoOffRails.Remove (new EventData.OnEvent (onVesselUnpack)); 57 | GameEvents.onPartDie.Remove (new EventData.OnEvent (OnPartDestroyed)); 58 | } 59 | 60 | public void FixedUpdate () 61 | { 62 | if (needReset) 63 | { 64 | needReset = false; 65 | 66 | getFairingParams (); 67 | 68 | bool shield = (HighLogic.LoadedSceneIsEditor || (HighLogic.LoadedSceneIsFlight && !vessel.packed)); 69 | 70 | if (shield) 71 | { 72 | enableShielding (); 73 | } 74 | } 75 | } 76 | 77 | public void reset () 78 | { 79 | needReset = true; 80 | } 81 | 82 | AttachNode [] getFairingParams () 83 | { 84 | var nnt = part.GetComponent(); 85 | 86 | // Check for attached side parts and get their parameters. 87 | 88 | var attached = part.FindAttachNodes ("connect"); 89 | 90 | ProceduralFairingSide sf = null; 91 | 92 | for (int i = 0; i < nnt.numNodes; ++i) 93 | { 94 | var n = attached [i]; 95 | 96 | if (!n.attachedPart) 97 | { 98 | sf = null; 99 | 100 | break; 101 | } 102 | 103 | sf = n.attachedPart.GetComponent(); 104 | 105 | if (!sf) 106 | { 107 | break; 108 | } 109 | } 110 | 111 | sideFairing = sf; 112 | 113 | if (!sf) 114 | { 115 | shape = null; 116 | boundCylY0 = boundCylY1 = boundCylRad = 0; 117 | lookupCenter = Vector3.zero; 118 | lookupRad = 0; 119 | 120 | return null; 121 | } 122 | 123 | // Get the polyline shape. 124 | 125 | if (sf.inlineHeight <= 0) 126 | { 127 | shape = ProceduralFairingBase.buildFairingShape (sf.baseRad, sf.maxRad, sf.cylStart, sf.cylEnd, sf.noseHeightRatio, sf.baseConeShape, sf.noseConeShape, (int) sf.baseConeSegments, (int) sf.noseConeSegments, sf.vertMapping, sf.mappingScale.y); 128 | } 129 | else 130 | { 131 | shape = ProceduralFairingBase.buildInlineFairingShape (sf.baseRad, sf.maxRad, sf.topRad, sf.cylStart, sf.cylEnd, sf.inlineHeight, sf.baseConeShape, (int) sf.baseConeSegments, sf.vertMapping, sf.mappingScale.y); 132 | } 133 | 134 | // Offset shape by thickness. 135 | 136 | for (int i = 0; i < shape.Length; ++i) 137 | { 138 | if (i == 0 || i == shape.Length - 1) 139 | { 140 | shape [i] += new Vector3 (sf.sideThickness, 0, 0); 141 | } 142 | else 143 | { 144 | Vector2 n = shape [i + 1] - shape [i - 1]; 145 | 146 | n.Set (n.y, -n.x); 147 | 148 | n.Normalize (); 149 | 150 | shape [i] += new Vector3 (n.x, n.y, 0) * sf.sideThickness; 151 | } 152 | } 153 | 154 | // Compute the bounds. 155 | 156 | float y0, y1, mr; 157 | 158 | y0 = y1 = shape [0].y; 159 | mr = shape [0].x; 160 | 161 | for (int i = 0; i < shape.Length; ++i) 162 | { 163 | var p = shape [i]; 164 | 165 | if (p.x > mr) 166 | { 167 | mr = p.x; 168 | } 169 | 170 | if (p.y < y0) 171 | { 172 | y0 = p.y; 173 | } 174 | else if (p.y > y1) 175 | { 176 | y1 = p.y; 177 | } 178 | } 179 | 180 | boundCylY0 = y0; 181 | boundCylY1 = y1; 182 | boundCylRad = mr; 183 | 184 | lookupCenter = new Vector3 (0, (y0 + y1) * 0.5f, 0); 185 | lookupRad = new Vector2 (mr, (y1 - y0) * 0.5f).magnitude; 186 | 187 | return attached; 188 | } 189 | 190 | void enableShielding () 191 | { 192 | disableShielding (); 193 | 194 | var attached = getFairingParams (); 195 | 196 | if (!sideFairing) 197 | { 198 | return; 199 | } 200 | 201 | // Get all parts in range. 202 | 203 | var parts = new List(); 204 | 205 | var colliders = Physics.OverlapSphere (part.transform.TransformPoint (lookupCenter), lookupRad, 1); 206 | 207 | for (int i = colliders.Length - 1; i >= 0; --i) 208 | { 209 | var p = colliders [i].gameObject.GetComponentUpwards(); 210 | 211 | if (p != null) 212 | { 213 | parts.AddUnique (p); 214 | } 215 | } 216 | 217 | // Filter parts. 218 | 219 | float sizeSqr = lookupRad * lookupRad * 4; 220 | float boundCylRadSq = boundCylRad * boundCylRad; 221 | 222 | bool isInline = (sideFairing.inlineHeight > 0); 223 | bool topClosed = false; 224 | 225 | Matrix4x4 w2l = Matrix4x4.identity, w2lb = Matrix4x4.identity; 226 | 227 | Bounds topBounds = default (Bounds); 228 | 229 | if (isInline) 230 | { 231 | w2l = part.transform.worldToLocalMatrix; 232 | w2lb = w2l; 233 | 234 | for (int i = 0; i < 3; ++i) 235 | { 236 | for (int j = 0; j < 3; ++j) 237 | { 238 | w2lb [i, j] = Mathf.Abs (w2lb [i, j]); 239 | } 240 | } 241 | 242 | topBounds = new Bounds (new Vector3 (0, boundCylY1, 0), new Vector3 (sideFairing.topRad * 2, sideFairing.sideThickness, sideFairing.topRad * 2)); 243 | } 244 | 245 | for (int pi = 0; pi < parts.Count; ++pi) 246 | { 247 | var pt = parts [pi]; 248 | 249 | // Check special cases. 250 | 251 | if (pt == part) 252 | { 253 | shieldedParts.Add (pt); 254 | 255 | continue; 256 | } 257 | 258 | bool isSide = false; 259 | 260 | for (int i = 0; i < attached.Length; ++i) 261 | { 262 | if (attached [i].attachedPart == pt) 263 | { 264 | isSide = true; 265 | 266 | break; 267 | } 268 | } 269 | 270 | if (isSide) 271 | { 272 | continue; 273 | } 274 | 275 | // Check if the top is closed in the inline case. 276 | 277 | var bounds = pt.GetRendererBounds (); 278 | 279 | var box = PartGeometryUtil.MergeBounds (bounds, pt.transform); 280 | 281 | if (isInline && !topClosed && pt.vessel == vessel) 282 | { 283 | var wb = box; wb.Expand (sideFairing.sideThickness * 4); 284 | 285 | var b = new Bounds (w2l.MultiplyPoint3x4 (wb.center), w2lb.MultiplyVector (wb.size)); 286 | 287 | if (b.Contains (topBounds.min) && b.Contains (topBounds.max)) 288 | { 289 | topClosed = true; 290 | } 291 | } 292 | 293 | // Check if the centroid is within the fairing bounds. 294 | 295 | var c = part.transform.InverseTransformPoint (PartGeometryUtil.FindBoundsCentroid (bounds, null)); 296 | 297 | float y = c.y; 298 | 299 | if (y < boundCylY0 || y > boundCylY1) 300 | { 301 | continue; 302 | } 303 | 304 | float xsq = new Vector2 (c.x, c.z).sqrMagnitude; 305 | 306 | if (xsq > boundCylRadSq) 307 | { 308 | continue; 309 | } 310 | 311 | // Accurate centroid check. 312 | 313 | float x = Mathf.Sqrt (xsq); 314 | 315 | bool inside = false; 316 | 317 | for (int i = 1; i < shape.Length; ++i) 318 | { 319 | var p0 = shape [i - 1]; 320 | var p1 = shape [i]; 321 | 322 | if (p0.y > p1.y) 323 | { 324 | var p = p0; 325 | 326 | p0 = p1; 327 | p1 = p; 328 | } 329 | 330 | if (y < p0.y || y > p1.y) 331 | { 332 | continue; 333 | } 334 | 335 | float dy = p1.y - p0.y, r; 336 | 337 | if (dy <= 1e-6f) 338 | { 339 | r = (p0.x + p1.x) * 0.5f; 340 | } 341 | else 342 | { 343 | r = (p1.x - p0.x) * (y - p0.y) / dy + p0.x; 344 | } 345 | 346 | if (x > r) 347 | { 348 | continue; 349 | } 350 | 351 | inside = true; 352 | 353 | break; 354 | } 355 | 356 | if (!inside) 357 | { 358 | continue; 359 | } 360 | 361 | shieldedParts.Add (pt); 362 | } 363 | 364 | if (isInline && !topClosed) 365 | { 366 | disableShielding (); 367 | 368 | return; 369 | } 370 | 371 | // Add shielding. 372 | 373 | for (int i = 0; i < shieldedParts.Count; ++i) 374 | { 375 | shieldedParts [i].AddShield (this); 376 | } 377 | 378 | numShieldedDisplay = shieldedParts.Count; 379 | 380 | var fbase = part.GetComponent(); 381 | 382 | if (fbase != null) 383 | { 384 | fbase.onShieldingEnabled (shieldedParts); 385 | } 386 | } 387 | 388 | void disableShielding () 389 | { 390 | if (shieldedParts != null) 391 | { 392 | var fbase = part.GetComponent(); 393 | 394 | if (fbase != null) 395 | { 396 | fbase.onShieldingDisabled (shieldedParts); 397 | } 398 | 399 | for (int i = shieldedParts.Count - 1; i >= 0; --i) 400 | { 401 | if (shieldedParts [i] != null) 402 | { 403 | shieldedParts [i].RemoveShield (this); 404 | } 405 | } 406 | 407 | shieldedParts.Clear (); 408 | } 409 | 410 | numShieldedDisplay = 0; 411 | } 412 | 413 | void onVesselModified (Vessel v) 414 | { 415 | if (v != vessel) 416 | { 417 | var dp = v.vesselTransform.position - part.transform.TransformPoint (lookupCenter); 418 | 419 | if (dp.sqrMagnitude > lookupRad * lookupRad) 420 | { 421 | return; 422 | } 423 | } 424 | 425 | enableShielding (); 426 | } 427 | 428 | void onVesselUnpack (Vessel v) 429 | { 430 | if (v == vessel) 431 | { 432 | enableShielding (); 433 | } 434 | } 435 | 436 | void onVesselPack (Vessel v) 437 | { 438 | if (v == vessel) 439 | { 440 | disableShielding (); 441 | } 442 | } 443 | 444 | void OnPartDestroyed (Part p) 445 | { 446 | var nnt = part.GetComponent(); 447 | 448 | if (p == part) 449 | { 450 | disableShielding (); 451 | 452 | return; 453 | } 454 | 455 | // Check for attached side fairing parts. 456 | 457 | var attached = part.FindAttachNodes ("connect"); 458 | 459 | for (int i = 0; i < nnt.numNodes; ++i) 460 | { 461 | if (p == attached [i].attachedPart) 462 | { 463 | disableShielding (); 464 | 465 | return; 466 | } 467 | } 468 | 469 | // Check for top parts in the inline/adapter case. 470 | 471 | if (p.vessel == vessel && sideFairing && sideFairing.inlineHeight > 0) 472 | { 473 | enableShielding (); 474 | } 475 | } 476 | 477 | public void OnPartPack () 478 | { 479 | disableShielding (); 480 | } 481 | } 482 | } 483 | -------------------------------------------------------------------------------- /Source/ProceduralFairings/NodeNumberTweaker.cs: -------------------------------------------------------------------------------- 1 | // ================================================== 2 | // Procedural Fairings plug-in by Alexey Volynskov. 3 | 4 | // Licensed under CC-BY-4.0 terms: https://creativecommons.org/licenses/by/4.0/legalcode 5 | // ================================================== 6 | 7 | using System; 8 | using UnityEngine; 9 | 10 | namespace Keramzit 11 | { 12 | public class KzNodeNumberTweaker : PartModule 13 | { 14 | [KSPField] public string nodePrefix = "bottom"; 15 | [KSPField] public int maxNumber; 16 | 17 | [KSPField (guiActiveEditor = true, guiName = "Fairing Nodes")] 18 | [UI_FloatRange (minValue = 1, maxValue = 8, stepIncrement = 1)] 19 | public float uiNumNodes = 2; 20 | 21 | [KSPField (isPersistant = true)] 22 | public int numNodes = 2; 23 | 24 | int numNodesBefore; 25 | 26 | [KSPField (isPersistant = true, guiActiveEditor = true, guiName = "Node offset", guiFormat = "S4", guiUnits = "m")] 27 | [UI_FloatEdit (sigFigs = 3, unit = "m", minValue = 0.1f, maxValue = 5, incrementLarge = 0.625f, incrementSmall = 0.125f, incrementSlide = 0.001f)] 28 | public float radius = 1.25f; 29 | 30 | [KSPField] public float radiusStepLarge = 0.625f; 31 | [KSPField] public float radiusStepSmall = 0.125f; 32 | 33 | [KSPField] public bool shouldResizeNodes = true; 34 | 35 | protected float oldRadius = -1000; 36 | protected bool justLoaded; 37 | 38 | public override string GetInfo () 39 | { 40 | return "Max. Nodes: " + maxNumber; 41 | } 42 | 43 | [KSPField (isPersistant = true, guiActiveEditor = true, guiName = "Interstage Nodes")] 44 | [UI_Toggle (disabledText = "Off", enabledText = "On")] 45 | public bool showInterstageNodes = true; 46 | 47 | public virtual void FixedUpdate () 48 | { 49 | if (!radius.Equals (oldRadius)) 50 | { 51 | oldRadius = radius; 52 | 53 | updateNodePositions (); 54 | } 55 | 56 | justLoaded = false; 57 | } 58 | 59 | public void Update () 60 | { 61 | if (HighLogic.LoadedSceneIsEditor) 62 | { 63 | if ((int) uiNumNodes != numNodesBefore) 64 | { 65 | if (checkNodeAttachments ()) 66 | { 67 | uiNumNodes = numNodesBefore; 68 | } 69 | else 70 | { 71 | numNodes = (int) uiNumNodes; 72 | numNodesBefore = numNodes; 73 | 74 | updateNodes (); 75 | 76 | bool removed = false; 77 | 78 | for (int i = numNodes + 1; i <= maxNumber; ++i) 79 | { 80 | var node = findNode (i); 81 | 82 | if (node == null) 83 | { 84 | continue; 85 | } 86 | 87 | // Fix for ghost node when inserting a new PF base in 88 | // the editor scene: do not delete unused nodes, move 89 | // them away instead. Be careful to check references 90 | // of the maximum number of nodes, mentioned elsewhere 91 | // and retrieved via 'Findattachnodes("connect")'! 92 | // Slightly hacky, but it works... 93 | 94 | HideUnusedNode (node); 95 | 96 | removed = true; 97 | } 98 | 99 | if (removed) 100 | { 101 | var fbase = part.GetComponent(); 102 | 103 | if (fbase) 104 | { 105 | fbase.needShapeUpdate = true; 106 | fbase.updateDelay = 0.5f; 107 | } 108 | } 109 | } 110 | } 111 | } 112 | } 113 | 114 | // Slightly hacky...but it removes the ghost nodes. 115 | 116 | void HideUnusedNode (AttachNode node) 117 | { 118 | node.position.x = 10000; 119 | } 120 | 121 | public override void OnStart (StartState state) 122 | { 123 | base.OnStart (state); 124 | 125 | if (state == StartState.None) 126 | { 127 | return; 128 | } 129 | 130 | ((UI_FloatEdit) Fields["radius"].uiControlEditor).incrementLarge = radiusStepLarge; 131 | ((UI_FloatEdit) Fields["radius"].uiControlEditor).incrementSmall = radiusStepSmall; 132 | 133 | Fields["radius"].guiActiveEditor = shouldResizeNodes; 134 | 135 | // Hide the interstage toggle button if there are no interstage nodes. 136 | 137 | var nodes = part.FindAttachNodes ("interstage"); 138 | 139 | if (nodes == null) 140 | { 141 | Fields["showInterstageNodes"].guiActiveEditor = false; 142 | } 143 | 144 | // Change the GUI text if there are no fairing attachment nodes. 145 | 146 | nodes = part.FindAttachNodes ("connect"); 147 | 148 | if (nodes == null) 149 | { 150 | Fields["uiNumNodes"].guiName = "Side Nodes"; 151 | } 152 | 153 | ((UI_FloatRange) Fields["uiNumNodes"].uiControlEditor).maxValue = maxNumber; 154 | 155 | uiNumNodes = numNodes; 156 | numNodesBefore = numNodes; 157 | 158 | updateNodes (); 159 | } 160 | 161 | public override void OnLoad (ConfigNode cfg) 162 | { 163 | base.OnLoad (cfg); 164 | 165 | justLoaded = true; 166 | 167 | uiNumNodes = numNodes; 168 | numNodesBefore = numNodes; 169 | 170 | if (HighLogic.LoadedSceneIsEditor || HighLogic.LoadedSceneIsFlight) 171 | { 172 | updateNodes (); 173 | } 174 | } 175 | 176 | void updateNodes () 177 | { 178 | addRemoveNodes (); 179 | 180 | updateNodePositions (); 181 | } 182 | 183 | string nodeName (int i) 184 | { 185 | return string.Format ("{0}{1:d2}", nodePrefix, i); 186 | } 187 | 188 | AttachNode findNode (int i) 189 | { 190 | return part.FindAttachNode (nodeName (i)); 191 | } 192 | 193 | bool checkNodeAttachments() 194 | { 195 | for (int i = 1; i <= maxNumber; ++i) 196 | { 197 | var node = findNode (i); 198 | 199 | if (node != null && node.attachedPart != null) 200 | { 201 | EditorScreenMessager.showMessage ("Please detach any fairing parts before changing the number of nodes!", 1); 202 | 203 | return true; 204 | } 205 | } 206 | 207 | return false; 208 | } 209 | 210 | void addRemoveNodes () 211 | { 212 | part.stackSymmetry = numNodes - 1; 213 | 214 | float y = 0; 215 | 216 | bool gotY = false; 217 | 218 | int nodeSize = 0; 219 | 220 | Vector3 dir = Vector3.up; 221 | 222 | int i; 223 | 224 | for (i = 1; i <= maxNumber; ++i) 225 | { 226 | var node = findNode (i); 227 | 228 | if (node == null) 229 | { 230 | continue; 231 | } 232 | 233 | y = node.position.y; 234 | nodeSize = node.size; 235 | dir = node.orientation; 236 | 237 | gotY = true; 238 | 239 | break; 240 | } 241 | 242 | if (!gotY) 243 | { 244 | var node = part.FindAttachNode ("bottom"); 245 | 246 | if (node != null) 247 | { 248 | y = node.position.y; 249 | } 250 | } 251 | 252 | for (i = 1; i <= numNodes; ++i) 253 | { 254 | var node = findNode (i); 255 | 256 | if (node != null) 257 | { 258 | continue; 259 | } 260 | 261 | // Create the fairing attachment node. 262 | 263 | node = new AttachNode (); 264 | 265 | node.id = nodeName (i); 266 | node.owner = part; 267 | node.nodeType = AttachNode.NodeType.Stack; 268 | node.position = new Vector3 (0, y, 0); 269 | node.orientation = dir; 270 | node.originalPosition = node.position; 271 | node.originalOrientation = node.orientation; 272 | node.size = nodeSize; 273 | 274 | part.attachNodes.Add (node); 275 | } 276 | 277 | for (; i <= maxNumber; ++i) 278 | { 279 | var node = findNode (i); 280 | 281 | if (node == null) 282 | { 283 | continue; 284 | } 285 | 286 | if (HighLogic.LoadedSceneIsEditor) 287 | { 288 | node.position.x = 10000; 289 | } 290 | else 291 | { 292 | part.attachNodes.Remove (node); 293 | } 294 | } 295 | 296 | var fbase = part.GetComponent(); 297 | 298 | if (fbase) 299 | { 300 | fbase.needShapeUpdate = true; 301 | } 302 | } 303 | 304 | void updateNodePositions () 305 | { 306 | float d = Mathf.Sin (Mathf.PI / numNodes) * radius * 2; 307 | 308 | int size = Mathf.RoundToInt (d / (radiusStepLarge * 2)); 309 | 310 | for (int i = 1; i <= numNodes; ++i) 311 | { 312 | var node = findNode (i); 313 | 314 | if (node == null) 315 | { 316 | continue; 317 | } 318 | 319 | float a = Mathf.PI * 2 * (i - 1) / numNodes; 320 | 321 | node.position.x = Mathf.Cos (a) * radius; 322 | node.position.z = Mathf.Sin (a) * radius; 323 | 324 | if (shouldResizeNodes) 325 | { 326 | node.size = size; 327 | } 328 | 329 | if (!justLoaded) 330 | { 331 | PFUtils.updateAttachedPartPos (node, part); 332 | } 333 | } 334 | 335 | for (int i = numNodes + 1; i <= maxNumber; ++i) 336 | { 337 | var node = findNode (i); 338 | 339 | if (node == null) 340 | { 341 | continue; 342 | } 343 | 344 | node.position.x = 10000; 345 | } 346 | } 347 | } 348 | } 349 | -------------------------------------------------------------------------------- /Source/ProceduralFairings/PFKMJoint.cs: -------------------------------------------------------------------------------- 1 | // ================================================== 2 | // Procedural Fairings plug-in by Alexey Volynskov. 3 | 4 | // Licensed under CC-BY-4.0 terms: https://creativecommons.org/licenses/by/4.0/legalcode 5 | // ================================================== 6 | 7 | using System; 8 | using System.Collections.Generic; 9 | using UnityEngine; 10 | 11 | namespace Keramzit 12 | { 13 | public class PFKMJoints : PartModule 14 | { 15 | [KSPField (isPersistant = true)] 16 | public float breakingForce = 500000f; 17 | 18 | [KSPField (guiActive = true, guiName = "View Joints")] 19 | [UI_Toggle (disabledText = "Off", enabledText = "On")] 20 | public bool viewJoints; 21 | 22 | const float w1 = 0.05f; 23 | const float w2 = 0.15f; 24 | 25 | readonly List jointLines = new List(); 26 | 27 | bool morejointsadded; 28 | 29 | Part bottomNodePart; 30 | 31 | List nodeParts = new List(); 32 | 33 | void AddMoreJoints () 34 | { 35 | int i; 36 | 37 | AttachNode attachNode; 38 | 39 | if (!morejointsadded) 40 | { 41 | AttachNode attachNode1 = base.part.FindAttachNode ("bottom"); 42 | 43 | AttachNode [] attachNodeArray = base.part.FindAttachNodes ("interstage"); 44 | AttachNode [] attachNodeArray1 = base.part.FindAttachNodes ("top"); 45 | 46 | string [] _vessel = { "[PF]: Adding Joints to Vessel: ", vessel.vesselName, " (Launch ID: ", base.part.launchID.ToString(), ") (GUID: ", base.vessel.id.ToString(), ")" }; 47 | 48 | Debug.Log (string.Concat (_vessel)); 49 | 50 | _vessel = new [] { "[PF]: For PF Part: ", base.part.name, " (", base.part.craftID.ToString (), ")" }; 51 | 52 | Debug.Log (string.Concat (_vessel)); 53 | 54 | Part part = null; 55 | 56 | if ((attachNode1 == null ? false : attachNode1.attachedPart != null)) 57 | { 58 | part = attachNode1.attachedPart; 59 | 60 | bottomNodePart = part; 61 | 62 | addStrut (part, base.part, Vector3.zero); 63 | 64 | _vessel = new [] { "[PF]: Bottom Part: ", part.name, " (", part.craftID.ToString (), ")" }; 65 | 66 | Debug.Log (string.Concat (_vessel)); 67 | } 68 | 69 | Debug.Log ("[PF]: Top Parts:"); 70 | 71 | if (attachNodeArray1 != null) 72 | { 73 | for (i = 0; i < (int)attachNodeArray1.Length; i++) 74 | { 75 | attachNode = attachNodeArray1 [i]; 76 | 77 | if (attachNode.attachedPart != null) 78 | { 79 | if (part != null) 80 | { 81 | AddPartJoint (attachNode.attachedPart, part, attachNode.FindOpposingNode (), attachNode1.FindOpposingNode ()); 82 | } 83 | 84 | addStrut (attachNode.attachedPart, base.part, Vector3.zero); 85 | 86 | nodeParts.Add (attachNode.attachedPart); 87 | 88 | _vessel = new [] { "[PF]:", attachNode.attachedPart.name, " (", attachNode.attachedPart.craftID.ToString (), ")" }; 89 | 90 | Debug.Log (string.Concat (_vessel)); 91 | } 92 | } 93 | } 94 | 95 | if (attachNodeArray != null) 96 | { 97 | for (i = 0; i < (int)attachNodeArray.Length; i++) 98 | { 99 | attachNode = attachNodeArray [i]; 100 | 101 | if (attachNode.attachedPart != null) 102 | { 103 | if (part != null) 104 | { 105 | AddPartJoint (attachNode.attachedPart, part, attachNode.FindOpposingNode (), attachNode1.FindOpposingNode ()); 106 | } 107 | 108 | addStrut (attachNode.attachedPart, base.part, Vector3.zero); 109 | 110 | nodeParts.Add (attachNode.attachedPart); 111 | 112 | _vessel = new [] { "[PF]:", attachNode.attachedPart.name, " (", attachNode.attachedPart.craftID.ToString (), ")" }; 113 | 114 | Debug.Log (string.Concat (_vessel)); 115 | } 116 | } 117 | } 118 | 119 | morejointsadded = true; 120 | } 121 | } 122 | 123 | void AddPartJoint (Part p, Part pp, AttachNode pnode, AttachNode ppnode) 124 | { 125 | PartJoint partJoint = PartJoint.Create (p, pp, pnode, ppnode, 0); 126 | 127 | partJoint.SetBreakingForces (breakingForce, breakingForce); 128 | 129 | PartJoint partJoint1 = p.gameObject.AddComponent(); 130 | 131 | partJoint1 = partJoint; 132 | } 133 | 134 | ConfigurableJoint addStrut (Part p, Part pp, Vector3 pos) 135 | { 136 | ConfigurableJoint configurableJoint; 137 | 138 | if (p != pp) 139 | { 140 | Rigidbody rigidbody = pp.Rigidbody; 141 | 142 | if ((rigidbody == null ? false : !(rigidbody == p.Rigidbody))) 143 | { 144 | ConfigurableJoint configurableJoint1 = p.gameObject.AddComponent(); 145 | 146 | configurableJoint1.xMotion = 0; 147 | configurableJoint1.yMotion = 0; 148 | configurableJoint1.zMotion = 0; 149 | configurableJoint1.angularXMotion = 0; 150 | configurableJoint1.angularYMotion = 0; 151 | configurableJoint1.angularZMotion = 0; 152 | configurableJoint1.projectionDistance = 0.1f; 153 | configurableJoint1.projectionAngle = 5f; 154 | configurableJoint1.breakForce = breakingForce; 155 | configurableJoint1.breakTorque = breakingForce; 156 | configurableJoint1.connectedBody = rigidbody; 157 | configurableJoint1.targetPosition = pos; 158 | configurableJoint = configurableJoint1; 159 | } 160 | else 161 | { 162 | configurableJoint = null; 163 | } 164 | } 165 | else 166 | { 167 | configurableJoint = null; 168 | } 169 | 170 | return configurableJoint; 171 | } 172 | 173 | void ClearJointLines () 174 | { 175 | for (int i = 0; i < jointLines.Count; i++) 176 | { 177 | UnityEngine.Object.Destroy (jointLines [i].gameObject); 178 | } 179 | 180 | jointLines.Clear (); 181 | } 182 | 183 | public virtual void FixedUpdate () 184 | { 185 | if (!morejointsadded) 186 | { 187 | if ((!FlightGlobals.ready || vessel.packed ? false : vessel.loaded)) 188 | { 189 | AddMoreJoints (); 190 | } 191 | } 192 | } 193 | 194 | LineRenderer JointLine (Vector3 posp, Vector3 pospp, Color col, float width) 195 | { 196 | LineRenderer lineRenderer = makeLineRenderer ("JointLine", col, width); 197 | 198 | lineRenderer.positionCount = 2; 199 | 200 | lineRenderer.SetPosition (0, posp); 201 | lineRenderer.SetPosition (1, pospp); 202 | 203 | lineRenderer.useWorldSpace = true; 204 | 205 | return lineRenderer; 206 | } 207 | 208 | public void ListJoints () 209 | { 210 | int j; 211 | 212 | string [] _name; 213 | 214 | float _breakForce; 215 | 216 | Vector3 _anchor; 217 | 218 | string str; 219 | string str1; 220 | 221 | ClearJointLines (); 222 | 223 | List activeVessel = FlightGlobals.ActiveVessel.parts; 224 | 225 | for (int i = 0; i < activeVessel.Count; i++) 226 | { 227 | ConfigurableJoint [] components = activeVessel[i].gameObject.GetComponents(); 228 | 229 | if (components != null) 230 | { 231 | for (j = 0; j < (int)components.Length; j++) 232 | { 233 | ConfigurableJoint configurableJoint = components [j]; 234 | 235 | _name = new string [18]; 236 | 237 | _name[0] = "[PF]: , "; 238 | _name[1] = activeVessel [i].name; 239 | _name[2] = ", "; 240 | _name[3] = (configurableJoint.connectedBody == null ? "" : configurableJoint.connectedBody.name); 241 | _name[4] = ", "; 242 | _breakForce = configurableJoint.breakForce; 243 | _name[5] = _breakForce.ToString (); 244 | _name[6] = ", "; 245 | _breakForce = configurableJoint.breakTorque; 246 | _name[7] = _breakForce.ToString (); 247 | _name[8] = ", "; 248 | _anchor = configurableJoint.anchor; 249 | _name[9] = _anchor.ToString (); 250 | _name[10] = ", "; 251 | _anchor = configurableJoint.connectedAnchor; 252 | _name[11] = _anchor.ToString (); 253 | _name[12] = ", "; 254 | 255 | string [] strArrays = _name; 256 | 257 | if (configurableJoint.connectedBody == null) 258 | { 259 | str1 = "--"; 260 | } 261 | else 262 | { 263 | _anchor = activeVessel [i].transform.position - configurableJoint.connectedBody.position; 264 | 265 | str1 = _anchor.ToString (); 266 | } 267 | 268 | strArrays [13] = str1; 269 | 270 | _name [14] = ", "; 271 | _breakForce = configurableJoint.linearLimitSpring.damper; 272 | _name [15] = _breakForce.ToString ("F2"); 273 | _name [16] = ", "; 274 | _breakForce = configurableJoint.linearLimitSpring.spring; 275 | _name [17] = _breakForce.ToString ("F2"); 276 | 277 | Debug.Log (string.Concat (_name)); 278 | } 279 | } 280 | 281 | PartJoint [] partJointArray = activeVessel[i].gameObject.GetComponents(); 282 | 283 | if (partJointArray != null) 284 | { 285 | for (j = 0; j < (int)partJointArray.Length; j++) 286 | { 287 | PartJoint partJoint = partJointArray [j]; 288 | 289 | if ((partJoint.Host != null ? true : !(partJoint.Target == null))) 290 | { 291 | _name = new string [] { "[PF]: , ", partJoint.Host.name, ", ", null, null, null, null, null, null, null, null }; 292 | 293 | _name[3] = (partJoint.Target == null ? "" : partJoint.Target.name); 294 | 295 | string [] strArrays1 = _name; 296 | 297 | if (partJoint.Joint == null) 298 | { 299 | int count = partJoint.joints.Count; 300 | 301 | str = string.Concat (" (", count.ToString (), ")"); 302 | } 303 | else 304 | { 305 | _breakForce = partJoint.Joint.breakForce; 306 | 307 | string str2 = _breakForce.ToString (); 308 | 309 | _breakForce = partJoint.Joint.breakTorque; 310 | 311 | str = string.Concat (", ", str2, ", ", _breakForce.ToString ()); 312 | } 313 | 314 | strArrays1 [4] = str; 315 | 316 | _name [5] = ", "; 317 | _breakForce = partJoint.stiffness; 318 | _name [6] = _breakForce.ToString ("F2"); 319 | _name [7] = ", "; 320 | _anchor = partJoint.HostAnchor; 321 | _name [8] = _anchor.ToString (); 322 | _name [9] = ", "; 323 | _anchor = partJoint.TgtAnchor; 324 | _name [10] = _anchor.ToString (); 325 | 326 | Debug.Log (string.Concat (_name)); 327 | } 328 | else 329 | { 330 | Debug.Log ("[PF]: , , "); 331 | } 332 | 333 | if (partJoint.Target) 334 | { 335 | AttachNode attachNode = activeVessel [i].FindAttachNodeByPart (partJoint.Target); 336 | 337 | if (attachNode != null) 338 | { 339 | object [] objArray = { "[PF]: , ", partJoint.Host.name, ", ", partJoint.Target.name, ", ", attachNode.breakingForce.ToString(), ", ", attachNode.breakingTorque.ToString(), ", ", attachNode.contactArea.ToString("F2"), ", ", attachNode.attachMethod, ", ", attachNode.rigid.ToString (), ", ", attachNode.radius.ToString ("F2") }; 340 | 341 | Debug.Log (string.Concat (objArray)); 342 | 343 | AttachNode attachNode1 = attachNode.FindOpposingNode (); 344 | 345 | if ((attachNode1 == null ? false : attachNode1.owner != null)) 346 | { 347 | objArray = new object [] { "[PF]: , ", attachNode1.owner.name, ", ", (attachNode1.attachedPart != null ? attachNode1.attachedPart.name : ""), ", ", attachNode1.breakingForce.ToString(), ", ", attachNode1.breakingTorque.ToString(), ", ", attachNode1.contactArea.ToString("F2"), ", ", attachNode1.attachMethod, ", ", attachNode1.rigid.ToString (), ", ", attachNode1.radius.ToString ("F2") }; 348 | 349 | Debug.Log (string.Concat (objArray)); 350 | } 351 | } 352 | } 353 | } 354 | } 355 | 356 | FixedJoint [] fixedJointArray = activeVessel [i].gameObject.GetComponents(); 357 | 358 | if (fixedJointArray != null) 359 | { 360 | for (j = 0; j < (int)fixedJointArray.Length; j++) 361 | { 362 | FixedJoint fixedJoint = fixedJointArray [j]; 363 | 364 | _name = new string [] { "[PF]: , ", fixedJoint.name, ", ", null, null, null, null, null, null, null, null, null }; 365 | 366 | _name [3] = (fixedJoint.connectedBody == null ? "" : fixedJoint.connectedBody.name); 367 | _name [4] = ", "; 368 | _breakForce = fixedJoint.breakForce; 369 | _name [5] = _breakForce.ToString (); 370 | _name [6] = ", "; 371 | _breakForce = fixedJoint.breakTorque; 372 | _name [7] = _breakForce.ToString (); 373 | _name [8] = ", "; 374 | _anchor = fixedJoint.anchor; 375 | _name [9] = _anchor.ToString (); 376 | _name [10] = ", "; 377 | _anchor = fixedJoint.connectedAnchor; 378 | _name [11] = _anchor.ToString (); 379 | 380 | Debug.Log (string.Concat (_name)); 381 | } 382 | } 383 | } 384 | } 385 | 386 | LineRenderer makeLineRenderer (string objectName, Color color, float wd) 387 | { 388 | var gameObjectLine = new GameObject (objectName); 389 | 390 | gameObjectLine.transform.parent = part.transform; 391 | 392 | gameObjectLine.transform.localPosition = Vector3.zero; 393 | gameObjectLine.transform.localRotation = Quaternion.identity; 394 | 395 | LineRenderer lineRenderer = gameObjectLine.AddComponent(); 396 | 397 | lineRenderer.useWorldSpace = true; 398 | lineRenderer.material = new Material (Shader.Find ("Particles/Additive")); 399 | lineRenderer.startColor = color; 400 | lineRenderer.endColor = color; 401 | lineRenderer.startWidth = wd; 402 | lineRenderer.endWidth = wd; 403 | lineRenderer.positionCount = 0; 404 | 405 | return lineRenderer; 406 | } 407 | 408 | public void OnDestroy () 409 | { 410 | viewJoints = false; 411 | 412 | ClearJointLines (); 413 | 414 | GameEvents.onGameSceneLoadRequested.Remove (new EventData.OnEvent (OnGameSceneLoadRequested)); 415 | GameEvents.onVesselWasModified.Remove (new EventData.OnEvent (OnVesselModified)); 416 | GameEvents.onPartJointBreak.Remove (new EventData.OnEvent (OnPartJointBreak)); 417 | GameEvents.onVesselGoOffRails.Remove (new EventData.OnEvent (OnVesselGoOffRails)); 418 | } 419 | 420 | void OnGameSceneLoadRequested (GameScenes scene) 421 | { 422 | if ((scene == GameScenes.FLIGHT ? false : viewJoints)) 423 | { 424 | viewJoints = false; 425 | 426 | ClearJointLines (); 427 | } 428 | } 429 | 430 | void OnPartJointBreak (PartJoint pj, float value) 431 | { 432 | Part host; 433 | int i; 434 | bool flag; 435 | 436 | if (pj.Host != part) 437 | { 438 | if (pj.Target == part) 439 | { 440 | host = pj.Host; 441 | 442 | if (nodeParts.Contains(host)) 443 | { 444 | if (bottomNodePart != null) 445 | { 446 | RemoveJoints (host, bottomNodePart); 447 | } 448 | 449 | RemoveJoints (host, part); 450 | 451 | flag = nodeParts.Remove (host); 452 | } 453 | else if (host == bottomNodePart) 454 | { 455 | for (i = 0; i < nodeParts.Count; i++) 456 | { 457 | RemoveJoints (nodeParts [i], bottomNodePart); 458 | } 459 | 460 | RemoveJoints (bottomNodePart, part); 461 | } 462 | 463 | return; 464 | } 465 | 466 | return; 467 | } 468 | 469 | host = pj.Target; 470 | 471 | if (nodeParts.Contains(host)) 472 | { 473 | if (bottomNodePart != null) 474 | { 475 | RemoveJoints (host, bottomNodePart); 476 | } 477 | 478 | RemoveJoints (host, part); 479 | 480 | flag = nodeParts.Remove (host); 481 | } 482 | else if (host == bottomNodePart) 483 | { 484 | for (i = 0; i < nodeParts.Count; i++) 485 | { 486 | RemoveJoints (nodeParts [i], bottomNodePart); 487 | } 488 | 489 | RemoveJoints (bottomNodePart, part); 490 | } 491 | } 492 | 493 | public override void OnStart (PartModule.StartState state) 494 | { 495 | base.OnStart (state); 496 | 497 | var _uiControlFlight = (UI_Toggle) Fields["viewJoints"].uiControlFlight; 498 | 499 | _uiControlFlight.onFieldChanged = (Callback)Delegate.Combine (_uiControlFlight.onFieldChanged, new Callback(UIviewJoints_changed)); 500 | 501 | GameEvents.onGameSceneLoadRequested.Add (new EventData.OnEvent (OnGameSceneLoadRequested)); 502 | GameEvents.onVesselWasModified.Add (new EventData.OnEvent (OnVesselModified)); 503 | GameEvents.onPartJointBreak.Add (new EventData.OnEvent (OnPartJointBreak)); 504 | GameEvents.onVesselGoOffRails.Add (new EventData.OnEvent (OnVesselGoOffRails)); 505 | } 506 | 507 | void OnVesselGoOffRails (Vessel v) 508 | { 509 | if ((v == null ? true : this == null)) 510 | { 511 | } 512 | } 513 | 514 | void OnVesselModified (Vessel v) 515 | { 516 | if (v == vessel) 517 | { 518 | if (viewJoints) 519 | { 520 | ViewJoints (); 521 | } 522 | } 523 | } 524 | 525 | void RemoveJoints (Part p, Part pp) 526 | { 527 | if ((p == null || p.Rigidbody == null || pp == null ? false : !(pp.Rigidbody == null))) 528 | { 529 | ConfigurableJoint [] components = p.gameObject.GetComponents(); 530 | 531 | for (int i = 0; i < (int)components.Length; i++) 532 | { 533 | ConfigurableJoint configurableJoint = components [i]; 534 | 535 | if (configurableJoint.connectedBody == pp.Rigidbody) 536 | { 537 | try 538 | { 539 | UnityEngine.Object.Destroy (configurableJoint); 540 | } 541 | catch (Exception exception1) 542 | { 543 | Exception exception = exception1; 544 | 545 | string [] str = { "[PF]: RemoveJoint Anomaly (", p.ToString(), ", ", pp.ToString(), "): ", exception.Message }; 546 | 547 | Debug.Log (string.Concat (str)); 548 | } 549 | } 550 | } 551 | } 552 | } 553 | 554 | void UIviewJoints_changed (BaseField bf, object obj) 555 | { 556 | if (viewJoints) 557 | { 558 | ListJoints (); 559 | 560 | ViewJoints (); 561 | } 562 | else 563 | { 564 | ClearJointLines(); 565 | } 566 | } 567 | 568 | public void ViewJoints () 569 | { 570 | ClearJointLines (); 571 | 572 | List activeVessel = FlightGlobals.ActiveVessel.parts; 573 | 574 | for (int i = 0; i < activeVessel.Count; i++) 575 | { 576 | ConfigurableJoint [] components = activeVessel [i].gameObject.GetComponents(); 577 | 578 | if (components != null) 579 | { 580 | for (int j = 0; j < (int)components.Length; j++) 581 | { 582 | ConfigurableJoint configurableJoint = components [j]; 583 | 584 | if (configurableJoint.connectedBody != null) 585 | { 586 | var vector3 = new Vector3 (0f, 5f, 0f); 587 | var vector31 = new Vector3 (0.25f, 0f, 0f); 588 | 589 | Vector3 _position = activeVessel [i].transform.position + vector3; 590 | Vector3 _position1 = configurableJoint.connectedBody.position + vector3; 591 | Vector3 _position2 = (activeVessel [i].transform.position + (activeVessel [i].transform.rotation * configurableJoint.anchor)) + vector3; 592 | 593 | Vector3 vector32 = (configurableJoint.connectedBody.position + (configurableJoint.connectedBody.rotation * configurableJoint.connectedAnchor)) + vector3; 594 | 595 | jointLines.Add (JointLine (_position, _position1, Color.blue, w1)); 596 | jointLines.Add (JointLine (_position2, vector32 + vector31, Color.yellow, w2)); 597 | jointLines.Add (JointLine (_position, _position2, Color.gray, 0.03f)); 598 | jointLines.Add (JointLine (_position1, vector32, Color.gray, 0.03f)); 599 | } 600 | } 601 | } 602 | } 603 | } 604 | } 605 | } 606 | -------------------------------------------------------------------------------- /Source/ProceduralFairings/PayloadScan.cs: -------------------------------------------------------------------------------- 1 | // ================================================== 2 | // Procedural Fairings plug-in by Alexey Volynskov. 3 | 4 | // Licensed under CC-BY-4.0 terms: https://creativecommons.org/licenses/by/4.0/legalcode 5 | // ================================================== 6 | 7 | using System; 8 | using System.Collections.Generic; 9 | using UnityEngine; 10 | 11 | namespace Keramzit 12 | { 13 | struct PayloadScan 14 | { 15 | public List profile; 16 | public List payload; 17 | public HashSet hash; 18 | 19 | public List targets; 20 | 21 | public Matrix4x4 w2l; 22 | 23 | public float ofs, verticalStep, extraRadius; 24 | 25 | public int nestedBases; 26 | 27 | public PayloadScan (Part p, float vs, float er) 28 | { 29 | profile = new List(); 30 | payload = new List(); 31 | targets = new List(); 32 | hash = new HashSet(); 33 | 34 | hash.Add (p); 35 | 36 | w2l = p.transform.worldToLocalMatrix; 37 | ofs = 0; 38 | verticalStep = vs; 39 | extraRadius = er; 40 | nestedBases = 0; 41 | } 42 | 43 | public void addPart (Part p, Part prevPart) 44 | { 45 | if (p == null || hash.Contains (p)) 46 | { 47 | return; 48 | } 49 | 50 | hash.Add (p); 51 | 52 | if (p.GetComponent() != null) 53 | { 54 | return; 55 | } 56 | 57 | if (p == prevPart.parent && prevPart.srfAttachNode.attachedPart == p) 58 | { 59 | return; 60 | } 61 | 62 | // Check for another fairing base. 63 | 64 | if (p.GetComponent() != null && p.GetComponent() == null) 65 | { 66 | AttachNode node = p.FindAttachNode ("top"); 67 | 68 | if (node != null && node.attachedPart == prevPart) 69 | { 70 | // Reversed base - potential inline fairing target. 71 | 72 | if (nestedBases <= 0) 73 | { 74 | targets.Add (p); 75 | 76 | return; 77 | } 78 | 79 | --nestedBases; 80 | } 81 | else 82 | { 83 | ++nestedBases; 84 | } 85 | } 86 | 87 | payload.Add (p); 88 | } 89 | 90 | public void addPayloadEdge (Vector3 v0, Vector3 v1) 91 | { 92 | float r0 = Mathf.Sqrt (v0.x * v0.x + v0.z * v0.z) + extraRadius; 93 | float r1 = Mathf.Sqrt (v1.x * v1.x + v1.z * v1.z) + extraRadius; 94 | 95 | float y0 = (v0.y - ofs) / verticalStep; 96 | float y1 = (v1.y - ofs) / verticalStep; 97 | 98 | if (y0 > y1) 99 | { 100 | float tmp; 101 | 102 | tmp = y0; y0 = y1; y1 = tmp; 103 | tmp = r0; r0 = r1; r1 = tmp; 104 | } 105 | 106 | int h0 = Mathf.FloorToInt (y0); 107 | int h1 = Mathf.FloorToInt (y1); 108 | 109 | if (h1 < 0) 110 | { 111 | return; 112 | } 113 | 114 | if (h1 >= profile.Count) 115 | { 116 | var farray = new float [h1 - profile.Count + 1]; 117 | 118 | for (int i = 0; i < farray.Length; i++) 119 | { 120 | farray [i] = 0; 121 | } 122 | 123 | profile.AddRange (farray); 124 | } 125 | 126 | if (h0 >= 0) 127 | { 128 | profile [h0] = Mathf.Max (profile [h0], r0); 129 | } 130 | 131 | profile [h1] = Mathf.Max (profile [h1], r1); 132 | 133 | if (h0 != h1) 134 | { 135 | float k = (r1 - r0) / (y1 - y0); 136 | float b = r0 + k * (h0 + 1 - y0); 137 | float maxR = Mathf.Max (r0, r1); 138 | 139 | for (int h = Math.Max (h0, 0); h < h1; ++h) 140 | { 141 | float r = Mathf.Min (k * (h - h0) + b, maxR); 142 | 143 | profile [h] = Mathf.Max (profile [h], r); 144 | profile [h + 1] = Mathf.Max (profile [h + 1], r); 145 | } 146 | } 147 | } 148 | 149 | public void addPayload (Bounds box, Matrix4x4 boxTm) 150 | { 151 | Matrix4x4 m = w2l * boxTm; 152 | 153 | Vector3 p0 = box.min, p1 = box.max; 154 | 155 | var verts = new Vector3 [8]; 156 | 157 | for (int i = 0; i < 8; ++i) 158 | { 159 | verts [i] = m.MultiplyPoint3x4 (new Vector3 ((i & 1) != 0 ? p1.x : p0.x, (i & 2) != 0 ? p1.y : p0.y, (i & 4) != 0 ? p1.z : p0.z)); 160 | } 161 | 162 | addPayloadEdge (verts [0], verts [1]); 163 | addPayloadEdge (verts [2], verts [3]); 164 | addPayloadEdge (verts [4], verts [5]); 165 | addPayloadEdge (verts [6], verts [7]); 166 | 167 | addPayloadEdge (verts [0], verts [2]); 168 | addPayloadEdge (verts [1], verts [3]); 169 | addPayloadEdge (verts [4], verts [6]); 170 | addPayloadEdge (verts [5], verts [7]); 171 | 172 | addPayloadEdge (verts [0], verts [4]); 173 | addPayloadEdge (verts [1], verts [5]); 174 | addPayloadEdge (verts [2], verts [6]); 175 | addPayloadEdge (verts [3], verts [7]); 176 | } 177 | 178 | public void addPayload (Collider c) 179 | { 180 | var mc = c as MeshCollider; 181 | var bc = c as BoxCollider; 182 | 183 | if (mc) 184 | { 185 | var m = w2l * mc.transform.localToWorldMatrix; 186 | 187 | var verts = mc.sharedMesh.vertices; 188 | var faces = mc.sharedMesh.triangles; 189 | 190 | for (int i = 0; i < faces.Length; i += 3) 191 | { 192 | var v0 = m.MultiplyPoint3x4 (verts [faces [i]]); 193 | var v1 = m.MultiplyPoint3x4 (verts [faces [i + 1]]); 194 | var v2 = m.MultiplyPoint3x4 (verts [faces [i + 2]]); 195 | 196 | addPayloadEdge (v0, v1); 197 | addPayloadEdge (v1, v2); 198 | addPayloadEdge (v2, v0); 199 | } 200 | } 201 | else if (bc) 202 | { 203 | addPayload (new Bounds (bc.center, bc.size), bc.transform.localToWorldMatrix); 204 | } 205 | else 206 | { 207 | addPayload (c.bounds, Matrix4x4.identity); 208 | } 209 | } 210 | } 211 | } 212 | -------------------------------------------------------------------------------- /Source/ProceduralFairings/ProcAdapter.cs: -------------------------------------------------------------------------------- 1 | // ================================================== 2 | // Procedural Fairings plug-in by Alexey Volynskov. 3 | 4 | // Licensed under CC-BY-4.0 terms: https://creativecommons.org/licenses/by/4.0/legalcode 5 | // ================================================== 6 | 7 | using KSP.UI.Screens; 8 | using System; 9 | using System.Collections.Generic; 10 | using UnityEngine; 11 | 12 | namespace Keramzit 13 | { 14 | abstract class ProceduralAdapterBase : PartModule 15 | { 16 | [KSPField (isPersistant = true, guiActiveEditor = true, guiName = "Base", guiFormat = "S4", guiUnits = "m")] 17 | [UI_FloatEdit (sigFigs = 3, unit = "m", minValue = 0.1f, maxValue = 5, incrementLarge = 1.25f, incrementSmall = 0.125f, incrementSlide = 0.001f)] 18 | public float baseSize = 1.25f; 19 | 20 | [KSPField (isPersistant = true, guiActiveEditor = true, guiName = "Top", guiFormat = "S4", guiUnits = "m")] 21 | [UI_FloatEdit (sigFigs = 3, unit = "m", minValue = 0.1f, maxValue = 5, incrementLarge = 1.25f, incrementSmall = 0.125f, incrementSlide = 0.001f)] 22 | public float topSize = 1.25f; 23 | 24 | [KSPField (isPersistant = true, guiActiveEditor = true, guiName = "Height", guiFormat = "S4", guiUnits = "m")] 25 | [UI_FloatEdit (sigFigs = 3, unit = "m", minValue = 0.1f, maxValue = 50, incrementLarge = 1.0f, incrementSmall = 0.1f, incrementSlide = 0.001f)] 26 | public float height = 1; 27 | 28 | [KSPField] public string topNodeName = "top1"; 29 | 30 | [KSPField] public float diameterStepLarge = 1.25f; 31 | [KSPField] public float diameterStepSmall = 0.125f; 32 | 33 | [KSPField] public float heightStepLarge = 1.0f; 34 | [KSPField] public float heightStepSmall = 0.1f; 35 | 36 | public bool changed = true; 37 | 38 | abstract public float minHeight { get; } 39 | 40 | float lastBaseSize = -1000; 41 | float lastTopSize = -1000; 42 | float lastHeight = -1000; 43 | 44 | protected bool justLoaded; 45 | 46 | public virtual void checkTweakables () 47 | { 48 | if (!baseSize.Equals (lastBaseSize)) 49 | { 50 | lastBaseSize = baseSize; 51 | 52 | changed = true; 53 | } 54 | 55 | if (!topSize.Equals (lastTopSize)) 56 | { 57 | lastTopSize = topSize; 58 | 59 | changed = true; 60 | } 61 | 62 | if (!height.Equals (lastHeight)) 63 | { 64 | lastHeight = height; 65 | 66 | changed = true; 67 | } 68 | } 69 | 70 | public virtual void FixedUpdate () 71 | { 72 | checkTweakables (); 73 | 74 | if (changed) 75 | { 76 | updateShape (); 77 | } 78 | 79 | justLoaded = false; 80 | } 81 | 82 | public virtual void updateShape () 83 | { 84 | changed = false; 85 | 86 | float topheight = 0; 87 | float topnodeheight = 0; 88 | 89 | var node = part.FindAttachNode ("bottom"); 90 | 91 | if (node != null) 92 | { 93 | node.size = Mathf.RoundToInt(baseSize / diameterStepLarge); 94 | } 95 | 96 | node = part.FindAttachNode ("top"); 97 | 98 | if (node != null) 99 | { 100 | node.size = Mathf.RoundToInt (baseSize / diameterStepLarge); 101 | 102 | topheight = node.position.y; 103 | } 104 | 105 | node = part.FindAttachNode (topNodeName); 106 | 107 | if (node != null) 108 | { 109 | node.position = new Vector3 (0, height, 0); 110 | 111 | node.size = Mathf.RoundToInt (topSize / diameterStepLarge); 112 | 113 | if (!justLoaded) 114 | { 115 | PFUtils.updateAttachedPartPos (node, part); 116 | } 117 | 118 | topnodeheight = height; 119 | } 120 | else 121 | { 122 | Debug.LogError ("[PF]: No '" + topNodeName + "' node in part!", this); 123 | } 124 | 125 | var internodes = part.FindAttachNodes ("interstage"); 126 | 127 | if (internodes != null) 128 | { 129 | var inc = (topnodeheight - topheight) / (internodes.Length / 2 + 1); 130 | 131 | for (int i = 0, j = 0; i < internodes.Length; i = i + 2) 132 | { 133 | var height = topheight + (j + 1) * inc; 134 | 135 | j++; 136 | 137 | node = internodes [i]; 138 | 139 | node.position.y = height; 140 | node.size = node.size = Mathf.RoundToInt (topSize / diameterStepLarge) - 1; 141 | 142 | if (!justLoaded) 143 | { 144 | PFUtils.updateAttachedPartPos (node, part); 145 | } 146 | 147 | node = internodes [i + 1]; 148 | 149 | node.position.y = height; 150 | node.size = node.size = Mathf.RoundToInt (topSize / diameterStepLarge) - 1; 151 | 152 | if (!justLoaded) 153 | { 154 | PFUtils.updateAttachedPartPos (node, part); 155 | } 156 | } 157 | } 158 | } 159 | 160 | public override void OnStart(StartState state) 161 | { 162 | base.OnStart (state); 163 | 164 | if (state == StartState.None) 165 | { 166 | return; 167 | } 168 | 169 | StartCoroutine (FireFirstChanged ()); 170 | 171 | } 172 | 173 | public IEnumerator FireFirstChanged () 174 | { 175 | while(!(part.editorStarted || part.started)) 176 | { 177 | yield return new WaitForFixedUpdate (); 178 | } 179 | 180 | // Wait a little more... 181 | 182 | yield return new WaitForSeconds (.01f); 183 | 184 | changed = true; 185 | } 186 | 187 | public override void OnLoad (ConfigNode cfg) 188 | { 189 | base.OnLoad (cfg); 190 | 191 | justLoaded = true; 192 | changed = true; 193 | } 194 | } 195 | 196 | class ProceduralFairingAdapter : ProceduralAdapterBase, IPartCostModifier, IPartMassModifier 197 | { 198 | [KSPField] public float sideThickness = 0.05f / 1.25f; 199 | [KSPField] public Vector4 specificMass = new Vector4 (0.005f, 0.011f, 0.009f, 0f); 200 | [KSPField] public float specificBreakingForce = 6050; 201 | [KSPField] public float specificBreakingTorque = 6050; 202 | [KSPField] public float costPerTonne = 2000; 203 | 204 | [KSPField] public float dragAreaScale = 1; 205 | 206 | [KSPField (isPersistant = true)] 207 | public bool topNodeDecouplesWhenFairingsGone; 208 | 209 | public bool isTopNodePartPresent = true; 210 | public bool isFairingPresent = true; 211 | 212 | [KSPEvent (name = "decNoFairings", active = true, guiActive = true, guiActiveEditor = true, guiActiveUnfocused = true, guiName = "text")] 213 | public void UIToggleTopNodeDecouple () 214 | { 215 | topNodeDecouplesWhenFairingsGone = !topNodeDecouplesWhenFairingsGone; 216 | 217 | UpdateUIdecNoFairingsText (topNodeDecouplesWhenFairingsGone); 218 | } 219 | 220 | void UpdateUIdecNoFairingsText (bool flag) 221 | { 222 | if (flag) 223 | { 224 | Events["UIToggleTopNodeDecouple"].guiName = "Decouple when Fairing gone: Yes"; 225 | } 226 | else 227 | { 228 | Events["UIToggleTopNodeDecouple"].guiName = "Decouple when Fairing gone: No"; 229 | } 230 | } 231 | 232 | public override float minHeight 233 | { 234 | get 235 | { 236 | return baseSize * 0.2f; 237 | } 238 | } 239 | 240 | public ModifierChangeWhen GetModuleCostChangeWhen() { return ModifierChangeWhen.FIXED; } 241 | public ModifierChangeWhen GetModuleMassChangeWhen() { return ModifierChangeWhen.FIXED; } 242 | 243 | public float GetModuleCost (float defcost, ModifierStagingSituation sit) 244 | { 245 | return totalMass * costPerTonne - defcost; 246 | } 247 | 248 | public float GetModuleMass (float defmass, ModifierStagingSituation sit) 249 | { 250 | return totalMass - defmass; 251 | } 252 | 253 | public float calcSideThickness () 254 | { 255 | return Mathf.Min (sideThickness * Mathf.Max (baseSize, topSize), Mathf.Min (baseSize, topSize) * 0.25f); 256 | } 257 | 258 | public float topRadius 259 | { 260 | get 261 | { 262 | return topSize * 0.5f - calcSideThickness (); 263 | } 264 | } 265 | 266 | [KSPField (isPersistant = true, guiActiveEditor = true, guiName = "Extra height", guiFormat = "S4", guiUnits = "m")] 267 | [UI_FloatEdit (sigFigs = 3, unit = "m", minValue = 0, maxValue = 50, incrementLarge = 1.0f, incrementSmall = 0.1f, incrementSlide = 0.001f)] 268 | public float extraHeight = 0; 269 | 270 | public bool engineFairingRemoved; 271 | 272 | [KSPField (isPersistant = false, guiActive = false, guiActiveEditor = true, guiName = "Mass")] 273 | public string massDisplay; 274 | 275 | [KSPField (isPersistant = false, guiActive = false, guiActiveEditor = true, guiName = "Cost")] 276 | public string costDisplay; 277 | 278 | bool limitsSet; 279 | 280 | float lastExtraHt = -1000; 281 | 282 | public override void checkTweakables () 283 | { 284 | base.checkTweakables (); 285 | 286 | if (!extraHeight.Equals (lastExtraHt)) 287 | { 288 | lastExtraHt = extraHeight; 289 | 290 | changed = true; 291 | } 292 | } 293 | 294 | void RemoveTopPartJoints () 295 | { 296 | Part topPart = getTopPart (); 297 | 298 | Part bottomPart = getBottomPart (); 299 | 300 | if (topPart == null ? false : (bottomPart != null)) 301 | { 302 | ConfigurableJoint [] components = topPart.gameObject.GetComponents(); 303 | 304 | for (int i = 0; i < (int) components.Length; i++) 305 | { 306 | ConfigurableJoint configurableJoint = components [i]; 307 | 308 | if (configurableJoint.connectedBody == bottomPart.Rigidbody) 309 | { 310 | UnityEngine.Object.Destroy (configurableJoint); 311 | } 312 | } 313 | } 314 | } 315 | 316 | public void Start () 317 | { 318 | part.mass = totalMass; 319 | } 320 | 321 | public override void OnStart (StartState state) 322 | { 323 | base.OnStart (state); 324 | 325 | limitsSet = false; 326 | 327 | part.mass = totalMass; 328 | 329 | isFairingPresent = CheckForFairingPresent (); 330 | 331 | isTopNodePartPresent = (getTopPart () != null); 332 | 333 | UpdateUIdecNoFairingsText (topNodeDecouplesWhenFairingsGone); 334 | 335 | GameEvents.onEditorShipModified.Add (OnEditorShipModified); 336 | GameEvents.onVesselWasModified.Add (OnVesselWasModified); 337 | GameEvents.onVesselCreate.Add (OnVesselCreate); 338 | GameEvents.onVesselGoOffRails.Add (OnVesselGoOffRails); 339 | GameEvents.onVesselLoaded.Add (OnVesselLoaded); 340 | GameEvents.onStageActivate.Add (OnStageActivate); 341 | } 342 | 343 | public void OnDestroy () 344 | { 345 | GameEvents.onEditorShipModified.Remove (OnEditorShipModified); 346 | GameEvents.onVesselWasModified.Remove (OnVesselWasModified); 347 | GameEvents.onVesselCreate.Remove (OnVesselCreate); 348 | GameEvents.onVesselGoOffRails.Remove (OnVesselGoOffRails); 349 | GameEvents.onVesselLoaded.Remove (OnVesselLoaded); 350 | GameEvents.onStageActivate.Remove (OnStageActivate); 351 | } 352 | 353 | bool isShipModified = true; 354 | bool isStaged; 355 | 356 | int stageNum; 357 | 358 | // Lets catch some events... 359 | 360 | void OnEditorShipModified (ShipConstruct sc) 361 | { 362 | isShipModified = true; 363 | } 364 | 365 | void OnVesselWasModified (Vessel ves) 366 | { 367 | isShipModified = true; 368 | } 369 | 370 | void OnVesselCreate (Vessel ves) 371 | { 372 | isShipModified = true; 373 | } 374 | 375 | void OnVesselGoOffRails (Vessel ves) 376 | { 377 | isShipModified = true; 378 | } 379 | 380 | void OnVesselLoaded (Vessel ves) 381 | { 382 | isShipModified = true; 383 | } 384 | 385 | void OnStageActivate (int stage) 386 | { 387 | isStaged = true; 388 | 389 | stageNum = stage; 390 | } 391 | 392 | public float totalMass; 393 | 394 | public override void updateShape () 395 | { 396 | base.updateShape (); 397 | 398 | float sth = calcSideThickness (); 399 | 400 | float br = baseSize * 0.5f - sth; 401 | float scale = br * 2; 402 | 403 | part.mass = totalMass = ((specificMass.x * scale + specificMass.y) * scale + specificMass.z) * scale + specificMass.w; 404 | 405 | massDisplay = PFUtils.formatMass (totalMass); 406 | costDisplay = PFUtils.formatCost (part.partInfo.cost + GetModuleCost (part.partInfo.cost, ModifierStagingSituation.CURRENT)); 407 | 408 | part.breakingForce = specificBreakingForce * Mathf.Pow (br, 2); 409 | part.breakingTorque = specificBreakingTorque * Mathf.Pow (br, 2); 410 | 411 | var model = part.FindModelTransform ("model"); 412 | 413 | if (model != null) 414 | { 415 | model.localScale = Vector3.one * scale; 416 | } 417 | else 418 | { 419 | Debug.LogError("[PF]: No 'model' transform found in part!", this); 420 | } 421 | 422 | part.rescaleFactor = scale; 423 | 424 | var node = part.FindAttachNode ("top"); 425 | 426 | node.position = node.originalPosition * scale; 427 | 428 | if (!justLoaded) 429 | { 430 | PFUtils.updateAttachedPartPos (node, part); 431 | } 432 | 433 | var topNode = part.FindAttachNode ("top"); 434 | var bottomNode = part.FindAttachNode ("bottom"); 435 | 436 | float y = (topNode.position.y + bottomNode.position.y) * 0.5f; 437 | 438 | int sideNodeSize = Mathf.RoundToInt(scale / diameterStepLarge) - 1; 439 | 440 | if (sideNodeSize < 0) 441 | { 442 | sideNodeSize = 0; 443 | } 444 | 445 | var nodes = part.FindAttachNodes ("connect"); 446 | 447 | if (nodes != null) 448 | { 449 | for (int i = 0; i < nodes.Length; i++) 450 | { 451 | var n = nodes [i]; 452 | 453 | n.position.y = y; 454 | n.size = sideNodeSize; 455 | 456 | if (!justLoaded) 457 | { 458 | PFUtils.updateAttachedPartPos (n, part); 459 | } 460 | } 461 | } 462 | 463 | var topnode2 = part.FindAttachNode (topNodeName); 464 | var internodes = part.FindAttachNodes ("interstage"); 465 | 466 | if (internodes != null && topnode2 != null) 467 | { 468 | var topheight = topNode.position.y; 469 | var topnode2height = topnode2.position.y; 470 | 471 | var inc = (topnode2height - topheight) / (internodes.Length / 2 + 1); 472 | 473 | for (int i = 0, j = 0; i < internodes.Length; i = i + 2) 474 | { 475 | var baseHeight = topheight + (j + 1) * inc; 476 | 477 | j++; 478 | 479 | node = internodes [i]; 480 | 481 | node.position.y = baseHeight; 482 | node.size = topNode.size; 483 | 484 | if (!justLoaded) 485 | { 486 | PFUtils.updateAttachedPartPos (node, part); 487 | } 488 | 489 | node = internodes [i + 1]; 490 | 491 | node.position.y = baseHeight; 492 | node.size = sideNodeSize; 493 | 494 | if (!justLoaded) 495 | { 496 | PFUtils.updateAttachedPartPos (node, part); 497 | } 498 | } 499 | } 500 | 501 | var nnt = part.GetComponent(); 502 | 503 | if (nnt) 504 | { 505 | nnt.radius = baseSize * 0.5f; 506 | } 507 | 508 | var fbase = part.GetComponent(); 509 | 510 | if (fbase) 511 | { 512 | fbase.baseSize = br * 2; 513 | fbase.sideThickness = sth; 514 | fbase.needShapeUpdate = true; 515 | } 516 | 517 | StartCoroutine (PFUtils.updateDragCubeCoroutine (part, dragAreaScale)); 518 | } 519 | 520 | public override void FixedUpdate () 521 | { 522 | base.FixedUpdate (); 523 | 524 | if (!limitsSet && PFUtils.canCheckTech ()) 525 | { 526 | limitsSet = true; 527 | 528 | float minSize = PFUtils.getTechMinValue ("PROCFAIRINGS_MINDIAMETER", 0.25f); 529 | float maxSize = PFUtils.getTechMaxValue ("PROCFAIRINGS_MAXDIAMETER", 30); 530 | 531 | PFUtils.setFieldRange (Fields["baseSize"], minSize, maxSize); 532 | PFUtils.setFieldRange (Fields["topSize"], minSize, maxSize); 533 | 534 | ((UI_FloatEdit) Fields["baseSize"].uiControlEditor).incrementLarge = diameterStepLarge; 535 | ((UI_FloatEdit) Fields["baseSize"].uiControlEditor).incrementSmall = diameterStepSmall; 536 | ((UI_FloatEdit) Fields["topSize"].uiControlEditor).incrementLarge = diameterStepLarge; 537 | ((UI_FloatEdit) Fields["topSize"].uiControlEditor).incrementSmall = diameterStepSmall; 538 | 539 | ((UI_FloatEdit) Fields["height"].uiControlEditor).incrementLarge = heightStepLarge; 540 | ((UI_FloatEdit) Fields["height"].uiControlEditor).incrementSmall = heightStepSmall; 541 | ((UI_FloatEdit) Fields["extraHeight"].uiControlEditor).incrementLarge = heightStepLarge; 542 | ((UI_FloatEdit) Fields["extraHeight"].uiControlEditor).incrementSmall = heightStepSmall; 543 | } 544 | 545 | if (isShipModified) 546 | { 547 | isShipModified = false; 548 | 549 | // We used to remove the engine fairing (if there is any) from topmost node, but lately that's been causing NREs. 550 | // Since KSP gives us this option nativley, let's just use KSP to do that if we want. 551 | 552 | if (!HighLogic.LoadedSceneIsEditor) 553 | { 554 | if (isTopNodePartPresent) 555 | { 556 | var tp = getTopPart (); 557 | 558 | if (tp == null) 559 | { 560 | isTopNodePartPresent = false; 561 | 562 | Events["UIToggleTopNodeDecouple"].guiActive = false; 563 | } 564 | else 565 | { 566 | if (topNodeDecouplesWhenFairingsGone && !CheckForFairingPresent ()) 567 | { 568 | PartModule item = part.Modules["ModuleDecouple"]; 569 | 570 | if (item == null) 571 | { 572 | Debug.LogError ("[PF]: Cannot decouple from top part!", this); 573 | } 574 | else 575 | { 576 | RemoveTopPartJoints (); 577 | 578 | ((ModuleDecouple)item).Decouple (); 579 | 580 | part.stackIcon.RemoveIcon (); 581 | 582 | StageManager.Instance.SortIcons (true); 583 | 584 | isFairingPresent = false; 585 | isTopNodePartPresent = false; 586 | 587 | Events["UIToggleTopNodeDecouple"].guiActive = false; 588 | } 589 | } 590 | } 591 | } 592 | 593 | if (isStaged) 594 | { 595 | isStaged = false; 596 | 597 | if (part != null) 598 | { 599 | if (stageNum == part.inverseStage) 600 | { 601 | part.stackIcon.RemoveIcon (); 602 | 603 | StageManager.Instance.SortIcons (true); 604 | 605 | Events["UIToggleTopNodeDecouple"].guiActive = false; 606 | } 607 | } 608 | } 609 | } 610 | } 611 | } 612 | 613 | public Part getBottomPart () 614 | { 615 | AttachNode attachNode = part.FindAttachNode ("bottom"); 616 | 617 | return (attachNode == null) ? null : attachNode.attachedPart; 618 | } 619 | 620 | public bool CheckForFairingPresent() 621 | { 622 | if (!isFairingPresent) 623 | { 624 | return false; 625 | } 626 | 627 | var nodes = part.FindAttachNodes ("connect"); 628 | 629 | if (nodes == null) 630 | { 631 | return false; 632 | } 633 | 634 | for (int i = 0; i < nodes.Length; i++) 635 | { 636 | var n = nodes [i]; 637 | 638 | if (n.attachedPart != null) 639 | { 640 | return true; 641 | } 642 | } 643 | 644 | return false; 645 | } 646 | 647 | public Part getTopPart () 648 | { 649 | var node = part.FindAttachNode (topNodeName); 650 | 651 | return (node == null) ? null : node.attachedPart; 652 | } 653 | 654 | public override void OnLoad (ConfigNode cfg) 655 | { 656 | base.OnLoad (cfg); 657 | 658 | if (cfg.HasValue ("baseRadius") && cfg.HasValue ("topRadius")) 659 | { 660 | // Load legacy settings. 661 | 662 | float br = float.Parse (cfg.GetValue ("baseRadius")); 663 | float tr = float.Parse (cfg.GetValue ("topRadius")); 664 | 665 | baseSize = (br + sideThickness * br) * 2; 666 | topSize = (tr + sideThickness * br) * 2; 667 | 668 | sideThickness *= 1.15f / 1.25f; 669 | } 670 | } 671 | } 672 | } 673 | -------------------------------------------------------------------------------- /Source/ProceduralFairings/ProceduralFairings.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | {51CE67F2-5981-4AD2-97E8-0E2B44792AB2} 7 | Library 8 | ProceduralFairings 9 | ProceduralFairings 10 | v3.5 11 | False 12 | OnBuildSuccess 13 | False 14 | False 15 | False 16 | ..\Builds\$(Configuration)\ 17 | 18 | 19 | true 20 | PdbOnly 21 | False 22 | ..\..\GameData\ProceduralFairings\Plugins\ 23 | prompt 24 | 4 25 | false 26 | 27 | 28 | None 29 | True 30 | ..\..\GameData\ProceduralFairings\Plugins\ 31 | prompt 32 | 4 33 | false 34 | 35 | 36 | False 37 | ..\Builds\ 38 | DEBUG; 39 | Project 40 | 41 | 42 | 4194304 43 | AnyCPU 44 | False 45 | Auto 46 | 4096 47 | 48 | 49 | False 50 | ..\Builds\ 51 | Project 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | ..\..\..\Dependencies\1.5.0\Assembly-CSharp.dll 69 | False 70 | 71 | 72 | 73 | ..\..\..\Dependencies\1.5.0\UnityEngine.dll 74 | False 75 | 76 | 77 | ..\..\..\Dependencies\1.5.0\UnityEngine.UI.dll 78 | False 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /Source/ProceduralFairings/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about the specified assembly. 6 | 7 | [assembly: AssemblyTitle ("ProceduralFairings")] 8 | [assembly: AssemblyDescription ("Procedural Fairings for KSP")] 9 | [assembly: AssemblyCopyright ("Copyright © 2016 - 2018, e-dog, rsparkyc, PhineasFreak")] 10 | [assembly: AssemblyConfiguration ("Release")] 11 | [assembly: AssemblyProduct ("ProceduralFairings")] 12 | 13 | // Hide the specified assembly from any COM components. 14 | 15 | [assembly: ComVisible (false)] 16 | 17 | // The following GUID is for the ID of the typelib if this project is exposed to COM. 18 | 19 | [assembly: Guid ("71c1f577-92c0-4ad6-9d1c-58a6eb02a0bc")] 20 | 21 | // Assembly version information. Consists of the following four values: 22 | // 23 | // • Major Version 24 | // • Minor Version 25 | // • Build Number 26 | // • Revision 27 | 28 | [assembly: AssemblyVersion ("1.5.0.2332")] 29 | [assembly: AssemblyFileVersion ("1.5.0.5")] 30 | 31 | // The KSPAssembly attribute can be used to ensure that the plugin assemblies 32 | // are loaded in the correct order. 33 | // This attribute is not currently used but it is included here for completeness. 34 | 35 | [assembly: KSPAssembly ("ProceduralFairings", 1, 0)] 36 | -------------------------------------------------------------------------------- /Source/ProceduralFairings/Resizers.cs: -------------------------------------------------------------------------------- 1 | // ================================================== 2 | // Procedural Fairings plug-in by Alexey Volynskov. 3 | 4 | // Licensed under CC-BY-4.0 terms: https://creativecommons.org/licenses/by/4.0/legalcode 5 | // ================================================== 6 | 7 | using System; 8 | using UnityEngine; 9 | 10 | namespace Keramzit 11 | { 12 | public abstract class KzPartResizer : PartModule, IPartCostModifier, IPartMassModifier 13 | { 14 | [KSPField (isPersistant = true, guiActiveEditor = true, guiName = "Size", guiFormat = "S4", guiUnits = "m")] 15 | [UI_FloatEdit (sigFigs = 3, unit = "m", minValue = 0.1f, maxValue = 5, incrementLarge = 1.25f, incrementSmall = 0.125f, incrementSlide = 0.001f)] 16 | public float size = 1.25f; 17 | 18 | [KSPField] public float diameterStepLarge = 1.25f; 19 | [KSPField] public float diameterStepSmall = 0.125f; 20 | 21 | [KSPField] public Vector4 specificMass = new Vector4 (0.005f, 0.011f, 0.009f, 0f); 22 | [KSPField] public float specificBreakingForce = 1536; 23 | [KSPField] public float specificBreakingTorque = 1536; 24 | [KSPField] public float costPerTonne = 2000; 25 | 26 | [KSPField] public string minSizeName = "PROCFAIRINGS_MINDIAMETER"; 27 | [KSPField] public string maxSizeName = "PROCFAIRINGS_MAXDIAMETER"; 28 | 29 | [KSPField] public float dragAreaScale = 1; 30 | 31 | [KSPField(isPersistant = false, guiActive = false, guiActiveEditor = true, guiName = "Mass")] 32 | public string massDisplay; 33 | 34 | [KSPField(isPersistant = false, guiActive = false, guiActiveEditor = true, guiName = "Cost")] 35 | public string costDisplay; 36 | 37 | protected float oldSize = -1000; 38 | protected bool justLoaded, limitsSet; 39 | 40 | public ModifierChangeWhen GetModuleCostChangeWhen () { return ModifierChangeWhen.FIXED; } 41 | public ModifierChangeWhen GetModuleMassChangeWhen () { return ModifierChangeWhen.FIXED; } 42 | 43 | public float GetModuleCost (float defcost, ModifierStagingSituation sit) 44 | { 45 | return totalMass * costPerTonne - defcost; 46 | } 47 | 48 | public float GetModuleMass (float defmass, ModifierStagingSituation sit) 49 | { 50 | return totalMass - defmass; 51 | } 52 | 53 | public void Start () 54 | { 55 | part.mass = totalMass; 56 | } 57 | 58 | public override void OnStart (StartState state) 59 | { 60 | base.OnStart (state); 61 | 62 | limitsSet = false; 63 | 64 | updateNodeSize (size); 65 | 66 | part.mass = totalMass; 67 | } 68 | 69 | public override void OnLoad (ConfigNode cfg) 70 | { 71 | base.OnLoad (cfg); 72 | 73 | justLoaded = true; 74 | 75 | if (HighLogic.LoadedSceneIsEditor || HighLogic.LoadedSceneIsFlight) 76 | { 77 | updateNodeSize (size); 78 | } 79 | } 80 | 81 | public virtual void FixedUpdate () 82 | { 83 | if (!limitsSet && PFUtils.canCheckTech ()) 84 | { 85 | limitsSet = true; 86 | 87 | float minSize = PFUtils.getTechMinValue (minSizeName, 0.25f); 88 | float maxSize = PFUtils.getTechMaxValue (maxSizeName, 30); 89 | 90 | PFUtils.setFieldRange (Fields["size"], minSize, maxSize); 91 | 92 | ((UI_FloatEdit) Fields["size"].uiControlEditor).incrementLarge = diameterStepLarge; 93 | ((UI_FloatEdit) Fields["size"].uiControlEditor).incrementSmall = diameterStepSmall; 94 | } 95 | 96 | if (!size.Equals (oldSize)) 97 | { 98 | resizePart (size); 99 | 100 | StartCoroutine (PFUtils.updateDragCubeCoroutine (part, dragAreaScale)); 101 | } 102 | 103 | justLoaded = false; 104 | } 105 | 106 | public void scaleNode (AttachNode node, float scale, bool setSize) 107 | { 108 | if (node == null) 109 | { 110 | return; 111 | } 112 | 113 | node.position = node.originalPosition * scale; 114 | 115 | if (!justLoaded) 116 | { 117 | PFUtils.updateAttachedPartPos (node, part); 118 | } 119 | 120 | if (setSize) 121 | { 122 | node.size = Mathf.RoundToInt (scale / diameterStepLarge); 123 | } 124 | 125 | if (node.attachedPart != null) 126 | { 127 | var baseEventDatum = new BaseEventDetails (0); 128 | 129 | baseEventDatum.Set("location", node.position); 130 | baseEventDatum.Set("orientation", node.orientation); 131 | baseEventDatum.Set("secondaryAxis", node.secondaryAxis); 132 | baseEventDatum.Set("node", node); 133 | 134 | node.attachedPart.SendEvent ("OnPartAttachNodePositionChanged", baseEventDatum); 135 | } 136 | } 137 | 138 | public void setNodeSize (AttachNode node, float scale) 139 | { 140 | if (node == null) 141 | { 142 | return; 143 | } 144 | 145 | node.size = Mathf.RoundToInt (scale / diameterStepLarge); 146 | } 147 | 148 | public virtual void updateNodeSize (float scale) 149 | { 150 | setNodeSize (part.FindAttachNode ("top"), scale); 151 | setNodeSize (part.FindAttachNode ("bottom"), scale); 152 | 153 | var nodes = part.FindAttachNodes ("interstage"); 154 | 155 | if (nodes != null) 156 | { 157 | for (int i = 0; i < nodes.Length; i++) 158 | { 159 | setNodeSize (nodes [i], scale); 160 | } 161 | } 162 | } 163 | 164 | public float totalMass; 165 | 166 | public virtual void resizePart (float scale) 167 | { 168 | oldSize = size; 169 | 170 | part.mass = totalMass = ((specificMass.x * scale + specificMass.y) * scale + specificMass.z) * scale + specificMass.w; 171 | 172 | massDisplay = PFUtils.formatMass (totalMass); 173 | costDisplay = PFUtils.formatCost (part.partInfo.cost + GetModuleCost(part.partInfo.cost, ModifierStagingSituation.CURRENT) + part.partInfo.cost); 174 | 175 | part.breakingForce = specificBreakingForce * Mathf.Pow (scale, 2); 176 | part.breakingTorque = specificBreakingTorque * Mathf.Pow (scale, 2); 177 | 178 | var model = part.FindModelTransform ("model"); 179 | 180 | if (model != null) 181 | { 182 | model.localScale = Vector3.one * scale; 183 | } 184 | else 185 | { 186 | Debug.LogError ("[PF]: No 'model' transform found in part!", this); 187 | } 188 | 189 | part.rescaleFactor = scale; 190 | 191 | scaleNode(part.FindAttachNode ("top"), scale, true); 192 | scaleNode(part.FindAttachNode ("bottom"), scale, true); 193 | 194 | var nodes = part.FindAttachNodes ("interstage"); 195 | 196 | if (nodes != null) 197 | { 198 | for (int i = 0; i < nodes.Length; i++) 199 | { 200 | scaleNode (nodes [i], scale, true); 201 | } 202 | } 203 | } 204 | } 205 | 206 | public class KzFairingBaseResizer : KzPartResizer 207 | { 208 | [KSPField] public float sideThickness = 0.05f / 1.25f; 209 | 210 | public float calcSideThickness () 211 | { 212 | return Mathf.Min (sideThickness * size, size * 0.25f); 213 | } 214 | 215 | public override void updateNodeSize (float scale) 216 | { 217 | float sth = calcSideThickness (); 218 | 219 | float br = size * 0.5f - sth; 220 | scale = br * 2; 221 | 222 | base.updateNodeSize (scale); 223 | 224 | int sideNodeSize = Mathf.RoundToInt (scale / diameterStepLarge) - 1; 225 | 226 | if (sideNodeSize < 0) 227 | { 228 | sideNodeSize = 0; 229 | } 230 | 231 | var nodes = part.FindAttachNodes ("connect"); 232 | 233 | for (int i = 0; i < nodes.Length; i++) 234 | { 235 | var n = nodes [i]; 236 | 237 | n.size = sideNodeSize; 238 | } 239 | } 240 | 241 | public override void resizePart (float scale) 242 | { 243 | float sth = calcSideThickness (); 244 | 245 | float br = size * 0.5f - sth; 246 | scale = br * 2; 247 | 248 | base.resizePart (scale); 249 | 250 | var topNode = part.FindAttachNode ("top"); 251 | var bottomNode = part.FindAttachNode ("bottom"); 252 | 253 | float y = (topNode.position.y + bottomNode.position.y) * 0.5f; 254 | 255 | int sideNodeSize = Mathf.RoundToInt(scale / diameterStepLarge) - 1; 256 | 257 | if (sideNodeSize < 0) 258 | { 259 | sideNodeSize = 0; 260 | } 261 | 262 | var nodes = part.FindAttachNodes ("connect"); 263 | 264 | for (int i = 0; i < nodes.Length; i++) 265 | { 266 | var n = nodes [i]; 267 | 268 | n.position.y = y; 269 | n.size = sideNodeSize; 270 | 271 | if (!justLoaded) 272 | { 273 | PFUtils.updateAttachedPartPos (n, part); 274 | } 275 | } 276 | 277 | var nnt = part.GetComponent(); 278 | 279 | if (nnt) 280 | { 281 | nnt.radius = size * 0.5f; 282 | } 283 | 284 | var fbase = part.GetComponent(); 285 | 286 | if (fbase) 287 | { 288 | fbase.baseSize = br * 2; 289 | fbase.sideThickness = sth; 290 | fbase.needShapeUpdate = true; 291 | } 292 | } 293 | } 294 | 295 | public class KzThrustPlateResizer : KzPartResizer 296 | { 297 | public override void resizePart (float scale) 298 | { 299 | base.resizePart (scale); 300 | 301 | var node = part.FindAttachNode ("bottom"); 302 | 303 | var nodes = part.FindAttachNodes ("bottom"); 304 | 305 | for (int i = 0; i < nodes.Length; i++) 306 | { 307 | var n = nodes [i]; 308 | 309 | n.position.y = node.position.y; 310 | 311 | if (!justLoaded) 312 | { 313 | PFUtils.updateAttachedPartPos (n, part); 314 | } 315 | } 316 | 317 | var nnt = part.GetComponent(); 318 | 319 | if (nnt) 320 | { 321 | float mr = size * 0.5f; 322 | 323 | if (nnt.radius > mr) 324 | { 325 | nnt.radius = mr; 326 | } 327 | 328 | ((UI_FloatEdit) nnt.Fields["radius"].uiControlEditor).maxValue = mr; 329 | } 330 | } 331 | } 332 | } 333 | -------------------------------------------------------------------------------- /Source/ProceduralFairings/Utilities.cs: -------------------------------------------------------------------------------- 1 | // ================================================== 2 | // Procedural Fairings plug-in by Alexey Volynskov. 3 | 4 | // Licensed under CC-BY-4.0 terms: https://creativecommons.org/licenses/by/4.0/legalcode 5 | // ================================================== 6 | 7 | using System; 8 | using System.Collections.Generic; 9 | using UnityEngine; 10 | 11 | namespace Keramzit 12 | { 13 | struct BezierSlope 14 | { 15 | Vector2 p1, p2; 16 | 17 | public BezierSlope (Vector4 v) 18 | { 19 | p1 = new Vector2 (v.x, v.y); 20 | p2 = new Vector2 (v.z, v.w); 21 | } 22 | 23 | public Vector2 interp (float t) 24 | { 25 | Vector2 a = Vector2.Lerp (Vector2.zero, p1, t); 26 | Vector2 b = Vector2.Lerp (p1, p2, t); 27 | Vector2 c = Vector2.Lerp (p2, Vector2.one, t); 28 | Vector2 d = Vector2.Lerp (a, b, t); 29 | Vector2 e = Vector2.Lerp (b, c, t); 30 | 31 | return Vector2.Lerp (d, e, t); 32 | } 33 | } 34 | 35 | class Tuple 36 | { 37 | internal T1 Item1 { get; set; } 38 | internal T2 Item2 { get; set; } 39 | 40 | public Tuple (T1 item1, T2 item2) 41 | { 42 | this.Item1 = item1; 43 | this.Item2 = item2; 44 | } 45 | } 46 | 47 | public static class PFUtils 48 | { 49 | public static bool canCheckTech () 50 | { 51 | return HighLogic.LoadedSceneIsEditor && (ResearchAndDevelopment.Instance != null || (HighLogic.CurrentGame.Mode != Game.Modes.CAREER && HighLogic.CurrentGame.Mode != Game.Modes.SCIENCE_SANDBOX)); 52 | } 53 | 54 | public static bool haveTech (string name) 55 | { 56 | if (HighLogic.CurrentGame.Mode != Game.Modes.CAREER && HighLogic.CurrentGame.Mode != Game.Modes.SCIENCE_SANDBOX) 57 | { 58 | return name == "sandbox"; 59 | } 60 | 61 | return ResearchAndDevelopment.GetTechnologyState (name) == RDTech.State.Available; 62 | } 63 | 64 | public static float getTechMinValue (string cfgname, float defVal) 65 | { 66 | bool hasValue = false; 67 | float minVal = 0; 68 | 69 | var confnodes = GameDatabase.Instance.GetConfigNodes (cfgname); 70 | 71 | for (int j = 0; j < confnodes.Length; j++) 72 | { 73 | var tech = confnodes [j]; 74 | 75 | for (int i = 0; i < tech.values.Count; ++i) 76 | { 77 | var value = tech.values [i]; 78 | 79 | if (!haveTech(value.name)) 80 | { 81 | continue; 82 | } 83 | 84 | float v = float.Parse (value.value); 85 | 86 | if (!hasValue || v < minVal) 87 | { 88 | minVal = v; 89 | hasValue = true; 90 | } 91 | } 92 | } 93 | 94 | return (!hasValue) ? defVal : minVal; 95 | } 96 | 97 | public static float getTechMaxValue (string cfgname, float defVal) 98 | { 99 | bool hasValue = false; 100 | float maxVal = 0; 101 | 102 | var confnodes = GameDatabase.Instance.GetConfigNodes (cfgname); 103 | 104 | for (int j = 0; j < confnodes.Length; j++) 105 | { 106 | var tech = confnodes [j]; 107 | 108 | for (int i = 0; i < tech.values.Count; ++i) 109 | { 110 | var value = tech.values [i]; 111 | 112 | if (!haveTech(value.name)) 113 | { 114 | continue; 115 | } 116 | 117 | float v = float.Parse (value.value); 118 | 119 | if (!hasValue || v > maxVal) 120 | { 121 | maxVal = v; 122 | hasValue = true; 123 | } 124 | } 125 | } 126 | 127 | return (!hasValue) ? defVal : maxVal; 128 | } 129 | 130 | public static void setFieldRange (BaseField field, float minval, float maxval) 131 | { 132 | var fr = field.uiControlEditor as UI_FloatRange; 133 | 134 | if (fr != null) 135 | { 136 | fr.minValue = minval; 137 | fr.maxValue = maxval; 138 | } 139 | 140 | var fe = field.uiControlEditor as UI_FloatEdit; 141 | 142 | if (fe != null) 143 | { 144 | fe.minValue = minval; 145 | fe.maxValue = maxval; 146 | } 147 | } 148 | 149 | public static void updateAttachedPartPos (AttachNode node, Part part) 150 | { 151 | if (node == null || part == null) 152 | { 153 | return; 154 | } 155 | 156 | var ap = node.attachedPart; 157 | 158 | if (!ap) 159 | { 160 | return; 161 | } 162 | 163 | var an = ap.FindAttachNodeByPart (part); 164 | 165 | if (an == null) 166 | { 167 | return; 168 | } 169 | 170 | var dp = part.transform.TransformPoint (node.position) - ap.transform.TransformPoint (an.position); 171 | 172 | if (ap == part.parent) 173 | { 174 | while (ap.parent) ap = ap.parent; 175 | ap.transform.position += dp; 176 | part.transform.position -= dp; 177 | } 178 | else 179 | { 180 | ap.transform.position += dp; 181 | } 182 | } 183 | 184 | public static string formatMass (float mass) 185 | { 186 | if (mass < 0.01f) 187 | { 188 | return (mass * 1e3f).ToString ("n3") + "kg"; 189 | } 190 | 191 | return mass.ToString("n3") + "t"; 192 | } 193 | 194 | public static string formatCost (float cost) 195 | { 196 | return cost.ToString ("n0"); 197 | } 198 | 199 | public static void enableRenderer (Transform t, bool e) 200 | { 201 | if (!t) 202 | { 203 | return; 204 | } 205 | 206 | var r = t.GetComponent(); 207 | 208 | if (r) 209 | { 210 | r.enabled = e; 211 | } 212 | } 213 | 214 | public static void hideDragStuff (Part part) 215 | { 216 | enableRenderer (part.FindModelTransform ("dragOnly"), false); 217 | } 218 | 219 | public static bool FARinstalled, FARchecked; 220 | 221 | public static bool isFarInstalled () 222 | { 223 | if (!FARchecked) 224 | { 225 | var asmlist = AssemblyLoader.loadedAssemblies; 226 | 227 | if (asmlist != null) 228 | { 229 | for (int i = 0; i < asmlist.Count; i++) 230 | { 231 | if (asmlist [i].name == "FerramAerospaceResearch") 232 | { 233 | FARinstalled = true; 234 | 235 | break; 236 | } 237 | } 238 | } 239 | 240 | FARchecked = true; 241 | } 242 | 243 | return FARinstalled; 244 | } 245 | 246 | public static void updateDragCube (Part part, float areaScale) 247 | { 248 | if (isFarInstalled ()) 249 | { 250 | Debug.Log ("[PF]: Calling FAR to update voxels..."); 251 | 252 | part.SendMessage ("GeometryPartModuleRebuildMeshData"); 253 | } 254 | 255 | if (!HighLogic.LoadedSceneIsFlight) 256 | { 257 | return; 258 | } 259 | 260 | enableRenderer (part.FindModelTransform ("dragOnly"), true); 261 | 262 | var dragCube = DragCubeSystem.Instance.RenderProceduralDragCube (part); 263 | 264 | enableRenderer (part.FindModelTransform ("dragOnly"), false); 265 | 266 | for (int i = 0; i < 6; ++i) 267 | { 268 | dragCube.Area [i] *= areaScale; 269 | } 270 | 271 | part.DragCubes.ClearCubes (); 272 | part.DragCubes.Cubes.Add (dragCube); 273 | part.DragCubes.ResetCubeWeights (); 274 | } 275 | 276 | public static IEnumerator updateDragCubeCoroutine (Part part, float areaScale) 277 | { 278 | while (true) 279 | { 280 | if (part == null || part.Equals (null)) 281 | { 282 | yield break; 283 | } 284 | 285 | if (HighLogic.LoadedSceneIsFlight) 286 | { 287 | if (part.vessel == null || part.vessel.Equals (null)) 288 | { 289 | yield break; 290 | } 291 | 292 | if (!FlightGlobals.ready || part.packed || !part.vessel.loaded) 293 | { 294 | yield return new WaitForFixedUpdate (); 295 | 296 | continue; 297 | } 298 | 299 | break; 300 | } 301 | 302 | if (HighLogic.LoadedSceneIsEditor) 303 | { 304 | yield return new WaitForFixedUpdate (); 305 | 306 | break; 307 | } 308 | 309 | yield break; 310 | } 311 | 312 | PFUtils.updateDragCube (part, areaScale); 313 | } 314 | 315 | public static void refreshPartWindow () 316 | { 317 | var objs = UnityEngine.Object.FindObjectsOfType(); 318 | 319 | for (int i = 0; i < objs.Length; i++) 320 | { 321 | var w = objs [i]; 322 | 323 | w.displayDirty = true; 324 | } 325 | } 326 | 327 | public static Part partFromHit (this RaycastHit hit) 328 | { 329 | if (hit.collider == null || hit.collider.gameObject == null) 330 | { 331 | return null; 332 | } 333 | 334 | var go = hit.collider.gameObject; 335 | 336 | var p = Part.FromGO (go); 337 | 338 | while (p == null) 339 | { 340 | if (go.transform != null && go.transform.parent != null && go.transform.parent.gameObject != null) 341 | { 342 | go = go.transform.parent.gameObject; 343 | } 344 | else 345 | { 346 | break; 347 | } 348 | 349 | p = Part.FromGO (go); 350 | } 351 | 352 | return p; 353 | } 354 | 355 | public static List getAllChildrenRecursive (this Part rootPart, bool root) 356 | { 357 | var children = new List(); 358 | 359 | if (!root) 360 | { 361 | children.Add (rootPart); 362 | } 363 | 364 | for (int i = 0; i < rootPart.children.Count; i++) 365 | { 366 | var child = rootPart.children [i]; 367 | 368 | children.AddRange (child.getAllChildrenRecursive (false)); 369 | } 370 | 371 | return children; 372 | } 373 | 374 | public static float GetMaxValueFromList (List list) 375 | { 376 | float max = 0; 377 | 378 | for (int i = 0; i < list.Count; i++) 379 | { 380 | if (max < list [i]) 381 | { 382 | max = list [i]; 383 | } 384 | } 385 | 386 | return max; 387 | } 388 | } 389 | 390 | [KSPAddon (KSPAddon.Startup.EditorAny, false)] 391 | 392 | public class EditorScreenMessager : MonoBehaviour 393 | { 394 | static float osdMessageTime; 395 | static string osdMessageText; 396 | 397 | public static void showMessage (string msg, float delay) 398 | { 399 | osdMessageText = msg; 400 | osdMessageTime = Time.time + delay; 401 | } 402 | 403 | void OnGUI () 404 | { 405 | if (!HighLogic.LoadedSceneIsEditor) 406 | { 407 | return; 408 | } 409 | 410 | if (Time.time < osdMessageTime) 411 | { 412 | GUI.skin = HighLogic.Skin; 413 | 414 | var style = new GUIStyle ("Label"); 415 | 416 | style.alignment = TextAnchor.MiddleCenter; 417 | style.fontSize = 20; 418 | style.normal.textColor = Color.black; 419 | 420 | GUI.Label (new Rect (2, 2 + (Screen.height / 9), Screen.width, 50), osdMessageText, style); 421 | 422 | style.normal.textColor = Color.yellow; 423 | 424 | GUI.Label (new Rect (0, Screen.height / 9, Screen.width, 50), osdMessageText, style); 425 | } 426 | } 427 | } 428 | } 429 | -------------------------------------------------------------------------------- /Unity/FairingBase.blend: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsparkyc/ProceduralFairings/fbbefcd1545e8cd904c1ed102856d7fe60de50c0/Unity/FairingBase.blend -------------------------------------------------------------------------------- /Unity/FairingBaseRing.blend: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsparkyc/ProceduralFairings/fbbefcd1545e8cd904c1ed102856d7fe60de50c0/Unity/FairingBaseRing.blend -------------------------------------------------------------------------------- /Unity/FairingSide.blend: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsparkyc/ProceduralFairings/fbbefcd1545e8cd904c1ed102856d7fe60de50c0/Unity/FairingSide.blend -------------------------------------------------------------------------------- /Unity/Materials/Material.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsparkyc/ProceduralFairings/fbbefcd1545e8cd904c1ed102856d7fe60de50c0/Unity/Materials/Material.mat -------------------------------------------------------------------------------- /Unity/Materials/No Name.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsparkyc/ProceduralFairings/fbbefcd1545e8cd904c1ed102856d7fe60de50c0/Unity/Materials/No Name.mat -------------------------------------------------------------------------------- /Unity/Materials/baseRingTex.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsparkyc/ProceduralFairings/fbbefcd1545e8cd904c1ed102856d7fe60de50c0/Unity/Materials/baseRingTex.mat -------------------------------------------------------------------------------- /Unity/Materials/baseTex.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsparkyc/ProceduralFairings/fbbefcd1545e8cd904c1ed102856d7fe60de50c0/Unity/Materials/baseTex.mat -------------------------------------------------------------------------------- /Unity/Materials/fairing1.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsparkyc/ProceduralFairings/fbbefcd1545e8cd904c1ed102856d7fe60de50c0/Unity/Materials/fairing1.mat -------------------------------------------------------------------------------- /Unity/Materials/thrustPlate1.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsparkyc/ProceduralFairings/fbbefcd1545e8cd904c1ed102856d7fe60de50c0/Unity/Materials/thrustPlate1.mat -------------------------------------------------------------------------------- /Unity/ThrustPlate.blend: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsparkyc/ProceduralFairings/fbbefcd1545e8cd904c1ed102856d7fe60de50c0/Unity/ThrustPlate.blend -------------------------------------------------------------------------------- /Unity/baseRingTex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsparkyc/ProceduralFairings/fbbefcd1545e8cd904c1ed102856d7fe60de50c0/Unity/baseRingTex.png -------------------------------------------------------------------------------- /Unity/baseTex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsparkyc/ProceduralFairings/fbbefcd1545e8cd904c1ed102856d7fe60de50c0/Unity/baseTex.png -------------------------------------------------------------------------------- /Unity/fairing1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsparkyc/ProceduralFairings/fbbefcd1545e8cd904c1ed102856d7fe60de50c0/Unity/fairing1.png -------------------------------------------------------------------------------- /Unity/scene.unity: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsparkyc/ProceduralFairings/fbbefcd1545e8cd904c1ed102856d7fe60de50c0/Unity/scene.unity -------------------------------------------------------------------------------- /Unity/thrustPlate1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsparkyc/ProceduralFairings/fbbefcd1545e8cd904c1ed102856d7fe60de50c0/Unity/thrustPlate1.png -------------------------------------------------------------------------------- /Unity/thrustPlate1bump.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsparkyc/ProceduralFairings/fbbefcd1545e8cd904c1ed102856d7fe60de50c0/Unity/thrustPlate1bump.png -------------------------------------------------------------------------------- /Unity/thrustPlate1bump_Normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsparkyc/ProceduralFairings/fbbefcd1545e8cd904c1ed102856d7fe60de50c0/Unity/thrustPlate1bump_Normal.png --------------------------------------------------------------------------------