├── LICENSE.md
├── README.md
├── build.py
├── html_ui
├── FPS_Setting.json
├── Pages
│ ├── FlightPlanning
│ │ └── Aircraft
│ │ │ ├── AircraftPanels.css
│ │ │ ├── AircraftPanels.html
│ │ │ └── TCasPanels.js
│ └── VCockpit
│ │ └── Instruments
│ │ └── Shared
│ │ └── BaseInstrument.js
└── SCSS
│ └── refresh.css
├── layout.json
└── manifest.json
/LICENSE.md:
--------------------------------------------------------------------------------
1 | This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 Unported License (CC-NC-SA) . To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/4.0/ or send a letter to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # FPS-Fix v 1.1.4a
2 |
3 | READ: Important as of V1.1.4a / Game Version v1.8.3 - Set Glass Cockpit Refresh Rate to HIGH. Setting this to MEDIUM or LOW will overwrite the mod's setting (and this is intentional). If you wish to use the mod, please set this to High. The game's inbuilt FPS reduction applies on a global setting, the mod allows you to set this value per aircraft in freeflight mode.
4 |
5 | ## Install
6 |
7 | Unzip and install the FPS-Fix directory in your Community folder. DO NOT REPLACE THE BASE GAME FILES.
8 |
9 | Your community directory by default is located in C:\Users\[YOUR USERNAME]\AppData\Roaming\Microsoft Flight Simulator\Packages\Community
10 |
11 | If you changed this location during installation, you will not see any files in ..\Packages and will have to find your Community folder.
12 |
13 | Open your game and enable Developer Mode (In Settings > Developer). This will enable the developer menu.
14 |
15 | From the developer menu at the top of the screen, go to Tools > Virtual File System.
16 |
17 | Expand the Watched Bases tab. This is your Community folder, where the mod must be installed to.
18 |
19 | -------------
20 |
21 | ## Usage
22 |
23 | Important as of V1.1.4a / Game Version v1.8.3 - Set Glass Cockpit Refresh Rate to HIGH. Setting this to MEDIUM or LOW will overwrite the mod's setting (and this is intentional). If you wish to use the mod, please set this to High. The game's inbuilt FPS reduction applies on a global setting, the mod allows you to set this value per aircraft in freeflight mode.
24 |
25 | By default, the default refresh settings are as listed.
26 |
27 | You can change this per airplane in the Flight Settings > FPS > Display Refresh options menu before you begin your flight. (Currently this read-only, you can modify it with a text editor but saving settings in game is not supported yet)
28 |
29 | Note that Very Low is a demonstration mode to simply make it obvious that the mod is actually doing something. It's not recommendeed and the recommended setting for most users is HIGH.
30 |
31 | ULTRA will completely disable the refresh rate modification and revert to vanilla behaviour.
32 |
33 | Default Settings:
34 |
35 | Unlisted - Ultra
36 |
37 | A320neo - High
38 |
39 | 747-8 Intercontinental - Medium
40 |
41 | 787-10 Dreamliner - Medium
42 |
43 | Cessna Citation CJ4 - Medium
44 |
45 | Cessna Citation Longitude - Medium
46 |
47 | TBM 930 - High
48 |
49 | Beechcraft King Air 350i - High
50 |
51 | Cessna 172 Skyhawk (G1000) - High
52 |
53 | Cessna 208 B Grand Caravan EX - High
54 |
55 | SR22 - High
56 |
57 | X Cub - High
58 |
59 | DA40 NG - High
60 |
61 | DA40 TDI - High
62 |
63 | DA62 - High
64 |
65 | DV20 - High
66 |
67 | EXTRA 330LT - High
68 |
69 | Flight Design CTSL - High
70 |
71 | A5 - High
72 |
73 | VL-3 - High
74 |
75 | Virus SW121 - High
76 |
77 | Cap10 - High
78 |
79 | Beechcraft Baron G58 - High
80 |
81 | Beechcraft Bonanza G36 - High
82 |
83 | Shock Ultra - Ultra
84 |
85 | Pitts Special S2S - Ultra
86 |
87 | Cessna 152 - Ultra
88 |
89 | Cessna 152 Aerobat - Ultra
90 |
91 | Cessna 172 Skyhawk - Ultra
92 |
93 | Savage Cub - Ultra
94 |
95 | ----
96 |
97 | ## License/Credit
98 |
99 | See License.MD.
100 |
101 | Credit to Asobo Studio and Microsoft for the base game files.
102 |
103 | See Credits page on [Nexusmod page](https://www.nexusmods.com/microsoftflightsimulator/mods/34) for full credits.
104 |
--------------------------------------------------------------------------------
/build.py:
--------------------------------------------------------------------------------
1 | import os
2 | import json
3 | import sys
4 |
5 |
6 | def check_prerequisites():
7 | if sys.version_info[0] < 3 or sys.version_info[1] < 6:
8 | raise Exception("Must be using Python 3.6 or later")
9 |
10 |
11 | def build_layout(project_dir):
12 | layout_entries = []
13 | for root, _, files in os.walk(project_dir):
14 | for filename in files:
15 | filepath = os.path.join(root, filename)
16 |
17 | if not "git" in filepath and not filepath.endswith(".txt") and not filepath.endswith(".md") and not filepath.endswith("layout.json") and not filepath.endswith("manifest.json") and not filepath.endswith(".py"):
18 | rel_dir = os.path.relpath(root)
19 | rel_file = str(os.path.join(rel_dir, filename))
20 | if rel_file[0] == '.':
21 | rel_file = rel_file[2:]
22 |
23 | print(" -- Processing " + rel_file)
24 | entry = {}
25 | entry["path"] = rel_file.replace('\\', '/')
26 | entry["size"] = os.path.getsize(filepath)
27 | entry["date"] = "132402817714110148"
28 | layout_entries.append(entry)
29 |
30 | layout_entries.sort(key=lambda e: e["path"])
31 |
32 | return layout_entries
33 |
34 |
35 | if __name__ == "__main__":
36 | check_prerequisites()
37 |
38 | cwd = os.getcwd()
39 |
40 | layout_content = build_layout(cwd)
41 |
42 | layout_json = {
43 | "content": layout_content
44 | }
45 |
46 | with open("layout.json", "w") as outfile:
47 | json.dump(layout_json, outfile, indent=4)
48 |
--------------------------------------------------------------------------------
/html_ui/FPS_Setting.json:
--------------------------------------------------------------------------------
1 | {
2 | "default":"High",
3 | "planes":[
4 | {"name":"A320neo ","fps":"Medium"},
5 | {"name":"747-8 Intercontinental ","fps":"Medium"},
6 | {"name":"787-10 Dreamliner ","fps":"Medium"},
7 | {"name":"Cessna Citation CJ4 ","fps":"Medium"},
8 | {"name":"Cessna Citation Longitude ","fps":"Medium"},
9 | {"name":"TBM 930 ","fps":"High"},
10 | {"name":"Beechcraft King Air 350i ","fps":"High"},
11 | {"name":"Cessna 172 Skyhawk (G1000) ","fps":"High"},
12 | {"name":"Cessna 208 B Grand Caravan EX ","fps":"High"},
13 | {"name":"SR22 ","fps":"High"},
14 | {"name":"X Cub ","fps":"High"},
15 | {"name":"DA40 NG ","fps":"High"},
16 | {"name":"DA40 TDI ","fps":"High"},
17 | {"name":"DA62 ","fps":"High"},
18 | {"name":"DV20 ","fps":"High"},
19 | {"name":"EXTRA 330LT ","fps":"High"},
20 | {"name":"Flight Design CTSL ","fps":"High"},
21 | {"name":"A5 ","fps":"High"},
22 | {"name":"VL-3 ","fps":"High"},
23 | {"name":"Virus SW121 ","fps":"High"},
24 | {"name":"Cap10 ","fps":"High"},
25 | {"name":"Beechcraft Baron G58 ","fps":"High"},
26 | {"name":"Beechcraft Bonanza G36 ","fps":"High"},
27 | {"name":"Shock Ultra ","fps":"Ultra"},
28 | {"name":"Pitts Special S2S ","fps":"Ultra"},
29 | {"name":"Cessna 152 ","fps":"Ultra"},
30 | {"name":"Cessna 152 Aerobat ","fps":"Ultra"},
31 | {"name":"Cessna 172 Skyhawk ","fps":"Ultra"},
32 | {"name":"Savage Cub ","fps":"Ultra"}
33 | ]
34 | }
35 |
--------------------------------------------------------------------------------
/html_ui/Pages/FlightPlanning/Aircraft/AircraftPanels.css:
--------------------------------------------------------------------------------
1 | /** This mixin makes a single line element fit exactly on the Roboto font for easier integration. */
2 | aircraft-selection {
3 | width: 100%;
4 | height: 100%;
5 | display: flex;
6 | flex-direction: column;
7 | /* &.ChildActive {
8 | border: var(--baseMargin) solid white; // HACK
9 | }
10 |
11 | &:not(.ChildActive) {
12 | border: var(--baseMargin) solid transparent; // HACK
13 | }
14 | */ }
15 | aircraft-selection .searchContainer {
16 | flex: 0 0 auto;
17 | display: flex;
18 | align-items: center; }
19 | aircraft-selection .searchContainer new-push-button {
20 | margin-right: var(--baseMargin); }
21 | aircraft-selection search-element {
22 | background-color: var(--backgroundColorPanel);
23 | margin-bottom: var(--halfMargin);
24 | flex-shrink: 0; }
25 |
26 | aircraft-liveries {
27 | display: block;
28 | width: 100%;
29 | height: 100%; }
30 |
31 | aircraft-panels {
32 | position: relative;
33 | display: flex;
34 | flex-direction: row;
35 | justify-content: flex-start;
36 | align-items: flex-start; }
37 | aircraft-panels > .Content {
38 | display: block;
39 | position: relative;
40 | width: 100%;
41 | height: 100%;
42 | min-width: 0;
43 | padding-left: var(--halfMargin); }
44 | aircraft-panels options-menu {
45 | width: calc(var(--unscaledScreenHeight) * (670px / 2160));
46 | background-color: var(--backgroundColorPanel);
47 | flex-shrink: 0; }
48 | aircraft-panels search-element {
49 | background-color: var(--backgroundColorPanel);
50 | margin-bottom: var(--halfMargin);
51 | flex-shrink: 0; }
52 |
53 | aircraft-atc {
54 | position: relative;
55 | width: 100%;
56 | height: 100%;
57 | display: flex;
58 | /*&.ChildActive {
59 | border: var(--baseMargin) solid white; // HACK
60 | }
61 |
62 | &:not(.ChildActive) {
63 | border: var(--baseMargin) solid transparent; // HACK
64 | }*/ }
65 | aircraft-atc #AircraftATCOptions_Content {
66 | display: block;
67 | flex: 1 0 auto;
68 | position: relative;
69 | padding: calc(var(--screenHeight) * (24px / 2160));
70 | background-color: var(--backgroundColorPanel); }
71 | aircraft-atc #AircraftATCOptions_Content > * {
72 | margin-bottom: var(--halfMargin); }
73 | aircraft-atc #AircraftATCOptions_Content:last-child {
74 | margin-bottom: 0; }
75 | aircraft-atc .TipsWrapper {
76 | display: flex;
77 | width: calc(var(--screenHeight) * (700px / 2160));
78 | margin-left: var(--halfMargin);
79 | padding: calc(var(--screenHeight) * (24px / 2160));
80 | background: var(--backgroundColorPanel); }
81 | aircraft-atc .TipsWrapper .Tips {
82 | flex: 1 0 auto;
83 | position: relative;
84 | text-align: left; }
85 |
86 | aircraft-tcas-framerate {
87 | position: relative;
88 | width: 100%;
89 | height: 100%;
90 | display: flex;
91 | /*&.ChildActive {
92 | border: var(--baseMargin) solid white; // HACK
93 | }
94 |
95 | &:not(.ChildActive) {
96 | border: var(--baseMargin) solid transparent; // HACK
97 | }*/ }
98 | aircraft-tcas-framerate #AircraftATCOptions_Content {
99 | display: block;
100 | flex: 1 0 auto;
101 | position: relative;
102 | padding: calc(var(--screenHeight) * (24px / 2160));
103 | background-color: var(--backgroundColorPanel); }
104 | aircraft-tcas-framerate #AircraftATCOptions_Content > * {
105 | margin-bottom: var(--halfMargin); }
106 | aircraft-tcas-framerate #AircraftATCOptions_Content:last-child {
107 | margin-bottom: 0; }
108 | aircraft-tcas-framerate .TipsWrapper {
109 | display: flex;
110 | width: calc(var(--screenHeight) * (700px / 2160));
111 | margin-left: var(--halfMargin);
112 | padding: calc(var(--screenHeight) * (24px / 2160));
113 | background: var(--backgroundColorPanel); }
114 | aircraft-tcas-framerate .TipsWrapper .Tips {
115 | flex: 1 0 auto;
116 | position: relative;
117 | text-align: left; }
118 |
119 | aircraft-specs {
120 | display: flex;
121 | flex-direction: column;
122 | background: var(--backgroundColorContrastedPanel);
123 | padding: var(--halfMargin); }
124 | aircraft-specs virtual-scroll {
125 | background-color: var(--backgroundColorPanel);
126 | padding: var(--basePadding); }
127 | aircraft-specs .Description > h1, aircraft-specs .Specs > h1 {
128 | padding-bottom: calc(var(--screenHeight) * (8px / 1080));
129 | border-bottom: var(--minimalBorderWidth) solid var(--textColor);
130 | margin-bottom: var(--baseMargin);
131 | text-transform: uppercase;
132 | margin-top: var(--baseMargin);
133 | font-size: var(--fontSizeDefault);
134 | font-weight: bold; }
135 | aircraft-specs .Description > .Content, aircraft-specs .Specs > .Content {
136 | font-weight: 500; }
137 | aircraft-specs .Description > h1 {
138 | margin-top: 0; }
139 |
140 |
--------------------------------------------------------------------------------
/html_ui/Pages/FlightPlanning/Aircraft/AircraftPanels.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
9 |
10 |
11 |
20 |
21 |
22 |
35 |
36 |
37 |
40 |
41 |
42 |
43 |
55 |
56 |
57 |
66 |
67 |
68 |
89 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/html_ui/Pages/FlightPlanning/Aircraft/TCasPanels.js:
--------------------------------------------------------------------------------
1 | // --------------------------
2 | // TCasPanels
3 | // v 1.1.3a
4 | // --------------------------
5 |
6 | /*
7 | +++++++++++++++++++++++
8 | Turbofans
9 | +++++++++++++++++++++++
10 | A320neo
11 | 747-8 Intercontinental
12 | 787-10 Dreamliner
13 | Cessna Citation CJ4
14 | Cessna Citation Longitude
15 | +++++++++++++++++++++++
16 | Turboprops
17 | +++++++++++++++++++++++
18 | TBM 930
19 | Beechcraft King Air 350i
20 | Cessna 208 B Grand Caravan EX
21 | +++++++++++++++++++++++
22 | Props
23 | +++++++++++++++++++++++
24 | SR22
25 | X Cub
26 | DA40 NG
27 | DA40 TDI
28 | DA62
29 | DV20
30 | EXTRA 330LT
31 | Flight Design CTSL
32 | A5
33 | VL-3
34 | Virus SW121
35 | Cap10
36 | Beechcraft Baron G58
37 | Beechcraft Bonanza G36
38 | ++++++++++++++++++++++
39 | */
40 |
41 | Include.addImport("/Templates/PanelInfoLine/PanelInfoLine.html");
42 | Include.addScript("/JS/Services/Aircraft.js");
43 | Include.addImport("/templates/searchElement/searchElement.html");
44 | Include.addImport("/templates/OptionsMenu/Item/OptionsMenuItem.html");
45 | Include.addImport("/templates/OptionsMenu/OptionsMenu.html");
46 | Include.addImport("/Pages/World/PlaneSelection/PlaneSelection.html");
47 | Include.addImport("/templates/FuelPayload/WM_FuelPayload.html");
48 | Include.addImport("/Pages/World/AircraftFailures/WM_AircraftFailures.html");
49 |
50 | const TC_DEBUG = false;
51 |
52 | class TCasOptionsElement extends TemplateElement {
53 | constructor() {
54 | super();
55 | if (TC_DEBUG && g_modDebugMgr){
56 | Include.addScript("/JS/debug.js", function () {
57 | g_modDebugMgr.AddConsole(null);
58 | });
59 | }
60 | var json_obj = null;
61 | this.current_aircraft = null;
62 | // Parsing JSON string into object
63 | loadJSON(function(response) {
64 | if (response) {
65 | json_obj = JSON.parse(response);
66 | }
67 | if (TC_DEBUG) {
68 | for (let i = 0; i < json_obj.length; i++) {
69 | console.log(json_obj[i].name + " = " + json_obj[i].fps);
70 | }
71 | }
72 | });
73 | this.onListenerRegistered = () => {
74 | this.m_gameFlightListener.requestGameFlight(this.onGameFlightUpdated);
75 | };
76 | this.onGameFlightUpdated = (flight) => {
77 | //Type: AircraftData
78 | if (TC_DEBUG) {
79 | console.log("aircraft ID: " + flight.aircraftData.aircraftId);
80 | console.log("name: [" + flight.aircraftData.name + "]");
81 | console.log("variation: " + flight.aircraftData.variation);
82 | }
83 | let factor = null;
84 | this.current_aircraft = flight.aircraftData.name;
85 | // Fetch from JSON
86 | if (json_obj) {
87 | for (let i = 0; i < json_obj.planes.length; i++) {
88 | if (json_obj.planes[i].name === flight.aircraftData.name) {
89 | if (TC_DEBUG) {
90 | console.log("FPS Quality: " + json_obj.planes[i].fps);
91 | console.log("QF: " + quality_factor[json_obj.planes[i].fps]);
92 | }
93 | factor = quality_factor[json_obj.planes[i].fps];
94 | break;
95 | }
96 | }
97 | // No aircraft found
98 | if (!factor && json_obj.default) {
99 | if (TC_DEBUG) console.log("Using default: "+ json_obj.default);
100 | factor = quality_factor[json_obj.default];
101 | localStorage.setItem("FPS_r_factor", factor);
102 | if (TC_DEBUG) console.log(localStorage.getItem("FPS_r_factor"));
103 | }
104 |
105 | }
106 | // Load factor variable (menus + local settings)
107 | if (factor) {
108 | localStorage.setItem("FPS_r_factor", factor);
109 | let index = factor_disp[factor] ? factor_disp[factor] : 0;
110 | this.fRedInd.setCurrentValue(index);
111 | } else {
112 | // If no factor, revert to High
113 | localStorage.setItem("FPS_r_factor", "2");
114 | this.fRedInd.setCurrentValue(1);
115 | if (json_obj) { json_obj.default = "High"; }
116 | }
117 | };
118 | // On menu change...
119 | this.onRateChange = () => {
120 | let index = this.fRedInd.getCurrentValue();
121 | let factor = "2";
122 | // Get rFactor from index
123 | for (let key in factor_disp) {
124 | if (factor_disp[key] == index) {
125 | factor = key;
126 | break;
127 | }
128 | }
129 | // Get quality from rFactor
130 | let quality = "High"; // Set High if nothing found
131 | for (let key in quality_factor) {
132 | if (quality_factor[key] == factor) {
133 | quality = key;
134 | break;
135 | }
136 | }
137 | // Set rFactor -> BaseInstrument
138 | localStorage.setItem("FPS_r_factor", factor);
139 | if (TC_DEBUG) console.log(localStorage.getItem("FPS_r_factor"));
140 | // Set quality for existing plane -> JSON
141 | let found = false;
142 | if (json_obj) {
143 | for (let i = 0; i < json_obj.planes.length; i++) {
144 | if (!found && json_obj.planes[i].name === this.current_aircraft) {
145 | json_obj.planes[i].fps = quality; // Set quality for this plane
146 | found = true;
147 | if (TC_DEBUG) { console.log("Found " + json_obj.planes[i].name); }
148 | //console.log(json_obj.planes[i].name + " = " + json_obj.planes[i].fps);
149 | }
150 | }
151 | // Create new plane -> JSON
152 | if (!found) {
153 | if (TC_DEBUG) { console.log(">>> Creating new: " + this.current_aircraft); }
154 | let new_plane = {
155 | name: this.current_aircraft,
156 | fps: quality
157 | }
158 | if (TC_DEBUG) { "JSON: " +json_obj.planes.push(new_plane); }
159 | //console.log("Created" + new_plane.name + " = " + new_plane.fps);
160 | }
161 | console.log(JSON.stringify(json_obj));
162 | //console.log("FPS_r_factor set to " + factor);
163 | }
164 | };
165 | this.copyToClipboard = () => {
166 | console.log(">>>> To Clipboard");
167 | const element = document.createElement('textarea');
168 | element.value = JSON.stringify(json_obj);
169 | element.setAttribute('readonly', '');
170 | element.style.position = 'absolute';
171 | element.style.left = '-9999px';
172 | document.body.appendChild(element);
173 | const selected =
174 | document.getSelection().rangeCount > 0
175 | ? document.getSelection().getRangeAt(0)
176 | : false;
177 | element.select();
178 | document.execCommand('copy');
179 | document.body.removeChild(element);
180 | if (selected) {
181 | document.getSelection().removeAllRanges();
182 | document.getSelection().addRange(selected);
183 | }
184 | };
185 | }
186 | get templateID() { return "TCasOptionsTemplate"; }
187 | ;
188 | connectedCallback() {
189 | super.connectedCallback();
190 | this.fRedInd = this.querySelector(".WM_TCOPTIONS_DISPLAY_RATE");
191 | this.fRedInd.addEventListener("OnValidate", this.onRateChange);
192 | this.fRedCopy = this.querySelector(".WM_TCOPTIONS_COPY");
193 | this.fRedCopy.addEventListener("OnValidate", this.copyToClipboard);
194 | if (!this.m_gameFlightListener)
195 | this.m_gameFlightListener = RegisterGameFlightListener(this.onListenerRegistered);
196 | this.m_gameFlightListener.onGameFlightUpdated(this.onGameFlightUpdated);
197 | }
198 | get canBeSelected() { return true; }
199 | getKeyNavigationStayInside(keycode) { return true; }
200 | getKeyNavigationDirection() { return KeyNavigationDirection.KeyNavigation_Vertical; }
201 | getAllFocusableChildren() {
202 | return [ this.fRedInd, this.fRedCopy ];
203 | }
204 |
205 | }
206 |
207 | function loadJSON(callback) {
208 | if (TC_DEBUG) console.log("Loading JSON");
209 | let xobj = new XMLHttpRequest();
210 | xobj.overrideMimeType("application/json");
211 | xobj.open("GET", "/FPS_Setting.json", true);
212 | xobj.onreadystatechange = function () {
213 | if (xobj.readyState == 4 && xobj.status == "200") {
214 | callback(xobj.responseText);
215 | }
216 | };
217 | xobj.send(null);
218 | }
219 |
220 | function saveJSON(json) {
221 |
222 | const filename = "FPS_Setting.json";
223 | let text = JSON.stringify(json);
224 | if (TC_DEBUG) {
225 | console.log("Saved to : " + filename);
226 | console.log(text);
227 | }
228 |
229 | var element = document.createElement('a');
230 | element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));
231 | element.setAttribute('download', filename);
232 |
233 | element.style.display = 'none';
234 | document.body.appendChild(element);
235 |
236 | element.click();
237 |
238 | document.body.removeChild(element);
239 | }
240 |
241 | /*
242 | // :(
243 | function saveJSON(filename, text) {
244 | console.log("Saved to : " + filename);
245 | console.log(text);
246 | var a = document.createElement("a");
247 | var file = new Blob([text], {type: "text/plain"});
248 | a.href = URL.createObjectURL(file);
249 | a.download = filename;
250 | document.body.appendChild(a);
251 | a.click();
252 | document.body.removeChild(a);
253 | }
254 | */
255 |
256 | var factor_disp = {
257 | "1" : 0, // Ultra
258 | "2" : 1, // High
259 | "3" : 2, // Medium
260 | "4" : 3, // Low
261 | "16" : 4 // Very Low
262 | };
263 | var quality_factor = {
264 | "Ultra" : "1",
265 | "High" : "2",
266 | "Medium" : "3",
267 | "Low" : "4",
268 | "Very Low" : "16"
269 | };
270 |
271 | window.customElements.define("aircraft-tcas-framerate", TCasOptionsElement);
272 | checkAutoload();
273 | //# sourceMappingURL=AircraftPanels.js.map
274 |
--------------------------------------------------------------------------------
/html_ui/Pages/VCockpit/Instruments/Shared/BaseInstrument.js:
--------------------------------------------------------------------------------
1 | // --------------------------
2 | // BaseInstrument
3 | // v 1.1.4.1a
4 | // --------------------------
5 |
6 | const TC_DEBUG = false;
7 |
8 | class BaseInstrument extends TemplateElement {
9 |
10 | constructor() {
11 | super();
12 | this.urlConfig = new URLConfig();
13 | this.xmlConfigLoading = false;
14 | this.frameCount = 0;
15 | this.highlightList = [];
16 | this.backgroundList = [];
17 | this._lastTime = 0;
18 | this._isConnected = false;
19 | this._isInitialized = false;
20 | this._quality = Quality.high;
21 | this._gameState = GameState.ingame;
22 | this._deltaTime = 0;
23 | this._alwaysUpdate = false;
24 | this._pendingCalls = [];
25 | // --------------------------- MOD ------------------------------------------ //
26 | this._refresh = Refresh.ultra; // Refresh at FPS by default
27 | this.frameReduce = 1; // Default reduction factor
28 | // --------------------------- MOD ------------------------------------------ //
29 | this.dataMetaManager = new DataReadMetaManager();
30 | }
31 | get initialized() { return this._isInitialized; }
32 | get instrumentIdentifier() { return this._instrumentId; }
33 | get instrumentIndex() { return (this.urlConfig.index != null) ? this.urlConfig.index : 1; }
34 | get isInteractive() { return false; }
35 | get IsGlassCockpit() { return false; }
36 | get isPrimary() { return (this.urlConfig.index == null || this.urlConfig.index == 1); }
37 | get deltaTime() { return this._deltaTime; }
38 | get flightPlanManager() { return null; }
39 | get facilityLoader() {
40 | if (!this._facilityLoader)
41 | this._facilityLoader = new FacilityLoader(this);
42 | return this._facilityLoader;
43 | }
44 | connectedCallback() {
45 | super.connectedCallback();
46 | if (TC_DEBUG && g_modDebugMgr){
47 | Include.addScript("/JS/debug.js", function () {
48 | g_modDebugMgr.AddConsole(null);
49 | });
50 | }
51 | this.electricity = this.getChildById("Electricity");
52 | this.highlightSvg = this.getChildById("highlight");
53 | this.loadDocumentAttributes();
54 | this.loadURLAttributes();
55 | this.loadXMLConfig();
56 | window.document.addEventListener("OnVCockpitPanelAttributesChanged", this.loadDocumentAttributes.bind(this));
57 | this.startTime = Date.now();
58 | if (this.getGameState() != GameState.mainmenu) {
59 | this.createMainLoop();
60 | }
61 | // --------------------------- MOD ------------------------------------------ //
62 | this.frameReduce = this.loadFrameRed();
63 | // DEBUG
64 | if (TC_DEBUG) console.log(this.instrumentIdentifier);
65 | // --------------------------- MOD ------------------------------------------ //
66 | }
67 | disconnectedCallback() {
68 | super.disconnectedCallback();
69 | this._isConnected = false;
70 | }
71 | Init() {
72 | this._isInitialized = true;
73 | this.initTransponder();
74 | }
75 | setInstrumentIdentifier(_identifier) {
76 | if (_identifier && _identifier != "" && _identifier != this.instrumentIdentifier) {
77 | this._instrumentId = _identifier;
78 | var guid = this.getAttribute("Guid");
79 | if (guid != undefined) {
80 | LaunchFlowEvent("ON_VCOCKPIT_INSTRUMENT_INITIALIZED", guid, this.instrumentIdentifier, this.isInteractive, this.IsGlassCockpit);
81 | }
82 | }
83 | }
84 | setConfigFile(_path) {
85 | this._xmlConfigPath = _path;
86 | }
87 | getChildById(_selector) {
88 | if (_selector == "")
89 | return null;
90 | if (!_selector.startsWith("#") && !_selector.startsWith("."))
91 | _selector = "#" + _selector;
92 | var child = this.querySelector(_selector.toString());
93 | return child;
94 | }
95 | getChildrenById(_selector) {
96 | if (_selector == "")
97 | return null;
98 | if (!_selector.startsWith("#") && !_selector.startsWith("."))
99 | _selector = "#" + _selector;
100 | var children = this.querySelectorAll(_selector.toString());
101 | return children;
102 | }
103 | getChildrenByClassName(_selector) {
104 | return this.getElementsByClassName(_selector);
105 | }
106 | startHighlight(_id) {
107 | let elem = this.getChildById(_id);
108 | if (elem) {
109 | let highlight = new HighlightedElement();
110 | highlight.elem = elem;
111 | highlight.style = elem.style.cssText;
112 | this.highlightList.push(highlight);
113 | }
114 | let elems = this.getChildrenByClassName(_id);
115 | for (let i = 0; i < elems.length; i++) {
116 | let highlight = new HighlightedElement();
117 | highlight.elem = elems[i];
118 | highlight.style = elems[i].style.cssText;
119 | this.highlightList.push(highlight);
120 | }
121 | this.updateHighlightElements();
122 | }
123 | stopHighlight(_id) {
124 | let elem = this.getChildById(_id);
125 | if (elem) {
126 | for (let i = 0; i < this.highlightList.length; i++) {
127 | if (this.highlightList[i].elem == elem) {
128 | elem.style.cssText = this.highlightList[i].style;
129 | this.highlightList.splice(i, 1);
130 | }
131 | }
132 | }
133 | let elems = this.getChildrenByClassName(_id);
134 | for (let i = 0; i < elems.length; i++) {
135 | for (let j = 0; j < this.highlightList.length; j++) {
136 | if (this.highlightList[j].elem == elems[i]) {
137 | elems[i].style.cssText = this.highlightList[j].style;
138 | this.highlightList.splice(j, 1);
139 | }
140 | }
141 | }
142 | this.updateHighlightElements();
143 | }
144 | clearHighlights() {
145 | this.highlightList = [];
146 | this.updateHighlightElements();
147 | }
148 | updateHighlightElements() {
149 | for (let i = 0; i < this.backgroundList.length; i++) {
150 | this.backgroundList[i].remove();
151 | }
152 | this.backgroundList = [];
153 | if (this.highlightList.length > 0) {
154 | this.highlightSvg.setAttribute("active", "true");
155 | let elems = "";
156 | for (let i = 0; i < this.highlightList.length; i++) {
157 | let rect = this.highlightList[i].elem.getBoundingClientRect();
158 | if (this.highlightList[i] instanceof HTMLElement) {
159 | let bg = document.createElement("div");
160 | bg.style.backgroundColor = "rgba(0,0,0,0.9)";
161 | bg.style.zIndex = "-1";
162 | bg.style.left = this.highlightList[i].elem.offsetLeft.toString() + "px";
163 | bg.style.top = this.highlightList[i].elem.offsetTop.toString() + "px";
164 | bg.style.width = rect.width.toString() + "px";
165 | bg.style.height = rect.height.toString() + "px";
166 | bg.style.position = "absolute";
167 | this.highlightList[i].elem.parentElement.appendChild(bg);
168 | this.backgroundList.push(bg);
169 | }
170 | if (i > 0) {
171 | elems += ";";
172 | }
173 | elems += rect.left + " ";
174 | elems += rect.top + " ";
175 | elems += rect.right + " ";
176 | elems += rect.bottom;
177 | }
178 | this.highlightSvg.setAttribute("elements", elems);
179 | }
180 | else {
181 | this.highlightSvg.setAttribute("active", "false");
182 | }
183 | }
184 | onInteractionEvent(_args) {
185 | }
186 | onSoundEnd(_event) {
187 | }
188 | getQuality() {
189 | if (this._alwaysUpdate && this._quality != Quality.disabled) {
190 | return Quality.high;
191 | }
192 | return this._quality;
193 | }
194 | getGameState() {
195 | return this._gameState;
196 | }
197 | reboot() {
198 | console.log("Rebooting Instrument...");
199 | this.startTime = Date.now();
200 | this.frameCount = 0;
201 | this.initTransponder();
202 | }
203 | onFlightStart() {
204 | console.log("Flight Starting...");
205 | SimVar.SetSimVarValue("L:HUD_AP_SELECTED_SPEED", "Number", 0);
206 | SimVar.SetSimVarValue("L:HUD_AP_SELECTED_ALTITUDE", "Number", 0);
207 | this.dispatchEvent(new Event('FlightStart'));
208 | }
209 | onQualityChanged(_quality) {
210 | this._quality = _quality;
211 | }
212 | onGameStateChanged(_oldState, _newState) {
213 | if (_newState != GameState.mainmenu) {
214 | this.createMainLoop();
215 | if (_oldState == GameState.loading && (_newState == GameState.ingame || _newState == GameState.briefing)) {
216 | this.reboot();
217 | }
218 | else if (_oldState == GameState.briefing && _newState == GameState.ingame) {
219 | this.onFlightStart();
220 | }
221 | }
222 | else {
223 | this.killMainLoop();
224 | }
225 | this._gameState = _newState;
226 | }
227 | loadDocumentAttributes() {
228 | var attr = undefined;
229 | if (document.body.hasAttribute("quality"))
230 | attr = document.body.getAttribute("quality");
231 | else if (window.parent && window.parent.document.body.hasAttribute("quality"))
232 | attr = window.parent.document.body.getAttribute("quality");
233 | if (attr != undefined) {
234 | var quality = Quality[attr];
235 | if (quality != undefined && this._quality != quality) {
236 | this.onQualityChanged(quality);
237 | }
238 | }
239 | if (document.body.hasAttribute("gamestate"))
240 | attr = document.body.getAttribute("gamestate");
241 | else if (window.parent && window.parent.document.body.hasAttribute("gamestate"))
242 | attr = window.parent.document.body.getAttribute("gamestate");
243 | if (attr != undefined) {
244 | var state = GameState[attr];
245 | if (state != undefined && this._gameState != state) {
246 | this.onGameStateChanged(this._gameState, state);
247 | }
248 | }
249 | }
250 | parseXMLConfig() {
251 | if (this.instrumentXmlConfig) {
252 | let electric = this.instrumentXmlConfig.getElementsByTagName("Electric");
253 | if (electric.length > 0) {
254 | this.electricalLogic = new CompositeLogicXMLElement(this, electric[0]);
255 | }
256 | let alwaysUpdate = this.instrumentXmlConfig.getElementsByTagName("AlwaysUpdate");
257 | if (alwaysUpdate.length > 0) {
258 | if (alwaysUpdate[0].textContent.toLowerCase() == "true") {
259 | this._alwaysUpdate = true;
260 | }
261 | }
262 | }
263 | }
264 | parseURLAttributes() {
265 | var instrumentID = this.templateID;
266 | if (this.urlConfig.index)
267 | instrumentID += "_" + this.urlConfig.index;
268 | this.setInstrumentIdentifier(instrumentID);
269 | if (this.urlConfig.style)
270 | this.setAttribute("instrumentstyle", this.urlConfig.style);
271 | }
272 | beforeUpdate() {
273 | var curTime = Date.now();
274 | this._deltaTime = curTime - this._lastTime;
275 | this._lastTime = curTime;
276 | this.updatePendingCalls();
277 | }
278 | Update() {
279 | this.dataMetaManager.UpdateAll();
280 | this.updateHighlight();
281 | if (this._facilityLoader) {
282 | this._facilityLoader.update();
283 | }
284 | }
285 | afterUpdate() {
286 | this.frameCount++;
287 | if (this.frameCount >= Number.MAX_SAFE_INTEGER)
288 | this.frameCount = 0;
289 | }
290 | doUpdate() {
291 | this.beforeUpdate();
292 | this.Update();
293 | this.afterUpdate();
294 | }
295 | // ------------------------------------ MOD -------------------------------------------
296 | CanUpdate() {
297 | let frame_red = this.getFrameRed();
298 | let quality = this.getQuality();
299 |
300 | if (quality == Quality.ultra) {
301 | if ((this.frameCount % frame_red) != 0) {
302 | //console.log("Delta time updated - passed canupdate() " + this._deltaTime);
303 | return false;
304 | }
305 | return true;
306 | }
307 | else if (quality == Quality.high) {
308 | if ((this.frameCount % 2) != 0) {
309 | return false;
310 | }
311 | }
312 | else if (quality == Quality.medium) {
313 | if ((this.frameCount % 4) != 0) {
314 | return false;
315 | }
316 | }
317 | else if (quality == Quality.low) {
318 | if ((this.frameCount % 32) != 0) {
319 | return false;
320 | }
321 | }
322 | else if (quality == Quality.hidden) {
323 | if ((this.frameCount % 128) != 0) {
324 | return false;
325 | }
326 | }
327 | else if (quality == Quality.disabled) {
328 | return false;
329 | }
330 | return true;
331 | }
332 | // ------------------------------------ MOD -------------------------------------------
333 | updateElectricity() {
334 | let powerOn = this.isElectricityAvailable();
335 | if (this.electricity) {
336 | if (powerOn)
337 | this.electricity.setAttribute("state", "on");
338 | else
339 | this.electricity.setAttribute("state", "off");
340 | }
341 | return powerOn;
342 | }
343 | isElectricityAvailable() {
344 | if (this.electricalLogic) {
345 | return this.electricalLogic.getValue() != 0;
346 | }
347 | return SimVar.GetSimVarValue("CIRCUIT AVIONICS ON", "Bool");
348 | }
349 | playInstrumentSound(soundId) {
350 | if (this.isElectricityAvailable()) {
351 | Coherent.call("PLAY_INSTRUMENT_SOUND", soundId);
352 | return true;
353 | }
354 | return false;
355 | }
356 | createMainLoop() {
357 | if (this._isConnected)
358 | return;
359 | this._lastTime = Date.now();
360 | let updateLoop = () => {
361 | if (!this._isConnected) {
362 | console.log("Exiting MainLoop...");
363 | return;
364 | }
365 | try {
366 | if (BaseInstrument.allInstrumentsLoaded && !this.xmlConfigLoading && SimVar.IsReady()) {
367 | if (!this._isInitialized)
368 | this.Init();
369 | this.beforeUpdate();
370 | if (this.CanUpdate())
371 | this.Update();
372 | this.afterUpdate();
373 | }
374 | }
375 | catch (Error) {
376 | console.error(this.instrumentIdentifier + " : " + Error, Error.stack);
377 | }
378 | requestAnimationFrame(updateLoop);
379 | };
380 | this._isConnected = true;
381 | console.log("MainLoop created");
382 | requestAnimationFrame(updateLoop);
383 | }
384 | killMainLoop() {
385 | this._isConnected = false;
386 | }
387 | loadXMLConfig() {
388 | var xmlPath;
389 | if (this.urlConfig.config) {
390 | xmlPath = "/Pages/VCockpit/Instruments/Shared/Configs/" + this.urlConfig.config + ".xml";
391 | }
392 | else if (this._xmlConfigPath) {
393 | xmlPath = "/VFS/" + this._xmlConfigPath.replace(/\\/g, "/");
394 | }
395 | if (xmlPath) {
396 | this.xmlConfigLoading = true;
397 | var xmlRequest = new XMLHttpRequest();
398 | xmlRequest.onreadystatechange = function (_instrument) {
399 | if (this.readyState === XMLHttpRequest.DONE && this.status === 200) {
400 | _instrument.onXMLConfigLoaded(this);
401 | }
402 | }.bind(xmlRequest, this);
403 | xmlRequest.open("GET", xmlPath, true);
404 | xmlRequest.send();
405 | }
406 | }
407 | onXMLConfigLoaded(_xml) {
408 | this.xmlConfig = _xml.responseXML;
409 | if (this.xmlConfig) {
410 | let instruments = this.xmlConfig.getElementsByTagName("Instrument");
411 | for (let i = 0; i < instruments.length; i++) {
412 | let name = instruments[i].getElementsByTagName("Name")[0].textContent;
413 | if (name == this.instrumentIdentifier) {
414 | this.instrumentXmlConfig = instruments[i];
415 | }
416 | }
417 | this.parseXMLConfig();
418 | }
419 | else {
420 | console.error("XML Config file is not well-formatted");
421 | }
422 | this.xmlConfigLoading = false;
423 | }
424 | loadURLAttributes() {
425 | var parsedUrl = new URL(this.getAttribute("Url").toLowerCase());
426 | this.urlConfig.style = parsedUrl.searchParams.get("style");
427 | this.urlConfig.config = parsedUrl.searchParams.get("config");
428 | let index = parsedUrl.searchParams.get("index");
429 | this.urlConfig.index = index == null ? null : parseInt(index);
430 | this.urlConfig.wasmModule = parsedUrl.searchParams.get("wasm_module");
431 | this.urlConfig.wasmGauge = parsedUrl.searchParams.get("wasm_gauge");
432 | this.parseURLAttributes();
433 | }
434 | getTimeSinceStart() {
435 | return Date.now() - this.startTime;
436 | }
437 | getAspectRatio() {
438 | var vpRect = this.getBoundingClientRect();
439 | if (vpRect) {
440 | var vpWidth = vpRect.width;
441 | var vpHeight = vpRect.height;
442 | var aspectRatio = vpWidth / vpHeight;
443 | return aspectRatio;
444 | }
445 | return 1.0;
446 | }
447 | isComputingAspectRatio() { return false; }
448 | isAspectRatioForced() { return false; }
449 | getForcedScreenRatio() { return 1.0; }
450 | getForcedAspectRatio() { return 1.0; }
451 | updateHighlight() {
452 | }
453 | highlightGetState(_valueMin, _valueMax, _period) {
454 | let time = new Date().getTime();
455 | let size = _valueMax - _valueMin;
456 | let middle = _valueMin + size / 2;
457 | return middle + (Math.sin((time % _period / _period * Math.PI * 2)) * (size / 2));
458 | }
459 | wasTurnedOff() {
460 | return false;
461 | }
462 | initTransponder() {
463 | let transponderCode = ("0000" + SimVar.GetSimVarValue("TRANSPONDER CODE:1", "number")).slice(-4);
464 | if (transponderCode) {
465 | let currentCode = parseInt(transponderCode);
466 | if (currentCode == 0) {
467 | Simplane.setTransponderToRegion();
468 | }
469 | }
470 | }
471 | requestCall(_func) {
472 | this._pendingCalls.push(_func);
473 | }
474 | updatePendingCalls() {
475 | let length = this._pendingCalls.length;
476 | for (let i = 0; i < length; i++) {
477 | this._pendingCalls[i]();
478 | }
479 | this._pendingCalls.splice(0, length);
480 | }
481 |
482 | // ------------------------------------ MOD -------------------------------------------
483 | loadFrameRed() {
484 | let f_name = "FPS_r_factor";
485 | let def_factor = 2;
486 | if (!localStorage.getItem(f_name)) {
487 | localStorage.setItem(f_name, def_factor)
488 | console.log("Refresh Factor " + def_factor);
489 | return def_factor;
490 | } else {
491 | let factor_str = localStorage.getItem(f_name);
492 | let factor = parseInt(factor_str);
493 | console.log("Refresh Factor " + factor);
494 | return factor;
495 | }
496 | }
497 |
498 | getFrameRed() {
499 | return this.frameReduce;
500 | }
501 |
502 | // Can this refresh?
503 | getRefresh() {
504 | return this._refresh;
505 | }
506 | // ------------------------------------ MOD -------------------------------------------
507 | }
508 | BaseInstrument.allInstrumentsLoaded = false;
509 | BaseInstrument.useSvgImages = false;
510 | class URLConfig {
511 | }
512 | var Quality;
513 | (function (Quality) {
514 | Quality[Quality["ultra"] = 0] = "ultra";
515 | Quality[Quality["high"] = 1] = "high";
516 | Quality[Quality["medium"] = 2] = "medium";
517 | Quality[Quality["low"] = 3] = "low";
518 | Quality[Quality["hidden"] = 4] = "hidden";
519 | Quality[Quality["disabled"] = 5] = "disabled";
520 | })(Quality || (Quality = {}));
521 | var GameState;
522 | (function (GameState) {
523 | GameState[GameState["mainmenu"] = 0] = "mainmenu";
524 | GameState[GameState["loading"] = 1] = "loading";
525 | GameState[GameState["briefing"] = 2] = "briefing";
526 | GameState[GameState["ingame"] = 3] = "ingame";
527 | })(GameState || (GameState = {}));
528 |
529 | // ----------------------------- MOD ------------------------------------
530 | var Refresh;
531 | (function (Refresh) {
532 | Refresh[Refresh["ultra"] = 0] = "ultra";
533 | Refresh[Refresh["high"] = 1] = "high";
534 | Refresh[Refresh["medium"] = 2] = "medium";
535 | Refresh[Refresh["low"] = 3] = "low";
536 | Refresh[Refresh["hidden"] = 4] = "hidden";
537 | Refresh[Refresh["disable"] = 5] = "disable";
538 | })(Refresh || (Refresh = {}));
539 | // ----------------------------- MOD ------------------------------------
540 | class HighlightedElement {
541 | }
542 | customElements.define("base-instrument", BaseInstrument);
543 | checkAutoload();
544 | //# sourceMappingURL=BaseInstrument.js.map
545 |
--------------------------------------------------------------------------------
/html_ui/SCSS/refresh.css:
--------------------------------------------------------------------------------
1 | #rPanel {
2 | z-index: 10000;
3 | transform: rotateX(0);
4 | font-family: 'Segoe UI Symbol';
5 | }
6 |
7 | /* Links */
8 | a {
9 | padding: 2px 35px 2px 35px;
10 | text-decoration: none;
11 | color: #818181;
12 | display: block;
13 | transition: 0.3s;
14 | background: none;
15 | border: none;
16 | }
17 |
18 | a:hover {
19 | color: #f1f1f1;
20 | }
21 |
22 | /* Sliding Panel */
23 | .refreshPanel {
24 | height: 285px;
25 | width: 0%; /* JS */
26 | position: fixed;
27 | z-index: 1; /* Top */
28 | top: 0;
29 | left: 0;
30 | background-color: #111;
31 | overflow-x: hidden; /* Disable horizontal scroll */
32 | padding-top: 60px; /* Place content from the top */
33 | transition: 0.2s; /* 0.2 transition */
34 | font-size: 25px;
35 | }
36 |
--------------------------------------------------------------------------------
/layout.json:
--------------------------------------------------------------------------------
1 | {
2 | "content": [
3 | {
4 | "path": "html_ui/FPS_Setting.json",
5 | "size": 1496,
6 | "date": "132402817714110148"
7 | },
8 | {
9 | "path": "html_ui/Pages/FlightPlanning/Aircraft/AircraftPanels.css",
10 | "size": 4523,
11 | "date": "132402817714110148"
12 | },
13 | {
14 | "path": "html_ui/Pages/FlightPlanning/Aircraft/AircraftPanels.html",
15 | "size": 5811,
16 | "date": "132402817714110148"
17 | },
18 | {
19 | "path": "html_ui/Pages/FlightPlanning/Aircraft/TCasPanels.js",
20 | "size": 9886,
21 | "date": "132402817714110148"
22 | },
23 | {
24 | "path": "html_ui/Pages/VCockpit/Instruments/Shared/BaseInstrument.js",
25 | "size": 20180,
26 | "date": "132402817714110148"
27 | },
28 | {
29 | "path": "html_ui/SCSS/refresh.css",
30 | "size": 657,
31 | "date": "132402817714110148"
32 | }
33 | ]
34 | }
--------------------------------------------------------------------------------
/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "dependencies": [
3 | {
4 | "name": "asobo-vcockpits-core",
5 | "package_version": "0.1.12"
6 | }
7 | ],
8 | "content_type": "CORE",
9 | "title": "",
10 | "manufacturer": "",
11 | "creator": "2Cas",
12 | "package_version": "0.1.40",
13 | "minimum_game_version": "1.7.12",
14 | "release_notes": {
15 | "neutral": {
16 | "LastUpdate": "",
17 | "OlderHistory": ""
18 | }
19 | },
20 | "total_package_size": "0000000000000015657"
21 | }
22 |
--------------------------------------------------------------------------------