{"code":"(window.webpackJsonpGUI=window.webpackJsonpGUI||[]).push([[20],{1551:function(t,e,s){\"use strict\";s.r(e),s.d(e,\"resources\",(function(){return r}));const r={\"userscript.js\":async function(t){let{addon:e,console:s,msg:r}=t;await e.tab.traps.getPaper();const i=t=>Math.round(+t).toString(16).toUpperCase().padStart(2,\"0\"),n=t=>{if(null===t)return null;if(\"string\"==typeof t){if(t.startsWith(\"#\"))return t.substring(0,9).toUpperCase();const e=t.match(/^rgb\\((\\d+)\\s*,(\\d+)\\s*,(\\d+)\\)$/);if(e){const[t,s,r,n]=e;return\"#\".concat(i(s)).concat(i(r)).concat(i(n))}const s=t.match(/^rgba\\((\\d+)\\s*,(\\d+)\\s*,(\\d+),([\\d.]+)\\)$/);if(s){const[t,e,r,n,o]=s;return\"#\".concat(i(e)).concat(i(r)).concat(i(n)).concat(i(255*o))}}return s.log(\"Could not normalize color\",t),null},o=t=>t===a?a:n(t),a=\"scratch-paint/style-path/mixed\",c=n(\"#9966FF\"),p=n(\"#000000\"),l=Object.assign(Object.create(null),{BRUSH:{resetsFill:!0},ERASER:{},LINE:{resetsStroke:!0,requiresNonZeroStrokeWidth:!0,supportsGradient:!0},FILL:{resetsFill:!0,supportsGradient:!0},SELECT:{supportsGradient:!0},RESHAPE:{supportsGradient:!0},OVAL:{resetsFill:!0,resetsStroke:!0,supportsGradient:!0},RECT:{resetsFill:!0,resetsStroke:!0,supportsGradient:!0},TEXT:{resetsFill:!0,resetsStroke:!0},BIT_BRUSH:{resetsFill:!0},BIT_LINE:{resetsFill:!0,requiresNonZeroStrokeWidth:!0},BIT_OVAL:{resetsFill:!0,resetsStroke:!0,supportsGradient:!0},BIT_RECT:{resetsFill:!0,resetsStroke:!0,supportsGradient:!0},BIT_TEXT:{resetsFill:!0,resetsStroke:!0},BIT_FILL:{resetsFill:!0,supportsGradient:!0},BIT_ERASER:{},BIT_SELECT:{supportsGradient:!0}}),d=()=>l[e.tab.redux.state.scratchPaint.mode];class u{constructor(t,e,s,r){this.reduxPropertyName=t,this.primaryAction=e,this.secondaryAction=s,this.gradientTypeAction=r}get(){return(arguments.length>0&&void 0!==arguments[0]?arguments[0]:e.tab.redux.state).scratchPaint.color[this.reduxPropertyName]}set(t){const s=this.get(),r=o(t.primary);s.primary!==r&&e.tab.redux.dispatch({type:this.primaryAction,color:r});const i=d();if(i&&i.supportsGradient){const r=o(t.secondary);s.secondary!==r&&e.tab.redux.dispatch({type:this.secondaryAction,color:r}),s.gradientType!==t.gradientType&&e.tab.redux.dispatch({type:this.gradientTypeAction,gradientType:t.gradientType})}}}const h=new u(\"fillColor\",\"scratch-paint/fill-style/CHANGE_FILL_COLOR\",\"scratch-paint/fill-style/CHANGE_FILL_COLOR_2\",\"scratch-paint/fill-style/CHANGE_FILL_GRADIENT_TYPE\"),g=new u(\"strokeColor\",\"scratch-paint/stroke-style/CHANGE_STROKE_COLOR\",\"scratch-paint/stroke-style/CHANGE_STROKE_COLOR_2\",\"scratch-paint/stroke-style/CHANGE_STROKE_GRADIENT_TYPE\"),y=t=>({primary:t,secondary:null,gradientType:\"SOLID\"});let E,T,_;const S=()=>{E=y(n(e.settings.get(\"fill\"))),T=y(n(e.settings.get(\"stroke\"))),_=e.settings.get(\"strokeSize\")};S();const k=()=>{h.set(E)},f=()=>{g.set(T)},m=t=>{let s=_;0===s&&t&&(s=1),e.tab.redux.state.scratchPaint.color.strokeWidth!==s&&e.tab.redux.dispatch({type:\"scratch-paint/stroke-width/CHANGE_STROKE_WIDTH\",strokeWidth:s})};e.self.disabled||(k(),f(),m(!1)),e.settings.addEventListener(\"change\",(()=>{e.settings.get(\"persistence\")||S()}));const G=t=>null!==t.primary&&t.primary!==a;let L=!1;e.tab.redux.initialize(),e.tab.redux.addEventListener(\"statechanged\",(t=>{let{detail:r}=t;if(e.self.disabled)return;const i=r.action;if(!L&&e.settings.get(\"persistence\")){const t=h.get();h.get(r.prev)!==t&&G(t)&&(E=t);const e=g.get();g.get(r.prev)!==e&&G(e)&&(T=e);const s=r.next.scratchPaint.color.strokeWidth;\"number\"==typeof s&&(_=s)}\"scratch-paint/modes/CHANGE_MODE\"===i.type&&(L=!0,queueMicrotask((()=>{if(L=!1,e.settings.get(\"persistence\")){const t=d();if(!t)return void s.warn(\"unknown tool\",e.tab.redux.state.scratchPaint.mode);t.resetsFill&&k(),t.resetsStroke&&(m(!!t.requiresNonZeroStrokeWidth),f())}else{const t=h.get(r.prev);if(null===t.primary||t.primary===a){h.get().primary===c&&k()}const e=g.get(r.prev);if(null===e.primary||e.primary===a){g.get().primary===p&&(m(!0),f())}}})))}))}}}}]);","name":"js/pentapod/addon-entry-default-costume-editor-color.6dc492ab3d8e5dcdf944.js","input":"(window[\"webpackJsonpGUI\"] = window[\"webpackJsonpGUI\"] || []).push([[20],{\n\n/***/ 1551:\n/***/ (function(module, __webpack_exports__, __webpack_require__) {\n\n\"use strict\";\n// ESM COMPAT FLAG\n__webpack_require__.r(__webpack_exports__);\n\n// EXPORTS\n__webpack_require__.d(__webpack_exports__, \"resources\", function() { return /* binding */ resources; });\n\n// CONCATENATED MODULE: ./src/addons/addons/default-costume-editor-color/userscript.js\n/* harmony default export */ var userscript = (async function (_ref) {\n let {\n addon,\n console,\n msg\n } = _ref;\n // We don\"t *need* to wait for the costume editor to be opened, but redux updates take a non-zero\n // amount of CPU time so let's delay that for as long as possible.\n await addon.tab.traps.getPaper();\n const hexComponent = str => Math.round(+str).toString(16).toUpperCase().padStart(2, \"0\");\n const parseColor = color => {\n if (color === null) {\n return null;\n }\n if (typeof color === \"string\") {\n // TW natively supports hex color codes with or without transparency\n if (color.startsWith(\"#\")) {\n return color.substring(0, 9).toUpperCase();\n }\n // Sometimes paper gives us rgb() colors which have to be converted to hex\n const rgbMatch = color.match(/^rgb\\((\\d+)\\s*,(\\d+)\\s*,(\\d+)\\)$/);\n if (rgbMatch) {\n const [_, r, g, b] = rgbMatch;\n return \"#\".concat(hexComponent(r)).concat(hexComponent(g)).concat(hexComponent(b));\n }\n // It can also give us rgba() colors\n const rgbaMatch = color.match(/^rgba\\((\\d+)\\s*,(\\d+)\\s*,(\\d+),([\\d.]+)\\)$/);\n if (rgbaMatch) {\n const [_, r, g, b, a] = rgbaMatch;\n return \"#\".concat(hexComponent(r)).concat(hexComponent(g)).concat(hexComponent(b)).concat(hexComponent(a * 255));\n }\n }\n console.log(\"Could not normalize color\", color);\n return null;\n };\n const parseColorStyleColor = color => {\n if (color === MIXED) return MIXED;\n return parseColor(color);\n };\n\n // Special value Scratch uses as color when objects with different colors are selected\n // https://github.com/scratchfoundation/scratch-paint/blob/6733e20b56f52d139f9885952a57c7da012a542f/src/helper/style-path.js#L10\n const MIXED = \"scratch-paint/style-path/mixed\";\n const SCRATCH_DEFAULT_FILL = parseColor(\"#9966FF\");\n const SCRATCH_DEFAULT_STROKE = parseColor(\"#000000\");\n const TOOL_INFO = Object.assign(Object.create(null), {\n // Tool names and gradient info defined in https://github.com/scratchfoundation/scratch-paint/blob/develop/src/lib/modes.js\n // Search for activateTool() in matching file in https://github.com/scratchfoundation/scratch-paint/tree/develop/src/containers\n BRUSH: {\n resetsFill: true\n },\n ERASER: {},\n LINE: {\n resetsStroke: true,\n requiresNonZeroStrokeWidth: true,\n supportsGradient: true\n },\n FILL: {\n resetsFill: true,\n supportsGradient: true\n },\n SELECT: {\n supportsGradient: true\n },\n RESHAPE: {\n supportsGradient: true\n },\n OVAL: {\n resetsFill: true,\n resetsStroke: true,\n supportsGradient: true\n },\n RECT: {\n resetsFill: true,\n resetsStroke: true,\n supportsGradient: true\n },\n TEXT: {\n resetsFill: true,\n resetsStroke: true\n },\n BIT_BRUSH: {\n resetsFill: true\n },\n BIT_LINE: {\n resetsFill: true,\n requiresNonZeroStrokeWidth: true\n },\n BIT_OVAL: {\n resetsFill: true,\n resetsStroke: true,\n supportsGradient: true\n },\n BIT_RECT: {\n resetsFill: true,\n resetsStroke: true,\n supportsGradient: true\n },\n BIT_TEXT: {\n resetsFill: true,\n resetsStroke: true\n },\n BIT_FILL: {\n resetsFill: true,\n supportsGradient: true\n },\n BIT_ERASER: {},\n BIT_SELECT: {\n supportsGradient: true\n }\n });\n const getToolInfo = () => TOOL_INFO[addon.tab.redux.state.scratchPaint.mode];\n class ColorStyleReducerWrapper {\n constructor(reduxPropertyName, primaryAction, secondaryAction, gradientTypeAction) {\n this.reduxPropertyName = reduxPropertyName;\n this.primaryAction = primaryAction;\n this.secondaryAction = secondaryAction;\n this.gradientTypeAction = gradientTypeAction;\n }\n get() {\n let state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : addon.tab.redux.state;\n return state.scratchPaint.color[this.reduxPropertyName];\n }\n set(newColor) {\n const state = this.get();\n const newPrimary = parseColorStyleColor(newColor.primary);\n if (state.primary !== newPrimary) {\n addon.tab.redux.dispatch({\n type: this.primaryAction,\n color: newPrimary\n });\n }\n const toolInfo = getToolInfo();\n const toolSupportsGradient = toolInfo && toolInfo.supportsGradient;\n if (toolSupportsGradient) {\n const newSecondary = parseColorStyleColor(newColor.secondary);\n if (state.secondary !== newSecondary) {\n addon.tab.redux.dispatch({\n type: this.secondaryAction,\n color: newSecondary\n });\n }\n if (state.gradientType !== newColor.gradientType) {\n addon.tab.redux.dispatch({\n type: this.gradientTypeAction,\n gradientType: newColor.gradientType\n });\n }\n }\n }\n }\n const fillStyle = new ColorStyleReducerWrapper(\"fillColor\", \"scratch-paint/fill-style/CHANGE_FILL_COLOR\", \"scratch-paint/fill-style/CHANGE_FILL_COLOR_2\", \"scratch-paint/fill-style/CHANGE_FILL_GRADIENT_TYPE\");\n const strokeStyle = new ColorStyleReducerWrapper(\"strokeColor\", \"scratch-paint/stroke-style/CHANGE_STROKE_COLOR\", \"scratch-paint/stroke-style/CHANGE_STROKE_COLOR_2\", \"scratch-paint/stroke-style/CHANGE_STROKE_GRADIENT_TYPE\");\n const simpleHexColor = hex => ({\n primary: hex,\n secondary: null,\n gradientType: \"SOLID\"\n });\n let defaultFillColor;\n let defaultStrokeColor;\n let defaultStrokeWidth;\n const setDefaultColorsToSettings = () => {\n defaultFillColor = simpleHexColor(parseColor(addon.settings.get(\"fill\")));\n defaultStrokeColor = simpleHexColor(parseColor(addon.settings.get(\"stroke\")));\n defaultStrokeWidth = addon.settings.get(\"strokeSize\");\n };\n setDefaultColorsToSettings();\n const applyFillColor = () => {\n fillStyle.set(defaultFillColor);\n };\n const applyStrokeColor = () => {\n strokeStyle.set(defaultStrokeColor);\n };\n const applyStrokeWidth = mustBeNonZero => {\n let width = defaultStrokeWidth;\n if (width === 0 && mustBeNonZero) {\n width = 1;\n }\n if (addon.tab.redux.state.scratchPaint.color.strokeWidth !== width) {\n addon.tab.redux.dispatch({\n type: \"scratch-paint/stroke-width/CHANGE_STROKE_WIDTH\",\n strokeWidth: width\n });\n }\n };\n if (!addon.self.disabled) {\n applyFillColor();\n applyStrokeColor();\n applyStrokeWidth(false);\n }\n addon.settings.addEventListener(\"change\", () => {\n if (!addon.settings.get(\"persistence\")) {\n setDefaultColorsToSettings();\n }\n });\n const isValidColorToPersist = color => color.primary !== null && color.primary !== MIXED;\n let activatingTool = false;\n addon.tab.redux.initialize();\n addon.tab.redux.addEventListener(\"statechanged\", _ref2 => {\n let {\n detail\n } = _ref2;\n if (addon.self.disabled) {\n return;\n }\n const action = detail.action;\n if (!activatingTool && addon.settings.get(\"persistence\")) {\n // We always want to check for changes instead of filtering to just certain actions because quite a few\n // actions can change these.\n const newFill = fillStyle.get();\n if (fillStyle.get(detail.prev) !== newFill && isValidColorToPersist(newFill)) {\n defaultFillColor = newFill;\n }\n const newStroke = strokeStyle.get();\n if (strokeStyle.get(detail.prev) !== newStroke && isValidColorToPersist(newStroke)) {\n defaultStrokeColor = newStroke;\n }\n const newStrokeWidth = detail.next.scratchPaint.color.strokeWidth;\n if (typeof newStrokeWidth === \"number\") {\n defaultStrokeWidth = newStrokeWidth;\n }\n }\n if (action.type === \"scratch-paint/modes/CHANGE_MODE\") {\n activatingTool = true;\n queueMicrotask(() => {\n activatingTool = false;\n if (addon.settings.get(\"persistence\")) {\n // In persistence, we always want to re-apply the previous stroke and fill.\n const toolInfo = getToolInfo();\n if (!toolInfo) {\n console.warn(\"unknown tool\", addon.tab.redux.state.scratchPaint.mode);\n return;\n }\n if (toolInfo.resetsFill) {\n applyFillColor();\n }\n if (toolInfo.resetsStroke) {\n applyStrokeWidth(!!toolInfo.requiresNonZeroStrokeWidth);\n applyStrokeColor();\n }\n } else {\n // In non-persistence, we'll only apply the default colors when Scratch resets them to maintain the same behavior.\n // We have to do this weird redux trick because we can't modify these constants:\n // https://github.com/scratchfoundation/scratch-paint/blob/6733e20b56f52d139f9885952a57c7da012a542f/src/reducers/fill-style.js#L7\n // https://github.com/scratchfoundation/scratch-paint/blob/6733e20b56f52d139f9885952a57c7da012a542f/src/reducers/stroke-style.js#L7\n const oldFillColor = fillStyle.get(detail.prev);\n if (oldFillColor.primary === null || oldFillColor.primary === MIXED) {\n const newFillColor = fillStyle.get();\n if (newFillColor.primary === SCRATCH_DEFAULT_FILL) {\n applyFillColor();\n }\n }\n const oldStrokeColor = strokeStyle.get(detail.prev);\n if (oldStrokeColor.primary === null || oldStrokeColor.primary === MIXED) {\n const newStrokeColor = strokeStyle.get();\n if (newStrokeColor.primary === SCRATCH_DEFAULT_STROKE) {\n applyStrokeWidth(true);\n applyStrokeColor();\n }\n }\n }\n });\n }\n });\n});\n// CONCATENATED MODULE: ./src/addons/addons/default-costume-editor-color/_runtime_entry.js\n/* generated by pull.js */\n\nconst resources = {\n \"userscript.js\": userscript\n};\n\n/***/ })\n\n}]);","inputSourceMap":null}