Merge branch 'preference_extension' into 'master'

Add Extensions Preferences to Character Preferences

See merge request 
This commit is contained in:
BondageProjects 2024-03-01 20:05:39 +00:00
commit 8da9779b4f
6 changed files with 207 additions and 11 deletions

Binary file not shown.

After

(image error) Size: 2.8 KiB

View file

@ -103,6 +103,13 @@ let PreferenceScriptTimeoutHandle = null;
/** @type {null | number} */
let PreferenceScriptTimer = null;
let PreferenceScriptWarningAccepted = false;
/** @type {Record<string,PreferenceExtensionsSettingItem>} */
let PreferenceExtensionsSettings = {};
/** @type {PreferenceExtensionsMenuButtonInfo[]} */
let PreferenceExtensionsDisplay = [];
/** @type {PreferenceExtensionsSettingItem | null}*/
let PreferenceExtensionsCurrent = null;
const ScriptPermissionLevel = Object.freeze({
SELF: "Self",
@ -725,12 +732,14 @@ function PreferenceRun() {
DrawText(TextGet("Preferences"), 500, 125, "Black", "Gray");
MainCanvas.textAlign = "center";
// Draw all the buttons to access the submenus
for (let A = 0; A < PreferenceSubscreenList.length; A++) {
DrawButton(500 + 420 * Math.floor(A / 7), 160 + 110 * (A % 7), 400, 90, "", "White", "Icons/" + PreferenceSubscreenList[A] + ".png");
DrawTextFit(TextGet("Homepage" + PreferenceSubscreenList[A]), 745 + 420 * Math.floor(A / 7), 205 + 110 * (A % 7), 310, "Black");
}
// Only show the Extension settings if there are any registered
const adjustedSubscreenList = Object.keys(PreferenceExtensionsSettings).length > 0 ? PreferenceSubscreenList.concat("Extensions") : PreferenceSubscreenList;
// Draw all the buttons to access the submenus
for (let A = 0; A < adjustedSubscreenList.length; A++) {
DrawButton(500 + 420 * Math.floor(A / 7), 160 + 110 * (A % 7), 400, 90, "", "White", "Icons/" + adjustedSubscreenList[A] + ".png");
DrawTextFit(TextGet("Homepage" + adjustedSubscreenList[A]), 745 + 420 * Math.floor(A / 7), 205 + 110 * (A % 7), 310, "Black");
}
}
/**
@ -863,14 +872,16 @@ function PreferenceClick() {
// Exit button
if (MouseIn(1815, 75, 90, 90)) PreferenceExit();
const adjustedSubscreenList = Object.keys(PreferenceExtensionsSettings).length > 0 ? PreferenceSubscreenList.concat("Extensions") : PreferenceSubscreenList;
// Open the selected subscreen
for (let A = 0; A < PreferenceSubscreenList.length; A++)
for (let A = 0; A < adjustedSubscreenList.length; A++)
if (MouseIn(500 + 420 * Math.floor(A / 7), 160 + 110 * (A % 7), 400, 90)) {
if (typeof window["PreferenceSubscreen" + PreferenceSubscreenList[A] + "Load"] === "function")
CommonDynamicFunction("PreferenceSubscreen" + PreferenceSubscreenList[A] + "Load()");
PreferenceSubscreen = PreferenceSubscreenList[A];
if (typeof window["PreferenceSubscreen" + adjustedSubscreenList[A] + "Load"] === "function")
CommonDynamicFunction("PreferenceSubscreen" + adjustedSubscreenList[A] + "Load()");
PreferenceSubscreen = adjustedSubscreenList[A];
PreferencePageCurrent = 1;
if (PreferenceSubscreenList[A] === "Scripts") {
if (adjustedSubscreenList[A] === "Scripts") {
PreferenceScriptTimer = Date.now() + 5000;
PreferenceScriptTimeoutHandle = setTimeout(() => {
PreferenceScriptTimer = null;
@ -3070,3 +3081,111 @@ var PreferenceOnlineSharedSettingsValidate = {
};
},
};
/**
* Registers a new extension setting to the preference screen
* @param {PreferenceExtensionsSettingItem} Setting - The extension setting to register
* @returns {void} - Nothing
*/
function PreferenceRegisterExtensionSetting(Setting) {
if((typeof Setting.Identifier !== "string" || Setting.Identifier.length < 1)
|| typeof Setting.load !== "function"
|| typeof Setting.run !== "function"
|| typeof Setting.click !== "function"
|| (typeof Setting.ButtonText !== "string" && typeof Setting.ButtonText !== "function")
|| (typeof Setting.Image !== "string" && typeof Setting.Image !== "function" && typeof Setting.Image !== "undefined")) {
console.error("Invalid extension setting");
return;
}
// Setting Names must be unique
const existing = PreferenceExtensionsSettings[Setting.Identifier];
if(existing) {
console.error(`Extension setting "${existing.Identifier}" already exists`);
return;
}
PreferenceExtensionsSettings[Setting.Identifier] = Setting;
}
/**
* Handles the loading of the preference subscreen for extensions
* @returns {void} - Nothing
*/
function PreferenceSubscreenExtensionsLoad() {
PreferenceExtensionsDisplay = Object.keys(PreferenceExtensionsSettings).map(
k => (
s=>({
Button: typeof s.ButtonText === "function" ? s.ButtonText() : s.ButtonText,
Image: s.Image && (typeof s.Image === "function" ? s.Image() : s.Image),
click: () => {
PreferenceExtensionsCurrent = s;
s?.load();
}
}))(PreferenceExtensionsSettings[k]));
}
/**
* Runs and draws the preference subscreen for extensions
* @returns {void} - Nothing
*/
function PreferenceSubscreenExtensionsRun() {
if(PreferenceExtensionsCurrent === null) {
DrawCharacter(Player, 50, 50, 0.9);
MainCanvas.textAlign = "left";
DrawText(TextGet("ExtensionsPreferences"), 500, 125, "Black", "Gray");
MainCanvas.textAlign = "center";
PreferenceExtensionsDisplay.forEach((s, i) => {
const X = 500 + Math.floor(i / 7) * 420;
const Y = 160 + (i % 7) * 110;
DrawButton(X, Y, 400, 90, "", "White", s.Image || null);
DrawTextFit(s.Button, X + 245, Y + 45, 310, "Black");
});
DrawButton(1815, 75, 90, 90, "", "White", "Icons/Exit.png");
} else {
PreferenceExtensionsCurrent.run();
}
}
/**
* Handles clicks in the preference subscreen for extensions
* @returns {void} - Nothing
*/
function PreferenceSubscreenExtensionsClick() {
if(PreferenceExtensionsCurrent === null) {
if (MouseIn(1815, 75, 90, 90)) PreferenceSubscreenExtensionsExit();
PreferenceExtensionsDisplay.forEach((s, i) => {
const X = 500 + Math.floor(i / 7) * 420;
const Y = 160 + (i % 7) * 110;
if (MouseIn(X, Y, 400, 90)) s.click();
});
} else {
PreferenceExtensionsCurrent.click();
}
}
function PreferenceSubscreenExtensionsUnload() {
PreferenceExtensionsCurrent?.unload?.();
}
function PreferenceSubscreenExtensionsExit() {
if(PreferenceExtensionsCurrent === null) {
PreferenceSubscreen = "";
} else if(PreferenceExtensionsCurrent.exit()) {
PreferenceSubscreenExtensionsClear();
}
}
/**
* Exit the preference subscreen for extensions, should be called when
* leaving custom menu of extensions if the extension exits the menu from itself.
* @returns {void} - Nothing
*/
function PreferenceSubscreenExtensionsClear() {
if(PreferenceSubscreen !== "Extensions" || PreferenceExtensionsCurrent === null) return;
PreferenceExtensionsCurrent.unload();
PreferenceExtensionsCurrent = null;
// Reload the extension settings
PreferenceSubscreenExtensionsLoad();
}

View file

@ -14,6 +14,7 @@ ControllerPreferences,- Controller Preferences -
NotificationsPreferences,- Notification Preferences -
GenderPreferences,- Gender Preferences -
ScriptsPreferences,- Script Permission Preferences -
ExtensionsPreferences,- Extensions Preferences -
HomepageGeneral,General
HomepageDifficulty,Difficulty
HomepageRestriction,Restriction
@ -30,6 +31,7 @@ HomepageController,Controller
HomepageNotifications,Notifications
HomepageGender,Gender
HomepageScripts,Scripts
HomepageExtensions,Extensions
DifficultyTitle,The difficulty mode enforces BDSM restrictions in multi-player only. Click for details.
DifficultyLevel0,Roleplay
Difficulty0Text0,Roleplay - This mode is fully open to customise your experience.

1 Preferences - Preferences -
14 NotificationsPreferences - Notification Preferences -
15 GenderPreferences - Gender Preferences -
16 ScriptsPreferences - Script Permission Preferences -
17 ExtensionsPreferences - Extensions Preferences -
18 HomepageGeneral General
19 HomepageDifficulty Difficulty
20 HomepageRestriction Restriction
31 HomepageNotifications Notifications
32 HomepageGender Gender
33 HomepageScripts Scripts
34 HomepageExtensions Extensions
35 DifficultyTitle The difficulty mode enforces BDSM restrictions in multi-player only. Click for details.
36 DifficultyLevel0 Roleplay
37 Difficulty0Text0 Roleplay - This mode is fully open to customise your experience.

View file

@ -30,6 +30,8 @@
- 性别设置 -
- Script Permission Preferences -
- 脚本权限设置 -
- Extensions Preferences -
- 扩展组件设置 -
General
通用
Difficulty
@ -62,6 +64,8 @@ Gender
性别
Scripts
脚本
Extensions
扩展组件
The difficulty mode enforces BDSM restrictions in multi-player only. Click for details.
难度模式仅在多人游戏中使BDSM限制强制生效。点击以了解更多
Roleplay

View file

@ -30,6 +30,8 @@
- 性別設置 -
- Script Permission Preferences -
- 腳本權限設定 -
- Extensions Preferences -
- 擴充組件設定 -
General
通用
Difficulty
@ -62,6 +64,8 @@ Gender
性別
Scripts
腳本
Extensions
擴充組件
The difficulty mode enforces BDSM restrictions in multi-player only. Click for details.
難度模式僅在多人遊戲中使BDSM限制強制生效。點擊以了解更多
Roleplay

View file

@ -355,7 +355,7 @@ type GraphicsFontName =
type PreferenceSubscreenName =
"General" | "Difficulty" | "Restriction" | "Chat" | "CensoredWords" | "Audio" | "Arousal" |
"Security" | "Online" | "Visibility" | "Immersion" | "Graphics" | "Controller" | "Notifications" |
"Gender" | "Scripts"
"Gender" | "Scripts" | "Extensions"
;
type FetishName =
@ -3762,6 +3762,73 @@ interface ArousalSettingsType {
DisableAdvancedVibes: boolean;
}
/** Preference Menu info for extensions settings*/
interface PreferenceExtensionsSettingItem {
/**
* The identifier of the extension.
* This is used to identify the extension and should be unique.
*/
Identifier: string;
/**
* The button text for the button of extension.
* If it's a Function, it will be called once when entering
* the extension setting menu. Use the return value as button text.
*/
ButtonText: string | (()=>string);
/**
* The image path of the extension, and is passed
* into {@link DrawButton} for creating the HTMLImageElement
* that is needed for drawing the Button image.
* If it's a Function, it will be called once when entering
* the extension setting menu. Use the return value as image
* path.
* If it's undefined, there will be no image for the button
*/
Image?: string | (()=>string);
/** Handles loading on entering the extension setting */
load?: () => void;
/** Handles the clicks of the extension setting */
click: () => void;
/** Handles the run and draws of the extension setting */
run: () => void;
/**
* Handles the unloading of the extension setting, typically
* from {@link CommonSetScreen}, when the player is disconnected.
* If it's undefined, there will be no unloading for the extension
* setting.
* Remind to check those HTML elements that are created in the
* extension setting, and hide/remove them from the DOM.
* Note that HTML elements with `HideOnPopup` class will be hidden
* automatically when a popup is shown.
*/
unload?: () => void;
/**
* Handles the exits of the extension setting, typically when
* user press `Esc` key.
* If a extension wants to exit the menu by itself
* (clicking `exit` button, etc.), the extension should call
* `PreferenceSubscreenExtensionsClear`.
* @returns If it returns `true`, the extension setting will be unload.
* And `unload` will be called once if it's defined and then main extension
* setting page is shown.
*/
exit: () => boolean | void;
}
/** Preference Menu info for extensions settings*/
type PreferenceExtensionsMenuButtonInfo = {
Button: string;
Image?: string;
click: () => void;
}
// #end region
// #region fortune wheel