Skip to content

Commit

Permalink
refactored bandage rendering code
Browse files Browse the repository at this point in the history
  • Loading branch information
Andcool-Systems committed Jan 1, 2025
1 parent 55a9629 commit 645a0a2
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 132 deletions.
7 changes: 4 additions & 3 deletions src/app/modules/utils/apiManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import axios, { AxiosResponse, Method } from "axios";
import { Query } from "../components/Header";
import { SettingsResponse } from "@/app/me/settings/page";
import { SearchResponse } from "../components/NickSearch";
import { SkinResponse } from "@/app/workshop/[id]/bandage_engine";

type RequestProps = {
url: string,
Expand Down Expand Up @@ -235,11 +236,11 @@ class ApiManager {
}

/* Get Minecraft skin */
static async getSkin(nickname: string): Promise<AxiosResponse> {
static async getSkin(nickname: string): Promise<SkinResponse> {
return (await this.doRequestSimple({
url: `/minecraft/skin/${nickname}?cape=true`,
url: `/minecraft/skin/${nickname}`,
method: 'GET'
}));
})).data;
}

/* Get sessions */
Expand Down
125 changes: 46 additions & 79 deletions src/app/workshop/[id]/bandage_engine.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import asyncImage, { base64Encode } from '@/app/modules/utils/asyncImage';
import ApiManager from '@/app/modules/utils/apiManager';

interface SkinResponse {
export interface SkinResponse {
data: {
skin: {
data: string,
Expand Down Expand Up @@ -32,7 +32,6 @@ interface Settings {
class Client {
skin: string = "";
cape: string = "";
listeners: { [key: string]: Function } = {};
original_canvas: HTMLCanvasElement = null;

pepe_canvas: HTMLCanvasElement = null;
Expand All @@ -52,14 +51,18 @@ class Client {
colorable: boolean = false;
split_types: boolean = false;

onRendered: ({ skin, cape, slim }: { skin: string, cape: string, slim: boolean }) => void = undefined;
onInit: () => void = undefined;

private main_bandage: HTMLCanvasElement = null;

loadBase() {
asyncImage('/static/workshop_base.png').then(skin => {
const context = this.original_canvas.getContext("2d");
context?.drawImage(skin, 0, 0);
this.triggerEvent("init");
});
asyncImage('/static/workshop_base.png')
.then(skin => {
const context = this.original_canvas.getContext("2d");
context!.drawImage(skin, 0, 0);
!!this.onInit && this.onInit();
});
}

constructor() {
Expand All @@ -72,79 +75,45 @@ class Client {
color_picker?.addEventListener("input", () => this.rerender());
}

addEventListener(property: string, func: Function) {
this.listeners[property] = func;
}

removeEventListener(property: string) {
delete this.listeners[property];
}

async loadSkin(nickname: string): Promise<void> {
if (!nickname) return;

const response = await ApiManager.getSkin(nickname);

const data = response.data as SkinResponse;
const data = await ApiManager.getSkin(nickname);
this.slim = data.data.skin.slim;

this.addEventListener("onload", () => {

this.setOriginalCanvas(b64Prefix + data.data.skin.data, () => {
this.skin = b64Prefix + data.data.skin;
this.cape = b64Prefix + data.data.cape;

this.rerender();
this.removeEventListener("onload");
});

this.setOriginalCanvas(b64Prefix + data.data.skin.data);
}

loadSkinUrl(url: string) {
asyncImage(url)
.then(img => {
const base64 = base64Encode(img);
this.addEventListener("onload", () => {
this.setOriginalCanvas(base64, () => {
this.skin = base64;
this.rerender();
this.removeEventListener("onload");
});

this.setOriginalCanvas(base64);
})
.catch(console.error);
}

triggerEvent(property: string) {
if (property === 'rerender' || this.listeners[property]) {
switch (property) {
case "skin_changed":
this.listeners[property]({ skin: this.skin, cape: this.cape });
break;
case "rerender":
this.rerender();
break;
default:
this.listeners[property]();
break;
}
}
}

private setOriginalCanvas(b64: string) {
private setOriginalCanvas(b64: string, callback: () => void) {
const context = this.original_canvas.getContext('2d');
if (!context) {
return;
}

asyncImage(b64).then((img) => {
if (img.width != 64 || img.height != 64) {
return;
}
context.clearRect(0, 0, 64, 64);
context.drawImage(img, 0, 0, img.width, img.height);
this.triggerEvent("onload");
});
asyncImage(b64)
.then(img => {
if (img.width != 64 || img.height != 64) return;
context.clearRect(0, 0, 64, 64);
context.drawImage(img, 0, 0, img.width, img.height);
callback();
});
}

//---------------------bandage_manager-------------------
Expand All @@ -163,8 +132,14 @@ class Client {

context_pepe.drawImage(img, 0, 0, 16, height, 0, 0, 16, height);
context_lining.drawImage(img, 0, height, 16, height, 0, 0, 16, height);
!slim ? this.pepe_canvas = pepe_canvas : this.pepe_canvas_slim = pepe_canvas;
!slim ? this.lining_canvas = lining_canvas : this.lining_canvas_slim = lining_canvas;

if (slim) {
this.pepe_canvas_slim = pepe_canvas;
this.lining_canvas_slim = lining_canvas;
} else {
this.pepe_canvas = pepe_canvas;
this.lining_canvas = lining_canvas;
}
this.position = 6 - Math.floor(height / 2);

this.rerender();
Expand All @@ -176,37 +151,25 @@ class Client {
}

changeSkin(skin: string, slim?: boolean, cape?: string) {
if (slim != undefined) this.slim = slim;
this.addEventListener("onload", () => {
if (slim !== undefined) this.slim = slim;
this.setOriginalCanvas(skin, () => {
this.skin = skin;
this.cape = cape;

this.rerender();
this.removeEventListener("onload");
});
this.setOriginalCanvas(skin);
}

setParams({
body_part,
position,
clear_pix,
first_layer,
second_layer,
layers,
color,
colorable,
split_types
}: Settings) {
if (body_part != undefined) this.body_part = body_part;
if (position != undefined) this.position = position;
if (clear_pix != undefined) this.clear_pix = clear_pix;
if (first_layer != undefined) this.first_layer = first_layer;
if (second_layer != undefined) this.second_layer = second_layer;
if (layers != undefined) this.layers = layers;
if (color != undefined) this.color = color;
if (colorable != undefined) this.colorable = colorable;
if (split_types != undefined) this.split_types = split_types;
setParams(props: Settings) {
if (props.body_part != undefined) this.body_part = props.body_part;
if (props.position != undefined) this.position = props.position;
if (props.clear_pix != undefined) this.clear_pix = props.clear_pix;
if (props.first_layer != undefined) this.first_layer = props.first_layer;
if (props.second_layer != undefined) this.second_layer = props.second_layer;
if (props.layers != undefined) this.layers = props.layers;
if (props.color != undefined) this.color = props.color;
if (props.colorable != undefined) this.colorable = props.colorable;
if (props.split_types != undefined) this.split_types = props.split_types;

this.rerender();
}
Expand Down Expand Up @@ -282,7 +245,11 @@ class Client {

if (!download) {
this.skin = canvas.toDataURL();
this.triggerEvent("skin_changed");
!!this.onRendered && this.onRendered({
skin: this.skin,
cape: this.cape,
slim: this.slim
});
} else {
this.download(canvas.toDataURL());
}
Expand Down
57 changes: 23 additions & 34 deletions src/app/workshop/[id]/client.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,6 @@ export default function Home({ data, referrer }: { data: Interfaces.Bandage, ref

selector.value = rgbToHex(~~color.r, ~~color.g, ~~color.b);
client.current.setParams({ color: selector.value });
client.current.rerender();
}

useEffect(() => {
Expand All @@ -138,48 +137,38 @@ export default function Home({ data, referrer }: { data: Interfaces.Bandage, ref
}

client.current = new Client();
client.current.addEventListener('skin_changed', (event: { skin: string, cape: string }) => {
client.current.onRendered = (event) => {
setSkin(event.skin);
setCape(event.cape);
setSlim(client.current.slim);
});
setSlim(event.slim);
};

client.current.addEventListener('init', () => {
client.current.onInit = () => {
if (data.me_profile) client.current.loadSkin(data.me_profile.uuid);

asyncImage(b64Prefix + data.base64).then(bandage => {
const height = bandage.height / 2;
const pepe_canvas = document.createElement('canvas') as HTMLCanvasElement;
const context_pepe = pepe_canvas.getContext('2d');
pepe_canvas.width = 16;
pepe_canvas.height = height;

const lining_canvas = document.createElement('canvas') as HTMLCanvasElement;
const context_lining = lining_canvas.getContext('2d');
lining_canvas.width = 16;
lining_canvas.height = height;

context_pepe.drawImage(bandage, 0, 0, 16, height, 0, 0, 16, height);
context_lining.drawImage(bandage, 0, height, 16, height, 0, 0, 16, height);
client.current.pepe_canvas = pepe_canvas;
client.current.lining_canvas = lining_canvas;
client.current.position = 6 - Math.floor(height / 2);
setRangeProps({ value: client.current.position, max: (12 - client.current.pepe_canvas.height) });
client.current.colorable = data.categories.some(val => val.colorable);
const randomColor = getRandomColor();
setRandomColor(randomColor);
client.current.setParams({ color: randomColor });
client.current.rerender();
setLoaded(true);
});
asyncImage(b64Prefix + data.base64)
.then(bandage => {
client.current.loadFromImage(bandage);

setRangeProps({
value: client.current.position,
max: (12 - client.current.pepe_canvas.height)
});

client.current.colorable = data.categories.some(val => val.colorable);
if (client.current.colorable) {
const randomColor = getRandomColor();
setRandomColor(randomColor);
client.current.setParams({ color: randomColor });
}
setLoaded(true);
});

if (data.split_type) {
client.current.setParams({ split_types: true });
asyncImage(b64Prefix + data.base64_slim).then(img => {
client.current.loadFromImage(img, true)
});
asyncImage(b64Prefix + data.base64_slim).then(img => client.current.loadFromImage(img, true));
}
});
};
scrollTo(0, 0);
}, []);

Expand Down
14 changes: 2 additions & 12 deletions src/app/workshop/[id]/components/skinLoad.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import Searcher from "@/app/modules/components/NickSearch";
import ApiManager from "@/app/modules/utils/apiManager";
import { CSSTransition } from "react-transition-group";
import axios, { AxiosError } from "axios";
import { SkinResponse } from "../bandage_engine";

const b64Prefix = "data:image/png;base64,";

Expand All @@ -16,16 +17,6 @@ interface SkinLoadProps {
expanded: boolean
}

interface SkinResponse {
data: {
skin: {
data: string,
slim: boolean
},
cape: string
}
}

const SkinLoad = ({ expanded, onChange }: SkinLoadProps) => {
const [data, setData] = useState<{ data: string; slim: boolean; cape?: string }>(null);
const [loaded, setLoaded] = useState<boolean>(false);
Expand All @@ -48,8 +39,7 @@ const SkinLoad = ({ expanded, onChange }: SkinLoadProps) => {
if (!nickname) return;

ApiManager.getSkin(nickname)
.then(response => {
const data = response.data as SkinResponse;
.then(data => {
setData({
data: b64Prefix + data.data.skin.data,
slim: data.data.skin.slim,
Expand Down
9 changes: 5 additions & 4 deletions src/app/workshop/create/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,10 @@ export default function Home() {

useEffect(() => {
client.current = new Client();
client.current.addEventListener('skin_changed', (event: { skin: string, cape: string }) => {
client.current.onRendered = (event) => {
setSKIN(event.skin);
setSlim(client.current.slim);
});
setSlim(event.slim);
};

client.current.loadSkinUrl("/static/workshop_base.png");
window.addEventListener('beforeunload', beforeUnload);
Expand All @@ -70,7 +70,8 @@ export default function Home() {
<main className={style.main}>
<div className={style.central_panel}>
<aside className={style.skin_parent}>
<SkinView3D SKIN={SKIN}
<SkinView3D
SKIN={SKIN}
CAPE={null}
slim={slim}
className={style.skinview}
Expand Down

0 comments on commit 645a0a2

Please sign in to comment.