// ==UserScript==
// @name SketchfabTextureDump_V3
// @namespace Violentmonkey Scripts
// @match *://*.[Link]/3d-models/**
// @match *://*.[Link]/models/**
// @grant none
// @version 0.0.3
// @author krapnik
// @create-time 2023/7/31 [Link]
// @license MIT
// @run-at document-start
// ==/UserScript==
(function () {
const MIN_TEXTURE_WIDTH = 256,
MIN_TEXTURE_HEIGHT = 256;
let _log = [Link];
let _warn = [Link];
let model_name = [Link]("/")[2];
let model_name_arr = model_name.split("-");
let model_id = model_name_arr[model_name_arr.length - 1];
let downloadCnt = 0;
let originTextureArr = [];
if ([Link]('[Link]/3d-models/') > -1) {
return;
}
if ([Link] !== [Link]) {
setTimeout(() => {
addViewBtn();
}, 3000)
return;
}
_log("=======SketchfabTextureDump=======");
if (!model_id) {
_warn("can't find model_id!");
return;
} else {
_log("model_id:", model_id);
}
[Link] = () => {
try {
let results = [Link][`/i/models/${model_id}/textures?
optimized=1`].results;
coverTexture(results); // quality high
[Link]([Link][`/i/models/${model_id}/textures?
optimized=1`], "results", {
get: () => {
return results;
}
})
originTextureArr = [Link][`/i/models/${model_id}/textures?
optimized=1`].results || [];
} catch (e) {
_warn('oops~something went wrong,u can refresh the page & try again');
}
}
function coverTexture(results) {
[Link]((texture) => {
let images = [Link];
let img = images[[Link] - 2];
[Link] = [Link];
[Link]((item, idx) => {
images[idx] = img;
})
})
}
function addDownloadBtn() {
let btn = [Link]("button");
[Link] = "download";
[Link] = "absolute"
[Link] = "0"
[Link] = "0"
[Link](btn);
[Link] = dumpWebGLTextureData;
}
function addViewBtn() {
let btn = [Link]("button");
[Link] = "goto download";
[Link] = "absolute"
[Link] = "0"
[Link] = "0"
[Link](btn);
[Link] = () => {
let link = [Link]("a");
[Link]("href", `[Link]
autostart=1&internal=1&tracking=0&ui_ar=0&ui_infos=0&ui_snapshots=1&ui_stop=0&ui_th
eatre=1&ui_watermark=0`);
[Link]("target", "_blank");
[Link](link);
[Link]();
[Link](link);
};
}
let webGLTextureIdx = 0;
let webGLTextureMap = {};
[Link]("DOMContentLoaded", function () {
var str = [Link]("#js-dom-data-prefetched-
data").[Link]("\x3C!--", "").replace("-->", "").replaceAll(""",
"\"");
var prefetchedData = [Link](str);
let context = [Link].webgl2 ? WebGL2RenderingContext :
WebGLRenderingContext;
hookWebGLRenderingContext(context);
}, false);
function hookWebGLRenderingContext(context) {
//createTexture
let glCreateTexture = [Link];
[Link] = function (...args) {
let texture = [Link](this, args);
[Link] = webGLTextureIdx;
[Link] = this;
webGLTextureMap[`${webGLTextureIdx}`] = texture;
webGLTextureIdx++;
return texture;
};
//bindTexture
let glBindTexture = [Link];
[Link] = function (...args) {
let target = args[0], texture = args[1];
if (texture) {
[Link] = target;
}
[Link](this, args);
};
let glDeleteTexture = [Link];
[Link] = function (...args) {
// do notthing
};
//texImage
let lstTexture;
let glTexImage2D = [Link].texImage2D;
let hasCoverTex = 0;
let isAllTextureCover = false;
[Link].texImage2D = function (...args) {
let texture = [Link](this.TEXTURE_BINDING_2D) ||
[Link](this.TEXTURE_BINDING_CUBE_MAP);
let argments = parseTexImage2dArgs(args);
if ([Link] == [Link]) {
[Link] = argments;
let { width, height, src } = argments;
if (
width > MIN_TEXTURE_WIDTH &&
height > MIN_TEXTURE_HEIGHT &&
(width & width - 1) === 0 &&
(height & height - 1) === 0 &&
[Link] === this.TEXTURE_2D
) {
if (src) {
// let textureName = getFileNameByLink(src);
[Link] = [Link];
[Link] = [Link];
hasCoverTex++;
_log(`【origin texture cover】 total:${[Link]} count:$
{hasCoverTex}`);
if ([Link] == hasCoverTex) {
isAllTextureCover = true;
_log('all files are ready! click the 【download】 button');
addDownloadBtn();
}
}
lstTexture = texture;
}
}
[Link](this, args);
};
}
function parseTexImage2dArgs(args) {
let argments = {};
if ([Link] == 6) {
let [target, level, internalformat, format, type, source] = args;
let { width, height, src } = source;
argments = { target, level, width, height, internalformat, format, type,
src };
} else if ([Link] == 9) {
let [
target,
level,
internalformat,
width,
height,
border,
format,
type,
pixels,
] = args;
argments = { target, level, width, height, format, internalformat, type };
} else {
let [target] = args;
argments = { target };
}
return argments;
}
function readWebTextureData(texture) {
let { target, gl, args, src, lst } = texture;
if (!args) { // todo maybe other func bind
return
}
let { level, width, height, format, internalformat, type } = args;
if (
width > MIN_TEXTURE_WIDTH &&
height > MIN_TEXTURE_HEIGHT &&
(width & width - 1) === 0 &&
(height & height - 1) === 0 &&
target === gl.TEXTURE_2D &&
!src
) {
let fb = [Link]();
[Link]([Link], fb);
gl.framebufferTexture2D(
[Link],
gl.COLOR_ATTACHMENT0,
gl.TEXTURE_2D,
texture,
level
);
let framebufferStatus = [Link]([Link]);
if (
framebufferStatus == gl.FRAMEBUFFER_COMPLETE
) {
let fileName = `${[Link]()}.png`;
let originName = fileName;
let originTex = webGLTextureMap[lst];
if (originTex) {
if (originTex && [Link]) {
let path = [Link]("/");
let uid = path[[Link] - 2];
originName = getNameById(uid);
}
if (fileName == originName || !originName) { return }
let pixels = new Uint8Array(width * height * 4);
[Link](0, 0, width, height, format, type, pixels);
let canvas = [Link]("canvas");
[Link] = width;
[Link] = height;
let context = [Link]("2d");
let imageData = [Link](width, height);
[Link](pixels);
[Link](imageData, 0, 0);
downloadCnt++;
downLoadByLink([Link](), originName); // todo format
}
}
}
}
function dumpWebGLTextureData() {
downloadCnt = 0;
for (let key in webGLTextureMap) {
readWebTextureData(webGLTextureMap[key]);
}
if (downloadCnt == [Link]) {
_log(`【dump texture:${downloadCnt}/${[Link]}】 success!`);
} else {
_log(`【dump texture:${downloadCnt}/${[Link]}】oops~something
went wrong,u can refresh the page & try again`);
}
}
function getNameById(uid) {
let name;
let texture = [Link]((t) => {
return [Link] == uid;
});
if (texture) {
name = [Link];
}
return name;
}
function downLoadByLink(url, filename) {
let link, evt;
link = [Link]('a');
[Link] = url;
filename && [Link]('download', filename);
if ([Link]) {
[Link]([Link]);
} else {
evt = [Link]('MouseEvents');
[Link]('click', true, true);
[Link](evt);
}
};
[Link] = dumpWebGLTextureData;
})();