From 53a43b55363f02764f4e04c9e03c3685e0221928 Mon Sep 17 00:00:00 2001 From: Pax1601 Date: Sat, 18 May 2024 17:51:22 +0200 Subject: [PATCH] More work on new ui --- .../react/src/ui/panels/unitcontrolmenu.tsx | 2 +- .../src/ui/panels/unitmousecontrolbar.tsx | 55 ++++++++ frontend/react/src/ui/ui.tsx | 15 ++- frontend/react/src/unit/contextaction.ts | 9 +- frontend/react/src/unit/contextactionset.ts | 12 +- frontend/react/src/unit/unit.ts | 124 +++++++----------- scripts/python/map_generator/.gitignore | 3 +- .../python/map_generator/.vscode/launch.json | 8 -- 8 files changed, 127 insertions(+), 101 deletions(-) create mode 100644 frontend/react/src/ui/panels/unitmousecontrolbar.tsx diff --git a/frontend/react/src/ui/panels/unitcontrolmenu.tsx b/frontend/react/src/ui/panels/unitcontrolmenu.tsx index 5ce2e20a..b7ab0704 100644 --- a/frontend/react/src/ui/panels/unitcontrolmenu.tsx +++ b/frontend/react/src/ui/panels/unitcontrolmenu.tsx @@ -55,7 +55,7 @@ export function UnitControlMenu() { updateData(); }) - /* When all units are selected clean the view */ + /* When all units are deselected clean the view */ document.addEventListener("clearSelection", () => { setOpen(false); setSelectedUnits([]) diff --git a/frontend/react/src/ui/panels/unitmousecontrolbar.tsx b/frontend/react/src/ui/panels/unitmousecontrolbar.tsx new file mode 100644 index 00000000..7812044e --- /dev/null +++ b/frontend/react/src/ui/panels/unitmousecontrolbar.tsx @@ -0,0 +1,55 @@ +import React, { useEffect, useState } from 'react'; +import { Unit } from '../../unit/unit'; +import { ContextActionSet } from '../../unit/contextactionset'; +import { OlStateButton } from '../components/olstatebutton'; +import { faAccessibleIcon } from '@fortawesome/free-brands-svg-icons'; +import { faCamera } from '@fortawesome/free-solid-svg-icons'; +import { getApp } from '../../olympusapp'; + +export function UnitMouseControlBar(props: { + +}) { + var [open, setOpen] = useState(false); + var [selectedUnits, setSelectedUnits] = useState([] as Unit[]); + var [contextActionsSet, setContextActionsSet] = useState(new ContextActionSet()); + + /* When a unit is selected, open the menu */ + document.addEventListener("unitsSelection", (ev: CustomEventInit) => { + setOpen(true); + setSelectedUnits(ev.detail as Unit[]); + + updateData(); + }) + + /* When a unit is deselected, refresh the view */ + document.addEventListener("unitDeselection", (ev: CustomEventInit) => { + /* TODO add delay to avoid doing it too many times */ + updateData(); + }) + + /* When all units are deselected clean the view */ + document.addEventListener("clearSelection", () => { + setOpen(false); + setSelectedUnits([]); + updateData(); + }) + + /* Update the current values of the shown data */ + function updateData() { + var newContextActionSet = new ContextActionSet(); + + getApp().getUnitsManager().getSelectedUnits().forEach((unit: Unit) => { + unit.appendContextActions(newContextActionSet); + }) + + setContextActionsSet(newContextActionSet); + } + + return
+ { + Object.values(contextActionsSet.getContextActions()).map((contextAction) => { + return {}} /> + }) + } +
+} \ No newline at end of file diff --git a/frontend/react/src/ui/ui.tsx b/frontend/react/src/ui/ui.tsx index 9435bdfc..3447b82d 100644 --- a/frontend/react/src/ui/ui.tsx +++ b/frontend/react/src/ui/ui.tsx @@ -1,4 +1,4 @@ -import React, { useState } from 'react' +import React, { useEffect, useState } from 'react' import './ui.css' import { EventsProvider } from '../eventscontext' @@ -15,6 +15,7 @@ import { BLUE_COMMANDER, GAME_MASTER, MAP_HIDDEN_TYPES_DEFAULTS, MAP_OPTIONS_DEF import { getApp, setupApp } from '../olympusapp' import { LoginModal } from './modals/login' import { sha256 } from 'js-sha256' +import { UnitMouseControlBar } from './panels/unitmousecontrolbar' export type OlympusState = { mainMenuVisible: boolean, @@ -28,7 +29,7 @@ export type OlympusState = { } export function UI() { - var [loginModalVisible, setLoginModalVisible] = useState(true); + var [loginModalVisible, setLoginModalVisible] = useState(false /* Temporary during devel */); var [mainMenuVisible, setMainMenuVisible] = useState(false); var [spawnMenuVisible, setSpawnMenuVisible] = useState(false); var [unitControlMenuVisible, setUnitControlMenuVisible] = useState(false); @@ -84,6 +85,15 @@ export function UI() { setLoginModalVisible(false); } + /* Temporary during devel */ + useEffect(() => { + window.setTimeout(() => { + checkPassword("admin"); + connect("devel"); + }, 1000) + }, []) + + return (
setOptionsMenuVisible(false)} /> +
diff --git a/frontend/react/src/unit/contextaction.ts b/frontend/react/src/unit/contextaction.ts index dd3a4b6b..a6087d9c 100644 --- a/frontend/react/src/unit/contextaction.ts +++ b/frontend/react/src/unit/contextaction.ts @@ -1,3 +1,4 @@ +import { IconDefinition } from "@fortawesome/fontawesome-svg-core"; import { Unit } from "./unit"; export interface ContextActionOptions { @@ -11,13 +12,15 @@ export class ContextAction { #callback: CallableFunction | null = null; #units: Unit[] = []; #hideContextAfterExecution: boolean = true + #icon: IconDefinition; #options: ContextActionOptions; - constructor(id: string, label: string, description: string, callback: CallableFunction, hideContextAfterExecution: boolean = true, options: ContextActionOptions) { + constructor(id: string, label: string, description: string, icon: IconDefinition, callback: CallableFunction, hideContextAfterExecution: boolean = true, options: ContextActionOptions) { this.#id = id; this.#label = label; this.#description = description; this.#callback = callback; + this.#icon = icon; this.#hideContextAfterExecution = hideContextAfterExecution; this.#options = { "isScenic": false, @@ -49,6 +52,10 @@ export class ContextAction { return this.#callback; } + getIcon() { + return this.#icon; + } + executeCallback() { if (this.#callback) this.#callback(this.#units); diff --git a/frontend/react/src/unit/contextactionset.ts b/frontend/react/src/unit/contextactionset.ts index d061cd1d..833ec3a3 100644 --- a/frontend/react/src/unit/contextactionset.ts +++ b/frontend/react/src/unit/contextactionset.ts @@ -1,18 +1,16 @@ +import { LatLng } from "leaflet"; import { ContextAction, ContextActionOptions } from "./contextaction"; import { Unit } from "./unit"; +import { IconDefinition } from "@fortawesome/fontawesome-svg-core"; export class ContextActionSet { #contextActions: {[key: string]: ContextAction} = {}; - constructor() { - - } - - addContextAction(unit: Unit, id: string, label: string, description: string, callback: CallableFunction, hideContextAfterExecution: boolean = true, options?:ContextActionOptions) { + addContextAction(unit: Unit, id: string, label: string, description: string, icon: IconDefinition, callback: (units: Unit[], targetUnit: Unit, targetPosition: LatLng) => void, hideContextAfterExecution: boolean = true, options?:ContextActionOptions) { options = options || {}; if (!(id in this.#contextActions)) { - this.#contextActions[id] = new ContextAction(id, label, description, callback, hideContextAfterExecution, options); + this.#contextActions[id] = new ContextAction(id, label, description, icon, callback, hideContextAfterExecution, options); } this.#contextActions[id].addUnit(unit); } @@ -20,6 +18,4 @@ export class ContextActionSet { getContextActions() { return this.#contextActions; } - - } \ No newline at end of file diff --git a/frontend/react/src/unit/unit.ts b/frontend/react/src/unit/unit.ts index 5c587393..2113e6da 100644 --- a/frontend/react/src/unit/unit.ts +++ b/frontend/react/src/unit/unit.ts @@ -15,6 +15,8 @@ import { RangeCircle } from "../map/rangecircle"; import { Group } from './group'; import { ContextActionSet } from './contextactionset'; import * as turf from "@turf/turf"; +import { olIconsDiamond, olIconsEchelonLh, olIconsEchelonRh, olIconsFollow, olIconsFront, olIconsGroupGround, olIconsLandAtPoint, olIconsLineAbreast, olIconsTrail, olStatesAttack, olStatesRefuel } from '../ui/components/olicons'; +import { faArrowDown, faExclamation, faQuestionCircle } from '@fortawesome/free-solid-svg-icons'; var pathIcon = new Icon({ iconUrl: '/resources/theme/images/markers/marker-icon.png', @@ -230,7 +232,7 @@ export abstract class Unit extends CustomMarker { /** Get the actions that this unit can perform * */ - abstract appendContextActions(contextActionSet: ContextActionSet, targetUnit: Unit | null, targetPosition: LatLng | null): void; + abstract appendContextActions(contextActionSet: ContextActionSet): void; /** * @@ -998,14 +1000,14 @@ export abstract class Unit extends CustomMarker { showFollowOptions(units: Unit[]) { var contextActionSet = new ContextActionSet(); - contextActionSet.addContextAction(this, 'trail', "Trail", "Follow unit in trail formation", () => this.applyFollowOptions('trail', units)); - contextActionSet.addContextAction(this, 'echelon-lh', "Echelon (LH)", "Follow unit in echelon left formation", () => this.applyFollowOptions('echelon-lh', units)); - contextActionSet.addContextAction(this, 'echelon-rh', "Echelon (RH)", "Follow unit in echelon right formation", () => this.applyFollowOptions('echelon-rh', units)); - contextActionSet.addContextAction(this, 'line-abreast-lh', "Line abreast (LH)", "Follow unit in line abreast left formation", () => this.applyFollowOptions('line-abreast-lh', units)); - contextActionSet.addContextAction(this, 'line-abreast-rh', "Line abreast (RH)", "Follow unit in line abreast right formation", () => this.applyFollowOptions('line-abreast-rh', units)); - contextActionSet.addContextAction(this, 'front', "Front", "Fly in front of unit", () => this.applyFollowOptions('front', units)); - contextActionSet.addContextAction(this, 'diamond', "Diamond", "Follow unit in diamond formation", () => this.applyFollowOptions('diamond', units)); - contextActionSet.addContextAction(this, 'custom', "Custom", "Set a custom formation position", () => this.applyFollowOptions('custom', units)); + contextActionSet.addContextAction(this, 'trail', "Trail", "Follow unit in trail formation", olIconsTrail, () => this.applyFollowOptions('trail', units)); + contextActionSet.addContextAction(this, 'echelon-lh', "Echelon (LH)", "Follow unit in echelon left formation", olIconsEchelonLh, () => this.applyFollowOptions('echelon-lh', units)); + contextActionSet.addContextAction(this, 'echelon-rh', "Echelon (RH)", "Follow unit in echelon right formation", olIconsEchelonRh, () => this.applyFollowOptions('echelon-rh', units)); + contextActionSet.addContextAction(this, 'line-abreast-lh', "Line abreast (LH)", "Follow unit in line abreast left formation", olIconsLineAbreast, () => this.applyFollowOptions('line-abreast-lh', units)); + contextActionSet.addContextAction(this, 'line-abreast-rh', "Line abreast (RH)", "Follow unit in line abreast right formation", olIconsLineAbreast, () => this.applyFollowOptions('line-abreast-rh', units)); + contextActionSet.addContextAction(this, 'front', "Front", "Fly in front of unit", olIconsFront, () => this.applyFollowOptions('front', units)); + contextActionSet.addContextAction(this, 'diamond', "Diamond", "Follow unit in diamond formation", olIconsDiamond, () => this.applyFollowOptions('diamond', units)); + contextActionSet.addContextAction(this, 'custom', "Custom", "Set a custom formation position", faExclamation, () => this.applyFollowOptions('custom', units)); //getApp().getMap().getUnitContextMenu().setContextActions(contextActionSet); getApp().getMap().showUnitContextMenu(); @@ -1091,7 +1093,7 @@ export abstract class Unit extends CustomMarker { units.push(this); units.forEach((unit: Unit) => { - unit.appendContextActions(contextActionSet, this, null); + unit.appendContextActions(contextActionSet); }) if (Object.keys(contextActionSet.getContextActions()).length > 0) { @@ -1495,24 +1497,13 @@ export abstract class AirUnit extends Unit { }; } - appendContextActions(contextActionSet: ContextActionSet, targetUnit: Unit | null, targetPosition: LatLng | null) { - if (targetUnit !== null) { - if (targetUnit != this) { - contextActionSet.addContextAction(this, "attack", "Attack unit", "Attack the unit using A/A or A/G weapons", (units: Unit[]) => { getApp().getUnitsManager().attackUnit(targetUnit.ID, units) }); - contextActionSet.addContextAction(this, "follow", "Follow unit", "Follow this unit in formation", (units: Unit[]) => { targetUnit.showFollowOptions(units); }, false); // Don't hide the context menu after the execution (to show the follow options) - } - if (targetUnit.getSelected()) { - contextActionSet.addContextAction(this, "refuel", "Refuel", "Refuel units at the nearest AAR Tanker. If no tanker is available the unit will RTB", (units: Unit[]) => { getApp().getUnitsManager().refuel(units) }); - } - if (getApp().getUnitsManager().getSelectedUnits().length == 1 && targetUnit === this) { - contextActionSet.addContextAction(this, "center-map", "Center map", "Center the map on the unit and follow it", () => { getApp().getMap().centerOnUnit(this.ID); }); - } - } - - if (targetPosition !== null) { - contextActionSet.addContextAction(this, "bomb", "Precision bombing", "Precision bombing of a specific point", (units: Unit[]) => { getApp().getUnitsManager().bombPoint(targetPosition, units) }); - contextActionSet.addContextAction(this, "carpet-bomb", "Carpet bombing", "Carpet bombing close to a point", (units: Unit[]) => { getApp().getUnitsManager().carpetBomb(targetPosition, units) }); - } + appendContextActions(contextActionSet: ContextActionSet) { + contextActionSet.addContextAction(this, "attack", "Attack unit", "Attack the unit using A/A or A/G weapons", olStatesAttack, (units: Unit[], targetUnit: Unit, targetPosition: LatLng) => { getApp().getUnitsManager().attackUnit(targetUnit.ID, units) }); + contextActionSet.addContextAction(this, "follow", "Follow unit", "Follow this unit in formation", olIconsFollow, (units: Unit[], targetUnit: Unit, targetPosition: LatLng) => { targetUnit.showFollowOptions(units); }, false); // Don't hide the context menu after the execution (to show the follow options) + contextActionSet.addContextAction(this, "refuel", "Refuel", "Refuel units at the nearest AAR Tanker. If no tanker is available the unit will RTB", olStatesRefuel, (units: Unit[]) => { getApp().getUnitsManager().refuel(units) }); + contextActionSet.addContextAction(this, "center-map", "Center map", "Center the map on the unit and follow it", faQuestionCircle, () => { getApp().getMap().centerOnUnit(this.ID); }); + contextActionSet.addContextAction(this, "bomb", "Precision bombing", "Precision bombing of a specific point", faQuestionCircle, (units: Unit[], targetUnit: Unit, targetPosition: LatLng) => { getApp().getUnitsManager().bombPoint(targetPosition, units) }); + contextActionSet.addContextAction(this, "carpet-bomb", "Carpet bombing", "Carpet bombing close to a point", faQuestionCircle, (units: Unit[], targetUnit: Unit, targetPosition: LatLng) => { getApp().getUnitsManager().carpetBomb(targetPosition, units) }); } } @@ -1525,12 +1516,8 @@ export class Aircraft extends AirUnit { return "Aircraft"; } - appendContextActions(contextActionSet: ContextActionSet, targetUnit: Unit | null, targetPosition: LatLng | null) { - super.appendContextActions(contextActionSet, targetUnit, targetPosition); - - if (targetPosition === null && this.getSelected()) { - contextActionSet.addContextAction(this, "refuel", "Refuel", "Refuel units at the nearest AAR Tanker. If no tanker is available the unit will RTB", (units: Unit[]) => { getApp().getUnitsManager().refuel(units) }); - } + appendContextActions(contextActionSet: ContextActionSet) { + super.appendContextActions(contextActionSet); } getMarkerCategory() { @@ -1551,11 +1538,9 @@ export class Helicopter extends AirUnit { return "Helicopter"; } - appendContextActions(contextActionSet: ContextActionSet, targetUnit: Unit | null, targetPosition: LatLng | null) { - super.appendContextActions(contextActionSet, targetUnit, targetPosition); - - if (targetPosition !== null) - contextActionSet.addContextAction(this, "land-at-point", "Land here", "land at this precise location", (units: Unit[]) => { getApp().getUnitsManager().landAtPoint(targetPosition, units) }); + appendContextActions(contextActionSet: ContextActionSet) { + super.appendContextActions(contextActionSet); + contextActionSet.addContextAction(this, "land-at-point", "Land here", "Land at this precise location", olIconsLandAtPoint, (units: Unit[], targetUnit: Unit, targetPosition: LatLng) => { getApp().getUnitsManager().landAtPoint(targetPosition, units) }); } getMarkerCategory() { @@ -1589,34 +1574,23 @@ export class GroundUnit extends Unit { }; } - appendContextActions(contextActionSet: ContextActionSet, targetUnit: Unit | null, targetPosition: LatLng | null) { - contextActionSet.addContextAction(this, "group-ground", "Group ground units", "Create a group of ground units", (units: Unit[]) => { getApp().getUnitsManager().createGroup(units) }); - - if (targetUnit !== null) { - if (targetUnit != this) { - contextActionSet.addContextAction(this, "attack", "Attack unit", "Attack the unit using A/A or A/G weapons", (units: Unit[]) => { getApp().getUnitsManager().attackUnit(targetUnit.ID, units) }); - } - - if (getApp().getUnitsManager().getSelectedUnits().length == 1 && targetUnit === this) { - contextActionSet.addContextAction(this, "center-map", "Center map", "Center the map on the unit and follow it", () => { getApp().getMap().centerOnUnit(this.ID); }); - } + appendContextActions(contextActionSet: ContextActionSet) { + contextActionSet.addContextAction(this, "group-ground", "Group ground units", "Create a group of ground units", olIconsGroupGround, (units: Unit[], targetUnit: Unit, targetPosition: LatLng) => { getApp().getUnitsManager().createGroup(units) }); + contextActionSet.addContextAction(this, "attack", "Attack unit", "Attack the unit using A/A or A/G weapons", faQuestionCircle, (units: Unit[], targetUnit: Unit, targetPosition: LatLng) => { getApp().getUnitsManager().attackUnit(targetUnit.ID, units) }); + contextActionSet.addContextAction(this, "center-map", "Center map", "Center the map on the unit and follow it", faQuestionCircle, () => { getApp().getMap().centerOnUnit(this.ID); }); + + if (this.canTargetPoint()) { + contextActionSet.addContextAction(this, "fire-at-area", "Fire at area", "Fire at a specific area on the ground", faQuestionCircle, (units: Unit[], targetUnit: Unit, targetPosition: LatLng) => { getApp().getUnitsManager().fireAtArea(targetPosition, units) }); + contextActionSet.addContextAction(this, "simulate-fire-fight", "Simulate fire fight", "Simulate a fire fight by shooting randomly in a certain large area.\nWARNING: works correctly only on neutral units, blue or red units will aim", faQuestionCircle, (units: Unit[], targetUnit: Unit, targetPosition: LatLng) => { getApp().getUnitsManager().simulateFireFight(targetPosition, units) }); } - if (targetPosition !== null) { - if (this.canTargetPoint()) { - contextActionSet.addContextAction(this, "fire-at-area", "Fire at area", "Fire at a specific area on the ground", (units: Unit[]) => { getApp().getUnitsManager().fireAtArea(targetPosition, units) }); - contextActionSet.addContextAction(this, "simulate-fire-fight", "Simulate fire fight", "Simulate a fire fight by shooting randomly in a certain large area.\nWARNING: works correctly only on neutral units, blue or red units will aim", (units: Unit[]) => { getApp().getUnitsManager().simulateFireFight(targetPosition, units) }); - } - } - else { - if (this.canAAA()) { - contextActionSet.addContextAction(this, "scenic-aaa", "Scenic AAA", "Shoot AAA in the air without aiming at any target, when an enemy unit gets close enough.\nWARNING: works correctly only on neutral units, blue or red units will aim", (units: Unit[]) => { getApp().getUnitsManager().scenicAAA(units) }, undefined, { - "isScenic": true - }); - contextActionSet.addContextAction(this, "miss-aaa", "Dynamic accuracy AAA", "Shoot AAA towards the closest enemy unit, but don't aim precisely.\nWARNING: works correctly only on neutral units, blue or red units will aim", (units: Unit[]) => { getApp().getUnitsManager().missOnPurpose(units) }, undefined, { - "isScenic": true - }); - } + if (this.canAAA()) { + contextActionSet.addContextAction(this, "scenic-aaa", "Scenic AAA", "Shoot AAA in the air without aiming at any target, when an enemy unit gets close enough.\nWARNING: works correctly only on neutral units, blue or red units will aim", faQuestionCircle, (units: Unit[]) => { getApp().getUnitsManager().scenicAAA(units) }, undefined, { + "isScenic": true + }); + contextActionSet.addContextAction(this, "miss-aaa", "Dynamic accuracy AAA", "Shoot AAA towards the closest enemy unit, but don't aim precisely.\nWARNING: works correctly only on neutral units, blue or red units will aim", faQuestionCircle, (units: Unit[]) => { getApp().getUnitsManager().missOnPurpose(units) }, undefined, { + "isScenic": true + }); } } @@ -1688,21 +1662,11 @@ export class NavyUnit extends Unit { }; } - appendContextActions(contextActionSet: ContextActionSet, targetUnit: Unit | null, targetPosition: LatLng | null) { - contextActionSet.addContextAction(this, "group-navy", "Group navy units", "Create a group of navy units", (units: Unit[]) => { getApp().getUnitsManager().createGroup(units) }); - - if (targetUnit !== null) { - if (targetUnit != this) { - contextActionSet.addContextAction(this, "attack", "Attack unit", "Attack the unit using A/A or A/G weapons", (units: Unit[]) => { getApp().getUnitsManager().attackUnit(targetUnit.ID, units) }); - } - if (getApp().getUnitsManager().getSelectedUnits().length == 1 && targetUnit === this) { - contextActionSet.addContextAction(this, "center-map", "Center map", "Center the map on the unit and follow it", () => { getApp().getMap().centerOnUnit(this.ID); }); - } - } - - if (targetPosition !== null) { - contextActionSet.addContextAction(this, "fire-at-area", "Fire at area", "Fire at a specific area on the ground", (units: Unit[]) => { getApp().getUnitsManager().fireAtArea(targetPosition, units) }); - } + appendContextActions(contextActionSet: ContextActionSet) { + contextActionSet.addContextAction(this, "group-navy", "Group navy units", "Create a group of navy units", faQuestionCircle, (units: Unit[], targetUnit: Unit, targetPosition: LatLng) => { getApp().getUnitsManager().createGroup(units) }); + contextActionSet.addContextAction(this, "attack", "Attack unit", "Attack the unit using A/A or A/G weapons", faQuestionCircle, (units: Unit[], targetUnit: Unit, targetPosition: LatLng) => { getApp().getUnitsManager().attackUnit(targetUnit.ID, units) }); + contextActionSet.addContextAction(this, "center-map", "Center map", "Center the map on the unit and follow it", faQuestionCircle, () => { getApp().getMap().centerOnUnit(this.ID); }); + contextActionSet.addContextAction(this, "fire-at-area", "Fire at area", "Fire at a specific area on the ground", faQuestionCircle, (units: Unit[], targetUnit: Unit, targetPosition: LatLng) => { getApp().getUnitsManager().fireAtArea(targetPosition, units) }); } getCategory() { diff --git a/scripts/python/map_generator/.gitignore b/scripts/python/map_generator/.gitignore index a9ed7789..19d07396 100644 --- a/scripts/python/map_generator/.gitignore +++ b/scripts/python/map_generator/.gitignore @@ -1,3 +1,4 @@ Syria Test -Caucasus \ No newline at end of file +Caucasus +.venv \ No newline at end of file diff --git a/scripts/python/map_generator/.vscode/launch.json b/scripts/python/map_generator/.vscode/launch.json index 1138bd0a..50e7aed9 100644 --- a/scripts/python/map_generator/.vscode/launch.json +++ b/scripts/python/map_generator/.vscode/launch.json @@ -12,14 +12,6 @@ "console": "integratedTerminal", "args": ["./configs/Test/MediumResolution.yml"], "justMyCode": false - }, - { - "name": "Convert", - "type": "python", - "request": "launch", - "program": "convert_to_jpg.py", - "console": "integratedTerminal", - "args": ["./Syria/tiles", "./Syria/jpg"] } ] } \ No newline at end of file