waves/public/assets/g/turbowarp/main/js/addon-entry-swap-local-global.js
2025-04-09 17:11:14 -05:00

467 lines
17 KiB
JavaScript

(window["webpackJsonpGUI"] = window["webpackJsonpGUI"] || []).push([["addon-entry-swap-local-global"],{
/***/ "./node_modules/css-loader/index.js!./src/addons/addons/swap-local-global/style.css":
/*!*********************************************************************************!*\
!*** ./node_modules/css-loader!./src/addons/addons/swap-local-global/style.css ***!
\*********************************************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
exports = module.exports = __webpack_require__(/*! ../../../../node_modules/css-loader/lib/css-base.js */ "./node_modules/css-loader/lib/css-base.js")(false);
// imports
// module
exports.push([module.i, ".sa-swap-local-global-hint {\n padding-bottom: 1rem;\n}\n.sa-swap-local-global-stage {\n /* resolves scratch class style conflict */\n display: block;\n}\n", ""]);
// exports
/***/ }),
/***/ "./src/addons/addons/swap-local-global/_runtime_entry.js":
/*!***************************************************************!*\
!*** ./src/addons/addons/swap-local-global/_runtime_entry.js ***!
\***************************************************************/
/*! exports provided: resources */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "resources", function() { return resources; });
/* harmony import */ var _userscript_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./userscript.js */ "./src/addons/addons/swap-local-global/userscript.js");
/* harmony import */ var _css_loader_style_css__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! css-loader!./style.css */ "./node_modules/css-loader/index.js!./src/addons/addons/swap-local-global/style.css");
/* harmony import */ var _css_loader_style_css__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_css_loader_style_css__WEBPACK_IMPORTED_MODULE_1__);
/* generated by pull.js */
const resources = {
"userscript.js": _userscript_js__WEBPACK_IMPORTED_MODULE_0__["default"],
"style.css": _css_loader_style_css__WEBPACK_IMPORTED_MODULE_1___default.a
};
/***/ }),
/***/ "./src/addons/addons/swap-local-global/userscript.js":
/*!***********************************************************!*\
!*** ./src/addons/addons/swap-local-global/userscript.js ***!
\***********************************************************/
/*! exports provided: default */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony default export */ __webpack_exports__["default"] = (async function ({
addon,
msg,
console
}) {
const ScratchBlocks = await addon.tab.traps.getBlockly();
const vm = addon.tab.traps.vm;
const getTargetName = target => {
if (target.isStage) {
// Stage always has an internal name of "Stage", but we want a translatable name
return ScratchBlocks.ScratchMsgs.translate("SENSING_OF_STAGE", "Stage");
}
return target.getName();
};
const getTargetsThatUseVariable = id => vm.runtime.targets.filter(target => target.isOriginal).filter(target => Object.values(target.blocks._blocks).find(block => block.fields.LIST && block.fields.LIST.id === id || block.fields.VARIABLE && block.fields.VARIABLE.id === id)); // https://github.com/LLK/scratch-vm/blob/7c6f1e44fb0a9b0d0279225cd4c62fbe59b6af54/src/engine/blocks.js#L388-L394
const getTargetsWithLocalVariableNamed = (name, type) => vm.runtime.targets.filter(target => target.isOriginal && target.lookupVariableByNameAndType(name, type, true));
const getVmVariable = id => vm.editingTarget.lookupVariableById(id);
const isStageSelected = () => vm.editingTarget.isStage;
const deleteVariableWithoutDeletingBlocks = (workspace, variable) => {
// variable can be an ID or an actual Blockly variable object
if (typeof variable === "string") {
variable = workspace.getVariableById(variable);
}
workspace.variableMap_.deleteVariable(variable);
};
const syncBlockVariableNameWithActualVariableName = (workspace, id) => {
const variable = workspace.getVariableById(id);
for (const block of workspace.getAllBlocks()) {
block.updateVarName(variable);
}
};
let _undoRedoPreserveStateCallback = null;
const finishUndoRedoState = () => {
if (_undoRedoPreserveStateCallback) {
_undoRedoPreserveStateCallback();
_undoRedoPreserveStateCallback = null;
}
}; // https://github.com/LLK/scratch-blocks/blob/0d6012df1e18e66d82c1247f1f6d772a719982a7/core/variable_events.js#L194
const customUndoVarDelete = function customUndoVarDelete(forward) {
const workspace = this.getEventWorkspace_();
if (forward) {
_undoRedoPreserveStateCallback = beginPreservingState(workspace, this.varId);
deleteVariableWithoutDeletingBlocks(workspace, this.varId);
} else {
workspace.createVariable(this.varName, this.varType, this.varId, this.isLocal, this.isCloud);
finishUndoRedoState();
}
}; // https://github.com/LLK/scratch-blocks/blob/0d6012df1e18e66d82c1247f1f6d772a719982a7/core/variable_events.js#L131
const customUndoVarCreate = function customUndoVarCreate(forward) {
const workspace = this.getEventWorkspace_();
if (forward) {
workspace.createVariable(this.varName, this.varType, this.varId, this.isLocal, this.isCloud);
finishUndoRedoState();
} else {
_undoRedoPreserveStateCallback = beginPreservingState(workspace, this.varId);
deleteVariableWithoutDeletingBlocks(workspace, this.varId);
}
};
const flushBlocklyEventQueue = () => ScratchBlocks.Events.fireNow_();
const beginPreservingState = (workspace, id) => {
// oldMonitorState is an instance of https://github.com/LLK/scratch-vm/blob/develop/src/engine/monitor-record.js or undefined
const oldMonitorState = vm.runtime._monitorState.get(id);
const oldVmVariable = getVmVariable(id);
return () => {
flushBlocklyEventQueue();
const newVmVariable = getVmVariable(id);
if (newVmVariable) {
newVmVariable.value = oldVmVariable.value;
} // Update the variable monitor (state is maintained separately)
if (oldMonitorState) {
if (oldMonitorState.visible) {
vm.runtime.monitorBlocks.changeBlock({
id,
element: "checkbox",
value: true
});
}
const isLocal = !vm.runtime.getTargetForStage().variables[id];
let newMonitorState = oldMonitorState;
if (isLocal) {
const target = vm.editingTarget;
newMonitorState = newMonitorState.set("targetId", target.id);
newMonitorState = newMonitorState.set("spriteName", target.getName());
} else {
newMonitorState = newMonitorState.set("targetId", null);
newMonitorState = newMonitorState.set("spriteName", null);
}
if (newVmVariable.name !== oldVmVariable.name) {
const monitorBlocks = vm.runtime.monitorBlocks;
const block = monitorBlocks.getBlock(id);
if (block) {
newMonitorState = newMonitorState.set("params", monitorBlocks._getBlockParams(block));
}
}
vm.runtime.requestAddMonitor(newMonitorState);
}
if (newVmVariable.name !== oldVmVariable.name) {
syncBlockVariableNameWithActualVariableName(workspace, id);
}
};
};
const convertVariable = (oldBlocklyVariable, newLocal, newCloud) => {
const CLOUD_PREFIX = "☁ ";
const name = oldBlocklyVariable.name;
const id = oldBlocklyVariable.getId();
const type = oldBlocklyVariable.type;
const isLocal = oldBlocklyVariable.isLocal;
const isCloud = oldBlocklyVariable.isCloud;
if (isLocal === newLocal && isCloud === newCloud) {
return;
} // Cloud variables must always be global
if (newCloud && newLocal) {
alert(msg("cant-convert-cloud"));
return;
}
const editingTarget = vm.editingTarget;
if (isLocal !== newLocal) {
if (newLocal) {
// Stage cannot have local variables
if (isStageSelected()) {
alert(msg("cant-convert-stage"));
return;
} // Variables used by unfocused sprites cannot be made local
// That includes cases where the variable is used by multiple sprites and where it's only used by an unfocused sprite
const targets = getTargetsThatUseVariable(id);
if (!targets.every(i => i === editingTarget)) {
if (targets.length > 1) {
alert(msg("cant-convert-to-local", {
sprites: targets.map(getTargetName).join(", ")
}));
} else {
alert(msg("cant-convert-used-elsewhere", {
sprite: getTargetName(targets[0])
}));
}
return;
}
} else {
// Global variables must not conflict with any local variables
const targets = getTargetsWithLocalVariableNamed(name, type).filter(target => target !== editingTarget);
if (targets.length > 0) {
alert(msg("cant-convert-conflict", {
sprites: targets.map(getTargetName).join(", ")
}));
return;
}
}
}
let newName = name;
if (isCloud !== newCloud) {
if (newCloud) {
newName = CLOUD_PREFIX + name;
} else if (name.startsWith(CLOUD_PREFIX)) {
newName = name.replace(CLOUD_PREFIX, "");
}
}
const workspace = oldBlocklyVariable.workspace;
const finishPreservingState = beginPreservingState(workspace, id);
ScratchBlocks.Events.setGroup(true);
try {
deleteVariableWithoutDeletingBlocks(workspace, oldBlocklyVariable);
workspace.createVariable(newName, type, id, newLocal, newCloud);
} finally {
ScratchBlocks.Events.setGroup(false);
} // 2 items will be added to the queue: a variable create and delete
// We override their undo handlers to make undo/redo work properly
flushBlocklyEventQueue();
const stack = workspace.undoStack_;
const createEvent = stack[stack.length - 1];
const deleteEvent = stack[stack.length - 2];
if (createEvent instanceof ScratchBlocks.Events.VarCreate && deleteEvent instanceof ScratchBlocks.Events.VarDelete) {
createEvent.run = customUndoVarCreate;
deleteEvent.run = customUndoVarDelete;
}
finishPreservingState();
};
const canUserUseCloudVariables = () => {
const blocksWrapper = document.querySelector('[class^="gui_blocks-wrapper_"]');
let internalNode = blocksWrapper[addon.tab.traps.getInternalKey(blocksWrapper)];
while (true) {
var _internalNode$stateNo, _internalNode$stateNo2;
if (!internalNode) {
return false;
}
const canUseCloud = (_internalNode$stateNo = internalNode.stateNode) === null || _internalNode$stateNo === void 0 ? void 0 : (_internalNode$stateNo2 = _internalNode$stateNo.props) === null || _internalNode$stateNo2 === void 0 ? void 0 : _internalNode$stateNo2.canUseCloud;
if (typeof canUseCloud === "boolean") {
return canUseCloud;
}
internalNode = internalNode.child;
}
};
const addMoreOptionsToPrompt = variable => {
if (addon.self.disabled) {
return;
}
const promptBody = document.querySelector('[class^="prompt_body_"]');
if (!promptBody) {
return;
}
const headerTitle = promptBody.parentElement.querySelector('[class^="modal_header-item_"]');
if (headerTitle) {
if (variable.type === "") {
headerTitle.textContent = msg("edit-variable-header");
} else {
headerTitle.textContent = msg("edit-list-header");
}
}
const root = document.createElement("div");
addon.tab.displayNoneWhileDisabled(root);
const createLabeledInput = (text, value) => {
const outer = document.createElement("label");
const input = document.createElement("input");
if (value === "checkbox") {
input.type = "checkbox";
} else {
input.name = "variableScopeOption";
input.type = "radio";
input.value = value;
}
outer.appendChild(input);
const label = document.createElement("span");
label.textContent = text;
outer.appendChild(label);
return {
outer,
label,
input
};
};
const promptDisabledClass = addon.tab.scratchClass("prompt_disabled-label");
const noLocalsInStageSection = document.createElement("div");
noLocalsInStageSection.className = addon.tab.scratchClass("prompt_info-message", "prompt_cloud-option", {
others: "sa-swap-local-global-stage"
});
noLocalsInStageSection.appendChild(Object.assign(document.createElement("span"), {
textContent: addon.tab.scratchMessage("gui.gui.variablePromptAllSpritesMessage")
}));
const scopeSection = document.createElement("div");
scopeSection.className = addon.tab.scratchClass("prompt_options-row", "prompt_cloud-option");
const forAllSprites = createLabeledInput(addon.tab.scratchMessage("gui.gui.variableScopeOptionAllSprites"), "global");
const forThisSpriteOnly = createLabeledInput(addon.tab.scratchMessage("gui.gui.variableScopeOptionSpriteOnly"), "local");
forAllSprites.input.checked = !variable.isLocal;
forThisSpriteOnly.input.checked = variable.isLocal;
scopeSection.appendChild(forAllSprites.outer);
scopeSection.appendChild(forThisSpriteOnly.outer);
const cloudSection = document.createElement("div");
cloudSection.className = addon.tab.scratchClass("prompt_cloud-option");
const cloudCheckbox = createLabeledInput(addon.tab.scratchMessage("gui.gui.cloudVariableOption"), "checkbox");
cloudCheckbox.input.checked = variable.isCloud;
if (!vm.runtime.canAddCloudVariable() && !variable.isCloud) {
cloudCheckbox.input.disabled = true;
cloudSection.classList.add(promptDisabledClass);
}
cloudSection.appendChild(cloudCheckbox.outer);
const updateDisabledInputs = () => {
const thisSpriteOnlyDisabled = cloudCheckbox.input.checked;
forThisSpriteOnly.input.disabled = thisSpriteOnlyDisabled;
forThisSpriteOnly.label.classList.toggle(promptDisabledClass, thisSpriteOnlyDisabled);
if (thisSpriteOnlyDisabled) {
forAllSprites.input.click();
}
};
cloudCheckbox.input.addEventListener("change", updateDisabledInputs);
updateDisabledInputs();
let isAnythingConfigurable = false;
if (isStageSelected()) {
root.appendChild(noLocalsInStageSection);
} else {
isAnythingConfigurable = true;
root.appendChild(scopeSection);
}
if (variable.type === "" && canUserUseCloudVariables()) {
isAnythingConfigurable = true;
root.appendChild(cloudSection);
}
if (isAnythingConfigurable) {
root.prepend(Object.assign(document.createElement("div"), {
textContent: msg("edit"),
className: "sa-swap-local-global-hint"
}));
}
promptBody.insertBefore(root, promptBody.lastChild);
return {
isLocal: () => forThisSpriteOnly.input.checked,
isCloud: () => cloudCheckbox.input.checked
};
}; // https://github.com/LLK/scratch-blocks/blob/c5014f61e2e538e99601a9e0cb39e339e44c3910/core/variables.js#L470
const originalRenameVariable = ScratchBlocks.Variables.renameVariable;
ScratchBlocks.Variables.renameVariable = function (workspace, variable, opt_callback) {
const ret = originalRenameVariable.call(this, workspace, variable, (...args) => {
if (opt_callback) {
opt_callback(...args);
}
if (!addon.self.disabled && prompt) {
convertVariable(variable, prompt.isLocal(), prompt.isCloud());
}
});
const prompt = addMoreOptionsToPrompt(variable);
return ret;
};
addon.tab.createBlockContextMenu((items, block) => {
if (!addon.self.disabled && (block.getCategory() === "data" || block.getCategory() === "data-lists")) {
const variable = block.workspace.getVariableById(block.getVars()[0]);
if (variable) {
if (items.length > 0) {
if (items[0].text === ScratchBlocks.ScratchMsgs.translate("RENAME_VARIABLE")) {
items[0].text = msg("edit-variable-option");
} else if (items[0].text === ScratchBlocks.ScratchMsgs.translate("RENAME_LIST")) {
items[0].text = msg("edit-list-option");
}
}
items.push({
enabled: true,
separator: true,
text: msg("to-".concat(variable.isLocal ? "global" : "local")),
callback: () => convertVariable(variable, !variable.isLocal, variable.isCloud)
});
}
}
return items;
}, {
flyout: true,
blocks: true
});
});
/***/ })
}]);
//# sourceMappingURL=addon-entry-swap-local-global.js.map