DNA
DNA15mo ago

deno_tui Label-class

Hello. I just started testing around with deno_tui and found the DrawObject-Class. How do i actually use this class? Afaik there is no proper documentation to deno_tui at all and especially not for this class specifically.
72 Replies
Beast
Beast15mo ago
DrawObject doesn't do that much by itself, it's used to create TextDrawObject and BoxDrawObject which then are used in components to render on the canvas. To build Tui you probably want to use components instead, if you want to create your own components and use them you can take a look at any of the components in src/components, keep in mind that I'm planning on replacing DrawObjects in the future, I have PR open to do it, will try to finish it as soon as I will have some spare time.
DNA
DNAOP15mo ago
My problem is just, that i dont know, what i need to use for achieving my goal. Basically, i want to have blocks which consist of 16x16 pixel (16 rows, 32 columns) to display textures. The texture of each "block" has to be adjustable. Is there a component that does this?
Beast
Beast15mo ago
there's a way to workaround this using styles, but that's not good DX at all, it seems like your usecase is actually in need of custom DrawObject I was planning on implementing ShapePainter in my PR which is essentially what you need, but I didn't even start working on it :/ @realdna it totally escaped my head 🤦‍♂️ you could just use Label component for that
Beast
Beast15mo ago
No description
Beast
Beast15mo ago
essentially you could just convert the texture into a string and pass it to the label my brain isn't braining
DNA
DNAOP15mo ago
I tried that but with a textbox and it didnt work And i gave up I think the label is gonna work Let me try in a few minutes
Beast
Beast15mo ago
https://deno.land/x/tui@2.1.1/src/components/mod.ts you should check that for simple component descriptions textbox is a multiline text input :p
DNA
DNAOP15mo ago
Lmao Me being braindead Sorry I didnt want to waste your time
Beast
Beast15mo ago
you didn't tui definitely needs better docs
DNA
DNAOP15mo ago
I just tried that method, but it doesnt seem to work properly for me This is my code:
new Label({
parent: tui,
rectangle: {
column: 0,
row: 0
},
text: textures.stone,
theme: {
base(text) {
return text;
},
},
zIndex: 1,
});
new Label({
parent: tui,
rectangle: {
column: 0,
row: 0
},
text: textures.stone,
theme: {
base(text) {
return text;
},
},
zIndex: 1,
});
DNA
DNAOP15mo ago
The outcome in terminal:
No description
DNA
DNAOP15mo ago
When i manually print the text (textures.stone) reading it from the file:
No description
DNA
DNAOP15mo ago
Beast
Beast15mo ago
Okay, I think I know what's going wrong here, could you file an issue about it please?
DNA
DNAOP15mo ago
Beast
Beast15mo ago
thanks, I'll look at it ASAP im in bed rn so I will probably take a look at it tommorow/after tommorow
DNA
DNAOP15mo ago
Np np Thank you so much for even creating such an impressive tool in the first place
Beast
Beast15mo ago
@realdna Feel free to update to 2.1.2 it should work just fine now, simply set multiCodePointSupport to true in LabelOptions
DNA
DNAOP15mo ago
I just updated 2.1.2 and i think you might have broken a few things Code:
import {crayon} from "https://deno.land/x/crayon@3.3.3/mod.ts";
import {Canvas, Computed, Signal, Tui, handleInput, handleKeyboardControls, handleMouseControls} from "https://deno.land/x/tui@2.1.1/mod.ts";
import {Button, Text, Label} from "https://deno.land/x/tui@2.1.1/src/components/mod.ts";
import {createCanvas, loadImage} from "https://deno.land/x/canvas@v1.4.1/mod.ts";

const canvas = new Canvas({size: {rows: 128, columns: 512}, stdout: Deno.stdout});
const debug = new Signal("Nothing to see here!");
let output = "";

const textures: Record<string, string> = {
stone: "",
wood: "",
grass: "",
iron_ore: "",
iron_ingot: "",
};

for (const textureName in textures) {
const textureImage = await loadImage(`assets/${textureName}.png`);

const textureCanvas = createCanvas(16, 16);
const textureContext = textureCanvas.getContext("2d");
textureContext.drawImage(textureImage, 0, 0);

for (let row = 0; row < textureImage.height(); row++) {
for (let column = 0; column < textureImage.width(); column++) {
const imageData = textureContext.getImageData(column, row, 1, 1);
const pixel = imageData.data;
textures[textureName] += `\x1b[48;2;${pixel[0]};${pixel[1]};${pixel[2]}m \x1b[0m`;
}
textures[textureName] += "\n";
}

Deno.writeTextFileSync(`temp\\${textureName}`, textures[textureName]);
}

const blocks = [
{
id: "stone",
position: {
x: 2,
y: 0,
},
},
{
id: "stone",
position: {
x: 2,
y: 1,
},
},
{
id: "stone",
position: {
x: 1,
y: 2,
},
},
{
id: "stone",
position: {
x: 2,
y: 2,
},
},
{
id: "stone",
position: {
x: 3,
y: 2,
},
},
];

output = "";

for (const block of blocks) {
output += `[${block.position.y * 16}d[${block.position.x * 16}G${textures.stone}`;
}

const tui = new Tui({
canvas: canvas,
refreshRate: 1000 / 60,
style: crayon.bgRgb(0, 127, 127),
});

tui.dispatch();

handleInput(tui);
handleMouseControls(tui);
handleKeyboardControls(tui);

new Text({
parent: tui,
text: new Computed(() => {
return debug.value;
}),
rectangle: {column: 40, row: 1, width: 50},
theme: {active: crayon.bgRgb(0, 127, 127), base: crayon.bgRgb(0, 127, 127)},
zIndex: 128,
});

new Label({
parent: tui,
rectangle: {
column: 0,
row: 0,
},
text: textures.stone,
theme: {
base(text) {
return text;
},
},
zIndex: 1,
});

for (let row = 0; row < 8; row++)
for (let column = 0; column < 16; column++) {
const button = new Button({
parent: tui,
rectangle: {column: column * 32, row: row * 16, width: 32, height: 16},
theme: {active: crayon.bgRgb(0, 127, 127), base: crayon.bgRgb(0, 127, 255)},
zIndex: 0,
});

button.on("mousePress", (_event) => {
debug.value = `Mouse Press: r${row}c${column}`;
});
}

tui.run();
import {crayon} from "https://deno.land/x/crayon@3.3.3/mod.ts";
import {Canvas, Computed, Signal, Tui, handleInput, handleKeyboardControls, handleMouseControls} from "https://deno.land/x/tui@2.1.1/mod.ts";
import {Button, Text, Label} from "https://deno.land/x/tui@2.1.1/src/components/mod.ts";
import {createCanvas, loadImage} from "https://deno.land/x/canvas@v1.4.1/mod.ts";

const canvas = new Canvas({size: {rows: 128, columns: 512}, stdout: Deno.stdout});
const debug = new Signal("Nothing to see here!");
let output = "";

const textures: Record<string, string> = {
stone: "",
wood: "",
grass: "",
iron_ore: "",
iron_ingot: "",
};

for (const textureName in textures) {
const textureImage = await loadImage(`assets/${textureName}.png`);

const textureCanvas = createCanvas(16, 16);
const textureContext = textureCanvas.getContext("2d");
textureContext.drawImage(textureImage, 0, 0);

for (let row = 0; row < textureImage.height(); row++) {
for (let column = 0; column < textureImage.width(); column++) {
const imageData = textureContext.getImageData(column, row, 1, 1);
const pixel = imageData.data;
textures[textureName] += `\x1b[48;2;${pixel[0]};${pixel[1]};${pixel[2]}m \x1b[0m`;
}
textures[textureName] += "\n";
}

Deno.writeTextFileSync(`temp\\${textureName}`, textures[textureName]);
}

const blocks = [
{
id: "stone",
position: {
x: 2,
y: 0,
},
},
{
id: "stone",
position: {
x: 2,
y: 1,
},
},
{
id: "stone",
position: {
x: 1,
y: 2,
},
},
{
id: "stone",
position: {
x: 2,
y: 2,
},
},
{
id: "stone",
position: {
x: 3,
y: 2,
},
},
];

output = "";

for (const block of blocks) {
output += `[${block.position.y * 16}d[${block.position.x * 16}G${textures.stone}`;
}

const tui = new Tui({
canvas: canvas,
refreshRate: 1000 / 60,
style: crayon.bgRgb(0, 127, 127),
});

tui.dispatch();

handleInput(tui);
handleMouseControls(tui);
handleKeyboardControls(tui);

new Text({
parent: tui,
text: new Computed(() => {
return debug.value;
}),
rectangle: {column: 40, row: 1, width: 50},
theme: {active: crayon.bgRgb(0, 127, 127), base: crayon.bgRgb(0, 127, 127)},
zIndex: 128,
});

new Label({
parent: tui,
rectangle: {
column: 0,
row: 0,
},
text: textures.stone,
theme: {
base(text) {
return text;
},
},
zIndex: 1,
});

for (let row = 0; row < 8; row++)
for (let column = 0; column < 16; column++) {
const button = new Button({
parent: tui,
rectangle: {column: column * 32, row: row * 16, width: 32, height: 16},
theme: {active: crayon.bgRgb(0, 127, 127), base: crayon.bgRgb(0, 127, 255)},
zIndex: 0,
});

button.on("mousePress", (_event) => {
debug.value = `Mouse Press: r${row}c${column}`;
});
}

tui.run();
With 2.1.1 i have no errors at all
DNA
DNAOP15mo ago
After updating to 2.1.2:
No description
Beast
Beast15mo ago
the code you just posted has tui@2.1.1 and even then, it works fine for me (even after I updated it to 2.1.2)
DNA
DNAOP15mo ago
Oopsie I forgot to add the second code block Sorry The only thing i changed though was just the import version and this code block, where the only change is multiCodePointSupport is set true
new Label({
parent: tui,
rectangle: {
column: 0,
row: 0,
},
text: textures.stone,
theme: {
base(text) {
return text;
},
},
zIndex: 1,
multiCodePointSupport: true,
});
new Label({
parent: tui,
rectangle: {
column: 0,
row: 0,
},
text: textures.stone,
theme: {
base(text) {
return text;
},
},
zIndex: 1,
multiCodePointSupport: true,
});
Beast
Beast15mo ago
it still works fine in my case?
DNA
DNAOP15mo ago
No description
DNA
DNAOP15mo ago
I cant even compile a new version because the check fails
Beast
Beast15mo ago
what is your deno version?
DNA
DNAOP15mo ago
deno 1.36.4 (release, x86_64-pc-windows-msvc) v8 11.6.189.12 typescript 5.1.6
Beast
Beast15mo ago
wtf
DNA
DNAOP15mo ago
No description
Beast
Beast15mo ago
why does it work for me and not for you then?
DNA
DNAOP15mo ago
Idk tbh
Beast
Beast15mo ago
are you sure the only thing you changed is this? try running it with the -r flag, maybe your cache got fucked up
DNA
DNAOP15mo ago
Same issue with -r
Beast
Beast15mo ago
its definitely not deno_tui's issue I don't know...
DNA
DNAOP15mo ago
DNA
DNAOP15mo ago
Thats literally all i did
Beast
Beast15mo ago
No description
Beast
Beast15mo ago
you didn't update other imports...
DNA
DNAOP15mo ago
Imma kms Im done Naw cry now Im so sorry for wasting your time this bad
Beast
Beast15mo ago
thats fine :p
DNA
DNAOP15mo ago
It works now
No description
Beast
Beast15mo ago
great to see 😄
DNA
DNAOP15mo ago
If youre alreadyhere , is it possible to get the current fps? Like not what its supposed to be, but the actual current fps?
Beast
Beast15mo ago
after I'll rework DrawObject to TextPainter's I'll make sure that the styles will work fine even without multiCodePointSupport
DNA
DNAOP15mo ago
Nice
Beast
Beast15mo ago
to get the actual actual fps you'd need to use external program to see terminal's refreshrate to see how fast tui's drawing frames you can calculate that by using tui.canvas.on("render") you can go to https://deno.land/x/tui/examples/demo.ts to see how it can be done basically
const fps = new Signal(60);
let lastRender = 0;

const performanceStats = new Text({
parent: tui,
rectangle: { column: 0, row: 0 },
theme: ...,
text: new Computed(() => `FPS: ${fps.value.toFixed(2)`),
zIndex: 0,
});

tui.canvas.on("render", () => {
fps.value = 1000 / (performance.now() - lastRender);
});
const fps = new Signal(60);
let lastRender = 0;

const performanceStats = new Text({
parent: tui,
rectangle: { column: 0, row: 0 },
theme: ...,
text: new Computed(() => `FPS: ${fps.value.toFixed(2)`),
zIndex: 0,
});

tui.canvas.on("render", () => {
fps.value = 1000 / (performance.now() - lastRender);
});
DNA
DNAOP15mo ago
Oh ok Thank you
Beast
Beast15mo ago
np
DNA
DNAOP15mo ago
Hey New problem
DNA
DNAOP15mo ago
When changing the text via Signal/Computed afterwards, this is the outcome
No description
DNA
DNAOP15mo ago
The before texture and the newly set textures are both completely fine by themselves But when changing via signal, it doesnt work until the windows has been resized or something like that
const texture = new Signal(textures.stone);
setTimeout(() => texture.value = textures.wood, 1000)
const texture = new Signal(textures.stone);
setTimeout(() => texture.value = textures.wood, 1000)
Beast
Beast15mo ago
holy shit, that's a strange bug most likely I will take a swing at this in monday, I won't be home for a long time tommorow as a work around you could probably create multiple labels and toggle visible property on components
DNA
DNAOP15mo ago
Oh ok Have you already worked on this?
Beast
Beast15mo ago
oh, sorry I forgot yes I did, I actually fixed it but didn't push it yet gimme a sec released 2.1.3
DNA
DNAOP15mo ago
Ok np Another thing, how can i have, for example a rectangle completely transparent?
Beast
Beast15mo ago
what do you mean by transparent do you want to just hide a component?
DNA
DNAOP15mo ago
No I mean actually transparent Like this
new Box({
theme: {
base: crayon.bgRgb(0, 0, 0),
}
})
new Box({
theme: {
base: crayon.bgRgb(0, 0, 0),
}
})
But transparent Like No background color
Beast
Beast15mo ago
that's impossible in terminal
DNA
DNAOP15mo ago
Lemme try to explain this better
Beast
Beast15mo ago
if you don't want Tui to have a background by default (so default terminal background color) just don't set tui.style property
Beast
Beast15mo ago
just remove style here
No description
DNA
DNAOP15mo ago
When i have two elements, where one has zIndex 0 and theme.base crayon.blue, while the second is a Text and has zIndex 1 but its supposed to have no background To prevent something like this
DNA
DNAOP15mo ago
No description
DNA
DNAOP15mo ago
new Text({
parent: tui,
text: new Computed(() => {
return debug.value;
}),
rectangle: {column: 40, row: 1, width: 50},
theme: {
base: crayon.bgBlack,
},
zIndex: 128,
});
new Text({
parent: tui,
text: new Computed(() => {
return debug.value;
}),
rectangle: {column: 40, row: 1, width: 50},
theme: {
base: crayon.bgBlack,
},
zIndex: 128,
});
Beast
Beast15mo ago
do you mean "no background" here as "its supposed to be blue" or "its supposed to be default terminal background color"
DNA
DNAOP15mo ago
Just a transparent background In this case blue then
Beast
Beast15mo ago
there's no concept of transparency in a terminal you can assign a theme you used for the box to the text so they'll share their background color
DNA
DNAOP15mo ago
No other way then? Sadge cry
Beast
Beast15mo ago
No description
Beast
Beast15mo ago
not really
DNA
DNAOP15mo ago
Ok Thank you very much
Beast
Beast15mo ago
np