diff --git a/data/stock/bodies.yml b/data/stock/bodies.yml index 230a8f0..e1f98c9 100644 --- a/data/stock/bodies.yml +++ b/data/stock/bodies.yml @@ -7,8 +7,8 @@ # mass: kg # stdGravParam: m^3/s^2 # soi: m -# apoapsis: m -# periapsis: m +# apoapsis: m - optional +# periapsis: m - optional # eccentricity: None # inclination: ° (degrees) # argOfPeriapsis: ° @@ -19,6 +19,10 @@ # EDIT NOTES FOR CUSTOM SOLAR SYSTEMS +# If your solar system uses Kopernicus' configuration files, you can directly convert them +# into a `bodies.yml` file on this page : https://krafpy.github.io/KSP-MGA-Planner/tools/cfg-to-yml/ + +# For custom solar systems, the following rules apply to all `bodies.yml`: # - Follow the exact same format (names, indentations) as used in this file # - Numerical data must follow the units described above # - Each body has a unique ID, it must be an integer between 0 and N-1, where N is the number of bodies diff --git a/dist/tools/cfg-to-yml/body-data.js b/dist/tools/cfg-to-yml/body-data.js index 825c6b3..8d0efcd 100644 --- a/dist/tools/cfg-to-yml/body-data.js +++ b/dist/tools/cfg-to-yml/body-data.js @@ -58,6 +58,25 @@ export function parseToBodyConfig(bodyConfig, templateBodies) { }, }; } +export function completeBodytoUnorderedData(body) { + return { + name: body.name, + radius: body.radius, + mass: body.mass, + stdGravParam: body.stdGravParam, + soi: body.soi, + orbit: { + semiMajorAxis: body.orbit.semiMajorAxis, + eccentricity: body.orbit.eccentricity, + inclination: body.orbit.inclination, + argOfPeriapsis: body.orbit.argOfPeriapsis, + ascNodeLongitude: body.orbit.ascNodeLongitude, + }, + meanAnomaly0: body.meanAnomaly0, + epoch: body.epoch, + color: body.color, + }; +} function deduceStdGravParamAndMass(bodyConfig, radius, template) { let stdGravParam = 0, mass = 0; if (bodyConfig.Properties.gravParameter !== undefined) { diff --git a/dist/tools/cfg-to-yml/main.js b/dist/tools/cfg-to-yml/main.js index 6a9b4de..06eed57 100644 --- a/dist/tools/cfg-to-yml/main.js +++ b/dist/tools/cfg-to-yml/main.js @@ -1,5 +1,5 @@ import { loadBodiesData } from "../../main/utilities/data.js"; -import { orderOrbitingBodies, parseToBodyConfig, parseToSunConfig, recomputeSOIs } from "./body-data.js"; +import { completeBodytoUnorderedData, orderOrbitingBodies, parseToBodyConfig, parseToSunConfig, recomputeSOIs } from "./body-data.js"; import { parseConfigNodes } from "./cfg-parser.js"; import { dumpBodyToYaml, dumpSunToYaml, joinYamlBlocks } from "./dump.js"; import { readFilesFromInput } from "./file-reader.js"; @@ -16,6 +16,7 @@ async function main() { const convertBtn = document.getElementById("convert-btn"); const downloadBtn = document.getElementById("download-btn"); const filesInput = document.getElementById("files-input"); + const combineChkBox = document.getElementById("combine-checkbox"); const convert = async () => { var _a; if (!((_a = filesInput.files) === null || _a === void 0 ? void 0 : _a.length)) @@ -30,12 +31,18 @@ async function main() { configs.push(parseConfigNodes(content)); } const sunConfig = configs.find(c => { var _a; return ((_a = c.Orbit) === null || _a === void 0 ? void 0 : _a.referenceBody) === undefined; }); - if (sunConfig === undefined) { - throw new Error("Sun configuration not found."); + let sun; + if (sunConfig !== undefined) { + const unorderedSun = parseToSunConfig(sunConfig, template); + sun = { id: 0, ...unorderedSun }; + } + else { + if (!combineChkBox.checked) { + throw new Error("Sun configuration not found."); + } + TextareaLogger.log("Using stock Sun"); + sun = template.get("Sun"); } - const unorderedSun = parseToSunConfig(sunConfig, template); - const sun = { id: 0, ...unorderedSun }; - TextareaLogger.log(`Ordering...`); const orbitingUnordered = []; for (const config of configs) { if (config.Orbit) { @@ -43,6 +50,10 @@ async function main() { orbitingUnordered.push(orbiting); } } + if (combineChkBox.checked) { + completeWithStock(orbitingUnordered, stockBodies.bodies, sun.name); + } + TextareaLogger.log(`Ordering...`); const orbiting = orderOrbitingBodies(orbitingUnordered, sun.name); TextareaLogger.log("Recomputing SOIs..."); recomputeSOIs(orbiting, sun); @@ -50,14 +61,34 @@ async function main() { const sunYml = dumpSunToYaml(sun); const orbitingYml = orbiting.map(body => dumpBodyToYaml(body)); const yml = joinYamlBlocks([sunYml, ...orbitingYml]); - TextareaLogger.log(`\nSuccessfully converted solar system data.`); downloadBtn.onclick = () => download("bodies.yml", yml); + TextareaLogger.log(`\nSuccessfully converted solar system data.`); TextareaLogger.log(`Click to download \`bodies.yml\``); }; convertBtn.onclick = () => { convert().catch(reason => TextareaLogger.error(reason)); }; } +function completeWithStock(unorderedOrbiting, stockOrbiting, sunName) { + const definedOrbiting = new Set(); + for (const { data } of unorderedOrbiting) { + definedOrbiting.add(data.name); + } + for (const body of stockOrbiting) { + if (definedOrbiting.has(body.name)) + continue; + TextareaLogger.log(`Using stock ${body.name}`); + let referenceBody = sunName; + if (body.orbiting != 0) { + const idx = body.orbiting - 1; + referenceBody = stockOrbiting[idx].name; + } + unorderedOrbiting.push({ + referenceBody, + data: completeBodytoUnorderedData(body) + }); + } +} function download(filename, text) { const element = document.createElement('a'); const encoded = encodeURIComponent(text); diff --git a/src/tools/cfg-to-yml/body-data.ts b/src/tools/cfg-to-yml/body-data.ts index 75ae469..3968597 100644 --- a/src/tools/cfg-to-yml/body-data.ts +++ b/src/tools/cfg-to-yml/body-data.ts @@ -76,6 +76,27 @@ export function parseToBodyConfig(bodyConfig: any, templateBodies: Map { if(!filesInput.files?.length) return; @@ -39,13 +40,17 @@ async function main(){ // extract ICelestiaBody data for the sun const sunConfig = configs.find(c => c.Orbit?.referenceBody === undefined); - if(sunConfig === undefined){ - throw new Error("Sun configuration not found."); + let sun: ICelestialBody; + if(sunConfig !== undefined){ + const unorderedSun = parseToSunConfig(sunConfig, template); + sun = {id: 0, ...unorderedSun}; + } else { + if(!combineChkBox.checked){ + throw new Error("Sun configuration not found."); + } + TextareaLogger.log("Using stock Sun"); + sun = template.get("Sun") as ICelestialBody; } - const unorderedSun = parseToSunConfig(sunConfig, template); - const sun: ICelestialBody = {id: 0, ...unorderedSun}; - - TextareaLogger.log(`Ordering...`); // extract IOribitingBody_Unordered (without id and orbiting) // data for other bodies @@ -57,6 +62,14 @@ async function main(){ } } + // Combine with stock bodies, only add ones that have not been redefined + // in a cfg file + if(combineChkBox.checked){ + completeWithStock(orbitingUnordered, stockBodies.bodies, sun.name); + } + + TextareaLogger.log(`Ordering...`); + // Compute bodies's ids and sort them in the correct order const orbiting = orderOrbitingBodies(orbitingUnordered, sun.name); @@ -71,10 +84,9 @@ async function main(){ const orbitingYml = orbiting.map(body => dumpBodyToYaml(body)); const yml = joinYamlBlocks([sunYml, ...orbitingYml]); - TextareaLogger.log(`\nSuccessfully converted solar system data.`); - downloadBtn.onclick = () => download("bodies.yml", yml); + TextareaLogger.log(`\nSuccessfully converted solar system data.`); TextareaLogger.log(`Click to download \`bodies.yml\``); }; @@ -83,14 +95,37 @@ async function main(){ }; } +function completeWithStock(unorderedOrbiting: ParsedUnorderedOrbitingData[], stockOrbiting: IOrbitingBody[], sunName: string){ + const definedOrbiting = new Set(); + for(const {data} of unorderedOrbiting) { + definedOrbiting.add(data.name); + } + + for(const body of stockOrbiting){ + if(definedOrbiting.has(body.name)) continue; + + TextareaLogger.log(`Using stock ${body.name}`); + + let referenceBody = sunName; + if(body.orbiting != 0){ + const idx = body.orbiting - 1; + referenceBody = stockOrbiting[idx].name; + } + unorderedOrbiting.push({ + referenceBody, + data: completeBodytoUnorderedData(body) + }); + } +} + function download(filename: string, text: string) { const element = document.createElement('a'); const encoded = encodeURIComponent(text); element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encoded); element.setAttribute('download', filename); - + element.style.display = 'none'; document.body.appendChild(element); element.click(); document.body.removeChild(element); - } \ No newline at end of file +} \ No newline at end of file diff --git a/tools/cfg-to-yml/index.html b/tools/cfg-to-yml/index.html index cfca88a..ef2c28f 100644 --- a/tools/cfg-to-yml/index.html +++ b/tools/cfg-to-yml/index.html @@ -5,7 +5,7 @@ - + CFG converter for MGA Planner @@ -15,21 +15,30 @@

Kopernicus .CFG converter for KSP MGA Planner

Use this page to quickly convert Kopernicus' configuration files (.cfg) of solar systems to the `bodies.yml` - file used by the MGA planner tool. + file used by MGA planner.

- Select all .cfg files describing the solar system's bodies only, including the sun. + Select all .cfg files describing the solar system's bodies only. + Check the "Combine with stock" checkbox if the solar system is an extension to the stock one: missing configuration + files for stock bodies will be added automatically.

- Follow then these steps to - add the new solar system to the tool by contributing to the repository. + Follow then these steps + to add the new solar system to the tool by contributing to the repository.

-
- -
+
+
+ +
+ + +
+
+
+
diff --git a/tools/cfg-to-yml/style.css b/tools/cfg-to-yml/style.css index 2f9087d..01f2372 100644 --- a/tools/cfg-to-yml/style.css +++ b/tools/cfg-to-yml/style.css @@ -1,21 +1,58 @@ +body +{ + font-family: "Helvetica Neue", Helvetica; + /*background-color: #222425;*/ + background: #1c1e1f; + color: rgb(200, 195, 188); + display: flex; + align-items: center; +} + +p +{ + font-size: 0.8em; +} + +a:link +{ + color: rgb(86, 169, 224); + text-decoration: none; +} + +a:hover +{ + color: rgb(116, 190, 240); +} + #container { + display: inline-block; + margin-left: auto; + margin-right: auto; + margin-top: 50px; width: 570px; } -#inputs +#controls { display: flex; - align-items: center; + align-items: flex-end; justify-content: space-between; -} -#files-input -{ margin-top: 30px; margin-bottom: 30px; } +#combine-checkbox +{ + margin-top: 20px; +} + +#checkbox-container label +{ + font-size: 0.8em; +} + #log-box { width: 100%; @@ -38,9 +75,4 @@ button { width: 6em; -} - -/*p, button, input -{ - font-size: 0.85em; -}*/ \ No newline at end of file +} \ No newline at end of file