implement brush cost gauges
they're a little ugly at the moment, and can be a little useless for most simple brushes, but whatever we'll make them better later
|
@ -279,11 +279,24 @@ extern "C" fn haku_status_string(code: StatusCode) -> *const i8 {
|
||||||
.as_ptr()
|
.as_ptr()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct CompileStats {
|
||||||
|
ast_size: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct RunnableBrush {
|
||||||
|
chunk_id: ChunkId,
|
||||||
|
closure_spec: ClosureSpec,
|
||||||
|
|
||||||
|
compile_stats: CompileStats,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
enum BrushState {
|
enum BrushState {
|
||||||
#[default]
|
#[default]
|
||||||
Default,
|
Default,
|
||||||
Ready(ChunkId, ClosureSpec),
|
Ready(RunnableBrush),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
|
@ -431,7 +444,13 @@ unsafe extern "C" fn haku_compile_brush(
|
||||||
Ok(chunk_id) => chunk_id,
|
Ok(chunk_id) => chunk_id,
|
||||||
Err(_) => return StatusCode::TooManyChunks,
|
Err(_) => return StatusCode::TooManyChunks,
|
||||||
};
|
};
|
||||||
brush.state = BrushState::Ready(chunk_id, closure_spec);
|
brush.state = BrushState::Ready(RunnableBrush {
|
||||||
|
chunk_id,
|
||||||
|
closure_spec,
|
||||||
|
compile_stats: CompileStats {
|
||||||
|
ast_size: ast.len(),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
info!("brush compiled into {chunk_id:?}");
|
info!("brush compiled into {chunk_id:?}");
|
||||||
|
|
||||||
|
@ -470,7 +489,7 @@ unsafe extern "C" fn haku_begin_brush(instance: *mut Instance, brush: *const Bru
|
||||||
let instance = &mut *instance;
|
let instance = &mut *instance;
|
||||||
let brush = &*brush;
|
let brush = &*brush;
|
||||||
|
|
||||||
let BrushState::Ready(chunk_id, closure_spec) = brush.state else {
|
let BrushState::Ready(runnable) = &brush.state else {
|
||||||
panic!("brush is not compiled and ready to be used");
|
panic!("brush is not compiled and ready to be used");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -479,10 +498,10 @@ unsafe extern "C" fn haku_begin_brush(instance: *mut Instance, brush: *const Bru
|
||||||
instance.reset_exception();
|
instance.reset_exception();
|
||||||
instance.trampoline = None;
|
instance.trampoline = None;
|
||||||
|
|
||||||
let Ok(closure_id) = instance
|
let Ok(closure_id) = instance.vm.create_ref(Ref::Closure(Closure::chunk(
|
||||||
.vm
|
runnable.chunk_id,
|
||||||
.create_ref(Ref::Closure(Closure::chunk(chunk_id, closure_spec)))
|
runnable.closure_spec,
|
||||||
else {
|
))) else {
|
||||||
return StatusCode::OutOfRefSlots;
|
return StatusCode::OutOfRefSlots;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -574,3 +593,26 @@ unsafe extern "C" fn haku_cont_dotter(
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
unsafe extern "C" fn haku_stat_ast_size(brush: *const Brush) -> usize {
|
||||||
|
match &(*brush).state {
|
||||||
|
BrushState::Default => 0,
|
||||||
|
BrushState::Ready(runnable) => runnable.compile_stats.ast_size,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
unsafe extern "C" fn haku_stat_num_refs(instance: *const Instance) -> usize {
|
||||||
|
(*instance).vm.num_refs()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
unsafe extern "C" fn haku_stat_remaining_fuel(instance: *const Instance) -> usize {
|
||||||
|
(*instance).vm.remaining_fuel()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
unsafe extern "C" fn haku_stat_remaining_memory(instance: *const Instance) -> usize {
|
||||||
|
(*instance).vm.remaining_memory()
|
||||||
|
}
|
||||||
|
|
|
@ -73,10 +73,18 @@ impl Vm {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn num_refs(&self) -> usize {
|
||||||
|
self.refs.len()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn remaining_fuel(&self) -> usize {
|
pub fn remaining_fuel(&self) -> usize {
|
||||||
self.fuel
|
self.fuel
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn remaining_memory(&self) -> usize {
|
||||||
|
self.memory
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_fuel(&mut self, fuel: usize) {
|
pub fn set_fuel(&mut self, fuel: usize) {
|
||||||
self.fuel = fuel;
|
self.fuel = fuel;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,13 @@
|
||||||
#!/usr/bin/env fish
|
#!/usr/bin/env fish
|
||||||
|
|
||||||
set filename $argv[1]
|
function mkicon
|
||||||
set icon_name (basename $filename .svg)
|
set -l filename $argv[1]
|
||||||
set icon_base64 (svgcleaner --stdout $filename 2>/dev/null | base64 -w0)
|
set -l icon_name (basename $filename .svg)
|
||||||
|
set -l icon_base64 (svgcleaner --stdout $filename 2>/dev/null | base64 -w0)
|
||||||
|
|
||||||
printf "--icon-%s: url('data:image/svg+xml;base64,%s');" "$icon_name" "$icon_base64"
|
printf "--icon-%s: url('data:image/svg+xml;base64,%s');\n" "$icon_name" "$icon_base64"
|
||||||
|
end
|
||||||
|
|
||||||
|
for arg in $argv
|
||||||
|
mkicon $arg
|
||||||
|
end
|
||||||
|
|
|
@ -166,12 +166,20 @@ pre:has(code) {
|
||||||
/* Icons */
|
/* Icons */
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--icon-rkgk-grayscale: url("data:image/svg+xml;base64,PHN2ZyBmaWxsPSJub25lIiBoZWlnaHQ9IjE2IiB2aWV3Qm94PSIwIDAgMTYgMTYiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+PGNsaXBQYXRoIGlkPSJhIj48cGF0aCBkPSJtMCAwaDE2djE2aC0xNnoiLz48L2NsaXBQYXRoPjxnIGNsaXAtcGF0aD0idXJsKCNhKSIgc3Ryb2tlPSIjMDAwIiBzdHJva2Utd2lkdGg9IjIiPjxwYXRoIGQ9Im0xMiAxNy00LjU1Mjc5LTkuMTA1NTdjLS42NjQ5LTEuMzI5ODEuMzAyMDktMi44OTQ0MyAxLjc4ODg2LTIuODk0NDNoOC43NjM5MyIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPjxnIHN0cm9rZS1saW5lY2FwPSJyb3VuZCI+PHBhdGggZD0ibTUuNSAxMi0yLjUgNSIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLW9wYWNpdHk9Ii41Ii8+PHBhdGggZD0ibTMgNWgxIi8+PC9nPjwvZz48L3N2Zz4=");
|
--icon-brackets: url("data:image/svg+xml;base64,PHN2ZyBmaWxsPSJub25lIiBoZWlnaHQ9IjE2IiB2aWV3Qm94PSIwIDAgMTYgMTYiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJtNyA0aC0zdjhoM20yLThoM3Y4aC0zIiBzdHJva2U9IiMwMDAiIHN0cm9rZS13aWR0aD0iMiIvPjwvc3ZnPg==");
|
||||||
|
--icon-droplet: url("data:image/svg+xml;base64,PHN2ZyBmaWxsPSJub25lIiBoZWlnaHQ9IjE2IiB2aWV3Qm94PSIwIDAgMTYgMTYiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJtNSAxMGMwLTEuNjM0NzIgMS4wMDIxMi00LjI3MTU2IDIuMTg3MjYtNi41NDUzNy4zNDg5My0uNjY5NDQgMS4yNzY1NS0uNjY5NDQgMS42MjU0OCAwIDEuMTg1MTQgMi4yNzM4MSAyLjE4NzI2IDQuOTEwNjUgMi4xODcyNiA2LjU0NTM3IDAgMi0xLjUgMy0zIDNzLTMtMS0zLTN6IiBmaWxsPSIjMDAwIi8+PC9zdmc+");
|
||||||
--icon-external-link: url("data:image/svg+xml;base64,PHN2ZyBmaWxsPSJub25lIiBoZWlnaHQ9IjE2IiB2aWV3Qm94PSIwIDAgMTYgMTYiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48ZyBzdHJva2U9IiMwMDAiPjxwYXRoIGQ9Im0xMC41IDl2Mi41aC02di02aDIuNSIvPjxwYXRoIGQ9Im03IDkgNC41LTQuNW0wIDBoLTMuNW0zLjUgMHYzLjUiLz48L2c+PC9zdmc+");
|
--icon-external-link: url("data:image/svg+xml;base64,PHN2ZyBmaWxsPSJub25lIiBoZWlnaHQ9IjE2IiB2aWV3Qm94PSIwIDAgMTYgMTYiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48ZyBzdHJva2U9IiMwMDAiPjxwYXRoIGQ9Im0xMC41IDl2Mi41aC02di02aDIuNSIvPjxwYXRoIGQ9Im03IDkgNC41LTQuNW0wIDBoLTMuNW0zLjUgMHYzLjUiLz48L2c+PC9zdmc+");
|
||||||
|
--icon-memory: url("data:image/svg+xml;base64,PHN2ZyBmaWxsPSJub25lIiBoZWlnaHQ9IjE2IiB2aWV3Qm94PSIwIDAgMTYgMTYiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48ZyBmaWxsPSIjMDAwIiBzdHJva2U9IiMwMDAiIHN0cm9rZS13aWR0aD0iLjEiPjxwYXRoIGQ9Im01LjA1IDMuMDVoNS45djkuOWgtNS45eiIvPjxwYXRoIGQ9Im0zLjA1IDQuMDVoMS45djEuOWgtMS45eiIvPjxwYXRoIGQ9Im0xMS4wNSA0LjA1aDEuOXYxLjloLTEuOXoiLz48cGF0aCBkPSJtMy4wNSA3LjA1aDEuOXYxLjloLTEuOXoiLz48cGF0aCBkPSJtMTEuMDUgNy4wNWgxLjl2MS45aC0xLjl6Ii8+PHBhdGggZD0ibTMuMDUgMTAuMDVoMS45djEuOWgtMS45eiIvPjxwYXRoIGQ9Im0xMS4wNSAxMC4wNWgxLjl2MS45aC0xLjl6Ii8+PC9nPjwvc3ZnPg==");
|
||||||
|
--icon-object: url("data:image/svg+xml;base64,PHN2ZyBmaWxsPSJub25lIiBoZWlnaHQ9IjE2IiB2aWV3Qm94PSIwIDAgMTYgMTYiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Im0xMiA2YzAgMS4xMDQ1Ny0uODk1NCAyLTIgMnYyYzIuMjA5MSAwIDQtMS43OTA4NiA0LTRzLTEuNzkwOS00LTQtNGMtMi4yMDkxNCAwLTQgMS43OTA4Ni00IDRoMmMwLTEuMTA0NTcuODk1NDMtMiAyLTIgMS4xMDQ2IDAgMiAuODk1NDMgMiAyeiIgZmlsbD0iIzAwMCIgZmlsbC1ydWxlPSJldmVub2RkIi8+PHBhdGggZD0ibTMgN2g2djZoLTZ6IiBzdHJva2U9IiMwMDAiIHN0cm9rZS13aWR0aD0iMiIvPjwvc3ZnPg==");
|
||||||
|
--icon-rkgk-grayscale: url("data:image/svg+xml;base64,PHN2ZyBmaWxsPSJub25lIiBoZWlnaHQ9IjE2IiB2aWV3Qm94PSIwIDAgMTYgMTYiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+PGNsaXBQYXRoIGlkPSJhIj48cGF0aCBkPSJtMCAwaDE2djE2aC0xNnoiLz48L2NsaXBQYXRoPjxnIGNsaXAtcGF0aD0idXJsKCNhKSIgc3Ryb2tlPSIjMDAwIiBzdHJva2Utd2lkdGg9IjIiPjxwYXRoIGQ9Im0xMiAxNy00LjU1Mjc5LTkuMTA1NTdjLS42NjQ5LTEuMzI5ODEuMzAyMDktMi44OTQ0MyAxLjc4ODg2LTIuODk0NDNoOC43NjM5MyIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPjxnIHN0cm9rZS1saW5lY2FwPSJyb3VuZCI+PHBhdGggZD0ibTUuNSAxMi0yLjUgNSIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLW9wYWNpdHk9Ii41Ii8+PHBhdGggZD0ibTMgNWgxIi8+PC9nPjwvZz48L3N2Zz4=");
|
||||||
|
|
||||||
|
--icon-brackets-white: url("data:image/svg+xml;base64,PHN2ZyBmaWxsPSJub25lIiBoZWlnaHQ9IjE2IiB2aWV3Qm94PSIwIDAgMTYgMTYiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJtNyA0aC0zdjhoM20yLThoM3Y4aC0zIiBzdHJva2U9IiNmZmYiIHN0cm9rZS13aWR0aD0iMiIvPjwvc3ZnPg==");
|
||||||
|
--icon-droplet-white: url("data:image/svg+xml;base64,PHN2ZyBmaWxsPSJub25lIiBoZWlnaHQ9IjE2IiB2aWV3Qm94PSIwIDAgMTYgMTYiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJtNSAxMGMwLTEuNjM0NzIgMS4wMDIxMi00LjI3MTU2IDIuMTg3MjYtNi41NDUzNy4zNDg5My0uNjY5NDQgMS4yNzY1NS0uNjY5NDQgMS42MjU0OCAwIDEuMTg1MTQgMi4yNzM4MSAyLjE4NzI2IDQuOTEwNjUgMi4xODcyNiA2LjU0NTM3IDAgMi0xLjUgMy0zIDNzLTMtMS0zLTN6IiBmaWxsPSIjZmZmIi8+PC9zdmc+");
|
||||||
|
--icon-object-white: url("data:image/svg+xml;base64,PHN2ZyBmaWxsPSJub25lIiBoZWlnaHQ9IjE2IiB2aWV3Qm94PSIwIDAgMTYgMTYiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Im0xMiA2YzAgMS4xMDQ1Ny0uODk1NCAyLTIgMnYyYzIuMjA5MSAwIDQtMS43OTA4NiA0LTRzLTEuNzkwOS00LTQtNGMtMi4yMDkxNCAwLTQgMS43OTA4Ni00IDRoMmMwLTEuMTA0NTcuODk1NDMtMiAyLTIgMS4xMDQ2IDAgMiAuODk1NDMgMiAyeiIgZmlsbD0iI2ZmZiIgZmlsbC1ydWxlPSJldmVub2RkIi8+PHBhdGggZD0ibTMgN2g2djZoLTZ6IiBzdHJva2U9IiNmZmYiIHN0cm9rZS13aWR0aD0iMiIvPjwvc3ZnPg==");
|
||||||
|
--icon-memory-white: url("data:image/svg+xml;base64,PHN2ZyBmaWxsPSJub25lIiBoZWlnaHQ9IjE2IiB2aWV3Qm94PSIwIDAgMTYgMTYiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48ZyBmaWxsPSIjZmZmIiBzdHJva2U9IiNmZmYiIHN0cm9rZS13aWR0aD0iLjEiPjxwYXRoIGQ9Im01LjA1IDMuMDVoNS45djkuOWgtNS45eiIvPjxwYXRoIGQ9Im0zLjA1IDQuMDVoMS45djEuOWgtMS45eiIvPjxwYXRoIGQ9Im0xMS4wNSA0LjA1aDEuOXYxLjloLTEuOXoiLz48cGF0aCBkPSJtMy4wNSA3LjA1aDEuOXYxLjloLTEuOXoiLz48cGF0aCBkPSJtMTEuMDUgNy4wNWgxLjl2MS45aC0xLjl6Ii8+PHBhdGggZD0ibTMuMDUgMTAuMDVoMS45djEuOWgtMS45eiIvPjxwYXRoIGQ9Im0xMS4wNSAxMC4wNWgxLjl2MS45aC0xLjl6Ii8+PC9nPjwvc3ZnPg==");
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon {
|
.icon {
|
||||||
display: inline-block;
|
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
width: 16px;
|
width: 16px;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
|
@ -179,10 +187,35 @@ pre:has(code) {
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-position: 50% 50%;
|
background-position: 50% 50%;
|
||||||
|
|
||||||
&.icon-rkgk-grayscale {
|
&.icon-brackets {
|
||||||
background-image: var(--icon-rkgk-grayscale);
|
background-image: var(--icon-brackets);
|
||||||
|
}
|
||||||
|
&.icon-droplet {
|
||||||
|
background-image: var(--icon-droplet);
|
||||||
}
|
}
|
||||||
&.icon-external-link {
|
&.icon-external-link {
|
||||||
background-image: var(--icon-external-link);
|
background-image: var(--icon-external-link);
|
||||||
}
|
}
|
||||||
|
&.icon-memory {
|
||||||
|
background-image: var(--icon-memory);
|
||||||
|
}
|
||||||
|
&.icon-object {
|
||||||
|
background-image: var(--icon-object);
|
||||||
|
}
|
||||||
|
&.icon-rkgk-grayscale {
|
||||||
|
background-image: var(--icon-rkgk-grayscale);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.icon-brackets-white {
|
||||||
|
background-image: var(--icon-brackets-white);
|
||||||
|
}
|
||||||
|
&.icon-droplet-white {
|
||||||
|
background-image: var(--icon-droplet-white);
|
||||||
|
}
|
||||||
|
&.icon-memory-white {
|
||||||
|
background-image: var(--icon-memory-white);
|
||||||
|
}
|
||||||
|
&.icon-object-white {
|
||||||
|
background-image: var(--icon-object-white);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
81
static/brush-cost.js
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
class Gauge extends HTMLElement {
|
||||||
|
constructor(iconName, label) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.iconName = iconName;
|
||||||
|
this.label = label;
|
||||||
|
}
|
||||||
|
|
||||||
|
connectedCallback() {
|
||||||
|
this.role = "progressbar";
|
||||||
|
this.classList.add("icon", `icon-${this.iconName}`);
|
||||||
|
|
||||||
|
this.full = this.appendChild(document.createElement("div"));
|
||||||
|
this.full.classList.add("full", "icon", `icon-${this.iconName}-white`);
|
||||||
|
}
|
||||||
|
|
||||||
|
setValue(value, valueMax) {
|
||||||
|
let clampedNormalized = Math.max(0, Math.min(1, value / valueMax));
|
||||||
|
this.style.setProperty("--progress", `${clampedNormalized * 100}%`);
|
||||||
|
this.title = `${this.label}: ${value} / ${valueMax} (${Math.ceil((value / valueMax) * 100)}%)`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
customElements.define("rkgk-brush-cost-gauge", Gauge);
|
||||||
|
|
||||||
|
export class BrushCostGauges extends HTMLElement {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
connectedCallback() {
|
||||||
|
this.codeSizeGauge = this.appendChild(
|
||||||
|
createGauge({
|
||||||
|
className: "code-size",
|
||||||
|
iconName: "brackets",
|
||||||
|
label: "Code size",
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
this.fuelGauge = this.appendChild(
|
||||||
|
createGauge({
|
||||||
|
className: "fuel",
|
||||||
|
iconName: "droplet",
|
||||||
|
label: "Fuel",
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
this.objectsGauge = this.appendChild(
|
||||||
|
createGauge({
|
||||||
|
className: "objects",
|
||||||
|
iconName: "object",
|
||||||
|
label: "Objects",
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
this.memoryGauge = this.appendChild(
|
||||||
|
createGauge({
|
||||||
|
className: "memory",
|
||||||
|
iconName: "memory",
|
||||||
|
label: "Bulk memory",
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
this.codeSizeGauge.setValue(0);
|
||||||
|
this.fuelGauge.setValue(0);
|
||||||
|
this.objectsGauge.setValue(0);
|
||||||
|
this.memoryGauge.setValue(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
update(stats) {
|
||||||
|
this.codeSizeGauge.setValue(stats.astSize, stats.astSizeMax);
|
||||||
|
this.fuelGauge.setValue(stats.fuel, stats.fuelMax);
|
||||||
|
this.objectsGauge.setValue(stats.numRefs, stats.numRefsMax);
|
||||||
|
this.memoryGauge.setValue(stats.memory, stats.memoryMax);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
customElements.define("rkgk-brush-cost-gauges", BrushCostGauges);
|
||||||
|
|
||||||
|
function createGauge({ className, iconName, label }) {
|
||||||
|
let gauge = new Gauge(iconName, label);
|
||||||
|
gauge.classList.add(className);
|
||||||
|
return gauge;
|
||||||
|
}
|
|
@ -257,4 +257,24 @@ export class Haku {
|
||||||
|
|
||||||
return { status: "ok" };
|
return { status: "ok" };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get astSize() {
|
||||||
|
if (this.#pBrush != 0) {
|
||||||
|
return w.haku_stat_ast_size(this.#pBrush);
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get numRefs() {
|
||||||
|
return w.haku_stat_num_refs(this.#pInstance);
|
||||||
|
}
|
||||||
|
|
||||||
|
get remainingFuel() {
|
||||||
|
return w.haku_stat_remaining_fuel(this.#pInstance);
|
||||||
|
}
|
||||||
|
|
||||||
|
get remainingMemory() {
|
||||||
|
return w.haku_stat_remaining_memory(this.#pInstance);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
3
static/icon/brackets-white.svg
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M7 4H4V12H7M9 4H12V12H9" stroke="white" stroke-width="2"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 171 B |
3
static/icon/brackets.svg
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M7 4H4V12H7M9 4H12V12H9" stroke="black" stroke-width="2"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 171 B |
3
static/icon/droplet-white.svg
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M5 10C5 8.36528 6.00212 5.72844 7.18726 3.45463C7.53619 2.78519 8.46381 2.78519 8.81274 3.45463C9.99788 5.72844 11 8.36528 11 10C11 12 9.5 13 8 13C6.5 13 5 12 5 10Z" fill="white"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 293 B |
3
static/icon/droplet.svg
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M5 10C5 8.36528 6.00212 5.72844 7.18726 3.45463C7.53619 2.78519 8.46381 2.78519 8.81274 3.45463C9.99788 5.72844 11 8.36528 11 10C11 12 9.5 13 8 13C6.5 13 5 12 5 10Z" fill="black"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 293 B |
9
static/icon/memory-white.svg
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<rect x="5.05" y="3.05" width="5.9" height="9.9" fill="white" stroke="white" stroke-width="0.1"/>
|
||||||
|
<rect x="3.05" y="4.05" width="1.9" height="1.9" fill="white" stroke="white" stroke-width="0.1"/>
|
||||||
|
<rect x="11.05" y="4.05" width="1.9" height="1.9" fill="white" stroke="white" stroke-width="0.1"/>
|
||||||
|
<rect x="3.05" y="7.05" width="1.9" height="1.9" fill="white" stroke="white" stroke-width="0.1"/>
|
||||||
|
<rect x="11.05" y="7.05" width="1.9" height="1.9" fill="white" stroke="white" stroke-width="0.1"/>
|
||||||
|
<rect x="3.05" y="10.05" width="1.9" height="1.9" fill="white" stroke="white" stroke-width="0.1"/>
|
||||||
|
<rect x="11.05" y="10.05" width="1.9" height="1.9" fill="white" stroke="white" stroke-width="0.1"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 794 B |
9
static/icon/memory.svg
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<rect x="5.05" y="3.05" width="5.9" height="9.9" fill="black" stroke="black" stroke-width="0.1"/>
|
||||||
|
<rect x="3.05" y="4.05" width="1.9" height="1.9" fill="black" stroke="black" stroke-width="0.1"/>
|
||||||
|
<rect x="11.05" y="4.05" width="1.9" height="1.9" fill="black" stroke="black" stroke-width="0.1"/>
|
||||||
|
<rect x="3.05" y="7.05" width="1.9" height="1.9" fill="black" stroke="black" stroke-width="0.1"/>
|
||||||
|
<rect x="11.05" y="7.05" width="1.9" height="1.9" fill="black" stroke="black" stroke-width="0.1"/>
|
||||||
|
<rect x="3.05" y="10.05" width="1.9" height="1.9" fill="black" stroke="black" stroke-width="0.1"/>
|
||||||
|
<rect x="11.05" y="10.05" width="1.9" height="1.9" fill="black" stroke="black" stroke-width="0.1"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 794 B |
4
static/icon/object-white.svg
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 6C12 7.10457 11.1046 8 10 8V10C12.2091 10 14 8.20914 14 6C14 3.79086 12.2091 2 10 2C7.79086 2 6 3.79086 6 6H8C8 4.89543 8.89543 4 10 4C11.1046 4 12 4.89543 12 6Z" fill="white"/>
|
||||||
|
<rect x="3" y="7" width="6" height="6" stroke="white" stroke-width="2"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 407 B |
4
static/icon/object.svg
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 6C12 7.10457 11.1046 8 10 8V10C12.2091 10 14 8.20914 14 6C14 3.79086 12.2091 2 10 2C7.79086 2 6 3.79086 6 6H8C8 4.89543 8.89543 4 10 4C11.1046 4 12 4.89543 12 6Z" fill="black"/>
|
||||||
|
<rect x="3" y="7" width="6" height="6" stroke="black" stroke-width="2"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 407 B |
BIN
static/icon/rkgk design.zip
Normal file
|
@ -32,7 +32,10 @@ main {
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
|
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: [left] 1fr [right-resize] auto [right] minmax(0, var(--right-width));
|
grid-template-columns: [left] 1fr [right-resize] auto [right] minmax(
|
||||||
|
0,
|
||||||
|
var(--right-width)
|
||||||
|
);
|
||||||
|
|
||||||
/* Pass all events through. Children may receive events as normal. */
|
/* Pass all events through. Children may receive events as normal. */
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
@ -67,11 +70,23 @@ main {
|
||||||
pointer-events: auto;
|
pointer-events: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
&>.floating>rkgk-brush-preview {
|
& > .floating {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
gap: 12px;
|
||||||
|
|
||||||
|
& > rkgk-brush-preview {
|
||||||
width: 128px;
|
width: 128px;
|
||||||
height: 128px;
|
height: 128px;
|
||||||
pointer-events: auto;
|
pointer-events: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
& > rkgk-brush-cost-gauges {
|
||||||
|
width: 100%;
|
||||||
|
pointer-events: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,7 +134,8 @@ rkgk-resize-handle {
|
||||||
opacity: 0%;
|
opacity: 0%;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover>.visual, &.dragging>.visual {
|
&:hover > .visual,
|
||||||
|
&.dragging > .visual {
|
||||||
opacity: 100%;
|
opacity: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -306,7 +322,8 @@ rkgk-brush-editor.rkgk-panel {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
&>.errors:empty, &>.error-header:empty {
|
& > .errors:empty,
|
||||||
|
& > .error-header:empty {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,11 +351,17 @@ rkgk-brush-preview {
|
||||||
display: block;
|
display: block;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
background:
|
background: repeating-conic-gradient(
|
||||||
repeating-conic-gradient(var(--checkerboard-light) 0% 25%, var(--checkerboard-dark) 0% 50%)
|
var(--checkerboard-light) 0% 25%,
|
||||||
|
var(--checkerboard-dark) 0% 50%
|
||||||
|
)
|
||||||
50% 50% / var(--checkerboard-size) var(--checkerboard-size);
|
50% 50% / var(--checkerboard-size) var(--checkerboard-size);
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
|
|
||||||
|
& > canvas {
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
&.error {
|
&.error {
|
||||||
& > canvas {
|
& > canvas {
|
||||||
display: none;
|
display: none;
|
||||||
|
@ -354,6 +377,49 @@ rkgk-brush-preview {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Brush cost gauges */
|
||||||
|
|
||||||
|
rkgk-brush-cost-gauges,
|
||||||
|
rkgk-brush-cost-gauges.rkgk-panel {
|
||||||
|
--gauge-size: 20px;
|
||||||
|
|
||||||
|
height: var(--gauge-size);
|
||||||
|
border-radius: 4px;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
|
||||||
|
overflow: clip; /* clip corners */
|
||||||
|
|
||||||
|
& > rkgk-brush-cost-gauge {
|
||||||
|
display: block;
|
||||||
|
height: var(--gauge-size);
|
||||||
|
flex-grow: 1;
|
||||||
|
|
||||||
|
& > .full {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
clip-path: xywh(0 0 var(--progress) 100%);
|
||||||
|
|
||||||
|
background-color: var(--gauge-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.code-size {
|
||||||
|
--gauge-color: var(--color-brand-blue);
|
||||||
|
}
|
||||||
|
&.fuel {
|
||||||
|
--gauge-color: #f44096;
|
||||||
|
}
|
||||||
|
&.objects {
|
||||||
|
--gauge-color: #fd9916;
|
||||||
|
}
|
||||||
|
&.memory {
|
||||||
|
--gauge-color: #5aca40;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Welcome screen */
|
/* Welcome screen */
|
||||||
|
|
||||||
rkgk-welcome {
|
rkgk-welcome {
|
||||||
|
@ -369,7 +435,8 @@ rkgk-welcome {
|
||||||
/* Connection status dialogs */
|
/* Connection status dialogs */
|
||||||
|
|
||||||
rkgk-connection-status {
|
rkgk-connection-status {
|
||||||
&>dialog[name='logging-in-dialog'][open], &>dialog[name='disconnected-dialog'][open] {
|
& > dialog[name="logging-in-dialog"][open],
|
||||||
|
& > dialog[name="disconnected-dialog"][open] {
|
||||||
border: none;
|
border: none;
|
||||||
outline: none;
|
outline: none;
|
||||||
background: none;
|
background: none;
|
||||||
|
@ -379,8 +446,8 @@ rkgk-connection-status {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
&>dialog[name='error-dialog'][open] {
|
& > dialog[name="error-dialog"][open] {
|
||||||
& textarea[name='error-text'] {
|
& textarea[name="error-text"] {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
resize: none;
|
resize: none;
|
||||||
|
@ -439,4 +506,3 @@ rkgk-connection-status {
|
||||||
border-right: 1px solid var(--color-panel-border);
|
border-right: 1px solid var(--color-panel-border);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ let canvasRenderer = main.querySelector("rkgk-canvas-renderer");
|
||||||
let reticleRenderer = main.querySelector("rkgk-reticle-renderer");
|
let reticleRenderer = main.querySelector("rkgk-reticle-renderer");
|
||||||
let brushEditor = main.querySelector("rkgk-brush-editor");
|
let brushEditor = main.querySelector("rkgk-brush-editor");
|
||||||
let brushPreview = main.querySelector("rkgk-brush-preview");
|
let brushPreview = main.querySelector("rkgk-brush-preview");
|
||||||
|
let brushCostGauges = main.querySelector("rkgk-brush-cost-gauges");
|
||||||
let welcome = main.querySelector("rkgk-welcome");
|
let welcome = main.querySelector("rkgk-welcome");
|
||||||
let connectionStatus = main.querySelector("rkgk-connection-status");
|
let connectionStatus = main.querySelector("rkgk-connection-status");
|
||||||
|
|
||||||
|
@ -251,12 +252,15 @@ function readUrl(urlString) {
|
||||||
let compileResult = currentUser.setBrush(brushEditor.code);
|
let compileResult = currentUser.setBrush(brushEditor.code);
|
||||||
brushEditor.renderHakuResult("Compilation", compileResult);
|
brushEditor.renderHakuResult("Compilation", compileResult);
|
||||||
|
|
||||||
|
brushCostGauges.update(currentUser.getStats(session.wallInfo));
|
||||||
|
|
||||||
if (compileResult.status != "ok") {
|
if (compileResult.status != "ok") {
|
||||||
brushPreview.setErrorFlag();
|
brushPreview.setErrorFlag();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
brushPreview.renderBrush(currentUser.haku).then((previewResult) => {
|
brushPreview.renderBrush(currentUser.haku).then((previewResult) => {
|
||||||
|
brushCostGauges.update(currentUser.getStats(session.wallInfo));
|
||||||
if (previewResult.status == "error") {
|
if (previewResult.status == "error") {
|
||||||
brushEditor.renderHakuResult(
|
brushEditor.renderHakuResult(
|
||||||
previewResult.phase == "eval" ? "Evaluation" : "Rendering",
|
previewResult.phase == "eval" ? "Evaluation" : "Rendering",
|
||||||
|
|
|
@ -89,6 +89,19 @@ export class User {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getStats(wallInfo) {
|
||||||
|
return {
|
||||||
|
astSize: this.haku.astSize,
|
||||||
|
astSizeMax: wallInfo.hakuLimits.ast_capacity,
|
||||||
|
numRefs: this.haku.numRefs,
|
||||||
|
numRefsMax: wallInfo.hakuLimits.ref_capacity,
|
||||||
|
fuel: wallInfo.hakuLimits.fuel - this.haku.remainingFuel,
|
||||||
|
fuelMax: wallInfo.hakuLimits.fuel,
|
||||||
|
memory: wallInfo.hakuLimits.memory - this.haku.remainingMemory,
|
||||||
|
memoryMax: wallInfo.hakuLimits.memory,
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class OnlineUsers extends EventTarget {
|
export class OnlineUsers extends EventTarget {
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
<script type="module">
|
<script type="module">
|
||||||
import "rkgk/live-reload.js";
|
import "rkgk/live-reload.js";
|
||||||
|
|
||||||
|
import "rkgk/brush-cost.js";
|
||||||
import "rkgk/brush-editor.js";
|
import "rkgk/brush-editor.js";
|
||||||
import "rkgk/brush-preview.js";
|
import "rkgk/brush-preview.js";
|
||||||
import "rkgk/canvas-renderer.js";
|
import "rkgk/canvas-renderer.js";
|
||||||
|
@ -64,6 +65,7 @@
|
||||||
<div class="right">
|
<div class="right">
|
||||||
<div class="floating">
|
<div class="floating">
|
||||||
<rkgk-brush-preview></rkgk-brush-preview>
|
<rkgk-brush-preview></rkgk-brush-preview>
|
||||||
|
<rkgk-brush-cost-gauges class="rkgk-panel"></rkgk-brush-cost-gauges>
|
||||||
</div>
|
</div>
|
||||||
<rkgk-resize-handle
|
<rkgk-resize-handle
|
||||||
data-direction="vertical"
|
data-direction="vertical"
|
||||||
|
|