mirror of
https://github.com/tiennm99/WPlace-AutoBOT.git
synced 2026-10-13 02:14:29 +00:00
Merge pull request #91 from 7est/0831
Add Checkbox to Control Transparent Pixel Drawing
This commit is contained in:
16 files changed
+141
-42
No files matched your search
+78
-26
@@ -499,6 +499,7 @@ function applyTheme() {
|
||||
availableColors: [],
|
||||
activeColorPalette: [], // User-selected colors for conversion
|
||||
paintWhitePixels: true, // Default to ON
|
||||
paintTransparentPixels: false, // Default to OFF
|
||||
currentCharges: 0,
|
||||
maxCharges: 1, // Default max charges
|
||||
cooldown: CONFIG.COOLDOWN_DEFAULT,
|
||||
@@ -813,7 +814,7 @@ function applyTheme() {
|
||||
const d = cached.data;
|
||||
const a = d[idx + 3];
|
||||
const alphaThresh = state.customTransparencyThreshold || CONFIG.TRANSPARENCY_THRESHOLD;
|
||||
if (a < alphaThresh) {
|
||||
if (!state.paintTransparentPixels && a < alphaThresh) {
|
||||
// Treat as transparent / unavailable
|
||||
// Lightweight debug: show when transparency causes skip (only if verbose enabled)
|
||||
if (window._overlayDebug) console.debug('getTilePixelColor: transparent pixel, skipping', tileKey, x, y, a);
|
||||
@@ -845,7 +846,7 @@ function applyTheme() {
|
||||
const data = ctx.getImageData(x, y, 1, 1).data;
|
||||
const a = data[3];
|
||||
const alphaThresh = state.customTransparencyThreshold || CONFIG.TRANSPARENCY_THRESHOLD;
|
||||
if (a < alphaThresh) {
|
||||
if (!state.paintTransparentPixels && a < alphaThresh) {
|
||||
if (window._overlayDebug) console.debug('getTilePixelColor: transparent pixel (fallback), skipping', tileKey, x, y, a);
|
||||
return null;
|
||||
}
|
||||
@@ -3018,6 +3019,26 @@ function applyTheme() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Paint Options Section -->
|
||||
<div class="wplace-settings-section">
|
||||
<label class="wplace-settings-section-label">
|
||||
<i class="fas fa-paint-brush wplace-icon-paint"></i>
|
||||
${Utils.t("paintOptions")}
|
||||
</label>
|
||||
<div class="wplace-settings-section-wrapper wplace-notifications-wrapper">
|
||||
<!-- Paint White Pixels Toggle -->
|
||||
<label class="wplace-notification-toggle">
|
||||
<span>${Utils.t("paintWhitePixels")}</span>
|
||||
<input type="checkbox" id="settingsPaintWhiteToggle" ${state.paintWhitePixels ? 'checked' : ''} class="wplace-notification-checkbox" />
|
||||
</label>
|
||||
<!-- Paint Transparent Pixels Toggle -->
|
||||
<label class="wplace-notification-toggle">
|
||||
<span>${Utils.t("paintTransparentPixels")}</span>
|
||||
<input type="checkbox" id="settingsPaintTransparentToggle" ${state.paintTransparentPixels ? 'checked' : ''} class="wplace-notification-checkbox" />
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Speed Control Section -->
|
||||
<div class="wplace-settings-section">
|
||||
<label class="wplace-settings-section-label">
|
||||
@@ -3269,11 +3290,15 @@ function applyTheme() {
|
||||
</label>
|
||||
<label class="resize-checkbox-label">
|
||||
<input type="checkbox" id="keepAspect" checked>
|
||||
Keep Aspect Ratio
|
||||
${Utils.t("keepAspectRatio")}
|
||||
</label>
|
||||
<label class="resize-checkbox-label">
|
||||
<input type="checkbox" id="paintWhiteToggle" checked>
|
||||
Paint White Pixels
|
||||
${Utils.t("paintWhitePixels")}
|
||||
</label>
|
||||
<label class="resize-checkbox-label">
|
||||
<input type="checkbox" id="paintTransparentToggle" checked>
|
||||
${Utils.t("paintTransparentPixels")}
|
||||
</label>
|
||||
<div class="resize-zoom-controls">
|
||||
<button id="zoomOutBtn" class="wplace-btn resize-zoom-btn" title="${Utils.t('zoomOut')}"><i class="fas fa-search-minus"></i></button>
|
||||
@@ -3761,17 +3786,33 @@ function applyTheme() {
|
||||
})
|
||||
}
|
||||
|
||||
const overlayOpacitySlider = settingsContainer.querySelector("#overlayOpacitySlider");
|
||||
const overlayOpacityValue = settingsContainer.querySelector("#overlayOpacityValue");
|
||||
const enableBlueMarbleToggle = settingsContainer.querySelector("#enableBlueMarbleToggle");
|
||||
const overlayOpacitySlider = settingsContainer.querySelector("#overlayOpacitySlider");
|
||||
const overlayOpacityValue = settingsContainer.querySelector("#overlayOpacityValue");
|
||||
const enableBlueMarbleToggle = settingsContainer.querySelector("#enableBlueMarbleToggle");
|
||||
const settingsPaintWhiteToggle = settingsContainer.querySelector("#settingsPaintWhiteToggle");
|
||||
const settingsPaintTransparentToggle = settingsContainer.querySelector("#settingsPaintTransparentToggle");
|
||||
|
||||
if (overlayOpacitySlider && overlayOpacityValue) {
|
||||
overlayOpacitySlider.addEventListener('input', (e) => {
|
||||
const opacity = parseFloat(e.target.value);
|
||||
state.overlayOpacity = opacity;
|
||||
overlayOpacityValue.textContent = `${Math.round(opacity * 100)}%`;
|
||||
});
|
||||
}
|
||||
if (overlayOpacitySlider && overlayOpacityValue) {
|
||||
overlayOpacitySlider.addEventListener('input', (e) => {
|
||||
const opacity = parseFloat(e.target.value);
|
||||
state.overlayOpacity = opacity;
|
||||
overlayOpacityValue.textContent = `${Math.round(opacity * 100)}%`;
|
||||
});
|
||||
}
|
||||
|
||||
if (settingsPaintWhiteToggle) {
|
||||
settingsPaintWhiteToggle.addEventListener('change', (e) => {
|
||||
state.paintWhitePixels = e.target.checked;
|
||||
saveBotSettings();
|
||||
});
|
||||
}
|
||||
|
||||
if (settingsPaintTransparentToggle) {
|
||||
settingsPaintTransparentToggle.addEventListener('change', (e) => {
|
||||
state.paintTransparentPixels = e.target.checked;
|
||||
saveBotSettings();
|
||||
});
|
||||
}
|
||||
|
||||
// Speed slider event listener
|
||||
const speedSlider = settingsContainer.querySelector("#speedSlider");
|
||||
@@ -3822,6 +3863,7 @@ function applyTheme() {
|
||||
const heightValue = resizeContainer.querySelector("#heightValue")
|
||||
const keepAspect = resizeContainer.querySelector("#keepAspect")
|
||||
const paintWhiteToggle = resizeContainer.querySelector("#paintWhiteToggle");
|
||||
const paintTransparentToggle = resizeContainer.querySelector("#paintTransparentToggle");
|
||||
const zoomSlider = resizeContainer.querySelector("#zoomSlider");
|
||||
const zoomValue = resizeContainer.querySelector('#zoomValue');
|
||||
const zoomInBtn = resizeContainer.querySelector('#zoomInBtn');
|
||||
@@ -4133,6 +4175,7 @@ function applyTheme() {
|
||||
zoomSlider.value = 1;
|
||||
if (zoomValue) zoomValue.textContent = '100%';
|
||||
paintWhiteToggle.checked = state.paintWhitePixels;
|
||||
paintTransparentToggle.checked = state.paintTransparentPixels;
|
||||
|
||||
let _previewTimer = null;
|
||||
let _previewJobId = 0;
|
||||
@@ -4236,7 +4279,7 @@ function applyTheme() {
|
||||
const idx = y * w + x;
|
||||
const i4 = idx * 4;
|
||||
const r = data[i4], g = data[i4 + 1], b = data[i4 + 2], a = data[i4 + 3];
|
||||
const isEligible = a >= tThresh && (state.paintWhitePixels || !Utils.isWhitePixel(r, g, b));
|
||||
const isEligible = (state.paintTransparentPixels || a >= tThresh) && (state.paintWhitePixels || !Utils.isWhitePixel(r, g, b));
|
||||
eligible[idx] = isEligible ? 1 : 0;
|
||||
work[idx * 3] = r;
|
||||
work[idx * 3 + 1] = g;
|
||||
@@ -4288,7 +4331,7 @@ function applyTheme() {
|
||||
} else {
|
||||
for (let i = 0; i < data.length; i += 4) {
|
||||
const r = data[i], g = data[i + 1], b = data[i + 2], a = data[i + 3];
|
||||
if (a < tThresh || (!state.paintWhitePixels && Utils.isWhitePixel(r, g, b))) {
|
||||
if ((!state.paintTransparentPixels && a < tThresh) || (!state.paintWhitePixels && Utils.isWhitePixel(r, g, b))) {
|
||||
data[i + 3] = 0;
|
||||
continue;
|
||||
}
|
||||
@@ -4335,10 +4378,17 @@ function applyTheme() {
|
||||
if (!isNaN(fit) && isFinite(fit)) applyZoom(fit);
|
||||
};
|
||||
|
||||
paintWhiteToggle.onchange = (e) => {
|
||||
state.paintWhitePixels = e.target.checked;
|
||||
_updateResizePreview();
|
||||
};
|
||||
paintWhiteToggle.onchange = (e) => {
|
||||
state.paintWhitePixels = e.target.checked;
|
||||
_updateResizePreview();
|
||||
saveBotSettings();
|
||||
};
|
||||
|
||||
paintTransparentToggle.onchange = (e) => {
|
||||
state.paintTransparentPixels = e.target.checked;
|
||||
_updateResizePreview();
|
||||
saveBotSettings();
|
||||
};
|
||||
|
||||
let panX = 0, panY = 0;
|
||||
const clampPan = () => {
|
||||
@@ -4772,7 +4822,7 @@ function applyTheme() {
|
||||
const i4 = idx * 4;
|
||||
const r = data[i4], g = data[i4 + 1], b = data[i4 + 2], a = data[i4 + 3];
|
||||
const masked = mask && mask[idx];
|
||||
const isEligible = !masked && a >= tThresh2 && (state.paintWhitePixels || !Utils.isWhitePixel(r, g, b));
|
||||
const isEligible = !masked && (state.paintTransparentPixels || a >= tThresh2) && (state.paintWhitePixels || !Utils.isWhitePixel(r, g, b));
|
||||
eligible[idx] = isEligible ? 1 : 0;
|
||||
work[idx * 3] = r;
|
||||
work[idx * 3 + 1] = g;
|
||||
@@ -4829,7 +4879,7 @@ function applyTheme() {
|
||||
for (let i = 0; i < data.length; i += 4) {
|
||||
const r = data[i], g = data[i + 1], b = data[i + 2], a = data[i + 3];
|
||||
const masked = mask && mask[(i>>2)];
|
||||
const isTransparent = a < tThresh2 || masked;
|
||||
const isTransparent = (!state.paintTransparentPixels && a < tThresh2) || masked;
|
||||
const isWhiteAndSkipped = !state.paintWhitePixels && Utils.isWhitePixel(r, g, b);
|
||||
if (isTransparent || isWhiteAndSkipped) {
|
||||
data[i + 3] = 0; // overlay transparency
|
||||
@@ -4963,7 +5013,7 @@ function applyTheme() {
|
||||
|
||||
let totalValidPixels = 0;
|
||||
for (let i = 0; i < pixels.length; i += 4) {
|
||||
const isTransparent = pixels[i + 3] < (state.customTransparencyThreshold || CONFIG.TRANSPARENCY_THRESHOLD);
|
||||
const isTransparent = !state.paintTransparentPixels && pixels[i + 3] < (state.customTransparencyThreshold || CONFIG.TRANSPARENCY_THRESHOLD);
|
||||
const isWhiteAndSkipped = !state.paintWhitePixels && Utils.isWhitePixel(pixels[i], pixels[i + 1], pixels[i + 2]);
|
||||
if (!isTransparent && !isWhiteAndSkipped) {
|
||||
totalValidPixels++;
|
||||
@@ -5208,7 +5258,7 @@ function applyTheme() {
|
||||
const isEligibleAt = (x, y) => {
|
||||
const idx = (y * width + x) * 4;
|
||||
const r = pixels[idx], g = pixels[idx + 1], b = pixels[idx + 2], a = pixels[idx + 3];
|
||||
if (a < tThresh2) return false;
|
||||
if (!state.paintTransparentPixels && a < tThresh2) return false;
|
||||
if (!state.paintWhitePixels && Utils.isWhitePixel(r, g, b)) return false;
|
||||
return true;
|
||||
};
|
||||
@@ -5256,8 +5306,8 @@ function applyTheme() {
|
||||
const alpha = pixels[idx + 3]
|
||||
|
||||
const tThresh2 = state.customTransparencyThreshold || CONFIG.TRANSPARENCY_THRESHOLD;
|
||||
if (alpha < tThresh2 || (!state.paintWhitePixels && Utils.isWhitePixel(r, g, b))) {
|
||||
if (alpha < tThresh2) {
|
||||
if ((!state.paintTransparentPixels && alpha < tThresh2) || (!state.paintWhitePixels && Utils.isWhitePixel(r, g, b))) {
|
||||
if (!state.paintTransparentPixels && alpha < tThresh2) {
|
||||
skippedPixels.transparent++;
|
||||
} else {
|
||||
skippedPixels.white++;
|
||||
@@ -5654,6 +5704,7 @@ function applyTheme() {
|
||||
customTransparencyThreshold: state.customTransparencyThreshold,
|
||||
customWhiteThreshold: state.customWhiteThreshold,
|
||||
paintWhitePixels: state.paintWhitePixels,
|
||||
paintTransparentPixels: state.paintTransparentPixels,
|
||||
resizeSettings: state.resizeSettings,
|
||||
originalImage: state.originalImage,
|
||||
// Save ignore mask (as base64) with its dimensions
|
||||
@@ -5699,6 +5750,7 @@ function applyTheme() {
|
||||
state.customTransparencyThreshold = settings.customTransparencyThreshold ?? CONFIG.TRANSPARENCY_THRESHOLD;
|
||||
state.customWhiteThreshold = settings.customWhiteThreshold ?? CONFIG.WHITE_THRESHOLD;
|
||||
state.paintWhitePixels = settings.paintWhitePixels ?? true;
|
||||
state.paintTransparentPixels = settings.paintTransparentPixels ?? false;
|
||||
state.resizeSettings = settings.resizeSettings ?? null;
|
||||
state.originalImage = settings.originalImage ?? null;
|
||||
// Notifications
|
||||
|
||||
@@ -1117,6 +1117,10 @@
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.wplace-icon-paint {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
/* Section wrapper styling */
|
||||
.wplace-settings-section-wrapper {
|
||||
padding: 18px;
|
||||
@@ -1814,6 +1818,7 @@
|
||||
.wplace-icon-bell { font-size: 16px; }
|
||||
.wplace-icon-palette { font-size: 16px; }
|
||||
.wplace-icon-globe { font-size: 16px; }
|
||||
.wplace-icon-paint { font-size: 16px; }
|
||||
.wplace-icon-eye { font-size: 16px; }
|
||||
|
||||
/* Overlay Settings Controls */
|
||||
|
||||
+4
-1
@@ -136,5 +136,8 @@
|
||||
"expandMode": "Expand Mode",
|
||||
"minimize": "Minimize",
|
||||
"restore": "Restore",
|
||||
"hideStats": "Hide Stats"
|
||||
"hideStats": "Hide Stats",
|
||||
"paintOptions": "Paint Options",
|
||||
"paintWhitePixels": "Paint White Pixels",
|
||||
"paintTransparentPixels": "Paint Transparent Pixels"
|
||||
}
|
||||
+4
-1
@@ -137,5 +137,8 @@
|
||||
"expandMode": "Mode Étendu",
|
||||
"minimize": "Réduire",
|
||||
"restore": "Restaurer",
|
||||
"hideStats": "Masquer les Stats"
|
||||
"hideStats": "Masquer les Stats",
|
||||
"paintOptions": "Options de peinture",
|
||||
"paintWhitePixels": "Peindre les pixels blancs",
|
||||
"paintTransparentPixels": "Peindre les pixels transparents"
|
||||
}
|
||||
+4
-1
@@ -137,5 +137,8 @@
|
||||
"expandMode": "Mode Perluas",
|
||||
"minimize": "Minimalkan",
|
||||
"restore": "Pulihkan",
|
||||
"hideStats": "Sembunyikan Statistik"
|
||||
"hideStats": "Sembunyikan Statistik",
|
||||
"paintOptions": "Opsi Pewarnaan",
|
||||
"paintWhitePixels": "Warnai piksel putih",
|
||||
"paintTransparentPixels": "Warnai piksel transparan"
|
||||
}
|
||||
+4
-1
@@ -137,5 +137,8 @@
|
||||
"expandMode": "展開モード",
|
||||
"minimize": "最小化",
|
||||
"restore": "復元",
|
||||
"hideStats": "統計を非表示"
|
||||
"hideStats": "統計を非表示",
|
||||
"paintOptions": "描画オプション",
|
||||
"paintWhitePixels": "白いピクセルを描画",
|
||||
"paintTransparentPixels": "透明ピクセルを描画"
|
||||
}
|
||||
+4
-1
@@ -137,5 +137,8 @@
|
||||
"expandMode": "확장 모드",
|
||||
"minimize": "최소화",
|
||||
"restore": "복원",
|
||||
"hideStats": "통계 숨김"
|
||||
"hideStats": "통계 숨김",
|
||||
"paintOptions": "페인트 옵션",
|
||||
"paintWhitePixels": "흰색 픽셀 칠하기",
|
||||
"paintTransparentPixels": "투명 픽셀 칠하기"
|
||||
}
|
||||
+4
-1
@@ -136,5 +136,8 @@
|
||||
"expandMode": "Modo Expandir",
|
||||
"minimize": "Minimizar",
|
||||
"restore": "Restaurar",
|
||||
"hideStats": "Ocultar Estatísticas"
|
||||
"hideStats": "Ocultar Estatísticas",
|
||||
"paintOptions": "Opções de pintura",
|
||||
"paintWhitePixels": "Pintar pixels brancos",
|
||||
"paintTransparentPixels": "Pintar pixels transparentes"
|
||||
}
|
||||
+4
-1
@@ -136,5 +136,8 @@
|
||||
"expandMode": "Режим расширения",
|
||||
"minimize": "Свернуть",
|
||||
"restore": "Восстановить",
|
||||
"hideStats": "Скрыть статистику"
|
||||
"hideStats": "Скрыть статистику",
|
||||
"paintOptions": "Параметры рисования",
|
||||
"paintWhitePixels": "Рисовать белые пиксели",
|
||||
"paintTransparentPixels": "Рисовать прозрачные пиксели"
|
||||
}
|
||||
+4
-1
@@ -137,5 +137,8 @@
|
||||
"expandMode": "Genişletme Modu",
|
||||
"minimize": "Küçült",
|
||||
"restore": "Geri Yükle",
|
||||
"hideStats": "İstatistikleri Gizle"
|
||||
"hideStats": "İstatistikleri Gizle",
|
||||
"paintOptions": "Boya Seçenekleri",
|
||||
"paintWhitePixels": "Beyaz pikselleri boya",
|
||||
"paintTransparentPixels": "Şeffaf pikselleri boya"
|
||||
}
|
||||
+4
-1
@@ -137,5 +137,8 @@
|
||||
"expandMode": "Режим розширення",
|
||||
"minimize": "Мінімізувати",
|
||||
"restore": "Відновити",
|
||||
"hideStats": "Приховати статистику"
|
||||
"hideStats": "Приховати статистику",
|
||||
"paintOptions": "Параметри малювання",
|
||||
"paintWhitePixels": "Малювати білі пікселі",
|
||||
"paintTransparentPixels": "Малювати прозорі пікселі"
|
||||
}
|
||||
+4
-1
@@ -137,5 +137,8 @@
|
||||
"expandMode": "Chế độ mở rộng",
|
||||
"minimize": "Thu nhỏ",
|
||||
"restore": "Khôi phục",
|
||||
"hideStats": "Ẩn thống kê"
|
||||
"hideStats": "Ẩn thống kê",
|
||||
"paintOptions": "Tùy chọn vẽ",
|
||||
"paintWhitePixels": "Vẽ điểm ảnh trắng",
|
||||
"paintTransparentPixels": "Vẽ điểm ảnh trong suốt"
|
||||
}
|
||||
+4
-1
@@ -137,5 +137,8 @@
|
||||
"expandMode": "展开模式",
|
||||
"minimize": "最小化",
|
||||
"restore": "恢复",
|
||||
"hideStats": "隐藏统计"
|
||||
"hideStats": "隐藏统计",
|
||||
"paintOptions": "绘图选项",
|
||||
"paintWhitePixels": "绘制白色像素",
|
||||
"paintTransparentPixels": "绘制透明像素"
|
||||
}
|
||||
+4
-1
@@ -137,5 +137,8 @@
|
||||
"expandMode": "展開模式",
|
||||
"minimize": "最小化",
|
||||
"restore": "恢復",
|
||||
"hideStats": "隱藏統計"
|
||||
"hideStats": "隱藏統計",
|
||||
"paintOptions": "繪圖選項",
|
||||
"paintWhitePixels": "繪製白色像素",
|
||||
"paintTransparentPixels": "繪製透明像素"
|
||||
}
|
||||
@@ -425,6 +425,7 @@
|
||||
.wplace-theme--classic-light .wplace-icon-bell { color: #ffc107; }
|
||||
.wplace-theme--classic-light .wplace-icon-palette { color: #f093fb; }
|
||||
.wplace-theme--classic-light .wplace-icon-globe { color: #ffeaa7; }
|
||||
.wplace-theme--classic-light .wplace-icon-paint { color: #4facfe; }
|
||||
.wplace-theme--classic-light .wplace-icon-eye { color: #6f42c1; }
|
||||
|
||||
/* Clean light theme animations */
|
||||
|
||||
+9
-4
@@ -480,13 +480,18 @@
|
||||
}
|
||||
|
||||
:root .wplace-icon-globe,
|
||||
.wplace-theme--classic .wplace-icon-globe {
|
||||
color: #ffeaa7;
|
||||
.wplace-theme--classic .wplace-icon-globe {
|
||||
color: #ffeaa7;
|
||||
}
|
||||
|
||||
:root .wplace-icon-paint,
|
||||
.wplace-theme--classic .wplace-icon-paint {
|
||||
color: #4facfe;
|
||||
}
|
||||
|
||||
:root .wplace-icon-eye,
|
||||
.wplace-theme--classic .wplace-icon-eye {
|
||||
color: var(--wplace-highlight);
|
||||
.wplace-theme--classic .wplace-icon-eye {
|
||||
color: var(--wplace-highlight);
|
||||
}
|
||||
|
||||
/* Form controls and sliders for classic theme */
|
||||
|
||||
Reference in new issue
Block a user